From 6eeaf9e38ea447be776c683984cbd2cc3a89cb09 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Wed, 28 Sep 2022 14:26:47 +0200 Subject: [PATCH 001/282] Issue #303: framework for reference_dense added This commit comes from a split of the original commit whose details are as follows: SHA1 ID: a7c1db0eb45326184dadec39a6a7731eb16a39fd Author: Albert-Jan Yzelman 2022-01-14 15:52:26 Committer: Albert-Jan Yzelman 2022-01-30 13:48:35 The reason for splitting is to separate the changes irrelevant to the branch 303 into a separate branch. The split produced 3 separate commits. This commit is number 1. This commit in particular is relevant to 303 and will remain in it. --- bootstrap.sh | 8 ++ cmake/AddGRBInstall.cmake | 9 +- cmake/AddGRBVars.cmake | 11 +- include/CMakeLists.txt | 11 ++ include/graphblas/backends.hpp | 8 +- include/graphblas/base/collectives.hpp | 8 +- include/graphblas/benchmark.hpp | 7 +- include/graphblas/blas1.hpp | 1 + include/graphblas/blas2.hpp | 1 + include/graphblas/blas3.hpp | 5 +- include/graphblas/collectives.hpp | 7 +- include/graphblas/config.hpp | 1 + include/graphblas/coordinates.hpp | 6 +- include/graphblas/denseref/benchmark.hpp | 104 +++++++++++++++++++ include/graphblas/denseref/blas1.hpp | 31 ++++++ include/graphblas/denseref/blas2.hpp | 31 ++++++ include/graphblas/denseref/blas3.hpp | 31 ++++++ include/graphblas/denseref/collectives.hpp | 76 ++++++++++++++ include/graphblas/denseref/config.hpp | 54 ++++++++++ include/graphblas/denseref/exec.hpp | 109 ++++++++++++++++++++ include/graphblas/denseref/init.hpp | 41 ++++++++ include/graphblas/denseref/io.hpp | 31 ++++++ include/graphblas/denseref/matrix.hpp | 36 +++++++ include/graphblas/denseref/pinnedvector.hpp | 31 ++++++ include/graphblas/denseref/properties.hpp | 41 ++++++++ include/graphblas/denseref/spmd.hpp | 70 +++++++++++++ include/graphblas/denseref/vector.hpp | 36 +++++++ include/graphblas/distribution.hpp | 4 +- include/graphblas/exec.hpp | 7 +- include/graphblas/init.hpp | 1 + include/graphblas/io.hpp | 1 + include/graphblas/matrix.hpp | 1 + include/graphblas/pinnedvector.hpp | 7 +- include/graphblas/properties.hpp | 7 +- include/graphblas/spmd.hpp | 7 +- include/graphblas/vector.hpp | 1 + 36 files changed, 808 insertions(+), 33 deletions(-) create mode 100644 include/graphblas/denseref/benchmark.hpp create mode 100644 include/graphblas/denseref/blas1.hpp create mode 100644 include/graphblas/denseref/blas2.hpp create mode 100644 include/graphblas/denseref/blas3.hpp create mode 100644 include/graphblas/denseref/collectives.hpp create mode 100644 include/graphblas/denseref/config.hpp create mode 100644 include/graphblas/denseref/exec.hpp create mode 100644 include/graphblas/denseref/init.hpp create mode 100644 include/graphblas/denseref/io.hpp create mode 100644 include/graphblas/denseref/matrix.hpp create mode 100644 include/graphblas/denseref/pinnedvector.hpp create mode 100644 include/graphblas/denseref/properties.hpp create mode 100644 include/graphblas/denseref/spmd.hpp create mode 100644 include/graphblas/denseref/vector.hpp diff --git a/bootstrap.sh b/bootstrap.sh index 89b865a15..e0f8850c4 100755 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -73,6 +73,7 @@ print_help() { the location where LPF is installed" echo " --with-banshee= - path to the the tools to compile the banshee backend" echo " --with-snitch= - path to the tools for Snitch support within the banshee backend" + echo " --without-dense - to compile without support for dense algebraic programming" echo " --no-reference - disables the reference and reference_omp backends" echo " --debug-build - build the project with debug options (tests will run much slower!)" echo " --generator= - set the generator for CMake (otherwise use CMake's default)" @@ -92,6 +93,7 @@ the location where LPF is installed" reference=yes banshee=no lpf=no +dense=yes show=no FLAGS=$'' LPF_INSTALL_PATH= @@ -143,6 +145,9 @@ or assume default paths (--with-lpf)" SNITCH_PATH="${arg#--with-snitch=}" banshee=yes ;; + --without-dense) + dense=no + ;; --no-reference) reference=no ;; @@ -287,6 +292,9 @@ the current directory before invocation or confirm the deletion of its content w if [[ "${reference}" == "no" ]]; then CMAKE_OPTS+=" -DWITH_REFERENCE_BACKEND=OFF -DWITH_OMP_BACKEND=OFF" fi + if [[ "${dense}" == "no" ]]; then + CMAKE_OPTS+=" -DWITH_DENSE_BACKEND=OFF" + fi if [[ "${lpf}" == "yes" ]]; then CMAKE_OPTS+=" -DLPF_INSTALL_PATH='${ABSOLUTE_LPF_INSTALL_PATH}'" fi diff --git a/cmake/AddGRBInstall.cmake b/cmake/AddGRBInstall.cmake index f4b254b8f..1e023f1aa 100644 --- a/cmake/AddGRBInstall.cmake +++ b/cmake/AddGRBInstall.cmake @@ -112,7 +112,7 @@ endif() # paths may have spaces, hence wrap them inside single quotes '' # shared memory backends -if ( WITH_REFERENCE_BACKEND ) +if( WITH_REFERENCE_BACKEND ) addBackendWrapperGenOptions( "reference" COMPILE_DEFINITIONS "${REFERENCE_SELECTION_DEFS}" LINK_FLAGS "'${SHMEM_BACKEND_INSTALL_DIR}/lib${BACKEND_LIBRARY_OUTPUT_NAME}.a'" @@ -120,6 +120,13 @@ if ( WITH_REFERENCE_BACKEND ) ) endif() +if( WITH_DENSE_BACKEND ) + addBackendWrapperGenOptions( "reference_dense" + COMPILE_DEFINITIONS "${DENSE_SELECTION_DEFS}" + LINK_FLAGS "${SHMEM_BACKEND_INSTALL_DIR}/lib${BACKEND_LIBRARY_OUTPUT_NAME}.a" + ) +endif() + if( WITH_OMP_BACKEND ) addBackendWrapperGenOptions( "reference_omp" COMPILE_DEFINITIONS "${REFERENCE_OMP_SELECTION_DEFS}" diff --git a/cmake/AddGRBVars.cmake b/cmake/AddGRBVars.cmake index 2b1bc012b..298a7574a 100644 --- a/cmake/AddGRBVars.cmake +++ b/cmake/AddGRBVars.cmake @@ -31,6 +31,7 @@ set( REFERENCE_BACKEND_DEFAULT_NAME "backend_reference" ) set( REFERENCE_OMP_BACKEND_DEFAULT_NAME "backend_reference_omp" ) set( BSP1D_BACKEND_DEFAULT_NAME "backend_bsp1d" ) set( HYBRID_BACKEND_DEFAULT_NAME "backend_hybrid" ) +set( DENSE_BACKEND_DEFAULT_NAME "backend_reference_dense" ) ### COMPILER DEFINITIONS FOR HEADERS INCLUSION AND FOR BACKEND SELECTION @@ -39,6 +40,7 @@ set( HYBRID_BACKEND_DEFAULT_NAME "backend_hybrid" ) set( REFERENCE_INCLUDE_DEFS "_GRB_WITH_REFERENCE" ) set( REFERENCE_OMP_INCLUDE_DEFS "_GRB_WITH_OMP" ) set( LPF_INCLUDE_DEFS "_GRB_WITH_LPF" ) +set( DENSE_INCLUDE_DEFS "_GRB_WITH_DENSEREF" ) # compiler definitions to select a backend set( REFERENCE_SELECTION_DEFS "_GRB_BACKEND=reference" ) @@ -51,12 +53,13 @@ set( HYBRID_SELECTION_DEFS "_GRB_BACKEND=BSP1D" "_GRB_BSP1D_BACKEND=reference_omp" ) +set( DENSE_SELECTION_DEFS "_GRB_BACKEND=reference_dense" ) # definition to set if not depending on libnuma set( NO_NUMA_DEF "_GRB_NO_LIBNUMA" ) ### **ALL** BACKENDS, EVEN IF NOT ENABLED BY USER -set( ALL_BACKENDS "reference" "reference_omp" "bsp1d" "hybrid" ) +set( ALL_BACKENDS "reference" "reference_omp" "bsp1d" "hybrid" "reference_dense" ) # list of user-enabled backends, for tests and wrapper scripts (do not change!) @@ -66,7 +69,7 @@ set( AVAILABLE_BACKENDS "" ) # backends that are enabled by the user: append as in the following # shared memory backends -if ( WITH_REFERENCE_BACKEND ) +if( WITH_REFERENCE_BACKEND ) list( APPEND AVAILABLE_BACKENDS "reference" ) endif() @@ -74,6 +77,10 @@ if( WITH_OMP_BACKEND ) list( APPEND AVAILABLE_BACKENDS "reference_omp" ) endif() +if( WITH_DENSE_BACKEND ) + list( APPEND AVAILABLE_BACKENDS "reference_dense" ) +endif() + # distributed memory backends if( WITH_BSP1D_BACKEND ) list( APPEND AVAILABLE_BACKENDS "bsp1d" ) diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt index 65e033f5d..aeb2e10a2 100644 --- a/include/CMakeLists.txt +++ b/include/CMakeLists.txt @@ -117,6 +117,17 @@ if( WITH_REFERENCE_BACKEND_HEADERS ) install( TARGETS backend_reference_headers EXPORT GraphBLASTargets ) endif() +if( WITH_DENSE_BACKEND ) + add_library( backend_reference_dense_headers INTERFACE ) + target_link_libraries( backend_reference_dense_headers INTERFACE backend_headers_nodefs ) + install( DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/graphblas/denseref" + DESTINATION "${GRB_INCLUDE_INSTALL_DIR}" + FILES_MATCHING REGEX "${HEADERS_REGEX}" + ) + install( TARGETS backend_reference_dense_headers EXPORT GraphBLASTargets ) + target_link_libraries( all_headers INTERFACE backend_reference_dense_headers ) +endif() + if( WITH_REFERENCE_BACKEND OR WITH_OMP_BACKEND ) install( DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/graphblas/reference/" DESTINATION "${GRB_INCLUDE_INSTALL_DIR}/reference" diff --git a/include/graphblas/backends.hpp b/include/graphblas/backends.hpp index 72f1bcec1..3acee4fd5 100644 --- a/include/graphblas/backends.hpp +++ b/include/graphblas/backends.hpp @@ -151,7 +151,13 @@ namespace grb { * * Collaboration with ETH Zurich (ongoing). */ - banshee_ssr + banshee_ssr, + + /** + * The ALP/Dense backend. This is no longer a proper GraphBLAS implementation, as it assumes + * all containers are dense. No ``missing'' entries in containers are allowed. + */ + reference_dense }; diff --git a/include/graphblas/base/collectives.hpp b/include/graphblas/base/collectives.hpp index d9af31523..accb866f9 100644 --- a/include/graphblas/base/collectives.hpp +++ b/include/graphblas/base/collectives.hpp @@ -108,7 +108,7 @@ namespace grb { static RC allreduce( IOType & inout, const Operator op = Operator() ) { (void)inout; (void)op; - return PANIC; + return UNSUPPORTED; } /** @@ -175,7 +175,7 @@ namespace grb { (void)inout; (void)op; (void)root; - return PANIC; + return UNSUPPORTED; } /** @@ -233,7 +233,7 @@ namespace grb { static RC broadcast( IOType &inout, const size_t root = 0 ) { (void)inout; (void)root; - return PANIC; + return UNSUPPORTED; } /** @@ -247,7 +247,7 @@ namespace grb { (void)inout; (void)size; (void)root; - return PANIC; + return UNSUPPORTED; } }; // end class ``collectives'' diff --git a/include/graphblas/benchmark.hpp b/include/graphblas/benchmark.hpp index b0187a0b9..d040409bd 100644 --- a/include/graphblas/benchmark.hpp +++ b/include/graphblas/benchmark.hpp @@ -28,13 +28,14 @@ // include specialisations #ifdef _GRB_WITH_REFERENCE -#include "graphblas/reference/benchmark.hpp" + #include "graphblas/reference/benchmark.hpp" + #include "graphblas/denseref/benchmark.hpp" #endif #ifdef _GRB_WITH_BANSHEE -#include "graphblas/banshee/benchmark.hpp" + #include "graphblas/banshee/benchmark.hpp" #endif #ifdef _GRB_WITH_LPF -#include "graphblas/bsp1d/benchmark.hpp" + #include "graphblas/bsp1d/benchmark.hpp" #endif #ifdef _GRB_BACKEND diff --git a/include/graphblas/blas1.hpp b/include/graphblas/blas1.hpp index 9b796bee7..26ba991db 100644 --- a/include/graphblas/blas1.hpp +++ b/include/graphblas/blas1.hpp @@ -27,6 +27,7 @@ #ifdef _GRB_WITH_REFERENCE #include + #include #endif #ifdef _GRB_WITH_BANSHEE #include diff --git a/include/graphblas/blas2.hpp b/include/graphblas/blas2.hpp index e44d311a1..773457fc8 100644 --- a/include/graphblas/blas2.hpp +++ b/include/graphblas/blas2.hpp @@ -32,6 +32,7 @@ // now include all specialisations contained in the backend directories: #ifdef _GRB_WITH_REFERENCE #include + #include #endif #ifdef _GRB_WITH_BANSHEE #include diff --git a/include/graphblas/blas3.hpp b/include/graphblas/blas3.hpp index 3b485851f..6aca8a624 100644 --- a/include/graphblas/blas3.hpp +++ b/include/graphblas/blas3.hpp @@ -28,10 +28,11 @@ // now include all specialisations contained in the backend directories: #ifdef _GRB_WITH_REFERENCE -#include + #include + #include #endif #ifdef _GRB_WITH_LPF -#include + #include #endif #endif // end _H_GRB_BLAS3 diff --git a/include/graphblas/collectives.hpp b/include/graphblas/collectives.hpp index a99eac739..4949d3b42 100644 --- a/include/graphblas/collectives.hpp +++ b/include/graphblas/collectives.hpp @@ -28,13 +28,14 @@ // include template specialisations #ifdef _GRB_WITH_REFERENCE -#include + #include + #include #endif #ifdef _GRB_WITH_LPF -#include + #include #endif #ifdef _GRB_WITH_BANSHEE -#include + #include #endif // specify default only if requested during compilation diff --git a/include/graphblas/config.hpp b/include/graphblas/config.hpp index 8ef4e6a8d..264ed5a88 100644 --- a/include/graphblas/config.hpp +++ b/include/graphblas/config.hpp @@ -28,6 +28,7 @@ // include all active configurations #ifdef _GRB_WITH_REFERENCE #include "graphblas/reference/config.hpp" + #include "graphblas/denseref/config.hpp" #endif #ifdef _GRB_WITH_HYPERDAGS #include "graphblas/hyperdags/config.hpp" diff --git a/include/graphblas/coordinates.hpp b/include/graphblas/coordinates.hpp index 3ddf662bb..2bf40f2ed 100644 --- a/include/graphblas/coordinates.hpp +++ b/include/graphblas/coordinates.hpp @@ -27,13 +27,13 @@ // now include all specialisations contained in the backend directories: #ifdef _GRB_WITH_REFERENCE -#include + #include #endif #ifdef _GRB_WITH_LPF -// #include + // #include #endif #ifdef _GRB_WITH_BANSHEE -#include + #include #endif #endif // _H_GRB_COORDINATES diff --git a/include/graphblas/denseref/benchmark.hpp b/include/graphblas/denseref/benchmark.hpp new file mode 100644 index 000000000..fc388fac6 --- /dev/null +++ b/include/graphblas/denseref/benchmark.hpp @@ -0,0 +1,104 @@ + +/* + * Copyright 2021 Huawei Technologies Co., Ltd. + * + * 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. + */ + +/* + * @author A. N. Yzelman + * @date 14th of January, 2022 + */ + +#ifndef _H_GRB_DENSEREF_BENCH +#define _H_GRB_DENSEREF_BENCH + +#include +#include + +namespace grb { + + template< enum EXEC_MODE mode > + class Benchmarker< mode, reference_dense > : protected Launcher< mode, reference >, protected internal::BenchmarkerBase { + + public: + + /** \internal No implementation notes */ + Benchmarker( size_t process_id = 0, + size_t nprocs = 1, + std::string hostname = "localhost", + std::string port = "0" + ) : Launcher< mode, reference >( process_id, nprocs, hostname, port ) {} + + /** \internal No implementation notes */ + template< typename U > + RC exec( + void ( *grb_program )( const void *, const size_t, U & ), + const void * data_in, const size_t in_size, + U &data_out, + const size_t inner, const size_t outer, + const bool broadcast = false + ) const { + (void)broadcast; // value doesn't matter for a single user process + // initialise GraphBLAS + RC ret = init(); + // call graphBLAS algo + if( ret == SUCCESS ) { + benchmark< U >( grb_program, data_in, in_size, data_out, inner, outer, 0 ); + } + // finalise the GraphBLAS + const RC frc = finalize(); + if( ret == SUCCESS ) { + ret = frc; + } + // and done + return ret; + } + + /** No implementation notes. */ + template< typename T, typename U > + RC exec( void ( *grb_program )( const T &, U & ), + const T &data_in, + U &data_out, + const size_t inner, + const size_t outer, + const bool broadcast = false + ) { + (void)broadcast; // value doesn't matter for a single user process + // initialise GraphBLAS + RC ret = init(); + // call graphBLAS algo + if( ret == SUCCESS ) { + // call graphBLAS algo + benchmark< T, U >( grb_program, data_in, data_out, inner, outer, 0 ); + } + // finalise the GraphBLAS + const RC frc = finalize(); + if( ret == SUCCESS ) { + ret = frc; + } + // and done + return ret; + } + + /** No implementation notes. */ + static RC finalize() { + return Launcher< mode, reference >::finalize(); + } + + }; + +} // end namespace ``grb'' + +#endif // end ``_H_GRB_DENSEREF_BENCH'' + diff --git a/include/graphblas/denseref/blas1.hpp b/include/graphblas/denseref/blas1.hpp new file mode 100644 index 000000000..669b2e73f --- /dev/null +++ b/include/graphblas/denseref/blas1.hpp @@ -0,0 +1,31 @@ + +/* + * Copyright 2021 Huawei Technologies Co., Ltd. + * + * 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. + */ + +/* + * @author A. N. Yzelman + * @date 14th of January 2022 + */ + +#ifndef _H_GRB_DENSEREF_BLAS1 +#define _H_GRB_DENSEREF_BLAS1 + +namespace grb { + +} // end namespace ``grb'' + +#endif // end ``_H_GRB_DENSEREF_BLAS1'' + diff --git a/include/graphblas/denseref/blas2.hpp b/include/graphblas/denseref/blas2.hpp new file mode 100644 index 000000000..d185d74b1 --- /dev/null +++ b/include/graphblas/denseref/blas2.hpp @@ -0,0 +1,31 @@ + +/* + * Copyright 2021 Huawei Technologies Co., Ltd. + * + * 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. + */ + +/* + * @author A. N. Yzelman + * @date 14th of January 2022 + */ + +#ifndef _H_GRB_DENSEREF_BLAS2 +#define _H_GRB_DENSEREF_BLAS2 + +namespace grb { + +} // end namespace ``grb'' + +#endif // end ``_H_GRB_DENSEREF_BLAS2'' + diff --git a/include/graphblas/denseref/blas3.hpp b/include/graphblas/denseref/blas3.hpp new file mode 100644 index 000000000..fa4485fee --- /dev/null +++ b/include/graphblas/denseref/blas3.hpp @@ -0,0 +1,31 @@ + +/* + * Copyright 2021 Huawei Technologies Co., Ltd. + * + * 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. + */ + +/* + * @author A. N. Yzelman + * @date 14th of January 2022 + */ + +#ifndef _H_GRB_DENSEREF_BLAS3 +#define _H_GRB_DENSEREF_BLAS3 + +namespace grb { + +} // end namespace ``grb'' + +#endif // end ``_H_GRB_DENSEREF_BLAS3'' + diff --git a/include/graphblas/denseref/collectives.hpp b/include/graphblas/denseref/collectives.hpp new file mode 100644 index 000000000..5f2efa170 --- /dev/null +++ b/include/graphblas/denseref/collectives.hpp @@ -0,0 +1,76 @@ + +/* + * Copyright 2021 Huawei Technologies Co., Ltd. + * + * 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. + */ + +/* + * @author A. N. Yzelman + * @date 14th of January 2022 + */ + +#ifndef _H_GRB_DENSEREF_COLL +#define _H_GRB_DENSEREF_COLL + +namespace grb { + + /** + * \internal Since this backend only has a single user process, the below only + * contains trivial implementations. + */ + template<> + class collectives< reference_dense > { + + private: + + collectives() {} + + public: + + /** \internal Trivial no-op */ + template< Descriptor descr = descriptors::no_operation, + typename OP, typename IOType + > + static RC allreduce( IOType &, const OP &op = OP() ) { + (void)op; + return SUCCESS; + } + + /** \internal Trivial no-op */ + template< Descriptor descr = descriptors::no_operation, + typename OP, typename IOType + > + static RC reduce( IOType &, const size_t root = 0, const OP &op = OP() ) { + assert( root == 0 ); +#ifdef NDEBUG + (void)root; +#endif + return SUCCESS; + } + + template< typename IOType > + static RC broadcast( IOType &, const size_t root = 0 ) { + assert( root == 0 ); +#ifdef NDEBUG + (void)root; +#endif + return SUCCESS; + } + + }; + +} // end namespace ``grb'' + +#endif // end ``_H_GRB_DENSEREF_COLL'' + diff --git a/include/graphblas/denseref/config.hpp b/include/graphblas/denseref/config.hpp new file mode 100644 index 000000000..309920340 --- /dev/null +++ b/include/graphblas/denseref/config.hpp @@ -0,0 +1,54 @@ + +/* + * Copyright 2021 Huawei Technologies Co., Ltd. + * + * 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. + */ + +/** + * @file + * + * Contains the configuration parameters for the reference and reference_omp + * backends. + * + * @author A. N. Yzelman + * @date 14th of January 2022. + */ + +#ifndef _H_GRB_DENSEREF_CONFIG +#define _H_GRB_DENSEREF_CONFIG + +#include + +namespace grb { + + /** + * \defgroup reference The reference backend implementation + * + * Groups all definitions and documentations corresponding to the #reference + * and #reference_omp implementations. + * @{ + */ + + namespace config { + + /** \internal No backend-specific configuration parameters yet */ + + } // namespace config + + /** @} */ + +} // namespace grb + +#endif // end ``_H_GRB_DENSEREF_CONFIG'' + diff --git a/include/graphblas/denseref/exec.hpp b/include/graphblas/denseref/exec.hpp new file mode 100644 index 000000000..516c5e427 --- /dev/null +++ b/include/graphblas/denseref/exec.hpp @@ -0,0 +1,109 @@ + +/* + * Copyright 2021 Huawei Technologies Co., Ltd. + * + * 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. + */ + +/* + * @author A. N. Yzelman + * @date 14th of January 2022 + */ + +#ifndef _H_GRB_DENSEREF_EXEC +#define _H_GRB_DENSEREF_EXEC + +namespace grb { + + /** + * \internal No implementation notes. + */ + template< EXEC_MODE mode > + class Launcher< mode, reference_dense > { + + public: + + /** \internal No implementation notes. */ + Launcher( const size_t process_id = 0, + const size_t nprocs = 0, + const std::string hostname = "localhost", + const std::string port = "0" + ) { + (void) hostname; + (void) port; + if( nprocs != 1 ) { + throw std::invalid_argument( "Total number of user processes must be" + "exactly one when using the reference implementation." ); + } + if( process_id != 0 ) { + throw std::invalid_argument( "Process ID must always be zero in the reference" + "implementation." ); + } + } + + /** \internal No implementation notes. */ + template< typename U > + RC exec( + void ( *grb_program )( const void *, const size_t, U & ), + const void *data_in, const size_t in_size, + U &data_out, + const bool broadcast = false + ) const { + (void)broadcast; // value doesn't matter for a single user process + // intialise GraphBLAS + RC ret = init(); + // call graphBLAS algo + if( ret == SUCCESS ) { + ( *grb_program )( data_in, in_size, data_out ); + } + // finalise the GraphBLAS + if( ret == SUCCESS ) { + ret = finalize(); + } + // and done + return ret; + } + + /** \internal No implementation notes. */ + template< typename T, typename U > + RC exec( + void ( *grb_program )( const T &, U & ), + const T &data_in, U &data_out, + const bool broadcast = false + ) { + (void)broadcast; // value doesn't matter for a single user process + // intialise GraphBLAS + RC ret = init(); + // call graphBLAS algo + if( ret == SUCCESS ) { + ( *grb_program )( data_in, data_out ); + } + // finalise the GraphBLAS + if( ret == SUCCESS ) { + ret = finalize(); + } + // and done + return ret; + } + + /** \internal No implementation notes. */ + static inline RC finalize() { + return SUCCESS; + } + + }; + +} // end namespace ``grb'' + +#endif // end ``_H_GRB_DENSEREF_EXEC'' + diff --git a/include/graphblas/denseref/init.hpp b/include/graphblas/denseref/init.hpp new file mode 100644 index 000000000..a3156a490 --- /dev/null +++ b/include/graphblas/denseref/init.hpp @@ -0,0 +1,41 @@ + +/* + * Copyright 2021 Huawei Technologies Co., Ltd. + * + * 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. + */ + +/* + * @author A. N. Yzelman + * @date 14th of January 2022 + */ + +#ifndef _H_GRB_DENSEREF_INIT +#define _H_GRB_DENSEREF_INIT + +#include + +namespace grb { + + /** \internal No-op init */ + template<> + RC init< reference_dense >( const size_t, const size_t, void * const ); + + /** \internal No-op init */ + template<> + RC finalize< reference_dense >(); + +} // end namespace ``grb'' + +#endif // end ``_H_GRB_DENSEREF_INIT'' + diff --git a/include/graphblas/denseref/io.hpp b/include/graphblas/denseref/io.hpp new file mode 100644 index 000000000..137a0b7a6 --- /dev/null +++ b/include/graphblas/denseref/io.hpp @@ -0,0 +1,31 @@ + +/* + * Copyright 2021 Huawei Technologies Co., Ltd. + * + * 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. + */ + +/* + * @author A. N. Yzelman + * @date 14th of January 2022 + */ + +#ifndef _H_GRB_DENSEREF_IO +#define _H_GRB_DENSEREF_IO + +namespace grb { + +} // end namespace ``grb'' + +#endif // end ``_H_GRB_DENSEREF_IO'' + diff --git a/include/graphblas/denseref/matrix.hpp b/include/graphblas/denseref/matrix.hpp new file mode 100644 index 000000000..a74ef2efb --- /dev/null +++ b/include/graphblas/denseref/matrix.hpp @@ -0,0 +1,36 @@ + +/* + * Copyright 2021 Huawei Technologies Co., Ltd. + * + * 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. + */ + +/* + * @author A. N. Yzelman + * @date 14th of January 2022 + */ + +#ifndef _H_GRB_DENSEREF_MATRIX +#define _H_GRB_DENSEREF_MATRIX + +namespace grb { + + /** \internal TODO */ + template< typename T > + class Matrix< T, reference_dense > { + }; + +} // end namespace ``grb'' + +#endif // end ``_H_GRB_DENSEREF_MATRIX'' + diff --git a/include/graphblas/denseref/pinnedvector.hpp b/include/graphblas/denseref/pinnedvector.hpp new file mode 100644 index 000000000..8636cf52d --- /dev/null +++ b/include/graphblas/denseref/pinnedvector.hpp @@ -0,0 +1,31 @@ + +/* + * Copyright 2021 Huawei Technologies Co., Ltd. + * + * 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. + */ + +/* + * @author A. N. Yzelman + * @date 14th of January 2022 + */ + +#ifndef _H_GRB_DENSEREF_PINNEDVECTOR +#define _H_GRB_DENSEREF_PINNEDVECTOR + +namespace grb { + +} // end namespace ``grb'' + +#endif // end ``_H_GRB_DENSEREF_PINNEDVECTOR'' + diff --git a/include/graphblas/denseref/properties.hpp b/include/graphblas/denseref/properties.hpp new file mode 100644 index 000000000..03ae2df95 --- /dev/null +++ b/include/graphblas/denseref/properties.hpp @@ -0,0 +1,41 @@ + +/* + * Copyright 2021 Huawei Technologies Co., Ltd. + * + * 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. + */ + +/* + * @author A. N. Yzelman + * @date 14th of January 2022 + */ + +#ifndef _H_GRB_DENSEREF_PROPERTIES +#define _H_GRB_DENSEREF_PROPERTIES + +#include + +namespace grb { + + /** \internal No implementation notes. */ + template<> + class Properties< reference_dense > { + public: + /** No implementation notes. */ + constexpr static bool writableCaptured = true; + }; + +} // namespace grb + +#endif // end `_H_GRB_DENSEREF_PROPERTIES'' + diff --git a/include/graphblas/denseref/spmd.hpp b/include/graphblas/denseref/spmd.hpp new file mode 100644 index 000000000..dacb5fae1 --- /dev/null +++ b/include/graphblas/denseref/spmd.hpp @@ -0,0 +1,70 @@ + +/* + * Copyright 2021 Huawei Technologies Co., Ltd. + * + * 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. + */ + +/* + * @author A. N. Yzelman + * @date 14th of January, 2022 + */ + +#ifndef _H_GRB_DENSEREF_SPMD +#define _H_GRB_DENSEREF_SPMD + +#include //size_t + +#include + +namespace grb { + + /** \internal This is a single-process back-end. */ + template<> + class spmd< reference_dense > { + + public: + + /** + * @return The number of user processes in this GraphBLAS run. + * + * In this single-process backend, will always return 1. + */ + static inline size_t nprocs() noexcept { + return 1; + } + + /** + * @return The user process ID. + * + * In this single-process backend, will always return 0. + */ + static inline size_t pid() noexcept { + return 0; + } + + /** + * In this backend, corresponds to a no-op. + * + * @return grb::SUCCESS. + */ + static RC barrier() noexcept { + return SUCCESS; + } + + }; // end class ``spmd'' reference_dense implementation + +} // namespace grb + +#endif // end _H_GRB_DENSEREF_SPMD + diff --git a/include/graphblas/denseref/vector.hpp b/include/graphblas/denseref/vector.hpp new file mode 100644 index 000000000..2fe9aa52f --- /dev/null +++ b/include/graphblas/denseref/vector.hpp @@ -0,0 +1,36 @@ + +/* + * Copyright 2021 Huawei Technologies Co., Ltd. + * + * 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. + */ + +/* + * @author A. N. Yzelman + * @date 14th of January 2022 + */ + +#ifndef _H_GRB_DENSEREF_VECTOR +#define _H_GRB_DENSEREF_VECTOR + +namespace grb { + + /** \internal TODO */ + template< typename T > + class Vector< T, reference_dense, void > { + }; + +} // end namespace ``grb'' + +#endif // end ``_H_GRB_DENSEREF_VECTOR'' + diff --git a/include/graphblas/distribution.hpp b/include/graphblas/distribution.hpp index 845400337..c11d083de 100644 --- a/include/graphblas/distribution.hpp +++ b/include/graphblas/distribution.hpp @@ -26,10 +26,10 @@ #include "base/distribution.hpp" #ifdef _GRB_WITH_LPF -#include "graphblas/bsp1d/distribution.hpp" + #include "graphblas/bsp1d/distribution.hpp" #endif #ifdef _GRB_WITH_BANSHEE -#include "graphblas/banshee/distribution.hpp" + #include "graphblas/banshee/distribution.hpp" #endif #endif // end `_H_GRB_DISTRIBUTION' diff --git a/include/graphblas/exec.hpp b/include/graphblas/exec.hpp index 22a5bc422..6a5b74b6d 100644 --- a/include/graphblas/exec.hpp +++ b/include/graphblas/exec.hpp @@ -28,13 +28,14 @@ // include template specialisations #ifdef _GRB_WITH_REFERENCE -#include "graphblas/reference/exec.hpp" + #include "graphblas/reference/exec.hpp" + #include "graphblas/denseref/exec.hpp" #endif #ifdef _GRB_WITH_LPF -#include "graphblas/bsp1d/exec.hpp" + #include "graphblas/bsp1d/exec.hpp" #endif #ifdef _GRB_WITH_BANSHEE -#include "graphblas/banshee/exec.hpp" + #include "graphblas/banshee/exec.hpp" #endif #ifdef _GRB_BACKEND diff --git a/include/graphblas/init.hpp b/include/graphblas/init.hpp index 2b1af0a52..819ee59aa 100644 --- a/include/graphblas/init.hpp +++ b/include/graphblas/init.hpp @@ -30,6 +30,7 @@ // include all implementations #ifdef _GRB_WITH_REFERENCE #include "graphblas/reference/init.hpp" + #include "graphblas/denseref/init.hpp" #endif #ifdef _GRB_WITH_LPF #include "graphblas/bsp1d/init.hpp" diff --git a/include/graphblas/io.hpp b/include/graphblas/io.hpp index 9d09b95d2..dfcdd3e44 100644 --- a/include/graphblas/io.hpp +++ b/include/graphblas/io.hpp @@ -28,6 +28,7 @@ // now include all specialisations contained in the backend directories: #ifdef _GRB_WITH_REFERENCE #include + #include #endif #ifdef _GRB_WITH_LPF #include diff --git a/include/graphblas/matrix.hpp b/include/graphblas/matrix.hpp index 08d715df5..59ff28cf0 100644 --- a/include/graphblas/matrix.hpp +++ b/include/graphblas/matrix.hpp @@ -29,6 +29,7 @@ // now include all specialisations contained in the backend directories: #ifdef _GRB_WITH_REFERENCE #include + #include #endif #ifdef _GRB_WITH_LPF #include diff --git a/include/graphblas/pinnedvector.hpp b/include/graphblas/pinnedvector.hpp index 8e24582d2..e092d241e 100644 --- a/include/graphblas/pinnedvector.hpp +++ b/include/graphblas/pinnedvector.hpp @@ -32,13 +32,14 @@ // now include all specialisations contained in the backend directories: #ifdef _GRB_WITH_REFERENCE -#include + #include + #include #endif #ifdef _GRB_WITH_LPF -#include + #include #endif #ifdef _GRB_WITH_BANSHEE -#include + #include #endif // specify default only if requested during compilation diff --git a/include/graphblas/properties.hpp b/include/graphblas/properties.hpp index 1349e637e..49663d30a 100644 --- a/include/graphblas/properties.hpp +++ b/include/graphblas/properties.hpp @@ -28,13 +28,14 @@ // now include all specialisations contained in the backend directories: #ifdef _GRB_WITH_REFERENCE -#include + #include + #include #endif #ifdef _GRB_WITH_LPF -#include + #include #endif #ifdef _GRB_WITH_BANSHEE -#include + #include #endif // specify default only if requested during compilation diff --git a/include/graphblas/spmd.hpp b/include/graphblas/spmd.hpp index eab1b78b9..5eb01f39a 100644 --- a/include/graphblas/spmd.hpp +++ b/include/graphblas/spmd.hpp @@ -27,13 +27,14 @@ #include "base/spmd.hpp" #ifdef _GRB_WITH_REFERENCE -#include "graphblas/reference/spmd.hpp" + #include "graphblas/reference/spmd.hpp" + #include "graphblas/denseref/spmd.hpp" #endif #ifdef _GRB_WITH_LPF -#include "graphblas/bsp1d/spmd.hpp" + #include "graphblas/bsp1d/spmd.hpp" #endif #ifdef _GRB_WITH_BANSHEE -#include "graphblas/banshee/spmd.hpp" + #include "graphblas/banshee/spmd.hpp" #endif // specify default only if requested during compilation diff --git a/include/graphblas/vector.hpp b/include/graphblas/vector.hpp index 26a88fb00..8d06ea342 100644 --- a/include/graphblas/vector.hpp +++ b/include/graphblas/vector.hpp @@ -30,6 +30,7 @@ // now include all specialisations contained in the backend directories: #ifdef _GRB_WITH_REFERENCE #include + #include #endif #ifdef _GRB_WITH_LPF #include From f266c103d4de8e6ee63a2b5d5dd67099a4401831 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Fri, 14 Jan 2022 15:57:07 +0100 Subject: [PATCH 002/282] Issue #303: unify script argument similar to --no-reference --- bootstrap.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bootstrap.sh b/bootstrap.sh index e0f8850c4..37678f2e3 100755 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -73,7 +73,7 @@ print_help() { the location where LPF is installed" echo " --with-banshee= - path to the the tools to compile the banshee backend" echo " --with-snitch= - path to the tools for Snitch support within the banshee backend" - echo " --without-dense - to compile without support for dense algebraic programming" + echo " --no-dense - to compile without support for dense algebraic programming" echo " --no-reference - disables the reference and reference_omp backends" echo " --debug-build - build the project with debug options (tests will run much slower!)" echo " --generator= - set the generator for CMake (otherwise use CMake's default)" @@ -145,7 +145,7 @@ or assume default paths (--with-lpf)" SNITCH_PATH="${arg#--with-snitch=}" banshee=yes ;; - --without-dense) + --no-dense) dense=no ;; --no-reference) From f7359c1b24924d208adbd1933acc2a74dd648b5d Mon Sep 17 00:00:00 2001 From: Anonymous Date: Fri, 14 Jan 2022 17:01:01 +0100 Subject: [PATCH 003/282] Issue #303: complete implementation of Vector< reference_dense >, modulo output iteration. --- include/graphblas/denseref/vector.hpp | 123 ++++++++++++++++++++++++++ 1 file changed, 123 insertions(+) diff --git a/include/graphblas/denseref/vector.hpp b/include/graphblas/denseref/vector.hpp index 2fe9aa52f..af1359d94 100644 --- a/include/graphblas/denseref/vector.hpp +++ b/include/graphblas/denseref/vector.hpp @@ -23,13 +23,136 @@ #ifndef _H_GRB_DENSEREF_VECTOR #define _H_GRB_DENSEREF_VECTOR +#include +#include +#include + +#include + +#include + + namespace grb { + namespace internal { + + template< typename T > + T * getRaw( Vector< T, reference_dense, void > & ) noexcept; + + template< typename T > + const T * getRaw( Vector< T, reference_dense, void > & ) noexcept; + + template< typename T > + size_t getLength( const Vector< T, reference_dense, void > & ) noexcept; + + } // end namespace ``grb::internal'' + /** \internal TODO */ template< typename T > class Vector< T, reference_dense, void > { + + friend T * internal::getRaw< T >( Vector< T, reference_dense, void > & ) noexcept; + friend const T * internal::getRaw< T >( const Vector< T, reference_dense, void > & ) noexcept; + friend size_t internal::getLength< T >( const Vector< T, reference_dense, void > & ) noexcept; + + private: + + /** The length of the vector. */ + size_t n; + + /** The vector data. */ + T *__restrict__ data; + + /** Deleter corresponding to #data. */ + utils::AutoDeleter< T > data_deleter; + + + public: + + /** Exposes the element type. */ + typedef T value_type; + + /** The return type of #operator[](). */ + typedef T& lambda_reference; + + /** + * @param[in] length The requested vector length. + * + * \internal Allocates a single array of size \a length. + */ + Vector( const size_t length ) : n( length ) { + const RC rc = grb::utils::alloc( + "grb::Vector< T, reference_dense > (constructor)", "", + data, length, true, data_deleter + ); + if( rc == OUTOFMEM ) { + throw std::runtime_error( "Out-of-memory during Vector< T, reference_dense > construction" ); + } else if( rc != SUCCESS ) { + throw std::runtime_error( "Unhandled runtime error during Vector< T, reference_dense > construction " ); + } + } + + /** \internal Simply calls Vector( 0 ). */ + Vector() : Vector( 0 ) {} + + /** \internal Makes a deep copy of \a other. */ + Vector( const Vector< T, reference_dense, void > &other ) : Vector( other.n ) { + const RC rc = set( *this, other ); + if( rc != SUCCESS ) { + throw std::runtime_error( "grb::Vector< T, reference_dense > (copy constructor): error during call to grb::set (" + toString( rc ) + ")" ); + } + } + + /** \internal No implementation notes. */ + Vector( Vector< T, reference_dense, void > &&other ) { + n = other.n; other.n = 0; + data = other.data; other.data = 0; + } + + /** \internal No implementation notes. */ + ~Vector() { + n = 0; + // free of data will be handled by #data_deleter + } + + /** \internal No implementation notes. */ + lambda_reference operator[]( const size_t i ) noexcept { + assert( i < n ); + return data[ i ]; + } + + /** \internal No implementation notes. */ + const lambda_reference operator[]( const size_t i ) const noexcept { + assert( i < n ); + return data[ i ]; + } }; + template< typename T > + struct is_container< Vector< T, reference_dense, void > > { + /** A reference_vector is an ALP object. */ + static const constexpr bool value = true; + }; + + namespace internal { + + template< typename T > + T * getRaw( Vector< T, reference_dense, void > &v ) noexcept { + return v.data; + } + + template< typename T > + const T * getRaw( Vector< T, reference_dense, void > &v ) noexcept { + return v.data; + } + + template< typename T > + size_t getLength( const Vector< T, reference_dense, void > &v ) noexcept { + return v.n; + } + + } // end namespace ``grb::internal'' + } // end namespace ``grb'' #endif // end ``_H_GRB_DENSEREF_VECTOR'' From 151ca6bb811f8355c09e3cebac60eecdd54ae3ed Mon Sep 17 00:00:00 2001 From: Anonymous Date: Mon, 17 Jan 2022 11:54:21 +0100 Subject: [PATCH 004/282] Issue #303: modified vector implementation according to option 3 in handling dense container construction. --- include/graphblas/denseref/vector.hpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/include/graphblas/denseref/vector.hpp b/include/graphblas/denseref/vector.hpp index af1359d94..956e87197 100644 --- a/include/graphblas/denseref/vector.hpp +++ b/include/graphblas/denseref/vector.hpp @@ -66,6 +66,9 @@ namespace grb { /** Deleter corresponding to #data. */ utils::AutoDeleter< T > data_deleter; + /** Whether the container presently is empty (uninitialized). */ + bool empty; + public: @@ -80,7 +83,7 @@ namespace grb { * * \internal Allocates a single array of size \a length. */ - Vector( const size_t length ) : n( length ) { + Vector( const size_t length ) : n( length ), empty( true ) { const RC rc = grb::utils::alloc( "grb::Vector< T, reference_dense > (constructor)", "", data, length, true, data_deleter @@ -97,7 +100,8 @@ namespace grb { /** \internal Makes a deep copy of \a other. */ Vector( const Vector< T, reference_dense, void > &other ) : Vector( other.n ) { - const RC rc = set( *this, other ); + empty = true; + const RC rc = set( *this, other ); // note: empty will be set to false as part of this call if( rc != SUCCESS ) { throw std::runtime_error( "grb::Vector< T, reference_dense > (copy constructor): error during call to grb::set (" + toString( rc ) + ")" ); } @@ -107,23 +111,28 @@ namespace grb { Vector( Vector< T, reference_dense, void > &&other ) { n = other.n; other.n = 0; data = other.data; other.data = 0; + data_deleter = std::move( other.data_deleter ); + empty = other.empty; other.empty = true; } /** \internal No implementation notes. */ ~Vector() { n = 0; + empty = true; // free of data will be handled by #data_deleter } /** \internal No implementation notes. */ lambda_reference operator[]( const size_t i ) noexcept { assert( i < n ); + assert( !empty ); return data[ i ]; } /** \internal No implementation notes. */ const lambda_reference operator[]( const size_t i ) const noexcept { assert( i < n ); + assert( !empty ); return data[ i ]; } }; From 33195882d0fe7bf453c5173894190e7652c74e21 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Mon, 17 Jan 2022 13:00:37 +0100 Subject: [PATCH 005/282] Issue #303: vectors now have an iterator for the user to extract data from. --- include/graphblas/denseref/vector.hpp | 27 +++ include/graphblas/denseref/vectoriterator.hpp | 225 ++++++++++++++++++ 2 files changed, 252 insertions(+) create mode 100644 include/graphblas/denseref/vectoriterator.hpp diff --git a/include/graphblas/denseref/vector.hpp b/include/graphblas/denseref/vector.hpp index 956e87197..d6a44fb39 100644 --- a/include/graphblas/denseref/vector.hpp +++ b/include/graphblas/denseref/vector.hpp @@ -27,6 +27,8 @@ #include #include +#include + #include #include @@ -78,6 +80,9 @@ namespace grb { /** The return type of #operator[](). */ typedef T& lambda_reference; + /** The iterator type. */ + typedef typename internal::ConstDenserefVectorIterator< T, reference_dense > const_iterator; + /** * @param[in] length The requested vector length. * @@ -135,8 +140,30 @@ namespace grb { assert( !empty ); return data[ i ]; } + + /** \internal Relies on #internal::ConstDenserefVectorIterator. */ + const_iterator cbegin() const noexcept { + return const_iterator( data, n, false ); + } + + /** \internal Relies on #internal::ConstDenserefVectorIterator. */ + const_iterator begin() const noexcept { + return cbegin(); + } + + /** \internal Relies on #internal::ConstDenserefVectorIterator. */ + const_iterator cend() const noexcept { + return const_iterator( data, n, true ); + } + + /** \internal Relies on #internal::ConstDenserefVectorIterator. */ + const_iterator end() const noexcept { + return cend(); + } + }; + /** Identifies any reference_dense vector as an ALP vector. */ template< typename T > struct is_container< Vector< T, reference_dense, void > > { /** A reference_vector is an ALP object. */ diff --git a/include/graphblas/denseref/vectoriterator.hpp b/include/graphblas/denseref/vectoriterator.hpp new file mode 100644 index 000000000..b3a89cf35 --- /dev/null +++ b/include/graphblas/denseref/vectoriterator.hpp @@ -0,0 +1,225 @@ + +/* + * Copyright 2021 Huawei Technologies Co., Ltd. + * + * 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. + */ + +/* + * @author A. N. Yzelman + * @date 17th of January, 2022 + */ + +#ifndef _H_GRB_DENSEREF_VECTOR_ITERATOR +#define _H_GRB_DENSEREF_VECTOR_ITERATOR + +#include + +#include + + +namespace grb { + + namespace internal { + + template< typename T, Backend spmd_backend = reference_dense > + class ConstDenserefVectorIterator : public std::iterator< + std::random_access_iterator_tag, + std::pair< const size_t, const T >, + size_t + > { + friend class Vector< T, reference_dense, void >; + + private: + + using ActiveDistribution = internal::Distribution< spmd_backend >; + + const T *__restrict__ data; + + size_t pos; + + size_t n; + + size_t s; + + size_t P; + + std::pair< size_t, T > currentEntry; + + ConstDenserefVectorIterator( + const T * const data_in, const size_t n_in, const bool end, + const size_t processID = 0, const size_t numProcesses = 1 + ) noexcept : + data( data_in ), pos( 0 ), n( n_in ), + s( processID ), P( numProcesses ) + { + assert( P > 0 ); + assert( s < P ); + if( !end ) { + pos = 0; + if( n > 0 ) { + currentEntry.first = 0; + currentEntry.second = data[ 0 ]; + } + } else { + pos = n; + } + } + + ConstDenserefVectorIterator( const T * const data_in, + const size_t pos_in, const size_t n_in, + const size_t s_in, const size_t P_in + ) noexcept : data( data_in ), pos( pos_in ), n( n_in ), + s( s_in ), P( P_in ) + { + if( pos < n && n > 0 ) { + currentEntry.first = pos; + currentEntry.second = data[ pos ]; + } + } + + + public: + + ConstDenserefVectorIterator() noexcept : + ConstDenserefVectorIterator( nullptr, 0, true ) + {} + + ConstDenserefVectorIterator( const ConstDenserefVectorIterator< T, spmd_backend > &other ) noexcept : + data( other.data ), pos( other.pos ), n( other.n ), + s( other.s ), P( other.P ), + currentEntry( other.currentEntry ) + {} + + ConstDenserefVectorIterator( ConstDenserefVectorIterator< T, spmd_backend > &&other ) noexcept : + data( other.data ), pos( other.pos ), n( other.n ), + s( other.s ), P( other.P ) + { + other.data = nullptr; other.pos = 0; other.n = 0; + currentEntry = std::move( other.currentEntry ); + } + + ConstDenserefVectorIterator< T, spmd_backend >& operator=( const ConstDenserefVectorIterator< T, spmd_backend > &other ) noexcept { + data = other.data; pos = other.pos; n = other.n; + assert( s == other.s ); assert( P == other.P ); + currentEntry = other.currentEntry; + return *this; + } + + ConstDenserefVectorIterator< T, spmd_backend >& operator=( ConstDenserefVectorIterator< T, spmd_backend > &&other ) noexcept { + data = other.data; other.data = nullptr; + pos = other.pos; other.pos = 0; + n = other.n; other.n = 0; + assert( s == other.s ); assert( P == other.P ); + currentEntry = std::move( other.currentEntry ); + return *this; + } + + bool operator==( const ConstDenserefVectorIterator< T, spmd_backend > &other ) const noexcept { + assert( data == other.data ); assert( n == other.n ); + assert( s == other.s ); assert( P == other.P ); + return pos == other.pos; + } + + bool operator!=( const ConstDenserefVectorIterator< T, spmd_backend > &other ) const noexcept { + assert( data == other.data ); assert( n == other.n ); + assert( s == other.s ); assert( P == other.P ); + return pos != other.pos; + } + + bool operator<( const ConstDenserefVectorIterator< T, spmd_backend > &other ) const noexcept { + assert( data == other.data ); assert( n == other.n ); + assert( s == other.s ); assert( P == other.P ); + return pos < other.pos; + } + + std::pair< const size_t, const T > operator[]( const size_t i ) { + assert( pos + i < n ); + assert( n > 0 ); + std::pair< size_t, T > ret; + ret.first = pos + i; + ret.second = data[ pos + i ]; + return ret; + } + + std::pair< const size_t, const T >& operator*() const noexcept { + assert( n > 0 ); + assert( pos < n ); + return currentEntry; + } + + const std::pair< size_t, T >* operator->() const noexcept { + assert( n > 0 ); + assert( pos < n ); + return ¤tEntry; + } + + ConstDenserefVectorIterator< T, spmd_backend >& operator+=( const size_t i ) noexcept { + assert( pos + i <= n ); + pos = std::max( n, pos + i ); + if( n > 0 && pos < n ) { + currentEntry.first = pos; + currentEntry.second = data[ pos ]; + } + return *this; + } + + ConstDenserefVectorIterator< T, spmd_backend >& operator-=( const size_t i ) noexcept { + assert( i >= pos ); + if( i > pos ) { + pos = n; + } else { + pos -= i; + } + assert( pos <= n ); + if( n > 0 && pos < n ) { + currentEntry.first = pos; + currentEntry.second = data[ pos ]; + } + return *this; + } + + ConstDenserefVectorIterator< T, spmd_backend >& operator++() noexcept { + return operator+=( 1 ); + } + + ConstDenserefVectorIterator< T, spmd_backend >& operator--() noexcept { + return operator-=( 1 ); + } + + ConstDenserefVectorIterator< T, spmd_backend > operator+( const ConstDenserefVectorIterator< T, spmd_backend > &other ) noexcept { + assert( data == other.data ); + assert( pos + other.pos < n ); + assert( n == other.n ); + assert( s == other.s ); assert( P == other.P ); + const size_t newPos = std::max( pos + other.pos, n ); + return ConstDenserefVectorIterator< T, spmd_backend >( data, pos, n, s, P ); + } + + ConstDenserefVectorIterator< T, spmd_backend > operator-( const ConstDenserefVectorIterator< T, spmd_backend > &other ) noexcept { + assert( data == other.data ); + assert( pos >= other.pos ); + assert( n == other.n ); + assert( s == other.s ); assert( P == other.P ); + const size_t newPos = pos >= other.pos ? pos - other.pos : n; + return ConstDenserefVectorIterator< T, spmd_backend >( data, pos, n, s, P ); + } + + }; + + } // end namespace ``grb::internal'' + +} // end namespace ``grb'' + +#endif // end ``_H_GRB_DENSEREF_VECTOR_ITERATOR'' + From f9241be946c110c2bfaf66d4dcc36ecadd74f9c8 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Mon, 17 Jan 2022 13:52:06 +0100 Subject: [PATCH 006/282] Issue #303, fixed silly oops: the difference between two iterators should be an integer --- include/graphblas/denseref/vectoriterator.hpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/include/graphblas/denseref/vectoriterator.hpp b/include/graphblas/denseref/vectoriterator.hpp index b3a89cf35..868290a87 100644 --- a/include/graphblas/denseref/vectoriterator.hpp +++ b/include/graphblas/denseref/vectoriterator.hpp @@ -206,13 +206,16 @@ namespace grb { return ConstDenserefVectorIterator< T, spmd_backend >( data, pos, n, s, P ); } - ConstDenserefVectorIterator< T, spmd_backend > operator-( const ConstDenserefVectorIterator< T, spmd_backend > &other ) noexcept { + ptrdiff_t operator-( const ConstDenserefVectorIterator< T, spmd_backend > &other ) noexcept { assert( data == other.data ); assert( pos >= other.pos ); assert( n == other.n ); assert( s == other.s ); assert( P == other.P ); - const size_t newPos = pos >= other.pos ? pos - other.pos : n; - return ConstDenserefVectorIterator< T, spmd_backend >( data, pos, n, s, P ); + if( pos >= other.pos ) { + return static_cast< ptrdiff_t >( pos - other.pos ); + } else { + return -static_cast< ptrdiff_t >( other.pos - pos ); + } } }; From 7839a779735703603bc681b77241d43fdfbc5746 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Mon, 17 Jan 2022 13:55:39 +0100 Subject: [PATCH 007/282] Issue #303: containers are now uninitialized on construction. Iteration over uninitialized containers returns nothing. --- include/graphblas/denseref/vector.hpp | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/include/graphblas/denseref/vector.hpp b/include/graphblas/denseref/vector.hpp index d6a44fb39..22326de19 100644 --- a/include/graphblas/denseref/vector.hpp +++ b/include/graphblas/denseref/vector.hpp @@ -68,8 +68,8 @@ namespace grb { /** Deleter corresponding to #data. */ utils::AutoDeleter< T > data_deleter; - /** Whether the container presently is empty (uninitialized). */ - bool empty; + /** Whether the container presently is uninitialized. */ + bool initialized; public: @@ -88,7 +88,7 @@ namespace grb { * * \internal Allocates a single array of size \a length. */ - Vector( const size_t length ) : n( length ), empty( true ) { + Vector( const size_t length ) : n( length ), initialized( false ) { const RC rc = grb::utils::alloc( "grb::Vector< T, reference_dense > (constructor)", "", data, length, true, data_deleter @@ -105,8 +105,8 @@ namespace grb { /** \internal Makes a deep copy of \a other. */ Vector( const Vector< T, reference_dense, void > &other ) : Vector( other.n ) { - empty = true; - const RC rc = set( *this, other ); // note: empty will be set to false as part of this call + initialized = false; + const RC rc = set( *this, other ); // note: initialized will be set as part of this call if( rc != SUCCESS ) { throw std::runtime_error( "grb::Vector< T, reference_dense > (copy constructor): error during call to grb::set (" + toString( rc ) + ")" ); } @@ -117,33 +117,35 @@ namespace grb { n = other.n; other.n = 0; data = other.data; other.data = 0; data_deleter = std::move( other.data_deleter ); - empty = other.empty; other.empty = true; + initialized = other.initialized; other.initialized = false; } /** \internal No implementation notes. */ ~Vector() { n = 0; - empty = true; + initialized = false; // free of data will be handled by #data_deleter } /** \internal No implementation notes. */ lambda_reference operator[]( const size_t i ) noexcept { assert( i < n ); - assert( !empty ); + assert( initialized ); return data[ i ]; } /** \internal No implementation notes. */ const lambda_reference operator[]( const size_t i ) const noexcept { assert( i < n ); - assert( !empty ); + assert( initialized ); return data[ i ]; } /** \internal Relies on #internal::ConstDenserefVectorIterator. */ const_iterator cbegin() const noexcept { - return const_iterator( data, n, false ); + return initialized ? + const_iterator( data, n, false ) : + const_iterator( nullptr, 0, false ); } /** \internal Relies on #internal::ConstDenserefVectorIterator. */ @@ -153,7 +155,9 @@ namespace grb { /** \internal Relies on #internal::ConstDenserefVectorIterator. */ const_iterator cend() const noexcept { - return const_iterator( data, n, true ); + return initialized ? + const_iterator( data, n, true ) : + const_iterator( nullptr, 0, true ); } /** \internal Relies on #internal::ConstDenserefVectorIterator. */ From bff6cb18625594dc04b83ba1d973fa4b5cc40a22 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Mon, 17 Jan 2022 14:18:49 +0100 Subject: [PATCH 008/282] Issue #303: configure and cmake now properly do make install with reference_dense --- bootstrap.sh | 2 ++ cmake/AddGRBVars.cmake | 4 +++- src/graphblas/reference/CMakeLists.txt | 4 ++++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/bootstrap.sh b/bootstrap.sh index 37678f2e3..25c81da93 100755 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -294,6 +294,8 @@ the current directory before invocation or confirm the deletion of its content w fi if [[ "${dense}" == "no" ]]; then CMAKE_OPTS+=" -DWITH_DENSE_BACKEND=OFF" + else + CMAKE_OPTS+=" -DWITH_DENSE_BACKEND=ON" fi if [[ "${lpf}" == "yes" ]]; then CMAKE_OPTS+=" -DLPF_INSTALL_PATH='${ABSOLUTE_LPF_INSTALL_PATH}'" diff --git a/cmake/AddGRBVars.cmake b/cmake/AddGRBVars.cmake index 298a7574a..9eca8dbe8 100644 --- a/cmake/AddGRBVars.cmake +++ b/cmake/AddGRBVars.cmake @@ -45,6 +45,7 @@ set( DENSE_INCLUDE_DEFS "_GRB_WITH_DENSEREF" ) # compiler definitions to select a backend set( REFERENCE_SELECTION_DEFS "_GRB_BACKEND=reference" ) set( REFERENCE_OMP_SELECTION_DEFS "_GRB_BACKEND=reference_omp" ) +set( DENSE_SELECTION_DEFS "_GRB_BACKEND=reference_dense" ) set( BSP1D_SELECTION_DEFS "_GRB_BACKEND=BSP1D" "_GRB_BSP1D_BACKEND=reference" @@ -53,7 +54,6 @@ set( HYBRID_SELECTION_DEFS "_GRB_BACKEND=BSP1D" "_GRB_BSP1D_BACKEND=reference_omp" ) -set( DENSE_SELECTION_DEFS "_GRB_BACKEND=reference_dense" ) # definition to set if not depending on libnuma set( NO_NUMA_DEF "_GRB_NO_LIBNUMA" ) @@ -90,5 +90,7 @@ if( WITH_HYBRID_BACKEND ) list( APPEND AVAILABLE_BACKENDS "hybrid" ) endif() +message( STATUS "\n######### Configured with the following backends: #########\n${AVAILABLE_BACKENDS}\n" ) + # add your own here! diff --git a/src/graphblas/reference/CMakeLists.txt b/src/graphblas/reference/CMakeLists.txt index 9f99364e5..3bb12fa83 100644 --- a/src/graphblas/reference/CMakeLists.txt +++ b/src/graphblas/reference/CMakeLists.txt @@ -26,6 +26,7 @@ assert_valid_variables( BACKEND_LIBRARY_OUTPUT_NAME VERSION SHMEM_BACKEND_INSTALL_DIR INCLUDE_INSTALL_DIR REFERENCE_BACKEND_DEFAULT_NAME REFERENCE_OMP_BACKEND_DEFAULT_NAME REFERENCE_SELECTION_DEFS REFERENCE_OMP_SELECTION_DEFS backend_reference_srcs + DENSE_BACKEND_DEFAULT_NAME DENSE_SELECTION_DEFS ) assert_defined_targets( backend_flags ) @@ -150,6 +151,9 @@ if( WITH_REFERENCE_BACKEND ) endif( WITH_REFERENCE_BACKEND ) +if( WITH_DENSE_BACKEND ) + add_library( "${DENSE_BACKEND_DEFAULT_NAME}" ALIAS backend_reference_static ) +endif( WITH_DENSE_BACKEND ) if( WITH_OMP_BACKEND ) From 342795647aa092bb18f60db33184704743866e4c Mon Sep 17 00:00:00 2001 From: Anonymous Date: Sun, 30 Jan 2022 14:01:19 +0100 Subject: [PATCH 009/282] Issue #303: cmake infra has updated-- make dense_reference additions compatible to it --- include/CMakeLists.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt index aeb2e10a2..d1e163171 100644 --- a/include/CMakeLists.txt +++ b/include/CMakeLists.txt @@ -120,12 +120,12 @@ endif() if( WITH_DENSE_BACKEND ) add_library( backend_reference_dense_headers INTERFACE ) target_link_libraries( backend_reference_dense_headers INTERFACE backend_headers_nodefs ) + target_compile_definitions( backend_reference_dense_headers INTERFACE "${DENSEREF_INCLUDE_DEFS}" ) + install( TARGETS backend_reference_dense_headers EXPORT GraphBLASTargets ) install( DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/graphblas/denseref" - DESTINATION "${GRB_INCLUDE_INSTALL_DIR}" + DESTINATION "${GRB_INCLUDE_INSTALL_DIR}/denseref" FILES_MATCHING REGEX "${HEADERS_REGEX}" ) - install( TARGETS backend_reference_dense_headers EXPORT GraphBLASTargets ) - target_link_libraries( all_headers INTERFACE backend_reference_dense_headers ) endif() if( WITH_REFERENCE_BACKEND OR WITH_OMP_BACKEND ) From 3d100b66ebc028b3f735db57d6439f2a319439e5 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Wed, 2 Feb 2022 10:23:26 +0100 Subject: [PATCH 010/282] Drafting structured matrix interface using reference_dense backend --- .gitignore | 2 + include/graphblas/base/matrix.hpp | 80 +++++++++++++++++++ include/graphblas/matrix.hpp | 16 ++-- include/graphblas/storage.hpp | 81 +++++++++++++++++++ include/graphblas/structures.hpp | 127 ++++++++++++++++++++++++++++++ include/graphblas/views.hpp | 61 ++++++++++++++ 6 files changed, 362 insertions(+), 5 deletions(-) create mode 100644 include/graphblas/storage.hpp create mode 100644 include/graphblas/structures.hpp create mode 100644 include/graphblas/views.hpp diff --git a/.gitignore b/.gitignore index 389c37143..48db90670 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,5 @@ doxygen.log /lib/ flags.mk paths.mk +/build*/ +.vscode/ \ No newline at end of file diff --git a/include/graphblas/base/matrix.hpp b/include/graphblas/base/matrix.hpp index 2744a7434..acc0ee0c5 100644 --- a/include/graphblas/base/matrix.hpp +++ b/include/graphblas/base/matrix.hpp @@ -33,6 +33,10 @@ #include #include #include +#include +#include +#include +#include namespace grb { @@ -426,6 +430,82 @@ namespace grb { }; +/** + * An ALP structured matrix. + * + * This is an opaque data type for that implements the below functions. + * + * @tparam T The type of the matrix elements. \a T shall not be a GraphBLAS + * type. + * @tparam Structure One of the matrix structures in grb::structures. + * @tparam view One of the matrix views in enum grb::Views. All static views except for + * \a Views::original disable the possibility to instantiate a new container and only + * allow the creation of a reference to an existing \a StructuredMatrix + * (note that this could be view itself). A view could be instanciated into a separate container + * than its original source by explicit copy. + * @tparam backend Allows multiple backends to implement different + * versions of this data type. + * + * \note The presence of different combination of structures and views could produce many specialization + * with lots of logic replication. + */ +template< typename T, typename Structure, typename StorageSchemeType, typename View, enum Backend backend > +class StructuredMatrix { + + size_t m, n; + + /** + * The container's data. + * The geometry and access scheme are specified by a combination of + * \a Structure, \a storage_scheme, \a m, and \a n. + */ + T * __restrict__ data; + + /** + * The container's storage scheme. \a storage_scheme is not exposed to the user as an option + * but can defined by ALP at different points in the execution depending on the \a backend choice. + * For example, if the container is associated to an I/O matrix, with a reference backend + * it might be set to reflect the storage scheme of the user data as specified at buildMatrix. + * If \a backend is set to \a mlir then the scheme could be fixed by the JIT compiler to effectively + * support its optimization strategy. + * At construction time and until the moment the scheme decision is made it may be set to + * an appropriate default choice, e.g. if \a StorageSchemeType is \a storage::Dense then + * \a storage::Dense::full could be used. + */ + StorageSchemeType storage_scheme; + + /** Whether the container presently is initialized or not. */ + bool initialized; + + public : + + /** + * Usable only in case of an \a original view. Otherwise the view should only reference another view. + */ + StructuredMatrix( const size_t m, const size_t n ); + + /** + * In case of non-original views should set up the container so to share the data of other. + */ + StructuredMatrix( const StructuredMatrix< T, Structure, StorageSchemeType, View, backend > & other ); + + /** + * Usable only in case of an \a original view. Otherwise the view should only reference another view. + */ + StructuredMatrix( StructuredMatrix< T, Structure, StorageSchemeType, View, backend > && other ); + + /** + * When view is \a original data should be properly deallocated. + */ + ~StructuredMatrix(); +}; + +template< typename InputType, Backend backend > +RC clear( Matrix< InputType, backend > & A ) noexcept { + // this is the generic stub implementation + return UNSUPPORTED; +} + } // end namespace ``grb'' #endif // end _H_GRB_MATRIX_BASE diff --git a/include/graphblas/matrix.hpp b/include/graphblas/matrix.hpp index 59ff28cf0..d603976c1 100644 --- a/include/graphblas/matrix.hpp +++ b/include/graphblas/matrix.hpp @@ -28,14 +28,13 @@ // now include all specialisations contained in the backend directories: #ifdef _GRB_WITH_REFERENCE - #include - #include +#include #endif #ifdef _GRB_WITH_LPF - #include +#include #endif #ifdef _GRB_WITH_BANSHEE - #include +#include #endif // specify default only if requested during compilation @@ -48,7 +47,14 @@ namespace grb { typename NonzeroIndexType = config::NonzeroIndexType > class Matrix; -} + + /* + * The default value of \a StorageSchemeType could also be made conditional (Dense or Sparse) depending on \a config::default_backend + */ + template< typename T, typename Structure, typename StorageSchemeType = storage::Dense, typename View = view::Identity< void >, enum Backend backend = config::default_backend > + class StructuredMatrix; + +} // namespace grb #endif #endif // end ``_H_GRB_MATRIX'' diff --git a/include/graphblas/storage.hpp b/include/graphblas/storage.hpp new file mode 100644 index 000000000..55031a553 --- /dev/null +++ b/include/graphblas/storage.hpp @@ -0,0 +1,81 @@ +/* + * Copyright 2021 Huawei Technologies Co., Ltd. + * + * 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. + */ + +/** + * + * @file This file registers matrix storage schemes that are either + * implemented, under implementation, or were at any point in time + * conceived and noteworthy enough to be recorded for future consideration. + */ + +#ifndef _H_GRB_STORAGE +#define _H_GRB_STORAGE + +#include +#include + +namespace grb { + + namespace storage { + + /** + * Collection of possible storage scheme options for dense matrices (or now including classic BLAS/LAPACK storage schemes). + * \note Assumption is row-major but a complete specification might depend by a similar row/column-major option perhaps included + * at the level of Matrix (general ). + */ + enum Dense { + + /** + * Conventional storage in a 2D array. The matrix element \f$A(i,j)\f$ is stored in array element \f$a(i,j)\f$. + * Although some non-general structured matrices may forbid access to part of the array, + * with this storage option a full rectangular array must be allocated. + * This option could also be used as default/initial choice when a storage scheme decision has not yet been made. + */ + full, + + /** + * Compact 2D storage for Band matrices. An \f$m-\times-n\f$ band matrix with \f$kl\f$ subdiagonals + * and \f$ku\f$ superdiagonals may be stored compactly in a 2D array with \f$m\f$ rows and \f$kl+ku+1\f$ columns. + * Rows of the matrix are stored in corresponding rows of the array, and diagonals of the matrix are stored + * in columns of the array. + * This storage scheme should be used in practice only if \f$kl, ku \ll \min(m,n)\f$, although it should work correctly + * for all values of \f$kl\f$ and \f$ku\f$. + */ + band, + + /** + * A tridiagonal matrix of order \f$n\f$ is stored in three 1D arrays, one of length \f$n\f$ + * containing the diagonal elements, and two of length \f$n-1\f$ containing the subdiagonal + * and superdiagonal elements. + * Symmetric tridiagonal and bidiagonal matrices are stored in two 1D arrays, one of length \f$n\f$ + * containing the diagonal elements, and one of length \f$n-1\f$ containing the off-diagonal elements. + * A diagonal matrix is stored as a 1D array of length \f$n\f$. + * Symmetric, Hermitian or triangular matrices store the relevant triangle packed by rows in a 1D array: + * \li \c AlignLeft \f$A(i,j)\f$ is stored in \f$a( j + i*(i + 1)/2 )\f$ for \f$i \leq j\f$ + * \li \c AlignLeft \f$A(i,j)\f$ is stored in \f$a( j + i*(2*n - i - 1)/2 )\f$ for \f$j \leq i\f$ + */ + array1d + }; // Dense + + // enum Sparse { + // ... + // }; + + } // namespace storage + +} // namespace grb + +#endif // _H_GRB_STORAGE diff --git a/include/graphblas/structures.hpp b/include/graphblas/structures.hpp new file mode 100644 index 000000000..3d4ccc6e0 --- /dev/null +++ b/include/graphblas/structures.hpp @@ -0,0 +1,127 @@ + +/* + * Copyright 2021 Huawei Technologies Co., Ltd. + * + * 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. + */ + +/** + * + * @file This file registers all matrix structures that are either + * implemented, under implementation, or were at any point in time + * conceived and noteworthy enough to be recorded for future consideration. + */ + +#ifndef _H_GRB_STRUCTURES +#define _H_GRB_STRUCTURES + +#include +#include + +namespace grb { + + namespace structures { + + template< typename... Tuples > + struct tuple_cat { + using type = decltype( std::tuple_cat( std::declval< Tuples >()... ) ); + }; + + /** + * Check if a structure is part of a given tuple. + */ + template< typename Structure, typename Tuple > + struct is_in; + + template< typename Structure > + struct is_in< Structure, std::tuple<> > : std::false_type {}; + + template< typename Structure, typename TupleHead, typename... Structures > + struct is_in< Structure, std::tuple< TupleHead, Structures... > > : is_in< Structure, std::tuple< Structures... > > {}; + + template< typename Structure, typename... Structures > + struct is_in< Structure, std::tuple< Structure, Structures... > > : std::true_type {}; + + enum SymmetryDirection { + + unspecified, + + north, + + south, + + east, + + west, + + /* + * Could specify symmetry with upper access + */ + north_west, + + /* + * Could specify symmetry with lower access + */ + south_east, + + /* + * Could specify persymmetry with upper access + */ + north_east, + + /* + * Could specify persymmetry with lower access + */ + south_west + }; + + /** + * List of ALP matrix structures. + */ + struct Square { + using inferred_structures = std::tuple< Square >; + }; + + struct Symmetric { + using inferred_structures = structures::tuple_cat< std::tuple< Symmetric >, Square::inferred_structures >::type; + }; + + struct Triangular { + using inferred_structures = structures::tuple_cat< std::tuple< Triangular >, Square::inferred_structures >::type; + }; + + struct LowerTriangular { + using inferred_structures = structures::tuple_cat< std::tuple< LowerTriangular >, Triangular::inferred_structures >::type; + }; + + struct UpperTriangular { + using inferred_structures = structures::tuple_cat< std::tuple< UpperTriangular >, Triangular::inferred_structures >::type; + }; + + struct Diagonal { + using inferred_structures = structures::tuple_cat< std::tuple< Diagonal >, LowerTriangular::inferred_structures, UpperTriangular::inferred_structures >::type; + }; + + struct FullRank { + using inferred_structures = std::tuple< FullRank >; + }; + + struct NonSingular { + using inferred_structures = structures::tuple_cat< std::tuple< NonSingular >, Square::inferred_structures, FullRank::inferred_structures >::type; + }; + + } // namespace structures + +} // namespace grb + +#endif diff --git a/include/graphblas/views.hpp b/include/graphblas/views.hpp new file mode 100644 index 000000000..454d9d846 --- /dev/null +++ b/include/graphblas/views.hpp @@ -0,0 +1,61 @@ +/* + * Copyright 2021 Huawei Technologies Co., Ltd. + * + * 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. + */ + +/** + * + * @file This file registers (static) views on matrix containers that are either + * implemented, under implementation, or were at any point in time + * conceived and noteworthy enough to be recorded for future consideration. + * A static view represents a particular \em perspective on a container that + * can be defined at compile-time and that can always be applied to a container + * irrespective of features such as its dimensions. + */ + +#ifndef _H_GRB_VIEWS +#define _H_GRB_VIEWS + +#include + +namespace grb { + + namespace view { + + template< typename OriginalType > + struct Identity { + + using applied_to = OriginalType; + + static std::pair< size_t, size_t > dims( std::pair< size_t, size_t > dims_pair ) { + return std::make_pair( dims_pair.first, dims_pair.second ); + } + }; + + template< typename OriginalType > + struct Transpose { + + using applied_to = original_view; + using dims_retval_type = std::pair< size_t, size_t > + + static dims_retval_type dims( std::pair< size_t, size_t > dims_pair ) { + return std::make_pair( dims_pair.second, dims_pair.first ); + } + }; + + }; // namespace view + +} // namespace grb + +#endif // _H_GRB_VIEWS From e4fb2ab6cb58b74e4080657f2de5e4c7190d5529 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Mon, 31 Jan 2022 11:08:34 +0100 Subject: [PATCH 011/282] Issue #303: Copy test mxm.cpp to dense_mxm.cpp as a starting point --- tests/unit/dense_mxm.cpp | 223 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 223 insertions(+) create mode 100644 tests/unit/dense_mxm.cpp diff --git a/tests/unit/dense_mxm.cpp b/tests/unit/dense_mxm.cpp new file mode 100644 index 000000000..8a3bd1966 --- /dev/null +++ b/tests/unit/dense_mxm.cpp @@ -0,0 +1,223 @@ + +/* + * Copyright 2021 Huawei Technologies Co., Ltd. + * + * 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. + */ + +#include +#include + +#include + +using namespace grb; + +void grb_program( const size_t & n, grb::RC & rc ) { + grb::Semiring< grb::operators::add< double >, grb::operators::mul< double >, grb::identities::zero, grb::identities::one > ring; + + // initialize test + grb::Matrix< double > A( n, n ); + grb::Matrix< double > B( n, n ); + grb::Matrix< double > C( n, n ); + size_t I[ n ], J[ n ]; + double V[ n ]; + for( size_t k = 0; k < n; ++k ) { + I[ k ] = J[ k ] = k; + V[ k ] = 2.0; + } + rc = grb::resize( B, n ); + if( rc == SUCCESS ) { + rc = grb::buildMatrixUnique( B, I, J, V, n, SEQUENTIAL ); + } + if( rc == SUCCESS ) { + rc = grb::resize( A, n ); + } + if( rc == SUCCESS ) { + V[ 0 ] = 1.0; + for( size_t k = 1; k < n; ++k ) { + J[ k - 1 ] = k; + V[ k ] = 1.0; + } + J[ n - 1 ] = 0; + rc = grb::buildMatrixUnique( A, I, J, V, n, SEQUENTIAL ); + } + if( rc != SUCCESS ) { + std::cerr << "\tinitialisation FAILED\n"; + return; + } + + // compute with the semiring mxm + std::cout << "\tVerifying the semiring version of mxm\n"; + + rc = grb::mxm( C, A, B, ring, SYMBOLIC ); + if( rc == SUCCESS ) { + rc = grb::mxm( C, A, B, ring ); + if( rc != SUCCESS ) { + std::cerr << "Call to grb::mxm FAILED\n"; + } + } else { + std::cerr << "Call to grb::resize FAILED\n"; + } + if( rc != SUCCESS ) { + return; + } + + // check CRS output + const auto &crs1 = internal::getCRS( C ); + for( size_t i = 0; i < n; ++i ) { + const size_t entries = crs1.col_start[ i + 1 ] - crs1.col_start[ i ]; + if( entries != 1 ) { + std::cerr << "Error: unexpected number of entries " << entries << ", expected 1 (CRS).\n"; + rc = FAILED; + } + for( size_t k = crs1.col_start[ i ]; k < crs1.col_start[ i + 1 ]; ++k ) { + const size_t expect = i == n - 1 ? 0 : i + 1; + if( crs1.row_index[ k ] != expect ) { + std::cerr << "Error: unexpected entry at ( " << i << ", " << crs1.row_index[ k ] << " ), expected one at ( " << i << ", " << ( ( i + 1 ) % n ) << " ) instead (CRS).\n"; + rc = FAILED; + } + if( crs1.values[ k ] != 2.0 ) { + std::cerr << "Error: unexpected value " << crs1.values[ k ] << "; expected 2 (CRS).\n"; + rc = FAILED; + } + } + } + + // check CCS output + const auto &ccs1 = internal::getCCS( C ); + for( size_t j = 0; j < n; ++j ) { + const size_t entries = ccs1.col_start[ j + 1 ] - ccs1.col_start[ j ]; + if( entries != 1 ) { + std::cerr << "Error: unexpected number of entries " << entries << ", expected 1 (CCS).\n"; + rc = FAILED; + } + for( size_t k = ccs1.col_start[ j ]; k < ccs1.col_start[ j + 1 ]; ++k ) { + const size_t expect = j == 0 ? n - 1 : j - 1; + if( ccs1.row_index[ k ] != expect ) { + std::cerr << "Error: unexpected entry at ( " << ccs1.row_index[ k ] << ", " << j << " ), expected one at ( " << expect << ", " << j << " ) instead (CCS).\n"; + rc = FAILED; + } + if( ccs1.values[ k ] != 2.0 ) { + std::cerr << "Error: unexpected value " << ccs1.values[ k ] << "; expected 2 (CCS).\n"; + rc = FAILED; + } + } + } + + // compute with the operator-monoid mxm + std::cout << "\tVerifying the operator-monoid version of mxm\n"; + + rc = grb::mxm( C, A, B, ring.getMultiplicativeOperator(), ring.getAdditiveMonoid(), SYMBOLIC ); + if( rc == SUCCESS ) { + rc = grb::mxm( C, A, B, ring.getMultiplicativeOperator(), ring.getAdditiveMonoid() ); + if( rc != SUCCESS ) { + std::cerr << "Call to grb::mxm FAILED\n"; + } + } else { + std::cerr << "Call to grb::resize FAILED\n"; + } + if( rc != SUCCESS ) { + return; + } + + // check CRS output + const auto &crs2 = internal::getCRS( C ); + for( size_t i = 0; i < n; ++i ) { + const size_t entries = crs2.col_start[ i + 1 ] - crs2.col_start[ i ]; + if( entries != 1 ) { + std::cerr << "Error: unexpected number of entries " << entries << ", expected 1 (CRS).\n"; + rc = FAILED; + } + for( size_t k = crs2.col_start[ i ]; k < crs2.col_start[ i + 1 ]; ++k ) { + const size_t expect = i == n - 1 ? 0 : i + 1; + if( crs2.row_index[ k ] != expect ) { + std::cerr << "Error: unexpected entry at ( " << i << ", " << crs2.row_index[ k ] << " ), expected one at ( " << i << ", " << ( ( i + 1 ) % n ) << " ) instead (CRS).\n"; + rc = FAILED; + } + if( crs2.values[ k ] != 2.0 ) { + std::cerr << "Error: unexpected value " << crs2.values[ k ] << "; expected 2 (CRS).\n"; + rc = FAILED; + } + } + } + + // check CCS output + const auto &ccs2 = internal::getCCS( C ); + for( size_t j = 0; j < n; ++j ) { + const size_t entries = ccs2.col_start[ j + 1 ] - ccs2.col_start[ j ]; + if( entries != 1 ) { + std::cerr << "Error: unexpected number of entries " << entries << ", expected 1 (CCS).\n"; + rc = FAILED; + } + for( size_t k = ccs2.col_start[ j ]; k < ccs2.col_start[ j + 1 ]; ++k ) { + const size_t expect = j == 0 ? n - 1 : j - 1; + if( ccs2.row_index[ k ] != expect ) { + std::cerr << "Error: unexpected entry at ( " << ccs2.row_index[ k ] << ", " << j << " ), expected one at ( " << expect << ", " << j << " ) instead (CCS).\n"; + rc = FAILED; + } + if( ccs2.values[ k ] != 2.0 ) { + std::cerr << "Error: unexpected value " << ccs2.values[ k ] << "; expected 2 (CCS).\n"; + rc = FAILED; + } + } + } +} + +int main( int argc, char ** argv ) { + // defaults + bool printUsage = false; + size_t in = 100; + + // error checking + if( argc > 2 ) { + printUsage = true; + } + if( argc == 2 ) { + size_t read; + std::istringstream ss( argv[ 1 ] ); + if( ! ( ss >> read ) ) { + std::cerr << "Error parsing first argument\n"; + printUsage = true; + } else if( ! ss.eof() ) { + std::cerr << "Error parsing first argument\n"; + printUsage = true; + } else if( read % 2 != 0 ) { + std::cerr << "Given value for n is odd\n"; + printUsage = true; + } else { + // all OK + in = read; + } + } + if( printUsage ) { + std::cerr << "Usage: " << argv[ 0 ] << " [n]\n"; + std::cerr << " -n (optional, default is 100): an even integer, the " + "test size.\n"; + return 1; + } + + std::cout << "This is functional test " << argv[ 0 ] << "\n"; + grb::Launcher< AUTOMATIC > launcher; + grb::RC out; + if( launcher.exec( &grb_program, in, out, true ) != SUCCESS ) { + std::cerr << "Launching test FAILED\n"; + return 255; + } + if( out != SUCCESS ) { + std::cerr << "Test FAILED (" << grb::toString( out ) << ")" << std::endl; + } else { + std::cout << "Test OK" << std::endl; + } + return 0; +} + From 70278eb5dfb8059737cd2fb413b6046cb18ca502 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Tue, 1 Feb 2022 13:38:32 +0100 Subject: [PATCH 012/282] Issue #303: Add partial first version of Matrix interface for denseref --- include/graphblas/denseref/matrix.hpp | 72 +++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/include/graphblas/denseref/matrix.hpp b/include/graphblas/denseref/matrix.hpp index a74ef2efb..a3f94eeb9 100644 --- a/include/graphblas/denseref/matrix.hpp +++ b/include/graphblas/denseref/matrix.hpp @@ -23,11 +23,83 @@ #ifndef _H_GRB_DENSEREF_MATRIX #define _H_GRB_DENSEREF_MATRIX +#include +#include +#include +#include +#include +#include +//#include +//#include +//#include +#include +#include +//#include //for help with dealing with pattern matrix input + namespace grb { /** \internal TODO */ template< typename T > class Matrix< T, reference_dense > { + private: + /** Our own type. */ + typedef Matrix< T, reference_dense > self_type; + + /** + * The number of rows. + * + * \internal Not declared const to be able to implement move in an elegant way. + */ + size_t m; + + /** + * The number of columns. + * + * \internal Not declared const to be able to implement move in an elegant way. + */ + size_t n; + + /** Whether the container presently is uninitialized. */ + bool initialized; + + std::vector< T > container; + public: + /** @see Matrix::value_type */ + typedef T value_type; + + /** @see Matrix::Matrix() */ + Matrix( const size_t rows, const size_t columns ): m( rows ), n( columns ), initialized( false ) { + + } + + /** @see Matrix::Matrix( const Matrix & ) */ + Matrix( const Matrix< T, reference_dense > &other ) : Matrix( other.m, other.n ) { + initialized = other.initialized; + } + + /** @see Matrix::Matrix( Matrix&& ). */ + Matrix( self_type &&other ) noexcept { + moveFromOther( std::forward< self_type >(other) ); + } + + /** * Move from temporary. */ + self_type& operator=( self_type &&other ) noexcept { + moveFromOther( std::forward< self_type >(other) ); + return *this; + } + + /** @see Matrix::~Matrix(). */ + ~Matrix() { + + } + + }; + + // template specialisation for GraphBLAS type traits + template< typename T > + struct is_container< Matrix< T, reference_dense > > { + /** A reference_dense Matrix is a GraphBLAS object. */ + static const constexpr bool value = true; }; } // end namespace ``grb'' From cf5fcc2f1a36efb5a3b864c5d30018c138870980 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Tue, 1 Feb 2022 18:38:54 +0100 Subject: [PATCH 013/282] Issue #303: WIP: dense mxm test --- tests/unit/dense_mxm.cpp | 149 +++------------------------------------ 1 file changed, 11 insertions(+), 138 deletions(-) diff --git a/tests/unit/dense_mxm.cpp b/tests/unit/dense_mxm.cpp index 8a3bd1966..ab5e74d69 100644 --- a/tests/unit/dense_mxm.cpp +++ b/tests/unit/dense_mxm.cpp @@ -17,6 +17,7 @@ #include #include +#include #include @@ -25,152 +26,24 @@ using namespace grb; void grb_program( const size_t & n, grb::RC & rc ) { grb::Semiring< grb::operators::add< double >, grb::operators::mul< double >, grb::identities::zero, grb::identities::one > ring; + std::cout << "\tTesting dense mxm\n"; // initialize test grb::Matrix< double > A( n, n ); grb::Matrix< double > B( n, n ); grb::Matrix< double > C( n, n ); - size_t I[ n ], J[ n ]; - double V[ n ]; - for( size_t k = 0; k < n; ++k ) { - I[ k ] = J[ k ] = k; - V[ k ] = 2.0; - } - rc = grb::resize( B, n ); - if( rc == SUCCESS ) { - rc = grb::buildMatrixUnique( B, I, J, V, n, SEQUENTIAL ); - } - if( rc == SUCCESS ) { - rc = grb::resize( A, n ); - } - if( rc == SUCCESS ) { - V[ 0 ] = 1.0; - for( size_t k = 1; k < n; ++k ) { - J[ k - 1 ] = k; - V[ k ] = 1.0; - } - J[ n - 1 ] = 0; - rc = grb::buildMatrixUnique( A, I, J, V, n, SEQUENTIAL ); - } - if( rc != SUCCESS ) { - std::cerr << "\tinitialisation FAILED\n"; - return; - } - - // compute with the semiring mxm - std::cout << "\tVerifying the semiring version of mxm\n"; - - rc = grb::mxm( C, A, B, ring, SYMBOLIC ); - if( rc == SUCCESS ) { - rc = grb::mxm( C, A, B, ring ); - if( rc != SUCCESS ) { - std::cerr << "Call to grb::mxm FAILED\n"; - } - } else { - std::cerr << "Call to grb::resize FAILED\n"; - } - if( rc != SUCCESS ) { - return; - } - - // check CRS output - const auto &crs1 = internal::getCRS( C ); - for( size_t i = 0; i < n; ++i ) { - const size_t entries = crs1.col_start[ i + 1 ] - crs1.col_start[ i ]; - if( entries != 1 ) { - std::cerr << "Error: unexpected number of entries " << entries << ", expected 1 (CRS).\n"; - rc = FAILED; - } - for( size_t k = crs1.col_start[ i ]; k < crs1.col_start[ i + 1 ]; ++k ) { - const size_t expect = i == n - 1 ? 0 : i + 1; - if( crs1.row_index[ k ] != expect ) { - std::cerr << "Error: unexpected entry at ( " << i << ", " << crs1.row_index[ k ] << " ), expected one at ( " << i << ", " << ( ( i + 1 ) % n ) << " ) instead (CRS).\n"; - rc = FAILED; - } - if( crs1.values[ k ] != 2.0 ) { - std::cerr << "Error: unexpected value " << crs1.values[ k ] << "; expected 2 (CRS).\n"; - rc = FAILED; - } - } - } - // check CCS output - const auto &ccs1 = internal::getCCS( C ); - for( size_t j = 0; j < n; ++j ) { - const size_t entries = ccs1.col_start[ j + 1 ] - ccs1.col_start[ j ]; - if( entries != 1 ) { - std::cerr << "Error: unexpected number of entries " << entries << ", expected 1 (CCS).\n"; - rc = FAILED; - } - for( size_t k = ccs1.col_start[ j ]; k < ccs1.col_start[ j + 1 ]; ++k ) { - const size_t expect = j == 0 ? n - 1 : j - 1; - if( ccs1.row_index[ k ] != expect ) { - std::cerr << "Error: unexpected entry at ( " << ccs1.row_index[ k ] << ", " << j << " ), expected one at ( " << expect << ", " << j << " ) instead (CCS).\n"; - rc = FAILED; - } - if( ccs1.values[ k ] != 2.0 ) { - std::cerr << "Error: unexpected value " << ccs1.values[ k ] << "; expected 2 (CCS).\n"; - rc = FAILED; - } - } - } + std::cout << "_GRB_BACKEND = " << _GRB_BACKEND << "\n"; + + #ifdef _GRB_WITH_REFERENCE + std::cout << "_GRB_WITH_REFERENCE defined\n"; + #endif - // compute with the operator-monoid mxm - std::cout << "\tVerifying the operator-monoid version of mxm\n"; + #ifdef _GRB_WITH_DENSE + std::cout << "_GRB_WITH_DENSE defined\n"; + #endif - rc = grb::mxm( C, A, B, ring.getMultiplicativeOperator(), ring.getAdditiveMonoid(), SYMBOLIC ); - if( rc == SUCCESS ) { - rc = grb::mxm( C, A, B, ring.getMultiplicativeOperator(), ring.getAdditiveMonoid() ); - if( rc != SUCCESS ) { - std::cerr << "Call to grb::mxm FAILED\n"; - } - } else { - std::cerr << "Call to grb::resize FAILED\n"; - } - if( rc != SUCCESS ) { - return; - } + rc = grb::SUCCESS; - // check CRS output - const auto &crs2 = internal::getCRS( C ); - for( size_t i = 0; i < n; ++i ) { - const size_t entries = crs2.col_start[ i + 1 ] - crs2.col_start[ i ]; - if( entries != 1 ) { - std::cerr << "Error: unexpected number of entries " << entries << ", expected 1 (CRS).\n"; - rc = FAILED; - } - for( size_t k = crs2.col_start[ i ]; k < crs2.col_start[ i + 1 ]; ++k ) { - const size_t expect = i == n - 1 ? 0 : i + 1; - if( crs2.row_index[ k ] != expect ) { - std::cerr << "Error: unexpected entry at ( " << i << ", " << crs2.row_index[ k ] << " ), expected one at ( " << i << ", " << ( ( i + 1 ) % n ) << " ) instead (CRS).\n"; - rc = FAILED; - } - if( crs2.values[ k ] != 2.0 ) { - std::cerr << "Error: unexpected value " << crs2.values[ k ] << "; expected 2 (CRS).\n"; - rc = FAILED; - } - } - } - - // check CCS output - const auto &ccs2 = internal::getCCS( C ); - for( size_t j = 0; j < n; ++j ) { - const size_t entries = ccs2.col_start[ j + 1 ] - ccs2.col_start[ j ]; - if( entries != 1 ) { - std::cerr << "Error: unexpected number of entries " << entries << ", expected 1 (CCS).\n"; - rc = FAILED; - } - for( size_t k = ccs2.col_start[ j ]; k < ccs2.col_start[ j + 1 ]; ++k ) { - const size_t expect = j == 0 ? n - 1 : j - 1; - if( ccs2.row_index[ k ] != expect ) { - std::cerr << "Error: unexpected entry at ( " << ccs2.row_index[ k ] << ", " << j << " ), expected one at ( " << expect << ", " << j << " ) instead (CCS).\n"; - rc = FAILED; - } - if( ccs2.values[ k ] != 2.0 ) { - std::cerr << "Error: unexpected value " << ccs2.values[ k ] << "; expected 2 (CCS).\n"; - rc = FAILED; - } - } - } } int main( int argc, char ** argv ) { From 2cfde919623345a5b06227938428d049fe741309 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Tue, 1 Feb 2022 18:40:59 +0100 Subject: [PATCH 014/282] Issue #303: Add dense mxm test to CMakeLists --- tests/unit/CMakeLists.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/unit/CMakeLists.txt b/tests/unit/CMakeLists.txt index f6f467ae7..9f72f96ea 100644 --- a/tests/unit/CMakeLists.txt +++ b/tests/unit/CMakeLists.txt @@ -204,6 +204,10 @@ add_grb_executables( spy spy.cpp BACKENDS reference reference_omp ) +add_grb_executables( dense_mxm dense_mxm.cpp + BACKENDS reference_dense +) + add_grb_executables( dense_spmv dense_spmv.cpp BACKENDS reference reference_omp bsp1d hybrid ) From 0489d1453343c65390ca86b229ebec25ea1c91f1 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Wed, 2 Feb 2022 12:07:02 +0100 Subject: [PATCH 015/282] Issue #303: Separate reference and reference_dense includes --- include/graphblas/benchmark.hpp | 2 ++ include/graphblas/blas1.hpp | 2 ++ include/graphblas/blas2.hpp | 2 ++ include/graphblas/blas3.hpp | 2 ++ include/graphblas/collectives.hpp | 2 ++ include/graphblas/config.hpp | 2 ++ include/graphblas/exec.hpp | 2 ++ include/graphblas/init.hpp | 2 ++ include/graphblas/io.hpp | 2 ++ include/graphblas/matrix.hpp | 5 ++++- include/graphblas/pinnedvector.hpp | 2 ++ include/graphblas/properties.hpp | 2 ++ include/graphblas/spmd.hpp | 2 ++ include/graphblas/vector.hpp | 2 ++ 14 files changed, 30 insertions(+), 1 deletion(-) diff --git a/include/graphblas/benchmark.hpp b/include/graphblas/benchmark.hpp index d040409bd..d1c28f9e5 100644 --- a/include/graphblas/benchmark.hpp +++ b/include/graphblas/benchmark.hpp @@ -29,6 +29,8 @@ // include specialisations #ifdef _GRB_WITH_REFERENCE #include "graphblas/reference/benchmark.hpp" +#endif +#ifdef _GRB_WITH_DENSE #include "graphblas/denseref/benchmark.hpp" #endif #ifdef _GRB_WITH_BANSHEE diff --git a/include/graphblas/blas1.hpp b/include/graphblas/blas1.hpp index 26ba991db..24d9ba3d4 100644 --- a/include/graphblas/blas1.hpp +++ b/include/graphblas/blas1.hpp @@ -27,6 +27,8 @@ #ifdef _GRB_WITH_REFERENCE #include +#endif +#ifdef _GRB_WITH_DENSE #include #endif #ifdef _GRB_WITH_BANSHEE diff --git a/include/graphblas/blas2.hpp b/include/graphblas/blas2.hpp index 773457fc8..7c4e44398 100644 --- a/include/graphblas/blas2.hpp +++ b/include/graphblas/blas2.hpp @@ -32,6 +32,8 @@ // now include all specialisations contained in the backend directories: #ifdef _GRB_WITH_REFERENCE #include +#endif +#ifdef _GRB_WITH_DENSE #include #endif #ifdef _GRB_WITH_BANSHEE diff --git a/include/graphblas/blas3.hpp b/include/graphblas/blas3.hpp index 6aca8a624..acae03b56 100644 --- a/include/graphblas/blas3.hpp +++ b/include/graphblas/blas3.hpp @@ -29,6 +29,8 @@ // now include all specialisations contained in the backend directories: #ifdef _GRB_WITH_REFERENCE #include +#endif +#ifdef _GRB_WITH_DENSE #include #endif #ifdef _GRB_WITH_LPF diff --git a/include/graphblas/collectives.hpp b/include/graphblas/collectives.hpp index 4949d3b42..e0801b608 100644 --- a/include/graphblas/collectives.hpp +++ b/include/graphblas/collectives.hpp @@ -29,6 +29,8 @@ // include template specialisations #ifdef _GRB_WITH_REFERENCE #include +#endif +#ifdef _GRB_WITH_DENSE #include #endif #ifdef _GRB_WITH_LPF diff --git a/include/graphblas/config.hpp b/include/graphblas/config.hpp index 264ed5a88..cd614705b 100644 --- a/include/graphblas/config.hpp +++ b/include/graphblas/config.hpp @@ -28,6 +28,8 @@ // include all active configurations #ifdef _GRB_WITH_REFERENCE #include "graphblas/reference/config.hpp" +#endif +#ifdef _GRB_WITH_DENSE #include "graphblas/denseref/config.hpp" #endif #ifdef _GRB_WITH_HYPERDAGS diff --git a/include/graphblas/exec.hpp b/include/graphblas/exec.hpp index 6a5b74b6d..be2857df5 100644 --- a/include/graphblas/exec.hpp +++ b/include/graphblas/exec.hpp @@ -29,6 +29,8 @@ // include template specialisations #ifdef _GRB_WITH_REFERENCE #include "graphblas/reference/exec.hpp" +#endif +#ifdef _GRB_WITH_DENSE #include "graphblas/denseref/exec.hpp" #endif #ifdef _GRB_WITH_LPF diff --git a/include/graphblas/init.hpp b/include/graphblas/init.hpp index 819ee59aa..e54637fc8 100644 --- a/include/graphblas/init.hpp +++ b/include/graphblas/init.hpp @@ -30,6 +30,8 @@ // include all implementations #ifdef _GRB_WITH_REFERENCE #include "graphblas/reference/init.hpp" +#endif +#ifdef _GRB_WITH_DENSE #include "graphblas/denseref/init.hpp" #endif #ifdef _GRB_WITH_LPF diff --git a/include/graphblas/io.hpp b/include/graphblas/io.hpp index dfcdd3e44..7b0f24d28 100644 --- a/include/graphblas/io.hpp +++ b/include/graphblas/io.hpp @@ -28,6 +28,8 @@ // now include all specialisations contained in the backend directories: #ifdef _GRB_WITH_REFERENCE #include +#endif +#ifdef _GRB_WITH_DENSE #include #endif #ifdef _GRB_WITH_LPF diff --git a/include/graphblas/matrix.hpp b/include/graphblas/matrix.hpp index d603976c1..a44411a1d 100644 --- a/include/graphblas/matrix.hpp +++ b/include/graphblas/matrix.hpp @@ -28,7 +28,10 @@ // now include all specialisations contained in the backend directories: #ifdef _GRB_WITH_REFERENCE -#include + #include +#endif +#ifdef _GRB_WITH_DENSE + #include #endif #ifdef _GRB_WITH_LPF #include diff --git a/include/graphblas/pinnedvector.hpp b/include/graphblas/pinnedvector.hpp index e092d241e..b27dba86f 100644 --- a/include/graphblas/pinnedvector.hpp +++ b/include/graphblas/pinnedvector.hpp @@ -33,6 +33,8 @@ // now include all specialisations contained in the backend directories: #ifdef _GRB_WITH_REFERENCE #include +#endif +#ifdef _GRB_WITH_DENSE #include #endif #ifdef _GRB_WITH_LPF diff --git a/include/graphblas/properties.hpp b/include/graphblas/properties.hpp index 49663d30a..c8b099101 100644 --- a/include/graphblas/properties.hpp +++ b/include/graphblas/properties.hpp @@ -29,6 +29,8 @@ // now include all specialisations contained in the backend directories: #ifdef _GRB_WITH_REFERENCE #include +#endif +#ifdef _GRB_WITH_DENSE #include #endif #ifdef _GRB_WITH_LPF diff --git a/include/graphblas/spmd.hpp b/include/graphblas/spmd.hpp index 5eb01f39a..114a1141c 100644 --- a/include/graphblas/spmd.hpp +++ b/include/graphblas/spmd.hpp @@ -28,6 +28,8 @@ #ifdef _GRB_WITH_REFERENCE #include "graphblas/reference/spmd.hpp" +#endif +#ifdef _GRB_WITH_DENSE #include "graphblas/denseref/spmd.hpp" #endif #ifdef _GRB_WITH_LPF diff --git a/include/graphblas/vector.hpp b/include/graphblas/vector.hpp index 8d06ea342..6286cc59d 100644 --- a/include/graphblas/vector.hpp +++ b/include/graphblas/vector.hpp @@ -30,6 +30,8 @@ // now include all specialisations contained in the backend directories: #ifdef _GRB_WITH_REFERENCE #include +#endif +#ifdef _GRB_WITH_DENSE #include #endif #ifdef _GRB_WITH_LPF From 4e766c01bf538181f6857b24e5cbe405c462633c Mon Sep 17 00:00:00 2001 From: Anonymous Date: Wed, 2 Feb 2022 16:48:23 +0100 Subject: [PATCH 016/282] Issue #303: Fix grb include name mismatch --- cmake/AddGRBVars.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/AddGRBVars.cmake b/cmake/AddGRBVars.cmake index 9eca8dbe8..5f1d37b3f 100644 --- a/cmake/AddGRBVars.cmake +++ b/cmake/AddGRBVars.cmake @@ -40,7 +40,7 @@ set( DENSE_BACKEND_DEFAULT_NAME "backend_reference_dense" ) set( REFERENCE_INCLUDE_DEFS "_GRB_WITH_REFERENCE" ) set( REFERENCE_OMP_INCLUDE_DEFS "_GRB_WITH_OMP" ) set( LPF_INCLUDE_DEFS "_GRB_WITH_LPF" ) -set( DENSE_INCLUDE_DEFS "_GRB_WITH_DENSEREF" ) +set( DENSE_INCLUDE_DEFS "_GRB_WITH_DENSE" ) # compiler definitions to select a backend set( REFERENCE_SELECTION_DEFS "_GRB_BACKEND=reference" ) From efe1e3857b254a526750150ec0aa683f905051dc Mon Sep 17 00:00:00 2001 From: Anonymous Date: Wed, 2 Feb 2022 16:56:36 +0100 Subject: [PATCH 017/282] Issue #303: Add src files for reference dense backend --- src/graphblas/CMakeLists.txt | 4 ++ src/graphblas/denseref/CMakeLists.txt | 56 +++++++++++++++++++++++++++ src/graphblas/denseref/init.cpp | 46 ++++++++++++++++++++++ 3 files changed, 106 insertions(+) create mode 100644 src/graphblas/denseref/CMakeLists.txt create mode 100644 src/graphblas/denseref/init.cpp diff --git a/src/graphblas/CMakeLists.txt b/src/graphblas/CMakeLists.txt index c751a64ab..52e49d850 100644 --- a/src/graphblas/CMakeLists.txt +++ b/src/graphblas/CMakeLists.txt @@ -83,6 +83,10 @@ if( WITH_REFERENCE_BACKEND OR WITH_OMP_BACKEND ) add_subdirectory( reference ) endif() +if( WITH_DENSE_BACKEND ) + add_subdirectory( denseref ) +endif() + if( WITH_BSP1D_BACKEND OR WITH_HYBRID_BACKEND ) add_subdirectory( bsp1d ) endif() diff --git a/src/graphblas/denseref/CMakeLists.txt b/src/graphblas/denseref/CMakeLists.txt new file mode 100644 index 000000000..ea0bc7a7b --- /dev/null +++ b/src/graphblas/denseref/CMakeLists.txt @@ -0,0 +1,56 @@ +# +# Copyright 2021 Huawei Technologies Co., Ltd. +# +# 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. +# + +assert_valid_variables( BACKEND_LIBRARY_OUTPUT_NAME VERSION + SHMEM_BACKEND_INSTALL_DIR INCLUDE_INSTALL_DIR + DENSE_BACKEND_DEFAULT_NAME + DENSE_SELECTION_DEFS backend_reference_srcs +) + +# sources for bsp1d backend +set( backend_reference_dense_srcs + ${CMAKE_CURRENT_SOURCE_DIR}/init.cpp +) + +add_library( backend_reference_dense_static STATIC "${backend_reference_dense_srcs}" ) + +target_link_libraries( backend_reference_dense_static PUBLIC backend_reference_dense_headers ) +target_link_libraries( backend_reference_dense_static PRIVATE backend_common_utils ) + +set_target_properties( backend_reference_dense_static PROPERTIES + POSITION_INDEPENDENT_CODE true + INTERFACE_POSITION_INDEPENDENT_CODE true + OUTPUT_NAME "${BACKEND_LIBRARY_OUTPUT_NAME}" +) + +set_target_properties( backend_reference_dense_static PROPERTIES + ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/reference_dense" +) + +target_compile_options( backend_reference_dense_static PRIVATE "${BACKEND_COMPILE_OPTIONS}" ) +target_compile_definitions( backend_reference_dense_static PRIVATE "${BACKEND_COMPILE_DEFINITIONS}" ) +target_compile_definitions( backend_reference_dense_static INTERFACE "${REFERENCE_DENSE_SELECTION_DEFS}" ) + +add_dependencies( libs backend_reference_dense_static ) + +install( TARGETS backend_reference_dense_static + EXPORT GraphBLASTargets + ARCHIVE DESTINATION "${REFERENCE_DENSE_BACKEND_INSTALL_DIR}" +) + +# this is an alias for add_grb_executables() to select the backend to link against +# DO NOT CHANGE THE ALIAS NAME! +add_library( "${DENSE_BACKEND_DEFAULT_NAME}" ALIAS backend_reference_dense_static ) diff --git a/src/graphblas/denseref/init.cpp b/src/graphblas/denseref/init.cpp new file mode 100644 index 000000000..00090bae2 --- /dev/null +++ b/src/graphblas/denseref/init.cpp @@ -0,0 +1,46 @@ + +/* + * Copyright 2021 Huawei Technologies Co., Ltd. + * + * 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. + */ + +/* + * @author A. N. Yzelman + * @date 2nd of February, 2017 + */ + +#include + +template<> +grb::RC grb::init< grb::reference_dense >( const size_t s, const size_t P, void * const data ) { + // we don't use any implementation-specific init data + (void)data; + // print output + std::cerr << "Info: grb::init (reference_dense) called.\n"; + // sanity checks + if( P > 1 ) { + return grb::UNSUPPORTED; + } + if( s > 0 ) { + return grb::PANIC; + } + // done + return grb::SUCCESS; +} + + +template<> +grb::RC grb::finalize< grb::reference_dense >() { + return grb::SUCCESS; +} From 14622f3911797fc2bddac261b34ade938767ae07 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Wed, 2 Feb 2022 16:59:24 +0100 Subject: [PATCH 018/282] Issue #303: Add project related option for dense backend --- CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index a7dc72dd2..a896a4b25 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -50,6 +50,7 @@ endif() ### CONFIGURATION OPTIONS # to choose backends and dependencies option( WITH_REFERENCE_BACKEND "With Reference backend" ON ) +option( WITH_DENSE_BACKEND "With Dense backend" ON ) option( WITH_OMP_BACKEND "With OMP backend" ON ) option( WITH_NUMA "With NUMA support" ON ) option( LPF_INSTALL_PATH "Path to the LPF tools for the BSP1D and Hybrid backends" OFF ) From afed0534a3569ad0f9d93dce4678d1dd0a1ffdf0 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Wed, 2 Feb 2022 17:21:50 +0100 Subject: [PATCH 019/282] Issue #303: Remove dense_reference-related code from reference cmake --- src/graphblas/reference/CMakeLists.txt | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/graphblas/reference/CMakeLists.txt b/src/graphblas/reference/CMakeLists.txt index 3bb12fa83..fc17fb8d5 100644 --- a/src/graphblas/reference/CMakeLists.txt +++ b/src/graphblas/reference/CMakeLists.txt @@ -26,7 +26,6 @@ assert_valid_variables( BACKEND_LIBRARY_OUTPUT_NAME VERSION SHMEM_BACKEND_INSTALL_DIR INCLUDE_INSTALL_DIR REFERENCE_BACKEND_DEFAULT_NAME REFERENCE_OMP_BACKEND_DEFAULT_NAME REFERENCE_SELECTION_DEFS REFERENCE_OMP_SELECTION_DEFS backend_reference_srcs - DENSE_BACKEND_DEFAULT_NAME DENSE_SELECTION_DEFS ) assert_defined_targets( backend_flags ) @@ -151,10 +150,6 @@ if( WITH_REFERENCE_BACKEND ) endif( WITH_REFERENCE_BACKEND ) -if( WITH_DENSE_BACKEND ) - add_library( "${DENSE_BACKEND_DEFAULT_NAME}" ALIAS backend_reference_static ) -endif( WITH_DENSE_BACKEND ) - if( WITH_OMP_BACKEND ) ## reference_omp static From 9d955335ab27a4531d2f7130a83c591a571a1c46 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Wed, 2 Feb 2022 20:52:17 +0100 Subject: [PATCH 020/282] Keeping a clean separate denseref backend when building with cmake. --- CMakeLists.txt | 2 +- cmake/AddGRBInstall.cmake | 7 +- cmake/AddGRBVars.cmake | 8 +- include/CMakeLists.txt | 2 +- include/graphblas/benchmark.hpp | 6 +- include/graphblas/blas1.hpp | 345 ++++++++++++++++++++++++++ include/graphblas/collectives.hpp | 6 +- include/graphblas/denseref/exec.hpp | 6 +- include/graphblas/exec.hpp | 2 +- include/graphblas/init.hpp | 2 +- include/graphblas/matrix.hpp | 2 +- include/graphblas/spmd.hpp | 6 +- include/graphblas/vector.hpp | 6 +- include/graphblas/views.hpp | 5 +- src/graphblas/CMakeLists.txt | 2 +- src/graphblas/denseref/CMakeLists.txt | 21 +- tests/mlir/quick_test.cpp | 78 ++++++ tests/mlir/test.x | Bin 0 -> 17280 bytes tests/unit/dense_mxm.cpp | 4 +- 19 files changed, 470 insertions(+), 40 deletions(-) create mode 100644 tests/mlir/quick_test.cpp create mode 100755 tests/mlir/test.x diff --git a/CMakeLists.txt b/CMakeLists.txt index a896a4b25..4496d965c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -50,7 +50,7 @@ endif() ### CONFIGURATION OPTIONS # to choose backends and dependencies option( WITH_REFERENCE_BACKEND "With Reference backend" ON ) -option( WITH_DENSE_BACKEND "With Dense backend" ON ) +option( WITH_DENSEREF_BACKEND "With Reference Dense backend" ON ) option( WITH_OMP_BACKEND "With OMP backend" ON ) option( WITH_NUMA "With NUMA support" ON ) option( LPF_INSTALL_PATH "Path to the LPF tools for the BSP1D and Hybrid backends" OFF ) diff --git a/cmake/AddGRBInstall.cmake b/cmake/AddGRBInstall.cmake index 1e023f1aa..d6bfea317 100644 --- a/cmake/AddGRBInstall.cmake +++ b/cmake/AddGRBInstall.cmake @@ -44,6 +44,7 @@ install( EXPORT GraphBLASTargets # paths where to install the binaries of the various backends set( ALP_UTILS_INSTALL_DIR "${BINARY_LIBRARIES_INSTALL_DIR}" ) set( SHMEM_BACKEND_INSTALL_DIR "${BINARY_LIBRARIES_INSTALL_DIR}/sequential" ) +set( DENSEREF_BACKEND_INSTALL_DIR "${BINARY_LIBRARIES_INSTALL_DIR}/denseref" ) set( BSP1D_BACKEND_INSTALL_DIR "${BINARY_LIBRARIES_INSTALL_DIR}/spmd" ) set( HYBRID_BACKEND_INSTALL_DIR "${BINARY_LIBRARIES_INSTALL_DIR}/hybrid" ) @@ -120,10 +121,10 @@ if( WITH_REFERENCE_BACKEND ) ) endif() -if( WITH_DENSE_BACKEND ) +if( WITH_DENSEREF_BACKEND ) addBackendWrapperGenOptions( "reference_dense" - COMPILE_DEFINITIONS "${DENSE_SELECTION_DEFS}" - LINK_FLAGS "${SHMEM_BACKEND_INSTALL_DIR}/lib${BACKEND_LIBRARY_OUTPUT_NAME}.a" + COMPILE_DEFINITIONS "DENSEREF_INCLUDE_DEFS" "${DENSEREF_SELECTION_DEFS}" + LINK_FLAGS "${DENSEREF_BACKEND_INSTALL_DIR}/lib${BACKEND_LIBRARY_OUTPUT_NAME}.a" ) endif() diff --git a/cmake/AddGRBVars.cmake b/cmake/AddGRBVars.cmake index 5f1d37b3f..27d089ab7 100644 --- a/cmake/AddGRBVars.cmake +++ b/cmake/AddGRBVars.cmake @@ -31,7 +31,7 @@ set( REFERENCE_BACKEND_DEFAULT_NAME "backend_reference" ) set( REFERENCE_OMP_BACKEND_DEFAULT_NAME "backend_reference_omp" ) set( BSP1D_BACKEND_DEFAULT_NAME "backend_bsp1d" ) set( HYBRID_BACKEND_DEFAULT_NAME "backend_hybrid" ) -set( DENSE_BACKEND_DEFAULT_NAME "backend_reference_dense" ) +set( DENSEREF_BACKEND_DEFAULT_NAME "backend_reference_dense" ) ### COMPILER DEFINITIONS FOR HEADERS INCLUSION AND FOR BACKEND SELECTION @@ -40,12 +40,12 @@ set( DENSE_BACKEND_DEFAULT_NAME "backend_reference_dense" ) set( REFERENCE_INCLUDE_DEFS "_GRB_WITH_REFERENCE" ) set( REFERENCE_OMP_INCLUDE_DEFS "_GRB_WITH_OMP" ) set( LPF_INCLUDE_DEFS "_GRB_WITH_LPF" ) -set( DENSE_INCLUDE_DEFS "_GRB_WITH_DENSE" ) +set( DENSEREF_INCLUDE_DEFS "_GRB_WITH_DENSEREF" ) # compiler definitions to select a backend set( REFERENCE_SELECTION_DEFS "_GRB_BACKEND=reference" ) set( REFERENCE_OMP_SELECTION_DEFS "_GRB_BACKEND=reference_omp" ) -set( DENSE_SELECTION_DEFS "_GRB_BACKEND=reference_dense" ) +set( DENSEREF_SELECTION_DEFS "_GRB_BACKEND=reference_dense" ) set( BSP1D_SELECTION_DEFS "_GRB_BACKEND=BSP1D" "_GRB_BSP1D_BACKEND=reference" @@ -77,7 +77,7 @@ if( WITH_OMP_BACKEND ) list( APPEND AVAILABLE_BACKENDS "reference_omp" ) endif() -if( WITH_DENSE_BACKEND ) +if( WITH_DENSEREF_BACKEND ) list( APPEND AVAILABLE_BACKENDS "reference_dense" ) endif() diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt index d1e163171..847d8ca27 100644 --- a/include/CMakeLists.txt +++ b/include/CMakeLists.txt @@ -117,7 +117,7 @@ if( WITH_REFERENCE_BACKEND_HEADERS ) install( TARGETS backend_reference_headers EXPORT GraphBLASTargets ) endif() -if( WITH_DENSE_BACKEND ) +if( WITH_DENSEREF_BACKEND ) add_library( backend_reference_dense_headers INTERFACE ) target_link_libraries( backend_reference_dense_headers INTERFACE backend_headers_nodefs ) target_compile_definitions( backend_reference_dense_headers INTERFACE "${DENSEREF_INCLUDE_DEFS}" ) diff --git a/include/graphblas/benchmark.hpp b/include/graphblas/benchmark.hpp index d1c28f9e5..536ecc360 100644 --- a/include/graphblas/benchmark.hpp +++ b/include/graphblas/benchmark.hpp @@ -30,9 +30,9 @@ #ifdef _GRB_WITH_REFERENCE #include "graphblas/reference/benchmark.hpp" #endif -#ifdef _GRB_WITH_DENSE - #include "graphblas/denseref/benchmark.hpp" -#endif +// #ifdef _GRB_WITH_DENSE +// #include "graphblas/denseref/benchmark.hpp" +// #endif #ifdef _GRB_WITH_BANSHEE #include "graphblas/banshee/benchmark.hpp" #endif diff --git a/include/graphblas/blas1.hpp b/include/graphblas/blas1.hpp index 24d9ba3d4..87a4797e3 100644 --- a/include/graphblas/blas1.hpp +++ b/include/graphblas/blas1.hpp @@ -38,5 +38,350 @@ #include #endif +// the remainder implements several backend-agnostic short-cuts + +#define NO_CAST_RING_ASSERT( x, y, z ) \ + static_assert( x, \ + "\n\n" \ + "************************************************************************" \ + "************************************************************************" \ + "**********************\n" \ + "* ERROR | " y " " z ".\n" \ + "************************************************************************" \ + "************************************************************************" \ + "**********************\n" \ + "* Possible fix 1 | Remove no_casting from the template parameters in " \ + "this call to " y ".\n" \ + "* Possible fix 2 | For all mismatches in the domains of input " \ + "parameters and the semiring domains, as specified in the documentation " \ + "of the function " y ", supply an input argument of the expected type " \ + "instead.\n" \ + "* Possible fix 3 | Provide a compatible semiring where all domains " \ + "match those of the input parameters, as specified in the documentation " \ + "of the function " y ".\n" \ + "************************************************************************" \ + "************************************************************************" \ + "**********************\n" ); + +namespace grb { + + /** + * A standard vector to use for mask parameters. Indicates no mask shall be + * used. + */ + #define NO_MASK Vector< bool >( 0 ) + + /** + * Executes an arbitrary element-wise user-defined function \a f using any + * number of vectors of equal length, following the nonzero pattern of the + * given vector \a x. + * + * The user-defined function is passed as a lambda which can capture, at + * the very least, other instances of type grb::Vector. Use of this function + * is preferable whenever multiple element-wise operations are requested that + * use one or more identical input vectors. Performing the computation one + * after the other in blocking mode would require the same vector to be + * streamed multiple times, while with this function the operations can be + * fused explicitly instead. + * + * It shall always be legal to capture non-GraphBLAS objects for read access + * only. It shall \em not be legal to capture instances of type grb::Matrix + * for read and/or write access. + * + * If grb::Properties::writableCaptured evaluates true then captured + * non-GraphBLAS objects can also be written to, not just read from. The + * captured variable is, however, completely local to the calling user process + * only-- it will not be synchronised between user processes. + * As a rule of thumb, data-centric GraphBLAS implementations \em cannot + * support this and will thus have grb::Properties::writableCaptured evaluate + * to false. A portable GraphBLAS algorithm should provide a different code + * path to handle this case. + * When it is legal to write to captured scalar, this function can, e.g., be + * used to perform reduction-like operations on any number of equally sized + * input vectors. This would be preferable to a chained number of calls to + * grb::dot in case where some vectors are shared between subsequent calls, + * for example; the shared vectors are streamed only once using this lambda- + * enabled function. + * + * \warning The lambda shall only be executed on the data local to the user + * process calling this function! This is different from the various + * fold functions, or grb::dot, in that the semantics of those + * functions always end with a globally synchronised result. To + * achieve the same effect with user-defined lambdas, the users + * should manually prescribe how to combine the local results into + * global ones, for instance, by a subsequent call to + * grb::collectives<>::allreduce. + * + * \note This is an addition to the GraphBLAS. It is alike user-defined + * operators, monoids, and semirings, except it allows execution on + * arbitrarily many inputs and arbitrarily many outputs. + * + * @tparam Func the user-defined lambda function type. + * @tparam DataType the type of the user-supplied vector example. + * @tparam backend the backend type of the user-supplied vector example. + * + * @param[in] f The user-supplied lambda. This lambda should only capture + * and reference vectors of the same length as \a x. The lambda + * function should prescribe the operations required to execute + * at a given index \a i. Captured GraphBLAS vectors can access + * that element via the operator[]. It is illegal to access any + * element not at position \a i. The lambda takes only the single + * parameter \a i of type const size_t. Captured + * scalars will not be globally updated-- the user must program + * this explicitly. Scalars and other non-GraphBLAS containers + * are always local to their user process. + * @param[in] x The vector the lambda will be executed on. This argument + * determines which indices \a i will be accessed during the + * elementwise operation-- elements with indices \a i that + * do not appear in \a x will be skipped during evaluation of + * \a f. + * @param[in] args All vectors the lambda is to access elements of. Must be of + * the same length as \a x. If this constraint is violated, + * grb::MISMATCH shall be returned. This is a variadic + * argument and can contain any number of containers of type + * grb::Vector, passed as though they were separate + * arguments. + * + * \note In future GraphBLAS implementations, \a args, apart from doing + * dimension checking, should also facilitate any data distribution + * necessary to successfully execute the element-wise operation. Current + * implementations do not require this since they use the same static + * distribution for all containers. + * + * \warning Using a grb::Vector inside a lambda passed to this function while + * not passing that same vector into \a args, will result in undefined + * behaviour. + * + * \note It would be natural to have \a x equal to one of the captured + * GraphBLAS vectors in \a f. + * + * \warning Due to the constraints on \a f described above, it is illegal to + * capture some vector \a y and have the following line in the body + * of \a f: x[i] += x[i+1]. Vectors can only be + * dereferenced at position \a i and \a i alone. + * + * @return grb::SUCCESS When the lambda is successfully executed. + * @return grb::MISMATCH When two or more vectors passed to \a args are not of + * equal length. + * + * \parblock + * \par Example. + * + * An example valid use: + * + * \code + * void f( + * double &alpha, + * grb::Vector< double > &y, + * const double beta, + * const grb::Vector< double > &x, + * const grb::Semiring< double > ring + * ) { + * assert( grb::size(x) == grb::size(y) ); + * assert( grb::nnz(x) == grb::size(x) ); + * assert( grb::nnz(y) == grb::size(y) ); + * alpha = ring.getZero(); + * grb::eWiseLambda( + * [&alpha,beta,&x,&y,ring]( const size_t i ) { + * double mul; + * const auto mul_op = ring.getMultiplicativeOperator(); + * const auto add_op = ring.getAdditiveOperator(); + * grb::apply( y[i], beta, x[i], mul_op ); + * grb::apply( mul, x[i], y[i], mul_op ); + * grb::foldl( alpha, mul, add_op ); + * }, x, y ); + * grb::collectives::allreduce( alpha, add_op ); + * } + * \endcode + * + * This code takes a value \a beta, a vector \a x, and a semiring \a ring and + * computes: + * 1) \a y as the element-wise multiplication (under \a ring) of \a beta and + * \a x; and + * 2) \a alpha as the dot product (under \a ring) of \a x and \a y. + * This function can easily be made agnostic to whatever exact semiring is used + * by templating the type of \a ring. As it is, this code is functionally + * equivalent to: + * + * \code + * grb::eWiseMul( y, beta, x, ring ); + * grb::dot( alpha, x, y, ring ); + * \endcode + * + * The version using the lambdas, however, is expected to execute + * faster as both \a x and \a y are streamed only once, while the + * latter code may stream both vectors twice. + * \endparblock + * + * \warning The following code is invalid: + * \code + * template< class Operator > + * void f( + * grb::Vector< double > &x, + * const Operator op + * ) { + * grb::eWiseLambda( + * [&x,&op]( const size_t i ) { + * grb::apply( x[i], x[i], x[i+1], op ); + * }, x ); + * } + * \endcode + * Only a Vector::lambda_reference to position exactly equal to \a i + * may be used within this function. + * + * \warning There is no similar concept in the official GraphBLAS specs. + * + * \warning Captured scalars will be local to the user process executing the + * lambda. To retrieve the global dot product, an allreduce must + * explicitly be called. + * + * @see Vector::operator[]() + * @see Vector::lambda_reference + */ + template< + typename Func, + typename DataType, + Backend backend, + typename Coords, + typename... Args + > + RC eWiseLambda( + const Func f, + const Vector< DataType, backend, Coords > & x, Args... + ) { + (void)f; + (void)x; + return PANIC; + } + + /** + * Alias for a simple reduce call. + * + * Will use no mask and will set the accumulator to the given Monoid's + * operator. + */ + template< + Descriptor descr = descriptors::no_operation, + class Monoid, + typename IOType, typename InputType, + Backend backend, + typename Coords + > + RC foldl( IOType &x, + const Vector< InputType, backend, Coords > &y, + const Monoid &monoid = Monoid(), + const typename std::enable_if< !grb::is_object< IOType >::value && + grb::is_monoid< Monoid >::value, + void >::type * const = NULL + ) { + // create empty mask + Vector< bool, backend, Coords > mask( 0 ); + // call regular reduce function + return foldl< descr >( x, y, mask, monoid ); + } + + /** + * Alias for a simple reduce call. + * + * Will use no mask and will set the accumulator to the given Monoid's + * operator. + */ + template< + Descriptor descr = descriptors::no_operation, + class OP, + typename IOType, typename InputType, + Backend backend, typename Coords + > + RC foldl( IOType &x, + const Vector< InputType, backend, Coords > &y, + const OP &op = OP(), + const typename std::enable_if< !grb::is_object< IOType >::value && + grb::is_operator< OP >::value, + void >::type * const = NULL + ) { + // create empty mask + Vector< bool, backend, Coords > mask( 0 ); + // call regular reduce function + return foldl< descr >( x, y, mask, op ); + } + + /** + * Provides a generic implementation of the dot computation on semirings by + * translating it into a dot computation on an additive commutative monoid + * with any multiplicative operator. + * + * For return codes, exception behaviour, performance semantics, template + * and non-template arguments, @see grb::dot. + */ + template< + Descriptor descr = descriptors::no_operation, class Ring, + typename IOType, typename InputType1, typename InputType2, + Backend backend, typename Coords + > + RC dot( IOType &x, + const Vector< InputType1, backend, Coords > &left, + const Vector< InputType2, backend, Coords > &right, + const Ring &ring = Ring(), + const typename std::enable_if< + !grb::is_object< InputType1 >::value && + !grb::is_object< InputType2 >::value && + !grb::is_object< IOType >::value && + grb::is_semiring< Ring >::value, + void >::type * const = NULL + ) { + return grb::dot< descr >( x, + left, right, + ring.getAdditiveMonoid(), + ring.getMultiplicativeOperator() + ); + } + + /** + * Provides a generic implementation of the 2-norm computation. + * + * Proceeds by computing a dot-product on itself and then taking the square + * root of the result. + * + * This function is only available when the output type is floating point. + * + * For return codes, exception behaviour, performance semantics, template + * and non-template arguments, @see grb::dot. + * + * @param[out] x The 2-norm of \a y. The input value of \a x will be ignored. + * @param[in] y The vector to compute the norm of. + * @param[in] ring The Semiring under which the 2-norm is to be computed. + * + * \warning This function computes \a x out-of-place. This is contrary to + * standard ALP/GraphBLAS functions that are always in-place. + * + * \warning A \a ring is not sufficient for computing a two-norm. This + * implementation assumes the standard sqrt function + * must be applied on the result of a dot-product of \a y with + * itself under the supplied semiring. + */ + template< + Descriptor descr = descriptors::no_operation, class Ring, + typename InputType, typename OutputType, + Backend backend, typename Coords + > + RC norm2( OutputType &x, + const Vector< InputType, backend, Coords > &y, + const Ring &ring = Ring(), + const typename std::enable_if< + std::is_floating_point< OutputType >::value, + void >::type * const = NULL + ) { + RC ret = grb::dot< descr >( x, y, y, ring ); + if( ret == SUCCESS ) { + x = sqrt( x ); + } + return ret; + } + + +} // namespace grb + +#undef NO_CAST_RING_ASSERT + #endif // end ``_H_GRB_BLAS1'' diff --git a/include/graphblas/collectives.hpp b/include/graphblas/collectives.hpp index e0801b608..e541e317c 100644 --- a/include/graphblas/collectives.hpp +++ b/include/graphblas/collectives.hpp @@ -30,9 +30,9 @@ #ifdef _GRB_WITH_REFERENCE #include #endif -#ifdef _GRB_WITH_DENSE - #include -#endif +// #ifdef _GRB_WITH_DENSE +// #include +// #endif #ifdef _GRB_WITH_LPF #include #endif diff --git a/include/graphblas/denseref/exec.hpp b/include/graphblas/denseref/exec.hpp index 516c5e427..248e345a6 100644 --- a/include/graphblas/denseref/exec.hpp +++ b/include/graphblas/denseref/exec.hpp @@ -23,6 +23,10 @@ #ifndef _H_GRB_DENSEREF_EXEC #define _H_GRB_DENSEREF_EXEC +#include +#include +#include + namespace grb { /** @@ -35,7 +39,7 @@ namespace grb { /** \internal No implementation notes. */ Launcher( const size_t process_id = 0, - const size_t nprocs = 0, + const size_t nprocs = 1, const std::string hostname = "localhost", const std::string port = "0" ) { diff --git a/include/graphblas/exec.hpp b/include/graphblas/exec.hpp index be2857df5..95b8e325d 100644 --- a/include/graphblas/exec.hpp +++ b/include/graphblas/exec.hpp @@ -30,7 +30,7 @@ #ifdef _GRB_WITH_REFERENCE #include "graphblas/reference/exec.hpp" #endif -#ifdef _GRB_WITH_DENSE +#ifdef _GRB_WITH_DENSEREF #include "graphblas/denseref/exec.hpp" #endif #ifdef _GRB_WITH_LPF diff --git a/include/graphblas/init.hpp b/include/graphblas/init.hpp index e54637fc8..8fb5377c5 100644 --- a/include/graphblas/init.hpp +++ b/include/graphblas/init.hpp @@ -31,7 +31,7 @@ #ifdef _GRB_WITH_REFERENCE #include "graphblas/reference/init.hpp" #endif -#ifdef _GRB_WITH_DENSE +#ifdef _GRB_WITH_DENSEREF #include "graphblas/denseref/init.hpp" #endif #ifdef _GRB_WITH_LPF diff --git a/include/graphblas/matrix.hpp b/include/graphblas/matrix.hpp index a44411a1d..efab5ca60 100644 --- a/include/graphblas/matrix.hpp +++ b/include/graphblas/matrix.hpp @@ -30,7 +30,7 @@ #ifdef _GRB_WITH_REFERENCE #include #endif -#ifdef _GRB_WITH_DENSE +#ifdef _GRB_WITH_DENSEREF #include #endif #ifdef _GRB_WITH_LPF diff --git a/include/graphblas/spmd.hpp b/include/graphblas/spmd.hpp index 114a1141c..e9aee3f55 100644 --- a/include/graphblas/spmd.hpp +++ b/include/graphblas/spmd.hpp @@ -29,9 +29,9 @@ #ifdef _GRB_WITH_REFERENCE #include "graphblas/reference/spmd.hpp" #endif -#ifdef _GRB_WITH_DENSE - #include "graphblas/denseref/spmd.hpp" -#endif +// #ifdef _GRB_WITH_DENSE +// #include "graphblas/denseref/spmd.hpp" +// #endif #ifdef _GRB_WITH_LPF #include "graphblas/bsp1d/spmd.hpp" #endif diff --git a/include/graphblas/vector.hpp b/include/graphblas/vector.hpp index 6286cc59d..8c98bd886 100644 --- a/include/graphblas/vector.hpp +++ b/include/graphblas/vector.hpp @@ -31,9 +31,9 @@ #ifdef _GRB_WITH_REFERENCE #include #endif -#ifdef _GRB_WITH_DENSE - #include -#endif +// #ifdef _GRB_WITH_DENSE +// #include +// #endif #ifdef _GRB_WITH_LPF #include #endif diff --git a/include/graphblas/views.hpp b/include/graphblas/views.hpp index 454d9d846..4d2c5b315 100644 --- a/include/graphblas/views.hpp +++ b/include/graphblas/views.hpp @@ -46,10 +46,9 @@ namespace grb { template< typename OriginalType > struct Transpose { - using applied_to = original_view; - using dims_retval_type = std::pair< size_t, size_t > + using applied_to = OriginalType; - static dims_retval_type dims( std::pair< size_t, size_t > dims_pair ) { + static std::pair< size_t, size_t > dims( std::pair< size_t, size_t > dims_pair ) { return std::make_pair( dims_pair.second, dims_pair.first ); } }; diff --git a/src/graphblas/CMakeLists.txt b/src/graphblas/CMakeLists.txt index 52e49d850..6e2ffe06f 100644 --- a/src/graphblas/CMakeLists.txt +++ b/src/graphblas/CMakeLists.txt @@ -83,7 +83,7 @@ if( WITH_REFERENCE_BACKEND OR WITH_OMP_BACKEND ) add_subdirectory( reference ) endif() -if( WITH_DENSE_BACKEND ) +if( WITH_DENSEREF_BACKEND ) add_subdirectory( denseref ) endif() diff --git a/src/graphblas/denseref/CMakeLists.txt b/src/graphblas/denseref/CMakeLists.txt index ea0bc7a7b..f1e8c1b63 100644 --- a/src/graphblas/denseref/CMakeLists.txt +++ b/src/graphblas/denseref/CMakeLists.txt @@ -15,20 +15,22 @@ # assert_valid_variables( BACKEND_LIBRARY_OUTPUT_NAME VERSION - SHMEM_BACKEND_INSTALL_DIR INCLUDE_INSTALL_DIR - DENSE_BACKEND_DEFAULT_NAME - DENSE_SELECTION_DEFS backend_reference_srcs + DENSEREF_BACKEND_INSTALL_DIR INCLUDE_INSTALL_DIR + DENSEREF_BACKEND_DEFAULT_NAME + DENSEREF_SELECTION_DEFS #backend_reference_srcs ) -# sources for bsp1d backend +# sources for dense reference backend set( backend_reference_dense_srcs + ${CMAKE_CURRENT_SOURCE_DIR}/../descriptors.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/../rc.cpp ${CMAKE_CURRENT_SOURCE_DIR}/init.cpp ) add_library( backend_reference_dense_static STATIC "${backend_reference_dense_srcs}" ) target_link_libraries( backend_reference_dense_static PUBLIC backend_reference_dense_headers ) -target_link_libraries( backend_reference_dense_static PRIVATE backend_common_utils ) +# target_link_libraries( backend_reference_dense_static PRIVATE backend_common_utils ) set_target_properties( backend_reference_dense_static PROPERTIES POSITION_INDEPENDENT_CODE true @@ -42,15 +44,16 @@ set_target_properties( backend_reference_dense_static PROPERTIES target_compile_options( backend_reference_dense_static PRIVATE "${BACKEND_COMPILE_OPTIONS}" ) target_compile_definitions( backend_reference_dense_static PRIVATE "${BACKEND_COMPILE_DEFINITIONS}" ) -target_compile_definitions( backend_reference_dense_static INTERFACE "${REFERENCE_DENSE_SELECTION_DEFS}" ) +target_compile_definitions( backend_reference_dense_static PRIVATE "${DENSEREF_SELECTION_DEFS}" ) add_dependencies( libs backend_reference_dense_static ) install( TARGETS backend_reference_dense_static EXPORT GraphBLASTargets - ARCHIVE DESTINATION "${REFERENCE_DENSE_BACKEND_INSTALL_DIR}" -) + # ARCHIVE DESTINATION "${REFERENCE_DENSE_BACKEND_INSTALL_DIR}" + ARCHIVE DESTINATION "${DENSEREF_BACKEND_INSTALL_DIR}" + ) # this is an alias for add_grb_executables() to select the backend to link against # DO NOT CHANGE THE ALIAS NAME! -add_library( "${DENSE_BACKEND_DEFAULT_NAME}" ALIAS backend_reference_dense_static ) +add_library( "${DENSEREF_BACKEND_DEFAULT_NAME}" ALIAS backend_reference_dense_static ) diff --git a/tests/mlir/quick_test.cpp b/tests/mlir/quick_test.cpp new file mode 100644 index 000000000..1bb702ac6 --- /dev/null +++ b/tests/mlir/quick_test.cpp @@ -0,0 +1,78 @@ + +/* + * Copyright 2021 Huawei Technologies Co., Ltd. + * + * 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. + */ + +#include +#include +#include + +// template< typename ... S > +// struct structure_list {}; + +// template<> +// struct structure_list<> {}; + +// template< typename SA, typename SB > +// struct structure_list_cat; + +// template< typename ... SA, typename ... SB > +// struct structure_list_cat< structure_list< SA ... >, structure_list< SB ... > > +// { typedef structure_list< SA ..., SB ... > type; }; + +template< typename ... t > +struct structure_tuple_cat + { typedef decltype( std::tuple_cat( std::declval< t >() ... ) ) type; }; + +struct Square { + + using inferred_structures = std::tuple; + +}; + +struct FullRank { + + using inferred_structures = std::tuple; + +}; + +struct NonSingular { + + using inferred_structures = structure_tuple_cat< Square::inferred_structures, FullRank::inferred_structures >::type; + +}; + +template +struct is_in; + +template +struct is_in> : std::false_type {}; + +template +struct is_in< Structure, std::tuple > : is_in> {}; + +template +struct is_in> : std::true_type {}; + +template +struct is_a { + static constexpr bool value = is_in< Test, typename Structure::inferred_structures >::value; +}; + +int main(int argc, char **argv) { + + std::cout << is_a< NonSingular, Square >::value << std::endl; + return 0; +} diff --git a/tests/mlir/test.x b/tests/mlir/test.x new file mode 100755 index 0000000000000000000000000000000000000000..f7f67c790682144d19cd1f8aa0dc625eb6a9cde9 GIT binary patch literal 17280 zcmeHOZERcB89t7iHl?lObj?W9LCnXbmMU)2rXdBo+DV*Vv!sN4jPg-#9oucJC3di{ zX@Ump)D6{xjBJ0#CVqg}1c+(s_Nz<+QVOh-25Nt71F>m^tt{CXlrT`)+Ir7>?s;#n zZ=4Cx{vh2WUBBl%@7Fo+IX?EW&-=|tcUOhSBe;0QR|K`D{U#DpjOpuD1tcWe#45Zt zh|9%Nw3kTC{Z;76~VdBMSPk;324K;TRHayNY$S28AA$^`=YEyj$ z9+EM~|9x2}jLOO6tE06Kuk0{e3tx3Ws~5uJy+!a}E`lFl1aANyz~d}5nsR(@&G9>id`i+)kIx!NB z_Z!X4@!?ojH?pymk&DJ7kv?EshGMx?T+if;Y%(?)9nc4w^hkdzT*HXbmdfOGNF-aL z>6Fpg9JyQKWW2YluRqhTN6HCyn1b*f&*Tk(F~)g#@$r}*Gm_&e17oGezEnCklDY@u z(Me7XeKeLzi=Exk_Kw}V^)0~`v#xIrZVqmxxOuTMy>hiuZ65Jpby8?~K8+1Oz*gfG zm#KIY_l)9`R=z&9oL2b;#pivJ_oqi|NJ@xPEngfExif0&WD{2z-7c@Im$E|JDw@ zQ>8sn`T8aywC_wC6~&X{V+O>}MDo4B0-fsS9v~cQ9t?-t1=&xsc z2f8OK-$swL$yFIiwjYE0V(nZ|h<{CKliSxqSDUO{O=R0SqZUJd6+9aH^5W_0hJz3n z#}$SAEHNjyzC~oiMXhjFJNE7l?btc5=6P8=bF2CW@axIi!%uX=jF<0A?Mix-4gxT17MP&LFi$!{DphZ zYlZyT=cuFT;5b?N3#@2`7toiF@za4;cv&m_Vdm!mkCN1Hjyv=V`E!TvJ@3hH{?@(c zibZs80}O@We&)MmXtMSnWMy(|BSq!A z7vAkG{4HEu^JneQagVm`Px-&odc1v4_>SV|LAxa9hwl}f{t>)2Yk zlI^~@5pW~mM!=1L8v!>0ZUo#2xDjw8;6}iWfQo=e{fppP=e?f(bEW?#>dqF6he3xy zkARMYo&Y@xItKdK`^DmE&^JNp&z|61u^6DEHfRX+DCl826r#|7pj15f^a;#o^y^_2vZ z{vCLZKu#(Wh(fr5=SkopP%h-_K|IgEUx>hn&wqbK$Eu|V&>=L5|1&(VgWm&c@hdu| z0P%l|XDPO4E?+^}tl4zID|4>ELSNA<{#21)c67j8nu(H$FbpKM#*LG;x zPG2bPYYY3D!oKzGzCgRLuHENv_f^UN%~}wj^{`|Azllt`#f^X)0XG6}1l$O?5pW~m zM!=1L8-dSf1o&PX-(%x@YwFlU$0}Kvo>A?Uit>HoRjPeL-G`HB6JUIgZk^)u8L3{i z`Q99zYpBo}h{}f-iy5Mis!L?n8AMh1uGk61=R0d#RY&sm4j8CbKaKGvNNrms$vH#0W*c#t|istwrE>-b=rW|jtvWI^$ zWt;njc*1S+bYqn7r`uq8pOo*Pm*PvrH_F|^$BU)F^E;2yt<~j%*F`CQiQx5Dim$NNX(^6(ZJBxUB8wtW z7Wavq?~oc)2Hx& zx<|}h|eGVAJbY_Jt{v)K{A0Wzbx@K`m?&C z%=?#c7P8Tp#OL>cO^R2)hiVQrCFzB5ChpMgrq1-1TAF8#L@{Q z#h7~3Zc3$uzO(zL_HZ{;@Q-qjcGiRh7Cos>(XBgsjRXbRLi`-I+k>#lH5 zv;(}7o+nBHnT=z4xT&kFKY~1&aC>(IR+EXC5koT0P3UYQmDcmQB&pj|TS6h3$)d7X zK6_4%vZFF$Fr&GQK8#>cGLUp=Ce}FJnaMz$uj4d=oFWboB@0o)j#Gq2Xy)a>&rmMM z^@SNil=$P+mRUXVTwaFwe`hpt-qNBbXepu(jzl3P&hagiLbYg`RGAE?Qs*L=n;11> zL!d_1q{CcGrIC|0CW7gVkqqun=YwO}%vdsOOxU2IdU?a@XfwqHo`;aF~1 z1QQc!xG<@aH92=DvpKBnl7u?ntO~II{j=2{>>=~oj2g+=Up8=w8OxVKlS!@>m zzRr}-hl(v_xlZ&dJai^weg0n0GytBx@Oh1~R#fczyRpAgVM_l8+6#aFG8RR}uFvNL zrU4dI)Tw_9@Q-k&+`vTX&VI>h5ATU9zUN?Q^07* ztZ$u9)CU)zt05wbGRIAE7ix57Wqm%!Fy-?;_n+mM-Uod;19O|tJ4{2$6UUhQuV68W z3dNN5r<5b60o7sl&-y(6A1eKJWsuMLO!q3B^hw95{}?cG!S?ZG#4L(BPXx~Sf5f35 zP*ZcD=NzNm_FmspH>W}l{_&HeKz~NL!Zx! zO!@aEmUqVQC8ck<2`EWL`TLhb_o(4ukwDi^QYE$X}Fh)wY!um{?LfNh_LQ1&Fr0j=HupYNpLYXl39}1Zq zztXQGt5o1F19LMT?mzE8%Ykv``uYFxjukrL$6b{l~5|CF>j;8o8^kR5^ literal 0 HcmV?d00001 diff --git a/tests/unit/dense_mxm.cpp b/tests/unit/dense_mxm.cpp index ab5e74d69..06066636f 100644 --- a/tests/unit/dense_mxm.cpp +++ b/tests/unit/dense_mxm.cpp @@ -38,8 +38,8 @@ void grb_program( const size_t & n, grb::RC & rc ) { std::cout << "_GRB_WITH_REFERENCE defined\n"; #endif - #ifdef _GRB_WITH_DENSE - std::cout << "_GRB_WITH_DENSE defined\n"; + #ifdef _GRB_WITH_DENSEREF + std::cout << "_GRB_WITH_DENSEREF defined\n"; #endif rc = grb::SUCCESS; From 62dea77068742999cced049fb4dc95e22c085bc9 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Thu, 3 Feb 2022 11:35:55 +0100 Subject: [PATCH 021/282] Fix cmake option name --- bootstrap.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bootstrap.sh b/bootstrap.sh index 25c81da93..8a2e7e032 100755 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -293,9 +293,9 @@ the current directory before invocation or confirm the deletion of its content w CMAKE_OPTS+=" -DWITH_REFERENCE_BACKEND=OFF -DWITH_OMP_BACKEND=OFF" fi if [[ "${dense}" == "no" ]]; then - CMAKE_OPTS+=" -DWITH_DENSE_BACKEND=OFF" + CMAKE_OPTS+=" -DWITH_DENSEREF_BACKEND=OFF" else - CMAKE_OPTS+=" -DWITH_DENSE_BACKEND=ON" + CMAKE_OPTS+=" -DWITH_DENSEREF_BACKEND=ON" fi if [[ "${lpf}" == "yes" ]]; then CMAKE_OPTS+=" -DLPF_INSTALL_PATH='${ABSOLUTE_LPF_INSTALL_PATH}'" From 72efb6e521c5939b36d94f48775a90a6559f5d58 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Thu, 3 Feb 2022 12:02:59 +0100 Subject: [PATCH 022/282] Use a proper data container for a denseref matrix --- include/graphblas/denseref/matrix.hpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/include/graphblas/denseref/matrix.hpp b/include/graphblas/denseref/matrix.hpp index a3f94eeb9..67456c73b 100644 --- a/include/graphblas/denseref/matrix.hpp +++ b/include/graphblas/denseref/matrix.hpp @@ -59,10 +59,12 @@ namespace grb { */ size_t n; + /** The matrix data. */ + T *__restrict__ data; + /** Whether the container presently is uninitialized. */ bool initialized; - std::vector< T > container; public: /** @see Matrix::value_type */ typedef T value_type; From 18aa481446ed46851021134ec09f42833079368a Mon Sep 17 00:00:00 2001 From: Anonymous Date: Thu, 3 Feb 2022 13:03:47 +0100 Subject: [PATCH 023/282] Change PRIVATE to INTERFACE for denseref backend --- src/graphblas/denseref/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/graphblas/denseref/CMakeLists.txt b/src/graphblas/denseref/CMakeLists.txt index f1e8c1b63..38677d999 100644 --- a/src/graphblas/denseref/CMakeLists.txt +++ b/src/graphblas/denseref/CMakeLists.txt @@ -44,7 +44,7 @@ set_target_properties( backend_reference_dense_static PROPERTIES target_compile_options( backend_reference_dense_static PRIVATE "${BACKEND_COMPILE_OPTIONS}" ) target_compile_definitions( backend_reference_dense_static PRIVATE "${BACKEND_COMPILE_DEFINITIONS}" ) -target_compile_definitions( backend_reference_dense_static PRIVATE "${DENSEREF_SELECTION_DEFS}" ) +target_compile_definitions( backend_reference_dense_static INTERFACE "${DENSEREF_SELECTION_DEFS}" ) add_dependencies( libs backend_reference_dense_static ) From a4213df0325e8b697dca450927fa7f4c1fb896c5 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Thu, 3 Feb 2022 14:35:05 +0100 Subject: [PATCH 024/282] fix cmake config for building backend --- src/graphblas/denseref/CMakeLists.txt | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/src/graphblas/denseref/CMakeLists.txt b/src/graphblas/denseref/CMakeLists.txt index 38677d999..d78119234 100644 --- a/src/graphblas/denseref/CMakeLists.txt +++ b/src/graphblas/denseref/CMakeLists.txt @@ -17,7 +17,7 @@ assert_valid_variables( BACKEND_LIBRARY_OUTPUT_NAME VERSION DENSEREF_BACKEND_INSTALL_DIR INCLUDE_INSTALL_DIR DENSEREF_BACKEND_DEFAULT_NAME - DENSEREF_SELECTION_DEFS #backend_reference_srcs + DENSEREF_SELECTION_DEFS ) # sources for dense reference backend @@ -30,11 +30,8 @@ set( backend_reference_dense_srcs add_library( backend_reference_dense_static STATIC "${backend_reference_dense_srcs}" ) target_link_libraries( backend_reference_dense_static PUBLIC backend_reference_dense_headers ) -# target_link_libraries( backend_reference_dense_static PRIVATE backend_common_utils ) set_target_properties( backend_reference_dense_static PROPERTIES - POSITION_INDEPENDENT_CODE true - INTERFACE_POSITION_INDEPENDENT_CODE true OUTPUT_NAME "${BACKEND_LIBRARY_OUTPUT_NAME}" ) @@ -42,15 +39,13 @@ set_target_properties( backend_reference_dense_static PROPERTIES ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/reference_dense" ) -target_compile_options( backend_reference_dense_static PRIVATE "${BACKEND_COMPILE_OPTIONS}" ) -target_compile_definitions( backend_reference_dense_static PRIVATE "${BACKEND_COMPILE_DEFINITIONS}" ) -target_compile_definitions( backend_reference_dense_static INTERFACE "${DENSEREF_SELECTION_DEFS}" ) +target_compile_definitions( backend_reference_dense_static PUBLIC "${DENSEREF_SELECTION_DEFS}" ) +target_link_libraries( backend_reference_dense_static PRIVATE backend_flags ) add_dependencies( libs backend_reference_dense_static ) install( TARGETS backend_reference_dense_static EXPORT GraphBLASTargets - # ARCHIVE DESTINATION "${REFERENCE_DENSE_BACKEND_INSTALL_DIR}" ARCHIVE DESTINATION "${DENSEREF_BACKEND_INSTALL_DIR}" ) From 24da3dd62ff476adbfff4c2c86889edb96313ef3 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Thu, 3 Feb 2022 18:11:54 +0100 Subject: [PATCH 025/282] Add friend functions for accessing matrix dimensions and raw data --- include/graphblas/denseref/matrix.hpp | 52 +++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/include/graphblas/denseref/matrix.hpp b/include/graphblas/denseref/matrix.hpp index 67456c73b..c9a3d4963 100644 --- a/include/graphblas/denseref/matrix.hpp +++ b/include/graphblas/denseref/matrix.hpp @@ -38,9 +38,41 @@ namespace grb { + + template< typename T > + T * getRaw( Matrix< T, reference_dense > & ) noexcept; + + template< typename T > + const T * getRaw( const Matrix< T, reference_dense > & ) noexcept; + + template< typename T > + size_t nrows( const Matrix< T, reference_dense > & ) noexcept; + + template< typename T > + size_t ncols( const Matrix< T, reference_dense > & ) noexcept; + /** \internal TODO */ template< typename T > class Matrix< T, reference_dense > { + + /* ********************* + BLAS2 friends + ********************* */ + + template< typename DataType > + friend size_t nrows( const Matrix< DataType, reference_dense > & m ) noexcept; + + template< typename DataType > + friend size_t ncols( const Matrix< DataType, reference_dense > & m ) noexcept; + + /* ********************* + `Getter' friends + ********************* */ + + friend T * getRaw( Matrix< T, reference_dense > &) noexcept; + + friend const T * getRaw( const Matrix< T, reference_dense > & ) noexcept; + private: /** Our own type. */ typedef Matrix< T, reference_dense > self_type; @@ -104,6 +136,26 @@ namespace grb { static const constexpr bool value = true; }; + template< typename T > + T * getRaw( Matrix< T, reference_dense > &m ) noexcept { + return m.data; + } + + template< typename T > + const T * getRaw( const Matrix< T, reference_dense > &m ) noexcept { + return m.data; + } + + template< typename T > + size_t nrows( const Matrix< T, reference_dense > &m ) noexcept { + return m.m; + } + + template< typename T > + size_t ncols( const Matrix< T, reference_dense > &m ) noexcept { + return m.n; + } + } // end namespace ``grb'' #endif // end ``_H_GRB_DENSEREF_MATRIX'' From 769e0278a72240c16a919c1a960a5eaf9152b2eb Mon Sep 17 00:00:00 2001 From: Anonymous Date: Thu, 3 Feb 2022 21:08:13 +0100 Subject: [PATCH 026/282] Add first version of blas3 mxm for reference dense backend --- include/graphblas/blas3.hpp | 2 +- include/graphblas/denseref/blas3.hpp | 99 ++++++++++++++++++++++++++++ 2 files changed, 100 insertions(+), 1 deletion(-) diff --git a/include/graphblas/blas3.hpp b/include/graphblas/blas3.hpp index acae03b56..a6d3eae8c 100644 --- a/include/graphblas/blas3.hpp +++ b/include/graphblas/blas3.hpp @@ -30,7 +30,7 @@ #ifdef _GRB_WITH_REFERENCE #include #endif -#ifdef _GRB_WITH_DENSE +#ifdef _GRB_WITH_DENSEREF #include #endif #ifdef _GRB_WITH_LPF diff --git a/include/graphblas/denseref/blas3.hpp b/include/graphblas/denseref/blas3.hpp index fa4485fee..6177498c7 100644 --- a/include/graphblas/denseref/blas3.hpp +++ b/include/graphblas/denseref/blas3.hpp @@ -23,7 +23,106 @@ #ifndef _H_GRB_DENSEREF_BLAS3 #define _H_GRB_DENSEREF_BLAS3 +#include //for std::enable_if + +#include + +#include "io.hpp" +#include "matrix.hpp" + namespace grb { + namespace internal { + + /** + * \internal general mxm implementation that all mxm variants refer to + */ + template< + bool allow_void, + class MulMonoid, + typename OutputType, typename InputType1, typename InputType2, + class Operator, class Monoid + > + RC mxm_generic( Matrix< OutputType, reference_dense > &C, + const Matrix< InputType1, reference_dense > &A, + const Matrix< InputType2, reference_dense > &B, + const Operator &oper, + const Monoid &monoid, + const MulMonoid &mulMonoid, + const typename std::enable_if< !grb::is_object< OutputType >::value && + !grb::is_object< InputType1 >::value && ! + grb::is_object< InputType2 >::value && + grb::is_operator< Operator >::value && + grb::is_monoid< Monoid >::value, + void >::type * const = NULL + ) { + (void)oper; + (void)monoid; + (void)mulMonoid; + static_assert( allow_void || + ( !( + std::is_same< InputType1, void >::value || std::is_same< InputType2, void >::value + ) ), + "grb::mxm_generic: the operator-monoid version of mxm cannot be " + "used if either of the input matrices is a pattern matrix (of type " + "void)" + ); + +#ifdef _DEBUG + std::cout << "In grb::internal::mxm_generic (reference_dense, unmasked)\n"; +#endif + + // run-time checks + const size_t m = grb::nrows( C ); + const size_t n = grb::ncols( C ); + const size_t m_A = grb::nrows( A ); + const size_t k = grb::ncols( A ); + const size_t k_B = grb::nrows( B ); + const size_t n_B = grb::ncols( B ); + + if( m != m_A || k != k_B || n != n_B ) { + return MISMATCH; + } + + const auto A_raw = grb::getRaw( A ); + const auto B_raw = grb::getRaw( B ); + auto C_raw = grb::getRaw( C ); + + std::cout << "Multiplying dense matrices.\n"; + + for( size_t row = 0; row < m; ++row ) { + for( size_t col = 0; col < n; ++col ) { + C_raw[ row * k + col] = 0; + for( size_t i = 0; i < k; ++ i ) { + C_raw[ row * k + col] += A_raw[ row * k + i ] * B_raw[ i * n_B + col ]; + } + } + } + + // internal::setInitialized( true ); + // done + return SUCCESS; + } + + } // namespace internal + + /** + * \internal grb::mxm, semiring version. + * Dispatches to internal::mxm_generic + */ + template< typename OutputType, typename InputType1, typename InputType2, class Semiring > + RC mxm( Matrix< OutputType, reference_dense > & C, + const Matrix< InputType1, reference_dense > & A, + const Matrix< InputType2, reference_dense > & B, + const Semiring & ring = Semiring(), + const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_semiring< Semiring >::value, + void >::type * const = NULL ) { + +#ifdef _DEBUG + std::cout << "In grb::mxm (reference_dense, unmasked, semiring)\n"; +#endif + + return internal::mxm_generic< true >( C, A, B, ring.getMultiplicativeOperator(), ring.getAdditiveMonoid(), ring.getMultiplicativeMonoid() ); + } } // end namespace ``grb'' From 84ff879943d664f3cbf6a58e80e3f3762219d830 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Thu, 3 Feb 2022 21:17:46 +0100 Subject: [PATCH 027/282] Add temporary code for matrix data initialization --- include/graphblas/denseref/matrix.hpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/include/graphblas/denseref/matrix.hpp b/include/graphblas/denseref/matrix.hpp index c9a3d4963..f8d96bfd0 100644 --- a/include/graphblas/denseref/matrix.hpp +++ b/include/graphblas/denseref/matrix.hpp @@ -103,7 +103,12 @@ namespace grb { /** @see Matrix::Matrix() */ Matrix( const size_t rows, const size_t columns ): m( rows ), n( columns ), initialized( false ) { - + // Temporary solution to initialize a matrix + // TODO: Use buildUnique + data = new T[ m * n ]; + for( size_t i = 0; i <= m * n; ++i ){ + data[i] = 1; + } } /** @see Matrix::Matrix( const Matrix & ) */ From 7de27847d8de56dbebb37f04117638f555fb849b Mon Sep 17 00:00:00 2001 From: Anonymous Date: Thu, 3 Feb 2022 21:15:46 +0100 Subject: [PATCH 028/282] Complete first working dense mxm unit test --- tests/unit/dense_mxm.cpp | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/tests/unit/dense_mxm.cpp b/tests/unit/dense_mxm.cpp index 06066636f..b1063cc54 100644 --- a/tests/unit/dense_mxm.cpp +++ b/tests/unit/dense_mxm.cpp @@ -23,6 +23,16 @@ using namespace grb; +void print_matrix( const grb::Matrix< double > & A) { + const double * Araw = grb::getRaw( A ); + for( size_t row = 0; row < grb::nrows( A ); ++row ) { + for( size_t col = 0; col < grb::ncols( A ); ++col ) { + std::cout << Araw[row * grb::ncols( A ) + col] << " "; + } + std::cout << "\n"; + } +} + void grb_program( const size_t & n, grb::RC & rc ) { grb::Semiring< grb::operators::add< double >, grb::operators::mul< double >, grb::identities::zero, grb::identities::one > ring; @@ -42,7 +52,10 @@ void grb_program( const size_t & n, grb::RC & rc ) { std::cout << "_GRB_WITH_DENSEREF defined\n"; #endif - rc = grb::SUCCESS; + std::cout << "Output matrix nrows = " << nrows( C ) << ", ncols = " << ncols( C ) << "\n"; + + rc = grb::mxm( C, A, B, ring ); + print_matrix(C); } From ee32863ad210d76f2e5fe0ec04183f0c0dea8459 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Thu, 3 Feb 2022 21:27:43 +0100 Subject: [PATCH 029/282] Added structured matrix test including draft static views and references --- include/graphblas/base/matrix.hpp | 63 +++--- include/graphblas/denseref/matrix.hpp | 293 +++++++++++++++++++++++-- include/graphblas/structures.hpp | 8 +- include/graphblas/views.hpp | 2 +- tests/unit/CMakeLists.txt | 4 + tests/unit/dense_structured_matrix.cpp | 112 ++++++++++ 6 files changed, 421 insertions(+), 61 deletions(-) create mode 100644 tests/unit/dense_structured_matrix.cpp diff --git a/include/graphblas/base/matrix.hpp b/include/graphblas/base/matrix.hpp index acc0ee0c5..9cd449332 100644 --- a/include/graphblas/base/matrix.hpp +++ b/include/graphblas/base/matrix.hpp @@ -430,21 +430,37 @@ namespace grb { }; +template< typename InputType, Backend backend > +RC clear( Matrix< InputType, backend > & A ) noexcept { + // this is the generic stub implementation + return UNSUPPORTED; +} + /** * An ALP structured matrix. * - * This is an opaque data type for that implements the below functions. + * This is an opaque data type for that implements the below functions. In essence it can be + * used to instantiate containers or references of containers. References may be matrices with + * their specific structure but do access data from a referenced StructuredMatrix, the latter being + * either a container or a reference itself. * * @tparam T The type of the matrix elements. \a T shall not be a GraphBLAS * type. * @tparam Structure One of the matrix structures in grb::structures. - * @tparam view One of the matrix views in enum grb::Views. All static views except for - * \a Views::original disable the possibility to instantiate a new container and only - * allow the creation of a reference to an existing \a StructuredMatrix - * (note that this could be view itself). A view could be instanciated into a separate container - * than its original source by explicit copy. - * @tparam backend Allows multiple backends to implement different - * versions of this data type. + * @tparam StorageSchemeType Either \a enum \a storage::Dense or \a enum \a storage::Sparse. + * A StructuredMatrix will be allowed to pick among the storage schemes within their specified + * \a StorageSchemeType. + * @tparam view One of the matrix views in \a grb::view. + * All static views except for \a view::Identity cannot instantiate a new container and only + * allow the creation of a reference to an existing \a StructuredMatrix. + * \a view::identity triggers the instatiation of an actual container for the StructuredMatrix. + * A reference view could be instanciated into a separate container than its original source by explicit + * copy into a container (e.g., via \a grb::set). + * The \a View parameter should not be used directly by the user but can be set using + * specific member types appropriately defined by each StructuredMatrix. + * (See examples of StructuredMatrix definitions in denseref backend folder or the + * \a dense_structured_matrix.cpp unit test). + * @tparam backend Allows multiple backends to implement different versions of this data type. * * \note The presence of different combination of structures and views could produce many specialization * with lots of logic replication. @@ -454,26 +470,6 @@ class StructuredMatrix { size_t m, n; - /** - * The container's data. - * The geometry and access scheme are specified by a combination of - * \a Structure, \a storage_scheme, \a m, and \a n. - */ - T * __restrict__ data; - - /** - * The container's storage scheme. \a storage_scheme is not exposed to the user as an option - * but can defined by ALP at different points in the execution depending on the \a backend choice. - * For example, if the container is associated to an I/O matrix, with a reference backend - * it might be set to reflect the storage scheme of the user data as specified at buildMatrix. - * If \a backend is set to \a mlir then the scheme could be fixed by the JIT compiler to effectively - * support its optimization strategy. - * At construction time and until the moment the scheme decision is made it may be set to - * an appropriate default choice, e.g. if \a StorageSchemeType is \a storage::Dense then - * \a storage::Dense::full could be used. - */ - StorageSchemeType storage_scheme; - /** Whether the container presently is initialized or not. */ bool initialized; @@ -498,13 +494,12 @@ class StructuredMatrix { * When view is \a original data should be properly deallocated. */ ~StructuredMatrix(); -}; +}; // class StructuredMatrix -template< typename InputType, Backend backend > -RC clear( Matrix< InputType, backend > & A ) noexcept { - // this is the generic stub implementation - return UNSUPPORTED; -} +template< typename T > +struct is_structured_matrix : std::false_type {}; +template< typename T, typename Structure, typename StorageSchemeType, typename View, enum Backend backend > +struct is_structured_matrix< StructuredMatrix< T, Structure, StorageSchemeType, View, backend > > : std::true_type {}; } // end namespace ``grb'' diff --git a/include/graphblas/denseref/matrix.hpp b/include/graphblas/denseref/matrix.hpp index f8d96bfd0..dd1224794 100644 --- a/include/graphblas/denseref/matrix.hpp +++ b/include/graphblas/denseref/matrix.hpp @@ -26,13 +26,10 @@ #include #include #include -#include #include #include -//#include -//#include -//#include #include +#include #include //#include //for help with dealing with pattern matrix input @@ -78,21 +75,21 @@ namespace grb { typedef Matrix< T, reference_dense > self_type; /** - * The number of rows. - * - * \internal Not declared const to be able to implement move in an elegant way. - */ + * The number of rows. + * + * \internal Not declared const to be able to implement move in an elegant way. + */ size_t m; /** - * The number of columns. - * - * \internal Not declared const to be able to implement move in an elegant way. - */ + * The number of columns. + * + * \internal Not declared const to be able to implement move in an elegant way. + */ size_t n; /** The matrix data. */ - T *__restrict__ data; + T * __restrict__ data; /** Whether the container presently is uninitialized. */ bool initialized; @@ -112,26 +109,23 @@ namespace grb { } /** @see Matrix::Matrix( const Matrix & ) */ - Matrix( const Matrix< T, reference_dense > &other ) : Matrix( other.m, other.n ) { + Matrix( const Matrix< T, reference_dense > & other ) : Matrix( other.m, other.n ) { initialized = other.initialized; } /** @see Matrix::Matrix( Matrix&& ). */ - Matrix( self_type &&other ) noexcept { - moveFromOther( std::forward< self_type >(other) ); + Matrix( self_type && other ) noexcept { + moveFromOther( std::forward< self_type >( other ) ); } /** * Move from temporary. */ - self_type& operator=( self_type &&other ) noexcept { - moveFromOther( std::forward< self_type >(other) ); + self_type & operator=( self_type && other ) noexcept { + moveFromOther( std::forward< self_type >( other ) ); return *this; } /** @see Matrix::~Matrix(). */ - ~Matrix() { - - } - + ~Matrix() {} }; // template specialisation for GraphBLAS type traits @@ -161,7 +155,258 @@ namespace grb { return m.n; } -} // end namespace ``grb'' + /** + * Here starts spec draft for StructuredMatrix + */ -#endif // end ``_H_GRB_DENSEREF_MATRIX'' + template< typename D, typename Structure, typename View > + size_t nrows( const StructuredMatrix< D, Structure, storage::Dense, View, reference_dense > & A ) noexcept { + return A._dims().first; + } + + template< typename D, typename Structure, typename View > + size_t ncols( const StructuredMatrix< D, Structure, storage::Dense, View, reference_dense > & A ) noexcept { + return A._dims().second; + } + + template< typename D, typename Structure, typename View > + std::pair< size_t, size_t > dims( const StructuredMatrix< D, Structure, storage::Dense, View, reference_dense > & A ) noexcept { + return A._dims(); + } + + template< typename T, typename Structure > + class StructuredMatrix< T, Structure, storage::Dense, view::Identity< void >, reference_dense > { + + private: + /********************* + Storage info friends + ******************** */ + + friend size_t nrows<>( const StructuredMatrix< T, Structure, storage::Dense, view::Identity< void >, reference_dense > & ) noexcept; + + friend size_t ncols<>( const StructuredMatrix< T, Structure, storage::Dense, view::Identity< void >, reference_dense > & ) noexcept; + + friend std::pair< size_t, size_t > dims<>( const StructuredMatrix< T, Structure, storage::Dense, view::Identity< void >, reference_dense > & ) noexcept; + + using self_type = StructuredMatrix< T, Structure, storage::Dense, view::Identity< void >, reference_dense >; + + // Using a matrix for now just to get some test going. Need to implement alloc + // logic for this backend. + // Matrix< T, reference_dense > A; + + size_t m, n; + + /** + * A container's storage scheme. \a storage_scheme is not exposed to the user as an option + * but can defined by ALP at different points in the execution depending on the \a backend choice. + * For example, if the container is associated to an I/O matrix, with a reference backend + * it might be set to reflect the storage scheme of the user data as specified at buildMatrix. + * If \a backend is set to \a mlir then the scheme could be fixed by the JIT compiler to effectively + * support its optimization strategy. + * At construction time and until the moment the scheme decision is made it may be set to + * an appropriate default choice, e.g. if \a StorageSchemeType is \a storage::Dense then + * \a storage::Dense::full could be used. + */ + storage::Dense storage_scheme; + + /** Whether the container presently is initialized or not. */ + bool initialized; + + std::pair< size_t, size_t > _dims() const { + return std::make_pair( m, n ); + } + + public: + using value_type = T; + using structure = Structure; + + // A general Structure knows how to define a reference to itself (which is an identity reference view). + using identity_t = StructuredMatrix< T, Structure, storage::Dense, view::Identity< self_type >, reference_dense >; + using reference_t = identity_t; + + StructuredMatrix( const size_t rows, const size_t cols ) : m( rows ), n( cols ), storage_scheme( storage::full ), initialized( false ) {} + }; // class StructuredMatrix + + template< typename T > + class StructuredMatrix< T, structures::General, storage::Dense, view::Identity< void >, reference_dense > { + + private: + /********************* + Storage info friends + ******************** */ + + friend size_t nrows<>( const StructuredMatrix< T, structures::General, storage::Dense, view::Identity< void >, reference_dense > & ) noexcept; + + friend size_t ncols<>( const StructuredMatrix< T, structures::General, storage::Dense, view::Identity< void >, reference_dense > & ) noexcept; + + friend std::pair< size_t, size_t > dims<>( const StructuredMatrix< T, structures::General, storage::Dense, view::Identity< void >, reference_dense > & ) noexcept; + + using self_type = StructuredMatrix< T, structures::General, storage::Dense, view::Identity< void >, reference_dense >; + + // Using a matrix for now just to get some test going. Need to implement alloc + // logic for this backend. + // Matrix< T, reference_dense > A; + + size_t m, n; + + /** + * The container's storage scheme. + */ + storage::Dense storage_scheme; + + /** Whether the container presently is initialized or not. */ + bool initialized; + + std::pair< size_t, size_t > _dims() const { + return std::make_pair( m, n ); + } + + public: + /** Exposes the element type and the structure. */ + using value_type = T; + using structure = structures::General; + + // A general Structure knows how to define a reference to itself (which is an identity reference view) + // as well as other static views. + using identity_t = StructuredMatrix< T, structures::General, storage::Dense, view::Identity< self_type >, reference_dense >; + using transpose_t = StructuredMatrix< T, structures::General, storage::Dense, view::Transpose< self_type >, reference_dense >; + + using reference_t = identity_t; + + StructuredMatrix( const size_t rows, const size_t cols ) : m( rows ), n( cols ), storage_scheme( storage::full ), initialized( false ) {} + + }; // StructuredMatrix General, container + + template< typename T > + class StructuredMatrix< T, structures::Square, storage::Dense, view::Identity< void >, reference_dense > { + + private: + /********************* + Storage info friends + ******************** */ + + friend size_t nrows<>( const StructuredMatrix< T, structures::Square, storage::Dense, view::Identity< void >, reference_dense > & ) noexcept; + + friend size_t ncols<>( const StructuredMatrix< T, structures::Square, storage::Dense, view::Identity< void >, reference_dense > & ) noexcept; + + friend std::pair< size_t, size_t > dims<>( const StructuredMatrix< T, structures::Square, storage::Dense, view::Identity< void >, reference_dense > & ) noexcept; + + using self_type = StructuredMatrix< T, structures::Square, storage::Dense, view::Identity< void >, reference_dense >; + + // Using a matrix for now just to get some test going. Need to implement alloc + // logic for this backend. + // Matrix< T, reference_dense > A; + + size_t m, n; + + /** + * The container's storage scheme. + */ + storage::Dense storage_scheme; + + /** Whether the container presently is initialized or not. */ + bool initialized; + + std::pair< size_t, size_t > _dims() const { + return std::make_pair( m, n ); + } + + public: + /** Exposes the element type and the structure. */ + using value_type = T; + using structure = structures::Square; + + using identity_t = StructuredMatrix< T, structures::Square, storage::Dense, view::Identity< self_type >, reference_dense >; + using transpose_t = StructuredMatrix< T, structures::Square, storage::Dense, view::Transpose< self_type >, reference_dense >; + + using reference_t = identity_t; + + StructuredMatrix( const size_t rows ) : m( rows ), n( rows ), storage_scheme( storage::full ), initialized( false ) {} + + }; // StructuredMatrix Square, container + + template< typename T, typename View > + class StructuredMatrix< T, structures::General, storage::Dense, View, reference_dense > { + + private: + using self_type = StructuredMatrix< T, structures::General, storage::Dense, View, reference_dense >; + using original_type = typename View::applied_to; + /********************* + Storage info friends + ******************** */ + + friend size_t nrows<>( const self_type & ) noexcept; + + friend size_t ncols<>( const self_type & ) noexcept; + + friend std::pair< size_t, size_t > dims<>( const self_type & ) noexcept; + + original_type & ref; + + std::pair< size_t, size_t > _dims() const { + return View::dims( dims( ref ) ); + } + + public: + /** Exposes the element type and the structure. */ + using value_type = T; + using structure = structures::General; + + using identity_t = StructuredMatrix< T, structures::General, storage::Dense, view::Identity< self_type >, reference_dense >; + using transpose_t = StructuredMatrix< T, structures::General, storage::Dense, view::Transpose< self_type >, reference_dense >; + + using reference_t = identity_t; + + StructuredMatrix( original_type & struct_mat ) : ref( struct_mat ) {} + + }; // StructuredMatrix General reference + + template< typename T, typename View > + class StructuredMatrix< T, structures::Square, storage::Dense, View, reference_dense > { + + private: + using self_type = StructuredMatrix< T, structures::Square, storage::Dense, View, reference_dense >; + using original_type = typename View::applied_to; + /********************* + Storage info friends + ******************** */ + + friend size_t nrows<>( const self_type & ) noexcept; + + friend size_t ncols<>( const self_type & ) noexcept; + + friend std::pair< size_t, size_t > dims<>( const self_type & ) noexcept; + + original_type & ref; + std::pair< size_t, size_t > _dims() const { + return View::dims( dims( ref ) ); + } + + public: + /** Exposes the element type and the structure. */ + using value_type = T; + using structure = structures::Square; + + using identity_t = StructuredMatrix< T, structures::Square, storage::Dense, view::Identity< self_type >, reference_dense >; + using transpose_t = StructuredMatrix< T, structures::Square, storage::Dense, view::Transpose< self_type >, reference_dense >; + + using reference_t = identity_t; + + StructuredMatrix( original_type & struct_mat ) : ref( struct_mat ) {} + + }; // StructuredMatrix Square reference + + namespace structures { + + // GraphBLAS type traits for structure + template< typename StructuredMatrix, typename Structure > + struct is_a { + static constexpr bool value = is_in< Structure, typename StructuredMatrix::structure::inferred_structures >::value; + }; + + } // namespace structures + +} // namespace grb + +#endif // end ``_H_GRB_DENSEREF_MATRIX'' diff --git a/include/graphblas/structures.hpp b/include/graphblas/structures.hpp index 3d4ccc6e0..34bec606d 100644 --- a/include/graphblas/structures.hpp +++ b/include/graphblas/structures.hpp @@ -88,8 +88,12 @@ namespace grb { /** * List of ALP matrix structures. */ + struct General { + using inferred_structures = std::tuple< General >; + }; + struct Square { - using inferred_structures = std::tuple< Square >; + using inferred_structures = structures::tuple_cat< std::tuple< Square >, General::inferred_structures >::type; }; struct Symmetric { @@ -113,7 +117,7 @@ namespace grb { }; struct FullRank { - using inferred_structures = std::tuple< FullRank >; + using inferred_structures = structures::tuple_cat< std::tuple< FullRank >, General::inferred_structures >::type; }; struct NonSingular { diff --git a/include/graphblas/views.hpp b/include/graphblas/views.hpp index 4d2c5b315..b4f3280bf 100644 --- a/include/graphblas/views.hpp +++ b/include/graphblas/views.hpp @@ -21,7 +21,7 @@ * conceived and noteworthy enough to be recorded for future consideration. * A static view represents a particular \em perspective on a container that * can be defined at compile-time and that can always be applied to a container - * irrespective of features such as its dimensions. + * irrespective of dynamic features such as its dimensions. */ #ifndef _H_GRB_VIEWS diff --git a/tests/unit/CMakeLists.txt b/tests/unit/CMakeLists.txt index 9f72f96ea..4367de4a6 100644 --- a/tests/unit/CMakeLists.txt +++ b/tests/unit/CMakeLists.txt @@ -208,6 +208,10 @@ add_grb_executables( dense_mxm dense_mxm.cpp BACKENDS reference_dense ) +add_grb_executables( dense_structured_matrix dense_structured_matrix.cpp + BACKENDS reference_dense +) + add_grb_executables( dense_spmv dense_spmv.cpp BACKENDS reference reference_omp bsp1d hybrid ) diff --git a/tests/unit/dense_structured_matrix.cpp b/tests/unit/dense_structured_matrix.cpp new file mode 100644 index 000000000..8b9c4c824 --- /dev/null +++ b/tests/unit/dense_structured_matrix.cpp @@ -0,0 +1,112 @@ + +/* + * Copyright 2021 Huawei Technologies Co., Ltd. + * + * 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. + */ + +#include +#include +#include +#include +#include + +#include + +template< typename StructuredMat > +void ask_questions( const StructuredMat & M, std::string name ) { + + using M_type = typename std::remove_const< typename std::remove_reference< decltype( M ) >::type >::type; + + std::cout << name << "( " << grb::nrows( M ) << ", " << grb::ncols( M ) << " )" << std::endl; + std::cout << "Is " << name << ":" << std::endl; + std::cout << "\ta structured Matrix? " << grb::is_structured_matrix< M_type >::value << std::endl; + std::cout << "\tgeneral? " << grb::structures::is_a< M_type, grb::structures::General >::value << std::endl; + std::cout << "\tsquare? " << grb::structures::is_a< M_type, grb::structures::Square >::value << std::endl; + std::cout << "\tfull rank? " << grb::structures::is_a< M_type, grb::structures::FullRank >::value << std::endl; + std::cout << "\tnon-singular? " << grb::structures::is_a< M_type, grb::structures::NonSingular >::value << std::endl; +} + +void grb_program( const size_t & n, grb::RC & rc ) { + + std::cout << "\tStarting structured matrices test with size: " << n << "\n"; + + // initialize test + grb::StructuredMatrix< float, grb::structures::General > M( n, 2 * n ); + grb::StructuredMatrix< float, grb::structures::Square > A( n ); + grb::StructuredMatrix< float, grb::structures::NonSingular > B( n, n ); + grb::StructuredMatrix< float, grb::structures::FullRank > C( n, 2 * n ); + decltype( A )::transpose_t At( A ); + decltype( M )::transpose_t Mt( M ); + + decltype( M )::reference_t Mref( M ); + + ask_questions( M, "M" ); + ask_questions( A, "A" ); + ask_questions( B, "B" ); + ask_questions( C, "C" ); + + ask_questions( At, "At" ); + ask_questions( Mt, "Mt" ); + ask_questions( Mref, "Mref" ); + + rc = grb::SUCCESS; +} + +int main( int argc, char ** argv ) { + // defaults + bool printUsage = false; + size_t in = 5; + + // error checking + if( argc > 2 ) { + printUsage = true; + } + if( argc == 2 ) { + size_t read; + std::istringstream ss( argv[ 1 ] ); + if( ! ( ss >> read ) ) { + std::cerr << "Error parsing first argument\n"; + printUsage = true; + } else if( ! ss.eof() ) { + std::cerr << "Error parsing first argument\n"; + printUsage = true; + } else if( read % 2 != 0 ) { + std::cerr << "Given value for n is odd\n"; + printUsage = true; + } else { + // all OK + in = read; + } + } + if( printUsage ) { + std::cerr << "Usage: " << argv[ 0 ] << " [n]\n"; + std::cerr << " -n (optional, default is 100): an even integer, the " + "test size.\n"; + return 1; + } + + std::cout << "This is functional test " << argv[ 0 ] << "\n"; + grb::Launcher< grb::AUTOMATIC > launcher; + grb::RC out; + if( launcher.exec( &grb_program, in, out, true ) != grb::SUCCESS ) { + std::cerr << "Launching test FAILED\n"; + return 255; + } + if( out != grb::SUCCESS ) { + std::cerr << "Test FAILED (" << grb::toString( out ) << ")" << std::endl; + } else { + std::cout << "Test OK" << std::endl; + } + return 0; +} From 72cf507ee5e57b0173faf1116c56629ad93f46aa Mon Sep 17 00:00:00 2001 From: Anonymous Date: Fri, 4 Feb 2022 10:55:53 +0100 Subject: [PATCH 030/282] Convert spaces to tabs --- include/graphblas/denseref/blas3.hpp | 30 ++++++++++++++-------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/include/graphblas/denseref/blas3.hpp b/include/graphblas/denseref/blas3.hpp index 6177498c7..190740f7a 100644 --- a/include/graphblas/denseref/blas3.hpp +++ b/include/graphblas/denseref/blas3.hpp @@ -31,7 +31,7 @@ #include "matrix.hpp" namespace grb { - namespace internal { + namespace internal { /** * \internal general mxm implementation that all mxm variants refer to @@ -55,9 +55,9 @@ namespace grb { grb::is_monoid< Monoid >::value, void >::type * const = NULL ) { - (void)oper; - (void)monoid; - (void)mulMonoid; + (void)oper; + (void)monoid; + (void)mulMonoid; static_assert( allow_void || ( !( std::is_same< InputType1, void >::value || std::is_same< InputType2, void >::value @@ -87,25 +87,25 @@ namespace grb { const auto B_raw = grb::getRaw( B ); auto C_raw = grb::getRaw( C ); - std::cout << "Multiplying dense matrices.\n"; + std::cout << "Multiplying dense matrices.\n"; - for( size_t row = 0; row < m; ++row ) { - for( size_t col = 0; col < n; ++col ) { - C_raw[ row * k + col] = 0; - for( size_t i = 0; i < k; ++ i ) { - C_raw[ row * k + col] += A_raw[ row * k + i ] * B_raw[ i * n_B + col ]; - } - } - } + for( size_t row = 0; row < m; ++row ) { + for( size_t col = 0; col < n; ++col ) { + C_raw[ row * k + col] = 0; + for( size_t i = 0; i < k; ++ i ) { + C_raw[ row * k + col] += A_raw[ row * k + i ] * B_raw[ i * n_B + col ]; + } + } + } - // internal::setInitialized( true ); + // internal::setInitialized( true ); // done return SUCCESS; } } // namespace internal - /** + /** * \internal grb::mxm, semiring version. * Dispatches to internal::mxm_generic */ From f67f6540d6b118320b0e55af594b057e3505fd74 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Fri, 4 Feb 2022 11:24:37 +0100 Subject: [PATCH 031/282] Make use of operators and monoid provided to mxm --- include/graphblas/denseref/blas3.hpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/include/graphblas/denseref/blas3.hpp b/include/graphblas/denseref/blas3.hpp index 190740f7a..c90bf1046 100644 --- a/include/graphblas/denseref/blas3.hpp +++ b/include/graphblas/denseref/blas3.hpp @@ -91,13 +91,14 @@ namespace grb { for( size_t row = 0; row < m; ++row ) { for( size_t col = 0; col < n; ++col ) { - C_raw[ row * k + col] = 0; + C_raw[ row * k + col] = monoid.template getIdentity< OutputType >(); for( size_t i = 0; i < k; ++ i ) { - C_raw[ row * k + col] += A_raw[ row * k + i ] * B_raw[ i * n_B + col ]; + OutputType temp = monoid.template getIdentity< OutputType >(); + (void)grb::apply( temp, A_raw[ row * k + i ], B_raw[ i * n_B + col ], oper ); + (void)grb::foldl( C_raw[ row * k + col], temp, monoid.getOperator() ); } } } - // internal::setInitialized( true ); // done return SUCCESS; From 2045a66f761e58a58fb777a37c3523afebfc7100 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Fri, 4 Feb 2022 11:43:25 +0100 Subject: [PATCH 032/282] Add friend getter/setter for field 'initialized' of denseref matrix --- include/graphblas/denseref/blas3.hpp | 2 +- include/graphblas/denseref/matrix.hpp | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/include/graphblas/denseref/blas3.hpp b/include/graphblas/denseref/blas3.hpp index c90bf1046..bc19d25f1 100644 --- a/include/graphblas/denseref/blas3.hpp +++ b/include/graphblas/denseref/blas3.hpp @@ -99,7 +99,7 @@ namespace grb { } } } - // internal::setInitialized( true ); + grb::internal::setInitialized( C, true ); // done return SUCCESS; } diff --git a/include/graphblas/denseref/matrix.hpp b/include/graphblas/denseref/matrix.hpp index dd1224794..32eeae72c 100644 --- a/include/graphblas/denseref/matrix.hpp +++ b/include/graphblas/denseref/matrix.hpp @@ -48,6 +48,19 @@ namespace grb { template< typename T > size_t ncols( const Matrix< T, reference_dense > & ) noexcept; + namespace internal { + + template< typename T > + bool & getInitialized( grb::Matrix< T, reference_dense > & A ) noexcept { + return A.initialized; + } + + template< typename T > + void setInitialized( grb::Matrix< T, reference_dense > & A, bool initialized ) noexcept { + A.initialized = initialized; + } + } // namespace internal + /** \internal TODO */ template< typename T > class Matrix< T, reference_dense > { @@ -70,6 +83,12 @@ namespace grb { friend const T * getRaw( const Matrix< T, reference_dense > & ) noexcept; + template< typename DataType > + friend bool & internal::getInitialized( grb::Matrix< DataType, reference_dense > & ) noexcept; + + template< typename DataType > + friend void internal::setInitialized( grb::Matrix< DataType, reference_dense > & , bool ) noexcept; + private: /** Our own type. */ typedef Matrix< T, reference_dense > self_type; From c311d40b5752b811bcdd50a4527c30b9d8d2657d Mon Sep 17 00:00:00 2001 From: Anonymous Date: Fri, 4 Feb 2022 12:17:50 +0100 Subject: [PATCH 033/282] Revert "Add temporary code for matrix data initialization" This reverts commit 676cb4db7fe0ff54029c4b3b0ea31af60f8bc334. --- include/graphblas/denseref/matrix.hpp | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/include/graphblas/denseref/matrix.hpp b/include/graphblas/denseref/matrix.hpp index 32eeae72c..75fca83ec 100644 --- a/include/graphblas/denseref/matrix.hpp +++ b/include/graphblas/denseref/matrix.hpp @@ -119,12 +119,7 @@ namespace grb { /** @see Matrix::Matrix() */ Matrix( const size_t rows, const size_t columns ): m( rows ), n( columns ), initialized( false ) { - // Temporary solution to initialize a matrix - // TODO: Use buildUnique - data = new T[ m * n ]; - for( size_t i = 0; i <= m * n; ++i ){ - data[i] = 1; - } + } /** @see Matrix::Matrix( const Matrix & ) */ From 87978f5f2e89559a408dc3c6a8cda30904348b7f Mon Sep 17 00:00:00 2001 From: Anonymous Date: Fri, 4 Feb 2022 12:34:20 +0100 Subject: [PATCH 034/282] Add temporary way for allocating data of a denseref matrix --- include/graphblas/denseref/matrix.hpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/graphblas/denseref/matrix.hpp b/include/graphblas/denseref/matrix.hpp index 75fca83ec..dc67f2baf 100644 --- a/include/graphblas/denseref/matrix.hpp +++ b/include/graphblas/denseref/matrix.hpp @@ -119,7 +119,8 @@ namespace grb { /** @see Matrix::Matrix() */ Matrix( const size_t rows, const size_t columns ): m( rows ), n( columns ), initialized( false ) { - + // TODO Implement allocation properly + data = new T[ m * n ]; } /** @see Matrix::Matrix( const Matrix & ) */ From 23d07ece5af921363f62793454ea74da59634091 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Fri, 4 Feb 2022 12:35:38 +0100 Subject: [PATCH 035/282] Add functions to initialize matrix data from provided forward iterator --- include/graphblas/denseref/io.hpp | 8 ++++++++ include/graphblas/denseref/matrix.hpp | 27 +++++++++++++++++++++++++++ include/graphblas/io.hpp | 2 +- 3 files changed, 36 insertions(+), 1 deletion(-) diff --git a/include/graphblas/denseref/io.hpp b/include/graphblas/denseref/io.hpp index 137a0b7a6..4507c410a 100644 --- a/include/graphblas/denseref/io.hpp +++ b/include/graphblas/denseref/io.hpp @@ -23,8 +23,16 @@ #ifndef _H_GRB_DENSEREF_IO #define _H_GRB_DENSEREF_IO +#include +#include "matrix.hpp" + namespace grb { + template< typename InputType, typename fwd_iterator > + RC buildMatrix( Matrix< InputType, reference_dense > & A, fwd_iterator start, const fwd_iterator end ) { + return A.template buildMatrixUnique( start, end ); + } + } // end namespace ``grb'' #endif // end ``_H_GRB_DENSEREF_IO'' diff --git a/include/graphblas/denseref/matrix.hpp b/include/graphblas/denseref/matrix.hpp index dc67f2baf..d3210f0ed 100644 --- a/include/graphblas/denseref/matrix.hpp +++ b/include/graphblas/denseref/matrix.hpp @@ -83,6 +83,13 @@ namespace grb { friend const T * getRaw( const Matrix< T, reference_dense > & ) noexcept; + /* ******************** + IO friends + ******************** */ + + template< typename InputType, typename fwd_iterator > + friend RC buildMatrix( Matrix< InputType, reference_dense > &, fwd_iterator, const fwd_iterator ); + template< typename DataType > friend bool & internal::getInitialized( grb::Matrix< DataType, reference_dense > & ) noexcept; @@ -113,6 +120,26 @@ namespace grb { /** Whether the container presently is uninitialized. */ bool initialized; + /** @see Matrix::buildMatrixUnique */ + template< typename fwd_iterator > + RC buildMatrixUnique( const fwd_iterator & _start, const fwd_iterator & _end ) { + // detect trivial case + if ( _start == _end || m == 0 || n == 0) { + return SUCCESS; + } + + // TODO: Add more sanity checks (e.g. overflow) + + for( auto it = _start; it != _end; ++it ) { + data[ it - _start ] = *it; + } + + initialized = true; + + // done + return RC::SUCCESS; + } + public: /** @see Matrix::value_type */ typedef T value_type; diff --git a/include/graphblas/io.hpp b/include/graphblas/io.hpp index 7b0f24d28..c0ee2f932 100644 --- a/include/graphblas/io.hpp +++ b/include/graphblas/io.hpp @@ -29,7 +29,7 @@ #ifdef _GRB_WITH_REFERENCE #include #endif -#ifdef _GRB_WITH_DENSE +#ifdef _GRB_WITH_DENSEREF #include #endif #ifdef _GRB_WITH_LPF From 9444dadd99b256b1d177d9a4e838d1a91bf2ff97 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Fri, 4 Feb 2022 13:01:07 +0100 Subject: [PATCH 036/282] Make getters const --- include/graphblas/denseref/matrix.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/graphblas/denseref/matrix.hpp b/include/graphblas/denseref/matrix.hpp index d3210f0ed..b5d1b59b9 100644 --- a/include/graphblas/denseref/matrix.hpp +++ b/include/graphblas/denseref/matrix.hpp @@ -51,7 +51,7 @@ namespace grb { namespace internal { template< typename T > - bool & getInitialized( grb::Matrix< T, reference_dense > & A ) noexcept { + const bool & getInitialized( const grb::Matrix< T, reference_dense > & A ) noexcept { return A.initialized; } @@ -91,7 +91,7 @@ namespace grb { friend RC buildMatrix( Matrix< InputType, reference_dense > &, fwd_iterator, const fwd_iterator ); template< typename DataType > - friend bool & internal::getInitialized( grb::Matrix< DataType, reference_dense > & ) noexcept; + friend const bool & internal::getInitialized( const grb::Matrix< DataType, reference_dense > & ) noexcept; template< typename DataType > friend void internal::setInitialized( grb::Matrix< DataType, reference_dense > & , bool ) noexcept; From 205e96ebd75e54124c98b3eb01a665da5e961a9c Mon Sep 17 00:00:00 2001 From: Anonymous Date: Fri, 4 Feb 2022 13:02:17 +0100 Subject: [PATCH 037/282] Exploit new features in mxm unit test New features are building a matrix from an iterator and handling of uninitialized matrices. --- tests/unit/dense_mxm.cpp | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/tests/unit/dense_mxm.cpp b/tests/unit/dense_mxm.cpp index b1063cc54..2c98e09c2 100644 --- a/tests/unit/dense_mxm.cpp +++ b/tests/unit/dense_mxm.cpp @@ -24,6 +24,10 @@ using namespace grb; void print_matrix( const grb::Matrix< double > & A) { + if( ! grb::internal::getInitialized< double >( A ) ) { + std::cout << "Matrix is uninitialized, nothing to print.\n"; + return; + } const double * Araw = grb::getRaw( A ); for( size_t row = 0; row < grb::nrows( A ); ++row ) { for( size_t col = 0; col < grb::ncols( A ); ++col ) { @@ -41,6 +45,8 @@ void grb_program( const size_t & n, grb::RC & rc ) { grb::Matrix< double > A( n, n ); grb::Matrix< double > B( n, n ); grb::Matrix< double > C( n, n ); + std::vector< double > A_data( n * n, 1 ); + std::vector< double > B_data( n * n, 1 ); std::cout << "_GRB_BACKEND = " << _GRB_BACKEND << "\n"; @@ -52,10 +58,23 @@ void grb_program( const size_t & n, grb::RC & rc ) { std::cout << "_GRB_WITH_DENSEREF defined\n"; #endif + // Initialize input matrices + rc = grb::buildMatrix< double, decltype( A_data )::const_iterator >( A, A_data.begin(), A_data.end() ); + if( rc == SUCCESS ) { + rc = grb::buildMatrix< double, decltype( B_data )::const_iterator >( B, B_data.begin(), B_data.end() ); + } + + std::cout << "Output matrix nrows = " << nrows( C ) << ", ncols = " << ncols( C ) << "\n"; - rc = grb::mxm( C, A, B, ring ); - print_matrix(C); + // Test printing of an uninitialized matrix + print_matrix( C ); + + if( rc == SUCCESS ) { + rc = grb::mxm( C, A, B, ring ); + } + + print_matrix( C ); } From c5f8ae06187ad3e3f95ee8740f3c88580bfb6f0b Mon Sep 17 00:00:00 2001 From: Anonymous Date: Fri, 4 Feb 2022 14:15:22 +0100 Subject: [PATCH 038/282] added get/remove_ref type traits for StructuredMatrix types --- include/graphblas/base/matrix.hpp | 4 ++ include/graphblas/denseref/matrix.hpp | 59 +++++++++++++++++++++----- tests/unit/dense_structured_matrix.cpp | 5 ++- 3 files changed, 56 insertions(+), 12 deletions(-) diff --git a/include/graphblas/base/matrix.hpp b/include/graphblas/base/matrix.hpp index 9cd449332..9d2127918 100644 --- a/include/graphblas/base/matrix.hpp +++ b/include/graphblas/base/matrix.hpp @@ -27,6 +27,7 @@ #include +#include #include #include @@ -496,6 +497,9 @@ class StructuredMatrix { ~StructuredMatrix(); }; // class StructuredMatrix +/** + * Check if a type is a StructuredMatrix. + */ template< typename T > struct is_structured_matrix : std::false_type {}; template< typename T, typename Structure, typename StorageSchemeType, typename View, enum Backend backend > diff --git a/include/graphblas/denseref/matrix.hpp b/include/graphblas/denseref/matrix.hpp index b5d1b59b9..5ad566289 100644 --- a/include/graphblas/denseref/matrix.hpp +++ b/include/graphblas/denseref/matrix.hpp @@ -35,7 +35,6 @@ namespace grb { - template< typename T > T * getRaw( Matrix< T, reference_dense > & ) noexcept; @@ -79,9 +78,9 @@ namespace grb { `Getter' friends ********************* */ - friend T * getRaw( Matrix< T, reference_dense > &) noexcept; + friend T * getRaw< T >( Matrix< T, reference_dense > & ) noexcept; - friend const T * getRaw( const Matrix< T, reference_dense > & ) noexcept; + friend const T * getRaw< T >( const Matrix< T, reference_dense > & ) noexcept; /* ******************** IO friends @@ -178,22 +177,22 @@ namespace grb { }; template< typename T > - T * getRaw( Matrix< T, reference_dense > &m ) noexcept { + T * getRaw( Matrix< T, reference_dense > & m ) noexcept { return m.data; } template< typename T > - const T * getRaw( const Matrix< T, reference_dense > &m ) noexcept { + const T * getRaw( const Matrix< T, reference_dense > & m ) noexcept { return m.data; } template< typename T > - size_t nrows( const Matrix< T, reference_dense > &m ) noexcept { + size_t nrows( const Matrix< T, reference_dense > & m ) noexcept { return m.m; } template< typename T > - size_t ncols( const Matrix< T, reference_dense > &m ) noexcept { + size_t ncols( const Matrix< T, reference_dense > & m ) noexcept { return m.n; } @@ -367,12 +366,16 @@ namespace grb { }; // StructuredMatrix Square, container + /** + * Reference to a Square Matrix generalized over views. + */ template< typename T, typename View > class StructuredMatrix< T, structures::General, storage::Dense, View, reference_dense > { private: using self_type = StructuredMatrix< T, structures::General, storage::Dense, View, reference_dense >; using original_type = typename View::applied_to; + /********************* Storage info friends ******************** */ @@ -397,8 +400,6 @@ namespace grb { using identity_t = StructuredMatrix< T, structures::General, storage::Dense, view::Identity< self_type >, reference_dense >; using transpose_t = StructuredMatrix< T, structures::General, storage::Dense, view::Transpose< self_type >, reference_dense >; - using reference_t = identity_t; - StructuredMatrix( original_type & struct_mat ) : ref( struct_mat ) {} }; // StructuredMatrix General reference @@ -433,8 +434,6 @@ namespace grb { using identity_t = StructuredMatrix< T, structures::Square, storage::Dense, view::Identity< self_type >, reference_dense >; using transpose_t = StructuredMatrix< T, structures::Square, storage::Dense, view::Transpose< self_type >, reference_dense >; - using reference_t = identity_t; - StructuredMatrix( original_type & struct_mat ) : ref( struct_mat ) {} }; // StructuredMatrix Square reference @@ -449,6 +448,44 @@ namespace grb { } // namespace structures + /** + * Peel off any possible view from an input StructuredMatrix type. + * Returns a compatible container-type StructuredMatrix. + */ + template< typename StructuredMatrixT > + struct remove_ref; + + template< typename T, typename Structure, typename StorageSchemeType, typename View, enum Backend backend > + struct remove_ref< StructuredMatrix< T, Structure, StorageSchemeType, View, backend > > { + using type = StructuredMatrix< T, Structure, StorageSchemeType, view::Identity< void >, backend >; + }; + + /** + * Generate a ref StructuredMatrix type. + * If no target structure is specified the one of the source type is assumed. + * Otherwise it can only generate a type if the target structure is the same as the source type + * or a more specialized version that would preserve its static properties (e.g., symmetric reference + * to a square matrix -- any assumption based on symmetry would not break those based on square). + */ + template< typename StructuredMatrixT, typename TargetStructure = void > + struct get_ref; + + template< typename T, typename Structure, typename StorageSchemeType, typename View, enum Backend backend > + struct get_ref< StructuredMatrix< T, Structure, StorageSchemeType, View, backend >, void > { + using source_strmat_t = StructuredMatrix< T, Structure, StorageSchemeType, View, backend >; + using type = StructuredMatrix< T, Structure, StorageSchemeType, view::Identity< source_strmat_t >, backend >; + }; + + template< typename T, typename Structure, typename StorageSchemeType, typename View, enum Backend backend, typename TargetStructure > + struct get_ref< StructuredMatrix< T, Structure, StorageSchemeType, View, backend >, TargetStructure > { + + static_assert( structures::is_in< Structure, typename TargetStructure::inferred_structures >::value, + "Can only create a ref StructuredMatrix with a target structure that implies the source." ); + + using source_strmat_t = StructuredMatrix< T, Structure, StorageSchemeType, View, backend >; + using type = StructuredMatrix< T, TargetStructure, StorageSchemeType, view::Identity< source_strmat_t >, backend >; + }; + } // namespace grb #endif // end ``_H_GRB_DENSEREF_MATRIX'' diff --git a/tests/unit/dense_structured_matrix.cpp b/tests/unit/dense_structured_matrix.cpp index 8b9c4c824..50aa19b2e 100644 --- a/tests/unit/dense_structured_matrix.cpp +++ b/tests/unit/dense_structured_matrix.cpp @@ -49,7 +49,10 @@ void grb_program( const size_t & n, grb::RC & rc ) { decltype( A )::transpose_t At( A ); decltype( M )::transpose_t Mt( M ); - decltype( M )::reference_t Mref( M ); + grb::get_ref< decltype( M ) >::type Mref( M ); + grb::get_ref< decltype( M ), grb::structures::Square >::type Sq_Mref( M ); + + grb::remove_ref< decltype( Mt ) >::type M1( n, n ); ask_questions( M, "M" ); ask_questions( A, "A" ); From 281134b9b41c10aed8e9a5b5751aac89f2f01e78 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Fri, 4 Feb 2022 19:52:44 +0100 Subject: [PATCH 039/282] Temporary switch to pointers to target matrices to enable empty init. --- include/graphblas/denseref/matrix.hpp | 26 ++++++++++++++++++-------- tests/unit/dense_structured_matrix.cpp | 2 +- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/include/graphblas/denseref/matrix.hpp b/include/graphblas/denseref/matrix.hpp index 5ad566289..e43340de6 100644 --- a/include/graphblas/denseref/matrix.hpp +++ b/include/graphblas/denseref/matrix.hpp @@ -23,6 +23,8 @@ #ifndef _H_GRB_DENSEREF_MATRIX #define _H_GRB_DENSEREF_MATRIX +#include + #include #include #include @@ -374,7 +376,7 @@ namespace grb { private: using self_type = StructuredMatrix< T, structures::General, storage::Dense, View, reference_dense >; - using original_type = typename View::applied_to; + using target_type = typename View::applied_to; /********************* Storage info friends @@ -386,10 +388,10 @@ namespace grb { friend std::pair< size_t, size_t > dims<>( const self_type & ) noexcept; - original_type & ref; + target_type * ref; std::pair< size_t, size_t > _dims() const { - return View::dims( dims( ref ) ); + return View::dims( dims( *ref ) ); } public: @@ -400,7 +402,9 @@ namespace grb { using identity_t = StructuredMatrix< T, structures::General, storage::Dense, view::Identity< self_type >, reference_dense >; using transpose_t = StructuredMatrix< T, structures::General, storage::Dense, view::Transpose< self_type >, reference_dense >; - StructuredMatrix( original_type & struct_mat ) : ref( struct_mat ) {} + StructuredMatrix( ) : ref( nullptr ) {} + + StructuredMatrix( target_type & struct_mat ) : ref( &struct_mat ) {} }; // StructuredMatrix General reference @@ -409,7 +413,7 @@ namespace grb { private: using self_type = StructuredMatrix< T, structures::Square, storage::Dense, View, reference_dense >; - using original_type = typename View::applied_to; + using target_type = typename View::applied_to; /********************* Storage info friends ******************** */ @@ -420,10 +424,10 @@ namespace grb { friend std::pair< size_t, size_t > dims<>( const self_type & ) noexcept; - original_type & ref; + target_type * ref; std::pair< size_t, size_t > _dims() const { - return View::dims( dims( ref ) ); + return View::dims( dims( *ref ) ); } public: @@ -434,7 +438,13 @@ namespace grb { using identity_t = StructuredMatrix< T, structures::Square, storage::Dense, view::Identity< self_type >, reference_dense >; using transpose_t = StructuredMatrix< T, structures::Square, storage::Dense, view::Transpose< self_type >, reference_dense >; - StructuredMatrix( original_type & struct_mat ) : ref( struct_mat ) {} + StructuredMatrix( ) : ref( nullptr ) {} + + StructuredMatrix( target_type & struct_mat ) : ref( & struct_mat ) { + if( nrows( struct_mat ) == ncols( struct_mat ) ) { + throw std::length_error( "Square StructuredMatrix reference to non-square target." ); + } + } }; // StructuredMatrix Square reference diff --git a/tests/unit/dense_structured_matrix.cpp b/tests/unit/dense_structured_matrix.cpp index 50aa19b2e..f6e5a798a 100644 --- a/tests/unit/dense_structured_matrix.cpp +++ b/tests/unit/dense_structured_matrix.cpp @@ -50,7 +50,7 @@ void grb_program( const size_t & n, grb::RC & rc ) { decltype( M )::transpose_t Mt( M ); grb::get_ref< decltype( M ) >::type Mref( M ); - grb::get_ref< decltype( M ), grb::structures::Square >::type Sq_Mref( M ); + grb::get_ref< decltype( M ), grb::structures::Square >::type Sq_Mref; grb::remove_ref< decltype( Mt ) >::type M1( n, n ); From 397403cb106f90ce0be2c96c66d7c26ea3868506 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Fri, 4 Feb 2022 20:35:00 +0100 Subject: [PATCH 040/282] First draft of index mapping functions --- include/graphblas/denseref/matrix.hpp | 60 ++++++++++------ include/graphblas/imf.hpp | 98 +++++++++++++++++++++++++++ 2 files changed, 136 insertions(+), 22 deletions(-) create mode 100644 include/graphblas/imf.hpp diff --git a/include/graphblas/denseref/matrix.hpp b/include/graphblas/denseref/matrix.hpp index e43340de6..ac98a5e20 100644 --- a/include/graphblas/denseref/matrix.hpp +++ b/include/graphblas/denseref/matrix.hpp @@ -24,6 +24,7 @@ #define _H_GRB_DENSEREF_MATRIX #include +#include #include #include @@ -34,6 +35,10 @@ #include #include //#include //for help with dealing with pattern matrix input +#include +#include +#include +#include namespace grb { @@ -233,11 +238,10 @@ namespace grb { using self_type = StructuredMatrix< T, Structure, storage::Dense, view::Identity< void >, reference_dense >; - // Using a matrix for now just to get some test going. Need to implement alloc - // logic for this backend. + // Physical layout - TBD // Matrix< T, reference_dense > A; - size_t m, n; + std::shared_ptr imf_l, imf_r; /** * A container's storage scheme. \a storage_scheme is not exposed to the user as an option @@ -256,7 +260,7 @@ namespace grb { bool initialized; std::pair< size_t, size_t > _dims() const { - return std::make_pair( m, n ); + return std::make_pair( imf_l->n, imf_r->n ); } public: @@ -267,7 +271,7 @@ namespace grb { using identity_t = StructuredMatrix< T, Structure, storage::Dense, view::Identity< self_type >, reference_dense >; using reference_t = identity_t; - StructuredMatrix( const size_t rows, const size_t cols ) : m( rows ), n( cols ), storage_scheme( storage::full ), initialized( false ) {} + StructuredMatrix( const size_t rows, const size_t cols ) : imf_l( std::make_shared< imf::Id >( rows ) ), imf_r( std::make_shared< imf::Id >( cols ) ), storage_scheme( storage::full ), initialized( false ) {} }; // class StructuredMatrix template< typename T > @@ -286,11 +290,10 @@ namespace grb { using self_type = StructuredMatrix< T, structures::General, storage::Dense, view::Identity< void >, reference_dense >; - // Using a matrix for now just to get some test going. Need to implement alloc - // logic for this backend. + // Physical layout - TBD // Matrix< T, reference_dense > A; - size_t m, n; + std::shared_ptr imf_l, imf_r; /** * The container's storage scheme. @@ -301,7 +304,7 @@ namespace grb { bool initialized; std::pair< size_t, size_t > _dims() const { - return std::make_pair( m, n ); + return std::make_pair( imf_l->n, imf_r->n ); } public: @@ -316,7 +319,7 @@ namespace grb { using reference_t = identity_t; - StructuredMatrix( const size_t rows, const size_t cols ) : m( rows ), n( cols ), storage_scheme( storage::full ), initialized( false ) {} + StructuredMatrix( const size_t rows, const size_t cols ) : imf_l( std::make_shared< imf::Id >( rows ) ), imf_r( std::make_shared< imf::Id >( cols ) ), storage_scheme( storage::full ), initialized( false ) {} }; // StructuredMatrix General, container @@ -336,11 +339,10 @@ namespace grb { using self_type = StructuredMatrix< T, structures::Square, storage::Dense, view::Identity< void >, reference_dense >; - // Using a matrix for now just to get some test going. Need to implement alloc - // logic for this backend. + // Physical layout - TBD // Matrix< T, reference_dense > A; - size_t m, n; + std::shared_ptr imf_l, imf_r; /** * The container's storage scheme. @@ -351,7 +353,7 @@ namespace grb { bool initialized; std::pair< size_t, size_t > _dims() const { - return std::make_pair( m, n ); + return std::make_pair( imf_l->n, imf_r->n ); } public: @@ -364,7 +366,7 @@ namespace grb { using reference_t = identity_t; - StructuredMatrix( const size_t rows ) : m( rows ), n( rows ), storage_scheme( storage::full ), initialized( false ) {} + StructuredMatrix( const size_t rows ) : imf_l( std::make_shared< imf::Id >( rows ) ), imf_r( std::make_shared< imf::Id >( rows ) ), storage_scheme( storage::full ), initialized( false ) {} }; // StructuredMatrix Square, container @@ -390,8 +392,10 @@ namespace grb { target_type * ref; + std::shared_ptr imf_l, imf_r; + std::pair< size_t, size_t > _dims() const { - return View::dims( dims( *ref ) ); + return std::make_pair( imf_l->n, imf_r->n ); } public: @@ -402,9 +406,15 @@ namespace grb { using identity_t = StructuredMatrix< T, structures::General, storage::Dense, view::Identity< self_type >, reference_dense >; using transpose_t = StructuredMatrix< T, structures::General, storage::Dense, view::Transpose< self_type >, reference_dense >; - StructuredMatrix( ) : ref( nullptr ) {} + StructuredMatrix( ) : ref( nullptr ), imf_l( std::make_shared< imf::Id >( 0 ) ), imf_r( std::make_shared< imf::Id >( 0 ) ) {} + + StructuredMatrix( target_type & struct_mat ) : ref( &struct_mat ), imf_l( nullptr ), imf_r( nullptr ) { + + std::pair< size_t, size_t > _dims = View::dims( dims( *ref ) ); + imf_l = std::make_shared< imf::Id >( _dims.first ); + imf_r = std::make_shared< imf::Id >( _dims.second ); - StructuredMatrix( target_type & struct_mat ) : ref( &struct_mat ) {} + } }; // StructuredMatrix General reference @@ -426,8 +436,10 @@ namespace grb { target_type * ref; + std::shared_ptr imf_l, imf_r; + std::pair< size_t, size_t > _dims() const { - return View::dims( dims( *ref ) ); + return std::make_pair( imf_l->n, imf_r->n ); } public: @@ -438,12 +450,16 @@ namespace grb { using identity_t = StructuredMatrix< T, structures::Square, storage::Dense, view::Identity< self_type >, reference_dense >; using transpose_t = StructuredMatrix< T, structures::Square, storage::Dense, view::Transpose< self_type >, reference_dense >; - StructuredMatrix( ) : ref( nullptr ) {} + // ref to empty matrix + StructuredMatrix( ) : ref( nullptr ), imf_l( std::make_shared< imf::Id >( 0 ) ), imf_r( std::make_shared< imf::Id >( 0 ) ) {} - StructuredMatrix( target_type & struct_mat ) : ref( & struct_mat ) { - if( nrows( struct_mat ) == ncols( struct_mat ) ) { + StructuredMatrix( target_type & struct_mat ) : ref( & struct_mat ), imf_l( nullptr ), imf_r( nullptr ) { + if( nrows( struct_mat ) != ncols( struct_mat ) ) { throw std::length_error( "Square StructuredMatrix reference to non-square target." ); } + // No matter the view it has to be a square matrix + imf_l = std::make_shared< imf::Id >( nrows( struct_mat ) ); + imf_r = std::make_shared< imf::Id >( nrows( struct_mat ) ); } }; // StructuredMatrix Square reference diff --git a/include/graphblas/imf.hpp b/include/graphblas/imf.hpp new file mode 100644 index 000000000..d2c03cb3d --- /dev/null +++ b/include/graphblas/imf.hpp @@ -0,0 +1,98 @@ +/* + * Copyright 2021 Huawei Technologies Co., Ltd. + * + * 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. + */ + +/** + * + * @file This file registers available index mapping functions (IMFs). + * IMFs are maps between integer intervals. + */ + +#ifndef _H_GRB_IMF +#define _H_GRB_IMF + +#include + +namespace grb { + + namespace imf { + + class IMF { + public: + size_t n, N; + + IMF(size_t n, size_t N): n(n), N(N) {} + + virtual size_t map(size_t i) = 0; + + }; + + /** + * The identity IMF. + * I =[0, n) + * Id = I -> I; i \mapsto i + */ + class Id: public IMF { + + public: + size_t map(size_t i) { + return i; + } + + Id(size_t n): IMF(n, n) { } + }; + + /** + * The strided IMF. + * I_n =[0, n), I_N =[0, N) + * Strided_{b, s} = I_n -> I_N; i \mapsto b + s * i + */ + class Strided: public IMF { + + public: + size_t b, s; + + size_t map(size_t i) { + + return b + s * i; + } + + Strided(size_t n, size_t N, size_t b, size_t s): IMF(n, N), b(b), s(s) { } + }; + + /** + * A composition of two IMFs f\circ g = f(g(\cdot)) + * I_gn =[0, n), I_fN =[0, m) + * I_fn =[0, m), I_fN =[0, N) + * Composed_{f, g} = I_gn -> I_fN; i \mapsto f( g( i ) ) + */ + class Composed: public IMF { + + public: + std::shared_ptr f, g; + + size_t map(size_t i) { + return f->map( g->map( i ) ); + } + + Composed(std::shared_ptr f, std::shared_ptr g): IMF( g->n, f->N ), f(f), g(g) { } + + }; + + }; // namespace imf + +} // namespace grb + +#endif // _H_GRB_IMF From eabddfd6c997f282ee3652759d5a34cbb4c16d03 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Mon, 7 Feb 2022 14:06:17 +0100 Subject: [PATCH 041/282] Cleaned up StructuredMatrix-related doxygen drafts --- include/graphblas/base/matrix.hpp | 135 +++++++++++++++++++++--------- include/graphblas/imf.hpp | 41 +++++++-- include/graphblas/structures.hpp | 16 +++- include/graphblas/views.hpp | 2 + 4 files changed, 143 insertions(+), 51 deletions(-) diff --git a/include/graphblas/base/matrix.hpp b/include/graphblas/base/matrix.hpp index 9d2127918..6c604ef4f 100644 --- a/include/graphblas/base/matrix.hpp +++ b/include/graphblas/base/matrix.hpp @@ -24,11 +24,10 @@ #define _H_GRB_MATRIX_BASE #include - #include - #include #include +#include #include #include @@ -38,6 +37,7 @@ #include #include #include +#include namespace grb { @@ -438,67 +438,126 @@ RC clear( Matrix< InputType, backend > & A ) noexcept { } /** - * An ALP structured matrix. + * \brief An ALP structured matrix. * - * This is an opaque data type for that implements the below functions. In essence it can be - * used to instantiate containers or references of containers. References may be matrices with - * their specific structure but do access data from a referenced StructuredMatrix, the latter being - * either a container or a reference itself. + * This is an opaque data type for structured matrices. A structured matrix is + * generalized over five parameters further described below: its data type, + * its structure, whether it is stored using a dense or sparse storage scheme, + * a static view and the backend for which it is implemented. + * At a high level of abstraction a structured matrix exposes a mathematical + * \em logical layout which allows to express implementation-oblivious concepts + * (e.g., the transpose of a symmetric matrix). + * At the lowest level, the logical layout maps to its physical counterpart via + * a particular choice of a storage scheme within those exposed by the chosen + * backend. + * + * Views can be used to create logical \em perspectives on top of a container. + * For example, I could decide to refer to the transpose of a matrix or to see + * a for limited part of my program a square matrix as symmetric. + * If a view can be expressed as concept invariant of specific runtime features, + * such views can be defined statically (for example I can always refer to the + * transpose or the diagonal of a matrix irrespective of features such as its + * size). Other may depend on features such as the size of a matrix + * and can be expressed as linear transformations via operations such as \a mxm + * (e.g., gathering/scattering the rows/columns of a matrix or permuting them). + * Structured matrices defined as views on other matrices do not instantiate a + * new container but refer to the one used by their targets. (See the + * documentation of StructuredMatrix for both scenarios within the \em denseref + * backend folder). * * @tparam T The type of the matrix elements. \a T shall not be a GraphBLAS * type. - * @tparam Structure One of the matrix structures in grb::structures. - * @tparam StorageSchemeType Either \a enum \a storage::Dense or \a enum \a storage::Sparse. - * A StructuredMatrix will be allowed to pick among the storage schemes within their specified - * \a StorageSchemeType. - * @tparam view One of the matrix views in \a grb::view. - * All static views except for \a view::Identity cannot instantiate a new container and only - * allow the creation of a reference to an existing \a StructuredMatrix. - * \a view::identity triggers the instatiation of an actual container for the StructuredMatrix. - * A reference view could be instanciated into a separate container than its original source by explicit - * copy into a container (e.g., via \a grb::set). - * The \a View parameter should not be used directly by the user but can be set using - * specific member types appropriately defined by each StructuredMatrix. - * (See examples of StructuredMatrix definitions in denseref backend folder or the - * \a dense_structured_matrix.cpp unit test). - * @tparam backend Allows multiple backends to implement different versions of this data type. + * @tparam Structure One of the matrix structures in \a grb::structures. + * @tparam StorageSchemeType Either \em enum \a storage::Dense or \em enum + * \a storage::Sparse. + * A StructuredMatrix will be allowed to pick among the storage schemes + * within their specified \a StorageSchemeType. + * @tparam View One of the matrix views in \a grb::view. + * All static views except for \a view::Identity (via + * \a view::identity cannot instantiate a new container and only + * allow to refer to an existing \a StructuredMatrix. + * The \a View parameter should not be used directly by the user but + * can be set using specific member types appropriately + * defined by each StructuredMatrix. (See examples of StructuredMatrix + * definitions within \a include/graphblas/denseref/matrix.hpp and the + * \a dense_structured_matrix.cpp unit test). + * @tparam backend Allows multiple backends to implement different versions + * of this data type. * - * \note The presence of different combination of structures and views could produce many specialization - * with lots of logic replication. + * \note The presence of different combination of structures and views could + * produce many specialization with lots of logic replication. We might + * could use some degree of inheritence to limit this. */ template< typename T, typename Structure, typename StorageSchemeType, typename View, enum Backend backend > class StructuredMatrix { - size_t m, n; - /** Whether the container presently is initialized or not. */ + /** + * Whether the container presently is initialized or not. + * We differentiate the concept of empty matrix (matrix of size \f$0\times 0\f$) + * from the one of uninitialized (matrix of size \f$m\times n\f$ which was never set) + * and that of zero matrix (matrix with all zero elements). + * \note in sparse format a zero matrix result in an ampty data structure. Is this + * used to refer to uninitialized matrix in ALP/GraphBLAS? + **/ bool initialized; - public : - - /** - * Usable only in case of an \a original view. Otherwise the view should only reference another view. - */ - StructuredMatrix( const size_t m, const size_t n ); + /** + * The two following members define the \em logical layout of a structured matrix: + * Its structure and access relations. This is enabled only if the structured matrix + * does not define a View on another matrix. + */ + using structure = Structure; + /** + * A pair of pointers to index mapping functions (see imf.hpp) that express the + * logical access to the structured matrix. + */ + std::shared_ptr imf_l, imf_r; /** - * In case of non-original views should set up the container so to share the data of other. + * When a structured matrix instanciate a \em container it defines a new \em physical + * (concrete?) layout. This is characterized by an ALP container (aka a \a Matrix) and a + * storage scheme that defines a unique interpretation of its content. + * The combination of the logical and physical layout of a structured matrix enables to + * identify a precise mapping between an element in the structured matrix and a position + * wihtin one or more 1/2D-arrays that store it. */ - StructuredMatrix( const StructuredMatrix< T, Structure, StorageSchemeType, View, backend > & other ); + Matrix< T, reference_dense > * _container; /** - * Usable only in case of an \a original view. Otherwise the view should only reference another view. + * A container's storage scheme. \a storage_scheme is not exposed to the user as an option + * but can defined by ALP at different points in the execution depending on the \a backend choice. + * For example, if the container is associated to an I/O matrix, with a reference backend + * it might be set to reflect the storage scheme of the user data as specified at buildMatrix. + * If \a backend is set to \a mlir then the scheme could be fixed by the JIT compiler to effectively + * support its optimization strategy. + * At construction time and until the moment the scheme decision is made it may be set to + * an appropriate default choice, e.g. if \a StorageSchemeType is \a storage::Dense then + * \a storage::Dense::full could be used. */ - StructuredMatrix( StructuredMatrix< T, Structure, StorageSchemeType, View, backend > && other ); + StorageSchemeType storage_scheme; /** - * When view is \a original data should be properly deallocated. + * When a structured matrix defines a View over another matrix, it contains a pointer + * to the latter. Its type can be identified via the View parameter. */ + using target_type = typename std::enable_if >::value, typename View::applied_to>::type; + target_type * ref; + + public : + + StructuredMatrix( const size_t m, const size_t n ); + + StructuredMatrix( const StructuredMatrix< T, Structure, StorageSchemeType, View, backend > & other ); + + StructuredMatrix( StructuredMatrix< T, Structure, StorageSchemeType, View, backend > && other ); + ~StructuredMatrix(); + }; // class StructuredMatrix /** - * Check if a type is a StructuredMatrix. + * Check if type \a T is a StructuredMatrix. */ template< typename T > struct is_structured_matrix : std::false_type {}; diff --git a/include/graphblas/imf.hpp b/include/graphblas/imf.hpp index d2c03cb3d..2189c5117 100644 --- a/include/graphblas/imf.hpp +++ b/include/graphblas/imf.hpp @@ -17,7 +17,26 @@ /** * * @file This file registers available index mapping functions (IMFs). - * IMFs are maps between integer intervals. + * IMFs are maps between integer intervals and can be used to define + * affine \em access transformations in the form of access matrices. + * For example, an access matrix \f$G_f\in R^{N\times N}\f$ + * parametrized by the IMF \f$f\f$ such that + * \f[G_f = \sum_{i=0}^{n-1} e_i^n\left(e_{f(i)}^N\right)^T\f] + * could be used to access a group of $n\eN$ rows of matrix + * \f$A\in R^{N\times N}\f$ + * according to \f$f\f$ by multiplying \f$A\f$ by \f$G_f\f$ from the left: + * \f[\tilde{A} = G_f\cdot A,\quad \tilde{A}\in R^{n\times N}\f] + * + * \note In this draft we use integer maps. A symbolic version of them could be + * defined using external libraries such as the Integer Set Library (isl + * \link https://libisl.sourceforge.io/). + * + * \note The idea of parametrized matrices to express matrix accesses at + * a higher level of mathematical abstractions is inspired by the + * SPIRAL literature (cite?). Similar although more general concepts + * also exist in the polyhedral compilation literature (e.g., access + * relations, cite). + * */ #ifndef _H_GRB_IMF @@ -41,9 +60,11 @@ namespace grb { /** * The identity IMF. - * I =[0, n) - * Id = I -> I; i \mapsto i + * \f$I_n = [0, n)\f$ + * \f$Id = I_n \rightarrow I_n; i \mapsto i\f$ */ + + class Id: public IMF { public: @@ -56,9 +77,10 @@ namespace grb { /** * The strided IMF. - * I_n =[0, n), I_N =[0, N) - * Strided_{b, s} = I_n -> I_N; i \mapsto b + s * i + * \f$I_n =[0, n), I_N =[0, N)\f$ + * \f$Strided_{b, s} = I_n \rightarrow I_N; i \mapsto b + si\f$ */ + class Strided: public IMF { public: @@ -73,11 +95,12 @@ namespace grb { }; /** - * A composition of two IMFs f\circ g = f(g(\cdot)) - * I_gn =[0, n), I_fN =[0, m) - * I_fn =[0, m), I_fN =[0, N) - * Composed_{f, g} = I_gn -> I_fN; i \mapsto f( g( i ) ) + * A composition of two IMFs. + * \f$I_{g,n} =[0, n), I_{g,N} =[0, N)\f$ + * \f$I_{f,n} =[0, n), I_{f,N} =[0, N)\f$ + * \f$Composed_{f, g} = I_{g,n} \rightarrow I_{f,N}; i \mapsto f( g( i ) )\f$ */ + class Composed: public IMF { public: diff --git a/include/graphblas/structures.hpp b/include/graphblas/structures.hpp index 34bec606d..c927e4645 100644 --- a/include/graphblas/structures.hpp +++ b/include/graphblas/structures.hpp @@ -30,6 +30,17 @@ namespace grb { + /** + * Collects all ALP matrix structures. + * + * A matrix structure is characterized by having a member type \a inferred_structures. + * \a inferred_structures is a tuple used to define a partial order over the + * structures based on their logical implication. So if having structure \f$B\f$ implies + * also having structure \f$A\f$ than + * \code + * is_same< B::inferred_structures, std::tuple >::value == true + * \endcode + */ namespace structures { template< typename... Tuples > @@ -38,7 +49,7 @@ namespace grb { }; /** - * Check if a structure is part of a given tuple. + * Check if a structure \a Structure is part of a given \a std::tuple \a Tuple. */ template< typename Structure, typename Tuple > struct is_in; @@ -85,9 +96,6 @@ namespace grb { south_west }; - /** - * List of ALP matrix structures. - */ struct General { using inferred_structures = std::tuple< General >; }; diff --git a/include/graphblas/views.hpp b/include/graphblas/views.hpp index b4f3280bf..37f00c312 100644 --- a/include/graphblas/views.hpp +++ b/include/graphblas/views.hpp @@ -22,6 +22,8 @@ * A static view represents a particular \em perspective on a container that * can be defined at compile-time and that can always be applied to a container * irrespective of dynamic features such as its dimensions. + * A View provides information about the structured matrix it is applied to, + * including its type (member type \a applied_to), or how read its dimensions. */ #ifndef _H_GRB_VIEWS From b53077a9b2f20c3fba15a1ff1097826c6ef2e7c6 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Tue, 8 Feb 2022 11:25:50 +0100 Subject: [PATCH 042/282] Added to the spec draft --- include/graphblas/base/matrix.hpp | 17 ++++++++++++++--- include/graphblas/imf.hpp | 25 +++++++++++++------------ include/graphblas/storage.hpp | 13 ++++++++----- 3 files changed, 35 insertions(+), 20 deletions(-) diff --git a/include/graphblas/base/matrix.hpp b/include/graphblas/base/matrix.hpp index 6c604ef4f..360e56d3c 100644 --- a/include/graphblas/base/matrix.hpp +++ b/include/graphblas/base/matrix.hpp @@ -440,8 +440,12 @@ RC clear( Matrix< InputType, backend > & A ) noexcept { /** * \brief An ALP structured matrix. * - * This is an opaque data type for structured matrices. A structured matrix is - * generalized over five parameters further described below: its data type, + * This is an opaque data type for structured matrices. + * This container allows to maintain the interface of grb::Matrix and grb::Vector + * unaltered enabling back-compatibility while building on them to create + * semantically reacher algebraic objects. + * A structured matrix is generalized over five parameters further described + * below: its data type, * its structure, whether it is stored using a dense or sparse storage scheme, * a static view and the backend for which it is implemented. * At a high level of abstraction a structured matrix exposes a mathematical @@ -449,7 +453,14 @@ RC clear( Matrix< InputType, backend > & A ) noexcept { * (e.g., the transpose of a symmetric matrix). * At the lowest level, the logical layout maps to its physical counterpart via * a particular choice of a storage scheme within those exposed by the chosen - * backend. + * backend. grb::Matrix and grb::Vector are used as interfaces to the physical + * layout. + * To visualize this, you could think of a band matrix. Using either the + * \a storage::Dense:full or \a storage::Dense:band storage schemes would require + * the use of a \a grb::Matrix container (see include/graphblas/storage.hpp for + * more details about the two storage schemes). However, the interpration of its + * content would differ in the two cases being a function of both the Structure + * information and the storage scheme combined. * * Views can be used to create logical \em perspectives on top of a container. * For example, I could decide to refer to the transpose of a matrix or to see diff --git a/include/graphblas/imf.hpp b/include/graphblas/imf.hpp index 2189c5117..dceeca8f0 100644 --- a/include/graphblas/imf.hpp +++ b/include/graphblas/imf.hpp @@ -16,22 +16,23 @@ /** * - * @file This file registers available index mapping functions (IMFs). - * IMFs are maps between integer intervals and can be used to define - * affine \em access transformations in the form of access matrices. - * For example, an access matrix \f$G_f\in R^{N\times N}\f$ - * parametrized by the IMF \f$f\f$ such that - * \f[G_f = \sum_{i=0}^{n-1} e_i^n\left(e_{f(i)}^N\right)^T\f] - * could be used to access a group of $n\eN$ rows of matrix - * \f$A\in R^{N\times N}\f$ - * according to \f$f\f$ by multiplying \f$A\f$ by \f$G_f\f$ from the left: - * \f[\tilde{A} = G_f\cdot A,\quad \tilde{A}\in R^{n\times N}\f] + * @file + * + * This file registers available index mapping functions (IMFs). + * IMFs are maps between integer intervals and can be used to define + * affine \em access transformations in the form of access matrices. + * For example, an access matrix \f$G_f\in R^{N\times N}\f$ + * parametrized by the IMF \f$f\f$ such that + * \f[G_f = \sum_{i=0}^{n-1} e_i^n\left(e_{f(i)}^N\right)^T\f] + * could be used to access a group of $n\eN$ rows of matrix + * \f$A\in R^{N\times N}\f$ + * according to \f$f\f$ by multiplying \f$A\f$ by \f$G_f\f$ from the left: + * \f[\tilde{A} = G_f\cdot A,\quad \tilde{A}\in R^{n\times N}\f] * * \note In this draft we use integer maps. A symbolic version of them could be * defined using external libraries such as the Integer Set Library (isl * \link https://libisl.sourceforge.io/). - * - * \note The idea of parametrized matrices to express matrix accesses at + * The idea of parametrized matrices to express matrix accesses at * a higher level of mathematical abstractions is inspired by the * SPIRAL literature (cite?). Similar although more general concepts * also exist in the polyhedral compilation literature (e.g., access diff --git a/include/graphblas/storage.hpp b/include/graphblas/storage.hpp index 55031a553..18f6c92e4 100644 --- a/include/graphblas/storage.hpp +++ b/include/graphblas/storage.hpp @@ -16,9 +16,12 @@ /** * - * @file This file registers matrix storage schemes that are either - * implemented, under implementation, or were at any point in time - * conceived and noteworthy enough to be recorded for future consideration. + * @file + * + * This file registers matrix storage schemes that are either + * implemented, under implementation, or were at any point in time + * conceived and noteworthy enough to be recorded for future consideration. + * */ #ifndef _H_GRB_STORAGE @@ -32,9 +35,9 @@ namespace grb { namespace storage { /** - * Collection of possible storage scheme options for dense matrices (or now including classic BLAS/LAPACK storage schemes). + * Collection of possible storage scheme options for dense matrices (for now including classic BLAS/LAPACK storage schemes). * \note Assumption is row-major but a complete specification might depend by a similar row/column-major option perhaps included - * at the level of Matrix (general ). + * at the level of grb::Matrix. */ enum Dense { From ff59d8073c8588fca754ef44717be42ffc2ed9e8 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Tue, 8 Feb 2022 14:38:28 +0100 Subject: [PATCH 043/282] Add alloc primitives for denseref Currently they are a copy of the same primitives for reference backend. Think whether it makes sense to group the alloc functions for these two backends. --- include/graphblas/denseref/alloc.hpp | 188 +++++++++++++++++++++++++++ include/graphblas/utils/alloc.hpp | 3 + 2 files changed, 191 insertions(+) create mode 100644 include/graphblas/denseref/alloc.hpp diff --git a/include/graphblas/denseref/alloc.hpp b/include/graphblas/denseref/alloc.hpp new file mode 100644 index 000000000..7bc555c26 --- /dev/null +++ b/include/graphblas/denseref/alloc.hpp @@ -0,0 +1,188 @@ + +/* + * Copyright 2021 Huawei Technologies Co., Ltd. + * + * 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. + */ + +/* + * @author A. N. Yzelman + * @date 22nd of January, 2021 + */ + +#ifndef _H_GRB_DENSEREF_ALLOC +#define _H_GRB_DENSEREF_ALLOC + +#include + +#include + +#include "config.hpp" + +namespace grb { + namespace utils { + namespace internal { + + /** + * \internal AllocatorFunctions< reference_dense > is an exact copy of + * AllocatorFunctions< reference > as they provide exactly the same functionalities. + * TODO: Think if it makes sense to merge them together and, if so, how. + */ + + /** + * Provides standard allocation mechanisms using the POSIX and libnuma + * -# posix_memalign() and + * -# numa_alloc_interleaved() + * system calls. + * + * When one of these functions are not available a different allocation + * mechanism must be selected. + */ + template<> + class AllocatorFunctions< reference_dense > { + private: + /** Disable instantiation. */ + AllocatorFunctions() {} + + public: + /** + * Allocates a single chunk of memory. + * + * @param[in,out] allocd Running accumulation of memory that has been allocated. + */ + template< typename T > + static RC mode_alloc( T * __restrict__ &pointer, const size_t elements, + const grb::config::ALLOC_MODE mode, utils::AutoDeleter< T > &deleter, + size_t &allocd + ) { + // catch trivial case + if( elements == 0 ) { + pointer = NULL; + return SUCCESS; + } + // non-trivial case, first compute size + const size_t size = elements * sizeof( T ); + // check if the region is supposed to be shared or not + if( mode == grb::config::ALLOC_MODE::INTERLEAVED ) { +#ifdef _GRB_NO_LIBNUMA + return UNSUPPORTED; +#else + // allocate + pointer = static_cast< T * >( numa_alloc_interleaved( size ) ); + // check for error + if( pointer == NULL ) { + return OUTOFMEM; + } + // record appropriate deleter + deleter = utils::AutoDeleter< T >( pointer, size ); +#endif + } else if( mode == grb::config::ALLOC_MODE::ALIGNED ) { + // allocate + void * new_pointer = NULL; + const int prc = posix_memalign( &new_pointer, grb::config::CACHE_LINE_SIZE::value(), size ); + // check for error + if( prc == ENOMEM ) { + return OUTOFMEM; + } + if( prc != 0 ) { + return PANIC; + } + // record pointer + pointer = static_cast< T * >( new_pointer ); + // record appropriate deleter + deleter = utils::AutoDeleter< T >( pointer, 0 ); + } else { + // we should never reach this code block + assert( false ); + return PANIC; + } + // final sanity check + assert( pointer != NULL ); + // record memory taken + allocd += size; + // done + return SUCCESS; + } + + /** Allocates a single chunk of memory. Wrapper function that relies on the config parameters in #grb::config::MEMORY. */ + template< typename T > + static RC single_alloc( T * __restrict__ & pointer, const size_t elements, const bool shared, utils::AutoDeleter< T > & deleter, size_t & allocd ) { + if( shared ) { + return mode_alloc( pointer, elements, grb::config::IMPLEMENTATION<>::sharedAllocMode(), deleter, allocd ); + } else { + return mode_alloc( pointer, elements, grb::config::IMPLEMENTATION<>::defaultAllocMode(), deleter, allocd ); + } + } + + /** Base case for internal::alloc (variadic version). */ + template< typename T > + static RC alloc( size_t & allocd, T * __restrict__ & pointer, const size_t size, const bool shared, utils::AutoDeleter< T > & deleter ) { + // try new alloc + T * __restrict__ new_pointer = NULL; + utils::AutoDeleter< T > new_deleter; + RC recursive_error_code = single_alloc( new_pointer, size, shared, new_deleter, allocd ); + // if OK, set output pointer to newly allocated memory + if( recursive_error_code == SUCCESS ) { + pointer = new_pointer; + deleter = new_deleter; + } + // done + return recursive_error_code; + } + + /** Allocates multiple memory segments in a safe way. */ + template< typename T, typename... Targs > + static RC alloc( size_t & allocd, T * __restrict__ & pointer, const size_t size, const bool shared, utils::AutoDeleter< T > & deleter, Targs &&... args ) { + // set local deleter + utils::AutoDeleter< T > new_deleter; + // try new alloc + T * __restrict__ new_pointer = NULL; + RC recursive_error_code = single_alloc( new_pointer, size, shared, new_deleter, allocd ); + // check for success + if( recursive_error_code != SUCCESS ) { + // fail, so propagate + return recursive_error_code; + } + // recurse on remainder arguments + recursive_error_code = alloc( allocd, std::forward< Targs >( args )... ); + // check for failure + if( recursive_error_code != SUCCESS ) { + // fail, so reset old pointer and propagate error code + return recursive_error_code; + } + // all is OK, so finally 1) set pointer to newly allocated memory area and 2) propagate the deleter to user space + pointer = new_pointer; + deleter = new_deleter; + // done + return SUCCESS; + } + + /** Helper function that prints allocation information to stdout. */ + static void postAlloc( const RC ret, const size_t allocd, const std::string prefix, const std::string postfix ) { + if( ret == SUCCESS ) { + if( config::MEMORY::report( prefix, "allocated", allocd, false ) ) { + std::cout << postfix << ".\n"; + } + } else { + if( config::MEMORY::report( prefix, "failed to allocate", allocd, false ) ) { + std::cout << postfix << ".\n"; + } + } + } + }; + + } // namespace internal + } // namespace utils +} // namespace grb + +#endif diff --git a/include/graphblas/utils/alloc.hpp b/include/graphblas/utils/alloc.hpp index d673c26ed..4c67eb4ce 100644 --- a/include/graphblas/utils/alloc.hpp +++ b/include/graphblas/utils/alloc.hpp @@ -49,6 +49,9 @@ namespace grb { #ifdef _GRB_WITH_REFERENCE #include "graphblas/reference/alloc.hpp" #endif +#ifdef _GRB_WITH_DENSEREF + #include "graphblas/denseref/alloc.hpp" +#endif #ifdef _GRB_WITH_LPF #include "graphblas/bsp1d/alloc.hpp" #endif From 70e93171e013a0fdc089fc0495879010b18808dc Mon Sep 17 00:00:00 2001 From: Anonymous Date: Tue, 8 Feb 2022 18:23:30 +0100 Subject: [PATCH 044/282] Handle memory allocation failure. Implement destructor. --- include/graphblas/denseref/matrix.hpp | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/include/graphblas/denseref/matrix.hpp b/include/graphblas/denseref/matrix.hpp index ac98a5e20..78ffc4cd6 100644 --- a/include/graphblas/denseref/matrix.hpp +++ b/include/graphblas/denseref/matrix.hpp @@ -153,7 +153,16 @@ namespace grb { /** @see Matrix::Matrix() */ Matrix( const size_t rows, const size_t columns ): m( rows ), n( columns ), initialized( false ) { // TODO Implement allocation properly - data = new T[ m * n ]; + if( m > 0 && n > 0) { + data = new (std::nothrow) T[ m * n ]; + } else { + data = nullptr; + } + + if ( m > 0 && n > 0 && data == nullptr ) { + throw std::runtime_error( "Could not allocate memory during grb::Matrix construction." ); + } + } /** @see Matrix::Matrix( const Matrix & ) */ @@ -173,7 +182,11 @@ namespace grb { } /** @see Matrix::~Matrix(). */ - ~Matrix() {} + ~Matrix() { + if( data != nullptr ) { + delete [] data; + } + } }; // template specialisation for GraphBLAS type traits From 2f8708f13ee9d7a6791917bfb494cc60d645e725 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Tue, 8 Feb 2022 22:05:51 +0100 Subject: [PATCH 045/282] WIP: Add data size calculator depending on Storage scheme and structure. Also add a simple test to showcase the usage of this feature. --- include/graphblas/denseref/matrix.hpp | 63 +++++++++++++++ tests/unit/CMakeLists.txt | 4 + tests/unit/dense_matrix_allocation_size.cpp | 90 +++++++++++++++++++++ 3 files changed, 157 insertions(+) create mode 100644 tests/unit/dense_matrix_allocation_size.cpp diff --git a/include/graphblas/denseref/matrix.hpp b/include/graphblas/denseref/matrix.hpp index 78ffc4cd6..538dcc67d 100644 --- a/include/graphblas/denseref/matrix.hpp +++ b/include/graphblas/denseref/matrix.hpp @@ -42,6 +42,69 @@ namespace grb { + namespace internal { + /** Helper class to calculate number of elements for raw matrix storage, + * depending on the storage scheme and the structure. + * + * \internal Thoughts: + * Currently, this class has to depend on structure (to allow for "optimal" element count). + * E.g. Matrix< Dense:full, Structure::Triangular> can use less storage than + * Matrix< Dense::full, Structure::General>. + * If we add Storage::packed (which could store Triangular or Symetric matrices), + * then it seems that Structure can be removed from template list of this class. + * + * TODO: Expand the class to StructuredMatrix + */ + template< typename T, typename grb::storage::Dense, typename Structure = grb::structures::General > + class DataElementsCalculator { + public: + static size_t calculate( const Matrix< T, reference_dense > & A ) { + (void)A; + std::cout << "Cannot determine storage size due to unspecified storage scheme. \n"; + assert( false ); + return (size_t)-1; + } + }; + + template< typename T > + class DataElementsCalculator< T, grb::storage::Dense::full > { + public: + static size_t calculate( const Matrix< T, reference_dense > & A ) { + return nrows( A ) * ncols( A ); + } + }; + + template< typename T > + class DataElementsCalculator< T, grb::storage::Dense::full, grb::structures::Triangular > { + public: + static size_t calculate( const Matrix< T, reference_dense > & A ) { + // structures::Triangular assumes that the matrix is structures::Square + std::size_t m = nrows( A ); + return m * ( m + 1 ) / 2; + } + }; + + template< typename T > + class DataElementsCalculator< T, grb::storage::Dense::band > { + public: + static size_t calculate( const Matrix< T, reference_dense > & A ) { + size_t ku = 1; // nsuperdiagonals( A ); only exists in banded matrix + size_t kl = 1; // nsubdiagonals( A ); only exists in banded matrix + return ncols( A ) * ( ku + kl + 1 ); + } + }; + + template< typename T > + class DataElementsCalculator< T, grb::storage::Dense::array1d > { + public: + static size_t calculate( const Matrix< T, reference_dense > & A ) { + size_t min_dimension = min( nrows( A ), ncols( A ) ); + // Temporary: Assume main diagonal + one subdiagonal + one superdiagonal + return min_dimension + 2 * ( min_dimension - 1 ); + } + }; + } // namespace internal + template< typename T > T * getRaw( Matrix< T, reference_dense > & ) noexcept; diff --git a/tests/unit/CMakeLists.txt b/tests/unit/CMakeLists.txt index 4367de4a6..84ab17f81 100644 --- a/tests/unit/CMakeLists.txt +++ b/tests/unit/CMakeLists.txt @@ -204,6 +204,10 @@ add_grb_executables( spy spy.cpp BACKENDS reference reference_omp ) +add_grb_executables( dense_matrix_allocation_size dense_matrix_allocation_size.cpp + BACKENDS reference_dense +) + add_grb_executables( dense_mxm dense_mxm.cpp BACKENDS reference_dense ) diff --git a/tests/unit/dense_matrix_allocation_size.cpp b/tests/unit/dense_matrix_allocation_size.cpp new file mode 100644 index 000000000..2f9169675 --- /dev/null +++ b/tests/unit/dense_matrix_allocation_size.cpp @@ -0,0 +1,90 @@ + +/* + * Copyright 2021 Huawei Technologies Co., Ltd. + * + * 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. + */ + +#include +#include +#include +#include +#include + +#include + +void grb_program( const size_t & n, grb::RC & rc ) { + // initialize test + grb::Matrix< double, grb::reference_dense > M( n, n ); + + size_t elems = grb::internal::DataElementsCalculator< double, grb::storage::Dense::full >::calculate( M ); + std::cout << "Matrix< Dense::full, structure::General> " << n << " x " << n << " can be stored with " << elems << " elements.\n"; + + elems = grb::internal::DataElementsCalculator< double, grb::storage::Dense::full, grb::structures::Triangular >::calculate( M ); + std::cout << "Matrix< Dense::full, structure::Triangular> " << n << " x " << n << " can be stored with " << elems << " elements.\n"; + + // The following call does not work because the template cannot figure out that UpperTriangular is also Triangular. + // TODO: fix it + // grb::internal::DataElementsCalculator< double, grb::storage::Dense::full, grb::structures::UpperTriangular >::calculate( M ); + // std::cout << "Matrix< Dense::full, structure::UpperTriangular> " << n << " x " << n << " can be stored with " << elems << " elements.\n"; + + rc = grb::SUCCESS; +} + +int main( int argc, char ** argv ) { + // defaults + bool printUsage = false; + size_t in = 5; + + // error checking + if( argc > 2 ) { + printUsage = true; + } + if( argc == 2 ) { + size_t read; + std::istringstream ss( argv[ 1 ] ); + if( ! ( ss >> read ) ) { + std::cerr << "Error parsing first argument\n"; + printUsage = true; + } else if( ! ss.eof() ) { + std::cerr << "Error parsing first argument\n"; + printUsage = true; + } else if( read % 2 != 0 ) { + std::cerr << "Given value for n is odd\n"; + printUsage = true; + } else { + // all OK + in = read; + } + } + if( printUsage ) { + std::cerr << "Usage: " << argv[ 0 ] << " [n]\n"; + std::cerr << " -n (optional, default is 100): an even integer, the " + "test size.\n"; + return 1; + } + + std::cout << "This is functional test " << argv[ 0 ] << "\n"; + grb::Launcher< grb::AUTOMATIC > launcher; + grb::RC out; + if( launcher.exec( &grb_program, in, out, true ) != grb::SUCCESS ) { + std::cerr << "Launching test FAILED\n"; + return 255; + } + if( out != grb::SUCCESS ) { + std::cerr << "Test FAILED (" << grb::toString( out ) << ")" << std::endl; + } else { + std::cout << "Test OK" << std::endl; + } + return 0; +} From f26ad18459736992ee449e2df5129d92b53a44b6 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Thu, 10 Feb 2022 16:36:11 +0100 Subject: [PATCH 046/282] Add buildMatrix for general full StructuredMatrix --- include/graphblas/denseref/io.hpp | 5 +++++ include/graphblas/denseref/matrix.hpp | 22 +++++++++++++++++++++- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/include/graphblas/denseref/io.hpp b/include/graphblas/denseref/io.hpp index 4507c410a..15a792491 100644 --- a/include/graphblas/denseref/io.hpp +++ b/include/graphblas/denseref/io.hpp @@ -33,6 +33,11 @@ namespace grb { return A.template buildMatrixUnique( start, end ); } + template< typename InputType, typename Structure, typename Storage, typename View, typename fwd_iterator > + RC buildMatrix( StructuredMatrix< InputType, Structure, Storage, View, reference_dense > & A, const fwd_iterator & start, const fwd_iterator & end ) noexcept { + return A.template buildMatrixUnique( start, end ); + } + } // end namespace ``grb'' #endif // end ``_H_GRB_DENSEREF_IO'' diff --git a/include/graphblas/denseref/matrix.hpp b/include/graphblas/denseref/matrix.hpp index 538dcc67d..7c11d0648 100644 --- a/include/graphblas/denseref/matrix.hpp +++ b/include/graphblas/denseref/matrix.hpp @@ -312,6 +312,9 @@ namespace grb { friend std::pair< size_t, size_t > dims<>( const StructuredMatrix< T, Structure, storage::Dense, view::Identity< void >, reference_dense > & ) noexcept; + template< typename fwd_iterator > + friend RC buildMatrix( const StructuredMatrix< T, Structure, storage::Dense, view::Identity< void >, reference_dense > &, const fwd_iterator &, const fwd_iterator ) noexcept; + using self_type = StructuredMatrix< T, Structure, storage::Dense, view::Identity< void >, reference_dense >; // Physical layout - TBD @@ -364,6 +367,9 @@ namespace grb { friend std::pair< size_t, size_t > dims<>( const StructuredMatrix< T, structures::General, storage::Dense, view::Identity< void >, reference_dense > & ) noexcept; + template< typename InputType, typename Structure, typename Storage, typename View, typename fwd_iterator > + friend RC buildMatrix( StructuredMatrix< InputType, Structure, Storage, View, reference_dense > &, const fwd_iterator & start, const fwd_iterator & end ) noexcept; + using self_type = StructuredMatrix< T, structures::General, storage::Dense, view::Identity< void >, reference_dense >; // Physical layout - TBD @@ -371,6 +377,8 @@ namespace grb { std::shared_ptr imf_l, imf_r; + Matrix< T, reference_dense > * _container; + /** * The container's storage scheme. */ @@ -383,6 +391,12 @@ namespace grb { return std::make_pair( imf_l->n, imf_r->n ); } + template< typename fwd_iterator > + RC buildMatrixUnique( const fwd_iterator & start, const fwd_iterator & end ) { + std::cout << "Building StructuredMatrix<>; calling buildMatrix( Matrix<> )\n"; + return buildMatrix( *_container, start, end ); + } + public: /** Exposes the element type and the structure. */ using value_type = T; @@ -395,7 +409,13 @@ namespace grb { using reference_t = identity_t; - StructuredMatrix( const size_t rows, const size_t cols ) : imf_l( std::make_shared< imf::Id >( rows ) ), imf_r( std::make_shared< imf::Id >( cols ) ), storage_scheme( storage::full ), initialized( false ) {} + StructuredMatrix( const size_t rows, const size_t cols ) : + imf_l( std::make_shared< imf::Id >( rows ) ), + imf_r( std::make_shared< imf::Id >( cols ) ), + _container( new Matrix< T, reference_dense >(rows, cols) ), + storage_scheme( storage::full ), + initialized( false ) { + } }; // StructuredMatrix General, container From a1ac7dd002042a20b3acd6717e4fe9e9dffe9177 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Thu, 10 Feb 2022 16:56:43 +0100 Subject: [PATCH 047/282] Add a check for size mismatch in buildMatrix --- include/graphblas/denseref/matrix.hpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/include/graphblas/denseref/matrix.hpp b/include/graphblas/denseref/matrix.hpp index 7c11d0648..468f2c399 100644 --- a/include/graphblas/denseref/matrix.hpp +++ b/include/graphblas/denseref/matrix.hpp @@ -189,7 +189,9 @@ namespace grb { /** Whether the container presently is uninitialized. */ bool initialized; - /** @see Matrix::buildMatrixUnique */ + /** @see Matrix::buildMatrixUnique + * Returns RC::MISMATCH if the input size does not match the matrix storage size. + */ template< typename fwd_iterator > RC buildMatrixUnique( const fwd_iterator & _start, const fwd_iterator & _end ) { // detect trivial case @@ -197,6 +199,10 @@ namespace grb { return SUCCESS; } + if ( (size_t)( _end - _start ) != ( m * n ) ) { + return MISMATCH; + } + // TODO: Add more sanity checks (e.g. overflow) for( auto it = _start; it != _end; ++it ) { From 0c20fa8acf3fb01ad91ecc41249d11eacafeb73f Mon Sep 17 00:00:00 2001 From: Anonymous Date: Mon, 14 Feb 2022 11:49:26 +0100 Subject: [PATCH 048/282] Add mxm for dense Structured Matrices --- include/graphblas/denseref/blas3.hpp | 118 ++++++++++++++++++++++++++ include/graphblas/denseref/matrix.hpp | 32 +++++-- tests/unit/dense_mxm.cpp | 36 ++++---- 3 files changed, 163 insertions(+), 23 deletions(-) diff --git a/include/graphblas/denseref/blas3.hpp b/include/graphblas/denseref/blas3.hpp index bc19d25f1..1423917a9 100644 --- a/include/graphblas/denseref/blas3.hpp +++ b/include/graphblas/denseref/blas3.hpp @@ -104,6 +104,107 @@ namespace grb { return SUCCESS; } + /** + * \internal general mxm implementation that all mxm variants using structured matrices refer to + */ + template< + bool allow_void, + class MulMonoid, + typename OutputType, typename InputType1, typename InputType2, + class Operator, class Monoid, + typename OutputStructure, typename InputStructure1, typename InputStructure2, + typename OutputView, typename InputView1, typename InputView2 + > + RC mxm_generic( StructuredMatrix< OutputType, OutputStructure, storage::Dense, OutputView, reference_dense > &C, + const StructuredMatrix< InputType1, InputStructure1, storage::Dense, InputView1, reference_dense > &A, + const StructuredMatrix< InputType2, InputStructure2, storage::Dense, InputView2, reference_dense > &B, + const Operator &oper, + const Monoid &monoid, + const MulMonoid &mulMonoid, + const typename std::enable_if< !grb::is_object< OutputType >::value && + !grb::is_object< InputType1 >::value && ! + grb::is_object< InputType2 >::value && + grb::is_operator< Operator >::value && + grb::is_monoid< Monoid >::value, + void >::type * const = NULL + ) { + // TODO; Implement this as a backup version that works for any structure and storage. + // Even though the performance does not have to be optimal, we guarantee that any two matrices can be multiplied + // To provide better performing mxm, one should implement a function with specialized template elements + // This currently cannot work as we do not have a generic way to access elements in a given StructuredMatrix + return UNSUPPORTED; + } + + /** + * \internal mxm specialized to StructuredMatrices having general structure and full dense storage scheme + */ + template< + bool allow_void, + class MulMonoid, + typename OutputType, typename InputType1, typename InputType2, + class Operator, class Monoid, + typename OutputView = view::Identity< void >, typename InputView1 = view::Identity< void >, typename InputView2 = view::Identity< void > + > + RC mxm_generic( StructuredMatrix< OutputType, structures::General, storage::Dense, OutputView, reference_dense > &C, + const StructuredMatrix< InputType1, structures::General, storage::Dense, InputView1, reference_dense > &A, + const StructuredMatrix< InputType2, structures::General, storage::Dense, InputView2, reference_dense > &B, + const Operator &oper, + const Monoid &monoid, + const MulMonoid &mulMonoid, + const typename std::enable_if< !grb::is_object< OutputType >::value && + !grb::is_object< InputType1 >::value && ! + grb::is_object< InputType2 >::value && + grb::is_operator< Operator >::value && + grb::is_monoid< Monoid >::value, + void >::type * const = NULL + ) { + (void)oper; + (void)monoid; + (void)mulMonoid; + static_assert( allow_void || + ( !( + std::is_same< InputType1, void >::value || std::is_same< InputType2, void >::value + ) ), + "grb::mxm_generic: the operator-monoid version of mxm cannot be " + "used if either of the input matrices is a pattern matrix (of type " + "void)" + ); + +#ifdef _DEBUG + std::cout << "In grb::internal::mxm_generic (reference_dense, unmasked)\n"; +#endif + + // How to handle combinations of different storage schemes? + // For example for C = A * B we can directly call mxm for Matrix<> containers + // run-time checks + const size_t m = grb::nrows( C ); + const size_t n = grb::ncols( C ); + const size_t m_A = grb::nrows( A ); + const size_t k = grb::ncols( A ); + const size_t k_B = grb::nrows( B ); + const size_t n_B = grb::ncols( B ); + // Maybe we can offload these checks to mxm call later in this function + + if( m != m_A || k != k_B || n != n_B ) { + return MISMATCH; + } + + const auto A_container = grb::internal::getContainer( A ); + const auto B_container = grb::internal::getContainer( B ); + auto C_container = grb::internal::getContainer( C ); + + std::cout << "Multiplying dense matrices.\n"; + + RC rc = mxm_generic< true >( C_container, A_container, B_container, oper, monoid, mulMonoid ); + + if ( rc == SUCCESS ) { + // grb::internal::setInitialized( C, true ); + } + + // done + return rc; + } + } // namespace internal /** @@ -125,6 +226,23 @@ namespace grb { return internal::mxm_generic< true >( C, A, B, ring.getMultiplicativeOperator(), ring.getAdditiveMonoid(), ring.getMultiplicativeMonoid() ); } + /** + * \internal grb::mxm semiring version for dense Structured Matrices + */ + template< typename OutputType, typename InputType1, typename InputType2, class Semiring, + typename OutputStructure, typename OutputView = view::Identity< void >, + typename InputStructure1, typename InputView1 = view::Identity< void >, + typename InputStructure2, typename InputView2 = view::Identity< void > > + RC mxm( StructuredMatrix< OutputType, OutputStructure, storage::Dense, OutputView, reference_dense > & C, + const StructuredMatrix< InputType1, InputStructure1, storage::Dense, InputView1, reference_dense > & A, + const StructuredMatrix< InputType2, InputStructure2, storage::Dense, InputView2, reference_dense > & B, + const Semiring & ring = Semiring(), + const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_semiring< Semiring >::value, + void >::type * const = NULL ) { + // TODO: How should we handle multiplication of combinations of Structures and Storage schemes? + return internal::mxm_generic< true >( C, A, B, ring.getMultiplicativeOperator(), ring.getAdditiveMonoid(), ring.getMultiplicativeMonoid() ); + } + } // end namespace ``grb'' #endif // end ``_H_GRB_DENSEREF_BLAS3'' diff --git a/include/graphblas/denseref/matrix.hpp b/include/graphblas/denseref/matrix.hpp index 468f2c399..f05f21598 100644 --- a/include/graphblas/denseref/matrix.hpp +++ b/include/graphblas/denseref/matrix.hpp @@ -285,6 +285,18 @@ namespace grb { return m.n; } + namespace internal { + template< typename T, typename Structure, typename Storage, typename View > + const Matrix< T, reference_dense > & getContainer( const StructuredMatrix< T, Structure, Storage, View, reference_dense > & A ) { + return *( A._container ); + } + + template< typename T, typename Structure, typename Storage, typename View > + Matrix< T, reference_dense > & getContainer( StructuredMatrix< T, Structure, Storage, View, reference_dense > & A ) { + return *( A._container ); + } + } // namespace internal + /** * Here starts spec draft for StructuredMatrix */ @@ -312,16 +324,21 @@ namespace grb { Storage info friends ******************** */ + using self_type = StructuredMatrix< T, Structure, storage::Dense, view::Identity< void >, reference_dense >; + friend size_t nrows<>( const StructuredMatrix< T, Structure, storage::Dense, view::Identity< void >, reference_dense > & ) noexcept; friend size_t ncols<>( const StructuredMatrix< T, Structure, storage::Dense, view::Identity< void >, reference_dense > & ) noexcept; friend std::pair< size_t, size_t > dims<>( const StructuredMatrix< T, Structure, storage::Dense, view::Identity< void >, reference_dense > & ) noexcept; + + friend const Matrix< T, reference_dense> & internal::getContainer<>( const self_type & A ) noexcept; + + friend Matrix< T, reference_dense> & internal::getContainer<>( self_type & A ) noexcept; template< typename fwd_iterator > friend RC buildMatrix( const StructuredMatrix< T, Structure, storage::Dense, view::Identity< void >, reference_dense > &, const fwd_iterator &, const fwd_iterator ) noexcept; - using self_type = StructuredMatrix< T, Structure, storage::Dense, view::Identity< void >, reference_dense >; // Physical layout - TBD // Matrix< T, reference_dense > A; @@ -367,24 +384,27 @@ namespace grb { Storage info friends ******************** */ + using self_type = StructuredMatrix< T, structures::General, storage::Dense, view::Identity< void >, reference_dense >; + friend size_t nrows<>( const StructuredMatrix< T, structures::General, storage::Dense, view::Identity< void >, reference_dense > & ) noexcept; friend size_t ncols<>( const StructuredMatrix< T, structures::General, storage::Dense, view::Identity< void >, reference_dense > & ) noexcept; friend std::pair< size_t, size_t > dims<>( const StructuredMatrix< T, structures::General, storage::Dense, view::Identity< void >, reference_dense > & ) noexcept; + friend const Matrix< T, reference_dense> & internal::getContainer<>( const self_type & A ) noexcept; + + friend Matrix< T, reference_dense> & internal::getContainer<>( self_type & A ) noexcept; + template< typename InputType, typename Structure, typename Storage, typename View, typename fwd_iterator > friend RC buildMatrix( StructuredMatrix< InputType, Structure, Storage, View, reference_dense > &, const fwd_iterator & start, const fwd_iterator & end ) noexcept; - using self_type = StructuredMatrix< T, structures::General, storage::Dense, view::Identity< void >, reference_dense >; - // Physical layout - TBD // Matrix< T, reference_dense > A; + Matrix< T, reference_dense > * _container; std::shared_ptr imf_l, imf_r; - Matrix< T, reference_dense > * _container; - /** * The container's storage scheme. */ @@ -416,9 +436,9 @@ namespace grb { using reference_t = identity_t; StructuredMatrix( const size_t rows, const size_t cols ) : + _container( new Matrix< T, reference_dense >(rows, cols) ), imf_l( std::make_shared< imf::Id >( rows ) ), imf_r( std::make_shared< imf::Id >( cols ) ), - _container( new Matrix< T, reference_dense >(rows, cols) ), storage_scheme( storage::full ), initialized( false ) { } diff --git a/tests/unit/dense_mxm.cpp b/tests/unit/dense_mxm.cpp index 2c98e09c2..df6425e0d 100644 --- a/tests/unit/dense_mxm.cpp +++ b/tests/unit/dense_mxm.cpp @@ -23,18 +23,20 @@ using namespace grb; -void print_matrix( const grb::Matrix< double > & A) { - if( ! grb::internal::getInitialized< double >( A ) ) { - std::cout << "Matrix is uninitialized, nothing to print.\n"; - return; - } - const double * Araw = grb::getRaw( A ); - for( size_t row = 0; row < grb::nrows( A ); ++row ) { - for( size_t col = 0; col < grb::ncols( A ); ++col ) { - std::cout << Araw[row * grb::ncols( A ) + col] << " "; - } - std::cout << "\n"; - } +template< typename Structure > +void print_matrix( const grb::StructuredMatrix< double, Structure > & A) { + (void)A; + // if( ! grb::internal::getInitialized< double >( A ) ) { + // std::cout << "Matrix is uninitialized, nothing to print.\n"; + // return; + // } + // const double * Araw = grb::getRaw( internal::getContainer( A ) ); + // for( size_t row = 0; row < grb::nrows( A ); ++row ) { + // for( size_t col = 0; col < grb::ncols( A ); ++col ) { + // std::cout << Araw[row * grb::ncols( A ) + col] << " "; + // } + // std::cout << "\n"; + // } } void grb_program( const size_t & n, grb::RC & rc ) { @@ -42,9 +44,9 @@ void grb_program( const size_t & n, grb::RC & rc ) { std::cout << "\tTesting dense mxm\n"; // initialize test - grb::Matrix< double > A( n, n ); - grb::Matrix< double > B( n, n ); - grb::Matrix< double > C( n, n ); + grb::StructuredMatrix< double, structures::General > A( n, n ); + grb::StructuredMatrix< double, structures::General > B( n, n ); + grb::StructuredMatrix< double, structures::General > C( n, n ); std::vector< double > A_data( n * n, 1 ); std::vector< double > B_data( n * n, 1 ); @@ -59,9 +61,9 @@ void grb_program( const size_t & n, grb::RC & rc ) { #endif // Initialize input matrices - rc = grb::buildMatrix< double, decltype( A_data )::const_iterator >( A, A_data.begin(), A_data.end() ); + rc = grb::buildMatrix( A, A_data.begin(), A_data.end() ); if( rc == SUCCESS ) { - rc = grb::buildMatrix< double, decltype( B_data )::const_iterator >( B, B_data.begin(), B_data.end() ); + rc = grb::buildMatrix( B, B_data.begin(), B_data.end() ); } From f41d269f9ce2bed6322fc33a5e1a8047117c5d3a Mon Sep 17 00:00:00 2001 From: Anonymous Date: Thu, 17 Feb 2022 13:30:17 +0100 Subject: [PATCH 049/282] Introducing grb::get_view<> draft --- include/graphblas/denseref/matrix.hpp | 53 +++++++++++++++----------- tests/unit/dense_structured_matrix.cpp | 12 +++--- 2 files changed, 35 insertions(+), 30 deletions(-) diff --git a/include/graphblas/denseref/matrix.hpp b/include/graphblas/denseref/matrix.hpp index f05f21598..612219e87 100644 --- a/include/graphblas/denseref/matrix.hpp +++ b/include/graphblas/denseref/matrix.hpp @@ -597,42 +597,49 @@ namespace grb { } // namespace structures /** - * Peel off any possible view from an input StructuredMatrix type. - * Returns a compatible container-type StructuredMatrix. - */ - template< typename StructuredMatrixT > - struct remove_ref; - - template< typename T, typename Structure, typename StorageSchemeType, typename View, enum Backend backend > - struct remove_ref< StructuredMatrix< T, Structure, StorageSchemeType, View, backend > > { - using type = StructuredMatrix< T, Structure, StorageSchemeType, view::Identity< void >, backend >; - }; - - /** - * Generate a ref StructuredMatrix type. + * Generate an identity view where the type is compliant with the source StructuredMatrix. * If no target structure is specified the one of the source type is assumed. * Otherwise it can only generate a type if the target structure is the same as the source type * or a more specialized version that would preserve its static properties (e.g., symmetric reference * to a square matrix -- any assumption based on symmetry would not break those based on square). */ - template< typename StructuredMatrixT, typename TargetStructure = void > - struct get_ref; template< typename T, typename Structure, typename StorageSchemeType, typename View, enum Backend backend > - struct get_ref< StructuredMatrix< T, Structure, StorageSchemeType, View, backend >, void > { + StructuredMatrix< T, Structure, StorageSchemeType, view::Identity< StructuredMatrix< T, Structure, StorageSchemeType, View, backend > >, backend > + get_view( StructuredMatrix< T, Structure, StorageSchemeType, View, backend > &source ) { + using source_strmat_t = StructuredMatrix< T, Structure, StorageSchemeType, View, backend >; - using type = StructuredMatrix< T, Structure, StorageSchemeType, view::Identity< source_strmat_t >, backend >; - }; + using target_strmat_t = StructuredMatrix< T, Structure, StorageSchemeType, view::Identity< source_strmat_t >, backend >; - template< typename T, typename Structure, typename StorageSchemeType, typename View, enum Backend backend, typename TargetStructure > - struct get_ref< StructuredMatrix< T, Structure, StorageSchemeType, View, backend >, TargetStructure > { + target_strmat_t target( source ); + + return target; + } + + template< typename TargetStructure, typename T, typename Structure, typename StorageSchemeType, typename View, enum Backend backend > + StructuredMatrix< T, TargetStructure, StorageSchemeType, view::Identity< StructuredMatrix< T, Structure, StorageSchemeType, View, backend > >, backend > + get_view( StructuredMatrix< T, Structure, StorageSchemeType, View, backend > &source ) { static_assert( structures::is_in< Structure, typename TargetStructure::inferred_structures >::value, - "Can only create a ref StructuredMatrix with a target structure that implies the source." ); + "Can only create a view when the target structure is compatible with the source." ); using source_strmat_t = StructuredMatrix< T, Structure, StorageSchemeType, View, backend >; - using type = StructuredMatrix< T, TargetStructure, StorageSchemeType, view::Identity< source_strmat_t >, backend >; - }; + using target_strmat_t = StructuredMatrix< T, TargetStructure, StorageSchemeType, view::Identity< source_strmat_t >, backend >; + + target_strmat_t target( source ); + + return target; + } + + template< typename StructuredMatrixT > + typename StructuredMatrixT::transpose_t + transpose( StructuredMatrixT &smat ) { + + std::cout << "Using general version" << std::endl; + typename StructuredMatrixT::transpose_t smat_trans( smat ); + + return smat_trans; + } } // namespace grb diff --git a/tests/unit/dense_structured_matrix.cpp b/tests/unit/dense_structured_matrix.cpp index f6e5a798a..e994b6ccc 100644 --- a/tests/unit/dense_structured_matrix.cpp +++ b/tests/unit/dense_structured_matrix.cpp @@ -46,13 +46,11 @@ void grb_program( const size_t & n, grb::RC & rc ) { grb::StructuredMatrix< float, grb::structures::Square > A( n ); grb::StructuredMatrix< float, grb::structures::NonSingular > B( n, n ); grb::StructuredMatrix< float, grb::structures::FullRank > C( n, 2 * n ); - decltype( A )::transpose_t At( A ); - decltype( M )::transpose_t Mt( M ); + auto At = grb::transpose( A ); + auto Mt = grb::transpose( M ); - grb::get_ref< decltype( M ) >::type Mref( M ); - grb::get_ref< decltype( M ), grb::structures::Square >::type Sq_Mref; - - grb::remove_ref< decltype( Mt ) >::type M1( n, n ); + auto Mview = grb::get_view( M ); + auto Sq_Mref = grb::get_view< grb::structures::Square > ( A ); ask_questions( M, "M" ); ask_questions( A, "A" ); @@ -61,7 +59,7 @@ void grb_program( const size_t & n, grb::RC & rc ) { ask_questions( At, "At" ); ask_questions( Mt, "Mt" ); - ask_questions( Mref, "Mref" ); + ask_questions( Mview, "Mview" ); rc = grb::SUCCESS; } From 8b6a95f37e348451ffbf0189a5d7578e5a189746 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Thu, 17 Feb 2022 10:41:45 +0100 Subject: [PATCH 050/282] Add UpperTriangular StructuredMatrix (container and view) --- include/graphblas/denseref/matrix.hpp | 120 ++++++++++++++++++++++++++ 1 file changed, 120 insertions(+) diff --git a/include/graphblas/denseref/matrix.hpp b/include/graphblas/denseref/matrix.hpp index 612219e87..7dd16a916 100644 --- a/include/graphblas/denseref/matrix.hpp +++ b/include/graphblas/denseref/matrix.hpp @@ -586,6 +586,126 @@ namespace grb { }; // StructuredMatrix Square reference + // StructuredMatrix UpperTriangular, container + template< typename T > + class StructuredMatrix< T, structures::UpperTriangular, storage::Dense, view::Identity< void >, reference_dense > { + + private: + /********************* + Storage info friends + ******************** */ + + using self_type = StructuredMatrix< T, structures::UpperTriangular, storage::Dense, view::Identity< void >, reference_dense >; + + friend size_t nrows<>( const StructuredMatrix< T, structures::UpperTriangular, storage::Dense, view::Identity< void >, reference_dense > & ) noexcept; + + friend size_t ncols<>( const StructuredMatrix< T, structures::UpperTriangular, storage::Dense, view::Identity< void >, reference_dense > & ) noexcept; + + friend std::pair< size_t, size_t > dims<>( const StructuredMatrix< T, structures::UpperTriangular, storage::Dense, view::Identity< void >, reference_dense > & ) noexcept; + + friend const Matrix< T, reference_dense> & internal::getContainer<>( const self_type & A ) noexcept; + + friend Matrix< T, reference_dense> & internal::getContainer<>( self_type & A ) noexcept; + + template< typename InputType, typename Structure, typename Storage, typename View, typename fwd_iterator > + friend RC buildMatrix( StructuredMatrix< InputType, Structure, Storage, View, reference_dense > &, const fwd_iterator & start, const fwd_iterator & end ) noexcept; + + // Physical layout - TBD + // Matrix< T, reference_dense > A; + Matrix< T, reference_dense > * _container; + + std::shared_ptr imf_l, imf_r; + + /** + * The container's storage scheme. + */ + storage::Dense storage_scheme; + + /** Whether the container presently is initialized or not. */ + bool initialized; + + std::pair< size_t, size_t > _dims() const { + return std::make_pair( imf_l->n, imf_r->n ); + } + + template< typename fwd_iterator > + RC buildMatrixUnique( const fwd_iterator & start, const fwd_iterator & end ) { + std::cout << "Building StructuredMatrix<>; calling buildMatrix( Matrix<> )\n"; + return buildMatrix( *_container, start, end ); + } + + public: + /** Exposes the element type and the structure. */ + using value_type = T; + using structure = structures::UpperTriangular; + + // A general Structure knows how to define a reference to itself (which is an identity reference view) + // as well as other static views. + using identity_t = StructuredMatrix< T, structures::UpperTriangular, storage::Dense, view::Identity< self_type >, reference_dense >; + using transpose_t = StructuredMatrix< T, structures::LowerTriangular, storage::Dense, view::Transpose< self_type >, reference_dense >; + + using reference_t = identity_t; + + StructuredMatrix( const size_t rows, const size_t cols ) : + _container( new Matrix< T, reference_dense >(rows, cols) ), + imf_l( std::make_shared< imf::Id >( rows ) ), + imf_r( std::make_shared< imf::Id >( cols ) ), + storage_scheme( storage::full ), + initialized( false ) { + } + + }; // StructuredMatrix UpperTriangular, container + + // StructuredMatrix UpperTriangular, reference + template< typename T, typename View > + class StructuredMatrix< T, structures::UpperTriangular, storage::Dense, View, reference_dense > { + + private: + using self_type = StructuredMatrix< T, structures::UpperTriangular, storage::Dense, View, reference_dense >; + using target_type = typename View::applied_to; + /********************* + Storage info friends + ******************** */ + + friend size_t nrows<>( const self_type & ) noexcept; + + friend size_t ncols<>( const self_type & ) noexcept; + + friend std::pair< size_t, size_t > dims<>( const self_type & ) noexcept; + + target_type * ref; + + std::shared_ptr imf_l, imf_r; + + std::pair< size_t, size_t > _dims() const { + return std::make_pair( imf_l->n, imf_r->n ); + } + + public: + /** Exposes the element type and the structure. */ + using value_type = T; + using structure = structures::UpperTriangular; + + using identity_t = StructuredMatrix< T, structures::UpperTriangular, storage::Dense, view::Identity< self_type >, reference_dense >; + using transpose_t = StructuredMatrix< T, structures::UpperTriangular, storage::Dense, view::Transpose< self_type >, reference_dense >; + + // ref to empty matrix + StructuredMatrix( ) : ref( nullptr ), imf_l( std::make_shared< imf::Id >( 0 ) ), imf_r( std::make_shared< imf::Id >( 0 ) ) {} + + StructuredMatrix( target_type & struct_mat ) : ref( & struct_mat ), imf_l( nullptr ), imf_r( nullptr ) { + // No matter the view it has to be a square matrix + imf_l = std::make_shared< imf::Id >( nrows( struct_mat ) ); + imf_r = std::make_shared< imf::Id >( ncols( struct_mat ) ); + } + + StructuredMatrix( target_type & struct_mat, std::shared_ptr< imf::IMF > imf_l, std::shared_ptr< imf::IMF > imf_r ) : + ref( & struct_mat ), + imf_l( imf_l ), + imf_r( imf_r ) { + } + + }; // StructuredMatrix UpperTriangular, reference + namespace structures { // GraphBLAS type traits for structure From 5c503e0b732a05bba80601570d4af6df0f8eaad5 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Fri, 18 Feb 2022 10:44:57 +0100 Subject: [PATCH 051/282] Implement polymorphic comparison of IMFs --- include/graphblas/imf.hpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/include/graphblas/imf.hpp b/include/graphblas/imf.hpp index dceeca8f0..f1f29888f 100644 --- a/include/graphblas/imf.hpp +++ b/include/graphblas/imf.hpp @@ -57,6 +57,10 @@ namespace grb { virtual size_t map(size_t i) = 0; + virtual bool isSame( const IMF & other ) const { + return typeid( *this ) == typeid( other ) && n == other.n && N == other.N; + } + }; /** @@ -93,6 +97,12 @@ namespace grb { } Strided(size_t n, size_t N, size_t b, size_t s): IMF(n, N), b(b), s(s) { } + + virtual bool isSame( const IMF & other ) const { + return IMF::isSame( other ) + && b == dynamic_cast< const Strided & >( other ).b + && s == dynamic_cast< const Strided & >( other ).s; + } }; /** From ff150042eadfdcbdbe60eb4322be8754cc0ac65b Mon Sep 17 00:00:00 2001 From: Anonymous Date: Thu, 17 Feb 2022 18:25:31 +0100 Subject: [PATCH 052/282] Add to structures a compatibility check from source structure and IMF functions This is to be used when creating a view over a source matrix using provided IMF functions. The compatibility of TargetStructure depends on the SourceStructure and provided IMF functions. This is a runtime check. --- include/graphblas/structures.hpp | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/include/graphblas/structures.hpp b/include/graphblas/structures.hpp index c927e4645..9f5ad4e00 100644 --- a/include/graphblas/structures.hpp +++ b/include/graphblas/structures.hpp @@ -28,8 +28,13 @@ #include #include +#include "imf.hpp" + namespace grb { + template< typename T, typename Structure, typename Storage, typename View, enum Backend backend > + class StructuredMatrix; + /** * Collects all ALP matrix structures. * @@ -96,8 +101,16 @@ namespace grb { south_west }; + struct UpperTriangular; + struct General { using inferred_structures = std::tuple< General >; + + template< typename T, typename Storage, typename View, enum Backend backend > + static bool isInstantiableFrom( const StructuredMatrix< T, UpperTriangular, Storage, View, backend > & M, grb::imf::IMF & imf_l, grb::imf::IMF & imf_r ) { + (void)M; + return imf_l.map( 0 ) <= imf_r.map( imf_r.N ); + } }; struct Square { @@ -118,6 +131,15 @@ namespace grb { struct UpperTriangular { using inferred_structures = structures::tuple_cat< std::tuple< UpperTriangular >, Triangular::inferred_structures >::type; + + // Maybe we can consider inheritance here to allow calling checks in base classes. + // For example, in all cases we should check if IMFs do not overflow the original container. + // (if it is actually necessary. Maybe we want to assume that the user knows what he is doing) + template< typename T, typename Storage, typename View, enum Backend backend > + static bool isInstantiableFrom( const StructuredMatrix< T, UpperTriangular, Storage, View, backend > & M, const grb::imf::IMF & imf_l, const grb::imf::IMF & imf_r ) { + (void)M; + return imf_l.isSame(imf_r); + } }; struct Diagonal { From ba56a19698f8b1d18fd3101590c65e0417e9325f Mon Sep 17 00:00:00 2001 From: Anonymous Date: Fri, 18 Feb 2022 13:58:03 +0100 Subject: [PATCH 053/282] Add constructor taking two IMFs to reference SM with general structure --- include/graphblas/denseref/matrix.hpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/graphblas/denseref/matrix.hpp b/include/graphblas/denseref/matrix.hpp index 7dd16a916..8b542246a 100644 --- a/include/graphblas/denseref/matrix.hpp +++ b/include/graphblas/denseref/matrix.hpp @@ -538,6 +538,10 @@ namespace grb { } + StructuredMatrix( target_type & struct_mat, std::shared_ptr< imf::IMF > imf_l, std::shared_ptr< imf::IMF > imf_r ) : + ref( &struct_mat ), imf_l( imf_l ), imf_r( imf_r ) { + } + }; // StructuredMatrix General reference template< typename T, typename View > From 50eb25874186d40dcd1fb761ad361f902e5ff402 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Thu, 17 Feb 2022 17:27:56 +0100 Subject: [PATCH 054/282] Implement gather through view with provided TargetStructure and IMFs --- include/graphblas/denseref/matrix.hpp | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/include/graphblas/denseref/matrix.hpp b/include/graphblas/denseref/matrix.hpp index 8b542246a..cf82b4daf 100644 --- a/include/graphblas/denseref/matrix.hpp +++ b/include/graphblas/denseref/matrix.hpp @@ -765,6 +765,30 @@ namespace grb { return smat_trans; } + /** + * Implement a gather through a View over compatible Structure using provided Index Mapping Functions. + * The compatibility depends on the TargetStructure, SourceStructure and IMFs, and is calculated during runtime. + */ + + template< typename TargetStructure, typename T, typename Structure, typename StorageSchemeType, typename View, enum Backend backend > + StructuredMatrix< T, TargetStructure, StorageSchemeType, view::Identity< StructuredMatrix< T, Structure, StorageSchemeType, View, backend > >, backend > + get_view( StructuredMatrix< T, Structure, StorageSchemeType, View, backend > &source, + std::shared_ptr< imf::IMF > imf_r, std::shared_ptr< imf::IMF > imf_c ) { + + // No static check as the compatibility depends on IMF, which is a runtime level parameter + + if( ! TargetStructure::isInstantiableFrom( source, * imf_r, * imf_c ) ) { + throw std::runtime_error("Cannot gather into specified TargetStructure from provided SourceStructure and Index Mapping Functions."); + } + + using source_strmat_t = StructuredMatrix< T, Structure, StorageSchemeType, View, backend >; + using target_strmat_t = StructuredMatrix< T, TargetStructure, StorageSchemeType, view::Identity< source_strmat_t >, backend >; + + target_strmat_t target( source, imf_r, imf_c ); + + return target; + } + } // namespace grb #endif // end ``_H_GRB_DENSEREF_MATRIX'' From 8815b57568619a4751a861bed1ead701ccd9f0f7 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Tue, 15 Feb 2022 17:08:55 +0100 Subject: [PATCH 055/282] Add test for gathers on StructuredMatrix using views with IMFs --- tests/unit/CMakeLists.txt | 3 + tests/unit/dense_matrix_imf.cpp | 175 ++++++++++++++++++++++++++++++++ 2 files changed, 178 insertions(+) create mode 100644 tests/unit/dense_matrix_imf.cpp diff --git a/tests/unit/CMakeLists.txt b/tests/unit/CMakeLists.txt index 84ab17f81..c0a0fecc7 100644 --- a/tests/unit/CMakeLists.txt +++ b/tests/unit/CMakeLists.txt @@ -204,6 +204,9 @@ add_grb_executables( spy spy.cpp BACKENDS reference reference_omp ) +add_grb_executables( dense_matrix_imf dense_matrix_imf.cpp + BACKENDS reference_dense +) add_grb_executables( dense_matrix_allocation_size dense_matrix_allocation_size.cpp BACKENDS reference_dense ) diff --git a/tests/unit/dense_matrix_imf.cpp b/tests/unit/dense_matrix_imf.cpp new file mode 100644 index 000000000..c763341ad --- /dev/null +++ b/tests/unit/dense_matrix_imf.cpp @@ -0,0 +1,175 @@ + +/* + * Copyright 2021 Huawei Technologies Co., Ltd. + * + * 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. + */ + +#include +#include +#include +#include +#include + +#include + +void buildUpperTriangularRawArray( std::vector< double > & v, int n ) { + for (int i = 0; i < n; ++i ) { + for (int j = 0; j < n; ++j ) { + if( i >= j ) { + v[ i * n + j ] = 1; + } else { + v[ i * n + j ] = 0; + } + } + } +} + +void grb_program( const size_t & n, grb::RC & rc ) { + // initialize test + // using Upper Triangular Structured Matrix + grb::StructuredMatrix< double, grb::structures::UpperTriangular > U( n, n ); + + // Initialize StructuredMatrix + std::vector< double > Mdata ( n * n, 1 ); + buildUpperTriangularRawArray( Mdata, n ); + rc = grb::buildMatrix( U, Mdata.begin(), Mdata.end() ); + if( rc != grb::SUCCESS ) { + return; + } + + // Valid block + std::cout << "Gather to UpperTriangular (expect success)\n" + "|x x x x x x|\n" + "|. A A x x x|\n" + "|. A A x x x|\n" + "|. . . x x x|\n" + "|. . . . x x|\n" + "|. . . . . x|\n"; + try { + auto Uview1 = grb::get_view< grb::structures::UpperTriangular >( + U, + std::make_shared< grb::imf::Strided >( n, 2, 1, 1 ), + std::make_shared< grb::imf::Strided >( n, 2, 1, 1 ) ); + std::cout << "\tSUCCESS\n"; + } catch( const std::exception & e ) { + std::cerr << e.what() << "\n"; + } + + // Valid block - because of "casting" to general structure + std::cout << "Gather to General (expect success)\n" + "|x x x A A x|\n" + "|. x x A A x|\n" + "|. . x x x x|\n" + "|. . . x x x|\n" + "|. . . . x x|\n" + "|. . . . . x|\n"; + try { + auto Uview2 = grb::get_view< grb::structures::General >( + U, + std::make_shared< grb::imf::Strided >( n, 2, 0, 1 ), + std::make_shared< grb::imf::Strided >( n, 2, 3, 1 ) ); + std::cout << "\tSUCCESS\n"; + } catch( const std::exception & e ) { + std::cerr << e.what() << "\n"; + } + + // Invalid block - selecting a block that is not UpperTriangular + std::cout << "Gather to UpperTriangular (expect failure)\n" + "|x x x A A x|\n" + "|. x x A A x|\n" + "|. . x x x x|\n" + "|. . . x x x|\n" + "|. . . . x x|\n" + "|. . . . . x|\n"; + try { + auto Uview3 = grb::get_view< grb::structures::UpperTriangular >( + U, + std::make_shared< grb::imf::Strided >( n, 2, 0, 1 ), + std::make_shared< grb::imf::Strided >( n, 2, 3, 1 ) ); + std::cout << "\tSUCCESS\n"; + } catch( const std::exception & e ) { + std::cerr << e.what() << "\n"; + } + + // Invalid block - currently no support for zero matrix + std::cout << "Gather to General (expect failure)\n" + "|x x x x x x|\n" + "|. x x x x x|\n" + "|. . x x x x|\n" + "|. . . x x x|\n" + "|A A . . x x|\n" + "|A A . . . x|\n"; + try { + auto Uview4 = grb::get_view< grb::structures::General >( + U, + std::make_shared< grb::imf::Strided >( n, 2, 4, 1 ), + std::make_shared< grb::imf::Strided >( n, 2, 0, 1 ) ); + std::cout << "\tSUCCESS\n"; + } catch( const std::exception & e ) { + std::cerr << e.what() << "\n"; + } + + rc = grb::SUCCESS; +} + +int main( int argc, char ** argv ) { + // defaults + bool printUsage = false; + size_t in = 5; + + // error checking + if( argc > 2 ) { + printUsage = true; + } + if( argc == 2 ) { + size_t read; + std::istringstream ss( argv[ 1 ] ); + if( ! ( ss >> read ) ) { + std::cerr << "Error parsing first argument\n"; + printUsage = true; + } else if( ! ss.eof() ) { + std::cerr << "Error parsing first argument\n"; + printUsage = true; + } else if( read % 2 != 0 ) { + std::cerr << "Given value for n is odd\n"; + printUsage = true; + } else if( read < 6 ) { + std::cerr << "Given value for n is smaller than 6\n"; + printUsage = true; + } else { + // all OK + in = read; + } + } + if( printUsage ) { + std::cerr << "Usage: " << argv[ 0 ] << " [n]\n"; + std::cerr << " -n (optional, default is 100): an even integer >= 6, the " + "test size.\n"; + return 1; + } + + std::cout << "This is functional test " << argv[ 0 ] << "\n"; + grb::Launcher< grb::AUTOMATIC > launcher; + grb::RC out; + if( launcher.exec( &grb_program, in, out, true ) != grb::SUCCESS ) { + std::cerr << "Launching test FAILED\n"; + return 255; + } + if( out != grb::SUCCESS ) { + std::cerr << "Test FAILED (" << grb::toString( out ) << ")" << std::endl; + } else { + std::cout << "Test OK" << std::endl; + } + return 0; +} From ddae001fc4c3286609fa7f1005ce4b46e5c0485e Mon Sep 17 00:00:00 2001 From: Anonymous Date: Mon, 21 Feb 2022 20:28:42 +0100 Subject: [PATCH 056/282] Basic VectorView definition based on grb::vector container --- CMakeLists.txt | 2 +- include/graphblas/base/vector.hpp | 7 +- include/graphblas/config.hpp | 2 +- include/graphblas/denseref/matrix.hpp | 8 -- include/graphblas/denseref/vector.hpp | 167 ++++++++++++++++---------- include/graphblas/vector.hpp | 12 +- 6 files changed, 121 insertions(+), 77 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4496d965c..6ae7b8f90 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -37,7 +37,7 @@ project( GraphBLAS DESCRIPTION "The ultimate engine for sparse computation" LANGUAGES CXX C ) -set( CMAKE_CXX_STANDARD 11 ) +set( CMAKE_CXX_STANDARD 14 ) set( CMAKE_CXX_STANDARD_REQUIRED ON ) # install within the build directory by default (NOT to /usr/local or the likes) diff --git a/include/graphblas/base/vector.hpp b/include/graphblas/base/vector.hpp index 3d3e2c2e5..fb64a1502 100644 --- a/include/graphblas/base/vector.hpp +++ b/include/graphblas/base/vector.hpp @@ -899,8 +899,11 @@ namespace grb { "Vector backend." ); #endif } -} -; +}; + + template< typename T, typename View, typename StorageSchemeType, enum Backend backend, typename C > + class VectorView { }; + } #endif // _H_GRB_VECTOR_BASE diff --git a/include/graphblas/config.hpp b/include/graphblas/config.hpp index cd614705b..eb4d18dc9 100644 --- a/include/graphblas/config.hpp +++ b/include/graphblas/config.hpp @@ -29,7 +29,7 @@ #ifdef _GRB_WITH_REFERENCE #include "graphblas/reference/config.hpp" #endif -#ifdef _GRB_WITH_DENSE +#ifdef _GRB_WITH_DENSEREF #include "graphblas/denseref/config.hpp" #endif #ifdef _GRB_WITH_HYPERDAGS diff --git a/include/graphblas/denseref/matrix.hpp b/include/graphblas/denseref/matrix.hpp index cf82b4daf..f52dc0420 100644 --- a/include/graphblas/denseref/matrix.hpp +++ b/include/graphblas/denseref/matrix.hpp @@ -371,7 +371,6 @@ namespace grb { // A general Structure knows how to define a reference to itself (which is an identity reference view). using identity_t = StructuredMatrix< T, Structure, storage::Dense, view::Identity< self_type >, reference_dense >; - using reference_t = identity_t; StructuredMatrix( const size_t rows, const size_t cols ) : imf_l( std::make_shared< imf::Id >( rows ) ), imf_r( std::make_shared< imf::Id >( cols ) ), storage_scheme( storage::full ), initialized( false ) {} }; // class StructuredMatrix @@ -433,8 +432,6 @@ namespace grb { using identity_t = StructuredMatrix< T, structures::General, storage::Dense, view::Identity< self_type >, reference_dense >; using transpose_t = StructuredMatrix< T, structures::General, storage::Dense, view::Transpose< self_type >, reference_dense >; - using reference_t = identity_t; - StructuredMatrix( const size_t rows, const size_t cols ) : _container( new Matrix< T, reference_dense >(rows, cols) ), imf_l( std::make_shared< imf::Id >( rows ) ), @@ -486,8 +483,6 @@ namespace grb { using identity_t = StructuredMatrix< T, structures::Square, storage::Dense, view::Identity< self_type >, reference_dense >; using transpose_t = StructuredMatrix< T, structures::Square, storage::Dense, view::Transpose< self_type >, reference_dense >; - using reference_t = identity_t; - StructuredMatrix( const size_t rows ) : imf_l( std::make_shared< imf::Id >( rows ) ), imf_r( std::make_shared< imf::Id >( rows ) ), storage_scheme( storage::full ), initialized( false ) {} }; // StructuredMatrix Square, container @@ -648,8 +643,6 @@ namespace grb { using identity_t = StructuredMatrix< T, structures::UpperTriangular, storage::Dense, view::Identity< self_type >, reference_dense >; using transpose_t = StructuredMatrix< T, structures::LowerTriangular, storage::Dense, view::Transpose< self_type >, reference_dense >; - using reference_t = identity_t; - StructuredMatrix( const size_t rows, const size_t cols ) : _container( new Matrix< T, reference_dense >(rows, cols) ), imf_l( std::make_shared< imf::Id >( rows ) ), @@ -759,7 +752,6 @@ namespace grb { typename StructuredMatrixT::transpose_t transpose( StructuredMatrixT &smat ) { - std::cout << "Using general version" << std::endl; typename StructuredMatrixT::transpose_t smat_trans( smat ); return smat_trans; diff --git a/include/graphblas/denseref/vector.hpp b/include/graphblas/denseref/vector.hpp index 22326de19..29483003e 100644 --- a/include/graphblas/denseref/vector.hpp +++ b/include/graphblas/denseref/vector.hpp @@ -23,16 +23,25 @@ #ifndef _H_GRB_DENSEREF_VECTOR #define _H_GRB_DENSEREF_VECTOR -#include -#include -#include - -#include #include +#include #include +#include +#include + +// #include +// #include +// #include + +#include +#include +#include + +#include + namespace grb { @@ -65,9 +74,6 @@ namespace grb { /** The vector data. */ T *__restrict__ data; - /** Deleter corresponding to #data. */ - utils::AutoDeleter< T > data_deleter; - /** Whether the container presently is uninitialized. */ bool initialized; @@ -80,51 +86,44 @@ namespace grb { /** The return type of #operator[](). */ typedef T& lambda_reference; - /** The iterator type. */ - typedef typename internal::ConstDenserefVectorIterator< T, reference_dense > const_iterator; - /** * @param[in] length The requested vector length. * * \internal Allocates a single array of size \a length. */ Vector( const size_t length ) : n( length ), initialized( false ) { - const RC rc = grb::utils::alloc( - "grb::Vector< T, reference_dense > (constructor)", "", - data, length, true, data_deleter - ); - if( rc == OUTOFMEM ) { - throw std::runtime_error( "Out-of-memory during Vector< T, reference_dense > construction" ); - } else if( rc != SUCCESS ) { - throw std::runtime_error( "Unhandled runtime error during Vector< T, reference_dense > construction " ); + // TODO: Implement allocation properly + if( n > 0) { + data = new (std::nothrow) T[ n ]; + } else { + data = nullptr; } - } - /** \internal Simply calls Vector( 0 ). */ - Vector() : Vector( 0 ) {} - - /** \internal Makes a deep copy of \a other. */ - Vector( const Vector< T, reference_dense, void > &other ) : Vector( other.n ) { - initialized = false; - const RC rc = set( *this, other ); // note: initialized will be set as part of this call - if( rc != SUCCESS ) { - throw std::runtime_error( "grb::Vector< T, reference_dense > (copy constructor): error during call to grb::set (" + toString( rc ) + ")" ); + if ( n > 0 && data == nullptr ) { + throw std::runtime_error( "Could not allocate memory during grb::Vector construction." ); } } - /** \internal No implementation notes. */ - Vector( Vector< T, reference_dense, void > &&other ) { - n = other.n; other.n = 0; - data = other.data; other.data = 0; - data_deleter = std::move( other.data_deleter ); - initialized = other.initialized; other.initialized = false; - } + // /** \internal Makes a deep copy of \a other. */ + // Vector( const Vector< T, reference_dense, void > &other ) : Vector( other.n ) { + // initialized = false; + // const RC rc = set( *this, other ); // note: initialized will be set as part of this call + // if( rc != SUCCESS ) { + // throw std::runtime_error( "grb::Vector< T, reference_dense > (copy constructor): error during call to grb::set (" + toString( rc ) + ")" ); + // } + // } + + // /** \internal No implementation notes. */ + // Vector( Vector< T, reference_dense, void > &&other ) { + // n = other.n; other.n = 0; + // data = other.data; other.data = 0; + // data_deleter = std::move( other.data_deleter ); + // initialized = other.initialized; other.initialized = false; + // } /** \internal No implementation notes. */ ~Vector() { - n = 0; - initialized = false; - // free of data will be handled by #data_deleter + delete [] data; } /** \internal No implementation notes. */ @@ -141,29 +140,29 @@ namespace grb { return data[ i ]; } - /** \internal Relies on #internal::ConstDenserefVectorIterator. */ - const_iterator cbegin() const noexcept { - return initialized ? - const_iterator( data, n, false ) : - const_iterator( nullptr, 0, false ); - } - - /** \internal Relies on #internal::ConstDenserefVectorIterator. */ - const_iterator begin() const noexcept { - return cbegin(); - } - - /** \internal Relies on #internal::ConstDenserefVectorIterator. */ - const_iterator cend() const noexcept { - return initialized ? - const_iterator( data, n, true ) : - const_iterator( nullptr, 0, true ); - } - - /** \internal Relies on #internal::ConstDenserefVectorIterator. */ - const_iterator end() const noexcept { - return cend(); - } + // /** \internal Relies on #internal::ConstDenserefVectorIterator. */ + // const_iterator cbegin() const noexcept { + // return initialized ? + // const_iterator( data, n, false ) : + // const_iterator( nullptr, 0, false ); + // } + + // /** \internal Relies on #internal::ConstDenserefVectorIterator. */ + // const_iterator begin() const noexcept { + // return cbegin(); + // } + + // /** \internal Relies on #internal::ConstDenserefVectorIterator. */ + // const_iterator cend() const noexcept { + // return initialized ? + // const_iterator( data, n, true ) : + // const_iterator( nullptr, 0, true ); + // } + + // /** \internal Relies on #internal::ConstDenserefVectorIterator. */ + // const_iterator end() const noexcept { + // return cend(); + // } }; @@ -193,6 +192,50 @@ namespace grb { } // end namespace ``grb::internal'' + + + /** + * Here starts spec draft for vectorView + */ + + template< typename T, typename View > + size_t getLength( const VectorView< T, View, storage::Dense, reference_dense, void > &v ) noexcept { + return v._length(); + } + + template< typename T> + class VectorView< T, view::Identity< void >, storage::Dense, reference_dense, void > { + + private: + /********************* + Storage info friends + ******************** */ + + using self_type = VectorView< T, view::Identity< void >, storage::Dense, reference_dense, void >; + + friend size_t getLength<>( const self_type & ) noexcept; + + // Physical layout + std::unique_ptr< Vector< T, reference_dense, void > > v; + + std::shared_ptr imf; + + /** Whether the container presently is initialized or not. */ + bool initialized; + + size_t _length() const { + return imf->n; + } + + public: + using value_type = T; + + VectorView( const size_t length ) : v( std::make_unique< Vector< T, reference_dense, void > >( length ) ), imf( std::make_shared< imf::Id >( length ) ), initialized( false ) {} + + }; // class VectorView + + + } // end namespace ``grb'' #endif // end ``_H_GRB_DENSEREF_VECTOR'' diff --git a/include/graphblas/vector.hpp b/include/graphblas/vector.hpp index 8c98bd886..53c72097d 100644 --- a/include/graphblas/vector.hpp +++ b/include/graphblas/vector.hpp @@ -31,9 +31,9 @@ #ifdef _GRB_WITH_REFERENCE #include #endif -// #ifdef _GRB_WITH_DENSE -// #include -// #endif +#ifdef _GRB_WITH_DENSEREF + #include +#endif #ifdef _GRB_WITH_LPF #include #endif @@ -54,6 +54,12 @@ namespace grb { > class Vector; + /* + * The default value of \a StorageSchemeType could also be made conditional (Dense or Sparse) depending on \a config::default_backend + */ + template< typename T, typename View = view::Identity< void >, typename StorageSchemeType = storage::Dense, enum Backend backend = config::default_backend, typename C = internal::DefaultCoordinates > + class VectorView; + } #endif From b04c03354ea5497057400f72adcfb2c978a8bc20 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Mon, 21 Feb 2022 21:07:08 +0100 Subject: [PATCH 057/282] Draft of diagonal (vector) view of a matrix --- include/graphblas/denseref/matrix.hpp | 2 +- include/graphblas/denseref/vector.hpp | 54 +++++++++++++++++++++++++- include/graphblas/views.hpp | 11 ++++++ tests/unit/dense_structured_matrix.cpp | 3 ++ 4 files changed, 68 insertions(+), 2 deletions(-) diff --git a/include/graphblas/denseref/matrix.hpp b/include/graphblas/denseref/matrix.hpp index f52dc0420..b517206b3 100644 --- a/include/graphblas/denseref/matrix.hpp +++ b/include/graphblas/denseref/matrix.hpp @@ -488,7 +488,7 @@ namespace grb { }; // StructuredMatrix Square, container /** - * Reference to a Square Matrix generalized over views. + * Reference to a general Matrix generalized over views. */ template< typename T, typename View > class StructuredMatrix< T, structures::General, storage::Dense, View, reference_dense > { diff --git a/include/graphblas/denseref/vector.hpp b/include/graphblas/denseref/vector.hpp index 29483003e..40cfd12dc 100644 --- a/include/graphblas/denseref/vector.hpp +++ b/include/graphblas/denseref/vector.hpp @@ -37,8 +37,9 @@ // #include #include -#include +#include #include +#include #include @@ -198,6 +199,10 @@ namespace grb { * Here starts spec draft for vectorView */ + + /** + * Identity View over a vector container. + */ template< typename T, typename View > size_t getLength( const VectorView< T, View, storage::Dense, reference_dense, void > &v ) noexcept { return v._length(); @@ -235,6 +240,53 @@ namespace grb { }; // class VectorView + /** + * Diagonal Vector View of a structured matrix. + */ + template< typename T, typename StructuredMatrixT > + class VectorView< T, view::Diagonal< StructuredMatrixT >, storage::Dense, reference_dense, void > { + + private: + using self_type = VectorView< T, view::Diagonal< StructuredMatrixT >, storage::Dense, reference_dense, void >; + using target_type = StructuredMatrixT; + + /********************* + Storage info friends + ******************** */ + + friend size_t getLength<>( const self_type & ) noexcept; + + std::shared_ptr< target_type > ref; + + std::shared_ptr imf; + + size_t _length() const { + return imf->n; + } + + public: + /** Exposes the element type and the structure. */ + using value_type = T; + + VectorView( target_type & struct_mat ) : ref( &struct_mat ), imf( nullptr ) { + + size_t _length = view::Diagonal< target_type >::getLength( dims( *ref ) ); + imf = std::make_shared< imf::Id >( _length ); + + } + + }; // StructuredMatrix General reference + + template< typename StructuredMatrixT > + VectorView< typename StructuredMatrixT::value_type, view::Diagonal< StructuredMatrixT >, storage::Dense, reference_dense, void > + diagonal( StructuredMatrixT &smat ) { + + VectorView< typename StructuredMatrixT::value_type, view::Diagonal< StructuredMatrixT >, storage::Dense, reference_dense, void > smat_diag( smat ); + + return smat_diag; + } + + } // end namespace ``grb'' diff --git a/include/graphblas/views.hpp b/include/graphblas/views.hpp index 37f00c312..4d8f418bf 100644 --- a/include/graphblas/views.hpp +++ b/include/graphblas/views.hpp @@ -29,6 +29,7 @@ #ifndef _H_GRB_VIEWS #define _H_GRB_VIEWS +#include #include namespace grb { @@ -55,6 +56,16 @@ namespace grb { } }; + template< typename OriginalType > + struct Diagonal { + + using applied_to = OriginalType; + + static size_t getLength( std::pair< size_t, size_t > dims_pair ) { + return std::min( dims_pair.first, dims_pair.second ); + } + }; + }; // namespace view } // namespace grb diff --git a/tests/unit/dense_structured_matrix.cpp b/tests/unit/dense_structured_matrix.cpp index e994b6ccc..ea9e06222 100644 --- a/tests/unit/dense_structured_matrix.cpp +++ b/tests/unit/dense_structured_matrix.cpp @@ -48,6 +48,7 @@ void grb_program( const size_t & n, grb::RC & rc ) { grb::StructuredMatrix< float, grb::structures::FullRank > C( n, 2 * n ); auto At = grb::transpose( A ); auto Mt = grb::transpose( M ); + auto v_diag = grb::diagonal( M ); auto Mview = grb::get_view( M ); auto Sq_Mref = grb::get_view< grb::structures::Square > ( A ); @@ -60,6 +61,8 @@ void grb_program( const size_t & n, grb::RC & rc ) { ask_questions( At, "At" ); ask_questions( Mt, "Mt" ); ask_questions( Mview, "Mview" ); + + std::cout << "v_diag( " << grb::getLength( v_diag ) << " )" << std::endl; rc = grb::SUCCESS; } From 370d24ca7bdfd1165d1b5cbc44d406b250c19c2e Mon Sep 17 00:00:00 2001 From: Anonymous Date: Mon, 21 Feb 2022 21:36:48 +0100 Subject: [PATCH 058/282] Initial get_view for VectorViews --- include/graphblas/denseref/vector.hpp | 71 +++++++++++++++++++++++++- tests/unit/dense_structured_matrix.cpp | 5 +- 2 files changed, 73 insertions(+), 3 deletions(-) diff --git a/include/graphblas/denseref/vector.hpp b/include/graphblas/denseref/vector.hpp index 40cfd12dc..fc0439f3b 100644 --- a/include/graphblas/denseref/vector.hpp +++ b/include/graphblas/denseref/vector.hpp @@ -237,7 +237,49 @@ namespace grb { VectorView( const size_t length ) : v( std::make_unique< Vector< T, reference_dense, void > >( length ) ), imf( std::make_shared< imf::Id >( length ) ), initialized( false ) {} - }; // class VectorView + }; // class VectorView with physical container + + /** + * Vector view of a vector only via \a view::Identity of another VectorView. + */ + template< typename T, typename VectorViewT > + class VectorView< T, view::Identity< VectorViewT >, storage::Dense, reference_dense, void > { + + private: + using self_type = VectorView< T, view::Identity< VectorViewT >, storage::Dense, reference_dense, void >; + using target_type = VectorViewT; + + /********************* + Storage info friends + ******************** */ + + friend size_t getLength<>( const self_type & ) noexcept; + + std::shared_ptr< target_type > ref; + + std::shared_ptr imf; + + size_t _length() const { + return imf->n; + } + + public: + /** Exposes the element type and the structure. */ + using value_type = T; + + VectorView( target_type & vec_view ) : ref( &vec_view ), imf( nullptr ) { + + imf = std::make_shared< imf::Id >( getLength( *ref ) ); + + } + + VectorView( target_type & vec_view, std::shared_ptr< imf::IMF > imf ) : ref( & vec_view ), imf( imf ) { + if( getLength( vec_view ) != imf->N ) { + throw std::length_error( "VectorView(vec_view, * imf): IMF range differs from target's vector length." ); + } + } + + }; // Identity VectorView /** @@ -275,7 +317,7 @@ namespace grb { } - }; // StructuredMatrix General reference + }; // Diagonal Vector view template< typename StructuredMatrixT > VectorView< typename StructuredMatrixT::value_type, view::Diagonal< StructuredMatrixT >, storage::Dense, reference_dense, void > @@ -286,6 +328,31 @@ namespace grb { return smat_diag; } + /** + * Generate an identity view of a VectorView. + */ + template< typename T, typename View, typename StorageSchemeType, enum Backend backend > + VectorView< T, view::Identity< VectorView< T, View, StorageSchemeType, backend, void > >, StorageSchemeType, backend, void > + get_view( VectorView< T, View, StorageSchemeType, backend, void > &source ) { + + VectorView< T, view::Identity< VectorView< T, View, StorageSchemeType, backend, void > >, StorageSchemeType, backend, void > vec_view( source ); + + return vec_view; + } + + /** + * Implement a gather through a View over compatible Structure using provided Index Mapping Functions. + */ + + template< typename T, typename View, typename StorageSchemeType, enum Backend backend > + VectorView< T, view::Identity< VectorView< T, View, StorageSchemeType, backend, void > >, StorageSchemeType, backend, void > + get_view( VectorView< T, View, StorageSchemeType, backend, void > &source, std::shared_ptr< imf::IMF > imf ) { + + VectorView< T, view::Identity< VectorView< T, View, StorageSchemeType, backend, void > >, StorageSchemeType, backend, void > vec_view( source, imf ); + + return vec_view; + } + } // end namespace ``grb'' diff --git a/tests/unit/dense_structured_matrix.cpp b/tests/unit/dense_structured_matrix.cpp index ea9e06222..b9f53aac2 100644 --- a/tests/unit/dense_structured_matrix.cpp +++ b/tests/unit/dense_structured_matrix.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include @@ -48,7 +49,6 @@ void grb_program( const size_t & n, grb::RC & rc ) { grb::StructuredMatrix< float, grb::structures::FullRank > C( n, 2 * n ); auto At = grb::transpose( A ); auto Mt = grb::transpose( M ); - auto v_diag = grb::diagonal( M ); auto Mview = grb::get_view( M ); auto Sq_Mref = grb::get_view< grb::structures::Square > ( A ); @@ -62,7 +62,10 @@ void grb_program( const size_t & n, grb::RC & rc ) { ask_questions( Mt, "Mt" ); ask_questions( Mview, "Mview" ); + auto v_diag = grb::diagonal( M ); + auto v_view = grb::get_view( v_diag, std::make_shared< grb::imf::Strided >( 2, 5, 1, 1 ) ); std::cout << "v_diag( " << grb::getLength( v_diag ) << " )" << std::endl; + std::cout << "v_view( " << grb::getLength( v_view ) << " )" << std::endl; rc = grb::SUCCESS; } From 9f4391c4a53274a77cbf8043f529cad4c50c1f9e Mon Sep 17 00:00:00 2001 From: Anonymous Date: Mon, 21 Feb 2022 13:44:44 +0100 Subject: [PATCH 059/282] Add a stub for Storage Mapping Functions --- include/graphblas/smf.hpp | 56 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 include/graphblas/smf.hpp diff --git a/include/graphblas/smf.hpp b/include/graphblas/smf.hpp new file mode 100644 index 000000000..c028d10c6 --- /dev/null +++ b/include/graphblas/smf.hpp @@ -0,0 +1,56 @@ +/* + * Copyright 2021 Huawei Technologies Co., Ltd. + * + * 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. + */ + +/** + * + * @file + * + * This file registers available storage mapping functions (SMFs). + * SMFs are maps between logical and physical storage space. + * + */ + +#ifndef _H_GRB_SMF +#define _H_GRB_SMF + +#include + +namespace grb { + + namespace smf { + + class SMF { + public: + size_t n, N; + + SMF(size_t n, size_t N): n(n), N(N) {} + + /** Maps logical to physical coordinate + * */ + virtual size_t map(size_t i) = 0; + + /** Returns the physical dimension of the container needed to + * store all elements + * */ + virtual size_t allocSize() const = 0; + + }; + + }; // namespace smf + +} // namespace grb + +#endif // _H_GRB_SMF From f96264e3086d25c229037de1678089dfa97d4fb9 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Mon, 21 Feb 2022 15:10:26 +0100 Subject: [PATCH 060/282] Define interface for dense StructuredMatrices and scalars --- include/graphblas/denseref/blas3.hpp | 290 +++++++++++++++++++++++++++ 1 file changed, 290 insertions(+) diff --git a/include/graphblas/denseref/blas3.hpp b/include/graphblas/denseref/blas3.hpp index 1423917a9..4d4ed617b 100644 --- a/include/graphblas/denseref/blas3.hpp +++ b/include/graphblas/denseref/blas3.hpp @@ -30,6 +30,29 @@ #include "io.hpp" #include "matrix.hpp" +#define NO_CAST_ASSERT( x, y, z ) \ + static_assert( x, \ + "\n\n" \ + "********************************************************************" \ + "********************************************************************" \ + "******************************\n" \ + "* ERROR | " y " " z ".\n" \ + "********************************************************************" \ + "********************************************************************" \ + "******************************\n" \ + "* Possible fix 1 | Remove no_casting from the template parameters " \ + "in this call to " y ".\n" \ + "* Possible fix 2 | For all mismatches in the domains of input " \ + "parameters and the semiring domains, as specified in the " \ + "documentation of the function " y ", supply a container argument of " \ + "the expected type instead.\n" \ + "* Possible fix 3 | Provide a compatible semiring where all domains " \ + "match those of the container arguments, as specified in the " \ + "documentation of the function " y ".\n" \ + "********************************************************************" \ + "********************************************************************" \ + "******************************\n" ); + namespace grb { namespace internal { @@ -243,6 +266,273 @@ namespace grb { return internal::mxm_generic< true >( C, A, B, ring.getMultiplicativeOperator(), ring.getAdditiveMonoid(), ring.getMultiplicativeMonoid() ); } + namespace internal { + + /** + * \internal general elementwise matrix application that all eWiseApply variants refer to. + */ + + template< + bool allow_void, + bool left_scalar, bool right_scalar, + Descriptor descr, + class MulMonoid, + typename OutputType, typename InputType1, typename InputType2, + typename OutputStructure, typename InputStructure1, typename InputStructure2, + typename OutputStorage, typename InputStorage1, typename InputStorage2, + typename OutputView, typename InputView1, typename InputView2, + class Operator + > + RC eWiseApply_matrix_generic( StructuredMatrix< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > *C, + const StructuredMatrix< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense > *A, + const InputType1 *alpha, + const StructuredMatrix< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > *B, + const InputType1 *beta, + const Operator &oper, + const MulMonoid &mulMonoid, + const PHASE &phase, + const typename std::enable_if< + !grb::is_object< OutputType >::value && + !grb::is_object< InputType1 >::value && + !grb::is_object< InputType2 >::value && + grb::is_operator< Operator >::value, + void >::type * const = NULL + ) { + (void)C; + (void)A; + (void)alpha; + (void)B; + (void)beta; + (void)oper; + (void)mulMonoid; + static_assert( allow_void || + ( !( + std::is_same< InputType1, void >::value || + std::is_same< InputType2, void >::value + ) ), + "grb::internal::eWiseApply_matrix_generic: the non-monoid version of " + "elementwise mxm can only be used if neither of the input matrices " + "is a pattern matrix (of type void)" ); + +#ifdef _DEBUG + std::cout << "In grb::internal::eWiseApply_matrix_generic\n"; +#endif + + // get whether the matrices should be transposed prior to execution + // constexpr bool trans_left = descr & descriptors::transpose_left; + // constexpr bool trans_right = descr & descriptors::transpose_right; + + // run-time checks + // TODO: support left/right_scalar + // const size_t m = grb::nrows( *C ); + // const size_t n = grb::ncols( *C ); + // const size_t m_A = !trans_left ? grb::nrows( *A ) : grb::ncols( *A ); + // const size_t n_A = !trans_left ? grb::ncols( *A ) : grb::nrows( *A ); + // const size_t m_B = !trans_right ? grb::nrows( *B ) : grb::ncols( *B ); + // const size_t n_B = !trans_right ? grb::ncols( *B ) : grb::nrows( *B ); + + // if( m != m_A || m != m_B || n != n_A || n != n_B ) { + // return MISMATCH; + // } + + + // retrieve buffers + // end buffer retrieval + + // initialisations + // end initialisations + + // symbolic phase + if( phase == SYMBOLIC ) { + } + + // computational phase + if( phase == NUMERICAL ) { + } + + // done + return SUCCESS; + } + + } // namespace internal + + /** + * Computes \f$ C = A . B \f$ for a given monoid. + * + * \internal Allows pattern matrix inputs. + * + * \internal Dispatches to internal::eWiseApply_matrix_generic + */ + template< + Descriptor descr = descriptors::no_operation, + typename OutputType, typename InputType1, typename InputType2, + typename OutputStructure, typename InputStructure1, typename InputStructure2, + typename OutputStorage, typename InputStorage1, typename InputStorage2, + typename OutputView, typename InputView1, typename InputView2, + class MulMonoid + > + RC eWiseApply( StructuredMatrix< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > &C, + const StructuredMatrix< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense > &A, + const StructuredMatrix< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > &B, + const MulMonoid &mulmono, + const PHASE phase = NUMERICAL, + const typename std::enable_if< !grb::is_object< OutputType >::value && + !grb::is_object< InputType1 >::value && + !grb::is_object< InputType2 >::value && + grb::is_monoid< MulMonoid >::value, + void >::type * const = NULL + ) { + // static checks + NO_CAST_ASSERT( ( !( descr & descriptors::no_casting ) || + std::is_same< typename MulMonoid::D1, InputType1 >::value ), + "grb::eWiseApply (reference, matrix <- matrix x matrix, monoid)", + "called with a prefactor input matrix A that does not match the first " + "domain of the monoid operator" + ); + NO_CAST_ASSERT( ( !( descr & descriptors::no_casting ) || + std::is_same< typename MulMonoid::D2, InputType2 >::value ), + "grb::eWiseApply (reference, matrix <- matrix x matrix, monoid)", + "called with a postfactor input matrix B that does not match the " + "second domain of the monoid operator" + ); + NO_CAST_ASSERT( ( !( descr & descriptors::no_casting ) || + std::is_same< typename MulMonoid::D3, OutputType >::value ), + "grb::eWiseApply (reference, matrix <- matrix x matrix, monoid)", + "called with an output matrix C that does not match the output domain " + "of the monoid operator" + ); + +#ifdef _DEBUG + std::cout << "In grb::eWiseApply_matrix_generic (reference, monoid)\n"; +#endif + + return internal::eWiseApply_matrix_generic< true, false, false, descr >( + &C, &A, static_cast< const InputType1 * >( nullptr ), &B, static_cast< const InputType2 * >( nullptr ), mulmono.getOperator(), mulmono, phase + ); + } + + /** + * Computes \f$ C = alpha . B \f$ for a given monoid. + * + * \internal Allows pattern matrix inputs. + * + * \internal Dispatches to internal::eWiseApply_matrix_generic + */ + template< + Descriptor descr = descriptors::no_operation, + typename OutputType, typename InputType1, typename InputType2, + typename OutputStructure, typename InputStructure2, + typename OutputStorage, typename InputStorage2, + typename OutputView, typename InputView2, + class MulMonoid + > + RC eWiseApply( StructuredMatrix< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > &C, + const InputType1 &alpha, + const StructuredMatrix< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > &B, + const MulMonoid &mulmono, + const PHASE phase = NUMERICAL, + const typename std::enable_if< !grb::is_object< OutputType >::value && + !grb::is_object< InputType1 >::value && + !grb::is_object< InputType2 >::value && + grb::is_monoid< MulMonoid >::value, + void >::type * const = NULL + ) { + // static checks + NO_CAST_ASSERT( ( !( descr & descriptors::no_casting ) || + std::is_same< typename MulMonoid::D1, InputType1 >::value ), + "grb::eWiseApply (reference, matrix <- matrix x matrix, monoid)", + "called with a prefactor input matrix A that does not match the first " + "domain of the monoid operator" + ); + NO_CAST_ASSERT( ( !( descr & descriptors::no_casting ) || + std::is_same< typename MulMonoid::D2, InputType2 >::value ), + "grb::eWiseApply (reference, matrix <- matrix x matrix, monoid)", + "called with a postfactor input matrix B that does not match the " + "second domain of the monoid operator" + ); + NO_CAST_ASSERT( ( !( descr & descriptors::no_casting ) || + std::is_same< typename MulMonoid::D3, OutputType >::value ), + "grb::eWiseApply (reference, matrix <- matrix x matrix, monoid)", + "called with an output matrix C that does not match the output domain " + "of the monoid operator" + ); + +#ifdef _DEBUG + std::cout << "In grb::eWiseApply_matrix_generic (reference_dense, monoid)\n"; +#endif + + const StructuredMatrix< InputType1, structures::General, storage::Dense, view::Identity< void >, reference_dense> * no_matrix = nullptr; + return internal::eWiseApply_matrix_generic< true, true, false, descr >( + &C, + no_matrix, + &alpha, + &B, + static_cast< const InputType2 * >( nullptr ), + mulmono.getOperator(), mulmono, phase + ); + } + +/** + * Computes \f$ C = A . beta \f$ for a given monoid. + * + * \internal Allows pattern matrix inputs. + * + * \internal Dispatches to internal::eWiseApply_matrix_generic + */ + template< + Descriptor descr = descriptors::no_operation, + typename OutputType, typename InputType1, typename InputType2, + typename OutputStructure, typename InputStructure1, + typename OutputStorage, typename InputStorage1, + typename OutputView, typename InputView1, + class MulMonoid + > + RC eWiseApply( StructuredMatrix< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > &C, + const StructuredMatrix< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense > &A, + const InputType2 &beta, + const MulMonoid &mulmono, + const PHASE phase = NUMERICAL, + const typename std::enable_if< !grb::is_object< OutputType >::value && + !grb::is_object< InputType1 >::value && + !grb::is_object< InputType2 >::value && + grb::is_monoid< MulMonoid >::value, + void >::type * const = NULL + ) { + // static checks + NO_CAST_ASSERT( ( !( descr & descriptors::no_casting ) || + std::is_same< typename MulMonoid::D1, InputType1 >::value ), + "grb::eWiseApply (reference, matrix <- matrix x matrix, monoid)", + "called with a prefactor input matrix A that does not match the first " + "domain of the monoid operator" + ); + NO_CAST_ASSERT( ( !( descr & descriptors::no_casting ) || + std::is_same< typename MulMonoid::D2, InputType2 >::value ), + "grb::eWiseApply (reference, matrix <- matrix x matrix, monoid)", + "called with a postfactor input matrix B that does not match the " + "second domain of the monoid operator" + ); + NO_CAST_ASSERT( ( !( descr & descriptors::no_casting ) || + std::is_same< typename MulMonoid::D3, OutputType >::value ), + "grb::eWiseApply (reference, matrix <- matrix x matrix, monoid)", + "called with an output matrix C that does not match the output domain " + "of the monoid operator" + ); + +#ifdef _DEBUG + std::cout << "In grb::eWiseApply_matrix_generic (reference_dense, monoid)\n"; +#endif + + const StructuredMatrix< InputType2, structures::General, storage::Dense, view::Identity< void >, reference_dense> * no_matrix = nullptr; + return internal::eWiseApply_matrix_generic< true, false, true, descr >( + &C, + &A, + static_cast< const InputType1 * >( nullptr ), + no_matrix, + &beta, + mulmono.getOperator(), mulmono, phase + ); + } + } // end namespace ``grb'' #endif // end ``_H_GRB_DENSEREF_BLAS3'' From 36dc650a667c031a3f6317be89ebca6bbdb9f2f0 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Mon, 21 Feb 2022 16:26:28 +0100 Subject: [PATCH 061/282] Add test showcasing eWiseApply operations on Structured Matrices --- tests/unit/CMakeLists.txt | 5 + tests/unit/dense_matrix_eWiseApply.cpp | 129 +++++++++++++++++++++++++ 2 files changed, 134 insertions(+) create mode 100644 tests/unit/dense_matrix_eWiseApply.cpp diff --git a/tests/unit/CMakeLists.txt b/tests/unit/CMakeLists.txt index c0a0fecc7..483d25ced 100644 --- a/tests/unit/CMakeLists.txt +++ b/tests/unit/CMakeLists.txt @@ -207,6 +207,11 @@ add_grb_executables( spy spy.cpp add_grb_executables( dense_matrix_imf dense_matrix_imf.cpp BACKENDS reference_dense ) + +add_grb_executables( dense_matrix_eWiseApply dense_matrix_eWiseApply.cpp + BACKENDS reference_dense +) + add_grb_executables( dense_matrix_allocation_size dense_matrix_allocation_size.cpp BACKENDS reference_dense ) diff --git a/tests/unit/dense_matrix_eWiseApply.cpp b/tests/unit/dense_matrix_eWiseApply.cpp new file mode 100644 index 000000000..85832dc41 --- /dev/null +++ b/tests/unit/dense_matrix_eWiseApply.cpp @@ -0,0 +1,129 @@ + +/* + * Copyright 2021 Huawei Technologies Co., Ltd. + * + * 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. + */ + +#include +#include +#include + +#include + +using namespace grb; + +template< typename Structure > +void print_matrix( const grb::StructuredMatrix< double, Structure > & A) { + (void)A; + // if( ! grb::internal::getInitialized< double >( A ) ) { + // std::cout << "Matrix is uninitialized, nothing to print.\n"; + // return; + // } + // const double * Araw = grb::getRaw( internal::getContainer( A ) ); + // for( size_t row = 0; row < grb::nrows( A ); ++row ) { + // for( size_t col = 0; col < grb::ncols( A ); ++col ) { + // std::cout << Araw[row * grb::ncols( A ) + col] << " "; + // } + // std::cout << "\n"; + // } +} + +void grb_program( const size_t & n, grb::RC & rc ) { + grb::Semiring< grb::operators::add< double >, grb::operators::mul< double >, grb::identities::zero, grb::identities::one > ring; + + std::cout << "\tTesting dense mxm\n"; + // initialize test + grb::StructuredMatrix< double, structures::General > A( n, n ); + grb::StructuredMatrix< double, structures::General > B( n, n ); + grb::StructuredMatrix< double, structures::General > C( n, n ); + std::vector< double > A_data( n * n, 1 ); + std::vector< double > B_data( n * n, 2 ); + + double alpha = 10; + double beta = 20; + + // Initialize input matrices + rc = grb::buildMatrix( A, A_data.begin(), A_data.end() ); + if( rc == SUCCESS ) { + rc = grb::buildMatrix( B, B_data.begin(), B_data.end() ); + } + + + std::cout << "Output matrix nrows = " << nrows( C ) << ", ncols = " << ncols( C ) << "\n"; + + // C = A + B + if( rc == SUCCESS ) { + rc = grb::eWiseApply( C, A, B, ring.getAdditiveMonoid()); + } + + // C = alpha . B + if ( rc == SUCCESS ) { + rc = grb::eWiseApply( C, alpha, B, ring.getMultiplicativeMonoid()); + } + + // C = A . beta + if( rc == SUCCESS ) { + rc = grb::eWiseApply( C, A, beta, ring.getMultiplicativeMonoid()); + } + +} + +int main( int argc, char ** argv ) { + // defaults + bool printUsage = false; + size_t in = 100; + + // error checking + if( argc > 2 ) { + printUsage = true; + } + if( argc == 2 ) { + size_t read; + std::istringstream ss( argv[ 1 ] ); + if( ! ( ss >> read ) ) { + std::cerr << "Error parsing first argument\n"; + printUsage = true; + } else if( ! ss.eof() ) { + std::cerr << "Error parsing first argument\n"; + printUsage = true; + } else if( read % 2 != 0 ) { + std::cerr << "Given value for n is odd\n"; + printUsage = true; + } else { + // all OK + in = read; + } + } + if( printUsage ) { + std::cerr << "Usage: " << argv[ 0 ] << " [n]\n"; + std::cerr << " -n (optional, default is 100): an even integer, the " + "test size.\n"; + return 1; + } + + std::cout << "This is functional test " << argv[ 0 ] << "\n"; + grb::Launcher< AUTOMATIC > launcher; + grb::RC out; + if( launcher.exec( &grb_program, in, out, true ) != SUCCESS ) { + std::cerr << "Launching test FAILED\n"; + return 255; + } + if( out != SUCCESS ) { + std::cerr << "Test FAILED (" << grb::toString( out ) << ")" << std::endl; + } else { + std::cout << "Test OK" << std::endl; + } + return 0; +} + From a6915abb0aba9ea1ee4811739c8c244d0e38c8f7 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Tue, 22 Feb 2022 17:38:28 +0100 Subject: [PATCH 062/282] Minor changes for dense reference vector --- include/graphblas/denseref/vector.hpp | 9 ++++++++- include/graphblas/vector.hpp | 3 ++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/include/graphblas/denseref/vector.hpp b/include/graphblas/denseref/vector.hpp index fc0439f3b..34e698c69 100644 --- a/include/graphblas/denseref/vector.hpp +++ b/include/graphblas/denseref/vector.hpp @@ -52,7 +52,7 @@ namespace grb { T * getRaw( Vector< T, reference_dense, void > & ) noexcept; template< typename T > - const T * getRaw( Vector< T, reference_dense, void > & ) noexcept; + const T * getRaw( const Vector< T, reference_dense, void > & ) noexcept; template< typename T > size_t getLength( const Vector< T, reference_dense, void > & ) noexcept; @@ -239,6 +239,13 @@ namespace grb { }; // class VectorView with physical container + /** Identifies any reference_dense vector as an ALP vector. */ + template< typename T, typename View, typename Storage > + struct is_container< VectorView< T, View, Storage, reference_dense, void > > { + /** A reference_vector is an ALP object. */ + static const constexpr bool value = true; + }; + /** * Vector view of a vector only via \a view::Identity of another VectorView. */ diff --git a/include/graphblas/vector.hpp b/include/graphblas/vector.hpp index 53c72097d..d74a6425a 100644 --- a/include/graphblas/vector.hpp +++ b/include/graphblas/vector.hpp @@ -57,7 +57,8 @@ namespace grb { /* * The default value of \a StorageSchemeType could also be made conditional (Dense or Sparse) depending on \a config::default_backend */ - template< typename T, typename View = view::Identity< void >, typename StorageSchemeType = storage::Dense, enum Backend backend = config::default_backend, typename C = internal::DefaultCoordinates > + // template< typename T, typename View = view::Identity< void >, typename StorageSchemeType = storage::Dense, enum Backend backend = config::default_backend, typename C = internal::DefaultCoordinates > + template< typename T, typename View = view::Identity< void >, typename StorageSchemeType = storage::Dense, enum Backend backend = config::default_backend, typename C = void > class VectorView; } From 5050789e05e886d8af222ce3ab999230fec2b410 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Mon, 21 Feb 2022 17:56:54 +0100 Subject: [PATCH 063/282] Add outer product of two vectors for reference_dense backend --- include/graphblas/denseref/blas3.hpp | 82 ++++++++++++++++++++ tests/unit/CMakeLists.txt | 4 + tests/unit/dense_outer.cpp | 112 +++++++++++++++++++++++++++ 3 files changed, 198 insertions(+) create mode 100644 tests/unit/dense_outer.cpp diff --git a/include/graphblas/denseref/blas3.hpp b/include/graphblas/denseref/blas3.hpp index 4d4ed617b..72079c885 100644 --- a/include/graphblas/denseref/blas3.hpp +++ b/include/graphblas/denseref/blas3.hpp @@ -266,6 +266,26 @@ namespace grb { return internal::mxm_generic< true >( C, A, B, ring.getMultiplicativeOperator(), ring.getAdditiveMonoid(), ring.getMultiplicativeMonoid() ); } + /** + * \internal mxm implementation with additive monoid and multiplicative operator + * Dispatches to internal::mxm_generic + */ + template< typename OutputType, typename InputType1, typename InputType2, class Operator, class Monoid, + typename OutputStructure, typename OutputView = view::Identity< void >, + typename InputStructure1, typename InputView1 = view::Identity< void >, + typename InputStructure2, typename InputView2 = view::Identity< void > > + RC mxm( StructuredMatrix< OutputType, OutputStructure, storage::Dense, OutputView, reference_dense > & C, + const StructuredMatrix< InputType1, InputStructure1, storage::Dense, InputView1, reference_dense > & A, + const StructuredMatrix< InputType2, InputStructure2, storage::Dense, InputView2, reference_dense > & B, + const Operator & mulOp, + const Monoid & addM, + const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && + grb::is_operator< Operator >::value && grb::is_monoid< Monoid >::value, + void >::type * const = NULL ) { + // TODO: How should we handle multiplication of combinations of Structures and Storage schemes? + return internal::mxm_generic< true >( C, A, B, mulOp, addM, Monoid() ); + } + namespace internal { /** @@ -533,6 +553,68 @@ namespace grb { ); } + /** + * Outer product of two vectors. Assuming vectors \a u and \a v are oriented + * column-wise, the result matrix \a A will contain \f$ uv^T \f$. + * + * \internal Implemented via mxm as a multiplication of a column vector with + * a row vector. + */ + template< Descriptor descr = descriptors::no_operation, + typename InputType1, typename InputType2, typename OutputType, + typename OutputStructure, + typename OutputStorage, typename InputStorage1, typename InputStorage2, + typename OutputView, typename InputView1, typename InputView2, + typename InputCoords1, typename InputCoords2, class Operator > + RC outer( StructuredMatrix< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > & A, + const VectorView< InputType1, InputView1, InputStorage1, reference_dense, InputCoords1 > & u, + const VectorView< InputType2, InputView2, InputStorage2, reference_dense, InputCoords2 > & v, + const Operator & mul = Operator(), + const PHASE & phase = NUMERICAL, + const typename std::enable_if< grb::is_operator< Operator >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< OutputType >::value, + void >::type * const = NULL ) { + // static checks + NO_CAST_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Operator::D1, InputType1 >::value ), "grb::outerProduct", + "called with a prefactor vector that does not match the first domain " + "of the given multiplication operator" ); + NO_CAST_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Operator::D2, InputType2 >::value ), "grb::outerProduct", + "called with a postfactor vector that does not match the first domain " + "of the given multiplication operator" ); + NO_CAST_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Operator::D3, OutputType >::value ), "grb::outerProduct", + "called with an output matrix that does not match the output domain of " + "the given multiplication operator" ); + + const size_t nrows = getLength( u ); + const size_t ncols = getLength( v ); + + if( nrows != grb::nrows( A ) ) { + return MISMATCH; + } + + if( ncols != grb::ncols( A ) ) { + return MISMATCH; + } + + grb::StructuredMatrix< InputType1, structures::General, storage::Dense, view::Identity< void >, reference_dense > u_matrix( nrows, 1 ); + grb::StructuredMatrix< InputType2, structures::General, storage::Dense, view::Identity< void >, reference_dense > v_matrix( 1, ncols ); + + // auto u_converter = grb::utils::makeVectorToMatrixConverter< InputType1 >( u, []( const size_t & ind, const InputType1 & val ) { + // return std::make_pair( std::make_pair( ind, 0 ), val ); + // } ); + + // grb::buildMatrixUnique( u_matrix, u_converter.begin(), u_converter.end(), PARALLEL ); + + // auto v_converter = grb::utils::makeVectorToMatrixConverter< InputType2 >( v, []( const size_t & ind, const InputType2 & val ) { + // return std::make_pair( std::make_pair( 0, ind ), val ); + // } ); + // grb::buildMatrixUnique( v_matrix, v_converter.begin(), v_converter.end(), PARALLEL ); + + grb::Monoid< grb::operators::left_assign< OutputType >, grb::identities::zero > mono; + + (void)phase; + return grb::mxm( A, u_matrix, v_matrix, mul, mono ); + } + } // end namespace ``grb'' #endif // end ``_H_GRB_DENSEREF_BLAS3'' diff --git a/tests/unit/CMakeLists.txt b/tests/unit/CMakeLists.txt index 483d25ced..4684c9234 100644 --- a/tests/unit/CMakeLists.txt +++ b/tests/unit/CMakeLists.txt @@ -220,6 +220,10 @@ add_grb_executables( dense_mxm dense_mxm.cpp BACKENDS reference_dense ) +add_grb_executables( dense_outer dense_outer.cpp + BACKENDS reference_dense +) + add_grb_executables( dense_structured_matrix dense_structured_matrix.cpp BACKENDS reference_dense ) diff --git a/tests/unit/dense_outer.cpp b/tests/unit/dense_outer.cpp new file mode 100644 index 000000000..193243961 --- /dev/null +++ b/tests/unit/dense_outer.cpp @@ -0,0 +1,112 @@ + +/* + * Copyright 2021 Huawei Technologies Co., Ltd. + * + * 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. + */ + +#include +#include + +#include "graphblas.hpp" + + +using namespace grb; + +// sample data +static const double vec1_vals[ 3 ] = { 1, 2, 3 }; +static const double vec2_vals[ 3 ] = { 4, 5, 6 }; + +static const size_t I[ 3 ] = { 0, 1, 2 }; + +static const double test1_in[ 3 ] = { 1, 1, 1 }; +static const double test1_expect[ 3 ] = { 24, 30, 36 }; + +static const double test2_in[ 3 ] = { 1, 1, 1 }; +static const double test2_expect[ 3 ] = { 15, 30, 45 }; + +// graphblas program +void grbProgram( const void *, const size_t in_size, int &error ) { + /** \internal TODO: Implement initialization and result checking. + * Currently only serves as the interface showcase. + * */ + error = 0; + + if( in_size != 0 ) { + (void)fprintf( stderr, "Unit tests called with unexpected input\n" ); + error = 1; + return; + } + + // allocate + grb::VectorView< double > u( 3 ); + grb::VectorView< double > v( 3 ); + grb::StructuredMatrix< double, structures::General > M( 3, 3 ); + // grb::Vector< double > test1( 3 ); + // grb::Vector< double > out1( 3 ); + // grb::Vector< double > test2( 3 ); + // grb::Vector< double > out2( 3 ); + + // semiring + grb::Semiring< + grb::operators::add< double >, grb::operators::mul< double >, + grb::identities::zero, grb::identities::one + > ring; + + grb::RC rc; + + // initialise vec + // const double * vec_iter = &(vec1_vals[ 0 ]); + // grb::RC rc = grb::buildVector( u, vec_iter, vec_iter + 3, SEQUENTIAL ); + // if( rc != SUCCESS ) { + // std::cerr << "\t initial buildVector FAILED\n"; + // error = 5; + // } + + // if( !error ) { + // vec_iter = &(vec2_vals[ 0 ]); + // rc = grb::buildVector( v, vec_iter, vec_iter + 3, SEQUENTIAL ); + // } + // if( rc != SUCCESS ) { + // std::cerr << "\t initial buildVector FAILED\n"; + // error = 10; + // } + + if( !error ) { + rc = grb::outer( M, u, v, ring.getMultiplicativeOperator(), SYMBOLIC ); + rc = rc ? rc : grb::outer( M, u, v, ring.getMultiplicativeOperator() ); + } + +} + +int main( int argc, char ** argv ) { + (void)argc; + std::cout << "Functional test executable: " << argv[ 0 ] << "\n"; + + int error; + grb::Launcher< AUTOMATIC > launcher; + if( launcher.exec( &grbProgram, NULL, 0, error ) != SUCCESS ) { + std::cerr << "Test failed to launch\n"; + error = 255; + } + if( error == 0 ) { + std::cout << "Test OK\n" << std::endl; + } else { + std::cerr << std::flush; + std::cout << "Test FAILED\n" << std::endl; + } + + // done + return error; +} + From f01d38fe1c9ba31d68353b72942858e6dc09a98a Mon Sep 17 00:00:00 2001 From: Anonymous Date: Mon, 21 Feb 2022 17:57:30 +0100 Subject: [PATCH 064/282] Expand the gather via IMF to general view of general Storage Matrix --- include/graphblas/structures.hpp | 8 ++++++++ tests/unit/dense_matrix_imf.cpp | 15 +++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/include/graphblas/structures.hpp b/include/graphblas/structures.hpp index 9f5ad4e00..7659dd66d 100644 --- a/include/graphblas/structures.hpp +++ b/include/graphblas/structures.hpp @@ -111,6 +111,14 @@ namespace grb { (void)M; return imf_l.map( 0 ) <= imf_r.map( imf_r.N ); } + + template< typename T, typename Storage, typename View, enum Backend backend > + static bool isInstantiableFrom( const StructuredMatrix< T, General, Storage, View, backend > & M, grb::imf::IMF & imf_l, grb::imf::IMF & imf_r ) { + (void)M; + (void)imf_l; + (void)imf_r; + return true; + } }; struct Square { diff --git a/tests/unit/dense_matrix_imf.cpp b/tests/unit/dense_matrix_imf.cpp index c763341ad..b67a95f19 100644 --- a/tests/unit/dense_matrix_imf.cpp +++ b/tests/unit/dense_matrix_imf.cpp @@ -37,6 +37,21 @@ void buildUpperTriangularRawArray( std::vector< double > & v, int n ) { void grb_program( const size_t & n, grb::RC & rc ) { // initialize test + // using General Views over General Structured Matrix + grb::StructuredMatrix< double, grb::structures::General > A( n, n ); + std::cout << "General gather from a general StructuredMatrix (expect success)\n"; + try { + auto Aview = grb::get_view< grb::structures::General >( + A, + std::make_shared< grb::imf::Strided >( n, 2, 1, 1 ), + std::make_shared< grb::imf::Strided >( n, 4, 1, 1 ) + ); + std::cout << "\tSUCCESS\n"; + } catch( const std::exception & e ) { + std::cerr << e.what() << "\n"; + } + + // using Upper Triangular Structured Matrix grb::StructuredMatrix< double, grb::structures::UpperTriangular > U( n, n ); From a64a305c1a5c7b267328f8f07862be8c0f5c5b8a Mon Sep 17 00:00:00 2001 From: Anonymous Date: Tue, 22 Feb 2022 18:12:29 +0100 Subject: [PATCH 065/282] Add more Structures for StructuredMatrix --- include/graphblas/structures.hpp | 48 +++++++++++++++++++++++++++++--- 1 file changed, 44 insertions(+), 4 deletions(-) diff --git a/include/graphblas/structures.hpp b/include/graphblas/structures.hpp index 7659dd66d..79105a84e 100644 --- a/include/graphblas/structures.hpp +++ b/include/graphblas/structures.hpp @@ -150,10 +150,6 @@ namespace grb { } }; - struct Diagonal { - using inferred_structures = structures::tuple_cat< std::tuple< Diagonal >, LowerTriangular::inferred_structures, UpperTriangular::inferred_structures >::type; - }; - struct FullRank { using inferred_structures = structures::tuple_cat< std::tuple< FullRank >, General::inferred_structures >::type; }; @@ -162,6 +158,50 @@ namespace grb { using inferred_structures = structures::tuple_cat< std::tuple< NonSingular >, Square::inferred_structures, FullRank::inferred_structures >::type; }; + struct OrthogonalColumns { + using inferred_structures = structures::tuple_cat< std::tuple< OrthogonalColumns >, FullRank::inferred_structures >::type; + }; + + struct OrthogonalRows { + using inferred_structures = structures::tuple_cat< std::tuple< OrthogonalRows >, FullRank::inferred_structures >::type; + }; + + struct Orthogonal { + using inferred_structures = structures::tuple_cat< std::tuple< Orthogonal >, NonSingular::inferred_structures, OrthogonalColumns::inferred_structures, OrthogonalRows::inferred_structures >::type; + }; + + struct Tridiagonal { + using inferred_structures = structures::tuple_cat< std::tuple< Tridiagonal >, General::inferred_structures >::type; + }; + + struct Bidiagonal { + using inferred_structures = structures::tuple_cat< std::tuple< Bidiagonal >, Tridiagonal::inferred_structures >::type; + }; + + struct LowerBidiagonal { + using inferred_structures = structures::tuple_cat< std::tuple< LowerBidiagonal >, Bidiagonal::inferred_structures >::type; + }; + + struct UpperBidiagonal { + using inferred_structures = structures::tuple_cat< std::tuple< UpperBidiagonal >, Bidiagonal::inferred_structures >::type; + }; + + struct Diagonal { + using inferred_structures = structures::tuple_cat< std::tuple< Diagonal >, LowerTriangular::inferred_structures, UpperTriangular::inferred_structures, LowerBidiagonal::inferred_structures, UpperBidiagonal::inferred_structures >::type; + }; + + struct Constant { + using inferred_structures = structures::tuple_cat< std::tuple< Constant >, General::inferred_structures >::type; + }; + + struct Identity { + using inferred_structures = structures::tuple_cat< std::tuple< Identity >, FullRank::inferred_structures, Diagonal::inferred_structures, Constant::inferred_structures >::type; + }; + + struct Zero { + using inferred_structures = structures::tuple_cat< std::tuple< Zero >, Constant::inferred_structures >::type; + }; + } // namespace structures } // namespace grb From 0183d1f6fa193e27e0c24208f04df81585894df0 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Wed, 23 Feb 2022 14:57:45 +0100 Subject: [PATCH 066/282] Add dot product and norm2 in blas1 for dense reference backend Also add a stub for a test showcasing their use --- include/graphblas/blas1.hpp | 2 +- include/graphblas/denseref/blas1.hpp | 247 +++++++++++++++++++++++++++ tests/unit/CMakeLists.txt | 4 + tests/unit/dense_dot_norm2.cpp | 193 +++++++++++++++++++++ 4 files changed, 445 insertions(+), 1 deletion(-) create mode 100644 tests/unit/dense_dot_norm2.cpp diff --git a/include/graphblas/blas1.hpp b/include/graphblas/blas1.hpp index 87a4797e3..adaa213a9 100644 --- a/include/graphblas/blas1.hpp +++ b/include/graphblas/blas1.hpp @@ -28,7 +28,7 @@ #ifdef _GRB_WITH_REFERENCE #include #endif -#ifdef _GRB_WITH_DENSE +#ifdef _GRB_WITH_DENSEREF #include #endif #ifdef _GRB_WITH_BANSHEE diff --git a/include/graphblas/denseref/blas1.hpp b/include/graphblas/denseref/blas1.hpp index 669b2e73f..0641b0ba5 100644 --- a/include/graphblas/denseref/blas1.hpp +++ b/include/graphblas/denseref/blas1.hpp @@ -23,8 +23,255 @@ #ifndef _H_GRB_DENSEREF_BLAS1 #define _H_GRB_DENSEREF_BLAS1 +#include +#include +#include + namespace grb { + /** + * Calculates the dot product, \f$ \alpha = (x,y) \f$, under a given additive + * monoid and multiplicative operator. + * + * @tparam descr The descriptor to be used (descriptors::no_operation + * if left unspecified). + * @tparam Ring The semiring type to use. + * @tparam OutputType The output type. + * @tparam InputType1 The input element type of the left-hand input vector. + * @tparam InputType2 The input element type of the right-hand input vector. + * + * @param[in,out] z The output element \f$ z + \alpha \f$. + * @param[in] x The left-hand input vector. + * @param[in] y The right-hand input vector. + * @param[in] addMonoid The additive monoid under which the reduction of the + * results of element-wise multiplications of \a x and + * \a y are performed. + * @param[in] anyop The multiplicative operator under which element-wise + * multiplications of \a x and \a y are performed. This can + * be any binary operator. + * + * By the definition that a dot-product operates under any additive monoid and + * any binary operator, it follows that a dot-product under any semiring can be + * trivially reduced to a call to this version instead. + * + * @return grb::MISMATCH When the dimensions of \a x and \a y do not match. All + * input data containers are left untouched if this exit + * code is returned; it will be as though this call was + * never made. + * @return grb::SUCCESS On successful completion of this call. + * + * \parblock + * \par Performance semantics + * -# This call takes \f$ \Theta(n/p) \f$ work at each user process, where + * \f$ n \f$ equals the size of the vectors \a x and \a y, and + * \f$ p \f$ is the number of user processes. The constant factor + * depends on the cost of evaluating the addition and multiplication + * operators. A good implementation uses vectorised instructions + * whenever the input domains, output domain, and the operators used + * allow for this. + * + * -# This call takes \f$ \mathcal{O}(1) \f$ memory beyond the memory used + * by the application at the point of a call to this function. + * + * -# This call incurs at most + * \f$ n( \mathit{sizeof}(\mathit{D1}) + \mathit{sizeof}(\mathit{D2}) ) + \mathcal{O}(p) \f$ + * bytes of data movement. + * + * -# This call incurs at most \f$ \Theta(\log p) \f$ synchronisations + * between two or more user processes. + * + * -# A call to this function does result in any system calls. + * \endparblock + * + * \note This requires an implementation to pre-allocate \f$ \Theta(p) \f$ + * memory for inter-process reduction, if the underlying communication + * layer indeed requires such a buffer. This buffer may not be allocated + * (nor freed) during a call to this function. + * + * \parblock + * \par Valid descriptors + * -# grb::descriptors::no_operation + * -# grb::descriptors::no_casting + * -# grb::descriptors::dense + * \endparblock + * + * If the dense descriptor is set, this implementation returns grb::ILLEGAL if + * it was detected that either \a x or \a y was sparse. In this case, it shall + * otherwise be as though the call to this function had not occurred (no side + * effects). + * + * \note The standard, in contrast, only specifies undefined behaviour would + * occur. This implementation goes beyond the standard by actually + * specifying what will happen. + */ + template< + Descriptor descr = descriptors::no_operation, + class AddMonoid, class AnyOp, + typename OutputType, typename InputType1, typename InputType2, + typename InputView1, typename InputView2, + typename InputStorage1, typename InputStorage2, + typename InputCoords1, typename InputCoords2 + > + RC dot( OutputType &z, + const VectorView< InputType1, InputView1, InputStorage1, reference_dense, InputCoords1 > &x, + const VectorView< InputType2, InputView2, InputStorage2, reference_dense, InputCoords2 > &y, + const AddMonoid &addMonoid = AddMonoid(), + const AnyOp &anyOp = AnyOp(), + const typename std::enable_if< !grb::is_object< OutputType >::value && + !grb::is_object< InputType1 >::value && + !grb::is_object< InputType2 >::value && + grb::is_monoid< AddMonoid >::value && + grb::is_operator< AnyOp >::value, + void >::type * const = NULL + ) { + (void)z; + (void)x; + (void)y; + (void)addMonoid; + (void)anyOp; + // static sanity checks + // NO_CAST_ASSERT( ( !( descr & descriptors::no_casting ) || std::is_same< InputType1, typename AnyOp::D1 >::value ), "grb::dot", + // "called with a left-hand vector value type that does not match the first " + // "domain of the given multiplicative operator" ); + // NO_CAST_ASSERT( ( !( descr & descriptors::no_casting ) || std::is_same< InputType2, typename AnyOp::D2 >::value ), "grb::dot", + // "called with a right-hand vector value type that does not match the second " + // "domain of the given multiplicative operator" ); + // NO_CAST_ASSERT( ( !( descr & descriptors::no_casting ) || std::is_same< typename AddMonoid::D3, typename AnyOp::D1 >::value ), "grb::dot", + // "called with a multiplicative operator output domain that does not match " + // "the first domain of the given additive operator" ); + // NO_CAST_ASSERT( ( !( descr & descriptors::no_casting ) || std::is_same< OutputType, typename AddMonoid::D2 >::value ), "grb::dot", + // "called with an output vector value type that does not match the second " + // "domain of the given additive operator" ); + // NO_CAST_ASSERT( ( !( descr & descriptors::no_casting ) || std::is_same< typename AddMonoid::D3, typename AddMonoid::D2 >::value ), "grb::dot", + // "called with an additive operator whose output domain does not match its " + // "second input domain" ); + // NO_CAST_ASSERT( ( !( descr & descriptors::no_casting ) || std::is_same< OutputType, typename AddMonoid::D3 >::value ), "grb::dot", + // "called with an output vector value type that does not match the third " + // "domain of the given additive operator" ); + + // dynamic sanity check + // const size_t n = internal::getCoordinates( y ).size(); + // if( internal::getCoordinates( x ).size() != n ) { + // return MISMATCH; + // } + + // // cache nnzs + // const size_t nnzx = internal::getCoordinates( x ).nonzeroes(); + // const size_t nnzy = internal::getCoordinates( y ).nonzeroes(); + + // // catch trivial case + // if( nnzx == 0 && nnzy == 0 ) { + // return SUCCESS; + // } + + // // dot will be computed out-of-place here. A separate field is needed because + // // of possible multi-threaded computation of the dot. + // OutputType oop = addMonoid.template getIdentity< OutputType >(); + + // if descriptor says nothing about being dense... + RC ret = SUCCESS; + // if( !( descr & descriptors::dense ) ) { + // // check if inputs are actually dense... + // if( nnzx == n && nnzy == n ) { + // // call dense implementation + // ret = internal::dot_generic< descr | descriptors::dense >( oop, x, y, addMonoid, anyOp ); + // } else { + // // pass to sparse implementation + // ret = internal::dot_generic< descr >( oop, x, y, addMonoid, anyOp ); + // } + // } else { + // // descriptor says dense, but if any of the vectors are actually sparse... + // if( nnzx < n || nnzy < n ) { + // return ILLEGAL; + // } else { + // // all OK, pass to dense implementation + // ret = internal::dot_generic< descr >( oop, x, y, addMonoid, anyOp ); + // } + // } + + // fold out-of-place dot product into existing input, and exit + // ret = ret ? ret : foldl( z, oop, addMonoid.getOperator() ); + return ret; + } + + /** + * Provides a generic implementation of the dot computation on semirings by + * translating it into a dot computation on an additive commutative monoid + * with any multiplicative operator. + * + * For return codes, exception behaviour, performance semantics, template + * and non-template arguments, @see grb::dot. + */ + template< + Descriptor descr = descriptors::no_operation, class Ring, + typename IOType, typename InputType1, typename InputType2, + typename InputView1, typename InputView2, + typename InputStorage1, typename InputStorage2, + Backend backend, typename Coords1, typename Coords2 + > + RC dot( IOType &x, + const VectorView< InputType1, InputView1, InputStorage1, backend, Coords1 > &left, + const VectorView< InputType2, InputView2, InputStorage2, backend, Coords2 > &right, + const Ring &ring = Ring(), + const typename std::enable_if< + !grb::is_object< InputType1 >::value && + !grb::is_object< InputType2 >::value && + !grb::is_object< IOType >::value && + grb::is_semiring< Ring >::value, + void >::type * const = NULL + ) { + // return grb::dot< descr >( x, + return grb::dot( x, + left, right, + ring.getAdditiveMonoid(), + ring.getMultiplicativeOperator() + ); + } + + /** + * Provides a generic implementation of the 2-norm computation. + * + * Proceeds by computing a dot-product on itself and then taking the square + * root of the result. + * + * This function is only available when the output type is floating point. + * + * For return codes, exception behaviour, performance semantics, template + * and non-template arguments, @see grb::dot. + * + * @param[out] x The 2-norm of \a y. The input value of \a x will be ignored. + * @param[in] y The vector to compute the norm of. + * @param[in] ring The Semiring under which the 2-norm is to be computed. + * + * \warning This function computes \a x out-of-place. This is contrary to + * standard ALP/GraphBLAS functions that are always in-place. + * + * \warning A \a ring is not sufficient for computing a two-norm. This + * implementation assumes the standard sqrt function + * must be applied on the result of a dot-product of \a y with + * itself under the supplied semiring. + */ + template< + Descriptor descr = descriptors::no_operation, class Ring, + typename InputType, typename OutputType, + typename InputView, + typename InputStorage, + Backend backend, typename Coords + > + RC norm2( OutputType &x, + const VectorView< InputType, InputView, InputStorage, backend, Coords > &y, + const Ring &ring = Ring(), + const typename std::enable_if< + std::is_floating_point< OutputType >::value, + void >::type * const = NULL + ) { + RC ret = grb::dot< descr >( x, y, y, ring ); + if( ret == SUCCESS ) { + x = sqrt( x ); + } + return ret; + } + } // end namespace ``grb'' #endif // end ``_H_GRB_DENSEREF_BLAS1'' diff --git a/tests/unit/CMakeLists.txt b/tests/unit/CMakeLists.txt index 4684c9234..8436075d2 100644 --- a/tests/unit/CMakeLists.txt +++ b/tests/unit/CMakeLists.txt @@ -204,6 +204,10 @@ add_grb_executables( spy spy.cpp BACKENDS reference reference_omp ) +add_grb_executables( dense_dot_norm2 dense_dot_norm2.cpp + BACKENDS reference_dense +) + add_grb_executables( dense_matrix_imf dense_matrix_imf.cpp BACKENDS reference_dense ) diff --git a/tests/unit/dense_dot_norm2.cpp b/tests/unit/dense_dot_norm2.cpp new file mode 100644 index 000000000..31acb78d8 --- /dev/null +++ b/tests/unit/dense_dot_norm2.cpp @@ -0,0 +1,193 @@ + +/* + * Copyright 2021 Huawei Technologies Co., Ltd. + * + * 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. + */ + +#include +#include + +#include + +using namespace grb; + +void grb_program( const size_t &n, grb::RC &rc ) { + + // repeatedly used containers + grb::VectorView< double > left( n ); + grb::VectorView< double > right( n ); + + // test 1, init + grb::Semiring< + grb::operators::add< double >, grb::operators::mul< double >, + grb::identities::zero, grb::identities::one + > ring; + // rc = grb::set( left, 1.5 ); // left = 1.5 everywhere + // rc = rc ? rc : grb::set( right, -1.0 ); + // if( rc != SUCCESS ) { + // std::cerr << "\t test 1 (dense, regular semiring): initialisation FAILED\n"; + // return; + // } + double out = 2.55; + + // test 1, exec + rc = grb::dot( out, left, right, ring ); + if( rc != SUCCESS ) { + std::cerr << "\t test 1 (dense, regular semiring): dot FAILED\n"; + return; + } + + // // test 1, check + // const double expected = 2.55 - static_cast< double >( n + n / 2 ); + // if( !utils::equals( out, expected, 2 * n + 1 ) ) { + // std::cerr << "\t test 1 (dense, regular semiring): unexpected output " + // << "( " << out << ", expected " + // << ( 2.55 - static_cast< double >(n + n/2) ) + // << " )\n"; + // rc = FAILED; + // } + // if( rc != SUCCESS ) { + // return; + // } + + // test 2, init + // grb::Semiring< + // grb::operators::add< double >, grb::operators::left_assign_if< double, bool, double >, + // grb::identities::zero, grb::identities::logical_true + // > pattern_sum_if; + // rc = grb::clear( left ); + // rc = rc ? rc : grb::clear( right ); + // for( size_t i = 0; 2 * i < n; ++i ) { + // rc = rc ? rc : grb::setElement( left, 2.0, 2 * i ); + // rc = rc ? rc : grb::setElement( right, 1.0, 2 * i ); + // } + // if( rc != SUCCESS ) { + // std::cerr << "\t test 2 (sparse, non-standard semiring) initialisation FAILED\n"; + // return; + // } + // out = 0; + + // // test 2, exec + // rc = grb::dot( out, left, right, pattern_sum_if ); + // if( rc != SUCCESS ) { + // std::cerr << "\t test 2 (sparse, non-standard semiring) dot FAILED\n"; + // return; + // } + + // // test 2, check + // if( !utils::equals( out, static_cast< double >( n ), 2 * n ) ) { + // std::cerr << "\t test 2 (sparse, non-standard semiring), " + // << "unexpected output: " << out << ", expected " << n + // << ".\n"; + // rc = FAILED; + // return; + // } + + // // test 3, init + // grb::Semiring< + // grb::operators::add< int >, grb::operators::mul< int >, + // grb::identities::zero, grb::identities::one + // > intRing; + // grb::Vector< int > x( n ), y( n ); + // rc = grb::set( x, 1 ); + // rc = rc ? rc : grb::set( y, 2 ); + // if( rc != grb::SUCCESS ) { + // std::cerr << "\t test 3 (dense integer vectors) initialisation FAILED\n"; + // return; + // } + // int alpha = 0; + + // // test 3, exec + // rc = grb::dot( alpha, x, y, intRing ); + // if( rc != grb::SUCCESS ) { + // std::cerr << "\t test 3 (dense integer vectors) dot FAILED\n"; + // return; + // } + + // // test 3, check + // if( alpha != 2 * static_cast< int >(n) ) { + // std::cerr << "\t test 3 (dense integer vectors) unexpected value " + // << alpha << ", expected 2 * n = " << (2*n) << ".\n"; + // rc = FAILED; + // return; + // } + + // // test 4, init + // grb::Vector< int > empty_left( 0 ), empty_right( 0 ); + // // retain old value of alpha + + // // test 4, exec + // rc = grb::dot( alpha, empty_left, empty_right, intRing ); + // if( rc != SUCCESS ) { + // std::cerr << "\t test 4 (empty vectors) dot FAILED\n"; + // return; + // } + + // // test 4, check + // if( alpha != 2 * static_cast< int >(n) ) { + // std::cerr << "\t test 4 (empty vectors) unexpected value " + // << alpha << ", expected 2 * n = " << (2*n) << ".\n"; + // rc = FAILED; + // return; + // } + +} + +int main( int argc, char ** argv ) { + // defaults + bool printUsage = false; + size_t in = 100; + + // error checking + if( argc > 2 ) { + printUsage = true; + } + if( argc == 2 ) { + size_t read; + std::istringstream ss( argv[ 1 ] ); + if( ! ( ss >> read ) ) { + std::cerr << "Error parsing first argument\n"; + printUsage = true; + } else if( ! ss.eof() ) { + std::cerr << "Error parsing first argument\n"; + printUsage = true; + } else if( read % 2 != 0 ) { + std::cerr << "Given value for n is odd\n"; + printUsage = true; + } else { + // all OK + in = read; + } + } + if( printUsage ) { + std::cerr << "Usage: " << argv[ 0 ] << " [n]\n"; + std::cerr << " -n (optional, default is 100): an even integer, the " + "test size.\n"; + return 1; + } + + std::cout << "This is functional test " << argv[ 0 ] << "\n"; + grb::Launcher< AUTOMATIC > launcher; + grb::RC out; + if( launcher.exec( &grb_program, in, out, true ) != SUCCESS ) { + std::cerr << "Launching test FAILED\n"; + return 255; + } + if( out != SUCCESS ) { + std::cerr << "Test FAILED (" << grb::toString( out ) << ")" << std::endl; + } else { + std::cout << "Test OK" << std::endl; + } + return 0; +} From c24665197718feababfaaaa3f8a0fca16bce77a4 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Thu, 24 Feb 2022 10:36:00 +0100 Subject: [PATCH 067/282] WIP Constant matrix factory methods --- include/graphblas/constant_matrices.hpp | 64 +++++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 include/graphblas/constant_matrices.hpp diff --git a/include/graphblas/constant_matrices.hpp b/include/graphblas/constant_matrices.hpp new file mode 100644 index 000000000..8c8b0796d --- /dev/null +++ b/include/graphblas/constant_matrices.hpp @@ -0,0 +1,64 @@ + +/* + * Copyright 2021 Huawei Technologies Co., Ltd. + * + * 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. + */ + +/* + * @author A. N. Yzelman + * @date 10 of August + */ + +#ifndef _H_GRB_MATRIX +#define _H_GRB_MATRIX + +#include "base/config.hpp" +#include "base/matrix.hpp" + +// now include all specialisations contained in the backend directories: +#ifdef _GRB_WITH_REFERENCE + +#endif +#ifdef _GRB_WITH_DENSEREF + +#endif +#ifdef _GRB_WITH_LPF + +#endif +#ifdef _GRB_WITH_BANSHEE + +#endif + +// specify default only if requested during compilation +#ifdef _GRB_BACKEND +namespace grb { + + /** Returns a constant reference to an Identity matrix of the provided size + * */ + template< typename T > + const StructuredMatrix< T, structures::Identity, storage::Dense, view::Identity< void >, enum Backend backend = config::default_backend > & + I( size_t n ) { + return StructuredMatrix< T, structures::Identity, storage::Dense, view::Identity< void >, backend >( n ); + } + + template< typename T > + const StructuredMatrix< T, structures::Zero, storage::Dense, view::Identity< void >, enum Backend backend = config::default_backend > & + Zero() { + return StructuredMatrix< T, structures::Zero, storage::Dense, view::Identity< void >, backend >(); + } + +} // namespace grb +#endif + +#endif // end ``_H_GRB_MATRIX'' From 6f96781990f8e5a00d2d5a3beac5cb81797e27c6 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Thu, 24 Feb 2022 10:36:32 +0100 Subject: [PATCH 068/282] WIP Base classes for StructuredMatrix --- include/graphblas/denseref/matrix.hpp | 45 +++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/include/graphblas/denseref/matrix.hpp b/include/graphblas/denseref/matrix.hpp index b517206b3..e5e4b5fba 100644 --- a/include/graphblas/denseref/matrix.hpp +++ b/include/graphblas/denseref/matrix.hpp @@ -316,6 +316,51 @@ namespace grb { return A._dims(); } + namespace internal { + /** + * Base StructuredMatrix class containing attributes common to all StructuredMatrix specialization + */ + template< typename T > + class StructuredMatrixBase { + + protected: + std::shared_ptr imf_l, imf_r; + + /** Whether the container presently is initialized or not. */ + bool initialized; + + std::pair< size_t, size_t > _dims() const { + return std::make_pair( imf_l->n, imf_r->n ); + } + + public: + using value_type = T; + }; + + /** + * Base class with container-related attributes, used in container-type StructuredMatrix specializations + */ + template< typename T > + class StructuredMatrixContainer { + protected: + Matrix< T, reference_dense > * _container; + + /** + * The container's storage scheme. + */ + storage::Dense storage_scheme; + + }; + + /** + * Base class with reference-related attributes, used in Views on container-type StructuredMatrix specializations + * + */ + class StructuredMatrixReference { + + }; + } // namespace internal + template< typename T, typename Structure > class StructuredMatrix< T, Structure, storage::Dense, view::Identity< void >, reference_dense > { From 696cd747f42be59a82cbf82b72eba175242ff6c3 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Thu, 24 Feb 2022 17:23:50 +0100 Subject: [PATCH 069/282] WIP Refactor StructuredMatrix using inheritance from Base classes --- include/graphblas/denseref/matrix.hpp | 219 ++++++++------------------ 1 file changed, 65 insertions(+), 154 deletions(-) diff --git a/include/graphblas/denseref/matrix.hpp b/include/graphblas/denseref/matrix.hpp index e5e4b5fba..2cc15552a 100644 --- a/include/graphblas/denseref/matrix.hpp +++ b/include/graphblas/denseref/matrix.hpp @@ -319,8 +319,9 @@ namespace grb { namespace internal { /** * Base StructuredMatrix class containing attributes common to all StructuredMatrix specialization + * \internal Maybe this class can be inherited by Container and Reference classes below */ - template< typename T > + class StructuredMatrixBase { protected: @@ -333,36 +334,65 @@ namespace grb { return std::make_pair( imf_l->n, imf_r->n ); } - public: - using value_type = T; + StructuredMatrixBase( size_t rows, size_t cols ) : + imf_l( std::make_shared< imf::Id >( rows ) ), + imf_r( std::make_shared< imf::Id >( cols ) ), + initialized( false ) {} + + StructuredMatrixBase( std::shared_ptr< imf::IMF > imf_l, std::shared_ptr< imf::IMF > imf_r ) : + imf_l( imf_l ), + imf_r( imf_r ), + initialized( false ) {} + }; /** * Base class with container-related attributes, used in container-type StructuredMatrix specializations */ template< typename T > - class StructuredMatrixContainer { + class StructuredMatrixContainer : public StructuredMatrixBase { protected: Matrix< T, reference_dense > * _container; /** - * The container's storage scheme. + * A container's storage scheme. \a storage_scheme is not exposed to the user as an option + * but can defined by ALP at different points in the execution depending on the \a backend choice. + * For example, if the container is associated to an I/O matrix, with a reference backend + * it might be set to reflect the storage scheme of the user data as specified at buildMatrix. + * If \a backend is set to \a mlir then the scheme could be fixed by the JIT compiler to effectively + * support its optimization strategy. + * At construction time and until the moment the scheme decision is made it may be set to + * an appropriate default choice, e.g. if \a StorageSchemeType is \a storage::Dense then + * \a storage::Dense::full could be used. */ storage::Dense storage_scheme; + StructuredMatrixContainer( size_t rows, size_t cols ) : + StructuredMatrixBase( rows, cols ), + _container( new Matrix< T, reference_dense >(rows, cols) ), + storage_scheme( storage::full ) {} + }; /** * Base class with reference-related attributes, used in Views on container-type StructuredMatrix specializations * */ - class StructuredMatrixReference { + template< typename TargetType > + class StructuredMatrixReference : public StructuredMatrixBase { + protected: + TargetType * ref; + StructuredMatrixReference() : StructuredMatrixBase( 0, 0 ), ref( nullptr ) {} + StructuredMatrixReference( TargetType & struct_mat ) : StructuredMatrixBase( nrows( struct_mat ), ncols( struct_mat ) ), ref( & struct_mat ) {} + StructuredMatrixReference( TargetType & struct_mat, std::shared_ptr< imf::IMF > imf_l, std::shared_ptr< imf::IMF > imf_r ) : + StructuredMatrixBase( imf_l, imf_r ), ref( & struct_mat ) {} }; } // namespace internal template< typename T, typename Structure > - class StructuredMatrix< T, Structure, storage::Dense, view::Identity< void >, reference_dense > { + class StructuredMatrix< T, Structure, storage::Dense, view::Identity< void >, reference_dense > : + public internal::StructuredMatrixContainer< T > { private: /********************* @@ -384,32 +414,6 @@ namespace grb { template< typename fwd_iterator > friend RC buildMatrix( const StructuredMatrix< T, Structure, storage::Dense, view::Identity< void >, reference_dense > &, const fwd_iterator &, const fwd_iterator ) noexcept; - - // Physical layout - TBD - // Matrix< T, reference_dense > A; - - std::shared_ptr imf_l, imf_r; - - /** - * A container's storage scheme. \a storage_scheme is not exposed to the user as an option - * but can defined by ALP at different points in the execution depending on the \a backend choice. - * For example, if the container is associated to an I/O matrix, with a reference backend - * it might be set to reflect the storage scheme of the user data as specified at buildMatrix. - * If \a backend is set to \a mlir then the scheme could be fixed by the JIT compiler to effectively - * support its optimization strategy. - * At construction time and until the moment the scheme decision is made it may be set to - * an appropriate default choice, e.g. if \a StorageSchemeType is \a storage::Dense then - * \a storage::Dense::full could be used. - */ - storage::Dense storage_scheme; - - /** Whether the container presently is initialized or not. */ - bool initialized; - - std::pair< size_t, size_t > _dims() const { - return std::make_pair( imf_l->n, imf_r->n ); - } - public: using value_type = T; using structure = Structure; @@ -417,11 +421,13 @@ namespace grb { // A general Structure knows how to define a reference to itself (which is an identity reference view). using identity_t = StructuredMatrix< T, Structure, storage::Dense, view::Identity< self_type >, reference_dense >; - StructuredMatrix( const size_t rows, const size_t cols ) : imf_l( std::make_shared< imf::Id >( rows ) ), imf_r( std::make_shared< imf::Id >( cols ) ), storage_scheme( storage::full ), initialized( false ) {} + StructuredMatrix( const size_t rows, const size_t cols ) : + internal::StructuredMatrixContainer< T >( rows, cols ) {} }; // class StructuredMatrix template< typename T > - class StructuredMatrix< T, structures::General, storage::Dense, view::Identity< void >, reference_dense > { + class StructuredMatrix< T, structures::General, storage::Dense, view::Identity< void >, reference_dense > : + public internal::StructuredMatrixContainer< T > { private: /********************* @@ -443,28 +449,10 @@ namespace grb { template< typename InputType, typename Structure, typename Storage, typename View, typename fwd_iterator > friend RC buildMatrix( StructuredMatrix< InputType, Structure, Storage, View, reference_dense > &, const fwd_iterator & start, const fwd_iterator & end ) noexcept; - // Physical layout - TBD - // Matrix< T, reference_dense > A; - Matrix< T, reference_dense > * _container; - - std::shared_ptr imf_l, imf_r; - - /** - * The container's storage scheme. - */ - storage::Dense storage_scheme; - - /** Whether the container presently is initialized or not. */ - bool initialized; - - std::pair< size_t, size_t > _dims() const { - return std::make_pair( imf_l->n, imf_r->n ); - } - template< typename fwd_iterator > RC buildMatrixUnique( const fwd_iterator & start, const fwd_iterator & end ) { std::cout << "Building StructuredMatrix<>; calling buildMatrix( Matrix<> )\n"; - return buildMatrix( *_container, start, end ); + return buildMatrix( *(this->_container), start, end ); } public: @@ -478,17 +466,14 @@ namespace grb { using transpose_t = StructuredMatrix< T, structures::General, storage::Dense, view::Transpose< self_type >, reference_dense >; StructuredMatrix( const size_t rows, const size_t cols ) : - _container( new Matrix< T, reference_dense >(rows, cols) ), - imf_l( std::make_shared< imf::Id >( rows ) ), - imf_r( std::make_shared< imf::Id >( cols ) ), - storage_scheme( storage::full ), - initialized( false ) { + internal::StructuredMatrixContainer< T >( rows, cols ) { } }; // StructuredMatrix General, container template< typename T > - class StructuredMatrix< T, structures::Square, storage::Dense, view::Identity< void >, reference_dense > { + class StructuredMatrix< T, structures::Square, storage::Dense, view::Identity< void >, reference_dense > : + public internal::StructuredMatrixContainer< T > { private: /********************* @@ -503,23 +488,6 @@ namespace grb { using self_type = StructuredMatrix< T, structures::Square, storage::Dense, view::Identity< void >, reference_dense >; - // Physical layout - TBD - // Matrix< T, reference_dense > A; - - std::shared_ptr imf_l, imf_r; - - /** - * The container's storage scheme. - */ - storage::Dense storage_scheme; - - /** Whether the container presently is initialized or not. */ - bool initialized; - - std::pair< size_t, size_t > _dims() const { - return std::make_pair( imf_l->n, imf_r->n ); - } - public: /** Exposes the element type and the structure. */ using value_type = T; @@ -528,7 +496,8 @@ namespace grb { using identity_t = StructuredMatrix< T, structures::Square, storage::Dense, view::Identity< self_type >, reference_dense >; using transpose_t = StructuredMatrix< T, structures::Square, storage::Dense, view::Transpose< self_type >, reference_dense >; - StructuredMatrix( const size_t rows ) : imf_l( std::make_shared< imf::Id >( rows ) ), imf_r( std::make_shared< imf::Id >( rows ) ), storage_scheme( storage::full ), initialized( false ) {} + StructuredMatrix( const size_t rows ) : + internal::StructuredMatrixContainer< T >( rows, rows ) {} }; // StructuredMatrix Square, container @@ -536,7 +505,8 @@ namespace grb { * Reference to a general Matrix generalized over views. */ template< typename T, typename View > - class StructuredMatrix< T, structures::General, storage::Dense, View, reference_dense > { + class StructuredMatrix< T, structures::General, storage::Dense, View, reference_dense > : + public internal::StructuredMatrixReference< typename View::applied_to > { private: using self_type = StructuredMatrix< T, structures::General, storage::Dense, View, reference_dense >; @@ -552,14 +522,6 @@ namespace grb { friend std::pair< size_t, size_t > dims<>( const self_type & ) noexcept; - target_type * ref; - - std::shared_ptr imf_l, imf_r; - - std::pair< size_t, size_t > _dims() const { - return std::make_pair( imf_l->n, imf_r->n ); - } - public: /** Exposes the element type and the structure. */ using value_type = T; @@ -568,24 +530,18 @@ namespace grb { using identity_t = StructuredMatrix< T, structures::General, storage::Dense, view::Identity< self_type >, reference_dense >; using transpose_t = StructuredMatrix< T, structures::General, storage::Dense, view::Transpose< self_type >, reference_dense >; - StructuredMatrix( ) : ref( nullptr ), imf_l( std::make_shared< imf::Id >( 0 ) ), imf_r( std::make_shared< imf::Id >( 0 ) ) {} + StructuredMatrix( ) : internal::StructuredMatrixBase( 0, 0 ) {} - StructuredMatrix( target_type & struct_mat ) : ref( &struct_mat ), imf_l( nullptr ), imf_r( nullptr ) { - - std::pair< size_t, size_t > _dims = View::dims( dims( *ref ) ); - imf_l = std::make_shared< imf::Id >( _dims.first ); - imf_r = std::make_shared< imf::Id >( _dims.second ); - - } + StructuredMatrix( target_type & struct_mat ) : internal::StructuredMatrixReference< target_type >( struct_mat ) {} StructuredMatrix( target_type & struct_mat, std::shared_ptr< imf::IMF > imf_l, std::shared_ptr< imf::IMF > imf_r ) : - ref( &struct_mat ), imf_l( imf_l ), imf_r( imf_r ) { - } + internal::StructuredMatrixReference< target_type >( struct_mat, imf_l, imf_r ) {} }; // StructuredMatrix General reference template< typename T, typename View > - class StructuredMatrix< T, structures::Square, storage::Dense, View, reference_dense > { + class StructuredMatrix< T, structures::Square, storage::Dense, View, reference_dense > : + public internal::StructuredMatrixReference< typename View::applied_to > { private: using self_type = StructuredMatrix< T, structures::Square, storage::Dense, View, reference_dense >; @@ -600,14 +556,6 @@ namespace grb { friend std::pair< size_t, size_t > dims<>( const self_type & ) noexcept; - target_type * ref; - - std::shared_ptr imf_l, imf_r; - - std::pair< size_t, size_t > _dims() const { - return std::make_pair( imf_l->n, imf_r->n ); - } - public: /** Exposes the element type and the structure. */ using value_type = T; @@ -617,22 +565,20 @@ namespace grb { using transpose_t = StructuredMatrix< T, structures::Square, storage::Dense, view::Transpose< self_type >, reference_dense >; // ref to empty matrix - StructuredMatrix( ) : ref( nullptr ), imf_l( std::make_shared< imf::Id >( 0 ) ), imf_r( std::make_shared< imf::Id >( 0 ) ) {} + StructuredMatrix( ) : internal::StructuredMatrixReference< target_type >() {} - StructuredMatrix( target_type & struct_mat ) : ref( & struct_mat ), imf_l( nullptr ), imf_r( nullptr ) { + StructuredMatrix( target_type & struct_mat ) : internal::StructuredMatrixReference< target_type >( struct_mat ) { if( nrows( struct_mat ) != ncols( struct_mat ) ) { throw std::length_error( "Square StructuredMatrix reference to non-square target." ); } - // No matter the view it has to be a square matrix - imf_l = std::make_shared< imf::Id >( nrows( struct_mat ) ); - imf_r = std::make_shared< imf::Id >( nrows( struct_mat ) ); } }; // StructuredMatrix Square reference // StructuredMatrix UpperTriangular, container template< typename T > - class StructuredMatrix< T, structures::UpperTriangular, storage::Dense, view::Identity< void >, reference_dense > { + class StructuredMatrix< T, structures::UpperTriangular, storage::Dense, view::Identity< void >, reference_dense > : + public internal::StructuredMatrixContainer< T > { private: /********************* @@ -654,28 +600,10 @@ namespace grb { template< typename InputType, typename Structure, typename Storage, typename View, typename fwd_iterator > friend RC buildMatrix( StructuredMatrix< InputType, Structure, Storage, View, reference_dense > &, const fwd_iterator & start, const fwd_iterator & end ) noexcept; - // Physical layout - TBD - // Matrix< T, reference_dense > A; - Matrix< T, reference_dense > * _container; - - std::shared_ptr imf_l, imf_r; - - /** - * The container's storage scheme. - */ - storage::Dense storage_scheme; - - /** Whether the container presently is initialized or not. */ - bool initialized; - - std::pair< size_t, size_t > _dims() const { - return std::make_pair( imf_l->n, imf_r->n ); - } - template< typename fwd_iterator > RC buildMatrixUnique( const fwd_iterator & start, const fwd_iterator & end ) { std::cout << "Building StructuredMatrix<>; calling buildMatrix( Matrix<> )\n"; - return buildMatrix( *_container, start, end ); + return buildMatrix( *(this->_container), start, end ); } public: @@ -689,18 +617,14 @@ namespace grb { using transpose_t = StructuredMatrix< T, structures::LowerTriangular, storage::Dense, view::Transpose< self_type >, reference_dense >; StructuredMatrix( const size_t rows, const size_t cols ) : - _container( new Matrix< T, reference_dense >(rows, cols) ), - imf_l( std::make_shared< imf::Id >( rows ) ), - imf_r( std::make_shared< imf::Id >( cols ) ), - storage_scheme( storage::full ), - initialized( false ) { - } + internal::StructuredMatrixContainer< T >( rows, cols ) {} }; // StructuredMatrix UpperTriangular, container // StructuredMatrix UpperTriangular, reference template< typename T, typename View > - class StructuredMatrix< T, structures::UpperTriangular, storage::Dense, View, reference_dense > { + class StructuredMatrix< T, structures::UpperTriangular, storage::Dense, View, reference_dense > : + public internal::StructuredMatrixReference< typename View::applied_to > { private: using self_type = StructuredMatrix< T, structures::UpperTriangular, storage::Dense, View, reference_dense >; @@ -715,14 +639,6 @@ namespace grb { friend std::pair< size_t, size_t > dims<>( const self_type & ) noexcept; - target_type * ref; - - std::shared_ptr imf_l, imf_r; - - std::pair< size_t, size_t > _dims() const { - return std::make_pair( imf_l->n, imf_r->n ); - } - public: /** Exposes the element type and the structure. */ using value_type = T; @@ -732,19 +648,14 @@ namespace grb { using transpose_t = StructuredMatrix< T, structures::UpperTriangular, storage::Dense, view::Transpose< self_type >, reference_dense >; // ref to empty matrix - StructuredMatrix( ) : ref( nullptr ), imf_l( std::make_shared< imf::Id >( 0 ) ), imf_r( std::make_shared< imf::Id >( 0 ) ) {} + StructuredMatrix( ) : internal::StructuredMatrixReference< target_type >() {} - StructuredMatrix( target_type & struct_mat ) : ref( & struct_mat ), imf_l( nullptr ), imf_r( nullptr ) { + StructuredMatrix( target_type & struct_mat ) : internal::StructuredMatrixReference< target_type >( struct_mat ) { // No matter the view it has to be a square matrix - imf_l = std::make_shared< imf::Id >( nrows( struct_mat ) ); - imf_r = std::make_shared< imf::Id >( ncols( struct_mat ) ); } StructuredMatrix( target_type & struct_mat, std::shared_ptr< imf::IMF > imf_l, std::shared_ptr< imf::IMF > imf_r ) : - ref( & struct_mat ), - imf_l( imf_l ), - imf_r( imf_r ) { - } + internal::StructuredMatrixReference< target_type >( struct_mat, imf_l, imf_r ) {} }; // StructuredMatrix UpperTriangular, reference From 6d491ea53f84138d73d7859460a1cdf32d7374b6 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Thu, 24 Feb 2022 22:25:38 +0100 Subject: [PATCH 070/282] Implement friend functions through base classes This avoids the need to declare friend functions inside every StructuredMatrix specialization. --- include/graphblas/denseref/matrix.hpp | 133 ++++++++++---------------- 1 file changed, 53 insertions(+), 80 deletions(-) diff --git a/include/graphblas/denseref/matrix.hpp b/include/graphblas/denseref/matrix.hpp index 2cc15552a..c4fc082c9 100644 --- a/include/graphblas/denseref/matrix.hpp +++ b/include/graphblas/denseref/matrix.hpp @@ -286,15 +286,36 @@ namespace grb { } namespace internal { - template< typename T, typename Structure, typename Storage, typename View > - const Matrix< T, reference_dense > & getContainer( const StructuredMatrix< T, Structure, Storage, View, reference_dense > & A ) { - return *( A._container ); - } + /** Forward declaration */ + template< typename T > + class StructuredMatrixContainer; - template< typename T, typename Structure, typename Storage, typename View > - Matrix< T, reference_dense > & getContainer( StructuredMatrix< T, Structure, Storage, View, reference_dense > & A ) { - return *( A._container ); - } + /** Container reference getters used by friend functions of specialized StructuredMatrix */ + template< typename T > + const Matrix< T, reference_dense > & getContainer( const StructuredMatrixContainer< T > & A ); + + template< typename T > + Matrix< T, reference_dense > & getContainer( StructuredMatrixContainer< T > & A ); + + /** Container reference getters. Defer the call to base class friend function */ + template< typename T, typename Structure, typename Storage, typename View > + const Matrix< T, reference_dense > & getContainer( const StructuredMatrix< T, Structure, Storage, View, reference_dense > & A ) { + return getContainer( A ); + } + + template< typename T, typename Structure, typename Storage, typename View > + Matrix< T, reference_dense > & getContainer( StructuredMatrix< T, Structure, Storage, View, reference_dense > & A ) { + return getContainer( A ); + } + + /** Forward declaration */ + class StructuredMatrixBase; + + size_t nrows( const StructuredMatrixBase & A ) noexcept; + + size_t ncols( const StructuredMatrixBase & A ) noexcept; + + std::pair< size_t, size_t > dims( const StructuredMatrixBase & A ) noexcept; } // namespace internal /** @@ -303,17 +324,17 @@ namespace grb { template< typename D, typename Structure, typename View > size_t nrows( const StructuredMatrix< D, Structure, storage::Dense, View, reference_dense > & A ) noexcept { - return A._dims().first; + return internal::nrows( A ); } template< typename D, typename Structure, typename View > size_t ncols( const StructuredMatrix< D, Structure, storage::Dense, View, reference_dense > & A ) noexcept { - return A._dims().second; + return internal::ncols( A ); } template< typename D, typename Structure, typename View > std::pair< size_t, size_t > dims( const StructuredMatrix< D, Structure, storage::Dense, View, reference_dense > & A ) noexcept { - return A._dims(); + return internal::dims( A ); } namespace internal { @@ -325,12 +346,24 @@ namespace grb { class StructuredMatrixBase { protected: + friend size_t nrows( const StructuredMatrixBase & A ) noexcept { + return A._dims().first; + } + + friend size_t ncols( const StructuredMatrixBase & A ) noexcept { + return A._dims().second; + } + + friend std::pair< size_t, size_t > dims( const StructuredMatrixBase & A ) noexcept { + return A._dims(); + } + std::shared_ptr imf_l, imf_r; /** Whether the container presently is initialized or not. */ bool initialized; - std::pair< size_t, size_t > _dims() const { + virtual std::pair< size_t, size_t > _dims() const { return std::make_pair( imf_l->n, imf_r->n ); } @@ -352,6 +385,14 @@ namespace grb { template< typename T > class StructuredMatrixContainer : public StructuredMatrixBase { protected: + friend const Matrix< T, reference_dense > & getContainer( const StructuredMatrixContainer< T > & A ) { + return *( A._container ); + } + + friend Matrix< T, reference_dense > & getContainer( StructuredMatrixContainer< T > & A ) { + return *( A._container ); + } + Matrix< T, reference_dense > * _container; /** @@ -401,16 +442,6 @@ namespace grb { using self_type = StructuredMatrix< T, Structure, storage::Dense, view::Identity< void >, reference_dense >; - friend size_t nrows<>( const StructuredMatrix< T, Structure, storage::Dense, view::Identity< void >, reference_dense > & ) noexcept; - - friend size_t ncols<>( const StructuredMatrix< T, Structure, storage::Dense, view::Identity< void >, reference_dense > & ) noexcept; - - friend std::pair< size_t, size_t > dims<>( const StructuredMatrix< T, Structure, storage::Dense, view::Identity< void >, reference_dense > & ) noexcept; - - friend const Matrix< T, reference_dense> & internal::getContainer<>( const self_type & A ) noexcept; - - friend Matrix< T, reference_dense> & internal::getContainer<>( self_type & A ) noexcept; - template< typename fwd_iterator > friend RC buildMatrix( const StructuredMatrix< T, Structure, storage::Dense, view::Identity< void >, reference_dense > &, const fwd_iterator &, const fwd_iterator ) noexcept; @@ -436,16 +467,6 @@ namespace grb { using self_type = StructuredMatrix< T, structures::General, storage::Dense, view::Identity< void >, reference_dense >; - friend size_t nrows<>( const StructuredMatrix< T, structures::General, storage::Dense, view::Identity< void >, reference_dense > & ) noexcept; - - friend size_t ncols<>( const StructuredMatrix< T, structures::General, storage::Dense, view::Identity< void >, reference_dense > & ) noexcept; - - friend std::pair< size_t, size_t > dims<>( const StructuredMatrix< T, structures::General, storage::Dense, view::Identity< void >, reference_dense > & ) noexcept; - - friend const Matrix< T, reference_dense> & internal::getContainer<>( const self_type & A ) noexcept; - - friend Matrix< T, reference_dense> & internal::getContainer<>( self_type & A ) noexcept; - template< typename InputType, typename Structure, typename Storage, typename View, typename fwd_iterator > friend RC buildMatrix( StructuredMatrix< InputType, Structure, Storage, View, reference_dense > &, const fwd_iterator & start, const fwd_iterator & end ) noexcept; @@ -476,16 +497,6 @@ namespace grb { public internal::StructuredMatrixContainer< T > { private: - /********************* - Storage info friends - ******************** */ - - friend size_t nrows<>( const StructuredMatrix< T, structures::Square, storage::Dense, view::Identity< void >, reference_dense > & ) noexcept; - - friend size_t ncols<>( const StructuredMatrix< T, structures::Square, storage::Dense, view::Identity< void >, reference_dense > & ) noexcept; - - friend std::pair< size_t, size_t > dims<>( const StructuredMatrix< T, structures::Square, storage::Dense, view::Identity< void >, reference_dense > & ) noexcept; - using self_type = StructuredMatrix< T, structures::Square, storage::Dense, view::Identity< void >, reference_dense >; public: @@ -512,16 +523,6 @@ namespace grb { using self_type = StructuredMatrix< T, structures::General, storage::Dense, View, reference_dense >; using target_type = typename View::applied_to; - /********************* - Storage info friends - ******************** */ - - friend size_t nrows<>( const self_type & ) noexcept; - - friend size_t ncols<>( const self_type & ) noexcept; - - friend std::pair< size_t, size_t > dims<>( const self_type & ) noexcept; - public: /** Exposes the element type and the structure. */ using value_type = T; @@ -546,15 +547,6 @@ namespace grb { private: using self_type = StructuredMatrix< T, structures::Square, storage::Dense, View, reference_dense >; using target_type = typename View::applied_to; - /********************* - Storage info friends - ******************** */ - - friend size_t nrows<>( const self_type & ) noexcept; - - friend size_t ncols<>( const self_type & ) noexcept; - - friend std::pair< size_t, size_t > dims<>( const self_type & ) noexcept; public: /** Exposes the element type and the structure. */ @@ -587,16 +579,6 @@ namespace grb { using self_type = StructuredMatrix< T, structures::UpperTriangular, storage::Dense, view::Identity< void >, reference_dense >; - friend size_t nrows<>( const StructuredMatrix< T, structures::UpperTriangular, storage::Dense, view::Identity< void >, reference_dense > & ) noexcept; - - friend size_t ncols<>( const StructuredMatrix< T, structures::UpperTriangular, storage::Dense, view::Identity< void >, reference_dense > & ) noexcept; - - friend std::pair< size_t, size_t > dims<>( const StructuredMatrix< T, structures::UpperTriangular, storage::Dense, view::Identity< void >, reference_dense > & ) noexcept; - - friend const Matrix< T, reference_dense> & internal::getContainer<>( const self_type & A ) noexcept; - - friend Matrix< T, reference_dense> & internal::getContainer<>( self_type & A ) noexcept; - template< typename InputType, typename Structure, typename Storage, typename View, typename fwd_iterator > friend RC buildMatrix( StructuredMatrix< InputType, Structure, Storage, View, reference_dense > &, const fwd_iterator & start, const fwd_iterator & end ) noexcept; @@ -629,15 +611,6 @@ namespace grb { private: using self_type = StructuredMatrix< T, structures::UpperTriangular, storage::Dense, View, reference_dense >; using target_type = typename View::applied_to; - /********************* - Storage info friends - ******************** */ - - friend size_t nrows<>( const self_type & ) noexcept; - - friend size_t ncols<>( const self_type & ) noexcept; - - friend std::pair< size_t, size_t > dims<>( const self_type & ) noexcept; public: /** Exposes the element type and the structure. */ From 3a3460f508dcf191923383c6e287daffc41f22d9 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Thu, 24 Feb 2022 23:09:10 +0100 Subject: [PATCH 071/282] Add getter and setter for initialized field in StructuredMatrix --- include/graphblas/denseref/matrix.hpp | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/include/graphblas/denseref/matrix.hpp b/include/graphblas/denseref/matrix.hpp index c4fc082c9..94b520c37 100644 --- a/include/graphblas/denseref/matrix.hpp +++ b/include/graphblas/denseref/matrix.hpp @@ -316,6 +316,20 @@ namespace grb { size_t ncols( const StructuredMatrixBase & A ) noexcept; std::pair< size_t, size_t > dims( const StructuredMatrixBase & A ) noexcept; + + bool getInitialized( StructuredMatrixBase & ) noexcept; + + void getInitialized( StructuredMatrixBase &, bool ) noexcept; + + template< typename T, typename Structure, typename Storage, typename View > + bool getInitialized( StructuredMatrix< T, Structure, Storage, View, reference_dense > & A ) noexcept { + return getInitialized( A ); + } + + template< typename T, typename Structure, typename Storage, typename View > + void setInitialized( StructuredMatrix< T, Structure, Storage, View, reference_dense > & A, bool initialized ) noexcept { + setInitialized( A, initialized ); + } } // namespace internal /** @@ -358,6 +372,14 @@ namespace grb { return A._dims(); } + friend bool getInitialized( StructuredMatrixBase & A ) noexcept { + return A.initialized; + } + + friend void setInitialized( StructuredMatrixBase & A, bool initialized ) noexcept { + A.initialized = initialized; + } + std::shared_ptr imf_l, imf_r; /** Whether the container presently is initialized or not. */ From 2edadeaeb6099766fdfd4091595486865767bcc0 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Thu, 24 Feb 2022 23:30:40 +0100 Subject: [PATCH 072/282] Revert "WIP Constant matrix factory methods" This reverts commit 742fe9f3ded2aaff5c389c6cdc6d6483081f756b. --- include/graphblas/constant_matrices.hpp | 64 ------------------------- 1 file changed, 64 deletions(-) delete mode 100644 include/graphblas/constant_matrices.hpp diff --git a/include/graphblas/constant_matrices.hpp b/include/graphblas/constant_matrices.hpp deleted file mode 100644 index 8c8b0796d..000000000 --- a/include/graphblas/constant_matrices.hpp +++ /dev/null @@ -1,64 +0,0 @@ - -/* - * Copyright 2021 Huawei Technologies Co., Ltd. - * - * 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. - */ - -/* - * @author A. N. Yzelman - * @date 10 of August - */ - -#ifndef _H_GRB_MATRIX -#define _H_GRB_MATRIX - -#include "base/config.hpp" -#include "base/matrix.hpp" - -// now include all specialisations contained in the backend directories: -#ifdef _GRB_WITH_REFERENCE - -#endif -#ifdef _GRB_WITH_DENSEREF - -#endif -#ifdef _GRB_WITH_LPF - -#endif -#ifdef _GRB_WITH_BANSHEE - -#endif - -// specify default only if requested during compilation -#ifdef _GRB_BACKEND -namespace grb { - - /** Returns a constant reference to an Identity matrix of the provided size - * */ - template< typename T > - const StructuredMatrix< T, structures::Identity, storage::Dense, view::Identity< void >, enum Backend backend = config::default_backend > & - I( size_t n ) { - return StructuredMatrix< T, structures::Identity, storage::Dense, view::Identity< void >, backend >( n ); - } - - template< typename T > - const StructuredMatrix< T, structures::Zero, storage::Dense, view::Identity< void >, enum Backend backend = config::default_backend > & - Zero() { - return StructuredMatrix< T, structures::Zero, storage::Dense, view::Identity< void >, backend >(); - } - -} // namespace grb -#endif - -#endif // end ``_H_GRB_MATRIX'' From 4c1047aacc6a3edef608c15ce96263309155bdc7 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Thu, 24 Feb 2022 23:31:15 +0100 Subject: [PATCH 073/282] Add interface for creating constant matrices This includes Identity matrix, Zero matrix and Givens rotations --- include/graphblas/denseref/matrix.hpp | 78 +++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) diff --git a/include/graphblas/denseref/matrix.hpp b/include/graphblas/denseref/matrix.hpp index 94b520c37..78014138d 100644 --- a/include/graphblas/denseref/matrix.hpp +++ b/include/graphblas/denseref/matrix.hpp @@ -521,6 +521,15 @@ namespace grb { private: using self_type = StructuredMatrix< T, structures::Square, storage::Dense, view::Identity< void >, reference_dense >; + template< typename InputType, typename Structure, typename Storage, typename View, typename fwd_iterator > + friend RC buildMatrix( StructuredMatrix< InputType, Structure, Storage, View, reference_dense > &, const fwd_iterator & start, const fwd_iterator & end ) noexcept; + + template< typename fwd_iterator > + RC buildMatrixUnique( const fwd_iterator & start, const fwd_iterator & end ) { + std::cout << "Building StructuredMatrix<>; calling buildMatrix( Matrix<> )\n"; + return buildMatrix( *(this->_container), start, end ); + } + public: /** Exposes the element type and the structure. */ using value_type = T; @@ -654,6 +663,42 @@ namespace grb { }; // StructuredMatrix UpperTriangular, reference + // StructuredMatrix Identity, container + template< typename T > + class StructuredMatrix< T, structures::Identity, storage::Dense, view::Identity< void >, reference_dense > : + public internal::StructuredMatrixContainer< T > { + + private: + /********************* + Storage info friends + ******************** */ + + using self_type = StructuredMatrix< T, structures::Identity, storage::Dense, view::Identity< void >, reference_dense >; + + template< typename InputType, typename Structure, typename Storage, typename View, typename fwd_iterator > + friend RC buildMatrix( StructuredMatrix< InputType, Structure, Storage, View, reference_dense > &, const fwd_iterator & start, const fwd_iterator & end ) noexcept; + + template< typename fwd_iterator > + RC buildMatrixUnique( const fwd_iterator & start, const fwd_iterator & end ) { + std::cout << "Building StructuredMatrix<>; calling buildMatrix( Matrix<> )\n"; + return buildMatrix( *(this->_container), start, end ); + } + + public: + /** Exposes the element type and the structure. */ + using value_type = T; + using structure = structures::Identity; + + // A general Structure knows how to define a reference to itself (which is an identity reference view) + // as well as other static views. + using identity_t = StructuredMatrix< T, structures::Identity, storage::Dense, view::Identity< self_type >, reference_dense >; + using transpose_t = StructuredMatrix< T, structures::Identity, storage::Dense, view::Transpose< self_type >, reference_dense >; + + StructuredMatrix( const size_t rows ) : + internal::StructuredMatrixContainer< T >( rows, rows ) {} + + }; // StructuredMatrix Identity, container + namespace structures { // GraphBLAS type traits for structure @@ -732,6 +777,39 @@ namespace grb { return target; } + /** Returns a constant reference to an Identity matrix of the provided size + * */ + template< typename T > + const StructuredMatrix< T, structures::Identity, storage::Dense, view::Identity< void >, reference_dense > & + I( const size_t n ) { + using return_type = StructuredMatrix< T, structures::Identity, storage::Dense, view::Identity< void >, reference_dense >; + return_type * ret = new return_type( n ); + return * ret; + } + + /** Returns a constant reference to a Zero matrix of the provided size + * */ + template< typename T > + const StructuredMatrix< T, structures::Zero, storage::Dense, view::Identity< void >, reference_dense > & + Zero( const size_t rows, const size_t cols ) { + using return_type = StructuredMatrix< T, structures::Zero, storage::Dense, view::Identity< void >, reference_dense >; + return_type * ret = new return_type( rows, cols ); + return * ret; + } + + /** Returns a constant reference to a matrix representing Givens rotation + * of the provided size n and parameters i, j, s and c, where + * s = sin( theta ) and c = cos( theta ) + * */ + template< typename T > + const StructuredMatrix< T, structures::Square, storage::Dense, view::Identity< void >, reference_dense > & + Givens( const size_t n, const size_t i, const size_t j, const T s, const T c ) { + using return_type = const StructuredMatrix< T, structures::Square, storage::Dense, view::Identity< void >, reference_dense >; + return_type * ret = new return_type( n ); + // TODO: initialize matrix values according to the provided parameters + return * ret; + } + } // namespace grb #endif // end ``_H_GRB_DENSEREF_MATRIX'' From 9ac3cd2e81cf15254fa4b9390e21240b52def3ca Mon Sep 17 00:00:00 2001 From: Anonymous Date: Thu, 24 Feb 2022 23:42:16 +0100 Subject: [PATCH 074/282] Add test showcasing the use of Identity and Zero matrices --- include/graphblas/denseref/blas3.hpp | 6 ++ tests/unit/CMakeLists.txt | 4 ++ tests/unit/dense_constant_matrices.cpp | 98 ++++++++++++++++++++++++++ 3 files changed, 108 insertions(+) create mode 100644 tests/unit/dense_constant_matrices.cpp diff --git a/include/graphblas/denseref/blas3.hpp b/include/graphblas/denseref/blas3.hpp index 72079c885..d1719b464 100644 --- a/include/graphblas/denseref/blas3.hpp +++ b/include/graphblas/denseref/blas3.hpp @@ -151,6 +151,12 @@ namespace grb { grb::is_monoid< Monoid >::value, void >::type * const = NULL ) { + (void)C; + (void)A; + (void)B; + (void)oper; + (void)monoid; + (void)mulMonoid; // TODO; Implement this as a backup version that works for any structure and storage. // Even though the performance does not have to be optimal, we guarantee that any two matrices can be multiplied // To provide better performing mxm, one should implement a function with specialized template elements diff --git a/tests/unit/CMakeLists.txt b/tests/unit/CMakeLists.txt index 8436075d2..0fa40a6f3 100644 --- a/tests/unit/CMakeLists.txt +++ b/tests/unit/CMakeLists.txt @@ -204,6 +204,10 @@ add_grb_executables( spy spy.cpp BACKENDS reference reference_omp ) +add_grb_executables( dense_constant_matrices dense_constant_matrices.cpp + BACKENDS reference_dense +) + add_grb_executables( dense_dot_norm2 dense_dot_norm2.cpp BACKENDS reference_dense ) diff --git a/tests/unit/dense_constant_matrices.cpp b/tests/unit/dense_constant_matrices.cpp new file mode 100644 index 000000000..db561128e --- /dev/null +++ b/tests/unit/dense_constant_matrices.cpp @@ -0,0 +1,98 @@ + +/* + * Copyright 2021 Huawei Technologies Co., Ltd. + * + * 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. + */ + +#include +#include +#include + +#include + +using namespace grb; + +void grb_program( const size_t & n, grb::RC & rc ) { + grb::Semiring< grb::operators::add< double >, grb::operators::mul< double >, grb::identities::zero, grb::identities::one > ring; + + std::cout << "\tTesting dense Identity and Zero matrices\n"; + // initialize test + grb::StructuredMatrix< double, structures::Square > A( n ); + grb::StructuredMatrix< double, structures::Square > C( n ); + auto I = grb::I< double >( n ); + auto Zero = grb::Zero< double >( n, n ); + + // Initialize input matrix + std::vector< double > A_data( n * n, 1 ); + rc = grb::buildMatrix( A, A_data.begin(), A_data.end() ); + + if( rc == SUCCESS ) { + grb::mxm( C, A, I, ring ); + // C should be equal to A + } + + if (rc == SUCCESS ) { + grb::mxm( C, A, Zero, ring ); + // C should be a zero + } +} + +int main( int argc, char ** argv ) { + // defaults + bool printUsage = false; + size_t in = 100; + + // error checking + if( argc > 2 ) { + printUsage = true; + } + if( argc == 2 ) { + size_t read; + std::istringstream ss( argv[ 1 ] ); + if( ! ( ss >> read ) ) { + std::cerr << "Error parsing first argument\n"; + printUsage = true; + } else if( ! ss.eof() ) { + std::cerr << "Error parsing first argument\n"; + printUsage = true; + } else if( read % 2 != 0 ) { + std::cerr << "Given value for n is odd\n"; + printUsage = true; + } else { + // all OK + in = read; + } + } + if( printUsage ) { + std::cerr << "Usage: " << argv[ 0 ] << " [n]\n"; + std::cerr << " -n (optional, default is 100): an even integer, the " + "test size.\n"; + return 1; + } + + std::cout << "This is functional test " << argv[ 0 ] << "\n"; + grb::Launcher< AUTOMATIC > launcher; + grb::RC out; + if( launcher.exec( &grb_program, in, out, true ) != SUCCESS ) { + std::cerr << "Launching test FAILED\n"; + return 255; + } + if( out != SUCCESS ) { + std::cerr << "Test FAILED (" << grb::toString( out ) << ")" << std::endl; + } else { + std::cout << "Test OK" << std::endl; + } + return 0; +} + From 1c3fd3899c8f556b6f409be0f91414ceadeb7392 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Thu, 24 Feb 2022 23:47:20 +0100 Subject: [PATCH 075/282] Revert "WIP: Add data size calculator depending on Storage scheme and structure." This reverts commit 1f7b6c4f59c6473b7696a77ebb8b7d7b51358386. --- include/graphblas/denseref/matrix.hpp | 63 --------------- tests/unit/CMakeLists.txt | 4 - tests/unit/dense_matrix_allocation_size.cpp | 90 --------------------- 3 files changed, 157 deletions(-) delete mode 100644 tests/unit/dense_matrix_allocation_size.cpp diff --git a/include/graphblas/denseref/matrix.hpp b/include/graphblas/denseref/matrix.hpp index 78014138d..5de25d321 100644 --- a/include/graphblas/denseref/matrix.hpp +++ b/include/graphblas/denseref/matrix.hpp @@ -42,69 +42,6 @@ namespace grb { - namespace internal { - /** Helper class to calculate number of elements for raw matrix storage, - * depending on the storage scheme and the structure. - * - * \internal Thoughts: - * Currently, this class has to depend on structure (to allow for "optimal" element count). - * E.g. Matrix< Dense:full, Structure::Triangular> can use less storage than - * Matrix< Dense::full, Structure::General>. - * If we add Storage::packed (which could store Triangular or Symetric matrices), - * then it seems that Structure can be removed from template list of this class. - * - * TODO: Expand the class to StructuredMatrix - */ - template< typename T, typename grb::storage::Dense, typename Structure = grb::structures::General > - class DataElementsCalculator { - public: - static size_t calculate( const Matrix< T, reference_dense > & A ) { - (void)A; - std::cout << "Cannot determine storage size due to unspecified storage scheme. \n"; - assert( false ); - return (size_t)-1; - } - }; - - template< typename T > - class DataElementsCalculator< T, grb::storage::Dense::full > { - public: - static size_t calculate( const Matrix< T, reference_dense > & A ) { - return nrows( A ) * ncols( A ); - } - }; - - template< typename T > - class DataElementsCalculator< T, grb::storage::Dense::full, grb::structures::Triangular > { - public: - static size_t calculate( const Matrix< T, reference_dense > & A ) { - // structures::Triangular assumes that the matrix is structures::Square - std::size_t m = nrows( A ); - return m * ( m + 1 ) / 2; - } - }; - - template< typename T > - class DataElementsCalculator< T, grb::storage::Dense::band > { - public: - static size_t calculate( const Matrix< T, reference_dense > & A ) { - size_t ku = 1; // nsuperdiagonals( A ); only exists in banded matrix - size_t kl = 1; // nsubdiagonals( A ); only exists in banded matrix - return ncols( A ) * ( ku + kl + 1 ); - } - }; - - template< typename T > - class DataElementsCalculator< T, grb::storage::Dense::array1d > { - public: - static size_t calculate( const Matrix< T, reference_dense > & A ) { - size_t min_dimension = min( nrows( A ), ncols( A ) ); - // Temporary: Assume main diagonal + one subdiagonal + one superdiagonal - return min_dimension + 2 * ( min_dimension - 1 ); - } - }; - } // namespace internal - template< typename T > T * getRaw( Matrix< T, reference_dense > & ) noexcept; diff --git a/tests/unit/CMakeLists.txt b/tests/unit/CMakeLists.txt index 0fa40a6f3..68db94bf4 100644 --- a/tests/unit/CMakeLists.txt +++ b/tests/unit/CMakeLists.txt @@ -220,10 +220,6 @@ add_grb_executables( dense_matrix_eWiseApply dense_matrix_eWiseApply.cpp BACKENDS reference_dense ) -add_grb_executables( dense_matrix_allocation_size dense_matrix_allocation_size.cpp - BACKENDS reference_dense -) - add_grb_executables( dense_mxm dense_mxm.cpp BACKENDS reference_dense ) diff --git a/tests/unit/dense_matrix_allocation_size.cpp b/tests/unit/dense_matrix_allocation_size.cpp deleted file mode 100644 index 2f9169675..000000000 --- a/tests/unit/dense_matrix_allocation_size.cpp +++ /dev/null @@ -1,90 +0,0 @@ - -/* - * Copyright 2021 Huawei Technologies Co., Ltd. - * - * 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. - */ - -#include -#include -#include -#include -#include - -#include - -void grb_program( const size_t & n, grb::RC & rc ) { - // initialize test - grb::Matrix< double, grb::reference_dense > M( n, n ); - - size_t elems = grb::internal::DataElementsCalculator< double, grb::storage::Dense::full >::calculate( M ); - std::cout << "Matrix< Dense::full, structure::General> " << n << " x " << n << " can be stored with " << elems << " elements.\n"; - - elems = grb::internal::DataElementsCalculator< double, grb::storage::Dense::full, grb::structures::Triangular >::calculate( M ); - std::cout << "Matrix< Dense::full, structure::Triangular> " << n << " x " << n << " can be stored with " << elems << " elements.\n"; - - // The following call does not work because the template cannot figure out that UpperTriangular is also Triangular. - // TODO: fix it - // grb::internal::DataElementsCalculator< double, grb::storage::Dense::full, grb::structures::UpperTriangular >::calculate( M ); - // std::cout << "Matrix< Dense::full, structure::UpperTriangular> " << n << " x " << n << " can be stored with " << elems << " elements.\n"; - - rc = grb::SUCCESS; -} - -int main( int argc, char ** argv ) { - // defaults - bool printUsage = false; - size_t in = 5; - - // error checking - if( argc > 2 ) { - printUsage = true; - } - if( argc == 2 ) { - size_t read; - std::istringstream ss( argv[ 1 ] ); - if( ! ( ss >> read ) ) { - std::cerr << "Error parsing first argument\n"; - printUsage = true; - } else if( ! ss.eof() ) { - std::cerr << "Error parsing first argument\n"; - printUsage = true; - } else if( read % 2 != 0 ) { - std::cerr << "Given value for n is odd\n"; - printUsage = true; - } else { - // all OK - in = read; - } - } - if( printUsage ) { - std::cerr << "Usage: " << argv[ 0 ] << " [n]\n"; - std::cerr << " -n (optional, default is 100): an even integer, the " - "test size.\n"; - return 1; - } - - std::cout << "This is functional test " << argv[ 0 ] << "\n"; - grb::Launcher< grb::AUTOMATIC > launcher; - grb::RC out; - if( launcher.exec( &grb_program, in, out, true ) != grb::SUCCESS ) { - std::cerr << "Launching test FAILED\n"; - return 255; - } - if( out != grb::SUCCESS ) { - std::cerr << "Test FAILED (" << grb::toString( out ) << ")" << std::endl; - } else { - std::cout << "Test OK" << std::endl; - } - return 0; -} From b658fe9562a6b07eee9c762697222313eb5a3fbe Mon Sep 17 00:00:00 2001 From: Anonymous Date: Fri, 25 Feb 2022 09:27:19 +0100 Subject: [PATCH 076/282] draft of selection and range views. --- include/graphblas/denseref/matrix.hpp | 59 +++++++++++++++++++-------- include/graphblas/imf.hpp | 25 ++++++++++++ include/graphblas/structures.hpp | 3 +- include/graphblas/utils.hpp | 14 +++++++ tests/unit/dense_matrix_imf.cpp | 25 ++++++------ 5 files changed, 96 insertions(+), 30 deletions(-) diff --git a/include/graphblas/denseref/matrix.hpp b/include/graphblas/denseref/matrix.hpp index 5de25d321..db00d6162 100644 --- a/include/graphblas/denseref/matrix.hpp +++ b/include/graphblas/denseref/matrix.hpp @@ -25,6 +25,7 @@ #include #include +#include #include #include @@ -690,29 +691,55 @@ namespace grb { return smat_trans; } - /** - * Implement a gather through a View over compatible Structure using provided Index Mapping Functions. - * The compatibility depends on the TargetStructure, SourceStructure and IMFs, and is calculated during runtime. - */ + namespace internal { + /** + * Implement a gather through a View over compatible Structure using provided Index Mapping Functions. + * The compatibility depends on the TargetStructure, SourceStructure and IMFs, and is calculated during runtime. + */ - template< typename TargetStructure, typename T, typename Structure, typename StorageSchemeType, typename View, enum Backend backend > - StructuredMatrix< T, TargetStructure, StorageSchemeType, view::Identity< StructuredMatrix< T, Structure, StorageSchemeType, View, backend > >, backend > - get_view( StructuredMatrix< T, Structure, StorageSchemeType, View, backend > &source, - std::shared_ptr< imf::IMF > imf_r, std::shared_ptr< imf::IMF > imf_c ) { + template< typename TargetStructure, typename T, typename Structure, typename StorageSchemeType, typename View, enum Backend backend > + StructuredMatrix< T, TargetStructure, StorageSchemeType, view::Identity< StructuredMatrix< T, Structure, StorageSchemeType, View, backend > >, backend > + get_view( StructuredMatrix< T, Structure, StorageSchemeType, View, backend > &source, + std::shared_ptr< imf::IMF > imf_r, std::shared_ptr< imf::IMF > imf_c ) { + + if( dynamic_cast< imf::Select >( imf_r ) == nullptr || dynamic_cast< imf::Select >( imf_c ) == nullptr ) { + throw std::runtime_error("Cannot gather with imf::Select yet."); + } + // No static check as the compatibility depends on IMF, which is a runtime level parameter + if( ! TargetStructure::isInstantiableFrom( source, * imf_r, * imf_c ) ) { + throw std::runtime_error("Cannot gather into specified TargetStructure from provided SourceStructure and Index Mapping Functions."); + } - // No static check as the compatibility depends on IMF, which is a runtime level parameter + using source_strmat_t = StructuredMatrix< T, Structure, StorageSchemeType, View, backend >; + using target_strmat_t = StructuredMatrix< T, TargetStructure, StorageSchemeType, view::Identity< source_strmat_t >, backend >; - if( ! TargetStructure::isInstantiableFrom( source, * imf_r, * imf_c ) ) { - throw std::runtime_error("Cannot gather into specified TargetStructure from provided SourceStructure and Index Mapping Functions."); + target_strmat_t target( source, imf_r, imf_c ); + + return target; } + } // namespace internal - using source_strmat_t = StructuredMatrix< T, Structure, StorageSchemeType, View, backend >; - using target_strmat_t = StructuredMatrix< T, TargetStructure, StorageSchemeType, view::Identity< source_strmat_t >, backend >; + template< typename TargetStructure, typename T, typename Structure, typename StorageSchemeType, typename View, enum Backend backend > + StructuredMatrix< T, TargetStructure, StorageSchemeType, view::Identity< StructuredMatrix< T, Structure, StorageSchemeType, View, backend > >, backend > + get_view( StructuredMatrix< T, Structure, StorageSchemeType, View, backend > &source, + const utils::range& rng_r, const utils::range& rng_c ) { + + auto imf_r = std::make_shared< imf::Strided >( rng_r.count(), nrows(source), rng_r.start, rng_r.stride ); + auto imf_c = std::make_shared< imf::Strided >( rng_c.count(), ncols(source), rng_c.start, rng_c.stride ); - target_strmat_t target( source, imf_r, imf_c ); + return internal::get_view( source, imf_r, imf_c ); + } - return target; - } + template< typename TargetStructure, typename T, typename Structure, typename StorageSchemeType, typename View, enum Backend backend > + StructuredMatrix< T, TargetStructure, StorageSchemeType, view::Identity< StructuredMatrix< T, Structure, StorageSchemeType, View, backend > >, backend > + get_view( StructuredMatrix< T, Structure, StorageSchemeType, View, backend > &source, + const std::vector< size_t >& sel_r, const std::vector< size_t >& sel_c ) { + + auto imf_r = std::make_shared< imf::Select >( nrows(source), sel_r ); + auto imf_c = std::make_shared< imf::Strided >( ncols(source), sel_c ); + + return internal::get_view( source, imf_r, imf_c ); + } /** Returns a constant reference to an Identity matrix of the provided size * */ diff --git a/include/graphblas/imf.hpp b/include/graphblas/imf.hpp index f1f29888f..31b190017 100644 --- a/include/graphblas/imf.hpp +++ b/include/graphblas/imf.hpp @@ -44,6 +44,10 @@ #define _H_GRB_IMF #include +#include +#include +#include + namespace grb { @@ -105,6 +109,27 @@ namespace grb { } }; + class Select: public IMF { + + public: + std::vector< size_t > select; + + size_t map(size_t i) { + return select.at( i ); + } + + Select(size_t N, std::vector< size_t > & select): IMF( select.size(), N ), select( select ) { + if ( *std::max_element( select.cbegin(), select.cend() ) >= N) { + throw std::runtime_error("IMF Select beyond range."); + } + } + + virtual bool isSame( const IMF & other ) const { + return IMF::isSame( other ) + && select == dynamic_cast< const Select & >( other ).select; + } + }; + /** * A composition of two IMFs. * \f$I_{g,n} =[0, n), I_{g,N} =[0, N)\f$ diff --git a/include/graphblas/structures.hpp b/include/graphblas/structures.hpp index 79105a84e..b0fc0821a 100644 --- a/include/graphblas/structures.hpp +++ b/include/graphblas/structures.hpp @@ -109,7 +109,8 @@ namespace grb { template< typename T, typename Storage, typename View, enum Backend backend > static bool isInstantiableFrom( const StructuredMatrix< T, UpperTriangular, Storage, View, backend > & M, grb::imf::IMF & imf_l, grb::imf::IMF & imf_r ) { (void)M; - return imf_l.map( 0 ) <= imf_r.map( imf_r.N ); + // return imf_l.map( 0 ) <= imf_r.map( imf_r.N ); + return imf_l.map( imf_l.n - 1 ) <= imf_r.map( 0 ) + 1; } template< typename T, typename Storage, typename View, enum Backend backend > diff --git a/include/graphblas/utils.hpp b/include/graphblas/utils.hpp index 35a3f3bf8..8757e3031 100644 --- a/include/graphblas/utils.hpp +++ b/include/graphblas/utils.hpp @@ -366,6 +366,20 @@ namespace grb { } } + /** + * @brief Simple range [ \a start, \a end) with optional \a stride. + * + */ + struct range { + size_t start, end, stride; + + range(size_t start, size_t end, size_t stride=1): start( start ), end( end ), stride( stride ) {} + + inline size_t count() const { + return (end - start)/stride; + } + }; + } // namespace utils } // namespace grb diff --git a/tests/unit/dense_matrix_imf.cpp b/tests/unit/dense_matrix_imf.cpp index b67a95f19..02e03fedb 100644 --- a/tests/unit/dense_matrix_imf.cpp +++ b/tests/unit/dense_matrix_imf.cpp @@ -43,8 +43,7 @@ void grb_program( const size_t & n, grb::RC & rc ) { try { auto Aview = grb::get_view< grb::structures::General >( A, - std::make_shared< grb::imf::Strided >( n, 2, 1, 1 ), - std::make_shared< grb::imf::Strided >( n, 4, 1, 1 ) + grb::utils::range(1,3), grb::utils::range(1,5) ); std::cout << "\tSUCCESS\n"; } catch( const std::exception & e ) { @@ -74,8 +73,8 @@ void grb_program( const size_t & n, grb::RC & rc ) { try { auto Uview1 = grb::get_view< grb::structures::UpperTriangular >( U, - std::make_shared< grb::imf::Strided >( n, 2, 1, 1 ), - std::make_shared< grb::imf::Strided >( n, 2, 1, 1 ) ); + grb::utils::range(1,3), grb::utils::range(1,3) + ); std::cout << "\tSUCCESS\n"; } catch( const std::exception & e ) { std::cerr << e.what() << "\n"; @@ -92,8 +91,8 @@ void grb_program( const size_t & n, grb::RC & rc ) { try { auto Uview2 = grb::get_view< grb::structures::General >( U, - std::make_shared< grb::imf::Strided >( n, 2, 0, 1 ), - std::make_shared< grb::imf::Strided >( n, 2, 3, 1 ) ); + grb::utils::range(0,2), grb::utils::range(3,5) + ); std::cout << "\tSUCCESS\n"; } catch( const std::exception & e ) { std::cerr << e.what() << "\n"; @@ -101,17 +100,17 @@ void grb_program( const size_t & n, grb::RC & rc ) { // Invalid block - selecting a block that is not UpperTriangular std::cout << "Gather to UpperTriangular (expect failure)\n" - "|x x x A A x|\n" - "|. x x A A x|\n" - "|. . x x x x|\n" + "|x x x x x x|\n" + "|. A A A A x|\n" + "|. A A A A x|\n" "|. . . x x x|\n" "|. . . . x x|\n" "|. . . . . x|\n"; try { auto Uview3 = grb::get_view< grb::structures::UpperTriangular >( U, - std::make_shared< grb::imf::Strided >( n, 2, 0, 1 ), - std::make_shared< grb::imf::Strided >( n, 2, 3, 1 ) ); + grb::utils::range(1,3), grb::utils::range(1,5) + ); std::cout << "\tSUCCESS\n"; } catch( const std::exception & e ) { std::cerr << e.what() << "\n"; @@ -128,8 +127,8 @@ void grb_program( const size_t & n, grb::RC & rc ) { try { auto Uview4 = grb::get_view< grb::structures::General >( U, - std::make_shared< grb::imf::Strided >( n, 2, 4, 1 ), - std::make_shared< grb::imf::Strided >( n, 2, 0, 1 ) ); + grb::utils::range(4,n), grb::utils::range(0,2) + ); std::cout << "\tSUCCESS\n"; } catch( const std::exception & e ) { std::cerr << e.what() << "\n"; From 23614d56c4f54150b873031d251d2c796c02b025 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Fri, 25 Feb 2022 11:58:31 +0100 Subject: [PATCH 077/282] Using default coords template param for VectorView. --- include/graphblas/denseref/alloc.hpp | 157 -------------------------- include/graphblas/denseref/matrix.hpp | 4 +- include/graphblas/denseref/vector.hpp | 102 +++++++++-------- include/graphblas/structures.hpp | 3 +- include/graphblas/vector.hpp | 3 +- 5 files changed, 60 insertions(+), 209 deletions(-) diff --git a/include/graphblas/denseref/alloc.hpp b/include/graphblas/denseref/alloc.hpp index 7bc555c26..f340c506f 100644 --- a/include/graphblas/denseref/alloc.hpp +++ b/include/graphblas/denseref/alloc.hpp @@ -23,166 +23,9 @@ #ifndef _H_GRB_DENSEREF_ALLOC #define _H_GRB_DENSEREF_ALLOC -#include - -#include - -#include "config.hpp" namespace grb { - namespace utils { - namespace internal { - - /** - * \internal AllocatorFunctions< reference_dense > is an exact copy of - * AllocatorFunctions< reference > as they provide exactly the same functionalities. - * TODO: Think if it makes sense to merge them together and, if so, how. - */ - - /** - * Provides standard allocation mechanisms using the POSIX and libnuma - * -# posix_memalign() and - * -# numa_alloc_interleaved() - * system calls. - * - * When one of these functions are not available a different allocation - * mechanism must be selected. - */ - template<> - class AllocatorFunctions< reference_dense > { - private: - /** Disable instantiation. */ - AllocatorFunctions() {} - - public: - /** - * Allocates a single chunk of memory. - * - * @param[in,out] allocd Running accumulation of memory that has been allocated. - */ - template< typename T > - static RC mode_alloc( T * __restrict__ &pointer, const size_t elements, - const grb::config::ALLOC_MODE mode, utils::AutoDeleter< T > &deleter, - size_t &allocd - ) { - // catch trivial case - if( elements == 0 ) { - pointer = NULL; - return SUCCESS; - } - // non-trivial case, first compute size - const size_t size = elements * sizeof( T ); - // check if the region is supposed to be shared or not - if( mode == grb::config::ALLOC_MODE::INTERLEAVED ) { -#ifdef _GRB_NO_LIBNUMA - return UNSUPPORTED; -#else - // allocate - pointer = static_cast< T * >( numa_alloc_interleaved( size ) ); - // check for error - if( pointer == NULL ) { - return OUTOFMEM; - } - // record appropriate deleter - deleter = utils::AutoDeleter< T >( pointer, size ); -#endif - } else if( mode == grb::config::ALLOC_MODE::ALIGNED ) { - // allocate - void * new_pointer = NULL; - const int prc = posix_memalign( &new_pointer, grb::config::CACHE_LINE_SIZE::value(), size ); - // check for error - if( prc == ENOMEM ) { - return OUTOFMEM; - } - if( prc != 0 ) { - return PANIC; - } - // record pointer - pointer = static_cast< T * >( new_pointer ); - // record appropriate deleter - deleter = utils::AutoDeleter< T >( pointer, 0 ); - } else { - // we should never reach this code block - assert( false ); - return PANIC; - } - // final sanity check - assert( pointer != NULL ); - // record memory taken - allocd += size; - // done - return SUCCESS; - } - - /** Allocates a single chunk of memory. Wrapper function that relies on the config parameters in #grb::config::MEMORY. */ - template< typename T > - static RC single_alloc( T * __restrict__ & pointer, const size_t elements, const bool shared, utils::AutoDeleter< T > & deleter, size_t & allocd ) { - if( shared ) { - return mode_alloc( pointer, elements, grb::config::IMPLEMENTATION<>::sharedAllocMode(), deleter, allocd ); - } else { - return mode_alloc( pointer, elements, grb::config::IMPLEMENTATION<>::defaultAllocMode(), deleter, allocd ); - } - } - - /** Base case for internal::alloc (variadic version). */ - template< typename T > - static RC alloc( size_t & allocd, T * __restrict__ & pointer, const size_t size, const bool shared, utils::AutoDeleter< T > & deleter ) { - // try new alloc - T * __restrict__ new_pointer = NULL; - utils::AutoDeleter< T > new_deleter; - RC recursive_error_code = single_alloc( new_pointer, size, shared, new_deleter, allocd ); - // if OK, set output pointer to newly allocated memory - if( recursive_error_code == SUCCESS ) { - pointer = new_pointer; - deleter = new_deleter; - } - // done - return recursive_error_code; - } - - /** Allocates multiple memory segments in a safe way. */ - template< typename T, typename... Targs > - static RC alloc( size_t & allocd, T * __restrict__ & pointer, const size_t size, const bool shared, utils::AutoDeleter< T > & deleter, Targs &&... args ) { - // set local deleter - utils::AutoDeleter< T > new_deleter; - // try new alloc - T * __restrict__ new_pointer = NULL; - RC recursive_error_code = single_alloc( new_pointer, size, shared, new_deleter, allocd ); - // check for success - if( recursive_error_code != SUCCESS ) { - // fail, so propagate - return recursive_error_code; - } - // recurse on remainder arguments - recursive_error_code = alloc( allocd, std::forward< Targs >( args )... ); - // check for failure - if( recursive_error_code != SUCCESS ) { - // fail, so reset old pointer and propagate error code - return recursive_error_code; - } - // all is OK, so finally 1) set pointer to newly allocated memory area and 2) propagate the deleter to user space - pointer = new_pointer; - deleter = new_deleter; - // done - return SUCCESS; - } - - /** Helper function that prints allocation information to stdout. */ - static void postAlloc( const RC ret, const size_t allocd, const std::string prefix, const std::string postfix ) { - if( ret == SUCCESS ) { - if( config::MEMORY::report( prefix, "allocated", allocd, false ) ) { - std::cout << postfix << ".\n"; - } - } else { - if( config::MEMORY::report( prefix, "failed to allocate", allocd, false ) ) { - std::cout << postfix << ".\n"; - } - } - } - }; - } // namespace internal - } // namespace utils } // namespace grb #endif diff --git a/include/graphblas/denseref/matrix.hpp b/include/graphblas/denseref/matrix.hpp index db00d6162..66e774dcd 100644 --- a/include/graphblas/denseref/matrix.hpp +++ b/include/graphblas/denseref/matrix.hpp @@ -702,7 +702,7 @@ namespace grb { get_view( StructuredMatrix< T, Structure, StorageSchemeType, View, backend > &source, std::shared_ptr< imf::IMF > imf_r, std::shared_ptr< imf::IMF > imf_c ) { - if( dynamic_cast< imf::Select >( imf_r ) == nullptr || dynamic_cast< imf::Select >( imf_c ) == nullptr ) { + if( std::dynamic_pointer_cast< imf::Select >( imf_r ) || std::dynamic_pointer_cast< imf::Select >( imf_c ) ) { throw std::runtime_error("Cannot gather with imf::Select yet."); } // No static check as the compatibility depends on IMF, which is a runtime level parameter @@ -736,7 +736,7 @@ namespace grb { const std::vector< size_t >& sel_r, const std::vector< size_t >& sel_c ) { auto imf_r = std::make_shared< imf::Select >( nrows(source), sel_r ); - auto imf_c = std::make_shared< imf::Strided >( ncols(source), sel_c ); + auto imf_c = std::make_shared< imf::Select >( ncols(source), sel_c ); return internal::get_view( source, imf_r, imf_c ); } diff --git a/include/graphblas/denseref/vector.hpp b/include/graphblas/denseref/vector.hpp index 34e698c69..85073fb46 100644 --- a/include/graphblas/denseref/vector.hpp +++ b/include/graphblas/denseref/vector.hpp @@ -48,24 +48,34 @@ namespace grb { namespace internal { - template< typename T > - T * getRaw( Vector< T, reference_dense, void > & ) noexcept; + template< typename T, typename C > + T * getRaw( Vector< T, reference_dense, C > & ) noexcept; - template< typename T > - const T * getRaw( const Vector< T, reference_dense, void > & ) noexcept; + template< typename T, typename C > + const T * getRaw( const Vector< T, reference_dense, C > & ) noexcept; - template< typename T > - size_t getLength( const Vector< T, reference_dense, void > & ) noexcept; + template< typename T, typename C > + size_t getLength( const Vector< T, reference_dense, C > & ) noexcept; } // end namespace ``grb::internal'' - /** \internal TODO */ - template< typename T > - class Vector< T, reference_dense, void > { + /** + * The reference implementation of the ALP/Dense vector. + * + * @tparam D The type of an element of this vector. \a D shall not be a + * GraphBLAS type. + * + * \warning Creating a grb::Vector of other GraphBLAS types is + * not allowed. + * Passing a GraphBLAS type as template parameter will lead to + * undefined behaviour. + */ + template< typename T, typename C > + class Vector< T, reference_dense, C > { - friend T * internal::getRaw< T >( Vector< T, reference_dense, void > & ) noexcept; - friend const T * internal::getRaw< T >( const Vector< T, reference_dense, void > & ) noexcept; - friend size_t internal::getLength< T >( const Vector< T, reference_dense, void > & ) noexcept; + friend T * internal::getRaw< T >( Vector< T, reference_dense, C > & ) noexcept; + friend const T * internal::getRaw< T >( const Vector< T, reference_dense, C > & ) noexcept; + friend size_t internal::getLength< T >( const Vector< T, reference_dense, C > & ) noexcept; private: @@ -168,26 +178,26 @@ namespace grb { }; /** Identifies any reference_dense vector as an ALP vector. */ - template< typename T > - struct is_container< Vector< T, reference_dense, void > > { + template< typename T, typename C > + struct is_container< Vector< T, reference_dense, C > > { /** A reference_vector is an ALP object. */ static const constexpr bool value = true; }; namespace internal { - template< typename T > - T * getRaw( Vector< T, reference_dense, void > &v ) noexcept { + template< typename T, typename C > + T * getRaw( Vector< T, reference_dense, C > &v ) noexcept { return v.data; } - template< typename T > - const T * getRaw( Vector< T, reference_dense, void > &v ) noexcept { + template< typename T, typename C > + const T * getRaw( Vector< T, reference_dense, C > &v ) noexcept { return v.data; } - template< typename T > - size_t getLength( const Vector< T, reference_dense, void > &v ) noexcept { + template< typename T, typename C > + size_t getLength( const Vector< T, reference_dense, C > &v ) noexcept { return v.n; } @@ -203,25 +213,25 @@ namespace grb { /** * Identity View over a vector container. */ - template< typename T, typename View > - size_t getLength( const VectorView< T, View, storage::Dense, reference_dense, void > &v ) noexcept { + template< typename T, typename View, typename C > + size_t getLength( const VectorView< T, View, storage::Dense, reference_dense, C > &v ) noexcept { return v._length(); } - template< typename T> - class VectorView< T, view::Identity< void >, storage::Dense, reference_dense, void > { + template< typename T, typename C > + class VectorView< T, view::Identity< void >, storage::Dense, reference_dense, C > { private: /********************* Storage info friends ******************** */ - using self_type = VectorView< T, view::Identity< void >, storage::Dense, reference_dense, void >; + using self_type = VectorView< T, view::Identity< void >, storage::Dense, reference_dense, C >; friend size_t getLength<>( const self_type & ) noexcept; // Physical layout - std::unique_ptr< Vector< T, reference_dense, void > > v; + std::unique_ptr< Vector< T, reference_dense, C > > v; std::shared_ptr imf; @@ -235,13 +245,13 @@ namespace grb { public: using value_type = T; - VectorView( const size_t length ) : v( std::make_unique< Vector< T, reference_dense, void > >( length ) ), imf( std::make_shared< imf::Id >( length ) ), initialized( false ) {} + VectorView( const size_t length ) : v( std::make_unique< Vector< T, reference_dense, C > >( length ) ), imf( std::make_shared< imf::Id >( length ) ), initialized( false ) {} }; // class VectorView with physical container /** Identifies any reference_dense vector as an ALP vector. */ - template< typename T, typename View, typename Storage > - struct is_container< VectorView< T, View, Storage, reference_dense, void > > { + template< typename T, typename View, typename Storage, typename C > + struct is_container< VectorView< T, View, Storage, reference_dense, C > > { /** A reference_vector is an ALP object. */ static const constexpr bool value = true; }; @@ -249,11 +259,11 @@ namespace grb { /** * Vector view of a vector only via \a view::Identity of another VectorView. */ - template< typename T, typename VectorViewT > - class VectorView< T, view::Identity< VectorViewT >, storage::Dense, reference_dense, void > { + template< typename T, typename VectorViewT, typename C > + class VectorView< T, view::Identity< VectorViewT >, storage::Dense, reference_dense, C > { private: - using self_type = VectorView< T, view::Identity< VectorViewT >, storage::Dense, reference_dense, void >; + using self_type = VectorView< T, view::Identity< VectorViewT >, storage::Dense, reference_dense, C >; using target_type = VectorViewT; /********************* @@ -292,11 +302,11 @@ namespace grb { /** * Diagonal Vector View of a structured matrix. */ - template< typename T, typename StructuredMatrixT > - class VectorView< T, view::Diagonal< StructuredMatrixT >, storage::Dense, reference_dense, void > { + template< typename T, typename StructuredMatrixT, typename C > + class VectorView< T, view::Diagonal< StructuredMatrixT >, storage::Dense, reference_dense, C > { private: - using self_type = VectorView< T, view::Diagonal< StructuredMatrixT >, storage::Dense, reference_dense, void >; + using self_type = VectorView< T, view::Diagonal< StructuredMatrixT >, storage::Dense, reference_dense, C >; using target_type = StructuredMatrixT; /********************* @@ -326,11 +336,11 @@ namespace grb { }; // Diagonal Vector view - template< typename StructuredMatrixT > - VectorView< typename StructuredMatrixT::value_type, view::Diagonal< StructuredMatrixT >, storage::Dense, reference_dense, void > + template< typename StructuredMatrixT, typename C > + VectorView< typename StructuredMatrixT::value_type, view::Diagonal< StructuredMatrixT >, storage::Dense, reference_dense, C > diagonal( StructuredMatrixT &smat ) { - VectorView< typename StructuredMatrixT::value_type, view::Diagonal< StructuredMatrixT >, storage::Dense, reference_dense, void > smat_diag( smat ); + VectorView< typename StructuredMatrixT::value_type, view::Diagonal< StructuredMatrixT >, storage::Dense, reference_dense, C > smat_diag( smat ); return smat_diag; } @@ -338,11 +348,11 @@ namespace grb { /** * Generate an identity view of a VectorView. */ - template< typename T, typename View, typename StorageSchemeType, enum Backend backend > - VectorView< T, view::Identity< VectorView< T, View, StorageSchemeType, backend, void > >, StorageSchemeType, backend, void > - get_view( VectorView< T, View, StorageSchemeType, backend, void > &source ) { + template< typename T, typename View, typename StorageSchemeType, enum Backend backend, typename C > + VectorView< T, view::Identity< VectorView< T, View, StorageSchemeType, backend, C > >, StorageSchemeType, backend, C > + get_view( VectorView< T, View, StorageSchemeType, backend, C > &source ) { - VectorView< T, view::Identity< VectorView< T, View, StorageSchemeType, backend, void > >, StorageSchemeType, backend, void > vec_view( source ); + VectorView< T, view::Identity< VectorView< T, View, StorageSchemeType, backend, C > >, StorageSchemeType, backend, C > vec_view( source ); return vec_view; } @@ -351,11 +361,11 @@ namespace grb { * Implement a gather through a View over compatible Structure using provided Index Mapping Functions. */ - template< typename T, typename View, typename StorageSchemeType, enum Backend backend > - VectorView< T, view::Identity< VectorView< T, View, StorageSchemeType, backend, void > >, StorageSchemeType, backend, void > - get_view( VectorView< T, View, StorageSchemeType, backend, void > &source, std::shared_ptr< imf::IMF > imf ) { + template< typename T, typename View, typename StorageSchemeType, enum Backend backend, typename C > + VectorView< T, view::Identity< VectorView< T, View, StorageSchemeType, backend, C > >, StorageSchemeType, backend, C > + get_view( VectorView< T, View, StorageSchemeType, backend, C > &source, std::shared_ptr< imf::IMF > imf ) { - VectorView< T, view::Identity< VectorView< T, View, StorageSchemeType, backend, void > >, StorageSchemeType, backend, void > vec_view( source, imf ); + VectorView< T, view::Identity< VectorView< T, View, StorageSchemeType, backend, C > >, StorageSchemeType, backend, C > vec_view( source, imf ); return vec_view; } diff --git a/include/graphblas/structures.hpp b/include/graphblas/structures.hpp index b0fc0821a..fbebc280e 100644 --- a/include/graphblas/structures.hpp +++ b/include/graphblas/structures.hpp @@ -109,8 +109,7 @@ namespace grb { template< typename T, typename Storage, typename View, enum Backend backend > static bool isInstantiableFrom( const StructuredMatrix< T, UpperTriangular, Storage, View, backend > & M, grb::imf::IMF & imf_l, grb::imf::IMF & imf_r ) { (void)M; - // return imf_l.map( 0 ) <= imf_r.map( imf_r.N ); - return imf_l.map( imf_l.n - 1 ) <= imf_r.map( 0 ) + 1; + return imf_l.map( imf_l.n - 1 ) <= imf_r.map( 0 ); } template< typename T, typename Storage, typename View, enum Backend backend > diff --git a/include/graphblas/vector.hpp b/include/graphblas/vector.hpp index d74a6425a..53c72097d 100644 --- a/include/graphblas/vector.hpp +++ b/include/graphblas/vector.hpp @@ -57,8 +57,7 @@ namespace grb { /* * The default value of \a StorageSchemeType could also be made conditional (Dense or Sparse) depending on \a config::default_backend */ - // template< typename T, typename View = view::Identity< void >, typename StorageSchemeType = storage::Dense, enum Backend backend = config::default_backend, typename C = internal::DefaultCoordinates > - template< typename T, typename View = view::Identity< void >, typename StorageSchemeType = storage::Dense, enum Backend backend = config::default_backend, typename C = void > + template< typename T, typename View = view::Identity< void >, typename StorageSchemeType = storage::Dense, enum Backend backend = config::default_backend, typename C = internal::DefaultCoordinates > class VectorView; } From d5cfcf0d958e5bfc00a0dbdc5493e7cfb9a586d4 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Sun, 27 Feb 2022 21:26:27 +0100 Subject: [PATCH 078/282] Added matrix-related doxygen draft. In need of compilation check (had to push to from machine without compiler support). --- include/graphblas/base/matrix.hpp | 64 +-- include/graphblas/denseref/alloc.hpp | 2 +- include/graphblas/denseref/benchmark.hpp | 70 --- include/graphblas/denseref/io.hpp | 121 ++++- include/graphblas/denseref/matrix.hpp | 614 ++++++++++++++++------- include/graphblas/imf.hpp | 14 +- include/graphblas/matrix.hpp | 2 +- include/graphblas/storage.hpp | 14 +- include/graphblas/structures.hpp | 101 ++-- 9 files changed, 646 insertions(+), 356 deletions(-) diff --git a/include/graphblas/base/matrix.hpp b/include/graphblas/base/matrix.hpp index 360e56d3c..38cf3f4b4 100644 --- a/include/graphblas/base/matrix.hpp +++ b/include/graphblas/base/matrix.hpp @@ -437,69 +437,7 @@ RC clear( Matrix< InputType, backend > & A ) noexcept { return UNSUPPORTED; } -/** - * \brief An ALP structured matrix. - * - * This is an opaque data type for structured matrices. - * This container allows to maintain the interface of grb::Matrix and grb::Vector - * unaltered enabling back-compatibility while building on them to create - * semantically reacher algebraic objects. - * A structured matrix is generalized over five parameters further described - * below: its data type, - * its structure, whether it is stored using a dense or sparse storage scheme, - * a static view and the backend for which it is implemented. - * At a high level of abstraction a structured matrix exposes a mathematical - * \em logical layout which allows to express implementation-oblivious concepts - * (e.g., the transpose of a symmetric matrix). - * At the lowest level, the logical layout maps to its physical counterpart via - * a particular choice of a storage scheme within those exposed by the chosen - * backend. grb::Matrix and grb::Vector are used as interfaces to the physical - * layout. - * To visualize this, you could think of a band matrix. Using either the - * \a storage::Dense:full or \a storage::Dense:band storage schemes would require - * the use of a \a grb::Matrix container (see include/graphblas/storage.hpp for - * more details about the two storage schemes). However, the interpration of its - * content would differ in the two cases being a function of both the Structure - * information and the storage scheme combined. - * - * Views can be used to create logical \em perspectives on top of a container. - * For example, I could decide to refer to the transpose of a matrix or to see - * a for limited part of my program a square matrix as symmetric. - * If a view can be expressed as concept invariant of specific runtime features, - * such views can be defined statically (for example I can always refer to the - * transpose or the diagonal of a matrix irrespective of features such as its - * size). Other may depend on features such as the size of a matrix - * and can be expressed as linear transformations via operations such as \a mxm - * (e.g., gathering/scattering the rows/columns of a matrix or permuting them). - * Structured matrices defined as views on other matrices do not instantiate a - * new container but refer to the one used by their targets. (See the - * documentation of StructuredMatrix for both scenarios within the \em denseref - * backend folder). - * - * @tparam T The type of the matrix elements. \a T shall not be a GraphBLAS - * type. - * @tparam Structure One of the matrix structures in \a grb::structures. - * @tparam StorageSchemeType Either \em enum \a storage::Dense or \em enum - * \a storage::Sparse. - * A StructuredMatrix will be allowed to pick among the storage schemes - * within their specified \a StorageSchemeType. - * @tparam View One of the matrix views in \a grb::view. - * All static views except for \a view::Identity (via - * \a view::identity cannot instantiate a new container and only - * allow to refer to an existing \a StructuredMatrix. - * The \a View parameter should not be used directly by the user but - * can be set using specific member types appropriately - * defined by each StructuredMatrix. (See examples of StructuredMatrix - * definitions within \a include/graphblas/denseref/matrix.hpp and the - * \a dense_structured_matrix.cpp unit test). - * @tparam backend Allows multiple backends to implement different versions - * of this data type. - * - * \note The presence of different combination of structures and views could - * produce many specialization with lots of logic replication. We might - * could use some degree of inheritence to limit this. - */ -template< typename T, typename Structure, typename StorageSchemeType, typename View, enum Backend backend > +template< typename T, typename Structure, typename StorageSchemeType, typename View, enum Backend backend, bool tmp > class StructuredMatrix { diff --git a/include/graphblas/denseref/alloc.hpp b/include/graphblas/denseref/alloc.hpp index f340c506f..e5cf3d14e 100644 --- a/include/graphblas/denseref/alloc.hpp +++ b/include/graphblas/denseref/alloc.hpp @@ -5,7 +5,7 @@ * 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 diff --git a/include/graphblas/denseref/benchmark.hpp b/include/graphblas/denseref/benchmark.hpp index fc388fac6..d3c162cb9 100644 --- a/include/graphblas/denseref/benchmark.hpp +++ b/include/graphblas/denseref/benchmark.hpp @@ -28,76 +28,6 @@ namespace grb { - template< enum EXEC_MODE mode > - class Benchmarker< mode, reference_dense > : protected Launcher< mode, reference >, protected internal::BenchmarkerBase { - - public: - - /** \internal No implementation notes */ - Benchmarker( size_t process_id = 0, - size_t nprocs = 1, - std::string hostname = "localhost", - std::string port = "0" - ) : Launcher< mode, reference >( process_id, nprocs, hostname, port ) {} - - /** \internal No implementation notes */ - template< typename U > - RC exec( - void ( *grb_program )( const void *, const size_t, U & ), - const void * data_in, const size_t in_size, - U &data_out, - const size_t inner, const size_t outer, - const bool broadcast = false - ) const { - (void)broadcast; // value doesn't matter for a single user process - // initialise GraphBLAS - RC ret = init(); - // call graphBLAS algo - if( ret == SUCCESS ) { - benchmark< U >( grb_program, data_in, in_size, data_out, inner, outer, 0 ); - } - // finalise the GraphBLAS - const RC frc = finalize(); - if( ret == SUCCESS ) { - ret = frc; - } - // and done - return ret; - } - - /** No implementation notes. */ - template< typename T, typename U > - RC exec( void ( *grb_program )( const T &, U & ), - const T &data_in, - U &data_out, - const size_t inner, - const size_t outer, - const bool broadcast = false - ) { - (void)broadcast; // value doesn't matter for a single user process - // initialise GraphBLAS - RC ret = init(); - // call graphBLAS algo - if( ret == SUCCESS ) { - // call graphBLAS algo - benchmark< T, U >( grb_program, data_in, data_out, inner, outer, 0 ); - } - // finalise the GraphBLAS - const RC frc = finalize(); - if( ret == SUCCESS ) { - ret = frc; - } - // and done - return ret; - } - - /** No implementation notes. */ - static RC finalize() { - return Launcher< mode, reference >::finalize(); - } - - }; - } // end namespace ``grb'' #endif // end ``_H_GRB_DENSEREF_BENCH'' diff --git a/include/graphblas/denseref/io.hpp b/include/graphblas/denseref/io.hpp index 15a792491..d8cd872af 100644 --- a/include/graphblas/denseref/io.hpp +++ b/include/graphblas/denseref/io.hpp @@ -28,13 +28,130 @@ namespace grb { + /** + * Assigns elements to a matrix from an iterator. + * + * @tparam InputType The matrix's element type. + * @tparam fwd_iterator The source iterator type. + * + * The iterator \a fwd_iterator must be STL-compatible, may + * support the following three public functions: + * -# S fwd_iterator.i(); which returns the row index of the current + * nonzero; + * -# S fwd_iterator.j(); which returns the column index of the + * current nonzero; + * -# V fwd_iterator.v(); which returns the nonzero value of the + * current nonzero. + * + * It also may provide the following public typedefs: + * -# fwd_iterator::row_coordinate_type + * -# fwd_iterator::column_coordinate_type + * -# fwd_iterator::nonzero_value_type + * + * @param[in] _start Iterator pointing to the first element to be added. + * @param[in] _end Iterator pointing past the last element to be added. + * + * @return grb::MISMATCH -# the dimension of the input and output containers + * do not match. + * When this error code is returned the state of this + * container will be as though this function was never + * called; however, the given forward iterators may + * have been copied and the copied iterators may have + * incurred multiple increments and dereferences. + * @return grb::SUCCESS When the function completes successfully. + * + * \parblock + * \par Performance semantics. + * -# A call to this function will use \f$ \Theta(1) \f$ bytes + * of memory beyond the memory in use at the function call entry. + * -# This function will copy the input forward iterator at most + * \em once. + * -# This function moves + * \f$ \Theta(mn) \f$ bytes of data. + * -# This function will likely make system calls. + * \endparblock + * + * \warning This is an expensive function. Use sparingly and only when + * absolutely necessary. + * + */ + template< typename InputType, typename fwd_iterator > + RC buildMatrixUnique( Matrix< InputType, reference_dense > & A, fwd_iterator start, const fwd_iterator end ) { + return A.template buildMatrixUnique( start, end ); + } + + /** + * @brief \a buildMatrix version. The semantics of this function equals the one of + * \a buildMatrixUnique for the \a reference_dense backend. + * + * @see grb::buildMatrix + */ template< typename InputType, typename fwd_iterator > RC buildMatrix( Matrix< InputType, reference_dense > & A, fwd_iterator start, const fwd_iterator end ) { return A.template buildMatrixUnique( start, end ); } - template< typename InputType, typename Structure, typename Storage, typename View, typename fwd_iterator > - RC buildMatrix( StructuredMatrix< InputType, Structure, Storage, View, reference_dense > & A, const fwd_iterator & start, const fwd_iterator & end ) noexcept { + + /** + * Assigns elements to a structured matrix from an iterator. + * + * @tparam StructuredMatrixT The structured matrix type. + * @tparam fwd_iterator The source iterator type. + * + * The iterator \a fwd_iterator must be STL-compatible, may + * support the following three public functions: + * -# S fwd_iterator.i(); which returns the row index of the current + * nonzero; + * -# S fwd_iterator.j(); which returns the column index of the + * current nonzero; + * -# V fwd_iterator.v(); which returns the nonzero value of the + * current nonzero. + * + * It also may provide the following public typedefs: + * -# fwd_iterator::row_coordinate_type + * -# fwd_iterator::column_coordinate_type + * -# fwd_iterator::nonzero_value_type + * + * @param[in] _start Iterator pointing to the first element to be added. + * @param[in] _end Iterator pointing past the last element to be added. + * + * @return grb::MISMATCH -# the dimension of the input and output containers + * do not match. + * When this error code is returned the state of this + * container will be as though this function was never + * called; however, the given forward iterators may + * have been copied and the copied iterators may have + * incurred multiple increments and dereferences. + * @return grb::SUCCESS When the function completes successfully. + * + * \parblock + * \par Performance semantics. + * -# A call to this function will use \f$ \Theta(1) \f$ bytes + * of memory beyond the memory in use at the function call entry. + * -# This function will copy the input forward iterator at most + * \em once. + * -# This function moves + * \f$ \mathcal{O}(mn) \f$ bytes of data. + * -# This function will likely make system calls. + * \endparblock + * + * \warning This is an expensive function. Use sparingly and only when + * absolutely necessary. + * + */ + template< typename StructuredMatrixT, typename fwd_iterator > + RC buildMatrixUnique( StructuredMatrixT & A, const fwd_iterator & start, const fwd_iterator & end ) noexcept { + return A.template buildMatrixUnique( start, end ); + } + + /** + * @brief \a buildMatrix version. The semantics of this function equals the one of + * \a buildMatrixUnique for the \a reference_dense backend. + * + * @see grb::buildMatrix + */ + template< typename StructuredMatrixT, typename fwd_iterator > + RC buildMatrix( StructuredMatrixT & A, const fwd_iterator & start, const fwd_iterator & end ) noexcept { return A.template buildMatrixUnique( start, end ); } diff --git a/include/graphblas/denseref/matrix.hpp b/include/graphblas/denseref/matrix.hpp index 66e774dcd..d4d976fa4 100644 --- a/include/graphblas/denseref/matrix.hpp +++ b/include/graphblas/denseref/matrix.hpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -43,35 +44,43 @@ namespace grb { - template< typename T > - T * getRaw( Matrix< T, reference_dense > & ) noexcept; + template< typename D > + size_t nrows( const Matrix< D, reference_dense > & ) noexcept; - template< typename T > - const T * getRaw( const Matrix< T, reference_dense > & ) noexcept; + template< typename D > + size_t ncols( const Matrix< D, reference_dense > & ) noexcept; - template< typename T > - size_t nrows( const Matrix< T, reference_dense > & ) noexcept; + namespace internal { - template< typename T > - size_t ncols( const Matrix< T, reference_dense > & ) noexcept; + template< typename D > + D * getRaw( Matrix< D, reference_dense > & ) noexcept; - namespace internal { + template< typename D > + const D * getRaw( const Matrix< D, reference_dense > & ) noexcept; - template< typename T > - const bool & getInitialized( const grb::Matrix< T, reference_dense > & A ) noexcept { + template< typename D > + const bool & getInitialized( const grb::Matrix< D, reference_dense > & A ) noexcept { return A.initialized; } - template< typename T > - void setInitialized( grb::Matrix< T, reference_dense > & A, bool initialized ) noexcept { + template< typename D > + void setInitialized( grb::Matrix< D, reference_dense > & A, bool initialized ) noexcept { A.initialized = initialized; } } // namespace internal - /** \internal TODO */ - template< typename T > - class Matrix< T, reference_dense > { + /** + * ALP/Dense matrix container. + * + * A matrix is stored in full format. + * \a Matrix may be used by \a StructuredMatrix as a raw container. + * + * @tparam D The element type. + */ + template< typename D > + class Matrix< D, reference_dense > { + private: /* ********************* BLAS2 friends ********************* */ @@ -86,9 +95,9 @@ namespace grb { `Getter' friends ********************* */ - friend T * getRaw< T >( Matrix< T, reference_dense > & ) noexcept; + friend D * internal::getRaw< D >( Matrix< D, reference_dense > & ) noexcept; - friend const T * getRaw< T >( const Matrix< T, reference_dense > & ) noexcept; + friend const D * internal::getRaw< D >( const Matrix< D, reference_dense > & ) noexcept; /* ******************** IO friends @@ -103,33 +112,33 @@ namespace grb { template< typename DataType > friend void internal::setInitialized( grb::Matrix< DataType, reference_dense > & , bool ) noexcept; - private: - /** Our own type. */ typedef Matrix< T, reference_dense > self_type; /** * The number of rows. - * - * \internal Not declared const to be able to implement move in an elegant way. */ size_t m; /** * The number of columns. - * - * \internal Not declared const to be able to implement move in an elegant way. */ size_t n; + /** The container capacity (in elements). */ + size_t cap; + /** The matrix data. */ - T * __restrict__ data; + D * __restrict__ data; - /** Whether the container presently is uninitialized. */ + /** + * Whether the container presently is uninitialized. + * Matrix is in such state when the object is constructed. + */ bool initialized; - /** @see Matrix::buildMatrixUnique - * Returns RC::MISMATCH if the input size does not match the matrix storage size. - */ + /** + * @see grb::buildMatrixUnique + */ template< typename fwd_iterator > RC buildMatrixUnique( const fwd_iterator & _start, const fwd_iterator & _end ) { // detect trivial case @@ -155,10 +164,37 @@ namespace grb { public: /** @see Matrix::value_type */ - typedef T value_type; + typedef D value_type; - /** @see Matrix::Matrix() */ - Matrix( const size_t rows, const size_t columns ): m( rows ), n( columns ), initialized( false ) { + /** + * The main ALP/Dense matrix constructor. + * + * The constructed object will be uninitalised after successful construction. + * + * Requesting a matrix with zero \a rows or \a columns will yield an empty + * matrix. + * + * @param rows The number of rows in the new matrix. + * @param columns The number of columns in the new matrix. + * @param cap The capacity in terms of elements of the new matrix. Optional. + * + * @return SUCCESS This function never fails. + * + * \parblock + * \par Performance semantics. + * -# This constructor entails \f$ \Theta(1) \f$ amount of work. + * -# This constructor may allocate \f$ \Theta( \max{mn, cap} ) \f$ bytes + * of dynamic memory. + * -# This constructor will use \f$ \Theta(1) \f$ extra bytes of + * memory beyond that at constructor entry. + * -# This constructor incurs \f$ \Theta(1) \f$ data movement. + * -# This constructor \em may make system calls. + * \endparblock + * + * \warning Avoid the use of this constructor within performance critical + * code sections. + */ + Matrix( const size_t rows, const size_t columns, const size_t cap = 0 ): m( rows ), n( columns ), cap( std::max( m*n, cap ) ), initialized( false ) { // TODO Implement allocation properly if( m > 0 && n > 0) { data = new (std::nothrow) T[ m * n ]; @@ -172,23 +208,75 @@ namespace grb { } - /** @see Matrix::Matrix( const Matrix & ) */ - Matrix( const Matrix< T, reference_dense > & other ) : Matrix( other.m, other.n ) { + /** + * Copy constructor. + * + * @param other The matrix to copy. The initialization state of the copy + * reflects the state of \a other. + * + * \parblock + * \par Performance semantics. + * Allocates the same capacity as the \a other matrix, even if the + * actual number of elements contained in \a other is less. + * -# This constructor entails \f$ \Theta(1) \f$ amount of work. + * -# This constructor allocates \f$ \Theta(\max{mn, cap} ) \f$ bytes + * of dynamic memory. + * -# This constructor incurs \f$ \Theta(mn) \f$ of data + * movement. + * -# This constructor \em may make system calls. + * \endparblock + * + * \warning Avoid the use of this constructor within performance critical + * code sections. + */ + Matrix( const Matrix< D, reference_dense > & other ) : Matrix( other.m, other.n ) { initialized = other.initialized; } - /** @see Matrix::Matrix( Matrix&& ). */ + /** + * Move constructor. The new matrix equal the given + * matrix. Invalidates the use of the input matrix. + * + * @param[in] other The GraphBLAS matrix to move to this new instance. + * + * \parblock + * \par Performance semantics. + * -# This constructor entails \f$ \Theta(1) \f$ amount of work. + * -# This constructor will not allocate any new dynamic memory. + * -# This constructor will use \f$ \Theta(1) \f$ extra bytes of + * memory beyond that at constructor entry. + * -# This constructor will move \f$ \Theta(1) \f$ bytes of data. + * \endparblock + */ Matrix( self_type && other ) noexcept { moveFromOther( std::forward< self_type >( other ) ); } - /** * Move from temporary. */ + /** + * Move assignment operator. + * @see Matrix::Matrix( Matrix && ) + */ self_type & operator=( self_type && other ) noexcept { moveFromOther( std::forward< self_type >( other ) ); return *this; } - /** @see Matrix::~Matrix(). */ + /** + * Matrix destructor. + * + * \parblock + * \par Performance semantics. + * -# This destructor entails \f$ \Theta(1) \f$ amount of work. + * -# This destructor will not perform any memory allocations. + * -# This destructor will use \f$ \mathcal{O}(1) \f$ extra bytes of + * memory beyond that at constructor entry. + * -# This destructor will move \f$ \Theta(1) \f$ bytes of data. + * -# This destructor makes system calls. + * \endparblock + * + * \warning Avoid calling destructors from within performance critical + * code sections. + */ ~Matrix() { if( data != nullptr ) { delete [] data; @@ -196,20 +284,21 @@ namespace grb { } }; - // template specialisation for GraphBLAS type traits + /** + * @brief A reference_dense Matrix is an ALP object. + */ template< typename T > struct is_container< Matrix< T, reference_dense > > { - /** A reference_dense Matrix is a GraphBLAS object. */ static const constexpr bool value = true; }; template< typename T > - T * getRaw( Matrix< T, reference_dense > & m ) noexcept { + T * internal::getRaw( Matrix< T, reference_dense > & m ) noexcept { return m.data; } template< typename T > - const T * getRaw( const Matrix< T, reference_dense > & m ) noexcept { + const T * internal::getRaw( const Matrix< T, reference_dense > & m ) noexcept { return m.data; } @@ -223,6 +312,11 @@ namespace grb { return m.n; } + + + // StructuredMatrix-related implementation + + namespace internal { /** Forward declaration */ template< typename T > @@ -270,10 +364,6 @@ namespace grb { } } // namespace internal - /** - * Here starts spec draft for StructuredMatrix - */ - template< typename D, typename Structure, typename View > size_t nrows( const StructuredMatrix< D, Structure, storage::Dense, View, reference_dense > & A ) noexcept { return internal::nrows( A ); @@ -358,13 +448,12 @@ namespace grb { /** * A container's storage scheme. \a storage_scheme is not exposed to the user as an option * but can defined by ALP at different points in the execution depending on the \a backend choice. - * For example, if the container is associated to an I/O matrix, with a reference backend - * it might be set to reflect the storage scheme of the user data as specified at buildMatrix. - * If \a backend is set to \a mlir then the scheme could be fixed by the JIT compiler to effectively - * support its optimization strategy. - * At construction time and until the moment the scheme decision is made it may be set to - * an appropriate default choice, e.g. if \a StorageSchemeType is \a storage::Dense then - * \a storage::Dense::full could be used. + * In particular, if the structured matrix is not a temporary matrix than it is fixed at construction + * time when the allocation takes place. + * If the structured matrix is a temporary one than a storage storage scheme choice may or may not be + * made depending on whether a decision about instantiating the matrix is made by the framework. + * + * The specific storage scheme choice depends on the chosen backend and the structure of the matrix. */ storage::Dense storage_scheme; @@ -391,33 +480,80 @@ namespace grb { }; } // namespace internal - template< typename T, typename Structure > - class StructuredMatrix< T, Structure, storage::Dense, view::Identity< void >, reference_dense > : - public internal::StructuredMatrixContainer< T > { - - private: - /********************* - Storage info friends - ******************** */ - - using self_type = StructuredMatrix< T, Structure, storage::Dense, view::Identity< void >, reference_dense >; - - template< typename fwd_iterator > - friend RC buildMatrix( const StructuredMatrix< T, Structure, storage::Dense, view::Identity< void >, reference_dense > &, const fwd_iterator &, const fwd_iterator ) noexcept; - - public: - using value_type = T; - using structure = Structure; - - // A general Structure knows how to define a reference to itself (which is an identity reference view). - using identity_t = StructuredMatrix< T, Structure, storage::Dense, view::Identity< self_type >, reference_dense >; - - StructuredMatrix( const size_t rows, const size_t cols ) : - internal::StructuredMatrixContainer< T >( rows, cols ) {} - }; // class StructuredMatrix + /** + * \brief An ALP structured matrix. + * + * This is an opaque data type for structured matrices. + * + * A structured matrix exposes a mathematical + * \em logical layout which allows to express implementation-oblivious concepts + * including the matrix structure itself and \em views on the matrix. + * The logical layout of a structured matrix maps to a physical counterpart via + * a storage scheme which typically depends on the chosen structure and the selected + * backend. grb::Matrix and grb::Vector may be used as interfaces to such a physical + * layout. + * To visualize this, you may think of a band matrix. Using a + * \a storage::Dense:full or a \a storage::Dense:band storage schemes would require + * the use of a \a grb::Matrix container (see include/graphblas/storage.hpp for + * more details about the two storage schemes). However, the interpration of its + * content would differ in the two cases being a function of both the Structure + * information and the storage scheme combined. + * + * Views can be used to create logical \em perspectives on top of a container. + * For example, one may decide to refer to the transpose of a matrix or to treat + * for a limited part of my program a square matrix as symmetric. + * If a view can be expressed as a concept \em invariant of specific runtime features, + * such views can be defined statically (for example, one may always refer to the + * transpose or the diagonal of a matrix irrespective of features such as the matrix's + * size). Other may depend on features such as the size of a matrix + * (e.g., gathering/scattering the rows/columns of a matrix or permuting them). + * + * Structured matrices defined as views on other matrices do not instantiate a + * new container but refer to the one used by their targets. + * See the two specializations + * \a StructuredMatrix + * and \a StructuredMatrix, reference_dense, tmp > + * as examples of structured matrix types without and with physical container, respectively. + * + * Finally, a structured matrix can be declared as temporary, in which case the ALP + * framework has the freedom to decide whether a container should be allocated in practice + * or not. For example, a JIT backend may optimize away the use of such matrix which + * would make memory allocation for such matrix unnecessary. + * + * @tparam T The type of the matrix elements. \a T shall not be a GraphBLAS + * type. + * @tparam Structure One of the matrix structures defined in \a grb::structures. + * @tparam StorageSchemeType Either \em enum \a storage::Dense or \em enum + * \a storage::Sparse. + * \a StructuredMatrix will be allowed to pick storage schemes + * defined within their specified \a StorageSchemeType. + * @tparam View One of the matrix views in \a grb::view. + * All static views except for \a view::Identity (via + * \a view::identity cannot instantiate a new container + * and only allow to refer to a previously defined + * \a StructuredMatrix. + * The \a View parameter should not be used directly + * by the user but can be set using specific member types + * appropriately defined by each StructuredMatrix and + * accessible via functions such as \a grb::transpose or + * \a grb::diagonal. (See examples of StructuredMatrix + * definitions within \a include/graphblas/denseref/matrix.hpp + * and the \a dense_structured_matrix.cpp unit test). + * @tparam tmp Whether the structured matrix is temporary. If \a true and the + * and the structured matrix can instantiate a physical container + * (i.e., it is defined with \a View = \a view::identity) + * then the framework may or may not decide to actually allocate + * memory for such matrix. + * + */ + template< typename T, typename Structure, typename StorageSchemeType, typename View, bool tmp > + class StructuredMatrix { }; - template< typename T > - class StructuredMatrix< T, structures::General, storage::Dense, view::Identity< void >, reference_dense > : + /** + * @brief General matrix with physical container. + */ + template< typename T, bool tmp > + class StructuredMatrix< T, structures::General, storage::Dense, view::Identity< void >, reference_dense, tmp > : public internal::StructuredMatrixContainer< T > { private: @@ -425,7 +561,7 @@ namespace grb { Storage info friends ******************** */ - using self_type = StructuredMatrix< T, structures::General, storage::Dense, view::Identity< void >, reference_dense >; + using self_type = StructuredMatrix< T, structures::General, storage::Dense, view::Identity< void >, reference_dense, tmp >; template< typename InputType, typename Structure, typename Storage, typename View, typename fwd_iterator > friend RC buildMatrix( StructuredMatrix< InputType, Structure, Storage, View, reference_dense > &, const fwd_iterator & start, const fwd_iterator & end ) noexcept; @@ -441,10 +577,16 @@ namespace grb { using value_type = T; using structure = structures::General; + /** + * @brief Any structured matrix type which allocates a physical container provides a version of + * itself for defining a temporary matrix of the same type via the \a tmp_t member type. + */ + using tmp_t = StructuredMatrix< T, structures::General, storage::Dense, view::Identity< void >, reference_dense, true >; + // A general Structure knows how to define a reference to itself (which is an identity reference view) // as well as other static views. - using identity_t = StructuredMatrix< T, structures::General, storage::Dense, view::Identity< self_type >, reference_dense >; - using transpose_t = StructuredMatrix< T, structures::General, storage::Dense, view::Transpose< self_type >, reference_dense >; + using identity_t = StructuredMatrix< T, structures::General, storage::Dense, view::Identity< self_type >, reference_dense, tmp >; + using transpose_t = StructuredMatrix< T, structures::General, storage::Dense, view::Transpose< self_type >, reference_dense, tmp >; StructuredMatrix( const size_t rows, const size_t cols ) : internal::StructuredMatrixContainer< T >( rows, cols ) { @@ -452,69 +594,97 @@ namespace grb { }; // StructuredMatrix General, container - template< typename T > - class StructuredMatrix< T, structures::Square, storage::Dense, view::Identity< void >, reference_dense > : + /** + * View of a general Matrix. + */ + template< typename T, typename View, bool tmp > + class StructuredMatrix< T, structures::General, storage::Dense, View, reference_dense, tmp > : + public internal::StructuredMatrixReference< typename View::applied_to > { + + private: + using self_type = StructuredMatrix< T, structures::General, storage::Dense, View, reference_dense, tmp >; + using target_type = typename View::applied_to; + + public: + /** Exposes the element type and the structure. */ + using value_type = T; + using structure = structures::General; + + using identity_t = StructuredMatrix< T, structures::General, storage::Dense, view::Identity< self_type >, reference_dense, tmp >; + using transpose_t = StructuredMatrix< T, structures::General, storage::Dense, view::Transpose< self_type >, reference_dense, tmp >; + + StructuredMatrix( ) : internal::StructuredMatrixBase( 0, 0 ) {} + + StructuredMatrix( target_type & struct_mat ) : internal::StructuredMatrixReference< target_type >( struct_mat ) {} + + StructuredMatrix( target_type & struct_mat, std::shared_ptr< imf::IMF > imf_l, std::shared_ptr< imf::IMF > imf_r ) : + internal::StructuredMatrixReference< target_type >( struct_mat, imf_l, imf_r ) {} + + }; // StructuredMatrix General reference + + template< typename T, typename Structure, bool tmp > + class StructuredMatrix< T, Structure, storage::Dense, view::Identity< void >, reference_dense, tmp > : public internal::StructuredMatrixContainer< T > { private: - using self_type = StructuredMatrix< T, structures::Square, storage::Dense, view::Identity< void >, reference_dense >; + /********************* + Storage info friends + ******************** */ - template< typename InputType, typename Structure, typename Storage, typename View, typename fwd_iterator > - friend RC buildMatrix( StructuredMatrix< InputType, Structure, Storage, View, reference_dense > &, const fwd_iterator & start, const fwd_iterator & end ) noexcept; + using self_type = StructuredMatrix< T, Structure, storage::Dense, view::Identity< void >, reference_dense, tmp >; template< typename fwd_iterator > - RC buildMatrixUnique( const fwd_iterator & start, const fwd_iterator & end ) { - std::cout << "Building StructuredMatrix<>; calling buildMatrix( Matrix<> )\n"; - return buildMatrix( *(this->_container), start, end ); - } + friend RC buildMatrix( const StructuredMatrix< T, Structure, storage::Dense, view::Identity< void >, reference_dense > &, const fwd_iterator &, const fwd_iterator ) noexcept; public: - /** Exposes the element type and the structure. */ using value_type = T; - using structure = structures::Square; + using structure = Structure; - using identity_t = StructuredMatrix< T, structures::Square, storage::Dense, view::Identity< self_type >, reference_dense >; - using transpose_t = StructuredMatrix< T, structures::Square, storage::Dense, view::Transpose< self_type >, reference_dense >; + using tmp_t = StructuredMatrix< T, Structure, storage::Dense, view::Identity< void >, reference_dense, true >; - StructuredMatrix( const size_t rows ) : - internal::StructuredMatrixContainer< T >( rows, rows ) {} + /** The type of an identify view over the present type */ + using identity_t = StructuredMatrix< T, Structure, storage::Dense, view::Identity< self_type >, reference_dense, tmp >; - }; // StructuredMatrix Square, container + StructuredMatrix( const size_t rows, const size_t cols ) : + internal::StructuredMatrixContainer< T >( rows, cols ) {} + }; // class StructuredMatrix - /** - * Reference to a general Matrix generalized over views. - */ - template< typename T, typename View > - class StructuredMatrix< T, structures::General, storage::Dense, View, reference_dense > : - public internal::StructuredMatrixReference< typename View::applied_to > { + template< typename T, bool tmp > + class StructuredMatrix< T, structures::Square, storage::Dense, view::Identity< void >, reference_dense, tmp > : + public internal::StructuredMatrixContainer< T > { private: - using self_type = StructuredMatrix< T, structures::General, storage::Dense, View, reference_dense >; - using target_type = typename View::applied_to; + using self_type = StructuredMatrix< T, structures::Square, storage::Dense, view::Identity< void >, reference_dense, tmp >; + + template< typename InputType, typename Structure, typename Storage, typename View, typename fwd_iterator > + friend RC buildMatrix( StructuredMatrix< InputType, Structure, Storage, View, reference_dense, tmp > &, const fwd_iterator & start, const fwd_iterator & end ) noexcept; + + template< typename fwd_iterator > + RC buildMatrixUnique( const fwd_iterator & start, const fwd_iterator & end ) { + std::cout << "Building StructuredMatrix<>; calling buildMatrix( Matrix<> )\n"; + return buildMatrix( *(this->_container), start, end ); + } public: /** Exposes the element type and the structure. */ using value_type = T; - using structure = structures::General; - - using identity_t = StructuredMatrix< T, structures::General, storage::Dense, view::Identity< self_type >, reference_dense >; - using transpose_t = StructuredMatrix< T, structures::General, storage::Dense, view::Transpose< self_type >, reference_dense >; - - StructuredMatrix( ) : internal::StructuredMatrixBase( 0, 0 ) {} + using structure = structures::Square; + using tmp_t = StructuredMatrix< T, structures::Square, storage::Dense, view::Identity< void >, reference_dense, true >; - StructuredMatrix( target_type & struct_mat ) : internal::StructuredMatrixReference< target_type >( struct_mat ) {} + using identity_t = StructuredMatrix< T, structures::Square, storage::Dense, view::Identity< self_type >, reference_dense, tmp >; + using transpose_t = StructuredMatrix< T, structures::Square, storage::Dense, view::Transpose< self_type >, reference_dense, tmp >; - StructuredMatrix( target_type & struct_mat, std::shared_ptr< imf::IMF > imf_l, std::shared_ptr< imf::IMF > imf_r ) : - internal::StructuredMatrixReference< target_type >( struct_mat, imf_l, imf_r ) {} + StructuredMatrix( const size_t rows ) : + internal::StructuredMatrixContainer< T >( rows, rows ) {} - }; // StructuredMatrix General reference + }; // StructuredMatrix Square, container - template< typename T, typename View > - class StructuredMatrix< T, structures::Square, storage::Dense, View, reference_dense > : + template< typename T, typename View, bool tmp > + class StructuredMatrix< T, structures::Square, storage::Dense, View, reference_dense, tmp > : public internal::StructuredMatrixReference< typename View::applied_to > { private: - using self_type = StructuredMatrix< T, structures::Square, storage::Dense, View, reference_dense >; + using self_type = StructuredMatrix< T, structures::Square, storage::Dense, View, reference_dense, tmp >; using target_type = typename View::applied_to; public: @@ -522,8 +692,8 @@ namespace grb { using value_type = T; using structure = structures::Square; - using identity_t = StructuredMatrix< T, structures::Square, storage::Dense, view::Identity< self_type >, reference_dense >; - using transpose_t = StructuredMatrix< T, structures::Square, storage::Dense, view::Transpose< self_type >, reference_dense >; + using identity_t = StructuredMatrix< T, structures::Square, storage::Dense, view::Identity< self_type >, reference_dense, tmp >; + using transpose_t = StructuredMatrix< T, structures::Square, storage::Dense, view::Transpose< self_type >, reference_dense, tmp >; // ref to empty matrix StructuredMatrix( ) : internal::StructuredMatrixReference< target_type >() {} @@ -537,8 +707,8 @@ namespace grb { }; // StructuredMatrix Square reference // StructuredMatrix UpperTriangular, container - template< typename T > - class StructuredMatrix< T, structures::UpperTriangular, storage::Dense, view::Identity< void >, reference_dense > : + template< typename T, bool tmp > + class StructuredMatrix< T, structures::UpperTriangular, storage::Dense, view::Identity< void >, reference_dense, tmp > : public internal::StructuredMatrixContainer< T > { private: @@ -546,10 +716,10 @@ namespace grb { Storage info friends ******************** */ - using self_type = StructuredMatrix< T, structures::UpperTriangular, storage::Dense, view::Identity< void >, reference_dense >; + using self_type = StructuredMatrix< T, structures::UpperTriangular, storage::Dense, view::Identity< void >, reference_dense, tmp >; template< typename InputType, typename Structure, typename Storage, typename View, typename fwd_iterator > - friend RC buildMatrix( StructuredMatrix< InputType, Structure, Storage, View, reference_dense > &, const fwd_iterator & start, const fwd_iterator & end ) noexcept; + friend RC buildMatrix( StructuredMatrix< InputType, Structure, Storage, View, reference_dense, tmp > &, const fwd_iterator & start, const fwd_iterator & end ) noexcept; template< typename fwd_iterator > RC buildMatrixUnique( const fwd_iterator & start, const fwd_iterator & end ) { @@ -561,11 +731,12 @@ namespace grb { /** Exposes the element type and the structure. */ using value_type = T; using structure = structures::UpperTriangular; + using tmp_t = StructuredMatrix< T, structures::UpperTriangular, storage::Dense, view::Identity< void >, reference_dense, true >; // A general Structure knows how to define a reference to itself (which is an identity reference view) // as well as other static views. - using identity_t = StructuredMatrix< T, structures::UpperTriangular, storage::Dense, view::Identity< self_type >, reference_dense >; - using transpose_t = StructuredMatrix< T, structures::LowerTriangular, storage::Dense, view::Transpose< self_type >, reference_dense >; + using identity_t = StructuredMatrix< T, structures::UpperTriangular, storage::Dense, view::Identity< self_type >, reference_dense, tmp >; + using transpose_t = StructuredMatrix< T, structures::LowerTriangular, storage::Dense, view::Transpose< self_type >, reference_dense, tmp >; StructuredMatrix( const size_t rows, const size_t cols ) : internal::StructuredMatrixContainer< T >( rows, cols ) {} @@ -573,12 +744,12 @@ namespace grb { }; // StructuredMatrix UpperTriangular, container // StructuredMatrix UpperTriangular, reference - template< typename T, typename View > - class StructuredMatrix< T, structures::UpperTriangular, storage::Dense, View, reference_dense > : + template< typename T, typename View, bool tmp > + class StructuredMatrix< T, structures::UpperTriangular, storage::Dense, View, reference_dense, tmp > : public internal::StructuredMatrixReference< typename View::applied_to > { private: - using self_type = StructuredMatrix< T, structures::UpperTriangular, storage::Dense, View, reference_dense >; + using self_type = StructuredMatrix< T, structures::UpperTriangular, storage::Dense, View, reference_dense, tmp >; using target_type = typename View::applied_to; public: @@ -586,8 +757,8 @@ namespace grb { using value_type = T; using structure = structures::UpperTriangular; - using identity_t = StructuredMatrix< T, structures::UpperTriangular, storage::Dense, view::Identity< self_type >, reference_dense >; - using transpose_t = StructuredMatrix< T, structures::UpperTriangular, storage::Dense, view::Transpose< self_type >, reference_dense >; + using identity_t = StructuredMatrix< T, structures::UpperTriangular, storage::Dense, view::Identity< self_type >, reference_dense, tmp >; + using transpose_t = StructuredMatrix< T, structures::UpperTriangular, storage::Dense, view::Transpose< self_type >, reference_dense, tmp >; // ref to empty matrix StructuredMatrix( ) : internal::StructuredMatrixReference< target_type >() {} @@ -602,8 +773,9 @@ namespace grb { }; // StructuredMatrix UpperTriangular, reference // StructuredMatrix Identity, container - template< typename T > - class StructuredMatrix< T, structures::Identity, storage::Dense, view::Identity< void >, reference_dense > : + // Should Identity be a StructuredMatrixContainer? + template< typename T, bool tmp > + class StructuredMatrix< T, structures::Identity, storage::Dense, view::Identity< void >, reference_dense, tmp > : public internal::StructuredMatrixContainer< T > { private: @@ -611,10 +783,10 @@ namespace grb { Storage info friends ******************** */ - using self_type = StructuredMatrix< T, structures::Identity, storage::Dense, view::Identity< void >, reference_dense >; + using self_type = StructuredMatrix< T, structures::Identity, storage::Dense, view::Identity< void >, reference_dense, tmp >; template< typename InputType, typename Structure, typename Storage, typename View, typename fwd_iterator > - friend RC buildMatrix( StructuredMatrix< InputType, Structure, Storage, View, reference_dense > &, const fwd_iterator & start, const fwd_iterator & end ) noexcept; + friend RC buildMatrix( StructuredMatrix< InputType, Structure, Storage, View, reference_dense, tmp > &, const fwd_iterator & start, const fwd_iterator & end ) noexcept; template< typename fwd_iterator > RC buildMatrixUnique( const fwd_iterator & start, const fwd_iterator & end ) { @@ -626,11 +798,12 @@ namespace grb { /** Exposes the element type and the structure. */ using value_type = T; using structure = structures::Identity; + using tmp_t = StructuredMatrix< T, structures::Identity, storage::Dense, view::Identity< void >, reference_dense, true >; // A general Structure knows how to define a reference to itself (which is an identity reference view) // as well as other static views. - using identity_t = StructuredMatrix< T, structures::Identity, storage::Dense, view::Identity< self_type >, reference_dense >; - using transpose_t = StructuredMatrix< T, structures::Identity, storage::Dense, view::Transpose< self_type >, reference_dense >; + using identity_t = StructuredMatrix< T, structures::Identity, storage::Dense, view::Identity< self_type >, reference_dense, tmp >; + using transpose_t = StructuredMatrix< T, structures::Identity, storage::Dense, view::Transpose< self_type >, reference_dense, tmp >; StructuredMatrix( const size_t rows ) : internal::StructuredMatrixContainer< T >( rows, rows ) {} @@ -639,49 +812,98 @@ namespace grb { namespace structures { - // GraphBLAS type traits for structure - template< typename StructuredMatrix, typename Structure > + /** + * @brief Checks if a structured matrix has structure \a Structure. + * + * @tparam StructuredMatrixT The structured matrix type to be tested. + * @tparam Structure The structure type which should be implied by \a StructuredMatrixT::structure. + */ + template< typename StructuredMatrixT, typename Structure > struct is_a { - static constexpr bool value = is_in< Structure, typename StructuredMatrix::structure::inferred_structures >::value; + /** + * \a value is true iff \a Structure is implied by \a StructuredMatrixT::structure. + */ + static constexpr bool value = is_in< Structure, typename StructuredMatrixT::structure::inferred_structures >::value; }; } // namespace structures /** - * Generate an identity view where the type is compliant with the source StructuredMatrix. - * If no target structure is specified the one of the source type is assumed. - * Otherwise it can only generate a type if the target structure is the same as the source type - * or a more specialized version that would preserve its static properties (e.g., symmetric reference - * to a square matrix -- any assumption based on symmetry would not break those based on square). + * + * @brief Generate an identity view where the type is compliant with the source StructuredMatrix. + * Version where no target structure is specified. In this case the structure of the source type is assumed. + * + * @tparam T The matrix' elements type + * @tparam Structure The structure of the source and target matrix view + * @tparam StorageSchemeType The type (i.e., sparse or dense) of storage scheme + * @tparam View The source's View type + * @tparam backend The target backend + * @tparam tmp Whether the source view is a temporary structured matrix + * + * @param source The source structured matrix + * + * @return A new identity view over the source structured matrix. + * */ + template< typename T, typename Structure, typename StorageSchemeType, typename View, enum Backend backend, bool tmp > + StructuredMatrix< T, Structure, StorageSchemeType, view::Identity< StructuredMatrix< T, Structure, StorageSchemeType, View, backend, tmp > >, backend, tmp > + get_view( StructuredMatrix< T, Structure, StorageSchemeType, View, backend, tmp > &source ) { - template< typename T, typename Structure, typename StorageSchemeType, typename View, enum Backend backend > - StructuredMatrix< T, Structure, StorageSchemeType, view::Identity< StructuredMatrix< T, Structure, StorageSchemeType, View, backend > >, backend > - get_view( StructuredMatrix< T, Structure, StorageSchemeType, View, backend > &source ) { - - using source_strmat_t = StructuredMatrix< T, Structure, StorageSchemeType, View, backend >; - using target_strmat_t = StructuredMatrix< T, Structure, StorageSchemeType, view::Identity< source_strmat_t >, backend >; + using source_strmat_t = StructuredMatrix< T, Structure, StorageSchemeType, View, backend, tmp >; + using target_strmat_t = StructuredMatrix< T, Structure, StorageSchemeType, view::Identity< source_strmat_t >, backend, tmp >; target_strmat_t target( source ); return target; } - template< typename TargetStructure, typename T, typename Structure, typename StorageSchemeType, typename View, enum Backend backend > - StructuredMatrix< T, TargetStructure, StorageSchemeType, view::Identity< StructuredMatrix< T, Structure, StorageSchemeType, View, backend > >, backend > - get_view( StructuredMatrix< T, Structure, StorageSchemeType, View, backend > &source ) { + /** + * + * @brief Generate an identity view where the type is compliant with the source StructuredMatrix. + * Version where a target structure is specified. It can only generate a valide type if the target + * structure is the same as the source's + * or a more specialized one that would preserve its static properties (e.g., symmetric reference + * to a square matrix -- any assumption based on symmetry would not break those based on square). + * + * @tparam TargetStructure The target structure of the new view. It should verify + * grb::is_in . + * @tparam T The matrix' elements type + * @tparam Structure The structure of the source and target matrix view + * @tparam StorageSchemeType The type (i.e., sparse or dense) of storage scheme + * @tparam View The source's View type + * @tparam backend The target backend + * @tparam tmp Whether the source view is a temporary structured matrix + * + * @param source The source structured matrix + * + * @return A new identity view over the source structured matrix. + * + */ + template< typename TargetStructure, typename T, typename Structure, typename StorageSchemeType, typename View, enum Backend backend, bool tmp > + StructuredMatrix< T, TargetStructure, StorageSchemeType, view::Identity< StructuredMatrix< T, Structure, StorageSchemeType, View, backend, tmp > >, backend, tmp > + get_view( StructuredMatrix< T, Structure, StorageSchemeType, View, backend, tmp > &source ) { static_assert( structures::is_in< Structure, typename TargetStructure::inferred_structures >::value, "Can only create a view when the target structure is compatible with the source." ); - using source_strmat_t = StructuredMatrix< T, Structure, StorageSchemeType, View, backend >; - using target_strmat_t = StructuredMatrix< T, TargetStructure, StorageSchemeType, view::Identity< source_strmat_t >, backend >; + using source_strmat_t = StructuredMatrix< T, Structure, StorageSchemeType, View, backend, tmp >; + using target_strmat_t = StructuredMatrix< T, TargetStructure, StorageSchemeType, view::Identity< source_strmat_t >, backend, tmp >; target_strmat_t target( source ); return target; } + /** + * @brief Construct a new transpose view. + * + * @tparam StructuredMatrixT The type of the source structured matrix. + * + * @param smat The source structure matrix. + * + * @return A transposed view of the source matrix. + * + */ template< typename StructuredMatrixT > typename StructuredMatrixT::transpose_t transpose( StructuredMatrixT &smat ) { @@ -706,7 +928,7 @@ namespace grb { throw std::runtime_error("Cannot gather with imf::Select yet."); } // No static check as the compatibility depends on IMF, which is a runtime level parameter - if( ! TargetStructure::isInstantiableFrom( source, * imf_r, * imf_c ) ) { + if( ! TargetStructure::isInstantiableFrom< Structure >( * imf_r, * imf_c ) ) { throw std::runtime_error("Cannot gather into specified TargetStructure from provided SourceStructure and Index Mapping Functions."); } @@ -719,17 +941,66 @@ namespace grb { } } // namespace internal - template< typename TargetStructure, typename T, typename Structure, typename StorageSchemeType, typename View, enum Backend backend > - StructuredMatrix< T, TargetStructure, StorageSchemeType, view::Identity< StructuredMatrix< T, Structure, StorageSchemeType, View, backend > >, backend > - get_view( StructuredMatrix< T, Structure, StorageSchemeType, View, backend > &source, - const utils::range& rng_r, const utils::range& rng_c ) { - - auto imf_r = std::make_shared< imf::Strided >( rng_r.count(), nrows(source), rng_r.start, rng_r.stride ); - auto imf_c = std::make_shared< imf::Strided >( rng_c.count(), ncols(source), rng_c.start, rng_c.stride ); - - return internal::get_view( source, imf_r, imf_c ); - } + /** + * + * @brief Generate an identity view where the type is compliant with the source StructuredMatrix. + * Version where a range of rows and columns are selected to form a new view with specified target + * structure. It can only generate a valide type if the target + * structure is guaranteed to preserve the static properties of the source's structure. + * + * @tparam TargetStructure The target structure of the new view. It should verify + * grb::is_in . + * @tparam T The matrix' elements type + * @tparam Structure The structure of the source and target matrix view + * @tparam StorageSchemeType The type (i.e., sparse or dense) of storage scheme + * @tparam View The source's View type + * @tparam backend The target backend + * @tparam tmp Whether the source view is a temporary structured matrix + * + * @param source The source structured matrix + * @param rng_r A valid range of rows + * @param rng_c A valid range of columns + * + * @return A new identity view over the source structured matrix. + * + */ + template< typename TargetStructure, typename T, typename Structure, typename StorageSchemeType, typename View, enum Backend backend, bool tmp > + StructuredMatrix< T, TargetStructure, StorageSchemeType, view::Identity< StructuredMatrix< T, Structure, StorageSchemeType, View, backend, tmp > >, backend, tmp > + get_view( StructuredMatrix< T, Structure, StorageSchemeType, View, backend, tmp > &source, + const utils::range& rng_r, const utils::range& rng_c ) { + + auto imf_r = std::make_shared< imf::Strided >( rng_r.count(), nrows(source), rng_r.start, rng_r.stride ); + auto imf_c = std::make_shared< imf::Strided >( rng_c.count(), ncols(source), rng_c.start, rng_c.stride ); + + return internal::get_view( source, imf_r, imf_c ); + } + namespace internal { + /** + * + * @brief Generate an identity view where the type is compliant with the source StructuredMatrix. + * Version where a selection of rows and columns expressed as vectors of positions + * form a new view with specified target structure. + * + * \warning WIP interface. Checking the structural correctness is a costly runtime operation for a + * general vector selection. + * + * @tparam TargetStructure The target structure of the new view. It should verify + * grb::is_in . + * @tparam T The matrix' elements type + * @tparam Structure The structure of the source and target matrix view + * @tparam StorageSchemeType The type (i.e., sparse or dense) of storage scheme + * @tparam View The source's View type + * @tparam backend The target backend + * @tparam tmp Whether the source view is a temporary structured matrix + * + * @param source The source structured matrix + * @param sel_r A valid vector of row indeces (possibly in any permuted order and with repetition) + * @param sel_c A valid vector of column indeces (possibly in any permuted order and with repetition) + * + * @return A new identity view over the source structured matrix. + * + */ template< typename TargetStructure, typename T, typename Structure, typename StorageSchemeType, typename View, enum Backend backend > StructuredMatrix< T, TargetStructure, StorageSchemeType, view::Identity< StructuredMatrix< T, Structure, StorageSchemeType, View, backend > >, backend > get_view( StructuredMatrix< T, Structure, StorageSchemeType, View, backend > &source, @@ -740,9 +1011,9 @@ namespace grb { return internal::get_view( source, imf_r, imf_c ); } + } //namespace internal - /** Returns a constant reference to an Identity matrix of the provided size - * */ + /** Returns a constant reference to an Identity matrix of the provided size */ template< typename T > const StructuredMatrix< T, structures::Identity, storage::Dense, view::Identity< void >, reference_dense > & I( const size_t n ) { @@ -751,8 +1022,7 @@ namespace grb { return * ret; } - /** Returns a constant reference to a Zero matrix of the provided size - * */ + /** Returns a constant reference to a Zero matrix of the provided size */ template< typename T > const StructuredMatrix< T, structures::Zero, storage::Dense, view::Identity< void >, reference_dense > & Zero( const size_t rows, const size_t cols ) { @@ -764,7 +1034,7 @@ namespace grb { /** Returns a constant reference to a matrix representing Givens rotation * of the provided size n and parameters i, j, s and c, where * s = sin( theta ) and c = cos( theta ) - * */ + */ template< typename T > const StructuredMatrix< T, structures::Square, storage::Dense, view::Identity< void >, reference_dense > & Givens( const size_t n, const size_t i, const size_t j, const T s, const T c ) { diff --git a/include/graphblas/imf.hpp b/include/graphblas/imf.hpp index 31b190017..58897ef55 100644 --- a/include/graphblas/imf.hpp +++ b/include/graphblas/imf.hpp @@ -29,14 +29,16 @@ * according to \f$f\f$ by multiplying \f$A\f$ by \f$G_f\f$ from the left: * \f[\tilde{A} = G_f\cdot A,\quad \tilde{A}\in R^{n\times N}\f] * - * \note In this draft we use integer maps. A symbolic version of them could be + * \note The idea of parametrized matrices to express matrix accesses at + * a higher level of mathematical abstractions is inspired by the + * SPIRAL literature (Franchetti et al. SPIRAL: Extreme Performance Portability. + * http://spiral.net/doc/papers/08510983_Spiral_IEEE_Final.pdf). + * Similar affine formulations are also used in the polyhedral + * compilation literature to express concepts such as access + * relations. + * In this draft we use integer maps. A symbolic version of them could be * defined using external libraries such as the Integer Set Library (isl * \link https://libisl.sourceforge.io/). - * The idea of parametrized matrices to express matrix accesses at - * a higher level of mathematical abstractions is inspired by the - * SPIRAL literature (cite?). Similar although more general concepts - * also exist in the polyhedral compilation literature (e.g., access - * relations, cite). * */ diff --git a/include/graphblas/matrix.hpp b/include/graphblas/matrix.hpp index efab5ca60..d5699f86a 100644 --- a/include/graphblas/matrix.hpp +++ b/include/graphblas/matrix.hpp @@ -54,7 +54,7 @@ namespace grb { /* * The default value of \a StorageSchemeType could also be made conditional (Dense or Sparse) depending on \a config::default_backend */ - template< typename T, typename Structure, typename StorageSchemeType = storage::Dense, typename View = view::Identity< void >, enum Backend backend = config::default_backend > + template< typename T, typename Structure, typename StorageSchemeType = storage::Dense, typename View = view::Identity< void >, enum Backend backend = config::default_backend, bool tmp = false > class StructuredMatrix; } // namespace grb diff --git a/include/graphblas/storage.hpp b/include/graphblas/storage.hpp index 18f6c92e4..85edb7483 100644 --- a/include/graphblas/storage.hpp +++ b/include/graphblas/storage.hpp @@ -35,9 +35,17 @@ namespace grb { namespace storage { /** - * Collection of possible storage scheme options for dense matrices (for now including classic BLAS/LAPACK storage schemes). - * \note Assumption is row-major but a complete specification might depend by a similar row/column-major option perhaps included - * at the level of grb::Matrix. + * WIP. + * Collection of possible storage scheme options for dense matrices. + * + * \note Although the list for now includes classic BLAS/LAPACK storage schemes we may decide to extend or replace + * this list with different schemes. A user should not make any assumptions on which specific scheme is + * selected internally by a backend to to store a given structure. + * + * \note This labelled formulation will be replaced by a more flexible description of the underlying mappings + * associated to each scheme in the spirit of the index mapping functions formualation. + * + * @see \a imf.hpp */ enum Dense { diff --git a/include/graphblas/structures.hpp b/include/graphblas/structures.hpp index fbebc280e..a3754e65e 100644 --- a/include/graphblas/structures.hpp +++ b/include/graphblas/structures.hpp @@ -17,9 +17,13 @@ /** * - * @file This file registers all matrix structures that are either - * implemented, under implementation, or were at any point in time - * conceived and noteworthy enough to be recorded for future consideration. + * @file + * + * This file registers all matrix structures that are either + * implemented, under implementation, or were at any point in time + * conceived and noteworthy enough to be recorded for future consideration. + * + * A structure */ #ifndef _H_GRB_STRUCTURES @@ -32,9 +36,6 @@ namespace grb { - template< typename T, typename Structure, typename Storage, typename View, enum Backend backend > - class StructuredMatrix; - /** * Collects all ALP matrix structures. * @@ -68,53 +69,75 @@ namespace grb { template< typename Structure, typename... Structures > struct is_in< Structure, std::tuple< Structure, Structures... > > : std::true_type {}; - enum SymmetryDirection { - unspecified, + namespace internal { + /** + * @internal WIP interface. Symmetry may be extended so to describe the + * direction of the symmetry. + */ + enum SymmetryDirection { - north, + unspecified, - south, + north, - east, + south, - west, + east, - /* - * Could specify symmetry with upper access - */ - north_west, + west, - /* - * Could specify symmetry with lower access - */ - south_east, + /* + * Could specify symmetry with upper access + */ + north_west, - /* - * Could specify persymmetry with upper access - */ - north_east, + /* + * Could specify symmetry with lower access + */ + south_east, - /* - * Could specify persymmetry with lower access - */ - south_west - }; + /* + * Could specify persymmetry with upper access + */ + north_east, + + /* + * Could specify persymmetry with lower access + */ + south_west + }; + } // namespace internal struct UpperTriangular; struct General { using inferred_structures = std::tuple< General >; - template< typename T, typename Storage, typename View, enum Backend backend > - static bool isInstantiableFrom( const StructuredMatrix< T, UpperTriangular, Storage, View, backend > & M, grb::imf::IMF & imf_l, grb::imf::IMF & imf_r ) { - (void)M; + /** + * @brief Static and runtime check to determine if a matrix view of structure TargetStructure + * and index mapping functions (IMFs) \a imf_l and \a imf_r can be defined over \a SrcStructure. + * + * @tparam SrcStructure The underlying structure of the target view. + * @param imf_l The IMF applied to the rows of the source matrix. + * @param imf_r The IMF applied to the columns of the source matrix. + + * @return \a false if the function can determined that the new view may alter underlying assumptions + * associated with the source structure \a SrcStructure; \a true otherwise. + */ + template< typename SrcStructure > + static bool isInstantiableFrom( grb::imf::IMF & imf_l, grb::imf::IMF & imf_r ) { + + static_assert( std::is_same< SrcStructure, UpperTriangular >::value ); + return imf_l.map( imf_l.n - 1 ) <= imf_r.map( 0 ); } - template< typename T, typename Storage, typename View, enum Backend backend > - static bool isInstantiableFrom( const StructuredMatrix< T, General, Storage, View, backend > & M, grb::imf::IMF & imf_l, grb::imf::IMF & imf_r ) { - (void)M; + template< typename SrcStructure > + static bool isInstantiableFrom( grb::imf::IMF & imf_l, grb::imf::IMF & imf_r ) { + + static_assert( std::is_same< SrcStructure, General >::value ); + (void)imf_l; (void)imf_r; return true; @@ -143,9 +166,11 @@ namespace grb { // Maybe we can consider inheritance here to allow calling checks in base classes. // For example, in all cases we should check if IMFs do not overflow the original container. // (if it is actually necessary. Maybe we want to assume that the user knows what he is doing) - template< typename T, typename Storage, typename View, enum Backend backend > - static bool isInstantiableFrom( const StructuredMatrix< T, UpperTriangular, Storage, View, backend > & M, const grb::imf::IMF & imf_l, const grb::imf::IMF & imf_r ) { - (void)M; + template< typename SrcStructure > + static bool isInstantiableFrom( const grb::imf::IMF & imf_l, const grb::imf::IMF & imf_r ) { + + static_assert( std::is_same< SrcStructure, UpperTriangular >::value ); + return imf_l.isSame(imf_r); } }; From 0e80e5db51dc1fa27fcfdef6b46c379e977df4a9 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Sun, 27 Feb 2022 23:02:31 +0100 Subject: [PATCH 079/282] Fixed interface compilation (need to double check buildMatrix friend functions though) --- include/graphblas/base/matrix.hpp | 8 +-- include/graphblas/denseref/blas3.hpp | 77 +++++++++++++----------- include/graphblas/denseref/io.hpp | 16 +++-- include/graphblas/denseref/matrix.hpp | 86 ++++++++++++++------------- include/graphblas/denseref/vector.hpp | 4 +- include/graphblas/structures.hpp | 26 ++++---- 6 files changed, 118 insertions(+), 99 deletions(-) diff --git a/include/graphblas/base/matrix.hpp b/include/graphblas/base/matrix.hpp index 38cf3f4b4..3e72bafbc 100644 --- a/include/graphblas/base/matrix.hpp +++ b/include/graphblas/base/matrix.hpp @@ -497,9 +497,9 @@ class StructuredMatrix { StructuredMatrix( const size_t m, const size_t n ); - StructuredMatrix( const StructuredMatrix< T, Structure, StorageSchemeType, View, backend > & other ); + StructuredMatrix( const StructuredMatrix< T, Structure, StorageSchemeType, View, backend, tmp > & other ); - StructuredMatrix( StructuredMatrix< T, Structure, StorageSchemeType, View, backend > && other ); + StructuredMatrix( StructuredMatrix< T, Structure, StorageSchemeType, View, backend, tmp > && other ); ~StructuredMatrix(); @@ -510,8 +510,8 @@ class StructuredMatrix { */ template< typename T > struct is_structured_matrix : std::false_type {}; -template< typename T, typename Structure, typename StorageSchemeType, typename View, enum Backend backend > -struct is_structured_matrix< StructuredMatrix< T, Structure, StorageSchemeType, View, backend > > : std::true_type {}; +template< typename T, typename Structure, typename StorageSchemeType, typename View, enum Backend backend, bool tmp > +struct is_structured_matrix< StructuredMatrix< T, Structure, StorageSchemeType, View, backend, tmp > > : std::true_type {}; } // end namespace ``grb'' diff --git a/include/graphblas/denseref/blas3.hpp b/include/graphblas/denseref/blas3.hpp index d1719b464..3bfb106ee 100644 --- a/include/graphblas/denseref/blas3.hpp +++ b/include/graphblas/denseref/blas3.hpp @@ -106,9 +106,9 @@ namespace grb { return MISMATCH; } - const auto A_raw = grb::getRaw( A ); - const auto B_raw = grb::getRaw( B ); - auto C_raw = grb::getRaw( C ); + const auto A_raw = grb::internal::getRaw( A ); + const auto B_raw = grb::internal::getRaw( B ); + auto C_raw = grb::internal::getRaw( C ); std::cout << "Multiplying dense matrices.\n"; @@ -136,11 +136,12 @@ namespace grb { typename OutputType, typename InputType1, typename InputType2, class Operator, class Monoid, typename OutputStructure, typename InputStructure1, typename InputStructure2, - typename OutputView, typename InputView1, typename InputView2 + typename OutputView, typename InputView1, typename InputView2, + bool OutputTmp, bool InputTmp1, bool InputTmp2 > - RC mxm_generic( StructuredMatrix< OutputType, OutputStructure, storage::Dense, OutputView, reference_dense > &C, - const StructuredMatrix< InputType1, InputStructure1, storage::Dense, InputView1, reference_dense > &A, - const StructuredMatrix< InputType2, InputStructure2, storage::Dense, InputView2, reference_dense > &B, + RC mxm_generic( StructuredMatrix< OutputType, OutputStructure, storage::Dense, OutputView, reference_dense, OutputTmp > &C, + const StructuredMatrix< InputType1, InputStructure1, storage::Dense, InputView1, reference_dense, InputTmp1 > &A, + const StructuredMatrix< InputType2, InputStructure2, storage::Dense, InputView2, reference_dense, InputTmp2 > &B, const Operator &oper, const Monoid &monoid, const MulMonoid &mulMonoid, @@ -172,11 +173,12 @@ namespace grb { class MulMonoid, typename OutputType, typename InputType1, typename InputType2, class Operator, class Monoid, - typename OutputView = view::Identity< void >, typename InputView1 = view::Identity< void >, typename InputView2 = view::Identity< void > + typename OutputView = view::Identity< void >, typename InputView1 = view::Identity< void >, typename InputView2 = view::Identity< void >, + bool OutputTmp, bool InputTmp1, bool InputTmp2 > - RC mxm_generic( StructuredMatrix< OutputType, structures::General, storage::Dense, OutputView, reference_dense > &C, - const StructuredMatrix< InputType1, structures::General, storage::Dense, InputView1, reference_dense > &A, - const StructuredMatrix< InputType2, structures::General, storage::Dense, InputView2, reference_dense > &B, + RC mxm_generic( StructuredMatrix< OutputType, structures::General, storage::Dense, OutputView, reference_dense, OutputTmp > &C, + const StructuredMatrix< InputType1, structures::General, storage::Dense, InputView1, reference_dense, InputTmp1 > &A, + const StructuredMatrix< InputType2, structures::General, storage::Dense, InputView2, reference_dense, InputTmp2 > &B, const Operator &oper, const Monoid &monoid, const MulMonoid &mulMonoid, @@ -261,10 +263,11 @@ namespace grb { template< typename OutputType, typename InputType1, typename InputType2, class Semiring, typename OutputStructure, typename OutputView = view::Identity< void >, typename InputStructure1, typename InputView1 = view::Identity< void >, - typename InputStructure2, typename InputView2 = view::Identity< void > > - RC mxm( StructuredMatrix< OutputType, OutputStructure, storage::Dense, OutputView, reference_dense > & C, - const StructuredMatrix< InputType1, InputStructure1, storage::Dense, InputView1, reference_dense > & A, - const StructuredMatrix< InputType2, InputStructure2, storage::Dense, InputView2, reference_dense > & B, + typename InputStructure2, typename InputView2 = view::Identity< void >, + bool OutputTmp, bool InputTmp1, bool InputTmp2 > + RC mxm( StructuredMatrix< OutputType, OutputStructure, storage::Dense, OutputView, reference_dense, OutputTmp > & C, + const StructuredMatrix< InputType1, InputStructure1, storage::Dense, InputView1, reference_dense, InputTmp1 > & A, + const StructuredMatrix< InputType2, InputStructure2, storage::Dense, InputView2, reference_dense, InputTmp2 > & B, const Semiring & ring = Semiring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_semiring< Semiring >::value, void >::type * const = NULL ) { @@ -279,10 +282,11 @@ namespace grb { template< typename OutputType, typename InputType1, typename InputType2, class Operator, class Monoid, typename OutputStructure, typename OutputView = view::Identity< void >, typename InputStructure1, typename InputView1 = view::Identity< void >, - typename InputStructure2, typename InputView2 = view::Identity< void > > - RC mxm( StructuredMatrix< OutputType, OutputStructure, storage::Dense, OutputView, reference_dense > & C, - const StructuredMatrix< InputType1, InputStructure1, storage::Dense, InputView1, reference_dense > & A, - const StructuredMatrix< InputType2, InputStructure2, storage::Dense, InputView2, reference_dense > & B, + typename InputStructure2, typename InputView2 = view::Identity< void >, + bool OutputTmp, bool InputTmp1, bool InputTmp2 > + RC mxm( StructuredMatrix< OutputType, OutputStructure, storage::Dense, OutputView, reference_dense, OutputTmp > & C, + const StructuredMatrix< InputType1, InputStructure1, storage::Dense, InputView1, reference_dense, InputTmp1 > & A, + const StructuredMatrix< InputType2, InputStructure2, storage::Dense, InputView2, reference_dense, InputTmp2 > & B, const Operator & mulOp, const Monoid & addM, const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && @@ -307,12 +311,13 @@ namespace grb { typename OutputStructure, typename InputStructure1, typename InputStructure2, typename OutputStorage, typename InputStorage1, typename InputStorage2, typename OutputView, typename InputView1, typename InputView2, + bool OutputTmp, bool InputTmp1, bool InputTmp2, class Operator > - RC eWiseApply_matrix_generic( StructuredMatrix< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > *C, - const StructuredMatrix< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense > *A, + RC eWiseApply_matrix_generic( StructuredMatrix< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, OutputTmp > *C, + const StructuredMatrix< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense, InputTmp1 > *A, const InputType1 *alpha, - const StructuredMatrix< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > *B, + const StructuredMatrix< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense, InputTmp2 > *B, const InputType1 *beta, const Operator &oper, const MulMonoid &mulMonoid, @@ -395,11 +400,12 @@ namespace grb { typename OutputStructure, typename InputStructure1, typename InputStructure2, typename OutputStorage, typename InputStorage1, typename InputStorage2, typename OutputView, typename InputView1, typename InputView2, + bool OutputTmp, bool InputTmp1, bool InputTmp2, class MulMonoid > - RC eWiseApply( StructuredMatrix< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > &C, - const StructuredMatrix< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense > &A, - const StructuredMatrix< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > &B, + RC eWiseApply( StructuredMatrix< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, OutputTmp > &C, + const StructuredMatrix< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense, InputTmp1 > &A, + const StructuredMatrix< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense, InputTmp2 > &B, const MulMonoid &mulmono, const PHASE phase = NUMERICAL, const typename std::enable_if< !grb::is_object< OutputType >::value && @@ -450,11 +456,12 @@ namespace grb { typename OutputStructure, typename InputStructure2, typename OutputStorage, typename InputStorage2, typename OutputView, typename InputView2, + bool OutputTmp, bool InputTmp2, class MulMonoid > - RC eWiseApply( StructuredMatrix< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > &C, + RC eWiseApply( StructuredMatrix< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, OutputTmp > &C, const InputType1 &alpha, - const StructuredMatrix< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > &B, + const StructuredMatrix< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense, InputTmp2 > &B, const MulMonoid &mulmono, const PHASE phase = NUMERICAL, const typename std::enable_if< !grb::is_object< OutputType >::value && @@ -487,7 +494,7 @@ namespace grb { std::cout << "In grb::eWiseApply_matrix_generic (reference_dense, monoid)\n"; #endif - const StructuredMatrix< InputType1, structures::General, storage::Dense, view::Identity< void >, reference_dense> * no_matrix = nullptr; + const StructuredMatrix< InputType1, structures::General, storage::Dense, view::Identity< void >, reference_dense, false> * no_matrix = nullptr; return internal::eWiseApply_matrix_generic< true, true, false, descr >( &C, no_matrix, @@ -511,10 +518,11 @@ namespace grb { typename OutputStructure, typename InputStructure1, typename OutputStorage, typename InputStorage1, typename OutputView, typename InputView1, + bool OutputTmp, bool InputTmp1, class MulMonoid > - RC eWiseApply( StructuredMatrix< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > &C, - const StructuredMatrix< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense > &A, + RC eWiseApply( StructuredMatrix< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, OutputTmp > &C, + const StructuredMatrix< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense, InputTmp1 > &A, const InputType2 &beta, const MulMonoid &mulmono, const PHASE phase = NUMERICAL, @@ -548,7 +556,7 @@ namespace grb { std::cout << "In grb::eWiseApply_matrix_generic (reference_dense, monoid)\n"; #endif - const StructuredMatrix< InputType2, structures::General, storage::Dense, view::Identity< void >, reference_dense> * no_matrix = nullptr; + const StructuredMatrix< InputType2, structures::General, storage::Dense, view::Identity< void >, reference_dense, false > * no_matrix = nullptr; return internal::eWiseApply_matrix_generic< true, false, true, descr >( &C, &A, @@ -571,8 +579,9 @@ namespace grb { typename OutputStructure, typename OutputStorage, typename InputStorage1, typename InputStorage2, typename OutputView, typename InputView1, typename InputView2, + bool OutputTmp, typename InputCoords1, typename InputCoords2, class Operator > - RC outer( StructuredMatrix< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > & A, + RC outer( StructuredMatrix< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, OutputTmp > & A, const VectorView< InputType1, InputView1, InputStorage1, reference_dense, InputCoords1 > & u, const VectorView< InputType2, InputView2, InputStorage2, reference_dense, InputCoords2 > & v, const Operator & mul = Operator(), @@ -601,8 +610,8 @@ namespace grb { return MISMATCH; } - grb::StructuredMatrix< InputType1, structures::General, storage::Dense, view::Identity< void >, reference_dense > u_matrix( nrows, 1 ); - grb::StructuredMatrix< InputType2, structures::General, storage::Dense, view::Identity< void >, reference_dense > v_matrix( 1, ncols ); + grb::StructuredMatrix< InputType1, structures::General, storage::Dense, view::Identity< void >, reference_dense, false > u_matrix( nrows, 1 ); + grb::StructuredMatrix< InputType2, structures::General, storage::Dense, view::Identity< void >, reference_dense, false > v_matrix( 1, ncols ); // auto u_converter = grb::utils::makeVectorToMatrixConverter< InputType1 >( u, []( const size_t & ind, const InputType1 & val ) { // return std::make_pair( std::make_pair( ind, 0 ), val ); diff --git a/include/graphblas/denseref/io.hpp b/include/graphblas/denseref/io.hpp index d8cd872af..c0111b3ed 100644 --- a/include/graphblas/denseref/io.hpp +++ b/include/graphblas/denseref/io.hpp @@ -141,7 +141,11 @@ namespace grb { */ template< typename StructuredMatrixT, typename fwd_iterator > RC buildMatrixUnique( StructuredMatrixT & A, const fwd_iterator & start, const fwd_iterator & end ) noexcept { - return A.template buildMatrixUnique( start, end ); + (void)A; + (void)start; + (void)end; + return PANIC; + // return A.template buildMatrixUnique( start, end ); } /** @@ -150,9 +154,13 @@ namespace grb { * * @see grb::buildMatrix */ - template< typename StructuredMatrixT, typename fwd_iterator > - RC buildMatrix( StructuredMatrixT & A, const fwd_iterator & start, const fwd_iterator & end ) noexcept { - return A.template buildMatrixUnique( start, end ); + template< typename InputType, typename Structure, typename Storage, typename View, bool tmp, typename fwd_iterator > + RC buildMatrix( StructuredMatrix< InputType, Structure, Storage, View, reference_dense, tmp > & A, const fwd_iterator & start, const fwd_iterator & end ) { + (void)A; + (void)start; + (void)end; + return PANIC; + // return A.template buildMatrixUnique( start, end ); } } // end namespace ``grb'' diff --git a/include/graphblas/denseref/matrix.hpp b/include/graphblas/denseref/matrix.hpp index d4d976fa4..d4b2a4156 100644 --- a/include/graphblas/denseref/matrix.hpp +++ b/include/graphblas/denseref/matrix.hpp @@ -112,7 +112,7 @@ namespace grb { template< typename DataType > friend void internal::setInitialized( grb::Matrix< DataType, reference_dense > & , bool ) noexcept; - typedef Matrix< T, reference_dense > self_type; + typedef Matrix< D, reference_dense > self_type; /** * The number of rows. @@ -197,7 +197,7 @@ namespace grb { Matrix( const size_t rows, const size_t columns, const size_t cap = 0 ): m( rows ), n( columns ), cap( std::max( m*n, cap ) ), initialized( false ) { // TODO Implement allocation properly if( m > 0 && n > 0) { - data = new (std::nothrow) T[ m * n ]; + data = new (std::nothrow) D[ m * n ]; } else { data = nullptr; } @@ -248,18 +248,18 @@ namespace grb { * -# This constructor will move \f$ \Theta(1) \f$ bytes of data. * \endparblock */ - Matrix( self_type && other ) noexcept { - moveFromOther( std::forward< self_type >( other ) ); - } + // Matrix( self_type && other ) noexcept { + // moveFromOther( std::forward< self_type >( other ) ); + // } /** * Move assignment operator. * @see Matrix::Matrix( Matrix && ) */ - self_type & operator=( self_type && other ) noexcept { - moveFromOther( std::forward< self_type >( other ) ); - return *this; - } + // self_type & operator=( self_type && other ) noexcept { + // moveFromOther( std::forward< self_type >( other ) ); + // return *this; + // } /** * Matrix destructor. @@ -330,13 +330,13 @@ namespace grb { Matrix< T, reference_dense > & getContainer( StructuredMatrixContainer< T > & A ); /** Container reference getters. Defer the call to base class friend function */ - template< typename T, typename Structure, typename Storage, typename View > - const Matrix< T, reference_dense > & getContainer( const StructuredMatrix< T, Structure, Storage, View, reference_dense > & A ) { + template< typename T, typename Structure, typename Storage, typename View, bool tmp > + const Matrix< T, reference_dense > & getContainer( const StructuredMatrix< T, Structure, Storage, View, reference_dense, tmp > & A ) { return getContainer( A ); } - template< typename T, typename Structure, typename Storage, typename View > - Matrix< T, reference_dense > & getContainer( StructuredMatrix< T, Structure, Storage, View, reference_dense > & A ) { + template< typename T, typename Structure, typename Storage, typename View, bool tmp > + Matrix< T, reference_dense > & getContainer( StructuredMatrix< T, Structure, Storage, View, reference_dense, tmp > & A ) { return getContainer( A ); } @@ -353,29 +353,29 @@ namespace grb { void getInitialized( StructuredMatrixBase &, bool ) noexcept; - template< typename T, typename Structure, typename Storage, typename View > - bool getInitialized( StructuredMatrix< T, Structure, Storage, View, reference_dense > & A ) noexcept { + template< typename T, typename Structure, typename Storage, typename View, bool tmp > + bool getInitialized( StructuredMatrix< T, Structure, Storage, View, reference_dense, tmp > & A ) noexcept { return getInitialized( A ); } - template< typename T, typename Structure, typename Storage, typename View > - void setInitialized( StructuredMatrix< T, Structure, Storage, View, reference_dense > & A, bool initialized ) noexcept { + template< typename T, typename Structure, typename Storage, typename View, bool tmp > + void setInitialized( StructuredMatrix< T, Structure, Storage, View, reference_dense, tmp > & A, bool initialized ) noexcept { setInitialized( A, initialized ); } } // namespace internal - template< typename D, typename Structure, typename View > - size_t nrows( const StructuredMatrix< D, Structure, storage::Dense, View, reference_dense > & A ) noexcept { + template< typename D, typename Structure, typename View, bool tmp > + size_t nrows( const StructuredMatrix< D, Structure, storage::Dense, View, reference_dense, tmp > & A ) noexcept { return internal::nrows( A ); } - template< typename D, typename Structure, typename View > - size_t ncols( const StructuredMatrix< D, Structure, storage::Dense, View, reference_dense > & A ) noexcept { + template< typename D, typename Structure, typename View, bool tmp > + size_t ncols( const StructuredMatrix< D, Structure, storage::Dense, View, reference_dense, tmp > & A ) noexcept { return internal::ncols( A ); } - template< typename D, typename Structure, typename View > - std::pair< size_t, size_t > dims( const StructuredMatrix< D, Structure, storage::Dense, View, reference_dense > & A ) noexcept { + template< typename D, typename Structure, typename View, bool tmp > + std::pair< size_t, size_t > dims( const StructuredMatrix< D, Structure, storage::Dense, View, reference_dense, tmp > & A ) noexcept { return internal::dims( A ); } @@ -563,8 +563,10 @@ namespace grb { using self_type = StructuredMatrix< T, structures::General, storage::Dense, view::Identity< void >, reference_dense, tmp >; - template< typename InputType, typename Structure, typename Storage, typename View, typename fwd_iterator > - friend RC buildMatrix( StructuredMatrix< InputType, Structure, Storage, View, reference_dense > &, const fwd_iterator & start, const fwd_iterator & end ) noexcept; + // template< typename fwd_iterator > + // friend RC buildMatrix( StructuredMatrix< T, structures::General, storage::Dense, view::Identity< void >, reference_dense, tmp > &, const fwd_iterator & start, const fwd_iterator & end ); + template< typename fwd_iterator > + friend RC buildMatrix( StructuredMatrix< T, structures::General, storage::Dense, view::Identity< void >, reference_dense, tmp > & A, const fwd_iterator & start, const fwd_iterator & end ); template< typename fwd_iterator > RC buildMatrixUnique( const fwd_iterator & start, const fwd_iterator & end ) { @@ -634,7 +636,7 @@ namespace grb { using self_type = StructuredMatrix< T, Structure, storage::Dense, view::Identity< void >, reference_dense, tmp >; template< typename fwd_iterator > - friend RC buildMatrix( const StructuredMatrix< T, Structure, storage::Dense, view::Identity< void >, reference_dense > &, const fwd_iterator &, const fwd_iterator ) noexcept; + friend RC buildMatrix( StructuredMatrix< T, Structure, storage::Dense, view::Identity< void >, reference_dense, tmp > &, const fwd_iterator &, const fwd_iterator ) noexcept; public: using value_type = T; @@ -919,21 +921,21 @@ namespace grb { * The compatibility depends on the TargetStructure, SourceStructure and IMFs, and is calculated during runtime. */ - template< typename TargetStructure, typename T, typename Structure, typename StorageSchemeType, typename View, enum Backend backend > - StructuredMatrix< T, TargetStructure, StorageSchemeType, view::Identity< StructuredMatrix< T, Structure, StorageSchemeType, View, backend > >, backend > - get_view( StructuredMatrix< T, Structure, StorageSchemeType, View, backend > &source, + template< typename TargetStructure, typename T, typename Structure, typename StorageSchemeType, typename View, enum Backend backend, bool tmp > + StructuredMatrix< T, TargetStructure, StorageSchemeType, view::Identity< StructuredMatrix< T, Structure, StorageSchemeType, View, backend, tmp > >, backend, tmp > + get_view( StructuredMatrix< T, Structure, StorageSchemeType, View, backend, tmp > &source, std::shared_ptr< imf::IMF > imf_r, std::shared_ptr< imf::IMF > imf_c ) { if( std::dynamic_pointer_cast< imf::Select >( imf_r ) || std::dynamic_pointer_cast< imf::Select >( imf_c ) ) { throw std::runtime_error("Cannot gather with imf::Select yet."); } // No static check as the compatibility depends on IMF, which is a runtime level parameter - if( ! TargetStructure::isInstantiableFrom< Structure >( * imf_r, * imf_c ) ) { + if( ! (TargetStructure::template isInstantiableFrom< Structure >( * imf_r, * imf_c ) ) ) { throw std::runtime_error("Cannot gather into specified TargetStructure from provided SourceStructure and Index Mapping Functions."); } - using source_strmat_t = StructuredMatrix< T, Structure, StorageSchemeType, View, backend >; - using target_strmat_t = StructuredMatrix< T, TargetStructure, StorageSchemeType, view::Identity< source_strmat_t >, backend >; + using source_strmat_t = StructuredMatrix< T, Structure, StorageSchemeType, View, backend, tmp >; + using target_strmat_t = StructuredMatrix< T, TargetStructure, StorageSchemeType, view::Identity< source_strmat_t >, backend, tmp >; target_strmat_t target( source, imf_r, imf_c ); @@ -1001,32 +1003,32 @@ namespace grb { * @return A new identity view over the source structured matrix. * */ - template< typename TargetStructure, typename T, typename Structure, typename StorageSchemeType, typename View, enum Backend backend > - StructuredMatrix< T, TargetStructure, StorageSchemeType, view::Identity< StructuredMatrix< T, Structure, StorageSchemeType, View, backend > >, backend > - get_view( StructuredMatrix< T, Structure, StorageSchemeType, View, backend > &source, + template< typename TargetStructure, typename T, typename Structure, typename StorageSchemeType, typename View, enum Backend backend, bool tmp > + StructuredMatrix< T, TargetStructure, StorageSchemeType, view::Identity< StructuredMatrix< T, Structure, StorageSchemeType, View, backend, tmp > >, backend, tmp > + get_view( StructuredMatrix< T, Structure, StorageSchemeType, View, backend, tmp > &source, const std::vector< size_t >& sel_r, const std::vector< size_t >& sel_c ) { auto imf_r = std::make_shared< imf::Select >( nrows(source), sel_r ); auto imf_c = std::make_shared< imf::Select >( ncols(source), sel_c ); - return internal::get_view( source, imf_r, imf_c ); + return internal::get_view( source, imf_r, imf_c ); } } //namespace internal /** Returns a constant reference to an Identity matrix of the provided size */ template< typename T > - const StructuredMatrix< T, structures::Identity, storage::Dense, view::Identity< void >, reference_dense > & + const StructuredMatrix< T, structures::Identity, storage::Dense, view::Identity< void >, reference_dense, true > & I( const size_t n ) { - using return_type = StructuredMatrix< T, structures::Identity, storage::Dense, view::Identity< void >, reference_dense >; + using return_type = StructuredMatrix< T, structures::Identity, storage::Dense, view::Identity< void >, reference_dense, true >; return_type * ret = new return_type( n ); return * ret; } /** Returns a constant reference to a Zero matrix of the provided size */ template< typename T > - const StructuredMatrix< T, structures::Zero, storage::Dense, view::Identity< void >, reference_dense > & + const StructuredMatrix< T, structures::Zero, storage::Dense, view::Identity< void >, reference_dense, true > & Zero( const size_t rows, const size_t cols ) { - using return_type = StructuredMatrix< T, structures::Zero, storage::Dense, view::Identity< void >, reference_dense >; + using return_type = StructuredMatrix< T, structures::Zero, storage::Dense, view::Identity< void >, reference_dense, true >; return_type * ret = new return_type( rows, cols ); return * ret; } @@ -1036,9 +1038,9 @@ namespace grb { * s = sin( theta ) and c = cos( theta ) */ template< typename T > - const StructuredMatrix< T, structures::Square, storage::Dense, view::Identity< void >, reference_dense > & + const StructuredMatrix< T, structures::Square, storage::Dense, view::Identity< void >, reference_dense, true > & Givens( const size_t n, const size_t i, const size_t j, const T s, const T c ) { - using return_type = const StructuredMatrix< T, structures::Square, storage::Dense, view::Identity< void >, reference_dense >; + using return_type = const StructuredMatrix< T, structures::Square, storage::Dense, view::Identity< void >, reference_dense, true >; return_type * ret = new return_type( n ); // TODO: initialize matrix values according to the provided parameters return * ret; diff --git a/include/graphblas/denseref/vector.hpp b/include/graphblas/denseref/vector.hpp index 85073fb46..f3d5164e6 100644 --- a/include/graphblas/denseref/vector.hpp +++ b/include/graphblas/denseref/vector.hpp @@ -336,7 +336,7 @@ namespace grb { }; // Diagonal Vector view - template< typename StructuredMatrixT, typename C > + template< typename StructuredMatrixT, typename C = internal::DefaultCoordinates > VectorView< typename StructuredMatrixT::value_type, view::Diagonal< StructuredMatrixT >, storage::Dense, reference_dense, C > diagonal( StructuredMatrixT &smat ) { @@ -348,7 +348,7 @@ namespace grb { /** * Generate an identity view of a VectorView. */ - template< typename T, typename View, typename StorageSchemeType, enum Backend backend, typename C > + template< typename T, typename View, typename StorageSchemeType, enum Backend backend, typename C = internal::DefaultCoordinates > VectorView< T, view::Identity< VectorView< T, View, StorageSchemeType, backend, C > >, StorageSchemeType, backend, C > get_view( VectorView< T, View, StorageSchemeType, backend, C > &source ) { diff --git a/include/graphblas/structures.hpp b/include/graphblas/structures.hpp index a3754e65e..febca0643 100644 --- a/include/graphblas/structures.hpp +++ b/include/graphblas/structures.hpp @@ -125,25 +125,25 @@ namespace grb { * @return \a false if the function can determined that the new view may alter underlying assumptions * associated with the source structure \a SrcStructure; \a true otherwise. */ - template< typename SrcStructure > - static bool isInstantiableFrom( grb::imf::IMF & imf_l, grb::imf::IMF & imf_r ) { - - static_assert( std::is_same< SrcStructure, UpperTriangular >::value ); - - return imf_l.map( imf_l.n - 1 ) <= imf_r.map( 0 ); - } template< typename SrcStructure > static bool isInstantiableFrom( grb::imf::IMF & imf_l, grb::imf::IMF & imf_r ) { - - static_assert( std::is_same< SrcStructure, General >::value ); - - (void)imf_l; - (void)imf_r; - return true; + return false; } }; + template<> + bool General::isInstantiableFrom< UpperTriangular >( grb::imf::IMF & imf_l, grb::imf::IMF & imf_r ) { + return imf_l.map( imf_l.n - 1 ) <= imf_r.map( 0 ); + } + + template<> + bool General::isInstantiableFrom< General >( grb::imf::IMF & imf_l, grb::imf::IMF & imf_r ) { + (void)imf_l; + (void)imf_r; + return true; + } + struct Square { using inferred_structures = structures::tuple_cat< std::tuple< Square >, General::inferred_structures >::type; }; From f7749ac2d6bc2b8bba5ed18720f93a4788809642 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Fri, 25 Feb 2022 16:22:40 +0100 Subject: [PATCH 080/282] Add doxygen for reference_dense vector Also minor code cleanup. --- include/graphblas/denseref/vector.hpp | 57 +++++++++++++++++++++------ 1 file changed, 45 insertions(+), 12 deletions(-) diff --git a/include/graphblas/denseref/vector.hpp b/include/graphblas/denseref/vector.hpp index f3d5164e6..7533a1506 100644 --- a/include/graphblas/denseref/vector.hpp +++ b/include/graphblas/denseref/vector.hpp @@ -62,7 +62,7 @@ namespace grb { /** * The reference implementation of the ALP/Dense vector. * - * @tparam D The type of an element of this vector. \a D shall not be a + * @tparam T The type of an element of this vector. \a T shall not be a * GraphBLAS type. * * \warning Creating a grb::Vector of other GraphBLAS types is @@ -209,25 +209,24 @@ namespace grb { * Here starts spec draft for vectorView */ - - /** - * Identity View over a vector container. - */ template< typename T, typename View, typename C > size_t getLength( const VectorView< T, View, storage::Dense, reference_dense, C > &v ) noexcept { return v._length(); } + /** + * Identity View over a vector container. + */ template< typename T, typename C > class VectorView< T, view::Identity< void >, storage::Dense, reference_dense, C > { private: + using self_type = VectorView< T, view::Identity< void >, storage::Dense, reference_dense, C >; + /********************* Storage info friends ******************** */ - using self_type = VectorView< T, view::Identity< void >, storage::Dense, reference_dense, C >; - friend size_t getLength<>( const self_type & ) noexcept; // Physical layout @@ -235,14 +234,19 @@ namespace grb { std::shared_ptr imf; - /** Whether the container presently is initialized or not. */ + /** Whether the container presently is initialized or not. Currently, + * container is created as uninitialized and set to initialized in a + * buildMatrix call. + */ bool initialized; + /** Returns the length of the vector */ size_t _length() const { return imf->n; } public: + /** @see Vector::value_type. */ using value_type = T; VectorView( const size_t length ) : v( std::make_unique< Vector< T, reference_dense, C > >( length ) ), imf( std::make_shared< imf::Id >( length ) ), initialized( false ) {} @@ -272,8 +276,10 @@ namespace grb { friend size_t getLength<>( const self_type & ) noexcept; + /** Reference to a target vector to which this vector view points to */ std::shared_ptr< target_type > ref; + /** Index-mapping function. @see IMF */ std::shared_ptr imf; size_t _length() const { @@ -281,15 +287,18 @@ namespace grb { } public: - /** Exposes the element type and the structure. */ + /** Exposes the element type. */ using value_type = T; + /** Constructor for creating a view over a given target vector */ VectorView( target_type & vec_view ) : ref( &vec_view ), imf( nullptr ) { imf = std::make_shared< imf::Id >( getLength( *ref ) ); } + /** Constructor for creating a view over a given target vector and + * applying the given index mapping function */ VectorView( target_type & vec_view, std::shared_ptr< imf::IMF > imf ) : ref( & vec_view ), imf( imf ) { if( getLength( vec_view ) != imf->N ) { throw std::length_error( "VectorView(vec_view, * imf): IMF range differs from target's vector length." ); @@ -306,6 +315,8 @@ namespace grb { class VectorView< T, view::Diagonal< StructuredMatrixT >, storage::Dense, reference_dense, C > { private: + /** Exposes the own type and the type of the VectorView object over + * which this view is created. */ using self_type = VectorView< T, view::Diagonal< StructuredMatrixT >, storage::Dense, reference_dense, C >; using target_type = StructuredMatrixT; @@ -315,8 +326,10 @@ namespace grb { friend size_t getLength<>( const self_type & ) noexcept; + /** Pointer to a VectorView object upon which this view is created */ std::shared_ptr< target_type > ref; + /** @see IMF */ std::shared_ptr imf; size_t _length() const { @@ -324,7 +337,7 @@ namespace grb { } public: - /** Exposes the element type and the structure. */ + /** Exposes the element type. */ using value_type = T; VectorView( target_type & struct_mat ) : ref( &struct_mat ), imf( nullptr ) { @@ -336,7 +349,17 @@ namespace grb { }; // Diagonal Vector view - template< typename StructuredMatrixT, typename C = internal::DefaultCoordinates > + /** Creates a Diagonal Vector View over a given \a StructuredMatrix + * + * @paramt StructuredMatrixT Type of the StructuredMatrix over which the + * view is created. + * @paramt C @see Coordinates + * @param[in] smat StructuredMatrix object over which the view + * is created. + * + * @returns A VectorView object. + * */ + template< typename StructuredMatrixT, typename C > VectorView< typename StructuredMatrixT::value_type, view::Diagonal< StructuredMatrixT >, storage::Dense, reference_dense, C > diagonal( StructuredMatrixT &smat ) { @@ -347,6 +370,10 @@ namespace grb { /** * Generate an identity view of a VectorView. + * + * @param[in] source The VectorView object over which the view is created. + * + * @returns A VectorView object. */ template< typename T, typename View, typename StorageSchemeType, enum Backend backend, typename C = internal::DefaultCoordinates > VectorView< T, view::Identity< VectorView< T, View, StorageSchemeType, backend, C > >, StorageSchemeType, backend, C > @@ -358,7 +385,13 @@ namespace grb { } /** - * Implement a gather through a View over compatible Structure using provided Index Mapping Functions. + * Implement a gather through a View over compatible Structure using + * provided Index Mapping Functions. + * + * @param[in] source The VectorView object over which the view is created. + * @param[in] imf Index-mapping function applied to the created view. + * + * @returns A VectorView object. */ template< typename T, typename View, typename StorageSchemeType, enum Backend backend, typename C > From 199f26c8d01afea076b344a2446c6f64c1e21947 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Fri, 25 Feb 2022 20:25:49 +0100 Subject: [PATCH 081/282] WIP blas1 interface for reference dense --- include/graphblas/denseref/blas1.hpp | 3516 +++++++++++++++++++++++++- 1 file changed, 3513 insertions(+), 3 deletions(-) diff --git a/include/graphblas/denseref/blas1.hpp b/include/graphblas/denseref/blas1.hpp index 0641b0ba5..dfa5666d4 100644 --- a/include/graphblas/denseref/blas1.hpp +++ b/include/graphblas/denseref/blas1.hpp @@ -29,6 +29,3517 @@ namespace grb { + /** + * \defgroup BLAS1 The Level-1 Basic Linear Algebra Subroutines (BLAS) + * + * A collection of functions that allow GraphBLAS operators, monoids, and + * semirings work on a mix of zero-dimensional and one-dimensional containers; + * i.e., allows various linear algebra operations on scalars and objects of + * type grb::VectorView. + * + * All functions except for grb::size and grb::nnz return an error code of + * the enum-type grb::RC. The two functions for retrieving the size and the + * nonzeroes of two vectors are excluded from this because they are never + * allowed to fail. + * + * Operations which require a single input vector only and produce scalar + * output: + * -# grb::size, + * -# grb::nnz, and + * -# grb::set (three variants). + * These do not require an operator, monoid, nor semiring. The following + * require an operator: + * -# grb::foldr (reduction to the right), + * -# grb::foldl (reduction to the left). + * Operators can only be applied on \em dense vectors. Operations on sparse + * vectors require a well-defined way to handle missing vector elements. The + * following functions require a monoid instead of an operator and are able + * to handle sparse vectors by interpreting missing items as an identity + * value: + * -# grb::reducer (reduction to the right), + * -# grb::reducel (reduction to the left). + * + * Operations which require two input vectors and produce scalar output: + * -# grb::dot (dot product-- requires a semiring). + // * Sparse vectors under a semiring have their missing values interpreted as a + // * zero element under the given semiring; i.e., the identity of the additive + // * operator. + * + * Operations which require one input vector and one input/output vector for + * full and efficient in-place operations: + * -# grb::foldr (reduction to the right-- requires an operator), + * -# grb::foldl (reduction to the left-- requires an operator). + * For grb::foldr, the left-hand side input vector may be replaced by an + * input scalar. For grb::foldl, the right-hand side input vector may be + * replaced by an input scalar. In either of those cases, the reduction + * is equivalent to an in-place vector scaling. + * + * Operations which require two input vectors and one output vector for + * out-of-place operations: + * -# grb::eWiseApply (requires an operator), + * -# grb::eWiseMul (requires a semiring), + * -# grb::eWiseAdd (requires a semiring). + * Note that multiplication will consider any zero elements as an annihilator + * to the multiplicative operator. Therefore, the operator will only be + * applied at vector indices where both input vectors have nonzeroes. This is + * different from eWiseAdd. This difference only manifests itself when dealing + * with semirings, and reflects the intuitively expected behaviour. Any of the + * two input vectors (or both) may be replaced with an input scalar instead. + * + * Operations which require three input vectors and one output vector for + * out-of-place operations: + * -# grb::eWiseMulAdd (requires a semiring). + * This function can be emulated by first successive calls to grb::eWiseMul + * and grb::eWiseAdd. This specialised function, however, has better + * performance semantics. This function is closest to the standard axpy + * BLAS1 call, with out-of-place semantics. The first input vector may be + * replaced by a scalar. + * + * Again, each of grb::eWiseMul, grb::eWiseAdd, grb::eWiseMulAdd accept sparse + * vectors as input and output (since they operate on semirings), while + * grb::eWiseApply. + * + * For fusing multiple BLAS-1 style operations on any number of inputs and + * outputs, users can pass their own operator function to be executed for + * every index \a i. + * -# grb::eWiseLambda. + * This requires manual application of operators, monoids, and/or semirings + * via the BLAS-0 interface (see grb::apply, grb::foldl, and grb::foldr). + * + * For all of these functions, the element types of input and output types + * do not have to match the domains of the given operator, monoid, or + * semiring unless the grb::descriptors::no_casting descriptor was passed. + * + * An implementation, whether blocking or non-blocking, should have clear + * performance semantics for every sequence of graphBLAS calls, no matter + * whether those are made from sequential or parallel contexts. + * + * @{ + */ + + /** + * Clears all elements from the given vector \a x. + * + * At the end of this operation, the number of nonzero elements in this vector + * will be zero. The size of the vector remains unchanged. + * + * @return grb::SUCCESS When the vector is successfully cleared. + * + * \note This function cannot fail. + * + * \parblock + * \par Performance semantics + * This function + * -# contains \f$ \mathcal{O}(n) \f$ work, + * -# will not allocate new dynamic memory, + * -# will take at most \f$ \Theta(1) \f$ memory beyond the memory + * already used by the application before the call to this + * function. + * -# will move at most \f$ \mathit{sizeof}(\mathit{bool}) + + * \mathit{sizeof}(\mathit{size\_t}) \f$ bytes of data. + * \endparblock + */ + template< typename DataType, typename View, typename Coords > + RC clear( VectorView< DataType, View, storage::Dense, storage::Dense, reference_dense, Coords > & x ) noexcept { + throw std::runtime_error( "Needs an implementation" ); + return SUCCESS; + } + + /** + * Request the size (dimension) of a given VectorView. + * + * The dimension is set at construction of the given VectorView and cannot + * be changed. A call to this function shall always succeed. + * + * @tparam DataType The type of elements contained in the vector \a x. + * + * @param[in] x The VectorView of which to retrieve the size. + * + * @return The size of the VectorView \a x. + * + * \parblock + * \par Performance semantics + * A call to this function + * -# consists of \f$ \Theta(1) \f$ work; + * -# moves \f$ \Theta(1) \f$ bytes of memory; + * -# does not allocate any dynamic memory; + * -# shall not make any system calls. + * \endparblock + */ + template< typename DataType, typename View, typename Coords > + size_t size( const VectorView< DataType, View, storage::Dense, storage::Dense, reference_dense, Coords > & x ) noexcept { + return getLength( x ); + } + + /** + * Request the number of nonzeroes in a given VectorView. + * + * A call to this function always succeeds. + * + * @tparam DataType The type of elements contained in this VectorView. + * + * @param[in] x The VectorView of which to retrieve the number of nonzeroes. + * + * @return The number of nonzeroes in \a x. + * + * \parblock + * \par Performance semantics + * A call to this function + * -# consists of \f$ \Theta(1) \f$ work; + * -# moves \f$ \Theta(1) \f$ bytes of memory; + * -# does not allocate nor free any dynamic memory; + * -# shall not make any system calls. + * \endparblock + */ + template< typename DataType, typename View, typename Coords > + size_t nnz( const VectorView< DataType, View, storage::Dense, storage::Dense, reference_dense, Coords > & x ) noexcept { + throw std::runtime_error( "Needs an implementation." ); + return 0; + } + + /** \todo add documentation. In particular, think about the meaning with \a P > 1. */ + template< typename InputType, typename View, typename length_type, typename Coords > + RC resize( VectorView< InputType, View, storage::Dense, storage::Dense, reference_dense, Coords > & x, const length_type new_nz ) { + // check if we have a mismatch + if( new_nz > grb::size( x ) ) { + return MISMATCH; + } + // in the reference_dense implementation, vectors are of static size + // so this function immediately succeeds + return SUCCESS; + } + + /** + * Sets all elements of a VectorView to the given value. Can be masked. + * + * This function is functionally equivalent to + * \code + * grb::operators::right_assign< DataType > op; + * return foldl< descr >( x, val, op ); + * \endcode, + * \code + * grb::operators::left_assign< DataType > op; + * return foldr< descr >( val, x, op ); + * \endcode, and the following pseudocode + * \code + * for( size_t i = 0; i < size(x); ++i ) { + * if( mask(i) ) { setElement( x, i, val ); } + * \endcode. + * + * @tparam descr The descriptor used for this operation. + * @tparam DataType The type of each element in the given VectorView. + * @tparam T The type of the given value. + * + * \parblock + * \par Accepted descriptors + * -# grb::descriptors::no_operation + * -# grb::descriptors::no_casting + * \endparblock + * + * @param[in,out] x The VectorView of which every element is to be set to equal + * \a val. + * @param[in] val The value to set each element of \a x equal to. + * + * @returns SUCCESS When the call completes successfully. + * + * When \a descr includes grb::descriptors::no_casting and if \a T does not + * match \a DataType, the code shall not compile. + * + * \parblock + * \par Performance semantics + * A call to this function + * -# consists of \f$ \Theta(n) \f$ work; + * -# moves \f$ \Theta(n) \f$ bytes of memory; + * -# does not allocate nor free any dynamic memory; + * -# shall not make any system calls. + * \endparblock + * + * @see grb::foldl. + * @see grb::foldr. + * @see grb::operators::left_assign. + * @see grb::operators::right_assign. + * @see grb::setElement. + */ + template< + Descriptor descr = descriptors::no_operation, + typename DataType, typename View, typename T, + typename Coords + > + RC set( VectorView< DataType, View, storage::Dense, reference_dense, Coords > & x, const T val, + const typename std::enable_if< + !grb::is_object< DataType >::value && + !grb::is_object< T >::value, + void >::type * const = NULL + ) { + // static sanity checks + NO_CAST_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< DataType, T >::value ), "grb::set (Vector, unmasked)", + "called with a value type that does not match that of the given " + "vector" ); + throw std::runtime_error( "Needs an implementation." ); + + // done + return SUCCESS; + } + + /** + * Sets all elements of a VectorView to the given value. Masked variant. + * + * This function is functionally equivalent to + * \code + * grb::operators::right_assign< DataType > op; + * return foldl< descr >( x, mask, val, op ); + * \endcode, + * \code + * grb::operators::left_assign< DataType > op; + * return foldr< descr >( val, x, mask, op ); + * \endcode, and the following pseudocode + * \code + * for( size_t i = 0; i < size(x); ++i ) { + * if( mask(i) ) { setElement( x, i, val ); } + * \endcode. + * + * @tparam descr The descriptor used for this operation. + * @tparam DataType The type of each element in the given vector. + * @tparam T The type of the given value. + * + * \parblock + * \par Accepted descriptors + * -# grb::descriptors::no_operation + * -# grb::descriptors::no_casting + * -# grb::descriptors::invert_mask + * -# grb::descriptors::structural_mask + * \endparblock + * + * @param[in,out] x The VectorView of which every element is to be set to equal + * \a val. + * @param[in] val The value to set each element of \a x equal to. + * + * @returns SUCCESS When the call completes successfully. + * + * When \a descr includes grb::descriptors::no_casting and if \a T does not + * match \a DataType, the code shall not compile. + * + * \parblock + * \par Performance semantics + * A call to this function + * -# consists of \f$ \Theta( nnz( m ) ) \f$ work; + * -# moves \f$ \Theta( nnz( m ) ) \f$ bytes of memory; + * -# does not allocate nor free any dynamic memory; + * -# shall not make any system calls. + * If grb::descriptors::invert_mask is given, then \f$ nnz( m ) \f$ in the + * above shall be interpreted as \f$ size( m ) \f$ instead. + * \endparblock + * + * @see grb::foldl. + * @see grb::foldr. + * @see grb::operators::left_assign. + * @see grb::operators::right_assign. + * @see grb::setElement. + */ + template< Descriptor descr = descriptors::no_operation, typename DataType, typename DataView, typename MaskType, typename MaskView, typename T, typename Coords > + RC set( VectorView< DataType, View, storage::Dense, reference_dense, Coords > & x, + const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & m, + const T val, + const typename std::enable_if< ! grb::is_object< DataType >::value && ! grb::is_object< T >::value, void >::type * const = NULL ) { +#ifdef _DEBUG + std::cout << "In grb::set (vector-to-value, masked)\n"; +#endif + // static sanity checks + NO_CAST_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< DataType, T >::value ), "grb::set (Vector to scalar, masked)", + "called with a value type that does not match that of the given " + "vector" ); + + // catch empty mask + if( size( m ) == 0 ) { + return set< descr >( x, val ); + } + + // dynamic sanity checks + if( size( x ) != size( m ) ) { + return MISMATCH; + } + + // pre-cast value to be copied + const DataType toCopy = static_cast< DataType >( val ); + + throw std::runtime_error( "Needs implementation" ); + + // done + return SUCCESS; + } + + /** + * Sets the element of a given VectorView at a given position to a given value. + * + * If the input VectorView \a x already has an element \f$ x_i \f$, that element + * is overwritten to the given value \a val. If no such element existed, it + * is added and set equal to \a val. The number of nonzeroes in \a x may thus + * be increased by one due to a call to this function. + * + * The parameter \a i may not be greater or equal than the size of \a x. + * + * @tparam descr The descriptor to be used during evaluation of this + * function. + * @tparam DataType The type of the elements of \a x. + * @tparam T The type of the value to be set. + * + * @param[in,out] x The vector to be modified. + * @param[in] val The value \f$ x_i \f$ should read after function exit. + * @param[in] i The index of the element of \a x to set. + * + * @return grb::SUCCESS Upon successful execution of this operation. + * @return grb::MISMATCH If \a i is greater or equal than the dimension of + * \a x. + * + * \parblock + * \par Accepted descriptors + * -# grb::descriptors::no_operation + * -# grb::descriptors::no_casting + * \endparblock + * + * When \a descr includes grb::descriptors::no_casting and if \a T does not + * match \a DataType, the code shall not compile. + * + * \parblock + * \par Performance semantics + * A call to this function + * -# consists of \f$ \Theta(1) \f$ work; + * -# moves \f$ \Theta(1) \f$ bytes of memory; + * -# does not allocate nor free any dynamic memory; + * -# shall not make any system calls. + * \endparblock + */ + template< Descriptor descr = descriptors::no_operation, typename DataType, typename View, typename T, typename Coords > + RC setElement( VectorView< DataType, View, storage::Dense, reference_dense, Coords > & x, + const T val, + const size_t i, + const typename std::enable_if< ! grb::is_object< DataType >::value && ! grb::is_object< T >::value, void >::type * const = NULL ) { + // static sanity checks + NO_CAST_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< DataType, T >::value ), "grb::set (VectorView, at index)", + "called with a value type that does not match that of the given " + "VectorView" ); + + throw std::runtime_error( "Needs an implementation." ); + + // done + return SUCCESS; + } + + /** + * Sets the content of a given vector \a x to be equal to that of + * another given vector \a y. Can be masked. + * + * This operation is functionally equivalent to + * \code + * grb::operators::right_assign< T > op; + * grb::foldl( x, y, op ); + * \endcode, + * \code + * grb::operators::left_assign < T > op; + * grb::foldr( y, x, op ); + * \endcode, as well as the following pseudocode + * \code + * for( each nonzero in y ) { + * setElement( x, nonzero.index, nonzero.value ); + * } + * \endcode. + * + * The vector \a x may not equal \a y. + * + * \parblock + * \par Accepted descriptors + * -# grb::descriptors::no_operation + * -# grb::descriptors::no_casting + * \endparblock + * + * @tparam descr The descriptor of the operation. + * @tparam OutputType The type of each element in the output vector. + * @tparam InputType The type of each element in the input vector. + * + * @param[in,out] x The vector to be set. + * @param[in] y The source vector. + * + * When \a descr includes grb::descriptors::no_casting and if \a InputType + * does not match \a OutputType, the code shall not compile. + * + * \parblock + * \par Performance semantics + * A call to this function + * -# consists of \f$ \Theta(n) \f$ work; + * -# moves \f$ \Theta(n) \f$ bytes of memory; + * -# does not allocate nor free any dynamic memory; + * -# shall not make any system calls. + * \endparblock + * + * @see grb::foldl. + * @see grb::foldr. + * @see grb::operators::left_assign. + * @see grb::operators::right_assign. + * @see grb::setElement. + */ + template< Descriptor descr = descriptors::no_operation, typename OutputType, typename InputType, typename OutputView, typename InputView, typename Coords > + RC set( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & x, const VectorView< InputType, InputView, storage::Dense, reference_dense, Coords > & y ) { + // static sanity checks + NO_CAST_ASSERT( + ( ! ( descr & descriptors::no_casting ) || std::is_same< OutputType, InputType >::value ), "grb::copy (Vector)", "called with vector parameters whose element data types do not match" ); + constexpr bool out_is_void = std::is_void< OutputType >::value; + constexpr bool in_is_void = std::is_void< OutputType >::value; + static_assert( ! in_is_void || out_is_void, + "grb::set (reference, VectorView <- VectorView, masked): " + "if input is void, then the output must be also" ); + static_assert( ! ( descr & descriptors::use_index ) || ! out_is_void, + "grb::set (reference, VectorView <- VectorView, masked): " + "use_index descriptor cannot be set if output vector is void" ); + + // check contract + if( reinterpret_cast< void * >( &x ) == reinterpret_cast< const void * >( &y ) ) { + return ILLEGAL; + } + + throw std::runtime_error( "Needs an implementation." ); + + // done + return SUCCESS; + } + + /** + * Sets the content of a given vector \a x to be equal to that of + * another given vector \a y. Masked variant. + * + * This operation is functionally equivalent to + * \code + * grb::operators::right_assign< T > op; + * grb::foldl( x, mask, y, op ); + * \endcode, + * \code + * grb::operators::left_assign < T > op; + * grb::foldr( y, x, mask, op ); + * \endcode, as well as the following pseudocode + * \code + * for( each nonzero in y ) { + * if( mask( nonzero.index ) ) { + * setElement( x, nonzero.index, nonzero.value ); + * } + * } + * \endcode. + * + * The vector \a x may not equal \a y. + * + * @tparam descr The descriptor of the operation. + * @tparam OutputType The type of each element in the output vector. + * @tparam MaskType The type of each element in the mask vector. + * @tparam InputType The type of each element in the input vector. + * + * \parblock + * \par Accepted descriptors + * -# grb::descriptors::no_operation + * -# grb::descriptors::no_casting + * -# grb::descriptors::invert_mask + * -# grb::descriptors::structural_mask + * \endparblock + * + * @param[in,out] x The vector to be set. + * @param[in] mask The output mask. + * @param[in] y The source vector. + * + * When \a descr includes grb::descriptors::no_casting and if \a InputType + * does not match \a OutputType, the code shall not compile. + * + * \parblock + * \par Performance semantics + * A call to this function + * -# consists of \f$ \Theta( \min\{ nnz( mask ), nnz( y ) \} ) \f$ work; + * -# moves \f$ \Theta( \min\{ nnz( mask ), nnz( y ) \} ) \f$ bytes of memory; + * -# does not allocate nor free any dynamic memory; + * -# shall not make any system calls. + * If grb::descriptors::invert_mask is given, then \f$ nnz( mask ) \f$ in the + * above shall be considered equal to \f$ nnz( y ) \f$. + * \endparblock + * + * @see grb::foldl. + * @see grb::foldr. + * @see grb::operators::left_assign. + * @see grb::operators::right_assign. + * @see grb::setElement. + */ + template< Descriptor descr = descriptors::no_operation, typename OutputType, typename MaskType, typename InputType, typename OutputView, typename MaskView, typename InputView, typename Coords > + RC set( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & x, + const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & mask, + const VectorView< InputType, InputView, storage::Dense, reference_dense, Coords > & y, + const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType >::value, void >::type * const = NULL ) { + // static sanity checks + NO_CAST_ASSERT( + ( ! ( descr & descriptors::no_casting ) || std::is_same< OutputType, InputType >::value ), "grb::set (VectorView)", "called with vector parameters whose element data types do not match" ); + NO_CAST_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< MaskType, bool >::value ), "grb::set (VectorView)", "called with non-bool mask element types" ); + constexpr bool out_is_void = std::is_void< OutputType >::value; + constexpr bool in_is_void = std::is_void< OutputType >::value; + static_assert( ! in_is_void || out_is_void, + "grb::set (reference, VectorView <- VectorView, masked): " + "if input is void, then the output must be also" ); + static_assert( ! ( descr & descriptors::use_index ) || ! out_is_void, + "grb::set (reference, VectorView <- VectorView, masked): " + "use_index descriptor cannot be set if output VectorView is void" ); + + // delegate if possible + if( internal::getCoordinates( mask ).size() == 0 ) { + return set( x, y ); + } + + // catch contract violations + if( reinterpret_cast< void * >( &x ) == reinterpret_cast< const void * >( &y ) ) { + return ILLEGAL; + } + + throw std::runtime_error( "Needs an implementation." ); + + // done + return ret; + } + + /** + * Folds all elements in a ALP VectorView \a x into a single value \a beta. + * + * The original value of \a beta is used as the right-hand side input of the + * operator \a op. A left-hand side input for \a op is retrieved from the + * input VectorView \a x. The result of the operation is stored in \a beta. + * This process is repeated for every element in \a x. + * + * At function exit, \a beta will equal + * \f$ \beta \odot x_0 \odot x_1 \odot \ldots x_{n-1} \f$. + * + * @tparam descr The descriptor used for evaluating this function. By + * default, this is grb::descriptors::no_operation. + * @tparam OP The type of the operator to be applied. + * The operator must be associative. + * @tparam InputType The type of the elements of \a x. + * @tparam IOType The type of the value \a y. + * + * @param[in] x The input VectorView \a x that will not be modified. + * This input VectorView must be dense. + * @param[in,out] beta On function entry: the initial value to be applied to + * \a op from the right-hand side. + * On function exit: the result of repeated applications + * from the left-hand side of elements of \a x. + * @param[in] op The monoid under which to perform this right-folding. + * + * \note We only define fold under monoids, not under plain operators. + * + * @returns grb::SUCCESS This function always succeeds. + * @returns grb::ILLEGAL When a sparse VectorView is passed. In this case, the + * call to this function will have no other effects. + * + * \warning Since this function folds from left-to-right using binary + * operators, this function \em cannot take sparse vectors as input-- + * a monoid is required to give meaning to missing vector entries. + * See grb::reducer for use with sparse vectors instead. + * + * \parblock + * \par Valid descriptors + * grb::descriptors::no_operation, grb::descriptors::no_casting. + * + * \note Invalid descriptors will be ignored. + * + * If grb::descriptors::no_casting is specified, then 1) the first domain of + * \a op must match \a IOType, 2) the second domain of \a op must match + * \a InputType, and 3) the third domain must match \a IOType. If one of these + * is not true, the code shall not compile. + * + * \endparblock + * + * \parblock + * \par Valid operator types + * The given operator \a op is required to be: + * -# associative. + * \endparblock + * + * \parblock + * \par Performance semantics + * -# This call comprises \f$ \Theta(n) \f$ work, where \f$ n \f$ equals + * the size of the vector \a x. The constant factor depends on the + * cost of evaluating the underlying binary operator. A good + * implementation uses vectorised instructions whenever the input + * domains, the output domain, and the operator used allow for this. + * + * -# This call will not result in additional dynamic memory allocations. + * + * -# This call takes \f$ \mathcal{O}(1) \f$ memory beyond the memory + * used by the application at the point of a call to this function. + * + * -# This call incurs at most + * \f$ n \cdot\mathit{sizeof}(\mathit{InputType}) + \mathcal{O}(1) \f$ + * bytes of data movement. A good implementation will rely on in-place + * operators. + * \endparblock + * + * @see grb::operators::internal::Operator for a discussion on when in-place + * and/or vectorised operations are used. + */ + template< Descriptor descr = descriptors::no_operation, class Monoid, typename InputType, typename InputView, typename IOType, typename Coords > + RC foldr( const Vector< InputType, InputView, storage::Dense, reference_dense, Coords > & x, + IOType & beta, + const Monoid & monoid = Monoid(), + const typename std::enable_if< ! grb::is_object< InputType >::value && ! grb::is_object< IOType >::value && grb::is_monoid< Monoid >::value, void >::type * const = NULL ) { + + throw std::runtime_error( "Needs an implementation." ); + return SUCCESS; + } + + /** + * For all elements in a ALP VectorView \a y, fold the value \f$ \alpha \f$ + * into each element. + * + * The original value of \f$ \alpha \f$ is used as the left-hand side input + * of the operator \a op. The right-hand side inputs for \a op are retrieved + * from the input vector \a y. The result of the operation is stored in \a y, + * thus overwriting its previous values. + * + * The value of \f$ y_i \f$ after a call to thus function thus equals + * \f$ \alpha \odot y_i \f$, for all \f$ i \in \{ 0, 1, \dots, n - 1 \} \f$. + * + * @tparam descr The descriptor used for evaluating this function. By + * default, this is grb::descriptors::no_operation. + * @tparam OP The type of the operator to be applied. + * @tparam InputType The type of \a alpha. + * @tparam IOType The type of the elements in \a y. + * + * @param[in] alpha The input value to apply as the left-hand side input + * to \a op. + * @param[in,out] y On function entry: the initial values to be applied as + * the right-hand side input to \a op. + * On function exit: the output data. + * @param[in] op The monoid under which to perform this left-folding. + * + * @returns grb::SUCCESS This function always succeeds. + * + * \note We only define fold under monoids, not under plain operators. + * + * \parblock + * \par Valid descriptors + * grb::descriptors::no_operation, grb::descriptors::no_casting. + * + * \note Invalid descriptors will be ignored. + * + * If grb::descriptors::no_casting is specified, then 1) the first domain of + * \a op must match \a IOType, 2) the second domain of \a op must match + * \a InputType, and 3) the third domain must match \a IOType. If one of these + * is not true, the code shall not compile. + * + * \endparblock + * + * \parblock + * \par Valid operator types + * The given operator \a op is required to be: + * -# (no requirements). + * \endparblock + * + * \parblock + * \par Performance semantics + * -# This call comprises \f$ \Theta(n) \f$ work, where \f$ n \f$ equals + * the size of the vector \a x. The constant factor depends on the + * cost of evaluating the underlying binary operator. A good + * implementation uses vectorised instructions whenever the input + * domains, the output domain, and the operator used allow for this. + * + * -# This call will not result in additional dynamic memory allocations. + * + * -# This call takes \f$ \mathcal{O}(1) \f$ memory beyond the memory + * used by the application at the point of a call to this function. + * + * -# This call incurs at most + * \f$ 2n \cdot \mathit{sizeof}(\mathit{IOType}) + \mathcal{O}(1) \f$ + * bytes of data movement. + * \endparblock + * + * @see grb::operators::internal::Operator for a discussion on when in-place + * and/or vectorised operations are used. + */ + template< Descriptor descr = descriptors::no_operation, class Monoid, typename IOType, typename InputType, typename InputView, typename Coords > + RC foldr( const InputType & alpha, + VectorView< IOType, InputView, storage::Dense, reference_dense, Coords > & y, + const Monoid & monoid = Monoid(), + const typename std::enable_if< ! grb::is_object< InputType >::value && ! grb::is_object< IOType >::value && grb::is_monoid< Monoid >::value, void >::type * const = NULL ) { + // static sanity checks + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Monoid::D1, IOType >::value ), "grb::foldl", + "called with a vector x of a type that does not match the first domain " + "of the given operator" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Monoid::D2, InputType >::value ), "grb::foldl", + "called on a vector y of a type that does not match the second domain " + "of the given operator" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Monoid::D3, IOType >::value ), "grb::foldl", + "called on a vector x of a type that does not match the third domain " + "of the given operator" ); + + throw std::runtime_error( "Needs an implementation." ); + return SUCCESS; + } + + /** + * Computes y = x + y, operator variant. + * + * Specialisation for scalar \a x. + */ + template< Descriptor descr = descriptors::no_operation, class OP, typename IOType, typename InputType, typename IOView, typename Coords > + RC foldr( const InputType & alpha, + VectorView< IOType, IOView, storage::Dense, reference_dense, Coords > & y, + const OP & op = OP(), + const typename std::enable_if< ! grb::is_object< InputType >::value && ! grb::is_object< IOType >::value && grb::is_operator< OP >::value, void >::type * const = NULL ) { + // static sanity checks + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename OP::D1, IOType >::value ), "grb::foldl", + "called with a vector x of a type that does not match the first domain " + "of the given operator" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename OP::D2, InputType >::value ), "grb::foldl", + "called on a vector y of a type that does not match the second domain " + "of the given operator" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename OP::D3, IOType >::value ), "grb::foldl", + "called on a vector x of a type that does not match the third domain " + "of the given operator" ); + + throw std::runtime_error( "Needs an implementation." ); + return SUCCESS; + } + + /** + * Folds all elements in a ALP VectorView \a x into the corresponding + * elements from an input/output vector \a y. The vectors must be of equal + * size \f$ n \f$. For all \f$ i \in \{0,1,\ldots,n-1\} \f$, the new value + * of at the i-th index of \a y after a call to this function thus equals + * \f$ x_i \odot y_i \f$. + * + * @tparam descr The descriptor used for evaluating this function. By + * default, this is grb::descriptors::no_operation. + * @tparam OP The type of the operator to be applied. + * @tparam IOType The type of the elements of \a x. + * @tparam InputType The type of the elements of \a y. + * + * @param[in] x The input vector \a y that will not be modified. + * @param[in,out] y On function entry: the initial value to be applied to + * \a op as the right-hand side input. + * On function exit: the result of repeated applications + * from the right-hand side using elements from \a y. + * @param[in] op The operator under which to perform this right-folding. + * + * @returns grb::SUCCESS This function always succeeds. + * + * \note The element-wise fold is also defined for monoids. + * + * \parblock + * \par Valid descriptors + * grb::descriptors::no_operation, grb::descriptors::no_casting. + * + * \note Invalid descriptors will be ignored. + * + * If grb::descriptors::no_casting is specified, then 1) the first domain of + * \a op must match \a InputType, 2) the second domain of \a op must match + * \a IOType, and 3) the third domain must match \a IOType. If one of these + * is not true, the code shall not compile. + * + * \endparblock + * + * \parblock + * \par Valid operator types + * The given operator \a op is required to be: + * -# (no requirements). + * \endparblock + * + * \parblock + * \par Performance semantics + * -# This call comprises \f$ \Theta(n) \f$ work, where \f$ n \f$ equals + * the size of the vector \a x. The constant factor depends on the + * cost of evaluating the underlying binary operator. A good + * implementation uses vectorised instructions whenever the input + * domains, the output domain, and the operator used allow for this. + * + * -# This call will not result in additional dynamic memory allocations. + * + * -# This call takes \f$ \mathcal{O}(1) \f$ memory beyond the memory + * used by the application at the point of a call to this function. + * + * -# This call incurs at most + * \f$ n \cdot ( + * \mathit{sizeof}(InputType) + 2\mathit{sizeof}(IOType) + * ) + \mathcal{O}(1) + * \f$ + * bytes of data movement. A good implementation will rely on in-place + * operators whenever allowed. + * \endparblock + * + * @see grb::operators::internal::Operator for a discussion on when in-place + * and/or vectorised operations are used. + */ + template< Descriptor descr = descriptors::no_operation, class OP, typename IOType, typename InputType, typename IOView, typename InputView, typename Coords > + RC foldr( const VectorView< InputType, InputView, storage::Dense, reference_dense, Coords > & x, + VectorView< IOType, IOView, storage::Dense, reference_dense, Coords > & y, + const OP & op = OP(), + const typename std::enable_if< grb::is_operator< OP >::value && ! grb::is_object< InputType >::value && ! grb::is_object< IOType >::value, void >::type * = NULL ) { + // static sanity checks + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename OP::D1, InputType >::value ), "grb::eWiseFoldr", + "called with a vector x of a type that does not match the first domain " + "of the given operator" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename OP::D2, IOType >::value ), "grb::eWiseFoldr", + "called on a vector y of a type that does not match the second domain " + "of the given operator" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename OP::D3, IOType >::value ), "grb::eWiseFoldr", + "called on a vector y of a type that does not match the third domain " + "of the given operator" ); + + if( size( x ) != size( y ) ) { + return MISMATCH; + } + + throw std::runtime_error( "Needs an implementation." ); + return SUCCESS; + } + + /** + * Calculates \f$ x = x . y \f$ using a given operator. + * + * Masked variant. + */ + template< Descriptor descr = descriptors::no_operation, class OP, typename IOType, typename MaskType, typename InputType, typename IOView, typename MaskView, typename InputView, typename Coords > + RC foldr( const VectorView< InputType, InputView, storage::Dense, reference_dense, Coords > & x, + const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & m, + VectorView< IOType, IOView, storage::Dense, reference_dense, Coords > & y, + const OP & op = OP(), + const typename std::enable_if< grb::is_operator< OP >::value && ! grb::is_object< InputType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< IOType >::value, void >::type * = + NULL ) { + // static sanity checks + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename OP::D1, InputType >::value ), "grb::eWiseFoldr", + "called with a vector x of a type that does not match the first domain " + "of the given operator" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename OP::D2, IOType >::value ), "grb::eWiseFoldr", + "called on a vector y of a type that does not match the second domain " + "of the given operator" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename OP::D3, IOType >::value ), "grb::eWiseFoldr", + "called on a vector y of a type that does not match the third domain " + "of the given operator" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< bool, MaskType >::value ), "grb::eWiseFoldr", "called with a non-Boolean mask" ); + + if( size( m ) == 0 ) { + return foldr< descr >( x, y, op ); + } + + const size_t n = size( x ); + if( n != size( y ) || n != size( m ) ) { + return MISMATCH; + } + + throw std::runtime_error( "Needs an implementation." ); + return SUCCESS; + } + + /** + * Folds all elements in a ALP VectorView \a x into the corresponding + * elements from an input/output vector \a y. The vectors must be of equal + * size \f$ n \f$. For all \f$ i \in \{0,1,\ldots,n-1\} \f$, the new value + * of at the i-th index of \a y after a call to this function thus equals + * \f$ x_i \odot y_i \f$. + * + * @tparam descr The descriptor used for evaluating this function. By + * default, this is grb::descriptors::no_operation. + * @tparam Monoid The type of the monoid to be applied. + * @tparam IOType The type of the elements of \a x. + * @tparam InputType The type of the elements of \a y. + * + * @param[in] x The input vector \a y that will not be modified. + * @param[in,out] y On function entry: the initial value to be applied + * to \a op as the right-hand side input. + * On function exit: the result of repeated applications + * from the right-hand side using elements from \a y. + * @param[in] monoid The monoid under which to perform this right-folding. + * + * @returns grb::SUCCESS This function always succeeds. + * + * \note The element-wise fold is also defined for operators. + * + * \parblock + * \par Valid descriptors + * grb::descriptors::no_operation, grb::descriptors::no_casting. + * + * \note Invalid descriptors will be ignored. + * + * If grb::descriptors::no_casting is specified, then 1) the first domain of + * \a op must match \a InputType, 2) the second domain of \a op must match + * \a IOType, and 3) the third domain must match \a IOType. If one of these + * is not true, the code shall not compile. + * + * \endparblock + * + * \parblock + * \par Valid monoid types + * The given operator \a op is required to be: + * -# (no requirements). + * \endparblock + * + * \parblock + * \par Performance semantics + * -# This call comprises \f$ \Theta(n) \f$ work, where \f$ n \f$ equals + * the size of the vector \a x. The constant factor depends on the + * cost of evaluating the underlying binary operator. A good + * implementation uses vectorised instructions whenever the input + * domains, the output domain, and the operator used allow for this. + * + * -# This call will not result in additional dynamic memory allocations. + * + * -# This call takes \f$ \mathcal{O}(1) \f$ memory beyond the memory + * used by the application at the point of a call to this function. + * + * -# This call incurs at most + * \f$ n \cdot ( + * \mathit{sizeof}(InputType) + 2\mathit{sizeof}(IOType) + * ) + \mathcal{O}(1) + * \f$ + * bytes of data movement. A good implementation will rely on in-place + * operators whenever allowed. + * \endparblock + * + * @see grb::operators::internal::Operator for a discussion on when in-place + * and/or vectorised operations are used. + */ + template< Descriptor descr = descriptors::no_operation, class Monoid, typename IOType, typename InputType,, typename IOView, typename InputView, typename Coords > + RC foldr( const VectorView< InputType, storage::Dense, reference_dense, Coords > & x, + VectorView< IOType, storage::Dense, reference_dense, Coords > & y, + const Monoid & monoid = Monoid(), + const typename std::enable_if< grb::is_monoid< Monoid >::value && ! grb::is_object< InputType >::value && ! grb::is_object< IOType >::value, void >::type * = NULL ) { + // static sanity checks + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Monoid::D1, InputType >::value ), "grb::eWiseFoldr", + "called with a vector x of a type that does not match the first domain " + "of the given monoid" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Monoid::D2, IOType >::value ), "grb::eWiseFoldr", + "called on a vector y of a type that does not match the second domain " + "of the given monoid" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Monoid::D3, IOType >::value ), "grb::eWiseFoldr", + "called on a vector y of a type that does not match the third domain " + "of the given monoid" ); + + // dynamic sanity checks + const size_t n = size( x ); + if( n != size( y ) ) { + return MISMATCH; + } + + throw std::runtime_error( "Needs an implementation." ); + return SUCCESS; + } + + /** + * Calculates \f$ x = x + y \f$ for a given monoid. + * + * Masked variant. + */ + template< Descriptor descr = descriptors::no_operation, class Monoid, typename IOType, typename MaskType, typename InputType, typename IOView, typename MaskView, typename InputView, typename Coords > + RC foldr( const VectorView< InputType, InputView, storage::Dense, reference_dense, Coords > & x, + const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & m, + VectorView< IOType, IOView, storage::Dense, reference_dense, Coords > & y, + const Monoid & monoid = Monoid(), + const typename std::enable_if< grb::is_monoid< Monoid >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType >::value && ! grb::is_object< IOType >::value, void >::type * = + NULL ) { + // static sanity checks + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Monoid::D1, InputType >::value ), "grb::eWiseFoldr", + "called with a vector x of a type that does not match the first domain " + "of the given monoid" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Monoid::D2, IOType >::value ), "grb::eWiseFoldr", + "called on a vector y of a type that does not match the second domain " + "of the given monoid" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Monoid::D3, IOType >::value ), "grb::eWiseFoldr", + "called on a vector y of a type that does not match the third domain " + "of the given monoid" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< bool, MaskType >::value ), "grb::eWiseFoldr", "called with a mask of non-Boolean type" ); + + // check empty mask + if( size( m ) == 0 ) { + return foldr< descr >( x, y, monoid ); + } + + // dynamic sanity checks + const size_t n = size( x ); + if( n != size( y ) || n != size( m ) ) { + return MISMATCH; + } + + throw std::runtime_error( "Needs an implementation." ); + return SUCCESS; + } + + /** + * For all elements in a ALP VectorView \a x, fold the value \f$ \beta \f$ + * into each element. + * + * The original value of \f$ \beta \f$ is used as the right-hand side input + * of the operator \a op. The left-hand side inputs for \a op are retrieved + * from the input vector \a x. The result of the operation is stored in + * \f$ \beta \f$, thus overwriting its previous value. This process is + * repeated for every element in \a y. + * + * The value of \f$ x_i \f$ after a call to thus function thus equals + * \f$ x_i \odot \beta \f$, for all \f$ i \in \{ 0, 1, \dots, n - 1 \} \f$. + * + * @tparam descr The descriptor used for evaluating this function. By + * default, this is grb::descriptors::no_operation. + * @tparam OP The type of the operator to be applied. + * @tparam IOType The type of the value \a beta. + * @tparam InputType The type of the elements of \a x. + * + * @param[in,out] x On function entry: the initial values to be applied as + * the left-hand side input to \a op. The input vector must + * be dense. + * On function exit: the output data. + * @param[in] beta The input value to apply as the right-hand side input + * to \a op. + * @param[in] op The operator under which to perform this left-folding. + * + * @returns grb::SUCCESS This function always succeeds. + * + * \note This function is also defined for monoids. + * + * \warning If \a x is sparse and this operation is requested, a monoid instead + * of an operator is required! + * + * \parblock + * \par Valid descriptors + * grb::descriptors::no_operation, grb::descriptors::no_casting. + * + * \note Invalid descriptors will be ignored. + * + * If grb::descriptors::no_casting is specified, then 1) the first domain of + * \a op must match \a IOType, 2) the second domain of \a op must match + * \a InputType, and 3) the third domain must match \a IOType. If one of these + * is not true, the code shall not compile. + * + * \endparblock + * + * \parblock + * \par Valid operator types + * The given operator \a op is required to be: + * -# (no requirement). + * \endparblock + * + * \parblock + * \par Performance semantics + * -# This call comprises \f$ \Theta(n) \f$ work, where \f$ n \f$ equals + * the size of the vector \a x. The constant factor depends on the + * cost of evaluating the underlying binary operator. A good + * implementation uses vectorised instructions whenever the input + * domains, the output domain, and the operator used allow for this. + * + * -# This call will not result in additional dynamic memory allocations. + * + * -# This call takes \f$ \mathcal{O}(1) \f$ memory beyond the memory + * used by the application at the point of a call to this function. + * + * -# This call incurs at most + * \f$ 2n \cdot \mathit{sizeof}(\mathit{IOType}) + \mathcal{O}(1) \f$ + * bytes of data movement. + * \endparblock + * + * @see grb::operators::internal::Operator for a discussion on when in-place + * and/or vectorised operations are used. + */ + template< Descriptor descr = descriptors::no_operation, class Op, typename IOType, typename InputType, typename IOView, typename Coords > + RC foldl( VectorView< IOType, IOView, storage::Dense, reference_dense, Coords > & x, + const InputType beta, + const Op & op = Op(), + const typename std::enable_if< ! grb::is_object< IOType >::value && ! grb::is_object< InputType >::value && grb::is_operator< Op >::value, void >::type * = NULL ) { + // static sanity checks + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Op::D1, IOType >::value ), "grb::foldl", + "called with a vector x of a type that does not match the first domain " + "of the given operator" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Op::D2, InputType >::value ), "grb::foldl", + "called on a vector y of a type that does not match the second domain " + "of the given operator" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Op::D3, IOType >::value ), "grb::foldl", + "called on a vector x of a type that does not match the third domain " + "of the given operator" ); + + throw std::runtime_error( "Needs an implementation." ); + return SUCCESS; + } + + /** + * For all elements in a ALP VectorView \a x, fold the value \f$ \beta \f$ + * into each element. + * + * Masked operator variant. + */ + template< Descriptor descr = descriptors::no_operation, class Op, typename IOType, typename MaskType, typename InputType, typename MaskView, typename InputView, typename Coords > + RC foldl( VectorView< IOType, IOView, storage::Dense, reference_dense, Coords > & x, + const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & m, + const InputType beta, + const Op & op = Op(), + const typename std::enable_if< ! grb::is_object< IOType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType >::value && grb::is_operator< Op >::value, void >::type * = + NULL ) { + // static sanity checks + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Op::D1, IOType >::value ), "grb::foldl", + "called with a vector x of a type that does not match the first domain " + "of the given operator" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Op::D2, InputType >::value ), "grb::foldl", + "called on a vector y of a type that does not match the second domain " + "of the given operator" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Op::D3, IOType >::value ), "grb::foldl", + "called on a vector x of a type that does not match the third domain " + "of the given operator" ); + NO_CAST_OP_ASSERT( + ( ! ( descr & descriptors::no_casting ) || std::is_same< bool, MaskType >::value ), "grb::foldl (reference_dense, vector <- scalar, masked)", "provided mask does not have boolean entries" ); + if( size( m ) == 0 ) { + return foldl< descr >( x, beta, op ); + } + throw std::runtime_error( "Needs an implementation." ); + return SUCCESS; + } + + /** + * For all elements in a ALP VectorView \a x, fold the value \f$ \beta \f$ + * into each element. + * + * The original value of \f$ \beta \f$ is used as the right-hand side input + * of the operator \a op. The left-hand side inputs for \a op are retrieved + * from the input vector \a x. The result of the operation is stored in + * \f$ \beta \f$, thus overwriting its previous value. This process is + * repeated for every element in \a y. + * + * The value of \f$ x_i \f$ after a call to thus function thus equals + * \f$ x_i \odot \beta \f$, for all \f$ i \in \{ 0, 1, \dots, n - 1 \} \f$. + * + * @tparam descr The descriptor used for evaluating this function. By + * default, this is grb::descriptors::no_operation. + * @tparam Monoid The type of the monoid to be applied. + * @tparam IOType The type of the value \a beta. + * @tparam InputType The type of the elements of \a x. + * + * @param[in,out] x On function entry: the initial values to be applied as + * the left-hand side input to \a op. + * On function exit: the output data. + * @param[in] beta The input value to apply as the right-hand side input + * to \a op. + * @param[in] monoid The monoid under which to perform this left-folding. + * + * @returns grb::SUCCESS This function always succeeds. + * + * \note This function is also defined for operators. + * + * \parblock + * \par Valid descriptors + * grb::descriptors::no_operation, grb::descriptors::no_casting. + * + * \note Invalid descriptors will be ignored. + * + * If grb::descriptors::no_casting is specified, then 1) the first domain of + * \a op must match \a IOType, 2) the second domain of \a op must match + * \a InputType, and 3) the third domain must match \a IOType. If one of these + * is not true, the code shall not compile. + * + * \endparblock + * + * \parblock + * \par Valid operator types + * The given operator \a op is required to be: + * -# (no requirement). + * \endparblock + * + * \parblock + * \par Performance semantics + * -# This call comprises \f$ \Theta(n) \f$ work, where \f$ n \f$ equals + * the size of the vector \a x. The constant factor depends on the + * cost of evaluating the underlying binary operator. A good + * implementation uses vectorised instructions whenever the input + * domains, the output domain, and the operator used allow for this. + * + * -# This call will not result in additional dynamic memory allocations. + * + * -# This call takes \f$ \mathcal{O}(1) \f$ memory beyond the memory + * used by the application at the point of a call to this function. + * + * -# This call incurs at most + * \f$ 2n \cdot \mathit{sizeof}(\mathit{IOType}) + \mathcal{O}(1) \f$ + * bytes of data movement. + * \endparblock + * + * @see grb::operators::internal::Operator for a discussion on when in-place + * and/or vectorised operations are used. + */ + template< Descriptor descr = descriptors::no_operation, class Monoid, typename IOType, typename InputType, typename IOView, typename Coords > + RC foldl( VectorView< IOType, IOView, storage::Dense, reference_dense, Coords > & x, + const InputType beta, + const Monoid & monoid = Monoid(), + const typename std::enable_if< ! grb::is_object< IOType >::value && ! grb::is_object< InputType >::value && grb::is_monoid< Monoid >::value, void >::type * = NULL ) { + // static sanity checks + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Monoid::D1, IOType >::value ), "grb::foldl", + "called with a vector x of a type that does not match the first domain " + "of the given monoid" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Monoid::D2, InputType >::value ), "grb::foldl", + "called on a vector y of a type that does not match the second domain " + "of the given monoid" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Monoid::D3, IOType >::value ), "grb::foldl", + "called on a vector x of a type that does not match the third domain " + "of the given monoid" ); + + throw std::runtime_error( "Needs an implementation." ); + return SUCCESS; + } + + /** + * For all elements in a ALP VectorView \a x, fold the value \f$ \beta \f$ + * into each element. + * + * Masked monoid variant. + */ + template< Descriptor descr = descriptors::no_operation, class Monoid, typename IOType, typename MaskType, typename InputType, typename IOView, typename MaskView, typename Coords > + RC foldl( VectorView< IOType, IOView, storage::Dense, reference_dense, Coords > & x, + const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & m, + const InputType & beta, + const Monoid & monoid = Monoid(), + const typename std::enable_if< ! grb::is_object< IOType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType >::value && grb::is_monoid< Monoid >::value, void >::type * = + NULL ) { + // static sanity checks + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Monoid::D1, IOType >::value ), "grb::foldl", + "called with a vector x of a type that does not match the first domain " + "of the given monoid" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Monoid::D2, InputType >::value ), "grb::foldl", + "called on a vector y of a type that does not match the second domain " + "of the given monoid" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Monoid::D3, IOType >::value ), "grb::foldl", + "called on a vector x of a type that does not match the third domain " + "of the given monoid" ); + NO_CAST_OP_ASSERT( + ( ! ( descr & descriptors::no_casting ) || std::is_same< bool, MaskType >::value ), "grb::foldl (reference_dense, vector <- scalar, masked, monoid)", "provided mask does not have boolean entries" ); + if( size( m ) == 0 ) { + return foldl< descr >( x, beta, monoid ); + } + + throw std::runtime_error( "Needs an implementation." ); + return SUCCESS; + } + + /** + * Folds all elements in a ALP VectorView \a y into the corresponding + * elements from an input/output vector \a x. The vectors must be of equal + * size \f$ n \f$. For all \f$ i \in \{0,1,\ldots,n-1\} \f$, the new value + * of at the i-th index of \a x after a call to this function thus equals + * \f$ x_i \odot y_i \f$. + * + * @tparam descr The descriptor used for evaluating this function. By + * default, this is grb::descriptors::no_operation. + * @tparam OP The type of the operator to be applied. + * @tparam IOType The type of the value \a x. + * @tparam InputType The type of the elements of \a y. + * + * @param[in,out] x On function entry: the vector whose elements are to be + * applied to \a op as the left-hand side input. + * On function exit: the vector containing the result of + * the requested computation. + * @param[in] y The input vector \a y whose elements are to be applied + * to \a op as right-hand side input. + * @param[in] op The operator under which to perform this left-folding. + * + * @returns grb::SUCCESS This function always succeeds. + * + * \note This function is also defined for monoids. + * + * \parblock + * \par Valid descriptors + * grb::descriptors::no_operation, grb::descriptors::no_casting. + * + * \note Invalid descriptors will be ignored. + * + * If grb::descriptors::no_casting is specified, then 1) the first domain of + * \a op must match \a IOType, 2) the second domain of \a op must match + * \a InputType, and 3) the third domain must match \a IOType. If one of these + * is not true, the code shall not compile. + * + * \endparblock + * + * \parblock + * \par Valid operator types + * The given operator \a op is required to be: + * -# (no requirements). + * \endparblock + * + * \parblock + * \par Performance semantics + * -# This call comprises \f$ \Theta(n) \f$ work, where \f$ n \f$ equals + * the size of the vector \a x. The constant factor depends on the + * cost of evaluating the underlying binary operator. A good + * implementation uses vectorised instructions whenever the input + * domains, the output domain, and the operator used allow for this. + * + * -# This call will not result in additional dynamic memory allocations. + * + * -# This call takes \f$ \mathcal{O}(1) \f$ memory beyond the memory + * used by the application at the point of a call to this function. + * + * -# This call incurs at most + * \f$ n \cdot ( + * \mathit{sizeof}(\mathit{IOType}) + + * \mathit{sizeof}(\mathit{InputType}) + * ) + \mathcal{O}(1) \f$ + * bytes of data movement. A good implementation will apply in-place + * vectorised instructions whenever the input domains, the output + * domain, and the operator used allow for this. + * \endparblock + * + * @see grb::operators::internal::Operator for a discussion on when in-place + * and/or vectorised operations are used. + */ + template< Descriptor descr = descriptors::no_operation, class OP, typename IOType, typename InputType, typename IOView, typename InputView, typename Coords > + RC foldl( VectorView< IOType, IOView, storage::Dense, reference_dense, Coords > & x, + const VectorView< InputType, InputView, storage::Dense, reference_dense, Coords > & y, + const OP & op = OP(), + const typename std::enable_if< grb::is_operator< OP >::value && ! grb::is_object< IOType >::value && ! grb::is_object< InputType >::value, void >::type * = NULL ) { + // static sanity checks + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename OP::D1, IOType >::value ), "grb::foldl", + "called with a vector x of a type that does not match the first domain " + "of the given operator" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename OP::D2, InputType >::value ), "grb::foldl", + "called on a vector y of a type that does not match the second domain " + "of the given operator" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename OP::D3, IOType >::value ), "grb::foldl", + "called on a vector x of a type that does not match the third domain " + "of the given operator" ); + + // dynamic sanity checks + const size_t n = size( x ); + if( n != size( y ) ) { + return MISMATCH; + } + + throw std::runtime_error( "Needs an implementation." ); + return SUCCESS; + } + + /** + * Folds all elements in a ALP VectorView \a y into the corresponding + * elements from an input/output vector \a x. The vectors must be of equal + * size \f$ n \f$. For all \f$ i \in \{0,1,\ldots,n-1\} \f$, the new value + * of at the i-th index of \a x after a call to this function thus equals + * \f$ x_i \odot y_i \f$. + * + * @tparam descr The descriptor used for evaluating this function. By + * default, this is grb::descriptors::no_operation. + * @tparam Monoid The type of the monoid to be applied. + * @tparam IOType The type of the value \a x. + * @tparam InputType The type of the elements of \a y. + * + * @param[in,out] x On function entry: the vector whose elements are to be + * applied to \a op as the left-hand side input. + * On function exit: the vector containing the result of + * the requested computation. + * @param[in] y The input vector \a y whose elements are to be applied + * to \a op as right-hand side input. + * @param[in] monoid The operator under which to perform this left-folding. + * + * @returns grb::SUCCESS This function always succeeds. + * + * \note This function is also defined for operators. + * + * \parblock + * \par Valid descriptors + * grb::descriptors::no_operation, grb::descriptors::no_casting. + * + * \note Invalid descriptors will be ignored. + * + * If grb::descriptors::no_casting is specified, then 1) the first domain of + * \a op must match \a IOType, 2) the second domain of \a op must match + * \a InputType, and 3) the third domain must match \a IOType. If one of these + * is not true, the code shall not compile. + * + * \endparblock + * + * \parblock + * \par Valid operator types + * The given operator \a op is required to be: + * -# (no requirements). + * \endparblock + * + * \parblock + * \par Performance semantics + * -# This call comprises \f$ \Theta(n) \f$ work, where \f$ n \f$ equals + * the size of the vector \a x. The constant factor depends on the + * cost of evaluating the underlying binary operator. A good + * implementation uses vectorised instructions whenever the input + * domains, the output domain, and the operator used allow for this. + * + * -# This call will not result in additional dynamic memory allocations. + * + * -# This call takes \f$ \mathcal{O}(1) \f$ memory beyond the memory + * used by the application at the point of a call to this function. + * + * -# This call incurs at most + * \f$ n \cdot ( + * \mathit{sizeof}(\mathit{IOType}) + + * \mathit{sizeof}(\mathit{InputType}) + * ) + \mathcal{O}(1) \f$ + * bytes of data movement. A good implementation will apply in-place + * vectorised instructions whenever the input domains, the output + * domain, and the operator used allow for this. + * \endparblock + * + * @see grb::operators::internal::Operator for a discussion on when in-place + * and/or vectorised operations are used. + */ + template< Descriptor descr = descriptors::no_operation, class Monoid, typename IOType, typename InputType, typename IOView, typename InputView, typename Coords > + RC foldl( VectorView< IOType, IOView, storage::Dense, reference_dense, Coords > & x, + const VectorView< InputType, InputView, storage::Dense, reference_dense, Coords > & y, + const Monoid & monoid = Monoid(), + const typename std::enable_if< grb::is_monoid< Monoid >::value && ! grb::is_object< IOType >::value && ! grb::is_object< InputType >::value, void >::type * = NULL ) { + // static sanity checks + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Monoid::D1, IOType >::value ), "grb::foldl", + "called with a vector x of a type that does not match the first domain " + "of the given operator" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Monoid::D2, InputType >::value ), "grb::foldl", + "called on a vector y of a type that does not match the second domain " + "of the given operator" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Monoid::D3, IOType >::value ), "grb::foldl", + "called on a vector x of a type that does not match the third domain " + "of the given operator" ); + + // dynamic sanity checks + const size_t n = size( x ); + if( n != size( y ) ) { + return MISMATCH; + } + + throw std::runtime_error( "Needs an implementation." ); + return SUCCESS; + } + + /** + * Computes \f$ y = y . x \f$ for a given operator. + * + * Masked variant. + */ + template< Descriptor descr = descriptors::no_operation, class OP, typename IOType, typename MaskType, typename InputType, typename IOView, typename MaskView, typename InputView, typename Coords > + RC foldl( VectorView< IOType, IOView, storage::Dense, reference_dense, Coords > & x, + const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & m, + const VectorView< InputType, InputView, storage::Dense, reference_dense, Coords > & y, + const OP & op = OP(), + const typename std::enable_if< grb::is_operator< OP >::value && ! grb::is_object< IOType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType >::value, void >::type * = + NULL ) { + // static sanity checks + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename OP::D1, IOType >::value ), "grb::foldl", + "called with a vector x of a type that does not match the first domain " + "of the given operator" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename OP::D2, InputType >::value ), "grb::foldl", + "called on a vector y of a type that does not match the second domain " + "of the given operator" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename OP::D3, IOType >::value ), "grb::foldl", + "called on a vector x of a type that does not match the third domain " + "of the given operator" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< bool, MaskType >::value ), "grb::foldl", "called with a mask that does not have boolean entries " ); + + // catch empty mask + if( size( m ) == 0 ) { + return foldl< descr >( x, y, op ); + } + + // dynamic sanity checks + const size_t n = size( x ); + if( n != size( y ) || n != size( m ) ) { + return MISMATCH; + } + + throw std::runtime_error( "Needs an implementation." ); + return SUCCESS; + } + + /** + * Computes \f$ y = y + x \f$ for a given monoid. + * + * Masked variant. + */ + template< Descriptor descr = descriptors::no_operation, class Monoid, typename IOType, typename MaskType, typename InputType, typename IOView, typename MaskView, typename InputView, typename Coords > + RC foldl( VectorView< IOType, IOView, storage::Dense, reference_dense, Coords > & x, + const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & m, + const VectorView< InputType, InputView, storage::Dense, reference_dense, Coords > & y, + const Monoid & monoid = Monoid(), + const typename std::enable_if< grb::is_monoid< Monoid >::value && ! grb::is_object< IOType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType >::value, void >::type * = + NULL ) { + // static sanity checks + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Monoid::D1, IOType >::value ), "grb::foldl", + "called with a vector x of a type that does not match the first domain " + "of the given operator" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Monoid::D2, InputType >::value ), "grb::foldl", + "called on a vector y of a type that does not match the second domain " + "of the given operator" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Monoid::D3, IOType >::value ), "grb::foldl", + "called on a vector x of a type that does not match the third domain " + "of the given operator" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< bool, MaskType >::value ), "grb::foldl", "called with a mask that does not have boolean entries " ); + + // catch empty mask + if( size( m ) == 0 ) { + return foldl< descr >( x, y, monoid ); + } + + // dynamic sanity checks + const size_t n = size( x ); + if( n != size( y ) || n != size( m ) ) { + return MISMATCH; + } + + throw std::runtime_error( "Needs an implementation." ); + return SUCCESS; + } + + /** + * Calculates the element-wise operation on one scalar to elements of one + * vector, \f$ z = x .* \beta \f$, using the given operator. The input and + * output vectors must be of equal length. + * + * The vectors \a x or \a y may not be sparse. + * + * For all valid indices \a i of \a z, its element \f$ z_i \f$ after + * the call to this function completes equals \f$ x_i \odot \beta \f$. + * + * \warning Use of sparse vectors is only supported in full generality + * when applied via a monoid or semiring; otherwise, there is + * no concept for correctly interpreting any missing vector + * elements during the requested computation. + * \note When applying element-wise operators on sparse vectors + * using semirings, there is a difference between interpreting missing + * values as an annihilating identity or as a neutral identity-- + * intuitively, such identities are known as `zero' or `one', + * respectively. As a consequence, there are three different variants + * for element-wise operations whose names correspond to their + * intuitive meanings w.r.t. those identities: + * -# eWiseAdd (neutral), + * -# eWiseMul (annihilating), and + * -# eWiseApply using monoids (neutral). + * An eWiseAdd with some semiring and an eWiseApply using its additive + * monoid are totally equivalent. + * + * @tparam descr The descriptor to be used. Equal to + * descriptors::no_operation if left unspecified. + * @tparam OP The operator to use. + * @tparam InputType1 The value type of the left-hand vector. + * @tparam InputType2 The value type of the right-hand scalar. + * @tparam OutputType The value type of the ouput vector. + * + * @param[in] x The left-hand input vector. + * @param[in] beta The right-hand input scalar. + * @param[out] z The pre-allocated output vector. + * @param[in] op The operator to use. + * + * @return grb::MISMATCH Whenever the dimensions of \a x and \a z do not + * match. All input data containers are left untouched + * if this exit code is returned; it will be as though + * this call was never made. + * @return grb::SUCCESS On successful completion of this call. + * + * \parblock + * \par Performance semantics + * -# This call comprises \f$ \Theta(n) \f$ work, where \f$ n \f$ equals + * the size of the vectors \a x and \a z. The constant factor depends + * on the cost of evaluating the operator. A good implementation uses + * vectorised instructions whenever the input domains, the output + * domain, and the operator used allow for this. + * + * -# This call takes \f$ \mathcal{O}(1) \f$ memory beyond the memory + * used by the application at the point of a call to this function. + * + * -# This call incurs at most + * \f$ n( + * \mathit{sizeof}(\mathit{D1}) + \mathit{sizeof}(\mathit{D3}) + * ) + + * \mathcal{O}(1) \f$ + * bytes of data movement. A good implementation will stream \a y + * into \a z to apply the multiplication operator in-place, whenever + * the input domains, the output domain, and the operator allow for + * this. + * \endparblock + */ + template< Descriptor descr = descriptors::no_operation, class OP, typename OutputType, typename InputType1, typename InputType2, typename OutputView, typename InputView1, typename InputView2, typename OutputView, typename InputView1, typename Coords > + RC eWiseApply( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, + const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords > & x, + const InputType2 beta, + const OP & op = OP(), + const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_operator< OP >::value, + void >::type * const = NULL ) { + #ifdef _DEBUG + std::cout << "In eWiseApply ([T1]<-[T2]<-T3), operator variant\n"; + #endif + throw std::runtime_error( "Needs an implementation." ); + return SUCCESS; + } + + /** + * Computes \f$ z = x \odot y \f$, out of place. + * + * Specialisation for \a x and \a y scalar, operator version. + */ + template< Descriptor descr = descriptors::no_operation, class OP, typename OutputType, typename InputType1, typename InputType2, typename OutputView, typename InputView1, typename InputView2, typename OutputView, typename Coords > + RC eWiseApply( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, + const InputType1 alpha, + const InputType2 beta, + const OP & op = OP(), + const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_operator< OP >::value, + void >::type * const = NULL ) { + #ifdef _DEBUG + std::cout << "In eWiseApply ([T1]<-T2<-T3), operator variant\n"; + #endif + typename OP::D3 val; + RC ret = apply< descr >( val, alpha, beta, op ); + ret = ret ? ret : set< descr >( z, val ); + return ret; + } + + /** + * Computes \f$ z = x \odot y \f$, out of place. + * + * Specialisation for \a x and \a y scalar, monoid version. + */ + template< Descriptor descr = descriptors::no_operation, class Monoid, typename OutputType, typename InputType1, typename InputType2, typename OutputView, typename InputView1, typename InputView2, typename OutputView, typename Coords > + RC eWiseApply( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, + const InputType1 alpha, + const InputType2 beta, + const Monoid & monoid = Monoid(), + const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_monoid< Monoid >::value, + void >::type * const = NULL ) { + #ifdef _DEBUG + std::cout << "In eWiseApply ([T1]<-T2<-T3), monoid variant\n"; + #endif + // simply delegate to operator variant + return eWiseApply< descr >( z, alpha, beta, monoid.getOperator() ); + } + + /** + * Computes \f$ z = x \odot y \f$, out of place. + * + * Specialisation for scalar \a y, masked operator version. + */ + template< Descriptor descr = descriptors::no_operation, class OP, typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename OutputView, typename MaskView, typename InputView1, typename InputView2, typename OutputView, typename MaskView, typename InputView1, typename Coords > + RC eWiseApply( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, + const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & mask, + const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords > & x, + const InputType2 beta, + const OP & op = OP(), + const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && + grb::is_operator< OP >::value, + void >::type * const = NULL ) { + #ifdef _DEBUG + std::cout << "In masked eWiseApply ([T1]<-[T2]<-T3, using operator)\n"; + #endif + // check for empty mask + if( size( mask ) == 0 ) { + return eWiseApply< descr >( z, x, beta, op ); + } + throw std::runtime_error( "Needs an implementation." ); + return SUCCESS; + } + + /** + * Computes \f$ z = x \odot y \f$, out of place. + * + * Monoid version. + */ + template< Descriptor descr = descriptors::no_operation, class Monoid, typename OutputType, typename InputType1, typename InputType2, typename OutputView, typename InputView1, typename InputView2, typename OutputView, typename InputView1, typename InputView2, typename Coords > + RC eWiseApply( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, + const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords > & x, + const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords > & y, + const Monoid & monoid = Monoid(), + const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_monoid< Monoid >::value, + void >::type * const = NULL ) { + #ifdef _DEBUG + std::cout << "In unmasked eWiseApply ([T1]<-[T2]<-[T3], using monoid)\n"; + #endif + throw std::runtime_error( "Needs an implementation." ); + return SUCCESS; + } + + /** + * Computes \f$ z = x \odot y \f$, out of place. + * + * Specialisation for scalar \a x. Monoid version. + */ + template< Descriptor descr = descriptors::no_operation, class Monoid, typename OutputType, typename InputType1, typename InputType2, typename OutputView, typename InputView1, typename InputView2, typename OutputView, typename InputView2, typename Coords > + RC eWiseApply( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, + const InputType1 alpha, + const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords > & y, + const Monoid & monoid = Monoid(), + const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_monoid< Monoid >::value, + void >::type * const = NULL ) { + #ifdef _DEBUG + std::cout << "In unmasked eWiseApply ([T1]<-T2<-[T3], using monoid)\n"; + #endif + throw std::runtime_error( "Needs an implementation." ); + return SUCCESS; + } + + /** + * Computes \f$ z = x \odot y \f$, out of place. + * + * Specialisation for scalar \a y. Monoid version. + */ + template< Descriptor descr = descriptors::no_operation, class Monoid, typename OutputType, typename InputType1, typename InputType2, typename OutputView, typename InputView1, typename InputView2, typename OutputView, typename InputView1, typename Coords > + RC eWiseApply( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, + const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords > & x, + const InputType2 beta, + const Monoid & monoid = Monoid(), + const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_monoid< Monoid >::value, + void >::type * const = NULL ) { + #ifdef _DEBUG + std::cout << "In unmasked eWiseApply ([T1]<-[T2]<-T3, using monoid)\n"; + #endif + throw std::runtime_error( "Needs an implementation." ); + return SUCCESS; + } + + /** + * Computes \f$ z = x \odot y \f$, out of place. + * + * Masked monoid version. + */ + template< Descriptor descr = descriptors::no_operation, class Monoid, typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename OutputView, typename MaskView, typename InputView1, typename InputView2, typename Coords > + RC eWiseApply( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, + const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & mask, + const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords > & x, + const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords > & y, + const Monoid & monoid = Monoid(), + const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && + grb::is_monoid< Monoid >::value, + void >::type * const = NULL ) { + #ifdef _DEBUG + std::cout << "In masked eWiseApply ([T1]<-[T2]<-[T3], using monoid)\n"; + #endif + throw std::runtime_error( "Needs an implementation." ); + return SUCCESS; + } + + /** + * Computes \f$ z = x \odot y \f$, out of place. + * + * Specialisation for scalar \a x. Masked monoid version. + */ + template< Descriptor descr = descriptors::no_operation, class Monoid, typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename OutputView, typename MaskView, typename InputView1, typename InputView2, typename Coords > + RC eWiseApply( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, + const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & mask, + const InputType1 alpha, + const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords > & y, + const Monoid & monoid = Monoid(), + const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && + grb::is_monoid< Monoid >::value, + void >::type * const = NULL ) { + #ifdef _DEBUG + std::cout << "In masked eWiseApply ([T1]<-T2<-[T3], using monoid)\n"; + #endif + throw std::runtime_error( "Needs an implementation." ); + return SUCCESS; + } + + /** + * Computes \f$ z = x \odot y \f$, out of place. + * + * Specialisation for scalar \a y. Masked monoid version. + */ + template< Descriptor descr = descriptors::no_operation, class Monoid, typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename OutputView, typename MaskView, typename InputView1, typename InputView2, typename Coords > + RC eWiseApply( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, + const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & mask, + const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords > & x, + const InputType2 beta, + const Monoid & monoid = Monoid(), + const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && + grb::is_monoid< Monoid >::value, + void >::type * const = NULL ) { + #ifdef _DEBUG + std::cout << "In masked eWiseApply ([T1]<-[T2]<-T3, using monoid)\n"; + #endif + throw std::runtime_error( "Needs an implementation." ); + return SUCCESS; + } + + /** + * Calculates the element-wise operation on one scalar to elements of one + * vector, \f$ z = \alpha .* y \f$, using the given operator. The input and + * output vectors must be of equal length. + * + * The vectors \a x or \a y may not be sparse. + * + * For all valid indices \a i of \a z, its element \f$ z_i \f$ after + * the call to this function completes equals \f$ \alpha \odot y_i \f$. + * + * \warning Use of sparse vectors is only supported in full generality + * when applied via a monoid or semiring; otherwise, there is + * no concept for correctly interpreting any missing vector + * elements during the requested computation. + * \note When applying element-wise operators on sparse vectors + * using semirings, there is a difference between interpreting missing + * values as an annihilating identity or as a neutral identity-- + * intuitively, identities are known as `zero' or `one', + * respectively. As a consequence, there are three different variants + * for element-wise operations whose names correspond to their + * intuitive meanings w.r.t. those identities: + * -# eWiseAdd, + * -# eWiseMul, and + * -# eWiseMulAdd. + * + * @tparam descr The descriptor to be used. Equal to descriptors::no_operation + * if left unspecified. + * @tparam OP The operator to use. + * @tparam InputType1 The value type of the left-hand scalar. + * @tparam InputType2 The value type of the right-hand side vector. + * @tparam OutputType The value type of the ouput vector. + * + * @param[in] alpha The left-hand scalar. + * @param[in] y The right-hand input vector. + * @param[out] z The pre-allocated output vector. + * @param[in] op The operator to use. + * + * @return grb::MISMATCH Whenever the dimensions of \a y and \a z do not + * match. All input data containers are left untouched + * if this exit code is returned; it will be as though + * this call was never made. + * @return grb::SUCCESS On successful completion of this call. + * + * \parblock + * \par Performance semantics + * -# This call comprises \f$ \Theta(n) \f$ work, where \f$ n \f$ equals + * the size of the vectors \a y and \a z. The constant factor depends + * on the cost of evaluating the operator. A good implementation uses + * vectorised instructions whenever the input domains, the output + * domain, and the operator used allow for this. + * + * -# This call takes \f$ \mathcal{O}(1) \f$ memory beyond the memory + * used by the application at the point of a call to this function. + * + * -# This call incurs at most + * \f$ n( + * \mathit{sizeof}(\mathit{D2}) + \mathit{sizeof}(\mathit{D3}) + * ) + + * \mathcal{O}(1) \f$ + * bytes of data movement. A good implementation will stream \a y + * into \a z to apply the multiplication operator in-place, whenever + * the input domains, the output domain, and the operator allow for + * this. + * \endparblock + */ + template< Descriptor descr = descriptors::no_operation, class OP, typename OutputType, typename InputType1, typename InputType2, typename OutputView, typename InputView1, typename InputView2, typename Coords > + RC eWiseApply( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, + const InputType1 alpha, + const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords > & y, + const OP & op = OP(), + const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_operator< OP >::value, + void >::type * const = NULL ) { + #ifdef _DEBUG + std::cout << "In eWiseApply ([T1]<-T2<-[T3]), operator variant\n"; + #endif + throw std::runtime_error( "Needs an implementation." ); + return SUCCESS; + } + + /** + * Computes \f$ z = x \odot y \f$, out of place. + * + * Specialisation for scalar \a x. Masked operator version. + */ + template< Descriptor descr = descriptors::no_operation, class OP, typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename OutputView, typename MaskView, typename InputView1, typename InputView2, typename Coords > + RC eWiseApply( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, + const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & mask, + const InputType1 alpha, + const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords > & y, + const OP & op = OP(), + const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && + grb::is_operator< OP >::value, + void >::type * const = NULL ) { + #ifdef _DEBUG + std::cout << "In masked eWiseApply ([T1]<-T2<-[T3], operator variant)\n"; + #endif + throw std::runtime_error( "Needs an implementation." ); + return SUCCESS; + } + + /** + * Calculates the element-wise operation on elements of two vectors, + * \f$ z = x .* y \f$, using the given operator. The vectors must be + * of equal length. + * + * The vectors \a x or \a y may not be sparse. + * + * For all valid indices \a i of \a z, its element \f$ z_i \f$ after + * the call to this function completes equals \f$ x_i \odot y_i \f$. + * + * \warning Use of sparse vectors is only supported in full generality + * when applied via a monoid or semiring; otherwise, there is + * no concept for correctly interpreting any missing vector + * elements during the requested computation. + * \note When applying element-wise operators on sparse vectors + * using semirings, there is a difference between interpreting missing + * values as an annihilating identity or as a neutral identity-- + * intuitively, identities are known as `zero' or `one', + * respectively. As a consequence, there are three different variants + * for element-wise operations whose names correspond to their + * intuitive meanings w.r.t. those identities: + * -# eWiseAdd, + * -# eWiseMul, and + * -# eWiseMulAdd. + * + * @tparam descr The descriptor to be used (descriptors::no_operation if left + * unspecified). + * @tparam OP The operator to use. + * @tparam InputType1 The value type of the left-hand side vector. + * @tparam InputType2 The value type of the right-hand side vector. + * @tparam OutputType The value type of the ouput vector. + * + * @param[in] x The left-hand input vector. May not equal \a y. + * @param[in] y The right-hand input vector. May not equal \a x. + * @param[out] z The pre-allocated output vector. + * @param[in] op The operator to use. + * + * @return grb::ILLEGAL When \a x equals \a y. + * @return grb::MISMATCH Whenever the dimensions of \a x, \a y, and \a z + * do not match. All input data containers are left + * untouched if this exit code is returned; it will + * be as though this call was never made. + * @return grb::SUCCESS On successful completion of this call. + * + * \parblock + * \par Performance semantics + * -# This call comprises \f$ \Theta(n) \f$ work, where \f$ n \f$ equals + * the size of the vectors \a x, \a y, and \a z. The constant factor + * depends on the cost of evaluating the operator. A good + * implementation uses vectorised instructions whenever the input + * domains, the output domain, and the operator used allow for this. + * + * -# This call takes \f$ \mathcal{O}(1) \f$ memory beyond the memory + * used by the application at the point of a call to this function. + * + * -# This call incurs at most + * \f$ n( + * \mathit{sizeof}(\mathit{OutputType}) + + * \mathit{sizeof}(\mathit{InputType1}) + + * \mathit{sizeof}(\mathit{InputType2}) + * ) + + * \mathcal{O}(1) \f$ + * bytes of data movement. A good implementation will stream \a x or + * \a y into \a z to apply the multiplication operator in-place, + * whenever the input domains, the output domain, and the operator + * used allow for this. + * \endparblock + */ + template< Descriptor descr = descriptors::no_operation, class OP, typename OutputType, typename InputType1, typename InputType2, typename OutputView, typename InputView1, typename InputView2, typename Coords > + RC eWiseApply( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, + const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords > & x, + const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords > & y, + const OP & op = OP(), + const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_operator< OP >::value, + void >::type * const = NULL ) { + #ifdef _DEBUG + std::cout << "In eWiseApply ([T1]<-[T2]<-[T3]), operator variant\n"; + #endif + throw std::runtime_error( "Needs an implementation." ); + return SUCCESS; + } + + /** + * Computes \f$ z = x \odot y \f$, out of place. + * + * Masked operator version. + */ + template< Descriptor descr = descriptors::no_operation, class OP, typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename OutputView, typename MaskView, typename InputView1, typename InputView2, typename Coords > + RC eWiseApply( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, + const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & mask, + const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords > & x, + const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords > & y, + const OP & op = OP(), + const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && + grb::is_operator< OP >::value, + void >::type * const = NULL ) { + #ifdef _DEBUG + std::cout << "In masked eWiseApply ([T1]<-[T2]<-[T3], using operator)\n"; + #endif + throw std::runtime_error( "Needs an implementation." ); + return SUCCESS; + } + + /** + * Calculates the element-wise addition of two vectors, \f$ z = x .+ y \f$, + * under this semiring. + * + * @tparam descr The descriptor to be used (descriptors::no_operation + * if left unspecified). + * @tparam Ring The semiring type to perform the element-wise addition + * on. + * @tparam InputType1 The left-hand side input type to the additive operator + * of the \a ring. + * @tparam InputType2 The right-hand side input type to the additive operator + * of the \a ring. + * @tparam OutputType The the result type of the additive operator of the + * \a ring. + * + * @param[out] z The output vector of type \a OutputType. This may be a + * sparse vector. + * @param[in] x The left-hand input vector of type \a InputType1. This may + * be a sparse vector. + * @param[in] y The right-hand input vector of type \a InputType2. This may + * be a sparse vector. + * @param[in] ring The generalized semiring under which to perform this + * element-wise multiplication. + * + * @return grb::MISMATCH Whenever the dimensions of \a x, \a y, and \a z do + * not match. All input data containers are left + * untouched; it will be as though this call was never + * made. + * @return grb::SUCCESS On successful completion of this call. + * + * \parblock + * \par Valid descriptors + * grb::descriptors::no_operation, grb::descriptors::no_casting, + * grb::descriptors::dense. + * + * \note Invalid descriptors will be ignored. + * + * If grb::descriptors::no_casting is specified, then 1) the third domain of + * \a ring must match \a InputType1, 2) the fourth domain of \a ring must match + * \a InputType2, 3) the fourth domain of \a ring must match \a OutputType. If + * one of these is not true, the code shall not compile. + * \endparblock + * + * \parblock + * \par Performance semantics + * -# This call takes \f$ \Theta(n) \f$ work, where \f$ n \f$ equals the + * size of the vectors \a x, \a y, and \a z. The constant factor + * depends on the cost of evaluating the addition operator. A good + * implementation uses vectorised instructions whenever the input + * domains, the output domain, and the the additive operator used + * allow for this. + * + * -# This call will not result in additional dynamic memory allocations. + * No system calls will be made. + * + * -# This call takes \f$ \mathcal{O}(1) \f$ memory beyond the memory + * used by the application at the point of a call to this function. + * + * -# This call incurs at most + * \f$ n( \mathit{sizeof}( + * \mathit{InputType1} + + * \mathit{InputType2} + + * \mathit{OutputType} + * ) + \mathcal{O}(1) \f$ + * bytes of data movement. A good implementation will stream \a x or + * \a y into \a z to apply the additive operator in-place, whenever + * the input domains, the output domain, and the operator used allow + * for this. + * \endparblock + * + * @see This is a specialised form of eWiseMulAdd. + */ + template< Descriptor descr = descriptors::no_operation, class Ring, typename OutputType, typename InputType1, typename InputType2, typename OutputView, typename InputView1, typename InputView2, typename Coords > + RC eWiseAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, + const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords > & x, + const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords > & y, + const Ring & ring = Ring(), + const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_semiring< Ring >::value, + void >::type * const = NULL ) { + // static sanity checks + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, OutputType >::value ), "grb::eWiseAdd", + "called with an output vector with element type that does not match the " + "fourth domain of the given semiring" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D3, InputType1 >::value ), "grb::eWiseAdd", + "called with a left-hand side input vector with element type that does not " + "match the third domain of the given semiring" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, OutputType >::value ), "grb::eWiseAdd", + "called with a right-hand side input vector with element type that does " + "not match the fourth domain of the given semiring" ); + #ifdef _DEBUG + std::cout << "eWiseAdd (reference_dense, vector <- vector + vector) dispatches to eWiseApply( reference_dense, vector <- vector . vector ) using additive monoid\n"; + #endif + return eWiseApply< descr >( z, x, y, ring.getAdditiveMonoid() ); + } + + /** + * Calculates the element-wise addition of two vectors, \f$ z = x .+ y \f$, + * under the given semiring. + * + * Specialisation for scalar \a x. + */ + template< Descriptor descr = descriptors::no_operation, class Ring, typename InputType1, typename InputType2, typename OutputType, typename InputView2, typename OutputView, typename Coords > + RC eWiseAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, + const InputType1 alpha, + const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords > & y, + const Ring & ring = Ring(), + const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_semiring< Ring >::value, + void >::type * const = NULL ) { + // static sanity checks + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D1, InputType1 >::value ), "grb::eWiseAdd", + "called with a left-hand side input vector with element type that does not " + "match the first domain of the given semiring" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D2, InputType2 >::value ), "grb::eWiseAdd", + "called with a right-hand side input vector with element type that does " + "not match the second domain of the given semiring" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D3, OutputType >::value ), "grb::eWiseAdd", + "called with an output vector with element type that does not match the " + "third domain of the given semiring" ); + #ifdef _DEBUG + std::cout << "eWiseAdd (reference_dense, vector <- scalar + vector) dispatches to eWiseApply with additive monoid\n"; + #endif + return eWiseApply< descr >( z, alpha, y, ring.getAdditiveMonoid() ); + } + + /** + * Calculates the element-wise addition of two vectors, \f$ z = x .+ y \f$, + * under the given semiring. + * + * Specialisation for scalar \a y. + */ + template< Descriptor descr = descriptors::no_operation, class Ring, typename InputType1, typename InputType2, typename OutputType, typename InputView1, typename OutputView,typename Coords > + RC eWiseAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, + const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords > & x, + const InputType2 beta, + const Ring & ring = Ring(), + const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_semiring< Ring >::value, + void >::type * const = NULL ) { + // static sanity checks + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D1, InputType1 >::value ), "grb::eWiseAdd", + "called with a left-hand side input vector with element type that does not " + "match the first domain of the given semiring" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D2, InputType2 >::value ), "grb::eWiseAdd", + "called with a right-hand side input vector with element type that does " + "not match the second domain of the given semiring" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D3, OutputType >::value ), "grb::eWiseAdd", + "called with an output vector with element type that does not match the " + "third domain of the given semiring" ); + #ifdef _DEBUG + std::cout << "eWiseAdd (reference_dense, vector <- vector + scalar) dispatches to eWiseApply with additive monoid\n"; + #endif + return eWiseApply< descr >( z, x, beta, ring.getAdditiveMonoid() ); + } + + /** + * Calculates the element-wise addition of two vectors, \f$ z = x .+ y \f$, + * under the given semiring. + * + * Specialisation for scalar \a x and \a y. + */ + template< Descriptor descr = descriptors::no_operation, class Ring, typename InputType1, typename InputType2, typename OutputType, typename OutputView, typename Coords > + RC eWiseAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, + const InputType1 alpha, + const InputType2 beta, + const Ring & ring = Ring(), + const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_semiring< Ring >::value, + void >::type * const = NULL ) { + // static sanity checks + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D1, InputType1 >::value ), "grb::eWiseAdd", + "called with a left-hand side input vector with element type that does not " + "match the first domain of the given semiring" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D2, InputType2 >::value ), "grb::eWiseAdd", + "called with a right-hand side input vector with element type that does " + "not match the second domain of the given semiring" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D3, OutputType >::value ), "grb::eWiseAdd", + "called with an output vector with element type that does not match the " + "third domain of the given semiring" ); + #ifdef _DEBUG + std::cout << "eWiseAdd (reference_dense, vector <- scalar + scalar) dispatches to foldl with precomputed scalar and additive monoid\n"; + #endif + const typename Ring::D4 add; + (void)apply( add, alpha, beta, ring.getAdditiveOperator() ); + return foldl< descr >( z, add, ring.getAdditiveMonoid() ); + } + + /** + * Calculates the element-wise addition of two vectors, \f$ z = x .+ y \f$, + * under the given semiring. + * + * Masked version. + */ + template< Descriptor descr = descriptors::no_operation, class Ring, typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename OutputView, typename MaskView, typename InputView1, typename InputView2, typename Coords > + RC eWiseAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, + const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & m, + const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords > & x, + const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords > & y, + const Ring & ring = Ring(), + const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && + grb::is_semiring< Ring >::value, + void >::type * const = NULL ) { + // static sanity checks + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, OutputType >::value ), "grb::eWiseAdd", + "called with an output vector with element type that does not match the " + "fourth domain of the given semiring" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D3, InputType1 >::value ), "grb::eWiseAdd", + "called with a left-hand side input vector with element type that does not " + "match the third domain of the given semiring" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, OutputType >::value ), "grb::eWiseAdd", + "called with a right-hand side input vector with element type that does " + "not match the fourth domain of the given semiring" ); + NO_CAST_ASSERT( + ( ! ( descr & descriptors::no_casting ) || std::is_same< MaskType, bool >::value ), "grb::eWiseAdd (vector <- vector + vector, masked)", "called with non-bool mask element types" ); + #ifdef _DEBUG + std::cout << "eWiseAdd (reference_dense, vector <- vector + vector, masked) dispatches to eWiseApply( reference_dense, vector <- vector . vector ) using additive monoid\n"; + #endif + return eWiseApply< descr >( z, m, x, y, ring.getAdditiveMonoid() ); + } + + /** + * Calculates the element-wise addition of two vectors, \f$ z = x .+ y \f$, + * under the given semiring. + * + * Specialisation for scalar \a x, masked version + */ + template< Descriptor descr = descriptors::no_operation, class Ring, typename InputType1, typename InputType2, typename OutputType, typename MaskType, typename InputView2, typename OutputView, typename MaskView, typename Coords > + RC eWiseAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, + const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & m, + const InputType1 alpha, + const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords > & y, + const Ring & ring = Ring(), + const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && + grb::is_semiring< Ring >::value, + void >::type * const = NULL ) { + // static sanity checks + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D1, InputType1 >::value ), "grb::eWiseAdd", + "called with a left-hand side input vector with element type that does not " + "match the first domain of the given semiring" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D2, InputType2 >::value ), "grb::eWiseAdd", + "called with a right-hand side input vector with element type that does " + "not match the second domain of the given semiring" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D3, OutputType >::value ), "grb::eWiseAdd", + "called with an output vector with element type that does not match the " + "third domain of the given semiring" ); + NO_CAST_ASSERT( + ( ! ( descr & descriptors::no_casting ) || std::is_same< MaskType, bool >::value ), "grb::eWiseAdd (vector <- scalar + vector, masked)", "called with non-bool mask element types" ); + #ifdef _DEBUG + std::cout << "eWiseAdd (reference_dense, vector <- scalar + vector, masked) dispatches to eWiseApply with additive monoid\n"; + #endif + return eWiseApply< descr >( z, m, alpha, y, ring.getAdditiveMonoid() ); + } + + /** + * Calculates the element-wise addition of two vectors, \f$ z = x .+ y \f$, + * under the given semiring. + * + * Specialisation for scalar \a y, masked version. + */ + template< Descriptor descr = descriptors::no_operation, class Ring, typename InputType1, typename InputType2, typename OutputType, typename MaskType, typename InputView1, typename OutputView, typename MaskView, typename Coords > + RC eWiseAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, + const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & m, + const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords > & x, + const InputType2 beta, + const Ring & ring = Ring(), + const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && + grb::is_semiring< Ring >::value, + void >::type * const = NULL ) { + // static sanity checks + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D1, InputType1 >::value ), "grb::eWiseAdd", + "called with a left-hand side input vector with element type that does not " + "match the first domain of the given semiring" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D2, InputType2 >::value ), "grb::eWiseAdd", + "called with a right-hand side input vector with element type that does " + "not match the second domain of the given semiring" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D3, OutputType >::value ), "grb::eWiseAdd", + "called with an output vector with element type that does not match the " + "third domain of the given semiring" ); + NO_CAST_ASSERT( + ( ! ( descr & descriptors::no_casting ) || std::is_same< MaskType, bool >::value ), "grb::eWiseAdd (vector <- vector + scalar, masked)", "called with non-bool mask element types" ); + #ifdef _DEBUG + std::cout << "eWiseAdd (reference_dense, vector <- vector + scalar, masked) dispatches to eWiseApply with additive monoid\n"; + #endif + return eWiseApply< descr >( z, m, x, beta, ring.getAdditiveMonoid() ); + } + + /** + * Calculates the element-wise addition of two vectors, \f$ z = x .+ y \f$, + * under the given semiring. + * + * Specialisation for scalar \a x and \a y, masked version. + */ + template< Descriptor descr = descriptors::no_operation, class Ring, typename InputType1, typename InputType2, typename OutputType, typename MaskType, typename OutputView, typename Coords > + RC eWiseAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, + const VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & m, + const InputType1 alpha, + const InputType2 beta, + const Ring & ring = Ring(), + const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && + grb::is_semiring< Ring >::value, + void >::type * const = NULL ) { + // static sanity checks + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D1, InputType1 >::value ), "grb::eWiseAdd", + "called with a left-hand side input vector with element type that does not " + "match the first domain of the given semiring" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D2, InputType2 >::value ), "grb::eWiseAdd", + "called with a right-hand side input vector with element type that does " + "not match the second domain of the given semiring" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D3, OutputType >::value ), "grb::eWiseAdd", + "called with an output vector with element type that does not match the " + "third domain of the given semiring" ); + NO_CAST_ASSERT( + ( ! ( descr & descriptors::no_casting ) || std::is_same< MaskType, bool >::value ), "grb::eWiseAdd (vector <- scalar + scalar, masked)", "called with non-bool mask element types" ); + #ifdef _DEBUG + std::cout << "eWiseAdd (reference_dense, vector <- scalar + scalar, masked) dispatches to foldl with precomputed scalar and additive monoid\n"; + #endif + const typename Ring::D4 add; + (void)apply( add, alpha, beta, ring.getAdditiveOperator() ); + return foldl< descr >( z, m, add, ring.getAdditiveMonoid() ); + } + + /** + * Calculates the axpy, \f$ z = a * x .+ y \f$, under this semiring. + * + * Specialisation for when \a a is a scalar. + */ + template< Descriptor descr = descriptors::no_operation, class Ring, typename InputType1, typename InputType2, typename InputType3, typename OutputType, typename InputView2, typename InputView3, typename OutputView, typename Coords > + RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & _z, + const InputType1 alpha, + const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords > & _x, + const VectorView< InputType3, InputView3, storage::Dense, reference_dense, Coords > & _y, + const Ring & ring = Ring(), + const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && + grb::is_semiring< Ring >::value, + void >::type * const = NULL ) { + // static sanity checks + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D1, InputType1 >::value ), "grb::eWiseMulAdd", + "called with a left-hand scalar alpha of an element type that does not " + "match the first domain of the given semiring" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D2, InputType2 >::value ), "grb::eWiseMulAdd", + "called with a right-hand vector _x with an element type that does not " + "match the second domain of the given semiring" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, InputType3 >::value ), "grb::eWiseMulAdd", + "called with an additive vector _y with an element type that does not " + "match the fourth domain of the given semiring" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, OutputType >::value ), "grb::eWiseMulAdd", + "called with a result vector _z with an element type that does not match " + "the fourth domain of the given semiring" ); + throw std::runtime_error( "Needs an implementation." ); + return SUCCESS; + } + + /** + * Calculates the elementwise multiply-add, \f$ z = a .* x .+ y \f$, under + * this semiring. + * + * Specialisation for when \a x is a scalar. + */ + template< Descriptor descr = descriptors::no_operation, class Ring, typename InputType1, typename InputType2, typename InputType3, typename OutputType, typename InputView1, typename InputView3, typename OutputView, typename Coords > + RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & _z, + const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords > & _a, + const InputType2 chi, + const VectorView< InputType3, InputView3, storage::Dense, reference_dense, Coords > & _y, + const Ring & ring = Ring(), + const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && + grb::is_semiring< Ring >::value, + void >::type * const = NULL ) { + // static sanity checks + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D1, InputType1 >::value ), "grb::eWiseMulAdd", + "called with a left-hand scalar alpha of an element type that does not " + "match the first domain of the given semiring" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D2, InputType2 >::value ), "grb::eWiseMulAdd", + "called with a right-hand vector _x with an element type that does not " + "match the second domain of the given semiring" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, InputType3 >::value ), "grb::eWiseMulAdd", + "called with an additive vector _y with an element type that does not " + "match the fourth domain of the given semiring" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, OutputType >::value ), "grb::eWiseMulAdd", + "called with a result vector _z with an element type that does not match " + "the fourth domain of the given semiring" ); + throw std::runtime_error( "Needs an implementation." ); + return SUCCESS; + } + + /** + * Calculates the axpy, \f$ z = a * x .+ y \f$, under this semiring. + * + * Specialisation for when \a y is a scalar. + */ + template< Descriptor descr = descriptors::no_operation, class Ring, typename InputType1, typename InputType2, typename InputType3, typename OutputType, typename InputView1, typename InputView2, typename OutputView, typename Coords > + RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & _z, + const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords > & _a, + const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords > & _x, + const InputType3 gamma, + const Ring & ring = Ring(), + const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && + grb::is_semiring< Ring >::value, + void >::type * const = NULL ) { + // static sanity checks + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D1, InputType1 >::value ), "grb::eWiseMulAdd", + "called with a left-hand scalar alpha of an element type that does not " + "match the first domain of the given semiring" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D2, InputType2 >::value ), "grb::eWiseMulAdd", + "called with a right-hand vector _x with an element type that does not " + "match the second domain of the given semiring" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, InputType3 >::value ), "grb::eWiseMulAdd", + "called with an additive vector _y with an element type that does not " + "match the fourth domain of the given semiring" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, OutputType >::value ), "grb::eWiseMulAdd", + "called with a result vector _z with an element type that does not match " + "the fourth domain of the given semiring" ); + throw std::runtime_error( "Needs an implementation." ); + return SUCCESS; + } + + /** + * Calculates the axpy, \f$ z = a * x .+ y \f$, under this semiring. + * + * Specialisation for when \a x and \a y are scalar. + */ + template< Descriptor descr = descriptors::no_operation, class Ring, typename InputType1, typename InputType2, typename InputType3, typename OutputType, typename InputView1, typename OutputView, typename Coords > + RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & _z, + const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords > & _a, + const InputType2 beta, + const InputType3 gamma, + const Ring & ring = Ring(), + const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && + grb::is_semiring< Ring >::value, + void >::type * const = NULL ) { + // static sanity checks + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D1, InputType1 >::value ), "grb::eWiseMulAdd", + "called with a left-hand scalar alpha of an element type that does not " + "match the first domain of the given semiring" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D2, InputType2 >::value ), "grb::eWiseMulAdd", + "called with a right-hand vector _x with an element type that does not " + "match the second domain of the given semiring" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, InputType3 >::value ), "grb::eWiseMulAdd", + "called with an additive vector _y with an element type that does not " + "match the fourth domain of the given semiring" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, OutputType >::value ), "grb::eWiseMulAdd", + "called with a result vector _z with an element type that does not match " + "the fourth domain of the given semiring" ); + throw std::runtime_error( "Needs an implementation." ); + return SUCCESS; + } + + /** + * Calculates the axpy, \f$ z = a * x .+ y \f$, under this semiring. + * + * Specialisation for when \a a and \a y are scalar. + */ + template< Descriptor descr = descriptors::no_operation, class Ring, typename InputType1, typename InputType2, typename InputType3, typename OutputType, typename InputView2, typename OutputView, typename Coords > + RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & _z, + const InputType1 alpha, + const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords > & _x, + const InputType3 gamma, + const Ring & ring = Ring(), + const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && + grb::is_semiring< Ring >::value, + void >::type * const = NULL ) { + // static sanity checks + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D1, InputType1 >::value ), "grb::eWiseMulAdd", + "called with a left-hand scalar alpha of an element type that does not " + "match the first domain of the given semiring" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D2, InputType2 >::value ), "grb::eWiseMulAdd", + "called with a right-hand vector _x with an element type that does not " + "match the second domain of the given semiring" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, InputType3 >::value ), "grb::eWiseMulAdd", + "called with an additive vector _y with an element type that does not " + "match the fourth domain of the given semiring" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, OutputType >::value ), "grb::eWiseMulAdd", + "called with a result vector _z with an element type that does not match " + "the fourth domain of the given semiring" ); + throw std::runtime_error( "Needs an implementation." ); + return SUCCESS; + } + + /** + * Calculates the axpy, \f$ z = a * x .+ y \f$, under this semiring. + * + * Specialisation for when \a a and \a x are scalar. + * + * \internal Dispatches to eWiseAdd. + */ + template< Descriptor descr = descriptors::no_operation, class Ring, typename OutputType, typename InputType1, typename InputType2, typename InputType3, typename InputView3, typename OutputView, typename Coords > + RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, + const InputType1 alpha, + const InputType2 beta, + const VectorView< InputType3, InputView3, storage::Dense, reference_dense, Coords > & y, + const Ring & ring = Ring(), + const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && + grb::is_semiring< Ring >::value, + void >::type * const = NULL ) { + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D1, InputType1 >::value ), "grb::eWiseMulAdd(vector,scalar,scalar,scalar)", + "First domain of semiring does not match first input type" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D2, InputType2 >::value ), "grb::eWiseMulAdd(vector,scalar,scalar,scalar)", + "Second domain of semiring does not match second input type" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, InputType3 >::value ), "grb::eWiseMulAdd(vector,scalar,scalar,scalar)", + "Fourth domain of semiring does not match third input type" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, OutputType >::value ), "grb::eWiseMulAdd(vector,scalar,scalar,scalar)", + "Fourth domain of semiring does not match output type" ); + #ifdef _DEBUG + std::cout << "eWiseMulAdd (reference_dense, vector <- scalar x scalar + vector) precomputes scalar multiply and dispatches to eWiseAdd (reference_dense, vector <- scalar + vector)\n"; + #endif + typename Ring::D3 mul_result; + RC rc = grb::apply( mul_result, alpha, beta, ring.getMultiplicativeOperator() ); + #ifdef NDEBUG + (void)rc; + #else + assert( rc == SUCCESS ); + #endif + return grb::eWiseAdd( z, mul_result, y, ring ); + } + + /** + * Calculates the axpy, \f$ z = a * x .+ y \f$, under this semiring. + * + * Specialisation for when \a a, \a x, and \a y are scalar. + * + * \internal Dispatches to set. + */ + template< Descriptor descr = descriptors::no_operation, class Ring, typename OutputType, typename InputType1, typename InputType2, typename OutputView, typename Coords > + RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, + const InputType1 alpha, + const InputType2 beta, + const InputType3 gamma, + const Ring & ring = Ring(), + const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && + grb::is_semiring< Ring >::value, + void >::type * const = NULL ) { + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D1, InputType1 >::value ), "grb::eWiseMulAdd(vector,scalar,scalar,scalar)", + "First domain of semiring does not match first input type" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D2, InputType2 >::value ), "grb::eWiseMulAdd(vector,scalar,scalar,scalar)", + "Second domain of semiring does not match second input type" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, InputType3 >::value ), "grb::eWiseMulAdd(vector,scalar,scalar,scalar)", + "Fourth domain of semiring does not match third input type" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, OutputType >::value ), "grb::eWiseMulAdd(vector,scalar,scalar,scalar)", + "Fourth domain of semiring does not match output type" ); + #ifdef _DEBUG + std::cout << "eWiseMulAdd (reference_dense, vector <- scalar x scalar + scalar) precomputes scalar operations and dispatches to set (reference_dense)\n"; + #endif + typename Ring::D3 mul_result; + RC rc = grb::apply( mul_result, alpha, beta, ring.getMultiplicativeOperator() ); + #ifdef NDEBUG + (void)rc; + #endif + assert( rc == SUCCESS ); + typename Ring::D4 add_result; + rc = grb::apply( add_result, mul_result, gamma, ring.getAdditiveOperator() ); + #ifdef NDEBUG + (void)rc; + #endif + assert( rc == SUCCESS ); + return grb::set( z, add_result ); + } + + /** + * Calculates the elementwise multiply-add, \f$ z = a .* x .+ y \f$, under + * this semiring. + * + * Any combination of \a a, \a x, and \a y may be a scalar. Any scalars equal + * to the given semiring's zero will be detected and automatically be + * transformed into calls to eWiseMul, eWiseAdd, and so on. + * + * @tparam descr The descriptor to be used (descriptors::no_operation + * if left unspecified). + * @tparam Ring The semiring type to perform the element-wise + * multiply-add on. + * @tparam InputType1 The left-hand side input type to the multiplicative + * operator of the \a ring. + * @tparam InputType2 The right-hand side input type to the multiplicative + * operator of the \a ring. + * @tparam InputType3 The output type to the multiplicative operator of the + * \a ring \em and the left-hand side input type to the + * additive operator of the \a ring. + * @tparam OutputType The right-hand side input type to the additive operator + * of the \a ring \em and the result type of the same + * operator. + * + * @param[out] _z The pre-allocated output vector. + * @param[in] _a The elements for left-hand side multiplication. + * @param[in] _x The elements for right-hand side multiplication. + * @param[in] _y The elements for right-hand size addition. + * @param[in] ring The ring to perform the eWiseMulAdd under. + * + * @return grb::MISMATCH Whenever the dimensions of \a _a, \a _x, \a _y, and + * \a z do not match. In this case, all input data + * containers are left untouched and it will simply be + * as though this call was never made. + * @return grb::SUCCESS On successful completion of this call. + * + * \warning An implementation is not obligated to detect overlap whenever + * it occurs. If part of \a z overlaps with \a x, \a y, or \a a, + * undefined behaviour will occur \em unless this function returns + * grb::OVERLAP. In other words: an implementation which returns + * erroneous results when vectors overlap and still returns + * grb::SUCCESS thus is also a valid GraphBLAS implementation! + * + * \parblock + * \par Valid descriptors + * grb::descriptors::no_operation, grb::descriptors::no_casting. + * + * \note Invalid descriptors will be ignored. + * + * If grb::descriptors::no_casting is specified, then 1) the first domain of + * \a ring must match \a InputType1, 2) the second domain of \a ring must match + * \a InputType2, 3) the third domain of \a ring must match \a InputType3, + * 4) the fourth domain of \a ring must match \a OutputType. If one of these is + * not true, the code shall not compile. + * \endparblock + * + * \parblock + * \par Performance semantics + * -# This call takes \f$ \Theta(n) \f$ work, where \f$ n \f$ equals the + * size of the vectors \a _a, \a _x, \a _y, and \a _z. The constant + * factor depends on the cost of evaluating the addition and + * multiplication operators. A good implementation uses vectorised + * instructions whenever the input domains, the output domain, and + * the operators used allow for this. + * + * -# This call takes \f$ \mathcal{O}(1) \f$ memory beyond the memory + * already used by the application when this function is called. + * + * -# This call incurs at most \f$ n( \mathit{sizeof}( + * \mathit{InputType1} + \mathit{bool} + * \mathit{InputType2} + \mathit{bool} + * \mathit{InputType3} + \mathit{bool} + * \mathit{OutputType} + \mathit{bool} + * ) + \mathcal{O}(1) \f$ + * bytes of data movement. A good implementation will stream \a _a, + * \a _x or \a _y into \a _z to apply the additive and multiplicative + * operators in-place, whenever the input domains, the output domain, + * and the operators used allow for this. + * \endparblock + */ + template< Descriptor descr = descriptors::no_operation, class Ring, typename InputType1, typename InputType2, typename InputType3, typename OutputType, typename InputView1, typename InputView2, typename InputView3, typename OutputView, typename Coords > + RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & _z, + const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords > & _a, + const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords > & _x, + const VectorView< InputType3, InputView3, storage::Dense, reference_dense, Coords > & _y, + const Ring & ring = Ring(), + const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && + grb::is_semiring< Ring >::value, + void >::type * const = NULL ) { + (void)ring; + // static sanity checks + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D1, InputType1 >::value ), "grb::eWiseMulAdd", + "called with a left-hand vector _a with an element type that does not " + "match the first domain of the given semiring" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D2, InputType2 >::value ), "grb::eWiseMulAdd", + "called with a right-hand vector _x with an element type that does not " + "match the second domain of the given semiring" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, InputType3 >::value ), "grb::eWiseMulAdd", + "called with an additive vector _y with an element type that does not " + "match the fourth domain of the given semiring" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, OutputType >::value ), "grb::eWiseMulAdd", + "called with a result vector _z with an element type that does not match " + "the fourth domain of the given semiring" ); + throw std::runtime_error( "Needs an implementation." ); + return SUCCESS; + } + + /** + * Calculates the element-wise multiplication of two vectors, + * \f$ z = z + x .* y \f$, + * under a given semiring. + * + * @tparam descr The descriptor to be used (descriptors::no_operation + * if left unspecified). + * @tparam Ring The semiring type to perform the element-wise multiply + * on. + * @tparam InputType1 The left-hand side input type to the multiplicative + * operator of the \a ring. + * @tparam InputType2 The right-hand side input type to the multiplicative + * operator of the \a ring. + * @tparam OutputType The the result type of the multiplicative operator of + * the \a ring. + * + * @param[out] z The output vector of type \a OutputType. + * @param[in] x The left-hand input vector of type \a InputType1. + * @param[in] y The right-hand input vector of type \a InputType2. + * @param[in] ring The generalized semiring under which to perform this + * element-wise multiplication. + * + * @return grb::MISMATCH Whenever the dimensions of \a x, \a y, and \a z do + * not match. All input data containers are left + * untouched if this exit code is returned; it will be + * as though this call was never made. + * @return grb::SUCCESS On successful completion of this call. + * + * \parblock + * \par Valid descriptors + * grb::descriptors::no_operation, grb::descriptors::no_casting. + * + * \note Invalid descriptors will be ignored. + * + * If grb::descriptors::no_casting is specified, then 1) the first domain of + * \a ring must match \a InputType1, 2) the second domain of \a ring must match + * \a InputType2, 3) the third domain of \a ring must match \a OutputType. If + * one of these is not true, the code shall not compile. + * + * \endparblock + * + * \parblock + * \par Performance semantics + * -# This call takes \f$ \Theta(n) \f$ work, where \f$ n \f$ equals the + * size of the vectors \a x, \a y, and \a z. The constant factor + * depends on the cost of evaluating the multiplication operator. A + * good implementation uses vectorised instructions whenever the input + * domains, the output domain, and the multiplicative operator used + * allow for this. + * + * -# This call will not result in additional dynamic memory allocations. + * + * -# This call takes \f$ \mathcal{O}(1) \f$ memory beyond the memory + * used by the application at the point of a call to this function. + * + * -# This call incurs at most \f$ n( \mathit{sizeof}(\mathit{D1}) + + * \mathit{sizeof}(\mathit{D2}) + \mathit{sizeof}(\mathit{D3})) + + * \mathcal{O}(1) \f$ bytes of data movement. A good implementation + * will stream \a x or \a y into \a z to apply the multiplication + * operator in-place, whenever the input domains, the output domain, + * and the operator used allow for this. + * \endparblock + * + * \warning When given sparse vectors, the zero now annihilates instead of + * acting as an identity. Thus the eWiseMul cannot simply map to an + * eWiseApply of the multiplicative operator. + * + * @see This is a specialised form of eWiseMulAdd. + */ + template< Descriptor descr = descriptors::no_operation, class Ring, typename InputType1, typename InputType2, typename OutputType, typename InputView1, typename InputView2, typename OutputView, typename Coords > + RC eWiseMul( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, + const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords > & x, + const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords > & y, + const Ring & ring = Ring(), + const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_semiring< Ring >::value, + void >::type * const = NULL ) { + // static sanity checks + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D1, InputType1 >::value ), "grb::eWiseMul", + "called with a left-hand side input vector with element type that does not " + "match the first domain of the given semiring" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D2, InputType2 >::value ), "grb::eWiseMul", + "called with a right-hand side input vector with element type that does " + "not match the second domain of the given semiring" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D3, OutputType >::value ), "grb::eWiseMul", + "called with an output vector with element type that does not match the " + "third domain of the given semiring" ); + #ifdef _DEBUG + std::cout << "eWiseMul (reference_dense, vector <- vector x vector) dispatches to eWiseMulAdd (vector <- vector x vector + 0)\n"; + #endif + return eWiseMulAdd< descr >( z, x, y, ring.template getZero< Ring::D4 >(), ring ); + } + + /** + * Computes \f$ z = z + x * y \f$. + * + * Specialisation for scalar \a x. + */ + template< Descriptor descr = descriptors::no_operation, class Ring, typename InputType1, typename InputType2, typename OutputType, typename InputView2, typename OutputView, typename Coords > + RC eWiseMul( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, + const InputType1 alpha, + const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords > & y, + const Ring & ring = Ring(), + const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_semiring< Ring >::value, + void >::type * const = NULL ) { + // static sanity checks + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D1, InputType1 >::value ), "grb::eWiseMul", + "called with a left-hand side input vector with element type that does not " + "match the first domain of the given semiring" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D2, InputType2 >::value ), "grb::eWiseMul", + "called with a right-hand side input vector with element type that does " + "not match the second domain of the given semiring" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D3, OutputType >::value ), "grb::eWiseMul", + "called with an output vector with element type that does not match the " + "third domain of the given semiring" ); + #ifdef _DEBUG + std::cout << "eWiseMul (reference_dense, vector <- scalar x vector) dispatches to eWiseMulAdd (vector <- scalar x vector + 0)\n"; + #endif + return eWiseMulAdd< descr >( z, alpha, y, ring.template getZero< typename Ring::D4 >(), ring ); + } + + /** + * Computes \f$ z = z + x * y \f$. + * + * Specialisation for scalar \a y. + */ + template< Descriptor descr = descriptors::no_operation, class Ring, typename InputType1, typename InputType2, typename OutputType, typename InputView1, typename OutputView, typename Coords > + RC eWiseMul( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, + const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords > & x, + const InputType2 beta, + const Ring & ring = Ring(), + const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_semiring< Ring >::value, + void >::type * const = NULL ) { + // static sanity checks + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D1, InputType1 >::value ), "grb::eWiseMul", + "called with a left-hand side input vector with element type that does not " + "match the first domain of the given semiring" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D2, InputType2 >::value ), "grb::eWiseMul", + "called with a right-hand side input vector with element type that does " + "not match the second domain of the given semiring" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D3, OutputType >::value ), "grb::eWiseMul", + "called with an output vector with element type that does not match the " + "third domain of the given semiring" ); + #ifdef _DEBUG + std::cout << "eWiseMul (reference_dense) dispatches to eWiseMulAdd with 0.0 as additive scalar\n"; + #endif + return eWiseMulAdd< descr >( z, x, beta, ring.template getZero< typename Ring::D4 >(), ring.getMultiplicativeOperator() ); + } + + /** + * Calculates the axpy, \f$ z = a * x .+ y \f$, under this semiring. + * + * Specialisation for when \a a is a scalar, masked version. + */ + template< Descriptor descr = descriptors::no_operation, class Ring, typename InputType1, typename InputType2, typename InputType3, typename OutputType, typename MaskType, typename InputView2, typename InputView3, typename OutputView, typename MaskView, typename Coords > + RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & _z, + const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & _m, + const InputType1 alpha, + const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords > & _x, + const VectorView< InputType3, InputView3, storage::Dense, reference_dense, Coords > & _y, + const Ring & ring = Ring(), + const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && + grb::is_semiring< Ring >::value && ! grb::is_object< MaskType >::value, + void >::type * const = NULL ) { + // static sanity checks + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D1, InputType1 >::value ), "grb::eWiseMulAdd", + "called with a left-hand scalar alpha of an element type that does not " + "match the first domain of the given semiring" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D2, InputType2 >::value ), "grb::eWiseMulAdd", + "called with a right-hand vector _x with an element type that does not " + "match the second domain of the given semiring" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, InputType3 >::value ), "grb::eWiseMulAdd", + "called with an additive vector _y with an element type that does not " + "match the fourth domain of the given semiring" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, OutputType >::value ), "grb::eWiseMulAdd", + "called with a result vector _z with an element type that does not match " + "the fourth domain of the given semiring" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< bool, MaskType >::value ), "grb::eWiseMulAdd", "called with a mask vector _m with a non-bool element type" ); + throw std::runtime_error( "Needs an implementation." ); + return SUCCESS; + } + + /** + * Calculates the elementwise multiply-add, \f$ z = a .* x .+ y \f$, under + * this semiring. + * + * Specialisation for when \a x is a scalar, masked version. + */ + template< Descriptor descr = descriptors::no_operation, class Ring, typename InputType1, typename InputType2, typename InputType3, typename OutputType, typename MaskType, typename InputView1, typename InputView3, typename OutputView, typename MaskView, typename Coords > + RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & _z, + const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & _m, + const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords > & _a, + const InputType2 chi, + const VectorView< InputType3, InputView3, storage::Dense, reference_dense, Coords > & _y, + const Ring & ring = Ring(), + const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && + grb::is_semiring< Ring >::value && ! grb::is_object< MaskType >::value, + void >::type * const = NULL ) { + // static sanity checks + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D1, InputType1 >::value ), "grb::eWiseMulAdd", + "called with a left-hand scalar alpha of an element type that does not " + "match the first domain of the given semiring" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D2, InputType2 >::value ), "grb::eWiseMulAdd", + "called with a right-hand vector _x with an element type that does not " + "match the second domain of the given semiring" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, InputType3 >::value ), "grb::eWiseMulAdd", + "called with an additive vector _y with an element type that does not " + "match the fourth domain of the given semiring" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, OutputType >::value ), "grb::eWiseMulAdd", + "called with a result vector _z with an element type that does not match " + "the fourth domain of the given semiring" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< bool, MaskType >::value ), "grb::eWiseMulAdd", "called with a mask vector _m with a non-bool element type" ); + throw std::runtime_error( "Needs an implementation." ); + return SUCCESS; + } + + /** + * Calculates the axpy, \f$ z = a * x .+ y \f$, under this semiring. + * + * Specialisation for when \a y is a scalar, masked version. + */ + template< Descriptor descr = descriptors::no_operation, class Ring, typename InputType1, typename InputType2, typename InputType3, typename OutputType, typename MaskType, typename InputView1, typename InputView2, typename OutputView, typename MaskView, typename Coords > + RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & _z, + const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & _m, + const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords > & _a, + const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords > & _x, + const InputType3 gamma, + const Ring & ring = Ring(), + const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && + grb::is_semiring< Ring >::value && ! grb::is_object< MaskType >::value, + void >::type * const = NULL ) { + // static sanity checks + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D1, InputType1 >::value ), "grb::eWiseMulAdd", + "called with a left-hand scalar alpha of an element type that does not " + "match the first domain of the given semiring" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D2, InputType2 >::value ), "grb::eWiseMulAdd", + "called with a right-hand vector _x with an element type that does not " + "match the second domain of the given semiring" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, InputType3 >::value ), "grb::eWiseMulAdd", + "called with an additive vector _y with an element type that does not " + "match the fourth domain of the given semiring" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, OutputType >::value ), "grb::eWiseMulAdd", + "called with a result vector _z with an element type that does not match " + "the fourth domain of the given semiring" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< bool, MaskType >::value ), "grb::eWiseMulAdd", "called with a mask vector _m with a non-bool element type" ); + throw std::runtime_error( "Needs an implementation." ); + return SUCCESS; + } + + /** + * Calculates the axpy, \f$ z = a * x .+ y \f$, under this semiring. + * + * Specialisation for when \a x and \a y are scalar, masked version. + */ + template< Descriptor descr = descriptors::no_operation, class Ring, typename InputType1, typename InputType2, typename InputType3, typename OutputType, typename MaskType, + typename InputView1, typename OutputView, typename MaskView, typename Coords > + RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & _z, + const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & _m, + const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords > & _a, + const InputType2 beta, + const InputType3 gamma, + const Ring & ring = Ring(), + const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && + grb::is_semiring< Ring >::value && ! grb::is_object< MaskType >::value, + void >::type * const = NULL ) { + // static sanity checks + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D1, InputType1 >::value ), "grb::eWiseMulAdd", + "called with a left-hand scalar alpha of an element type that does not " + "match the first domain of the given semiring" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D2, InputType2 >::value ), "grb::eWiseMulAdd", + "called with a right-hand vector _x with an element type that does not " + "match the second domain of the given semiring" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, InputType3 >::value ), "grb::eWiseMulAdd", + "called with an additive vector _y with an element type that does not " + "match the fourth domain of the given semiring" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, OutputType >::value ), "grb::eWiseMulAdd", + "called with a result vector _z with an element type that does not match " + "the fourth domain of the given semiring" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< bool, MaskType >::value ), "grb::eWiseMulAdd", "called with a mask vector _m with a non-bool element type" ); + throw std::runtime_error( "Needs an implementation." ); + return SUCCESS; + } + + /** + * Calculates the axpy, \f$ z = a * x .+ y \f$, under this semiring. + * + * Specialisation for when \a a and \a y are scalar, masked version. + */ + template< Descriptor descr = descriptors::no_operation, class Ring, typename InputType1, typename InputType2, typename InputType3, typename OutputType, typename MaskType, + typename InputView2, typename OutputView, typename MaskView, typename Coords > + RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & _z, + const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & _m, + const InputType1 alpha, + const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords > & _x, + const InputType3 gamma, + const Ring & ring = Ring(), + const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && + grb::is_semiring< Ring >::value && ! grb::is_object< MaskType >::value, + void >::type * const = NULL ) { + // static sanity checks + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D1, InputType1 >::value ), "grb::eWiseMulAdd", + "called with a left-hand scalar alpha of an element type that does not " + "match the first domain of the given semiring" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D2, InputType2 >::value ), "grb::eWiseMulAdd", + "called with a right-hand vector _x with an element type that does not " + "match the second domain of the given semiring" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, InputType3 >::value ), "grb::eWiseMulAdd", + "called with an additive vector _y with an element type that does not " + "match the fourth domain of the given semiring" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, OutputType >::value ), "grb::eWiseMulAdd", + "called with a result vector _z with an element type that does not match " + "the fourth domain of the given semiring" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< bool, MaskType >::value ), "grb::eWiseMulAdd", "called with a mask vector _m with a non-bool element type" ); + throw std::runtime_error( "Needs an implementation." ); + return SUCCESS; + } + + /** + * Calculates the axpy, \f$ z = a * x .+ y \f$, under this semiring. + * + * Masked version. + */ + template< Descriptor descr = descriptors::no_operation, class Ring, typename InputType1, typename InputType2, typename InputType3, typename OutputType, typename MaskType, + typename InputView1, typename InputView2, typename InputView3, typename OutputView, typename MaskView, typename Coords > + RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & _z, + const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & _m, + const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords > & _a, + const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords > & _x, + const VectorView< InputType3, InputView3, storage::Dense, reference_dense, Coords > & _y, + const Ring & ring = Ring(), + const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && + grb::is_semiring< Ring >::value && ! grb::is_object< MaskType >::value, + void >::type * const = NULL ) { + (void)ring; + // static sanity checks + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D1, InputType1 >::value ), "grb::eWiseMulAdd", + "called with a left-hand vector _a with an element type that does not " + "match the first domain of the given semiring" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D2, InputType2 >::value ), "grb::eWiseMulAdd", + "called with a right-hand vector _x with an element type that does not " + "match the second domain of the given semiring" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, InputType3 >::value ), "grb::eWiseMulAdd", + "called with an additive vector _y with an element type that does not " + "match the fourth domain of the given semiring" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, OutputType >::value ), "grb::eWiseMulAdd", + "called with a result vector _z with an element type that does not match " + "the fourth domain of the given semiring" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< bool, MaskType >::value ), "grb::eWiseMulAdd", "called with a mask vector _m with a non-bool element type" ); + throw std::runtime_error( "Needs an implementation." ); + return SUCCESS; + } + + /** + * Calculates the element-wise multiplication of two vectors, + * \f$ z = z + x .* y \f$, + * under a given semiring. + * + * Masked verison. + * + * \internal Dispatches to eWiseMulAdd with zero additive scalar. + */ + template< Descriptor descr = descriptors::no_operation, class Ring, typename InputType1, typename InputType2, typename OutputType, typename MaskType, + typename InputView1, typename InputView2, typename InputView3, typename OutputView, typename MaskView, typename Coords > + RC eWiseMul( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, + const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & m, + const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords > & x, + const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords > & y, + const Ring & ring = Ring(), + const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< MaskType >::value && + grb::is_semiring< Ring >::value, + void >::type * const = NULL ) { + // static sanity checks + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D1, InputType1 >::value ), "grb::eWiseMul", + "called with a left-hand side input vector with element type that does not " + "match the first domain of the given semiring" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D2, InputType2 >::value ), "grb::eWiseMul", + "called with a right-hand side input vector with element type that does " + "not match the second domain of the given semiring" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D3, OutputType >::value ), "grb::eWiseMul", + "called with an output vector with element type that does not match the " + "third domain of the given semiring" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< bool, MaskType >::value ), "grb::eWiseMulAdd", "called with a mask vector with a non-bool element type" ); + #ifdef _DEBUG + std::cout << "eWiseMul (reference_dense, vector <- vector x vector, masked) dispatches to eWiseMulAdd (vector <- vector x vector + 0, masked)\n"; + #endif + return eWiseMulAdd< descr >( z, m, x, y, ring.template getZero< Ring::D4 >(), ring ); + } + + /** + * Computes \f$ z = z + x * y \f$. + * + * Specialisation for scalar \a x, masked version. + * + * \internal Dispatches to eWiseMulAdd with zero additive scalar. + */ + template< Descriptor descr = descriptors::no_operation, class Ring, typename InputType1, typename InputType2, typename OutputType, typename MaskType, + typename InputView2, typename InputView3, typename OutputView, typename MaskView, typename Coords > + RC eWiseMul( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, + const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & m, + const InputType1 alpha, + const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords > & y, + const Ring & ring = Ring(), + const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< MaskType >::value && + grb::is_semiring< Ring >::value, + void >::type * const = NULL ) { + // static sanity checks + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D1, InputType1 >::value ), "grb::eWiseMul", + "called with a left-hand side input vector with element type that does not " + "match the first domain of the given semiring" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D2, InputType2 >::value ), "grb::eWiseMul", + "called with a right-hand side input vector with element type that does " + "not match the second domain of the given semiring" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D3, OutputType >::value ), "grb::eWiseMul", + "called with an output vector with element type that does not match the " + "third domain of the given semiring" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< bool, MaskType >::value ), "grb::eWiseMulAdd", "called with a mask vector _m with a non-bool element type" ); + #ifdef _DEBUG + std::cout << "eWiseMul (reference_dense, vector <- scalar x vector, masked) dispatches to eWiseMulAdd (vector <- scalar x vector + 0, masked)\n"; + #endif + return eWiseMulAdd< descr >( z, m, alpha, y, ring.template getZero< typename Ring::D4 >(), ring ); + } + + /** + * Computes \f$ z = z + x * y \f$. + * + * Specialisation for scalar \a y, masked version. + * + * \internal Dispatches to eWiseMulAdd with zero additive scalar. + */ + template< Descriptor descr = descriptors::no_operation, class Ring, typename InputType1, typename InputType2, typename OutputType, typename MaskType, + typename InputView1, typename InputView3, typename OutputView, typename MaskView, typename Coords > + RC eWiseMul( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, + const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & m, + const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords > & x, + const InputType2 beta, + const Ring & ring = Ring(), + const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< MaskType >::value && + grb::is_semiring< Ring >::value, + void >::type * const = NULL ) { + // static sanity checks + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D1, InputType1 >::value ), "grb::eWiseMul", + "called with a left-hand side input vector with element type that does not " + "match the first domain of the given semiring" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D2, InputType2 >::value ), "grb::eWiseMul", + "called with a right-hand side input vector with element type that does " + "not match the second domain of the given semiring" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D3, OutputType >::value ), "grb::eWiseMul", + "called with an output vector with element type that does not match the " + "third domain of the given semiring" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< bool, MaskType >::value ), "grb::eWiseMulAdd", "called with a mask vector _m with a non-bool element type" ); + #ifdef _DEBUG + std::cout << "eWiseMul (reference_dense, masked) dispatches to masked eWiseMulAdd with 0.0 as additive scalar\n"; + #endif + return eWiseMulAdd< descr >( z, m, x, beta, ring.template getZero< typename Ring::D4 >(), ring.getMultiplicativeOperator() ); + } + + /** + * Computes \f$ z = z + a * x + y \f$. + * + * Specialisation for scalar \a a and \a x, masked version. + * + * \internal Dispatches to masked eWiseAdd. + */ + template< Descriptor descr = descriptors::no_operation, class Ring, typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename InputType3, + typename OutputView, typename MaskView, typename InputView3, typename Coords > + RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, + const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & m, + const InputType1 alpha, + const InputType2 beta, + const VectorView< InputType3, InputView3, storage::Dense, reference_dense, Coords > & y, + const Ring & ring = Ring(), + const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && + grb::is_semiring< Ring >::value && ! grb::is_object< MaskType >::value, + void >::type * const = NULL ) { + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D1, InputType1 >::value ), "grb::eWiseMulAdd(vector,scalar,scalar,scalar)", + "First domain of semiring does not match first input type" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D2, InputType2 >::value ), "grb::eWiseMulAdd(vector,scalar,scalar,scalar)", + "Second domain of semiring does not match second input type" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, InputType3 >::value ), "grb::eWiseMulAdd(vector,scalar,scalar,scalar)", + "Fourth domain of semiring does not match third input type" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, OutputType >::value ), "grb::eWiseMulAdd(vector,scalar,scalar,scalar)", + "Fourth domain of semiring does not match output type" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< bool, MaskType >::value ), "grb::eWiseMulAdd", "called with a mask vector with a non-bool element type" ); + #ifdef _DEBUG + std::cout << "eWiseMulAdd (reference_dense, vector <- scalar x scalar + vector, masked) precomputes scalar multiply and dispatches to eWiseAdd (reference_dense, vector <- scalar + vector, masked)\n"; + #endif + typename Ring::D3 mul_result; + RC rc = grb::apply( mul_result, alpha, beta, ring.getMultiplicativeOperator() ); + #ifdef NDEBUG + (void)rc; + #else + assert( rc == SUCCESS ); + #endif + return grb::eWiseAdd( z, m, mul_result, y, ring ); + } + + /** + * Computes \f$ z = z + a * x + y \f$. + * + * Specialisation for scalar \a a, \a x, and \a y, masked version. + * + * \internal Dispatches to masked set. + */ + template< Descriptor descr = descriptors::no_operation, class Ring, typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename InputType3, + typename OutputView, typename MaskView, typename Coords > + RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, + const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & m, + const InputType1 alpha, + const InputType2 beta, + const InputType3 gamma, + const Ring & ring = Ring(), + const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && + grb::is_semiring< Ring >::value, + void >::type * const = NULL ) { + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D1, InputType1 >::value ), "grb::eWiseMulAdd(vector,scalar,scalar,scalar)", + "First domain of semiring does not match first input type" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D2, InputType2 >::value ), "grb::eWiseMulAdd(vector,scalar,scalar,scalar)", + "Second domain of semiring does not match second input type" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, InputType3 >::value ), "grb::eWiseMulAdd(vector,scalar,scalar,scalar)", + "Fourth domain of semiring does not match third input type" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, OutputType >::value ), "grb::eWiseMulAdd(vector,scalar,scalar,scalar)", + "Fourth domain of semiring does not match output type" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< bool, MaskType >::value ), "grb::eWiseMulAdd", "called with a mask vector with a non-bool element type" ); + #ifdef _DEBUG + std::cout << "eWiseMulAdd (reference_dense, vector <- scalar x scalar + scalar, masked) precomputes scalar operations and dispatches to set (reference_dense, masked)\n"; + #endif + typename Ring::D3 mul_result; + RC rc = grb::apply( mul_result, alpha, beta, ring.getMultiplicativeOperator() ); + #ifdef NDEBUG + (void)rc; + #endif + assert( rc == SUCCESS ); + typename Ring::D4 add_result; + rc = grb::apply( add_result, mul_result, gamma, ring.getAdditiveOperator() ); + #ifdef NDEBUG + (void)rc; + #endif + assert( rc == SUCCESS ); + return grb::set( z, m, add_result ); + } + + // internal namespace for implementation of grb::dot + namespace internal { + + /** @see grb::dot */ + template< + Descriptor descr = descriptors::no_operation, + class AddMonoid, class AnyOp, + typename OutputType, typename InputType1, typename InputType2, typename OutputView, typename InputView1, typename InputView2, + typename Coords + > + RC dot_generic( OutputType &z, + const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords > &x, + const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords > &y, + const AddMonoid &addMonoid = AddMonoid(), + const AnyOp &anyOp = AnyOp() + ) { + throw std::runtime_error( "Needs an implementation." ); + return SUCCESS; + } + + } // namespace internal + + /** + * Calculates the dot product, \f$ \alpha = (x,y) \f$, under a given additive + * monoid and multiplicative operator. + * + * @tparam descr The descriptor to be used (descriptors::no_operation + * if left unspecified). + * @tparam Ring The semiring type to use. + * @tparam OutputType The output type. + * @tparam InputType1 The input element type of the left-hand input vector. + * @tparam InputType2 The input element type of the right-hand input vector. + * + * @param[in,out] z The output element \f$ z + \alpha \f$. + * @param[in] x The left-hand input vector. + * @param[in] y The right-hand input vector. + * @param[in] addMonoid The additive monoid under which the reduction of the + * results of element-wise multiplications of \a x and + * \a y are performed. + * @param[in] anyop The multiplicative operator under which element-wise + * multiplications of \a x and \a y are performed. This can + * be any binary operator. + * + * By the definition that a dot-product operates under any additive monoid and + * any binary operator, it follows that a dot-product under any semiring can be + * trivially reduced to a call to this version instead. + * + * @return grb::MISMATCH When the dimensions of \a x and \a y do not match. All + * input data containers are left untouched if this exit + * code is returned; it will be as though this call was + * never made. + * @return grb::SUCCESS On successful completion of this call. + * + * \parblock + * \par Performance semantics + * -# This call takes \f$ \Theta(n/p) \f$ work at each user process, where + * \f$ n \f$ equals the size of the vectors \a x and \a y, and + * \f$ p \f$ is the number of user processes. The constant factor + * depends on the cost of evaluating the addition and multiplication + * operators. A good implementation uses vectorised instructions + * whenever the input domains, output domain, and the operators used + * allow for this. + * + * -# This call takes \f$ \mathcal{O}(1) \f$ memory beyond the memory used + * by the application at the point of a call to this function. + * + * -# This call incurs at most + * \f$ n( \mathit{sizeof}(\mathit{D1}) + \mathit{sizeof}(\mathit{D2}) ) + \mathcal{O}(p) \f$ + * bytes of data movement. + * + * -# This call incurs at most \f$ \Theta(\log p) \f$ synchronisations + * between two or more user processes. + * + * -# A call to this function does result in any system calls. + * \endparblock + * + * \note This requires an implementation to pre-allocate \f$ \Theta(p) \f$ + * memory for inter-process reduction, if the underlying communication + * layer indeed requires such a buffer. This buffer may not be allocated + * (nor freed) during a call to this function. + * + * \parblock + * \par Valid descriptors + * -# grb::descriptors::no_operation + * -# grb::descriptors::no_casting + * -# grb::descriptors::dense + * \endparblock + * + * If the dense descriptor is set, this implementation returns grb::ILLEGAL if + * it was detected that either \a x or \a y was sparse. In this case, it shall + * otherwise be as though the call to this function had not occurred (no side + * effects). + * + * \note The standard, in contrast, only specifies undefined behaviour would + * occur. This implementation goes beyond the standard by actually + * specifying what will happen. + */ + template< + Descriptor descr = descriptors::no_operation, + class AddMonoid, class AnyOp, + typename OutputType, typename InputType1, typename InputType2, typename OutputView, typename InputView1, typename InputView2, + typename Coords + > + RC dot( OutputType &z, + const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords > &x, + const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords > &y, + const AddMonoid &addMonoid = AddMonoid(), + const AnyOp &anyOp = AnyOp(), + const typename std::enable_if< !grb::is_object< OutputType >::value && + !grb::is_object< InputType1 >::value && + !grb::is_object< InputType2 >::value && + grb::is_monoid< AddMonoid >::value && + grb::is_operator< AnyOp >::value, + void >::type * const = NULL + ) { + // static sanity checks + NO_CAST_ASSERT( ( !( descr & descriptors::no_casting ) || std::is_same< InputType1, typename AnyOp::D1 >::value ), "grb::dot", + "called with a left-hand vector value type that does not match the first " + "domain of the given multiplicative operator" ); + NO_CAST_ASSERT( ( !( descr & descriptors::no_casting ) || std::is_same< InputType2, typename AnyOp::D2 >::value ), "grb::dot", + "called with a right-hand vector value type that does not match the second " + "domain of the given multiplicative operator" ); + NO_CAST_ASSERT( ( !( descr & descriptors::no_casting ) || std::is_same< typename AddMonoid::D3, typename AnyOp::D1 >::value ), "grb::dot", + "called with a multiplicative operator output domain that does not match " + "the first domain of the given additive operator" ); + NO_CAST_ASSERT( ( !( descr & descriptors::no_casting ) || std::is_same< OutputType, typename AddMonoid::D2 >::value ), "grb::dot", + "called with an output vector value type that does not match the second " + "domain of the given additive operator" ); + NO_CAST_ASSERT( ( !( descr & descriptors::no_casting ) || std::is_same< typename AddMonoid::D3, typename AddMonoid::D2 >::value ), "grb::dot", + "called with an additive operator whose output domain does not match its " + "second input domain" ); + NO_CAST_ASSERT( ( !( descr & descriptors::no_casting ) || std::is_same< OutputType, typename AddMonoid::D3 >::value ), "grb::dot", + "called with an output vector value type that does not match the third " + "domain of the given additive operator" ); + + throw std::runtime_error( "Needs an implementation." ); + return SUCCESS; + } + + /** No implementation notes. */ + template< typename Func, typename DataType, typename DataView, typename Coords > + RC eWiseMap( const Func f, VectorView< DataType, DataView, storage::Dense, reference_dense, Coords > & x ) { + throw std::runtime_error( "Needs an implementation." ); + return SUCCESS; + } + + /** + * This is the eWiseLambda that performs length checking by recursion. + * + * in the reference_dense implementation all vectors are distributed equally, so no + * need to synchronise any data structures. We do need to do error checking + * though, to see when to return grb::MISMATCH. That's this function. + * + * @see VectorView::operator[]() + * @see VectorView::lambda_reference + */ + template< typename Func, typename DataType1, typename DataType2, typename DataView1, typename DataView2, typename Coords, typename... Args > + RC eWiseLambda( const Func f, const VectorView< DataType1, DataView1, storage::Dense, reference_dense, Coords > & x, const VectorView< DataType2, DataView2, storage::Dense, reference_dense, Coords > & y, Args const &... args ) { + // catch mismatch + if( size( x ) != size( y ) ) { + return MISMATCH; + } + // continue + return eWiseLambda( f, x, args... ); + } + + /** + * No implementation notes. This is the `real' implementation on reference_dense + * vectors. + * + * @see VectorView::operator[]() + * @see VectorView::lambda_reference + */ + template< typename Func, typename DataType, typename DataView, typename Coords > + RC eWiseLambda( const Func f, const VectorView< DataType, DataView, storage::Dense, reference_dense, Coords > & x ) { + #ifdef _DEBUG + std::cout << "Info: entering eWiseLambda function on vectors.\n"; + #endif + throw std::runtime_error( "Needs an implementation." ); + return SUCCESS; + } + + /** + * Reduces a vector into a scalar. Reduction takes place according a monoid + * \f$ (\oplus,1) \f$, where \f$ \oplus:\ D_1 \times D_2 \to D_3 \f$ with an + * associated identity \f$ 1 \in \{D_1,D_2,D_3\} \f$. Elements from the given + * vector \f$ y \in \{D_1,D_2\} \f$ will be applied at the left-hand or right- + * hand side of \f$ \oplus \f$; which, exactly, is implementation-dependent + * but should not matter since \f$ \oplus \f$ should be associative. + * + * Let \f$ x_0 = 1 \f$ and let + * \f$ x_{i+1} = \begin{cases} + * x_i \oplus y_i\text{ if }y_i\text{ is nonzero} + * x_i\text{ otherwise} + * \end{cases},\f$ + * for all \f$ i \in \{ 0, 1, \ldots, n-1 \} \f$. On function exit \a x will be + * set to \f$ x_n \f$. + * + * This function assumes that \f$ \odot \f$ under the given domains consitutes + * a valid monoid, which for standard associative operators it usually means + * that \f$ D_3 \subseteq D_2 \subseteq D_1 \f$. If not, or if the operator is + * non-standard, the monoid axioms are to be enforced in some other way-- the + * user is responsible for checking this is indeed the case or undefined + * behaviour will occur. + * + * \note While the monoid identity may be used to easily provide parallel + * implementations of this function, having a notion of an identity is + * mandatory to be able to interpret sparse vectors; this is why we do + * not allow a plain operator to be passed to this function. + * + * @tparam descr The descriptor to be used (descriptors::no_operation if + * left unspecified). + * @tparam Monoid The monoid to use for reduction. A monoid is required + * because the output value \a y needs to be initialised + * with an identity first. + * @tparam InputType The type of the elements in the supplied GraphBLAS + * vector \a y. + * @tparam IOType The type of the output value \a x. + * + * @param[out] x The result of reduction. + * @param[in] y A valid GraphBLAS vector. This vector may be sparse. + * @param[in] monoid The monoid under which to perform this reduction. + * + * @return grb::SUCCESS When the call completed successfully. + * @return grb::ILLEGAL If the provided input vector \a y was not dense. + * @return grb::ILLEGAL If the provided input vector \a y was empty. + * + * \parblock + * \par Valid descriptors + * grb::descriptors::no_operation, grb::descriptors::no_casting, + * grb::descriptors::dense + * + * \note Invalid descriptors will be ignored. + * + * If grb::descriptors::no_casting is specified, then 1) the first domain of + * \a monoid must match \a InputType, 2) the second domain of \a op must match + * \a IOType, and 3) the third domain must match \a IOType. If one of + * these is not true, the code shall not compile. + * \endparblock + * + * \parblock + * \par Performance semantics + * -# This call comprises \f$ \Theta(n) \f$ work, where \f$ n \f$ equals + * the size of the vector \a x. The constant factor depends on the + * cost of evaluating the underlying binary operator. A good + * implementation uses vectorised instructions whenever the input + * domains, the output domain, and the operator used allow for this. + * + * -# This call will not result in additional dynamic memory allocations. + * No system calls will be made. + * + * -# This call takes \f$ \mathcal{O}(1) \f$ memory beyond the memory + * used by the application at the point of a call to this function. + * + * -# This call incurs at most + * \f$ n \mathit{sizeof}(\mathit{InputType}) + \mathcal{O}(1) \f$ + * bytes of data movement. If \a y is sparse, a call to this function + * incurs at most \f$ n \mathit{sizeof}( \mathit{bool} ) \f$ extra + * bytes of data movement. + * \endparblock + * + * @see grb::foldl provides similar functionality. + */ + template< Descriptor descr = descriptors::no_operation, class Monoid, typename InputType, typename IOType, typename MaskType, typename InputView, typename MaskView, typename Coords > + RC foldl( IOType & x, + const VectorView< InputType, InputView, storage::Dense, reference_dense, Coords > & y, + const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & mask, + const Monoid & monoid = Monoid(), + const typename std::enable_if< ! grb::is_object< IOType >::value && ! grb::is_object< InputType >::value && ! grb::is_object< MaskType >::value && grb::is_monoid< Monoid >::value, + void >::type * const = NULL ) { + #ifdef _DEBUG + std::cout << "foldl: IOType <- [InputType] with a monoid called. Array has size " << size( y ) << " with " << nnz( y ) << " nonzeroes. It has a mask of size " << size( mask ) << " with " + << nnz( mask ) << " nonzeroes.\n"; + #endif + + // static sanity checks + NO_CAST_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< IOType, InputType >::value ), "grb::reduce", "called with a scalar IO type that does not match the input vector type" ); + NO_CAST_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< InputType, typename Monoid::D1 >::value ), "grb::reduce", + "called with an input vector value type that does not match the first " + "domain of the given monoid" ); + NO_CAST_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< InputType, typename Monoid::D2 >::value ), "grb::reduce", + "called with an input vector type that does not match the second domain of " + "the given monoid" ); + NO_CAST_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< InputType, typename Monoid::D3 >::value ), "grb::reduce", + "called with an input vector type that does not match the third domain of " + "the given monoid" ); + NO_CAST_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< bool, MaskType >::value ), "grb::reduce", "called with a vector mask type that is not boolean" ); + + throw std::runtime_error( "Needs an implementation." ); + return SUCCESS; + } + + /** * Calculates the dot product, \f$ \alpha = (x,y) \f$, under a given additive * monoid and multiplicative operator. @@ -109,12 +3620,11 @@ namespace grb { class AddMonoid, class AnyOp, typename OutputType, typename InputType1, typename InputType2, typename InputView1, typename InputView2, - typename InputStorage1, typename InputStorage2, typename InputCoords1, typename InputCoords2 > RC dot( OutputType &z, - const VectorView< InputType1, InputView1, InputStorage1, reference_dense, InputCoords1 > &x, - const VectorView< InputType2, InputView2, InputStorage2, reference_dense, InputCoords2 > &y, + const VectorView< InputType1, InputView1, storage::Dense, reference_dense, InputCoords1 > &x, + const VectorView< InputType2, InputView2, storage::Dense, reference_dense, InputCoords2 > &y, const AddMonoid &addMonoid = AddMonoid(), const AnyOp &anyOp = AnyOp(), const typename std::enable_if< !grb::is_object< OutputType >::value && From 7c53acff99192d445fc5d9c49dbbb414aa70b870 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Fri, 25 Feb 2022 21:12:39 +0100 Subject: [PATCH 082/282] WIP: Add blas2 interface for reference_dense backend --- include/graphblas/denseref/blas2.hpp | 355 +++++++++++++++++++++++++++ 1 file changed, 355 insertions(+) diff --git a/include/graphblas/denseref/blas2.hpp b/include/graphblas/denseref/blas2.hpp index d185d74b1..5860cda3a 100644 --- a/include/graphblas/denseref/blas2.hpp +++ b/include/graphblas/denseref/blas2.hpp @@ -23,8 +23,363 @@ #ifndef _H_GRB_DENSEREF_BLAS2 #define _H_GRB_DENSEREF_BLAS2 +#include + namespace grb { + /** + * \addtogroup reference_dense + * @{ + */ + + /** + * Retrieve the row dimension size of this matrix. + * + * @returns The number of rows the current matrix contains. + * + * \parblock + * \par Performance semantics. + * -# This function consitutes \f$ \Theta(1) \f$ work. + * -# This function allocates no additional dynamic memory. + * -# This function uses \f$ \mathcal{O}(1) \f$ memory + * beyond that which was already used at function entry. + * -# This function will move + * \f$ \mathit{sizeof}( size\_t ) \f$ + * bytes of memory. + * \endparblock + */ + template< typename InputType > + size_t nrows( const Matrix< InputType, reference > & A ) noexcept { + return A.m; + } + + /** + * Retrieve the column dimension size of this matrix. + * + * @returns The number of columns the current matrix contains. + * + * \parblock + * \par Performance semantics. + * -# This function consitutes \f$ \Theta(1) \f$ work. + * -# This function allocates no additional dynamic memory. + * -# This function uses \f$ \mathcal{O}(1) \f$ memory + * beyond that which was already used at function entry. + * -# This function will move + * \f$ \mathit{sizeof}( size\_t ) \f$ + * bytes of memory. + * \endparblock + */ + template< typename InputType > + size_t ncols( const Matrix< InputType, reference > & A ) noexcept { + return A.n; + } + + /** + * Retrieve the number of nonzeroes contained in this matrix. + * + * @returns The number of nonzeroes the current matrix contains. + * + * \parblock + * \par Performance semantics. + * -# This function consitutes \f$ \Theta(1) \f$ work. + * -# This function allocates no additional dynamic memory. + * -# This function uses \f$ \mathcal{O}(1) \f$ memory + * beyond that which was already used at function entry. + * -# This function will move + * \f$ \mathit{sizeof}( size\_t ) \f$ + * bytes of memory. + * \endparblock + */ + template< typename InputType > + size_t nnz( const Matrix< InputType, reference > & A ) noexcept { + return A.nz; + } + + /** + * Resizes the nonzero capacity of this matrix. Any current contents of the + * matrix are \em not retained. + * + * The dimension of this matrix is fixed. Only the number of nonzeroes that + * may be stored can change. If the matrix has row or column dimension size + * zero, all calls to this function are ignored. A request for less capacity + * than currently already may be allocated, may be ignored by the + * implementation. + * + * @param[in] nonzeroes The number of nonzeroes this matrix is to contain. + * + * @return OUTOFMEM When no memory could be allocated to store this matrix. + * @return PANIC When allocation fails for any other reason. + * @return SUCCESS When a valid GraphBLAS matrix has been constructed. + * + * \parblock + * \par Performance semantics. + * -$ This function consitutes \f$ \mathcal{O}(\mathit{nz} \f$ work. + * -# This function allocates \f$ \mathcal{O}(\mathit{nz}+m+n+1) \f$ + * bytes of dynamic memory. + * -# This function will likely make system calls. + * \endparblock + * + * \warning This is an expensive function. Use sparingly and only when + * absolutely necessary + */ + template< typename InputType > + RC resize( Matrix< InputType, reference > & A, const size_t new_nz ) noexcept { + // delegate + return A.resize( new_nz ); + } + + /** \internal Delegates to fully masked variant */ + template< Descriptor descr = descriptors::no_operation, class Ring, typename IOType, typename InputType1, typename InputType2, typename InputType3, typename Coords > + RC vxm( Vector< IOType, reference, Coords > & u, + const Vector< InputType3, reference, Coords > & mask, + const Vector< InputType1, reference, Coords > & v, + const Matrix< InputType2, reference > & A, + const Ring & ring = Ring(), + const typename std::enable_if< grb::is_semiring< Ring >::value, void >::type * const = NULL ) { + const Vector< bool, reference, Coords > empty_mask( 0 ); + return vxm< descr, true, false >( u, mask, v, empty_mask, A, ring ); + } + + /** \internal Delegates to fully masked variant */ + template< Descriptor descr = descriptors::no_operation, + class AdditiveMonoid, + class MultiplicativeOperator, + typename IOType, + typename InputType1, + typename InputType2, + typename InputType3, + typename Coords > + RC vxm( Vector< IOType, reference, Coords > & u, + const Vector< InputType3, reference, Coords > & mask, + const Vector< InputType1, reference, Coords > & v, + const Matrix< InputType2, reference > & A, + const AdditiveMonoid & add = AdditiveMonoid(), + const MultiplicativeOperator & mul = MultiplicativeOperator(), + const typename std::enable_if< grb::is_monoid< AdditiveMonoid >::value && grb::is_operator< MultiplicativeOperator >::value && ! grb::is_object< IOType >::value && + ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && ! std::is_same< InputType2, void >::value, + void >::type * const = NULL ) { + const grb::Vector< bool, reference, Coords > empty_mask( 0 ); + return vxm< descr, true, false >( u, mask, v, empty_mask, A, add, mul ); + } + + /** \internal Delegates to vxm_generic. */ + template< Descriptor descr = descriptors::no_operation, + bool output_may_be_masked = true, + bool input_may_be_masked = true, + class Ring, + typename IOType, + typename InputType1, + typename InputType2, + typename InputType3, + typename InputType4, + typename Coords > + RC vxm( Vector< IOType, reference, Coords > & u, + const Vector< InputType3, reference, Coords > & mask, + const Vector< InputType1, reference, Coords > & v, + const Vector< InputType4, reference, Coords > & v_mask, + const Matrix< InputType2, reference > & A, + const Ring & ring = Ring(), + const typename std::enable_if< grb::is_semiring< Ring >::value, void >::type * const = NULL ) { + throw std::runtime_error( "Needs an implementation." ); + return SUCCESS; + } + + /** \internal Delegates to fully masked version */ + template< Descriptor descr = descriptors::no_operation, + class Ring, + typename IOType = typename Ring::D4, + typename InputType1 = typename Ring::D1, + typename InputType2 = typename Ring::D2, + typename Coords > + RC vxm( Vector< IOType, reference, Coords > & u, + const Vector< InputType1, reference, Coords > & v, + const Matrix< InputType2, reference > & A, + const Ring & ring = Ring(), + const typename std::enable_if< grb::is_semiring< Ring >::value, void >::type * const = NULL ) { + const Vector< bool, reference, Coords > empty_mask( 0 ); + return vxm< descr, false, false >( u, empty_mask, v, empty_mask, A, ring ); + } + + /** \internal Delegates to fully masked version */ + template< Descriptor descr = descriptors::no_operation, class AdditiveMonoid, class MultiplicativeOperator, typename IOType, typename InputType1, typename InputType2, typename Coords > + RC vxm( Vector< IOType, reference, Coords > & u, + const Vector< InputType1, reference, Coords > & v, + const Matrix< InputType2, reference > & A, + const AdditiveMonoid & add = AdditiveMonoid(), + const MultiplicativeOperator & mul = MultiplicativeOperator(), + const typename std::enable_if< grb::is_monoid< AdditiveMonoid >::value && grb::is_operator< MultiplicativeOperator >::value && ! grb::is_object< IOType >::value && + ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! std::is_same< InputType2, void >::value, + void >::type * const = NULL ) { + const grb::Vector< bool, reference, Coords > empty_mask( 0 ); + return vxm< descr, false, false >( u, empty_mask, v, empty_mask, A, add, mul ); + } + + /** \internal Delegates to fully masked version */ + template< Descriptor descr = descriptors::no_operation, + class Ring, + typename IOType = typename Ring::D4, + typename InputType1 = typename Ring::D1, + typename InputType2 = typename Ring::D2, + typename InputType3 = bool, + typename Coords > + RC mxv( Vector< IOType, reference, Coords > & u, + const Vector< InputType3, reference, Coords > & mask, + const Matrix< InputType2, reference > & A, + const Vector< InputType1, reference, Coords > & v, + const Ring & ring, + const typename std::enable_if< grb::is_semiring< Ring >::value, void >::type * const = NULL ) { + const Vector< bool, reference, Coords > empty_mask( 0 ); + return mxv< descr, true, false >( u, mask, A, v, empty_mask, ring ); + } + + /** \internal Delegates to vxm_generic */ + template< Descriptor descr = descriptors::no_operation, + bool output_may_be_masked = true, + bool input_may_be_masked = true, + class Ring, + typename IOType, + typename InputType1, + typename InputType2, + typename InputType3, + typename InputType4, + typename Coords > + RC mxv( Vector< IOType, reference, Coords > & u, + const Vector< InputType3, reference, Coords > & mask, + const Matrix< InputType2, reference > & A, + const Vector< InputType1, reference, Coords > & v, + const Vector< InputType4, reference, Coords > & v_mask, + const Ring & ring, + const typename std::enable_if< grb::is_semiring< Ring >::value, void >::type * const = NULL ) { + + throw std::runtime_error( "Needs an implementation." ); + return SUCCESS; + } + + /** + * \internal Delegates to fully masked variant. + */ + template< Descriptor descr = descriptors::no_operation, + class Ring, + typename IOType = typename Ring::D4, + typename InputType1 = typename Ring::D1, + typename InputType2 = typename Ring::D2, + typename Coords > + RC mxv( Vector< IOType, reference, Coords > & u, + const Matrix< InputType2, reference > & A, + const Vector< InputType1, reference, Coords > & v, + const Ring & ring, + const typename std::enable_if< grb::is_semiring< Ring >::value, void >::type * const = NULL ) { + const Vector< bool, reference, Coords > empty_mask( 0 ); + return mxv< descr, false, false >( u, empty_mask, A, v, empty_mask, ring ); + } + + /** \internal Delegates to fully masked version */ + template< Descriptor descr = descriptors::no_operation, class AdditiveMonoid, class MultiplicativeOperator, typename IOType, typename InputType1, typename InputType2, typename Coords > + RC mxv( Vector< IOType, reference, Coords > & u, + const Matrix< InputType2, reference > & A, + const Vector< InputType1, reference, Coords > & v, + const AdditiveMonoid & add = AdditiveMonoid(), + const MultiplicativeOperator & mul = MultiplicativeOperator(), + const typename std::enable_if< grb::is_monoid< AdditiveMonoid >::value && grb::is_operator< MultiplicativeOperator >::value && ! grb::is_object< IOType >::value && + ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! std::is_same< InputType2, void >::value, + void >::type * const = NULL ) { + const grb::Vector< bool, reference, Coords > empty_mask( 0 ); + return mxv< descr, false, false >( u, empty_mask, A, v, empty_mask, add, mul ); + } + + /** + * \internal Delegates to vxm_generic + */ + template< Descriptor descr = descriptors::no_operation, + bool output_may_be_masked = true, + bool input_may_be_masked = true, + class AdditiveMonoid, + class MultiplicativeOperator, + typename IOType, + typename InputType1, + typename InputType2, + typename InputType3, + typename InputType4, + typename Coords > + RC vxm( Vector< IOType, reference, Coords > & u, + const Vector< InputType3, reference, Coords > & mask, + const Vector< InputType1, reference, Coords > & v, + const Vector< InputType4, reference, Coords > & v_mask, + const Matrix< InputType2, reference > & A, + const AdditiveMonoid & add = AdditiveMonoid(), + const MultiplicativeOperator & mul = MultiplicativeOperator(), + const typename std::enable_if< grb::is_monoid< AdditiveMonoid >::value && grb::is_operator< MultiplicativeOperator >::value && ! grb::is_object< IOType >::value && + ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && ! grb::is_object< InputType4 >::value && + ! std::is_same< InputType2, void >::value, + void >::type * const = NULL ) { + + throw std::runtime_error( "Needs an implementation." ); + return SUCCESS; + } + + /** + * \internal Delegates to vxm_generic. + */ + template< Descriptor descr = descriptors::no_operation, + bool output_may_be_masked = true, + bool input_may_be_masked = true, + class AdditiveMonoid, + class MultiplicativeOperator, + typename IOType, + typename InputType1, + typename InputType2, + typename InputType3, + typename InputType4, + typename Coords > + RC mxv( Vector< IOType, reference, Coords > & u, + const Vector< InputType3, reference, Coords > & mask, + const Matrix< InputType2, reference > & A, + const Vector< InputType1, reference, Coords > & v, + const Vector< InputType4, reference, Coords > & v_mask, + const AdditiveMonoid & add = AdditiveMonoid(), + const MultiplicativeOperator & mul = MultiplicativeOperator(), + const typename std::enable_if< grb::is_monoid< AdditiveMonoid >::value && grb::is_operator< MultiplicativeOperator >::value && ! grb::is_object< IOType >::value && + ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && ! grb::is_object< InputType4 >::value && + ! std::is_same< InputType2, void >::value, + void >::type * const = NULL ) { + + throw std::runtime_error( "Needs an implementation." ); + return SUCCESS; + } + + /** + * Straightforward implementation using the column-major layout. + * + * @see grb::eWiseLambda for the user-level specification. + */ + template< class ActiveDistribution, typename Func, typename DataType > + RC eWiseLambda( const Func f, const Matrix< DataType, reference > & A, const size_t s, const size_t P ) { +#ifdef _DEBUG + std::cout << "entering grb::eWiseLambda (matrices, reference ). A is " << grb::nrows( A ) << " by " << grb::ncols( A ) << " and holds " << grb::nnz( A ) << " nonzeroes.\n"; +#endif + throw std::runtime_error( "Needs an implementation." ); + return SUCCESS; + } + + /** + * This function provides dimension checking and will defer to the below + * function for the actual implementation. + * + * @see grb::eWiseLambda for the user-level specification. + */ + template< typename Func, typename DataType1, typename DataType2, typename Coords, typename... Args > + RC eWiseLambda( const Func f, const Matrix< DataType1, reference > & A, const Vector< DataType2, reference, Coords > x, Args... args ) { + // do size checking + if( ! ( size( x ) == nrows( A ) || size( x ) == ncols( A ) ) ) { + std::cerr << "Mismatching dimensions: given vector of size " << size( x ) << " has nothing to do with either matrix dimension (" << nrows( A ) << " nor " << ncols( A ) << ").\n"; + return MISMATCH; + } + // no need for synchronisation, everything is local in reference implementation + return eWiseLambda( f, A, args... ); + } + + /** @} */ + } // end namespace ``grb'' #endif // end ``_H_GRB_DENSEREF_BLAS2'' From 5ce7a7d4a413a1d15dbe30e40f0e38e69d2e65ed Mon Sep 17 00:00:00 2001 From: Anonymous Date: Mon, 28 Feb 2022 14:12:39 +0100 Subject: [PATCH 083/282] Fix compilation errors in denseref blas1 --- include/graphblas/denseref/blas1.hpp | 44 +++++++++++++--------------- 1 file changed, 20 insertions(+), 24 deletions(-) diff --git a/include/graphblas/denseref/blas1.hpp b/include/graphblas/denseref/blas1.hpp index dfa5666d4..940740284 100644 --- a/include/graphblas/denseref/blas1.hpp +++ b/include/graphblas/denseref/blas1.hpp @@ -26,6 +26,7 @@ #include #include #include +#include namespace grb { @@ -140,7 +141,7 @@ namespace grb { * \endparblock */ template< typename DataType, typename View, typename Coords > - RC clear( VectorView< DataType, View, storage::Dense, storage::Dense, reference_dense, Coords > & x ) noexcept { + RC clear( VectorView< DataType, View, storage::Dense, reference_dense, Coords > & x ) noexcept { throw std::runtime_error( "Needs an implementation" ); return SUCCESS; } @@ -167,7 +168,7 @@ namespace grb { * \endparblock */ template< typename DataType, typename View, typename Coords > - size_t size( const VectorView< DataType, View, storage::Dense, storage::Dense, reference_dense, Coords > & x ) noexcept { + size_t size( const VectorView< DataType, View, storage::Dense, reference_dense, Coords > & x ) noexcept { return getLength( x ); } @@ -192,14 +193,14 @@ namespace grb { * \endparblock */ template< typename DataType, typename View, typename Coords > - size_t nnz( const VectorView< DataType, View, storage::Dense, storage::Dense, reference_dense, Coords > & x ) noexcept { + size_t nnz( const VectorView< DataType, View, storage::Dense, reference_dense, Coords > & x ) noexcept { throw std::runtime_error( "Needs an implementation." ); return 0; } /** \todo add documentation. In particular, think about the meaning with \a P > 1. */ template< typename InputType, typename View, typename length_type, typename Coords > - RC resize( VectorView< InputType, View, storage::Dense, storage::Dense, reference_dense, Coords > & x, const length_type new_nz ) { + RC resize( VectorView< InputType, View, storage::Dense, reference_dense, Coords > & x, const length_type new_nz ) { // check if we have a mismatch if( new_nz > grb::size( x ) ) { return MISMATCH; @@ -337,7 +338,7 @@ namespace grb { * @see grb::setElement. */ template< Descriptor descr = descriptors::no_operation, typename DataType, typename DataView, typename MaskType, typename MaskView, typename T, typename Coords > - RC set( VectorView< DataType, View, storage::Dense, reference_dense, Coords > & x, + RC set( VectorView< DataType, DataView, storage::Dense, reference_dense, Coords > & x, const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & m, const T val, const typename std::enable_if< ! grb::is_object< DataType >::value && ! grb::is_object< T >::value, void >::type * const = NULL ) { @@ -580,11 +581,6 @@ namespace grb { "grb::set (reference, VectorView <- VectorView, masked): " "use_index descriptor cannot be set if output VectorView is void" ); - // delegate if possible - if( internal::getCoordinates( mask ).size() == 0 ) { - return set( x, y ); - } - // catch contract violations if( reinterpret_cast< void * >( &x ) == reinterpret_cast< const void * >( &y ) ) { return ILLEGAL; @@ -593,7 +589,7 @@ namespace grb { throw std::runtime_error( "Needs an implementation." ); // done - return ret; + return SUCCESS; } /** @@ -675,7 +671,7 @@ namespace grb { * and/or vectorised operations are used. */ template< Descriptor descr = descriptors::no_operation, class Monoid, typename InputType, typename InputView, typename IOType, typename Coords > - RC foldr( const Vector< InputType, InputView, storage::Dense, reference_dense, Coords > & x, + RC foldr( const VectorView< InputType, InputView, storage::Dense, reference_dense, Coords > & x, IOType & beta, const Monoid & monoid = Monoid(), const typename std::enable_if< ! grb::is_object< InputType >::value && ! grb::is_object< IOType >::value && grb::is_monoid< Monoid >::value, void >::type * const = NULL ) { @@ -995,9 +991,9 @@ namespace grb { * @see grb::operators::internal::Operator for a discussion on when in-place * and/or vectorised operations are used. */ - template< Descriptor descr = descriptors::no_operation, class Monoid, typename IOType, typename InputType,, typename IOView, typename InputView, typename Coords > - RC foldr( const VectorView< InputType, storage::Dense, reference_dense, Coords > & x, - VectorView< IOType, storage::Dense, reference_dense, Coords > & y, + template< Descriptor descr = descriptors::no_operation, class Monoid, typename IOType, typename InputType, typename IOView, typename InputView, typename Coords > + RC foldr( const VectorView< InputType, InputView, storage::Dense, reference_dense, Coords > & x, + VectorView< IOType, IOView, storage::Dense, reference_dense, Coords > & y, const Monoid & monoid = Monoid(), const typename std::enable_if< grb::is_monoid< Monoid >::value && ! grb::is_object< InputType >::value && ! grb::is_object< IOType >::value, void >::type * = NULL ) { // static sanity checks @@ -1160,7 +1156,7 @@ namespace grb { * * Masked operator variant. */ - template< Descriptor descr = descriptors::no_operation, class Op, typename IOType, typename MaskType, typename InputType, typename MaskView, typename InputView, typename Coords > + template< Descriptor descr = descriptors::no_operation, class Op, typename IOType, typename MaskType, typename InputType, typename IOView, typename MaskView, typename InputView, typename Coords > RC foldl( VectorView< IOType, IOView, storage::Dense, reference_dense, Coords > & x, const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & m, const InputType beta, @@ -1646,7 +1642,7 @@ namespace grb { * this. * \endparblock */ - template< Descriptor descr = descriptors::no_operation, class OP, typename OutputType, typename InputType1, typename InputType2, typename OutputView, typename InputView1, typename InputView2, typename OutputView, typename InputView1, typename Coords > + template< Descriptor descr = descriptors::no_operation, class OP, typename OutputType, typename InputType1, typename InputType2, typename OutputView, typename InputView1, typename InputView2, typename Coords > RC eWiseApply( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords > & x, const InputType2 beta, @@ -1665,7 +1661,7 @@ namespace grb { * * Specialisation for \a x and \a y scalar, operator version. */ - template< Descriptor descr = descriptors::no_operation, class OP, typename OutputType, typename InputType1, typename InputType2, typename OutputView, typename InputView1, typename InputView2, typename OutputView, typename Coords > + template< Descriptor descr = descriptors::no_operation, class OP, typename OutputType, typename InputType1, typename InputType2, typename OutputView, typename InputView1, typename InputView2, typename Coords > RC eWiseApply( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, const InputType1 alpha, const InputType2 beta, @@ -1686,7 +1682,7 @@ namespace grb { * * Specialisation for \a x and \a y scalar, monoid version. */ - template< Descriptor descr = descriptors::no_operation, class Monoid, typename OutputType, typename InputType1, typename InputType2, typename OutputView, typename InputView1, typename InputView2, typename OutputView, typename Coords > + template< Descriptor descr = descriptors::no_operation, class Monoid, typename OutputType, typename InputType1, typename InputType2, typename OutputView, typename InputView1, typename InputView2, typename Coords > RC eWiseApply( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, const InputType1 alpha, const InputType2 beta, @@ -1705,7 +1701,7 @@ namespace grb { * * Specialisation for scalar \a y, masked operator version. */ - template< Descriptor descr = descriptors::no_operation, class OP, typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename OutputView, typename MaskView, typename InputView1, typename InputView2, typename OutputView, typename MaskView, typename InputView1, typename Coords > + template< Descriptor descr = descriptors::no_operation, class OP, typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename OutputView, typename MaskView, typename InputView1, typename InputView2, typename Coords > RC eWiseApply( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & mask, const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords > & x, @@ -1730,7 +1726,7 @@ namespace grb { * * Monoid version. */ - template< Descriptor descr = descriptors::no_operation, class Monoid, typename OutputType, typename InputType1, typename InputType2, typename OutputView, typename InputView1, typename InputView2, typename OutputView, typename InputView1, typename InputView2, typename Coords > + template< Descriptor descr = descriptors::no_operation, class Monoid, typename OutputType, typename InputType1, typename InputType2, typename OutputView, typename InputView1, typename InputView2, typename Coords > RC eWiseApply( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords > & x, const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords > & y, @@ -1749,7 +1745,7 @@ namespace grb { * * Specialisation for scalar \a x. Monoid version. */ - template< Descriptor descr = descriptors::no_operation, class Monoid, typename OutputType, typename InputType1, typename InputType2, typename OutputView, typename InputView1, typename InputView2, typename OutputView, typename InputView2, typename Coords > + template< Descriptor descr = descriptors::no_operation, class Monoid, typename OutputType, typename InputType1, typename InputType2, typename OutputView, typename InputView1, typename InputView2, typename Coords > RC eWiseApply( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, const InputType1 alpha, const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords > & y, @@ -1768,7 +1764,7 @@ namespace grb { * * Specialisation for scalar \a y. Monoid version. */ - template< Descriptor descr = descriptors::no_operation, class Monoid, typename OutputType, typename InputType1, typename InputType2, typename OutputView, typename InputView1, typename InputView2, typename OutputView, typename InputView1, typename Coords > + template< Descriptor descr = descriptors::no_operation, class Monoid, typename OutputType, typename InputType1, typename InputType2, typename OutputView, typename InputView1, typename InputView2, typename Coords > RC eWiseApply( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords > & x, const InputType2 beta, @@ -2566,7 +2562,7 @@ namespace grb { * * \internal Dispatches to set. */ - template< Descriptor descr = descriptors::no_operation, class Ring, typename OutputType, typename InputType1, typename InputType2, typename OutputView, typename Coords > + template< Descriptor descr = descriptors::no_operation, class Ring, typename OutputType, typename InputType1, typename InputType2, typename InputType3, typename OutputView, typename Coords > RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, const InputType1 alpha, const InputType2 beta, From 27b3d9d3bcb711a5359a157333afbb0af8860fce Mon Sep 17 00:00:00 2001 From: Anonymous Date: Mon, 28 Feb 2022 14:14:42 +0100 Subject: [PATCH 084/282] Complete blas2 interface for denseref backend --- include/graphblas/denseref/blas2.hpp | 209 +++++++++++++++------------ 1 file changed, 113 insertions(+), 96 deletions(-) diff --git a/include/graphblas/denseref/blas2.hpp b/include/graphblas/denseref/blas2.hpp index 5860cda3a..2d687264f 100644 --- a/include/graphblas/denseref/blas2.hpp +++ b/include/graphblas/denseref/blas2.hpp @@ -25,6 +25,10 @@ #include +#include +#include +#include + namespace grb { /** @@ -48,8 +52,8 @@ namespace grb { * bytes of memory. * \endparblock */ - template< typename InputType > - size_t nrows( const Matrix< InputType, reference > & A ) noexcept { + template< typename InputType, typename InputStructure, typename InputStorage, typename InputView > + size_t nrows( const StructuredMatrix< InputType, InputStructure, InputStorage, InputView, reference_dense > & A ) noexcept { return A.m; } @@ -69,8 +73,8 @@ namespace grb { * bytes of memory. * \endparblock */ - template< typename InputType > - size_t ncols( const Matrix< InputType, reference > & A ) noexcept { + template< typename InputType, typename InputStructure, typename InputStorage, typename InputView > + size_t ncols( const StructuredMatrix< InputType, InputStructure, InputStorage, InputView, reference_dense > & A ) noexcept { return A.n; } @@ -91,7 +95,7 @@ namespace grb { * \endparblock */ template< typename InputType > - size_t nnz( const Matrix< InputType, reference > & A ) noexcept { + size_t nnz( const StructuredMatrix< InputType, InputStructure, InputStorage, InputView, reference_dense > & A ) noexcept { return A.nz; } @@ -123,20 +127,26 @@ namespace grb { * absolutely necessary */ template< typename InputType > - RC resize( Matrix< InputType, reference > & A, const size_t new_nz ) noexcept { + RC resize( StructuredMatrix< InputType, InputStructure, InputStorage, InputView, reference_dense > & A, const size_t new_nz ) noexcept { // delegate return A.resize( new_nz ); } /** \internal Delegates to fully masked variant */ - template< Descriptor descr = descriptors::no_operation, class Ring, typename IOType, typename InputType1, typename InputType2, typename InputType3, typename Coords > - RC vxm( Vector< IOType, reference, Coords > & u, - const Vector< InputType3, reference, Coords > & mask, - const Vector< InputType1, reference, Coords > & v, - const Matrix< InputType2, reference > & A, + template< Descriptor descr = descriptors::no_operation, + class Ring, + typename IOType, typename IOView, typename IOStorage, + typename InputType1, typename InputType1, typename InputView1, typename InputStorage1, + typename InputType2, typename InputStructure2, typename InputStorage2, typename InputView2, + typename InputType3, typename InputType3, typename InputView3, typename InputStorage3, + typename Coords > + RC vxm( VectorView< IOType, IOView, IOStorage, reference_dense, Coords > & u, + const VectorView< InputType3, InputView3, InputStorage3, reference_dense, Coords > & mask, + const VectorView< InputType1, InputView1, InputStorage1, reference_dense, Coords > & v, + const StructuredMatrix< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > & A, const Ring & ring = Ring(), const typename std::enable_if< grb::is_semiring< Ring >::value, void >::type * const = NULL ) { - const Vector< bool, reference, Coords > empty_mask( 0 ); + const VectorView< bool, reference, Coords > empty_mask( 0 ); return vxm< descr, true, false >( u, mask, v, empty_mask, A, ring ); } @@ -144,21 +154,21 @@ namespace grb { template< Descriptor descr = descriptors::no_operation, class AdditiveMonoid, class MultiplicativeOperator, - typename IOType, - typename InputType1, - typename InputType2, - typename InputType3, + typename IOType, typename IOView, typename IOStorage, + typename InputType1, typename InputView1, typename InputStorage1, + typename InputType2, typename InputStructure2, typename InputStorage2, typename InputView2, + typename InputType3, typename InputView3, typename InputStorage3, typename Coords > - RC vxm( Vector< IOType, reference, Coords > & u, - const Vector< InputType3, reference, Coords > & mask, - const Vector< InputType1, reference, Coords > & v, - const Matrix< InputType2, reference > & A, + RC vxm( VectorView< IOType, IOView, IOStorage, reference_dense, Coords > & u, + const VectorView< InputType3, InputView3, InputStorage3, reference_dense, Coords > & mask, + const VectorView< InputType1, InputView1, InputStorage1, reference_dense, Coords > & v, + const StructuredMatrix< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > & A, const AdditiveMonoid & add = AdditiveMonoid(), const MultiplicativeOperator & mul = MultiplicativeOperator(), const typename std::enable_if< grb::is_monoid< AdditiveMonoid >::value && grb::is_operator< MultiplicativeOperator >::value && ! grb::is_object< IOType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && ! std::is_same< InputType2, void >::value, void >::type * const = NULL ) { - const grb::Vector< bool, reference, Coords > empty_mask( 0 ); + const grb::VectorView< bool, reference, Coords > empty_mask( 0 ); return vxm< descr, true, false >( u, mask, v, empty_mask, A, add, mul ); } @@ -167,17 +177,17 @@ namespace grb { bool output_may_be_masked = true, bool input_may_be_masked = true, class Ring, - typename IOType, - typename InputType1, - typename InputType2, - typename InputType3, - typename InputType4, + typename IOType, typename IOView, typename IOStorage, + typename InputType1, typename InputView1, typename InputStorage1, + typename InputType2, typename InputStructure2, typename InputStorage2, typename InputView2, + typename InputType3, typename InputView3, typename InputStorage3, + typename InputType4, typename InputView4, typename InputStorage4, typename Coords > - RC vxm( Vector< IOType, reference, Coords > & u, - const Vector< InputType3, reference, Coords > & mask, - const Vector< InputType1, reference, Coords > & v, - const Vector< InputType4, reference, Coords > & v_mask, - const Matrix< InputType2, reference > & A, + RC vxm( VectorView< IOType, IOView, IOStorage, reference_dense, Coords > & u, + const VectorView< InputType3, InputView3, InputStorage3, reference_dense, Coords > & mask, + const VectorView< InputType1, InputView1, InputStorage1, reference_dense, Coords > & v, + const VectorView< InputType4, InputView4, InputStorage4, reference_dense, Coords > & v_mask, + const StructuredMatrix< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > & A, const Ring & ring = Ring(), const typename std::enable_if< grb::is_semiring< Ring >::value, void >::type * const = NULL ) { throw std::runtime_error( "Needs an implementation." ); @@ -187,48 +197,48 @@ namespace grb { /** \internal Delegates to fully masked version */ template< Descriptor descr = descriptors::no_operation, class Ring, - typename IOType = typename Ring::D4, - typename InputType1 = typename Ring::D1, - typename InputType2 = typename Ring::D2, + typename IOType = typename Ring::D4, typename IOView, typename IOStorage, + typename InputType1 = typename Ring::D1, typename InputView1, typename InputStorage1, + typename InputType2 = typename Ring::D2, typename InputStructure2, typename InputStorage2, typename InputView2, typename Coords > - RC vxm( Vector< IOType, reference, Coords > & u, - const Vector< InputType1, reference, Coords > & v, - const Matrix< InputType2, reference > & A, + RC vxm( VectorView< IOType, IOView, IOStorage, reference_dense, Coords > & u, + const VectorView< InputType1, InputView1, InputStorage1, reference_dense, Coords > & v, + const StructuredMatrix< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > & A, const Ring & ring = Ring(), const typename std::enable_if< grb::is_semiring< Ring >::value, void >::type * const = NULL ) { - const Vector< bool, reference, Coords > empty_mask( 0 ); + const VectorView< bool, reference_dense, Coords > empty_mask( 0 ); return vxm< descr, false, false >( u, empty_mask, v, empty_mask, A, ring ); } /** \internal Delegates to fully masked version */ template< Descriptor descr = descriptors::no_operation, class AdditiveMonoid, class MultiplicativeOperator, typename IOType, typename InputType1, typename InputType2, typename Coords > - RC vxm( Vector< IOType, reference, Coords > & u, - const Vector< InputType1, reference, Coords > & v, - const Matrix< InputType2, reference > & A, + RC vxm( VectorView< IOType, IOView, IOStorage, reference_dense, Coords > & u, + const VectorView< InputType1, InputView1, InputStorage1, reference_dense, Coords > & v, + const StructuredMatrix< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > & A, const AdditiveMonoid & add = AdditiveMonoid(), const MultiplicativeOperator & mul = MultiplicativeOperator(), const typename std::enable_if< grb::is_monoid< AdditiveMonoid >::value && grb::is_operator< MultiplicativeOperator >::value && ! grb::is_object< IOType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! std::is_same< InputType2, void >::value, void >::type * const = NULL ) { - const grb::Vector< bool, reference, Coords > empty_mask( 0 ); + const grb::VectorView< bool, reference_dense, Coords > empty_mask( 0 ); return vxm< descr, false, false >( u, empty_mask, v, empty_mask, A, add, mul ); } /** \internal Delegates to fully masked version */ template< Descriptor descr = descriptors::no_operation, class Ring, - typename IOType = typename Ring::D4, - typename InputType1 = typename Ring::D1, - typename InputType2 = typename Ring::D2, - typename InputType3 = bool, + typename IOType, typename IOView, typename IOStorage, + typename InputType1, typename InputView1, typename InputStorage1, + typename InputType2, typename InputStructure2, typename InputStorage2, typename InputView2, + typename InputType3 = bool, typename InputView3, typename InputStorage3, typename Coords > - RC mxv( Vector< IOType, reference, Coords > & u, - const Vector< InputType3, reference, Coords > & mask, - const Matrix< InputType2, reference > & A, - const Vector< InputType1, reference, Coords > & v, + RC mxv( VectorView< IOType, IOView, IOStorage, reference_dense, Coords > & u, + const VectorView< InputType3, InputView3, InputStorage3, reference_dense, Coords > & mask, + const StructuredMatrix< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > & A, + const VectorView< InputType1, InputView1, InputStorage1, reference_dense, Coords > & v, const Ring & ring, const typename std::enable_if< grb::is_semiring< Ring >::value, void >::type * const = NULL ) { - const Vector< bool, reference, Coords > empty_mask( 0 ); + const VectorView< bool, reference_dense, Coords > empty_mask( 0 ); return mxv< descr, true, false >( u, mask, A, v, empty_mask, ring ); } @@ -237,17 +247,17 @@ namespace grb { bool output_may_be_masked = true, bool input_may_be_masked = true, class Ring, - typename IOType, - typename InputType1, - typename InputType2, - typename InputType3, - typename InputType4, + typename IOType, typename IOView, typename IOStorage, + typename InputType1, typename InputView1, typename InputStorage1, + typename InputType2, typename InputStructure2, typename InputStorage2, typename InputView2, + typename InputType3, typename InputView3, typename InputStorage3, + typename InputType4, typename InputView4, typename InputStorage4, typename Coords > - RC mxv( Vector< IOType, reference, Coords > & u, - const Vector< InputType3, reference, Coords > & mask, - const Matrix< InputType2, reference > & A, - const Vector< InputType1, reference, Coords > & v, - const Vector< InputType4, reference, Coords > & v_mask, + RC mxv( VectorView< IOType, IOView, IOStorage, reference_dense, Coords > & u, + const VectorView< InputType3, InputView3, InputStorage3, reference_dense, Coords > & mask, + const StructuredMatrix< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > & A, + const VectorView< InputType1, InputView1, InputStorage1, reference_dense, Coords > & v, + const VectorView< InputType4, InputView4, InputStorage4, reference_dense, Coords > & v_mask, const Ring & ring, const typename std::enable_if< grb::is_semiring< Ring >::value, void >::type * const = NULL ) { @@ -260,30 +270,30 @@ namespace grb { */ template< Descriptor descr = descriptors::no_operation, class Ring, - typename IOType = typename Ring::D4, - typename InputType1 = typename Ring::D1, - typename InputType2 = typename Ring::D2, + typename IOType = typename Ring::D4, typename IOView, IOStorage, + typename InputType1 = typename Ring::D1, typename InputStructure2, typename InputStorage2, typename InputView2, + typename InputType2 = typename Ring::D2, typename InputView1, typename InputStorage1, typename Coords > - RC mxv( Vector< IOType, reference, Coords > & u, - const Matrix< InputType2, reference > & A, - const Vector< InputType1, reference, Coords > & v, + RC mxv( VectorView< IOType, IOView, IOStorage, reference_dense, Coords > & u, + const StructuredMatrix< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > & A, + const VectorView< InputType1, InputView1, InputStorage1, reference_dense, Coords > & v, const Ring & ring, const typename std::enable_if< grb::is_semiring< Ring >::value, void >::type * const = NULL ) { - const Vector< bool, reference, Coords > empty_mask( 0 ); + const VectorView< bool, view::Identity< void >, structure::full, reference_dense, Coords > empty_mask( 0 ); return mxv< descr, false, false >( u, empty_mask, A, v, empty_mask, ring ); } /** \internal Delegates to fully masked version */ template< Descriptor descr = descriptors::no_operation, class AdditiveMonoid, class MultiplicativeOperator, typename IOType, typename InputType1, typename InputType2, typename Coords > - RC mxv( Vector< IOType, reference, Coords > & u, - const Matrix< InputType2, reference > & A, - const Vector< InputType1, reference, Coords > & v, + RC mxv( VectorView< IOType, IOView, IOStorage, reference_dense, Coords > & u, + const StructuredMatrix< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > & A, + const VectorView< InputType1, InputView1, InputStorage1, reference_dense, Coords > & v, const AdditiveMonoid & add = AdditiveMonoid(), const MultiplicativeOperator & mul = MultiplicativeOperator(), const typename std::enable_if< grb::is_monoid< AdditiveMonoid >::value && grb::is_operator< MultiplicativeOperator >::value && ! grb::is_object< IOType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! std::is_same< InputType2, void >::value, void >::type * const = NULL ) { - const grb::Vector< bool, reference, Coords > empty_mask( 0 ); + const grb::VectorView< bool, view::Identity< void >, structure::full, reference_dense, Coords > empty_mask( 0 ); return mxv< descr, false, false >( u, empty_mask, A, v, empty_mask, add, mul ); } @@ -295,17 +305,17 @@ namespace grb { bool input_may_be_masked = true, class AdditiveMonoid, class MultiplicativeOperator, - typename IOType, - typename InputType1, - typename InputType2, - typename InputType3, - typename InputType4, + typename IOType, typename IOView, typename IOStorage, + typename InputType1, typename InputView1, typename InputStorage1, + typename InputType2, typename InputStructure2, typename InputStorage2, typename InputView2, + typename InputType3, typename InputView3, typename InputStorage3, + typename InputType4, typename InputView4, typename InputStorage4, typename Coords > - RC vxm( Vector< IOType, reference, Coords > & u, - const Vector< InputType3, reference, Coords > & mask, - const Vector< InputType1, reference, Coords > & v, - const Vector< InputType4, reference, Coords > & v_mask, - const Matrix< InputType2, reference > & A, + RC vxm( VectorView< IOType, IOView, IOStorage, reference_dense, Coords > & u, + const VectorView< InputType3, InputView3, InputStorage3, reference_dense, Coords > & mask, + const VectorView< InputType1, InputView1, InputStorage1, reference_dense, Coords > & v, + const VectorView< InputType4, InputView4, InputStorage4, reference_dense, Coords > & v_mask, + const StructuredMatrix< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > & A, const AdditiveMonoid & add = AdditiveMonoid(), const MultiplicativeOperator & mul = MultiplicativeOperator(), const typename std::enable_if< grb::is_monoid< AdditiveMonoid >::value && grb::is_operator< MultiplicativeOperator >::value && ! grb::is_object< IOType >::value && @@ -325,17 +335,17 @@ namespace grb { bool input_may_be_masked = true, class AdditiveMonoid, class MultiplicativeOperator, - typename IOType, - typename InputType1, - typename InputType2, - typename InputType3, - typename InputType4, + typename IOType, typename IOView, typename IOStorage, + typename InputType1, typename InputView1, typename InputStorage1, + typename InputType2, typename InputStructure2, typename InputStorage2, typename InputView2, + typename InputType3, typename InputView3, typename InputStorage3, + typename InputType4, typename InputView4, typename InputStorage4, typename Coords > - RC mxv( Vector< IOType, reference, Coords > & u, - const Vector< InputType3, reference, Coords > & mask, - const Matrix< InputType2, reference > & A, - const Vector< InputType1, reference, Coords > & v, - const Vector< InputType4, reference, Coords > & v_mask, + RC mxv( VectorView< IOType, reference_dense, Coords > & u, + const VectorView< InputType3, reference_dense, Coords > & mask, + const StructuredMatrix< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > & A, + const VectorView< InputType1, reference_dense, Coords > & v, + const VectorView< InputType4, reference_dense, Coords > & v_mask, const AdditiveMonoid & add = AdditiveMonoid(), const MultiplicativeOperator & mul = MultiplicativeOperator(), const typename std::enable_if< grb::is_monoid< AdditiveMonoid >::value && grb::is_operator< MultiplicativeOperator >::value && ! grb::is_object< IOType >::value && @@ -352,8 +362,11 @@ namespace grb { * * @see grb::eWiseLambda for the user-level specification. */ - template< class ActiveDistribution, typename Func, typename DataType > - RC eWiseLambda( const Func f, const Matrix< DataType, reference > & A, const size_t s, const size_t P ) { + template< class ActiveDistribution, typename Func, typename DataType, typename Structure, typename Storage, typename View> + RC eWiseLambda( const Func f, + const StructuredMatrix< DataType, Structure, Storage, View, reference_dense > & A, + const size_t s, + const size_t P ) { #ifdef _DEBUG std::cout << "entering grb::eWiseLambda (matrices, reference ). A is " << grb::nrows( A ) << " by " << grb::ncols( A ) << " and holds " << grb::nnz( A ) << " nonzeroes.\n"; #endif @@ -367,8 +380,12 @@ namespace grb { * * @see grb::eWiseLambda for the user-level specification. */ - template< typename Func, typename DataType1, typename DataType2, typename Coords, typename... Args > - RC eWiseLambda( const Func f, const Matrix< DataType1, reference > & A, const Vector< DataType2, reference, Coords > x, Args... args ) { + template< typename Func, + typename DataType1, typename Structure1, typename Storage1, typename View1, + typename DataType2, typename View2, typename Storage2, typename Coords, typename... Args > + RC eWiseLambda( const Func f, + const StructuredMatrix< DataType1, Structure1, Storage1, View1, reference_dense > & A, + const VectorView< DataType2, View2, Storage2, reference_dense, Coords > x, Args... args ) { // do size checking if( ! ( size( x ) == nrows( A ) || size( x ) == ncols( A ) ) ) { std::cerr << "Mismatching dimensions: given vector of size " << size( x ) << " has nothing to do with either matrix dimension (" << nrows( A ) << " nor " << ncols( A ) << ").\n"; From c4701a80757c100eafdcaac9f6255089d867d31a Mon Sep 17 00:00:00 2001 From: Anonymous Date: Mon, 28 Feb 2022 14:17:25 +0100 Subject: [PATCH 085/282] Fix compilation of vector --- include/graphblas/denseref/vector.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/graphblas/denseref/vector.hpp b/include/graphblas/denseref/vector.hpp index 7533a1506..dedf9a50e 100644 --- a/include/graphblas/denseref/vector.hpp +++ b/include/graphblas/denseref/vector.hpp @@ -359,7 +359,7 @@ namespace grb { * * @returns A VectorView object. * */ - template< typename StructuredMatrixT, typename C > + template< typename StructuredMatrixT, typename C = internal::DefaultCoordinates > VectorView< typename StructuredMatrixT::value_type, view::Diagonal< StructuredMatrixT >, storage::Dense, reference_dense, C > diagonal( StructuredMatrixT &smat ) { From 99abd12d93b33ee39ea8b6e7ba020ab42a5b49ee Mon Sep 17 00:00:00 2001 From: Anonymous Date: Mon, 28 Feb 2022 16:29:22 +0100 Subject: [PATCH 086/282] Add possibility for VectorView to be a temporary --- include/graphblas/base/vector.hpp | 2 +- include/graphblas/denseref/vector.hpp | 54 +++++++++++++++------------ include/graphblas/vector.hpp | 2 +- 3 files changed, 32 insertions(+), 26 deletions(-) diff --git a/include/graphblas/base/vector.hpp b/include/graphblas/base/vector.hpp index fb64a1502..fa635fe0e 100644 --- a/include/graphblas/base/vector.hpp +++ b/include/graphblas/base/vector.hpp @@ -901,7 +901,7 @@ namespace grb { } }; - template< typename T, typename View, typename StorageSchemeType, enum Backend backend, typename C > + template< typename T, typename View, typename StorageSchemeType, enum Backend backend, typename C, typename tmp > class VectorView { }; } diff --git a/include/graphblas/denseref/vector.hpp b/include/graphblas/denseref/vector.hpp index dedf9a50e..49e7cdf18 100644 --- a/include/graphblas/denseref/vector.hpp +++ b/include/graphblas/denseref/vector.hpp @@ -209,19 +209,19 @@ namespace grb { * Here starts spec draft for vectorView */ - template< typename T, typename View, typename C > - size_t getLength( const VectorView< T, View, storage::Dense, reference_dense, C > &v ) noexcept { + template< typename T, typename View, typename C, typename tmp > + size_t getLength( const VectorView< T, View, storage::Dense, reference_dense, C, tmp > &v ) noexcept { return v._length(); } /** * Identity View over a vector container. */ - template< typename T, typename C > - class VectorView< T, view::Identity< void >, storage::Dense, reference_dense, C > { + template< typename T, typename C, typename tmp > + class VectorView< T, view::Identity< void >, storage::Dense, reference_dense, C, tmp > { private: - using self_type = VectorView< T, view::Identity< void >, storage::Dense, reference_dense, C >; + using self_type = VectorView< T, view::Identity< void >, storage::Dense, reference_dense, C, tmp >; /********************* Storage info friends @@ -249,13 +249,19 @@ namespace grb { /** @see Vector::value_type. */ using value_type = T; + /** + * @brief Any vector view type which allocates a physical container provides a version of + * itself for defining a temporary vector of the same type via the \a tmp_t member type. + */ + using tmp_t = VectorView< T, view::Identity< void >, storage::Dense, reference_dense, C, true >; + VectorView( const size_t length ) : v( std::make_unique< Vector< T, reference_dense, C > >( length ) ), imf( std::make_shared< imf::Id >( length ) ), initialized( false ) {} }; // class VectorView with physical container /** Identifies any reference_dense vector as an ALP vector. */ - template< typename T, typename View, typename Storage, typename C > - struct is_container< VectorView< T, View, Storage, reference_dense, C > > { + template< typename T, typename View, typename Storage, typename C, typename tmp > + struct is_container< VectorView< T, View, Storage, reference_dense, C, tmp > > { /** A reference_vector is an ALP object. */ static const constexpr bool value = true; }; @@ -263,11 +269,11 @@ namespace grb { /** * Vector view of a vector only via \a view::Identity of another VectorView. */ - template< typename T, typename VectorViewT, typename C > - class VectorView< T, view::Identity< VectorViewT >, storage::Dense, reference_dense, C > { + template< typename T, typename VectorViewT, typename C, typename tmp > + class VectorView< T, view::Identity< VectorViewT >, storage::Dense, reference_dense, C, tmp > { private: - using self_type = VectorView< T, view::Identity< VectorViewT >, storage::Dense, reference_dense, C >; + using self_type = VectorView< T, view::Identity< VectorViewT >, storage::Dense, reference_dense, C, tmp >; using target_type = VectorViewT; /********************* @@ -311,13 +317,13 @@ namespace grb { /** * Diagonal Vector View of a structured matrix. */ - template< typename T, typename StructuredMatrixT, typename C > - class VectorView< T, view::Diagonal< StructuredMatrixT >, storage::Dense, reference_dense, C > { + template< typename T, typename StructuredMatrixT, typename C, typename tmp > + class VectorView< T, view::Diagonal< StructuredMatrixT >, storage::Dense, reference_dense, C, tmp > { private: /** Exposes the own type and the type of the VectorView object over * which this view is created. */ - using self_type = VectorView< T, view::Diagonal< StructuredMatrixT >, storage::Dense, reference_dense, C >; + using self_type = VectorView< T, view::Diagonal< StructuredMatrixT >, storage::Dense, reference_dense, C, tmp >; using target_type = StructuredMatrixT; /********************* @@ -359,11 +365,11 @@ namespace grb { * * @returns A VectorView object. * */ - template< typename StructuredMatrixT, typename C = internal::DefaultCoordinates > - VectorView< typename StructuredMatrixT::value_type, view::Diagonal< StructuredMatrixT >, storage::Dense, reference_dense, C > + template< typename StructuredMatrixT, typename C = internal::DefaultCoordinates, typename tmp = false > + VectorView< typename StructuredMatrixT::value_type, view::Diagonal< StructuredMatrixT >, storage::Dense, reference_dense, C, tmp > diagonal( StructuredMatrixT &smat ) { - VectorView< typename StructuredMatrixT::value_type, view::Diagonal< StructuredMatrixT >, storage::Dense, reference_dense, C > smat_diag( smat ); + VectorView< typename StructuredMatrixT::value_type, view::Diagonal< StructuredMatrixT >, storage::Dense, reference_dense, C, tmp > smat_diag( smat ); return smat_diag; } @@ -375,11 +381,11 @@ namespace grb { * * @returns A VectorView object. */ - template< typename T, typename View, typename StorageSchemeType, enum Backend backend, typename C = internal::DefaultCoordinates > - VectorView< T, view::Identity< VectorView< T, View, StorageSchemeType, backend, C > >, StorageSchemeType, backend, C > - get_view( VectorView< T, View, StorageSchemeType, backend, C > &source ) { + template< typename T, typename View, typename StorageSchemeType, enum Backend backend, typename C = internal::DefaultCoordinates, typename tmp = false > + VectorView< T, view::Identity< VectorView< T, View, StorageSchemeType, backend, C > >, StorageSchemeType, backend, C, tmp > + get_view( VectorView< T, View, StorageSchemeType, backend, C, tmp > &source ) { - VectorView< T, view::Identity< VectorView< T, View, StorageSchemeType, backend, C > >, StorageSchemeType, backend, C > vec_view( source ); + VectorView< T, view::Identity< VectorView< T, View, StorageSchemeType, backend, C > >, StorageSchemeType, backend, C, tmp > vec_view( source ); return vec_view; } @@ -394,11 +400,11 @@ namespace grb { * @returns A VectorView object. */ - template< typename T, typename View, typename StorageSchemeType, enum Backend backend, typename C > - VectorView< T, view::Identity< VectorView< T, View, StorageSchemeType, backend, C > >, StorageSchemeType, backend, C > - get_view( VectorView< T, View, StorageSchemeType, backend, C > &source, std::shared_ptr< imf::IMF > imf ) { + template< typename T, typename View, typename StorageSchemeType, enum Backend backend, typename C, typename tmp = false > + VectorView< T, view::Identity< VectorView< T, View, StorageSchemeType, backend, C > >, StorageSchemeType, backend, C, tmp > + get_view( VectorView< T, View, StorageSchemeType, backend, C, tmp > &source, std::shared_ptr< imf::IMF > imf ) { - VectorView< T, view::Identity< VectorView< T, View, StorageSchemeType, backend, C > >, StorageSchemeType, backend, C > vec_view( source, imf ); + VectorView< T, view::Identity< VectorView< T, View, StorageSchemeType, backend, C > >, StorageSchemeType, backend, C, tmp > vec_view( source, imf ); return vec_view; } diff --git a/include/graphblas/vector.hpp b/include/graphblas/vector.hpp index 53c72097d..b3e091051 100644 --- a/include/graphblas/vector.hpp +++ b/include/graphblas/vector.hpp @@ -57,7 +57,7 @@ namespace grb { /* * The default value of \a StorageSchemeType could also be made conditional (Dense or Sparse) depending on \a config::default_backend */ - template< typename T, typename View = view::Identity< void >, typename StorageSchemeType = storage::Dense, enum Backend backend = config::default_backend, typename C = internal::DefaultCoordinates > + template< typename T, typename View = view::Identity< void >, typename StorageSchemeType = storage::Dense, enum Backend backend = config::default_backend, typename C = internal::DefaultCoordinates, bool tmp = false > class VectorView; } From d8df3550611a69b0584dfbaf6991893577d8229d Mon Sep 17 00:00:00 2001 From: Anonymous Date: Mon, 28 Feb 2022 18:35:57 +0100 Subject: [PATCH 087/282] Add VectorView tmp parameter to blas1 and blas2 --- include/graphblas/denseref/blas1.hpp | 722 +++++++++++++++++---------- include/graphblas/denseref/blas2.hpp | 38 +- 2 files changed, 480 insertions(+), 280 deletions(-) diff --git a/include/graphblas/denseref/blas1.hpp b/include/graphblas/denseref/blas1.hpp index 940740284..4e6174847 100644 --- a/include/graphblas/denseref/blas1.hpp +++ b/include/graphblas/denseref/blas1.hpp @@ -140,8 +140,8 @@ namespace grb { * \mathit{sizeof}(\mathit{size\_t}) \f$ bytes of data. * \endparblock */ - template< typename DataType, typename View, typename Coords > - RC clear( VectorView< DataType, View, storage::Dense, reference_dense, Coords > & x ) noexcept { + template< typename DataType, typename View, typename Coords, typename Tmp > + RC clear( VectorView< DataType, View, storage::Dense, reference_dense, Coords, Tmp> & x ) noexcept { throw std::runtime_error( "Needs an implementation" ); return SUCCESS; } @@ -167,8 +167,8 @@ namespace grb { * -# shall not make any system calls. * \endparblock */ - template< typename DataType, typename View, typename Coords > - size_t size( const VectorView< DataType, View, storage::Dense, reference_dense, Coords > & x ) noexcept { + template< typename DataType, typename View, typename Coords, typename Tmp > + size_t size( const VectorView< DataType, View, storage::Dense, reference_dense, Coords, Tmp > & x ) noexcept { return getLength( x ); } @@ -192,15 +192,15 @@ namespace grb { * -# shall not make any system calls. * \endparblock */ - template< typename DataType, typename View, typename Coords > - size_t nnz( const VectorView< DataType, View, storage::Dense, reference_dense, Coords > & x ) noexcept { + template< typename DataType, typename View, typename Coords, typename Tmp > + size_t nnz( const VectorView< DataType, View, storage::Dense, reference_dense, Coords, Tmp > & x ) noexcept { throw std::runtime_error( "Needs an implementation." ); return 0; } /** \todo add documentation. In particular, think about the meaning with \a P > 1. */ - template< typename InputType, typename View, typename length_type, typename Coords > - RC resize( VectorView< InputType, View, storage::Dense, reference_dense, Coords > & x, const length_type new_nz ) { + template< typename InputType, typename View, typename length_type, typename Coords, typename Tmp > + RC resize( VectorView< InputType, View, storage::Dense, reference_dense, Coords, Tmp > & x, const length_type new_nz ) { // check if we have a mismatch if( new_nz > grb::size( x ) ) { return MISMATCH; @@ -264,9 +264,9 @@ namespace grb { template< Descriptor descr = descriptors::no_operation, typename DataType, typename View, typename T, - typename Coords + typename Coords, typename Tmp > - RC set( VectorView< DataType, View, storage::Dense, reference_dense, Coords > & x, const T val, + RC set( VectorView< DataType, View, storage::Dense, reference_dense, Coords, Tmp > & x, const T val, const typename std::enable_if< !grb::is_object< DataType >::value && !grb::is_object< T >::value, @@ -337,9 +337,9 @@ namespace grb { * @see grb::operators::right_assign. * @see grb::setElement. */ - template< Descriptor descr = descriptors::no_operation, typename DataType, typename DataView, typename MaskType, typename MaskView, typename T, typename Coords > - RC set( VectorView< DataType, DataView, storage::Dense, reference_dense, Coords > & x, - const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & m, + template< Descriptor descr = descriptors::no_operation, typename DataType, typename DataView, typename MaskType, typename MaskView, typename DataTmp, typename MaskTmp, typename T, typename Coords > + RC set( VectorView< DataType, DataView, storage::Dense, reference_dense, Coords, DataTmp > & x, + const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords, MaskTmp > & m, const T val, const typename std::enable_if< ! grb::is_object< DataType >::value && ! grb::is_object< T >::value, void >::type * const = NULL ) { #ifdef _DEBUG @@ -410,8 +410,8 @@ namespace grb { * -# shall not make any system calls. * \endparblock */ - template< Descriptor descr = descriptors::no_operation, typename DataType, typename View, typename T, typename Coords > - RC setElement( VectorView< DataType, View, storage::Dense, reference_dense, Coords > & x, + template< Descriptor descr = descriptors::no_operation, typename DataType, typename View, typename T, typename Coords, typename Tmp > + RC setElement( VectorView< DataType, View, storage::Dense, reference_dense, Coords, Tmp > & x, const T val, const size_t i, const typename std::enable_if< ! grb::is_object< DataType >::value && ! grb::is_object< T >::value, void >::type * const = NULL ) { @@ -478,8 +478,8 @@ namespace grb { * @see grb::operators::right_assign. * @see grb::setElement. */ - template< Descriptor descr = descriptors::no_operation, typename OutputType, typename InputType, typename OutputView, typename InputView, typename Coords > - RC set( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & x, const VectorView< InputType, InputView, storage::Dense, reference_dense, Coords > & y ) { + template< Descriptor descr = descriptors::no_operation, typename OutputType, typename InputType, typename OutputView, typename InputView, typename Coords, typename OutputTmp, typename InputTmp > + RC set( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & x, const VectorView< InputType, InputView, storage::Dense, reference_dense, Coords, InputTmp > & y ) { // static sanity checks NO_CAST_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< OutputType, InputType >::value ), "grb::copy (Vector)", "called with vector parameters whose element data types do not match" ); @@ -563,10 +563,10 @@ namespace grb { * @see grb::operators::right_assign. * @see grb::setElement. */ - template< Descriptor descr = descriptors::no_operation, typename OutputType, typename MaskType, typename InputType, typename OutputView, typename MaskView, typename InputView, typename Coords > - RC set( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & x, - const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & mask, - const VectorView< InputType, InputView, storage::Dense, reference_dense, Coords > & y, + template< Descriptor descr = descriptors::no_operation, typename OutputType, typename MaskType, typename InputType, typename OutputView, typename MaskView, typename InputView, typename Coords, typename OutputTmp, typename MaskTmp, typename InputTmp > + RC set( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & x, + const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords, MaskTmp > & mask, + const VectorView< InputType, InputView, storage::Dense, reference_dense, Coords, InputTmp > & y, const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType >::value, void >::type * const = NULL ) { // static sanity checks NO_CAST_ASSERT( @@ -670,8 +670,8 @@ namespace grb { * @see grb::operators::internal::Operator for a discussion on when in-place * and/or vectorised operations are used. */ - template< Descriptor descr = descriptors::no_operation, class Monoid, typename InputType, typename InputView, typename IOType, typename Coords > - RC foldr( const VectorView< InputType, InputView, storage::Dense, reference_dense, Coords > & x, + template< Descriptor descr = descriptors::no_operation, class Monoid, typename InputType, typename InputView, typename IOType, typename Coords, typename InputTmp > + RC foldr( const VectorView< InputType, InputView, storage::Dense, reference_dense, Coords, InputTmp > & x, IOType & beta, const Monoid & monoid = Monoid(), const typename std::enable_if< ! grb::is_object< InputType >::value && ! grb::is_object< IOType >::value && grb::is_monoid< Monoid >::value, void >::type * const = NULL ) { @@ -749,9 +749,9 @@ namespace grb { * @see grb::operators::internal::Operator for a discussion on when in-place * and/or vectorised operations are used. */ - template< Descriptor descr = descriptors::no_operation, class Monoid, typename IOType, typename InputType, typename InputView, typename Coords > + template< Descriptor descr = descriptors::no_operation, class Monoid, typename IOType, typename InputType, typename InputView, typename Coords, typename InputTmp > RC foldr( const InputType & alpha, - VectorView< IOType, InputView, storage::Dense, reference_dense, Coords > & y, + VectorView< IOType, InputView, storage::Dense, reference_dense, Coords, InputTmp > & y, const Monoid & monoid = Monoid(), const typename std::enable_if< ! grb::is_object< InputType >::value && ! grb::is_object< IOType >::value && grb::is_monoid< Monoid >::value, void >::type * const = NULL ) { // static sanity checks @@ -774,9 +774,9 @@ namespace grb { * * Specialisation for scalar \a x. */ - template< Descriptor descr = descriptors::no_operation, class OP, typename IOType, typename InputType, typename IOView, typename Coords > + template< Descriptor descr = descriptors::no_operation, class OP, typename IOType, typename InputType, typename IOView, typename Coords, typename IOTmp > RC foldr( const InputType & alpha, - VectorView< IOType, IOView, storage::Dense, reference_dense, Coords > & y, + VectorView< IOType, IOView, storage::Dense, reference_dense, Coords, IOTmp > & y, const OP & op = OP(), const typename std::enable_if< ! grb::is_object< InputType >::value && ! grb::is_object< IOType >::value && grb::is_operator< OP >::value, void >::type * const = NULL ) { // static sanity checks @@ -862,9 +862,9 @@ namespace grb { * @see grb::operators::internal::Operator for a discussion on when in-place * and/or vectorised operations are used. */ - template< Descriptor descr = descriptors::no_operation, class OP, typename IOType, typename InputType, typename IOView, typename InputView, typename Coords > - RC foldr( const VectorView< InputType, InputView, storage::Dense, reference_dense, Coords > & x, - VectorView< IOType, IOView, storage::Dense, reference_dense, Coords > & y, + template< Descriptor descr = descriptors::no_operation, class OP, typename IOType, typename InputType, typename IOView, typename InputView, typename Coords, typename IOTmp, typename InputTmp > + RC foldr( const VectorView< InputType, InputView, storage::Dense, reference_dense, Coords, InputTmp > & x, + VectorView< IOType, IOView, storage::Dense, reference_dense, Coords, IOTmp > & y, const OP & op = OP(), const typename std::enable_if< grb::is_operator< OP >::value && ! grb::is_object< InputType >::value && ! grb::is_object< IOType >::value, void >::type * = NULL ) { // static sanity checks @@ -891,10 +891,14 @@ namespace grb { * * Masked variant. */ - template< Descriptor descr = descriptors::no_operation, class OP, typename IOType, typename MaskType, typename InputType, typename IOView, typename MaskView, typename InputView, typename Coords > - RC foldr( const VectorView< InputType, InputView, storage::Dense, reference_dense, Coords > & x, - const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & m, - VectorView< IOType, IOView, storage::Dense, reference_dense, Coords > & y, + template< Descriptor descr = descriptors::no_operation, class OP, + typename IOType, typename MaskType, typename InputType, + typename IOView, typename MaskView, typename InputView, + typename Coords, + typename IOTmp, typename MaskTmp, typename InputTmp > + RC foldr( const VectorView< InputType, InputView, storage::Dense, reference_dense, Coords, InputTmp > & x, + const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords, MaskTmp > & m, + VectorView< IOType, IOView, storage::Dense, reference_dense, Coords, IOTmp > & y, const OP & op = OP(), const typename std::enable_if< grb::is_operator< OP >::value && ! grb::is_object< InputType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< IOType >::value, void >::type * = NULL ) { @@ -991,9 +995,9 @@ namespace grb { * @see grb::operators::internal::Operator for a discussion on when in-place * and/or vectorised operations are used. */ - template< Descriptor descr = descriptors::no_operation, class Monoid, typename IOType, typename InputType, typename IOView, typename InputView, typename Coords > - RC foldr( const VectorView< InputType, InputView, storage::Dense, reference_dense, Coords > & x, - VectorView< IOType, IOView, storage::Dense, reference_dense, Coords > & y, + template< Descriptor descr = descriptors::no_operation, class Monoid, typename IOType, typename InputType, typename IOView, typename InputView, typename Coords, typename IOTmp, typename InputTmp > + RC foldr( const VectorView< InputType, InputView, storage::Dense, reference_dense, Coords, InputTmp > & x, + VectorView< IOType, IOView, storage::Dense, reference_dense, Coords, IOTmp > & y, const Monoid & monoid = Monoid(), const typename std::enable_if< grb::is_monoid< Monoid >::value && ! grb::is_object< InputType >::value && ! grb::is_object< IOType >::value, void >::type * = NULL ) { // static sanity checks @@ -1022,10 +1026,10 @@ namespace grb { * * Masked variant. */ - template< Descriptor descr = descriptors::no_operation, class Monoid, typename IOType, typename MaskType, typename InputType, typename IOView, typename MaskView, typename InputView, typename Coords > - RC foldr( const VectorView< InputType, InputView, storage::Dense, reference_dense, Coords > & x, - const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & m, - VectorView< IOType, IOView, storage::Dense, reference_dense, Coords > & y, + template< Descriptor descr = descriptors::no_operation, class Monoid, typename IOType, typename MaskType, typename InputType, typename IOView, typename MaskView, typename InputView, typename Coords, typename IOTmp, typename MaskTmp, typename InputTmp > + RC foldr( const VectorView< InputType, InputView, storage::Dense, reference_dense, Coords, InputTmp > & x, + const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords, MaskTmp > & m, + VectorView< IOType, IOView, storage::Dense, reference_dense, Coords, IOTmp > & y, const Monoid & monoid = Monoid(), const typename std::enable_if< grb::is_monoid< Monoid >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType >::value && ! grb::is_object< IOType >::value, void >::type * = NULL ) { @@ -1130,8 +1134,8 @@ namespace grb { * @see grb::operators::internal::Operator for a discussion on when in-place * and/or vectorised operations are used. */ - template< Descriptor descr = descriptors::no_operation, class Op, typename IOType, typename InputType, typename IOView, typename Coords > - RC foldl( VectorView< IOType, IOView, storage::Dense, reference_dense, Coords > & x, + template< Descriptor descr = descriptors::no_operation, class Op, typename IOType, typename InputType, typename IOView, typename Coords, typename IOTmp > + RC foldl( VectorView< IOType, IOView, storage::Dense, reference_dense, Coords, IOTmp > & x, const InputType beta, const Op & op = Op(), const typename std::enable_if< ! grb::is_object< IOType >::value && ! grb::is_object< InputType >::value && grb::is_operator< Op >::value, void >::type * = NULL ) { @@ -1156,9 +1160,9 @@ namespace grb { * * Masked operator variant. */ - template< Descriptor descr = descriptors::no_operation, class Op, typename IOType, typename MaskType, typename InputType, typename IOView, typename MaskView, typename InputView, typename Coords > - RC foldl( VectorView< IOType, IOView, storage::Dense, reference_dense, Coords > & x, - const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & m, + template< Descriptor descr = descriptors::no_operation, class Op, typename IOType, typename MaskType, typename InputType, typename IOView, typename MaskView, typename InputView, typename Coords, typename IOTmp, typename MaskTmp > + RC foldl( VectorView< IOType, IOView, storage::Dense, reference_dense, Coords, IOTmp > & x, + const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords, MaskTmp > & m, const InputType beta, const Op & op = Op(), const typename std::enable_if< ! grb::is_object< IOType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType >::value && grb::is_operator< Op >::value, void >::type * = @@ -1252,8 +1256,8 @@ namespace grb { * @see grb::operators::internal::Operator for a discussion on when in-place * and/or vectorised operations are used. */ - template< Descriptor descr = descriptors::no_operation, class Monoid, typename IOType, typename InputType, typename IOView, typename Coords > - RC foldl( VectorView< IOType, IOView, storage::Dense, reference_dense, Coords > & x, + template< Descriptor descr = descriptors::no_operation, class Monoid, typename IOType, typename InputType, typename IOView, typename Coords, typename IOTmp > + RC foldl( VectorView< IOType, IOView, storage::Dense, reference_dense, Coords, IOTmp > & x, const InputType beta, const Monoid & monoid = Monoid(), const typename std::enable_if< ! grb::is_object< IOType >::value && ! grb::is_object< InputType >::value && grb::is_monoid< Monoid >::value, void >::type * = NULL ) { @@ -1278,9 +1282,9 @@ namespace grb { * * Masked monoid variant. */ - template< Descriptor descr = descriptors::no_operation, class Monoid, typename IOType, typename MaskType, typename InputType, typename IOView, typename MaskView, typename Coords > - RC foldl( VectorView< IOType, IOView, storage::Dense, reference_dense, Coords > & x, - const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & m, + template< Descriptor descr = descriptors::no_operation, class Monoid, typename IOType, typename MaskType, typename InputType, typename IOView, typename MaskView, typename Coords, typename IOTmp, typename MaskTmp > + RC foldl( VectorView< IOType, IOView, storage::Dense, reference_dense, Coords, IOTmp > & x, + const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords, MaskTmp > & m, const InputType & beta, const Monoid & monoid = Monoid(), const typename std::enable_if< ! grb::is_object< IOType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType >::value && grb::is_monoid< Monoid >::value, void >::type * = @@ -1375,9 +1379,9 @@ namespace grb { * @see grb::operators::internal::Operator for a discussion on when in-place * and/or vectorised operations are used. */ - template< Descriptor descr = descriptors::no_operation, class OP, typename IOType, typename InputType, typename IOView, typename InputView, typename Coords > - RC foldl( VectorView< IOType, IOView, storage::Dense, reference_dense, Coords > & x, - const VectorView< InputType, InputView, storage::Dense, reference_dense, Coords > & y, + template< Descriptor descr = descriptors::no_operation, class OP, typename IOType, typename InputType, typename IOView, typename InputView, typename Coords, typename IOTmp, typename InputTmp > + RC foldl( VectorView< IOType, IOView, storage::Dense, reference_dense, Coords, IOTmp > & x, + const VectorView< InputType, InputView, storage::Dense, reference_dense, Coords, InputTmp > & y, const OP & op = OP(), const typename std::enable_if< grb::is_operator< OP >::value && ! grb::is_object< IOType >::value && ! grb::is_object< InputType >::value, void >::type * = NULL ) { // static sanity checks @@ -1471,9 +1475,9 @@ namespace grb { * @see grb::operators::internal::Operator for a discussion on when in-place * and/or vectorised operations are used. */ - template< Descriptor descr = descriptors::no_operation, class Monoid, typename IOType, typename InputType, typename IOView, typename InputView, typename Coords > - RC foldl( VectorView< IOType, IOView, storage::Dense, reference_dense, Coords > & x, - const VectorView< InputType, InputView, storage::Dense, reference_dense, Coords > & y, + template< Descriptor descr = descriptors::no_operation, class Monoid, typename IOType, typename InputType, typename IOView, typename InputView, typename Coords, typename IOTmp, typename InputTmp > + RC foldl( VectorView< IOType, IOView, storage::Dense, reference_dense, Coords, IOTmp > & x, + const VectorView< InputType, InputView, storage::Dense, reference_dense, Coords, InputTmp > & y, const Monoid & monoid = Monoid(), const typename std::enable_if< grb::is_monoid< Monoid >::value && ! grb::is_object< IOType >::value && ! grb::is_object< InputType >::value, void >::type * = NULL ) { // static sanity checks @@ -1502,10 +1506,14 @@ namespace grb { * * Masked variant. */ - template< Descriptor descr = descriptors::no_operation, class OP, typename IOType, typename MaskType, typename InputType, typename IOView, typename MaskView, typename InputView, typename Coords > - RC foldl( VectorView< IOType, IOView, storage::Dense, reference_dense, Coords > & x, - const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & m, - const VectorView< InputType, InputView, storage::Dense, reference_dense, Coords > & y, + template< Descriptor descr = descriptors::no_operation, class OP, + typename IOType, typename MaskType, typename InputType, + typename IOView, typename MaskView, typename InputView, + typename Coords, + typename IOTmp, typename MaskTmp, typename InputTmp > + RC foldl( VectorView< IOType, IOView, storage::Dense, reference_dense, Coords, IOTmp > & x, + const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords, MaskTmp > & m, + const VectorView< InputType, InputView, storage::Dense, reference_dense, Coords, InputTmp > & y, const OP & op = OP(), const typename std::enable_if< grb::is_operator< OP >::value && ! grb::is_object< IOType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType >::value, void >::type * = NULL ) { @@ -1541,10 +1549,14 @@ namespace grb { * * Masked variant. */ - template< Descriptor descr = descriptors::no_operation, class Monoid, typename IOType, typename MaskType, typename InputType, typename IOView, typename MaskView, typename InputView, typename Coords > - RC foldl( VectorView< IOType, IOView, storage::Dense, reference_dense, Coords > & x, - const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & m, - const VectorView< InputType, InputView, storage::Dense, reference_dense, Coords > & y, + template< Descriptor descr = descriptors::no_operation, class Monoid, + typename IOType, typename MaskType, typename InputType, + typename IOView, typename MaskView, typename InputView, + typename Coords, + typename IOTmp, typename MaskTmp, typename InputTmp > + RC foldl( VectorView< IOType, IOView, storage::Dense, reference_dense, Coords, IOTmp > & x, + const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords, MaskTmp > & m, + const VectorView< InputType, InputView, storage::Dense, reference_dense, Coords, InputTmp > & y, const Monoid & monoid = Monoid(), const typename std::enable_if< grb::is_monoid< Monoid >::value && ! grb::is_object< IOType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType >::value, void >::type * = NULL ) { @@ -1642,9 +1654,13 @@ namespace grb { * this. * \endparblock */ - template< Descriptor descr = descriptors::no_operation, class OP, typename OutputType, typename InputType1, typename InputType2, typename OutputView, typename InputView1, typename InputView2, typename Coords > - RC eWiseApply( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, - const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords > & x, + template< Descriptor descr = descriptors::no_operation, class OP, + typename OutputType, typename InputType1, typename InputType2, + typename OutputView, typename InputView1, typename InputView2, + typename Coords, + typename OutputTmp, typename InputTmp > + RC eWiseApply( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & z, + const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords, InputTmp > & x, const InputType2 beta, const OP & op = OP(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_operator< OP >::value, @@ -1661,8 +1677,12 @@ namespace grb { * * Specialisation for \a x and \a y scalar, operator version. */ - template< Descriptor descr = descriptors::no_operation, class OP, typename OutputType, typename InputType1, typename InputType2, typename OutputView, typename InputView1, typename InputView2, typename Coords > - RC eWiseApply( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, + template< Descriptor descr = descriptors::no_operation, class OP, + typename OutputType, typename InputType1, typename InputType2, + typename OutputView, typename InputView1, typename InputView2, + typename Coords, + typename OutputTmp > + RC eWiseApply( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & z, const InputType1 alpha, const InputType2 beta, const OP & op = OP(), @@ -1682,8 +1702,12 @@ namespace grb { * * Specialisation for \a x and \a y scalar, monoid version. */ - template< Descriptor descr = descriptors::no_operation, class Monoid, typename OutputType, typename InputType1, typename InputType2, typename OutputView, typename InputView1, typename InputView2, typename Coords > - RC eWiseApply( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, + template< Descriptor descr = descriptors::no_operation, class Monoid, + typename OutputType, typename InputType1, typename InputType2, + typename OutputView, typename InputView1, typename InputView2, + typename Coords, + typename OutputTmp > + RC eWiseApply( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & z, const InputType1 alpha, const InputType2 beta, const Monoid & monoid = Monoid(), @@ -1701,10 +1725,14 @@ namespace grb { * * Specialisation for scalar \a y, masked operator version. */ - template< Descriptor descr = descriptors::no_operation, class OP, typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename OutputView, typename MaskView, typename InputView1, typename InputView2, typename Coords > - RC eWiseApply( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, - const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & mask, - const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords > & x, + template< Descriptor descr = descriptors::no_operation, class OP, + typename OutputType, typename MaskType, typename InputType1, typename InputType2, + typename OutputView, typename MaskView, typename InputView1, + typename Coords, + typename OutputTmp, typename MaskTmp, typename InputTmp1 > + RC eWiseApply( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & z, + const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords, MaskTmp > & mask, + const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords, InputTmp1 > & x, const InputType2 beta, const OP & op = OP(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && @@ -1726,10 +1754,14 @@ namespace grb { * * Monoid version. */ - template< Descriptor descr = descriptors::no_operation, class Monoid, typename OutputType, typename InputType1, typename InputType2, typename OutputView, typename InputView1, typename InputView2, typename Coords > - RC eWiseApply( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, - const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords > & x, - const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords > & y, + template< Descriptor descr = descriptors::no_operation, class Monoid, + typename OutputType, typename InputType1, typename InputType2, + typename OutputView, typename InputView1, typename InputView2, + typename Coords, + typename OutputTmp, typename InputTmp1, typename InputTmp2 > + RC eWiseApply( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & z, + const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords, InputTmp1 > & x, + const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords, InputTmp2 > & y, const Monoid & monoid = Monoid(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_monoid< Monoid >::value, void >::type * const = NULL ) { @@ -1745,10 +1777,14 @@ namespace grb { * * Specialisation for scalar \a x. Monoid version. */ - template< Descriptor descr = descriptors::no_operation, class Monoid, typename OutputType, typename InputType1, typename InputType2, typename OutputView, typename InputView1, typename InputView2, typename Coords > - RC eWiseApply( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, + template< Descriptor descr = descriptors::no_operation, class Monoid, + typename OutputType, typename InputType1, typename InputType2, + typename OutputView, typename InputView1, typename InputView2, + typename Coords, + typename OutputTmp, typename InputTmp2 > + RC eWiseApply( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & z, const InputType1 alpha, - const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords > & y, + const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords, InputTmp2 > & y, const Monoid & monoid = Monoid(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_monoid< Monoid >::value, void >::type * const = NULL ) { @@ -1764,9 +1800,13 @@ namespace grb { * * Specialisation for scalar \a y. Monoid version. */ - template< Descriptor descr = descriptors::no_operation, class Monoid, typename OutputType, typename InputType1, typename InputType2, typename OutputView, typename InputView1, typename InputView2, typename Coords > - RC eWiseApply( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, - const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords > & x, + template< Descriptor descr = descriptors::no_operation, class Monoid, + typename OutputType, typename InputType1, typename InputType2, + typename OutputView, typename InputView1, typename InputView2, + typename Coords, + typename OutputTmp, typename InputTmp1 > + RC eWiseApply( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & z, + const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords, InputTmp1 > & x, const InputType2 beta, const Monoid & monoid = Monoid(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_monoid< Monoid >::value, @@ -1783,11 +1823,15 @@ namespace grb { * * Masked monoid version. */ - template< Descriptor descr = descriptors::no_operation, class Monoid, typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename OutputView, typename MaskView, typename InputView1, typename InputView2, typename Coords > - RC eWiseApply( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, - const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & mask, - const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords > & x, - const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords > & y, + template< Descriptor descr = descriptors::no_operation, class Monoid, + typename OutputType, typename MaskType, typename InputType1, typename InputType2, + typename OutputView, typename MaskView, typename InputView1, typename InputView2, + typename Coords, + typename OutputTmp, typename MaskTmp, typename InputTmp1, typename InputTmp2 > + RC eWiseApply( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & z, + const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords, MaskTmp > & mask, + const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords, InputTmp1 > & x, + const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords, InputTmp2 > & y, const Monoid & monoid = Monoid(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_monoid< Monoid >::value, @@ -1804,11 +1848,15 @@ namespace grb { * * Specialisation for scalar \a x. Masked monoid version. */ - template< Descriptor descr = descriptors::no_operation, class Monoid, typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename OutputView, typename MaskView, typename InputView1, typename InputView2, typename Coords > - RC eWiseApply( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, - const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & mask, + template< Descriptor descr = descriptors::no_operation, class Monoid, + typename OutputType, typename MaskType, typename InputType1, typename InputType2, + typename OutputView, typename MaskView, typename InputView1, typename InputView2, + typename Coords, + typename OutputTmp, typename MaskTmp, typename InputTmp2 > + RC eWiseApply( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & z, + const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords, MaskTmp > & mask, const InputType1 alpha, - const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords > & y, + const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords, InputTmp2 > & y, const Monoid & monoid = Monoid(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_monoid< Monoid >::value, @@ -1825,10 +1873,14 @@ namespace grb { * * Specialisation for scalar \a y. Masked monoid version. */ - template< Descriptor descr = descriptors::no_operation, class Monoid, typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename OutputView, typename MaskView, typename InputView1, typename InputView2, typename Coords > - RC eWiseApply( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, - const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & mask, - const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords > & x, + template< Descriptor descr = descriptors::no_operation, class Monoid, + typename OutputType, typename MaskType, typename InputType1, typename InputType2, + typename OutputView, typename MaskView, typename InputView1, + typename Coords, + typename OutputTmp, typename MaskTmp, typename InputTmp1, typename InputTmp2 > + RC eWiseApply( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & z, + const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords, MaskTmp > & mask, + const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords, InputTmp1 > & x, const InputType2 beta, const Monoid & monoid = Monoid(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && @@ -1906,10 +1958,14 @@ namespace grb { * this. * \endparblock */ - template< Descriptor descr = descriptors::no_operation, class OP, typename OutputType, typename InputType1, typename InputType2, typename OutputView, typename InputView1, typename InputView2, typename Coords > - RC eWiseApply( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, + template< Descriptor descr = descriptors::no_operation, class OP, + typename OutputType, typename InputType1, typename InputType2, + typename OutputView, typename InputView1, typename InputView2, + typename Coords, + typename OutputTmp, typename InputTmp2 > + RC eWiseApply( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & z, const InputType1 alpha, - const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords > & y, + const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords, InputTmp2 > & y, const OP & op = OP(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_operator< OP >::value, void >::type * const = NULL ) { @@ -1925,11 +1981,15 @@ namespace grb { * * Specialisation for scalar \a x. Masked operator version. */ - template< Descriptor descr = descriptors::no_operation, class OP, typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename OutputView, typename MaskView, typename InputView1, typename InputView2, typename Coords > - RC eWiseApply( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, - const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & mask, + template< Descriptor descr = descriptors::no_operation, class OP, + typename OutputType, typename MaskType, typename InputType1, typename InputType2, + typename OutputView, typename MaskView, typename InputView1, typename InputView2, + typename Coords, + typename OutputTmp, typename MaskTmp, typename InputTmp2 > + RC eWiseApply( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & z, + const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords, MaskTmp > & mask, const InputType1 alpha, - const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords > & y, + const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords, InputTmp2 > & y, const OP & op = OP(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_operator< OP >::value, @@ -2009,10 +2069,14 @@ namespace grb { * used allow for this. * \endparblock */ - template< Descriptor descr = descriptors::no_operation, class OP, typename OutputType, typename InputType1, typename InputType2, typename OutputView, typename InputView1, typename InputView2, typename Coords > - RC eWiseApply( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, - const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords > & x, - const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords > & y, + template< Descriptor descr = descriptors::no_operation, class OP, + typename OutputType, typename InputType1, typename InputType2, + typename OutputView, typename InputView1, typename InputView2, + typename Coords, + typename OutputTmp, typename InputTmp1, typename InputTmp2 > + RC eWiseApply( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & z, + const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords, InputTmp1 > & x, + const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords, InputTmp2 > & y, const OP & op = OP(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_operator< OP >::value, void >::type * const = NULL ) { @@ -2028,11 +2092,15 @@ namespace grb { * * Masked operator version. */ - template< Descriptor descr = descriptors::no_operation, class OP, typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename OutputView, typename MaskView, typename InputView1, typename InputView2, typename Coords > - RC eWiseApply( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, - const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & mask, - const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords > & x, - const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords > & y, + template< Descriptor descr = descriptors::no_operation, class OP, + typename OutputType, typename MaskType, typename InputType1, typename InputType2, + typename OutputView, typename MaskView, typename InputView1, typename InputView2, + typename Coords, + typename OutputTmp, typename MaskTmp, typename InputTmp1, typename InputTmp2 > + RC eWiseApply( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & z, + const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords, MaskTmp > & mask, + const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords, InputTmp1 > & x, + const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords, InputTmp2 > & y, const OP & op = OP(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_operator< OP >::value, @@ -2116,10 +2184,14 @@ namespace grb { * * @see This is a specialised form of eWiseMulAdd. */ - template< Descriptor descr = descriptors::no_operation, class Ring, typename OutputType, typename InputType1, typename InputType2, typename OutputView, typename InputView1, typename InputView2, typename Coords > - RC eWiseAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, - const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords > & x, - const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords > & y, + template< Descriptor descr = descriptors::no_operation, class Ring, + typename OutputType, typename InputType1, typename InputType2, + typename OutputView, typename InputView1, typename InputView2, + typename Coords, + typename OutputTmp, typename InputTmp1, typename InputTmp2 > + RC eWiseAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & z, + const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords, InputTmp1 > & x, + const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords, InputTmp2 > & y, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_semiring< Ring >::value, void >::type * const = NULL ) { @@ -2145,10 +2217,14 @@ namespace grb { * * Specialisation for scalar \a x. */ - template< Descriptor descr = descriptors::no_operation, class Ring, typename InputType1, typename InputType2, typename OutputType, typename InputView2, typename OutputView, typename Coords > - RC eWiseAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, + template< Descriptor descr = descriptors::no_operation, class Ring, + typename InputType1, typename InputType2, typename OutputType, + typename InputView2, typename OutputView, + typename Coords, + typename OutputTmp, typename InputTmp2 > + RC eWiseAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & z, const InputType1 alpha, - const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords > & y, + const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords, InputTmp2 > & y, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_semiring< Ring >::value, void >::type * const = NULL ) { @@ -2174,9 +2250,13 @@ namespace grb { * * Specialisation for scalar \a y. */ - template< Descriptor descr = descriptors::no_operation, class Ring, typename InputType1, typename InputType2, typename OutputType, typename InputView1, typename OutputView,typename Coords > - RC eWiseAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, - const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords > & x, + template< Descriptor descr = descriptors::no_operation, class Ring, + typename InputType1, typename InputType2, typename OutputType, + typename InputView1, typename OutputView, + typename Coords, + typename OutputTmp, typename InputTmp1 > + RC eWiseAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & z, + const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords, InputTmp1 > & x, const InputType2 beta, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_semiring< Ring >::value, @@ -2203,8 +2283,12 @@ namespace grb { * * Specialisation for scalar \a x and \a y. */ - template< Descriptor descr = descriptors::no_operation, class Ring, typename InputType1, typename InputType2, typename OutputType, typename OutputView, typename Coords > - RC eWiseAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, + template< Descriptor descr = descriptors::no_operation, class Ring, + typename InputType1, typename InputType2, typename OutputType, + typename OutputView, + typename Coords, + typename OutputTmp > + RC eWiseAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & z, const InputType1 alpha, const InputType2 beta, const Ring & ring = Ring(), @@ -2234,11 +2318,15 @@ namespace grb { * * Masked version. */ - template< Descriptor descr = descriptors::no_operation, class Ring, typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename OutputView, typename MaskView, typename InputView1, typename InputView2, typename Coords > - RC eWiseAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, - const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & m, - const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords > & x, - const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords > & y, + template< Descriptor descr = descriptors::no_operation, class Ring, + typename OutputType, typename MaskType, typename InputType1, typename InputType2, + typename OutputView, typename MaskView, typename InputView1, typename InputView2, + typename Coords, + typename OutputTmp, typename MaskTmp, typename InputTmp1, typename InputTmp2 > + RC eWiseAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & z, + const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords, MaskTmp > & m, + const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords, InputTmp1 > & x, + const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords, InputTmp2 > & y, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_semiring< Ring >::value, @@ -2267,11 +2355,15 @@ namespace grb { * * Specialisation for scalar \a x, masked version */ - template< Descriptor descr = descriptors::no_operation, class Ring, typename InputType1, typename InputType2, typename OutputType, typename MaskType, typename InputView2, typename OutputView, typename MaskView, typename Coords > - RC eWiseAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, - const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & m, + template< Descriptor descr = descriptors::no_operation, class Ring, + typename InputType1, typename InputType2, typename OutputType, typename MaskType, + typename InputView2, typename OutputView, typename MaskView, + typename Coords, + typename OutputTmp, typename MaskTmp, typename InputTmp2 > + RC eWiseAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & z, + const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords, MaskTmp > & m, const InputType1 alpha, - const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords > & y, + const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords, InputTmp2 > & y, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_semiring< Ring >::value, @@ -2300,10 +2392,14 @@ namespace grb { * * Specialisation for scalar \a y, masked version. */ - template< Descriptor descr = descriptors::no_operation, class Ring, typename InputType1, typename InputType2, typename OutputType, typename MaskType, typename InputView1, typename OutputView, typename MaskView, typename Coords > - RC eWiseAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, - const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & m, - const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords > & x, + template< Descriptor descr = descriptors::no_operation, class Ring, + typename InputType1, typename InputType2, typename OutputType, typename MaskType, + typename InputView1, typename OutputView, typename MaskView, + typename Coords, + typename OutputTmp, typename MaskTmp, typename InputTmp1 > + RC eWiseAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & z, + const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords, MaskTmp > & m, + const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords, InputTmp1 > & x, const InputType2 beta, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && @@ -2333,9 +2429,13 @@ namespace grb { * * Specialisation for scalar \a x and \a y, masked version. */ - template< Descriptor descr = descriptors::no_operation, class Ring, typename InputType1, typename InputType2, typename OutputType, typename MaskType, typename OutputView, typename Coords > - RC eWiseAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, - const VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & m, + template< Descriptor descr = descriptors::no_operation, class Ring, + typename InputType1, typename InputType2, typename OutputType, typename MaskType, + typename OutputView, + typename Coords, + typename OutputTmp, typename MaskTmp > + RC eWiseAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & z, + const VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & m, /** \internal \todo Should this be MaskType, MaskView (copied as is from reference/blas1.hpp) */ const InputType1 alpha, const InputType2 beta, const Ring & ring = Ring(), @@ -2367,11 +2467,15 @@ namespace grb { * * Specialisation for when \a a is a scalar. */ - template< Descriptor descr = descriptors::no_operation, class Ring, typename InputType1, typename InputType2, typename InputType3, typename OutputType, typename InputView2, typename InputView3, typename OutputView, typename Coords > - RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & _z, + template< Descriptor descr = descriptors::no_operation, class Ring, + typename InputType1, typename InputType2, typename InputType3, typename OutputType, + typename InputView2, typename InputView3, typename OutputView, + typename Coords, + typename OutputTmp, typename InputTmp2, typename InputTmp3 > + RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & _z, const InputType1 alpha, - const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords > & _x, - const VectorView< InputType3, InputView3, storage::Dense, reference_dense, Coords > & _y, + const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords, InputTmp2 > & _x, + const VectorView< InputType3, InputView3, storage::Dense, reference_dense, Coords, InputTmp3 > & _y, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && grb::is_semiring< Ring >::value, @@ -2399,11 +2503,15 @@ namespace grb { * * Specialisation for when \a x is a scalar. */ - template< Descriptor descr = descriptors::no_operation, class Ring, typename InputType1, typename InputType2, typename InputType3, typename OutputType, typename InputView1, typename InputView3, typename OutputView, typename Coords > - RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & _z, - const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords > & _a, + template< Descriptor descr = descriptors::no_operation, class Ring, + typename InputType1, typename InputType2, typename InputType3, typename OutputType, + typename InputView1, typename InputView3, typename OutputView, + typename Coords, + typename OutputTmp, typename InputTmp1, typename InputTmp3 > + RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & _z, + const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords, InputTmp1 > & _a, const InputType2 chi, - const VectorView< InputType3, InputView3, storage::Dense, reference_dense, Coords > & _y, + const VectorView< InputType3, InputView3, storage::Dense, reference_dense, Coords, InputTmp3 > & _y, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && grb::is_semiring< Ring >::value, @@ -2430,10 +2538,14 @@ namespace grb { * * Specialisation for when \a y is a scalar. */ - template< Descriptor descr = descriptors::no_operation, class Ring, typename InputType1, typename InputType2, typename InputType3, typename OutputType, typename InputView1, typename InputView2, typename OutputView, typename Coords > - RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & _z, - const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords > & _a, - const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords > & _x, + template< Descriptor descr = descriptors::no_operation, class Ring, + typename InputType1, typename InputType2, typename InputType3, typename OutputType, + typename InputView1, typename InputView2, typename OutputView, + typename Coords, + typename OutputTmp, typename InputTmp1, typename InputTmp2 > + RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & _z, + const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords, InputTmp1 > & _a, + const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords, InputTmp2 > & _x, const InputType3 gamma, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && @@ -2461,9 +2573,13 @@ namespace grb { * * Specialisation for when \a x and \a y are scalar. */ - template< Descriptor descr = descriptors::no_operation, class Ring, typename InputType1, typename InputType2, typename InputType3, typename OutputType, typename InputView1, typename OutputView, typename Coords > - RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & _z, - const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords > & _a, + template< Descriptor descr = descriptors::no_operation, class Ring, + typename InputType1, typename InputType2, typename InputType3, typename OutputType, + typename InputView1, typename OutputView, + typename Coords, + typename OutputTmp, typename InputTmp1 > + RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & _z, + const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords, InputTmp1 > & _a, const InputType2 beta, const InputType3 gamma, const Ring & ring = Ring(), @@ -2492,10 +2608,14 @@ namespace grb { * * Specialisation for when \a a and \a y are scalar. */ - template< Descriptor descr = descriptors::no_operation, class Ring, typename InputType1, typename InputType2, typename InputType3, typename OutputType, typename InputView2, typename OutputView, typename Coords > - RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & _z, + template< Descriptor descr = descriptors::no_operation, class Ring, + typename InputType1, typename InputType2, typename InputType3, typename OutputType, + typename InputView2, typename OutputView, + typename Coords, + typename OutputTmp, typename InputTmp2 > + RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & _z, const InputType1 alpha, - const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords > & _x, + const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords, InputTmp2 > & _x, const InputType3 gamma, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && @@ -2525,11 +2645,15 @@ namespace grb { * * \internal Dispatches to eWiseAdd. */ - template< Descriptor descr = descriptors::no_operation, class Ring, typename OutputType, typename InputType1, typename InputType2, typename InputType3, typename InputView3, typename OutputView, typename Coords > - RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, + template< Descriptor descr = descriptors::no_operation, class Ring, + typename OutputType, typename InputType1, typename InputType2, typename InputType3, + typename InputView3, typename OutputView, + typename Coords, + typename OutputTmp, typename InputTmp3 > + RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & z, const InputType1 alpha, const InputType2 beta, - const VectorView< InputType3, InputView3, storage::Dense, reference_dense, Coords > & y, + const VectorView< InputType3, InputView3, storage::Dense, reference_dense, Coords, InputTmp3 > & y, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && grb::is_semiring< Ring >::value, @@ -2562,8 +2686,12 @@ namespace grb { * * \internal Dispatches to set. */ - template< Descriptor descr = descriptors::no_operation, class Ring, typename OutputType, typename InputType1, typename InputType2, typename InputType3, typename OutputView, typename Coords > - RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, + template< Descriptor descr = descriptors::no_operation, class Ring, + typename OutputType, typename InputType1, typename InputType2, typename InputType3, + typename OutputView, + typename Coords, + typename OutputTmp > + RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & z, const InputType1 alpha, const InputType2 beta, const InputType3 gamma, @@ -2676,11 +2804,15 @@ namespace grb { * and the operators used allow for this. * \endparblock */ - template< Descriptor descr = descriptors::no_operation, class Ring, typename InputType1, typename InputType2, typename InputType3, typename OutputType, typename InputView1, typename InputView2, typename InputView3, typename OutputView, typename Coords > - RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & _z, - const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords > & _a, - const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords > & _x, - const VectorView< InputType3, InputView3, storage::Dense, reference_dense, Coords > & _y, + template< Descriptor descr = descriptors::no_operation, class Ring, + typename InputType1, typename InputType2, typename InputType3, typename OutputType, + typename InputView1, typename InputView2, typename InputView3, typename OutputView, + typename Coords, + typename OutputTmp, typename InputTmp1, typename InputTmp2, typename InputTmp3 > + RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & _z, + const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords, InputTmp1 > & _a, + const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords, InputTmp2 > & _x, + const VectorView< InputType3, InputView3, storage::Dense, reference_dense, Coords, InputTmp3 > & _y, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && grb::is_semiring< Ring >::value, @@ -2772,10 +2904,14 @@ namespace grb { * * @see This is a specialised form of eWiseMulAdd. */ - template< Descriptor descr = descriptors::no_operation, class Ring, typename InputType1, typename InputType2, typename OutputType, typename InputView1, typename InputView2, typename OutputView, typename Coords > - RC eWiseMul( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, - const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords > & x, - const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords > & y, + template< Descriptor descr = descriptors::no_operation, class Ring, + typename InputType1, typename InputType2, typename OutputType, + typename InputView1, typename InputView2, typename OutputView, + typename Coords, + typename OutputTmp, typename InputTmp1, typename InputTmp2 > + RC eWiseMul( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & z, + const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords, InputTmp1 > & x, + const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords, InputTmp2 > & y, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_semiring< Ring >::value, void >::type * const = NULL ) { @@ -2800,10 +2936,14 @@ namespace grb { * * Specialisation for scalar \a x. */ - template< Descriptor descr = descriptors::no_operation, class Ring, typename InputType1, typename InputType2, typename OutputType, typename InputView2, typename OutputView, typename Coords > - RC eWiseMul( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, + template< Descriptor descr = descriptors::no_operation, class Ring, + typename InputType1, typename InputType2, typename OutputType, + typename InputView2, typename OutputView, + typename Coords, + typename OutputTmp, typename InputTmp2 > + RC eWiseMul( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & z, const InputType1 alpha, - const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords > & y, + const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords, InputTmp2 > & y, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_semiring< Ring >::value, void >::type * const = NULL ) { @@ -2828,9 +2968,13 @@ namespace grb { * * Specialisation for scalar \a y. */ - template< Descriptor descr = descriptors::no_operation, class Ring, typename InputType1, typename InputType2, typename OutputType, typename InputView1, typename OutputView, typename Coords > - RC eWiseMul( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, - const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords > & x, + template< Descriptor descr = descriptors::no_operation, class Ring, + typename InputType1, typename InputType2, typename OutputType, + typename InputView1, typename OutputView, + typename Coords, + typename OutputTmp, typename InputTmp2 > + RC eWiseMul( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & z, + const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords, InputTmp2 > & x, const InputType2 beta, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_semiring< Ring >::value, @@ -2856,12 +3000,16 @@ namespace grb { * * Specialisation for when \a a is a scalar, masked version. */ - template< Descriptor descr = descriptors::no_operation, class Ring, typename InputType1, typename InputType2, typename InputType3, typename OutputType, typename MaskType, typename InputView2, typename InputView3, typename OutputView, typename MaskView, typename Coords > - RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & _z, - const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & _m, + template< Descriptor descr = descriptors::no_operation, class Ring, + typename InputType1, typename InputType2, typename InputType3, typename OutputType, typename MaskType, + typename InputView2, typename InputView3, typename OutputView, typename MaskView, + typename Coords, + typename OutputTmp, typename MaskTmp, typename InputTmp2, typename InputTmp3 > + RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & _z, + const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords, MaskTmp > & _m, const InputType1 alpha, - const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords > & _x, - const VectorView< InputType3, InputView3, storage::Dense, reference_dense, Coords > & _y, + const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords, InputTmp2 > & _x, + const VectorView< InputType3, InputView3, storage::Dense, reference_dense, Coords, InputTmp3 > & _y, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && grb::is_semiring< Ring >::value && ! grb::is_object< MaskType >::value, @@ -2890,12 +3038,16 @@ namespace grb { * * Specialisation for when \a x is a scalar, masked version. */ - template< Descriptor descr = descriptors::no_operation, class Ring, typename InputType1, typename InputType2, typename InputType3, typename OutputType, typename MaskType, typename InputView1, typename InputView3, typename OutputView, typename MaskView, typename Coords > - RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & _z, - const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & _m, - const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords > & _a, + template< Descriptor descr = descriptors::no_operation, class Ring, + typename InputType1, typename InputType2, typename InputType3, typename OutputType, typename MaskType, + typename InputView1, typename InputView3, typename OutputView, typename MaskView, + typename Coords, + typename OutputTmp, typename MaskTmp, typename InputTmp1, typename InputTmp3 > + RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & _z, + const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords, MaskTmp > & _m, + const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords, InputTmp1 > & _a, const InputType2 chi, - const VectorView< InputType3, InputView3, storage::Dense, reference_dense, Coords > & _y, + const VectorView< InputType3, InputView3, storage::Dense, reference_dense, Coords, InputTmp3 > & _y, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && grb::is_semiring< Ring >::value && ! grb::is_object< MaskType >::value, @@ -2923,11 +3075,15 @@ namespace grb { * * Specialisation for when \a y is a scalar, masked version. */ - template< Descriptor descr = descriptors::no_operation, class Ring, typename InputType1, typename InputType2, typename InputType3, typename OutputType, typename MaskType, typename InputView1, typename InputView2, typename OutputView, typename MaskView, typename Coords > - RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & _z, - const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & _m, - const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords > & _a, - const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords > & _x, + template< Descriptor descr = descriptors::no_operation, class Ring, + typename InputType1, typename InputType2, typename InputType3, typename OutputType, typename MaskType, + typename InputView1, typename InputView2, typename OutputView, typename MaskView, + typename Coords, + typename OutputTmp, typename MaskTmp, typename InputTmp1, typename InputTmp2 > + RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & _z, + const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords, MaskTmp > & _m, + const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords, InputTmp1 > & _a, + const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords, InputTmp2 > & _x, const InputType3 gamma, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && @@ -2956,11 +3112,14 @@ namespace grb { * * Specialisation for when \a x and \a y are scalar, masked version. */ - template< Descriptor descr = descriptors::no_operation, class Ring, typename InputType1, typename InputType2, typename InputType3, typename OutputType, typename MaskType, - typename InputView1, typename OutputView, typename MaskView, typename Coords > - RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & _z, - const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & _m, - const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords > & _a, + template< Descriptor descr = descriptors::no_operation, class Ring, + typename InputType1, typename InputType2, typename InputType3, typename OutputType, typename MaskType, + typename InputView1, typename OutputView, typename MaskView, + typename Coords, + typename OutputTmp, typename MaskTmp, typename InputTmp1 > + RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & _z, + const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords, MaskTmp > & _m, + const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords, InputTmp1 > & _a, const InputType2 beta, const InputType3 gamma, const Ring & ring = Ring(), @@ -2990,12 +3149,15 @@ namespace grb { * * Specialisation for when \a a and \a y are scalar, masked version. */ - template< Descriptor descr = descriptors::no_operation, class Ring, typename InputType1, typename InputType2, typename InputType3, typename OutputType, typename MaskType, - typename InputView2, typename OutputView, typename MaskView, typename Coords > - RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & _z, - const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & _m, + template< Descriptor descr = descriptors::no_operation, class Ring, + typename InputType1, typename InputType2, typename InputType3, typename OutputType, typename MaskType, + typename InputView2, typename OutputView, typename MaskView, + typename Coords, + typename OutputTmp, typename MaskTmp, typename InputTmp2 > + RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & _z, + const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords, MaskTmp > & _m, const InputType1 alpha, - const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords > & _x, + const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords, InputTmp2 > & _x, const InputType3 gamma, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && @@ -3024,13 +3186,16 @@ namespace grb { * * Masked version. */ - template< Descriptor descr = descriptors::no_operation, class Ring, typename InputType1, typename InputType2, typename InputType3, typename OutputType, typename MaskType, - typename InputView1, typename InputView2, typename InputView3, typename OutputView, typename MaskView, typename Coords > - RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & _z, - const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & _m, - const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords > & _a, - const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords > & _x, - const VectorView< InputType3, InputView3, storage::Dense, reference_dense, Coords > & _y, + template< Descriptor descr = descriptors::no_operation, class Ring, + typename InputType1, typename InputType2, typename InputType3, typename OutputType, typename MaskType, + typename InputView1, typename InputView2, typename InputView3, typename OutputView, typename MaskView, + typename Coords, + typename OutputTmp, typename MaskTmp, typename InputTmp1, typename InputTmp2, typename InputTmp3 > + RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & _z, + const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords, MaskTmp > & _m, + const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords, InputTmp1 > & _a, + const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords, InputTmp2 > & _x, + const VectorView< InputType3, InputView3, storage::Dense, reference_dense, Coords, InputTmp3 > & _y, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && grb::is_semiring< Ring >::value && ! grb::is_object< MaskType >::value, @@ -3063,12 +3228,15 @@ namespace grb { * * \internal Dispatches to eWiseMulAdd with zero additive scalar. */ - template< Descriptor descr = descriptors::no_operation, class Ring, typename InputType1, typename InputType2, typename OutputType, typename MaskType, - typename InputView1, typename InputView2, typename InputView3, typename OutputView, typename MaskView, typename Coords > - RC eWiseMul( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, - const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & m, - const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords > & x, - const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords > & y, + template< Descriptor descr = descriptors::no_operation, class Ring, + typename InputType1, typename InputType2, typename OutputType, typename MaskType, + typename InputView1, typename InputView2, typename OutputView, typename MaskView, + typename Coords, + typename OutputTmp, typename MaskTmp, typename InputTmp1, typename InputTmp2 > + RC eWiseMul( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & z, + const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords, MaskTmp > & m, + const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords, InputTmp1 > & x, + const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords, InputTmp2 > & y, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< MaskType >::value && grb::is_semiring< Ring >::value, @@ -3097,12 +3265,15 @@ namespace grb { * * \internal Dispatches to eWiseMulAdd with zero additive scalar. */ - template< Descriptor descr = descriptors::no_operation, class Ring, typename InputType1, typename InputType2, typename OutputType, typename MaskType, - typename InputView2, typename InputView3, typename OutputView, typename MaskView, typename Coords > - RC eWiseMul( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, - const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & m, + template< Descriptor descr = descriptors::no_operation, class Ring, + typename InputType1, typename InputType2, typename OutputType, typename MaskType, + typename InputView2, typename InputView3, typename OutputView, typename MaskView, + typename Coords, + typename OutputTmp, typename MaskTmp, typename InputTmp2 > + RC eWiseMul( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & z, + const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords, MaskTmp > & m, const InputType1 alpha, - const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords > & y, + const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords, InputTmp2 > & y, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< MaskType >::value && grb::is_semiring< Ring >::value, @@ -3131,11 +3302,14 @@ namespace grb { * * \internal Dispatches to eWiseMulAdd with zero additive scalar. */ - template< Descriptor descr = descriptors::no_operation, class Ring, typename InputType1, typename InputType2, typename OutputType, typename MaskType, - typename InputView1, typename InputView3, typename OutputView, typename MaskView, typename Coords > - RC eWiseMul( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, - const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & m, - const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords > & x, + template< Descriptor descr = descriptors::no_operation, class Ring, + typename InputType1, typename InputType2, typename OutputType, typename MaskType, + typename InputView1, typename InputView3, typename OutputView, typename MaskView, + typename Coords, + typename OutputTmp, typename MaskTmp, typename InputTmp1 > + RC eWiseMul( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & z, + const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords, MaskTmp > & m, + const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords, InputTmp1 > & x, const InputType2 beta, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< MaskType >::value && @@ -3165,13 +3339,16 @@ namespace grb { * * \internal Dispatches to masked eWiseAdd. */ - template< Descriptor descr = descriptors::no_operation, class Ring, typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename InputType3, - typename OutputView, typename MaskView, typename InputView3, typename Coords > - RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, - const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & m, + template< Descriptor descr = descriptors::no_operation, class Ring, + typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename InputType3, + typename OutputView, typename MaskView, typename InputView3, + typename Coords, + typename OutputTmp, typename MaskTmp, typename InputTmp3 > + RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & z, + const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords, MaskTmp > & m, const InputType1 alpha, const InputType2 beta, - const VectorView< InputType3, InputView3, storage::Dense, reference_dense, Coords > & y, + const VectorView< InputType3, InputView3, storage::Dense, reference_dense, Coords, InputTmp3 > & y, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && grb::is_semiring< Ring >::value && ! grb::is_object< MaskType >::value, @@ -3205,10 +3382,13 @@ namespace grb { * * \internal Dispatches to masked set. */ - template< Descriptor descr = descriptors::no_operation, class Ring, typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename InputType3, - typename OutputView, typename MaskView, typename Coords > - RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, - const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & m, + template< Descriptor descr = descriptors::no_operation, class Ring, + typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename InputType3, + typename OutputView, typename MaskView, + typename Coords, + typename OutputTmp, typename MaskTmp > + RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & z, + const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords, MaskTmp > & m, const InputType1 alpha, const InputType2 beta, const InputType3 gamma, @@ -3251,11 +3431,12 @@ namespace grb { Descriptor descr = descriptors::no_operation, class AddMonoid, class AnyOp, typename OutputType, typename InputType1, typename InputType2, typename OutputView, typename InputView1, typename InputView2, - typename Coords + typename Coords, + typename InputTmp1, typename InputTmp2 > RC dot_generic( OutputType &z, - const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords > &x, - const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords > &y, + const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords, InputTmp1 > &x, + const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords, InputTmp2 > &y, const AddMonoid &addMonoid = AddMonoid(), const AnyOp &anyOp = AnyOp() ) { @@ -3343,12 +3524,14 @@ namespace grb { template< Descriptor descr = descriptors::no_operation, class AddMonoid, class AnyOp, - typename OutputType, typename InputType1, typename InputType2, typename OutputView, typename InputView1, typename InputView2, - typename Coords + typename OutputType, typename InputType1, typename InputType2, + typename OutputView, typename InputView1, typename InputView2, + typename Coords, + typename InputTmp1, typename InputTmp2 > RC dot( OutputType &z, - const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords > &x, - const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords > &y, + const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords, InputTmp1 > &x, + const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords, InputTmp2 > &y, const AddMonoid &addMonoid = AddMonoid(), const AnyOp &anyOp = AnyOp(), const typename std::enable_if< !grb::is_object< OutputType >::value && @@ -3383,8 +3566,8 @@ namespace grb { } /** No implementation notes. */ - template< typename Func, typename DataType, typename DataView, typename Coords > - RC eWiseMap( const Func f, VectorView< DataType, DataView, storage::Dense, reference_dense, Coords > & x ) { + template< typename Func, typename DataType, typename DataView, typename Coords, typename DataTmp > + RC eWiseMap( const Func f, VectorView< DataType, DataView, storage::Dense, reference_dense, Coords, DataTmp > & x ) { throw std::runtime_error( "Needs an implementation." ); return SUCCESS; } @@ -3399,8 +3582,16 @@ namespace grb { * @see VectorView::operator[]() * @see VectorView::lambda_reference */ - template< typename Func, typename DataType1, typename DataType2, typename DataView1, typename DataView2, typename Coords, typename... Args > - RC eWiseLambda( const Func f, const VectorView< DataType1, DataView1, storage::Dense, reference_dense, Coords > & x, const VectorView< DataType2, DataView2, storage::Dense, reference_dense, Coords > & y, Args const &... args ) { + template< typename Func, + typename DataType1, typename DataType2, + typename DataView1, typename DataView2, + typename Coords, + typename InputTmp1, typename InputTmp2, + typename... Args > + RC eWiseLambda( const Func f, + const VectorView< DataType1, DataView1, storage::Dense, reference_dense, Coords, InputTmp1 > & x, + const VectorView< DataType2, DataView2, storage::Dense, reference_dense, Coords, InputTmp2 > & y, + Args const &... args ) { // catch mismatch if( size( x ) != size( y ) ) { return MISMATCH; @@ -3416,8 +3607,8 @@ namespace grb { * @see VectorView::operator[]() * @see VectorView::lambda_reference */ - template< typename Func, typename DataType, typename DataView, typename Coords > - RC eWiseLambda( const Func f, const VectorView< DataType, DataView, storage::Dense, reference_dense, Coords > & x ) { + template< typename Func, typename DataType, typename DataView, typename Coords, typename DataTmp > + RC eWiseLambda( const Func f, const VectorView< DataType, DataView, storage::Dense, reference_dense, Coords, DataTmp > & x ) { #ifdef _DEBUG std::cout << "Info: entering eWiseLambda function on vectors.\n"; #endif @@ -3506,10 +3697,14 @@ namespace grb { * * @see grb::foldl provides similar functionality. */ - template< Descriptor descr = descriptors::no_operation, class Monoid, typename InputType, typename IOType, typename MaskType, typename InputView, typename MaskView, typename Coords > + template< Descriptor descr = descriptors::no_operation, class Monoid, + typename InputType, typename IOType, typename MaskType, + typename InputView, typename MaskView, + typename Coords, + typename IOTmp, typename MaskTmp > RC foldl( IOType & x, - const VectorView< InputType, InputView, storage::Dense, reference_dense, Coords > & y, - const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & mask, + const VectorView< InputType, InputView, storage::Dense, reference_dense, Coords, IOTmp > & y, + const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords, MaskTmp > & mask, const Monoid & monoid = Monoid(), const typename std::enable_if< ! grb::is_object< IOType >::value && ! grb::is_object< InputType >::value && ! grb::is_object< MaskType >::value && grb::is_monoid< Monoid >::value, void >::type * const = NULL ) { @@ -3616,11 +3811,12 @@ namespace grb { class AddMonoid, class AnyOp, typename OutputType, typename InputType1, typename InputType2, typename InputView1, typename InputView2, - typename InputCoords1, typename InputCoords2 + typename InputCoords1, typename InputCoords2, + typename InputTmp1, typename InputTmp2 > RC dot( OutputType &z, - const VectorView< InputType1, InputView1, storage::Dense, reference_dense, InputCoords1 > &x, - const VectorView< InputType2, InputView2, storage::Dense, reference_dense, InputCoords2 > &y, + const VectorView< InputType1, InputView1, storage::Dense, reference_dense, InputCoords1, InputTmp1 > &x, + const VectorView< InputType2, InputView2, storage::Dense, reference_dense, InputCoords2, InputTmp2 > &y, const AddMonoid &addMonoid = AddMonoid(), const AnyOp &anyOp = AnyOp(), const typename std::enable_if< !grb::is_object< OutputType >::value && @@ -3713,11 +3909,12 @@ namespace grb { typename IOType, typename InputType1, typename InputType2, typename InputView1, typename InputView2, typename InputStorage1, typename InputStorage2, - Backend backend, typename Coords1, typename Coords2 + Backend backend, typename Coords1, typename Coords2, + typename InputTmp1, typename InputTmp2 > RC dot( IOType &x, - const VectorView< InputType1, InputView1, InputStorage1, backend, Coords1 > &left, - const VectorView< InputType2, InputView2, InputStorage2, backend, Coords2 > &right, + const VectorView< InputType1, InputView1, InputStorage1, backend, Coords1, InputTmp1 > &left, + const VectorView< InputType2, InputView2, InputStorage2, backend, Coords2, InputTmp2 > &right, const Ring &ring = Ring(), const typename std::enable_if< !grb::is_object< InputType1 >::value && @@ -3762,10 +3959,11 @@ namespace grb { typename InputType, typename OutputType, typename InputView, typename InputStorage, - Backend backend, typename Coords + Backend backend, typename Coords, + typename InputTmp > RC norm2( OutputType &x, - const VectorView< InputType, InputView, InputStorage, backend, Coords > &y, + const VectorView< InputType, InputView, InputStorage, backend, Coords, InputTmp > &y, const Ring &ring = Ring(), const typename std::enable_if< std::is_floating_point< OutputType >::value, diff --git a/include/graphblas/denseref/blas2.hpp b/include/graphblas/denseref/blas2.hpp index 2d687264f..e3c58bf9e 100644 --- a/include/graphblas/denseref/blas2.hpp +++ b/include/graphblas/denseref/blas2.hpp @@ -52,8 +52,8 @@ namespace grb { * bytes of memory. * \endparblock */ - template< typename InputType, typename InputStructure, typename InputStorage, typename InputView > - size_t nrows( const StructuredMatrix< InputType, InputStructure, InputStorage, InputView, reference_dense > & A ) noexcept { + template< typename InputType, typename InputStructure, typename InputStorage, typename InputView, typename InputTmp > + size_t nrows( const StructuredMatrix< InputType, InputStructure, InputStorage, InputView, reference_dense, InputTmp > & A ) noexcept { return A.m; } @@ -73,8 +73,8 @@ namespace grb { * bytes of memory. * \endparblock */ - template< typename InputType, typename InputStructure, typename InputStorage, typename InputView > - size_t ncols( const StructuredMatrix< InputType, InputStructure, InputStorage, InputView, reference_dense > & A ) noexcept { + template< typename InputType, typename InputStructure, typename InputStorage, typename InputView, typename InputTmp > + size_t ncols( const StructuredMatrix< InputType, InputStructure, InputStorage, InputView, reference_dense, InputTmp > & A ) noexcept { return A.n; } @@ -94,8 +94,8 @@ namespace grb { * bytes of memory. * \endparblock */ - template< typename InputType > - size_t nnz( const StructuredMatrix< InputType, InputStructure, InputStorage, InputView, reference_dense > & A ) noexcept { + template< typename InputType, typename InputStructure, typename InputStorage, typename InputView, typename InputTmp > + size_t nnz( const StructuredMatrix< InputType, InputStructure, InputStorage, InputView, reference_dense, InputTmp > & A ) noexcept { return A.nz; } @@ -126,8 +126,8 @@ namespace grb { * \warning This is an expensive function. Use sparingly and only when * absolutely necessary */ - template< typename InputType > - RC resize( StructuredMatrix< InputType, InputStructure, InputStorage, InputView, reference_dense > & A, const size_t new_nz ) noexcept { + template< typename InputType, typename InputStructure, typename InputStorage, typename InputView, typename InputTmp > + RC resize( StructuredMatrix< InputType, InputStructure, InputStorage, InputView, reference_dense, InputTmp > & A, const size_t new_nz ) noexcept { // delegate return A.resize( new_nz ); } @@ -139,11 +139,12 @@ namespace grb { typename InputType1, typename InputType1, typename InputView1, typename InputStorage1, typename InputType2, typename InputStructure2, typename InputStorage2, typename InputView2, typename InputType3, typename InputType3, typename InputView3, typename InputStorage3, - typename Coords > - RC vxm( VectorView< IOType, IOView, IOStorage, reference_dense, Coords > & u, - const VectorView< InputType3, InputView3, InputStorage3, reference_dense, Coords > & mask, - const VectorView< InputType1, InputView1, InputStorage1, reference_dense, Coords > & v, - const StructuredMatrix< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > & A, + typename Coords, + typename IOTmp, typename InputTmp1, typename InputTmp2, typename InputTmp3 > + RC vxm( VectorView< IOType, IOView, IOStorage, reference_dense, Coords, IOTmp > & u, + const VectorView< InputType3, InputView3, InputStorage3, reference_dense, Coords, InputTmp3 > & mask, + const VectorView< InputType1, InputView1, InputStorage1, reference_dense, Coords, InputTmp1 > & v, + const StructuredMatrix< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense, InputTmp2 > & A, const Ring & ring = Ring(), const typename std::enable_if< grb::is_semiring< Ring >::value, void >::type * const = NULL ) { const VectorView< bool, reference, Coords > empty_mask( 0 ); @@ -158,11 +159,12 @@ namespace grb { typename InputType1, typename InputView1, typename InputStorage1, typename InputType2, typename InputStructure2, typename InputStorage2, typename InputView2, typename InputType3, typename InputView3, typename InputStorage3, - typename Coords > - RC vxm( VectorView< IOType, IOView, IOStorage, reference_dense, Coords > & u, - const VectorView< InputType3, InputView3, InputStorage3, reference_dense, Coords > & mask, - const VectorView< InputType1, InputView1, InputStorage1, reference_dense, Coords > & v, - const StructuredMatrix< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > & A, + typename Coords, + typename IOTmp, typename InputTmp1, typename InputTmp2, typename InputTmp3 > + RC vxm( VectorView< IOType, IOView, IOStorage, reference_dense, Coords, IOTmp > & u, + const VectorView< InputType3, InputView3, InputStorage3, reference_dense, Coords, InputTmp3 > & mask, + const VectorView< InputType1, InputView1, InputStorage1, reference_dense, Coords, InputTmp1 > & v, + const StructuredMatrix< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense, InputTmp2 > & A, const AdditiveMonoid & add = AdditiveMonoid(), const MultiplicativeOperator & mul = MultiplicativeOperator(), const typename std::enable_if< grb::is_monoid< AdditiveMonoid >::value && grb::is_operator< MultiplicativeOperator >::value && ! grb::is_object< IOType >::value && From 6f8ed531644c0bfbb96dc2b3cb12169b0cad927a Mon Sep 17 00:00:00 2001 From: Anonymous Date: Mon, 28 Feb 2022 19:26:55 +0100 Subject: [PATCH 088/282] Add doxygen for VectorView Provides detailed description of relevant concepts. --- include/graphblas/denseref/vector.hpp | 51 +++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/include/graphblas/denseref/vector.hpp b/include/graphblas/denseref/vector.hpp index 49e7cdf18..fa62ae808 100644 --- a/include/graphblas/denseref/vector.hpp +++ b/include/graphblas/denseref/vector.hpp @@ -214,6 +214,57 @@ namespace grb { return v._length(); } + /** + * \brief An ALP vector view. + * + * This is an opaque data type for vector views. + * + * A vector exposes a mathematical + * \em logical layout which allows to express implementation-oblivious concepts + * including the matrix structure itself and \em views on the matrix. + * The logical layout of a vector view maps to a physical counterpart via + * a storage scheme which typically depends on the selected backend. + * grb::Vector may be used as an interface to such a physical layout. + * + * Views can be used to create logical \em perspectives on top of a container. + * For example, one may decide to refer to the part of the vector or + * to reference a diagonal of a matrix as a vector. + * See specialization \a VectorView< T, view::Diagonal< StructuredMatrixT >, storage::Dense, reference_dense, C, tmp > + * as an example of such usage. + * + * Vector View defined as views on other vectors do not instantiate a + * new container but refer to the one used by their targets. + * + * Finally, a vector view can be declared as temporary, in which case the ALP + * framework has the freedom to decide whether a container should be allocated in practice + * or not. For example, a JIT backend may optimize away the use of such vector which + * would make memory allocation for such vector unnecessary. + * + * @tparam T The type of the vector elements. \a T shall not be a GraphBLAS + * type. + * @tparam View One of the vector views. + * All static views except for \a view::Identity (via + * \a view::identity cannot instantiate a new container + * and only allow to refer to a previously defined + * \a VectorView. + * The \a View parameter should not be used directly + * by the user but can be set using specific member types + * appropriately defined by each VectorView and + * accessible via functions. + * @tparam StorageSchemeType Either \em enum \a storage::Dense or \em enum + * \a storage::Sparse. + * \a VectorView will be allowed to pick storage schemes + * defined within their specified \a StorageSchemeType. + * @tparam tmp Whether the vector view is temporary. If \a true and the + * and the vector view can instantiate a physical container + * (i.e., it is defined with \a View = \a view::identity) + * then the framework may or may not decide to actually allocate + * memory for such vector. + * + */ + template< typename T, typename View, typename C, typename tmp > + class VectorView< T, View, storage::Dense, reference_dense, C, tmp > { }; + /** * Identity View over a vector container. */ From 66e7c4d3c0f50d4d74bff93c636b2717712c82bc Mon Sep 17 00:00:00 2001 From: Anonymous Date: Mon, 28 Feb 2022 19:50:56 +0100 Subject: [PATCH 089/282] Fix specification of tmp template parameters in blas1 and blas2 --- include/graphblas/denseref/blas1.hpp | 142 +++++++++++++-------------- include/graphblas/denseref/blas2.hpp | 12 +-- 2 files changed, 77 insertions(+), 77 deletions(-) diff --git a/include/graphblas/denseref/blas1.hpp b/include/graphblas/denseref/blas1.hpp index 4e6174847..3475c9586 100644 --- a/include/graphblas/denseref/blas1.hpp +++ b/include/graphblas/denseref/blas1.hpp @@ -337,7 +337,7 @@ namespace grb { * @see grb::operators::right_assign. * @see grb::setElement. */ - template< Descriptor descr = descriptors::no_operation, typename DataType, typename DataView, typename MaskType, typename MaskView, typename DataTmp, typename MaskTmp, typename T, typename Coords > + template< Descriptor descr = descriptors::no_operation, typename DataType, typename DataView, typename MaskType, typename MaskView, bool DataTmp, bool MaskTmp, typename T, typename Coords > RC set( VectorView< DataType, DataView, storage::Dense, reference_dense, Coords, DataTmp > & x, const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords, MaskTmp > & m, const T val, @@ -478,7 +478,7 @@ namespace grb { * @see grb::operators::right_assign. * @see grb::setElement. */ - template< Descriptor descr = descriptors::no_operation, typename OutputType, typename InputType, typename OutputView, typename InputView, typename Coords, typename OutputTmp, typename InputTmp > + template< Descriptor descr = descriptors::no_operation, typename OutputType, typename InputType, typename OutputView, typename InputView, typename Coords, bool OutputTmp, bool InputTmp > RC set( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & x, const VectorView< InputType, InputView, storage::Dense, reference_dense, Coords, InputTmp > & y ) { // static sanity checks NO_CAST_ASSERT( @@ -563,7 +563,7 @@ namespace grb { * @see grb::operators::right_assign. * @see grb::setElement. */ - template< Descriptor descr = descriptors::no_operation, typename OutputType, typename MaskType, typename InputType, typename OutputView, typename MaskView, typename InputView, typename Coords, typename OutputTmp, typename MaskTmp, typename InputTmp > + template< Descriptor descr = descriptors::no_operation, typename OutputType, typename MaskType, typename InputType, typename OutputView, typename MaskView, typename InputView, typename Coords, bool OutputTmp, bool MaskTmp, bool InputTmp > RC set( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & x, const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords, MaskTmp > & mask, const VectorView< InputType, InputView, storage::Dense, reference_dense, Coords, InputTmp > & y, @@ -670,7 +670,7 @@ namespace grb { * @see grb::operators::internal::Operator for a discussion on when in-place * and/or vectorised operations are used. */ - template< Descriptor descr = descriptors::no_operation, class Monoid, typename InputType, typename InputView, typename IOType, typename Coords, typename InputTmp > + template< Descriptor descr = descriptors::no_operation, class Monoid, typename InputType, typename InputView, typename IOType, typename Coords, bool InputTmp > RC foldr( const VectorView< InputType, InputView, storage::Dense, reference_dense, Coords, InputTmp > & x, IOType & beta, const Monoid & monoid = Monoid(), @@ -749,7 +749,7 @@ namespace grb { * @see grb::operators::internal::Operator for a discussion on when in-place * and/or vectorised operations are used. */ - template< Descriptor descr = descriptors::no_operation, class Monoid, typename IOType, typename InputType, typename InputView, typename Coords, typename InputTmp > + template< Descriptor descr = descriptors::no_operation, class Monoid, typename IOType, typename InputType, typename InputView, typename Coords, bool InputTmp > RC foldr( const InputType & alpha, VectorView< IOType, InputView, storage::Dense, reference_dense, Coords, InputTmp > & y, const Monoid & monoid = Monoid(), @@ -774,7 +774,7 @@ namespace grb { * * Specialisation for scalar \a x. */ - template< Descriptor descr = descriptors::no_operation, class OP, typename IOType, typename InputType, typename IOView, typename Coords, typename IOTmp > + template< Descriptor descr = descriptors::no_operation, class OP, typename IOType, typename InputType, typename IOView, typename Coords, bool IOTmp > RC foldr( const InputType & alpha, VectorView< IOType, IOView, storage::Dense, reference_dense, Coords, IOTmp > & y, const OP & op = OP(), @@ -862,7 +862,7 @@ namespace grb { * @see grb::operators::internal::Operator for a discussion on when in-place * and/or vectorised operations are used. */ - template< Descriptor descr = descriptors::no_operation, class OP, typename IOType, typename InputType, typename IOView, typename InputView, typename Coords, typename IOTmp, typename InputTmp > + template< Descriptor descr = descriptors::no_operation, class OP, typename IOType, typename InputType, typename IOView, typename InputView, typename Coords, bool IOTmp, bool InputTmp > RC foldr( const VectorView< InputType, InputView, storage::Dense, reference_dense, Coords, InputTmp > & x, VectorView< IOType, IOView, storage::Dense, reference_dense, Coords, IOTmp > & y, const OP & op = OP(), @@ -895,7 +895,7 @@ namespace grb { typename IOType, typename MaskType, typename InputType, typename IOView, typename MaskView, typename InputView, typename Coords, - typename IOTmp, typename MaskTmp, typename InputTmp > + bool IOTmp, bool MaskTmp, bool InputTmp > RC foldr( const VectorView< InputType, InputView, storage::Dense, reference_dense, Coords, InputTmp > & x, const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords, MaskTmp > & m, VectorView< IOType, IOView, storage::Dense, reference_dense, Coords, IOTmp > & y, @@ -995,7 +995,7 @@ namespace grb { * @see grb::operators::internal::Operator for a discussion on when in-place * and/or vectorised operations are used. */ - template< Descriptor descr = descriptors::no_operation, class Monoid, typename IOType, typename InputType, typename IOView, typename InputView, typename Coords, typename IOTmp, typename InputTmp > + template< Descriptor descr = descriptors::no_operation, class Monoid, typename IOType, typename InputType, typename IOView, typename InputView, typename Coords, bool IOTmp, bool InputTmp > RC foldr( const VectorView< InputType, InputView, storage::Dense, reference_dense, Coords, InputTmp > & x, VectorView< IOType, IOView, storage::Dense, reference_dense, Coords, IOTmp > & y, const Monoid & monoid = Monoid(), @@ -1026,7 +1026,7 @@ namespace grb { * * Masked variant. */ - template< Descriptor descr = descriptors::no_operation, class Monoid, typename IOType, typename MaskType, typename InputType, typename IOView, typename MaskView, typename InputView, typename Coords, typename IOTmp, typename MaskTmp, typename InputTmp > + template< Descriptor descr = descriptors::no_operation, class Monoid, typename IOType, typename MaskType, typename InputType, typename IOView, typename MaskView, typename InputView, typename Coords, bool IOTmp, bool MaskTmp, bool InputTmp > RC foldr( const VectorView< InputType, InputView, storage::Dense, reference_dense, Coords, InputTmp > & x, const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords, MaskTmp > & m, VectorView< IOType, IOView, storage::Dense, reference_dense, Coords, IOTmp > & y, @@ -1134,7 +1134,7 @@ namespace grb { * @see grb::operators::internal::Operator for a discussion on when in-place * and/or vectorised operations are used. */ - template< Descriptor descr = descriptors::no_operation, class Op, typename IOType, typename InputType, typename IOView, typename Coords, typename IOTmp > + template< Descriptor descr = descriptors::no_operation, class Op, typename IOType, typename InputType, typename IOView, typename Coords, bool IOTmp > RC foldl( VectorView< IOType, IOView, storage::Dense, reference_dense, Coords, IOTmp > & x, const InputType beta, const Op & op = Op(), @@ -1160,7 +1160,7 @@ namespace grb { * * Masked operator variant. */ - template< Descriptor descr = descriptors::no_operation, class Op, typename IOType, typename MaskType, typename InputType, typename IOView, typename MaskView, typename InputView, typename Coords, typename IOTmp, typename MaskTmp > + template< Descriptor descr = descriptors::no_operation, class Op, typename IOType, typename MaskType, typename InputType, typename IOView, typename MaskView, typename InputView, typename Coords, bool IOTmp, bool MaskTmp > RC foldl( VectorView< IOType, IOView, storage::Dense, reference_dense, Coords, IOTmp > & x, const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords, MaskTmp > & m, const InputType beta, @@ -1256,7 +1256,7 @@ namespace grb { * @see grb::operators::internal::Operator for a discussion on when in-place * and/or vectorised operations are used. */ - template< Descriptor descr = descriptors::no_operation, class Monoid, typename IOType, typename InputType, typename IOView, typename Coords, typename IOTmp > + template< Descriptor descr = descriptors::no_operation, class Monoid, typename IOType, typename InputType, typename IOView, typename Coords, bool IOTmp > RC foldl( VectorView< IOType, IOView, storage::Dense, reference_dense, Coords, IOTmp > & x, const InputType beta, const Monoid & monoid = Monoid(), @@ -1282,7 +1282,7 @@ namespace grb { * * Masked monoid variant. */ - template< Descriptor descr = descriptors::no_operation, class Monoid, typename IOType, typename MaskType, typename InputType, typename IOView, typename MaskView, typename Coords, typename IOTmp, typename MaskTmp > + template< Descriptor descr = descriptors::no_operation, class Monoid, typename IOType, typename MaskType, typename InputType, typename IOView, typename MaskView, typename Coords, bool IOTmp, bool MaskTmp > RC foldl( VectorView< IOType, IOView, storage::Dense, reference_dense, Coords, IOTmp > & x, const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords, MaskTmp > & m, const InputType & beta, @@ -1379,7 +1379,7 @@ namespace grb { * @see grb::operators::internal::Operator for a discussion on when in-place * and/or vectorised operations are used. */ - template< Descriptor descr = descriptors::no_operation, class OP, typename IOType, typename InputType, typename IOView, typename InputView, typename Coords, typename IOTmp, typename InputTmp > + template< Descriptor descr = descriptors::no_operation, class OP, typename IOType, typename InputType, typename IOView, typename InputView, typename Coords, bool IOTmp, bool InputTmp > RC foldl( VectorView< IOType, IOView, storage::Dense, reference_dense, Coords, IOTmp > & x, const VectorView< InputType, InputView, storage::Dense, reference_dense, Coords, InputTmp > & y, const OP & op = OP(), @@ -1475,7 +1475,7 @@ namespace grb { * @see grb::operators::internal::Operator for a discussion on when in-place * and/or vectorised operations are used. */ - template< Descriptor descr = descriptors::no_operation, class Monoid, typename IOType, typename InputType, typename IOView, typename InputView, typename Coords, typename IOTmp, typename InputTmp > + template< Descriptor descr = descriptors::no_operation, class Monoid, typename IOType, typename InputType, typename IOView, typename InputView, typename Coords, bool IOTmp, bool InputTmp > RC foldl( VectorView< IOType, IOView, storage::Dense, reference_dense, Coords, IOTmp > & x, const VectorView< InputType, InputView, storage::Dense, reference_dense, Coords, InputTmp > & y, const Monoid & monoid = Monoid(), @@ -1510,7 +1510,7 @@ namespace grb { typename IOType, typename MaskType, typename InputType, typename IOView, typename MaskView, typename InputView, typename Coords, - typename IOTmp, typename MaskTmp, typename InputTmp > + bool IOTmp, bool MaskTmp, bool InputTmp > RC foldl( VectorView< IOType, IOView, storage::Dense, reference_dense, Coords, IOTmp > & x, const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords, MaskTmp > & m, const VectorView< InputType, InputView, storage::Dense, reference_dense, Coords, InputTmp > & y, @@ -1553,7 +1553,7 @@ namespace grb { typename IOType, typename MaskType, typename InputType, typename IOView, typename MaskView, typename InputView, typename Coords, - typename IOTmp, typename MaskTmp, typename InputTmp > + bool IOTmp, bool MaskTmp, bool InputTmp > RC foldl( VectorView< IOType, IOView, storage::Dense, reference_dense, Coords, IOTmp > & x, const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords, MaskTmp > & m, const VectorView< InputType, InputView, storage::Dense, reference_dense, Coords, InputTmp > & y, @@ -1658,7 +1658,7 @@ namespace grb { typename OutputType, typename InputType1, typename InputType2, typename OutputView, typename InputView1, typename InputView2, typename Coords, - typename OutputTmp, typename InputTmp > + bool OutputTmp, bool InputTmp > RC eWiseApply( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & z, const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords, InputTmp > & x, const InputType2 beta, @@ -1681,7 +1681,7 @@ namespace grb { typename OutputType, typename InputType1, typename InputType2, typename OutputView, typename InputView1, typename InputView2, typename Coords, - typename OutputTmp > + bool OutputTmp > RC eWiseApply( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & z, const InputType1 alpha, const InputType2 beta, @@ -1706,7 +1706,7 @@ namespace grb { typename OutputType, typename InputType1, typename InputType2, typename OutputView, typename InputView1, typename InputView2, typename Coords, - typename OutputTmp > + bool OutputTmp > RC eWiseApply( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & z, const InputType1 alpha, const InputType2 beta, @@ -1729,7 +1729,7 @@ namespace grb { typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename OutputView, typename MaskView, typename InputView1, typename Coords, - typename OutputTmp, typename MaskTmp, typename InputTmp1 > + bool OutputTmp, bool MaskTmp, bool InputTmp1 > RC eWiseApply( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & z, const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords, MaskTmp > & mask, const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords, InputTmp1 > & x, @@ -1758,7 +1758,7 @@ namespace grb { typename OutputType, typename InputType1, typename InputType2, typename OutputView, typename InputView1, typename InputView2, typename Coords, - typename OutputTmp, typename InputTmp1, typename InputTmp2 > + bool OutputTmp, bool InputTmp1, bool InputTmp2 > RC eWiseApply( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & z, const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords, InputTmp1 > & x, const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords, InputTmp2 > & y, @@ -1781,7 +1781,7 @@ namespace grb { typename OutputType, typename InputType1, typename InputType2, typename OutputView, typename InputView1, typename InputView2, typename Coords, - typename OutputTmp, typename InputTmp2 > + bool OutputTmp, bool InputTmp2 > RC eWiseApply( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & z, const InputType1 alpha, const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords, InputTmp2 > & y, @@ -1804,7 +1804,7 @@ namespace grb { typename OutputType, typename InputType1, typename InputType2, typename OutputView, typename InputView1, typename InputView2, typename Coords, - typename OutputTmp, typename InputTmp1 > + bool OutputTmp, bool InputTmp1 > RC eWiseApply( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & z, const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords, InputTmp1 > & x, const InputType2 beta, @@ -1827,7 +1827,7 @@ namespace grb { typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename OutputView, typename MaskView, typename InputView1, typename InputView2, typename Coords, - typename OutputTmp, typename MaskTmp, typename InputTmp1, typename InputTmp2 > + bool OutputTmp, bool MaskTmp, bool InputTmp1, bool InputTmp2 > RC eWiseApply( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & z, const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords, MaskTmp > & mask, const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords, InputTmp1 > & x, @@ -1852,7 +1852,7 @@ namespace grb { typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename OutputView, typename MaskView, typename InputView1, typename InputView2, typename Coords, - typename OutputTmp, typename MaskTmp, typename InputTmp2 > + bool OutputTmp, bool MaskTmp, bool InputTmp2 > RC eWiseApply( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & z, const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords, MaskTmp > & mask, const InputType1 alpha, @@ -1877,7 +1877,7 @@ namespace grb { typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename OutputView, typename MaskView, typename InputView1, typename Coords, - typename OutputTmp, typename MaskTmp, typename InputTmp1, typename InputTmp2 > + bool OutputTmp, bool MaskTmp, bool InputTmp1, bool InputTmp2 > RC eWiseApply( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & z, const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords, MaskTmp > & mask, const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords, InputTmp1 > & x, @@ -1962,7 +1962,7 @@ namespace grb { typename OutputType, typename InputType1, typename InputType2, typename OutputView, typename InputView1, typename InputView2, typename Coords, - typename OutputTmp, typename InputTmp2 > + bool OutputTmp, bool InputTmp2 > RC eWiseApply( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & z, const InputType1 alpha, const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords, InputTmp2 > & y, @@ -1985,7 +1985,7 @@ namespace grb { typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename OutputView, typename MaskView, typename InputView1, typename InputView2, typename Coords, - typename OutputTmp, typename MaskTmp, typename InputTmp2 > + bool OutputTmp, bool MaskTmp, bool InputTmp2 > RC eWiseApply( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & z, const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords, MaskTmp > & mask, const InputType1 alpha, @@ -2073,7 +2073,7 @@ namespace grb { typename OutputType, typename InputType1, typename InputType2, typename OutputView, typename InputView1, typename InputView2, typename Coords, - typename OutputTmp, typename InputTmp1, typename InputTmp2 > + bool OutputTmp, bool InputTmp1, bool InputTmp2 > RC eWiseApply( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & z, const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords, InputTmp1 > & x, const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords, InputTmp2 > & y, @@ -2096,7 +2096,7 @@ namespace grb { typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename OutputView, typename MaskView, typename InputView1, typename InputView2, typename Coords, - typename OutputTmp, typename MaskTmp, typename InputTmp1, typename InputTmp2 > + bool OutputTmp, bool MaskTmp, bool InputTmp1, bool InputTmp2 > RC eWiseApply( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & z, const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords, MaskTmp > & mask, const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords, InputTmp1 > & x, @@ -2188,7 +2188,7 @@ namespace grb { typename OutputType, typename InputType1, typename InputType2, typename OutputView, typename InputView1, typename InputView2, typename Coords, - typename OutputTmp, typename InputTmp1, typename InputTmp2 > + bool OutputTmp, bool InputTmp1, bool InputTmp2 > RC eWiseAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & z, const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords, InputTmp1 > & x, const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords, InputTmp2 > & y, @@ -2221,7 +2221,7 @@ namespace grb { typename InputType1, typename InputType2, typename OutputType, typename InputView2, typename OutputView, typename Coords, - typename OutputTmp, typename InputTmp2 > + bool OutputTmp, bool InputTmp2 > RC eWiseAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & z, const InputType1 alpha, const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords, InputTmp2 > & y, @@ -2254,7 +2254,7 @@ namespace grb { typename InputType1, typename InputType2, typename OutputType, typename InputView1, typename OutputView, typename Coords, - typename OutputTmp, typename InputTmp1 > + bool OutputTmp, bool InputTmp1 > RC eWiseAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & z, const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords, InputTmp1 > & x, const InputType2 beta, @@ -2287,7 +2287,7 @@ namespace grb { typename InputType1, typename InputType2, typename OutputType, typename OutputView, typename Coords, - typename OutputTmp > + bool OutputTmp > RC eWiseAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & z, const InputType1 alpha, const InputType2 beta, @@ -2322,7 +2322,7 @@ namespace grb { typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename OutputView, typename MaskView, typename InputView1, typename InputView2, typename Coords, - typename OutputTmp, typename MaskTmp, typename InputTmp1, typename InputTmp2 > + bool OutputTmp, bool MaskTmp, bool InputTmp1, bool InputTmp2 > RC eWiseAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & z, const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords, MaskTmp > & m, const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords, InputTmp1 > & x, @@ -2359,7 +2359,7 @@ namespace grb { typename InputType1, typename InputType2, typename OutputType, typename MaskType, typename InputView2, typename OutputView, typename MaskView, typename Coords, - typename OutputTmp, typename MaskTmp, typename InputTmp2 > + bool OutputTmp, bool MaskTmp, bool InputTmp2 > RC eWiseAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & z, const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords, MaskTmp > & m, const InputType1 alpha, @@ -2396,7 +2396,7 @@ namespace grb { typename InputType1, typename InputType2, typename OutputType, typename MaskType, typename InputView1, typename OutputView, typename MaskView, typename Coords, - typename OutputTmp, typename MaskTmp, typename InputTmp1 > + bool OutputTmp, bool MaskTmp, bool InputTmp1 > RC eWiseAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & z, const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords, MaskTmp > & m, const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords, InputTmp1 > & x, @@ -2433,7 +2433,7 @@ namespace grb { typename InputType1, typename InputType2, typename OutputType, typename MaskType, typename OutputView, typename Coords, - typename OutputTmp, typename MaskTmp > + bool OutputTmp, bool MaskTmp > RC eWiseAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & z, const VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & m, /** \internal \todo Should this be MaskType, MaskView (copied as is from reference/blas1.hpp) */ const InputType1 alpha, @@ -2471,7 +2471,7 @@ namespace grb { typename InputType1, typename InputType2, typename InputType3, typename OutputType, typename InputView2, typename InputView3, typename OutputView, typename Coords, - typename OutputTmp, typename InputTmp2, typename InputTmp3 > + bool OutputTmp, bool InputTmp2, bool InputTmp3 > RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & _z, const InputType1 alpha, const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords, InputTmp2 > & _x, @@ -2507,7 +2507,7 @@ namespace grb { typename InputType1, typename InputType2, typename InputType3, typename OutputType, typename InputView1, typename InputView3, typename OutputView, typename Coords, - typename OutputTmp, typename InputTmp1, typename InputTmp3 > + bool OutputTmp, bool InputTmp1, bool InputTmp3 > RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & _z, const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords, InputTmp1 > & _a, const InputType2 chi, @@ -2542,7 +2542,7 @@ namespace grb { typename InputType1, typename InputType2, typename InputType3, typename OutputType, typename InputView1, typename InputView2, typename OutputView, typename Coords, - typename OutputTmp, typename InputTmp1, typename InputTmp2 > + bool OutputTmp, bool InputTmp1, bool InputTmp2 > RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & _z, const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords, InputTmp1 > & _a, const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords, InputTmp2 > & _x, @@ -2577,7 +2577,7 @@ namespace grb { typename InputType1, typename InputType2, typename InputType3, typename OutputType, typename InputView1, typename OutputView, typename Coords, - typename OutputTmp, typename InputTmp1 > + bool OutputTmp, bool InputTmp1 > RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & _z, const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords, InputTmp1 > & _a, const InputType2 beta, @@ -2612,7 +2612,7 @@ namespace grb { typename InputType1, typename InputType2, typename InputType3, typename OutputType, typename InputView2, typename OutputView, typename Coords, - typename OutputTmp, typename InputTmp2 > + bool OutputTmp, bool InputTmp2 > RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & _z, const InputType1 alpha, const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords, InputTmp2 > & _x, @@ -2649,7 +2649,7 @@ namespace grb { typename OutputType, typename InputType1, typename InputType2, typename InputType3, typename InputView3, typename OutputView, typename Coords, - typename OutputTmp, typename InputTmp3 > + bool OutputTmp, bool InputTmp3 > RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & z, const InputType1 alpha, const InputType2 beta, @@ -2690,7 +2690,7 @@ namespace grb { typename OutputType, typename InputType1, typename InputType2, typename InputType3, typename OutputView, typename Coords, - typename OutputTmp > + bool OutputTmp > RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & z, const InputType1 alpha, const InputType2 beta, @@ -2808,7 +2808,7 @@ namespace grb { typename InputType1, typename InputType2, typename InputType3, typename OutputType, typename InputView1, typename InputView2, typename InputView3, typename OutputView, typename Coords, - typename OutputTmp, typename InputTmp1, typename InputTmp2, typename InputTmp3 > + bool OutputTmp, bool InputTmp1, bool InputTmp2, bool InputTmp3 > RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & _z, const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords, InputTmp1 > & _a, const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords, InputTmp2 > & _x, @@ -2908,7 +2908,7 @@ namespace grb { typename InputType1, typename InputType2, typename OutputType, typename InputView1, typename InputView2, typename OutputView, typename Coords, - typename OutputTmp, typename InputTmp1, typename InputTmp2 > + bool OutputTmp, bool InputTmp1, bool InputTmp2 > RC eWiseMul( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & z, const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords, InputTmp1 > & x, const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords, InputTmp2 > & y, @@ -2940,7 +2940,7 @@ namespace grb { typename InputType1, typename InputType2, typename OutputType, typename InputView2, typename OutputView, typename Coords, - typename OutputTmp, typename InputTmp2 > + bool OutputTmp, bool InputTmp2 > RC eWiseMul( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & z, const InputType1 alpha, const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords, InputTmp2 > & y, @@ -2972,7 +2972,7 @@ namespace grb { typename InputType1, typename InputType2, typename OutputType, typename InputView1, typename OutputView, typename Coords, - typename OutputTmp, typename InputTmp2 > + bool OutputTmp, bool InputTmp2 > RC eWiseMul( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & z, const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords, InputTmp2 > & x, const InputType2 beta, @@ -3004,7 +3004,7 @@ namespace grb { typename InputType1, typename InputType2, typename InputType3, typename OutputType, typename MaskType, typename InputView2, typename InputView3, typename OutputView, typename MaskView, typename Coords, - typename OutputTmp, typename MaskTmp, typename InputTmp2, typename InputTmp3 > + bool OutputTmp, bool MaskTmp, bool InputTmp2, bool InputTmp3 > RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & _z, const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords, MaskTmp > & _m, const InputType1 alpha, @@ -3042,7 +3042,7 @@ namespace grb { typename InputType1, typename InputType2, typename InputType3, typename OutputType, typename MaskType, typename InputView1, typename InputView3, typename OutputView, typename MaskView, typename Coords, - typename OutputTmp, typename MaskTmp, typename InputTmp1, typename InputTmp3 > + bool OutputTmp, bool MaskTmp, bool InputTmp1, bool InputTmp3 > RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & _z, const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords, MaskTmp > & _m, const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords, InputTmp1 > & _a, @@ -3079,7 +3079,7 @@ namespace grb { typename InputType1, typename InputType2, typename InputType3, typename OutputType, typename MaskType, typename InputView1, typename InputView2, typename OutputView, typename MaskView, typename Coords, - typename OutputTmp, typename MaskTmp, typename InputTmp1, typename InputTmp2 > + bool OutputTmp, bool MaskTmp, bool InputTmp1, bool InputTmp2 > RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & _z, const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords, MaskTmp > & _m, const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords, InputTmp1 > & _a, @@ -3116,7 +3116,7 @@ namespace grb { typename InputType1, typename InputType2, typename InputType3, typename OutputType, typename MaskType, typename InputView1, typename OutputView, typename MaskView, typename Coords, - typename OutputTmp, typename MaskTmp, typename InputTmp1 > + bool OutputTmp, bool MaskTmp, bool InputTmp1 > RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & _z, const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords, MaskTmp > & _m, const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords, InputTmp1 > & _a, @@ -3153,7 +3153,7 @@ namespace grb { typename InputType1, typename InputType2, typename InputType3, typename OutputType, typename MaskType, typename InputView2, typename OutputView, typename MaskView, typename Coords, - typename OutputTmp, typename MaskTmp, typename InputTmp2 > + bool OutputTmp, bool MaskTmp, bool InputTmp2 > RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & _z, const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords, MaskTmp > & _m, const InputType1 alpha, @@ -3190,7 +3190,7 @@ namespace grb { typename InputType1, typename InputType2, typename InputType3, typename OutputType, typename MaskType, typename InputView1, typename InputView2, typename InputView3, typename OutputView, typename MaskView, typename Coords, - typename OutputTmp, typename MaskTmp, typename InputTmp1, typename InputTmp2, typename InputTmp3 > + bool OutputTmp, bool MaskTmp, bool InputTmp1, bool InputTmp2, bool InputTmp3 > RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & _z, const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords, MaskTmp > & _m, const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords, InputTmp1 > & _a, @@ -3232,7 +3232,7 @@ namespace grb { typename InputType1, typename InputType2, typename OutputType, typename MaskType, typename InputView1, typename InputView2, typename OutputView, typename MaskView, typename Coords, - typename OutputTmp, typename MaskTmp, typename InputTmp1, typename InputTmp2 > + bool OutputTmp, bool MaskTmp, bool InputTmp1, bool InputTmp2 > RC eWiseMul( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & z, const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords, MaskTmp > & m, const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords, InputTmp1 > & x, @@ -3269,7 +3269,7 @@ namespace grb { typename InputType1, typename InputType2, typename OutputType, typename MaskType, typename InputView2, typename InputView3, typename OutputView, typename MaskView, typename Coords, - typename OutputTmp, typename MaskTmp, typename InputTmp2 > + bool OutputTmp, bool MaskTmp, bool InputTmp2 > RC eWiseMul( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & z, const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords, MaskTmp > & m, const InputType1 alpha, @@ -3306,7 +3306,7 @@ namespace grb { typename InputType1, typename InputType2, typename OutputType, typename MaskType, typename InputView1, typename InputView3, typename OutputView, typename MaskView, typename Coords, - typename OutputTmp, typename MaskTmp, typename InputTmp1 > + bool OutputTmp, bool MaskTmp, bool InputTmp1 > RC eWiseMul( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & z, const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords, MaskTmp > & m, const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords, InputTmp1 > & x, @@ -3343,7 +3343,7 @@ namespace grb { typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename InputType3, typename OutputView, typename MaskView, typename InputView3, typename Coords, - typename OutputTmp, typename MaskTmp, typename InputTmp3 > + bool OutputTmp, bool MaskTmp, bool InputTmp3 > RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & z, const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords, MaskTmp > & m, const InputType1 alpha, @@ -3386,7 +3386,7 @@ namespace grb { typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename InputType3, typename OutputView, typename MaskView, typename Coords, - typename OutputTmp, typename MaskTmp > + bool OutputTmp, bool MaskTmp > RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & z, const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords, MaskTmp > & m, const InputType1 alpha, @@ -3432,7 +3432,7 @@ namespace grb { class AddMonoid, class AnyOp, typename OutputType, typename InputType1, typename InputType2, typename OutputView, typename InputView1, typename InputView2, typename Coords, - typename InputTmp1, typename InputTmp2 + bool InputTmp1, bool InputTmp2 > RC dot_generic( OutputType &z, const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords, InputTmp1 > &x, @@ -3527,7 +3527,7 @@ namespace grb { typename OutputType, typename InputType1, typename InputType2, typename OutputView, typename InputView1, typename InputView2, typename Coords, - typename InputTmp1, typename InputTmp2 + bool InputTmp1, bool InputTmp2 > RC dot( OutputType &z, const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords, InputTmp1 > &x, @@ -3566,7 +3566,7 @@ namespace grb { } /** No implementation notes. */ - template< typename Func, typename DataType, typename DataView, typename Coords, typename DataTmp > + template< typename Func, typename DataType, typename DataView, typename Coords, bool DataTmp > RC eWiseMap( const Func f, VectorView< DataType, DataView, storage::Dense, reference_dense, Coords, DataTmp > & x ) { throw std::runtime_error( "Needs an implementation." ); return SUCCESS; @@ -3586,7 +3586,7 @@ namespace grb { typename DataType1, typename DataType2, typename DataView1, typename DataView2, typename Coords, - typename InputTmp1, typename InputTmp2, + bool InputTmp1, bool InputTmp2, typename... Args > RC eWiseLambda( const Func f, const VectorView< DataType1, DataView1, storage::Dense, reference_dense, Coords, InputTmp1 > & x, @@ -3607,7 +3607,7 @@ namespace grb { * @see VectorView::operator[]() * @see VectorView::lambda_reference */ - template< typename Func, typename DataType, typename DataView, typename Coords, typename DataTmp > + template< typename Func, typename DataType, typename DataView, typename Coords, bool DataTmp > RC eWiseLambda( const Func f, const VectorView< DataType, DataView, storage::Dense, reference_dense, Coords, DataTmp > & x ) { #ifdef _DEBUG std::cout << "Info: entering eWiseLambda function on vectors.\n"; @@ -3701,7 +3701,7 @@ namespace grb { typename InputType, typename IOType, typename MaskType, typename InputView, typename MaskView, typename Coords, - typename IOTmp, typename MaskTmp > + bool IOTmp, bool MaskTmp > RC foldl( IOType & x, const VectorView< InputType, InputView, storage::Dense, reference_dense, Coords, IOTmp > & y, const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords, MaskTmp > & mask, @@ -3812,7 +3812,7 @@ namespace grb { typename OutputType, typename InputType1, typename InputType2, typename InputView1, typename InputView2, typename InputCoords1, typename InputCoords2, - typename InputTmp1, typename InputTmp2 + bool InputTmp1, bool InputTmp2 > RC dot( OutputType &z, const VectorView< InputType1, InputView1, storage::Dense, reference_dense, InputCoords1, InputTmp1 > &x, @@ -3910,7 +3910,7 @@ namespace grb { typename InputView1, typename InputView2, typename InputStorage1, typename InputStorage2, Backend backend, typename Coords1, typename Coords2, - typename InputTmp1, typename InputTmp2 + bool InputTmp1, bool InputTmp2 > RC dot( IOType &x, const VectorView< InputType1, InputView1, InputStorage1, backend, Coords1, InputTmp1 > &left, @@ -3960,7 +3960,7 @@ namespace grb { typename InputView, typename InputStorage, Backend backend, typename Coords, - typename InputTmp + bool InputTmp > RC norm2( OutputType &x, const VectorView< InputType, InputView, InputStorage, backend, Coords, InputTmp > &y, diff --git a/include/graphblas/denseref/blas2.hpp b/include/graphblas/denseref/blas2.hpp index e3c58bf9e..0424f84bf 100644 --- a/include/graphblas/denseref/blas2.hpp +++ b/include/graphblas/denseref/blas2.hpp @@ -52,7 +52,7 @@ namespace grb { * bytes of memory. * \endparblock */ - template< typename InputType, typename InputStructure, typename InputStorage, typename InputView, typename InputTmp > + template< typename InputType, typename InputStructure, typename InputStorage, typename InputView, bool InputTmp > size_t nrows( const StructuredMatrix< InputType, InputStructure, InputStorage, InputView, reference_dense, InputTmp > & A ) noexcept { return A.m; } @@ -73,7 +73,7 @@ namespace grb { * bytes of memory. * \endparblock */ - template< typename InputType, typename InputStructure, typename InputStorage, typename InputView, typename InputTmp > + template< typename InputType, typename InputStructure, typename InputStorage, typename InputView, bool InputTmp > size_t ncols( const StructuredMatrix< InputType, InputStructure, InputStorage, InputView, reference_dense, InputTmp > & A ) noexcept { return A.n; } @@ -94,7 +94,7 @@ namespace grb { * bytes of memory. * \endparblock */ - template< typename InputType, typename InputStructure, typename InputStorage, typename InputView, typename InputTmp > + template< typename InputType, typename InputStructure, typename InputStorage, typename InputView, bool InputTmp > size_t nnz( const StructuredMatrix< InputType, InputStructure, InputStorage, InputView, reference_dense, InputTmp > & A ) noexcept { return A.nz; } @@ -126,7 +126,7 @@ namespace grb { * \warning This is an expensive function. Use sparingly and only when * absolutely necessary */ - template< typename InputType, typename InputStructure, typename InputStorage, typename InputView, typename InputTmp > + template< typename InputType, typename InputStructure, typename InputStorage, typename InputView, bool InputTmp > RC resize( StructuredMatrix< InputType, InputStructure, InputStorage, InputView, reference_dense, InputTmp > & A, const size_t new_nz ) noexcept { // delegate return A.resize( new_nz ); @@ -140,7 +140,7 @@ namespace grb { typename InputType2, typename InputStructure2, typename InputStorage2, typename InputView2, typename InputType3, typename InputType3, typename InputView3, typename InputStorage3, typename Coords, - typename IOTmp, typename InputTmp1, typename InputTmp2, typename InputTmp3 > + bool IOTmp, bool InputTmp1, bool InputTmp2, bool InputTmp3 > RC vxm( VectorView< IOType, IOView, IOStorage, reference_dense, Coords, IOTmp > & u, const VectorView< InputType3, InputView3, InputStorage3, reference_dense, Coords, InputTmp3 > & mask, const VectorView< InputType1, InputView1, InputStorage1, reference_dense, Coords, InputTmp1 > & v, @@ -160,7 +160,7 @@ namespace grb { typename InputType2, typename InputStructure2, typename InputStorage2, typename InputView2, typename InputType3, typename InputView3, typename InputStorage3, typename Coords, - typename IOTmp, typename InputTmp1, typename InputTmp2, typename InputTmp3 > + bool IOTmp, bool InputTmp1, bool InputTmp2, bool InputTmp3 > RC vxm( VectorView< IOType, IOView, IOStorage, reference_dense, Coords, IOTmp > & u, const VectorView< InputType3, InputView3, InputStorage3, reference_dense, Coords, InputTmp3 > & mask, const VectorView< InputType1, InputView1, InputStorage1, reference_dense, Coords, InputTmp1 > & v, From 7d8f0e6014cf76e074bc7d06cfe1bcf0d905b258 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Mon, 28 Feb 2022 19:57:45 +0100 Subject: [PATCH 090/282] Fix remaining tmp template errors in blas1 --- include/graphblas/denseref/blas1.hpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/include/graphblas/denseref/blas1.hpp b/include/graphblas/denseref/blas1.hpp index 3475c9586..258529baa 100644 --- a/include/graphblas/denseref/blas1.hpp +++ b/include/graphblas/denseref/blas1.hpp @@ -140,7 +140,7 @@ namespace grb { * \mathit{sizeof}(\mathit{size\_t}) \f$ bytes of data. * \endparblock */ - template< typename DataType, typename View, typename Coords, typename Tmp > + template< typename DataType, typename View, typename Coords, bool Tmp > RC clear( VectorView< DataType, View, storage::Dense, reference_dense, Coords, Tmp> & x ) noexcept { throw std::runtime_error( "Needs an implementation" ); return SUCCESS; @@ -167,7 +167,7 @@ namespace grb { * -# shall not make any system calls. * \endparblock */ - template< typename DataType, typename View, typename Coords, typename Tmp > + template< typename DataType, typename View, typename Coords, bool Tmp > size_t size( const VectorView< DataType, View, storage::Dense, reference_dense, Coords, Tmp > & x ) noexcept { return getLength( x ); } @@ -192,14 +192,14 @@ namespace grb { * -# shall not make any system calls. * \endparblock */ - template< typename DataType, typename View, typename Coords, typename Tmp > + template< typename DataType, typename View, typename Coords, bool Tmp > size_t nnz( const VectorView< DataType, View, storage::Dense, reference_dense, Coords, Tmp > & x ) noexcept { throw std::runtime_error( "Needs an implementation." ); return 0; } /** \todo add documentation. In particular, think about the meaning with \a P > 1. */ - template< typename InputType, typename View, typename length_type, typename Coords, typename Tmp > + template< typename InputType, typename View, typename length_type, typename Coords, bool Tmp > RC resize( VectorView< InputType, View, storage::Dense, reference_dense, Coords, Tmp > & x, const length_type new_nz ) { // check if we have a mismatch if( new_nz > grb::size( x ) ) { @@ -264,7 +264,7 @@ namespace grb { template< Descriptor descr = descriptors::no_operation, typename DataType, typename View, typename T, - typename Coords, typename Tmp + typename Coords, bool Tmp > RC set( VectorView< DataType, View, storage::Dense, reference_dense, Coords, Tmp > & x, const T val, const typename std::enable_if< @@ -410,7 +410,7 @@ namespace grb { * -# shall not make any system calls. * \endparblock */ - template< Descriptor descr = descriptors::no_operation, typename DataType, typename View, typename T, typename Coords, typename Tmp > + template< Descriptor descr = descriptors::no_operation, typename DataType, typename View, typename T, typename Coords, bool Tmp > RC setElement( VectorView< DataType, View, storage::Dense, reference_dense, Coords, Tmp > & x, const T val, const size_t i, From 8a02a1a13234a9686da21871e1671dc4dd24bcb0 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Mon, 28 Feb 2022 20:06:59 +0100 Subject: [PATCH 091/282] Correct tmp template specializaiton in denseref VectorView --- include/graphblas/base/vector.hpp | 2 +- include/graphblas/denseref/vector.hpp | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/include/graphblas/base/vector.hpp b/include/graphblas/base/vector.hpp index fa635fe0e..99b269082 100644 --- a/include/graphblas/base/vector.hpp +++ b/include/graphblas/base/vector.hpp @@ -901,7 +901,7 @@ namespace grb { } }; - template< typename T, typename View, typename StorageSchemeType, enum Backend backend, typename C, typename tmp > + template< typename T, typename View, typename StorageSchemeType, enum Backend backend, typename C, bool tmp > class VectorView { }; } diff --git a/include/graphblas/denseref/vector.hpp b/include/graphblas/denseref/vector.hpp index fa62ae808..ddcf44f1c 100644 --- a/include/graphblas/denseref/vector.hpp +++ b/include/graphblas/denseref/vector.hpp @@ -209,7 +209,7 @@ namespace grb { * Here starts spec draft for vectorView */ - template< typename T, typename View, typename C, typename tmp > + template< typename T, typename View, typename C, bool tmp > size_t getLength( const VectorView< T, View, storage::Dense, reference_dense, C, tmp > &v ) noexcept { return v._length(); } @@ -262,13 +262,13 @@ namespace grb { * memory for such vector. * */ - template< typename T, typename View, typename C, typename tmp > + template< typename T, typename View, typename C, bool tmp > class VectorView< T, View, storage::Dense, reference_dense, C, tmp > { }; /** * Identity View over a vector container. */ - template< typename T, typename C, typename tmp > + template< typename T, typename C, bool tmp > class VectorView< T, view::Identity< void >, storage::Dense, reference_dense, C, tmp > { private: @@ -311,7 +311,7 @@ namespace grb { }; // class VectorView with physical container /** Identifies any reference_dense vector as an ALP vector. */ - template< typename T, typename View, typename Storage, typename C, typename tmp > + template< typename T, typename View, typename Storage, typename C, bool tmp > struct is_container< VectorView< T, View, Storage, reference_dense, C, tmp > > { /** A reference_vector is an ALP object. */ static const constexpr bool value = true; @@ -320,7 +320,7 @@ namespace grb { /** * Vector view of a vector only via \a view::Identity of another VectorView. */ - template< typename T, typename VectorViewT, typename C, typename tmp > + template< typename T, typename VectorViewT, typename C, bool tmp > class VectorView< T, view::Identity< VectorViewT >, storage::Dense, reference_dense, C, tmp > { private: @@ -368,7 +368,7 @@ namespace grb { /** * Diagonal Vector View of a structured matrix. */ - template< typename T, typename StructuredMatrixT, typename C, typename tmp > + template< typename T, typename StructuredMatrixT, typename C, bool tmp > class VectorView< T, view::Diagonal< StructuredMatrixT >, storage::Dense, reference_dense, C, tmp > { private: @@ -416,7 +416,7 @@ namespace grb { * * @returns A VectorView object. * */ - template< typename StructuredMatrixT, typename C = internal::DefaultCoordinates, typename tmp = false > + template< typename StructuredMatrixT, typename C = internal::DefaultCoordinates, bool tmp = false > VectorView< typename StructuredMatrixT::value_type, view::Diagonal< StructuredMatrixT >, storage::Dense, reference_dense, C, tmp > diagonal( StructuredMatrixT &smat ) { @@ -432,7 +432,7 @@ namespace grb { * * @returns A VectorView object. */ - template< typename T, typename View, typename StorageSchemeType, enum Backend backend, typename C = internal::DefaultCoordinates, typename tmp = false > + template< typename T, typename View, typename StorageSchemeType, enum Backend backend, typename C = internal::DefaultCoordinates, bool tmp = false > VectorView< T, view::Identity< VectorView< T, View, StorageSchemeType, backend, C > >, StorageSchemeType, backend, C, tmp > get_view( VectorView< T, View, StorageSchemeType, backend, C, tmp > &source ) { @@ -451,7 +451,7 @@ namespace grb { * @returns A VectorView object. */ - template< typename T, typename View, typename StorageSchemeType, enum Backend backend, typename C, typename tmp = false > + template< typename T, typename View, typename StorageSchemeType, enum Backend backend, typename C, bool tmp = false > VectorView< T, view::Identity< VectorView< T, View, StorageSchemeType, backend, C > >, StorageSchemeType, backend, C, tmp > get_view( VectorView< T, View, StorageSchemeType, backend, C, tmp > &source, std::shared_ptr< imf::IMF > imf ) { From 0ed238d63b818bb2f0cc4d50c1d8e73453939d17 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Mon, 28 Feb 2022 20:17:54 +0100 Subject: [PATCH 092/282] Add missing tmp parameter to view source type --- include/graphblas/denseref/vector.hpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/graphblas/denseref/vector.hpp b/include/graphblas/denseref/vector.hpp index ddcf44f1c..7eac3e09d 100644 --- a/include/graphblas/denseref/vector.hpp +++ b/include/graphblas/denseref/vector.hpp @@ -433,10 +433,10 @@ namespace grb { * @returns A VectorView object. */ template< typename T, typename View, typename StorageSchemeType, enum Backend backend, typename C = internal::DefaultCoordinates, bool tmp = false > - VectorView< T, view::Identity< VectorView< T, View, StorageSchemeType, backend, C > >, StorageSchemeType, backend, C, tmp > + VectorView< T, view::Identity< VectorView< T, View, StorageSchemeType, backend, C, tmp > >, StorageSchemeType, backend, C, tmp > get_view( VectorView< T, View, StorageSchemeType, backend, C, tmp > &source ) { - VectorView< T, view::Identity< VectorView< T, View, StorageSchemeType, backend, C > >, StorageSchemeType, backend, C, tmp > vec_view( source ); + VectorView< T, view::Identity< VectorView< T, View, StorageSchemeType, backend, C, tmp > >, StorageSchemeType, backend, C, tmp > vec_view( source ); return vec_view; } @@ -452,10 +452,10 @@ namespace grb { */ template< typename T, typename View, typename StorageSchemeType, enum Backend backend, typename C, bool tmp = false > - VectorView< T, view::Identity< VectorView< T, View, StorageSchemeType, backend, C > >, StorageSchemeType, backend, C, tmp > + VectorView< T, view::Identity< VectorView< T, View, StorageSchemeType, backend, C, tmp > >, StorageSchemeType, backend, C, tmp > get_view( VectorView< T, View, StorageSchemeType, backend, C, tmp > &source, std::shared_ptr< imf::IMF > imf ) { - VectorView< T, view::Identity< VectorView< T, View, StorageSchemeType, backend, C > >, StorageSchemeType, backend, C, tmp > vec_view( source, imf ); + VectorView< T, view::Identity< VectorView< T, View, StorageSchemeType, backend, C, tmp > >, StorageSchemeType, backend, C, tmp > vec_view( source, imf ); return vec_view; } From d74eecaed73c75fcd98637d10b8db6507ef3ed64 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Mon, 28 Feb 2022 20:23:33 +0100 Subject: [PATCH 093/282] Expand doxygen for denseref blas1 --- include/graphblas/denseref/blas1.hpp | 48 +++++++++++++++++++++++++++- 1 file changed, 47 insertions(+), 1 deletion(-) diff --git a/include/graphblas/denseref/blas1.hpp b/include/graphblas/denseref/blas1.hpp index 258529baa..5df71f221 100644 --- a/include/graphblas/denseref/blas1.hpp +++ b/include/graphblas/denseref/blas1.hpp @@ -153,6 +153,8 @@ namespace grb { * be changed. A call to this function shall always succeed. * * @tparam DataType The type of elements contained in the vector \a x. + * @tparam View The view type applied to the vector \a x. + * @tparam Tmp Whether the vector \a x is a temporary. * * @param[in] x The VectorView of which to retrieve the size. * @@ -178,6 +180,8 @@ namespace grb { * A call to this function always succeeds. * * @tparam DataType The type of elements contained in this VectorView. + * @tparam View The view type applied to the vector \a x. + * @tparam Tmp Whether the vector \a x is a temporary. * * @param[in] x The VectorView of which to retrieve the number of nonzeroes. * @@ -229,6 +233,8 @@ namespace grb { * * @tparam descr The descriptor used for this operation. * @tparam DataType The type of each element in the given VectorView. + * @tparam View The view type applied to the vector \a x. + * @tparam Tmp Whether the vector \a x is a temporary. * @tparam T The type of the given value. * * \parblock @@ -301,6 +307,8 @@ namespace grb { * * @tparam descr The descriptor used for this operation. * @tparam DataType The type of each element in the given vector. + * @tparam View The view type applied to the given vector. + * @tparam Tmp Whether the vector is a temporary. * @tparam T The type of the given value. * * \parblock @@ -382,6 +390,8 @@ namespace grb { * @tparam descr The descriptor to be used during evaluation of this * function. * @tparam DataType The type of the elements of \a x. + * @tparam View The view type applied to the vector \a x. + * @tparam Tmp Whether the vector \a x is a temporary. * @tparam T The type of the value to be set. * * @param[in,out] x The vector to be modified. @@ -609,6 +619,10 @@ namespace grb { * The operator must be associative. * @tparam InputType The type of the elements of \a x. * @tparam IOType The type of the value \a y. + * @tparam InputView The view type applied to the vector \a x. + * @tparam IOView The view type applied to the vector \a y. + * @tparam InputTmp Whether the vector \a x is a temporary. + * @tparam IOTmp Whether the vector \a y is a temporary. * * @param[in] x The input VectorView \a x that will not be modified. * This input VectorView must be dense. @@ -1078,6 +1092,8 @@ namespace grb { * @tparam OP The type of the operator to be applied. * @tparam IOType The type of the value \a beta. * @tparam InputType The type of the elements of \a x. + * @tparam IOView The view type applied to the vector \a x. + * @tparam IOTmp Whether the vector \a x is a temporary. * * @param[in,out] x On function entry: the initial values to be applied as * the left-hand side input to \a op. The input vector must @@ -1620,6 +1636,12 @@ namespace grb { * @tparam InputType1 The value type of the left-hand vector. * @tparam InputType2 The value type of the right-hand scalar. * @tparam OutputType The value type of the ouput vector. + * @tparam InputView1 The view type applied to the left-hand vector. + * @tparam InputView2 The view type applied to the right-hand vector. + * @tparam OutputView1 The view type applied to the output vector. + * @tparam InputTmp1 Whether the left-hand vector is a temporary. + * @tparam InputTmp2 Whether the right-hand vector is a temporary. + * @tparam OutputTmp1 Whether the output vector is a temporary. * * @param[in] x The left-hand input vector. * @param[in] beta The right-hand input scalar. @@ -2126,6 +2148,12 @@ namespace grb { * of the \a ring. * @tparam OutputType The the result type of the additive operator of the * \a ring. + * @tparam InputView1 The view type applied to the left-hand vector. + * @tparam InputView2 The view type applied to the right-hand vector. + * @tparam OutputView1 The view type applied to the output vector. + * @tparam InputTmp1 Whether the left-hand vector is a temporary. + * @tparam InputTmp2 Whether the right-hand vector is a temporary. + * @tparam OutputTmp1 Whether the output vector is a temporary. * * @param[out] z The output vector of type \a OutputType. This may be a * sparse vector. @@ -2747,6 +2775,14 @@ namespace grb { * @tparam OutputType The right-hand side input type to the additive operator * of the \a ring \em and the result type of the same * operator. + * @tparam InputView1 The view type applied to the left-hand vector. + * @tparam InputView2 The view type applied to the right-hand vector. + * @tparam InputView3 The view applied to the vector \a _y + * @tparam OutputView1 The view type applied to the output vector. + * @tparam InputTmp1 Whether the left-hand vector is a temporary. + * @tparam InputTmp2 Whether the right-hand vector is a temporary. + * @tparam InputView3 Whether the vector \a _y is a temporary. + * @tparam OutputTmp1 Whether the output vector is a temporary. * * @param[out] _z The pre-allocated output vector. * @param[in] _a The elements for left-hand side multiplication. @@ -2850,6 +2886,12 @@ namespace grb { * operator of the \a ring. * @tparam OutputType The the result type of the multiplicative operator of * the \a ring. + * @tparam InputView1 The view type applied to the left-hand vector. + * @tparam InputView2 The view type applied to the right-hand vector. + * @tparam OutputView1 The view type applied to the output vector. + * @tparam InputTmp1 Whether the left-hand vector is a temporary. + * @tparam InputTmp2 Whether the right-hand vector is a temporary. + * @tparam OutputTmp1 Whether the output vector is a temporary. * * @param[out] z The output vector of type \a OutputType. * @param[in] x The left-hand input vector of type \a InputType1. @@ -3456,6 +3498,10 @@ namespace grb { * @tparam OutputType The output type. * @tparam InputType1 The input element type of the left-hand input vector. * @tparam InputType2 The input element type of the right-hand input vector. + * @tparam InputView1 The view type applied to the left-hand input vector. + * @tparam InputView2 The view type applied to the right-hand input vector. + * @tparam InputTmp1 Whether the left-hand input vector is a temporary. + * @tparam InputTmp2 Whether the right-hand input vector is a temporary. * * @param[in,out] z The output element \f$ z + \alpha \f$. * @param[in] x The left-hand input vector. @@ -3525,7 +3571,7 @@ namespace grb { Descriptor descr = descriptors::no_operation, class AddMonoid, class AnyOp, typename OutputType, typename InputType1, typename InputType2, - typename OutputView, typename InputView1, typename InputView2, + typename InputView1, typename InputView2, typename Coords, bool InputTmp1, bool InputTmp2 > From 33452503108d0d595968f0a330cd986f10c501e5 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Mon, 28 Feb 2022 20:39:59 +0100 Subject: [PATCH 094/282] Comment out performance semantics doxygen from blas1 It requires revision if still applies to the denseref backend --- include/graphblas/denseref/blas1.hpp | 850 +++++++++++++-------------- 1 file changed, 425 insertions(+), 425 deletions(-) diff --git a/include/graphblas/denseref/blas1.hpp b/include/graphblas/denseref/blas1.hpp index 5df71f221..37af6a05f 100644 --- a/include/graphblas/denseref/blas1.hpp +++ b/include/graphblas/denseref/blas1.hpp @@ -128,17 +128,17 @@ namespace grb { * * \note This function cannot fail. * - * \parblock - * \par Performance semantics - * This function - * -# contains \f$ \mathcal{O}(n) \f$ work, - * -# will not allocate new dynamic memory, - * -# will take at most \f$ \Theta(1) \f$ memory beyond the memory - * already used by the application before the call to this - * function. - * -# will move at most \f$ \mathit{sizeof}(\mathit{bool}) + - * \mathit{sizeof}(\mathit{size\_t}) \f$ bytes of data. - * \endparblock + // * \parblock + // * \par Performance semantics + // * This function + // * -# contains \f$ \mathcal{O}(n) \f$ work, + // * -# will not allocate new dynamic memory, + // * -# will take at most \f$ \Theta(1) \f$ memory beyond the memory + // * already used by the application before the call to this + // * function. + // * -# will move at most \f$ \mathit{sizeof}(\mathit{bool}) + + // * \mathit{sizeof}(\mathit{size\_t}) \f$ bytes of data. + // * \endparblock */ template< typename DataType, typename View, typename Coords, bool Tmp > RC clear( VectorView< DataType, View, storage::Dense, reference_dense, Coords, Tmp> & x ) noexcept { @@ -160,14 +160,14 @@ namespace grb { * * @return The size of the VectorView \a x. * - * \parblock - * \par Performance semantics - * A call to this function - * -# consists of \f$ \Theta(1) \f$ work; - * -# moves \f$ \Theta(1) \f$ bytes of memory; - * -# does not allocate any dynamic memory; - * -# shall not make any system calls. - * \endparblock + // * \parblock + // * \par Performance semantics + // * A call to this function + // * -# consists of \f$ \Theta(1) \f$ work; + // * -# moves \f$ \Theta(1) \f$ bytes of memory; + // * -# does not allocate any dynamic memory; + // * -# shall not make any system calls. + // * \endparblock */ template< typename DataType, typename View, typename Coords, bool Tmp > size_t size( const VectorView< DataType, View, storage::Dense, reference_dense, Coords, Tmp > & x ) noexcept { @@ -187,14 +187,14 @@ namespace grb { * * @return The number of nonzeroes in \a x. * - * \parblock - * \par Performance semantics - * A call to this function - * -# consists of \f$ \Theta(1) \f$ work; - * -# moves \f$ \Theta(1) \f$ bytes of memory; - * -# does not allocate nor free any dynamic memory; - * -# shall not make any system calls. - * \endparblock + // * \parblock + // * \par Performance semantics + // * A call to this function + // * -# consists of \f$ \Theta(1) \f$ work; + // * -# moves \f$ \Theta(1) \f$ bytes of memory; + // * -# does not allocate nor free any dynamic memory; + // * -# shall not make any system calls. + // * \endparblock */ template< typename DataType, typename View, typename Coords, bool Tmp > size_t nnz( const VectorView< DataType, View, storage::Dense, reference_dense, Coords, Tmp > & x ) noexcept { @@ -252,14 +252,14 @@ namespace grb { * When \a descr includes grb::descriptors::no_casting and if \a T does not * match \a DataType, the code shall not compile. * - * \parblock - * \par Performance semantics - * A call to this function - * -# consists of \f$ \Theta(n) \f$ work; - * -# moves \f$ \Theta(n) \f$ bytes of memory; - * -# does not allocate nor free any dynamic memory; - * -# shall not make any system calls. - * \endparblock + // * \parblock + // * \par Performance semantics + // * A call to this function + // * -# consists of \f$ \Theta(n) \f$ work; + // * -# moves \f$ \Theta(n) \f$ bytes of memory; + // * -# does not allocate nor free any dynamic memory; + // * -# shall not make any system calls. + // * \endparblock * * @see grb::foldl. * @see grb::foldr. @@ -328,16 +328,16 @@ namespace grb { * When \a descr includes grb::descriptors::no_casting and if \a T does not * match \a DataType, the code shall not compile. * - * \parblock - * \par Performance semantics - * A call to this function - * -# consists of \f$ \Theta( nnz( m ) ) \f$ work; - * -# moves \f$ \Theta( nnz( m ) ) \f$ bytes of memory; - * -# does not allocate nor free any dynamic memory; - * -# shall not make any system calls. - * If grb::descriptors::invert_mask is given, then \f$ nnz( m ) \f$ in the - * above shall be interpreted as \f$ size( m ) \f$ instead. - * \endparblock + // * \parblock + // * \par Performance semantics + // * A call to this function + // * -# consists of \f$ \Theta( nnz( m ) ) \f$ work; + // * -# moves \f$ \Theta( nnz( m ) ) \f$ bytes of memory; + // * -# does not allocate nor free any dynamic memory; + // * -# shall not make any system calls. + // * If grb::descriptors::invert_mask is given, then \f$ nnz( m ) \f$ in the + // * above shall be interpreted as \f$ size( m ) \f$ instead. + // * \endparblock * * @see grb::foldl. * @see grb::foldr. @@ -411,14 +411,14 @@ namespace grb { * When \a descr includes grb::descriptors::no_casting and if \a T does not * match \a DataType, the code shall not compile. * - * \parblock - * \par Performance semantics - * A call to this function - * -# consists of \f$ \Theta(1) \f$ work; - * -# moves \f$ \Theta(1) \f$ bytes of memory; - * -# does not allocate nor free any dynamic memory; - * -# shall not make any system calls. - * \endparblock + // * \parblock + // * \par Performance semantics + // * A call to this function + // * -# consists of \f$ \Theta(1) \f$ work; + // * -# moves \f$ \Theta(1) \f$ bytes of memory; + // * -# does not allocate nor free any dynamic memory; + // * -# shall not make any system calls. + // * \endparblock */ template< Descriptor descr = descriptors::no_operation, typename DataType, typename View, typename T, typename Coords, bool Tmp > RC setElement( VectorView< DataType, View, storage::Dense, reference_dense, Coords, Tmp > & x, @@ -473,14 +473,14 @@ namespace grb { * When \a descr includes grb::descriptors::no_casting and if \a InputType * does not match \a OutputType, the code shall not compile. * - * \parblock - * \par Performance semantics - * A call to this function - * -# consists of \f$ \Theta(n) \f$ work; - * -# moves \f$ \Theta(n) \f$ bytes of memory; - * -# does not allocate nor free any dynamic memory; - * -# shall not make any system calls. - * \endparblock + // * \parblock + // * \par Performance semantics + // * A call to this function + // * -# consists of \f$ \Theta(n) \f$ work; + // * -# moves \f$ \Theta(n) \f$ bytes of memory; + // * -# does not allocate nor free any dynamic memory; + // * -# shall not make any system calls. + // * \endparblock * * @see grb::foldl. * @see grb::foldr. @@ -556,16 +556,16 @@ namespace grb { * When \a descr includes grb::descriptors::no_casting and if \a InputType * does not match \a OutputType, the code shall not compile. * - * \parblock - * \par Performance semantics - * A call to this function - * -# consists of \f$ \Theta( \min\{ nnz( mask ), nnz( y ) \} ) \f$ work; - * -# moves \f$ \Theta( \min\{ nnz( mask ), nnz( y ) \} ) \f$ bytes of memory; - * -# does not allocate nor free any dynamic memory; - * -# shall not make any system calls. - * If grb::descriptors::invert_mask is given, then \f$ nnz( mask ) \f$ in the - * above shall be considered equal to \f$ nnz( y ) \f$. - * \endparblock + // * \parblock + // * \par Performance semantics + // * A call to this function + // * -# consists of \f$ \Theta( \min\{ nnz( mask ), nnz( y ) \} ) \f$ work; + // * -# moves \f$ \Theta( \min\{ nnz( mask ), nnz( y ) \} ) \f$ bytes of memory; + // * -# does not allocate nor free any dynamic memory; + // * -# shall not make any system calls. + // * If grb::descriptors::invert_mask is given, then \f$ nnz( mask ) \f$ in the + // * above shall be considered equal to \f$ nnz( y ) \f$. + // * \endparblock * * @see grb::foldl. * @see grb::foldr. @@ -662,24 +662,24 @@ namespace grb { * -# associative. * \endparblock * - * \parblock - * \par Performance semantics - * -# This call comprises \f$ \Theta(n) \f$ work, where \f$ n \f$ equals - * the size of the vector \a x. The constant factor depends on the - * cost of evaluating the underlying binary operator. A good - * implementation uses vectorised instructions whenever the input - * domains, the output domain, and the operator used allow for this. - * - * -# This call will not result in additional dynamic memory allocations. - * - * -# This call takes \f$ \mathcal{O}(1) \f$ memory beyond the memory - * used by the application at the point of a call to this function. - * - * -# This call incurs at most - * \f$ n \cdot\mathit{sizeof}(\mathit{InputType}) + \mathcal{O}(1) \f$ - * bytes of data movement. A good implementation will rely on in-place - * operators. - * \endparblock + // * \parblock + // * \par Performance semantics + // * -# This call comprises \f$ \Theta(n) \f$ work, where \f$ n \f$ equals + // * the size of the vector \a x. The constant factor depends on the + // * cost of evaluating the underlying binary operator. A good + // * implementation uses vectorised instructions whenever the input + // * domains, the output domain, and the operator used allow for this. + // * + // * -# This call will not result in additional dynamic memory allocations. + // * + // * -# This call takes \f$ \mathcal{O}(1) \f$ memory beyond the memory + // * used by the application at the point of a call to this function. + // * + // * -# This call incurs at most + // * \f$ n \cdot\mathit{sizeof}(\mathit{InputType}) + \mathcal{O}(1) \f$ + // * bytes of data movement. A good implementation will rely on in-place + // * operators. + // * \endparblock * * @see grb::operators::internal::Operator for a discussion on when in-place * and/or vectorised operations are used. @@ -742,23 +742,23 @@ namespace grb { * -# (no requirements). * \endparblock * - * \parblock - * \par Performance semantics - * -# This call comprises \f$ \Theta(n) \f$ work, where \f$ n \f$ equals - * the size of the vector \a x. The constant factor depends on the - * cost of evaluating the underlying binary operator. A good - * implementation uses vectorised instructions whenever the input - * domains, the output domain, and the operator used allow for this. - * - * -# This call will not result in additional dynamic memory allocations. - * - * -# This call takes \f$ \mathcal{O}(1) \f$ memory beyond the memory - * used by the application at the point of a call to this function. - * - * -# This call incurs at most - * \f$ 2n \cdot \mathit{sizeof}(\mathit{IOType}) + \mathcal{O}(1) \f$ - * bytes of data movement. - * \endparblock + // * \parblock + // * \par Performance semantics + // * -# This call comprises \f$ \Theta(n) \f$ work, where \f$ n \f$ equals + // * the size of the vector \a x. The constant factor depends on the + // * cost of evaluating the underlying binary operator. A good + // * implementation uses vectorised instructions whenever the input + // * domains, the output domain, and the operator used allow for this. + // * + // * -# This call will not result in additional dynamic memory allocations. + // * + // * -# This call takes \f$ \mathcal{O}(1) \f$ memory beyond the memory + // * used by the application at the point of a call to this function. + // * + // * -# This call incurs at most + // * \f$ 2n \cdot \mathit{sizeof}(\mathit{IOType}) + \mathcal{O}(1) \f$ + // * bytes of data movement. + // * \endparblock * * @see grb::operators::internal::Operator for a discussion on when in-place * and/or vectorised operations are used. @@ -851,27 +851,27 @@ namespace grb { * -# (no requirements). * \endparblock * - * \parblock - * \par Performance semantics - * -# This call comprises \f$ \Theta(n) \f$ work, where \f$ n \f$ equals - * the size of the vector \a x. The constant factor depends on the - * cost of evaluating the underlying binary operator. A good - * implementation uses vectorised instructions whenever the input - * domains, the output domain, and the operator used allow for this. - * - * -# This call will not result in additional dynamic memory allocations. - * - * -# This call takes \f$ \mathcal{O}(1) \f$ memory beyond the memory - * used by the application at the point of a call to this function. - * - * -# This call incurs at most - * \f$ n \cdot ( - * \mathit{sizeof}(InputType) + 2\mathit{sizeof}(IOType) - * ) + \mathcal{O}(1) - * \f$ - * bytes of data movement. A good implementation will rely on in-place - * operators whenever allowed. - * \endparblock + // * \parblock + // * \par Performance semantics + // * -# This call comprises \f$ \Theta(n) \f$ work, where \f$ n \f$ equals + // * the size of the vector \a x. The constant factor depends on the + // * cost of evaluating the underlying binary operator. A good + // * implementation uses vectorised instructions whenever the input + // * domains, the output domain, and the operator used allow for this. + // * + // * -# This call will not result in additional dynamic memory allocations. + // * + // * -# This call takes \f$ \mathcal{O}(1) \f$ memory beyond the memory + // * used by the application at the point of a call to this function. + // * + // * -# This call incurs at most + // * \f$ n \cdot ( + // * \mathit{sizeof}(InputType) + 2\mathit{sizeof}(IOType) + // * ) + \mathcal{O}(1) + // * \f$ + // * bytes of data movement. A good implementation will rely on in-place + // * operators whenever allowed. + // * \endparblock * * @see grb::operators::internal::Operator for a discussion on when in-place * and/or vectorised operations are used. @@ -984,27 +984,27 @@ namespace grb { * -# (no requirements). * \endparblock * - * \parblock - * \par Performance semantics - * -# This call comprises \f$ \Theta(n) \f$ work, where \f$ n \f$ equals - * the size of the vector \a x. The constant factor depends on the - * cost of evaluating the underlying binary operator. A good - * implementation uses vectorised instructions whenever the input - * domains, the output domain, and the operator used allow for this. - * - * -# This call will not result in additional dynamic memory allocations. - * - * -# This call takes \f$ \mathcal{O}(1) \f$ memory beyond the memory - * used by the application at the point of a call to this function. - * - * -# This call incurs at most - * \f$ n \cdot ( - * \mathit{sizeof}(InputType) + 2\mathit{sizeof}(IOType) - * ) + \mathcal{O}(1) - * \f$ - * bytes of data movement. A good implementation will rely on in-place - * operators whenever allowed. - * \endparblock + // * \parblock + // * \par Performance semantics + // * -# This call comprises \f$ \Theta(n) \f$ work, where \f$ n \f$ equals + // * the size of the vector \a x. The constant factor depends on the + // * cost of evaluating the underlying binary operator. A good + // * implementation uses vectorised instructions whenever the input + // * domains, the output domain, and the operator used allow for this. + // * + // * -# This call will not result in additional dynamic memory allocations. + // * + // * -# This call takes \f$ \mathcal{O}(1) \f$ memory beyond the memory + // * used by the application at the point of a call to this function. + // * + // * -# This call incurs at most + // * \f$ n \cdot ( + // * \mathit{sizeof}(InputType) + 2\mathit{sizeof}(IOType) + // * ) + \mathcal{O}(1) + // * \f$ + // * bytes of data movement. A good implementation will rely on in-place + // * operators whenever allowed. + // * \endparblock * * @see grb::operators::internal::Operator for a discussion on when in-place * and/or vectorised operations are used. @@ -1129,23 +1129,23 @@ namespace grb { * -# (no requirement). * \endparblock * - * \parblock - * \par Performance semantics - * -# This call comprises \f$ \Theta(n) \f$ work, where \f$ n \f$ equals - * the size of the vector \a x. The constant factor depends on the - * cost of evaluating the underlying binary operator. A good - * implementation uses vectorised instructions whenever the input - * domains, the output domain, and the operator used allow for this. - * - * -# This call will not result in additional dynamic memory allocations. - * - * -# This call takes \f$ \mathcal{O}(1) \f$ memory beyond the memory - * used by the application at the point of a call to this function. - * - * -# This call incurs at most - * \f$ 2n \cdot \mathit{sizeof}(\mathit{IOType}) + \mathcal{O}(1) \f$ - * bytes of data movement. - * \endparblock + // * \parblock + // * \par Performance semantics + // * -# This call comprises \f$ \Theta(n) \f$ work, where \f$ n \f$ equals + // * the size of the vector \a x. The constant factor depends on the + // * cost of evaluating the underlying binary operator. A good + // * implementation uses vectorised instructions whenever the input + // * domains, the output domain, and the operator used allow for this. + // * + // * -# This call will not result in additional dynamic memory allocations. + // * + // * -# This call takes \f$ \mathcal{O}(1) \f$ memory beyond the memory + // * used by the application at the point of a call to this function. + // * + // * -# This call incurs at most + // * \f$ 2n \cdot \mathit{sizeof}(\mathit{IOType}) + \mathcal{O}(1) \f$ + // * bytes of data movement. + // * \endparblock * * @see grb::operators::internal::Operator for a discussion on when in-place * and/or vectorised operations are used. @@ -1251,23 +1251,23 @@ namespace grb { * -# (no requirement). * \endparblock * - * \parblock - * \par Performance semantics - * -# This call comprises \f$ \Theta(n) \f$ work, where \f$ n \f$ equals - * the size of the vector \a x. The constant factor depends on the - * cost of evaluating the underlying binary operator. A good - * implementation uses vectorised instructions whenever the input - * domains, the output domain, and the operator used allow for this. - * - * -# This call will not result in additional dynamic memory allocations. - * - * -# This call takes \f$ \mathcal{O}(1) \f$ memory beyond the memory - * used by the application at the point of a call to this function. - * - * -# This call incurs at most - * \f$ 2n \cdot \mathit{sizeof}(\mathit{IOType}) + \mathcal{O}(1) \f$ - * bytes of data movement. - * \endparblock + // * \parblock + // * \par Performance semantics + // * -# This call comprises \f$ \Theta(n) \f$ work, where \f$ n \f$ equals + // * the size of the vector \a x. The constant factor depends on the + // * cost of evaluating the underlying binary operator. A good + // * implementation uses vectorised instructions whenever the input + // * domains, the output domain, and the operator used allow for this. + // * + // * -# This call will not result in additional dynamic memory allocations. + // * + // * -# This call takes \f$ \mathcal{O}(1) \f$ memory beyond the memory + // * used by the application at the point of a call to this function. + // * + // * -# This call incurs at most + // * \f$ 2n \cdot \mathit{sizeof}(\mathit{IOType}) + \mathcal{O}(1) \f$ + // * bytes of data movement. + // * \endparblock * * @see grb::operators::internal::Operator for a discussion on when in-place * and/or vectorised operations are used. @@ -1369,28 +1369,28 @@ namespace grb { * -# (no requirements). * \endparblock * - * \parblock - * \par Performance semantics - * -# This call comprises \f$ \Theta(n) \f$ work, where \f$ n \f$ equals - * the size of the vector \a x. The constant factor depends on the - * cost of evaluating the underlying binary operator. A good - * implementation uses vectorised instructions whenever the input - * domains, the output domain, and the operator used allow for this. - * - * -# This call will not result in additional dynamic memory allocations. - * - * -# This call takes \f$ \mathcal{O}(1) \f$ memory beyond the memory - * used by the application at the point of a call to this function. - * - * -# This call incurs at most - * \f$ n \cdot ( - * \mathit{sizeof}(\mathit{IOType}) + - * \mathit{sizeof}(\mathit{InputType}) - * ) + \mathcal{O}(1) \f$ - * bytes of data movement. A good implementation will apply in-place - * vectorised instructions whenever the input domains, the output - * domain, and the operator used allow for this. - * \endparblock + // * \parblock + // * \par Performance semantics + // * -# This call comprises \f$ \Theta(n) \f$ work, where \f$ n \f$ equals + // * the size of the vector \a x. The constant factor depends on the + // * cost of evaluating the underlying binary operator. A good + // * implementation uses vectorised instructions whenever the input + // * domains, the output domain, and the operator used allow for this. + // * + // * -# This call will not result in additional dynamic memory allocations. + // * + // * -# This call takes \f$ \mathcal{O}(1) \f$ memory beyond the memory + // * used by the application at the point of a call to this function. + // * + // * -# This call incurs at most + // * \f$ n \cdot ( + // * \mathit{sizeof}(\mathit{IOType}) + + // * \mathit{sizeof}(\mathit{InputType}) + // * ) + \mathcal{O}(1) \f$ + // * bytes of data movement. A good implementation will apply in-place + // * vectorised instructions whenever the input domains, the output + // * domain, and the operator used allow for this. + // * \endparblock * * @see grb::operators::internal::Operator for a discussion on when in-place * and/or vectorised operations are used. @@ -1465,28 +1465,28 @@ namespace grb { * -# (no requirements). * \endparblock * - * \parblock - * \par Performance semantics - * -# This call comprises \f$ \Theta(n) \f$ work, where \f$ n \f$ equals - * the size of the vector \a x. The constant factor depends on the - * cost of evaluating the underlying binary operator. A good - * implementation uses vectorised instructions whenever the input - * domains, the output domain, and the operator used allow for this. - * - * -# This call will not result in additional dynamic memory allocations. - * - * -# This call takes \f$ \mathcal{O}(1) \f$ memory beyond the memory - * used by the application at the point of a call to this function. - * - * -# This call incurs at most - * \f$ n \cdot ( - * \mathit{sizeof}(\mathit{IOType}) + - * \mathit{sizeof}(\mathit{InputType}) - * ) + \mathcal{O}(1) \f$ - * bytes of data movement. A good implementation will apply in-place - * vectorised instructions whenever the input domains, the output - * domain, and the operator used allow for this. - * \endparblock + // * \parblock + // * \par Performance semantics + // * -# This call comprises \f$ \Theta(n) \f$ work, where \f$ n \f$ equals + // * the size of the vector \a x. The constant factor depends on the + // * cost of evaluating the underlying binary operator. A good + // * implementation uses vectorised instructions whenever the input + // * domains, the output domain, and the operator used allow for this. + // * + // * -# This call will not result in additional dynamic memory allocations. + // * + // * -# This call takes \f$ \mathcal{O}(1) \f$ memory beyond the memory + // * used by the application at the point of a call to this function. + // * + // * -# This call incurs at most + // * \f$ n \cdot ( + // * \mathit{sizeof}(\mathit{IOType}) + + // * \mathit{sizeof}(\mathit{InputType}) + // * ) + \mathcal{O}(1) \f$ + // * bytes of data movement. A good implementation will apply in-place + // * vectorised instructions whenever the input domains, the output + // * domain, and the operator used allow for this. + // * \endparblock * * @see grb::operators::internal::Operator for a discussion on when in-place * and/or vectorised operations are used. @@ -1654,27 +1654,27 @@ namespace grb { * this call was never made. * @return grb::SUCCESS On successful completion of this call. * - * \parblock - * \par Performance semantics - * -# This call comprises \f$ \Theta(n) \f$ work, where \f$ n \f$ equals - * the size of the vectors \a x and \a z. The constant factor depends - * on the cost of evaluating the operator. A good implementation uses - * vectorised instructions whenever the input domains, the output - * domain, and the operator used allow for this. - * - * -# This call takes \f$ \mathcal{O}(1) \f$ memory beyond the memory - * used by the application at the point of a call to this function. - * - * -# This call incurs at most - * \f$ n( - * \mathit{sizeof}(\mathit{D1}) + \mathit{sizeof}(\mathit{D3}) - * ) + - * \mathcal{O}(1) \f$ - * bytes of data movement. A good implementation will stream \a y - * into \a z to apply the multiplication operator in-place, whenever - * the input domains, the output domain, and the operator allow for - * this. - * \endparblock + // * \parblock + // * \par Performance semantics + // * -# This call comprises \f$ \Theta(n) \f$ work, where \f$ n \f$ equals + // * the size of the vectors \a x and \a z. The constant factor depends + // * on the cost of evaluating the operator. A good implementation uses + // * vectorised instructions whenever the input domains, the output + // * domain, and the operator used allow for this. + // * + // * -# This call takes \f$ \mathcal{O}(1) \f$ memory beyond the memory + // * used by the application at the point of a call to this function. + // * + // * -# This call incurs at most + // * \f$ n( + // * \mathit{sizeof}(\mathit{D1}) + \mathit{sizeof}(\mathit{D3}) + // * ) + + // * \mathcal{O}(1) \f$ + // * bytes of data movement. A good implementation will stream \a y + // * into \a z to apply the multiplication operator in-place, whenever + // * the input domains, the output domain, and the operator allow for + // * this. + // * \endparblock */ template< Descriptor descr = descriptors::no_operation, class OP, typename OutputType, typename InputType1, typename InputType2, @@ -1958,27 +1958,27 @@ namespace grb { * this call was never made. * @return grb::SUCCESS On successful completion of this call. * - * \parblock - * \par Performance semantics - * -# This call comprises \f$ \Theta(n) \f$ work, where \f$ n \f$ equals - * the size of the vectors \a y and \a z. The constant factor depends - * on the cost of evaluating the operator. A good implementation uses - * vectorised instructions whenever the input domains, the output - * domain, and the operator used allow for this. - * - * -# This call takes \f$ \mathcal{O}(1) \f$ memory beyond the memory - * used by the application at the point of a call to this function. - * - * -# This call incurs at most - * \f$ n( - * \mathit{sizeof}(\mathit{D2}) + \mathit{sizeof}(\mathit{D3}) - * ) + - * \mathcal{O}(1) \f$ - * bytes of data movement. A good implementation will stream \a y - * into \a z to apply the multiplication operator in-place, whenever - * the input domains, the output domain, and the operator allow for - * this. - * \endparblock + // * \parblock + // * \par Performance semantics + // * -# This call comprises \f$ \Theta(n) \f$ work, where \f$ n \f$ equals + // * the size of the vectors \a y and \a z. The constant factor depends + // * on the cost of evaluating the operator. A good implementation uses + // * vectorised instructions whenever the input domains, the output + // * domain, and the operator used allow for this. + // * + // * -# This call takes \f$ \mathcal{O}(1) \f$ memory beyond the memory + // * used by the application at the point of a call to this function. + // * + // * -# This call incurs at most + // * \f$ n( + // * \mathit{sizeof}(\mathit{D2}) + \mathit{sizeof}(\mathit{D3}) + // * ) + + // * \mathcal{O}(1) \f$ + // * bytes of data movement. A good implementation will stream \a y + // * into \a z to apply the multiplication operator in-place, whenever + // * the input domains, the output domain, and the operator allow for + // * this. + // * \endparblock */ template< Descriptor descr = descriptors::no_operation, class OP, typename OutputType, typename InputType1, typename InputType2, @@ -2067,29 +2067,29 @@ namespace grb { * be as though this call was never made. * @return grb::SUCCESS On successful completion of this call. * - * \parblock - * \par Performance semantics - * -# This call comprises \f$ \Theta(n) \f$ work, where \f$ n \f$ equals - * the size of the vectors \a x, \a y, and \a z. The constant factor - * depends on the cost of evaluating the operator. A good - * implementation uses vectorised instructions whenever the input - * domains, the output domain, and the operator used allow for this. - * - * -# This call takes \f$ \mathcal{O}(1) \f$ memory beyond the memory - * used by the application at the point of a call to this function. - * - * -# This call incurs at most - * \f$ n( - * \mathit{sizeof}(\mathit{OutputType}) + - * \mathit{sizeof}(\mathit{InputType1}) + - * \mathit{sizeof}(\mathit{InputType2}) - * ) + - * \mathcal{O}(1) \f$ - * bytes of data movement. A good implementation will stream \a x or - * \a y into \a z to apply the multiplication operator in-place, - * whenever the input domains, the output domain, and the operator - * used allow for this. - * \endparblock + // * \parblock + // * \par Performance semantics + // * -# This call comprises \f$ \Theta(n) \f$ work, where \f$ n \f$ equals + // * the size of the vectors \a x, \a y, and \a z. The constant factor + // * depends on the cost of evaluating the operator. A good + // * implementation uses vectorised instructions whenever the input + // * domains, the output domain, and the operator used allow for this. + // * + // * -# This call takes \f$ \mathcal{O}(1) \f$ memory beyond the memory + // * used by the application at the point of a call to this function. + // * + // * -# This call incurs at most + // * \f$ n( + // * \mathit{sizeof}(\mathit{OutputType}) + + // * \mathit{sizeof}(\mathit{InputType1}) + + // * \mathit{sizeof}(\mathit{InputType2}) + // * ) + + // * \mathcal{O}(1) \f$ + // * bytes of data movement. A good implementation will stream \a x or + // * \a y into \a z to apply the multiplication operator in-place, + // * whenever the input domains, the output domain, and the operator + // * used allow for this. + // * \endparblock */ template< Descriptor descr = descriptors::no_operation, class OP, typename OutputType, typename InputType1, typename InputType2, @@ -2183,32 +2183,32 @@ namespace grb { * one of these is not true, the code shall not compile. * \endparblock * - * \parblock - * \par Performance semantics - * -# This call takes \f$ \Theta(n) \f$ work, where \f$ n \f$ equals the - * size of the vectors \a x, \a y, and \a z. The constant factor - * depends on the cost of evaluating the addition operator. A good - * implementation uses vectorised instructions whenever the input - * domains, the output domain, and the the additive operator used - * allow for this. - * - * -# This call will not result in additional dynamic memory allocations. - * No system calls will be made. - * - * -# This call takes \f$ \mathcal{O}(1) \f$ memory beyond the memory - * used by the application at the point of a call to this function. - * - * -# This call incurs at most - * \f$ n( \mathit{sizeof}( - * \mathit{InputType1} + - * \mathit{InputType2} + - * \mathit{OutputType} - * ) + \mathcal{O}(1) \f$ - * bytes of data movement. A good implementation will stream \a x or - * \a y into \a z to apply the additive operator in-place, whenever - * the input domains, the output domain, and the operator used allow - * for this. - * \endparblock + // * \parblock + // * \par Performance semantics + // * -# This call takes \f$ \Theta(n) \f$ work, where \f$ n \f$ equals the + // * size of the vectors \a x, \a y, and \a z. The constant factor + // * depends on the cost of evaluating the addition operator. A good + // * implementation uses vectorised instructions whenever the input + // * domains, the output domain, and the the additive operator used + // * allow for this. + // * + // * -# This call will not result in additional dynamic memory allocations. + // * No system calls will be made. + // * + // * -# This call takes \f$ \mathcal{O}(1) \f$ memory beyond the memory + // * used by the application at the point of a call to this function. + // * + // * -# This call incurs at most + // * \f$ n( \mathit{sizeof}( + // * \mathit{InputType1} + + // * \mathit{InputType2} + + // * \mathit{OutputType} + // * ) + \mathcal{O}(1) \f$ + // * bytes of data movement. A good implementation will stream \a x or + // * \a y into \a z to apply the additive operator in-place, whenever + // * the input domains, the output domain, and the operator used allow + // * for this. + // * \endparblock * * @see This is a specialised form of eWiseMulAdd. */ @@ -2816,29 +2816,29 @@ namespace grb { * not true, the code shall not compile. * \endparblock * - * \parblock - * \par Performance semantics - * -# This call takes \f$ \Theta(n) \f$ work, where \f$ n \f$ equals the - * size of the vectors \a _a, \a _x, \a _y, and \a _z. The constant - * factor depends on the cost of evaluating the addition and - * multiplication operators. A good implementation uses vectorised - * instructions whenever the input domains, the output domain, and - * the operators used allow for this. - * - * -# This call takes \f$ \mathcal{O}(1) \f$ memory beyond the memory - * already used by the application when this function is called. - * - * -# This call incurs at most \f$ n( \mathit{sizeof}( - * \mathit{InputType1} + \mathit{bool} - * \mathit{InputType2} + \mathit{bool} - * \mathit{InputType3} + \mathit{bool} - * \mathit{OutputType} + \mathit{bool} - * ) + \mathcal{O}(1) \f$ - * bytes of data movement. A good implementation will stream \a _a, - * \a _x or \a _y into \a _z to apply the additive and multiplicative - * operators in-place, whenever the input domains, the output domain, - * and the operators used allow for this. - * \endparblock + // * \parblock + // * \par Performance semantics + // * -# This call takes \f$ \Theta(n) \f$ work, where \f$ n \f$ equals the + // * size of the vectors \a _a, \a _x, \a _y, and \a _z. The constant + // * factor depends on the cost of evaluating the addition and + // * multiplication operators. A good implementation uses vectorised + // * instructions whenever the input domains, the output domain, and + // * the operators used allow for this. + // * + // * -# This call takes \f$ \mathcal{O}(1) \f$ memory beyond the memory + // * already used by the application when this function is called. + // * + // * -# This call incurs at most \f$ n( \mathit{sizeof}( + // * \mathit{InputType1} + \mathit{bool} + // * \mathit{InputType2} + \mathit{bool} + // * \mathit{InputType3} + \mathit{bool} + // * \mathit{OutputType} + \mathit{bool} + // * ) + \mathcal{O}(1) \f$ + // * bytes of data movement. A good implementation will stream \a _a, + // * \a _x or \a _y into \a _z to apply the additive and multiplicative + // * operators in-place, whenever the input domains, the output domain, + // * and the operators used allow for this. + // * \endparblock */ template< Descriptor descr = descriptors::no_operation, class Ring, typename InputType1, typename InputType2, typename InputType3, typename OutputType, @@ -2918,27 +2918,27 @@ namespace grb { * * \endparblock * - * \parblock - * \par Performance semantics - * -# This call takes \f$ \Theta(n) \f$ work, where \f$ n \f$ equals the - * size of the vectors \a x, \a y, and \a z. The constant factor - * depends on the cost of evaluating the multiplication operator. A - * good implementation uses vectorised instructions whenever the input - * domains, the output domain, and the multiplicative operator used - * allow for this. - * - * -# This call will not result in additional dynamic memory allocations. - * - * -# This call takes \f$ \mathcal{O}(1) \f$ memory beyond the memory - * used by the application at the point of a call to this function. - * - * -# This call incurs at most \f$ n( \mathit{sizeof}(\mathit{D1}) + - * \mathit{sizeof}(\mathit{D2}) + \mathit{sizeof}(\mathit{D3})) + - * \mathcal{O}(1) \f$ bytes of data movement. A good implementation - * will stream \a x or \a y into \a z to apply the multiplication - * operator in-place, whenever the input domains, the output domain, - * and the operator used allow for this. - * \endparblock + // * \parblock + // * \par Performance semantics + // * -# This call takes \f$ \Theta(n) \f$ work, where \f$ n \f$ equals the + // * size of the vectors \a x, \a y, and \a z. The constant factor + // * depends on the cost of evaluating the multiplication operator. A + // * good implementation uses vectorised instructions whenever the input + // * domains, the output domain, and the multiplicative operator used + // * allow for this. + // * + // * -# This call will not result in additional dynamic memory allocations. + // * + // * -# This call takes \f$ \mathcal{O}(1) \f$ memory beyond the memory + // * used by the application at the point of a call to this function. + // * + // * -# This call incurs at most \f$ n( \mathit{sizeof}(\mathit{D1}) + + // * \mathit{sizeof}(\mathit{D2}) + \mathit{sizeof}(\mathit{D3})) + + // * \mathcal{O}(1) \f$ bytes of data movement. A good implementation + // * will stream \a x or \a y into \a z to apply the multiplication + // * operator in-place, whenever the input domains, the output domain, + // * and the operator used allow for this. + // * \endparblock * * \warning When given sparse vectors, the zero now annihilates instead of * acting as an identity. Thus the eWiseMul cannot simply map to an @@ -3523,28 +3523,28 @@ namespace grb { * never made. * @return grb::SUCCESS On successful completion of this call. * - * \parblock - * \par Performance semantics - * -# This call takes \f$ \Theta(n/p) \f$ work at each user process, where - * \f$ n \f$ equals the size of the vectors \a x and \a y, and - * \f$ p \f$ is the number of user processes. The constant factor - * depends on the cost of evaluating the addition and multiplication - * operators. A good implementation uses vectorised instructions - * whenever the input domains, output domain, and the operators used - * allow for this. - * - * -# This call takes \f$ \mathcal{O}(1) \f$ memory beyond the memory used - * by the application at the point of a call to this function. - * - * -# This call incurs at most - * \f$ n( \mathit{sizeof}(\mathit{D1}) + \mathit{sizeof}(\mathit{D2}) ) + \mathcal{O}(p) \f$ - * bytes of data movement. - * - * -# This call incurs at most \f$ \Theta(\log p) \f$ synchronisations - * between two or more user processes. - * - * -# A call to this function does result in any system calls. - * \endparblock + // * \parblock + // * \par Performance semantics + // * -# This call takes \f$ \Theta(n/p) \f$ work at each user process, where + // * \f$ n \f$ equals the size of the vectors \a x and \a y, and + // * \f$ p \f$ is the number of user processes. The constant factor + // * depends on the cost of evaluating the addition and multiplication + // * operators. A good implementation uses vectorised instructions + // * whenever the input domains, output domain, and the operators used + // * allow for this. + // * + // * -# This call takes \f$ \mathcal{O}(1) \f$ memory beyond the memory used + // * by the application at the point of a call to this function. + // * + // * -# This call incurs at most + // * \f$ n( \mathit{sizeof}(\mathit{D1}) + \mathit{sizeof}(\mathit{D2}) ) + \mathcal{O}(p) \f$ + // * bytes of data movement. + // * + // * -# This call incurs at most \f$ \Theta(\log p) \f$ synchronisations + // * between two or more user processes. + // * + // * -# A call to this function does result in any system calls. + // * \endparblock * * \note This requires an implementation to pre-allocate \f$ \Theta(p) \f$ * memory for inter-process reduction, if the underlying communication @@ -3720,26 +3720,26 @@ namespace grb { * these is not true, the code shall not compile. * \endparblock * - * \parblock - * \par Performance semantics - * -# This call comprises \f$ \Theta(n) \f$ work, where \f$ n \f$ equals - * the size of the vector \a x. The constant factor depends on the - * cost of evaluating the underlying binary operator. A good - * implementation uses vectorised instructions whenever the input - * domains, the output domain, and the operator used allow for this. - * - * -# This call will not result in additional dynamic memory allocations. - * No system calls will be made. - * - * -# This call takes \f$ \mathcal{O}(1) \f$ memory beyond the memory - * used by the application at the point of a call to this function. - * - * -# This call incurs at most - * \f$ n \mathit{sizeof}(\mathit{InputType}) + \mathcal{O}(1) \f$ - * bytes of data movement. If \a y is sparse, a call to this function - * incurs at most \f$ n \mathit{sizeof}( \mathit{bool} ) \f$ extra - * bytes of data movement. - * \endparblock + // * \parblock + // * \par Performance semantics + // * -# This call comprises \f$ \Theta(n) \f$ work, where \f$ n \f$ equals + // * the size of the vector \a x. The constant factor depends on the + // * cost of evaluating the underlying binary operator. A good + // * implementation uses vectorised instructions whenever the input + // * domains, the output domain, and the operator used allow for this. + // * + // * -# This call will not result in additional dynamic memory allocations. + // * No system calls will be made. + // * + // * -# This call takes \f$ \mathcal{O}(1) \f$ memory beyond the memory + // * used by the application at the point of a call to this function. + // * + // * -# This call incurs at most + // * \f$ n \mathit{sizeof}(\mathit{InputType}) + \mathcal{O}(1) \f$ + // * bytes of data movement. If \a y is sparse, a call to this function + // * incurs at most \f$ n \mathit{sizeof}( \mathit{bool} ) \f$ extra + // * bytes of data movement. + // * \endparblock * * @see grb::foldl provides similar functionality. */ @@ -3808,28 +3808,28 @@ namespace grb { * never made. * @return grb::SUCCESS On successful completion of this call. * - * \parblock - * \par Performance semantics - * -# This call takes \f$ \Theta(n/p) \f$ work at each user process, where - * \f$ n \f$ equals the size of the vectors \a x and \a y, and - * \f$ p \f$ is the number of user processes. The constant factor - * depends on the cost of evaluating the addition and multiplication - * operators. A good implementation uses vectorised instructions - * whenever the input domains, output domain, and the operators used - * allow for this. - * - * -# This call takes \f$ \mathcal{O}(1) \f$ memory beyond the memory used - * by the application at the point of a call to this function. - * - * -# This call incurs at most - * \f$ n( \mathit{sizeof}(\mathit{D1}) + \mathit{sizeof}(\mathit{D2}) ) + \mathcal{O}(p) \f$ - * bytes of data movement. - * - * -# This call incurs at most \f$ \Theta(\log p) \f$ synchronisations - * between two or more user processes. - * - * -# A call to this function does result in any system calls. - * \endparblock + // * \parblock + // * \par Performance semantics + // * -# This call takes \f$ \Theta(n/p) \f$ work at each user process, where + // * \f$ n \f$ equals the size of the vectors \a x and \a y, and + // * \f$ p \f$ is the number of user processes. The constant factor + // * depends on the cost of evaluating the addition and multiplication + // * operators. A good implementation uses vectorised instructions + // * whenever the input domains, output domain, and the operators used + // * allow for this. + // * + // * -# This call takes \f$ \mathcal{O}(1) \f$ memory beyond the memory used + // * by the application at the point of a call to this function. + // * + // * -# This call incurs at most + // * \f$ n( \mathit{sizeof}(\mathit{D1}) + \mathit{sizeof}(\mathit{D2}) ) + \mathcal{O}(p) \f$ + // * bytes of data movement. + // * + // * -# This call incurs at most \f$ \Theta(\log p) \f$ synchronisations + // * between two or more user processes. + // * + // * -# A call to this function does result in any system calls. + // * \endparblock * * \note This requires an implementation to pre-allocate \f$ \Theta(p) \f$ * memory for inter-process reduction, if the underlying communication From 1199caa6f0b8b7e998ac21b7d36cbff186430e0d Mon Sep 17 00:00:00 2001 From: Anonymous Date: Mon, 28 Feb 2022 17:49:17 +0100 Subject: [PATCH 095/282] Started working on doxygen description for level3 functions --- include/graphblas/denseref/blas3.hpp | 101 ++++++++++++++++++++------- 1 file changed, 77 insertions(+), 24 deletions(-) diff --git a/include/graphblas/denseref/blas3.hpp b/include/graphblas/denseref/blas3.hpp index 3bfb106ee..4fa6c894f 100644 --- a/include/graphblas/denseref/blas3.hpp +++ b/include/graphblas/denseref/blas3.hpp @@ -239,10 +239,38 @@ namespace grb { } // namespace internal /** - * \internal grb::mxm, semiring version. - * Dispatches to internal::mxm_generic + * Dense Matrix-Matrix multiply between unstructured containers. + * Version with semiring parameter. + * + * @tparam descr The descriptors under which to perform the computation. + * @tparam OutputType The type of elements in the output matrix. + * @tparam InputType1 The type of elements in the left-hand side input + * matrix. + * @tparam InputType2 The type of elements in the right-hand side input + * matrix. + * @tparam Semiring The semiring under which to perform the + * multiplication. + * @tparam Backend The backend that should perform the computation. + * + * @returns SUCCESS If the computation completed as intended. + * @returns FAILED If the call was not not preceded by one to + * #grb::resize( C, A, B ); \em and the current capacity of + * \a C was insufficient to store the multiplication of \a A + * and \a B. The contents of \a C shall be undefined (which + * is why #FAILED is returned instead of #ILLEGAL-- this + * error has side effects). + * + * @param[out] C The output matrix \f$ C = AB \f$ when the function returns + * #SUCCESS. + * @param[in] A The left-hand side input matrix \f$ A \f$. + * @param[in] B The left-hand side input matrix \f$ B \f$. + * + * @param[in] ring (Optional.) The semiring under which the computation should + * proceed. */ - template< typename OutputType, typename InputType1, typename InputType2, class Semiring > + template< Descriptor descr = descriptors::no_operation, + typename OutputType, typename InputType1, typename InputType2, + class Semiring > RC mxm( Matrix< OutputType, reference_dense > & C, const Matrix< InputType1, reference_dense > & A, const Matrix< InputType2, reference_dense > & B, @@ -258,38 +286,63 @@ namespace grb { } /** - * \internal grb::mxm semiring version for dense Structured Matrices + * Dense Matrix-Matrix multiply between structured matrices. + * Version with semiring parameter. + * + * @tparam descr The descriptors under which to perform the computation. + * @tparam OutputStructMatT The structured matrix type of the output matrix. + * @tparam InputStructMatT1 The structured matrix type of the the left-hand side input + * matrix. + * @tparam InputStructMatT2 The structured matrix type of the right-hand side input + * matrix. + * @tparam Semiring The semiring under which to perform the + * multiplication. + * + * @returns SUCCESS If the computation completed as intended. + * @returns FAILED If the current capacity of + * \a C was insufficient to store the multiplication of \a A + * and \a B, including due to an incorrect structure formulation. + * The contents of \a C shall be undefined (which + * is why #FAILED is returned instead of #ILLEGAL-- this + * error has side effects). + * + * @param[out] C The output matrix \f$ C = AB \f$ when the function returns + * #SUCCESS. + * @param[in] A The left-hand side input matrix \f$ A \f$. + * @param[in] B The left-hand side input matrix \f$ B \f$. + * + * @param[in] ring (Optional.) The semiring under which the computation should + * proceed. */ - template< typename OutputType, typename InputType1, typename InputType2, class Semiring, - typename OutputStructure, typename OutputView = view::Identity< void >, - typename InputStructure1, typename InputView1 = view::Identity< void >, - typename InputStructure2, typename InputView2 = view::Identity< void >, - bool OutputTmp, bool InputTmp1, bool InputTmp2 > - RC mxm( StructuredMatrix< OutputType, OutputStructure, storage::Dense, OutputView, reference_dense, OutputTmp > & C, - const StructuredMatrix< InputType1, InputStructure1, storage::Dense, InputView1, reference_dense, InputTmp1 > & A, - const StructuredMatrix< InputType2, InputStructure2, storage::Dense, InputView2, reference_dense, InputTmp2 > & B, + template< Descriptor descr = descriptors::no_operation, + typename OutputStructMatT, + typename InputStructMatT1, + typename InputStructMatT2, + class Semiring> + RC mxm( OutputStructMatT & C, + const InputStructMatT1 & A, + const InputStructMatT2 & B, const Semiring & ring = Semiring(), - const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_semiring< Semiring >::value, + const typename std::enable_if< ! grb::is_object< typename OutputStructMatT::value_type >::value && ! grb::is_object< typename InputStructMatT1::value_type >::value && ! grb::is_object< typename InputStructMatT2::value_type >::value && grb::is_semiring< Semiring >::value, void >::type * const = NULL ) { // TODO: How should we handle multiplication of combinations of Structures and Storage schemes? return internal::mxm_generic< true >( C, A, B, ring.getMultiplicativeOperator(), ring.getAdditiveMonoid(), ring.getMultiplicativeMonoid() ); } /** - * \internal mxm implementation with additive monoid and multiplicative operator - * Dispatches to internal::mxm_generic + * Dense Matrix-Matrix multiply between structured matrices. + * Version with additive monoid and multiplicative operator */ - template< typename OutputType, typename InputType1, typename InputType2, class Operator, class Monoid, - typename OutputStructure, typename OutputView = view::Identity< void >, - typename InputStructure1, typename InputView1 = view::Identity< void >, - typename InputStructure2, typename InputView2 = view::Identity< void >, - bool OutputTmp, bool InputTmp1, bool InputTmp2 > - RC mxm( StructuredMatrix< OutputType, OutputStructure, storage::Dense, OutputView, reference_dense, OutputTmp > & C, - const StructuredMatrix< InputType1, InputStructure1, storage::Dense, InputView1, reference_dense, InputTmp1 > & A, - const StructuredMatrix< InputType2, InputStructure2, storage::Dense, InputView2, reference_dense, InputTmp2 > & B, + template< typename OutputStructMatT, + typename InputStructMatT1, + typename InputStructMatT2, + class Operator, class Monoid > + RC mxm( OutputStructMatT & C, + const InputStructMatT1 & A, + const InputStructMatT2 & B, const Operator & mulOp, const Monoid & addM, - const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && + const typename std::enable_if< ! grb::is_object< typename OutputStructMatT::value_type >::value && ! grb::is_object< typename InputStructMatT1::value_type >::value && ! grb::is_object< typename InputStructMatT2::value_type >::value && grb::is_operator< Operator >::value && grb::is_monoid< Monoid >::value, void >::type * const = NULL ) { // TODO: How should we handle multiplication of combinations of Structures and Storage schemes? From 98eadb754c93321c9d0d038ce0d0cc207b0428b1 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Mon, 28 Feb 2022 23:46:58 +0100 Subject: [PATCH 096/282] Added doxygen draft to blas3 operations --- include/graphblas/denseref/blas1.hpp | 18 ++ include/graphblas/denseref/blas3.hpp | 228 +++++++++++++++++++++----- include/graphblas/denseref/vector.hpp | 1 + 3 files changed, 206 insertions(+), 41 deletions(-) diff --git a/include/graphblas/denseref/blas1.hpp b/include/graphblas/denseref/blas1.hpp index 37af6a05f..941b7fd64 100644 --- a/include/graphblas/denseref/blas1.hpp +++ b/include/graphblas/denseref/blas1.hpp @@ -28,6 +28,24 @@ #include #include + +#define NO_CAST_ASSERT( x, y, z ) \ + static_assert( x, \ + "\n\n" \ + "********************************************************************" \ + "********************************************************************" \ + "******************************\n" \ + "* ERROR | " y " " z ".\n" \ + "********************************************************************" \ + "********************************************************************" \ + "******************************\n" \ + "* Possible fix 1 | Remove no_casting from the template parameters " \ + "in this call to " y ".\n" \ + "* Possible fix 2 | Provide a value that matches the expected type.\n" \ + "********************************************************************" \ + "********************************************************************" \ + "******************************\n" ); + namespace grb { /** diff --git a/include/graphblas/denseref/blas3.hpp b/include/graphblas/denseref/blas3.hpp index 4fa6c894f..b163215f9 100644 --- a/include/graphblas/denseref/blas3.hpp +++ b/include/graphblas/denseref/blas3.hpp @@ -26,9 +26,11 @@ #include //for std::enable_if #include +#include #include "io.hpp" #include "matrix.hpp" +#include "vector.hpp" #define NO_CAST_ASSERT( x, y, z ) \ static_assert( x, \ @@ -260,13 +262,13 @@ namespace grb { * is why #FAILED is returned instead of #ILLEGAL-- this * error has side effects). * - * @param[out] C The output matrix \f$ C = AB \f$ when the function returns - * #SUCCESS. - * @param[in] A The left-hand side input matrix \f$ A \f$. - * @param[in] B The left-hand side input matrix \f$ B \f$. - * - * @param[in] ring (Optional.) The semiring under which the computation should + * @param[out] C The output matrix \f$ C = AB \f$ when the function returns + * #SUCCESS. + * @param[in] A The left-hand side input matrix \f$ A \f$. + * @param[in] B The left-hand side input matrix \f$ B \f$. + * @param[in] ring (Optional.) The semiring under which the computation should * proceed. + * @param phase The execution phase. */ template< Descriptor descr = descriptors::no_operation, typename OutputType, typename InputType1, typename InputType2, @@ -275,6 +277,7 @@ namespace grb { const Matrix< InputType1, reference_dense > & A, const Matrix< InputType2, reference_dense > & B, const Semiring & ring = Semiring(), + const PHASE &phase = NUMERICAL, const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_semiring< Semiring >::value, void >::type * const = NULL ) { @@ -298,21 +301,19 @@ namespace grb { * @tparam Semiring The semiring under which to perform the * multiplication. * - * @returns SUCCESS If the computation completed as intended. - * @returns FAILED If the current capacity of - * \a C was insufficient to store the multiplication of \a A - * and \a B, including due to an incorrect structure formulation. - * The contents of \a C shall be undefined (which - * is why #FAILED is returned instead of #ILLEGAL-- this - * error has side effects). + * @returns SUCCESS If the computation completed as intended. + * @returns MISMATCH Whenever the structures or dimensions of \a A, \a B, and \a C do + * not match. All input data containers are left + * untouched if this exit code is returned; it will be + * as though this call was never made. * - * @param[out] C The output matrix \f$ C = AB \f$ when the function returns - * #SUCCESS. - * @param[in] A The left-hand side input matrix \f$ A \f$. - * @param[in] B The left-hand side input matrix \f$ B \f$. - * - * @param[in] ring (Optional.) The semiring under which the computation should + * @param[out] C The output matrix \f$ C = AB \f$ when the function returns + * #SUCCESS. + * @param[in] A The left-hand side input matrix \f$ A \f$. + * @param[in] B The left-hand side input matrix \f$ B \f$. + * @param[in] ring (Optional.) The semiring under which the computation should * proceed. + * @param phase The execution phase. */ template< Descriptor descr = descriptors::no_operation, typename OutputStructMatT, @@ -323,6 +324,7 @@ namespace grb { const InputStructMatT1 & A, const InputStructMatT2 & B, const Semiring & ring = Semiring(), + const PHASE &phase = NUMERICAL, const typename std::enable_if< ! grb::is_object< typename OutputStructMatT::value_type >::value && ! grb::is_object< typename InputStructMatT1::value_type >::value && ! grb::is_object< typename InputStructMatT2::value_type >::value && grb::is_semiring< Semiring >::value, void >::type * const = NULL ) { // TODO: How should we handle multiplication of combinations of Structures and Storage schemes? @@ -342,6 +344,7 @@ namespace grb { const InputStructMatT2 & B, const Operator & mulOp, const Monoid & addM, + const PHASE &phase = NUMERICAL, const typename std::enable_if< ! grb::is_object< typename OutputStructMatT::value_type >::value && ! grb::is_object< typename InputStructMatT1::value_type >::value && ! grb::is_object< typename InputStructMatT2::value_type >::value && grb::is_operator< Operator >::value && grb::is_monoid< Monoid >::value, void >::type * const = NULL ) { @@ -441,12 +444,39 @@ namespace grb { } // namespace internal /** - * Computes \f$ C = A . B \f$ for a given monoid. - * - * \internal Allows pattern matrix inputs. - * - * \internal Dispatches to internal::eWiseApply_matrix_generic - */ + * @brief Computes \f$ C = A . B \f$ for a given monoid. + * + * @tparam descr The descriptor to be used (descriptors::no_operation + * if left unspecified). + * @tparam OutputType The element type of the output matrix + * @tparam InputType1 The element type of the left-hand side matrix + * @tparam InputType2 The element type of the right-hand side matrix + * @tparam OutputStructure The structure of the output matrix + * @tparam InputStructure1 The structure of the left-hand side matrix + * @tparam InputStructure2 The structure of the right-hand matrix + * @tparam OutputStorage The type of storage scheme of the output matrix + * @tparam InputStorage1 The type of storage scheme of the left-hand side matrix + * @tparam InputStorage2 The type of storage scheme of the right-hand side matrix + * @tparam OutputView The type of view of the output matrix + * @tparam InputView1 The type of view of the left-hand matrix + * @tparam InputView2 The type of view of the right-hand matrix + * @tparam OutputTmp If the output matrix is a temporary container + * @tparam InputTmp1 If the left-hand side matrix is a temporary container + * @tparam InputTmp2 If the right-hand side matrix is a temporary container + * @tparam MulMonoid The type of monoid used for this element-wise operation + * + * @param C The output structured matrix + * @param A The left-hand side structured matrix + * @param B The right-hand side structured matrix + * @param mulmono The monoid used in the element-wise operation + * @param phase The execution phase + * + * @return grb::MISMATCH Whenever the structures or dimensions of \a A, \a B, and \a C do + * not match. All input data containers are left + * untouched if this exit code is returned; it will be + * as though this call was never made. + * @return grb::SUCCESS On successful completion of this call. + */ template< Descriptor descr = descriptors::no_operation, typename OutputType, typename InputType1, typename InputType2, @@ -470,25 +500,25 @@ namespace grb { // static checks NO_CAST_ASSERT( ( !( descr & descriptors::no_casting ) || std::is_same< typename MulMonoid::D1, InputType1 >::value ), - "grb::eWiseApply (reference, matrix <- matrix x matrix, monoid)", + "grb::eWiseApply (reference_dense, matrix <- matrix x matrix, monoid)", "called with a prefactor input matrix A that does not match the first " "domain of the monoid operator" ); NO_CAST_ASSERT( ( !( descr & descriptors::no_casting ) || std::is_same< typename MulMonoid::D2, InputType2 >::value ), - "grb::eWiseApply (reference, matrix <- matrix x matrix, monoid)", + "grb::eWiseApply (reference_dense, matrix <- matrix x matrix, monoid)", "called with a postfactor input matrix B that does not match the " "second domain of the monoid operator" ); NO_CAST_ASSERT( ( !( descr & descriptors::no_casting ) || std::is_same< typename MulMonoid::D3, OutputType >::value ), - "grb::eWiseApply (reference, matrix <- matrix x matrix, monoid)", + "grb::eWiseApply (reference_dense, matrix <- matrix x matrix, monoid)", "called with an output matrix C that does not match the output domain " "of the monoid operator" ); #ifdef _DEBUG - std::cout << "In grb::eWiseApply_matrix_generic (reference, monoid)\n"; + std::cout << "In grb::eWiseApply_matrix_generic (reference_dense, monoid)\n"; #endif return internal::eWiseApply_matrix_generic< true, false, false, descr >( @@ -496,12 +526,11 @@ namespace grb { ); } + /** * Computes \f$ C = alpha . B \f$ for a given monoid. * - * \internal Allows pattern matrix inputs. - * - * \internal Dispatches to internal::eWiseApply_matrix_generic + * Case where \a A is a scalar. */ template< Descriptor descr = descriptors::no_operation, @@ -561,9 +590,7 @@ namespace grb { /** * Computes \f$ C = A . beta \f$ for a given monoid. * - * \internal Allows pattern matrix inputs. - * - * \internal Dispatches to internal::eWiseApply_matrix_generic + * Case where \a B is a scalar. */ template< Descriptor descr = descriptors::no_operation, @@ -621,11 +648,130 @@ namespace grb { } /** - * Outer product of two vectors. Assuming vectors \a u and \a v are oriented - * column-wise, the result matrix \a A will contain \f$ uv^T \f$. + * Calculates the element-wise addition of two structured matrices, \f$ C = A + B \f$, + * under the selected semiring. + * + * @tparam descr The descriptor to be used (descriptors::no_operation + * if left unspecified). + * @tparam OutputType The element type of the output matrix + * @tparam InputType1 The element type of the left-hand side matrix + * @tparam InputType2 The element type of the right-hand side matrix + * @tparam OutputStructure The structure of the output matrix + * @tparam InputStructure1 The structure of the left-hand side matrix + * @tparam InputStructure2 The structure of the right-hand matrix + * @tparam OutputStorage The type of storage scheme of the output matrix + * @tparam InputStorage1 The type of storage scheme of the left-hand side matrix + * @tparam InputStorage2 The type of storage scheme of the right-hand side matrix + * @tparam OutputView The type of view of the output matrix + * @tparam InputView1 The type of view of the left-hand matrix + * @tparam InputView2 The type of view of the right-hand matrix + * @tparam OutputTmp If the output matrix is a temporary container + * @tparam InputTmp1 If the left-hand side matrix is a temporary container + * @tparam InputTmp2 If the right-hand side matrix is a temporary container + * @tparam Ring The semiring type to perform the element-wise addition + * on. * - * \internal Implemented via mxm as a multiplication of a column vector with - * a row vector. + * @param[out] C The output vector of type \a OutputType. This may be a + * sparse vector. + * @param[in] x The left-hand input vector of type \a InputType1. This may + * be a sparse vector. + * @param[in] y The right-hand input vector of type \a InputType2. This may + * be a sparse vector. + * @param[in] ring The generalized semiring under which to perform this + * element-wise operation. + * + * @return grb::MISMATCH Whenever the dimensions of \a x, \a y, and \a z do + * not match. All input data containers are left + * untouched; it will be as though this call was never + * made. + * @return grb::SUCCESS On successful completion of this call. + * + * \note Invalid descriptors will be ignored. + * + // * \parblock + // * \par Performance semantics + // * -# This call takes \f$ \Theta(n) \f$ work, where \f$ n \f$ equals the + // * size of the vectors \a x, \a y, and \a z. The constant factor + // * depends on the cost of evaluating the addition operator. A good + // * implementation uses vectorised instructions whenever the input + // * domains, the output domain, and the the additive operator used + // * allow for this. + // * + // * -# This call will not result in additional dynamic memory allocations. + // * No system calls will be made. + // * + // * -# This call takes \f$ \mathcal{O}(1) \f$ memory beyond the memory + // * used by the application at the point of a call to this function. + // * + // * -# This call incurs at most + // * \f$ n( \mathit{sizeof}( + // * \mathit{InputType1} + + // * \mathit{InputType2} + + // * \mathit{OutputType} + // * ) + \mathcal{O}(1) \f$ + // * bytes of data movement. A good implementation will stream \a x or + // * \a y into \a z to apply the additive operator in-place, whenever + // * the input domains, the output domain, and the operator used allow + // * for this. + // * \endparblock + */ + template< + Descriptor descr = descriptors::no_operation, + typename OutputType, typename InputType1, typename InputType2, + typename OutputStructure, typename InputStructure1, typename InputStructure2, + typename OutputStorage, typename InputStorage1, typename InputStorage2, + typename OutputView, typename InputView1, typename InputView2, + bool OutputTmp, bool InputTmp1, bool InputTmp2, + typename Ring> + RC eWiseAdd( StructuredMatrix< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, OutputTmp > &C, + const StructuredMatrix< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense, InputTmp1 > &A, + const StructuredMatrix< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense, InputTmp2 > &B, + const Ring & ring = Ring(), + const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_semiring< Ring >::value, + void >::type * const = NULL ) { + // static sanity checks + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, OutputType >::value ), "grb::eWiseAdd", + "called with an output vector with element type that does not match the " + "fourth domain of the given semiring" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D3, InputType1 >::value ), "grb::eWiseAdd", + "called with a left-hand side input vector with element type that does not " + "match the third domain of the given semiring" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, OutputType >::value ), "grb::eWiseAdd", + "called with a right-hand side input vector with element type that does " + "not match the fourth domain of the given semiring" ); + #ifdef _DEBUG + std::cout << "eWiseAdd (reference_dense, StrMat <- StrMat + StrMat) dispatches to eWiseApply( reference_dense, StrMat <- StrMat . StrMat ) using additive monoid\n"; + #endif + return eWiseApply< descr >( C, A, B, ring.getAdditiveMonoid() ); + } + + /** + * @brief Outer product of two vectors. The result matrix \a A will contain \f$ uv^T \f$. + * + * @tparam descr The descriptor to be used (descriptors::no_operation + * if left unspecified). + * @tparam InputType1 The value type of the left-hand vector. + * @tparam InputType2 The value type of the right-hand scalar. + * @tparam OutputType The value type of the ouput vector. + * @tparam InputView1 The view type applied to the left-hand vector. + * @tparam InputView2 The view type applied to the right-hand vector. + * @tparam OutputView1 The view type applied to the output vector. + * @tparam InputTmp1 Whether the left-hand vector is a temporary. + * @tparam InputTmp2 Whether the right-hand vector is a temporary. + * @tparam OutputTmp1 Whether the output vector is a temporary. + * @tparam Operator The opertor type used for this element-wise operation + * + * @param A The output structured matrix + * @param u The left-hand side vector view + * @param v The right-hand side vector view + * @param mul The operator + * @param phase The execution phase + * + * @return grb::MISMATCH Whenever the structures or dimensions of \a A, \a u, and \a v do + * not match. All input data containers are left + * untouched if this exit code is returned; it will be + * as though this call was never made. + * @return grb::SUCCESS On successful completion of this call. */ template< Descriptor descr = descriptors::no_operation, typename InputType1, typename InputType2, typename OutputType, @@ -635,8 +781,8 @@ namespace grb { bool OutputTmp, typename InputCoords1, typename InputCoords2, class Operator > RC outer( StructuredMatrix< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, OutputTmp > & A, - const VectorView< InputType1, InputView1, InputStorage1, reference_dense, InputCoords1 > & u, - const VectorView< InputType2, InputView2, InputStorage2, reference_dense, InputCoords2 > & v, + const VectorView< InputType1, InputView1, InputStorage1, reference_dense, InputCoords1, false > & u, + const VectorView< InputType2, InputView2, InputStorage2, reference_dense, InputCoords2, false > & v, const Operator & mul = Operator(), const PHASE & phase = NUMERICAL, const typename std::enable_if< grb::is_operator< Operator >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< OutputType >::value, diff --git a/include/graphblas/denseref/vector.hpp b/include/graphblas/denseref/vector.hpp index 7eac3e09d..649f74d91 100644 --- a/include/graphblas/denseref/vector.hpp +++ b/include/graphblas/denseref/vector.hpp @@ -31,6 +31,7 @@ #include #include +#include // #include // #include From da00e34149a683fd6688c232e28ff3c686814cd1 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Tue, 1 Mar 2022 00:37:11 +0100 Subject: [PATCH 097/282] compiler messages cleanup --- include/graphblas/denseref/blas1.hpp | 9 +++++-- include/graphblas/denseref/blas3.hpp | 6 +++-- include/graphblas/denseref/matrix.hpp | 39 +++++++++++++++++++++++++-- tests/unit/dense_outer.cpp | 2 +- 4 files changed, 49 insertions(+), 7 deletions(-) diff --git a/include/graphblas/denseref/blas1.hpp b/include/graphblas/denseref/blas1.hpp index 941b7fd64..7b5ce8fd2 100644 --- a/include/graphblas/denseref/blas1.hpp +++ b/include/graphblas/denseref/blas1.hpp @@ -28,7 +28,7 @@ #include #include - +#ifndef NO_CAST_ASSERT #define NO_CAST_ASSERT( x, y, z ) \ static_assert( x, \ "\n\n" \ @@ -45,6 +45,7 @@ "********************************************************************" \ "********************************************************************" \ "******************************\n" ); +#endif namespace grb { @@ -3624,7 +3625,11 @@ namespace grb { NO_CAST_ASSERT( ( !( descr & descriptors::no_casting ) || std::is_same< OutputType, typename AddMonoid::D3 >::value ), "grb::dot", "called with an output vector value type that does not match the third " "domain of the given additive operator" ); - + (void)z; + (void)x; + (void)y; + (void)addMonoid; + (void)anyOp; throw std::runtime_error( "Needs an implementation." ); return SUCCESS; } diff --git a/include/graphblas/denseref/blas3.hpp b/include/graphblas/denseref/blas3.hpp index b163215f9..0079e697b 100644 --- a/include/graphblas/denseref/blas3.hpp +++ b/include/graphblas/denseref/blas3.hpp @@ -32,6 +32,7 @@ #include "matrix.hpp" #include "vector.hpp" +#ifndef NO_CAST_ASSERT #define NO_CAST_ASSERT( x, y, z ) \ static_assert( x, \ "\n\n" \ @@ -54,6 +55,7 @@ "********************************************************************" \ "********************************************************************" \ "******************************\n" ); +#endif namespace grb { namespace internal { @@ -327,6 +329,7 @@ namespace grb { const PHASE &phase = NUMERICAL, const typename std::enable_if< ! grb::is_object< typename OutputStructMatT::value_type >::value && ! grb::is_object< typename InputStructMatT1::value_type >::value && ! grb::is_object< typename InputStructMatT2::value_type >::value && grb::is_semiring< Semiring >::value, void >::type * const = NULL ) { + (void)phase; // TODO: How should we handle multiplication of combinations of Structures and Storage schemes? return internal::mxm_generic< true >( C, A, B, ring.getMultiplicativeOperator(), ring.getAdditiveMonoid(), ring.getMultiplicativeMonoid() ); } @@ -348,6 +351,7 @@ namespace grb { const typename std::enable_if< ! grb::is_object< typename OutputStructMatT::value_type >::value && ! grb::is_object< typename InputStructMatT1::value_type >::value && ! grb::is_object< typename InputStructMatT2::value_type >::value && grb::is_operator< Operator >::value && grb::is_monoid< Monoid >::value, void >::type * const = NULL ) { + (void)phase; // TODO: How should we handle multiplication of combinations of Structures and Storage schemes? return internal::mxm_generic< true >( C, A, B, mulOp, addM, Monoid() ); } @@ -784,7 +788,6 @@ namespace grb { const VectorView< InputType1, InputView1, InputStorage1, reference_dense, InputCoords1, false > & u, const VectorView< InputType2, InputView2, InputStorage2, reference_dense, InputCoords2, false > & v, const Operator & mul = Operator(), - const PHASE & phase = NUMERICAL, const typename std::enable_if< grb::is_operator< Operator >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< OutputType >::value, void >::type * const = NULL ) { // static checks @@ -825,7 +828,6 @@ namespace grb { grb::Monoid< grb::operators::left_assign< OutputType >, grb::identities::zero > mono; - (void)phase; return grb::mxm( A, u_matrix, v_matrix, mul, mono ); } diff --git a/include/graphblas/denseref/matrix.hpp b/include/graphblas/denseref/matrix.hpp index d4b2a4156..b3a1c0974 100644 --- a/include/graphblas/denseref/matrix.hpp +++ b/include/graphblas/denseref/matrix.hpp @@ -408,15 +408,38 @@ namespace grb { A.initialized = initialized; } + /** + * All matrix views use a pair of index mapping functions to + * capture the correspondence between their logical layout and the one + * of their underlying container. This may be another view leading to a composition + * of IMFs between the top matrix view and the physical container. + */ std::shared_ptr imf_l, imf_r; - /** Whether the container presently is initialized or not. */ + /** + * Whether the container presently is initialized or not. + * TODO: Should be pushed down to the container and reference classess + * so to obtain this status directly from the underlying container. + */ bool initialized; + /** + * @brief determines the size of the structured matrix via the domain of + * the index mapping functions. + * + * @return A pair of dimensions. + */ virtual std::pair< size_t, size_t > _dims() const { return std::make_pair( imf_l->n, imf_r->n ); } + /** + * @brief Construct a new structured matrix Base object assigning identity + * mapping functions both to the row and column dimensions. + * + * @param rows The number of rows of the matrix. + * @param cols The number of columns of the matrix. + */ StructuredMatrixBase( size_t rows, size_t cols ) : imf_l( std::make_shared< imf::Id >( rows ) ), imf_r( std::make_shared< imf::Id >( cols ) ), @@ -443,10 +466,11 @@ namespace grb { return *( A._container ); } + /** A container-type view is characterized by its association with a physical container */ Matrix< T, reference_dense > * _container; /** - * A container's storage scheme. \a storage_scheme is not exposed to the user as an option + * The container's storage scheme. \a storage_scheme is not exposed to the user as an option * but can defined by ALP at different points in the execution depending on the \a backend choice. * In particular, if the structured matrix is not a temporary matrix than it is fixed at construction * time when the allocation takes place. @@ -457,6 +481,12 @@ namespace grb { */ storage::Dense storage_scheme; + /** + * @brief Construct a new structured matrix container object. + * + * TODO: Add the storage scheme a parameter to the constructor + * so that allocation can be made accordingly, generalizing the full case. + */ StructuredMatrixContainer( size_t rows, size_t cols ) : StructuredMatrixBase( rows, cols ), _container( new Matrix< T, reference_dense >(rows, cols) ), @@ -471,6 +501,11 @@ namespace grb { template< typename TargetType > class StructuredMatrixReference : public StructuredMatrixBase { protected: + /** A reference-type view is characterized by an indirect association with a + * physical layout via either another \a StructuredMatrixReference or a \a + * StructuredMatrixContainer. Thus a \a StructuredMatrixReference never allocates + * memory but only establishes a logical view on top of it. + */ TargetType * ref; StructuredMatrixReference() : StructuredMatrixBase( 0, 0 ), ref( nullptr ) {} diff --git a/tests/unit/dense_outer.cpp b/tests/unit/dense_outer.cpp index 193243961..3e9b6fbc7 100644 --- a/tests/unit/dense_outer.cpp +++ b/tests/unit/dense_outer.cpp @@ -83,7 +83,7 @@ void grbProgram( const void *, const size_t in_size, int &error ) { // } if( !error ) { - rc = grb::outer( M, u, v, ring.getMultiplicativeOperator(), SYMBOLIC ); + rc = grb::outer( M, u, v, ring.getMultiplicativeOperator()); rc = rc ? rc : grb::outer( M, u, v, ring.getMultiplicativeOperator() ); } From b7d3f8874c240742f08656aec1c761b1c0257ff4 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Tue, 1 Mar 2022 10:22:16 +0100 Subject: [PATCH 098/282] Add capacity to dense vector --- include/graphblas/denseref/vector.hpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/include/graphblas/denseref/vector.hpp b/include/graphblas/denseref/vector.hpp index 649f74d91..ab3b037ec 100644 --- a/include/graphblas/denseref/vector.hpp +++ b/include/graphblas/denseref/vector.hpp @@ -83,6 +83,9 @@ namespace grb { /** The length of the vector. */ size_t n; + /** The container capacity (in elements). */ + size_t cap; + /** The vector data. */ T *__restrict__ data; @@ -103,7 +106,7 @@ namespace grb { * * \internal Allocates a single array of size \a length. */ - Vector( const size_t length ) : n( length ), initialized( false ) { + Vector( const size_t length, const size_t cap = 0 ) : n( length ), cap( std::max( length, cap ) ), initialized( false ) { // TODO: Implement allocation properly if( n > 0) { data = new (std::nothrow) T[ n ]; From 7f61edc2a0ca843e75dfb31af7a7a370a39e58bc Mon Sep 17 00:00:00 2001 From: Anonymous Date: Tue, 1 Mar 2022 10:21:20 +0100 Subject: [PATCH 099/282] Expand doxygen for dense vector --- include/graphblas/denseref/vector.hpp | 114 +++++++++++++++++++++----- 1 file changed, 92 insertions(+), 22 deletions(-) diff --git a/include/graphblas/denseref/vector.hpp b/include/graphblas/denseref/vector.hpp index ab3b037ec..574ca1828 100644 --- a/include/graphblas/denseref/vector.hpp +++ b/include/graphblas/denseref/vector.hpp @@ -102,9 +102,28 @@ namespace grb { typedef T& lambda_reference; /** - * @param[in] length The requested vector length. + * The main ALP/Dense vector constructor. * - * \internal Allocates a single array of size \a length. + * The constructed object will be uninitalised after successful construction. + * + * + * @param length The number of elements in the new vector. + * + * @return SUCCESS This function never fails. + * + * \parblock + * \par Performance semantics. + * -# This constructor entails \f$ \Theta(1) \f$ amount of work. + * -# This constructor may allocate \f$ \Theta( length ) \f$ bytes + * of dynamic memory. + * -# This constructor will use \f$ \Theta(1) \f$ extra bytes of + * memory beyond that at constructor entry. + * -# This constructor incurs \f$ \Theta(1) \f$ data movement. + * -# This constructor \em may make system calls. + * \endparblock + * + * \warning Avoid the use of this constructor within performance critical + * code sections. */ Vector( const size_t length, const size_t cap = 0 ) : n( length ), cap( std::max( length, cap ) ), initialized( false ) { // TODO: Implement allocation properly @@ -119,26 +138,78 @@ namespace grb { } } - // /** \internal Makes a deep copy of \a other. */ - // Vector( const Vector< T, reference_dense, void > &other ) : Vector( other.n ) { - // initialized = false; - // const RC rc = set( *this, other ); // note: initialized will be set as part of this call - // if( rc != SUCCESS ) { - // throw std::runtime_error( "grb::Vector< T, reference_dense > (copy constructor): error during call to grb::set (" + toString( rc ) + ")" ); - // } - // } + /** + * Copy constructor. + * + * @param other The vector to copy. The initialization state of the copy + * reflects the state of \a other. + * + * \parblock + * \par Performance semantics. + * Allocates the same capacity as the \a other vector, even if the + * actual number of elements contained in \a other is less. + * -# This constructor entails \f$ \Theta(1) \f$ amount of work. + * -# This constructor allocates \f$ \Theta(\max{mn, cap} ) \f$ bytes + * of dynamic memory. + * -# This constructor incurs \f$ \Theta(mn) \f$ of data + * movement. + * -# This constructor \em may make system calls. + * \endparblock + * + * \warning Avoid the use of this constructor within performance critical + * code sections. + */ + Vector( const Vector< T, reference_dense, void > &other ) : Vector( other.n, other.cap ) { + initialized = other.initialized; + // const RC rc = set( *this, other ); // note: initialized will be set as part of this call + // if( rc != SUCCESS ) { + // throw std::runtime_error( "grb::Vector< T, reference_dense > (copy constructor): error during call to grb::set (" + toString( rc ) + ")" ); + // } + } - // /** \internal No implementation notes. */ - // Vector( Vector< T, reference_dense, void > &&other ) { - // n = other.n; other.n = 0; - // data = other.data; other.data = 0; - // data_deleter = std::move( other.data_deleter ); - // initialized = other.initialized; other.initialized = false; - // } + /** + * Move constructor. The new vector equal the given + * vector. Invalidates the use of the input vector. + * + * @param[in] other The GraphBLAS vector to move to this new instance. + * + * \parblock + * \par Performance semantics. + * -# This constructor entails \f$ \Theta(1) \f$ amount of work. + * -# This constructor will not allocate any new dynamic memory. + * -# This constructor will use \f$ \Theta(1) \f$ extra bytes of + * memory beyond that at constructor entry. + * -# This constructor will move \f$ \Theta(1) \f$ bytes of data. + * \endparblock + */ + Vector( Vector< T, reference_dense, void > &&other ) : n( other.n ), cap( other.cap ), data( other.data ) { + other.n = 0; + other.cap = 0; + other.data = 0; + // data_deleter = std::move( other.data_deleter ); + // initialized = other.initialized; other.initialized = false; + } - /** \internal No implementation notes. */ + /** + * Vector destructor. + * + * \parblock + * \par Performance semantics. + * -# This destructor entails \f$ \Theta(1) \f$ amount of work. + * -# This destructor will not perform any memory allocations. + * -# This destructor will use \f$ \mathcal{O}(1) \f$ extra bytes of + * memory beyond that at constructor entry. + * -# This destructor will move \f$ \Theta(1) \f$ bytes of data. + * -# This destructor makes system calls. + * \endparblock + * + * \warning Avoid calling destructors from within performance critical + * code sections. + */ ~Vector() { - delete [] data; + if( data != nullptr ) { + delete [] data; + } } /** \internal No implementation notes. */ @@ -223,9 +294,8 @@ namespace grb { * * This is an opaque data type for vector views. * - * A vector exposes a mathematical - * \em logical layout which allows to express implementation-oblivious concepts - * including the matrix structure itself and \em views on the matrix. + * A vector exposes a mathematical \em logical layout which allows to + * express implementation-oblivious concepts such as \em views on the vector. * The logical layout of a vector view maps to a physical counterpart via * a storage scheme which typically depends on the selected backend. * grb::Vector may be used as an interface to such a physical layout. From df3dacc098fe364a64f042817634b7e46b41163b Mon Sep 17 00:00:00 2001 From: Anonymous Date: Tue, 1 Mar 2022 12:20:22 +0100 Subject: [PATCH 100/282] Inline functions to avoid "multiple definitions" linking error --- include/graphblas/structures.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/graphblas/structures.hpp b/include/graphblas/structures.hpp index febca0643..16c221f20 100644 --- a/include/graphblas/structures.hpp +++ b/include/graphblas/structures.hpp @@ -133,12 +133,12 @@ namespace grb { }; template<> - bool General::isInstantiableFrom< UpperTriangular >( grb::imf::IMF & imf_l, grb::imf::IMF & imf_r ) { + inline bool General::isInstantiableFrom< UpperTriangular >( grb::imf::IMF & imf_l, grb::imf::IMF & imf_r ) { return imf_l.map( imf_l.n - 1 ) <= imf_r.map( 0 ); } template<> - bool General::isInstantiableFrom< General >( grb::imf::IMF & imf_l, grb::imf::IMF & imf_r ) { + inline bool General::isInstantiableFrom< General >( grb::imf::IMF & imf_l, grb::imf::IMF & imf_r ) { (void)imf_l; (void)imf_r; return true; From 1d297e141eaf5456640c808afca645ae58b828d3 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Thu, 3 Mar 2022 13:37:01 +0100 Subject: [PATCH 101/282] Remove tmp template parameter from VectorView interface. This commit is the result of squashing the commits listed above and cleanup of other locations where tmp parameter was introduced (doxygen, blas3). Revert "Add missing tmp parameter to view source type" This reverts commit cd7099968ef5f0d72d9e2dcda00a93ee3ee1ad97. Revert "Correct tmp template specializaiton in denseref VectorView" This reverts commit bdc728e467c1fecb8ca9dd54f7b2aefc3af8d6b1. Revert "Fix remaining tmp template errors in blas1" This reverts commit 882183057fc0ec8e2578c553dbbc9f1b500bcaab. Revert "Fix specification of tmp template parameters in blas1 and blas2" This reverts commit d00b3edcba14275a86af6889f2d927d3daf73c88. Revert "Add VectorView tmp parameter to blas1 and blas2" This reverts commit d009aacdccb5d01f98c8bd32759c9c3321122a20. Revert "Add possibility for VectorView to be a temporary" This reverts commit fd5bf70cbceccf25595b5da1590a3f8b17f6c91a. --- include/graphblas/base/vector.hpp | 2 +- include/graphblas/denseref/blas1.hpp | 719 ++++++++++---------------- include/graphblas/denseref/blas2.hpp | 38 +- include/graphblas/denseref/blas3.hpp | 4 +- include/graphblas/denseref/vector.hpp | 65 +-- include/graphblas/vector.hpp | 2 +- 6 files changed, 310 insertions(+), 520 deletions(-) diff --git a/include/graphblas/base/vector.hpp b/include/graphblas/base/vector.hpp index 99b269082..fb64a1502 100644 --- a/include/graphblas/base/vector.hpp +++ b/include/graphblas/base/vector.hpp @@ -901,7 +901,7 @@ namespace grb { } }; - template< typename T, typename View, typename StorageSchemeType, enum Backend backend, typename C, bool tmp > + template< typename T, typename View, typename StorageSchemeType, enum Backend backend, typename C > class VectorView { }; } diff --git a/include/graphblas/denseref/blas1.hpp b/include/graphblas/denseref/blas1.hpp index 7b5ce8fd2..fc7f16f40 100644 --- a/include/graphblas/denseref/blas1.hpp +++ b/include/graphblas/denseref/blas1.hpp @@ -159,8 +159,8 @@ namespace grb { // * \mathit{sizeof}(\mathit{size\_t}) \f$ bytes of data. // * \endparblock */ - template< typename DataType, typename View, typename Coords, bool Tmp > - RC clear( VectorView< DataType, View, storage::Dense, reference_dense, Coords, Tmp> & x ) noexcept { + template< typename DataType, typename View, typename Coords > + RC clear( VectorView< DataType, View, storage::Dense, reference_dense, Coords > & x ) noexcept { throw std::runtime_error( "Needs an implementation" ); return SUCCESS; } @@ -188,8 +188,8 @@ namespace grb { // * -# shall not make any system calls. // * \endparblock */ - template< typename DataType, typename View, typename Coords, bool Tmp > - size_t size( const VectorView< DataType, View, storage::Dense, reference_dense, Coords, Tmp > & x ) noexcept { + template< typename DataType, typename View, typename Coords > + size_t size( const VectorView< DataType, View, storage::Dense, reference_dense, Coords > & x ) noexcept { return getLength( x ); } @@ -215,15 +215,15 @@ namespace grb { // * -# shall not make any system calls. // * \endparblock */ - template< typename DataType, typename View, typename Coords, bool Tmp > - size_t nnz( const VectorView< DataType, View, storage::Dense, reference_dense, Coords, Tmp > & x ) noexcept { + template< typename DataType, typename View, typename Coords > + size_t nnz( const VectorView< DataType, View, storage::Dense, reference_dense, Coords > & x ) noexcept { throw std::runtime_error( "Needs an implementation." ); return 0; } /** \todo add documentation. In particular, think about the meaning with \a P > 1. */ - template< typename InputType, typename View, typename length_type, typename Coords, bool Tmp > - RC resize( VectorView< InputType, View, storage::Dense, reference_dense, Coords, Tmp > & x, const length_type new_nz ) { + template< typename InputType, typename View, typename length_type, typename Coords > + RC resize( VectorView< InputType, View, storage::Dense, reference_dense, Coords > & x, const length_type new_nz ) { // check if we have a mismatch if( new_nz > grb::size( x ) ) { return MISMATCH; @@ -289,9 +289,9 @@ namespace grb { template< Descriptor descr = descriptors::no_operation, typename DataType, typename View, typename T, - typename Coords, bool Tmp + typename Coords > - RC set( VectorView< DataType, View, storage::Dense, reference_dense, Coords, Tmp > & x, const T val, + RC set( VectorView< DataType, View, storage::Dense, reference_dense, Coords > & x, const T val, const typename std::enable_if< !grb::is_object< DataType >::value && !grb::is_object< T >::value, @@ -364,9 +364,9 @@ namespace grb { * @see grb::operators::right_assign. * @see grb::setElement. */ - template< Descriptor descr = descriptors::no_operation, typename DataType, typename DataView, typename MaskType, typename MaskView, bool DataTmp, bool MaskTmp, typename T, typename Coords > - RC set( VectorView< DataType, DataView, storage::Dense, reference_dense, Coords, DataTmp > & x, - const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords, MaskTmp > & m, + template< Descriptor descr = descriptors::no_operation, typename DataType, typename DataView, typename MaskType, typename MaskView, typename T, typename Coords > + RC set( VectorView< DataType, DataView, storage::Dense, reference_dense, Coords > & x, + const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & m, const T val, const typename std::enable_if< ! grb::is_object< DataType >::value && ! grb::is_object< T >::value, void >::type * const = NULL ) { #ifdef _DEBUG @@ -439,8 +439,8 @@ namespace grb { // * -# shall not make any system calls. // * \endparblock */ - template< Descriptor descr = descriptors::no_operation, typename DataType, typename View, typename T, typename Coords, bool Tmp > - RC setElement( VectorView< DataType, View, storage::Dense, reference_dense, Coords, Tmp > & x, + template< Descriptor descr = descriptors::no_operation, typename DataType, typename View, typename T, typename Coords > + RC setElement( VectorView< DataType, View, storage::Dense, reference_dense, Coords > & x, const T val, const size_t i, const typename std::enable_if< ! grb::is_object< DataType >::value && ! grb::is_object< T >::value, void >::type * const = NULL ) { @@ -507,8 +507,8 @@ namespace grb { * @see grb::operators::right_assign. * @see grb::setElement. */ - template< Descriptor descr = descriptors::no_operation, typename OutputType, typename InputType, typename OutputView, typename InputView, typename Coords, bool OutputTmp, bool InputTmp > - RC set( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & x, const VectorView< InputType, InputView, storage::Dense, reference_dense, Coords, InputTmp > & y ) { + template< Descriptor descr = descriptors::no_operation, typename OutputType, typename InputType, typename OutputView, typename InputView, typename Coords > + RC set( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & x, const VectorView< InputType, InputView, storage::Dense, reference_dense, Coords > & y ) { // static sanity checks NO_CAST_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< OutputType, InputType >::value ), "grb::copy (Vector)", "called with vector parameters whose element data types do not match" ); @@ -592,10 +592,10 @@ namespace grb { * @see grb::operators::right_assign. * @see grb::setElement. */ - template< Descriptor descr = descriptors::no_operation, typename OutputType, typename MaskType, typename InputType, typename OutputView, typename MaskView, typename InputView, typename Coords, bool OutputTmp, bool MaskTmp, bool InputTmp > - RC set( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & x, - const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords, MaskTmp > & mask, - const VectorView< InputType, InputView, storage::Dense, reference_dense, Coords, InputTmp > & y, + template< Descriptor descr = descriptors::no_operation, typename OutputType, typename MaskType, typename InputType, typename OutputView, typename MaskView, typename InputView, typename Coords > + RC set( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & x, + const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & mask, + const VectorView< InputType, InputView, storage::Dense, reference_dense, Coords > & y, const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType >::value, void >::type * const = NULL ) { // static sanity checks NO_CAST_ASSERT( @@ -703,8 +703,8 @@ namespace grb { * @see grb::operators::internal::Operator for a discussion on when in-place * and/or vectorised operations are used. */ - template< Descriptor descr = descriptors::no_operation, class Monoid, typename InputType, typename InputView, typename IOType, typename Coords, bool InputTmp > - RC foldr( const VectorView< InputType, InputView, storage::Dense, reference_dense, Coords, InputTmp > & x, + template< Descriptor descr = descriptors::no_operation, class Monoid, typename InputType, typename InputView, typename IOType, typename Coords > + RC foldr( const VectorView< InputType, InputView, storage::Dense, reference_dense, Coords > & x, IOType & beta, const Monoid & monoid = Monoid(), const typename std::enable_if< ! grb::is_object< InputType >::value && ! grb::is_object< IOType >::value && grb::is_monoid< Monoid >::value, void >::type * const = NULL ) { @@ -782,9 +782,9 @@ namespace grb { * @see grb::operators::internal::Operator for a discussion on when in-place * and/or vectorised operations are used. */ - template< Descriptor descr = descriptors::no_operation, class Monoid, typename IOType, typename InputType, typename InputView, typename Coords, bool InputTmp > + template< Descriptor descr = descriptors::no_operation, class Monoid, typename IOType, typename InputType, typename InputView, typename Coords > RC foldr( const InputType & alpha, - VectorView< IOType, InputView, storage::Dense, reference_dense, Coords, InputTmp > & y, + VectorView< IOType, InputView, storage::Dense, reference_dense, Coords > & y, const Monoid & monoid = Monoid(), const typename std::enable_if< ! grb::is_object< InputType >::value && ! grb::is_object< IOType >::value && grb::is_monoid< Monoid >::value, void >::type * const = NULL ) { // static sanity checks @@ -807,9 +807,9 @@ namespace grb { * * Specialisation for scalar \a x. */ - template< Descriptor descr = descriptors::no_operation, class OP, typename IOType, typename InputType, typename IOView, typename Coords, bool IOTmp > + template< Descriptor descr = descriptors::no_operation, class OP, typename IOType, typename InputType, typename IOView, typename Coords > RC foldr( const InputType & alpha, - VectorView< IOType, IOView, storage::Dense, reference_dense, Coords, IOTmp > & y, + VectorView< IOType, IOView, storage::Dense, reference_dense, Coords > & y, const OP & op = OP(), const typename std::enable_if< ! grb::is_object< InputType >::value && ! grb::is_object< IOType >::value && grb::is_operator< OP >::value, void >::type * const = NULL ) { // static sanity checks @@ -895,9 +895,9 @@ namespace grb { * @see grb::operators::internal::Operator for a discussion on when in-place * and/or vectorised operations are used. */ - template< Descriptor descr = descriptors::no_operation, class OP, typename IOType, typename InputType, typename IOView, typename InputView, typename Coords, bool IOTmp, bool InputTmp > - RC foldr( const VectorView< InputType, InputView, storage::Dense, reference_dense, Coords, InputTmp > & x, - VectorView< IOType, IOView, storage::Dense, reference_dense, Coords, IOTmp > & y, + template< Descriptor descr = descriptors::no_operation, class OP, typename IOType, typename InputType, typename IOView, typename InputView, typename Coords > + RC foldr( const VectorView< InputType, InputView, storage::Dense, reference_dense, Coords > & x, + VectorView< IOType, IOView, storage::Dense, reference_dense, Coords > & y, const OP & op = OP(), const typename std::enable_if< grb::is_operator< OP >::value && ! grb::is_object< InputType >::value && ! grb::is_object< IOType >::value, void >::type * = NULL ) { // static sanity checks @@ -924,14 +924,10 @@ namespace grb { * * Masked variant. */ - template< Descriptor descr = descriptors::no_operation, class OP, - typename IOType, typename MaskType, typename InputType, - typename IOView, typename MaskView, typename InputView, - typename Coords, - bool IOTmp, bool MaskTmp, bool InputTmp > - RC foldr( const VectorView< InputType, InputView, storage::Dense, reference_dense, Coords, InputTmp > & x, - const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords, MaskTmp > & m, - VectorView< IOType, IOView, storage::Dense, reference_dense, Coords, IOTmp > & y, + template< Descriptor descr = descriptors::no_operation, class OP, typename IOType, typename MaskType, typename InputType, typename IOView, typename MaskView, typename InputView, typename Coords > + RC foldr( const VectorView< InputType, InputView, storage::Dense, reference_dense, Coords > & x, + const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & m, + VectorView< IOType, IOView, storage::Dense, reference_dense, Coords > & y, const OP & op = OP(), const typename std::enable_if< grb::is_operator< OP >::value && ! grb::is_object< InputType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< IOType >::value, void >::type * = NULL ) { @@ -1028,9 +1024,9 @@ namespace grb { * @see grb::operators::internal::Operator for a discussion on when in-place * and/or vectorised operations are used. */ - template< Descriptor descr = descriptors::no_operation, class Monoid, typename IOType, typename InputType, typename IOView, typename InputView, typename Coords, bool IOTmp, bool InputTmp > - RC foldr( const VectorView< InputType, InputView, storage::Dense, reference_dense, Coords, InputTmp > & x, - VectorView< IOType, IOView, storage::Dense, reference_dense, Coords, IOTmp > & y, + template< Descriptor descr = descriptors::no_operation, class Monoid, typename IOType, typename InputType, typename IOView, typename InputView, typename Coords > + RC foldr( const VectorView< InputType, InputView, storage::Dense, reference_dense, Coords > & x, + VectorView< IOType, IOView, storage::Dense, reference_dense, Coords > & y, const Monoid & monoid = Monoid(), const typename std::enable_if< grb::is_monoid< Monoid >::value && ! grb::is_object< InputType >::value && ! grb::is_object< IOType >::value, void >::type * = NULL ) { // static sanity checks @@ -1059,10 +1055,10 @@ namespace grb { * * Masked variant. */ - template< Descriptor descr = descriptors::no_operation, class Monoid, typename IOType, typename MaskType, typename InputType, typename IOView, typename MaskView, typename InputView, typename Coords, bool IOTmp, bool MaskTmp, bool InputTmp > - RC foldr( const VectorView< InputType, InputView, storage::Dense, reference_dense, Coords, InputTmp > & x, - const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords, MaskTmp > & m, - VectorView< IOType, IOView, storage::Dense, reference_dense, Coords, IOTmp > & y, + template< Descriptor descr = descriptors::no_operation, class Monoid, typename IOType, typename MaskType, typename InputType, typename IOView, typename MaskView, typename InputView, typename Coords > + RC foldr( const VectorView< InputType, InputView, storage::Dense, reference_dense, Coords > & x, + const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & m, + VectorView< IOType, IOView, storage::Dense, reference_dense, Coords > & y, const Monoid & monoid = Monoid(), const typename std::enable_if< grb::is_monoid< Monoid >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType >::value && ! grb::is_object< IOType >::value, void >::type * = NULL ) { @@ -1169,8 +1165,8 @@ namespace grb { * @see grb::operators::internal::Operator for a discussion on when in-place * and/or vectorised operations are used. */ - template< Descriptor descr = descriptors::no_operation, class Op, typename IOType, typename InputType, typename IOView, typename Coords, bool IOTmp > - RC foldl( VectorView< IOType, IOView, storage::Dense, reference_dense, Coords, IOTmp > & x, + template< Descriptor descr = descriptors::no_operation, class Op, typename IOType, typename InputType, typename IOView, typename Coords > + RC foldl( VectorView< IOType, IOView, storage::Dense, reference_dense, Coords > & x, const InputType beta, const Op & op = Op(), const typename std::enable_if< ! grb::is_object< IOType >::value && ! grb::is_object< InputType >::value && grb::is_operator< Op >::value, void >::type * = NULL ) { @@ -1195,9 +1191,9 @@ namespace grb { * * Masked operator variant. */ - template< Descriptor descr = descriptors::no_operation, class Op, typename IOType, typename MaskType, typename InputType, typename IOView, typename MaskView, typename InputView, typename Coords, bool IOTmp, bool MaskTmp > - RC foldl( VectorView< IOType, IOView, storage::Dense, reference_dense, Coords, IOTmp > & x, - const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords, MaskTmp > & m, + template< Descriptor descr = descriptors::no_operation, class Op, typename IOType, typename MaskType, typename InputType, typename IOView, typename MaskView, typename InputView, typename Coords > + RC foldl( VectorView< IOType, IOView, storage::Dense, reference_dense, Coords > & x, + const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & m, const InputType beta, const Op & op = Op(), const typename std::enable_if< ! grb::is_object< IOType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType >::value && grb::is_operator< Op >::value, void >::type * = @@ -1291,8 +1287,8 @@ namespace grb { * @see grb::operators::internal::Operator for a discussion on when in-place * and/or vectorised operations are used. */ - template< Descriptor descr = descriptors::no_operation, class Monoid, typename IOType, typename InputType, typename IOView, typename Coords, bool IOTmp > - RC foldl( VectorView< IOType, IOView, storage::Dense, reference_dense, Coords, IOTmp > & x, + template< Descriptor descr = descriptors::no_operation, class Monoid, typename IOType, typename InputType, typename IOView, typename Coords > + RC foldl( VectorView< IOType, IOView, storage::Dense, reference_dense, Coords > & x, const InputType beta, const Monoid & monoid = Monoid(), const typename std::enable_if< ! grb::is_object< IOType >::value && ! grb::is_object< InputType >::value && grb::is_monoid< Monoid >::value, void >::type * = NULL ) { @@ -1317,9 +1313,9 @@ namespace grb { * * Masked monoid variant. */ - template< Descriptor descr = descriptors::no_operation, class Monoid, typename IOType, typename MaskType, typename InputType, typename IOView, typename MaskView, typename Coords, bool IOTmp, bool MaskTmp > - RC foldl( VectorView< IOType, IOView, storage::Dense, reference_dense, Coords, IOTmp > & x, - const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords, MaskTmp > & m, + template< Descriptor descr = descriptors::no_operation, class Monoid, typename IOType, typename MaskType, typename InputType, typename IOView, typename MaskView, typename Coords > + RC foldl( VectorView< IOType, IOView, storage::Dense, reference_dense, Coords > & x, + const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & m, const InputType & beta, const Monoid & monoid = Monoid(), const typename std::enable_if< ! grb::is_object< IOType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType >::value && grb::is_monoid< Monoid >::value, void >::type * = @@ -1414,9 +1410,9 @@ namespace grb { * @see grb::operators::internal::Operator for a discussion on when in-place * and/or vectorised operations are used. */ - template< Descriptor descr = descriptors::no_operation, class OP, typename IOType, typename InputType, typename IOView, typename InputView, typename Coords, bool IOTmp, bool InputTmp > - RC foldl( VectorView< IOType, IOView, storage::Dense, reference_dense, Coords, IOTmp > & x, - const VectorView< InputType, InputView, storage::Dense, reference_dense, Coords, InputTmp > & y, + template< Descriptor descr = descriptors::no_operation, class OP, typename IOType, typename InputType, typename IOView, typename InputView, typename Coords > + RC foldl( VectorView< IOType, IOView, storage::Dense, reference_dense, Coords > & x, + const VectorView< InputType, InputView, storage::Dense, reference_dense, Coords > & y, const OP & op = OP(), const typename std::enable_if< grb::is_operator< OP >::value && ! grb::is_object< IOType >::value && ! grb::is_object< InputType >::value, void >::type * = NULL ) { // static sanity checks @@ -1510,9 +1506,9 @@ namespace grb { * @see grb::operators::internal::Operator for a discussion on when in-place * and/or vectorised operations are used. */ - template< Descriptor descr = descriptors::no_operation, class Monoid, typename IOType, typename InputType, typename IOView, typename InputView, typename Coords, bool IOTmp, bool InputTmp > - RC foldl( VectorView< IOType, IOView, storage::Dense, reference_dense, Coords, IOTmp > & x, - const VectorView< InputType, InputView, storage::Dense, reference_dense, Coords, InputTmp > & y, + template< Descriptor descr = descriptors::no_operation, class Monoid, typename IOType, typename InputType, typename IOView, typename InputView, typename Coords > + RC foldl( VectorView< IOType, IOView, storage::Dense, reference_dense, Coords > & x, + const VectorView< InputType, InputView, storage::Dense, reference_dense, Coords > & y, const Monoid & monoid = Monoid(), const typename std::enable_if< grb::is_monoid< Monoid >::value && ! grb::is_object< IOType >::value && ! grb::is_object< InputType >::value, void >::type * = NULL ) { // static sanity checks @@ -1541,14 +1537,10 @@ namespace grb { * * Masked variant. */ - template< Descriptor descr = descriptors::no_operation, class OP, - typename IOType, typename MaskType, typename InputType, - typename IOView, typename MaskView, typename InputView, - typename Coords, - bool IOTmp, bool MaskTmp, bool InputTmp > - RC foldl( VectorView< IOType, IOView, storage::Dense, reference_dense, Coords, IOTmp > & x, - const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords, MaskTmp > & m, - const VectorView< InputType, InputView, storage::Dense, reference_dense, Coords, InputTmp > & y, + template< Descriptor descr = descriptors::no_operation, class OP, typename IOType, typename MaskType, typename InputType, typename IOView, typename MaskView, typename InputView, typename Coords > + RC foldl( VectorView< IOType, IOView, storage::Dense, reference_dense, Coords > & x, + const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & m, + const VectorView< InputType, InputView, storage::Dense, reference_dense, Coords > & y, const OP & op = OP(), const typename std::enable_if< grb::is_operator< OP >::value && ! grb::is_object< IOType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType >::value, void >::type * = NULL ) { @@ -1584,14 +1576,10 @@ namespace grb { * * Masked variant. */ - template< Descriptor descr = descriptors::no_operation, class Monoid, - typename IOType, typename MaskType, typename InputType, - typename IOView, typename MaskView, typename InputView, - typename Coords, - bool IOTmp, bool MaskTmp, bool InputTmp > - RC foldl( VectorView< IOType, IOView, storage::Dense, reference_dense, Coords, IOTmp > & x, - const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords, MaskTmp > & m, - const VectorView< InputType, InputView, storage::Dense, reference_dense, Coords, InputTmp > & y, + template< Descriptor descr = descriptors::no_operation, class Monoid, typename IOType, typename MaskType, typename InputType, typename IOView, typename MaskView, typename InputView, typename Coords > + RC foldl( VectorView< IOType, IOView, storage::Dense, reference_dense, Coords > & x, + const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & m, + const VectorView< InputType, InputView, storage::Dense, reference_dense, Coords > & y, const Monoid & monoid = Monoid(), const typename std::enable_if< grb::is_monoid< Monoid >::value && ! grb::is_object< IOType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType >::value, void >::type * = NULL ) { @@ -1695,13 +1683,9 @@ namespace grb { // * this. // * \endparblock */ - template< Descriptor descr = descriptors::no_operation, class OP, - typename OutputType, typename InputType1, typename InputType2, - typename OutputView, typename InputView1, typename InputView2, - typename Coords, - bool OutputTmp, bool InputTmp > - RC eWiseApply( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & z, - const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords, InputTmp > & x, + template< Descriptor descr = descriptors::no_operation, class OP, typename OutputType, typename InputType1, typename InputType2, typename OutputView, typename InputView1, typename InputView2, typename Coords > + RC eWiseApply( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, + const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords > & x, const InputType2 beta, const OP & op = OP(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_operator< OP >::value, @@ -1718,12 +1702,8 @@ namespace grb { * * Specialisation for \a x and \a y scalar, operator version. */ - template< Descriptor descr = descriptors::no_operation, class OP, - typename OutputType, typename InputType1, typename InputType2, - typename OutputView, typename InputView1, typename InputView2, - typename Coords, - bool OutputTmp > - RC eWiseApply( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & z, + template< Descriptor descr = descriptors::no_operation, class OP, typename OutputType, typename InputType1, typename InputType2, typename OutputView, typename InputView1, typename InputView2, typename Coords > + RC eWiseApply( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, const InputType1 alpha, const InputType2 beta, const OP & op = OP(), @@ -1743,12 +1723,8 @@ namespace grb { * * Specialisation for \a x and \a y scalar, monoid version. */ - template< Descriptor descr = descriptors::no_operation, class Monoid, - typename OutputType, typename InputType1, typename InputType2, - typename OutputView, typename InputView1, typename InputView2, - typename Coords, - bool OutputTmp > - RC eWiseApply( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & z, + template< Descriptor descr = descriptors::no_operation, class Monoid, typename OutputType, typename InputType1, typename InputType2, typename OutputView, typename InputView1, typename InputView2, typename Coords > + RC eWiseApply( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, const InputType1 alpha, const InputType2 beta, const Monoid & monoid = Monoid(), @@ -1766,14 +1742,10 @@ namespace grb { * * Specialisation for scalar \a y, masked operator version. */ - template< Descriptor descr = descriptors::no_operation, class OP, - typename OutputType, typename MaskType, typename InputType1, typename InputType2, - typename OutputView, typename MaskView, typename InputView1, - typename Coords, - bool OutputTmp, bool MaskTmp, bool InputTmp1 > - RC eWiseApply( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & z, - const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords, MaskTmp > & mask, - const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords, InputTmp1 > & x, + template< Descriptor descr = descriptors::no_operation, class OP, typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename OutputView, typename MaskView, typename InputView1, typename InputView2, typename Coords > + RC eWiseApply( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, + const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & mask, + const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords > & x, const InputType2 beta, const OP & op = OP(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && @@ -1795,14 +1767,10 @@ namespace grb { * * Monoid version. */ - template< Descriptor descr = descriptors::no_operation, class Monoid, - typename OutputType, typename InputType1, typename InputType2, - typename OutputView, typename InputView1, typename InputView2, - typename Coords, - bool OutputTmp, bool InputTmp1, bool InputTmp2 > - RC eWiseApply( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & z, - const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords, InputTmp1 > & x, - const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords, InputTmp2 > & y, + template< Descriptor descr = descriptors::no_operation, class Monoid, typename OutputType, typename InputType1, typename InputType2, typename OutputView, typename InputView1, typename InputView2, typename Coords > + RC eWiseApply( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, + const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords > & x, + const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords > & y, const Monoid & monoid = Monoid(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_monoid< Monoid >::value, void >::type * const = NULL ) { @@ -1818,14 +1786,10 @@ namespace grb { * * Specialisation for scalar \a x. Monoid version. */ - template< Descriptor descr = descriptors::no_operation, class Monoid, - typename OutputType, typename InputType1, typename InputType2, - typename OutputView, typename InputView1, typename InputView2, - typename Coords, - bool OutputTmp, bool InputTmp2 > - RC eWiseApply( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & z, + template< Descriptor descr = descriptors::no_operation, class Monoid, typename OutputType, typename InputType1, typename InputType2, typename OutputView, typename InputView1, typename InputView2, typename Coords > + RC eWiseApply( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, const InputType1 alpha, - const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords, InputTmp2 > & y, + const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords > & y, const Monoid & monoid = Monoid(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_monoid< Monoid >::value, void >::type * const = NULL ) { @@ -1841,13 +1805,9 @@ namespace grb { * * Specialisation for scalar \a y. Monoid version. */ - template< Descriptor descr = descriptors::no_operation, class Monoid, - typename OutputType, typename InputType1, typename InputType2, - typename OutputView, typename InputView1, typename InputView2, - typename Coords, - bool OutputTmp, bool InputTmp1 > - RC eWiseApply( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & z, - const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords, InputTmp1 > & x, + template< Descriptor descr = descriptors::no_operation, class Monoid, typename OutputType, typename InputType1, typename InputType2, typename OutputView, typename InputView1, typename InputView2, typename Coords > + RC eWiseApply( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, + const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords > & x, const InputType2 beta, const Monoid & monoid = Monoid(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_monoid< Monoid >::value, @@ -1864,15 +1824,11 @@ namespace grb { * * Masked monoid version. */ - template< Descriptor descr = descriptors::no_operation, class Monoid, - typename OutputType, typename MaskType, typename InputType1, typename InputType2, - typename OutputView, typename MaskView, typename InputView1, typename InputView2, - typename Coords, - bool OutputTmp, bool MaskTmp, bool InputTmp1, bool InputTmp2 > - RC eWiseApply( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & z, - const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords, MaskTmp > & mask, - const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords, InputTmp1 > & x, - const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords, InputTmp2 > & y, + template< Descriptor descr = descriptors::no_operation, class Monoid, typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename OutputView, typename MaskView, typename InputView1, typename InputView2, typename Coords > + RC eWiseApply( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, + const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & mask, + const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords > & x, + const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords > & y, const Monoid & monoid = Monoid(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_monoid< Monoid >::value, @@ -1889,15 +1845,11 @@ namespace grb { * * Specialisation for scalar \a x. Masked monoid version. */ - template< Descriptor descr = descriptors::no_operation, class Monoid, - typename OutputType, typename MaskType, typename InputType1, typename InputType2, - typename OutputView, typename MaskView, typename InputView1, typename InputView2, - typename Coords, - bool OutputTmp, bool MaskTmp, bool InputTmp2 > - RC eWiseApply( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & z, - const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords, MaskTmp > & mask, + template< Descriptor descr = descriptors::no_operation, class Monoid, typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename OutputView, typename MaskView, typename InputView1, typename InputView2, typename Coords > + RC eWiseApply( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, + const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & mask, const InputType1 alpha, - const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords, InputTmp2 > & y, + const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords > & y, const Monoid & monoid = Monoid(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_monoid< Monoid >::value, @@ -1914,14 +1866,10 @@ namespace grb { * * Specialisation for scalar \a y. Masked monoid version. */ - template< Descriptor descr = descriptors::no_operation, class Monoid, - typename OutputType, typename MaskType, typename InputType1, typename InputType2, - typename OutputView, typename MaskView, typename InputView1, - typename Coords, - bool OutputTmp, bool MaskTmp, bool InputTmp1, bool InputTmp2 > - RC eWiseApply( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & z, - const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords, MaskTmp > & mask, - const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords, InputTmp1 > & x, + template< Descriptor descr = descriptors::no_operation, class Monoid, typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename OutputView, typename MaskView, typename InputView1, typename InputView2, typename Coords > + RC eWiseApply( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, + const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & mask, + const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords > & x, const InputType2 beta, const Monoid & monoid = Monoid(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && @@ -1999,14 +1947,10 @@ namespace grb { // * this. // * \endparblock */ - template< Descriptor descr = descriptors::no_operation, class OP, - typename OutputType, typename InputType1, typename InputType2, - typename OutputView, typename InputView1, typename InputView2, - typename Coords, - bool OutputTmp, bool InputTmp2 > - RC eWiseApply( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & z, + template< Descriptor descr = descriptors::no_operation, class OP, typename OutputType, typename InputType1, typename InputType2, typename OutputView, typename InputView1, typename InputView2, typename Coords > + RC eWiseApply( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, const InputType1 alpha, - const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords, InputTmp2 > & y, + const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords > & y, const OP & op = OP(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_operator< OP >::value, void >::type * const = NULL ) { @@ -2022,15 +1966,11 @@ namespace grb { * * Specialisation for scalar \a x. Masked operator version. */ - template< Descriptor descr = descriptors::no_operation, class OP, - typename OutputType, typename MaskType, typename InputType1, typename InputType2, - typename OutputView, typename MaskView, typename InputView1, typename InputView2, - typename Coords, - bool OutputTmp, bool MaskTmp, bool InputTmp2 > - RC eWiseApply( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & z, - const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords, MaskTmp > & mask, + template< Descriptor descr = descriptors::no_operation, class OP, typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename OutputView, typename MaskView, typename InputView1, typename InputView2, typename Coords > + RC eWiseApply( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, + const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & mask, const InputType1 alpha, - const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords, InputTmp2 > & y, + const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords > & y, const OP & op = OP(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_operator< OP >::value, @@ -2110,14 +2050,10 @@ namespace grb { // * used allow for this. // * \endparblock */ - template< Descriptor descr = descriptors::no_operation, class OP, - typename OutputType, typename InputType1, typename InputType2, - typename OutputView, typename InputView1, typename InputView2, - typename Coords, - bool OutputTmp, bool InputTmp1, bool InputTmp2 > - RC eWiseApply( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & z, - const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords, InputTmp1 > & x, - const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords, InputTmp2 > & y, + template< Descriptor descr = descriptors::no_operation, class OP, typename OutputType, typename InputType1, typename InputType2, typename OutputView, typename InputView1, typename InputView2, typename Coords > + RC eWiseApply( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, + const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords > & x, + const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords > & y, const OP & op = OP(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_operator< OP >::value, void >::type * const = NULL ) { @@ -2133,15 +2069,11 @@ namespace grb { * * Masked operator version. */ - template< Descriptor descr = descriptors::no_operation, class OP, - typename OutputType, typename MaskType, typename InputType1, typename InputType2, - typename OutputView, typename MaskView, typename InputView1, typename InputView2, - typename Coords, - bool OutputTmp, bool MaskTmp, bool InputTmp1, bool InputTmp2 > - RC eWiseApply( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & z, - const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords, MaskTmp > & mask, - const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords, InputTmp1 > & x, - const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords, InputTmp2 > & y, + template< Descriptor descr = descriptors::no_operation, class OP, typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename OutputView, typename MaskView, typename InputView1, typename InputView2, typename Coords > + RC eWiseApply( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, + const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & mask, + const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords > & x, + const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords > & y, const OP & op = OP(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_operator< OP >::value, @@ -2231,14 +2163,10 @@ namespace grb { * * @see This is a specialised form of eWiseMulAdd. */ - template< Descriptor descr = descriptors::no_operation, class Ring, - typename OutputType, typename InputType1, typename InputType2, - typename OutputView, typename InputView1, typename InputView2, - typename Coords, - bool OutputTmp, bool InputTmp1, bool InputTmp2 > - RC eWiseAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & z, - const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords, InputTmp1 > & x, - const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords, InputTmp2 > & y, + template< Descriptor descr = descriptors::no_operation, class Ring, typename OutputType, typename InputType1, typename InputType2, typename OutputView, typename InputView1, typename InputView2, typename Coords > + RC eWiseAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, + const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords > & x, + const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords > & y, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_semiring< Ring >::value, void >::type * const = NULL ) { @@ -2264,14 +2192,10 @@ namespace grb { * * Specialisation for scalar \a x. */ - template< Descriptor descr = descriptors::no_operation, class Ring, - typename InputType1, typename InputType2, typename OutputType, - typename InputView2, typename OutputView, - typename Coords, - bool OutputTmp, bool InputTmp2 > - RC eWiseAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & z, + template< Descriptor descr = descriptors::no_operation, class Ring, typename InputType1, typename InputType2, typename OutputType, typename InputView2, typename OutputView, typename Coords > + RC eWiseAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, const InputType1 alpha, - const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords, InputTmp2 > & y, + const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords > & y, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_semiring< Ring >::value, void >::type * const = NULL ) { @@ -2297,13 +2221,9 @@ namespace grb { * * Specialisation for scalar \a y. */ - template< Descriptor descr = descriptors::no_operation, class Ring, - typename InputType1, typename InputType2, typename OutputType, - typename InputView1, typename OutputView, - typename Coords, - bool OutputTmp, bool InputTmp1 > - RC eWiseAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & z, - const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords, InputTmp1 > & x, + template< Descriptor descr = descriptors::no_operation, class Ring, typename InputType1, typename InputType2, typename OutputType, typename InputView1, typename OutputView,typename Coords > + RC eWiseAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, + const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords > & x, const InputType2 beta, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_semiring< Ring >::value, @@ -2330,12 +2250,8 @@ namespace grb { * * Specialisation for scalar \a x and \a y. */ - template< Descriptor descr = descriptors::no_operation, class Ring, - typename InputType1, typename InputType2, typename OutputType, - typename OutputView, - typename Coords, - bool OutputTmp > - RC eWiseAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & z, + template< Descriptor descr = descriptors::no_operation, class Ring, typename InputType1, typename InputType2, typename OutputType, typename OutputView, typename Coords > + RC eWiseAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, const InputType1 alpha, const InputType2 beta, const Ring & ring = Ring(), @@ -2365,15 +2281,11 @@ namespace grb { * * Masked version. */ - template< Descriptor descr = descriptors::no_operation, class Ring, - typename OutputType, typename MaskType, typename InputType1, typename InputType2, - typename OutputView, typename MaskView, typename InputView1, typename InputView2, - typename Coords, - bool OutputTmp, bool MaskTmp, bool InputTmp1, bool InputTmp2 > - RC eWiseAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & z, - const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords, MaskTmp > & m, - const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords, InputTmp1 > & x, - const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords, InputTmp2 > & y, + template< Descriptor descr = descriptors::no_operation, class Ring, typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename OutputView, typename MaskView, typename InputView1, typename InputView2, typename Coords > + RC eWiseAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, + const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & m, + const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords > & x, + const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords > & y, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_semiring< Ring >::value, @@ -2402,15 +2314,11 @@ namespace grb { * * Specialisation for scalar \a x, masked version */ - template< Descriptor descr = descriptors::no_operation, class Ring, - typename InputType1, typename InputType2, typename OutputType, typename MaskType, - typename InputView2, typename OutputView, typename MaskView, - typename Coords, - bool OutputTmp, bool MaskTmp, bool InputTmp2 > - RC eWiseAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & z, - const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords, MaskTmp > & m, + template< Descriptor descr = descriptors::no_operation, class Ring, typename InputType1, typename InputType2, typename OutputType, typename MaskType, typename InputView2, typename OutputView, typename MaskView, typename Coords > + RC eWiseAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, + const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & m, const InputType1 alpha, - const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords, InputTmp2 > & y, + const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords > & y, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_semiring< Ring >::value, @@ -2439,14 +2347,10 @@ namespace grb { * * Specialisation for scalar \a y, masked version. */ - template< Descriptor descr = descriptors::no_operation, class Ring, - typename InputType1, typename InputType2, typename OutputType, typename MaskType, - typename InputView1, typename OutputView, typename MaskView, - typename Coords, - bool OutputTmp, bool MaskTmp, bool InputTmp1 > - RC eWiseAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & z, - const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords, MaskTmp > & m, - const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords, InputTmp1 > & x, + template< Descriptor descr = descriptors::no_operation, class Ring, typename InputType1, typename InputType2, typename OutputType, typename MaskType, typename InputView1, typename OutputView, typename MaskView, typename Coords > + RC eWiseAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, + const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & m, + const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords > & x, const InputType2 beta, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && @@ -2476,13 +2380,9 @@ namespace grb { * * Specialisation for scalar \a x and \a y, masked version. */ - template< Descriptor descr = descriptors::no_operation, class Ring, - typename InputType1, typename InputType2, typename OutputType, typename MaskType, - typename OutputView, - typename Coords, - bool OutputTmp, bool MaskTmp > - RC eWiseAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & z, - const VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & m, /** \internal \todo Should this be MaskType, MaskView (copied as is from reference/blas1.hpp) */ + template< Descriptor descr = descriptors::no_operation, class Ring, typename InputType1, typename InputType2, typename OutputType, typename MaskType, typename OutputView, typename Coords > + RC eWiseAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, + const VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & m, const InputType1 alpha, const InputType2 beta, const Ring & ring = Ring(), @@ -2514,15 +2414,11 @@ namespace grb { * * Specialisation for when \a a is a scalar. */ - template< Descriptor descr = descriptors::no_operation, class Ring, - typename InputType1, typename InputType2, typename InputType3, typename OutputType, - typename InputView2, typename InputView3, typename OutputView, - typename Coords, - bool OutputTmp, bool InputTmp2, bool InputTmp3 > - RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & _z, + template< Descriptor descr = descriptors::no_operation, class Ring, typename InputType1, typename InputType2, typename InputType3, typename OutputType, typename InputView2, typename InputView3, typename OutputView, typename Coords > + RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & _z, const InputType1 alpha, - const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords, InputTmp2 > & _x, - const VectorView< InputType3, InputView3, storage::Dense, reference_dense, Coords, InputTmp3 > & _y, + const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords > & _x, + const VectorView< InputType3, InputView3, storage::Dense, reference_dense, Coords > & _y, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && grb::is_semiring< Ring >::value, @@ -2550,15 +2446,11 @@ namespace grb { * * Specialisation for when \a x is a scalar. */ - template< Descriptor descr = descriptors::no_operation, class Ring, - typename InputType1, typename InputType2, typename InputType3, typename OutputType, - typename InputView1, typename InputView3, typename OutputView, - typename Coords, - bool OutputTmp, bool InputTmp1, bool InputTmp3 > - RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & _z, - const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords, InputTmp1 > & _a, + template< Descriptor descr = descriptors::no_operation, class Ring, typename InputType1, typename InputType2, typename InputType3, typename OutputType, typename InputView1, typename InputView3, typename OutputView, typename Coords > + RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & _z, + const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords > & _a, const InputType2 chi, - const VectorView< InputType3, InputView3, storage::Dense, reference_dense, Coords, InputTmp3 > & _y, + const VectorView< InputType3, InputView3, storage::Dense, reference_dense, Coords > & _y, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && grb::is_semiring< Ring >::value, @@ -2585,14 +2477,10 @@ namespace grb { * * Specialisation for when \a y is a scalar. */ - template< Descriptor descr = descriptors::no_operation, class Ring, - typename InputType1, typename InputType2, typename InputType3, typename OutputType, - typename InputView1, typename InputView2, typename OutputView, - typename Coords, - bool OutputTmp, bool InputTmp1, bool InputTmp2 > - RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & _z, - const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords, InputTmp1 > & _a, - const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords, InputTmp2 > & _x, + template< Descriptor descr = descriptors::no_operation, class Ring, typename InputType1, typename InputType2, typename InputType3, typename OutputType, typename InputView1, typename InputView2, typename OutputView, typename Coords > + RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & _z, + const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords > & _a, + const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords > & _x, const InputType3 gamma, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && @@ -2620,13 +2508,9 @@ namespace grb { * * Specialisation for when \a x and \a y are scalar. */ - template< Descriptor descr = descriptors::no_operation, class Ring, - typename InputType1, typename InputType2, typename InputType3, typename OutputType, - typename InputView1, typename OutputView, - typename Coords, - bool OutputTmp, bool InputTmp1 > - RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & _z, - const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords, InputTmp1 > & _a, + template< Descriptor descr = descriptors::no_operation, class Ring, typename InputType1, typename InputType2, typename InputType3, typename OutputType, typename InputView1, typename OutputView, typename Coords > + RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & _z, + const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords > & _a, const InputType2 beta, const InputType3 gamma, const Ring & ring = Ring(), @@ -2655,14 +2539,10 @@ namespace grb { * * Specialisation for when \a a and \a y are scalar. */ - template< Descriptor descr = descriptors::no_operation, class Ring, - typename InputType1, typename InputType2, typename InputType3, typename OutputType, - typename InputView2, typename OutputView, - typename Coords, - bool OutputTmp, bool InputTmp2 > - RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & _z, + template< Descriptor descr = descriptors::no_operation, class Ring, typename InputType1, typename InputType2, typename InputType3, typename OutputType, typename InputView2, typename OutputView, typename Coords > + RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & _z, const InputType1 alpha, - const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords, InputTmp2 > & _x, + const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords > & _x, const InputType3 gamma, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && @@ -2692,15 +2572,11 @@ namespace grb { * * \internal Dispatches to eWiseAdd. */ - template< Descriptor descr = descriptors::no_operation, class Ring, - typename OutputType, typename InputType1, typename InputType2, typename InputType3, - typename InputView3, typename OutputView, - typename Coords, - bool OutputTmp, bool InputTmp3 > - RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & z, + template< Descriptor descr = descriptors::no_operation, class Ring, typename OutputType, typename InputType1, typename InputType2, typename InputType3, typename InputView3, typename OutputView, typename Coords > + RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, const InputType1 alpha, const InputType2 beta, - const VectorView< InputType3, InputView3, storage::Dense, reference_dense, Coords, InputTmp3 > & y, + const VectorView< InputType3, InputView3, storage::Dense, reference_dense, Coords > & y, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && grb::is_semiring< Ring >::value, @@ -2733,12 +2609,8 @@ namespace grb { * * \internal Dispatches to set. */ - template< Descriptor descr = descriptors::no_operation, class Ring, - typename OutputType, typename InputType1, typename InputType2, typename InputType3, - typename OutputView, - typename Coords, - bool OutputTmp > - RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & z, + template< Descriptor descr = descriptors::no_operation, class Ring, typename OutputType, typename InputType1, typename InputType2, typename InputType3, typename OutputView, typename Coords > + RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, const InputType1 alpha, const InputType2 beta, const InputType3 gamma, @@ -2859,15 +2731,11 @@ namespace grb { // * and the operators used allow for this. // * \endparblock */ - template< Descriptor descr = descriptors::no_operation, class Ring, - typename InputType1, typename InputType2, typename InputType3, typename OutputType, - typename InputView1, typename InputView2, typename InputView3, typename OutputView, - typename Coords, - bool OutputTmp, bool InputTmp1, bool InputTmp2, bool InputTmp3 > - RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & _z, - const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords, InputTmp1 > & _a, - const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords, InputTmp2 > & _x, - const VectorView< InputType3, InputView3, storage::Dense, reference_dense, Coords, InputTmp3 > & _y, + template< Descriptor descr = descriptors::no_operation, class Ring, typename InputType1, typename InputType2, typename InputType3, typename OutputType, typename InputView1, typename InputView2, typename InputView3, typename OutputView, typename Coords > + RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & _z, + const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords > & _a, + const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords > & _x, + const VectorView< InputType3, InputView3, storage::Dense, reference_dense, Coords > & _y, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && grb::is_semiring< Ring >::value, @@ -2965,14 +2833,10 @@ namespace grb { * * @see This is a specialised form of eWiseMulAdd. */ - template< Descriptor descr = descriptors::no_operation, class Ring, - typename InputType1, typename InputType2, typename OutputType, - typename InputView1, typename InputView2, typename OutputView, - typename Coords, - bool OutputTmp, bool InputTmp1, bool InputTmp2 > - RC eWiseMul( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & z, - const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords, InputTmp1 > & x, - const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords, InputTmp2 > & y, + template< Descriptor descr = descriptors::no_operation, class Ring, typename InputType1, typename InputType2, typename OutputType, typename InputView1, typename InputView2, typename OutputView, typename Coords > + RC eWiseMul( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, + const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords > & x, + const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords > & y, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_semiring< Ring >::value, void >::type * const = NULL ) { @@ -2997,14 +2861,10 @@ namespace grb { * * Specialisation for scalar \a x. */ - template< Descriptor descr = descriptors::no_operation, class Ring, - typename InputType1, typename InputType2, typename OutputType, - typename InputView2, typename OutputView, - typename Coords, - bool OutputTmp, bool InputTmp2 > - RC eWiseMul( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & z, + template< Descriptor descr = descriptors::no_operation, class Ring, typename InputType1, typename InputType2, typename OutputType, typename InputView2, typename OutputView, typename Coords > + RC eWiseMul( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, const InputType1 alpha, - const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords, InputTmp2 > & y, + const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords > & y, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_semiring< Ring >::value, void >::type * const = NULL ) { @@ -3029,13 +2889,9 @@ namespace grb { * * Specialisation for scalar \a y. */ - template< Descriptor descr = descriptors::no_operation, class Ring, - typename InputType1, typename InputType2, typename OutputType, - typename InputView1, typename OutputView, - typename Coords, - bool OutputTmp, bool InputTmp2 > - RC eWiseMul( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & z, - const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords, InputTmp2 > & x, + template< Descriptor descr = descriptors::no_operation, class Ring, typename InputType1, typename InputType2, typename OutputType, typename InputView1, typename OutputView, typename Coords > + RC eWiseMul( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, + const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords > & x, const InputType2 beta, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_semiring< Ring >::value, @@ -3061,16 +2917,12 @@ namespace grb { * * Specialisation for when \a a is a scalar, masked version. */ - template< Descriptor descr = descriptors::no_operation, class Ring, - typename InputType1, typename InputType2, typename InputType3, typename OutputType, typename MaskType, - typename InputView2, typename InputView3, typename OutputView, typename MaskView, - typename Coords, - bool OutputTmp, bool MaskTmp, bool InputTmp2, bool InputTmp3 > - RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & _z, - const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords, MaskTmp > & _m, + template< Descriptor descr = descriptors::no_operation, class Ring, typename InputType1, typename InputType2, typename InputType3, typename OutputType, typename MaskType, typename InputView2, typename InputView3, typename OutputView, typename MaskView, typename Coords > + RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & _z, + const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & _m, const InputType1 alpha, - const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords, InputTmp2 > & _x, - const VectorView< InputType3, InputView3, storage::Dense, reference_dense, Coords, InputTmp3 > & _y, + const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords > & _x, + const VectorView< InputType3, InputView3, storage::Dense, reference_dense, Coords > & _y, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && grb::is_semiring< Ring >::value && ! grb::is_object< MaskType >::value, @@ -3099,16 +2951,12 @@ namespace grb { * * Specialisation for when \a x is a scalar, masked version. */ - template< Descriptor descr = descriptors::no_operation, class Ring, - typename InputType1, typename InputType2, typename InputType3, typename OutputType, typename MaskType, - typename InputView1, typename InputView3, typename OutputView, typename MaskView, - typename Coords, - bool OutputTmp, bool MaskTmp, bool InputTmp1, bool InputTmp3 > - RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & _z, - const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords, MaskTmp > & _m, - const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords, InputTmp1 > & _a, + template< Descriptor descr = descriptors::no_operation, class Ring, typename InputType1, typename InputType2, typename InputType3, typename OutputType, typename MaskType, typename InputView1, typename InputView3, typename OutputView, typename MaskView, typename Coords > + RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & _z, + const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & _m, + const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords > & _a, const InputType2 chi, - const VectorView< InputType3, InputView3, storage::Dense, reference_dense, Coords, InputTmp3 > & _y, + const VectorView< InputType3, InputView3, storage::Dense, reference_dense, Coords > & _y, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && grb::is_semiring< Ring >::value && ! grb::is_object< MaskType >::value, @@ -3136,15 +2984,11 @@ namespace grb { * * Specialisation for when \a y is a scalar, masked version. */ - template< Descriptor descr = descriptors::no_operation, class Ring, - typename InputType1, typename InputType2, typename InputType3, typename OutputType, typename MaskType, - typename InputView1, typename InputView2, typename OutputView, typename MaskView, - typename Coords, - bool OutputTmp, bool MaskTmp, bool InputTmp1, bool InputTmp2 > - RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & _z, - const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords, MaskTmp > & _m, - const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords, InputTmp1 > & _a, - const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords, InputTmp2 > & _x, + template< Descriptor descr = descriptors::no_operation, class Ring, typename InputType1, typename InputType2, typename InputType3, typename OutputType, typename MaskType, typename InputView1, typename InputView2, typename OutputView, typename MaskView, typename Coords > + RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & _z, + const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & _m, + const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords > & _a, + const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords > & _x, const InputType3 gamma, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && @@ -3173,14 +3017,11 @@ namespace grb { * * Specialisation for when \a x and \a y are scalar, masked version. */ - template< Descriptor descr = descriptors::no_operation, class Ring, - typename InputType1, typename InputType2, typename InputType3, typename OutputType, typename MaskType, - typename InputView1, typename OutputView, typename MaskView, - typename Coords, - bool OutputTmp, bool MaskTmp, bool InputTmp1 > - RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & _z, - const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords, MaskTmp > & _m, - const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords, InputTmp1 > & _a, + template< Descriptor descr = descriptors::no_operation, class Ring, typename InputType1, typename InputType2, typename InputType3, typename OutputType, typename MaskType, + typename InputView1, typename OutputView, typename MaskView, typename Coords > + RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & _z, + const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & _m, + const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords > & _a, const InputType2 beta, const InputType3 gamma, const Ring & ring = Ring(), @@ -3210,15 +3051,12 @@ namespace grb { * * Specialisation for when \a a and \a y are scalar, masked version. */ - template< Descriptor descr = descriptors::no_operation, class Ring, - typename InputType1, typename InputType2, typename InputType3, typename OutputType, typename MaskType, - typename InputView2, typename OutputView, typename MaskView, - typename Coords, - bool OutputTmp, bool MaskTmp, bool InputTmp2 > - RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & _z, - const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords, MaskTmp > & _m, + template< Descriptor descr = descriptors::no_operation, class Ring, typename InputType1, typename InputType2, typename InputType3, typename OutputType, typename MaskType, + typename InputView2, typename OutputView, typename MaskView, typename Coords > + RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & _z, + const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & _m, const InputType1 alpha, - const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords, InputTmp2 > & _x, + const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords > & _x, const InputType3 gamma, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && @@ -3247,16 +3085,13 @@ namespace grb { * * Masked version. */ - template< Descriptor descr = descriptors::no_operation, class Ring, - typename InputType1, typename InputType2, typename InputType3, typename OutputType, typename MaskType, - typename InputView1, typename InputView2, typename InputView3, typename OutputView, typename MaskView, - typename Coords, - bool OutputTmp, bool MaskTmp, bool InputTmp1, bool InputTmp2, bool InputTmp3 > - RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & _z, - const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords, MaskTmp > & _m, - const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords, InputTmp1 > & _a, - const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords, InputTmp2 > & _x, - const VectorView< InputType3, InputView3, storage::Dense, reference_dense, Coords, InputTmp3 > & _y, + template< Descriptor descr = descriptors::no_operation, class Ring, typename InputType1, typename InputType2, typename InputType3, typename OutputType, typename MaskType, + typename InputView1, typename InputView2, typename InputView3, typename OutputView, typename MaskView, typename Coords > + RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & _z, + const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & _m, + const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords > & _a, + const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords > & _x, + const VectorView< InputType3, InputView3, storage::Dense, reference_dense, Coords > & _y, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && grb::is_semiring< Ring >::value && ! grb::is_object< MaskType >::value, @@ -3289,15 +3124,12 @@ namespace grb { * * \internal Dispatches to eWiseMulAdd with zero additive scalar. */ - template< Descriptor descr = descriptors::no_operation, class Ring, - typename InputType1, typename InputType2, typename OutputType, typename MaskType, - typename InputView1, typename InputView2, typename OutputView, typename MaskView, - typename Coords, - bool OutputTmp, bool MaskTmp, bool InputTmp1, bool InputTmp2 > - RC eWiseMul( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & z, - const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords, MaskTmp > & m, - const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords, InputTmp1 > & x, - const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords, InputTmp2 > & y, + template< Descriptor descr = descriptors::no_operation, class Ring, typename InputType1, typename InputType2, typename OutputType, typename MaskType, + typename InputView1, typename InputView2, typename InputView3, typename OutputView, typename MaskView, typename Coords > + RC eWiseMul( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, + const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & m, + const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords > & x, + const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords > & y, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< MaskType >::value && grb::is_semiring< Ring >::value, @@ -3326,15 +3158,12 @@ namespace grb { * * \internal Dispatches to eWiseMulAdd with zero additive scalar. */ - template< Descriptor descr = descriptors::no_operation, class Ring, - typename InputType1, typename InputType2, typename OutputType, typename MaskType, - typename InputView2, typename InputView3, typename OutputView, typename MaskView, - typename Coords, - bool OutputTmp, bool MaskTmp, bool InputTmp2 > - RC eWiseMul( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & z, - const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords, MaskTmp > & m, + template< Descriptor descr = descriptors::no_operation, class Ring, typename InputType1, typename InputType2, typename OutputType, typename MaskType, + typename InputView2, typename InputView3, typename OutputView, typename MaskView, typename Coords > + RC eWiseMul( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, + const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & m, const InputType1 alpha, - const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords, InputTmp2 > & y, + const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords > & y, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< MaskType >::value && grb::is_semiring< Ring >::value, @@ -3363,14 +3192,11 @@ namespace grb { * * \internal Dispatches to eWiseMulAdd with zero additive scalar. */ - template< Descriptor descr = descriptors::no_operation, class Ring, - typename InputType1, typename InputType2, typename OutputType, typename MaskType, - typename InputView1, typename InputView3, typename OutputView, typename MaskView, - typename Coords, - bool OutputTmp, bool MaskTmp, bool InputTmp1 > - RC eWiseMul( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & z, - const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords, MaskTmp > & m, - const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords, InputTmp1 > & x, + template< Descriptor descr = descriptors::no_operation, class Ring, typename InputType1, typename InputType2, typename OutputType, typename MaskType, + typename InputView1, typename InputView3, typename OutputView, typename MaskView, typename Coords > + RC eWiseMul( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, + const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & m, + const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords > & x, const InputType2 beta, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< MaskType >::value && @@ -3400,16 +3226,13 @@ namespace grb { * * \internal Dispatches to masked eWiseAdd. */ - template< Descriptor descr = descriptors::no_operation, class Ring, - typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename InputType3, - typename OutputView, typename MaskView, typename InputView3, - typename Coords, - bool OutputTmp, bool MaskTmp, bool InputTmp3 > - RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & z, - const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords, MaskTmp > & m, + template< Descriptor descr = descriptors::no_operation, class Ring, typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename InputType3, + typename OutputView, typename MaskView, typename InputView3, typename Coords > + RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, + const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & m, const InputType1 alpha, const InputType2 beta, - const VectorView< InputType3, InputView3, storage::Dense, reference_dense, Coords, InputTmp3 > & y, + const VectorView< InputType3, InputView3, storage::Dense, reference_dense, Coords > & y, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && grb::is_semiring< Ring >::value && ! grb::is_object< MaskType >::value, @@ -3443,13 +3266,10 @@ namespace grb { * * \internal Dispatches to masked set. */ - template< Descriptor descr = descriptors::no_operation, class Ring, - typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename InputType3, - typename OutputView, typename MaskView, - typename Coords, - bool OutputTmp, bool MaskTmp > - RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords, OutputTmp > & z, - const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords, MaskTmp > & m, + template< Descriptor descr = descriptors::no_operation, class Ring, typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename InputType3, + typename OutputView, typename MaskView, typename Coords > + RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, + const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & m, const InputType1 alpha, const InputType2 beta, const InputType3 gamma, @@ -3492,12 +3312,11 @@ namespace grb { Descriptor descr = descriptors::no_operation, class AddMonoid, class AnyOp, typename OutputType, typename InputType1, typename InputType2, typename OutputView, typename InputView1, typename InputView2, - typename Coords, - bool InputTmp1, bool InputTmp2 + typename Coords > RC dot_generic( OutputType &z, - const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords, InputTmp1 > &x, - const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords, InputTmp2 > &y, + const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords > &x, + const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords > &y, const AddMonoid &addMonoid = AddMonoid(), const AnyOp &anyOp = AnyOp() ) { @@ -3591,12 +3410,11 @@ namespace grb { class AddMonoid, class AnyOp, typename OutputType, typename InputType1, typename InputType2, typename InputView1, typename InputView2, - typename Coords, - bool InputTmp1, bool InputTmp2 + typename Coords > RC dot( OutputType &z, - const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords, InputTmp1 > &x, - const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords, InputTmp2 > &y, + const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords > &x, + const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords > &y, const AddMonoid &addMonoid = AddMonoid(), const AnyOp &anyOp = AnyOp(), const typename std::enable_if< !grb::is_object< OutputType >::value && @@ -3635,8 +3453,8 @@ namespace grb { } /** No implementation notes. */ - template< typename Func, typename DataType, typename DataView, typename Coords, bool DataTmp > - RC eWiseMap( const Func f, VectorView< DataType, DataView, storage::Dense, reference_dense, Coords, DataTmp > & x ) { + template< typename Func, typename DataType, typename DataView, typename Coords > + RC eWiseMap( const Func f, VectorView< DataType, DataView, storage::Dense, reference_dense, Coords > & x ) { throw std::runtime_error( "Needs an implementation." ); return SUCCESS; } @@ -3651,16 +3469,8 @@ namespace grb { * @see VectorView::operator[]() * @see VectorView::lambda_reference */ - template< typename Func, - typename DataType1, typename DataType2, - typename DataView1, typename DataView2, - typename Coords, - bool InputTmp1, bool InputTmp2, - typename... Args > - RC eWiseLambda( const Func f, - const VectorView< DataType1, DataView1, storage::Dense, reference_dense, Coords, InputTmp1 > & x, - const VectorView< DataType2, DataView2, storage::Dense, reference_dense, Coords, InputTmp2 > & y, - Args const &... args ) { + template< typename Func, typename DataType1, typename DataType2, typename DataView1, typename DataView2, typename Coords, typename... Args > + RC eWiseLambda( const Func f, const VectorView< DataType1, DataView1, storage::Dense, reference_dense, Coords > & x, const VectorView< DataType2, DataView2, storage::Dense, reference_dense, Coords > & y, Args const &... args ) { // catch mismatch if( size( x ) != size( y ) ) { return MISMATCH; @@ -3676,8 +3486,8 @@ namespace grb { * @see VectorView::operator[]() * @see VectorView::lambda_reference */ - template< typename Func, typename DataType, typename DataView, typename Coords, bool DataTmp > - RC eWiseLambda( const Func f, const VectorView< DataType, DataView, storage::Dense, reference_dense, Coords, DataTmp > & x ) { + template< typename Func, typename DataType, typename DataView, typename Coords > + RC eWiseLambda( const Func f, const VectorView< DataType, DataView, storage::Dense, reference_dense, Coords > & x ) { #ifdef _DEBUG std::cout << "Info: entering eWiseLambda function on vectors.\n"; #endif @@ -3766,14 +3576,10 @@ namespace grb { * * @see grb::foldl provides similar functionality. */ - template< Descriptor descr = descriptors::no_operation, class Monoid, - typename InputType, typename IOType, typename MaskType, - typename InputView, typename MaskView, - typename Coords, - bool IOTmp, bool MaskTmp > + template< Descriptor descr = descriptors::no_operation, class Monoid, typename InputType, typename IOType, typename MaskType, typename InputView, typename MaskView, typename Coords > RC foldl( IOType & x, - const VectorView< InputType, InputView, storage::Dense, reference_dense, Coords, IOTmp > & y, - const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords, MaskTmp > & mask, + const VectorView< InputType, InputView, storage::Dense, reference_dense, Coords > & y, + const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & mask, const Monoid & monoid = Monoid(), const typename std::enable_if< ! grb::is_object< IOType >::value && ! grb::is_object< InputType >::value && ! grb::is_object< MaskType >::value && grb::is_monoid< Monoid >::value, void >::type * const = NULL ) { @@ -3880,12 +3686,11 @@ namespace grb { class AddMonoid, class AnyOp, typename OutputType, typename InputType1, typename InputType2, typename InputView1, typename InputView2, - typename InputCoords1, typename InputCoords2, - bool InputTmp1, bool InputTmp2 + typename InputCoords1, typename InputCoords2 > RC dot( OutputType &z, - const VectorView< InputType1, InputView1, storage::Dense, reference_dense, InputCoords1, InputTmp1 > &x, - const VectorView< InputType2, InputView2, storage::Dense, reference_dense, InputCoords2, InputTmp2 > &y, + const VectorView< InputType1, InputView1, storage::Dense, reference_dense, InputCoords1 > &x, + const VectorView< InputType2, InputView2, storage::Dense, reference_dense, InputCoords2 > &y, const AddMonoid &addMonoid = AddMonoid(), const AnyOp &anyOp = AnyOp(), const typename std::enable_if< !grb::is_object< OutputType >::value && @@ -3978,12 +3783,11 @@ namespace grb { typename IOType, typename InputType1, typename InputType2, typename InputView1, typename InputView2, typename InputStorage1, typename InputStorage2, - Backend backend, typename Coords1, typename Coords2, - bool InputTmp1, bool InputTmp2 + Backend backend, typename Coords1, typename Coords2 > RC dot( IOType &x, - const VectorView< InputType1, InputView1, InputStorage1, backend, Coords1, InputTmp1 > &left, - const VectorView< InputType2, InputView2, InputStorage2, backend, Coords2, InputTmp2 > &right, + const VectorView< InputType1, InputView1, InputStorage1, backend, Coords1 > &left, + const VectorView< InputType2, InputView2, InputStorage2, backend, Coords2 > &right, const Ring &ring = Ring(), const typename std::enable_if< !grb::is_object< InputType1 >::value && @@ -4028,11 +3832,10 @@ namespace grb { typename InputType, typename OutputType, typename InputView, typename InputStorage, - Backend backend, typename Coords, - bool InputTmp + Backend backend, typename Coords > RC norm2( OutputType &x, - const VectorView< InputType, InputView, InputStorage, backend, Coords, InputTmp > &y, + const VectorView< InputType, InputView, InputStorage, backend, Coords > &y, const Ring &ring = Ring(), const typename std::enable_if< std::is_floating_point< OutputType >::value, diff --git a/include/graphblas/denseref/blas2.hpp b/include/graphblas/denseref/blas2.hpp index 0424f84bf..2d687264f 100644 --- a/include/graphblas/denseref/blas2.hpp +++ b/include/graphblas/denseref/blas2.hpp @@ -52,8 +52,8 @@ namespace grb { * bytes of memory. * \endparblock */ - template< typename InputType, typename InputStructure, typename InputStorage, typename InputView, bool InputTmp > - size_t nrows( const StructuredMatrix< InputType, InputStructure, InputStorage, InputView, reference_dense, InputTmp > & A ) noexcept { + template< typename InputType, typename InputStructure, typename InputStorage, typename InputView > + size_t nrows( const StructuredMatrix< InputType, InputStructure, InputStorage, InputView, reference_dense > & A ) noexcept { return A.m; } @@ -73,8 +73,8 @@ namespace grb { * bytes of memory. * \endparblock */ - template< typename InputType, typename InputStructure, typename InputStorage, typename InputView, bool InputTmp > - size_t ncols( const StructuredMatrix< InputType, InputStructure, InputStorage, InputView, reference_dense, InputTmp > & A ) noexcept { + template< typename InputType, typename InputStructure, typename InputStorage, typename InputView > + size_t ncols( const StructuredMatrix< InputType, InputStructure, InputStorage, InputView, reference_dense > & A ) noexcept { return A.n; } @@ -94,8 +94,8 @@ namespace grb { * bytes of memory. * \endparblock */ - template< typename InputType, typename InputStructure, typename InputStorage, typename InputView, bool InputTmp > - size_t nnz( const StructuredMatrix< InputType, InputStructure, InputStorage, InputView, reference_dense, InputTmp > & A ) noexcept { + template< typename InputType > + size_t nnz( const StructuredMatrix< InputType, InputStructure, InputStorage, InputView, reference_dense > & A ) noexcept { return A.nz; } @@ -126,8 +126,8 @@ namespace grb { * \warning This is an expensive function. Use sparingly and only when * absolutely necessary */ - template< typename InputType, typename InputStructure, typename InputStorage, typename InputView, bool InputTmp > - RC resize( StructuredMatrix< InputType, InputStructure, InputStorage, InputView, reference_dense, InputTmp > & A, const size_t new_nz ) noexcept { + template< typename InputType > + RC resize( StructuredMatrix< InputType, InputStructure, InputStorage, InputView, reference_dense > & A, const size_t new_nz ) noexcept { // delegate return A.resize( new_nz ); } @@ -139,12 +139,11 @@ namespace grb { typename InputType1, typename InputType1, typename InputView1, typename InputStorage1, typename InputType2, typename InputStructure2, typename InputStorage2, typename InputView2, typename InputType3, typename InputType3, typename InputView3, typename InputStorage3, - typename Coords, - bool IOTmp, bool InputTmp1, bool InputTmp2, bool InputTmp3 > - RC vxm( VectorView< IOType, IOView, IOStorage, reference_dense, Coords, IOTmp > & u, - const VectorView< InputType3, InputView3, InputStorage3, reference_dense, Coords, InputTmp3 > & mask, - const VectorView< InputType1, InputView1, InputStorage1, reference_dense, Coords, InputTmp1 > & v, - const StructuredMatrix< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense, InputTmp2 > & A, + typename Coords > + RC vxm( VectorView< IOType, IOView, IOStorage, reference_dense, Coords > & u, + const VectorView< InputType3, InputView3, InputStorage3, reference_dense, Coords > & mask, + const VectorView< InputType1, InputView1, InputStorage1, reference_dense, Coords > & v, + const StructuredMatrix< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > & A, const Ring & ring = Ring(), const typename std::enable_if< grb::is_semiring< Ring >::value, void >::type * const = NULL ) { const VectorView< bool, reference, Coords > empty_mask( 0 ); @@ -159,12 +158,11 @@ namespace grb { typename InputType1, typename InputView1, typename InputStorage1, typename InputType2, typename InputStructure2, typename InputStorage2, typename InputView2, typename InputType3, typename InputView3, typename InputStorage3, - typename Coords, - bool IOTmp, bool InputTmp1, bool InputTmp2, bool InputTmp3 > - RC vxm( VectorView< IOType, IOView, IOStorage, reference_dense, Coords, IOTmp > & u, - const VectorView< InputType3, InputView3, InputStorage3, reference_dense, Coords, InputTmp3 > & mask, - const VectorView< InputType1, InputView1, InputStorage1, reference_dense, Coords, InputTmp1 > & v, - const StructuredMatrix< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense, InputTmp2 > & A, + typename Coords > + RC vxm( VectorView< IOType, IOView, IOStorage, reference_dense, Coords > & u, + const VectorView< InputType3, InputView3, InputStorage3, reference_dense, Coords > & mask, + const VectorView< InputType1, InputView1, InputStorage1, reference_dense, Coords > & v, + const StructuredMatrix< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > & A, const AdditiveMonoid & add = AdditiveMonoid(), const MultiplicativeOperator & mul = MultiplicativeOperator(), const typename std::enable_if< grb::is_monoid< AdditiveMonoid >::value && grb::is_operator< MultiplicativeOperator >::value && ! grb::is_object< IOType >::value && diff --git a/include/graphblas/denseref/blas3.hpp b/include/graphblas/denseref/blas3.hpp index 0079e697b..21d28704c 100644 --- a/include/graphblas/denseref/blas3.hpp +++ b/include/graphblas/denseref/blas3.hpp @@ -785,8 +785,8 @@ namespace grb { bool OutputTmp, typename InputCoords1, typename InputCoords2, class Operator > RC outer( StructuredMatrix< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, OutputTmp > & A, - const VectorView< InputType1, InputView1, InputStorage1, reference_dense, InputCoords1, false > & u, - const VectorView< InputType2, InputView2, InputStorage2, reference_dense, InputCoords2, false > & v, + const VectorView< InputType1, InputView1, InputStorage1, reference_dense, InputCoords1 > & u, + const VectorView< InputType2, InputView2, InputStorage2, reference_dense, InputCoords2 > & v, const Operator & mul = Operator(), const typename std::enable_if< grb::is_operator< Operator >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< OutputType >::value, void >::type * const = NULL ) { diff --git a/include/graphblas/denseref/vector.hpp b/include/graphblas/denseref/vector.hpp index 574ca1828..110c82bde 100644 --- a/include/graphblas/denseref/vector.hpp +++ b/include/graphblas/denseref/vector.hpp @@ -284,8 +284,8 @@ namespace grb { * Here starts spec draft for vectorView */ - template< typename T, typename View, typename C, bool tmp > - size_t getLength( const VectorView< T, View, storage::Dense, reference_dense, C, tmp > &v ) noexcept { + template< typename T, typename View, typename C > + size_t getLength( const VectorView< T, View, storage::Dense, reference_dense, C > &v ) noexcept { return v._length(); } @@ -303,7 +303,7 @@ namespace grb { * Views can be used to create logical \em perspectives on top of a container. * For example, one may decide to refer to the part of the vector or * to reference a diagonal of a matrix as a vector. - * See specialization \a VectorView< T, view::Diagonal< StructuredMatrixT >, storage::Dense, reference_dense, C, tmp > + * See specialization \a VectorView< T, view::Diagonal< StructuredMatrixT >, storage::Dense, reference_dense, C > * as an example of such usage. * * Vector View defined as views on other vectors do not instantiate a @@ -329,24 +329,19 @@ namespace grb { * \a storage::Sparse. * \a VectorView will be allowed to pick storage schemes * defined within their specified \a StorageSchemeType. - * @tparam tmp Whether the vector view is temporary. If \a true and the - * and the vector view can instantiate a physical container - * (i.e., it is defined with \a View = \a view::identity) - * then the framework may or may not decide to actually allocate - * memory for such vector. * */ - template< typename T, typename View, typename C, bool tmp > - class VectorView< T, View, storage::Dense, reference_dense, C, tmp > { }; + template< typename T, typename View, typename C > + class VectorView< T, View, storage::Dense, reference_dense, C > { }; /** * Identity View over a vector container. */ - template< typename T, typename C, bool tmp > - class VectorView< T, view::Identity< void >, storage::Dense, reference_dense, C, tmp > { + template< typename T, typename C > + class VectorView< T, view::Identity< void >, storage::Dense, reference_dense, C > { private: - using self_type = VectorView< T, view::Identity< void >, storage::Dense, reference_dense, C, tmp >; + using self_type = VectorView< T, view::Identity< void >, storage::Dense, reference_dense, C >; /********************* Storage info friends @@ -374,19 +369,13 @@ namespace grb { /** @see Vector::value_type. */ using value_type = T; - /** - * @brief Any vector view type which allocates a physical container provides a version of - * itself for defining a temporary vector of the same type via the \a tmp_t member type. - */ - using tmp_t = VectorView< T, view::Identity< void >, storage::Dense, reference_dense, C, true >; - VectorView( const size_t length ) : v( std::make_unique< Vector< T, reference_dense, C > >( length ) ), imf( std::make_shared< imf::Id >( length ) ), initialized( false ) {} }; // class VectorView with physical container /** Identifies any reference_dense vector as an ALP vector. */ - template< typename T, typename View, typename Storage, typename C, bool tmp > - struct is_container< VectorView< T, View, Storage, reference_dense, C, tmp > > { + template< typename T, typename View, typename Storage, typename C > + struct is_container< VectorView< T, View, Storage, reference_dense, C > > { /** A reference_vector is an ALP object. */ static const constexpr bool value = true; }; @@ -394,11 +383,11 @@ namespace grb { /** * Vector view of a vector only via \a view::Identity of another VectorView. */ - template< typename T, typename VectorViewT, typename C, bool tmp > - class VectorView< T, view::Identity< VectorViewT >, storage::Dense, reference_dense, C, tmp > { + template< typename T, typename VectorViewT, typename C > + class VectorView< T, view::Identity< VectorViewT >, storage::Dense, reference_dense, C > { private: - using self_type = VectorView< T, view::Identity< VectorViewT >, storage::Dense, reference_dense, C, tmp >; + using self_type = VectorView< T, view::Identity< VectorViewT >, storage::Dense, reference_dense, C >; using target_type = VectorViewT; /********************* @@ -442,13 +431,13 @@ namespace grb { /** * Diagonal Vector View of a structured matrix. */ - template< typename T, typename StructuredMatrixT, typename C, bool tmp > - class VectorView< T, view::Diagonal< StructuredMatrixT >, storage::Dense, reference_dense, C, tmp > { + template< typename T, typename StructuredMatrixT, typename C > + class VectorView< T, view::Diagonal< StructuredMatrixT >, storage::Dense, reference_dense, C > { private: /** Exposes the own type and the type of the VectorView object over * which this view is created. */ - using self_type = VectorView< T, view::Diagonal< StructuredMatrixT >, storage::Dense, reference_dense, C, tmp >; + using self_type = VectorView< T, view::Diagonal< StructuredMatrixT >, storage::Dense, reference_dense, C >; using target_type = StructuredMatrixT; /********************* @@ -490,11 +479,11 @@ namespace grb { * * @returns A VectorView object. * */ - template< typename StructuredMatrixT, typename C = internal::DefaultCoordinates, bool tmp = false > - VectorView< typename StructuredMatrixT::value_type, view::Diagonal< StructuredMatrixT >, storage::Dense, reference_dense, C, tmp > + template< typename StructuredMatrixT, typename C = internal::DefaultCoordinates > + VectorView< typename StructuredMatrixT::value_type, view::Diagonal< StructuredMatrixT >, storage::Dense, reference_dense, C > diagonal( StructuredMatrixT &smat ) { - VectorView< typename StructuredMatrixT::value_type, view::Diagonal< StructuredMatrixT >, storage::Dense, reference_dense, C, tmp > smat_diag( smat ); + VectorView< typename StructuredMatrixT::value_type, view::Diagonal< StructuredMatrixT >, storage::Dense, reference_dense, C > smat_diag( smat ); return smat_diag; } @@ -506,11 +495,11 @@ namespace grb { * * @returns A VectorView object. */ - template< typename T, typename View, typename StorageSchemeType, enum Backend backend, typename C = internal::DefaultCoordinates, bool tmp = false > - VectorView< T, view::Identity< VectorView< T, View, StorageSchemeType, backend, C, tmp > >, StorageSchemeType, backend, C, tmp > - get_view( VectorView< T, View, StorageSchemeType, backend, C, tmp > &source ) { + template< typename T, typename View, typename StorageSchemeType, enum Backend backend, typename C = internal::DefaultCoordinates > + VectorView< T, view::Identity< VectorView< T, View, StorageSchemeType, backend, C > >, StorageSchemeType, backend, C > + get_view( VectorView< T, View, StorageSchemeType, backend, C > &source ) { - VectorView< T, view::Identity< VectorView< T, View, StorageSchemeType, backend, C, tmp > >, StorageSchemeType, backend, C, tmp > vec_view( source ); + VectorView< T, view::Identity< VectorView< T, View, StorageSchemeType, backend, C > >, StorageSchemeType, backend, C > vec_view( source ); return vec_view; } @@ -525,11 +514,11 @@ namespace grb { * @returns A VectorView object. */ - template< typename T, typename View, typename StorageSchemeType, enum Backend backend, typename C, bool tmp = false > - VectorView< T, view::Identity< VectorView< T, View, StorageSchemeType, backend, C, tmp > >, StorageSchemeType, backend, C, tmp > - get_view( VectorView< T, View, StorageSchemeType, backend, C, tmp > &source, std::shared_ptr< imf::IMF > imf ) { + template< typename T, typename View, typename StorageSchemeType, enum Backend backend, typename C > + VectorView< T, view::Identity< VectorView< T, View, StorageSchemeType, backend, C > >, StorageSchemeType, backend, C > + get_view( VectorView< T, View, StorageSchemeType, backend, C > &source, std::shared_ptr< imf::IMF > imf ) { - VectorView< T, view::Identity< VectorView< T, View, StorageSchemeType, backend, C, tmp > >, StorageSchemeType, backend, C, tmp > vec_view( source, imf ); + VectorView< T, view::Identity< VectorView< T, View, StorageSchemeType, backend, C > >, StorageSchemeType, backend, C > vec_view( source, imf ); return vec_view; } diff --git a/include/graphblas/vector.hpp b/include/graphblas/vector.hpp index b3e091051..53c72097d 100644 --- a/include/graphblas/vector.hpp +++ b/include/graphblas/vector.hpp @@ -57,7 +57,7 @@ namespace grb { /* * The default value of \a StorageSchemeType could also be made conditional (Dense or Sparse) depending on \a config::default_backend */ - template< typename T, typename View = view::Identity< void >, typename StorageSchemeType = storage::Dense, enum Backend backend = config::default_backend, typename C = internal::DefaultCoordinates, bool tmp = false > + template< typename T, typename View = view::Identity< void >, typename StorageSchemeType = storage::Dense, enum Backend backend = config::default_backend, typename C = internal::DefaultCoordinates > class VectorView; } From 426ce0fca8dbd6098aa9f1456b43134b0b1691b6 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Thu, 3 Mar 2022 13:56:23 +0100 Subject: [PATCH 102/282] Rename Identity view to Original including related variables, typenames and doxygen fixes --- include/graphblas/base/matrix.hpp | 2 +- include/graphblas/denseref/blas2.hpp | 4 +- include/graphblas/denseref/blas3.hpp | 10 +-- include/graphblas/denseref/matrix.hpp | 108 +++++++++++++------------- include/graphblas/denseref/vector.hpp | 22 +++--- include/graphblas/matrix.hpp | 2 +- include/graphblas/vector.hpp | 2 +- include/graphblas/views.hpp | 2 +- 8 files changed, 76 insertions(+), 76 deletions(-) diff --git a/include/graphblas/base/matrix.hpp b/include/graphblas/base/matrix.hpp index 3e72bafbc..4d00e7887 100644 --- a/include/graphblas/base/matrix.hpp +++ b/include/graphblas/base/matrix.hpp @@ -490,7 +490,7 @@ class StructuredMatrix { * When a structured matrix defines a View over another matrix, it contains a pointer * to the latter. Its type can be identified via the View parameter. */ - using target_type = typename std::enable_if >::value, typename View::applied_to>::type; + using target_type = typename std::enable_if >::value, typename View::applied_to>::type; target_type * ref; public : diff --git a/include/graphblas/denseref/blas2.hpp b/include/graphblas/denseref/blas2.hpp index 2d687264f..47386e0c3 100644 --- a/include/graphblas/denseref/blas2.hpp +++ b/include/graphblas/denseref/blas2.hpp @@ -279,7 +279,7 @@ namespace grb { const VectorView< InputType1, InputView1, InputStorage1, reference_dense, Coords > & v, const Ring & ring, const typename std::enable_if< grb::is_semiring< Ring >::value, void >::type * const = NULL ) { - const VectorView< bool, view::Identity< void >, structure::full, reference_dense, Coords > empty_mask( 0 ); + const VectorView< bool, view::Original< void >, structure::full, reference_dense, Coords > empty_mask( 0 ); return mxv< descr, false, false >( u, empty_mask, A, v, empty_mask, ring ); } @@ -293,7 +293,7 @@ namespace grb { const typename std::enable_if< grb::is_monoid< AdditiveMonoid >::value && grb::is_operator< MultiplicativeOperator >::value && ! grb::is_object< IOType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! std::is_same< InputType2, void >::value, void >::type * const = NULL ) { - const grb::VectorView< bool, view::Identity< void >, structure::full, reference_dense, Coords > empty_mask( 0 ); + const grb::VectorView< bool, view::Original< void >, structure::full, reference_dense, Coords > empty_mask( 0 ); return mxv< descr, false, false >( u, empty_mask, A, v, empty_mask, add, mul ); } diff --git a/include/graphblas/denseref/blas3.hpp b/include/graphblas/denseref/blas3.hpp index 21d28704c..476387aef 100644 --- a/include/graphblas/denseref/blas3.hpp +++ b/include/graphblas/denseref/blas3.hpp @@ -177,7 +177,7 @@ namespace grb { class MulMonoid, typename OutputType, typename InputType1, typename InputType2, class Operator, class Monoid, - typename OutputView = view::Identity< void >, typename InputView1 = view::Identity< void >, typename InputView2 = view::Identity< void >, + typename OutputView = view::Original< void >, typename InputView1 = view::Original< void >, typename InputView2 = view::Original< void >, bool OutputTmp, bool InputTmp1, bool InputTmp2 > RC mxm_generic( StructuredMatrix< OutputType, structures::General, storage::Dense, OutputView, reference_dense, OutputTmp > &C, @@ -580,7 +580,7 @@ namespace grb { std::cout << "In grb::eWiseApply_matrix_generic (reference_dense, monoid)\n"; #endif - const StructuredMatrix< InputType1, structures::General, storage::Dense, view::Identity< void >, reference_dense, false> * no_matrix = nullptr; + const StructuredMatrix< InputType1, structures::General, storage::Dense, view::Original< void >, reference_dense, false> * no_matrix = nullptr; return internal::eWiseApply_matrix_generic< true, true, false, descr >( &C, no_matrix, @@ -640,7 +640,7 @@ namespace grb { std::cout << "In grb::eWiseApply_matrix_generic (reference_dense, monoid)\n"; #endif - const StructuredMatrix< InputType2, structures::General, storage::Dense, view::Identity< void >, reference_dense, false > * no_matrix = nullptr; + const StructuredMatrix< InputType2, structures::General, storage::Dense, view::Original< void >, reference_dense, false > * no_matrix = nullptr; return internal::eWiseApply_matrix_generic< true, false, true, descr >( &C, &A, @@ -812,8 +812,8 @@ namespace grb { return MISMATCH; } - grb::StructuredMatrix< InputType1, structures::General, storage::Dense, view::Identity< void >, reference_dense, false > u_matrix( nrows, 1 ); - grb::StructuredMatrix< InputType2, structures::General, storage::Dense, view::Identity< void >, reference_dense, false > v_matrix( 1, ncols ); + grb::StructuredMatrix< InputType1, structures::General, storage::Dense, view::Original< void >, reference_dense, false > u_matrix( nrows, 1 ); + grb::StructuredMatrix< InputType2, structures::General, storage::Dense, view::Original< void >, reference_dense, false > v_matrix( 1, ncols ); // auto u_converter = grb::utils::makeVectorToMatrixConverter< InputType1 >( u, []( const size_t & ind, const InputType1 & val ) { // return std::make_pair( std::make_pair( ind, 0 ), val ); diff --git a/include/graphblas/denseref/matrix.hpp b/include/graphblas/denseref/matrix.hpp index b3a1c0974..a5935777c 100644 --- a/include/graphblas/denseref/matrix.hpp +++ b/include/graphblas/denseref/matrix.hpp @@ -563,8 +563,8 @@ namespace grb { * \a StructuredMatrix will be allowed to pick storage schemes * defined within their specified \a StorageSchemeType. * @tparam View One of the matrix views in \a grb::view. - * All static views except for \a view::Identity (via - * \a view::identity cannot instantiate a new container + * All static views except for \a view::Original (via + * \a view::Original cannot instantiate a new container * and only allow to refer to a previously defined * \a StructuredMatrix. * The \a View parameter should not be used directly @@ -576,7 +576,7 @@ namespace grb { * and the \a dense_structured_matrix.cpp unit test). * @tparam tmp Whether the structured matrix is temporary. If \a true and the * and the structured matrix can instantiate a physical container - * (i.e., it is defined with \a View = \a view::identity) + * (i.e., it is defined with \a View = \a view::Original) * then the framework may or may not decide to actually allocate * memory for such matrix. * @@ -588,7 +588,7 @@ namespace grb { * @brief General matrix with physical container. */ template< typename T, bool tmp > - class StructuredMatrix< T, structures::General, storage::Dense, view::Identity< void >, reference_dense, tmp > : + class StructuredMatrix< T, structures::General, storage::Dense, view::Original< void >, reference_dense, tmp > : public internal::StructuredMatrixContainer< T > { private: @@ -596,12 +596,12 @@ namespace grb { Storage info friends ******************** */ - using self_type = StructuredMatrix< T, structures::General, storage::Dense, view::Identity< void >, reference_dense, tmp >; + using self_type = StructuredMatrix< T, structures::General, storage::Dense, view::Original< void >, reference_dense, tmp >; // template< typename fwd_iterator > - // friend RC buildMatrix( StructuredMatrix< T, structures::General, storage::Dense, view::Identity< void >, reference_dense, tmp > &, const fwd_iterator & start, const fwd_iterator & end ); + // friend RC buildMatrix( StructuredMatrix< T, structures::General, storage::Dense, view::Original< void >, reference_dense, tmp > &, const fwd_iterator & start, const fwd_iterator & end ); template< typename fwd_iterator > - friend RC buildMatrix( StructuredMatrix< T, structures::General, storage::Dense, view::Identity< void >, reference_dense, tmp > & A, const fwd_iterator & start, const fwd_iterator & end ); + friend RC buildMatrix( StructuredMatrix< T, structures::General, storage::Dense, view::Original< void >, reference_dense, tmp > & A, const fwd_iterator & start, const fwd_iterator & end ); template< typename fwd_iterator > RC buildMatrixUnique( const fwd_iterator & start, const fwd_iterator & end ) { @@ -618,11 +618,11 @@ namespace grb { * @brief Any structured matrix type which allocates a physical container provides a version of * itself for defining a temporary matrix of the same type via the \a tmp_t member type. */ - using tmp_t = StructuredMatrix< T, structures::General, storage::Dense, view::Identity< void >, reference_dense, true >; + using tmp_t = StructuredMatrix< T, structures::General, storage::Dense, view::Original< void >, reference_dense, true >; - // A general Structure knows how to define a reference to itself (which is an identity reference view) + // A general Structure knows how to define a reference to itself (which is an original reference view) // as well as other static views. - using identity_t = StructuredMatrix< T, structures::General, storage::Dense, view::Identity< self_type >, reference_dense, tmp >; + using original_t = StructuredMatrix< T, structures::General, storage::Dense, view::Original< self_type >, reference_dense, tmp >; using transpose_t = StructuredMatrix< T, structures::General, storage::Dense, view::Transpose< self_type >, reference_dense, tmp >; StructuredMatrix( const size_t rows, const size_t cols ) : @@ -647,7 +647,7 @@ namespace grb { using value_type = T; using structure = structures::General; - using identity_t = StructuredMatrix< T, structures::General, storage::Dense, view::Identity< self_type >, reference_dense, tmp >; + using original_t = StructuredMatrix< T, structures::General, storage::Dense, view::Original< self_type >, reference_dense, tmp >; using transpose_t = StructuredMatrix< T, structures::General, storage::Dense, view::Transpose< self_type >, reference_dense, tmp >; StructuredMatrix( ) : internal::StructuredMatrixBase( 0, 0 ) {} @@ -660,7 +660,7 @@ namespace grb { }; // StructuredMatrix General reference template< typename T, typename Structure, bool tmp > - class StructuredMatrix< T, Structure, storage::Dense, view::Identity< void >, reference_dense, tmp > : + class StructuredMatrix< T, Structure, storage::Dense, view::Original< void >, reference_dense, tmp > : public internal::StructuredMatrixContainer< T > { private: @@ -668,30 +668,30 @@ namespace grb { Storage info friends ******************** */ - using self_type = StructuredMatrix< T, Structure, storage::Dense, view::Identity< void >, reference_dense, tmp >; + using self_type = StructuredMatrix< T, Structure, storage::Dense, view::Original< void >, reference_dense, tmp >; template< typename fwd_iterator > - friend RC buildMatrix( StructuredMatrix< T, Structure, storage::Dense, view::Identity< void >, reference_dense, tmp > &, const fwd_iterator &, const fwd_iterator ) noexcept; + friend RC buildMatrix( StructuredMatrix< T, Structure, storage::Dense, view::Original< void >, reference_dense, tmp > &, const fwd_iterator &, const fwd_iterator ) noexcept; public: using value_type = T; using structure = Structure; - using tmp_t = StructuredMatrix< T, Structure, storage::Dense, view::Identity< void >, reference_dense, true >; + using tmp_t = StructuredMatrix< T, Structure, storage::Dense, view::Original< void >, reference_dense, true >; /** The type of an identify view over the present type */ - using identity_t = StructuredMatrix< T, Structure, storage::Dense, view::Identity< self_type >, reference_dense, tmp >; + using original_t = StructuredMatrix< T, Structure, storage::Dense, view::Original< self_type >, reference_dense, tmp >; StructuredMatrix( const size_t rows, const size_t cols ) : internal::StructuredMatrixContainer< T >( rows, cols ) {} }; // class StructuredMatrix template< typename T, bool tmp > - class StructuredMatrix< T, structures::Square, storage::Dense, view::Identity< void >, reference_dense, tmp > : + class StructuredMatrix< T, structures::Square, storage::Dense, view::Original< void >, reference_dense, tmp > : public internal::StructuredMatrixContainer< T > { private: - using self_type = StructuredMatrix< T, structures::Square, storage::Dense, view::Identity< void >, reference_dense, tmp >; + using self_type = StructuredMatrix< T, structures::Square, storage::Dense, view::Original< void >, reference_dense, tmp >; template< typename InputType, typename Structure, typename Storage, typename View, typename fwd_iterator > friend RC buildMatrix( StructuredMatrix< InputType, Structure, Storage, View, reference_dense, tmp > &, const fwd_iterator & start, const fwd_iterator & end ) noexcept; @@ -706,9 +706,9 @@ namespace grb { /** Exposes the element type and the structure. */ using value_type = T; using structure = structures::Square; - using tmp_t = StructuredMatrix< T, structures::Square, storage::Dense, view::Identity< void >, reference_dense, true >; + using tmp_t = StructuredMatrix< T, structures::Square, storage::Dense, view::Original< void >, reference_dense, true >; - using identity_t = StructuredMatrix< T, structures::Square, storage::Dense, view::Identity< self_type >, reference_dense, tmp >; + using original_t = StructuredMatrix< T, structures::Square, storage::Dense, view::Original< self_type >, reference_dense, tmp >; using transpose_t = StructuredMatrix< T, structures::Square, storage::Dense, view::Transpose< self_type >, reference_dense, tmp >; StructuredMatrix( const size_t rows ) : @@ -729,7 +729,7 @@ namespace grb { using value_type = T; using structure = structures::Square; - using identity_t = StructuredMatrix< T, structures::Square, storage::Dense, view::Identity< self_type >, reference_dense, tmp >; + using original_t = StructuredMatrix< T, structures::Square, storage::Dense, view::Original< self_type >, reference_dense, tmp >; using transpose_t = StructuredMatrix< T, structures::Square, storage::Dense, view::Transpose< self_type >, reference_dense, tmp >; // ref to empty matrix @@ -745,7 +745,7 @@ namespace grb { // StructuredMatrix UpperTriangular, container template< typename T, bool tmp > - class StructuredMatrix< T, structures::UpperTriangular, storage::Dense, view::Identity< void >, reference_dense, tmp > : + class StructuredMatrix< T, structures::UpperTriangular, storage::Dense, view::Original< void >, reference_dense, tmp > : public internal::StructuredMatrixContainer< T > { private: @@ -753,7 +753,7 @@ namespace grb { Storage info friends ******************** */ - using self_type = StructuredMatrix< T, structures::UpperTriangular, storage::Dense, view::Identity< void >, reference_dense, tmp >; + using self_type = StructuredMatrix< T, structures::UpperTriangular, storage::Dense, view::Original< void >, reference_dense, tmp >; template< typename InputType, typename Structure, typename Storage, typename View, typename fwd_iterator > friend RC buildMatrix( StructuredMatrix< InputType, Structure, Storage, View, reference_dense, tmp > &, const fwd_iterator & start, const fwd_iterator & end ) noexcept; @@ -768,11 +768,11 @@ namespace grb { /** Exposes the element type and the structure. */ using value_type = T; using structure = structures::UpperTriangular; - using tmp_t = StructuredMatrix< T, structures::UpperTriangular, storage::Dense, view::Identity< void >, reference_dense, true >; + using tmp_t = StructuredMatrix< T, structures::UpperTriangular, storage::Dense, view::Original< void >, reference_dense, true >; - // A general Structure knows how to define a reference to itself (which is an identity reference view) + // A general Structure knows how to define a reference to itself (which is an original reference view) // as well as other static views. - using identity_t = StructuredMatrix< T, structures::UpperTriangular, storage::Dense, view::Identity< self_type >, reference_dense, tmp >; + using original_t = StructuredMatrix< T, structures::UpperTriangular, storage::Dense, view::Original< self_type >, reference_dense, tmp >; using transpose_t = StructuredMatrix< T, structures::LowerTriangular, storage::Dense, view::Transpose< self_type >, reference_dense, tmp >; StructuredMatrix( const size_t rows, const size_t cols ) : @@ -794,7 +794,7 @@ namespace grb { using value_type = T; using structure = structures::UpperTriangular; - using identity_t = StructuredMatrix< T, structures::UpperTriangular, storage::Dense, view::Identity< self_type >, reference_dense, tmp >; + using original_t = StructuredMatrix< T, structures::UpperTriangular, storage::Dense, view::Original< self_type >, reference_dense, tmp >; using transpose_t = StructuredMatrix< T, structures::UpperTriangular, storage::Dense, view::Transpose< self_type >, reference_dense, tmp >; // ref to empty matrix @@ -812,7 +812,7 @@ namespace grb { // StructuredMatrix Identity, container // Should Identity be a StructuredMatrixContainer? template< typename T, bool tmp > - class StructuredMatrix< T, structures::Identity, storage::Dense, view::Identity< void >, reference_dense, tmp > : + class StructuredMatrix< T, structures::Identity, storage::Dense, view::Original< void >, reference_dense, tmp > : public internal::StructuredMatrixContainer< T > { private: @@ -820,7 +820,7 @@ namespace grb { Storage info friends ******************** */ - using self_type = StructuredMatrix< T, structures::Identity, storage::Dense, view::Identity< void >, reference_dense, tmp >; + using self_type = StructuredMatrix< T, structures::Identity, storage::Dense, view::Original< void >, reference_dense, tmp >; template< typename InputType, typename Structure, typename Storage, typename View, typename fwd_iterator > friend RC buildMatrix( StructuredMatrix< InputType, Structure, Storage, View, reference_dense, tmp > &, const fwd_iterator & start, const fwd_iterator & end ) noexcept; @@ -835,11 +835,11 @@ namespace grb { /** Exposes the element type and the structure. */ using value_type = T; using structure = structures::Identity; - using tmp_t = StructuredMatrix< T, structures::Identity, storage::Dense, view::Identity< void >, reference_dense, true >; + using tmp_t = StructuredMatrix< T, structures::Identity, storage::Dense, view::Original< void >, reference_dense, true >; - // A general Structure knows how to define a reference to itself (which is an identity reference view) + // A general Structure knows how to define a reference to itself (which is an original reference view) // as well as other static views. - using identity_t = StructuredMatrix< T, structures::Identity, storage::Dense, view::Identity< self_type >, reference_dense, tmp >; + using original_t = StructuredMatrix< T, structures::Identity, storage::Dense, view::Original< self_type >, reference_dense, tmp >; using transpose_t = StructuredMatrix< T, structures::Identity, storage::Dense, view::Transpose< self_type >, reference_dense, tmp >; StructuredMatrix( const size_t rows ) : @@ -867,7 +867,7 @@ namespace grb { /** * - * @brief Generate an identity view where the type is compliant with the source StructuredMatrix. + * @brief Generate an original view where the type is compliant with the source StructuredMatrix. * Version where no target structure is specified. In this case the structure of the source type is assumed. * * @tparam T The matrix' elements type @@ -879,15 +879,15 @@ namespace grb { * * @param source The source structured matrix * - * @return A new identity view over the source structured matrix. + * @return A new original view over the source structured matrix. * */ template< typename T, typename Structure, typename StorageSchemeType, typename View, enum Backend backend, bool tmp > - StructuredMatrix< T, Structure, StorageSchemeType, view::Identity< StructuredMatrix< T, Structure, StorageSchemeType, View, backend, tmp > >, backend, tmp > + StructuredMatrix< T, Structure, StorageSchemeType, view::Original< StructuredMatrix< T, Structure, StorageSchemeType, View, backend, tmp > >, backend, tmp > get_view( StructuredMatrix< T, Structure, StorageSchemeType, View, backend, tmp > &source ) { using source_strmat_t = StructuredMatrix< T, Structure, StorageSchemeType, View, backend, tmp >; - using target_strmat_t = StructuredMatrix< T, Structure, StorageSchemeType, view::Identity< source_strmat_t >, backend, tmp >; + using target_strmat_t = StructuredMatrix< T, Structure, StorageSchemeType, view::Original< source_strmat_t >, backend, tmp >; target_strmat_t target( source ); @@ -896,7 +896,7 @@ namespace grb { /** * - * @brief Generate an identity view where the type is compliant with the source StructuredMatrix. + * @brief Generate an original view where the type is compliant with the source StructuredMatrix. * Version where a target structure is specified. It can only generate a valide type if the target * structure is the same as the source's * or a more specialized one that would preserve its static properties (e.g., symmetric reference @@ -913,18 +913,18 @@ namespace grb { * * @param source The source structured matrix * - * @return A new identity view over the source structured matrix. + * @return A new original view over the source structured matrix. * */ template< typename TargetStructure, typename T, typename Structure, typename StorageSchemeType, typename View, enum Backend backend, bool tmp > - StructuredMatrix< T, TargetStructure, StorageSchemeType, view::Identity< StructuredMatrix< T, Structure, StorageSchemeType, View, backend, tmp > >, backend, tmp > + StructuredMatrix< T, TargetStructure, StorageSchemeType, view::Original< StructuredMatrix< T, Structure, StorageSchemeType, View, backend, tmp > >, backend, tmp > get_view( StructuredMatrix< T, Structure, StorageSchemeType, View, backend, tmp > &source ) { static_assert( structures::is_in< Structure, typename TargetStructure::inferred_structures >::value, "Can only create a view when the target structure is compatible with the source." ); using source_strmat_t = StructuredMatrix< T, Structure, StorageSchemeType, View, backend, tmp >; - using target_strmat_t = StructuredMatrix< T, TargetStructure, StorageSchemeType, view::Identity< source_strmat_t >, backend, tmp >; + using target_strmat_t = StructuredMatrix< T, TargetStructure, StorageSchemeType, view::Original< source_strmat_t >, backend, tmp >; target_strmat_t target( source ); @@ -957,7 +957,7 @@ namespace grb { */ template< typename TargetStructure, typename T, typename Structure, typename StorageSchemeType, typename View, enum Backend backend, bool tmp > - StructuredMatrix< T, TargetStructure, StorageSchemeType, view::Identity< StructuredMatrix< T, Structure, StorageSchemeType, View, backend, tmp > >, backend, tmp > + StructuredMatrix< T, TargetStructure, StorageSchemeType, view::Original< StructuredMatrix< T, Structure, StorageSchemeType, View, backend, tmp > >, backend, tmp > get_view( StructuredMatrix< T, Structure, StorageSchemeType, View, backend, tmp > &source, std::shared_ptr< imf::IMF > imf_r, std::shared_ptr< imf::IMF > imf_c ) { @@ -970,7 +970,7 @@ namespace grb { } using source_strmat_t = StructuredMatrix< T, Structure, StorageSchemeType, View, backend, tmp >; - using target_strmat_t = StructuredMatrix< T, TargetStructure, StorageSchemeType, view::Identity< source_strmat_t >, backend, tmp >; + using target_strmat_t = StructuredMatrix< T, TargetStructure, StorageSchemeType, view::Original< source_strmat_t >, backend, tmp >; target_strmat_t target( source, imf_r, imf_c ); @@ -980,7 +980,7 @@ namespace grb { /** * - * @brief Generate an identity view where the type is compliant with the source StructuredMatrix. + * @brief Generate an original view where the type is compliant with the source StructuredMatrix. * Version where a range of rows and columns are selected to form a new view with specified target * structure. It can only generate a valide type if the target * structure is guaranteed to preserve the static properties of the source's structure. @@ -998,11 +998,11 @@ namespace grb { * @param rng_r A valid range of rows * @param rng_c A valid range of columns * - * @return A new identity view over the source structured matrix. + * @return A new original view over the source structured matrix. * */ template< typename TargetStructure, typename T, typename Structure, typename StorageSchemeType, typename View, enum Backend backend, bool tmp > - StructuredMatrix< T, TargetStructure, StorageSchemeType, view::Identity< StructuredMatrix< T, Structure, StorageSchemeType, View, backend, tmp > >, backend, tmp > + StructuredMatrix< T, TargetStructure, StorageSchemeType, view::Original< StructuredMatrix< T, Structure, StorageSchemeType, View, backend, tmp > >, backend, tmp > get_view( StructuredMatrix< T, Structure, StorageSchemeType, View, backend, tmp > &source, const utils::range& rng_r, const utils::range& rng_c ) { @@ -1015,7 +1015,7 @@ namespace grb { namespace internal { /** * - * @brief Generate an identity view where the type is compliant with the source StructuredMatrix. + * @brief Generate an original view where the type is compliant with the source StructuredMatrix. * Version where a selection of rows and columns expressed as vectors of positions * form a new view with specified target structure. * @@ -1035,11 +1035,11 @@ namespace grb { * @param sel_r A valid vector of row indeces (possibly in any permuted order and with repetition) * @param sel_c A valid vector of column indeces (possibly in any permuted order and with repetition) * - * @return A new identity view over the source structured matrix. + * @return A new original view over the source structured matrix. * */ template< typename TargetStructure, typename T, typename Structure, typename StorageSchemeType, typename View, enum Backend backend, bool tmp > - StructuredMatrix< T, TargetStructure, StorageSchemeType, view::Identity< StructuredMatrix< T, Structure, StorageSchemeType, View, backend, tmp > >, backend, tmp > + StructuredMatrix< T, TargetStructure, StorageSchemeType, view::Original< StructuredMatrix< T, Structure, StorageSchemeType, View, backend, tmp > >, backend, tmp > get_view( StructuredMatrix< T, Structure, StorageSchemeType, View, backend, tmp > &source, const std::vector< size_t >& sel_r, const std::vector< size_t >& sel_c ) { @@ -1052,18 +1052,18 @@ namespace grb { /** Returns a constant reference to an Identity matrix of the provided size */ template< typename T > - const StructuredMatrix< T, structures::Identity, storage::Dense, view::Identity< void >, reference_dense, true > & + const StructuredMatrix< T, structures::Identity, storage::Dense, view::Original< void >, reference_dense, true > & I( const size_t n ) { - using return_type = StructuredMatrix< T, structures::Identity, storage::Dense, view::Identity< void >, reference_dense, true >; + using return_type = StructuredMatrix< T, structures::Identity, storage::Dense, view::Original< void >, reference_dense, true >; return_type * ret = new return_type( n ); return * ret; } /** Returns a constant reference to a Zero matrix of the provided size */ template< typename T > - const StructuredMatrix< T, structures::Zero, storage::Dense, view::Identity< void >, reference_dense, true > & + const StructuredMatrix< T, structures::Zero, storage::Dense, view::Original< void >, reference_dense, true > & Zero( const size_t rows, const size_t cols ) { - using return_type = StructuredMatrix< T, structures::Zero, storage::Dense, view::Identity< void >, reference_dense, true >; + using return_type = StructuredMatrix< T, structures::Zero, storage::Dense, view::Original< void >, reference_dense, true >; return_type * ret = new return_type( rows, cols ); return * ret; } @@ -1073,9 +1073,9 @@ namespace grb { * s = sin( theta ) and c = cos( theta ) */ template< typename T > - const StructuredMatrix< T, structures::Square, storage::Dense, view::Identity< void >, reference_dense, true > & + const StructuredMatrix< T, structures::Square, storage::Dense, view::Original< void >, reference_dense, true > & Givens( const size_t n, const size_t i, const size_t j, const T s, const T c ) { - using return_type = const StructuredMatrix< T, structures::Square, storage::Dense, view::Identity< void >, reference_dense, true >; + using return_type = const StructuredMatrix< T, structures::Square, storage::Dense, view::Original< void >, reference_dense, true >; return_type * ret = new return_type( n ); // TODO: initialize matrix values according to the provided parameters return * ret; diff --git a/include/graphblas/denseref/vector.hpp b/include/graphblas/denseref/vector.hpp index 110c82bde..1245edd77 100644 --- a/include/graphblas/denseref/vector.hpp +++ b/include/graphblas/denseref/vector.hpp @@ -317,8 +317,8 @@ namespace grb { * @tparam T The type of the vector elements. \a T shall not be a GraphBLAS * type. * @tparam View One of the vector views. - * All static views except for \a view::Identity (via - * \a view::identity cannot instantiate a new container + * All static views except for \a view::Original (via + * \a view::Original cannot instantiate a new container * and only allow to refer to a previously defined * \a VectorView. * The \a View parameter should not be used directly @@ -338,10 +338,10 @@ namespace grb { * Identity View over a vector container. */ template< typename T, typename C > - class VectorView< T, view::Identity< void >, storage::Dense, reference_dense, C > { + class VectorView< T, view::Original< void >, storage::Dense, reference_dense, C > { private: - using self_type = VectorView< T, view::Identity< void >, storage::Dense, reference_dense, C >; + using self_type = VectorView< T, view::Original< void >, storage::Dense, reference_dense, C >; /********************* Storage info friends @@ -381,13 +381,13 @@ namespace grb { }; /** - * Vector view of a vector only via \a view::Identity of another VectorView. + * Vector view of a vector only via \a view::Original of another VectorView. */ template< typename T, typename VectorViewT, typename C > - class VectorView< T, view::Identity< VectorViewT >, storage::Dense, reference_dense, C > { + class VectorView< T, view::Original< VectorViewT >, storage::Dense, reference_dense, C > { private: - using self_type = VectorView< T, view::Identity< VectorViewT >, storage::Dense, reference_dense, C >; + using self_type = VectorView< T, view::Original< VectorViewT >, storage::Dense, reference_dense, C >; using target_type = VectorViewT; /********************* @@ -496,10 +496,10 @@ namespace grb { * @returns A VectorView object. */ template< typename T, typename View, typename StorageSchemeType, enum Backend backend, typename C = internal::DefaultCoordinates > - VectorView< T, view::Identity< VectorView< T, View, StorageSchemeType, backend, C > >, StorageSchemeType, backend, C > + VectorView< T, view::Original< VectorView< T, View, StorageSchemeType, backend, C > >, StorageSchemeType, backend, C > get_view( VectorView< T, View, StorageSchemeType, backend, C > &source ) { - VectorView< T, view::Identity< VectorView< T, View, StorageSchemeType, backend, C > >, StorageSchemeType, backend, C > vec_view( source ); + VectorView< T, view::Original< VectorView< T, View, StorageSchemeType, backend, C > >, StorageSchemeType, backend, C > vec_view( source ); return vec_view; } @@ -515,10 +515,10 @@ namespace grb { */ template< typename T, typename View, typename StorageSchemeType, enum Backend backend, typename C > - VectorView< T, view::Identity< VectorView< T, View, StorageSchemeType, backend, C > >, StorageSchemeType, backend, C > + VectorView< T, view::Original< VectorView< T, View, StorageSchemeType, backend, C > >, StorageSchemeType, backend, C > get_view( VectorView< T, View, StorageSchemeType, backend, C > &source, std::shared_ptr< imf::IMF > imf ) { - VectorView< T, view::Identity< VectorView< T, View, StorageSchemeType, backend, C > >, StorageSchemeType, backend, C > vec_view( source, imf ); + VectorView< T, view::Original< VectorView< T, View, StorageSchemeType, backend, C > >, StorageSchemeType, backend, C > vec_view( source, imf ); return vec_view; } diff --git a/include/graphblas/matrix.hpp b/include/graphblas/matrix.hpp index d5699f86a..02f96c1e9 100644 --- a/include/graphblas/matrix.hpp +++ b/include/graphblas/matrix.hpp @@ -54,7 +54,7 @@ namespace grb { /* * The default value of \a StorageSchemeType could also be made conditional (Dense or Sparse) depending on \a config::default_backend */ - template< typename T, typename Structure, typename StorageSchemeType = storage::Dense, typename View = view::Identity< void >, enum Backend backend = config::default_backend, bool tmp = false > + template< typename T, typename Structure, typename StorageSchemeType = storage::Dense, typename View = view::Original< void >, enum Backend backend = config::default_backend, bool tmp = false > class StructuredMatrix; } // namespace grb diff --git a/include/graphblas/vector.hpp b/include/graphblas/vector.hpp index 53c72097d..12f989adf 100644 --- a/include/graphblas/vector.hpp +++ b/include/graphblas/vector.hpp @@ -57,7 +57,7 @@ namespace grb { /* * The default value of \a StorageSchemeType could also be made conditional (Dense or Sparse) depending on \a config::default_backend */ - template< typename T, typename View = view::Identity< void >, typename StorageSchemeType = storage::Dense, enum Backend backend = config::default_backend, typename C = internal::DefaultCoordinates > + template< typename T, typename View = view::Original< void >, typename StorageSchemeType = storage::Dense, enum Backend backend = config::default_backend, typename C = internal::DefaultCoordinates > class VectorView; } diff --git a/include/graphblas/views.hpp b/include/graphblas/views.hpp index 4d8f418bf..429f8f66a 100644 --- a/include/graphblas/views.hpp +++ b/include/graphblas/views.hpp @@ -37,7 +37,7 @@ namespace grb { namespace view { template< typename OriginalType > - struct Identity { + struct Original { using applied_to = OriginalType; From 55e613b14a67a11214464b2a685fb8c6aaabbe5b Mon Sep 17 00:00:00 2001 From: Anonymous Date: Thu, 3 Mar 2022 14:09:37 +0100 Subject: [PATCH 103/282] Rename StructuredMatrix base classes This includes StructuredMatrixBase, StructuredMatrixContainer and StructuredMatrixReference --- include/graphblas/denseref/matrix.hpp | 102 +++++++++++++------------- 1 file changed, 51 insertions(+), 51 deletions(-) diff --git a/include/graphblas/denseref/matrix.hpp b/include/graphblas/denseref/matrix.hpp index a5935777c..854d39dd6 100644 --- a/include/graphblas/denseref/matrix.hpp +++ b/include/graphblas/denseref/matrix.hpp @@ -320,14 +320,14 @@ namespace grb { namespace internal { /** Forward declaration */ template< typename T > - class StructuredMatrixContainer; + class MatrixContainer; /** Container reference getters used by friend functions of specialized StructuredMatrix */ template< typename T > - const Matrix< T, reference_dense > & getContainer( const StructuredMatrixContainer< T > & A ); + const Matrix< T, reference_dense > & getContainer( const MatrixContainer< T > & A ); template< typename T > - Matrix< T, reference_dense > & getContainer( StructuredMatrixContainer< T > & A ); + Matrix< T, reference_dense > & getContainer( MatrixContainer< T > & A ); /** Container reference getters. Defer the call to base class friend function */ template< typename T, typename Structure, typename Storage, typename View, bool tmp > @@ -341,17 +341,17 @@ namespace grb { } /** Forward declaration */ - class StructuredMatrixBase; + class MatrixBase; - size_t nrows( const StructuredMatrixBase & A ) noexcept; + size_t nrows( const MatrixBase & A ) noexcept; - size_t ncols( const StructuredMatrixBase & A ) noexcept; + size_t ncols( const MatrixBase & A ) noexcept; - std::pair< size_t, size_t > dims( const StructuredMatrixBase & A ) noexcept; + std::pair< size_t, size_t > dims( const MatrixBase & A ) noexcept; - bool getInitialized( StructuredMatrixBase & ) noexcept; + bool getInitialized( MatrixBase & ) noexcept; - void getInitialized( StructuredMatrixBase &, bool ) noexcept; + void getInitialized( MatrixBase &, bool ) noexcept; template< typename T, typename Structure, typename Storage, typename View, bool tmp > bool getInitialized( StructuredMatrix< T, Structure, Storage, View, reference_dense, tmp > & A ) noexcept { @@ -385,26 +385,26 @@ namespace grb { * \internal Maybe this class can be inherited by Container and Reference classes below */ - class StructuredMatrixBase { + class MatrixBase { protected: - friend size_t nrows( const StructuredMatrixBase & A ) noexcept { + friend size_t nrows( const MatrixBase & A ) noexcept { return A._dims().first; } - friend size_t ncols( const StructuredMatrixBase & A ) noexcept { + friend size_t ncols( const MatrixBase & A ) noexcept { return A._dims().second; } - friend std::pair< size_t, size_t > dims( const StructuredMatrixBase & A ) noexcept { + friend std::pair< size_t, size_t > dims( const MatrixBase & A ) noexcept { return A._dims(); } - friend bool getInitialized( StructuredMatrixBase & A ) noexcept { + friend bool getInitialized( MatrixBase & A ) noexcept { return A.initialized; } - friend void setInitialized( StructuredMatrixBase & A, bool initialized ) noexcept { + friend void setInitialized( MatrixBase & A, bool initialized ) noexcept { A.initialized = initialized; } @@ -440,12 +440,12 @@ namespace grb { * @param rows The number of rows of the matrix. * @param cols The number of columns of the matrix. */ - StructuredMatrixBase( size_t rows, size_t cols ) : + MatrixBase( size_t rows, size_t cols ) : imf_l( std::make_shared< imf::Id >( rows ) ), imf_r( std::make_shared< imf::Id >( cols ) ), initialized( false ) {} - StructuredMatrixBase( std::shared_ptr< imf::IMF > imf_l, std::shared_ptr< imf::IMF > imf_r ) : + MatrixBase( std::shared_ptr< imf::IMF > imf_l, std::shared_ptr< imf::IMF > imf_r ) : imf_l( imf_l ), imf_r( imf_r ), initialized( false ) {} @@ -456,13 +456,13 @@ namespace grb { * Base class with container-related attributes, used in container-type StructuredMatrix specializations */ template< typename T > - class StructuredMatrixContainer : public StructuredMatrixBase { + class MatrixContainer : public MatrixBase { protected: - friend const Matrix< T, reference_dense > & getContainer( const StructuredMatrixContainer< T > & A ) { + friend const Matrix< T, reference_dense > & getContainer( const MatrixContainer< T > & A ) { return *( A._container ); } - friend Matrix< T, reference_dense > & getContainer( StructuredMatrixContainer< T > & A ) { + friend Matrix< T, reference_dense > & getContainer( MatrixContainer< T > & A ) { return *( A._container ); } @@ -487,8 +487,8 @@ namespace grb { * TODO: Add the storage scheme a parameter to the constructor * so that allocation can be made accordingly, generalizing the full case. */ - StructuredMatrixContainer( size_t rows, size_t cols ) : - StructuredMatrixBase( rows, cols ), + MatrixContainer( size_t rows, size_t cols ) : + MatrixBase( rows, cols ), _container( new Matrix< T, reference_dense >(rows, cols) ), storage_scheme( storage::full ) {} @@ -499,19 +499,19 @@ namespace grb { * */ template< typename TargetType > - class StructuredMatrixReference : public StructuredMatrixBase { + class MatrixReference : public MatrixBase { protected: /** A reference-type view is characterized by an indirect association with a - * physical layout via either another \a StructuredMatrixReference or a \a - * StructuredMatrixContainer. Thus a \a StructuredMatrixReference never allocates + * physical layout via either another \a MatrixReference or a \a + * MatrixContainer. Thus a \a MatrixReference never allocates * memory but only establishes a logical view on top of it. */ TargetType * ref; - StructuredMatrixReference() : StructuredMatrixBase( 0, 0 ), ref( nullptr ) {} - StructuredMatrixReference( TargetType & struct_mat ) : StructuredMatrixBase( nrows( struct_mat ), ncols( struct_mat ) ), ref( & struct_mat ) {} - StructuredMatrixReference( TargetType & struct_mat, std::shared_ptr< imf::IMF > imf_l, std::shared_ptr< imf::IMF > imf_r ) : - StructuredMatrixBase( imf_l, imf_r ), ref( & struct_mat ) {} + MatrixReference() : MatrixBase( 0, 0 ), ref( nullptr ) {} + MatrixReference( TargetType & struct_mat ) : MatrixBase( nrows( struct_mat ), ncols( struct_mat ) ), ref( & struct_mat ) {} + MatrixReference( TargetType & struct_mat, std::shared_ptr< imf::IMF > imf_l, std::shared_ptr< imf::IMF > imf_r ) : + MatrixBase( imf_l, imf_r ), ref( & struct_mat ) {} }; } // namespace internal @@ -589,7 +589,7 @@ namespace grb { */ template< typename T, bool tmp > class StructuredMatrix< T, structures::General, storage::Dense, view::Original< void >, reference_dense, tmp > : - public internal::StructuredMatrixContainer< T > { + public internal::MatrixContainer< T > { private: /********************* @@ -626,7 +626,7 @@ namespace grb { using transpose_t = StructuredMatrix< T, structures::General, storage::Dense, view::Transpose< self_type >, reference_dense, tmp >; StructuredMatrix( const size_t rows, const size_t cols ) : - internal::StructuredMatrixContainer< T >( rows, cols ) { + internal::MatrixContainer< T >( rows, cols ) { } }; // StructuredMatrix General, container @@ -636,7 +636,7 @@ namespace grb { */ template< typename T, typename View, bool tmp > class StructuredMatrix< T, structures::General, storage::Dense, View, reference_dense, tmp > : - public internal::StructuredMatrixReference< typename View::applied_to > { + public internal::MatrixReference< typename View::applied_to > { private: using self_type = StructuredMatrix< T, structures::General, storage::Dense, View, reference_dense, tmp >; @@ -650,18 +650,18 @@ namespace grb { using original_t = StructuredMatrix< T, structures::General, storage::Dense, view::Original< self_type >, reference_dense, tmp >; using transpose_t = StructuredMatrix< T, structures::General, storage::Dense, view::Transpose< self_type >, reference_dense, tmp >; - StructuredMatrix( ) : internal::StructuredMatrixBase( 0, 0 ) {} + StructuredMatrix( ) : internal::MatrixBase( 0, 0 ) {} - StructuredMatrix( target_type & struct_mat ) : internal::StructuredMatrixReference< target_type >( struct_mat ) {} + StructuredMatrix( target_type & struct_mat ) : internal::MatrixReference< target_type >( struct_mat ) {} StructuredMatrix( target_type & struct_mat, std::shared_ptr< imf::IMF > imf_l, std::shared_ptr< imf::IMF > imf_r ) : - internal::StructuredMatrixReference< target_type >( struct_mat, imf_l, imf_r ) {} + internal::MatrixReference< target_type >( struct_mat, imf_l, imf_r ) {} }; // StructuredMatrix General reference template< typename T, typename Structure, bool tmp > class StructuredMatrix< T, Structure, storage::Dense, view::Original< void >, reference_dense, tmp > : - public internal::StructuredMatrixContainer< T > { + public internal::MatrixContainer< T > { private: /********************* @@ -683,12 +683,12 @@ namespace grb { using original_t = StructuredMatrix< T, Structure, storage::Dense, view::Original< self_type >, reference_dense, tmp >; StructuredMatrix( const size_t rows, const size_t cols ) : - internal::StructuredMatrixContainer< T >( rows, cols ) {} + internal::MatrixContainer< T >( rows, cols ) {} }; // class StructuredMatrix template< typename T, bool tmp > class StructuredMatrix< T, structures::Square, storage::Dense, view::Original< void >, reference_dense, tmp > : - public internal::StructuredMatrixContainer< T > { + public internal::MatrixContainer< T > { private: using self_type = StructuredMatrix< T, structures::Square, storage::Dense, view::Original< void >, reference_dense, tmp >; @@ -712,13 +712,13 @@ namespace grb { using transpose_t = StructuredMatrix< T, structures::Square, storage::Dense, view::Transpose< self_type >, reference_dense, tmp >; StructuredMatrix( const size_t rows ) : - internal::StructuredMatrixContainer< T >( rows, rows ) {} + internal::MatrixContainer< T >( rows, rows ) {} }; // StructuredMatrix Square, container template< typename T, typename View, bool tmp > class StructuredMatrix< T, structures::Square, storage::Dense, View, reference_dense, tmp > : - public internal::StructuredMatrixReference< typename View::applied_to > { + public internal::MatrixReference< typename View::applied_to > { private: using self_type = StructuredMatrix< T, structures::Square, storage::Dense, View, reference_dense, tmp >; @@ -733,9 +733,9 @@ namespace grb { using transpose_t = StructuredMatrix< T, structures::Square, storage::Dense, view::Transpose< self_type >, reference_dense, tmp >; // ref to empty matrix - StructuredMatrix( ) : internal::StructuredMatrixReference< target_type >() {} + StructuredMatrix( ) : internal::MatrixReference< target_type >() {} - StructuredMatrix( target_type & struct_mat ) : internal::StructuredMatrixReference< target_type >( struct_mat ) { + StructuredMatrix( target_type & struct_mat ) : internal::MatrixReference< target_type >( struct_mat ) { if( nrows( struct_mat ) != ncols( struct_mat ) ) { throw std::length_error( "Square StructuredMatrix reference to non-square target." ); } @@ -746,7 +746,7 @@ namespace grb { // StructuredMatrix UpperTriangular, container template< typename T, bool tmp > class StructuredMatrix< T, structures::UpperTriangular, storage::Dense, view::Original< void >, reference_dense, tmp > : - public internal::StructuredMatrixContainer< T > { + public internal::MatrixContainer< T > { private: /********************* @@ -776,14 +776,14 @@ namespace grb { using transpose_t = StructuredMatrix< T, structures::LowerTriangular, storage::Dense, view::Transpose< self_type >, reference_dense, tmp >; StructuredMatrix( const size_t rows, const size_t cols ) : - internal::StructuredMatrixContainer< T >( rows, cols ) {} + internal::MatrixContainer< T >( rows, cols ) {} }; // StructuredMatrix UpperTriangular, container // StructuredMatrix UpperTriangular, reference template< typename T, typename View, bool tmp > class StructuredMatrix< T, structures::UpperTriangular, storage::Dense, View, reference_dense, tmp > : - public internal::StructuredMatrixReference< typename View::applied_to > { + public internal::MatrixReference< typename View::applied_to > { private: using self_type = StructuredMatrix< T, structures::UpperTriangular, storage::Dense, View, reference_dense, tmp >; @@ -798,22 +798,22 @@ namespace grb { using transpose_t = StructuredMatrix< T, structures::UpperTriangular, storage::Dense, view::Transpose< self_type >, reference_dense, tmp >; // ref to empty matrix - StructuredMatrix( ) : internal::StructuredMatrixReference< target_type >() {} + StructuredMatrix( ) : internal::MatrixReference< target_type >() {} - StructuredMatrix( target_type & struct_mat ) : internal::StructuredMatrixReference< target_type >( struct_mat ) { + StructuredMatrix( target_type & struct_mat ) : internal::MatrixReference< target_type >( struct_mat ) { // No matter the view it has to be a square matrix } StructuredMatrix( target_type & struct_mat, std::shared_ptr< imf::IMF > imf_l, std::shared_ptr< imf::IMF > imf_r ) : - internal::StructuredMatrixReference< target_type >( struct_mat, imf_l, imf_r ) {} + internal::MatrixReference< target_type >( struct_mat, imf_l, imf_r ) {} }; // StructuredMatrix UpperTriangular, reference // StructuredMatrix Identity, container - // Should Identity be a StructuredMatrixContainer? + // Should Identity be a MatrixContainer? template< typename T, bool tmp > class StructuredMatrix< T, structures::Identity, storage::Dense, view::Original< void >, reference_dense, tmp > : - public internal::StructuredMatrixContainer< T > { + public internal::MatrixContainer< T > { private: /********************* @@ -843,7 +843,7 @@ namespace grb { using transpose_t = StructuredMatrix< T, structures::Identity, storage::Dense, view::Transpose< self_type >, reference_dense, tmp >; StructuredMatrix( const size_t rows ) : - internal::StructuredMatrixContainer< T >( rows, rows ) {} + internal::MatrixContainer< T >( rows, rows ) {} }; // StructuredMatrix Identity, container From 8c03e823e2edb6a771f89f4842aea75efae950d5 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Thu, 3 Mar 2022 14:22:06 +0100 Subject: [PATCH 104/282] Remove tmp template parameter from StructuredMatrix interface --- include/graphblas/base/matrix.hpp | 10 +- include/graphblas/denseref/blas3.hpp | 78 ++++------ include/graphblas/denseref/io.hpp | 4 +- include/graphblas/denseref/matrix.hpp | 204 ++++++++++++-------------- include/graphblas/matrix.hpp | 2 +- 5 files changed, 129 insertions(+), 169 deletions(-) diff --git a/include/graphblas/base/matrix.hpp b/include/graphblas/base/matrix.hpp index 4d00e7887..500d29cd3 100644 --- a/include/graphblas/base/matrix.hpp +++ b/include/graphblas/base/matrix.hpp @@ -437,7 +437,7 @@ RC clear( Matrix< InputType, backend > & A ) noexcept { return UNSUPPORTED; } -template< typename T, typename Structure, typename StorageSchemeType, typename View, enum Backend backend, bool tmp > +template< typename T, typename Structure, typename StorageSchemeType, typename View, enum Backend backend > class StructuredMatrix { @@ -497,9 +497,9 @@ class StructuredMatrix { StructuredMatrix( const size_t m, const size_t n ); - StructuredMatrix( const StructuredMatrix< T, Structure, StorageSchemeType, View, backend, tmp > & other ); + StructuredMatrix( const StructuredMatrix< T, Structure, StorageSchemeType, View, backend > & other ); - StructuredMatrix( StructuredMatrix< T, Structure, StorageSchemeType, View, backend, tmp > && other ); + StructuredMatrix( StructuredMatrix< T, Structure, StorageSchemeType, View, backend > && other ); ~StructuredMatrix(); @@ -510,8 +510,8 @@ class StructuredMatrix { */ template< typename T > struct is_structured_matrix : std::false_type {}; -template< typename T, typename Structure, typename StorageSchemeType, typename View, enum Backend backend, bool tmp > -struct is_structured_matrix< StructuredMatrix< T, Structure, StorageSchemeType, View, backend, tmp > > : std::true_type {}; +template< typename T, typename Structure, typename StorageSchemeType, typename View, enum Backend backend > +struct is_structured_matrix< StructuredMatrix< T, Structure, StorageSchemeType, View, backend > > : std::true_type {}; } // end namespace ``grb'' diff --git a/include/graphblas/denseref/blas3.hpp b/include/graphblas/denseref/blas3.hpp index 476387aef..a11e289bd 100644 --- a/include/graphblas/denseref/blas3.hpp +++ b/include/graphblas/denseref/blas3.hpp @@ -140,12 +140,11 @@ namespace grb { typename OutputType, typename InputType1, typename InputType2, class Operator, class Monoid, typename OutputStructure, typename InputStructure1, typename InputStructure2, - typename OutputView, typename InputView1, typename InputView2, - bool OutputTmp, bool InputTmp1, bool InputTmp2 + typename OutputView, typename InputView1, typename InputView2 > - RC mxm_generic( StructuredMatrix< OutputType, OutputStructure, storage::Dense, OutputView, reference_dense, OutputTmp > &C, - const StructuredMatrix< InputType1, InputStructure1, storage::Dense, InputView1, reference_dense, InputTmp1 > &A, - const StructuredMatrix< InputType2, InputStructure2, storage::Dense, InputView2, reference_dense, InputTmp2 > &B, + RC mxm_generic( StructuredMatrix< OutputType, OutputStructure, storage::Dense, OutputView, reference_dense > &C, + const StructuredMatrix< InputType1, InputStructure1, storage::Dense, InputView1, reference_dense > &A, + const StructuredMatrix< InputType2, InputStructure2, storage::Dense, InputView2, reference_dense > &B, const Operator &oper, const Monoid &monoid, const MulMonoid &mulMonoid, @@ -177,12 +176,11 @@ namespace grb { class MulMonoid, typename OutputType, typename InputType1, typename InputType2, class Operator, class Monoid, - typename OutputView = view::Original< void >, typename InputView1 = view::Original< void >, typename InputView2 = view::Original< void >, - bool OutputTmp, bool InputTmp1, bool InputTmp2 + typename OutputView = view::Original< void >, typename InputView1 = view::Original< void >, typename InputView2 = view::Original< void > > - RC mxm_generic( StructuredMatrix< OutputType, structures::General, storage::Dense, OutputView, reference_dense, OutputTmp > &C, - const StructuredMatrix< InputType1, structures::General, storage::Dense, InputView1, reference_dense, InputTmp1 > &A, - const StructuredMatrix< InputType2, structures::General, storage::Dense, InputView2, reference_dense, InputTmp2 > &B, + RC mxm_generic( StructuredMatrix< OutputType, structures::General, storage::Dense, OutputView, reference_dense > &C, + const StructuredMatrix< InputType1, structures::General, storage::Dense, InputView1, reference_dense > &A, + const StructuredMatrix< InputType2, structures::General, storage::Dense, InputView2, reference_dense > &B, const Operator &oper, const Monoid &monoid, const MulMonoid &mulMonoid, @@ -371,13 +369,12 @@ namespace grb { typename OutputStructure, typename InputStructure1, typename InputStructure2, typename OutputStorage, typename InputStorage1, typename InputStorage2, typename OutputView, typename InputView1, typename InputView2, - bool OutputTmp, bool InputTmp1, bool InputTmp2, class Operator > - RC eWiseApply_matrix_generic( StructuredMatrix< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, OutputTmp > *C, - const StructuredMatrix< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense, InputTmp1 > *A, + RC eWiseApply_matrix_generic( StructuredMatrix< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > *C, + const StructuredMatrix< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense > *A, const InputType1 *alpha, - const StructuredMatrix< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense, InputTmp2 > *B, + const StructuredMatrix< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > *B, const InputType1 *beta, const Operator &oper, const MulMonoid &mulMonoid, @@ -464,9 +461,6 @@ namespace grb { * @tparam OutputView The type of view of the output matrix * @tparam InputView1 The type of view of the left-hand matrix * @tparam InputView2 The type of view of the right-hand matrix - * @tparam OutputTmp If the output matrix is a temporary container - * @tparam InputTmp1 If the left-hand side matrix is a temporary container - * @tparam InputTmp2 If the right-hand side matrix is a temporary container * @tparam MulMonoid The type of monoid used for this element-wise operation * * @param C The output structured matrix @@ -487,12 +481,10 @@ namespace grb { typename OutputStructure, typename InputStructure1, typename InputStructure2, typename OutputStorage, typename InputStorage1, typename InputStorage2, typename OutputView, typename InputView1, typename InputView2, - bool OutputTmp, bool InputTmp1, bool InputTmp2, - class MulMonoid - > - RC eWiseApply( StructuredMatrix< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, OutputTmp > &C, - const StructuredMatrix< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense, InputTmp1 > &A, - const StructuredMatrix< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense, InputTmp2 > &B, + class MulMonoid > + RC eWiseApply( StructuredMatrix< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > &C, + const StructuredMatrix< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense > &A, + const StructuredMatrix< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > &B, const MulMonoid &mulmono, const PHASE phase = NUMERICAL, const typename std::enable_if< !grb::is_object< OutputType >::value && @@ -542,12 +534,10 @@ namespace grb { typename OutputStructure, typename InputStructure2, typename OutputStorage, typename InputStorage2, typename OutputView, typename InputView2, - bool OutputTmp, bool InputTmp2, - class MulMonoid - > - RC eWiseApply( StructuredMatrix< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, OutputTmp > &C, + class MulMonoid > + RC eWiseApply( StructuredMatrix< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > &C, const InputType1 &alpha, - const StructuredMatrix< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense, InputTmp2 > &B, + const StructuredMatrix< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > &B, const MulMonoid &mulmono, const PHASE phase = NUMERICAL, const typename std::enable_if< !grb::is_object< OutputType >::value && @@ -580,7 +570,7 @@ namespace grb { std::cout << "In grb::eWiseApply_matrix_generic (reference_dense, monoid)\n"; #endif - const StructuredMatrix< InputType1, structures::General, storage::Dense, view::Original< void >, reference_dense, false> * no_matrix = nullptr; + const StructuredMatrix< InputType1, structures::General, storage::Dense, view::Original< void >, reference_dense > * no_matrix = nullptr; return internal::eWiseApply_matrix_generic< true, true, false, descr >( &C, no_matrix, @@ -602,11 +592,9 @@ namespace grb { typename OutputStructure, typename InputStructure1, typename OutputStorage, typename InputStorage1, typename OutputView, typename InputView1, - bool OutputTmp, bool InputTmp1, - class MulMonoid - > - RC eWiseApply( StructuredMatrix< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, OutputTmp > &C, - const StructuredMatrix< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense, InputTmp1 > &A, + class MulMonoid > + RC eWiseApply( StructuredMatrix< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > &C, + const StructuredMatrix< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense > &A, const InputType2 &beta, const MulMonoid &mulmono, const PHASE phase = NUMERICAL, @@ -640,7 +628,7 @@ namespace grb { std::cout << "In grb::eWiseApply_matrix_generic (reference_dense, monoid)\n"; #endif - const StructuredMatrix< InputType2, structures::General, storage::Dense, view::Original< void >, reference_dense, false > * no_matrix = nullptr; + const StructuredMatrix< InputType2, structures::General, storage::Dense, view::Original< void >, reference_dense > * no_matrix = nullptr; return internal::eWiseApply_matrix_generic< true, false, true, descr >( &C, &A, @@ -669,9 +657,6 @@ namespace grb { * @tparam OutputView The type of view of the output matrix * @tparam InputView1 The type of view of the left-hand matrix * @tparam InputView2 The type of view of the right-hand matrix - * @tparam OutputTmp If the output matrix is a temporary container - * @tparam InputTmp1 If the left-hand side matrix is a temporary container - * @tparam InputTmp2 If the right-hand side matrix is a temporary container * @tparam Ring The semiring type to perform the element-wise addition * on. * @@ -725,11 +710,10 @@ namespace grb { typename OutputStructure, typename InputStructure1, typename InputStructure2, typename OutputStorage, typename InputStorage1, typename InputStorage2, typename OutputView, typename InputView1, typename InputView2, - bool OutputTmp, bool InputTmp1, bool InputTmp2, typename Ring> - RC eWiseAdd( StructuredMatrix< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, OutputTmp > &C, - const StructuredMatrix< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense, InputTmp1 > &A, - const StructuredMatrix< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense, InputTmp2 > &B, + RC eWiseAdd( StructuredMatrix< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > &C, + const StructuredMatrix< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense > &A, + const StructuredMatrix< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > &B, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_semiring< Ring >::value, void >::type * const = NULL ) { @@ -760,9 +744,6 @@ namespace grb { * @tparam InputView1 The view type applied to the left-hand vector. * @tparam InputView2 The view type applied to the right-hand vector. * @tparam OutputView1 The view type applied to the output vector. - * @tparam InputTmp1 Whether the left-hand vector is a temporary. - * @tparam InputTmp2 Whether the right-hand vector is a temporary. - * @tparam OutputTmp1 Whether the output vector is a temporary. * @tparam Operator The opertor type used for this element-wise operation * * @param A The output structured matrix @@ -782,9 +763,8 @@ namespace grb { typename OutputStructure, typename OutputStorage, typename InputStorage1, typename InputStorage2, typename OutputView, typename InputView1, typename InputView2, - bool OutputTmp, typename InputCoords1, typename InputCoords2, class Operator > - RC outer( StructuredMatrix< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, OutputTmp > & A, + RC outer( StructuredMatrix< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > & A, const VectorView< InputType1, InputView1, InputStorage1, reference_dense, InputCoords1 > & u, const VectorView< InputType2, InputView2, InputStorage2, reference_dense, InputCoords2 > & v, const Operator & mul = Operator(), @@ -812,8 +792,8 @@ namespace grb { return MISMATCH; } - grb::StructuredMatrix< InputType1, structures::General, storage::Dense, view::Original< void >, reference_dense, false > u_matrix( nrows, 1 ); - grb::StructuredMatrix< InputType2, structures::General, storage::Dense, view::Original< void >, reference_dense, false > v_matrix( 1, ncols ); + grb::StructuredMatrix< InputType1, structures::General, storage::Dense, view::Original< void >, reference_dense > u_matrix( nrows, 1 ); + grb::StructuredMatrix< InputType2, structures::General, storage::Dense, view::Original< void >, reference_dense > v_matrix( 1, ncols ); // auto u_converter = grb::utils::makeVectorToMatrixConverter< InputType1 >( u, []( const size_t & ind, const InputType1 & val ) { // return std::make_pair( std::make_pair( ind, 0 ), val ); diff --git a/include/graphblas/denseref/io.hpp b/include/graphblas/denseref/io.hpp index c0111b3ed..bbd2131f4 100644 --- a/include/graphblas/denseref/io.hpp +++ b/include/graphblas/denseref/io.hpp @@ -154,8 +154,8 @@ namespace grb { * * @see grb::buildMatrix */ - template< typename InputType, typename Structure, typename Storage, typename View, bool tmp, typename fwd_iterator > - RC buildMatrix( StructuredMatrix< InputType, Structure, Storage, View, reference_dense, tmp > & A, const fwd_iterator & start, const fwd_iterator & end ) { + template< typename InputType, typename Structure, typename Storage, typename View, typename fwd_iterator > + RC buildMatrix( StructuredMatrix< InputType, Structure, Storage, View, reference_dense > & A, const fwd_iterator & start, const fwd_iterator & end ) noexcept { (void)A; (void)start; (void)end; diff --git a/include/graphblas/denseref/matrix.hpp b/include/graphblas/denseref/matrix.hpp index 854d39dd6..6a5edb2bb 100644 --- a/include/graphblas/denseref/matrix.hpp +++ b/include/graphblas/denseref/matrix.hpp @@ -330,13 +330,13 @@ namespace grb { Matrix< T, reference_dense > & getContainer( MatrixContainer< T > & A ); /** Container reference getters. Defer the call to base class friend function */ - template< typename T, typename Structure, typename Storage, typename View, bool tmp > - const Matrix< T, reference_dense > & getContainer( const StructuredMatrix< T, Structure, Storage, View, reference_dense, tmp > & A ) { + template< typename T, typename Structure, typename Storage, typename View > + const Matrix< T, reference_dense > & getContainer( const StructuredMatrix< T, Structure, Storage, View, reference_dense > & A ) { return getContainer( A ); } - template< typename T, typename Structure, typename Storage, typename View, bool tmp > - Matrix< T, reference_dense > & getContainer( StructuredMatrix< T, Structure, Storage, View, reference_dense, tmp > & A ) { + template< typename T, typename Structure, typename Storage, typename View > + Matrix< T, reference_dense > & getContainer( StructuredMatrix< T, Structure, Storage, View, reference_dense > & A ) { return getContainer( A ); } @@ -353,29 +353,29 @@ namespace grb { void getInitialized( MatrixBase &, bool ) noexcept; - template< typename T, typename Structure, typename Storage, typename View, bool tmp > - bool getInitialized( StructuredMatrix< T, Structure, Storage, View, reference_dense, tmp > & A ) noexcept { + template< typename T, typename Structure, typename Storage, typename View > + bool getInitialized( StructuredMatrix< T, Structure, Storage, View, reference_dense > & A ) noexcept { return getInitialized( A ); } - template< typename T, typename Structure, typename Storage, typename View, bool tmp > - void setInitialized( StructuredMatrix< T, Structure, Storage, View, reference_dense, tmp > & A, bool initialized ) noexcept { + template< typename T, typename Structure, typename Storage, typename View > + void setInitialized( StructuredMatrix< T, Structure, Storage, View, reference_dense > & A, bool initialized ) noexcept { setInitialized( A, initialized ); } } // namespace internal - template< typename D, typename Structure, typename View, bool tmp > - size_t nrows( const StructuredMatrix< D, Structure, storage::Dense, View, reference_dense, tmp > & A ) noexcept { + template< typename D, typename Structure, typename View > + size_t nrows( const StructuredMatrix< D, Structure, storage::Dense, View, reference_dense > & A ) noexcept { return internal::nrows( A ); } - template< typename D, typename Structure, typename View, bool tmp > - size_t ncols( const StructuredMatrix< D, Structure, storage::Dense, View, reference_dense, tmp > & A ) noexcept { + template< typename D, typename Structure, typename View > + size_t ncols( const StructuredMatrix< D, Structure, storage::Dense, View, reference_dense > & A ) noexcept { return internal::ncols( A ); } - template< typename D, typename Structure, typename View, bool tmp > - std::pair< size_t, size_t > dims( const StructuredMatrix< D, Structure, storage::Dense, View, reference_dense, tmp > & A ) noexcept { + template< typename D, typename Structure, typename View > + std::pair< size_t, size_t > dims( const StructuredMatrix< D, Structure, storage::Dense, View, reference_dense > & A ) noexcept { return internal::dims( A ); } @@ -546,8 +546,8 @@ namespace grb { * Structured matrices defined as views on other matrices do not instantiate a * new container but refer to the one used by their targets. * See the two specializations - * \a StructuredMatrix - * and \a StructuredMatrix, reference_dense, tmp > + * \a StructuredMatrix + * and \a StructuredMatrix, reference_dense > * as examples of structured matrix types without and with physical container, respectively. * * Finally, a structured matrix can be declared as temporary, in which case the ALP @@ -574,21 +574,16 @@ namespace grb { * \a grb::diagonal. (See examples of StructuredMatrix * definitions within \a include/graphblas/denseref/matrix.hpp * and the \a dense_structured_matrix.cpp unit test). - * @tparam tmp Whether the structured matrix is temporary. If \a true and the - * and the structured matrix can instantiate a physical container - * (i.e., it is defined with \a View = \a view::Original) - * then the framework may or may not decide to actually allocate - * memory for such matrix. * */ - template< typename T, typename Structure, typename StorageSchemeType, typename View, bool tmp > - class StructuredMatrix { }; + template< typename T, typename Structure, typename StorageSchemeType, typename View > + class StructuredMatrix { }; /** * @brief General matrix with physical container. */ - template< typename T, bool tmp > - class StructuredMatrix< T, structures::General, storage::Dense, view::Original< void >, reference_dense, tmp > : + template< typename T > + class StructuredMatrix< T, structures::General, storage::Dense, view::Original< void >, reference_dense > : public internal::MatrixContainer< T > { private: @@ -596,12 +591,12 @@ namespace grb { Storage info friends ******************** */ - using self_type = StructuredMatrix< T, structures::General, storage::Dense, view::Original< void >, reference_dense, tmp >; + using self_type = StructuredMatrix< T, structures::General, storage::Dense, view::Original< void >, reference_dense >; // template< typename fwd_iterator > - // friend RC buildMatrix( StructuredMatrix< T, structures::General, storage::Dense, view::Original< void >, reference_dense, tmp > &, const fwd_iterator & start, const fwd_iterator & end ); + // friend RC buildMatrix( StructuredMatrix< T, structures::General, storage::Dense, view::Original< void >, reference_dense > &, const fwd_iterator & start, const fwd_iterator & end ); template< typename fwd_iterator > - friend RC buildMatrix( StructuredMatrix< T, structures::General, storage::Dense, view::Original< void >, reference_dense, tmp > & A, const fwd_iterator & start, const fwd_iterator & end ); + friend RC buildMatrix( StructuredMatrix< T, structures::General, storage::Dense, view::Original< void >, reference_dense > & A, const fwd_iterator & start, const fwd_iterator & end ); template< typename fwd_iterator > RC buildMatrixUnique( const fwd_iterator & start, const fwd_iterator & end ) { @@ -614,16 +609,10 @@ namespace grb { using value_type = T; using structure = structures::General; - /** - * @brief Any structured matrix type which allocates a physical container provides a version of - * itself for defining a temporary matrix of the same type via the \a tmp_t member type. - */ - using tmp_t = StructuredMatrix< T, structures::General, storage::Dense, view::Original< void >, reference_dense, true >; - // A general Structure knows how to define a reference to itself (which is an original reference view) // as well as other static views. - using original_t = StructuredMatrix< T, structures::General, storage::Dense, view::Original< self_type >, reference_dense, tmp >; - using transpose_t = StructuredMatrix< T, structures::General, storage::Dense, view::Transpose< self_type >, reference_dense, tmp >; + using original_t = StructuredMatrix< T, structures::General, storage::Dense, view::Original< self_type >, reference_dense >; + using transpose_t = StructuredMatrix< T, structures::General, storage::Dense, view::Transpose< self_type >, reference_dense >; StructuredMatrix( const size_t rows, const size_t cols ) : internal::MatrixContainer< T >( rows, cols ) { @@ -634,12 +623,12 @@ namespace grb { /** * View of a general Matrix. */ - template< typename T, typename View, bool tmp > - class StructuredMatrix< T, structures::General, storage::Dense, View, reference_dense, tmp > : + template< typename T, typename View > + class StructuredMatrix< T, structures::General, storage::Dense, View, reference_dense > : public internal::MatrixReference< typename View::applied_to > { private: - using self_type = StructuredMatrix< T, structures::General, storage::Dense, View, reference_dense, tmp >; + using self_type = StructuredMatrix< T, structures::General, storage::Dense, View, reference_dense >; using target_type = typename View::applied_to; public: @@ -647,8 +636,8 @@ namespace grb { using value_type = T; using structure = structures::General; - using original_t = StructuredMatrix< T, structures::General, storage::Dense, view::Original< self_type >, reference_dense, tmp >; - using transpose_t = StructuredMatrix< T, structures::General, storage::Dense, view::Transpose< self_type >, reference_dense, tmp >; + using original_t = StructuredMatrix< T, structures::General, storage::Dense, view::Original< self_type >, reference_dense >; + using transpose_t = StructuredMatrix< T, structures::General, storage::Dense, view::Transpose< self_type >, reference_dense >; StructuredMatrix( ) : internal::MatrixBase( 0, 0 ) {} @@ -659,8 +648,8 @@ namespace grb { }; // StructuredMatrix General reference - template< typename T, typename Structure, bool tmp > - class StructuredMatrix< T, Structure, storage::Dense, view::Original< void >, reference_dense, tmp > : + template< typename T, typename Structure > + class StructuredMatrix< T, Structure, storage::Dense, view::Original< void >, reference_dense > : public internal::MatrixContainer< T > { private: @@ -668,33 +657,31 @@ namespace grb { Storage info friends ******************** */ - using self_type = StructuredMatrix< T, Structure, storage::Dense, view::Original< void >, reference_dense, tmp >; + using self_type = StructuredMatrix< T, Structure, storage::Dense, view::Original< void >, reference_dense >; template< typename fwd_iterator > - friend RC buildMatrix( StructuredMatrix< T, Structure, storage::Dense, view::Original< void >, reference_dense, tmp > &, const fwd_iterator &, const fwd_iterator ) noexcept; + friend RC buildMatrix( StructuredMatrix< T, Structure, storage::Dense, view::Original< void >, reference_dense > &, const fwd_iterator &, const fwd_iterator ) noexcept; public: using value_type = T; using structure = Structure; - using tmp_t = StructuredMatrix< T, Structure, storage::Dense, view::Original< void >, reference_dense, true >; - /** The type of an identify view over the present type */ - using original_t = StructuredMatrix< T, Structure, storage::Dense, view::Original< self_type >, reference_dense, tmp >; + using original_t = StructuredMatrix< T, Structure, storage::Dense, view::Original< self_type >, reference_dense >; StructuredMatrix( const size_t rows, const size_t cols ) : internal::MatrixContainer< T >( rows, cols ) {} }; // class StructuredMatrix - template< typename T, bool tmp > - class StructuredMatrix< T, structures::Square, storage::Dense, view::Original< void >, reference_dense, tmp > : + template< typename T > + class StructuredMatrix< T, structures::Square, storage::Dense, view::Original< void >, reference_dense > : public internal::MatrixContainer< T > { private: - using self_type = StructuredMatrix< T, structures::Square, storage::Dense, view::Original< void >, reference_dense, tmp >; + using self_type = StructuredMatrix< T, structures::Square, storage::Dense, view::Original< void >, reference_dense >; template< typename InputType, typename Structure, typename Storage, typename View, typename fwd_iterator > - friend RC buildMatrix( StructuredMatrix< InputType, Structure, Storage, View, reference_dense, tmp > &, const fwd_iterator & start, const fwd_iterator & end ) noexcept; + friend RC buildMatrix( StructuredMatrix< InputType, Structure, Storage, View, reference_dense > &, const fwd_iterator & start, const fwd_iterator & end ) noexcept; template< typename fwd_iterator > RC buildMatrixUnique( const fwd_iterator & start, const fwd_iterator & end ) { @@ -706,22 +693,21 @@ namespace grb { /** Exposes the element type and the structure. */ using value_type = T; using structure = structures::Square; - using tmp_t = StructuredMatrix< T, structures::Square, storage::Dense, view::Original< void >, reference_dense, true >; - using original_t = StructuredMatrix< T, structures::Square, storage::Dense, view::Original< self_type >, reference_dense, tmp >; - using transpose_t = StructuredMatrix< T, structures::Square, storage::Dense, view::Transpose< self_type >, reference_dense, tmp >; + using original_t = StructuredMatrix< T, structures::Square, storage::Dense, view::Original< self_type >, reference_dense >; + using transpose_t = StructuredMatrix< T, structures::Square, storage::Dense, view::Transpose< self_type >, reference_dense >; StructuredMatrix( const size_t rows ) : internal::MatrixContainer< T >( rows, rows ) {} }; // StructuredMatrix Square, container - template< typename T, typename View, bool tmp > - class StructuredMatrix< T, structures::Square, storage::Dense, View, reference_dense, tmp > : + template< typename T, typename View > + class StructuredMatrix< T, structures::Square, storage::Dense, View, reference_dense > : public internal::MatrixReference< typename View::applied_to > { private: - using self_type = StructuredMatrix< T, structures::Square, storage::Dense, View, reference_dense, tmp >; + using self_type = StructuredMatrix< T, structures::Square, storage::Dense, View, reference_dense >; using target_type = typename View::applied_to; public: @@ -729,8 +715,8 @@ namespace grb { using value_type = T; using structure = structures::Square; - using original_t = StructuredMatrix< T, structures::Square, storage::Dense, view::Original< self_type >, reference_dense, tmp >; - using transpose_t = StructuredMatrix< T, structures::Square, storage::Dense, view::Transpose< self_type >, reference_dense, tmp >; + using original_t = StructuredMatrix< T, structures::Square, storage::Dense, view::Original< self_type >, reference_dense >; + using transpose_t = StructuredMatrix< T, structures::Square, storage::Dense, view::Transpose< self_type >, reference_dense >; // ref to empty matrix StructuredMatrix( ) : internal::MatrixReference< target_type >() {} @@ -744,8 +730,8 @@ namespace grb { }; // StructuredMatrix Square reference // StructuredMatrix UpperTriangular, container - template< typename T, bool tmp > - class StructuredMatrix< T, structures::UpperTriangular, storage::Dense, view::Original< void >, reference_dense, tmp > : + template< typename T > + class StructuredMatrix< T, structures::UpperTriangular, storage::Dense, view::Original< void >, reference_dense > : public internal::MatrixContainer< T > { private: @@ -753,10 +739,10 @@ namespace grb { Storage info friends ******************** */ - using self_type = StructuredMatrix< T, structures::UpperTriangular, storage::Dense, view::Original< void >, reference_dense, tmp >; + using self_type = StructuredMatrix< T, structures::UpperTriangular, storage::Dense, view::Original< void >, reference_dense >; template< typename InputType, typename Structure, typename Storage, typename View, typename fwd_iterator > - friend RC buildMatrix( StructuredMatrix< InputType, Structure, Storage, View, reference_dense, tmp > &, const fwd_iterator & start, const fwd_iterator & end ) noexcept; + friend RC buildMatrix( StructuredMatrix< InputType, Structure, Storage, View, reference_dense > &, const fwd_iterator & start, const fwd_iterator & end ) noexcept; template< typename fwd_iterator > RC buildMatrixUnique( const fwd_iterator & start, const fwd_iterator & end ) { @@ -768,12 +754,11 @@ namespace grb { /** Exposes the element type and the structure. */ using value_type = T; using structure = structures::UpperTriangular; - using tmp_t = StructuredMatrix< T, structures::UpperTriangular, storage::Dense, view::Original< void >, reference_dense, true >; // A general Structure knows how to define a reference to itself (which is an original reference view) // as well as other static views. - using original_t = StructuredMatrix< T, structures::UpperTriangular, storage::Dense, view::Original< self_type >, reference_dense, tmp >; - using transpose_t = StructuredMatrix< T, structures::LowerTriangular, storage::Dense, view::Transpose< self_type >, reference_dense, tmp >; + using original_t = StructuredMatrix< T, structures::UpperTriangular, storage::Dense, view::Original< self_type >, reference_dense >; + using transpose_t = StructuredMatrix< T, structures::LowerTriangular, storage::Dense, view::Transpose< self_type >, reference_dense >; StructuredMatrix( const size_t rows, const size_t cols ) : internal::MatrixContainer< T >( rows, cols ) {} @@ -781,12 +766,12 @@ namespace grb { }; // StructuredMatrix UpperTriangular, container // StructuredMatrix UpperTriangular, reference - template< typename T, typename View, bool tmp > - class StructuredMatrix< T, structures::UpperTriangular, storage::Dense, View, reference_dense, tmp > : + template< typename T, typename View > + class StructuredMatrix< T, structures::UpperTriangular, storage::Dense, View, reference_dense > : public internal::MatrixReference< typename View::applied_to > { private: - using self_type = StructuredMatrix< T, structures::UpperTriangular, storage::Dense, View, reference_dense, tmp >; + using self_type = StructuredMatrix< T, structures::UpperTriangular, storage::Dense, View, reference_dense >; using target_type = typename View::applied_to; public: @@ -794,8 +779,8 @@ namespace grb { using value_type = T; using structure = structures::UpperTriangular; - using original_t = StructuredMatrix< T, structures::UpperTriangular, storage::Dense, view::Original< self_type >, reference_dense, tmp >; - using transpose_t = StructuredMatrix< T, structures::UpperTriangular, storage::Dense, view::Transpose< self_type >, reference_dense, tmp >; + using original_t = StructuredMatrix< T, structures::UpperTriangular, storage::Dense, view::Original< self_type >, reference_dense >; + using transpose_t = StructuredMatrix< T, structures::UpperTriangular, storage::Dense, view::Transpose< self_type >, reference_dense >; // ref to empty matrix StructuredMatrix( ) : internal::MatrixReference< target_type >() {} @@ -811,8 +796,8 @@ namespace grb { // StructuredMatrix Identity, container // Should Identity be a MatrixContainer? - template< typename T, bool tmp > - class StructuredMatrix< T, structures::Identity, storage::Dense, view::Original< void >, reference_dense, tmp > : + template< typename T > + class StructuredMatrix< T, structures::Identity, storage::Dense, view::Original< void >, reference_dense > : public internal::MatrixContainer< T > { private: @@ -820,10 +805,10 @@ namespace grb { Storage info friends ******************** */ - using self_type = StructuredMatrix< T, structures::Identity, storage::Dense, view::Original< void >, reference_dense, tmp >; + using self_type = StructuredMatrix< T, structures::Identity, storage::Dense, view::Original< void >, reference_dense >; template< typename InputType, typename Structure, typename Storage, typename View, typename fwd_iterator > - friend RC buildMatrix( StructuredMatrix< InputType, Structure, Storage, View, reference_dense, tmp > &, const fwd_iterator & start, const fwd_iterator & end ) noexcept; + friend RC buildMatrix( StructuredMatrix< InputType, Structure, Storage, View, reference_dense > &, const fwd_iterator & start, const fwd_iterator & end ) noexcept; template< typename fwd_iterator > RC buildMatrixUnique( const fwd_iterator & start, const fwd_iterator & end ) { @@ -835,12 +820,11 @@ namespace grb { /** Exposes the element type and the structure. */ using value_type = T; using structure = structures::Identity; - using tmp_t = StructuredMatrix< T, structures::Identity, storage::Dense, view::Original< void >, reference_dense, true >; // A general Structure knows how to define a reference to itself (which is an original reference view) // as well as other static views. - using original_t = StructuredMatrix< T, structures::Identity, storage::Dense, view::Original< self_type >, reference_dense, tmp >; - using transpose_t = StructuredMatrix< T, structures::Identity, storage::Dense, view::Transpose< self_type >, reference_dense, tmp >; + using original_t = StructuredMatrix< T, structures::Identity, storage::Dense, view::Original< self_type >, reference_dense >; + using transpose_t = StructuredMatrix< T, structures::Identity, storage::Dense, view::Transpose< self_type >, reference_dense >; StructuredMatrix( const size_t rows ) : internal::MatrixContainer< T >( rows, rows ) {} @@ -875,19 +859,18 @@ namespace grb { * @tparam StorageSchemeType The type (i.e., sparse or dense) of storage scheme * @tparam View The source's View type * @tparam backend The target backend - * @tparam tmp Whether the source view is a temporary structured matrix * * @param source The source structured matrix * * @return A new original view over the source structured matrix. * */ - template< typename T, typename Structure, typename StorageSchemeType, typename View, enum Backend backend, bool tmp > - StructuredMatrix< T, Structure, StorageSchemeType, view::Original< StructuredMatrix< T, Structure, StorageSchemeType, View, backend, tmp > >, backend, tmp > - get_view( StructuredMatrix< T, Structure, StorageSchemeType, View, backend, tmp > &source ) { + template< typename T, typename Structure, typename StorageSchemeType, typename View, enum Backend backend > + StructuredMatrix< T, Structure, StorageSchemeType, view::Original< StructuredMatrix< T, Structure, StorageSchemeType, View, backend > >, backend > + get_view( StructuredMatrix< T, Structure, StorageSchemeType, View, backend > &source ) { - using source_strmat_t = StructuredMatrix< T, Structure, StorageSchemeType, View, backend, tmp >; - using target_strmat_t = StructuredMatrix< T, Structure, StorageSchemeType, view::Original< source_strmat_t >, backend, tmp >; + using source_strmat_t = StructuredMatrix< T, Structure, StorageSchemeType, View, backend >; + using target_strmat_t = StructuredMatrix< T, Structure, StorageSchemeType, view::Original< source_strmat_t >, backend >; target_strmat_t target( source ); @@ -909,22 +892,21 @@ namespace grb { * @tparam StorageSchemeType The type (i.e., sparse or dense) of storage scheme * @tparam View The source's View type * @tparam backend The target backend - * @tparam tmp Whether the source view is a temporary structured matrix * * @param source The source structured matrix * * @return A new original view over the source structured matrix. * */ - template< typename TargetStructure, typename T, typename Structure, typename StorageSchemeType, typename View, enum Backend backend, bool tmp > - StructuredMatrix< T, TargetStructure, StorageSchemeType, view::Original< StructuredMatrix< T, Structure, StorageSchemeType, View, backend, tmp > >, backend, tmp > - get_view( StructuredMatrix< T, Structure, StorageSchemeType, View, backend, tmp > &source ) { + template< typename TargetStructure, typename T, typename Structure, typename StorageSchemeType, typename View, enum Backend backend > + StructuredMatrix< T, TargetStructure, StorageSchemeType, view::Original< StructuredMatrix< T, Structure, StorageSchemeType, View, backend > >, backend > + get_view( StructuredMatrix< T, Structure, StorageSchemeType, View, backend > &source ) { static_assert( structures::is_in< Structure, typename TargetStructure::inferred_structures >::value, "Can only create a view when the target structure is compatible with the source." ); - using source_strmat_t = StructuredMatrix< T, Structure, StorageSchemeType, View, backend, tmp >; - using target_strmat_t = StructuredMatrix< T, TargetStructure, StorageSchemeType, view::Original< source_strmat_t >, backend, tmp >; + using source_strmat_t = StructuredMatrix< T, Structure, StorageSchemeType, View, backend >; + using target_strmat_t = StructuredMatrix< T, TargetStructure, StorageSchemeType, view::Original< source_strmat_t >, backend >; target_strmat_t target( source ); @@ -956,9 +938,9 @@ namespace grb { * The compatibility depends on the TargetStructure, SourceStructure and IMFs, and is calculated during runtime. */ - template< typename TargetStructure, typename T, typename Structure, typename StorageSchemeType, typename View, enum Backend backend, bool tmp > - StructuredMatrix< T, TargetStructure, StorageSchemeType, view::Original< StructuredMatrix< T, Structure, StorageSchemeType, View, backend, tmp > >, backend, tmp > - get_view( StructuredMatrix< T, Structure, StorageSchemeType, View, backend, tmp > &source, + template< typename TargetStructure, typename T, typename Structure, typename StorageSchemeType, typename View, enum Backend backend > + StructuredMatrix< T, TargetStructure, StorageSchemeType, view::Original< StructuredMatrix< T, Structure, StorageSchemeType, View, backend > >, backend > + get_view( StructuredMatrix< T, Structure, StorageSchemeType, View, backend > &source, std::shared_ptr< imf::IMF > imf_r, std::shared_ptr< imf::IMF > imf_c ) { if( std::dynamic_pointer_cast< imf::Select >( imf_r ) || std::dynamic_pointer_cast< imf::Select >( imf_c ) ) { @@ -969,8 +951,8 @@ namespace grb { throw std::runtime_error("Cannot gather into specified TargetStructure from provided SourceStructure and Index Mapping Functions."); } - using source_strmat_t = StructuredMatrix< T, Structure, StorageSchemeType, View, backend, tmp >; - using target_strmat_t = StructuredMatrix< T, TargetStructure, StorageSchemeType, view::Original< source_strmat_t >, backend, tmp >; + using source_strmat_t = StructuredMatrix< T, Structure, StorageSchemeType, View, backend >; + using target_strmat_t = StructuredMatrix< T, TargetStructure, StorageSchemeType, view::Original< source_strmat_t >, backend >; target_strmat_t target( source, imf_r, imf_c ); @@ -992,7 +974,6 @@ namespace grb { * @tparam StorageSchemeType The type (i.e., sparse or dense) of storage scheme * @tparam View The source's View type * @tparam backend The target backend - * @tparam tmp Whether the source view is a temporary structured matrix * * @param source The source structured matrix * @param rng_r A valid range of rows @@ -1001,15 +982,15 @@ namespace grb { * @return A new original view over the source structured matrix. * */ - template< typename TargetStructure, typename T, typename Structure, typename StorageSchemeType, typename View, enum Backend backend, bool tmp > - StructuredMatrix< T, TargetStructure, StorageSchemeType, view::Original< StructuredMatrix< T, Structure, StorageSchemeType, View, backend, tmp > >, backend, tmp > - get_view( StructuredMatrix< T, Structure, StorageSchemeType, View, backend, tmp > &source, + template< typename TargetStructure, typename T, typename Structure, typename StorageSchemeType, typename View, enum Backend backend > + StructuredMatrix< T, TargetStructure, StorageSchemeType, view::Original< StructuredMatrix< T, Structure, StorageSchemeType, View, backend > >, backend > + get_view( StructuredMatrix< T, Structure, StorageSchemeType, View, backend > &source, const utils::range& rng_r, const utils::range& rng_c ) { auto imf_r = std::make_shared< imf::Strided >( rng_r.count(), nrows(source), rng_r.start, rng_r.stride ); auto imf_c = std::make_shared< imf::Strided >( rng_c.count(), ncols(source), rng_c.start, rng_c.stride ); - return internal::get_view( source, imf_r, imf_c ); + return internal::get_view( source, imf_r, imf_c ); } namespace internal { @@ -1029,7 +1010,6 @@ namespace grb { * @tparam StorageSchemeType The type (i.e., sparse or dense) of storage scheme * @tparam View The source's View type * @tparam backend The target backend - * @tparam tmp Whether the source view is a temporary structured matrix * * @param source The source structured matrix * @param sel_r A valid vector of row indeces (possibly in any permuted order and with repetition) @@ -1038,32 +1018,32 @@ namespace grb { * @return A new original view over the source structured matrix. * */ - template< typename TargetStructure, typename T, typename Structure, typename StorageSchemeType, typename View, enum Backend backend, bool tmp > - StructuredMatrix< T, TargetStructure, StorageSchemeType, view::Original< StructuredMatrix< T, Structure, StorageSchemeType, View, backend, tmp > >, backend, tmp > - get_view( StructuredMatrix< T, Structure, StorageSchemeType, View, backend, tmp > &source, + template< typename TargetStructure, typename T, typename Structure, typename StorageSchemeType, typename View, enum Backend backend > + StructuredMatrix< T, TargetStructure, StorageSchemeType, view::Original< StructuredMatrix< T, Structure, StorageSchemeType, View, backend > >, backend > + get_view( StructuredMatrix< T, Structure, StorageSchemeType, View, backend > &source, const std::vector< size_t >& sel_r, const std::vector< size_t >& sel_c ) { auto imf_r = std::make_shared< imf::Select >( nrows(source), sel_r ); auto imf_c = std::make_shared< imf::Select >( ncols(source), sel_c ); - return internal::get_view( source, imf_r, imf_c ); + return internal::get_view( source, imf_r, imf_c ); } } //namespace internal /** Returns a constant reference to an Identity matrix of the provided size */ template< typename T > - const StructuredMatrix< T, structures::Identity, storage::Dense, view::Original< void >, reference_dense, true > & + const StructuredMatrix< T, structures::Identity, storage::Dense, view::Original< void >, reference_dense > & I( const size_t n ) { - using return_type = StructuredMatrix< T, structures::Identity, storage::Dense, view::Original< void >, reference_dense, true >; + using return_type = StructuredMatrix< T, structures::Identity, storage::Dense, view::Original< void >, reference_dense >; return_type * ret = new return_type( n ); return * ret; } /** Returns a constant reference to a Zero matrix of the provided size */ template< typename T > - const StructuredMatrix< T, structures::Zero, storage::Dense, view::Original< void >, reference_dense, true > & + const StructuredMatrix< T, structures::Zero, storage::Dense, view::Original< void >, reference_dense > & Zero( const size_t rows, const size_t cols ) { - using return_type = StructuredMatrix< T, structures::Zero, storage::Dense, view::Original< void >, reference_dense, true >; + using return_type = StructuredMatrix< T, structures::Zero, storage::Dense, view::Original< void >, reference_dense >; return_type * ret = new return_type( rows, cols ); return * ret; } @@ -1073,9 +1053,9 @@ namespace grb { * s = sin( theta ) and c = cos( theta ) */ template< typename T > - const StructuredMatrix< T, structures::Square, storage::Dense, view::Original< void >, reference_dense, true > & + const StructuredMatrix< T, structures::Square, storage::Dense, view::Original< void >, reference_dense > & Givens( const size_t n, const size_t i, const size_t j, const T s, const T c ) { - using return_type = const StructuredMatrix< T, structures::Square, storage::Dense, view::Original< void >, reference_dense, true >; + using return_type = const StructuredMatrix< T, structures::Square, storage::Dense, view::Original< void >, reference_dense >; return_type * ret = new return_type( n ); // TODO: initialize matrix values according to the provided parameters return * ret; diff --git a/include/graphblas/matrix.hpp b/include/graphblas/matrix.hpp index 02f96c1e9..6923162af 100644 --- a/include/graphblas/matrix.hpp +++ b/include/graphblas/matrix.hpp @@ -54,7 +54,7 @@ namespace grb { /* * The default value of \a StorageSchemeType could also be made conditional (Dense or Sparse) depending on \a config::default_backend */ - template< typename T, typename Structure, typename StorageSchemeType = storage::Dense, typename View = view::Original< void >, enum Backend backend = config::default_backend, bool tmp = false > + template< typename T, typename Structure, typename StorageSchemeType = storage::Dense, typename View = view::Original< void >, enum Backend backend = config::default_backend > class StructuredMatrix; } // namespace grb From 7fd02cd2d90494685e2de1534f851c4c99a1387a Mon Sep 17 00:00:00 2001 From: Anonymous Date: Thu, 3 Mar 2022 14:45:57 +0100 Subject: [PATCH 105/282] Remove 'initialized' field from StructureMatrix classes as it is already present in the underlying container grb::Matrix. Expose that field through friend functions operaiting on StructuredMatrix classes. --- include/graphblas/base/matrix.hpp | 11 -------- include/graphblas/denseref/matrix.hpp | 39 ++++++++++++--------------- 2 files changed, 17 insertions(+), 33 deletions(-) diff --git a/include/graphblas/base/matrix.hpp b/include/graphblas/base/matrix.hpp index 500d29cd3..065203a1e 100644 --- a/include/graphblas/base/matrix.hpp +++ b/include/graphblas/base/matrix.hpp @@ -440,17 +440,6 @@ RC clear( Matrix< InputType, backend > & A ) noexcept { template< typename T, typename Structure, typename StorageSchemeType, typename View, enum Backend backend > class StructuredMatrix { - - /** - * Whether the container presently is initialized or not. - * We differentiate the concept of empty matrix (matrix of size \f$0\times 0\f$) - * from the one of uninitialized (matrix of size \f$m\times n\f$ which was never set) - * and that of zero matrix (matrix with all zero elements). - * \note in sparse format a zero matrix result in an ampty data structure. Is this - * used to refer to uninitialized matrix in ALP/GraphBLAS? - **/ - bool initialized; - /** * The two following members define the \em logical layout of a structured matrix: * Its structure and access relations. This is enabled only if the structured matrix diff --git a/include/graphblas/denseref/matrix.hpp b/include/graphblas/denseref/matrix.hpp index 6a5edb2bb..9a184825e 100644 --- a/include/graphblas/denseref/matrix.hpp +++ b/include/graphblas/denseref/matrix.hpp @@ -131,9 +131,13 @@ namespace grb { D * __restrict__ data; /** - * Whether the container presently is uninitialized. - * Matrix is in such state when the object is constructed. - */ + * Whether the container presently is initialized or not. + * We differentiate the concept of empty matrix (matrix of size \f$0\times 0\f$) + * from the one of uninitialized (matrix of size \f$m\times n\f$ which was never set) + * and that of zero matrix (matrix with all zero elements). + * \note in sparse format a zero matrix result in an ampty data structure. Is this + * used to refer to uninitialized matrix in ALP/GraphBLAS? + **/ bool initialized; /** @@ -400,14 +404,6 @@ namespace grb { return A._dims(); } - friend bool getInitialized( MatrixBase & A ) noexcept { - return A.initialized; - } - - friend void setInitialized( MatrixBase & A, bool initialized ) noexcept { - A.initialized = initialized; - } - /** * All matrix views use a pair of index mapping functions to * capture the correspondence between their logical layout and the one @@ -416,13 +412,6 @@ namespace grb { */ std::shared_ptr imf_l, imf_r; - /** - * Whether the container presently is initialized or not. - * TODO: Should be pushed down to the container and reference classess - * so to obtain this status directly from the underlying container. - */ - bool initialized; - /** * @brief determines the size of the structured matrix via the domain of * the index mapping functions. @@ -442,13 +431,11 @@ namespace grb { */ MatrixBase( size_t rows, size_t cols ) : imf_l( std::make_shared< imf::Id >( rows ) ), - imf_r( std::make_shared< imf::Id >( cols ) ), - initialized( false ) {} + imf_r( std::make_shared< imf::Id >( cols ) ) {} MatrixBase( std::shared_ptr< imf::IMF > imf_l, std::shared_ptr< imf::IMF > imf_r ) : imf_l( imf_l ), - imf_r( imf_r ), - initialized( false ) {} + imf_r( imf_r ) {} }; @@ -466,6 +453,14 @@ namespace grb { return *( A._container ); } + friend bool getInitialized( MatrixContainer & A ) noexcept { + return getInitialized( getCointainer( A ) ); + } + + friend void setInitialized( MatrixContainer & A, bool initialized ) noexcept { + setInitialized( getContainer( A, initialized )); + } + /** A container-type view is characterized by its association with a physical container */ Matrix< T, reference_dense > * _container; From fc784168d8331c0eda87549d9df4f9d53da6e5bc Mon Sep 17 00:00:00 2001 From: Anonymous Date: Thu, 3 Mar 2022 14:53:28 +0100 Subject: [PATCH 106/282] Store reference instead of a pointer to a source matrix --- include/graphblas/denseref/matrix.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/graphblas/denseref/matrix.hpp b/include/graphblas/denseref/matrix.hpp index 9a184825e..f68a2c7e9 100644 --- a/include/graphblas/denseref/matrix.hpp +++ b/include/graphblas/denseref/matrix.hpp @@ -501,12 +501,12 @@ namespace grb { * MatrixContainer. Thus a \a MatrixReference never allocates * memory but only establishes a logical view on top of it. */ - TargetType * ref; + TargetType & ref; MatrixReference() : MatrixBase( 0, 0 ), ref( nullptr ) {} - MatrixReference( TargetType & struct_mat ) : MatrixBase( nrows( struct_mat ), ncols( struct_mat ) ), ref( & struct_mat ) {} + MatrixReference( TargetType & struct_mat ) : MatrixBase( nrows( struct_mat ), ncols( struct_mat ) ), ref( struct_mat ) {} MatrixReference( TargetType & struct_mat, std::shared_ptr< imf::IMF > imf_l, std::shared_ptr< imf::IMF > imf_r ) : - MatrixBase( imf_l, imf_r ), ref( & struct_mat ) {} + MatrixBase( imf_l, imf_r ), ref( struct_mat ) {} }; } // namespace internal From 17fe106fc23cbb0438b0d5671bec87b64c122fa2 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Mon, 7 Mar 2022 10:47:56 +0100 Subject: [PATCH 107/282] Adjust comments to reflect renaming Identity to Original view --- include/graphblas/denseref/vector.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/graphblas/denseref/vector.hpp b/include/graphblas/denseref/vector.hpp index 1245edd77..04d200e7e 100644 --- a/include/graphblas/denseref/vector.hpp +++ b/include/graphblas/denseref/vector.hpp @@ -335,7 +335,7 @@ namespace grb { class VectorView< T, View, storage::Dense, reference_dense, C > { }; /** - * Identity View over a vector container. + * Original View over a vector container. */ template< typename T, typename C > class VectorView< T, view::Original< void >, storage::Dense, reference_dense, C > { @@ -425,7 +425,7 @@ namespace grb { } } - }; // Identity VectorView + }; // Original VectorView /** @@ -489,7 +489,7 @@ namespace grb { } /** - * Generate an identity view of a VectorView. + * Generate an original view of a VectorView. * * @param[in] source The VectorView object over which the view is created. * From 5d1884089e383a4cedfebfc3cf85762c7e3c21b5 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Mon, 7 Mar 2022 12:19:56 +0100 Subject: [PATCH 108/282] Remove 'initialized' field from VectorView as it is already present in the underlying container grb::Vector. Expose that field through friend functions operaiting on VectorView. --- include/graphblas/denseref/vector.hpp | 43 ++++++++++++++++++++++----- 1 file changed, 36 insertions(+), 7 deletions(-) diff --git a/include/graphblas/denseref/vector.hpp b/include/graphblas/denseref/vector.hpp index 04d200e7e..b6a7487b0 100644 --- a/include/graphblas/denseref/vector.hpp +++ b/include/graphblas/denseref/vector.hpp @@ -58,6 +58,12 @@ namespace grb { template< typename T, typename C > size_t getLength( const Vector< T, reference_dense, C > & ) noexcept; + template< typename T, typename C > + const bool & getInitialized( const Vector< T, reference_dense, C > & v ) noexcept; + + template< typename T, typename C > + void setInitialized( Vector< T, reference_dense, C > & v, bool initialized ) noexcept; + } // end namespace ``grb::internal'' /** @@ -78,6 +84,14 @@ namespace grb { friend const T * internal::getRaw< T >( const Vector< T, reference_dense, C > & ) noexcept; friend size_t internal::getLength< T >( const Vector< T, reference_dense, C > & ) noexcept; + /* ******************** + IO friends + ******************** */ + + friend const bool & internal::getInitialized< T >( const Vector< T, reference_dense, C > & ) noexcept; + + friend void internal::setInitialized< T >( Vector< T, reference_dense, C > & , bool ) noexcept; + private: /** The length of the vector. */ @@ -276,6 +290,15 @@ namespace grb { return v.n; } + template< typename T, typename C > + const bool & getInitialized( const Vector< T, reference_dense, C > & v ) noexcept { + return v.initialized; + } + + template< typename T, typename C > + void setInitialized( Vector< T, reference_dense, C > & v, bool initialized ) noexcept { + v.initialized = initialized; + } } // end namespace ``grb::internal'' @@ -289,6 +312,18 @@ namespace grb { return v._length(); } + namespace internal { + template< typename T, typename View, typename C > + bool getInitialized( VectorView< T, View, storage::Dense, reference_dense, C > & v ) noexcept { + return getInitialized( v ); + } + + template< typename T, typename View, typename C > + void setInitialized( VectorView< T, View, storage::Dense, reference_dense, C > & v, bool initialized ) noexcept { + setInitialized( v, initialized ); + } + } // end namespace ``grb::internal'' + /** * \brief An ALP vector view. * @@ -354,12 +389,6 @@ namespace grb { std::shared_ptr imf; - /** Whether the container presently is initialized or not. Currently, - * container is created as uninitialized and set to initialized in a - * buildMatrix call. - */ - bool initialized; - /** Returns the length of the vector */ size_t _length() const { return imf->n; @@ -369,7 +398,7 @@ namespace grb { /** @see Vector::value_type. */ using value_type = T; - VectorView( const size_t length ) : v( std::make_unique< Vector< T, reference_dense, C > >( length ) ), imf( std::make_shared< imf::Id >( length ) ), initialized( false ) {} + VectorView( const size_t length ) : v( std::make_unique< Vector< T, reference_dense, C > >( length ) ), imf( std::make_shared< imf::Id >( length ) ) {} }; // class VectorView with physical container From da7bd8a023526e6e145cde0b0403649748720435 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Mon, 14 Mar 2022 10:24:12 +0000 Subject: [PATCH 109/282] !19 Resolve internal issue #360: Make VectorView "compatible" with StructuredMatrix in terms of template parameters This commit mainly adds Structure to the VectorView and reorders VectorView's template parameters to follow the same order as in StructuredMatrix. Doxygen is updated to reflect these changes. In addition, there are the following changes: * Remove VectorView's Tmp parameter from blas1 doxygen * Use consistent ordering of template name parameters across blas 1/2/3. The order is Output, Mask, Inputs. * Fix minor unrelated issues * Generalize over storage scheme type for VectorView in level 1/2/3 routines --- include/graphblas/base/vector.hpp | 2 +- include/graphblas/denseref/blas1.hpp | 1136 +++++++++++++++++-------- include/graphblas/denseref/blas2.hpp | 70 +- include/graphblas/denseref/blas3.hpp | 29 +- include/graphblas/denseref/vector.hpp | 62 +- include/graphblas/vector.hpp | 2 +- 6 files changed, 857 insertions(+), 444 deletions(-) diff --git a/include/graphblas/base/vector.hpp b/include/graphblas/base/vector.hpp index fb64a1502..f22bb2a1b 100644 --- a/include/graphblas/base/vector.hpp +++ b/include/graphblas/base/vector.hpp @@ -901,7 +901,7 @@ namespace grb { } }; - template< typename T, typename View, typename StorageSchemeType, enum Backend backend, typename C > + template< typename T, typename Structure, typename StorageSchemeType, typename View, enum Backend backend, typename C > class VectorView { }; } diff --git a/include/graphblas/denseref/blas1.hpp b/include/graphblas/denseref/blas1.hpp index fc7f16f40..bbed3bb02 100644 --- a/include/graphblas/denseref/blas1.hpp +++ b/include/graphblas/denseref/blas1.hpp @@ -159,8 +159,8 @@ namespace grb { // * \mathit{sizeof}(\mathit{size\_t}) \f$ bytes of data. // * \endparblock */ - template< typename DataType, typename View, typename Coords > - RC clear( VectorView< DataType, View, storage::Dense, reference_dense, Coords > & x ) noexcept { + template< typename DataType, typename DataStructure, typename DataStorage, typename View, typename Coords > + RC clear( VectorView< DataType, DataStructure, DataStorage, View, reference_dense, Coords > & x ) noexcept { throw std::runtime_error( "Needs an implementation" ); return SUCCESS; } @@ -171,9 +171,10 @@ namespace grb { * The dimension is set at construction of the given VectorView and cannot * be changed. A call to this function shall always succeed. * - * @tparam DataType The type of elements contained in the vector \a x. - * @tparam View The view type applied to the vector \a x. - * @tparam Tmp Whether the vector \a x is a temporary. + * @tparam DataType The type of elements contained in the vector \a x. + * @tparam DataStructure The structure of the vector \a x. + * @tparam DataStorage The type of storage of the vector \a x. + * @tparam View The view type applied to the vector \a x. * * @param[in] x The VectorView of which to retrieve the size. * @@ -188,8 +189,8 @@ namespace grb { // * -# shall not make any system calls. // * \endparblock */ - template< typename DataType, typename View, typename Coords > - size_t size( const VectorView< DataType, View, storage::Dense, reference_dense, Coords > & x ) noexcept { + template< typename DataType, typename DataStructure, typename DataStorage, typename View, typename Coords > + size_t size( const VectorView< DataType, DataStructure, DataStorage, View, reference_dense, Coords > & x ) noexcept { return getLength( x ); } @@ -198,9 +199,10 @@ namespace grb { * * A call to this function always succeeds. * - * @tparam DataType The type of elements contained in this VectorView. - * @tparam View The view type applied to the vector \a x. - * @tparam Tmp Whether the vector \a x is a temporary. + * @tparam DataType The type of elements contained in the vector \a x. + * @tparam DataStructure The structure of the vector \a x. + * @tparam DataStorage The type of storage of the vector \a x. + * @tparam View The view type applied to the vector \a x. * * @param[in] x The VectorView of which to retrieve the number of nonzeroes. * @@ -215,15 +217,15 @@ namespace grb { // * -# shall not make any system calls. // * \endparblock */ - template< typename DataType, typename View, typename Coords > - size_t nnz( const VectorView< DataType, View, storage::Dense, reference_dense, Coords > & x ) noexcept { + template< typename DataType, typename DataStructure, typename DataStorage, typename View, typename Coords > + size_t nnz( const VectorView< DataType, DataStructure, DataStorage, View, reference_dense, Coords > & x ) noexcept { throw std::runtime_error( "Needs an implementation." ); return 0; } /** \todo add documentation. In particular, think about the meaning with \a P > 1. */ - template< typename InputType, typename View, typename length_type, typename Coords > - RC resize( VectorView< InputType, View, storage::Dense, reference_dense, Coords > & x, const length_type new_nz ) { + template< typename InputType, typename InputStructure, typename InputStorage, typename View, typename length_type, typename Coords > + RC resize( VectorView< InputType, InputStructure, InputStorage, View, reference_dense, Coords > & x, const length_type new_nz ) { // check if we have a mismatch if( new_nz > grb::size( x ) ) { return MISMATCH; @@ -250,11 +252,12 @@ namespace grb { * if( mask(i) ) { setElement( x, i, val ); } * \endcode. * - * @tparam descr The descriptor used for this operation. - * @tparam DataType The type of each element in the given VectorView. - * @tparam View The view type applied to the vector \a x. - * @tparam Tmp Whether the vector \a x is a temporary. - * @tparam T The type of the given value. + * @tparam descr The descriptor used for this operation. + * @tparam DataType The type of each element in the vector \a x. + * @tparam DataStructure The structure of the vector \a x. + * @tparam DataStorage The type of storage of the vector \a x. + * @tparam View The view type applied to the vector \a x. + * @tparam T The type of the given value. * * \parblock * \par Accepted descriptors @@ -288,10 +291,10 @@ namespace grb { */ template< Descriptor descr = descriptors::no_operation, - typename DataType, typename View, typename T, + typename DataType, typename DataStructure, typename DataStorage, typename View, typename T, typename Coords > - RC set( VectorView< DataType, View, storage::Dense, reference_dense, Coords > & x, const T val, + RC set( VectorView< DataType, DataStructure, DataStorage, View, reference_dense, Coords > & x, const T val, const typename std::enable_if< !grb::is_object< DataType >::value && !grb::is_object< T >::value, @@ -324,11 +327,12 @@ namespace grb { * if( mask(i) ) { setElement( x, i, val ); } * \endcode. * - * @tparam descr The descriptor used for this operation. - * @tparam DataType The type of each element in the given vector. - * @tparam View The view type applied to the given vector. - * @tparam Tmp Whether the vector is a temporary. - * @tparam T The type of the given value. + * @tparam descr The descriptor used for this operation. + * @tparam DataType The type of each element in the given vector. + * @tparam DataStructure The Structure of the given vector. + * @tparam DataStorage Storage Scheme type applied in the given vector. + * @tparam View The view type applied to the given vector. + * @tparam T The type of the given value. * * \parblock * \par Accepted descriptors @@ -364,9 +368,9 @@ namespace grb { * @see grb::operators::right_assign. * @see grb::setElement. */ - template< Descriptor descr = descriptors::no_operation, typename DataType, typename DataView, typename MaskType, typename MaskView, typename T, typename Coords > - RC set( VectorView< DataType, DataView, storage::Dense, reference_dense, Coords > & x, - const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & m, + template< Descriptor descr = descriptors::no_operation, typename DataType, typename DataView, typename DataStructure, typename DataStorage, typename MaskStructure, typename MaskStorage, typename MaskType, typename MaskView, typename T, typename Coords > + RC set( VectorView< DataType, DataStructure, DataStorage, DataView, reference_dense, Coords > & x, + const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense, Coords > & m, const T val, const typename std::enable_if< ! grb::is_object< DataType >::value && ! grb::is_object< T >::value, void >::type * const = NULL ) { #ifdef _DEBUG @@ -406,12 +410,13 @@ namespace grb { * * The parameter \a i may not be greater or equal than the size of \a x. * - * @tparam descr The descriptor to be used during evaluation of this - * function. - * @tparam DataType The type of the elements of \a x. - * @tparam View The view type applied to the vector \a x. - * @tparam Tmp Whether the vector \a x is a temporary. - * @tparam T The type of the value to be set. + * @tparam descr The descriptor to be used during evaluation of this + * function. + * @tparam DataType The type of the elements of \a x. + * @tparam DataStructure The structure of the vector \a x. + * @tparam DataStorage The storage scheme type applied to the vector \a x. + * @tparam View The view type applied to the vector \a x. + * @tparam T The type of the value to be set. * * @param[in,out] x The vector to be modified. * @param[in] val The value \f$ x_i \f$ should read after function exit. @@ -439,8 +444,8 @@ namespace grb { // * -# shall not make any system calls. // * \endparblock */ - template< Descriptor descr = descriptors::no_operation, typename DataType, typename View, typename T, typename Coords > - RC setElement( VectorView< DataType, View, storage::Dense, reference_dense, Coords > & x, + template< Descriptor descr = descriptors::no_operation, typename DataType, typename DataStructure, typename DataStorage, typename View, typename T, typename Coords > + RC setElement( VectorView< DataType, DataStructure, DataStorage, View, reference_dense, Coords > & x, const T val, const size_t i, const typename std::enable_if< ! grb::is_object< DataType >::value && ! grb::is_object< T >::value, void >::type * const = NULL ) { @@ -482,9 +487,15 @@ namespace grb { * -# grb::descriptors::no_casting * \endparblock * - * @tparam descr The descriptor of the operation. - * @tparam OutputType The type of each element in the output vector. - * @tparam InputType The type of each element in the input vector. + * @tparam descr The descriptor of the operation. + * @tparam OutputType The type of each element in the output vector. + * @tparam InputType The type of each element in the input vector. + * @tparam OutputStructure The structure of the ouput vector. + * @tparam InputStructure The structure of the input vector. + * @tparam OutputStorage The storage scheme applied to the output vector. + * @tparam InputStorage The storage scheme applied to the input vector. + * @tparam OuputView The view applied to the output vector. + * @tparam InputView The view applied to the input vector. * * @param[in,out] x The vector to be set. * @param[in] y The source vector. @@ -507,8 +518,8 @@ namespace grb { * @see grb::operators::right_assign. * @see grb::setElement. */ - template< Descriptor descr = descriptors::no_operation, typename OutputType, typename InputType, typename OutputView, typename InputView, typename Coords > - RC set( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & x, const VectorView< InputType, InputView, storage::Dense, reference_dense, Coords > & y ) { + template< Descriptor descr = descriptors::no_operation, typename OutputType, typename InputType, typename OutputStructure, typename OutputStorage, typename InputStructure, typename InputStorage, typename OutputView, typename InputView, typename Coords > + RC set( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & x, const VectorView< InputType, InputStructure, InputStorage, InputView, reference_dense, Coords > & y ) { // static sanity checks NO_CAST_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< OutputType, InputType >::value ), "grb::copy (Vector)", "called with vector parameters whose element data types do not match" ); @@ -555,10 +566,19 @@ namespace grb { * * The vector \a x may not equal \a y. * - * @tparam descr The descriptor of the operation. - * @tparam OutputType The type of each element in the output vector. - * @tparam MaskType The type of each element in the mask vector. - * @tparam InputType The type of each element in the input vector. + * @tparam descr The descriptor of the operation. + * @tparam OutputType The type of each element in the output vector. + * @tparam MaskType The type of each element in the mask vector. + * @tparam InputType The type of each element in the input vector. + * @tparam OutputStructure The structure of the output vector. + * @tparam MaskStructure The structure of the mask vector. + * @tparam InputStructure The structure of the input vector. + * @tparam OutputStorage The storage scheme type of the output vector. + * @tparam MaskStorage The storage scheme type of the mask vector. + * @tparam InputStorage The storage scheme type of the input vector. + * @tparam OutputView The view applied to the output vector. + * @tparam MaskView The view applied to the mask vector. + * @tparam InputView The view applied to the input vector. * * \parblock * \par Accepted descriptors @@ -592,10 +612,15 @@ namespace grb { * @see grb::operators::right_assign. * @see grb::setElement. */ - template< Descriptor descr = descriptors::no_operation, typename OutputType, typename MaskType, typename InputType, typename OutputView, typename MaskView, typename InputView, typename Coords > - RC set( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & x, - const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & mask, - const VectorView< InputType, InputView, storage::Dense, reference_dense, Coords > & y, + template< Descriptor descr = descriptors::no_operation, + typename OutputType, typename MaskType, typename InputType, + typename OutputStructure, typename MaskStructure, typename InputStructure, + typename OutputStorage, typename MaskStorage, typename InputStorage, + typename OutputView, typename MaskView, typename InputView, + typename Coords > + RC set( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & x, + const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense, Coords > & mask, + const VectorView< InputType, InputStructure, InputStorage, InputView, reference_dense, Coords > & y, const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType >::value, void >::type * const = NULL ) { // static sanity checks NO_CAST_ASSERT( @@ -638,10 +663,9 @@ namespace grb { * The operator must be associative. * @tparam InputType The type of the elements of \a x. * @tparam IOType The type of the value \a y. - * @tparam InputView The view type applied to the vector \a x. - * @tparam IOView The view type applied to the vector \a y. - * @tparam InputTmp Whether the vector \a x is a temporary. - * @tparam IOTmp Whether the vector \a y is a temporary. + * @tparam InputStructure The structure of the vector \a x. + * @tparam InputStorage The type of storage scheme of the vector \a x. + * @tparam InputView The view type applied to the vector \a x. * * @param[in] x The input VectorView \a x that will not be modified. * This input VectorView must be dense. @@ -703,8 +727,9 @@ namespace grb { * @see grb::operators::internal::Operator for a discussion on when in-place * and/or vectorised operations are used. */ - template< Descriptor descr = descriptors::no_operation, class Monoid, typename InputType, typename InputView, typename IOType, typename Coords > - RC foldr( const VectorView< InputType, InputView, storage::Dense, reference_dense, Coords > & x, + template< Descriptor descr = descriptors::no_operation, class Monoid, + typename InputType, typename InputStructure, typename InputStorage, typename InputView, typename IOType, typename Coords > + RC foldr( const VectorView< InputType, InputStructure, InputStorage, InputView, reference_dense, Coords > & x, IOType & beta, const Monoid & monoid = Monoid(), const typename std::enable_if< ! grb::is_object< InputType >::value && ! grb::is_object< IOType >::value && grb::is_monoid< Monoid >::value, void >::type * const = NULL ) { @@ -725,11 +750,14 @@ namespace grb { * The value of \f$ y_i \f$ after a call to thus function thus equals * \f$ \alpha \odot y_i \f$, for all \f$ i \in \{ 0, 1, \dots, n - 1 \} \f$. * - * @tparam descr The descriptor used for evaluating this function. By - * default, this is grb::descriptors::no_operation. - * @tparam OP The type of the operator to be applied. - * @tparam InputType The type of \a alpha. - * @tparam IOType The type of the elements in \a y. + * @tparam descr The descriptor used for evaluating this function. + * By default, this is grb::descriptors::no_operation. + * @tparam OP The type of the operator to be applied. + * @tparam InputType The type of \a alpha. + * @tparam IOType The type of the elements in \a y. + * @tparam IOStructure The structure of the vector \a y. + * @tparam IOStorage The type of storage scheme of the vector \a y. + * @tparam IOView The view applied to the vector \a y. * * @param[in] alpha The input value to apply as the left-hand side input * to \a op. @@ -782,9 +810,9 @@ namespace grb { * @see grb::operators::internal::Operator for a discussion on when in-place * and/or vectorised operations are used. */ - template< Descriptor descr = descriptors::no_operation, class Monoid, typename IOType, typename InputType, typename InputView, typename Coords > + template< Descriptor descr = descriptors::no_operation, class Monoid, typename IOType, typename InputType, typename IOStructure, typename IOStorage, typename IOView, typename Coords > RC foldr( const InputType & alpha, - VectorView< IOType, InputView, storage::Dense, reference_dense, Coords > & y, + VectorView< IOType, IOStructure, IOStorage, IOView, reference_dense, Coords > & y, const Monoid & monoid = Monoid(), const typename std::enable_if< ! grb::is_object< InputType >::value && ! grb::is_object< IOType >::value && grb::is_monoid< Monoid >::value, void >::type * const = NULL ) { // static sanity checks @@ -807,9 +835,9 @@ namespace grb { * * Specialisation for scalar \a x. */ - template< Descriptor descr = descriptors::no_operation, class OP, typename IOType, typename InputType, typename IOView, typename Coords > + template< Descriptor descr = descriptors::no_operation, class OP, typename IOType, typename InputType, typename IOStructure, typename IOStorage, typename IOView, typename Coords > RC foldr( const InputType & alpha, - VectorView< IOType, IOView, storage::Dense, reference_dense, Coords > & y, + VectorView< IOType, IOStructure, IOStorage, IOView, reference_dense, Coords > & y, const OP & op = OP(), const typename std::enable_if< ! grb::is_object< InputType >::value && ! grb::is_object< IOType >::value && grb::is_operator< OP >::value, void >::type * const = NULL ) { // static sanity checks @@ -837,8 +865,14 @@ namespace grb { * @tparam descr The descriptor used for evaluating this function. By * default, this is grb::descriptors::no_operation. * @tparam OP The type of the operator to be applied. - * @tparam IOType The type of the elements of \a x. - * @tparam InputType The type of the elements of \a y. + * @tparam IOType The type of the elements of \a y. + * @tparam InputType The type of the elements of \a x. + * @tparam IOStructure The structure of the vector \a y. + * @tparam InputStructure The structure of the vector \a x. + * @tparam IOStorage The type of storage scheme of the vector \a y. + * @tparam InputStorage The type of storage scheme of the vector \a x. + * @tparam IOView The View applied on the vector \a y. + * @tparam InputView The View applied on the vector \a x. * * @param[in] x The input vector \a y that will not be modified. * @param[in,out] y On function entry: the initial value to be applied to @@ -895,9 +929,14 @@ namespace grb { * @see grb::operators::internal::Operator for a discussion on when in-place * and/or vectorised operations are used. */ - template< Descriptor descr = descriptors::no_operation, class OP, typename IOType, typename InputType, typename IOView, typename InputView, typename Coords > - RC foldr( const VectorView< InputType, InputView, storage::Dense, reference_dense, Coords > & x, - VectorView< IOType, IOView, storage::Dense, reference_dense, Coords > & y, + template< Descriptor descr = descriptors::no_operation, class OP, + typename IOType, typename InputType, + typename IOStructure, typename InputStructure, + typename IOStorage, typename InputStorage, + typename IOView, typename InputView, + typename Coords > + RC foldr( const VectorView< InputType, InputStructure, InputStorage, InputView, reference_dense, Coords > & x, + VectorView< IOType, IOStructure, IOStorage, IOView, reference_dense, Coords > & y, const OP & op = OP(), const typename std::enable_if< grb::is_operator< OP >::value && ! grb::is_object< InputType >::value && ! grb::is_object< IOType >::value, void >::type * = NULL ) { // static sanity checks @@ -924,10 +963,15 @@ namespace grb { * * Masked variant. */ - template< Descriptor descr = descriptors::no_operation, class OP, typename IOType, typename MaskType, typename InputType, typename IOView, typename MaskView, typename InputView, typename Coords > - RC foldr( const VectorView< InputType, InputView, storage::Dense, reference_dense, Coords > & x, - const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & m, - VectorView< IOType, IOView, storage::Dense, reference_dense, Coords > & y, + template< Descriptor descr = descriptors::no_operation, class OP, + typename IOType, typename MaskType, typename InputType, + typename IOStructure, typename MaskStructure, typename InputStructure, + typename IOStorage, typename MaskStorage, typename InputStorage, + typename IOView, typename MaskView, typename InputView, + typename Coords > + RC foldr( const VectorView< InputType, InputStructure, InputStorage, InputView, reference_dense, Coords > & x, + const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense, Coords > & m, + VectorView< IOType, IOStructure, IOStorage, IOView, reference_dense, Coords > & y, const OP & op = OP(), const typename std::enable_if< grb::is_operator< OP >::value && ! grb::is_object< InputType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< IOType >::value, void >::type * = NULL ) { @@ -966,8 +1010,14 @@ namespace grb { * @tparam descr The descriptor used for evaluating this function. By * default, this is grb::descriptors::no_operation. * @tparam Monoid The type of the monoid to be applied. - * @tparam IOType The type of the elements of \a x. - * @tparam InputType The type of the elements of \a y. + * @tparam IOType The type of the elements of \a y. + * @tparam InputType The type of the elements of \a x. + * @tparam IOStructure The structure of the vector \a y. + * @tparam InputStructure The structure of the vector \a x. + * @tparam IOStorage The type of storage scheme of the vector \a y. + * @tparam InputStorage The type of storage scheme of the vector \a x. + * @tparam IOView The view type applied to the vector \a y. + * @tparam InputView The view type applied to the vector \a x. * * @param[in] x The input vector \a y that will not be modified. * @param[in,out] y On function entry: the initial value to be applied @@ -1024,9 +1074,14 @@ namespace grb { * @see grb::operators::internal::Operator for a discussion on when in-place * and/or vectorised operations are used. */ - template< Descriptor descr = descriptors::no_operation, class Monoid, typename IOType, typename InputType, typename IOView, typename InputView, typename Coords > - RC foldr( const VectorView< InputType, InputView, storage::Dense, reference_dense, Coords > & x, - VectorView< IOType, IOView, storage::Dense, reference_dense, Coords > & y, + template< Descriptor descr = descriptors::no_operation, class Monoid, + typename IOType, typename InputType, + typename IOStructure, typename InputStructure, + typename IOStorage, typename InputStorage, + typename IOView, typename InputView, + typename Coords > + RC foldr( const VectorView< InputType, InputStructure, InputStorage, InputView, reference_dense, Coords > & x, + VectorView< IOType, IOStructure, IOStorage, IOView, reference_dense, Coords > & y, const Monoid & monoid = Monoid(), const typename std::enable_if< grb::is_monoid< Monoid >::value && ! grb::is_object< InputType >::value && ! grb::is_object< IOType >::value, void >::type * = NULL ) { // static sanity checks @@ -1055,10 +1110,15 @@ namespace grb { * * Masked variant. */ - template< Descriptor descr = descriptors::no_operation, class Monoid, typename IOType, typename MaskType, typename InputType, typename IOView, typename MaskView, typename InputView, typename Coords > - RC foldr( const VectorView< InputType, InputView, storage::Dense, reference_dense, Coords > & x, - const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & m, - VectorView< IOType, IOView, storage::Dense, reference_dense, Coords > & y, + template< Descriptor descr = descriptors::no_operation, class Monoid, + typename IOType, typename MaskType, typename InputType, + typename IOStructure, typename MaskStructure, typename InputStructure, + typename IOStorage, typename MaskStorage, typename InputStorage, + typename IOView, typename MaskView, typename InputView, + typename Coords > + RC foldr( const VectorView< InputType, InputStructure, InputStorage, InputView, reference_dense, Coords > & x, + const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense, Coords > & m, + VectorView< IOType, IOStructure, IOStorage, IOView, reference_dense, Coords > & y, const Monoid & monoid = Monoid(), const typename std::enable_if< grb::is_monoid< Monoid >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType >::value && ! grb::is_object< IOType >::value, void >::type * = NULL ) { @@ -1102,13 +1162,14 @@ namespace grb { * The value of \f$ x_i \f$ after a call to thus function thus equals * \f$ x_i \odot \beta \f$, for all \f$ i \in \{ 0, 1, \dots, n - 1 \} \f$. * - * @tparam descr The descriptor used for evaluating this function. By - * default, this is grb::descriptors::no_operation. - * @tparam OP The type of the operator to be applied. - * @tparam IOType The type of the value \a beta. - * @tparam InputType The type of the elements of \a x. - * @tparam IOView The view type applied to the vector \a x. - * @tparam IOTmp Whether the vector \a x is a temporary. + * @tparam descr The descriptor used for evaluating this function. By + * default, this is grb::descriptors::no_operation. + * @tparam OP The type of the operator to be applied. + * @tparam IOType The type of the value \a beta. + * @tparam InputType The type of the elements of \a x. + * @tparam IOStructure The structure of the vector \a x. + * @tparam IOStorage The type of storage scheme of the vector \a x. + * @tparam IOView The view type applied to the vector \a x. * * @param[in,out] x On function entry: the initial values to be applied as * the left-hand side input to \a op. The input vector must @@ -1165,8 +1226,8 @@ namespace grb { * @see grb::operators::internal::Operator for a discussion on when in-place * and/or vectorised operations are used. */ - template< Descriptor descr = descriptors::no_operation, class Op, typename IOType, typename InputType, typename IOView, typename Coords > - RC foldl( VectorView< IOType, IOView, storage::Dense, reference_dense, Coords > & x, + template< Descriptor descr = descriptors::no_operation, class Op, typename IOType, typename InputType, typename IOStructure, typename IOStorage, typename IOView, typename Coords > + RC foldl( VectorView< IOType, IOStructure, IOStorage, IOView, reference_dense, Coords > & x, const InputType beta, const Op & op = Op(), const typename std::enable_if< ! grb::is_object< IOType >::value && ! grb::is_object< InputType >::value && grb::is_operator< Op >::value, void >::type * = NULL ) { @@ -1191,9 +1252,14 @@ namespace grb { * * Masked operator variant. */ - template< Descriptor descr = descriptors::no_operation, class Op, typename IOType, typename MaskType, typename InputType, typename IOView, typename MaskView, typename InputView, typename Coords > - RC foldl( VectorView< IOType, IOView, storage::Dense, reference_dense, Coords > & x, - const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & m, + template< Descriptor descr = descriptors::no_operation, class Op, + typename IOType, typename MaskType, typename InputType, + typename IOStructure, typename MaskStructure, + typename IOStorage, typename MaskStorage, + typename IOView, typename MaskView, typename InputView, + typename Coords > + RC foldl( VectorView< IOType, IOStructure, IOStorage, IOView, reference_dense, Coords > & x, + const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense, Coords > & m, const InputType beta, const Op & op = Op(), const typename std::enable_if< ! grb::is_object< IOType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType >::value && grb::is_operator< Op >::value, void >::type * = @@ -1230,11 +1296,14 @@ namespace grb { * The value of \f$ x_i \f$ after a call to thus function thus equals * \f$ x_i \odot \beta \f$, for all \f$ i \in \{ 0, 1, \dots, n - 1 \} \f$. * - * @tparam descr The descriptor used for evaluating this function. By - * default, this is grb::descriptors::no_operation. - * @tparam Monoid The type of the monoid to be applied. - * @tparam IOType The type of the value \a beta. - * @tparam InputType The type of the elements of \a x. + * @tparam descr The descriptor used for evaluating this function. By + * default, this is grb::descriptors::no_operation. + * @tparam Monoid The type of the monoid to be applied. + * @tparam IOType The type of the elements of \a x. + * @tparam InputType The type of the value \a beta. + * @tparam IOStructure The structure of the vector \a x. + * @tparam IOStorage The type of storage scheme of the vector \a x. + * @tparam IOView The view type applied to the vector \a x. * * @param[in,out] x On function entry: the initial values to be applied as * the left-hand side input to \a op. @@ -1287,8 +1356,8 @@ namespace grb { * @see grb::operators::internal::Operator for a discussion on when in-place * and/or vectorised operations are used. */ - template< Descriptor descr = descriptors::no_operation, class Monoid, typename IOType, typename InputType, typename IOView, typename Coords > - RC foldl( VectorView< IOType, IOView, storage::Dense, reference_dense, Coords > & x, + template< Descriptor descr = descriptors::no_operation, class Monoid, typename IOType, typename InputType, typename IOStructure, typename IOStorage, typename IOView, typename Coords > + RC foldl( VectorView< IOType, IOStructure, IOStorage, IOView, reference_dense, Coords > & x, const InputType beta, const Monoid & monoid = Monoid(), const typename std::enable_if< ! grb::is_object< IOType >::value && ! grb::is_object< InputType >::value && grb::is_monoid< Monoid >::value, void >::type * = NULL ) { @@ -1313,9 +1382,14 @@ namespace grb { * * Masked monoid variant. */ - template< Descriptor descr = descriptors::no_operation, class Monoid, typename IOType, typename MaskType, typename InputType, typename IOView, typename MaskView, typename Coords > - RC foldl( VectorView< IOType, IOView, storage::Dense, reference_dense, Coords > & x, - const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & m, + template< Descriptor descr = descriptors::no_operation, class Monoid, + typename IOType, typename MaskType, typename InputType, + typename IOStructure, typename MaskStructure, + typename IOStorage, typename MaskStorage, + typename IOView, typename MaskView, + typename Coords > + RC foldl( VectorView< IOType, IOStructure, IOStorage, IOView, reference_dense, Coords > & x, + const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense, Coords > & m, const InputType & beta, const Monoid & monoid = Monoid(), const typename std::enable_if< ! grb::is_object< IOType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType >::value && grb::is_monoid< Monoid >::value, void >::type * = @@ -1347,11 +1421,17 @@ namespace grb { * of at the i-th index of \a x after a call to this function thus equals * \f$ x_i \odot y_i \f$. * - * @tparam descr The descriptor used for evaluating this function. By - * default, this is grb::descriptors::no_operation. - * @tparam OP The type of the operator to be applied. - * @tparam IOType The type of the value \a x. - * @tparam InputType The type of the elements of \a y. + * @tparam descr The descriptor used for evaluating this function. By + * default, this is grb::descriptors::no_operation. + * @tparam OP The type of the operator to be applied. + * @tparam IOType The type of the value \a x. + * @tparam InputType The type of the elements of \a y. + * @tparam IOStructure The structure of the vector \a x. + * @tparam InputStructure The structure of the vector \a y. + * @tparam IOStorage The type of storage scheme of the vector \a x. + * @tparam InputStorage The type of storage scheme of the vector \a y. + * @tparam IOView The view type applied to the vector \a x. + * @tparam InputView The view type applied to the vector \a y. * * @param[in,out] x On function entry: the vector whose elements are to be * applied to \a op as the left-hand side input. @@ -1410,9 +1490,14 @@ namespace grb { * @see grb::operators::internal::Operator for a discussion on when in-place * and/or vectorised operations are used. */ - template< Descriptor descr = descriptors::no_operation, class OP, typename IOType, typename InputType, typename IOView, typename InputView, typename Coords > - RC foldl( VectorView< IOType, IOView, storage::Dense, reference_dense, Coords > & x, - const VectorView< InputType, InputView, storage::Dense, reference_dense, Coords > & y, + template< Descriptor descr = descriptors::no_operation, class OP, + typename IOType, typename InputType, + typename IOStructure, typename InputStructure, + typename IOStorage, typename InputStorage, + typename IOView, typename InputView, + typename Coords > + RC foldl( VectorView< IOType, IOStructure, IOStorage, IOView, reference_dense, Coords > & x, + const VectorView< InputType, InputStructure, InputStorage, InputView, reference_dense, Coords > & y, const OP & op = OP(), const typename std::enable_if< grb::is_operator< OP >::value && ! grb::is_object< IOType >::value && ! grb::is_object< InputType >::value, void >::type * = NULL ) { // static sanity checks @@ -1443,11 +1528,17 @@ namespace grb { * of at the i-th index of \a x after a call to this function thus equals * \f$ x_i \odot y_i \f$. * - * @tparam descr The descriptor used for evaluating this function. By - * default, this is grb::descriptors::no_operation. - * @tparam Monoid The type of the monoid to be applied. - * @tparam IOType The type of the value \a x. - * @tparam InputType The type of the elements of \a y. + * @tparam descr The descriptor used for evaluating this function. By + * default, this is grb::descriptors::no_operation. + * @tparam Monoid The type of the monoid to be applied. + * @tparam IOType The type of the value \a x. + * @tparam InputType The type of the elements of \a y. + * @tparam IOStructure The structure of the vector \a x. + * @tparam InputStructure The structure of the vector \a y. + * @tparam IOStorage The type of storage scheme of the vector \a x. + * @tparam InputStorage The type of storage scheme of the vector \a y. + * @tparam IOView The view type applied to the vector \a x. + * @tparam InputView The view type applied to the vector \a y. * * @param[in,out] x On function entry: the vector whose elements are to be * applied to \a op as the left-hand side input. @@ -1506,9 +1597,14 @@ namespace grb { * @see grb::operators::internal::Operator for a discussion on when in-place * and/or vectorised operations are used. */ - template< Descriptor descr = descriptors::no_operation, class Monoid, typename IOType, typename InputType, typename IOView, typename InputView, typename Coords > - RC foldl( VectorView< IOType, IOView, storage::Dense, reference_dense, Coords > & x, - const VectorView< InputType, InputView, storage::Dense, reference_dense, Coords > & y, + template< Descriptor descr = descriptors::no_operation, class Monoid, + typename IOType, typename InputType, + typename IOStructure, typename InputStructure, + typename IOStorage, typename InputStorage, + typename IOView, typename InputView, + typename Coords > + RC foldl( VectorView< IOType, IOStructure, IOStorage, IOView, reference_dense, Coords > & x, + const VectorView< InputType, InputStructure, InputStorage, InputView, reference_dense, Coords > & y, const Monoid & monoid = Monoid(), const typename std::enable_if< grb::is_monoid< Monoid >::value && ! grb::is_object< IOType >::value && ! grb::is_object< InputType >::value, void >::type * = NULL ) { // static sanity checks @@ -1537,10 +1633,15 @@ namespace grb { * * Masked variant. */ - template< Descriptor descr = descriptors::no_operation, class OP, typename IOType, typename MaskType, typename InputType, typename IOView, typename MaskView, typename InputView, typename Coords > - RC foldl( VectorView< IOType, IOView, storage::Dense, reference_dense, Coords > & x, - const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & m, - const VectorView< InputType, InputView, storage::Dense, reference_dense, Coords > & y, + template< Descriptor descr = descriptors::no_operation, class OP, + typename IOType, typename MaskType, typename InputType, + typename IOStructure, typename MaskStructure, typename InputStructure, + typename IOStorage, typename MaskStorage, typename InputStorage, + typename IOView, typename MaskView, typename InputView, + typename Coords > + RC foldl( VectorView< IOType, IOStructure, IOStorage, IOView, reference_dense, Coords > & x, + const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense, Coords > & m, + const VectorView< InputType, InputStructure, InputStorage, InputView, reference_dense, Coords > & y, const OP & op = OP(), const typename std::enable_if< grb::is_operator< OP >::value && ! grb::is_object< IOType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType >::value, void >::type * = NULL ) { @@ -1576,10 +1677,15 @@ namespace grb { * * Masked variant. */ - template< Descriptor descr = descriptors::no_operation, class Monoid, typename IOType, typename MaskType, typename InputType, typename IOView, typename MaskView, typename InputView, typename Coords > - RC foldl( VectorView< IOType, IOView, storage::Dense, reference_dense, Coords > & x, - const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & m, - const VectorView< InputType, InputView, storage::Dense, reference_dense, Coords > & y, + template< Descriptor descr = descriptors::no_operation, class Monoid, + typename IOType, typename MaskType, typename InputType, + typename IOStructure, typename MaskStructure, typename InputStructure, + typename IOStorage, typename MaskStorage, typename InputStorage, + typename IOView, typename MaskView, typename InputView, + typename Coords > + RC foldl( VectorView< IOType, IOStructure, IOStorage, IOView, reference_dense, Coords > & x, + const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense, Coords > & m, + const VectorView< InputType, InputStructure, InputStorage, InputView, reference_dense, Coords > & y, const Monoid & monoid = Monoid(), const typename std::enable_if< grb::is_monoid< Monoid >::value && ! grb::is_object< IOType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType >::value, void >::type * = NULL ) { @@ -1637,18 +1743,18 @@ namespace grb { * An eWiseAdd with some semiring and an eWiseApply using its additive * monoid are totally equivalent. * - * @tparam descr The descriptor to be used. Equal to - * descriptors::no_operation if left unspecified. - * @tparam OP The operator to use. - * @tparam InputType1 The value type of the left-hand vector. - * @tparam InputType2 The value type of the right-hand scalar. - * @tparam OutputType The value type of the ouput vector. - * @tparam InputView1 The view type applied to the left-hand vector. - * @tparam InputView2 The view type applied to the right-hand vector. - * @tparam OutputView1 The view type applied to the output vector. - * @tparam InputTmp1 Whether the left-hand vector is a temporary. - * @tparam InputTmp2 Whether the right-hand vector is a temporary. - * @tparam OutputTmp1 Whether the output vector is a temporary. + * @tparam descr The descriptor to be used. Equal to + * descriptors::no_operation if left unspecified. + * @tparam OP The operator to use. + * @tparam InputType1 The value type of the left-hand vector. + * @tparam InputType2 The value type of the right-hand scalar. + * @tparam OutputType The value type of the ouput vector. + * @tparam InputStructure1 The structure of the left-hand vector. + * @tparam OutputStructure1 The structure of the output vector. + * @tparam InputStorage1 The storage type of the left-hand vector. + * @tparam OutputStorage1 The storage type of the output vector. + * @tparam InputView1 The view type applied to the left-hand vector. + * @tparam OutputView1 The view type applied to the output vector. * * @param[in] x The left-hand input vector. * @param[in] beta The right-hand input scalar. @@ -1683,9 +1789,14 @@ namespace grb { // * this. // * \endparblock */ - template< Descriptor descr = descriptors::no_operation, class OP, typename OutputType, typename InputType1, typename InputType2, typename OutputView, typename InputView1, typename InputView2, typename Coords > - RC eWiseApply( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, - const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords > & x, + template< Descriptor descr = descriptors::no_operation, class OP, + typename OutputType, typename InputType1, typename InputType2, + typename OutputStructure, typename InputStructure1, + typename OutputStorage, typename InputStorage1, + typename OutputView, typename InputView1, + typename Coords > + RC eWiseApply( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & z, + const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense, Coords > & x, const InputType2 beta, const OP & op = OP(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_operator< OP >::value, @@ -1702,8 +1813,13 @@ namespace grb { * * Specialisation for \a x and \a y scalar, operator version. */ - template< Descriptor descr = descriptors::no_operation, class OP, typename OutputType, typename InputType1, typename InputType2, typename OutputView, typename InputView1, typename InputView2, typename Coords > - RC eWiseApply( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, + template< Descriptor descr = descriptors::no_operation, class OP, + typename OutputType, typename InputType1, typename InputType2, + typename OutputStructure, + typename OutputStorage, + typename OutputView, + typename Coords > + RC eWiseApply( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & z, const InputType1 alpha, const InputType2 beta, const OP & op = OP(), @@ -1723,8 +1839,13 @@ namespace grb { * * Specialisation for \a x and \a y scalar, monoid version. */ - template< Descriptor descr = descriptors::no_operation, class Monoid, typename OutputType, typename InputType1, typename InputType2, typename OutputView, typename InputView1, typename InputView2, typename Coords > - RC eWiseApply( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, + template< Descriptor descr = descriptors::no_operation, class Monoid, + typename OutputType, typename InputType1, typename InputType2, + typename OutputStructure, + typename OutputStorage, + typename OutputView, + typename Coords > + RC eWiseApply( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & z, const InputType1 alpha, const InputType2 beta, const Monoid & monoid = Monoid(), @@ -1742,10 +1863,15 @@ namespace grb { * * Specialisation for scalar \a y, masked operator version. */ - template< Descriptor descr = descriptors::no_operation, class OP, typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename OutputView, typename MaskView, typename InputView1, typename InputView2, typename Coords > - RC eWiseApply( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, - const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & mask, - const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords > & x, + template< Descriptor descr = descriptors::no_operation, class OP, + typename OutputType, typename MaskType, typename InputType1, typename InputType2, + typename OutputStructure, typename MaskStructure, typename InputStructure1, + typename OutputStorage, typename MaskStorage, typename InputStorage1, + typename OutputView, typename MaskView, typename InputView1, + typename Coords > + RC eWiseApply( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & z, + const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense, Coords > & mask, + const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense, Coords > & x, const InputType2 beta, const OP & op = OP(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && @@ -1767,10 +1893,15 @@ namespace grb { * * Monoid version. */ - template< Descriptor descr = descriptors::no_operation, class Monoid, typename OutputType, typename InputType1, typename InputType2, typename OutputView, typename InputView1, typename InputView2, typename Coords > - RC eWiseApply( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, - const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords > & x, - const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords > & y, + template< Descriptor descr = descriptors::no_operation, class Monoid, + typename OutputType, typename InputType1, typename InputType2, + typename OutputStructure, typename InputStructure1, typename InputStructure2, + typename OutputStorage, typename InputStorage1, typename InputStorage2, + typename OutputView, typename InputView1, typename InputView2, + typename Coords > + RC eWiseApply( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & z, + const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense, Coords > & x, + const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense, Coords > & y, const Monoid & monoid = Monoid(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_monoid< Monoid >::value, void >::type * const = NULL ) { @@ -1786,10 +1917,15 @@ namespace grb { * * Specialisation for scalar \a x. Monoid version. */ - template< Descriptor descr = descriptors::no_operation, class Monoid, typename OutputType, typename InputType1, typename InputType2, typename OutputView, typename InputView1, typename InputView2, typename Coords > - RC eWiseApply( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, + template< Descriptor descr = descriptors::no_operation, class Monoid, + typename OutputType, typename InputType1, typename InputType2, + typename OutputStructure, typename InputStructure2, + typename OutputStorage, typename InputStorage2, + typename OutputView, typename InputView2, + typename Coords > + RC eWiseApply( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & z, const InputType1 alpha, - const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords > & y, + const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense, Coords > & y, const Monoid & monoid = Monoid(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_monoid< Monoid >::value, void >::type * const = NULL ) { @@ -1805,9 +1941,14 @@ namespace grb { * * Specialisation for scalar \a y. Monoid version. */ - template< Descriptor descr = descriptors::no_operation, class Monoid, typename OutputType, typename InputType1, typename InputType2, typename OutputView, typename InputView1, typename InputView2, typename Coords > - RC eWiseApply( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, - const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords > & x, + template< Descriptor descr = descriptors::no_operation, class Monoid, + typename OutputType, typename InputType1, typename InputType2, + typename OutputStructure, typename InputStructure1, + typename OutputStorage, typename InputStorage1, + typename OutputView, typename InputView1, + typename Coords > + RC eWiseApply( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & z, + const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense, Coords > & x, const InputType2 beta, const Monoid & monoid = Monoid(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_monoid< Monoid >::value, @@ -1824,11 +1965,16 @@ namespace grb { * * Masked monoid version. */ - template< Descriptor descr = descriptors::no_operation, class Monoid, typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename OutputView, typename MaskView, typename InputView1, typename InputView2, typename Coords > - RC eWiseApply( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, - const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & mask, - const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords > & x, - const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords > & y, + template< Descriptor descr = descriptors::no_operation, class Monoid, + typename OutputType, typename MaskType, typename InputType1, typename InputType2, + typename OutputStructure, typename MaskStructure, typename InputStructure1, typename InputStructure2, + typename OutputStorage, typename MaskStorage, typename InputStorage1, typename InputStorage2, + typename OutputView, typename MaskView, typename InputView1, typename InputView2, + typename Coords > + RC eWiseApply( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & z, + const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense, Coords > & mask, + const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense, Coords > & x, + const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense, Coords > & y, const Monoid & monoid = Monoid(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_monoid< Monoid >::value, @@ -1845,11 +1991,16 @@ namespace grb { * * Specialisation for scalar \a x. Masked monoid version. */ - template< Descriptor descr = descriptors::no_operation, class Monoid, typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename OutputView, typename MaskView, typename InputView1, typename InputView2, typename Coords > - RC eWiseApply( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, - const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & mask, + template< Descriptor descr = descriptors::no_operation, class Monoid, + typename OutputType, typename MaskType, typename InputType1, typename InputType2, + typename OutputStructure, typename MaskStructure, typename InputStructure2, + typename OutputStorage, typename MaskStorage, typename InputStorage2, + typename OutputView, typename MaskView, typename InputView2, + typename Coords > + RC eWiseApply( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & z, + const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense, Coords > & mask, const InputType1 alpha, - const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords > & y, + const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense, Coords > & y, const Monoid & monoid = Monoid(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_monoid< Monoid >::value, @@ -1866,10 +2017,15 @@ namespace grb { * * Specialisation for scalar \a y. Masked monoid version. */ - template< Descriptor descr = descriptors::no_operation, class Monoid, typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename OutputView, typename MaskView, typename InputView1, typename InputView2, typename Coords > - RC eWiseApply( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, - const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & mask, - const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords > & x, + template< Descriptor descr = descriptors::no_operation, class Monoid, + typename OutputType, typename MaskType, typename InputType1, typename InputType2, + typename OutputStructure, typename MaskStructure, typename InputStructure1, + typename OutputStorage, typename MaskStorage, typename InputStorage1, + typename OutputView, typename MaskView, typename InputView1, + typename Coords > + RC eWiseApply( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & z, + const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense, Coords > & mask, + const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense, Coords > & x, const InputType2 beta, const Monoid & monoid = Monoid(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && @@ -1910,9 +2066,14 @@ namespace grb { * @tparam descr The descriptor to be used. Equal to descriptors::no_operation * if left unspecified. * @tparam OP The operator to use. - * @tparam InputType1 The value type of the left-hand scalar. - * @tparam InputType2 The value type of the right-hand side vector. - * @tparam OutputType The value type of the ouput vector. + * @tparam InputType1 The value type of the left-hand scalar. + * @tparam InputType2 The value type of the right-hand side vector. + * @tparam OutputStructure The value Structure of the ouput vector. + * @tparam InputStructure2 The value Structure of the right-hand side vector. + * @tparam OutputStorage The type of storage of the ouput vector. + * @tparam InputStorage2 The type of storage of the right-hand side vector. + * @tparam OutputView The view type of the ouput vector. + * @tparam InputView2 The view type of the right-hand side vector. * * @param[in] alpha The left-hand scalar. * @param[in] y The right-hand input vector. @@ -1947,10 +2108,15 @@ namespace grb { // * this. // * \endparblock */ - template< Descriptor descr = descriptors::no_operation, class OP, typename OutputType, typename InputType1, typename InputType2, typename OutputView, typename InputView1, typename InputView2, typename Coords > - RC eWiseApply( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, + template< Descriptor descr = descriptors::no_operation, class OP, + typename OutputType, typename InputType1, typename InputType2, + typename OutputStructure, typename InputStructure2, + typename OutputStorage, typename InputStorage2, + typename OutputView, typename InputView2, + typename Coords > + RC eWiseApply( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & z, const InputType1 alpha, - const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords > & y, + const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense, Coords > & y, const OP & op = OP(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_operator< OP >::value, void >::type * const = NULL ) { @@ -1966,11 +2132,16 @@ namespace grb { * * Specialisation for scalar \a x. Masked operator version. */ - template< Descriptor descr = descriptors::no_operation, class OP, typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename OutputView, typename MaskView, typename InputView1, typename InputView2, typename Coords > - RC eWiseApply( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, - const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & mask, + template< Descriptor descr = descriptors::no_operation, class OP, + typename OutputType, typename MaskType, typename InputType1, typename InputType2, + typename OutputStructure, typename MaskStructure, typename InputStructure2, + typename OutputStorage, typename MaskStorage, typename InputStorage2, + typename OutputView, typename MaskView, typename InputView2, + typename Coords > + RC eWiseApply( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & z, + const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense, Coords > & mask, const InputType1 alpha, - const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords > & y, + const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense, Coords > & y, const OP & op = OP(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_operator< OP >::value, @@ -2010,9 +2181,18 @@ namespace grb { * @tparam descr The descriptor to be used (descriptors::no_operation if left * unspecified). * @tparam OP The operator to use. - * @tparam InputType1 The value type of the left-hand side vector. - * @tparam InputType2 The value type of the right-hand side vector. - * @tparam OutputType The value type of the ouput vector. + * @tparam InputType1 The value type of the left-hand side vector. + * @tparam InputType2 The value type of the right-hand side vector. + * @tparam OutputType The value type of the ouput vector. + * @tparam InputStructure1 The structure of the left-hand side vector. + * @tparam InputStructure2 The structure of the right-hand side vector. + * @tparam OutputStructure The structure of the ouput vector. + * @tparam InputStorage1 The type of storage of the left-hand side vector. + * @tparam InputStorage2 The type of storage of the right-hand side vector. + * @tparam OutputStorage The type of storage of the ouput vector. + * @tparam InputView1 The value View of the left-hand side vector. + * @tparam InputView2 The value View of the right-hand side vector. + * @tparam OutputView The value View of the ouput vector. * * @param[in] x The left-hand input vector. May not equal \a y. * @param[in] y The right-hand input vector. May not equal \a x. @@ -2050,10 +2230,15 @@ namespace grb { // * used allow for this. // * \endparblock */ - template< Descriptor descr = descriptors::no_operation, class OP, typename OutputType, typename InputType1, typename InputType2, typename OutputView, typename InputView1, typename InputView2, typename Coords > - RC eWiseApply( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, - const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords > & x, - const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords > & y, + template< Descriptor descr = descriptors::no_operation, class OP, + typename OutputType, typename InputType1, typename InputType2, + typename OutputStructure, typename InputStructure1, typename InputStructure2, + typename OutputStorage, typename InputStorage1, typename InputStorage2, + typename OutputView, typename InputView1, typename InputView2, + typename Coords > + RC eWiseApply( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & z, + const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense, Coords > & x, + const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense, Coords > & y, const OP & op = OP(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_operator< OP >::value, void >::type * const = NULL ) { @@ -2069,11 +2254,16 @@ namespace grb { * * Masked operator version. */ - template< Descriptor descr = descriptors::no_operation, class OP, typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename OutputView, typename MaskView, typename InputView1, typename InputView2, typename Coords > - RC eWiseApply( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, - const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & mask, - const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords > & x, - const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords > & y, + template< Descriptor descr = descriptors::no_operation, class OP, + typename OutputType, typename MaskType, typename InputType1, typename InputType2, + typename OutputStructure, typename MaskStructure, typename InputStructure1, typename InputStructure2, + typename OutputStorage, typename MaskStorage, typename InputStorage1, typename InputStorage2, + typename OutputView, typename MaskView, typename InputView1, typename InputView2, + typename Coords > + RC eWiseApply( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & z, + const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense, Coords > & mask, + const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense, Coords > & x, + const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense, Coords > & y, const OP & op = OP(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_operator< OP >::value, @@ -2099,12 +2289,15 @@ namespace grb { * of the \a ring. * @tparam OutputType The the result type of the additive operator of the * \a ring. - * @tparam InputView1 The view type applied to the left-hand vector. - * @tparam InputView2 The view type applied to the right-hand vector. - * @tparam OutputView1 The view type applied to the output vector. - * @tparam InputTmp1 Whether the left-hand vector is a temporary. - * @tparam InputTmp2 Whether the right-hand vector is a temporary. - * @tparam OutputTmp1 Whether the output vector is a temporary. + * @tparam InputStructure1 The structure of the left-hand vector. + * @tparam InputStructure2 The structure of the right-hand vector. + * @tparam OutputStructure1 The structure of the output vector. + * @tparam InputStorage1 The type of storage of the left-hand vector. + * @tparam InputStorage2 The type of storage of the right-hand vector. + * @tparam OutputStorage1 The type of storage of the output vector. + * @tparam InputView1 The view type applied to the left-hand vector. + * @tparam InputView2 The view type applied to the right-hand vector. + * @tparam OutputView1 The view type applied to the output vector. * * @param[out] z The output vector of type \a OutputType. This may be a * sparse vector. @@ -2163,10 +2356,15 @@ namespace grb { * * @see This is a specialised form of eWiseMulAdd. */ - template< Descriptor descr = descriptors::no_operation, class Ring, typename OutputType, typename InputType1, typename InputType2, typename OutputView, typename InputView1, typename InputView2, typename Coords > - RC eWiseAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, - const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords > & x, - const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords > & y, + template< Descriptor descr = descriptors::no_operation, class Ring, + typename OutputType, typename InputType1, typename InputType2, + typename OutputStructure, typename InputStructure1, typename InputStructure2, + typename OutputStorage, typename InputStorage1, typename InputStorage2, + typename OutputView, typename InputView1, typename InputView2, + typename Coords > + RC eWiseAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & z, + const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense, Coords > & x, + const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense, Coords > & y, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_semiring< Ring >::value, void >::type * const = NULL ) { @@ -2192,10 +2390,15 @@ namespace grb { * * Specialisation for scalar \a x. */ - template< Descriptor descr = descriptors::no_operation, class Ring, typename InputType1, typename InputType2, typename OutputType, typename InputView2, typename OutputView, typename Coords > - RC eWiseAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, + template< Descriptor descr = descriptors::no_operation, class Ring, + typename OutputType, typename InputType1, typename InputType2, + typename OutputStructure, typename InputStructure2, + typename OutputStorage, typename InputStorage2, + typename OutputView, typename InputView2, + typename Coords > + RC eWiseAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & z, const InputType1 alpha, - const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords > & y, + const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense, Coords > & y, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_semiring< Ring >::value, void >::type * const = NULL ) { @@ -2221,9 +2424,14 @@ namespace grb { * * Specialisation for scalar \a y. */ - template< Descriptor descr = descriptors::no_operation, class Ring, typename InputType1, typename InputType2, typename OutputType, typename InputView1, typename OutputView,typename Coords > - RC eWiseAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, - const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords > & x, + template< Descriptor descr = descriptors::no_operation, class Ring, + typename OutputType, typename InputType1, typename InputType2, + typename OutputStructure, typename InputStructure1, + typename OutputStorage, typename InputStorage1, + typename OutputView, typename InputView1, + typename Coords > + RC eWiseAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & z, + const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense, Coords > & x, const InputType2 beta, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_semiring< Ring >::value, @@ -2250,8 +2458,13 @@ namespace grb { * * Specialisation for scalar \a x and \a y. */ - template< Descriptor descr = descriptors::no_operation, class Ring, typename InputType1, typename InputType2, typename OutputType, typename OutputView, typename Coords > - RC eWiseAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, + template< Descriptor descr = descriptors::no_operation, class Ring, + typename OutputType, typename InputType1, typename InputType2, + typename OutputStructure, + typename OutputStorage, + typename OutputView, + typename Coords > + RC eWiseAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & z, const InputType1 alpha, const InputType2 beta, const Ring & ring = Ring(), @@ -2281,11 +2494,16 @@ namespace grb { * * Masked version. */ - template< Descriptor descr = descriptors::no_operation, class Ring, typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename OutputView, typename MaskView, typename InputView1, typename InputView2, typename Coords > - RC eWiseAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, - const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & m, - const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords > & x, - const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords > & y, + template< Descriptor descr = descriptors::no_operation, class Ring, + typename OutputType, typename MaskType, typename InputType1, typename InputType2, + typename OutputStructure, typename MaskStructure, typename InputStructure1, typename InputStructure2, + typename OutputStorage, typename MaskStorage, typename InputStorage1, typename InputStorage2, + typename OutputView, typename MaskView, typename InputView1, typename InputView2, + typename Coords > + RC eWiseAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & z, + const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense, Coords > & m, + const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense, Coords > & x, + const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense, Coords > & y, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_semiring< Ring >::value, @@ -2314,11 +2532,16 @@ namespace grb { * * Specialisation for scalar \a x, masked version */ - template< Descriptor descr = descriptors::no_operation, class Ring, typename InputType1, typename InputType2, typename OutputType, typename MaskType, typename InputView2, typename OutputView, typename MaskView, typename Coords > - RC eWiseAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, - const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & m, + template< Descriptor descr = descriptors::no_operation, class Ring, + typename OutputType, typename MaskType, typename InputType1, typename InputType2, + typename OutputStructure, typename MaskStructure, typename InputStructure2, + typename OutputStorage, typename MaskStorage, typename InputStorage2, + typename OutputView, typename MaskView, typename InputView2, + typename Coords > + RC eWiseAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & z, + const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense, Coords > & m, const InputType1 alpha, - const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords > & y, + const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense, Coords > & y, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_semiring< Ring >::value, @@ -2347,10 +2570,15 @@ namespace grb { * * Specialisation for scalar \a y, masked version. */ - template< Descriptor descr = descriptors::no_operation, class Ring, typename InputType1, typename InputType2, typename OutputType, typename MaskType, typename InputView1, typename OutputView, typename MaskView, typename Coords > - RC eWiseAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, - const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & m, - const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords > & x, + template< Descriptor descr = descriptors::no_operation, class Ring, + typename OutputType, typename MaskType, typename InputType1, typename InputType2, + typename OutputStructure, typename MaskStructure, typename InputStructure1, + typename OutputStorage, typename MaskStorage, typename InputStorage1, + typename OutputView, typename MaskView, typename InputView1, + typename Coords > + RC eWiseAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & z, + const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense, Coords > & m, + const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense, Coords > & x, const InputType2 beta, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && @@ -2380,9 +2608,14 @@ namespace grb { * * Specialisation for scalar \a x and \a y, masked version. */ - template< Descriptor descr = descriptors::no_operation, class Ring, typename InputType1, typename InputType2, typename OutputType, typename MaskType, typename OutputView, typename Coords > - RC eWiseAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, - const VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & m, + template< Descriptor descr = descriptors::no_operation, class Ring, + typename OutputType, typename MaskType, typename InputType1, typename InputType2, + typename OutputStructure, typename MaskStructure, + typename OutputStorage, typename MaskStorage, + typename OutputView, typename MaskView, + typename Coords > + RC eWiseAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & z, + const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense, Coords > & m, const InputType1 alpha, const InputType2 beta, const Ring & ring = Ring(), @@ -2414,11 +2647,16 @@ namespace grb { * * Specialisation for when \a a is a scalar. */ - template< Descriptor descr = descriptors::no_operation, class Ring, typename InputType1, typename InputType2, typename InputType3, typename OutputType, typename InputView2, typename InputView3, typename OutputView, typename Coords > - RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & _z, + template< Descriptor descr = descriptors::no_operation, class Ring, + typename OutputType, typename InputType1, typename InputType2, typename InputType3, + typename OutputStructure, typename InputStructure2, typename InputStructure3, + typename OutputStorage, typename InputStorage2, typename InputStorage3, + typename OutputView, typename InputView2, typename InputView3, + typename Coords > + RC eWiseMulAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & _z, const InputType1 alpha, - const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords > & _x, - const VectorView< InputType3, InputView3, storage::Dense, reference_dense, Coords > & _y, + const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense, Coords > & _x, + const VectorView< InputType3, InputStructure3, InputStorage3, InputView3, reference_dense, Coords > & _y, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && grb::is_semiring< Ring >::value, @@ -2446,11 +2684,16 @@ namespace grb { * * Specialisation for when \a x is a scalar. */ - template< Descriptor descr = descriptors::no_operation, class Ring, typename InputType1, typename InputType2, typename InputType3, typename OutputType, typename InputView1, typename InputView3, typename OutputView, typename Coords > - RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & _z, - const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords > & _a, + template< Descriptor descr = descriptors::no_operation, class Ring, + typename OutputType, typename InputType1, typename InputType2, typename InputType3, + typename OutputStructure, typename InputStructure1, typename InputStructure3, + typename OutputStorage, typename InputStorage1, typename InputStorage3, + typename OutputView, typename InputView1, typename InputView3, + typename Coords > + RC eWiseMulAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & _z, + const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense, Coords > & _a, const InputType2 chi, - const VectorView< InputType3, InputView3, storage::Dense, reference_dense, Coords > & _y, + const VectorView< InputType3, InputStructure3, InputStorage3, InputView3, reference_dense, Coords > & _y, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && grb::is_semiring< Ring >::value, @@ -2477,10 +2720,15 @@ namespace grb { * * Specialisation for when \a y is a scalar. */ - template< Descriptor descr = descriptors::no_operation, class Ring, typename InputType1, typename InputType2, typename InputType3, typename OutputType, typename InputView1, typename InputView2, typename OutputView, typename Coords > - RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & _z, - const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords > & _a, - const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords > & _x, + template< Descriptor descr = descriptors::no_operation, class Ring, + typename OutputType, typename InputType1, typename InputType2, typename InputType3, + typename OutputStructure, typename InputStructure1, typename InputStructure2, + typename OutputStorage, typename InputStorage1, typename InputStorage2, + typename OutputView, typename InputView1, typename InputView2, + typename Coords > + RC eWiseMulAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & _z, + const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense, Coords > & _a, + const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense, Coords > & _x, const InputType3 gamma, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && @@ -2508,9 +2756,14 @@ namespace grb { * * Specialisation for when \a x and \a y are scalar. */ - template< Descriptor descr = descriptors::no_operation, class Ring, typename InputType1, typename InputType2, typename InputType3, typename OutputType, typename InputView1, typename OutputView, typename Coords > - RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & _z, - const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords > & _a, + template< Descriptor descr = descriptors::no_operation, class Ring, + typename OutputType, typename InputType1, typename InputType2, typename InputType3, + typename OutputStructure, typename InputStructure1, + typename OutputStorage, typename InputStorage1, + typename OutputView, typename InputView1, + typename Coords > + RC eWiseMulAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & _z, + const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense, Coords > & _a, const InputType2 beta, const InputType3 gamma, const Ring & ring = Ring(), @@ -2539,10 +2792,15 @@ namespace grb { * * Specialisation for when \a a and \a y are scalar. */ - template< Descriptor descr = descriptors::no_operation, class Ring, typename InputType1, typename InputType2, typename InputType3, typename OutputType, typename InputView2, typename OutputView, typename Coords > - RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & _z, + template< Descriptor descr = descriptors::no_operation, class Ring, + typename OutputType, typename InputType1, typename InputType2, typename InputType3, + typename OutputStructure, typename InputStructure2, + typename OutputStorage, typename InputStorage2, + typename OutputView, typename InputView2, + typename Coords > + RC eWiseMulAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & _z, const InputType1 alpha, - const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords > & _x, + const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense, Coords > & _x, const InputType3 gamma, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && @@ -2572,11 +2830,16 @@ namespace grb { * * \internal Dispatches to eWiseAdd. */ - template< Descriptor descr = descriptors::no_operation, class Ring, typename OutputType, typename InputType1, typename InputType2, typename InputType3, typename InputView3, typename OutputView, typename Coords > - RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, + template< Descriptor descr = descriptors::no_operation, class Ring, + typename OutputType, typename InputType1, typename InputType2, typename InputType3, + typename OutputStructure, typename InputStructure3, + typename OutputStorage, typename InputStorage3, + typename OutputView, typename InputView3, + typename Coords > + RC eWiseMulAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & z, const InputType1 alpha, const InputType2 beta, - const VectorView< InputType3, InputView3, storage::Dense, reference_dense, Coords > & y, + const VectorView< InputType3, InputStructure3, InputStorage3, InputView3, reference_dense, Coords > & y, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && grb::is_semiring< Ring >::value, @@ -2609,8 +2872,13 @@ namespace grb { * * \internal Dispatches to set. */ - template< Descriptor descr = descriptors::no_operation, class Ring, typename OutputType, typename InputType1, typename InputType2, typename InputType3, typename OutputView, typename Coords > - RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, + template< Descriptor descr = descriptors::no_operation, class Ring, + typename OutputType, typename InputType1, typename InputType2, typename InputType3, + typename OutputStructure, + typename OutputStorage, + typename OutputView, + typename Coords > + RC eWiseMulAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & z, const InputType1 alpha, const InputType2 beta, const InputType3 gamma, @@ -2666,14 +2934,38 @@ namespace grb { * @tparam OutputType The right-hand side input type to the additive operator * of the \a ring \em and the result type of the same * operator. - * @tparam InputView1 The view type applied to the left-hand vector. - * @tparam InputView2 The view type applied to the right-hand vector. - * @tparam InputView3 The view applied to the vector \a _y - * @tparam OutputView1 The view type applied to the output vector. - * @tparam InputTmp1 Whether the left-hand vector is a temporary. - * @tparam InputTmp2 Whether the right-hand vector is a temporary. - * @tparam InputView3 Whether the vector \a _y is a temporary. - * @tparam OutputTmp1 Whether the output vector is a temporary. + * @tparam InputStructure1 The structure of the left-hand side input to + * the multiplicative operator of the \a ring. + * @tparam InputStructure2 The structure of the left-hand side input to + * the multiplicative operator of the \a ring. + * @tparam InputStructure3 The structure of the output to the multiplicative + * operator of the \a ring \em and the left-hand side + * input to the aditive operator of the \a ring. + * @tparam OutputStructure1 The structure of the right-hand side input type + * to the additive operator of the \a ring \em and + * the result of the same operator. + * @tparam InputStorage1 The type of storage of the left-hand side input + * to the multiplicative operator of the \a ring. + * @tparam InputStorage2 The type of storage of the left-hand side input + * to the multiplicative operator of the \a ring. + * @tparam InputStorage3 The type of storage of the output to the + * multiplicative operator of the \a ring \em and + * the left-hand side input to the aditive operator + * of the \a ring. + * @tparam OutputStorage1 The type of storage of the right-hand side input + * type to the additive operator of the \a ring \em + * and the result of the same operator. + * @tparam InputView1 The view applied to the left-hand side input to + * the multiplicative operator of the \a ring. + * @tparam InputView2 The view applied to the left-hand side input to + * the multiplicative operator of the \a ring. + * @tparam InputView3 The view applied to the output to the + * multiplicative operator of the \a ring \em and + * the left-hand side input to the aditive operator + * of the \a ring. + * @tparam OutputView1 The view applied to the right-hand side input + * type to the additive operator of the \a ring \em + * and the result of the same operator. * * @param[out] _z The pre-allocated output vector. * @param[in] _a The elements for left-hand side multiplication. @@ -2731,11 +3023,16 @@ namespace grb { // * and the operators used allow for this. // * \endparblock */ - template< Descriptor descr = descriptors::no_operation, class Ring, typename InputType1, typename InputType2, typename InputType3, typename OutputType, typename InputView1, typename InputView2, typename InputView3, typename OutputView, typename Coords > - RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & _z, - const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords > & _a, - const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords > & _x, - const VectorView< InputType3, InputView3, storage::Dense, reference_dense, Coords > & _y, + template< Descriptor descr = descriptors::no_operation, class Ring, + typename OutputType, typename InputType1, typename InputType2, typename InputType3, + typename OutputStructure, typename InputStructure1, typename InputStructure2, typename InputStructure3, + typename OutputStorage, typename InputStorage1, typename InputStorage2, typename InputStorage3, + typename OutputView, typename InputView1, typename InputView2, typename InputView3, + typename Coords > + RC eWiseMulAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & _z, + const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense, Coords > & _a, + const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense, Coords > & _x, + const VectorView< InputType3, InputStructure3, InputStorage3, InputView3, reference_dense, Coords > & _y, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && grb::is_semiring< Ring >::value, @@ -2773,12 +3070,28 @@ namespace grb { * operator of the \a ring. * @tparam OutputType The the result type of the multiplicative operator of * the \a ring. - * @tparam InputView1 The view type applied to the left-hand vector. - * @tparam InputView2 The view type applied to the right-hand vector. - * @tparam OutputView1 The view type applied to the output vector. - * @tparam InputTmp1 Whether the left-hand vector is a temporary. - * @tparam InputTmp2 Whether the right-hand vector is a temporary. - * @tparam OutputTmp1 Whether the output vector is a temporary. + * @tparam InputStructure1 The structure of the left-hand side input to + * the multiplicative operator of the \a ring. + * @tparam InputStructure2 The structure of the right-hand side input + * to the multiplicative operator of the \a ring. + * @tparam OutputStructure1 The structure of the output to the + * multiplicative operator of the \a ring. + * @tparam InputStorage1 The type of storage type of the left-hand + * side input to the multiplicative operator + * of the \a ring. + * @tparam InputStorage2 The type of storage type of the right-hand + * side input to the multiplicative operator + * of the \a ring. + * @tparam OutputStorage1 The type of storage type of the output to + * the multiplicative operator of the \a ring. + * @tparam InputView1 The view type applied to the left-hand side + * input to the multiplicative operator + * of the \a ring. + * @tparam InputView2 The view type applied to the right-hand side + * input to the multiplicative operator + * of the \a ring. + * @tparam OutputView1 The view type applied to the output to the + * multiplicative operator of the \a ring. * * @param[out] z The output vector of type \a OutputType. * @param[in] x The left-hand input vector of type \a InputType1. @@ -2833,10 +3146,15 @@ namespace grb { * * @see This is a specialised form of eWiseMulAdd. */ - template< Descriptor descr = descriptors::no_operation, class Ring, typename InputType1, typename InputType2, typename OutputType, typename InputView1, typename InputView2, typename OutputView, typename Coords > - RC eWiseMul( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, - const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords > & x, - const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords > & y, + template< Descriptor descr = descriptors::no_operation, class Ring, + typename OutputType, typename InputType1, typename InputType2, + typename OutputStructure, typename InputStructure1, typename InputStructure2, + typename OutputStorage, typename InputStorage1, typename InputStorage2, + typename OutputView, typename InputView1, typename InputView2, + typename Coords > + RC eWiseMul( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & z, + const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense, Coords > & x, + const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense, Coords > & y, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_semiring< Ring >::value, void >::type * const = NULL ) { @@ -2861,10 +3179,15 @@ namespace grb { * * Specialisation for scalar \a x. */ - template< Descriptor descr = descriptors::no_operation, class Ring, typename InputType1, typename InputType2, typename OutputType, typename InputView2, typename OutputView, typename Coords > - RC eWiseMul( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, + template< Descriptor descr = descriptors::no_operation, class Ring, + typename OutputType, typename InputType1, typename InputType2, + typename OutputStructure, typename InputStructure2, + typename OutputStorage, typename InputStorage2, + typename OutputView, typename InputView2, + typename Coords > + RC eWiseMul( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & z, const InputType1 alpha, - const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords > & y, + const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense, Coords > & y, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_semiring< Ring >::value, void >::type * const = NULL ) { @@ -2889,9 +3212,14 @@ namespace grb { * * Specialisation for scalar \a y. */ - template< Descriptor descr = descriptors::no_operation, class Ring, typename InputType1, typename InputType2, typename OutputType, typename InputView1, typename OutputView, typename Coords > - RC eWiseMul( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, - const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords > & x, + template< Descriptor descr = descriptors::no_operation, class Ring, + typename OutputType, typename InputType1, typename InputType2, + typename OutputStructure, typename InputStructure1, + typename OutputStorage, typename InputStorage1, + typename OutputView, typename InputView1, + typename Coords > + RC eWiseMul( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & z, + const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense, Coords > & x, const InputType2 beta, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_semiring< Ring >::value, @@ -2917,12 +3245,17 @@ namespace grb { * * Specialisation for when \a a is a scalar, masked version. */ - template< Descriptor descr = descriptors::no_operation, class Ring, typename InputType1, typename InputType2, typename InputType3, typename OutputType, typename MaskType, typename InputView2, typename InputView3, typename OutputView, typename MaskView, typename Coords > - RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & _z, - const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & _m, + template< Descriptor descr = descriptors::no_operation, class Ring, + typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename InputType3, + typename OutputStructure, typename MaskStructure, typename InputStructure2, typename InputStructure3, + typename OutputStorage, typename MaskStorage, typename InputStorage2, typename InputStorage3, + typename OutputView, typename MaskView, typename InputView2, typename InputView3, + typename Coords > + RC eWiseMulAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & _z, + const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense, Coords > & _m, const InputType1 alpha, - const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords > & _x, - const VectorView< InputType3, InputView3, storage::Dense, reference_dense, Coords > & _y, + const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense, Coords > & _x, + const VectorView< InputType3, InputStructure3, InputStorage3, InputView3, reference_dense, Coords > & _y, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && grb::is_semiring< Ring >::value && ! grb::is_object< MaskType >::value, @@ -2951,12 +3284,17 @@ namespace grb { * * Specialisation for when \a x is a scalar, masked version. */ - template< Descriptor descr = descriptors::no_operation, class Ring, typename InputType1, typename InputType2, typename InputType3, typename OutputType, typename MaskType, typename InputView1, typename InputView3, typename OutputView, typename MaskView, typename Coords > - RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & _z, - const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & _m, - const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords > & _a, + template< Descriptor descr = descriptors::no_operation, class Ring, + typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename InputType3, + typename OutputStructure, typename MaskStructure, typename InputStructure1, typename InputStructure3, + typename OutputStorage, typename MaskStorage, typename InputStorage1, typename InputStorage3, + typename OutputView, typename MaskView, typename InputView1, typename InputView3, + typename Coords > + RC eWiseMulAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & _z, + const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense, Coords > & _m, + const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense, Coords > & _a, const InputType2 chi, - const VectorView< InputType3, InputView3, storage::Dense, reference_dense, Coords > & _y, + const VectorView< InputType3, InputStructure3, InputStorage3, InputView3, reference_dense, Coords > & _y, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && grb::is_semiring< Ring >::value && ! grb::is_object< MaskType >::value, @@ -2984,11 +3322,16 @@ namespace grb { * * Specialisation for when \a y is a scalar, masked version. */ - template< Descriptor descr = descriptors::no_operation, class Ring, typename InputType1, typename InputType2, typename InputType3, typename OutputType, typename MaskType, typename InputView1, typename InputView2, typename OutputView, typename MaskView, typename Coords > - RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & _z, - const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & _m, - const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords > & _a, - const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords > & _x, + template< Descriptor descr = descriptors::no_operation, class Ring, + typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename InputType3, + typename OutputStructure, typename MaskStructure, typename InputStructure1, typename InputStructure2, + typename OutputStorage, typename MaskStorage, typename InputStorage1, typename InputStorage2, + typename OutputView, typename MaskView, typename InputView1, typename InputView2, + typename Coords > + RC eWiseMulAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & _z, + const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense, Coords > & _m, + const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense, Coords > & _a, + const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense, Coords > & _x, const InputType3 gamma, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && @@ -3017,11 +3360,15 @@ namespace grb { * * Specialisation for when \a x and \a y are scalar, masked version. */ - template< Descriptor descr = descriptors::no_operation, class Ring, typename InputType1, typename InputType2, typename InputType3, typename OutputType, typename MaskType, - typename InputView1, typename OutputView, typename MaskView, typename Coords > - RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & _z, - const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & _m, - const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords > & _a, + template< Descriptor descr = descriptors::no_operation, class Ring, + typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename InputType3, + typename OutputStructure, typename MaskStructure, typename InputStructure1, + typename OutputStorage, typename MaskStorage, typename InputStorage1, + typename OutputView, typename MaskView, typename InputView1, + typename Coords > + RC eWiseMulAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & _z, + const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense, Coords > & _m, + const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense, Coords > & _a, const InputType2 beta, const InputType3 gamma, const Ring & ring = Ring(), @@ -3051,12 +3398,16 @@ namespace grb { * * Specialisation for when \a a and \a y are scalar, masked version. */ - template< Descriptor descr = descriptors::no_operation, class Ring, typename InputType1, typename InputType2, typename InputType3, typename OutputType, typename MaskType, - typename InputView2, typename OutputView, typename MaskView, typename Coords > - RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & _z, - const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & _m, + template< Descriptor descr = descriptors::no_operation, class Ring, + typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename InputType3, + typename OutputStructure, typename MaskStructure, typename InputStructure2, + typename OutputStorage, typename MaskStorage, typename InputStorage2, + typename OutputView, typename MaskView, typename InputView2, + typename Coords > + RC eWiseMulAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & _z, + const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense, Coords > & _m, const InputType1 alpha, - const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords > & _x, + const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense, Coords > & _x, const InputType3 gamma, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && @@ -3085,13 +3436,17 @@ namespace grb { * * Masked version. */ - template< Descriptor descr = descriptors::no_operation, class Ring, typename InputType1, typename InputType2, typename InputType3, typename OutputType, typename MaskType, - typename InputView1, typename InputView2, typename InputView3, typename OutputView, typename MaskView, typename Coords > - RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & _z, - const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & _m, - const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords > & _a, - const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords > & _x, - const VectorView< InputType3, InputView3, storage::Dense, reference_dense, Coords > & _y, + template< Descriptor descr = descriptors::no_operation, class Ring, + typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename InputType3, + typename OutputStructure, typename MaskStructure, typename InputStructure1, typename InputStructure2, typename InputStructure3, + typename OutputStorage, typename MaskStorage, typename InputStorage1, typename InputStorage2, typename InputStorage3, + typename OutputView, typename MaskView, typename InputView1, typename InputView2, typename InputView3, + typename Coords > + RC eWiseMulAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & _z, + const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense, Coords > & _m, + const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense, Coords > & _a, + const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense, Coords > & _x, + const VectorView< InputType3, InputStructure3, InputStorage3, InputView3, reference_dense, Coords > & _y, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && grb::is_semiring< Ring >::value && ! grb::is_object< MaskType >::value, @@ -3124,12 +3479,16 @@ namespace grb { * * \internal Dispatches to eWiseMulAdd with zero additive scalar. */ - template< Descriptor descr = descriptors::no_operation, class Ring, typename InputType1, typename InputType2, typename OutputType, typename MaskType, - typename InputView1, typename InputView2, typename InputView3, typename OutputView, typename MaskView, typename Coords > - RC eWiseMul( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, - const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & m, - const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords > & x, - const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords > & y, + template< Descriptor descr = descriptors::no_operation, class Ring, + typename OutputType, typename MaskType, typename InputType1, typename InputType2, + typename OutputStructure, typename MaskStructure, typename InputStructure1, typename InputStructure2, typename InputStructure3, + typename OutputStorage, typename MaskStorage, typename InputStorage1, typename InputStorage2, typename InputStorage3, + typename OutputView, typename MaskView, typename InputView1, typename InputView2, typename InputView3, + typename Coords > + RC eWiseMul( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & z, + const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense, Coords > & m, + const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense, Coords > & x, + const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense, Coords > & y, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< MaskType >::value && grb::is_semiring< Ring >::value, @@ -3158,12 +3517,16 @@ namespace grb { * * \internal Dispatches to eWiseMulAdd with zero additive scalar. */ - template< Descriptor descr = descriptors::no_operation, class Ring, typename InputType1, typename InputType2, typename OutputType, typename MaskType, - typename InputView2, typename InputView3, typename OutputView, typename MaskView, typename Coords > - RC eWiseMul( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, - const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & m, + template< Descriptor descr = descriptors::no_operation, class Ring, + typename OutputType, typename MaskType, typename InputType1, typename InputType2, + typename OutputStructure, typename MaskStructure, typename InputStructure2, typename InputStructure3, + typename OutputStorage, typename MaskStorage, typename InputStorage2, typename InputStorage3, + typename OutputView, typename MaskView, typename InputView2, typename InputView3, + typename Coords > + RC eWiseMul( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & z, + const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense, Coords > & m, const InputType1 alpha, - const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords > & y, + const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense, Coords > & y, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< MaskType >::value && grb::is_semiring< Ring >::value, @@ -3192,11 +3555,15 @@ namespace grb { * * \internal Dispatches to eWiseMulAdd with zero additive scalar. */ - template< Descriptor descr = descriptors::no_operation, class Ring, typename InputType1, typename InputType2, typename OutputType, typename MaskType, - typename InputView1, typename InputView3, typename OutputView, typename MaskView, typename Coords > - RC eWiseMul( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, - const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & m, - const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords > & x, + template< Descriptor descr = descriptors::no_operation, class Ring, + typename OutputType, typename MaskType, typename InputType1, typename InputType2, + typename OutputStructure, typename MaskStructure, typename InputStructure1, typename InputStructure3, + typename OutputStorage, typename MaskStorage, typename InputStorage1, typename InputStorage3, + typename OutputView, typename MaskView, typename InputView1, typename InputView3, + typename Coords > + RC eWiseMul( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & z, + const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense, Coords > & m, + const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense, Coords > & x, const InputType2 beta, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< MaskType >::value && @@ -3226,13 +3593,17 @@ namespace grb { * * \internal Dispatches to masked eWiseAdd. */ - template< Descriptor descr = descriptors::no_operation, class Ring, typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename InputType3, - typename OutputView, typename MaskView, typename InputView3, typename Coords > - RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, - const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & m, + template< Descriptor descr = descriptors::no_operation, class Ring, + typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename InputType3, + typename OutputStructure, typename MaskStructure, typename InputStructure3, + typename OutputStorage, typename MaskStorage, typename InputStorage3, + typename OutputView, typename MaskView, typename InputView3, + typename Coords > + RC eWiseMulAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & z, + const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense, Coords > & m, const InputType1 alpha, const InputType2 beta, - const VectorView< InputType3, InputView3, storage::Dense, reference_dense, Coords > & y, + const VectorView< InputType3, InputStructure3, InputStorage3, InputView3, reference_dense, Coords > & y, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && grb::is_semiring< Ring >::value && ! grb::is_object< MaskType >::value, @@ -3266,10 +3637,14 @@ namespace grb { * * \internal Dispatches to masked set. */ - template< Descriptor descr = descriptors::no_operation, class Ring, typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename InputType3, - typename OutputView, typename MaskView, typename Coords > - RC eWiseMulAdd( VectorView< OutputType, OutputView, storage::Dense, reference_dense, Coords > & z, - const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & m, + template< Descriptor descr = descriptors::no_operation, class Ring, + typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename InputType3, + typename OutputStructure, typename MaskStructure, + typename OutputStorage, typename MaskStorage, + typename OutputView, typename MaskView, + typename Coords > + RC eWiseMulAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & z, + const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense, Coords > & m, const InputType1 alpha, const InputType2 beta, const InputType3 gamma, @@ -3311,12 +3686,15 @@ namespace grb { template< Descriptor descr = descriptors::no_operation, class AddMonoid, class AnyOp, - typename OutputType, typename InputType1, typename InputType2, typename OutputView, typename InputView1, typename InputView2, + typename OutputType, typename InputType1, typename InputType2, + typename InputStructure1, typename InputStructure2, + typename InputStorage1, typename InputStorage2, + typename InputView1, typename InputView2, typename Coords > RC dot_generic( OutputType &z, - const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords > &x, - const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords > &y, + const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense, Coords > &x, + const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense, Coords > &y, const AddMonoid &addMonoid = AddMonoid(), const AnyOp &anyOp = AnyOp() ) { @@ -3336,10 +3714,12 @@ namespace grb { * @tparam OutputType The output type. * @tparam InputType1 The input element type of the left-hand input vector. * @tparam InputType2 The input element type of the right-hand input vector. - * @tparam InputView1 The view type applied to the left-hand input vector. - * @tparam InputView2 The view type applied to the right-hand input vector. - * @tparam InputTmp1 Whether the left-hand input vector is a temporary. - * @tparam InputTmp2 Whether the right-hand input vector is a temporary. + * @tparam InputStructure1 The structure of the left-hand input vector. + * @tparam InputStructure2 The structure of the right-hand input vector. + * @tparam InputStorage1 The type of storage of the left-hand input vector. + * @tparam InputStorage2 The type of storage of the right-hand input vector. + * @tparam InputView1 The view type applied to the left-hand input vector. + * @tparam InputView2 The view type applied to the right-hand input vector. * * @param[in,out] z The output element \f$ z + \alpha \f$. * @param[in] x The left-hand input vector. @@ -3409,12 +3789,14 @@ namespace grb { Descriptor descr = descriptors::no_operation, class AddMonoid, class AnyOp, typename OutputType, typename InputType1, typename InputType2, + typename InputStructure1, typename InputStructure2, + typename InputStorage1, typename InputStorage2, typename InputView1, typename InputView2, typename Coords > RC dot( OutputType &z, - const VectorView< InputType1, InputView1, storage::Dense, reference_dense, Coords > &x, - const VectorView< InputType2, InputView2, storage::Dense, reference_dense, Coords > &y, + const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense, Coords > &x, + const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense, Coords > &y, const AddMonoid &addMonoid = AddMonoid(), const AnyOp &anyOp = AnyOp(), const typename std::enable_if< !grb::is_object< OutputType >::value && @@ -3453,8 +3835,8 @@ namespace grb { } /** No implementation notes. */ - template< typename Func, typename DataType, typename DataView, typename Coords > - RC eWiseMap( const Func f, VectorView< DataType, DataView, storage::Dense, reference_dense, Coords > & x ) { + template< typename Func, typename DataType, typename DataStructure, typename DataStorage, typename DataView, typename Coords > + RC eWiseMap( const Func f, VectorView< DataType, DataStructure, DataStorage, DataView, reference_dense, Coords > & x ) { throw std::runtime_error( "Needs an implementation." ); return SUCCESS; } @@ -3469,8 +3851,15 @@ namespace grb { * @see VectorView::operator[]() * @see VectorView::lambda_reference */ - template< typename Func, typename DataType1, typename DataType2, typename DataView1, typename DataView2, typename Coords, typename... Args > - RC eWiseLambda( const Func f, const VectorView< DataType1, DataView1, storage::Dense, reference_dense, Coords > & x, const VectorView< DataType2, DataView2, storage::Dense, reference_dense, Coords > & y, Args const &... args ) { + template< typename Func, typename DataType1, typename DataType2, + typename DataStructure1, typename DataStructure2, + typename DataStorage1, typename DataStorage2, + typename DataView1, typename DataView2, + typename Coords, typename... Args > + RC eWiseLambda( const Func f, + const VectorView< DataType1, DataStructure1, DataStorage1, DataView1, reference_dense, Coords > & x, + const VectorView< DataType2, DataStructure2, DataStorage2, DataView2, reference_dense, Coords > & y, + Args const &... args ) { // catch mismatch if( size( x ) != size( y ) ) { return MISMATCH; @@ -3486,8 +3875,8 @@ namespace grb { * @see VectorView::operator[]() * @see VectorView::lambda_reference */ - template< typename Func, typename DataType, typename DataView, typename Coords > - RC eWiseLambda( const Func f, const VectorView< DataType, DataView, storage::Dense, reference_dense, Coords > & x ) { + template< typename Func, typename DataType, typename DataStructure, typename DataStorage, typename DataView, typename Coords > + RC eWiseLambda( const Func f, const VectorView< DataType, DataStructure, DataStorage, DataView, reference_dense, Coords > & x ) { #ifdef _DEBUG std::cout << "Info: entering eWiseLambda function on vectors.\n"; #endif @@ -3576,10 +3965,15 @@ namespace grb { * * @see grb::foldl provides similar functionality. */ - template< Descriptor descr = descriptors::no_operation, class Monoid, typename InputType, typename IOType, typename MaskType, typename InputView, typename MaskView, typename Coords > + template< Descriptor descr = descriptors::no_operation, class Monoid, + typename InputType, typename IOType, typename MaskType, + typename InputStructure, typename MaskStructure, + typename InputStorage, typename MaskStorage, + typename InputView, typename MaskView, + typename Coords > RC foldl( IOType & x, - const VectorView< InputType, InputView, storage::Dense, reference_dense, Coords > & y, - const VectorView< MaskType, MaskView, storage::Dense, reference_dense, Coords > & mask, + const VectorView< InputType, InputStructure, InputStorage, InputView, reference_dense, Coords > & y, + const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense, Coords > & mask, const Monoid & monoid = Monoid(), const typename std::enable_if< ! grb::is_object< IOType >::value && ! grb::is_object< InputType >::value && ! grb::is_object< MaskType >::value && grb::is_monoid< Monoid >::value, void >::type * const = NULL ) { @@ -3616,6 +4010,12 @@ namespace grb { * @tparam OutputType The output type. * @tparam InputType1 The input element type of the left-hand input vector. * @tparam InputType2 The input element type of the right-hand input vector. + * @tparam InputStructure1 The structure of the left-hand input vector. + * @tparam InputStructure2 The structure of the right-hand input vector. + * @tparam InputStorage1 The type of storage of the left-hand input vector. + * @tparam InputStorage2 The type of storage of the right-hand input vector. + * @tparam InputView1 The view type applied to the left-hand input vector. + * @tparam InputView2 The view type applied to the right-hand input vector. * * @param[in,out] z The output element \f$ z + \alpha \f$. * @param[in] x The left-hand input vector. @@ -3685,12 +4085,14 @@ namespace grb { Descriptor descr = descriptors::no_operation, class AddMonoid, class AnyOp, typename OutputType, typename InputType1, typename InputType2, + typename InputStructure1, typename InputStructure2, + typename InputStorage1, typename InputStorage2, typename InputView1, typename InputView2, typename InputCoords1, typename InputCoords2 > RC dot( OutputType &z, - const VectorView< InputType1, InputView1, storage::Dense, reference_dense, InputCoords1 > &x, - const VectorView< InputType2, InputView2, storage::Dense, reference_dense, InputCoords2 > &y, + const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense, InputCoords1 > &x, + const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense, InputCoords2 > &y, const AddMonoid &addMonoid = AddMonoid(), const AnyOp &anyOp = AnyOp(), const typename std::enable_if< !grb::is_object< OutputType >::value && @@ -3781,13 +4183,14 @@ namespace grb { template< Descriptor descr = descriptors::no_operation, class Ring, typename IOType, typename InputType1, typename InputType2, - typename InputView1, typename InputView2, + typename InputStructure1, typename InputStructure2, typename InputStorage1, typename InputStorage2, + typename InputView1, typename InputView2, Backend backend, typename Coords1, typename Coords2 > RC dot( IOType &x, - const VectorView< InputType1, InputView1, InputStorage1, backend, Coords1 > &left, - const VectorView< InputType2, InputView2, InputStorage2, backend, Coords2 > &right, + const VectorView< InputType1, InputStructure1, InputView1, InputStorage1, backend, Coords1 > &left, + const VectorView< InputType2, InputStructure2, InputView2, InputStorage2, backend, Coords2 > &right, const Ring &ring = Ring(), const typename std::enable_if< !grb::is_object< InputType1 >::value && @@ -3829,13 +4232,14 @@ namespace grb { */ template< Descriptor descr = descriptors::no_operation, class Ring, - typename InputType, typename OutputType, - typename InputView, + typename OutputType, typename InputType, + typename InputStructure, typename InputStorage, + typename InputView, Backend backend, typename Coords > RC norm2( OutputType &x, - const VectorView< InputType, InputView, InputStorage, backend, Coords > &y, + const VectorView< InputType, InputStructure, InputStorage, InputView, backend, Coords > &y, const Ring &ring = Ring(), const typename std::enable_if< std::is_floating_point< OutputType >::value, diff --git a/include/graphblas/denseref/blas2.hpp b/include/graphblas/denseref/blas2.hpp index 47386e0c3..425a68f66 100644 --- a/include/graphblas/denseref/blas2.hpp +++ b/include/graphblas/denseref/blas2.hpp @@ -140,9 +140,9 @@ namespace grb { typename InputType2, typename InputStructure2, typename InputStorage2, typename InputView2, typename InputType3, typename InputType3, typename InputView3, typename InputStorage3, typename Coords > - RC vxm( VectorView< IOType, IOView, IOStorage, reference_dense, Coords > & u, - const VectorView< InputType3, InputView3, InputStorage3, reference_dense, Coords > & mask, - const VectorView< InputType1, InputView1, InputStorage1, reference_dense, Coords > & v, + RC vxm( VectorView< IOType, IOStructure, IOStorage, IOView, reference_dense, Coords > & u, + const VectorView< InputType3, InputStructure3, InputStorage3, InputView3, reference_dense, Coords > & mask, + const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense, Coords > & v, const StructuredMatrix< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > & A, const Ring & ring = Ring(), const typename std::enable_if< grb::is_semiring< Ring >::value, void >::type * const = NULL ) { @@ -159,9 +159,9 @@ namespace grb { typename InputType2, typename InputStructure2, typename InputStorage2, typename InputView2, typename InputType3, typename InputView3, typename InputStorage3, typename Coords > - RC vxm( VectorView< IOType, IOView, IOStorage, reference_dense, Coords > & u, - const VectorView< InputType3, InputView3, InputStorage3, reference_dense, Coords > & mask, - const VectorView< InputType1, InputView1, InputStorage1, reference_dense, Coords > & v, + RC vxm( VectorView< IOType, IOStructure, IOStorage, IOView, reference_dense, Coords > & u, + const VectorView< InputType3, InputStructure3, InputStorage3, InputView3, reference_dense, Coords > & mask, + const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense, Coords > & v, const StructuredMatrix< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > & A, const AdditiveMonoid & add = AdditiveMonoid(), const MultiplicativeOperator & mul = MultiplicativeOperator(), @@ -183,10 +183,10 @@ namespace grb { typename InputType3, typename InputView3, typename InputStorage3, typename InputType4, typename InputView4, typename InputStorage4, typename Coords > - RC vxm( VectorView< IOType, IOView, IOStorage, reference_dense, Coords > & u, - const VectorView< InputType3, InputView3, InputStorage3, reference_dense, Coords > & mask, - const VectorView< InputType1, InputView1, InputStorage1, reference_dense, Coords > & v, - const VectorView< InputType4, InputView4, InputStorage4, reference_dense, Coords > & v_mask, + RC vxm( VectorView< IOType, IOStructure, IOStorage, IOView, reference_dense, Coords > & u, + const VectorView< InputType3, InputStructure3, InputStorage3, InputView3, reference_dense, Coords > & mask, + const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense, Coords > & v, + const VectorView< InputType4, InputStructure4, InputStorage4, InputView4, reference_dense, Coords > & v_mask, const StructuredMatrix< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > & A, const Ring & ring = Ring(), const typename std::enable_if< grb::is_semiring< Ring >::value, void >::type * const = NULL ) { @@ -201,8 +201,8 @@ namespace grb { typename InputType1 = typename Ring::D1, typename InputView1, typename InputStorage1, typename InputType2 = typename Ring::D2, typename InputStructure2, typename InputStorage2, typename InputView2, typename Coords > - RC vxm( VectorView< IOType, IOView, IOStorage, reference_dense, Coords > & u, - const VectorView< InputType1, InputView1, InputStorage1, reference_dense, Coords > & v, + RC vxm( VectorView< IOType, IOStructure, IOStorage, IOView, reference_dense, Coords > & u, + const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense, Coords > & v, const StructuredMatrix< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > & A, const Ring & ring = Ring(), const typename std::enable_if< grb::is_semiring< Ring >::value, void >::type * const = NULL ) { @@ -212,8 +212,8 @@ namespace grb { /** \internal Delegates to fully masked version */ template< Descriptor descr = descriptors::no_operation, class AdditiveMonoid, class MultiplicativeOperator, typename IOType, typename InputType1, typename InputType2, typename Coords > - RC vxm( VectorView< IOType, IOView, IOStorage, reference_dense, Coords > & u, - const VectorView< InputType1, InputView1, InputStorage1, reference_dense, Coords > & v, + RC vxm( VectorView< IOType, IOStructure, IOStorage, IOView, reference_dense, Coords > & u, + const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense, Coords > & v, const StructuredMatrix< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > & A, const AdditiveMonoid & add = AdditiveMonoid(), const MultiplicativeOperator & mul = MultiplicativeOperator(), @@ -232,10 +232,10 @@ namespace grb { typename InputType2, typename InputStructure2, typename InputStorage2, typename InputView2, typename InputType3 = bool, typename InputView3, typename InputStorage3, typename Coords > - RC mxv( VectorView< IOType, IOView, IOStorage, reference_dense, Coords > & u, - const VectorView< InputType3, InputView3, InputStorage3, reference_dense, Coords > & mask, + RC mxv( VectorView< IOType, IOStructure, IOStorage, IOView, reference_dense, Coords > & u, + const VectorView< InputType3, InputStructure3, InputStorage3, InputView3, reference_dense, Coords > & mask, const StructuredMatrix< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > & A, - const VectorView< InputType1, InputView1, InputStorage1, reference_dense, Coords > & v, + const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense, Coords > & v, const Ring & ring, const typename std::enable_if< grb::is_semiring< Ring >::value, void >::type * const = NULL ) { const VectorView< bool, reference_dense, Coords > empty_mask( 0 ); @@ -253,11 +253,11 @@ namespace grb { typename InputType3, typename InputView3, typename InputStorage3, typename InputType4, typename InputView4, typename InputStorage4, typename Coords > - RC mxv( VectorView< IOType, IOView, IOStorage, reference_dense, Coords > & u, - const VectorView< InputType3, InputView3, InputStorage3, reference_dense, Coords > & mask, + RC mxv( VectorView< IOType, IOStructure, IOStorage, IOView, reference_dense, Coords > & u, + const VectorView< InputType3, InputStructure3, InputStorage3, InputView3, reference_dense, Coords > & mask, const StructuredMatrix< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > & A, - const VectorView< InputType1, InputView1, InputStorage1, reference_dense, Coords > & v, - const VectorView< InputType4, InputView4, InputStorage4, reference_dense, Coords > & v_mask, + const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense, Coords > & v, + const VectorView< InputType4, InputStructure4, InputStorage4, InputView4, reference_dense, Coords > & v_mask, const Ring & ring, const typename std::enable_if< grb::is_semiring< Ring >::value, void >::type * const = NULL ) { @@ -270,13 +270,13 @@ namespace grb { */ template< Descriptor descr = descriptors::no_operation, class Ring, - typename IOType = typename Ring::D4, typename IOView, IOStorage, + typename IOType = typename Ring::D4, typename IOView, typename IOStorage, typename InputType1 = typename Ring::D1, typename InputStructure2, typename InputStorage2, typename InputView2, typename InputType2 = typename Ring::D2, typename InputView1, typename InputStorage1, typename Coords > - RC mxv( VectorView< IOType, IOView, IOStorage, reference_dense, Coords > & u, + RC mxv( VectorView< IOType, IOStructure, IOStorage, IOView, reference_dense, Coords > & u, const StructuredMatrix< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > & A, - const VectorView< InputType1, InputView1, InputStorage1, reference_dense, Coords > & v, + const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense, Coords > & v, const Ring & ring, const typename std::enable_if< grb::is_semiring< Ring >::value, void >::type * const = NULL ) { const VectorView< bool, view::Original< void >, structure::full, reference_dense, Coords > empty_mask( 0 ); @@ -285,9 +285,9 @@ namespace grb { /** \internal Delegates to fully masked version */ template< Descriptor descr = descriptors::no_operation, class AdditiveMonoid, class MultiplicativeOperator, typename IOType, typename InputType1, typename InputType2, typename Coords > - RC mxv( VectorView< IOType, IOView, IOStorage, reference_dense, Coords > & u, + RC mxv( VectorView< IOType, IOStructure, IOStorage, IOView, reference_dense, Coords > & u, const StructuredMatrix< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > & A, - const VectorView< InputType1, InputView1, InputStorage1, reference_dense, Coords > & v, + const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense, Coords > & v, const AdditiveMonoid & add = AdditiveMonoid(), const MultiplicativeOperator & mul = MultiplicativeOperator(), const typename std::enable_if< grb::is_monoid< AdditiveMonoid >::value && grb::is_operator< MultiplicativeOperator >::value && ! grb::is_object< IOType >::value && @@ -311,10 +311,10 @@ namespace grb { typename InputType3, typename InputView3, typename InputStorage3, typename InputType4, typename InputView4, typename InputStorage4, typename Coords > - RC vxm( VectorView< IOType, IOView, IOStorage, reference_dense, Coords > & u, - const VectorView< InputType3, InputView3, InputStorage3, reference_dense, Coords > & mask, - const VectorView< InputType1, InputView1, InputStorage1, reference_dense, Coords > & v, - const VectorView< InputType4, InputView4, InputStorage4, reference_dense, Coords > & v_mask, + RC vxm( VectorView< IOType, IOStructure, IOStorage, IOView, reference_dense, Coords > & u, + const VectorView< InputType3, InputStructure3, InputStorage3, InputView3, reference_dense, Coords > & mask, + const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense, Coords > & v, + const VectorView< InputType4, InputStructure4, InputStorage4, InputView4, reference_dense, Coords > & v_mask, const StructuredMatrix< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > & A, const AdditiveMonoid & add = AdditiveMonoid(), const MultiplicativeOperator & mul = MultiplicativeOperator(), @@ -341,11 +341,11 @@ namespace grb { typename InputType3, typename InputView3, typename InputStorage3, typename InputType4, typename InputView4, typename InputStorage4, typename Coords > - RC mxv( VectorView< IOType, reference_dense, Coords > & u, - const VectorView< InputType3, reference_dense, Coords > & mask, + RC mxv( VectorView< IOType, IOStructure, reference_dense, Coords > & u, + const VectorView< InputType3, InputStructure3, reference_dense, Coords > & mask, const StructuredMatrix< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > & A, - const VectorView< InputType1, reference_dense, Coords > & v, - const VectorView< InputType4, reference_dense, Coords > & v_mask, + const VectorView< InputType1, InputStructure1, reference_dense, Coords > & v, + const VectorView< InputType4, InputStructure4, reference_dense, Coords > & v_mask, const AdditiveMonoid & add = AdditiveMonoid(), const MultiplicativeOperator & mul = MultiplicativeOperator(), const typename std::enable_if< grb::is_monoid< AdditiveMonoid >::value && grb::is_operator< MultiplicativeOperator >::value && ! grb::is_object< IOType >::value && @@ -385,7 +385,7 @@ namespace grb { typename DataType2, typename View2, typename Storage2, typename Coords, typename... Args > RC eWiseLambda( const Func f, const StructuredMatrix< DataType1, Structure1, Storage1, View1, reference_dense > & A, - const VectorView< DataType2, View2, Storage2, reference_dense, Coords > x, Args... args ) { + const VectorView< DataType2, DataStructure2, Storage2, View2, reference_dense, Coords > x, Args... args ) { // do size checking if( ! ( size( x ) == nrows( A ) || size( x ) == ncols( A ) ) ) { std::cerr << "Mismatching dimensions: given vector of size " << size( x ) << " has nothing to do with either matrix dimension (" << nrows( A ) << " nor " << ncols( A ) << ").\n"; diff --git a/include/graphblas/denseref/blas3.hpp b/include/graphblas/denseref/blas3.hpp index a11e289bd..2ec5fdec2 100644 --- a/include/graphblas/denseref/blas3.hpp +++ b/include/graphblas/denseref/blas3.hpp @@ -140,11 +140,12 @@ namespace grb { typename OutputType, typename InputType1, typename InputType2, class Operator, class Monoid, typename OutputStructure, typename InputStructure1, typename InputStructure2, + typename OutputStorage, typename InputStorage1, typename InputStorage2, typename OutputView, typename InputView1, typename InputView2 > - RC mxm_generic( StructuredMatrix< OutputType, OutputStructure, storage::Dense, OutputView, reference_dense > &C, - const StructuredMatrix< InputType1, InputStructure1, storage::Dense, InputView1, reference_dense > &A, - const StructuredMatrix< InputType2, InputStructure2, storage::Dense, InputView2, reference_dense > &B, + RC mxm_generic( StructuredMatrix< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > &C, + const StructuredMatrix< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense > &A, + const StructuredMatrix< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > &B, const Operator &oper, const Monoid &monoid, const MulMonoid &mulMonoid, @@ -741,10 +742,16 @@ namespace grb { * @tparam InputType1 The value type of the left-hand vector. * @tparam InputType2 The value type of the right-hand scalar. * @tparam OutputType The value type of the ouput vector. - * @tparam InputView1 The view type applied to the left-hand vector. - * @tparam InputView2 The view type applied to the right-hand vector. - * @tparam OutputView1 The view type applied to the output vector. - * @tparam Operator The opertor type used for this element-wise operation + * @tparam InputStructure1 The Structure type applied to the left-hand vector. + * @tparam InputStructure2 The Structure type applied to the right-hand vector. + * @tparam OutputStructure1 The Structure type applied to the output vector. + * @tparam InputStorage1 The Storage type applied to the left-hand vector. + * @tparam InputStorage2 The Storage type applied to the right-hand vector. + * @tparam OutputStorage1 The Storage type applied to the output vector. + * @tparam InputView1 The view type applied to the left-hand vector. + * @tparam InputView2 The view type applied to the right-hand vector. + * @tparam OutputView1 The view type applied to the output vector. + * @tparam Operator The operator type used for this element-wise operation. * * @param A The output structured matrix * @param u The left-hand side vector view @@ -759,14 +766,14 @@ namespace grb { * @return grb::SUCCESS On successful completion of this call. */ template< Descriptor descr = descriptors::no_operation, - typename InputType1, typename InputType2, typename OutputType, - typename OutputStructure, + typename OutputType, typename InputType1, typename InputType2, + typename OutputStructure, typename InputStructure1, typename InputStructure2, typename OutputStorage, typename InputStorage1, typename InputStorage2, typename OutputView, typename InputView1, typename InputView2, typename InputCoords1, typename InputCoords2, class Operator > RC outer( StructuredMatrix< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > & A, - const VectorView< InputType1, InputView1, InputStorage1, reference_dense, InputCoords1 > & u, - const VectorView< InputType2, InputView2, InputStorage2, reference_dense, InputCoords2 > & v, + const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense, InputCoords1 > & u, + const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense, InputCoords2 > & v, const Operator & mul = Operator(), const typename std::enable_if< grb::is_operator< Operator >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< OutputType >::value, void >::type * const = NULL ) { diff --git a/include/graphblas/denseref/vector.hpp b/include/graphblas/denseref/vector.hpp index b6a7487b0..d3dffc3e9 100644 --- a/include/graphblas/denseref/vector.hpp +++ b/include/graphblas/denseref/vector.hpp @@ -307,19 +307,19 @@ namespace grb { * Here starts spec draft for vectorView */ - template< typename T, typename View, typename C > - size_t getLength( const VectorView< T, View, storage::Dense, reference_dense, C > &v ) noexcept { + template< typename T, typename Structure, typename View, typename C > + size_t getLength( const VectorView< T, Structure, storage::Dense, View, reference_dense, C > &v ) noexcept { return v._length(); } namespace internal { - template< typename T, typename View, typename C > - bool getInitialized( VectorView< T, View, storage::Dense, reference_dense, C > & v ) noexcept { + template< typename T, typename Structure, typename View, typename C > + bool getInitialized( VectorView< T, Structure, storage::Dense, View, reference_dense, C > & v ) noexcept { return getInitialized( v ); } - template< typename T, typename View, typename C > - void setInitialized( VectorView< T, View, storage::Dense, reference_dense, C > & v, bool initialized ) noexcept { + template< typename T, typename Structure, typename View, typename C > + void setInitialized( VectorView< T, Structure, storage::Dense, View, reference_dense, C > & v, bool initialized ) noexcept { setInitialized( v, initialized ); } } // end namespace ``grb::internal'' @@ -338,7 +338,7 @@ namespace grb { * Views can be used to create logical \em perspectives on top of a container. * For example, one may decide to refer to the part of the vector or * to reference a diagonal of a matrix as a vector. - * See specialization \a VectorView< T, view::Diagonal< StructuredMatrixT >, storage::Dense, reference_dense, C > + * See specialization \a VectorView< T, Structure, storage::Dense, view::Diagonal< StructuredMatrixT >, reference_dense, C > * as an example of such usage. * * Vector View defined as views on other vectors do not instantiate a @@ -351,6 +351,8 @@ namespace grb { * * @tparam T The type of the vector elements. \a T shall not be a GraphBLAS * type. + * @tparam Structure Structure introduced to match the template + * parameter list of \a StructuredMatrix * @tparam View One of the vector views. * All static views except for \a view::Original (via * \a view::Original cannot instantiate a new container @@ -366,17 +368,17 @@ namespace grb { * defined within their specified \a StorageSchemeType. * */ - template< typename T, typename View, typename C > - class VectorView< T, View, storage::Dense, reference_dense, C > { }; + template< typename T, typename Structure, typename View, typename C > + class VectorView< T, Structure, storage::Dense, View, reference_dense, C > { }; /** * Original View over a vector container. */ - template< typename T, typename C > - class VectorView< T, view::Original< void >, storage::Dense, reference_dense, C > { + template< typename T, typename Structure, typename C > + class VectorView< T, Structure, storage::Dense, view::Original< void >, reference_dense, C > { private: - using self_type = VectorView< T, view::Original< void >, storage::Dense, reference_dense, C >; + using self_type = VectorView< T, Structure, storage::Dense, view::Original< void >, reference_dense, C >; /********************* Storage info friends @@ -403,8 +405,8 @@ namespace grb { }; // class VectorView with physical container /** Identifies any reference_dense vector as an ALP vector. */ - template< typename T, typename View, typename Storage, typename C > - struct is_container< VectorView< T, View, Storage, reference_dense, C > > { + template< typename T, typename Structure, typename Storage, typename View, typename C > + struct is_container< VectorView< T, Structure, Storage, View, reference_dense, C > > { /** A reference_vector is an ALP object. */ static const constexpr bool value = true; }; @@ -412,11 +414,11 @@ namespace grb { /** * Vector view of a vector only via \a view::Original of another VectorView. */ - template< typename T, typename VectorViewT, typename C > - class VectorView< T, view::Original< VectorViewT >, storage::Dense, reference_dense, C > { + template< typename T, typename Structure, typename VectorViewT, typename C > + class VectorView< T, Structure, storage::Dense, view::Original< VectorViewT >, reference_dense, C > { private: - using self_type = VectorView< T, view::Original< VectorViewT >, storage::Dense, reference_dense, C >; + using self_type = VectorView< T, Structure, storage::Dense, view::Original< VectorViewT >, reference_dense, C >; using target_type = VectorViewT; /********************* @@ -460,13 +462,13 @@ namespace grb { /** * Diagonal Vector View of a structured matrix. */ - template< typename T, typename StructuredMatrixT, typename C > - class VectorView< T, view::Diagonal< StructuredMatrixT >, storage::Dense, reference_dense, C > { + template< typename T, typename Structure, typename StructuredMatrixT, typename C > + class VectorView< T, Structure, storage::Dense, view::Diagonal< StructuredMatrixT >, reference_dense, C > { private: /** Exposes the own type and the type of the VectorView object over * which this view is created. */ - using self_type = VectorView< T, view::Diagonal< StructuredMatrixT >, storage::Dense, reference_dense, C >; + using self_type = VectorView< T, Structure, storage::Dense, view::Diagonal< StructuredMatrixT >, reference_dense, C >; using target_type = StructuredMatrixT; /********************* @@ -509,10 +511,10 @@ namespace grb { * @returns A VectorView object. * */ template< typename StructuredMatrixT, typename C = internal::DefaultCoordinates > - VectorView< typename StructuredMatrixT::value_type, view::Diagonal< StructuredMatrixT >, storage::Dense, reference_dense, C > + VectorView< typename StructuredMatrixT::value_type, typename StructuredMatrixT::structure, storage::Dense, view::Diagonal< StructuredMatrixT >, reference_dense, C > diagonal( StructuredMatrixT &smat ) { - VectorView< typename StructuredMatrixT::value_type, view::Diagonal< StructuredMatrixT >, storage::Dense, reference_dense, C > smat_diag( smat ); + VectorView< typename StructuredMatrixT::value_type, typename StructuredMatrixT::structure, storage::Dense, view::Diagonal< StructuredMatrixT >, reference_dense, C > smat_diag( smat ); return smat_diag; } @@ -524,11 +526,11 @@ namespace grb { * * @returns A VectorView object. */ - template< typename T, typename View, typename StorageSchemeType, enum Backend backend, typename C = internal::DefaultCoordinates > - VectorView< T, view::Original< VectorView< T, View, StorageSchemeType, backend, C > >, StorageSchemeType, backend, C > - get_view( VectorView< T, View, StorageSchemeType, backend, C > &source ) { + template< typename T, typename Structure, typename View, typename StorageSchemeType, enum Backend backend, typename C = internal::DefaultCoordinates > + VectorView< T, Structure, StorageSchemeType, view::Original< VectorView< T, Structure, StorageSchemeType, View, backend, C > >, backend, C > + get_view( VectorView< T, Structure, View, StorageSchemeType, backend, C > &source ) { - VectorView< T, view::Original< VectorView< T, View, StorageSchemeType, backend, C > >, StorageSchemeType, backend, C > vec_view( source ); + VectorView< T, Structure, StorageSchemeType, view::Original< VectorView< T, Structure, View, StorageSchemeType, backend, C > >, backend, C > vec_view( source ); return vec_view; } @@ -543,11 +545,11 @@ namespace grb { * @returns A VectorView object. */ - template< typename T, typename View, typename StorageSchemeType, enum Backend backend, typename C > - VectorView< T, view::Original< VectorView< T, View, StorageSchemeType, backend, C > >, StorageSchemeType, backend, C > - get_view( VectorView< T, View, StorageSchemeType, backend, C > &source, std::shared_ptr< imf::IMF > imf ) { + template< typename T, typename Structure, typename View, typename StorageSchemeType, enum Backend backend, typename C > + VectorView< T, Structure, StorageSchemeType, view::Original< VectorView< T, Structure, StorageSchemeType, View, backend, C > >, backend, C > + get_view( VectorView< T, Structure, StorageSchemeType, View, backend, C > &source, std::shared_ptr< imf::IMF > imf ) { - VectorView< T, view::Original< VectorView< T, View, StorageSchemeType, backend, C > >, StorageSchemeType, backend, C > vec_view( source, imf ); + VectorView< T, Structure, StorageSchemeType, view::Original< VectorView< T, Structure, StorageSchemeType, View, backend, C > >, backend, C > vec_view( source, imf ); return vec_view; } diff --git a/include/graphblas/vector.hpp b/include/graphblas/vector.hpp index 12f989adf..f0c7ee493 100644 --- a/include/graphblas/vector.hpp +++ b/include/graphblas/vector.hpp @@ -57,7 +57,7 @@ namespace grb { /* * The default value of \a StorageSchemeType could also be made conditional (Dense or Sparse) depending on \a config::default_backend */ - template< typename T, typename View = view::Original< void >, typename StorageSchemeType = storage::Dense, enum Backend backend = config::default_backend, typename C = internal::DefaultCoordinates > + template< typename T, typename Structure = structures::General, typename StorageSchemeType = storage::Dense, typename View = view::Original< void >, enum Backend backend = config::default_backend, typename C = internal::DefaultCoordinates > class VectorView; } From 66c6f1e2411827d3a501595de49efb8f6b72db0b Mon Sep 17 00:00:00 2001 From: Anonymous Date: Fri, 18 Mar 2022 11:59:16 +0000 Subject: [PATCH 110/282] !18 Resolve internal issue #357: Include capacity argument to VectorView and StructuredMatrix --- include/graphblas/denseref/matrix.hpp | 33 +++++++++++++++++---------- include/graphblas/denseref/vector.hpp | 10 ++++++-- 2 files changed, 29 insertions(+), 14 deletions(-) diff --git a/include/graphblas/denseref/matrix.hpp b/include/graphblas/denseref/matrix.hpp index f68a2c7e9..5071cae72 100644 --- a/include/graphblas/denseref/matrix.hpp +++ b/include/graphblas/denseref/matrix.hpp @@ -197,6 +197,10 @@ namespace grb { * * \warning Avoid the use of this constructor within performance critical * code sections. + * \warning \a cap is present for compatibility with other matrix specializations. + * In reference_dense backend, the number of non-zeros (i.e. capacity) + * depends on the used storage scheme. Therefore, this parameter is + * ignored. */ Matrix( const size_t rows, const size_t columns, const size_t cap = 0 ): m( rows ), n( columns ), cap( std::max( m*n, cap ) ), initialized( false ) { // TODO Implement allocation properly @@ -479,12 +483,17 @@ namespace grb { /** * @brief Construct a new structured matrix container object. * + * \warning \a cap is present for compatibility with other matrix specializations. + * In reference_dense backend, the number of non-zeros (i.e. capacity) + * depends on the used storage scheme. Therefore, this parameter is + * ignored. + * * TODO: Add the storage scheme a parameter to the constructor * so that allocation can be made accordingly, generalizing the full case. */ - MatrixContainer( size_t rows, size_t cols ) : + MatrixContainer( size_t rows, size_t cols, size_t cap = 0 ) : MatrixBase( rows, cols ), - _container( new Matrix< T, reference_dense >(rows, cols) ), + _container( new Matrix< T, reference_dense >( rows, cols, cap ) ), storage_scheme( storage::full ) {} }; @@ -609,8 +618,8 @@ namespace grb { using original_t = StructuredMatrix< T, structures::General, storage::Dense, view::Original< self_type >, reference_dense >; using transpose_t = StructuredMatrix< T, structures::General, storage::Dense, view::Transpose< self_type >, reference_dense >; - StructuredMatrix( const size_t rows, const size_t cols ) : - internal::MatrixContainer< T >( rows, cols ) { + StructuredMatrix( const size_t rows, const size_t cols, const size_t cap = 0 ) : + internal::MatrixContainer< T >( rows, cols, cap ) { } }; // StructuredMatrix General, container @@ -664,8 +673,8 @@ namespace grb { /** The type of an identify view over the present type */ using original_t = StructuredMatrix< T, Structure, storage::Dense, view::Original< self_type >, reference_dense >; - StructuredMatrix( const size_t rows, const size_t cols ) : - internal::MatrixContainer< T >( rows, cols ) {} + StructuredMatrix( const size_t rows, const size_t cols, const size_t cap = 0 ) : + internal::MatrixContainer< T >( rows, cols, cap ) {} }; // class StructuredMatrix template< typename T > @@ -692,8 +701,8 @@ namespace grb { using original_t = StructuredMatrix< T, structures::Square, storage::Dense, view::Original< self_type >, reference_dense >; using transpose_t = StructuredMatrix< T, structures::Square, storage::Dense, view::Transpose< self_type >, reference_dense >; - StructuredMatrix( const size_t rows ) : - internal::MatrixContainer< T >( rows, rows ) {} + StructuredMatrix( const size_t rows, const size_t cap = 0 ) : + internal::MatrixContainer< T >( rows, rows, cap ) {} }; // StructuredMatrix Square, container @@ -755,8 +764,8 @@ namespace grb { using original_t = StructuredMatrix< T, structures::UpperTriangular, storage::Dense, view::Original< self_type >, reference_dense >; using transpose_t = StructuredMatrix< T, structures::LowerTriangular, storage::Dense, view::Transpose< self_type >, reference_dense >; - StructuredMatrix( const size_t rows, const size_t cols ) : - internal::MatrixContainer< T >( rows, cols ) {} + StructuredMatrix( const size_t rows, const size_t cols, const size_t cap = 0 ) : + internal::MatrixContainer< T >( rows, cols, cap ) {} }; // StructuredMatrix UpperTriangular, container @@ -821,8 +830,8 @@ namespace grb { using original_t = StructuredMatrix< T, structures::Identity, storage::Dense, view::Original< self_type >, reference_dense >; using transpose_t = StructuredMatrix< T, structures::Identity, storage::Dense, view::Transpose< self_type >, reference_dense >; - StructuredMatrix( const size_t rows ) : - internal::MatrixContainer< T >( rows, rows ) {} + StructuredMatrix( const size_t rows, const size_t cap = 0 ) : + internal::MatrixContainer< T >( rows, rows, cap ) {} }; // StructuredMatrix Identity, container diff --git a/include/graphblas/denseref/vector.hpp b/include/graphblas/denseref/vector.hpp index d3dffc3e9..9a4b9e6db 100644 --- a/include/graphblas/denseref/vector.hpp +++ b/include/graphblas/denseref/vector.hpp @@ -97,7 +97,13 @@ namespace grb { /** The length of the vector. */ size_t n; - /** The container capacity (in elements). */ + /** The container capacity (in elements). + * + * \warning \a cap is present for compatibility with other vector specializations. + * In reference_dense backend, the number of non-zeros (i.e. capacity) + * depends on the used storage scheme. Therefore, this parameter is + * ignored when provided by user. + */ size_t cap; /** The vector data. */ @@ -400,7 +406,7 @@ namespace grb { /** @see Vector::value_type. */ using value_type = T; - VectorView( const size_t length ) : v( std::make_unique< Vector< T, reference_dense, C > >( length ) ), imf( std::make_shared< imf::Id >( length ) ) {} + VectorView( const size_t length, const size_t cap = 0 ) : v( std::make_unique< Vector< T, reference_dense, C > >( length, cap ) ), imf( std::make_shared< imf::Id >( length ) ) {} }; // class VectorView with physical container From 315766b7bb4ea545edef95c5e3cf3a2a094fceba Mon Sep 17 00:00:00 2001 From: Anonymous Date: Fri, 18 Mar 2022 13:32:53 +0000 Subject: [PATCH 111/282] !20 Resolve internal issue #361: Introduce Scalar container --- include/graphblas.hpp | 1 + include/graphblas/base/scalar.hpp | 171 +++++++++++++++++++++ include/graphblas/denseref/scalar.hpp | 209 ++++++++++++++++++++++++++ include/graphblas/scalar.hpp | 40 +++++ 4 files changed, 421 insertions(+) create mode 100644 include/graphblas/base/scalar.hpp create mode 100644 include/graphblas/denseref/scalar.hpp create mode 100644 include/graphblas/scalar.hpp diff --git a/include/graphblas.hpp b/include/graphblas.hpp index 64df3b9e4..d8a5c2182 100644 --- a/include/graphblas.hpp +++ b/include/graphblas.hpp @@ -184,6 +184,7 @@ // declare those. #include #include +#include // The aforementioned forward declarations must be in sync with the // declarations of the user primitives defined as free functions in the below. diff --git a/include/graphblas/base/scalar.hpp b/include/graphblas/base/scalar.hpp new file mode 100644 index 000000000..f40b923f6 --- /dev/null +++ b/include/graphblas/base/scalar.hpp @@ -0,0 +1,171 @@ + +/* + * Copyright 2021 Huawei Technologies Co., Ltd. + * + * 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. + */ + +#ifndef _H_GRB_SCALAR_BASE +#define _H_GRB_SCALAR_BASE + +#include //size_t +#include + +#include +#include +#include +#include + +namespace grb { + + /** + * \brief An ALP scalar. + * + * This is an opaque data type for scalars. + * + * @tparam T The type of the vector elements. \a T shall not + * be an ALP type. + * @tparam Structure One of the structures. One of possible use cases + * for a structured scalar is a random structure. + * Depending on the backend implementation, this may mean, + * for example, randomizing the scalar value on each + * interaction with the scalar. + * + * \warning Creating a grb::Scalar of other ALP types is + * not allowed. + * Passing a ALP type as template parameter will lead to + * undefined behaviour. + * + */ + template< typename T, typename Structure, enum Backend backend > + class Scalar { + + public: + /** @see Vector::value_type. */ + typedef T value_type; + + /** + * The default ALP scalar constructor. + * + * The constructed object will be uninitalised after successful construction. + * + * + * \parblock + * \par Performance semantics. + * -# This constructor entails \f$ \Theta(1) \f$ amount of work. + * -# This constructor may allocate \f$ \Theta(1) \f$ bytes + * of dynamic memory. + * -# This constructor will use \f$ \Theta(1) \f$ extra bytes of + * memory beyond that at constructor entry. + * -# This constructor incurs \f$ \Theta(1) \f$ data movement. + * -# This constructor \em may make system calls. + * \endparblock + * + */ + Scalar() {} + + /** + * The ALP scalar constructor for converting a reference to C/C++ scalar + * to ALP scalar. + * + * The constructed object will be initialized after successful construction. + * + * + * \parblock + * \par Performance semantics. + * -# This constructor entails \f$ \Theta(1) \f$ amount of work. + * -# This constructor may allocate \f$ \Theta(1) \f$ bytes + * of dynamic memory. + * -# This constructor will use \f$ \Theta(1) \f$ extra bytes of + * memory beyond that at constructor entry. + * -# This constructor incurs \f$ \Theta(1) \f$ data movement. + * -# This constructor \em may make system calls. + * \endparblock + * + * \warning This constructor saves the reference to the provied value. + * Therefore, the changes to the container or the value will + * be mirrored into each-other. For preserving the separation, + * use Scalar( const T ) version. + * + */ + explicit Scalar( T &value ) { + (void)value; + } + + /** + * The ALP scalar constructor for converting a C/C++ scalar to ALP scalar. + * + * The constructed object will be initialized after successful construction. + * + * + * \parblock + * \par Performance semantics. + * -# This constructor entails \f$ \Theta(1) \f$ amount of work. + * -# This constructor may allocate \f$ \Theta(1) \f$ bytes + * of dynamic memory. + * -# This constructor will use \f$ \Theta(1) \f$ extra bytes of + * memory beyond that at constructor entry. + * -# This constructor incurs \f$ \Theta(1) \f$ data movement. + * -# This constructor \em may make system calls. + * \endparblock + * + */ + explicit Scalar( T value ) { + (void)value; + } + + /** + * Copy constructor. + * + * @param other The scalar to copy. The initialization state of the copy + * reflects the state of \a other. + * + * \parblock + * \par Performance semantics. + * -# This constructor entails \f$ \Theta(1) \f$ amount of work. + * -# This constructor allocates \f$ \Theta(1) \f$ bytes + * of dynamic memory. + * -# This constructor incurs \f$ \Theta(1) \f$ of data + * movement. + * -# This constructor \em may make system calls. + * \endparblock + * + */ + Scalar( const Scalar &other ) noexcept { + (void)other; + } + + /** + * Move constructor. The new scalar equals the given + * scalar. Invalidates the use of the input scalar. + * + * @param[in] other The ALP scalar to move to this new instance. + * + * \parblock + * \par Performance semantics. + * -# This constructor entails \f$ \Theta(1) \f$ amount of work. + * -# This constructor will not allocate any new dynamic memory. + * -# This constructor will use \f$ \Theta(1) \f$ extra bytes of + * memory beyond that at constructor entry. + * -# This constructor will move \f$ \Theta(1) \f$ bytes of data. + * \endparblock + */ + Scalar( Scalar &&other ) noexcept { + (void)other; + } + + }; // class Scalar + +} // namespace grb + +#endif // _H_GRB_SCALAR_BASE diff --git a/include/graphblas/denseref/scalar.hpp b/include/graphblas/denseref/scalar.hpp new file mode 100644 index 000000000..db3d10f8b --- /dev/null +++ b/include/graphblas/denseref/scalar.hpp @@ -0,0 +1,209 @@ + +/* + * Copyright 2021 Huawei Technologies Co., Ltd. + * + * 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. + */ + +#ifndef _H_GRB_DENSEREF_SCALAR +#define _H_GRB_DENSEREF_SCALAR + + +#include +#include + +#include + +#include +#include + +#include +#include +#include + +#include + +namespace grb { + + namespace internal { + template< typename T, typename Structure > + bool getInitialized( Scalar< T, Structure, reference_dense > & ) noexcept; + + template< typename T, typename Structure > + void setInitialized( Scalar< T, Structure, reference_dense > &, bool ) noexcept; + } // end namespace ``grb::internal'' + + /** + * \brief An ALP scalar. + * + * This is an opaque data type for scalars. + * + * @tparam T The type of the vector elements. \a T shall not + * be a ALP type. + * @tparam Structure One of the structures. + * + * \warning Creating a grb::Scalar of other ALP types is + * not allowed. + * Passing a ALP type as template parameter will lead to + * undefined behaviour. + * + */ + template< typename T, typename Structure > + class Scalar< T, Structure, reference_dense > { + private: + typedef Scalar< T, Structure, reference_dense > self_type; + + friend bool internal::getInitialized<>( self_type & ) noexcept; + + friend void internal::setInitialized<>( self_type &, bool ) noexcept; + + // Scalar value + T &value; + + /** Whether the scalar value is currently initialized */ + bool initialized; + + public: + /** @see Vector::value_type. */ + typedef T value_type; + + /** + * The main ALP scalar constructor. + * + * The constructed object will be uninitalised after successful construction. + * + * + * @return SUCCESS This function never fails. + * + * \parblock + * \par Performance semantics. + * -# This constructor entails \f$ \Theta(1) \f$ amount of work. + * -# This constructor may allocate \f$ \Theta(1) \f$ bytes + * of dynamic memory. + * -# This constructor will use \f$ \Theta(1) \f$ extra bytes of + * memory beyond that at constructor entry. + * -# This constructor incurs \f$ \Theta(1) \f$ data movement. + * -# This constructor \em may make system calls. + * \endparblock + * + */ + Scalar() : initialized( false ) {} + + /** + * The ALP scalar constructor for converting C/C++ scalar to ALP scalar. + * + * The constructed object will be initialized after successful construction. + * + * + * \parblock + * \par Performance semantics. + * -# This constructor entails \f$ \Theta(1) \f$ amount of work. + * -# This constructor may allocate \f$ \Theta(1) \f$ bytes + * of dynamic memory. + * -# This constructor will use \f$ \Theta(1) \f$ extra bytes of + * memory beyond that at constructor entry. + * -# This constructor incurs \f$ \Theta(1) \f$ data movement. + * -# This constructor \em may make system calls. + * \endparblock + * + */ + explicit Scalar( T &value ) : value( value ), initialized( true ) {} + + /** + * The ALP scalar constructor for converting a C/C++ scalar to ALP scalar. + * + * The constructed object will be initialized after successful construction. + * + * + * \parblock + * \par Performance semantics. + * -# This constructor entails \f$ \Theta(1) \f$ amount of work. + * -# This constructor may allocate \f$ \Theta(1) \f$ bytes + * of dynamic memory. + * -# This constructor will use \f$ \Theta(1) \f$ extra bytes of + * memory beyond that at constructor entry. + * -# This constructor incurs \f$ \Theta(1) \f$ data movement. + * -# This constructor \em may make system calls. + * \endparblock + * + */ + explicit Scalar( T value ) : value( value ), initialized( true ) {} + + /** + * Copy constructor. + * + * @param other The scalar to copy. The initialization state of the copy + * reflects the state of \a other. + * + * \parblock + * \par Performance semantics. + * -# This constructor entails \f$ \Theta(1) \f$ amount of work. + * -# This constructor allocates \f$ \Theta(1) \f$ bytes + * of dynamic memory. + * -# This constructor incurs \f$ \Theta(1) \f$ of data + * movement. + * -# This constructor \em may make system calls. + * \endparblock + * + */ + Scalar( const Scalar &other ) { + // const RC rc = set( *this, other ); // note: initialized will be set as part of this call + // if( rc != SUCCESS ) { + // throw std::runtime_error( "grb::Scalar< T, Structure, storage::Dense, View::Original< void >, reference_dense > (copy constructor): error during call to grb::set (" + toString( rc ) + ")" ); + // } + } + + /** + * Move constructor. The new scalar equals the given + * scalar. Invalidates the use of the input scalar. + * + * @param[in] other The ALP scalar to move to this new instance. + * + * \parblock + * \par Performance semantics. + * -# This constructor entails \f$ \Theta(1) \f$ amount of work. + * -# This constructor will not allocate any new dynamic memory. + * -# This constructor will use \f$ \Theta(1) \f$ extra bytes of + * memory beyond that at constructor entry. + * -# This constructor will move \f$ \Theta(1) \f$ bytes of data. + * \endparblock + */ + Scalar( Scalar &&other ) : value( other.value ), initialized( other.initialized ) { + other.initialized = false; + } + + }; // class Scalar with physical container + + /** Identifies any reference_dense scalar as an ALP scalar. */ + template< typename T, typename Structure > + struct is_container< Scalar< T, Structure, reference_dense > > { + /** A scalar is an ALP object. */ + static const constexpr bool value = true; + }; + + namespace internal { + template< typename T, typename Structure > + bool getInitialized( Scalar< T, Structure, reference_dense > &s ) noexcept { + return s.initialized; + } + + template< typename T, typename Structure > + void setInitialized( Scalar< T, Structure, reference_dense > &s, bool initialized ) noexcept { + s.initialized = s; + } + } // end namespace ``grb::internal'' + +} // end namespace ``grb'' + +#endif // end ``_H_GRB_DENSEREF_SCALAR'' + diff --git a/include/graphblas/scalar.hpp b/include/graphblas/scalar.hpp new file mode 100644 index 000000000..ac2c5cb44 --- /dev/null +++ b/include/graphblas/scalar.hpp @@ -0,0 +1,40 @@ + +/* + * Copyright 2021 Huawei Technologies Co., Ltd. + * + * 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. + */ + +#ifndef _H_GRB_SCALAR +#define _H_GRB_SCALAR + +#include "base/config.hpp" +#include "base/scalar.hpp" + +// now include all specialisations contained in the backend directories: +#ifdef _GRB_WITH_DENSEREF + #include +#endif + +// specify default only if requested during compilation +#ifdef _GRB_BACKEND +namespace grb { + + template< typename T, typename Structure = structures::General, enum Backend backend = config::default_backend > + class Scalar; + +} +#endif + +#endif // end ``_H_GRB_SCALAR'' + From f33ee00eeea93a48506dea9f5d12f36aa37a7e00 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Tue, 22 Mar 2022 11:32:32 +0000 Subject: [PATCH 112/282] !25 Resolve internal issue #366: Scalar version of operations at level 1 This commit introduces the following changes: * Update ALP tests to use ALP Scalar * Update level 1 functions to operate on ALP scalars --- include/graphblas/blas1.hpp | 20 + include/graphblas/denseref/blas1.hpp | 634 +++++++++++++-------------- tests/unit/dense_dot_norm2.cpp | 2 +- 3 files changed, 337 insertions(+), 319 deletions(-) diff --git a/include/graphblas/blas1.hpp b/include/graphblas/blas1.hpp index adaa213a9..9f035e776 100644 --- a/include/graphblas/blas1.hpp +++ b/include/graphblas/blas1.hpp @@ -359,6 +359,26 @@ namespace grb { * must be applied on the result of a dot-product of \a y with * itself under the supplied semiring. */ + // template< + // Descriptor descr = descriptors::no_operation, class Ring, + // typename InputType, typename OutputType, typename OutputStructure, + // Backend backend, typename Coords + // > + // RC norm2( Scalar< OutputType, OutputStructure, backend > &x, + // const Vector< InputType, backend, Coords > &y, + // const Ring &ring = Ring(), + // const typename std::enable_if< + // std::is_floating_point< OutputType >::value, + // void >::type * const = NULL + // ) { + // RC ret = grb::dot< descr >( x, y, y, ring ); + // if( ret == SUCCESS ) { + // x = sqrt( x ); + // } + // return ret; + // } + + /** Specialization for C++ scalars */ template< Descriptor descr = descriptors::no_operation, class Ring, typename InputType, typename OutputType, diff --git a/include/graphblas/denseref/blas1.hpp b/include/graphblas/denseref/blas1.hpp index bbed3bb02..8d43179bb 100644 --- a/include/graphblas/denseref/blas1.hpp +++ b/include/graphblas/denseref/blas1.hpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #ifndef NO_CAST_ASSERT @@ -52,10 +53,21 @@ namespace grb { /** * \defgroup BLAS1 The Level-1 Basic Linear Algebra Subroutines (BLAS) * - * A collection of functions that allow GraphBLAS operators, monoids, and + * A collection of functions that allow ALP/GraphBLAS operators, monoids, and * semirings work on a mix of zero-dimensional and one-dimensional containers; - * i.e., allows various linear algebra operations on scalars and objects of - * type grb::VectorView. + * i.e., allows various linear algebra operations on scalars (both built-in + * C++ scalars and objects of type grb::Scalar) and objects of type + * grb::VectorView. + * + * C++ built-in scalars are all scalar types that can be + * passed to BLAS functions. This includes simple types (e.g. double) and + * more complex types (e.g. std::pair as complex number representation). + * Such types are referred to as C++ scalars or built-in scalars. + * + * Operations producing scalars are specialized to both C++ built-in scalars + * and grb::Scalars. Functions taking scalars as inputs are specialized only + * to grb::Scalars. Depending on backend's Scalar implementation, the + * conversion from C++ scalar to grb::Scalar can be implicit or explicit. * * All functions except for grb::size and grb::nnz return an error code of * the enum-type grb::RC. The two functions for retrieving the size and the @@ -291,10 +303,11 @@ namespace grb { */ template< Descriptor descr = descriptors::no_operation, - typename DataType, typename DataStructure, typename DataStorage, typename View, typename T, + typename DataType, typename DataStructure, typename ValStructure, typename DataStorage, typename View, typename T, typename Coords > - RC set( VectorView< DataType, DataStructure, DataStorage, View, reference_dense, Coords > & x, const T val, + RC set( VectorView< DataType, DataStructure, DataStorage, View, reference_dense, Coords > & x, + const Scalar< T, ValStructure, reference_dense > val, const typename std::enable_if< !grb::is_object< DataType >::value && !grb::is_object< T >::value, @@ -368,10 +381,13 @@ namespace grb { * @see grb::operators::right_assign. * @see grb::setElement. */ - template< Descriptor descr = descriptors::no_operation, typename DataType, typename DataView, typename DataStructure, typename DataStorage, typename MaskStructure, typename MaskStorage, typename MaskType, typename MaskView, typename T, typename Coords > + template< Descriptor descr = descriptors::no_operation, + typename DataType, typename DataView, typename DataStructure, typename DataStorage, + typename MaskStructure, typename MaskStorage, typename MaskType, typename MaskView, + typename T, typename ValStructure, typename Coords > RC set( VectorView< DataType, DataStructure, DataStorage, DataView, reference_dense, Coords > & x, const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense, Coords > & m, - const T val, + const Scalar< T, ValStructure, reference_dense > val, const typename std::enable_if< ! grb::is_object< DataType >::value && ! grb::is_object< T >::value, void >::type * const = NULL ) { #ifdef _DEBUG std::cout << "In grb::set (vector-to-value, masked)\n"; @@ -400,6 +416,27 @@ namespace grb { return SUCCESS; } + /** C++ scalar variant */ + template< Descriptor descr = descriptors::no_operation, + typename DataType, typename DataView, typename DataStructure, typename DataStorage, + typename MaskStructure, typename MaskStorage, typename MaskType, typename MaskView, + typename T, typename Coords > + RC set( VectorView< DataType, DataStructure, DataStorage, DataView, reference_dense, Coords > & x, + const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense, Coords > & m, + const T val, + const typename std::enable_if< ! grb::is_object< DataType >::value && ! grb::is_object< T >::value, void >::type * const = NULL ) { +#ifdef _DEBUG + std::cout << "In grb::set (vector-to-value, masked)\n"; +#endif + // static sanity checks + NO_CAST_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< DataType, T >::value ), "grb::set (Vector to scalar, masked)", + "called with a value type that does not match that of the given " + "vector" ); + + // delegate to grb::Scalar version + return set( x, m, Scalar< T >( val ) ); + } + /** * Sets the element of a given VectorView at a given position to a given value. * @@ -444,9 +481,9 @@ namespace grb { // * -# shall not make any system calls. // * \endparblock */ - template< Descriptor descr = descriptors::no_operation, typename DataType, typename DataStructure, typename DataStorage, typename View, typename T, typename Coords > + template< Descriptor descr = descriptors::no_operation, typename DataType, typename DataStructure, typename ValStructure, typename DataStorage, typename View, typename T, typename Coords > RC setElement( VectorView< DataType, DataStructure, DataStorage, View, reference_dense, Coords > & x, - const T val, + const Scalar< T, ValStructure, reference_dense > val, const size_t i, const typename std::enable_if< ! grb::is_object< DataType >::value && ! grb::is_object< T >::value, void >::type * const = NULL ) { // static sanity checks @@ -460,6 +497,21 @@ namespace grb { return SUCCESS; } + /** C++ scalar variant */ + template< Descriptor descr = descriptors::no_operation, typename DataType, typename DataStructure, typename ValStructure, typename DataStorage, typename View, typename T, typename Coords > + RC setElement( VectorView< DataType, DataStructure, DataStorage, View, reference_dense, Coords > & x, + const T val, + const size_t i, + const typename std::enable_if< ! grb::is_object< DataType >::value && ! grb::is_object< T >::value, void >::type * const = NULL ) { + // static sanity checks + NO_CAST_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< DataType, T >::value ), "grb::set (VectorView, at index)", + "called with a value type that does not match that of the given " + "VectorView" ); + + // delegate + return setElement( x, Scalar< T >( val ), i ); + } + /** * Sets the content of a given vector \a x to be equal to that of * another given vector \a y. Can be masked. @@ -728,9 +780,9 @@ namespace grb { * and/or vectorised operations are used. */ template< Descriptor descr = descriptors::no_operation, class Monoid, - typename InputType, typename InputStructure, typename InputStorage, typename InputView, typename IOType, typename Coords > + typename InputType, typename InputStructure, typename InputStorage, typename InputView, typename IOType, typename IOStructure, typename Coords > RC foldr( const VectorView< InputType, InputStructure, InputStorage, InputView, reference_dense, Coords > & x, - IOType & beta, + Scalar< IOType, IOStructure, reference_dense > & beta, const Monoid & monoid = Monoid(), const typename std::enable_if< ! grb::is_object< InputType >::value && ! grb::is_object< IOType >::value && grb::is_monoid< Monoid >::value, void >::type * const = NULL ) { @@ -738,6 +790,17 @@ namespace grb { return SUCCESS; } + /** C++ scalar variant */ + template< Descriptor descr = descriptors::no_operation, class Monoid, + typename InputType, typename InputStructure, typename InputStorage, typename InputView, typename IOType, typename Coords > + RC foldr( const VectorView< InputType, InputStructure, InputStorage, InputView, reference_dense, Coords > & x, + IOType & beta, + const Monoid & monoid = Monoid(), + const typename std::enable_if< ! grb::is_object< InputType >::value && ! grb::is_object< IOType >::value && grb::is_monoid< Monoid >::value, void >::type * const = NULL ) { + + return foldr( x, Scalar< IOType >( beta ), monoid ); + } + /** * For all elements in a ALP VectorView \a y, fold the value \f$ \alpha \f$ * into each element. @@ -810,8 +873,8 @@ namespace grb { * @see grb::operators::internal::Operator for a discussion on when in-place * and/or vectorised operations are used. */ - template< Descriptor descr = descriptors::no_operation, class Monoid, typename IOType, typename InputType, typename IOStructure, typename IOStorage, typename IOView, typename Coords > - RC foldr( const InputType & alpha, + template< Descriptor descr = descriptors::no_operation, class Monoid, typename IOType, typename InputType, typename IOStructure, typename InputStructure, typename IOStorage, typename IOView, typename Coords > + RC foldr( const Scalar< InputType, InputStructure, reference_dense > & alpha, VectorView< IOType, IOStructure, IOStorage, IOView, reference_dense, Coords > & y, const Monoid & monoid = Monoid(), const typename std::enable_if< ! grb::is_object< InputType >::value && ! grb::is_object< IOType >::value && grb::is_monoid< Monoid >::value, void >::type * const = NULL ) { @@ -835,8 +898,8 @@ namespace grb { * * Specialisation for scalar \a x. */ - template< Descriptor descr = descriptors::no_operation, class OP, typename IOType, typename InputType, typename IOStructure, typename IOStorage, typename IOView, typename Coords > - RC foldr( const InputType & alpha, + template< Descriptor descr = descriptors::no_operation, class OP, typename IOType, typename InputType, typename IOStructure, typename InputStructure, typename IOStorage, typename IOView, typename Coords > + RC foldr( const Scalar< InputType, InputStructure, reference_dense > & alpha, VectorView< IOType, IOStructure, IOStorage, IOView, reference_dense, Coords > & y, const OP & op = OP(), const typename std::enable_if< ! grb::is_object< InputType >::value && ! grb::is_object< IOType >::value && grb::is_operator< OP >::value, void >::type * const = NULL ) { @@ -1226,9 +1289,9 @@ namespace grb { * @see grb::operators::internal::Operator for a discussion on when in-place * and/or vectorised operations are used. */ - template< Descriptor descr = descriptors::no_operation, class Op, typename IOType, typename InputType, typename IOStructure, typename IOStorage, typename IOView, typename Coords > + template< Descriptor descr = descriptors::no_operation, class Op, typename IOType, typename InputType, typename IOStructure, typename InputStructure, typename IOStorage, typename IOView, typename Coords > RC foldl( VectorView< IOType, IOStructure, IOStorage, IOView, reference_dense, Coords > & x, - const InputType beta, + const Scalar< InputType, InputStructure, reference_dense > beta, const Op & op = Op(), const typename std::enable_if< ! grb::is_object< IOType >::value && ! grb::is_object< InputType >::value && grb::is_operator< Op >::value, void >::type * = NULL ) { // static sanity checks @@ -1254,13 +1317,13 @@ namespace grb { */ template< Descriptor descr = descriptors::no_operation, class Op, typename IOType, typename MaskType, typename InputType, - typename IOStructure, typename MaskStructure, + typename IOStructure, typename MaskStructure, typename InputStructure, typename IOStorage, typename MaskStorage, typename IOView, typename MaskView, typename InputView, typename Coords > RC foldl( VectorView< IOType, IOStructure, IOStorage, IOView, reference_dense, Coords > & x, const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense, Coords > & m, - const InputType beta, + const Scalar< InputType, InputStructure, reference_dense > &beta, const Op & op = Op(), const typename std::enable_if< ! grb::is_object< IOType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType >::value && grb::is_operator< Op >::value, void >::type * = NULL ) { @@ -1791,13 +1854,13 @@ namespace grb { */ template< Descriptor descr = descriptors::no_operation, class OP, typename OutputType, typename InputType1, typename InputType2, - typename OutputStructure, typename InputStructure1, + typename OutputStructure, typename InputStructure1, typename InputStructure2, typename OutputStorage, typename InputStorage1, typename OutputView, typename InputView1, typename Coords > RC eWiseApply( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & z, const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense, Coords > & x, - const InputType2 beta, + const Scalar< InputType2, InputStructure2, reference_dense > &beta, const OP & op = OP(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_operator< OP >::value, void >::type * const = NULL ) { @@ -1815,13 +1878,13 @@ namespace grb { */ template< Descriptor descr = descriptors::no_operation, class OP, typename OutputType, typename InputType1, typename InputType2, - typename OutputStructure, + typename OutputStructure, typename InputStructure1, typename InputStructure2, typename OutputStorage, typename OutputView, typename Coords > RC eWiseApply( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & z, - const InputType1 alpha, - const InputType2 beta, + const Scalar< InputType1, InputStructure1, reference_dense> &alpha, + const Scalar< InputType2, InputStructure2, reference_dense> &beta, const OP & op = OP(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_operator< OP >::value, void >::type * const = NULL ) { @@ -1841,13 +1904,13 @@ namespace grb { */ template< Descriptor descr = descriptors::no_operation, class Monoid, typename OutputType, typename InputType1, typename InputType2, - typename OutputStructure, + typename OutputStructure, typename InputStructure1, typename InputStructure2, typename OutputStorage, typename OutputView, typename Coords > RC eWiseApply( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & z, - const InputType1 alpha, - const InputType2 beta, + const Scalar< InputType1, InputStructure1, reference_dense> &alpha, + const Scalar< InputType2, InputStructure2, reference_dense> &beta, const Monoid & monoid = Monoid(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_monoid< Monoid >::value, void >::type * const = NULL ) { @@ -1865,14 +1928,14 @@ namespace grb { */ template< Descriptor descr = descriptors::no_operation, class OP, typename OutputType, typename MaskType, typename InputType1, typename InputType2, - typename OutputStructure, typename MaskStructure, typename InputStructure1, + typename OutputStructure, typename MaskStructure, typename InputStructure1, typename InputStructure2, typename OutputStorage, typename MaskStorage, typename InputStorage1, typename OutputView, typename MaskView, typename InputView1, typename Coords > RC eWiseApply( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & z, const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense, Coords > & mask, const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense, Coords > & x, - const InputType2 beta, + const Scalar< InputType2, InputStructure2, reference_dense > &beta, const OP & op = OP(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_operator< OP >::value, @@ -1919,12 +1982,12 @@ namespace grb { */ template< Descriptor descr = descriptors::no_operation, class Monoid, typename OutputType, typename InputType1, typename InputType2, - typename OutputStructure, typename InputStructure2, + typename OutputStructure, typename InputStructure1, typename InputStructure2, typename OutputStorage, typename InputStorage2, typename OutputView, typename InputView2, typename Coords > RC eWiseApply( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & z, - const InputType1 alpha, + const Scalar< InputType1, InputStructure1, reference_dense> &alpha, const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense, Coords > & y, const Monoid & monoid = Monoid(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_monoid< Monoid >::value, @@ -1943,13 +2006,13 @@ namespace grb { */ template< Descriptor descr = descriptors::no_operation, class Monoid, typename OutputType, typename InputType1, typename InputType2, - typename OutputStructure, typename InputStructure1, + typename OutputStructure, typename InputStructure1, typename InputStructure2, typename OutputStorage, typename InputStorage1, typename OutputView, typename InputView1, typename Coords > RC eWiseApply( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & z, const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense, Coords > & x, - const InputType2 beta, + const Scalar< InputType2, InputStructure2, reference_dense > &beta, const Monoid & monoid = Monoid(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_monoid< Monoid >::value, void >::type * const = NULL ) { @@ -1993,13 +2056,13 @@ namespace grb { */ template< Descriptor descr = descriptors::no_operation, class Monoid, typename OutputType, typename MaskType, typename InputType1, typename InputType2, - typename OutputStructure, typename MaskStructure, typename InputStructure2, + typename OutputStructure, typename MaskStructure, typename InputStructure1, typename InputStructure2, typename OutputStorage, typename MaskStorage, typename InputStorage2, typename OutputView, typename MaskView, typename InputView2, typename Coords > RC eWiseApply( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & z, const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense, Coords > & mask, - const InputType1 alpha, + const Scalar< InputType1, InputStructure1, reference_dense> &alpha, const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense, Coords > & y, const Monoid & monoid = Monoid(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && @@ -2019,14 +2082,14 @@ namespace grb { */ template< Descriptor descr = descriptors::no_operation, class Monoid, typename OutputType, typename MaskType, typename InputType1, typename InputType2, - typename OutputStructure, typename MaskStructure, typename InputStructure1, + typename OutputStructure, typename MaskStructure, typename InputStructure1, typename InputStructure2, typename OutputStorage, typename MaskStorage, typename InputStorage1, typename OutputView, typename MaskView, typename InputView1, typename Coords > RC eWiseApply( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & z, const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense, Coords > & mask, const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense, Coords > & x, - const InputType2 beta, + const Scalar< InputType2, InputStructure2, reference_dense > &beta, const Monoid & monoid = Monoid(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_monoid< Monoid >::value, @@ -2110,12 +2173,12 @@ namespace grb { */ template< Descriptor descr = descriptors::no_operation, class OP, typename OutputType, typename InputType1, typename InputType2, - typename OutputStructure, typename InputStructure2, + typename OutputStructure, typename InputStructure1, typename InputStructure2, typename OutputStorage, typename InputStorage2, typename OutputView, typename InputView2, typename Coords > RC eWiseApply( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & z, - const InputType1 alpha, + const Scalar< InputType1, InputStructure1, reference_dense > &alpha, const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense, Coords > & y, const OP & op = OP(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_operator< OP >::value, @@ -2134,13 +2197,13 @@ namespace grb { */ template< Descriptor descr = descriptors::no_operation, class OP, typename OutputType, typename MaskType, typename InputType1, typename InputType2, - typename OutputStructure, typename MaskStructure, typename InputStructure2, + typename OutputStructure, typename MaskStructure, typename InputStructure1, typename InputStructure2, typename OutputStorage, typename MaskStorage, typename InputStorage2, typename OutputView, typename MaskView, typename InputView2, typename Coords > RC eWiseApply( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & z, const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense, Coords > & mask, - const InputType1 alpha, + const Scalar< InputType1, InputStructure1, reference_dense> &alpha, const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense, Coords > & y, const OP & op = OP(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && @@ -2392,12 +2455,12 @@ namespace grb { */ template< Descriptor descr = descriptors::no_operation, class Ring, typename OutputType, typename InputType1, typename InputType2, - typename OutputStructure, typename InputStructure2, + typename OutputStructure, typename InputStructure1, typename InputStructure2, typename OutputStorage, typename InputStorage2, typename OutputView, typename InputView2, typename Coords > RC eWiseAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & z, - const InputType1 alpha, + const Scalar< InputType1, InputStructure1, reference_dense> &alpha, const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense, Coords > & y, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_semiring< Ring >::value, @@ -2426,13 +2489,13 @@ namespace grb { */ template< Descriptor descr = descriptors::no_operation, class Ring, typename OutputType, typename InputType1, typename InputType2, - typename OutputStructure, typename InputStructure1, + typename OutputStructure, typename InputStructure1, typename InputStructure2, typename OutputStorage, typename InputStorage1, typename OutputView, typename InputView1, typename Coords > RC eWiseAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & z, const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense, Coords > & x, - const InputType2 beta, + const Scalar< InputType2, InputStructure2, reference_dense > &beta, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_semiring< Ring >::value, void >::type * const = NULL ) { @@ -2460,13 +2523,13 @@ namespace grb { */ template< Descriptor descr = descriptors::no_operation, class Ring, typename OutputType, typename InputType1, typename InputType2, - typename OutputStructure, + typename OutputStructure, typename InputStructure1, typename InputStructure2, typename OutputStorage, typename OutputView, typename Coords > RC eWiseAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & z, - const InputType1 alpha, - const InputType2 beta, + const Scalar< InputType1, InputStructure1, reference_dense > &alpha, + const Scalar< InputType2, InputStructure2, reference_dense > &beta, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_semiring< Ring >::value, void >::type * const = NULL ) { @@ -2534,13 +2597,13 @@ namespace grb { */ template< Descriptor descr = descriptors::no_operation, class Ring, typename OutputType, typename MaskType, typename InputType1, typename InputType2, - typename OutputStructure, typename MaskStructure, typename InputStructure2, + typename OutputStructure, typename MaskStructure, typename InputStructure1, typename InputStructure2, typename OutputStorage, typename MaskStorage, typename InputStorage2, typename OutputView, typename MaskView, typename InputView2, typename Coords > RC eWiseAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & z, const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense, Coords > & m, - const InputType1 alpha, + const Scalar< InputType1, InputStructure1, reference_dense> &alpha, const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense, Coords > & y, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && @@ -2572,14 +2635,14 @@ namespace grb { */ template< Descriptor descr = descriptors::no_operation, class Ring, typename OutputType, typename MaskType, typename InputType1, typename InputType2, - typename OutputStructure, typename MaskStructure, typename InputStructure1, + typename OutputStructure, typename MaskStructure, typename InputStructure1, typename InputStructure2, typename OutputStorage, typename MaskStorage, typename InputStorage1, typename OutputView, typename MaskView, typename InputView1, typename Coords > RC eWiseAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & z, const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense, Coords > & m, const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense, Coords > & x, - const InputType2 beta, + const Scalar< InputType2, InputStructure2, reference_dense > &beta, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_semiring< Ring >::value, @@ -2610,14 +2673,14 @@ namespace grb { */ template< Descriptor descr = descriptors::no_operation, class Ring, typename OutputType, typename MaskType, typename InputType1, typename InputType2, - typename OutputStructure, typename MaskStructure, + typename OutputStructure, typename MaskStructure, typename InputStructure1, typename InputStructure2, typename OutputStorage, typename MaskStorage, typename OutputView, typename MaskView, typename Coords > RC eWiseAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & z, const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense, Coords > & m, - const InputType1 alpha, - const InputType2 beta, + const Scalar< InputType1, InputStructure1, reference_dense > &alpha, + const Scalar< InputType2, InputStructure2, reference_dense > &beta, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_semiring< Ring >::value, @@ -2649,12 +2712,12 @@ namespace grb { */ template< Descriptor descr = descriptors::no_operation, class Ring, typename OutputType, typename InputType1, typename InputType2, typename InputType3, - typename OutputStructure, typename InputStructure2, typename InputStructure3, + typename OutputStructure, typename InputStructure1, typename InputStructure2, typename InputStructure3, typename OutputStorage, typename InputStorage2, typename InputStorage3, typename OutputView, typename InputView2, typename InputView3, typename Coords > RC eWiseMulAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & _z, - const InputType1 alpha, + const Scalar< InputType1, InputStructure1, reference_dense > &alpha, const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense, Coords > & _x, const VectorView< InputType3, InputStructure3, InputStorage3, InputView3, reference_dense, Coords > & _y, const Ring & ring = Ring(), @@ -2686,13 +2749,13 @@ namespace grb { */ template< Descriptor descr = descriptors::no_operation, class Ring, typename OutputType, typename InputType1, typename InputType2, typename InputType3, - typename OutputStructure, typename InputStructure1, typename InputStructure3, + typename OutputStructure, typename InputStructure1, typename InputStructure2, typename InputStructure3, typename OutputStorage, typename InputStorage1, typename InputStorage3, typename OutputView, typename InputView1, typename InputView3, typename Coords > RC eWiseMulAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & _z, const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense, Coords > & _a, - const InputType2 chi, + const Scalar< InputType2, InputStructure2, reference_dense> &chi, const VectorView< InputType3, InputStructure3, InputStorage3, InputView3, reference_dense, Coords > & _y, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && @@ -2722,14 +2785,14 @@ namespace grb { */ template< Descriptor descr = descriptors::no_operation, class Ring, typename OutputType, typename InputType1, typename InputType2, typename InputType3, - typename OutputStructure, typename InputStructure1, typename InputStructure2, + typename OutputStructure, typename InputStructure1, typename InputStructure2, typename InputStructure3, typename OutputStorage, typename InputStorage1, typename InputStorage2, typename OutputView, typename InputView1, typename InputView2, typename Coords > RC eWiseMulAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & _z, const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense, Coords > & _a, const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense, Coords > & _x, - const InputType3 gamma, + const Scalar< InputType3, InputStructure3, reference_dense > &gamma, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && grb::is_semiring< Ring >::value, @@ -2758,14 +2821,14 @@ namespace grb { */ template< Descriptor descr = descriptors::no_operation, class Ring, typename OutputType, typename InputType1, typename InputType2, typename InputType3, - typename OutputStructure, typename InputStructure1, + typename OutputStructure, typename InputStructure1, typename InputStructure2, typename InputStructure3, typename OutputStorage, typename InputStorage1, typename OutputView, typename InputView1, typename Coords > RC eWiseMulAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & _z, const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense, Coords > & _a, - const InputType2 beta, - const InputType3 gamma, + const Scalar< InputType2, InputStructure2, reference_dense> &beta, + const Scalar< InputType3, InputStructure3, reference_dense> &gamma, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && grb::is_semiring< Ring >::value, @@ -2794,14 +2857,14 @@ namespace grb { */ template< Descriptor descr = descriptors::no_operation, class Ring, typename OutputType, typename InputType1, typename InputType2, typename InputType3, - typename OutputStructure, typename InputStructure2, + typename OutputStructure, typename InputStructure1, typename InputStructure2, typename InputStructure3, typename OutputStorage, typename InputStorage2, typename OutputView, typename InputView2, typename Coords > RC eWiseMulAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & _z, - const InputType1 alpha, + const Scalar< InputType1, InputStructure1, reference_dense > &alpha, const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense, Coords > & _x, - const InputType3 gamma, + const Scalar< InputType3, InputStructure3, reference_dense > &gamma, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && grb::is_semiring< Ring >::value, @@ -2832,13 +2895,13 @@ namespace grb { */ template< Descriptor descr = descriptors::no_operation, class Ring, typename OutputType, typename InputType1, typename InputType2, typename InputType3, - typename OutputStructure, typename InputStructure3, + typename OutputStructure, typename InputStructure1, typename InputStructure2, typename InputStructure3, typename OutputStorage, typename InputStorage3, typename OutputView, typename InputView3, typename Coords > RC eWiseMulAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & z, - const InputType1 alpha, - const InputType2 beta, + const Scalar< InputType1, InputStructure1, reference_dense> &alpha, + const Scalar< InputType2, InputStructure2, reference_dense> &beta, const VectorView< InputType3, InputStructure3, InputStorage3, InputView3, reference_dense, Coords > & y, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && @@ -2874,14 +2937,14 @@ namespace grb { */ template< Descriptor descr = descriptors::no_operation, class Ring, typename OutputType, typename InputType1, typename InputType2, typename InputType3, - typename OutputStructure, + typename OutputStructure, typename InputStructure1, typename InputStructure2, typename InputStructure3, typename OutputStorage, typename OutputView, typename Coords > RC eWiseMulAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & z, - const InputType1 alpha, - const InputType2 beta, - const InputType3 gamma, + const Scalar< InputType1, InputStructure1, reference_dense> &alpha, + const Scalar< InputType2, InputStructure2, reference_dense> &beta, + const Scalar< InputType3, InputStructure3, reference_dense> &gamma, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && grb::is_semiring< Ring >::value, @@ -3181,12 +3244,12 @@ namespace grb { */ template< Descriptor descr = descriptors::no_operation, class Ring, typename OutputType, typename InputType1, typename InputType2, - typename OutputStructure, typename InputStructure2, + typename OutputStructure, typename InputStructure1, typename InputStructure2, typename OutputStorage, typename InputStorage2, typename OutputView, typename InputView2, typename Coords > RC eWiseMul( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & z, - const InputType1 alpha, + const Scalar< InputType1, InputStructure1, reference_dense > &alpha, const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense, Coords > & y, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_semiring< Ring >::value, @@ -3214,13 +3277,13 @@ namespace grb { */ template< Descriptor descr = descriptors::no_operation, class Ring, typename OutputType, typename InputType1, typename InputType2, - typename OutputStructure, typename InputStructure1, + typename OutputStructure, typename InputStructure1, typename InputStructure2, typename OutputStorage, typename InputStorage1, typename OutputView, typename InputView1, typename Coords > RC eWiseMul( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & z, const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense, Coords > & x, - const InputType2 beta, + const Scalar< InputType2, InputStructure2, reference_dense > &beta, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_semiring< Ring >::value, void >::type * const = NULL ) { @@ -3247,13 +3310,13 @@ namespace grb { */ template< Descriptor descr = descriptors::no_operation, class Ring, typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename InputType3, - typename OutputStructure, typename MaskStructure, typename InputStructure2, typename InputStructure3, + typename OutputStructure, typename MaskStructure, typename InputStructure1, typename InputStructure2, typename InputStructure3, typename OutputStorage, typename MaskStorage, typename InputStorage2, typename InputStorage3, typename OutputView, typename MaskView, typename InputView2, typename InputView3, typename Coords > RC eWiseMulAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & _z, const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense, Coords > & _m, - const InputType1 alpha, + const Scalar< InputType1, InputStructure1, reference_dense > &alpha, const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense, Coords > & _x, const VectorView< InputType3, InputStructure3, InputStorage3, InputView3, reference_dense, Coords > & _y, const Ring & ring = Ring(), @@ -3286,14 +3349,14 @@ namespace grb { */ template< Descriptor descr = descriptors::no_operation, class Ring, typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename InputType3, - typename OutputStructure, typename MaskStructure, typename InputStructure1, typename InputStructure3, + typename OutputStructure, typename MaskStructure, typename InputStructure1, typename InputStructure2, typename InputStructure3, typename OutputStorage, typename MaskStorage, typename InputStorage1, typename InputStorage3, typename OutputView, typename MaskView, typename InputView1, typename InputView3, typename Coords > RC eWiseMulAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & _z, const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense, Coords > & _m, const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense, Coords > & _a, - const InputType2 chi, + const Scalar< InputType2, InputStructure2, reference_dense> &chi, const VectorView< InputType3, InputStructure3, InputStorage3, InputView3, reference_dense, Coords > & _y, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && @@ -3324,7 +3387,7 @@ namespace grb { */ template< Descriptor descr = descriptors::no_operation, class Ring, typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename InputType3, - typename OutputStructure, typename MaskStructure, typename InputStructure1, typename InputStructure2, + typename OutputStructure, typename MaskStructure, typename InputStructure1, typename InputStructure2, typename InputStructure3, typename OutputStorage, typename MaskStorage, typename InputStorage1, typename InputStorage2, typename OutputView, typename MaskView, typename InputView1, typename InputView2, typename Coords > @@ -3332,7 +3395,7 @@ namespace grb { const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense, Coords > & _m, const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense, Coords > & _a, const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense, Coords > & _x, - const InputType3 gamma, + const Scalar< InputType3, InputStructure3, reference_dense > &gamma, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && grb::is_semiring< Ring >::value && ! grb::is_object< MaskType >::value, @@ -3362,15 +3425,15 @@ namespace grb { */ template< Descriptor descr = descriptors::no_operation, class Ring, typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename InputType3, - typename OutputStructure, typename MaskStructure, typename InputStructure1, + typename OutputStructure, typename MaskStructure, typename InputStructure1, typename InputStructure2, typename InputStructure3, typename OutputStorage, typename MaskStorage, typename InputStorage1, typename OutputView, typename MaskView, typename InputView1, typename Coords > RC eWiseMulAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & _z, const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense, Coords > & _m, const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense, Coords > & _a, - const InputType2 beta, - const InputType3 gamma, + const Scalar< InputType2, InputStructure2, reference_dense> &beta, + const Scalar< InputType3, InputStructure3, reference_dense> &gamma, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && grb::is_semiring< Ring >::value && ! grb::is_object< MaskType >::value, @@ -3400,15 +3463,15 @@ namespace grb { */ template< Descriptor descr = descriptors::no_operation, class Ring, typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename InputType3, - typename OutputStructure, typename MaskStructure, typename InputStructure2, + typename OutputStructure, typename MaskStructure, typename InputStructure1, typename InputStructure2, typename InputStructure3, typename OutputStorage, typename MaskStorage, typename InputStorage2, typename OutputView, typename MaskView, typename InputView2, typename Coords > RC eWiseMulAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & _z, const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense, Coords > & _m, - const InputType1 alpha, + const Scalar< InputType1, InputStructure1, reference_dense > &alpha, const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense, Coords > & _x, - const InputType3 gamma, + const Scalar< InputType3, InputStructure3, reference_dense > &gamma, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && grb::is_semiring< Ring >::value && ! grb::is_object< MaskType >::value, @@ -3520,12 +3583,12 @@ namespace grb { template< Descriptor descr = descriptors::no_operation, class Ring, typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename OutputStructure, typename MaskStructure, typename InputStructure2, typename InputStructure3, - typename OutputStorage, typename MaskStorage, typename InputStorage2, typename InputStorage3, + typename OutputStorage, typename MaskStorage, typename InputStructure1, typename InputStorage2, typename InputStorage3, typename OutputView, typename MaskView, typename InputView2, typename InputView3, typename Coords > RC eWiseMul( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & z, const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense, Coords > & m, - const InputType1 alpha, + const Scalar< InputType1, InputStructure1, reference_dense > &alpha, const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense, Coords > & y, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< MaskType >::value && @@ -3557,14 +3620,14 @@ namespace grb { */ template< Descriptor descr = descriptors::no_operation, class Ring, typename OutputType, typename MaskType, typename InputType1, typename InputType2, - typename OutputStructure, typename MaskStructure, typename InputStructure1, typename InputStructure3, + typename OutputStructure, typename MaskStructure, typename InputStructure1, typename InputStructure2, typename InputStructure3, typename OutputStorage, typename MaskStorage, typename InputStorage1, typename InputStorage3, typename OutputView, typename MaskView, typename InputView1, typename InputView3, typename Coords > RC eWiseMul( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & z, const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense, Coords > & m, const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense, Coords > & x, - const InputType2 beta, + const Scalar< InputType2, InputStructure2, reference_dense > &beta, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< MaskType >::value && grb::is_semiring< Ring >::value, @@ -3595,14 +3658,14 @@ namespace grb { */ template< Descriptor descr = descriptors::no_operation, class Ring, typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename InputType3, - typename OutputStructure, typename MaskStructure, typename InputStructure3, + typename OutputStructure, typename MaskStructure, typename InputStructure1, typename InputStructure2, typename InputStructure3, typename OutputStorage, typename MaskStorage, typename InputStorage3, typename OutputView, typename MaskView, typename InputView3, typename Coords > RC eWiseMulAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & z, const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense, Coords > & m, - const InputType1 alpha, - const InputType2 beta, + const Scalar< InputType1, InputStructure1, reference_dense > &alpha, + const Scalar< InputType2, InputStructure2, reference_dense > &beta, const VectorView< InputType3, InputStructure3, InputStorage3, InputView3, reference_dense, Coords > & y, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && @@ -3639,15 +3702,15 @@ namespace grb { */ template< Descriptor descr = descriptors::no_operation, class Ring, typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename InputType3, - typename OutputStructure, typename MaskStructure, + typename OutputStructure, typename MaskStructure, typename InputStructure1, typename InputStructure2, typename InputStructure3, typename OutputStorage, typename MaskStorage, typename OutputView, typename MaskView, typename Coords > RC eWiseMulAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & z, const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense, Coords > & m, - const InputType1 alpha, - const InputType2 beta, - const InputType3 gamma, + const Scalar< InputType1, InputStructure1, reference_dense> &alpha, + const Scalar< InputType2, InputStructure2, reference_dense> &beta, + const Scalar< InputType3, InputStructure3, reference_dense> &gamma, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && grb::is_semiring< Ring >::value, @@ -3687,12 +3750,12 @@ namespace grb { Descriptor descr = descriptors::no_operation, class AddMonoid, class AnyOp, typename OutputType, typename InputType1, typename InputType2, - typename InputStructure1, typename InputStructure2, + typename OutputStructure, typename InputStructure1, typename InputStructure2, typename InputStorage1, typename InputStorage2, typename InputView1, typename InputView2, typename Coords > - RC dot_generic( OutputType &z, + RC dot_generic( Scalar< OutputType, OutputStructure, reference_dense > &z, const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense, Coords > &x, const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense, Coords > &y, const AddMonoid &addMonoid = AddMonoid(), @@ -3789,12 +3852,12 @@ namespace grb { Descriptor descr = descriptors::no_operation, class AddMonoid, class AnyOp, typename OutputType, typename InputType1, typename InputType2, - typename InputStructure1, typename InputStructure2, + typename OutputStructure, typename InputStructure1, typename InputStructure2, typename InputStorage1, typename InputStorage2, typename InputView1, typename InputView2, typename Coords > - RC dot( OutputType &z, + RC dot( Scalar< OutputType, OutputStructure, reference_dense > &z, const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense, Coords > &x, const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense, Coords > &y, const AddMonoid &addMonoid = AddMonoid(), @@ -3834,6 +3897,124 @@ namespace grb { return SUCCESS; } + /** C++ scalar specialization */ + template< + Descriptor descr = descriptors::no_operation, + class AddMonoid, class AnyOp, + typename OutputType, typename InputType1, typename InputType2, + typename InputStructure1, typename InputStructure2, + typename InputStorage1, typename InputStorage2, + typename InputView1, typename InputView2, + typename Coords + > + RC dot( OutputType &z, + const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense, Coords > &x, + const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense, Coords > &y, + const AddMonoid &addMonoid = AddMonoid(), + const AnyOp &anyOp = AnyOp(), + const typename std::enable_if< !grb::is_object< OutputType >::value && + !grb::is_object< InputType1 >::value && + !grb::is_object< InputType2 >::value && + grb::is_monoid< AddMonoid >::value && + grb::is_operator< AnyOp >::value, + void >::type * const = NULL + ) { + // static sanity checks + NO_CAST_ASSERT( ( !( descr & descriptors::no_casting ) || std::is_same< InputType1, typename AnyOp::D1 >::value ), "grb::dot", + "called with a left-hand vector value type that does not match the first " + "domain of the given multiplicative operator" ); + NO_CAST_ASSERT( ( !( descr & descriptors::no_casting ) || std::is_same< InputType2, typename AnyOp::D2 >::value ), "grb::dot", + "called with a right-hand vector value type that does not match the second " + "domain of the given multiplicative operator" ); + NO_CAST_ASSERT( ( !( descr & descriptors::no_casting ) || std::is_same< typename AddMonoid::D3, typename AnyOp::D1 >::value ), "grb::dot", + "called with a multiplicative operator output domain that does not match " + "the first domain of the given additive operator" ); + NO_CAST_ASSERT( ( !( descr & descriptors::no_casting ) || std::is_same< OutputType, typename AddMonoid::D2 >::value ), "grb::dot", + "called with an output vector value type that does not match the second " + "domain of the given additive operator" ); + NO_CAST_ASSERT( ( !( descr & descriptors::no_casting ) || std::is_same< typename AddMonoid::D3, typename AddMonoid::D2 >::value ), "grb::dot", + "called with an additive operator whose output domain does not match its " + "second input domain" ); + NO_CAST_ASSERT( ( !( descr & descriptors::no_casting ) || std::is_same< OutputType, typename AddMonoid::D3 >::value ), "grb::dot", + "called with an output vector value type that does not match the third " + "domain of the given additive operator" ); + Scalar< OutputType, structures::General, reference_dense > res( z ); + RC rc = dot( res, x, y, addMonoid, anyOp ); + if( rc != SUCCESS ) { + return rc; + } + /** \internal \todo: extract res.value into z */ + return SUCCESS; + } + + /** + * Provides a generic implementation of the dot computation on semirings by + * translating it into a dot computation on an additive commutative monoid + * with any multiplicative operator. + * + * For return codes, exception behaviour, performance semantics, template + * and non-template arguments, @see grb::dot. + */ + template< + Descriptor descr = descriptors::no_operation, class Ring, + typename IOType, typename InputType1, typename InputType2, + typename IOStructure, typename InputStructure1, typename InputStructure2, + typename InputStorage1, typename InputStorage2, + typename InputView1, typename InputView2, + Backend backend, typename Coords1, typename Coords2 + > + RC dot( Scalar< IOType, IOStructure, backend > &x, + const VectorView< InputType1, InputStructure1, InputView1, InputStorage1, backend, Coords1 > &left, + const VectorView< InputType2, InputStructure2, InputView2, InputStorage2, backend, Coords2 > &right, + const Ring &ring = Ring(), + const typename std::enable_if< + !grb::is_object< InputType1 >::value && + !grb::is_object< InputType2 >::value && + !grb::is_object< IOType >::value && + grb::is_semiring< Ring >::value, + void >::type * const = NULL + ) { + return grb::dot< descr >( x, + // return grb::dot( x, + left, right, + ring.getAdditiveMonoid(), + ring.getMultiplicativeOperator() + ); + } + + /** C++ scalar specialization. */ + template< + Descriptor descr = descriptors::no_operation, class Ring, + typename IOType, typename InputType1, typename InputType2, + typename InputStructure1, typename InputStructure2, + typename InputStorage1, typename InputStorage2, + typename InputView1, typename InputView2, + Backend backend, typename Coords1, typename Coords2 + > + RC dot( IOType &x, + const VectorView< InputType1, InputStructure1, InputView1, InputStorage1, backend, Coords1 > &left, + const VectorView< InputType2, InputStructure2, InputView2, InputStorage2, backend, Coords2 > &right, + const Ring &ring = Ring(), + const typename std::enable_if< + !grb::is_object< InputType1 >::value && + !grb::is_object< InputType2 >::value && + !grb::is_object< IOType >::value && + grb::is_semiring< Ring >::value, + void >::type * const = NULL + ) { + Scalar< IOType, structures::General, backend > res( x ); + RC rc = grb::dot< descr >( x, + left, right, + ring.getAdditiveMonoid(), + ring.getMultiplicativeOperator() + ); + if( rc != SUCCESS ) { + return rc; + } + /** \internal \todo extract res.value into x */ + return SUCCESS; + } + /** No implementation notes. */ template< typename Func, typename DataType, typename DataStructure, typename DataStorage, typename DataView, typename Coords > RC eWiseMap( const Func f, VectorView< DataType, DataStructure, DataStorage, DataView, reference_dense, Coords > & x ) { @@ -3967,11 +4148,11 @@ namespace grb { */ template< Descriptor descr = descriptors::no_operation, class Monoid, typename InputType, typename IOType, typename MaskType, - typename InputStructure, typename MaskStructure, + typename IOStructure, typename InputStructure, typename MaskStructure, typename InputStorage, typename MaskStorage, typename InputView, typename MaskView, typename Coords > - RC foldl( IOType & x, + RC foldl( Scalar< IOType, IOStructure, reference_dense > &x, const VectorView< InputType, InputStructure, InputStorage, InputView, reference_dense, Coords > & y, const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense, Coords > & mask, const Monoid & monoid = Monoid(), @@ -3995,218 +4176,10 @@ namespace grb { "the given monoid" ); NO_CAST_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< bool, MaskType >::value ), "grb::reduce", "called with a vector mask type that is not boolean" ); - throw std::runtime_error( "Needs an implementation." ); + throw std::runtime_error( "Needs an implementation." ); return SUCCESS; } - - /** - * Calculates the dot product, \f$ \alpha = (x,y) \f$, under a given additive - * monoid and multiplicative operator. - * - * @tparam descr The descriptor to be used (descriptors::no_operation - * if left unspecified). - * @tparam Ring The semiring type to use. - * @tparam OutputType The output type. - * @tparam InputType1 The input element type of the left-hand input vector. - * @tparam InputType2 The input element type of the right-hand input vector. - * @tparam InputStructure1 The structure of the left-hand input vector. - * @tparam InputStructure2 The structure of the right-hand input vector. - * @tparam InputStorage1 The type of storage of the left-hand input vector. - * @tparam InputStorage2 The type of storage of the right-hand input vector. - * @tparam InputView1 The view type applied to the left-hand input vector. - * @tparam InputView2 The view type applied to the right-hand input vector. - * - * @param[in,out] z The output element \f$ z + \alpha \f$. - * @param[in] x The left-hand input vector. - * @param[in] y The right-hand input vector. - * @param[in] addMonoid The additive monoid under which the reduction of the - * results of element-wise multiplications of \a x and - * \a y are performed. - * @param[in] anyop The multiplicative operator under which element-wise - * multiplications of \a x and \a y are performed. This can - * be any binary operator. - * - * By the definition that a dot-product operates under any additive monoid and - * any binary operator, it follows that a dot-product under any semiring can be - * trivially reduced to a call to this version instead. - * - * @return grb::MISMATCH When the dimensions of \a x and \a y do not match. All - * input data containers are left untouched if this exit - * code is returned; it will be as though this call was - * never made. - * @return grb::SUCCESS On successful completion of this call. - * - // * \parblock - // * \par Performance semantics - // * -# This call takes \f$ \Theta(n/p) \f$ work at each user process, where - // * \f$ n \f$ equals the size of the vectors \a x and \a y, and - // * \f$ p \f$ is the number of user processes. The constant factor - // * depends on the cost of evaluating the addition and multiplication - // * operators. A good implementation uses vectorised instructions - // * whenever the input domains, output domain, and the operators used - // * allow for this. - // * - // * -# This call takes \f$ \mathcal{O}(1) \f$ memory beyond the memory used - // * by the application at the point of a call to this function. - // * - // * -# This call incurs at most - // * \f$ n( \mathit{sizeof}(\mathit{D1}) + \mathit{sizeof}(\mathit{D2}) ) + \mathcal{O}(p) \f$ - // * bytes of data movement. - // * - // * -# This call incurs at most \f$ \Theta(\log p) \f$ synchronisations - // * between two or more user processes. - // * - // * -# A call to this function does result in any system calls. - // * \endparblock - * - * \note This requires an implementation to pre-allocate \f$ \Theta(p) \f$ - * memory for inter-process reduction, if the underlying communication - * layer indeed requires such a buffer. This buffer may not be allocated - * (nor freed) during a call to this function. - * - * \parblock - * \par Valid descriptors - * -# grb::descriptors::no_operation - * -# grb::descriptors::no_casting - * -# grb::descriptors::dense - * \endparblock - * - * If the dense descriptor is set, this implementation returns grb::ILLEGAL if - * it was detected that either \a x or \a y was sparse. In this case, it shall - * otherwise be as though the call to this function had not occurred (no side - * effects). - * - * \note The standard, in contrast, only specifies undefined behaviour would - * occur. This implementation goes beyond the standard by actually - * specifying what will happen. - */ - template< - Descriptor descr = descriptors::no_operation, - class AddMonoid, class AnyOp, - typename OutputType, typename InputType1, typename InputType2, - typename InputStructure1, typename InputStructure2, - typename InputStorage1, typename InputStorage2, - typename InputView1, typename InputView2, - typename InputCoords1, typename InputCoords2 - > - RC dot( OutputType &z, - const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense, InputCoords1 > &x, - const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense, InputCoords2 > &y, - const AddMonoid &addMonoid = AddMonoid(), - const AnyOp &anyOp = AnyOp(), - const typename std::enable_if< !grb::is_object< OutputType >::value && - !grb::is_object< InputType1 >::value && - !grb::is_object< InputType2 >::value && - grb::is_monoid< AddMonoid >::value && - grb::is_operator< AnyOp >::value, - void >::type * const = NULL - ) { - (void)z; - (void)x; - (void)y; - (void)addMonoid; - (void)anyOp; - // static sanity checks - // NO_CAST_ASSERT( ( !( descr & descriptors::no_casting ) || std::is_same< InputType1, typename AnyOp::D1 >::value ), "grb::dot", - // "called with a left-hand vector value type that does not match the first " - // "domain of the given multiplicative operator" ); - // NO_CAST_ASSERT( ( !( descr & descriptors::no_casting ) || std::is_same< InputType2, typename AnyOp::D2 >::value ), "grb::dot", - // "called with a right-hand vector value type that does not match the second " - // "domain of the given multiplicative operator" ); - // NO_CAST_ASSERT( ( !( descr & descriptors::no_casting ) || std::is_same< typename AddMonoid::D3, typename AnyOp::D1 >::value ), "grb::dot", - // "called with a multiplicative operator output domain that does not match " - // "the first domain of the given additive operator" ); - // NO_CAST_ASSERT( ( !( descr & descriptors::no_casting ) || std::is_same< OutputType, typename AddMonoid::D2 >::value ), "grb::dot", - // "called with an output vector value type that does not match the second " - // "domain of the given additive operator" ); - // NO_CAST_ASSERT( ( !( descr & descriptors::no_casting ) || std::is_same< typename AddMonoid::D3, typename AddMonoid::D2 >::value ), "grb::dot", - // "called with an additive operator whose output domain does not match its " - // "second input domain" ); - // NO_CAST_ASSERT( ( !( descr & descriptors::no_casting ) || std::is_same< OutputType, typename AddMonoid::D3 >::value ), "grb::dot", - // "called with an output vector value type that does not match the third " - // "domain of the given additive operator" ); - - // dynamic sanity check - // const size_t n = internal::getCoordinates( y ).size(); - // if( internal::getCoordinates( x ).size() != n ) { - // return MISMATCH; - // } - - // // cache nnzs - // const size_t nnzx = internal::getCoordinates( x ).nonzeroes(); - // const size_t nnzy = internal::getCoordinates( y ).nonzeroes(); - - // // catch trivial case - // if( nnzx == 0 && nnzy == 0 ) { - // return SUCCESS; - // } - - // // dot will be computed out-of-place here. A separate field is needed because - // // of possible multi-threaded computation of the dot. - // OutputType oop = addMonoid.template getIdentity< OutputType >(); - - // if descriptor says nothing about being dense... - RC ret = SUCCESS; - // if( !( descr & descriptors::dense ) ) { - // // check if inputs are actually dense... - // if( nnzx == n && nnzy == n ) { - // // call dense implementation - // ret = internal::dot_generic< descr | descriptors::dense >( oop, x, y, addMonoid, anyOp ); - // } else { - // // pass to sparse implementation - // ret = internal::dot_generic< descr >( oop, x, y, addMonoid, anyOp ); - // } - // } else { - // // descriptor says dense, but if any of the vectors are actually sparse... - // if( nnzx < n || nnzy < n ) { - // return ILLEGAL; - // } else { - // // all OK, pass to dense implementation - // ret = internal::dot_generic< descr >( oop, x, y, addMonoid, anyOp ); - // } - // } - - // fold out-of-place dot product into existing input, and exit - // ret = ret ? ret : foldl( z, oop, addMonoid.getOperator() ); - return ret; - } - - /** - * Provides a generic implementation of the dot computation on semirings by - * translating it into a dot computation on an additive commutative monoid - * with any multiplicative operator. - * - * For return codes, exception behaviour, performance semantics, template - * and non-template arguments, @see grb::dot. - */ - template< - Descriptor descr = descriptors::no_operation, class Ring, - typename IOType, typename InputType1, typename InputType2, - typename InputStructure1, typename InputStructure2, - typename InputStorage1, typename InputStorage2, - typename InputView1, typename InputView2, - Backend backend, typename Coords1, typename Coords2 - > - RC dot( IOType &x, - const VectorView< InputType1, InputStructure1, InputView1, InputStorage1, backend, Coords1 > &left, - const VectorView< InputType2, InputStructure2, InputView2, InputStorage2, backend, Coords2 > &right, - const Ring &ring = Ring(), - const typename std::enable_if< - !grb::is_object< InputType1 >::value && - !grb::is_object< InputType2 >::value && - !grb::is_object< IOType >::value && - grb::is_semiring< Ring >::value, - void >::type * const = NULL - ) { - // return grb::dot< descr >( x, - return grb::dot( x, - left, right, - ring.getAdditiveMonoid(), - ring.getMultiplicativeOperator() - ); - } - /** * Provides a generic implementation of the 2-norm computation. * @@ -4233,12 +4206,12 @@ namespace grb { template< Descriptor descr = descriptors::no_operation, class Ring, typename OutputType, typename InputType, - typename InputStructure, + typename OutputStructure, typename InputStructure, typename InputStorage, typename InputView, Backend backend, typename Coords > - RC norm2( OutputType &x, + RC norm2( Scalar< OutputType, OutputStructure, reference_dense > &x, const VectorView< InputType, InputStructure, InputStorage, InputView, backend, Coords > &y, const Ring &ring = Ring(), const typename std::enable_if< @@ -4252,6 +4225,31 @@ namespace grb { return ret; } + /** C++ scalar version */ + template< + Descriptor descr = descriptors::no_operation, class Ring, + typename OutputType, typename InputType, + typename InputStructure, + typename InputStorage, + typename InputView, + Backend backend, typename Coords + > + RC norm2( OutputType &x, + const VectorView< InputType, InputStructure, InputStorage, InputView, backend, Coords > &y, + const Ring &ring = Ring(), + const typename std::enable_if< + std::is_floating_point< OutputType >::value, + void >::type * const = NULL + ) { + Scalar< OutputType, structures::General, reference_dense > res( x ); + RC rc = norm2( res, y, ring ); + if( rc != SUCCESS ) { + return rc; + } + /** \internal \todo extract res.value into x */ + return SUCCESS; + } + } // end namespace ``grb'' #endif // end ``_H_GRB_DENSEREF_BLAS1'' diff --git a/tests/unit/dense_dot_norm2.cpp b/tests/unit/dense_dot_norm2.cpp index 31acb78d8..f73902f5c 100644 --- a/tests/unit/dense_dot_norm2.cpp +++ b/tests/unit/dense_dot_norm2.cpp @@ -39,7 +39,7 @@ void grb_program( const size_t &n, grb::RC &rc ) { // std::cerr << "\t test 1 (dense, regular semiring): initialisation FAILED\n"; // return; // } - double out = 2.55; + Scalar< double > out( 2.55 ); // test 1, exec rc = grb::dot( out, left, right, ring ); From 9ac08fb976c6673ddc0b1fe7abe02610d6aebfa7 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Tue, 22 Mar 2022 14:17:39 +0000 Subject: [PATCH 113/282] !30 Resolve internal issue #377: Do not expose coordinates template argument in alp vectors --- include/graphblas/base/vector.hpp | 2 +- include/graphblas/denseref/blas1.hpp | 607 ++++++++++++-------------- include/graphblas/denseref/blas2.hpp | 115 +++-- include/graphblas/denseref/blas3.hpp | 7 +- include/graphblas/denseref/vector.hpp | 69 +-- include/graphblas/vector.hpp | 2 +- 6 files changed, 362 insertions(+), 440 deletions(-) diff --git a/include/graphblas/base/vector.hpp b/include/graphblas/base/vector.hpp index f22bb2a1b..2a93366a3 100644 --- a/include/graphblas/base/vector.hpp +++ b/include/graphblas/base/vector.hpp @@ -901,7 +901,7 @@ namespace grb { } }; - template< typename T, typename Structure, typename StorageSchemeType, typename View, enum Backend backend, typename C > + template< typename T, typename Structure, typename StorageSchemeType, typename View, enum Backend backend > class VectorView { }; } diff --git a/include/graphblas/denseref/blas1.hpp b/include/graphblas/denseref/blas1.hpp index 8d43179bb..ab239e051 100644 --- a/include/graphblas/denseref/blas1.hpp +++ b/include/graphblas/denseref/blas1.hpp @@ -171,8 +171,8 @@ namespace grb { // * \mathit{sizeof}(\mathit{size\_t}) \f$ bytes of data. // * \endparblock */ - template< typename DataType, typename DataStructure, typename DataStorage, typename View, typename Coords > - RC clear( VectorView< DataType, DataStructure, DataStorage, View, reference_dense, Coords > & x ) noexcept { + template< typename DataType, typename DataStructure, typename DataStorage, typename View > + RC clear( VectorView< DataType, DataStructure, DataStorage, View, reference_dense > & x ) noexcept { throw std::runtime_error( "Needs an implementation" ); return SUCCESS; } @@ -201,8 +201,8 @@ namespace grb { // * -# shall not make any system calls. // * \endparblock */ - template< typename DataType, typename DataStructure, typename DataStorage, typename View, typename Coords > - size_t size( const VectorView< DataType, DataStructure, DataStorage, View, reference_dense, Coords > & x ) noexcept { + template< typename DataType, typename DataStructure, typename DataStorage, typename View > + size_t size( const VectorView< DataType, DataStructure, DataStorage, View, reference_dense > & x ) noexcept { return getLength( x ); } @@ -229,15 +229,15 @@ namespace grb { // * -# shall not make any system calls. // * \endparblock */ - template< typename DataType, typename DataStructure, typename DataStorage, typename View, typename Coords > - size_t nnz( const VectorView< DataType, DataStructure, DataStorage, View, reference_dense, Coords > & x ) noexcept { + template< typename DataType, typename DataStructure, typename DataStorage, typename View > + size_t nnz( const VectorView< DataType, DataStructure, DataStorage, View, reference_dense > & x ) noexcept { throw std::runtime_error( "Needs an implementation." ); return 0; } /** \todo add documentation. In particular, think about the meaning with \a P > 1. */ - template< typename InputType, typename InputStructure, typename InputStorage, typename View, typename length_type, typename Coords > - RC resize( VectorView< InputType, InputStructure, InputStorage, View, reference_dense, Coords > & x, const length_type new_nz ) { + template< typename InputType, typename InputStructure, typename InputStorage, typename View, typename length_type > + RC resize( VectorView< InputType, InputStructure, InputStorage, View, reference_dense > & x, const length_type new_nz ) { // check if we have a mismatch if( new_nz > grb::size( x ) ) { return MISMATCH; @@ -303,10 +303,8 @@ namespace grb { */ template< Descriptor descr = descriptors::no_operation, - typename DataType, typename DataStructure, typename ValStructure, typename DataStorage, typename View, typename T, - typename Coords - > - RC set( VectorView< DataType, DataStructure, DataStorage, View, reference_dense, Coords > & x, + typename DataType, typename DataStructure, typename ValStructure, typename DataStorage, typename View, typename T > + RC set( VectorView< DataType, DataStructure, DataStorage, View, reference_dense > & x, const Scalar< T, ValStructure, reference_dense > val, const typename std::enable_if< !grb::is_object< DataType >::value && @@ -384,9 +382,9 @@ namespace grb { template< Descriptor descr = descriptors::no_operation, typename DataType, typename DataView, typename DataStructure, typename DataStorage, typename MaskStructure, typename MaskStorage, typename MaskType, typename MaskView, - typename T, typename ValStructure, typename Coords > - RC set( VectorView< DataType, DataStructure, DataStorage, DataView, reference_dense, Coords > & x, - const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense, Coords > & m, + typename T, typename ValStructure > + RC set( VectorView< DataType, DataStructure, DataStorage, DataView, reference_dense > & x, + const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense > & m, const Scalar< T, ValStructure, reference_dense > val, const typename std::enable_if< ! grb::is_object< DataType >::value && ! grb::is_object< T >::value, void >::type * const = NULL ) { #ifdef _DEBUG @@ -420,9 +418,9 @@ namespace grb { template< Descriptor descr = descriptors::no_operation, typename DataType, typename DataView, typename DataStructure, typename DataStorage, typename MaskStructure, typename MaskStorage, typename MaskType, typename MaskView, - typename T, typename Coords > - RC set( VectorView< DataType, DataStructure, DataStorage, DataView, reference_dense, Coords > & x, - const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense, Coords > & m, + typename T > + RC set( VectorView< DataType, DataStructure, DataStorage, DataView, reference_dense > & x, + const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense > & m, const T val, const typename std::enable_if< ! grb::is_object< DataType >::value && ! grb::is_object< T >::value, void >::type * const = NULL ) { #ifdef _DEBUG @@ -481,8 +479,8 @@ namespace grb { // * -# shall not make any system calls. // * \endparblock */ - template< Descriptor descr = descriptors::no_operation, typename DataType, typename DataStructure, typename ValStructure, typename DataStorage, typename View, typename T, typename Coords > - RC setElement( VectorView< DataType, DataStructure, DataStorage, View, reference_dense, Coords > & x, + template< Descriptor descr = descriptors::no_operation, typename DataType, typename DataStructure, typename ValStructure, typename DataStorage, typename View, typename T > + RC setElement( VectorView< DataType, DataStructure, DataStorage, View, reference_dense > & x, const Scalar< T, ValStructure, reference_dense > val, const size_t i, const typename std::enable_if< ! grb::is_object< DataType >::value && ! grb::is_object< T >::value, void >::type * const = NULL ) { @@ -498,8 +496,8 @@ namespace grb { } /** C++ scalar variant */ - template< Descriptor descr = descriptors::no_operation, typename DataType, typename DataStructure, typename ValStructure, typename DataStorage, typename View, typename T, typename Coords > - RC setElement( VectorView< DataType, DataStructure, DataStorage, View, reference_dense, Coords > & x, + template< Descriptor descr = descriptors::no_operation, typename DataType, typename DataStructure, typename ValStructure, typename DataStorage, typename View, typename T > + RC setElement( VectorView< DataType, DataStructure, DataStorage, View, reference_dense > & x, const T val, const size_t i, const typename std::enable_if< ! grb::is_object< DataType >::value && ! grb::is_object< T >::value, void >::type * const = NULL ) { @@ -570,8 +568,8 @@ namespace grb { * @see grb::operators::right_assign. * @see grb::setElement. */ - template< Descriptor descr = descriptors::no_operation, typename OutputType, typename InputType, typename OutputStructure, typename OutputStorage, typename InputStructure, typename InputStorage, typename OutputView, typename InputView, typename Coords > - RC set( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & x, const VectorView< InputType, InputStructure, InputStorage, InputView, reference_dense, Coords > & y ) { + template< Descriptor descr = descriptors::no_operation, typename OutputType, typename InputType, typename OutputStructure, typename OutputStorage, typename InputStructure, typename InputStorage, typename OutputView, typename InputView > + RC set( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > & x, const VectorView< InputType, InputStructure, InputStorage, InputView, reference_dense > & y ) { // static sanity checks NO_CAST_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< OutputType, InputType >::value ), "grb::copy (Vector)", "called with vector parameters whose element data types do not match" ); @@ -668,11 +666,10 @@ namespace grb { typename OutputType, typename MaskType, typename InputType, typename OutputStructure, typename MaskStructure, typename InputStructure, typename OutputStorage, typename MaskStorage, typename InputStorage, - typename OutputView, typename MaskView, typename InputView, - typename Coords > - RC set( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & x, - const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense, Coords > & mask, - const VectorView< InputType, InputStructure, InputStorage, InputView, reference_dense, Coords > & y, + typename OutputView, typename MaskView, typename InputView > + RC set( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > & x, + const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense > & mask, + const VectorView< InputType, InputStructure, InputStorage, InputView, reference_dense > & y, const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType >::value, void >::type * const = NULL ) { // static sanity checks NO_CAST_ASSERT( @@ -780,8 +777,8 @@ namespace grb { * and/or vectorised operations are used. */ template< Descriptor descr = descriptors::no_operation, class Monoid, - typename InputType, typename InputStructure, typename InputStorage, typename InputView, typename IOType, typename IOStructure, typename Coords > - RC foldr( const VectorView< InputType, InputStructure, InputStorage, InputView, reference_dense, Coords > & x, + typename InputType, typename InputStructure, typename InputStorage, typename InputView, typename IOType, typename IOStructure > + RC foldr( const VectorView< InputType, InputStructure, InputStorage, InputView, reference_dense > & x, Scalar< IOType, IOStructure, reference_dense > & beta, const Monoid & monoid = Monoid(), const typename std::enable_if< ! grb::is_object< InputType >::value && ! grb::is_object< IOType >::value && grb::is_monoid< Monoid >::value, void >::type * const = NULL ) { @@ -792,8 +789,8 @@ namespace grb { /** C++ scalar variant */ template< Descriptor descr = descriptors::no_operation, class Monoid, - typename InputType, typename InputStructure, typename InputStorage, typename InputView, typename IOType, typename Coords > - RC foldr( const VectorView< InputType, InputStructure, InputStorage, InputView, reference_dense, Coords > & x, + typename InputType, typename InputStructure, typename InputStorage, typename InputView, typename IOType > + RC foldr( const VectorView< InputType, InputStructure, InputStorage, InputView, reference_dense > & x, IOType & beta, const Monoid & monoid = Monoid(), const typename std::enable_if< ! grb::is_object< InputType >::value && ! grb::is_object< IOType >::value && grb::is_monoid< Monoid >::value, void >::type * const = NULL ) { @@ -873,9 +870,9 @@ namespace grb { * @see grb::operators::internal::Operator for a discussion on when in-place * and/or vectorised operations are used. */ - template< Descriptor descr = descriptors::no_operation, class Monoid, typename IOType, typename InputType, typename IOStructure, typename InputStructure, typename IOStorage, typename IOView, typename Coords > + template< Descriptor descr = descriptors::no_operation, class Monoid, typename IOType, typename InputType, typename IOStructure, typename InputStructure, typename IOStorage, typename IOView > RC foldr( const Scalar< InputType, InputStructure, reference_dense > & alpha, - VectorView< IOType, IOStructure, IOStorage, IOView, reference_dense, Coords > & y, + VectorView< IOType, IOStructure, IOStorage, IOView, reference_dense > & y, const Monoid & monoid = Monoid(), const typename std::enable_if< ! grb::is_object< InputType >::value && ! grb::is_object< IOType >::value && grb::is_monoid< Monoid >::value, void >::type * const = NULL ) { // static sanity checks @@ -898,9 +895,9 @@ namespace grb { * * Specialisation for scalar \a x. */ - template< Descriptor descr = descriptors::no_operation, class OP, typename IOType, typename InputType, typename IOStructure, typename InputStructure, typename IOStorage, typename IOView, typename Coords > + template< Descriptor descr = descriptors::no_operation, class OP, typename IOType, typename InputType, typename IOStructure, typename InputStructure, typename IOStorage, typename IOView > RC foldr( const Scalar< InputType, InputStructure, reference_dense > & alpha, - VectorView< IOType, IOStructure, IOStorage, IOView, reference_dense, Coords > & y, + VectorView< IOType, IOStructure, IOStorage, IOView, reference_dense > & y, const OP & op = OP(), const typename std::enable_if< ! grb::is_object< InputType >::value && ! grb::is_object< IOType >::value && grb::is_operator< OP >::value, void >::type * const = NULL ) { // static sanity checks @@ -996,10 +993,9 @@ namespace grb { typename IOType, typename InputType, typename IOStructure, typename InputStructure, typename IOStorage, typename InputStorage, - typename IOView, typename InputView, - typename Coords > - RC foldr( const VectorView< InputType, InputStructure, InputStorage, InputView, reference_dense, Coords > & x, - VectorView< IOType, IOStructure, IOStorage, IOView, reference_dense, Coords > & y, + typename IOView, typename InputView > + RC foldr( const VectorView< InputType, InputStructure, InputStorage, InputView, reference_dense > & x, + VectorView< IOType, IOStructure, IOStorage, IOView, reference_dense > & y, const OP & op = OP(), const typename std::enable_if< grb::is_operator< OP >::value && ! grb::is_object< InputType >::value && ! grb::is_object< IOType >::value, void >::type * = NULL ) { // static sanity checks @@ -1030,11 +1026,10 @@ namespace grb { typename IOType, typename MaskType, typename InputType, typename IOStructure, typename MaskStructure, typename InputStructure, typename IOStorage, typename MaskStorage, typename InputStorage, - typename IOView, typename MaskView, typename InputView, - typename Coords > - RC foldr( const VectorView< InputType, InputStructure, InputStorage, InputView, reference_dense, Coords > & x, - const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense, Coords > & m, - VectorView< IOType, IOStructure, IOStorage, IOView, reference_dense, Coords > & y, + typename IOView, typename MaskView, typename InputView > + RC foldr( const VectorView< InputType, InputStructure, InputStorage, InputView, reference_dense > & x, + const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense > & m, + VectorView< IOType, IOStructure, IOStorage, IOView, reference_dense > & y, const OP & op = OP(), const typename std::enable_if< grb::is_operator< OP >::value && ! grb::is_object< InputType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< IOType >::value, void >::type * = NULL ) { @@ -1141,10 +1136,9 @@ namespace grb { typename IOType, typename InputType, typename IOStructure, typename InputStructure, typename IOStorage, typename InputStorage, - typename IOView, typename InputView, - typename Coords > - RC foldr( const VectorView< InputType, InputStructure, InputStorage, InputView, reference_dense, Coords > & x, - VectorView< IOType, IOStructure, IOStorage, IOView, reference_dense, Coords > & y, + typename IOView, typename InputView > + RC foldr( const VectorView< InputType, InputStructure, InputStorage, InputView, reference_dense > & x, + VectorView< IOType, IOStructure, IOStorage, IOView, reference_dense > & y, const Monoid & monoid = Monoid(), const typename std::enable_if< grb::is_monoid< Monoid >::value && ! grb::is_object< InputType >::value && ! grb::is_object< IOType >::value, void >::type * = NULL ) { // static sanity checks @@ -1177,11 +1171,10 @@ namespace grb { typename IOType, typename MaskType, typename InputType, typename IOStructure, typename MaskStructure, typename InputStructure, typename IOStorage, typename MaskStorage, typename InputStorage, - typename IOView, typename MaskView, typename InputView, - typename Coords > - RC foldr( const VectorView< InputType, InputStructure, InputStorage, InputView, reference_dense, Coords > & x, - const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense, Coords > & m, - VectorView< IOType, IOStructure, IOStorage, IOView, reference_dense, Coords > & y, + typename IOView, typename MaskView, typename InputView > + RC foldr( const VectorView< InputType, InputStructure, InputStorage, InputView, reference_dense > & x, + const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense > & m, + VectorView< IOType, IOStructure, IOStorage, IOView, reference_dense > & y, const Monoid & monoid = Monoid(), const typename std::enable_if< grb::is_monoid< Monoid >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType >::value && ! grb::is_object< IOType >::value, void >::type * = NULL ) { @@ -1289,8 +1282,8 @@ namespace grb { * @see grb::operators::internal::Operator for a discussion on when in-place * and/or vectorised operations are used. */ - template< Descriptor descr = descriptors::no_operation, class Op, typename IOType, typename InputType, typename IOStructure, typename InputStructure, typename IOStorage, typename IOView, typename Coords > - RC foldl( VectorView< IOType, IOStructure, IOStorage, IOView, reference_dense, Coords > & x, + template< Descriptor descr = descriptors::no_operation, class Op, typename IOType, typename InputType, typename IOStructure, typename InputStructure, typename IOStorage, typename IOView > + RC foldl( VectorView< IOType, IOStructure, IOStorage, IOView, reference_dense > & x, const Scalar< InputType, InputStructure, reference_dense > beta, const Op & op = Op(), const typename std::enable_if< ! grb::is_object< IOType >::value && ! grb::is_object< InputType >::value && grb::is_operator< Op >::value, void >::type * = NULL ) { @@ -1319,14 +1312,12 @@ namespace grb { typename IOType, typename MaskType, typename InputType, typename IOStructure, typename MaskStructure, typename InputStructure, typename IOStorage, typename MaskStorage, - typename IOView, typename MaskView, typename InputView, - typename Coords > - RC foldl( VectorView< IOType, IOStructure, IOStorage, IOView, reference_dense, Coords > & x, - const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense, Coords > & m, + typename IOView, typename MaskView, typename InputView > + RC foldl( VectorView< IOType, IOStructure, IOStorage, IOView, reference_dense > & x, + const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense > & m, const Scalar< InputType, InputStructure, reference_dense > &beta, const Op & op = Op(), - const typename std::enable_if< ! grb::is_object< IOType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType >::value && grb::is_operator< Op >::value, void >::type * = - NULL ) { + const typename std::enable_if< ! grb::is_object< IOType >::value && ! grb::is_object< InputType >::value && grb::is_operator< Op >::value, void >::type * = NULL ) { // static sanity checks NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Op::D1, IOType >::value ), "grb::foldl", "called with a vector x of a type that does not match the first domain " @@ -1419,8 +1410,8 @@ namespace grb { * @see grb::operators::internal::Operator for a discussion on when in-place * and/or vectorised operations are used. */ - template< Descriptor descr = descriptors::no_operation, class Monoid, typename IOType, typename InputType, typename IOStructure, typename IOStorage, typename IOView, typename Coords > - RC foldl( VectorView< IOType, IOStructure, IOStorage, IOView, reference_dense, Coords > & x, + template< Descriptor descr = descriptors::no_operation, class Monoid, typename IOType, typename InputType, typename IOStructure, typename IOStorage, typename IOView > + RC foldl( VectorView< IOType, IOStructure, IOStorage, IOView, reference_dense > & x, const InputType beta, const Monoid & monoid = Monoid(), const typename std::enable_if< ! grb::is_object< IOType >::value && ! grb::is_object< InputType >::value && grb::is_monoid< Monoid >::value, void >::type * = NULL ) { @@ -1449,10 +1440,9 @@ namespace grb { typename IOType, typename MaskType, typename InputType, typename IOStructure, typename MaskStructure, typename IOStorage, typename MaskStorage, - typename IOView, typename MaskView, - typename Coords > - RC foldl( VectorView< IOType, IOStructure, IOStorage, IOView, reference_dense, Coords > & x, - const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense, Coords > & m, + typename IOView, typename MaskView > + RC foldl( VectorView< IOType, IOStructure, IOStorage, IOView, reference_dense > & x, + const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense > & m, const InputType & beta, const Monoid & monoid = Monoid(), const typename std::enable_if< ! grb::is_object< IOType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType >::value && grb::is_monoid< Monoid >::value, void >::type * = @@ -1557,10 +1547,9 @@ namespace grb { typename IOType, typename InputType, typename IOStructure, typename InputStructure, typename IOStorage, typename InputStorage, - typename IOView, typename InputView, - typename Coords > - RC foldl( VectorView< IOType, IOStructure, IOStorage, IOView, reference_dense, Coords > & x, - const VectorView< InputType, InputStructure, InputStorage, InputView, reference_dense, Coords > & y, + typename IOView, typename InputView > + RC foldl( VectorView< IOType, IOStructure, IOStorage, IOView, reference_dense > & x, + const VectorView< InputType, InputStructure, InputStorage, InputView, reference_dense > & y, const OP & op = OP(), const typename std::enable_if< grb::is_operator< OP >::value && ! grb::is_object< IOType >::value && ! grb::is_object< InputType >::value, void >::type * = NULL ) { // static sanity checks @@ -1664,10 +1653,9 @@ namespace grb { typename IOType, typename InputType, typename IOStructure, typename InputStructure, typename IOStorage, typename InputStorage, - typename IOView, typename InputView, - typename Coords > - RC foldl( VectorView< IOType, IOStructure, IOStorage, IOView, reference_dense, Coords > & x, - const VectorView< InputType, InputStructure, InputStorage, InputView, reference_dense, Coords > & y, + typename IOView, typename InputView > + RC foldl( VectorView< IOType, IOStructure, IOStorage, IOView, reference_dense > & x, + const VectorView< InputType, InputStructure, InputStorage, InputView, reference_dense > & y, const Monoid & monoid = Monoid(), const typename std::enable_if< grb::is_monoid< Monoid >::value && ! grb::is_object< IOType >::value && ! grb::is_object< InputType >::value, void >::type * = NULL ) { // static sanity checks @@ -1700,11 +1688,10 @@ namespace grb { typename IOType, typename MaskType, typename InputType, typename IOStructure, typename MaskStructure, typename InputStructure, typename IOStorage, typename MaskStorage, typename InputStorage, - typename IOView, typename MaskView, typename InputView, - typename Coords > - RC foldl( VectorView< IOType, IOStructure, IOStorage, IOView, reference_dense, Coords > & x, - const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense, Coords > & m, - const VectorView< InputType, InputStructure, InputStorage, InputView, reference_dense, Coords > & y, + typename IOView, typename MaskView, typename InputView > + RC foldl( VectorView< IOType, IOStructure, IOStorage, IOView, reference_dense > & x, + const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense > & m, + const VectorView< InputType, InputStructure, InputStorage, InputView, reference_dense > & y, const OP & op = OP(), const typename std::enable_if< grb::is_operator< OP >::value && ! grb::is_object< IOType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType >::value, void >::type * = NULL ) { @@ -1744,11 +1731,10 @@ namespace grb { typename IOType, typename MaskType, typename InputType, typename IOStructure, typename MaskStructure, typename InputStructure, typename IOStorage, typename MaskStorage, typename InputStorage, - typename IOView, typename MaskView, typename InputView, - typename Coords > - RC foldl( VectorView< IOType, IOStructure, IOStorage, IOView, reference_dense, Coords > & x, - const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense, Coords > & m, - const VectorView< InputType, InputStructure, InputStorage, InputView, reference_dense, Coords > & y, + typename IOView, typename MaskView, typename InputView > + RC foldl( VectorView< IOType, IOStructure, IOStorage, IOView, reference_dense > & x, + const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense > & m, + const VectorView< InputType, InputStructure, InputStorage, InputView, reference_dense > & y, const Monoid & monoid = Monoid(), const typename std::enable_if< grb::is_monoid< Monoid >::value && ! grb::is_object< IOType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType >::value, void >::type * = NULL ) { @@ -1856,10 +1842,9 @@ namespace grb { typename OutputType, typename InputType1, typename InputType2, typename OutputStructure, typename InputStructure1, typename InputStructure2, typename OutputStorage, typename InputStorage1, - typename OutputView, typename InputView1, - typename Coords > - RC eWiseApply( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & z, - const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense, Coords > & x, + typename OutputView, typename InputView1 > + RC eWiseApply( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > & z, + const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense > & x, const Scalar< InputType2, InputStructure2, reference_dense > &beta, const OP & op = OP(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_operator< OP >::value, @@ -1880,9 +1865,8 @@ namespace grb { typename OutputType, typename InputType1, typename InputType2, typename OutputStructure, typename InputStructure1, typename InputStructure2, typename OutputStorage, - typename OutputView, - typename Coords > - RC eWiseApply( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & z, + typename OutputView > + RC eWiseApply( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > & z, const Scalar< InputType1, InputStructure1, reference_dense> &alpha, const Scalar< InputType2, InputStructure2, reference_dense> &beta, const OP & op = OP(), @@ -1906,9 +1890,8 @@ namespace grb { typename OutputType, typename InputType1, typename InputType2, typename OutputStructure, typename InputStructure1, typename InputStructure2, typename OutputStorage, - typename OutputView, - typename Coords > - RC eWiseApply( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & z, + typename OutputView > + RC eWiseApply( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > & z, const Scalar< InputType1, InputStructure1, reference_dense> &alpha, const Scalar< InputType2, InputStructure2, reference_dense> &beta, const Monoid & monoid = Monoid(), @@ -1930,11 +1913,10 @@ namespace grb { typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename OutputStructure, typename MaskStructure, typename InputStructure1, typename InputStructure2, typename OutputStorage, typename MaskStorage, typename InputStorage1, - typename OutputView, typename MaskView, typename InputView1, - typename Coords > - RC eWiseApply( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & z, - const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense, Coords > & mask, - const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense, Coords > & x, + typename OutputView, typename MaskView, typename InputView1 > + RC eWiseApply( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > & z, + const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense > & mask, + const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense > & x, const Scalar< InputType2, InputStructure2, reference_dense > &beta, const OP & op = OP(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && @@ -1960,11 +1942,10 @@ namespace grb { typename OutputType, typename InputType1, typename InputType2, typename OutputStructure, typename InputStructure1, typename InputStructure2, typename OutputStorage, typename InputStorage1, typename InputStorage2, - typename OutputView, typename InputView1, typename InputView2, - typename Coords > - RC eWiseApply( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & z, - const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense, Coords > & x, - const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense, Coords > & y, + typename OutputView, typename InputView1, typename InputView2 > + RC eWiseApply( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > & z, + const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense > & x, + const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > & y, const Monoid & monoid = Monoid(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_monoid< Monoid >::value, void >::type * const = NULL ) { @@ -1984,11 +1965,10 @@ namespace grb { typename OutputType, typename InputType1, typename InputType2, typename OutputStructure, typename InputStructure1, typename InputStructure2, typename OutputStorage, typename InputStorage2, - typename OutputView, typename InputView2, - typename Coords > - RC eWiseApply( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & z, + typename OutputView, typename InputView2 > + RC eWiseApply( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > & z, const Scalar< InputType1, InputStructure1, reference_dense> &alpha, - const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense, Coords > & y, + const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > & y, const Monoid & monoid = Monoid(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_monoid< Monoid >::value, void >::type * const = NULL ) { @@ -2008,16 +1988,15 @@ namespace grb { typename OutputType, typename InputType1, typename InputType2, typename OutputStructure, typename InputStructure1, typename InputStructure2, typename OutputStorage, typename InputStorage1, - typename OutputView, typename InputView1, - typename Coords > - RC eWiseApply( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & z, - const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense, Coords > & x, + typename OutputView, typename InputView1 > + RC eWiseApply( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > & z, + const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense > & x, const Scalar< InputType2, InputStructure2, reference_dense > &beta, const Monoid & monoid = Monoid(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_monoid< Monoid >::value, void >::type * const = NULL ) { #ifdef _DEBUG - std::cout << "In unmasked eWiseApply ([T1]<-[T2]<-T3, using monoid)\n"; + std::cout << "In unmasked eWiseApply ([T1]<-T2<-[T3], using monoid)\n"; #endif throw std::runtime_error( "Needs an implementation." ); return SUCCESS; @@ -2032,12 +2011,11 @@ namespace grb { typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename OutputStructure, typename MaskStructure, typename InputStructure1, typename InputStructure2, typename OutputStorage, typename MaskStorage, typename InputStorage1, typename InputStorage2, - typename OutputView, typename MaskView, typename InputView1, typename InputView2, - typename Coords > - RC eWiseApply( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & z, - const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense, Coords > & mask, - const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense, Coords > & x, - const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense, Coords > & y, + typename OutputView, typename MaskView, typename InputView1, typename InputView2 > + RC eWiseApply( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > & z, + const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense > & mask, + const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense > & x, + const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > & y, const Monoid & monoid = Monoid(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_monoid< Monoid >::value, @@ -2058,12 +2036,11 @@ namespace grb { typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename OutputStructure, typename MaskStructure, typename InputStructure1, typename InputStructure2, typename OutputStorage, typename MaskStorage, typename InputStorage2, - typename OutputView, typename MaskView, typename InputView2, - typename Coords > - RC eWiseApply( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & z, - const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense, Coords > & mask, + typename OutputView, typename MaskView, typename InputView2 > + RC eWiseApply( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > & z, + const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense > & mask, const Scalar< InputType1, InputStructure1, reference_dense> &alpha, - const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense, Coords > & y, + const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > & y, const Monoid & monoid = Monoid(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_monoid< Monoid >::value, @@ -2084,11 +2061,10 @@ namespace grb { typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename OutputStructure, typename MaskStructure, typename InputStructure1, typename InputStructure2, typename OutputStorage, typename MaskStorage, typename InputStorage1, - typename OutputView, typename MaskView, typename InputView1, - typename Coords > - RC eWiseApply( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & z, - const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense, Coords > & mask, - const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense, Coords > & x, + typename OutputView, typename MaskView, typename InputView1 > + RC eWiseApply( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > & z, + const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense > & mask, + const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense > & x, const Scalar< InputType2, InputStructure2, reference_dense > &beta, const Monoid & monoid = Monoid(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && @@ -2175,11 +2151,10 @@ namespace grb { typename OutputType, typename InputType1, typename InputType2, typename OutputStructure, typename InputStructure1, typename InputStructure2, typename OutputStorage, typename InputStorage2, - typename OutputView, typename InputView2, - typename Coords > - RC eWiseApply( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & z, + typename OutputView, typename InputView2 > + RC eWiseApply( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > & z, const Scalar< InputType1, InputStructure1, reference_dense > &alpha, - const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense, Coords > & y, + const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > & y, const OP & op = OP(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_operator< OP >::value, void >::type * const = NULL ) { @@ -2199,12 +2174,11 @@ namespace grb { typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename OutputStructure, typename MaskStructure, typename InputStructure1, typename InputStructure2, typename OutputStorage, typename MaskStorage, typename InputStorage2, - typename OutputView, typename MaskView, typename InputView2, - typename Coords > - RC eWiseApply( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & z, - const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense, Coords > & mask, + typename OutputView, typename MaskView, typename InputView2 > + RC eWiseApply( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > & z, + const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense > & mask, const Scalar< InputType1, InputStructure1, reference_dense> &alpha, - const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense, Coords > & y, + const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > & y, const OP & op = OP(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_operator< OP >::value, @@ -2297,11 +2271,10 @@ namespace grb { typename OutputType, typename InputType1, typename InputType2, typename OutputStructure, typename InputStructure1, typename InputStructure2, typename OutputStorage, typename InputStorage1, typename InputStorage2, - typename OutputView, typename InputView1, typename InputView2, - typename Coords > - RC eWiseApply( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & z, - const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense, Coords > & x, - const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense, Coords > & y, + typename OutputView, typename InputView1, typename InputView2 > + RC eWiseApply( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > & z, + const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense > & x, + const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > & y, const OP & op = OP(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_operator< OP >::value, void >::type * const = NULL ) { @@ -2321,12 +2294,11 @@ namespace grb { typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename OutputStructure, typename MaskStructure, typename InputStructure1, typename InputStructure2, typename OutputStorage, typename MaskStorage, typename InputStorage1, typename InputStorage2, - typename OutputView, typename MaskView, typename InputView1, typename InputView2, - typename Coords > - RC eWiseApply( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & z, - const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense, Coords > & mask, - const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense, Coords > & x, - const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense, Coords > & y, + typename OutputView, typename MaskView, typename InputView1, typename InputView2 > + RC eWiseApply( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > & z, + const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense > & mask, + const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense > & x, + const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > & y, const OP & op = OP(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_operator< OP >::value, @@ -2423,11 +2395,10 @@ namespace grb { typename OutputType, typename InputType1, typename InputType2, typename OutputStructure, typename InputStructure1, typename InputStructure2, typename OutputStorage, typename InputStorage1, typename InputStorage2, - typename OutputView, typename InputView1, typename InputView2, - typename Coords > - RC eWiseAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & z, - const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense, Coords > & x, - const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense, Coords > & y, + typename OutputView, typename InputView1, typename InputView2 > + RC eWiseAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > & z, + const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense > & x, + const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > & y, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_semiring< Ring >::value, void >::type * const = NULL ) { @@ -2457,11 +2428,10 @@ namespace grb { typename OutputType, typename InputType1, typename InputType2, typename OutputStructure, typename InputStructure1, typename InputStructure2, typename OutputStorage, typename InputStorage2, - typename OutputView, typename InputView2, - typename Coords > - RC eWiseAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & z, + typename OutputView, typename InputView2 > + RC eWiseAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > & z, const Scalar< InputType1, InputStructure1, reference_dense> &alpha, - const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense, Coords > & y, + const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > & y, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_semiring< Ring >::value, void >::type * const = NULL ) { @@ -2491,10 +2461,9 @@ namespace grb { typename OutputType, typename InputType1, typename InputType2, typename OutputStructure, typename InputStructure1, typename InputStructure2, typename OutputStorage, typename InputStorage1, - typename OutputView, typename InputView1, - typename Coords > - RC eWiseAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & z, - const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense, Coords > & x, + typename OutputView, typename InputView1 > + RC eWiseAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > & z, + const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense > & x, const Scalar< InputType2, InputStructure2, reference_dense > &beta, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_semiring< Ring >::value, @@ -2525,9 +2494,8 @@ namespace grb { typename OutputType, typename InputType1, typename InputType2, typename OutputStructure, typename InputStructure1, typename InputStructure2, typename OutputStorage, - typename OutputView, - typename Coords > - RC eWiseAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & z, + typename OutputView > + RC eWiseAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > & z, const Scalar< InputType1, InputStructure1, reference_dense > &alpha, const Scalar< InputType2, InputStructure2, reference_dense > &beta, const Ring & ring = Ring(), @@ -2561,12 +2529,11 @@ namespace grb { typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename OutputStructure, typename MaskStructure, typename InputStructure1, typename InputStructure2, typename OutputStorage, typename MaskStorage, typename InputStorage1, typename InputStorage2, - typename OutputView, typename MaskView, typename InputView1, typename InputView2, - typename Coords > - RC eWiseAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & z, - const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense, Coords > & m, - const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense, Coords > & x, - const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense, Coords > & y, + typename OutputView, typename MaskView, typename InputView1, typename InputView2 > + RC eWiseAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > & z, + const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense > & m, + const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense > & x, + const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > & y, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_semiring< Ring >::value, @@ -2599,12 +2566,11 @@ namespace grb { typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename OutputStructure, typename MaskStructure, typename InputStructure1, typename InputStructure2, typename OutputStorage, typename MaskStorage, typename InputStorage2, - typename OutputView, typename MaskView, typename InputView2, - typename Coords > - RC eWiseAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & z, - const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense, Coords > & m, + typename OutputView, typename MaskView, typename InputView2 > + RC eWiseAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > & z, + const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense > & m, const Scalar< InputType1, InputStructure1, reference_dense> &alpha, - const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense, Coords > & y, + const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > & y, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_semiring< Ring >::value, @@ -2637,11 +2603,10 @@ namespace grb { typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename OutputStructure, typename MaskStructure, typename InputStructure1, typename InputStructure2, typename OutputStorage, typename MaskStorage, typename InputStorage1, - typename OutputView, typename MaskView, typename InputView1, - typename Coords > - RC eWiseAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & z, - const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense, Coords > & m, - const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense, Coords > & x, + typename OutputView, typename MaskView, typename InputView1 > + RC eWiseAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > & z, + const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense > & m, + const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense > & x, const Scalar< InputType2, InputStructure2, reference_dense > &beta, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && @@ -2675,10 +2640,9 @@ namespace grb { typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename OutputStructure, typename MaskStructure, typename InputStructure1, typename InputStructure2, typename OutputStorage, typename MaskStorage, - typename OutputView, typename MaskView, - typename Coords > - RC eWiseAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & z, - const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense, Coords > & m, + typename OutputView, typename MaskView > + RC eWiseAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > & z, + const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense > & m, const Scalar< InputType1, InputStructure1, reference_dense > &alpha, const Scalar< InputType2, InputStructure2, reference_dense > &beta, const Ring & ring = Ring(), @@ -2714,12 +2678,11 @@ namespace grb { typename OutputType, typename InputType1, typename InputType2, typename InputType3, typename OutputStructure, typename InputStructure1, typename InputStructure2, typename InputStructure3, typename OutputStorage, typename InputStorage2, typename InputStorage3, - typename OutputView, typename InputView2, typename InputView3, - typename Coords > - RC eWiseMulAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & _z, + typename OutputView, typename InputView2, typename InputView3 > + RC eWiseMulAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > & _z, const Scalar< InputType1, InputStructure1, reference_dense > &alpha, - const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense, Coords > & _x, - const VectorView< InputType3, InputStructure3, InputStorage3, InputView3, reference_dense, Coords > & _y, + const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > & _x, + const VectorView< InputType3, InputStructure3, InputStorage3, InputView3, reference_dense > & _y, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && grb::is_semiring< Ring >::value, @@ -2751,12 +2714,11 @@ namespace grb { typename OutputType, typename InputType1, typename InputType2, typename InputType3, typename OutputStructure, typename InputStructure1, typename InputStructure2, typename InputStructure3, typename OutputStorage, typename InputStorage1, typename InputStorage3, - typename OutputView, typename InputView1, typename InputView3, - typename Coords > - RC eWiseMulAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & _z, - const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense, Coords > & _a, + typename OutputView, typename InputView1, typename InputView3 > + RC eWiseMulAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > & _z, + const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense > & _a, const Scalar< InputType2, InputStructure2, reference_dense> &chi, - const VectorView< InputType3, InputStructure3, InputStorage3, InputView3, reference_dense, Coords > & _y, + const VectorView< InputType3, InputStructure3, InputStorage3, InputView3, reference_dense > & _y, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && grb::is_semiring< Ring >::value, @@ -2787,11 +2749,10 @@ namespace grb { typename OutputType, typename InputType1, typename InputType2, typename InputType3, typename OutputStructure, typename InputStructure1, typename InputStructure2, typename InputStructure3, typename OutputStorage, typename InputStorage1, typename InputStorage2, - typename OutputView, typename InputView1, typename InputView2, - typename Coords > - RC eWiseMulAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & _z, - const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense, Coords > & _a, - const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense, Coords > & _x, + typename OutputView, typename InputView1, typename InputView2 > + RC eWiseMulAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > & _z, + const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense > & _a, + const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > & _x, const Scalar< InputType3, InputStructure3, reference_dense > &gamma, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && @@ -2823,10 +2784,9 @@ namespace grb { typename OutputType, typename InputType1, typename InputType2, typename InputType3, typename OutputStructure, typename InputStructure1, typename InputStructure2, typename InputStructure3, typename OutputStorage, typename InputStorage1, - typename OutputView, typename InputView1, - typename Coords > - RC eWiseMulAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & _z, - const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense, Coords > & _a, + typename OutputView, typename InputView1 > + RC eWiseMulAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > & _z, + const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense > & _a, const Scalar< InputType2, InputStructure2, reference_dense> &beta, const Scalar< InputType3, InputStructure3, reference_dense> &gamma, const Ring & ring = Ring(), @@ -2859,11 +2819,10 @@ namespace grb { typename OutputType, typename InputType1, typename InputType2, typename InputType3, typename OutputStructure, typename InputStructure1, typename InputStructure2, typename InputStructure3, typename OutputStorage, typename InputStorage2, - typename OutputView, typename InputView2, - typename Coords > - RC eWiseMulAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & _z, + typename OutputView, typename InputView2 > + RC eWiseMulAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > & _z, const Scalar< InputType1, InputStructure1, reference_dense > &alpha, - const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense, Coords > & _x, + const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > & _x, const Scalar< InputType3, InputStructure3, reference_dense > &gamma, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && @@ -2897,12 +2856,11 @@ namespace grb { typename OutputType, typename InputType1, typename InputType2, typename InputType3, typename OutputStructure, typename InputStructure1, typename InputStructure2, typename InputStructure3, typename OutputStorage, typename InputStorage3, - typename OutputView, typename InputView3, - typename Coords > - RC eWiseMulAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & z, + typename OutputView, typename InputView3 > + RC eWiseMulAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > & z, const Scalar< InputType1, InputStructure1, reference_dense> &alpha, const Scalar< InputType2, InputStructure2, reference_dense> &beta, - const VectorView< InputType3, InputStructure3, InputStorage3, InputView3, reference_dense, Coords > & y, + const VectorView< InputType3, InputStructure3, InputStorage3, InputView3, reference_dense > & y, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && grb::is_semiring< Ring >::value, @@ -2939,9 +2897,8 @@ namespace grb { typename OutputType, typename InputType1, typename InputType2, typename InputType3, typename OutputStructure, typename InputStructure1, typename InputStructure2, typename InputStructure3, typename OutputStorage, - typename OutputView, - typename Coords > - RC eWiseMulAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & z, + typename OutputView > + RC eWiseMulAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > & z, const Scalar< InputType1, InputStructure1, reference_dense> &alpha, const Scalar< InputType2, InputStructure2, reference_dense> &beta, const Scalar< InputType3, InputStructure3, reference_dense> &gamma, @@ -3090,12 +3047,11 @@ namespace grb { typename OutputType, typename InputType1, typename InputType2, typename InputType3, typename OutputStructure, typename InputStructure1, typename InputStructure2, typename InputStructure3, typename OutputStorage, typename InputStorage1, typename InputStorage2, typename InputStorage3, - typename OutputView, typename InputView1, typename InputView2, typename InputView3, - typename Coords > - RC eWiseMulAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & _z, - const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense, Coords > & _a, - const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense, Coords > & _x, - const VectorView< InputType3, InputStructure3, InputStorage3, InputView3, reference_dense, Coords > & _y, + typename OutputView, typename InputView1, typename InputView2, typename InputView3 > + RC eWiseMulAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > & _z, + const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense > & _a, + const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > & _x, + const VectorView< InputType3, InputStructure3, InputStorage3, InputView3, reference_dense > & _y, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && grb::is_semiring< Ring >::value, @@ -3213,11 +3169,10 @@ namespace grb { typename OutputType, typename InputType1, typename InputType2, typename OutputStructure, typename InputStructure1, typename InputStructure2, typename OutputStorage, typename InputStorage1, typename InputStorage2, - typename OutputView, typename InputView1, typename InputView2, - typename Coords > - RC eWiseMul( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & z, - const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense, Coords > & x, - const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense, Coords > & y, + typename OutputView, typename InputView1, typename InputView2 > + RC eWiseMul( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > & z, + const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense > & x, + const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > & y, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_semiring< Ring >::value, void >::type * const = NULL ) { @@ -3246,11 +3201,10 @@ namespace grb { typename OutputType, typename InputType1, typename InputType2, typename OutputStructure, typename InputStructure1, typename InputStructure2, typename OutputStorage, typename InputStorage2, - typename OutputView, typename InputView2, - typename Coords > - RC eWiseMul( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & z, + typename OutputView, typename InputView2 > + RC eWiseMul( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > & z, const Scalar< InputType1, InputStructure1, reference_dense > &alpha, - const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense, Coords > & y, + const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > & y, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_semiring< Ring >::value, void >::type * const = NULL ) { @@ -3279,10 +3233,9 @@ namespace grb { typename OutputType, typename InputType1, typename InputType2, typename OutputStructure, typename InputStructure1, typename InputStructure2, typename OutputStorage, typename InputStorage1, - typename OutputView, typename InputView1, - typename Coords > - RC eWiseMul( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & z, - const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense, Coords > & x, + typename OutputView, typename InputView1 > + RC eWiseMul( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > & z, + const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense > & x, const Scalar< InputType2, InputStructure2, reference_dense > &beta, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_semiring< Ring >::value, @@ -3312,13 +3265,12 @@ namespace grb { typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename InputType3, typename OutputStructure, typename MaskStructure, typename InputStructure1, typename InputStructure2, typename InputStructure3, typename OutputStorage, typename MaskStorage, typename InputStorage2, typename InputStorage3, - typename OutputView, typename MaskView, typename InputView2, typename InputView3, - typename Coords > - RC eWiseMulAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & _z, - const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense, Coords > & _m, + typename OutputView, typename MaskView, typename InputView2, typename InputView3 > + RC eWiseMulAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > & _z, + const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense > & _m, const Scalar< InputType1, InputStructure1, reference_dense > &alpha, - const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense, Coords > & _x, - const VectorView< InputType3, InputStructure3, InputStorage3, InputView3, reference_dense, Coords > & _y, + const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > & _x, + const VectorView< InputType3, InputStructure3, InputStorage3, InputView3, reference_dense > & _y, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && grb::is_semiring< Ring >::value && ! grb::is_object< MaskType >::value, @@ -3351,13 +3303,12 @@ namespace grb { typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename InputType3, typename OutputStructure, typename MaskStructure, typename InputStructure1, typename InputStructure2, typename InputStructure3, typename OutputStorage, typename MaskStorage, typename InputStorage1, typename InputStorage3, - typename OutputView, typename MaskView, typename InputView1, typename InputView3, - typename Coords > - RC eWiseMulAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & _z, - const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense, Coords > & _m, - const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense, Coords > & _a, + typename OutputView, typename MaskView, typename InputView1, typename InputView3 > + RC eWiseMulAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > & _z, + const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense > & _m, + const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense > & _a, const Scalar< InputType2, InputStructure2, reference_dense> &chi, - const VectorView< InputType3, InputStructure3, InputStorage3, InputView3, reference_dense, Coords > & _y, + const VectorView< InputType3, InputStructure3, InputStorage3, InputView3, reference_dense > & _y, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && grb::is_semiring< Ring >::value && ! grb::is_object< MaskType >::value, @@ -3389,12 +3340,11 @@ namespace grb { typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename InputType3, typename OutputStructure, typename MaskStructure, typename InputStructure1, typename InputStructure2, typename InputStructure3, typename OutputStorage, typename MaskStorage, typename InputStorage1, typename InputStorage2, - typename OutputView, typename MaskView, typename InputView1, typename InputView2, - typename Coords > - RC eWiseMulAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & _z, - const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense, Coords > & _m, - const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense, Coords > & _a, - const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense, Coords > & _x, + typename OutputView, typename MaskView, typename InputView1, typename InputView2 > + RC eWiseMulAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > & _z, + const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense > & _m, + const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense > & _a, + const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > & _x, const Scalar< InputType3, InputStructure3, reference_dense > &gamma, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && @@ -3427,11 +3377,10 @@ namespace grb { typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename InputType3, typename OutputStructure, typename MaskStructure, typename InputStructure1, typename InputStructure2, typename InputStructure3, typename OutputStorage, typename MaskStorage, typename InputStorage1, - typename OutputView, typename MaskView, typename InputView1, - typename Coords > - RC eWiseMulAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & _z, - const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense, Coords > & _m, - const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense, Coords > & _a, + typename OutputView, typename MaskView, typename InputView1 > + RC eWiseMulAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > & _z, + const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense > & _m, + const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense > & _a, const Scalar< InputType2, InputStructure2, reference_dense> &beta, const Scalar< InputType3, InputStructure3, reference_dense> &gamma, const Ring & ring = Ring(), @@ -3465,12 +3414,11 @@ namespace grb { typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename InputType3, typename OutputStructure, typename MaskStructure, typename InputStructure1, typename InputStructure2, typename InputStructure3, typename OutputStorage, typename MaskStorage, typename InputStorage2, - typename OutputView, typename MaskView, typename InputView2, - typename Coords > - RC eWiseMulAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & _z, - const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense, Coords > & _m, + typename OutputView, typename MaskView, typename InputView2 > + RC eWiseMulAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > & _z, + const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense > & _m, const Scalar< InputType1, InputStructure1, reference_dense > &alpha, - const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense, Coords > & _x, + const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > & _x, const Scalar< InputType3, InputStructure3, reference_dense > &gamma, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && @@ -3503,13 +3451,12 @@ namespace grb { typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename InputType3, typename OutputStructure, typename MaskStructure, typename InputStructure1, typename InputStructure2, typename InputStructure3, typename OutputStorage, typename MaskStorage, typename InputStorage1, typename InputStorage2, typename InputStorage3, - typename OutputView, typename MaskView, typename InputView1, typename InputView2, typename InputView3, - typename Coords > - RC eWiseMulAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & _z, - const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense, Coords > & _m, - const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense, Coords > & _a, - const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense, Coords > & _x, - const VectorView< InputType3, InputStructure3, InputStorage3, InputView3, reference_dense, Coords > & _y, + typename OutputView, typename MaskView, typename InputView1, typename InputView2, typename InputView3 > + RC eWiseMulAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > & _z, + const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense > & _m, + const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense > & _a, + const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > & _x, + const VectorView< InputType3, InputStructure3, InputStorage3, InputView3, reference_dense > & _y, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && grb::is_semiring< Ring >::value && ! grb::is_object< MaskType >::value, @@ -3546,12 +3493,11 @@ namespace grb { typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename OutputStructure, typename MaskStructure, typename InputStructure1, typename InputStructure2, typename InputStructure3, typename OutputStorage, typename MaskStorage, typename InputStorage1, typename InputStorage2, typename InputStorage3, - typename OutputView, typename MaskView, typename InputView1, typename InputView2, typename InputView3, - typename Coords > - RC eWiseMul( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & z, - const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense, Coords > & m, - const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense, Coords > & x, - const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense, Coords > & y, + typename OutputView, typename MaskView, typename InputView1, typename InputView2, typename InputView3 > + RC eWiseMul( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > & z, + const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense > & m, + const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense > & x, + const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > & y, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< MaskType >::value && grb::is_semiring< Ring >::value, @@ -3584,12 +3530,11 @@ namespace grb { typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename OutputStructure, typename MaskStructure, typename InputStructure2, typename InputStructure3, typename OutputStorage, typename MaskStorage, typename InputStructure1, typename InputStorage2, typename InputStorage3, - typename OutputView, typename MaskView, typename InputView2, typename InputView3, - typename Coords > - RC eWiseMul( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & z, - const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense, Coords > & m, + typename OutputView, typename MaskView, typename InputView2, typename InputView3 > + RC eWiseMul( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > & z, + const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense > & m, const Scalar< InputType1, InputStructure1, reference_dense > &alpha, - const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense, Coords > & y, + const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > & y, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< MaskType >::value && grb::is_semiring< Ring >::value, @@ -3622,11 +3567,10 @@ namespace grb { typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename OutputStructure, typename MaskStructure, typename InputStructure1, typename InputStructure2, typename InputStructure3, typename OutputStorage, typename MaskStorage, typename InputStorage1, typename InputStorage3, - typename OutputView, typename MaskView, typename InputView1, typename InputView3, - typename Coords > - RC eWiseMul( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & z, - const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense, Coords > & m, - const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense, Coords > & x, + typename OutputView, typename MaskView, typename InputView1, typename InputView3 > + RC eWiseMul( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > & z, + const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense > & m, + const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense > & x, const Scalar< InputType2, InputStructure2, reference_dense > &beta, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< MaskType >::value && @@ -3660,13 +3604,12 @@ namespace grb { typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename InputType3, typename OutputStructure, typename MaskStructure, typename InputStructure1, typename InputStructure2, typename InputStructure3, typename OutputStorage, typename MaskStorage, typename InputStorage3, - typename OutputView, typename MaskView, typename InputView3, - typename Coords > - RC eWiseMulAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & z, - const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense, Coords > & m, + typename OutputView, typename MaskView, typename InputView3 > + RC eWiseMulAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > & z, + const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense > & m, const Scalar< InputType1, InputStructure1, reference_dense > &alpha, const Scalar< InputType2, InputStructure2, reference_dense > &beta, - const VectorView< InputType3, InputStructure3, InputStorage3, InputView3, reference_dense, Coords > & y, + const VectorView< InputType3, InputStructure3, InputStorage3, InputView3, reference_dense > & y, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && grb::is_semiring< Ring >::value && ! grb::is_object< MaskType >::value, @@ -3704,10 +3647,9 @@ namespace grb { typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename InputType3, typename OutputStructure, typename MaskStructure, typename InputStructure1, typename InputStructure2, typename InputStructure3, typename OutputStorage, typename MaskStorage, - typename OutputView, typename MaskView, - typename Coords > - RC eWiseMulAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense, Coords > & z, - const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense, Coords > & m, + typename OutputView, typename MaskView > + RC eWiseMulAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > & z, + const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense > & m, const Scalar< InputType1, InputStructure1, reference_dense> &alpha, const Scalar< InputType2, InputStructure2, reference_dense> &beta, const Scalar< InputType3, InputStructure3, reference_dense> &gamma, @@ -3752,12 +3694,10 @@ namespace grb { typename OutputType, typename InputType1, typename InputType2, typename OutputStructure, typename InputStructure1, typename InputStructure2, typename InputStorage1, typename InputStorage2, - typename InputView1, typename InputView2, - typename Coords - > + typename InputView1, typename InputView2 > RC dot_generic( Scalar< OutputType, OutputStructure, reference_dense > &z, - const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense, Coords > &x, - const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense, Coords > &y, + const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense > &x, + const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > &y, const AddMonoid &addMonoid = AddMonoid(), const AnyOp &anyOp = AnyOp() ) { @@ -3854,12 +3794,10 @@ namespace grb { typename OutputType, typename InputType1, typename InputType2, typename OutputStructure, typename InputStructure1, typename InputStructure2, typename InputStorage1, typename InputStorage2, - typename InputView1, typename InputView2, - typename Coords - > + typename InputView1, typename InputView2 > RC dot( Scalar< OutputType, OutputStructure, reference_dense > &z, - const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense, Coords > &x, - const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense, Coords > &y, + const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense > &x, + const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > &y, const AddMonoid &addMonoid = AddMonoid(), const AnyOp &anyOp = AnyOp(), const typename std::enable_if< !grb::is_object< OutputType >::value && @@ -3904,12 +3842,10 @@ namespace grb { typename OutputType, typename InputType1, typename InputType2, typename InputStructure1, typename InputStructure2, typename InputStorage1, typename InputStorage2, - typename InputView1, typename InputView2, - typename Coords - > + typename InputView1, typename InputView2 > RC dot( OutputType &z, - const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense, Coords > &x, - const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense, Coords > &y, + const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense > &x, + const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > &y, const AddMonoid &addMonoid = AddMonoid(), const AnyOp &anyOp = AnyOp(), const typename std::enable_if< !grb::is_object< OutputType >::value && @@ -3961,11 +3897,10 @@ namespace grb { typename IOStructure, typename InputStructure1, typename InputStructure2, typename InputStorage1, typename InputStorage2, typename InputView1, typename InputView2, - Backend backend, typename Coords1, typename Coords2 - > + Backend backend > RC dot( Scalar< IOType, IOStructure, backend > &x, - const VectorView< InputType1, InputStructure1, InputView1, InputStorage1, backend, Coords1 > &left, - const VectorView< InputType2, InputStructure2, InputView2, InputStorage2, backend, Coords2 > &right, + const VectorView< InputType1, InputStructure1, InputView1, InputStorage1, backend > &left, + const VectorView< InputType2, InputStructure2, InputView2, InputStorage2, backend > &right, const Ring &ring = Ring(), const typename std::enable_if< !grb::is_object< InputType1 >::value && @@ -3989,11 +3924,10 @@ namespace grb { typename InputStructure1, typename InputStructure2, typename InputStorage1, typename InputStorage2, typename InputView1, typename InputView2, - Backend backend, typename Coords1, typename Coords2 - > + Backend backend > RC dot( IOType &x, - const VectorView< InputType1, InputStructure1, InputView1, InputStorage1, backend, Coords1 > &left, - const VectorView< InputType2, InputStructure2, InputView2, InputStorage2, backend, Coords2 > &right, + const VectorView< InputType1, InputStructure1, InputView1, InputStorage1, backend > &left, + const VectorView< InputType2, InputStructure2, InputView2, InputStorage2, backend > &right, const Ring &ring = Ring(), const typename std::enable_if< !grb::is_object< InputType1 >::value && @@ -4016,8 +3950,8 @@ namespace grb { } /** No implementation notes. */ - template< typename Func, typename DataType, typename DataStructure, typename DataStorage, typename DataView, typename Coords > - RC eWiseMap( const Func f, VectorView< DataType, DataStructure, DataStorage, DataView, reference_dense, Coords > & x ) { + template< typename Func, typename DataType, typename DataStructure, typename DataStorage, typename DataView > + RC eWiseMap( const Func f, VectorView< DataType, DataStructure, DataStorage, DataView, reference_dense > & x ) { throw std::runtime_error( "Needs an implementation." ); return SUCCESS; } @@ -4036,10 +3970,10 @@ namespace grb { typename DataStructure1, typename DataStructure2, typename DataStorage1, typename DataStorage2, typename DataView1, typename DataView2, - typename Coords, typename... Args > + typename... Args > RC eWiseLambda( const Func f, - const VectorView< DataType1, DataStructure1, DataStorage1, DataView1, reference_dense, Coords > & x, - const VectorView< DataType2, DataStructure2, DataStorage2, DataView2, reference_dense, Coords > & y, + const VectorView< DataType1, DataStructure1, DataStorage1, DataView1, reference_dense > & x, + const VectorView< DataType2, DataStructure2, DataStorage2, DataView2, reference_dense > & y, Args const &... args ) { // catch mismatch if( size( x ) != size( y ) ) { @@ -4056,8 +3990,8 @@ namespace grb { * @see VectorView::operator[]() * @see VectorView::lambda_reference */ - template< typename Func, typename DataType, typename DataStructure, typename DataStorage, typename DataView, typename Coords > - RC eWiseLambda( const Func f, const VectorView< DataType, DataStructure, DataStorage, DataView, reference_dense, Coords > & x ) { + template< typename Func, typename DataType, typename DataStructure, typename DataStorage, typename DataView > + RC eWiseLambda( const Func f, const VectorView< DataType, DataStructure, DataStorage, DataView, reference_dense > & x ) { #ifdef _DEBUG std::cout << "Info: entering eWiseLambda function on vectors.\n"; #endif @@ -4150,11 +4084,10 @@ namespace grb { typename InputType, typename IOType, typename MaskType, typename IOStructure, typename InputStructure, typename MaskStructure, typename InputStorage, typename MaskStorage, - typename InputView, typename MaskView, - typename Coords > + typename InputView, typename MaskView > RC foldl( Scalar< IOType, IOStructure, reference_dense > &x, - const VectorView< InputType, InputStructure, InputStorage, InputView, reference_dense, Coords > & y, - const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense, Coords > & mask, + const VectorView< InputType, InputStructure, InputStorage, InputView, reference_dense > & y, + const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense > & mask, const Monoid & monoid = Monoid(), const typename std::enable_if< ! grb::is_object< IOType >::value && ! grb::is_object< InputType >::value && ! grb::is_object< MaskType >::value && grb::is_monoid< Monoid >::value, void >::type * const = NULL ) { @@ -4209,10 +4142,9 @@ namespace grb { typename OutputStructure, typename InputStructure, typename InputStorage, typename InputView, - Backend backend, typename Coords - > - RC norm2( Scalar< OutputType, OutputStructure, reference_dense > &x, - const VectorView< InputType, InputStructure, InputStorage, InputView, backend, Coords > &y, + Backend backend > + RC norm2( Scalar< OutputType, OutputStructure, backend > &x, + const VectorView< InputType, InputStructure, InputStorage, InputView, backend > &y, const Ring &ring = Ring(), const typename std::enable_if< std::is_floating_point< OutputType >::value, @@ -4232,10 +4164,9 @@ namespace grb { typename InputStructure, typename InputStorage, typename InputView, - Backend backend, typename Coords - > + Backend backend > RC norm2( OutputType &x, - const VectorView< InputType, InputStructure, InputStorage, InputView, backend, Coords > &y, + const VectorView< InputType, InputStructure, InputStorage, InputView, backend > &y, const Ring &ring = Ring(), const typename std::enable_if< std::is_floating_point< OutputType >::value, diff --git a/include/graphblas/denseref/blas2.hpp b/include/graphblas/denseref/blas2.hpp index 425a68f66..7ee8bdfee 100644 --- a/include/graphblas/denseref/blas2.hpp +++ b/include/graphblas/denseref/blas2.hpp @@ -138,15 +138,14 @@ namespace grb { typename IOType, typename IOView, typename IOStorage, typename InputType1, typename InputType1, typename InputView1, typename InputStorage1, typename InputType2, typename InputStructure2, typename InputStorage2, typename InputView2, - typename InputType3, typename InputType3, typename InputView3, typename InputStorage3, - typename Coords > - RC vxm( VectorView< IOType, IOStructure, IOStorage, IOView, reference_dense, Coords > & u, - const VectorView< InputType3, InputStructure3, InputStorage3, InputView3, reference_dense, Coords > & mask, - const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense, Coords > & v, + typename InputType3, typename InputType3, typename InputView3, typename InputStorage3 > + RC vxm( VectorView< IOType, IOStructure, IOStorage, IOView, reference_dense > & u, + const VectorView< InputType3, InputStructure3, InputStorage3, InputView3, reference_dense > & mask, + const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense > & v, const StructuredMatrix< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > & A, const Ring & ring = Ring(), const typename std::enable_if< grb::is_semiring< Ring >::value, void >::type * const = NULL ) { - const VectorView< bool, reference, Coords > empty_mask( 0 ); + const VectorView< bool, reference, internal::DefaultCoordinates > empty_mask( 0 ); return vxm< descr, true, false >( u, mask, v, empty_mask, A, ring ); } @@ -157,18 +156,17 @@ namespace grb { typename IOType, typename IOView, typename IOStorage, typename InputType1, typename InputView1, typename InputStorage1, typename InputType2, typename InputStructure2, typename InputStorage2, typename InputView2, - typename InputType3, typename InputView3, typename InputStorage3, - typename Coords > - RC vxm( VectorView< IOType, IOStructure, IOStorage, IOView, reference_dense, Coords > & u, - const VectorView< InputType3, InputStructure3, InputStorage3, InputView3, reference_dense, Coords > & mask, - const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense, Coords > & v, + typename InputType3, typename InputView3, typename InputStorage3 > + RC vxm( VectorView< IOType, IOStructure, IOStorage, IOView, reference_dense > & u, + const VectorView< InputType3, InputStructure3, InputStorage3, InputView3, reference_dense > & mask, + const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense > & v, const StructuredMatrix< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > & A, const AdditiveMonoid & add = AdditiveMonoid(), const MultiplicativeOperator & mul = MultiplicativeOperator(), const typename std::enable_if< grb::is_monoid< AdditiveMonoid >::value && grb::is_operator< MultiplicativeOperator >::value && ! grb::is_object< IOType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && ! std::is_same< InputType2, void >::value, void >::type * const = NULL ) { - const grb::VectorView< bool, reference, Coords > empty_mask( 0 ); + const grb::VectorView< bool, reference, internal::DefaultCoordinates > empty_mask( 0 ); return vxm< descr, true, false >( u, mask, v, empty_mask, A, add, mul ); } @@ -181,12 +179,11 @@ namespace grb { typename InputType1, typename InputView1, typename InputStorage1, typename InputType2, typename InputStructure2, typename InputStorage2, typename InputView2, typename InputType3, typename InputView3, typename InputStorage3, - typename InputType4, typename InputView4, typename InputStorage4, - typename Coords > - RC vxm( VectorView< IOType, IOStructure, IOStorage, IOView, reference_dense, Coords > & u, - const VectorView< InputType3, InputStructure3, InputStorage3, InputView3, reference_dense, Coords > & mask, - const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense, Coords > & v, - const VectorView< InputType4, InputStructure4, InputStorage4, InputView4, reference_dense, Coords > & v_mask, + typename InputType4, typename InputView4, typename InputStorage4 > + RC vxm( VectorView< IOType, IOStructure, IOStorage, IOView, reference_dense > & u, + const VectorView< InputType3, InputStructure3, InputStorage3, InputView3, reference_dense > & mask, + const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense > & v, + const VectorView< InputType4, InputStructure4, InputStorage4, InputView4, reference_dense > & v_mask, const StructuredMatrix< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > & A, const Ring & ring = Ring(), const typename std::enable_if< grb::is_semiring< Ring >::value, void >::type * const = NULL ) { @@ -199,28 +196,27 @@ namespace grb { class Ring, typename IOType = typename Ring::D4, typename IOView, typename IOStorage, typename InputType1 = typename Ring::D1, typename InputView1, typename InputStorage1, - typename InputType2 = typename Ring::D2, typename InputStructure2, typename InputStorage2, typename InputView2, - typename Coords > - RC vxm( VectorView< IOType, IOStructure, IOStorage, IOView, reference_dense, Coords > & u, - const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense, Coords > & v, + typename InputType2 = typename Ring::D2, typename InputStructure2, typename InputStorage2, typename InputView2 > + RC vxm( VectorView< IOType, IOStructure, IOStorage, IOView, reference_dense > & u, + const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense > & v, const StructuredMatrix< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > & A, const Ring & ring = Ring(), const typename std::enable_if< grb::is_semiring< Ring >::value, void >::type * const = NULL ) { - const VectorView< bool, reference_dense, Coords > empty_mask( 0 ); + const VectorView< bool, reference_dense, internal::DefaultCoordinates > empty_mask( 0 ); return vxm< descr, false, false >( u, empty_mask, v, empty_mask, A, ring ); } /** \internal Delegates to fully masked version */ - template< Descriptor descr = descriptors::no_operation, class AdditiveMonoid, class MultiplicativeOperator, typename IOType, typename InputType1, typename InputType2, typename Coords > - RC vxm( VectorView< IOType, IOStructure, IOStorage, IOView, reference_dense, Coords > & u, - const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense, Coords > & v, + template< Descriptor descr = descriptors::no_operation, class AdditiveMonoid, class MultiplicativeOperator, typename IOType, typename InputType1, typename InputType2 > + RC vxm( VectorView< IOType, IOStructure, IOStorage, IOView, reference_dense > & u, + const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense > & v, const StructuredMatrix< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > & A, const AdditiveMonoid & add = AdditiveMonoid(), const MultiplicativeOperator & mul = MultiplicativeOperator(), const typename std::enable_if< grb::is_monoid< AdditiveMonoid >::value && grb::is_operator< MultiplicativeOperator >::value && ! grb::is_object< IOType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! std::is_same< InputType2, void >::value, void >::type * const = NULL ) { - const grb::VectorView< bool, reference_dense, Coords > empty_mask( 0 ); + const grb::VectorView< bool, reference_dense, internal::DefaultCoordinates > empty_mask( 0 ); return vxm< descr, false, false >( u, empty_mask, v, empty_mask, A, add, mul ); } @@ -230,15 +226,14 @@ namespace grb { typename IOType, typename IOView, typename IOStorage, typename InputType1, typename InputView1, typename InputStorage1, typename InputType2, typename InputStructure2, typename InputStorage2, typename InputView2, - typename InputType3 = bool, typename InputView3, typename InputStorage3, - typename Coords > - RC mxv( VectorView< IOType, IOStructure, IOStorage, IOView, reference_dense, Coords > & u, - const VectorView< InputType3, InputStructure3, InputStorage3, InputView3, reference_dense, Coords > & mask, + typename InputType3 = bool, typename InputView3, typename InputStorage3 > + RC mxv( VectorView< IOType, IOStructure, IOStorage, IOView, reference_dense > & u, + const VectorView< InputType3, InputStructure3, InputStorage3, InputView3, reference_dense > & mask, const StructuredMatrix< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > & A, - const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense, Coords > & v, + const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense > & v, const Ring & ring, const typename std::enable_if< grb::is_semiring< Ring >::value, void >::type * const = NULL ) { - const VectorView< bool, reference_dense, Coords > empty_mask( 0 ); + const VectorView< bool, reference_dense, internal::DefaultCoordinates > empty_mask( 0 ); return mxv< descr, true, false >( u, mask, A, v, empty_mask, ring ); } @@ -251,13 +246,12 @@ namespace grb { typename InputType1, typename InputView1, typename InputStorage1, typename InputType2, typename InputStructure2, typename InputStorage2, typename InputView2, typename InputType3, typename InputView3, typename InputStorage3, - typename InputType4, typename InputView4, typename InputStorage4, - typename Coords > - RC mxv( VectorView< IOType, IOStructure, IOStorage, IOView, reference_dense, Coords > & u, - const VectorView< InputType3, InputStructure3, InputStorage3, InputView3, reference_dense, Coords > & mask, + typename InputType4, typename InputView4, typename InputStorage4 > + RC mxv( VectorView< IOType, IOStructure, IOStorage, IOView, reference_dense > & u, + const VectorView< InputType3, InputStructure3, InputStorage3, InputView3, reference_dense > & mask, const StructuredMatrix< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > & A, - const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense, Coords > & v, - const VectorView< InputType4, InputStructure4, InputStorage4, InputView4, reference_dense, Coords > & v_mask, + const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense > & v, + const VectorView< InputType4, InputStructure4, InputStorage4, InputView4, reference_dense > & v_mask, const Ring & ring, const typename std::enable_if< grb::is_semiring< Ring >::value, void >::type * const = NULL ) { @@ -272,28 +266,27 @@ namespace grb { class Ring, typename IOType = typename Ring::D4, typename IOView, typename IOStorage, typename InputType1 = typename Ring::D1, typename InputStructure2, typename InputStorage2, typename InputView2, - typename InputType2 = typename Ring::D2, typename InputView1, typename InputStorage1, - typename Coords > - RC mxv( VectorView< IOType, IOStructure, IOStorage, IOView, reference_dense, Coords > & u, + typename InputType2 = typename Ring::D2, typename InputView1, typename InputStorage1 > + RC mxv( VectorView< IOType, IOStructure, IOStorage, IOView, reference_dense > & u, const StructuredMatrix< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > & A, - const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense, Coords > & v, + const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense > & v, const Ring & ring, const typename std::enable_if< grb::is_semiring< Ring >::value, void >::type * const = NULL ) { - const VectorView< bool, view::Original< void >, structure::full, reference_dense, Coords > empty_mask( 0 ); + const VectorView< bool, view::Original< void >, structure::full, reference_dense, internal::DefaultCoordinates > empty_mask( 0 ); return mxv< descr, false, false >( u, empty_mask, A, v, empty_mask, ring ); } /** \internal Delegates to fully masked version */ - template< Descriptor descr = descriptors::no_operation, class AdditiveMonoid, class MultiplicativeOperator, typename IOType, typename InputType1, typename InputType2, typename Coords > - RC mxv( VectorView< IOType, IOStructure, IOStorage, IOView, reference_dense, Coords > & u, + template< Descriptor descr = descriptors::no_operation, class AdditiveMonoid, class MultiplicativeOperator, typename IOType, typename InputType1, typename InputType2 > + RC mxv( VectorView< IOType, IOStructure, IOStorage, IOView, reference_dense > & u, const StructuredMatrix< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > & A, - const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense, Coords > & v, + const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense > & v, const AdditiveMonoid & add = AdditiveMonoid(), const MultiplicativeOperator & mul = MultiplicativeOperator(), const typename std::enable_if< grb::is_monoid< AdditiveMonoid >::value && grb::is_operator< MultiplicativeOperator >::value && ! grb::is_object< IOType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! std::is_same< InputType2, void >::value, void >::type * const = NULL ) { - const grb::VectorView< bool, view::Original< void >, structure::full, reference_dense, Coords > empty_mask( 0 ); + const grb::VectorView< bool, view::Original< void >, structure::full, reference_dense, internal::DefaultCoordinates > empty_mask( 0 ); return mxv< descr, false, false >( u, empty_mask, A, v, empty_mask, add, mul ); } @@ -309,12 +302,11 @@ namespace grb { typename InputType1, typename InputView1, typename InputStorage1, typename InputType2, typename InputStructure2, typename InputStorage2, typename InputView2, typename InputType3, typename InputView3, typename InputStorage3, - typename InputType4, typename InputView4, typename InputStorage4, - typename Coords > - RC vxm( VectorView< IOType, IOStructure, IOStorage, IOView, reference_dense, Coords > & u, - const VectorView< InputType3, InputStructure3, InputStorage3, InputView3, reference_dense, Coords > & mask, - const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense, Coords > & v, - const VectorView< InputType4, InputStructure4, InputStorage4, InputView4, reference_dense, Coords > & v_mask, + typename InputType4, typename InputView4, typename InputStorage4 > + RC vxm( VectorView< IOType, IOStructure, IOStorage, IOView, reference_dense > & u, + const VectorView< InputType3, InputStructure3, InputStorage3, InputView3, reference_dense > & mask, + const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense > & v, + const VectorView< InputType4, InputStructure4, InputStorage4, InputView4, reference_dense > & v_mask, const StructuredMatrix< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > & A, const AdditiveMonoid & add = AdditiveMonoid(), const MultiplicativeOperator & mul = MultiplicativeOperator(), @@ -339,13 +331,12 @@ namespace grb { typename InputType1, typename InputView1, typename InputStorage1, typename InputType2, typename InputStructure2, typename InputStorage2, typename InputView2, typename InputType3, typename InputView3, typename InputStorage3, - typename InputType4, typename InputView4, typename InputStorage4, - typename Coords > - RC mxv( VectorView< IOType, IOStructure, reference_dense, Coords > & u, - const VectorView< InputType3, InputStructure3, reference_dense, Coords > & mask, + typename InputType4, typename InputView4, typename InputStorage4 > + RC mxv( VectorView< IOType, IOStructure, reference_dense > & u, + const VectorView< InputType3, InputStructure3, reference_dense > & mask, const StructuredMatrix< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > & A, - const VectorView< InputType1, InputStructure1, reference_dense, Coords > & v, - const VectorView< InputType4, InputStructure4, reference_dense, Coords > & v_mask, + const VectorView< InputType1, InputStructure1, reference_dense > & v, + const VectorView< InputType4, InputStructure4, reference_dense > & v_mask, const AdditiveMonoid & add = AdditiveMonoid(), const MultiplicativeOperator & mul = MultiplicativeOperator(), const typename std::enable_if< grb::is_monoid< AdditiveMonoid >::value && grb::is_operator< MultiplicativeOperator >::value && ! grb::is_object< IOType >::value && @@ -382,10 +373,10 @@ namespace grb { */ template< typename Func, typename DataType1, typename Structure1, typename Storage1, typename View1, - typename DataType2, typename View2, typename Storage2, typename Coords, typename... Args > + typename DataType2, typename View2, typename Storage2, typename... Args > RC eWiseLambda( const Func f, const StructuredMatrix< DataType1, Structure1, Storage1, View1, reference_dense > & A, - const VectorView< DataType2, DataStructure2, Storage2, View2, reference_dense, Coords > x, Args... args ) { + const VectorView< DataType2, DataStructure2, Storage2, View2, reference_dense > x, Args... args ) { // do size checking if( ! ( size( x ) == nrows( A ) || size( x ) == ncols( A ) ) ) { std::cerr << "Mismatching dimensions: given vector of size " << size( x ) << " has nothing to do with either matrix dimension (" << nrows( A ) << " nor " << ncols( A ) << ").\n"; diff --git a/include/graphblas/denseref/blas3.hpp b/include/graphblas/denseref/blas3.hpp index 2ec5fdec2..2e55cfcbe 100644 --- a/include/graphblas/denseref/blas3.hpp +++ b/include/graphblas/denseref/blas3.hpp @@ -769,11 +769,10 @@ namespace grb { typename OutputType, typename InputType1, typename InputType2, typename OutputStructure, typename InputStructure1, typename InputStructure2, typename OutputStorage, typename InputStorage1, typename InputStorage2, - typename OutputView, typename InputView1, typename InputView2, - typename InputCoords1, typename InputCoords2, class Operator > + typename OutputView, typename InputView1, typename InputView2, class Operator > RC outer( StructuredMatrix< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > & A, - const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense, InputCoords1 > & u, - const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense, InputCoords2 > & v, + const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense > & u, + const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > & v, const Operator & mul = Operator(), const typename std::enable_if< grb::is_operator< Operator >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< OutputType >::value, void >::type * const = NULL ) { diff --git a/include/graphblas/denseref/vector.hpp b/include/graphblas/denseref/vector.hpp index 9a4b9e6db..7e01aa3cf 100644 --- a/include/graphblas/denseref/vector.hpp +++ b/include/graphblas/denseref/vector.hpp @@ -313,19 +313,19 @@ namespace grb { * Here starts spec draft for vectorView */ - template< typename T, typename Structure, typename View, typename C > - size_t getLength( const VectorView< T, Structure, storage::Dense, View, reference_dense, C > &v ) noexcept { + template< typename T, typename Structure, typename View > + size_t getLength( const VectorView< T, Structure, storage::Dense, View, reference_dense > &v ) noexcept { return v._length(); } namespace internal { - template< typename T, typename Structure, typename View, typename C > - bool getInitialized( VectorView< T, Structure, storage::Dense, View, reference_dense, C > & v ) noexcept { + template< typename T, typename Structure, typename View > + bool getInitialized( VectorView< T, Structure, storage::Dense, View, reference_dense > & v ) noexcept { return getInitialized( v ); } - template< typename T, typename Structure, typename View, typename C > - void setInitialized( VectorView< T, Structure, storage::Dense, View, reference_dense, C > & v, bool initialized ) noexcept { + template< typename T, typename Structure, typename View > + void setInitialized( VectorView< T, Structure, storage::Dense, View, reference_dense > & v, bool initialized ) noexcept { setInitialized( v, initialized ); } } // end namespace ``grb::internal'' @@ -344,7 +344,7 @@ namespace grb { * Views can be used to create logical \em perspectives on top of a container. * For example, one may decide to refer to the part of the vector or * to reference a diagonal of a matrix as a vector. - * See specialization \a VectorView< T, Structure, storage::Dense, view::Diagonal< StructuredMatrixT >, reference_dense, C > + * See specialization \a VectorView< T, Structure, storage::Dense, view::Diagonal< StructuredMatrixT >, reference_dense > * as an example of such usage. * * Vector View defined as views on other vectors do not instantiate a @@ -374,17 +374,17 @@ namespace grb { * defined within their specified \a StorageSchemeType. * */ - template< typename T, typename Structure, typename View, typename C > - class VectorView< T, Structure, storage::Dense, View, reference_dense, C > { }; + template< typename T, typename Structure, typename View > + class VectorView< T, Structure, storage::Dense, View, reference_dense > { }; /** * Original View over a vector container. */ - template< typename T, typename Structure, typename C > - class VectorView< T, Structure, storage::Dense, view::Original< void >, reference_dense, C > { + template< typename T, typename Structure > + class VectorView< T, Structure, storage::Dense, view::Original< void >, reference_dense > { private: - using self_type = VectorView< T, Structure, storage::Dense, view::Original< void >, reference_dense, C >; + using self_type = VectorView< T, Structure, storage::Dense, view::Original< void >, reference_dense >; /********************* Storage info friends @@ -393,7 +393,7 @@ namespace grb { friend size_t getLength<>( const self_type & ) noexcept; // Physical layout - std::unique_ptr< Vector< T, reference_dense, C > > v; + std::unique_ptr< Vector< T, reference_dense, internal::DefaultCoordinates > > v; std::shared_ptr imf; @@ -406,13 +406,15 @@ namespace grb { /** @see Vector::value_type. */ using value_type = T; - VectorView( const size_t length, const size_t cap = 0 ) : v( std::make_unique< Vector< T, reference_dense, C > >( length, cap ) ), imf( std::make_shared< imf::Id >( length ) ) {} + VectorView( const size_t length, const size_t cap = 0 ) : + v( std::make_unique< Vector< T, reference_dense, internal::DefaultCoordinates > >( length, cap ) ), + imf( std::make_shared< imf::Id >( length ) ) {} }; // class VectorView with physical container /** Identifies any reference_dense vector as an ALP vector. */ - template< typename T, typename Structure, typename Storage, typename View, typename C > - struct is_container< VectorView< T, Structure, Storage, View, reference_dense, C > > { + template< typename T, typename Structure, typename Storage, typename View > + struct is_container< VectorView< T, Structure, Storage, View, reference_dense > > { /** A reference_vector is an ALP object. */ static const constexpr bool value = true; }; @@ -420,11 +422,11 @@ namespace grb { /** * Vector view of a vector only via \a view::Original of another VectorView. */ - template< typename T, typename Structure, typename VectorViewT, typename C > - class VectorView< T, Structure, storage::Dense, view::Original< VectorViewT >, reference_dense, C > { + template< typename T, typename Structure, typename VectorViewT > + class VectorView< T, Structure, storage::Dense, view::Original< VectorViewT >, reference_dense > { private: - using self_type = VectorView< T, Structure, storage::Dense, view::Original< VectorViewT >, reference_dense, C >; + using self_type = VectorView< T, Structure, storage::Dense, view::Original< VectorViewT >, reference_dense >; using target_type = VectorViewT; /********************* @@ -468,13 +470,13 @@ namespace grb { /** * Diagonal Vector View of a structured matrix. */ - template< typename T, typename Structure, typename StructuredMatrixT, typename C > - class VectorView< T, Structure, storage::Dense, view::Diagonal< StructuredMatrixT >, reference_dense, C > { + template< typename T, typename Structure, typename StructuredMatrixT > + class VectorView< T, Structure, storage::Dense, view::Diagonal< StructuredMatrixT >, reference_dense > { private: /** Exposes the own type and the type of the VectorView object over * which this view is created. */ - using self_type = VectorView< T, Structure, storage::Dense, view::Diagonal< StructuredMatrixT >, reference_dense, C >; + using self_type = VectorView< T, Structure, storage::Dense, view::Diagonal< StructuredMatrixT >, reference_dense >; using target_type = StructuredMatrixT; /********************* @@ -510,17 +512,16 @@ namespace grb { * * @paramt StructuredMatrixT Type of the StructuredMatrix over which the * view is created. - * @paramt C @see Coordinates * @param[in] smat StructuredMatrix object over which the view * is created. * * @returns A VectorView object. * */ - template< typename StructuredMatrixT, typename C = internal::DefaultCoordinates > - VectorView< typename StructuredMatrixT::value_type, typename StructuredMatrixT::structure, storage::Dense, view::Diagonal< StructuredMatrixT >, reference_dense, C > + template< typename StructuredMatrixT > + VectorView< typename StructuredMatrixT::value_type, typename StructuredMatrixT::structure, storage::Dense, view::Diagonal< StructuredMatrixT >, reference_dense > diagonal( StructuredMatrixT &smat ) { - VectorView< typename StructuredMatrixT::value_type, typename StructuredMatrixT::structure, storage::Dense, view::Diagonal< StructuredMatrixT >, reference_dense, C > smat_diag( smat ); + VectorView< typename StructuredMatrixT::value_type, typename StructuredMatrixT::structure, storage::Dense, view::Diagonal< StructuredMatrixT >, reference_dense > smat_diag( smat ); return smat_diag; } @@ -532,11 +533,11 @@ namespace grb { * * @returns A VectorView object. */ - template< typename T, typename Structure, typename View, typename StorageSchemeType, enum Backend backend, typename C = internal::DefaultCoordinates > - VectorView< T, Structure, StorageSchemeType, view::Original< VectorView< T, Structure, StorageSchemeType, View, backend, C > >, backend, C > - get_view( VectorView< T, Structure, View, StorageSchemeType, backend, C > &source ) { + template< typename T, typename Structure, typename View, typename StorageSchemeType, enum Backend backend > + VectorView< T, Structure, StorageSchemeType, view::Original< VectorView< T, Structure, StorageSchemeType, View, backend > >, backend > + get_view( VectorView< T, Structure, View, StorageSchemeType, backend > &source ) { - VectorView< T, Structure, StorageSchemeType, view::Original< VectorView< T, Structure, View, StorageSchemeType, backend, C > >, backend, C > vec_view( source ); + VectorView< T, Structure, StorageSchemeType, view::Original< VectorView< T, Structure, View, StorageSchemeType, backend > >, backend > vec_view( source ); return vec_view; } @@ -551,11 +552,11 @@ namespace grb { * @returns A VectorView object. */ - template< typename T, typename Structure, typename View, typename StorageSchemeType, enum Backend backend, typename C > - VectorView< T, Structure, StorageSchemeType, view::Original< VectorView< T, Structure, StorageSchemeType, View, backend, C > >, backend, C > - get_view( VectorView< T, Structure, StorageSchemeType, View, backend, C > &source, std::shared_ptr< imf::IMF > imf ) { + template< typename T, typename Structure, typename View, typename StorageSchemeType, enum Backend backend > + VectorView< T, Structure, StorageSchemeType, view::Original< VectorView< T, Structure, StorageSchemeType, View, backend > >, backend > + get_view( VectorView< T, Structure, StorageSchemeType, View, backend > &source, std::shared_ptr< imf::IMF > imf ) { - VectorView< T, Structure, StorageSchemeType, view::Original< VectorView< T, Structure, StorageSchemeType, View, backend, C > >, backend, C > vec_view( source, imf ); + VectorView< T, Structure, StorageSchemeType, view::Original< VectorView< T, Structure, StorageSchemeType, View, backend > >, backend > vec_view( source, imf ); return vec_view; } diff --git a/include/graphblas/vector.hpp b/include/graphblas/vector.hpp index f0c7ee493..b7962b9c7 100644 --- a/include/graphblas/vector.hpp +++ b/include/graphblas/vector.hpp @@ -57,7 +57,7 @@ namespace grb { /* * The default value of \a StorageSchemeType could also be made conditional (Dense or Sparse) depending on \a config::default_backend */ - template< typename T, typename Structure = structures::General, typename StorageSchemeType = storage::Dense, typename View = view::Original< void >, enum Backend backend = config::default_backend, typename C = internal::DefaultCoordinates > + template< typename T, typename Structure = structures::General, typename StorageSchemeType = storage::Dense, typename View = view::Original< void >, enum Backend backend = config::default_backend > class VectorView; } From 4e0baffbb3c658fab8ebeeaab763b7812885f1eb Mon Sep 17 00:00:00 2001 From: Anonymous Date: Thu, 24 Mar 2022 08:37:09 +0000 Subject: [PATCH 114/282] !24 Resolves internal issue #371: Introducing Union of Bands Structure * Using past-the-end notation for static grb::Interval * Indent comments from MR !24 * simple example of usage in test * Initial draft of Band structure --- include/graphblas/denseref/vector.hpp | 15 ++- include/graphblas/structures.hpp | 170 ++++++++++++++++++++++--- tests/unit/dense_structured_matrix.cpp | 4 + 3 files changed, 161 insertions(+), 28 deletions(-) diff --git a/include/graphblas/denseref/vector.hpp b/include/graphblas/denseref/vector.hpp index 7e01aa3cf..399a8e544 100644 --- a/include/graphblas/denseref/vector.hpp +++ b/include/graphblas/denseref/vector.hpp @@ -436,7 +436,8 @@ namespace grb { friend size_t getLength<>( const self_type & ) noexcept; /** Reference to a target vector to which this vector view points to */ - std::shared_ptr< target_type > ref; + // std::shared_ptr< target_type > ref; + target_type & ref; /** Index-mapping function. @see IMF */ std::shared_ptr imf; @@ -450,15 +451,15 @@ namespace grb { using value_type = T; /** Constructor for creating a view over a given target vector */ - VectorView( target_type & vec_view ) : ref( &vec_view ), imf( nullptr ) { + VectorView( target_type & vec_view ) : ref( vec_view ), imf( nullptr ) { - imf = std::make_shared< imf::Id >( getLength( *ref ) ); + imf = std::make_shared< imf::Id >( getLength( ref ) ); } /** Constructor for creating a view over a given target vector and * applying the given index mapping function */ - VectorView( target_type & vec_view, std::shared_ptr< imf::IMF > imf ) : ref( & vec_view ), imf( imf ) { + VectorView( target_type & vec_view, std::shared_ptr< imf::IMF > imf ) : ref( vec_view ), imf( imf ) { if( getLength( vec_view ) != imf->N ) { throw std::length_error( "VectorView(vec_view, * imf): IMF range differs from target's vector length." ); } @@ -486,7 +487,7 @@ namespace grb { friend size_t getLength<>( const self_type & ) noexcept; /** Pointer to a VectorView object upon which this view is created */ - std::shared_ptr< target_type > ref; + target_type & ref; /** @see IMF */ std::shared_ptr imf; @@ -499,9 +500,9 @@ namespace grb { /** Exposes the element type. */ using value_type = T; - VectorView( target_type & struct_mat ) : ref( &struct_mat ), imf( nullptr ) { + VectorView( target_type & struct_mat ) : ref( struct_mat ), imf( nullptr ) { - size_t _length = view::Diagonal< target_type >::getLength( dims( *ref ) ); + size_t _length = view::Diagonal< target_type >::getLength( dims( ref ) ); imf = std::make_shared< imf::Id >( _length ); } diff --git a/include/graphblas/structures.hpp b/include/graphblas/structures.hpp index 16c221f20..b09134a32 100644 --- a/include/graphblas/structures.hpp +++ b/include/graphblas/structures.hpp @@ -36,6 +36,61 @@ namespace grb { + /** + * @brief Compile-time interval [ _left, _right ) + * + * @tparam _left left boundary of the interval. + * @tparam _right right boundary of the interval. Optional, in which case + * _left == _right + */ + template + struct Interval { + + static_assert( _left < _right ); + + static constexpr int left = _left; + static constexpr int right = _right; + + }; + + /** + * @brief Compile-time interval [ -inf, _right ) + */ + template < int _right > + using LeftOpenInterval = Interval::min(), _right >; + + /** + * @brief Compile-time interval [ _left, +inf ] + */ + template + using RightOpenInterval = Interval< _left, std::numeric_limits::max() >; + + /** + * @brief Compile-time interval [ -inf, +inf ] + */ + typedef Interval::min(), std::numeric_limits::max() > OpenInterval; + + namespace internal { + /** + * @internal Compile-time check if a tuple of intervals is sorted and non-overlapping. + * E.g., a pair ( [a,b) [c, d) ) with a < b <= c < d + */ + template< typename IntervalTuple > + struct is_tuple_sorted_non_overlapping; + + template< int _left0, int _right0, int _left1, int _right1, typename... Intervals > + struct is_tuple_sorted_non_overlapping < std::tuple< Interval< _left0, _right0 >, Interval< _left1, _right1 >, Intervals... > > { + static constexpr bool value = ( _right0 <= _left1 ) && is_tuple_sorted_non_overlapping< std::tuple< Interval< _left1, _right1 >, Intervals... > >::value; + }; + + template< int _left, int _right > + struct is_tuple_sorted_non_overlapping < std::tuple< Interval< _left, _right > > > : std::true_type { }; + + template< > + struct is_tuple_sorted_non_overlapping < std::tuple< > > : std::true_type { }; + + } + /** * Collects all ALP matrix structures. * @@ -148,19 +203,80 @@ namespace grb { using inferred_structures = structures::tuple_cat< std::tuple< Square >, General::inferred_structures >::type; }; + /** + * @brief A Band is a structure described by a compile-time tuple of + * sorted, non-overlapping integer intervals which + * list the groups of contiguous non-zero diagonals of a + * matrix with this structure. + * Different intervals should be described considering the + * position of the main diagonal as 0 reference. This enables + * comparing intervals as well as sorting them. + * Subdiagonals have negative positions (the farer from the + * main diagonal the smaller the position) while superdiagonals + * have positive ones (the farer from the main diagonal the + * larger the position). + * E.g., Band< grb::Interval<-1, 2> > is a band + * structure that can be used to describe a tridiagonal matrix. + * + * \note grb::Interval uses a past-the-end + * notation for the intervals [a, b). @see grb::Interval. + * + * The first value of the left-most (second value of the right- + * most) interval in the sequence is the lower (upper, resp.) + * bandwidth (referred to as \a lb and \a ub) of the matrix. + * Such values may be open-ended if limited by the size of the + * matrix. If the lower bandwith is finite and negative than + * the number of rows + * \f$m \f$ at runtime must ensure \f$m > |lb| \f$. + * Similarly, if the upper bandwith is finite and positive + * than the number of columns + * \f$n \f$ at runtime must ensure \f$n >= ub \f$. + * The concept of Band< OpenInterval > is a very + * general notion of Band and may be used for inference purposes + * (e.g., checking if a matrix is a Band matrix irrespective + * of specific bands in the structure). + * + * @tparam Intervals One or more \a grb::Interval types specifying the + * bands of the structure. These intervals should be + * non-overlapping and sorted according to the above + * assumption that all intervals are defined assuming + * the main diagonal has position zero. + * \a grb::LeftOpenInterval ( \a grb::RightOpenInterval) + * can be used to indicate that the left bandwidth + * (right bandwidth, respectively) is defined by the + * size of the matrix at runtime. + * + */ + template < typename... Intervals > + struct Band { + + typedef std::tuple< Intervals... > band_intervals; + + static_assert( grb::internal::is_tuple_sorted_non_overlapping< band_intervals >::value ); + + typedef typename structures::tuple_cat< std::tuple< Band< Intervals... > >, General::inferred_structures >::type inferred_structures; + }; + struct Symmetric { using inferred_structures = structures::tuple_cat< std::tuple< Symmetric >, Square::inferred_structures >::type; }; struct Triangular { - using inferred_structures = structures::tuple_cat< std::tuple< Triangular >, Square::inferred_structures >::type; + + using inferred_structures = structures::tuple_cat< std::tuple< Triangular >, Square::inferred_structures, Band< OpenInterval >::inferred_structures >::type; }; struct LowerTriangular { + + typedef std::tuple< LeftOpenInterval< 0 > > band_intervals; + using inferred_structures = structures::tuple_cat< std::tuple< LowerTriangular >, Triangular::inferred_structures >::type; }; struct UpperTriangular { + + typedef std::tuple< RightOpenInterval< 0 > > band_intervals; + using inferred_structures = structures::tuple_cat< std::tuple< UpperTriangular >, Triangular::inferred_structures >::type; // Maybe we can consider inheritance here to allow calling checks in base classes. @@ -175,44 +291,56 @@ namespace grb { } }; - struct FullRank { - using inferred_structures = structures::tuple_cat< std::tuple< FullRank >, General::inferred_structures >::type; + struct Tridiagonal { + + typedef std::tuple< Interval< -1, 1 > > band_intervals; + + using inferred_structures = structures::tuple_cat< std::tuple< Tridiagonal >, Square::inferred_structures, Band< OpenInterval >::inferred_structures >::type; }; - struct NonSingular { - using inferred_structures = structures::tuple_cat< std::tuple< NonSingular >, Square::inferred_structures, FullRank::inferred_structures >::type; + struct Bidiagonal { + using inferred_structures = structures::tuple_cat< std::tuple< Bidiagonal >, Triangular::inferred_structures, Tridiagonal::inferred_structures >::type; }; - struct OrthogonalColumns { - using inferred_structures = structures::tuple_cat< std::tuple< OrthogonalColumns >, FullRank::inferred_structures >::type; + struct LowerBidiagonal { + + typedef std::tuple< Interval< -1, 0 > > band_intervals; + + using inferred_structures = structures::tuple_cat< std::tuple< LowerBidiagonal >, Bidiagonal::inferred_structures, LowerTriangular::inferred_structures >::type; }; - struct OrthogonalRows { - using inferred_structures = structures::tuple_cat< std::tuple< OrthogonalRows >, FullRank::inferred_structures >::type; + struct UpperBidiagonal { + + typedef std::tuple< Interval< 0, 1 > > band_intervals; + + using inferred_structures = structures::tuple_cat< std::tuple< UpperBidiagonal >, Bidiagonal::inferred_structures, UpperTriangular::inferred_structures >::type; }; - struct Orthogonal { - using inferred_structures = structures::tuple_cat< std::tuple< Orthogonal >, NonSingular::inferred_structures, OrthogonalColumns::inferred_structures, OrthogonalRows::inferred_structures >::type; + struct Diagonal { + + typedef std::tuple< Interval< 0 > > band_intervals; + + using inferred_structures = structures::tuple_cat< std::tuple< Diagonal >, LowerBidiagonal::inferred_structures, UpperBidiagonal::inferred_structures >::type; }; - struct Tridiagonal { - using inferred_structures = structures::tuple_cat< std::tuple< Tridiagonal >, General::inferred_structures >::type; + struct FullRank { + using inferred_structures = structures::tuple_cat< std::tuple< FullRank >, General::inferred_structures >::type; }; - struct Bidiagonal { - using inferred_structures = structures::tuple_cat< std::tuple< Bidiagonal >, Tridiagonal::inferred_structures >::type; + struct NonSingular { + using inferred_structures = structures::tuple_cat< std::tuple< NonSingular >, Square::inferred_structures, FullRank::inferred_structures >::type; }; - struct LowerBidiagonal { - using inferred_structures = structures::tuple_cat< std::tuple< LowerBidiagonal >, Bidiagonal::inferred_structures >::type; + struct OrthogonalColumns { + using inferred_structures = structures::tuple_cat< std::tuple< OrthogonalColumns >, FullRank::inferred_structures >::type; }; - struct UpperBidiagonal { - using inferred_structures = structures::tuple_cat< std::tuple< UpperBidiagonal >, Bidiagonal::inferred_structures >::type; + struct OrthogonalRows { + using inferred_structures = structures::tuple_cat< std::tuple< OrthogonalRows >, FullRank::inferred_structures >::type; }; - struct Diagonal { - using inferred_structures = structures::tuple_cat< std::tuple< Diagonal >, LowerTriangular::inferred_structures, UpperTriangular::inferred_structures, LowerBidiagonal::inferred_structures, UpperBidiagonal::inferred_structures >::type; + struct Orthogonal { + using inferred_structures = structures::tuple_cat< std::tuple< Orthogonal >, NonSingular::inferred_structures, OrthogonalColumns::inferred_structures, OrthogonalRows::inferred_structures >::type; }; struct Constant { diff --git a/tests/unit/dense_structured_matrix.cpp b/tests/unit/dense_structured_matrix.cpp index b9f53aac2..fac4f4639 100644 --- a/tests/unit/dense_structured_matrix.cpp +++ b/tests/unit/dense_structured_matrix.cpp @@ -67,6 +67,10 @@ void grb_program( const size_t & n, grb::RC & rc ) { std::cout << "v_diag( " << grb::getLength( v_diag ) << " )" << std::endl; std::cout << "v_view( " << grb::getLength( v_view ) << " )" << std::endl; + grb::StructuredMatrix< float, grb::structures::Band< grb::Interval<-2, 5> > > BM0( n, n ); + grb::StructuredMatrix< float, grb::structures::Band< grb::RightOpenInterval<-2> > > BM1( n, n ); + grb::StructuredMatrix< float, grb::structures::Band< grb::LeftOpenInterval<-2> > > BM2( n, n ); + grb::StructuredMatrix< double, grb::structures::Band< grb::Interval<-2>, grb::Interval<1>, grb::Interval<3> > > BM3( n, n ); rc = grb::SUCCESS; } From a0ef5c3b410ddfb5e2f9de80de0e2eaccdf6d520 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Thu, 24 Mar 2022 08:57:50 +0000 Subject: [PATCH 115/282] !26 Resolve internal issue #364: Resize operations for reference dense containers * Add resize functions for dense ALP containers * Resize for dense containers succeeds if new_cap <= current_cap --- include/graphblas/denseref/blas0.hpp | 134 +++++++++++++++++++++++++++ include/graphblas/denseref/blas1.hpp | 42 +++++++-- include/graphblas/denseref/blas2.hpp | 41 ++++---- 3 files changed, 191 insertions(+), 26 deletions(-) create mode 100644 include/graphblas/denseref/blas0.hpp diff --git a/include/graphblas/denseref/blas0.hpp b/include/graphblas/denseref/blas0.hpp new file mode 100644 index 000000000..e95b89f23 --- /dev/null +++ b/include/graphblas/denseref/blas0.hpp @@ -0,0 +1,134 @@ + +/* + * Copyright 2021 Huawei Technologies Co., Ltd. + * + * 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. + */ + +/* + * @author A. N. Yzelman + * @date 14th of January 2022 + */ + +#ifndef _H_GRB_DENSEREF_BLAS0 +#define _H_GRB_DENSEREF_BLAS0 + +#include +#include +#include +#include + +#ifndef NO_CAST_ASSERT +#define NO_CAST_ASSERT( x, y, z ) \ + static_assert( x, \ + "\n\n" \ + "********************************************************************" \ + "********************************************************************" \ + "******************************\n" \ + "* ERROR | " y " " z ".\n" \ + "********************************************************************" \ + "********************************************************************" \ + "******************************\n" \ + "* Possible fix 1 | Remove no_casting from the template parameters " \ + "in this call to " y ".\n" \ + "* Possible fix 2 | Provide a value that matches the expected type.\n" \ + "********************************************************************" \ + "********************************************************************" \ + "******************************\n" ); +#endif + +namespace grb { + + /** + * \defgroup BLAS0 The Level-0 Basic Linear Algebra Subroutines (BLAS) + * + * A collection of functions that let GraphBLAS operators work on + * zero-dimensional containers, i.e., on scalars. + * + * The GraphBLAS uses opaque data types and defines several standard functions + * to operate on these data types. Examples types are grb::Vector and + * grb::Matrix, example functions are grb::dot and grb::vxm. + * + * To input data into an opaque GraphBLAS type, each opaque type defines a + * member function \a build: grb::Vector::build() and grb::Matrix::build(). + * + * To extract data from opaque GraphBLAS types, each opaque type provides + * \em iterators that may be obtained via the STL standard \a begin and \a end + * functions: + * - grb::Vector::begin or grb::Vector::cbegin + * - grb::Vector::end or grb::Vector::cend + * - grb::Matrix::begin or grb::Matrix::cbegin + * - grb::Matrix::end or grb::Matrix::cend + * + * Some GraphBLAS functions, however, reduce all elements in a GraphBLAS + * container into a single element of a given type. So for instance, grb::dot + * on two vectors of type grb::Vector using the regular real semiring + * grb::Semiring will store its output in a variable of type \a double. + * + * When parametrising GraphBLAS functions in terms of arbitrary Semirings, + * Monoids, Operators, and object types, it is useful to have a way to apply + * the same operators on whatever type they make functions like grb::dot + * produce-- that is, we require functions that enable the application of + * GraphBLAS operators on single elements. + * + * This group of BLAS level 0 functions provides this functionality. + * + * @{ + */ + + /** Resizes the Scalar to have at least the given number of nonzeroes. + * The contents of the scalar are not retained. + * + * Resizing of dense containers is not allowed as the capacity is determined + * by the container dimensions and the storage scheme. Therefore, this + * function will not change the capacity of the container. + * + * The resize function for Scalars exist to maintain compatibility with + * other containers (i.e., vector and matrix). + * + * Even though the capacity remains unchanged, the contents of the scalar + * are not retained to maintain compatibility with the general specification. + * However, the actual memory will not be reallocated. Rather, the scalar + * will be marked as uninitialized. + * + * @param[in] x The Scalar to be resized. + * @param[in] new_nz The number of nonzeroes this vector is to contain. + * + * @return SUCCESS If \a new_nz is not larger than 1. + * ILLEGAL If \a new_nz is larger than 1. + * + * \parblock + * \par Performance semantics. + * -$ This function consitutes \f$ \Theta(1) \f$ work. + * -# This function allocates \f$ \Theta(0) \f$ + * bytes of dynamic memory. + * -# This function does not make system calls. + * \endparblock + * \todo add documentation. In particular, think about the meaning with \a P > 1. + */ + template< typename InputType, typename InputStructure, typename length_type > + RC resize( Scalar< InputType, InputStructure, reference_dense > & s, const length_type new_nz ) { + if( new_nz <= 1 ) { + setInitialized( s, false ); + return SUCCESS; + } else { + return ILLEGAL; + } + } + + /** @} */ + +} // end namespace ``grb'' + +#endif // end ``_H_GRB_DENSEREF_BLAS0'' + diff --git a/include/graphblas/denseref/blas1.hpp b/include/graphblas/denseref/blas1.hpp index ab239e051..22a895c0d 100644 --- a/include/graphblas/denseref/blas1.hpp +++ b/include/graphblas/denseref/blas1.hpp @@ -235,16 +235,42 @@ namespace grb { return 0; } - /** \todo add documentation. In particular, think about the meaning with \a P > 1. */ + /** Resizes the vector to have at least the given number of nonzeroes. + * The contents of the vector are not retained. + * + * Resizing of dense containers is not allowed as the capacity is determined + * by the container dimensions and the storage scheme. Therefore, this + * function will not change the capacity of the vector. + * + * Even though the capacity remains unchanged, the contents of the vector + * are not retained to maintain compatibility with the general specification. + * However, the actual memory will not be reallocated. Rather, the vector + * will be marked as uninitialized. + * + * @param[in] x The VectorView to be resized. + * @param[in] new_nz The number of nonzeroes this vector is to contain. + * + * @return SUCCESS If \a new_nz is not larger than the current capacity + * of the vector. + * ILLEGAL If \a new_nz is larger than the current capacity of + * the vector. + * + * \parblock + * \par Performance semantics. + * -$ This function consitutes \f$ \Theta(1) \f$ work. + * -# This function allocates \f$ \Theta(0) \f$ + * bytes of dynamic memory. + * -# This function does not make system calls. + * \endparblock + * \todo add documentation. In particular, think about the meaning with \a P > 1. + */ template< typename InputType, typename InputStructure, typename InputStorage, typename View, typename length_type > RC resize( VectorView< InputType, InputStructure, InputStorage, View, reference_dense > & x, const length_type new_nz ) { - // check if we have a mismatch - if( new_nz > grb::size( x ) ) { - return MISMATCH; - } - // in the reference_dense implementation, vectors are of static size - // so this function immediately succeeds - return SUCCESS; + (void)x; + (void)new_nz; + // TODO implement + // setInitialized( x, false ); + return PANIC; } /** diff --git a/include/graphblas/denseref/blas2.hpp b/include/graphblas/denseref/blas2.hpp index 7ee8bdfee..d73432c81 100644 --- a/include/graphblas/denseref/blas2.hpp +++ b/include/graphblas/denseref/blas2.hpp @@ -100,36 +100,41 @@ namespace grb { } /** - * Resizes the nonzero capacity of this matrix. Any current contents of the - * matrix are \em not retained. + * Resizes the matrix to have at least the given number of nonzeroes. + * The contents of the matrix are not retained. * - * The dimension of this matrix is fixed. Only the number of nonzeroes that - * may be stored can change. If the matrix has row or column dimension size - * zero, all calls to this function are ignored. A request for less capacity - * than currently already may be allocated, may be ignored by the - * implementation. + * Resizing of dense containers is not allowed as the capacity is determined + * by the container dimensions and the storage scheme. Therefore, this + * function will not change the capacity of the matrix. * + * Even though the capacity remains unchanged, the contents of the matrix + * are not retained to maintain compatibility with the general specification. + * However, the actual memory will not be reallocated. Rather, the matrix + * will be marked as uninitialized. + * + * @param[in] A The matrix to be resized. * @param[in] nonzeroes The number of nonzeroes this matrix is to contain. * - * @return OUTOFMEM When no memory could be allocated to store this matrix. - * @return PANIC When allocation fails for any other reason. - * @return SUCCESS When a valid GraphBLAS matrix has been constructed. + * @return SUCCESS If \a new_nz is not larger than the current capacity + * of the matrix. + * ILLEGAL If \a new_nz is larger than the current capacity of + * the matrix. * * \parblock * \par Performance semantics. - * -$ This function consitutes \f$ \mathcal{O}(\mathit{nz} \f$ work. - * -# This function allocates \f$ \mathcal{O}(\mathit{nz}+m+n+1) \f$ + * -$ This function consitutes \f$ \Theta(1) \f$ work. + * -# This function allocates \f$ \Theta(0) \f$ * bytes of dynamic memory. - * -# This function will likely make system calls. + * -# This function does not make system calls. * \endparblock - * - * \warning This is an expensive function. Use sparingly and only when - * absolutely necessary */ template< typename InputType > RC resize( StructuredMatrix< InputType, InputStructure, InputStorage, InputView, reference_dense > & A, const size_t new_nz ) noexcept { - // delegate - return A.resize( new_nz ); + (void)A; + (void)new_nz; + // TODO implement + // setInitialized( A, false ); + return PANIC; } /** \internal Delegates to fully masked variant */ From e8f12e2ac5840e697dde4f3d6b2c064d10178326 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Thu, 24 Mar 2022 09:49:12 +0000 Subject: [PATCH 116/282] !29 Resolve internal issue #362: Implement bracket operator for accessing single element * Add bracket operator for ALP scalars. * Add bracket operator to VectorView --- include/graphblas/base/scalar.hpp | 57 +++++++++++++++++++++++++++ include/graphblas/base/vector.hpp | 7 ++-- include/graphblas/denseref/scalar.hpp | 15 +++++++ include/graphblas/denseref/vector.hpp | 51 ++++++++++++++++++++++++ 4 files changed, 126 insertions(+), 4 deletions(-) diff --git a/include/graphblas/base/scalar.hpp b/include/graphblas/base/scalar.hpp index f40b923f6..06075d3e8 100644 --- a/include/graphblas/base/scalar.hpp +++ b/include/graphblas/base/scalar.hpp @@ -54,6 +54,9 @@ namespace grb { /** @see Vector::value_type. */ typedef T value_type; + /** @see Vector::lambda_reference */ + typedef T& lambda_reference; + /** * The default ALP scalar constructor. * @@ -164,6 +167,60 @@ namespace grb { (void)other; } + /** + * Returns a lambda reference to the value of this Scalar. The user + * ensures that the requested reference only corresponds to a pre-existing + * nonzero in this scalar, or undefined behaviour will occur. + * This addresses the sparse specialization of scalars. In the dense + * context, scalar is considered to have a nonzero value \em iff initialized. + * + * A lambda reference to the value of this scalar is only valid when used + * inside a lambda function evaluated via grb::eWiseLambda. Outside this + * scope the returned reference incurs undefined behaviour. + * + * + * \warning In parallel contexts the use of a returned lambda reference + * outside the context of an eWiseLambda will incur at least one of + * the following ill effects: it may + * -# fail outright, + * -# work on stale data, + * -# work on incorrect data, or + * -# incur high communication costs to guarantee correctness. + * In short, such usage causes undefined behaviour. Implementers are + * \em not advised to provide GAS-like functionality through this + * interface, as it invites bad programming practices and bad + * algorithm design decisions. This operator is instead intended to + * provide for generic BLAS0-type operations only. + * + * \note For I/O, use the iterator retrieved via cbegin() instead of + * relying on a lambda_reference. + * + * @return A lambda reference to the value of this scalar + * + * \par Example. + * See grb::eWiseLambda() for a practical and useful example. + * + * \warning There is no similar concept in the official GraphBLAS specs. + * + * @see lambda_reference For more details on the returned reference type. + * @see grb::eWiseLambda For one legal way in which to use the returned + * #lambda_reference. + */ + lambda_reference operator*() noexcept { +#ifndef _GRB_NO_EXCEPTIONS + assert( false ); // Requesting lambda reference of unimplemented Scalar backend. +#endif + } + + /** Returns a constant reference to the scalar value. + * See the non-constant variant for further details. + */ + const lambda_reference operator*() const noexcept { +#ifndef _GRB_NO_EXCEPTIONS + assert( false ); // Requesting lambda reference of unimplemented Scalar backend. +#endif + } + }; // class Scalar } // namespace grb diff --git a/include/graphblas/base/vector.hpp b/include/graphblas/base/vector.hpp index 2a93366a3..efdab2dfb 100644 --- a/include/graphblas/base/vector.hpp +++ b/include/graphblas/base/vector.hpp @@ -894,10 +894,9 @@ namespace grb { */ lambda_reference operator[]( const size_t i ) { (void)i; - #ifndef _GRB_NO_EXCEPTIONS - throw std::runtime_error( "Requesting lambda reference of unimplemented " - "Vector backend." ); - #endif +#ifndef _GRB_NO_EXCEPTIONS + assert( false ); // Requesting lambda reference of unimplemented Vector backend. +#endif } }; diff --git a/include/graphblas/denseref/scalar.hpp b/include/graphblas/denseref/scalar.hpp index db3d10f8b..0570b49a1 100644 --- a/include/graphblas/denseref/scalar.hpp +++ b/include/graphblas/denseref/scalar.hpp @@ -77,6 +77,9 @@ namespace grb { /** @see Vector::value_type. */ typedef T value_type; + /** @see Vector::lambda_reference */ + typedef T& lambda_reference; + /** * The main ALP scalar constructor. * @@ -182,6 +185,18 @@ namespace grb { other.initialized = false; } + /** \internal No implementation notes. */ + lambda_reference operator*() noexcept { + assert( getInitialized( *this ) ); + return value; + } + + /** \internal No implementation notes. */ + const lambda_reference operator*() const noexcept { + assert( getInitialized( *this ) ); + return value; + } + }; // class Scalar with physical container /** Identifies any reference_dense scalar as an ALP scalar. */ diff --git a/include/graphblas/denseref/vector.hpp b/include/graphblas/denseref/vector.hpp index 399a8e544..1928c99b5 100644 --- a/include/graphblas/denseref/vector.hpp +++ b/include/graphblas/denseref/vector.hpp @@ -406,10 +406,27 @@ namespace grb { /** @see Vector::value_type. */ using value_type = T; + /** @see Vector::lambda_reference */ + typedef T& lambda_reference; + VectorView( const size_t length, const size_t cap = 0 ) : v( std::make_unique< Vector< T, reference_dense, internal::DefaultCoordinates > >( length, cap ) ), imf( std::make_shared< imf::Id >( length ) ) {} + /** \internal No implementation notes. */ + lambda_reference operator[]( const size_t i ) noexcept { + assert( i < _length() ); + assert( getInitialized( *v ) ); + // TODO implement; + } + + /** \internal No implementation notes. */ + const lambda_reference operator[]( const size_t i ) const noexcept { + assert( i < _length() ); + assert( getInitialized( *v ) ); + // TODO implement; + } + }; // class VectorView with physical container /** Identifies any reference_dense vector as an ALP vector. */ @@ -450,6 +467,9 @@ namespace grb { /** Exposes the element type. */ using value_type = T; + /** @see Vector::lambda_reference */ + typedef T& lambda_reference; + /** Constructor for creating a view over a given target vector */ VectorView( target_type & vec_view ) : ref( vec_view ), imf( nullptr ) { @@ -465,6 +485,20 @@ namespace grb { } } + /** \internal No implementation notes. */ + lambda_reference operator[]( const size_t i ) noexcept { + assert( i < _length() ); + assert( getInitialized( *ref ) ); + // TODO implement; + } + + /** \internal No implementation notes. */ + const lambda_reference operator[]( const size_t i ) const noexcept { + assert( i < _length() ); + assert( getInitialized( *ref ) ); + // TODO implement; + } + }; // Original VectorView @@ -500,6 +534,9 @@ namespace grb { /** Exposes the element type. */ using value_type = T; + /** @see Vector::lambda_reference */ + typedef T& lambda_reference; + VectorView( target_type & struct_mat ) : ref( struct_mat ), imf( nullptr ) { size_t _length = view::Diagonal< target_type >::getLength( dims( ref ) ); @@ -507,6 +544,20 @@ namespace grb { } + /** \internal No implementation notes. */ + lambda_reference operator[]( const size_t i ) noexcept { + assert( i < _length() ); + assert( getInitialized( *ref ) ); + // TODO implement; + } + + /** \internal No implementation notes. */ + const lambda_reference operator[]( const size_t i ) const noexcept { + assert( i < _length() ); + assert( getInitialized( *ref ) ); + // TODO implement; + } + }; // Diagonal Vector view /** Creates a Diagonal Vector View over a given \a StructuredMatrix From 9b11cca5e0c2496f78bb916a72edd02519bea4aa Mon Sep 17 00:00:00 2001 From: Anonymous Date: Fri, 25 Mar 2022 08:09:04 +0000 Subject: [PATCH 117/282] !31 Resolves internal issue #376: All views applied via get_view * Dropped leftover coord arguments in VectorView * Integrating comments from MR !31 * Doxygen cleanup * Started using get_view for all views in matrix.hpp --- include/graphblas/denseref/matrix.hpp | 330 +++++++++++++++++++------ include/graphblas/denseref/vector.hpp | 118 +++++---- include/graphblas/utils.hpp | 11 + include/graphblas/views.hpp | 5 + tests/unit/dense_structured_matrix.cpp | 22 +- 5 files changed, 358 insertions(+), 128 deletions(-) diff --git a/include/graphblas/denseref/matrix.hpp b/include/graphblas/denseref/matrix.hpp index 5071cae72..383eacc78 100644 --- a/include/graphblas/denseref/matrix.hpp +++ b/include/graphblas/denseref/matrix.hpp @@ -37,6 +37,7 @@ #include #include //#include //for help with dealing with pattern matrix input +#include #include #include #include @@ -512,7 +513,6 @@ namespace grb { */ TargetType & ref; - MatrixReference() : MatrixBase( 0, 0 ), ref( nullptr ) {} MatrixReference( TargetType & struct_mat ) : MatrixBase( nrows( struct_mat ), ncols( struct_mat ) ), ref( struct_mat ) {} MatrixReference( TargetType & struct_mat, std::shared_ptr< imf::IMF > imf_l, std::shared_ptr< imf::IMF > imf_r ) : MatrixBase( imf_l, imf_r ), ref( struct_mat ) {} @@ -530,13 +530,8 @@ namespace grb { * The logical layout of a structured matrix maps to a physical counterpart via * a storage scheme which typically depends on the chosen structure and the selected * backend. grb::Matrix and grb::Vector may be used as interfaces to such a physical - * layout. - * To visualize this, you may think of a band matrix. Using a - * \a storage::Dense:full or a \a storage::Dense:band storage schemes would require - * the use of a \a grb::Matrix container (see include/graphblas/storage.hpp for - * more details about the two storage schemes). However, the interpration of its - * content would differ in the two cases being a function of both the Structure - * information and the storage scheme combined. + * layout, where the interpration of their content is a function of the structure + * information. * * Views can be used to create logical \em perspectives on top of a container. * For example, one may decide to refer to the transpose of a matrix or to treat @@ -554,17 +549,13 @@ namespace grb { * and \a StructuredMatrix, reference_dense > * as examples of structured matrix types without and with physical container, respectively. * - * Finally, a structured matrix can be declared as temporary, in which case the ALP - * framework has the freedom to decide whether a container should be allocated in practice - * or not. For example, a JIT backend may optimize away the use of such matrix which - * would make memory allocation for such matrix unnecessary. * * @tparam T The type of the matrix elements. \a T shall not be a GraphBLAS * type. * @tparam Structure One of the matrix structures defined in \a grb::structures. * @tparam StorageSchemeType Either \em enum \a storage::Dense or \em enum * \a storage::Sparse. - * \a StructuredMatrix will be allowed to pick storage schemes + * \a StructuredMatrix will be allowed to use storage schemes * defined within their specified \a StorageSchemeType. * @tparam View One of the matrix views in \a grb::view. * All static views except for \a view::Original (via @@ -572,12 +563,10 @@ namespace grb { * and only allow to refer to a previously defined * \a StructuredMatrix. * The \a View parameter should not be used directly - * by the user but can be set using specific member types - * appropriately defined by each StructuredMatrix and - * accessible via functions such as \a grb::transpose or - * \a grb::diagonal. (See examples of StructuredMatrix - * definitions within \a include/graphblas/denseref/matrix.hpp - * and the \a dense_structured_matrix.cpp unit test). + * by the user but selected via \a get_view function. + * + * See examples of StructuredMatrix definitions within \a include/graphblas/denseref/matrix.hpp + * and the \a dense_structured_matrix.cpp unit test. * */ template< typename T, typename Structure, typename StorageSchemeType, typename View > @@ -615,8 +604,23 @@ namespace grb { // A general Structure knows how to define a reference to itself (which is an original reference view) // as well as other static views. - using original_t = StructuredMatrix< T, structures::General, storage::Dense, view::Original< self_type >, reference_dense >; - using transpose_t = StructuredMatrix< T, structures::General, storage::Dense, view::Transpose< self_type >, reference_dense >; + template < view::Views view_tag, bool d=false > + struct view_type; + + template < bool d > + struct view_type< view::original, d > { + using type = StructuredMatrix< T, structures::General, storage::Dense, view::Original< self_type >, reference_dense >; + }; + + template < bool d > + struct view_type< view::transpose, d > { + using type = StructuredMatrix< T, structures::General, storage::Dense, view::Transpose< self_type >, reference_dense >; + }; + + template < bool d > + struct view_type< view::diagonal, d > { + using type = VectorView< T, structures::General, storage::Dense, view::Diagonal< self_type >, reference_dense >; + }; StructuredMatrix( const size_t rows, const size_t cols, const size_t cap = 0 ) : internal::MatrixContainer< T >( rows, cols, cap ) { @@ -640,8 +644,18 @@ namespace grb { using value_type = T; using structure = structures::General; - using original_t = StructuredMatrix< T, structures::General, storage::Dense, view::Original< self_type >, reference_dense >; - using transpose_t = StructuredMatrix< T, structures::General, storage::Dense, view::Transpose< self_type >, reference_dense >; + template < view::Views view_tag, bool d=false > + struct view_type; + + template < bool d > + struct view_type< view::original, d > { + using type = StructuredMatrix< T, structures::General, storage::Dense, view::Original< self_type >, reference_dense >; + }; + + template < bool d > + struct view_type< view::transpose, d > { + using type = StructuredMatrix< T, structures::General, storage::Dense, view::Transpose< self_type >, reference_dense >; + }; StructuredMatrix( ) : internal::MatrixBase( 0, 0 ) {} @@ -671,7 +685,13 @@ namespace grb { using structure = Structure; /** The type of an identify view over the present type */ - using original_t = StructuredMatrix< T, Structure, storage::Dense, view::Original< self_type >, reference_dense >; + template < view::Views view_tag, bool d=false > + struct view_type; + + template < bool d > + struct view_type< view::original, d > { + using type = StructuredMatrix< T, Structure, storage::Dense, view::Original< self_type >, reference_dense >; + }; StructuredMatrix( const size_t rows, const size_t cols, const size_t cap = 0 ) : internal::MatrixContainer< T >( rows, cols, cap ) {} @@ -698,8 +718,18 @@ namespace grb { using value_type = T; using structure = structures::Square; - using original_t = StructuredMatrix< T, structures::Square, storage::Dense, view::Original< self_type >, reference_dense >; - using transpose_t = StructuredMatrix< T, structures::Square, storage::Dense, view::Transpose< self_type >, reference_dense >; + template < view::Views view_tag, bool d=false > + struct view_type; + + template < bool d > + struct view_type< view::original, d > { + using type = StructuredMatrix< T, structures::Square, storage::Dense, view::Original< self_type >, reference_dense >; + }; + + template < bool d > + struct view_type< view::transpose, d > { + using type = StructuredMatrix< T, structures::Square, storage::Dense, view::Transpose< self_type >, reference_dense >; + }; StructuredMatrix( const size_t rows, const size_t cap = 0 ) : internal::MatrixContainer< T >( rows, rows, cap ) {} @@ -719,8 +749,18 @@ namespace grb { using value_type = T; using structure = structures::Square; - using original_t = StructuredMatrix< T, structures::Square, storage::Dense, view::Original< self_type >, reference_dense >; - using transpose_t = StructuredMatrix< T, structures::Square, storage::Dense, view::Transpose< self_type >, reference_dense >; + template < view::Views view_tag, bool d=false > + struct view_type; + + template < bool d > + struct view_type< view::original, d > { + using type = StructuredMatrix< T, structures::Square, storage::Dense, view::Original< self_type >, reference_dense >; + }; + + template < bool d > + struct view_type< view::transpose, d > { + using type = StructuredMatrix< T, structures::Square, storage::Dense, view::Transpose< self_type >, reference_dense >; + }; // ref to empty matrix StructuredMatrix( ) : internal::MatrixReference< target_type >() {} @@ -759,10 +799,18 @@ namespace grb { using value_type = T; using structure = structures::UpperTriangular; - // A general Structure knows how to define a reference to itself (which is an original reference view) - // as well as other static views. - using original_t = StructuredMatrix< T, structures::UpperTriangular, storage::Dense, view::Original< self_type >, reference_dense >; - using transpose_t = StructuredMatrix< T, structures::LowerTriangular, storage::Dense, view::Transpose< self_type >, reference_dense >; + template < view::Views view_tag, bool d=false > + struct view_type; + + template < bool d > + struct view_type< view::original, d > { + using type = StructuredMatrix< T, structures::UpperTriangular, storage::Dense, view::Original< self_type >, reference_dense >; + }; + + template < bool d > + struct view_type< view::transpose, d > { + using type = StructuredMatrix< T, structures::LowerTriangular, storage::Dense, view::Transpose< self_type >, reference_dense >; + }; StructuredMatrix( const size_t rows, const size_t cols, const size_t cap = 0 ) : internal::MatrixContainer< T >( rows, cols, cap ) {} @@ -783,8 +831,18 @@ namespace grb { using value_type = T; using structure = structures::UpperTriangular; - using original_t = StructuredMatrix< T, structures::UpperTriangular, storage::Dense, view::Original< self_type >, reference_dense >; - using transpose_t = StructuredMatrix< T, structures::UpperTriangular, storage::Dense, view::Transpose< self_type >, reference_dense >; + template < view::Views view_tag, bool d=false > + struct view_type; + + template < bool d > + struct view_type< view::original, d > { + using type = StructuredMatrix< T, structures::UpperTriangular, storage::Dense, view::Original< self_type >, reference_dense >; + }; + + template < bool d > + struct view_type< view::transpose, d > { + using type = StructuredMatrix< T, structures::LowerTriangular, storage::Dense, view::Transpose< self_type >, reference_dense >; + }; // ref to empty matrix StructuredMatrix( ) : internal::MatrixReference< target_type >() {} @@ -825,10 +883,18 @@ namespace grb { using value_type = T; using structure = structures::Identity; - // A general Structure knows how to define a reference to itself (which is an original reference view) - // as well as other static views. - using original_t = StructuredMatrix< T, structures::Identity, storage::Dense, view::Original< self_type >, reference_dense >; - using transpose_t = StructuredMatrix< T, structures::Identity, storage::Dense, view::Transpose< self_type >, reference_dense >; + template < view::Views view_tag, bool d=false > + struct view_type; + + template < bool d > + struct view_type< view::original, d > { + using type = StructuredMatrix< T, structures::Identity, storage::Dense, view::Original< self_type >, reference_dense >; + }; + + template < bool d > + struct view_type< view::transpose, d > { + using type = StructuredMatrix< T, structures::Identity, storage::Dense, view::Transpose< self_type >, reference_dense >; + }; StructuredMatrix( const size_t rows, const size_t cap = 0 ) : internal::MatrixContainer< T >( rows, rows, cap ) {} @@ -855,26 +921,38 @@ namespace grb { /** * - * @brief Generate an original view where the type is compliant with the source StructuredMatrix. - * Version where no target structure is specified. In this case the structure of the source type is assumed. + * @brief Generate an original view of \a source maintaining the same \a Structure. + * The function guarantees the created view is non-overlapping with other + * existing views only when the check can be performed in constant time. * * @tparam T The matrix' elements type * @tparam Structure The structure of the source and target matrix view - * @tparam StorageSchemeType The type (i.e., sparse or dense) of storage scheme + * @tparam StorageSchemeType The type (i.e., \a grb::storage:Dense or \a grb::storage:Sparse) of storage scheme * @tparam View The source's View type * @tparam backend The target backend * - * @param source The source structured matrix + * @param source The source matrix * * @return A new original view over the source structured matrix. * + * \parblock + * \par Performance semantics. + * -# This function performs + * \f$ \Theta(nref) \f$ amount of work where \f$ nref \f$ is the number + * of available views of \a source. + * -# A call to this function may use \f$ \mathcal{O}(1) \f$ bytes + * of memory beyond the memory in use at the function call entry. + * -# This function may make system calls. + * \endparblock + * */ - template< typename T, typename Structure, typename StorageSchemeType, typename View, enum Backend backend > - StructuredMatrix< T, Structure, StorageSchemeType, view::Original< StructuredMatrix< T, Structure, StorageSchemeType, View, backend > >, backend > - get_view( StructuredMatrix< T, Structure, StorageSchemeType, View, backend > &source ) { + template< + typename T, typename Structure, typename StorageSchemeType, typename View, enum Backend backend > + typename StructuredMatrix< T, Structure, StorageSchemeType, View, backend >::template view_type< view::original >::type + get_view( StructuredMatrix< T, Structure, StorageSchemeType, View, backend > & source ) { using source_strmat_t = StructuredMatrix< T, Structure, StorageSchemeType, View, backend >; - using target_strmat_t = StructuredMatrix< T, Structure, StorageSchemeType, view::Original< source_strmat_t >, backend >; + using target_strmat_t = typename source_strmat_t::template view_type< view::original >::type; target_strmat_t target( source ); @@ -883,34 +961,41 @@ namespace grb { /** * - * @brief Generate an original view where the type is compliant with the source StructuredMatrix. - * Version where a target structure is specified. It can only generate a valide type if the target - * structure is the same as the source's - * or a more specialized one that would preserve its static properties (e.g., symmetric reference - * to a square matrix -- any assumption based on symmetry would not break those based on square). + * @brief Generate a view specified by \a target_view where the type is compliant with the + * \a source matrix. + * The function guarantees the created view is non-overlapping with other + * existing views only when the check can be performed in constant time. * - * @tparam TargetStructure The target structure of the new view. It should verify - * grb::is_in . + * @tparam target_view One of the supported views listed in \a view::Views * @tparam T The matrix' elements type * @tparam Structure The structure of the source and target matrix view - * @tparam StorageSchemeType The type (i.e., sparse or dense) of storage scheme + * @tparam StorageSchemeType The type (i.e., \a grb::storage:Dense or \a grb::storage:Sparse) of storage scheme * @tparam View The source's View type * @tparam backend The target backend * * @param source The source structured matrix * - * @return A new original view over the source structured matrix. + * @return A new \a target_view view over the source matrix. + + * \parblock + * \par Performance semantics. + * -# This function performs + * \f$ \Theta(nref) \f$ amount of work where \f$ nref \f$ is the number + * of available views of \a source. + * -# A call to this function may use \f$ \mathcal{O}(1) \f$ bytes + * of memory beyond the memory in use at the function call entry. + * -# This function may make system calls. + * \endparblock * */ - template< typename TargetStructure, typename T, typename Structure, typename StorageSchemeType, typename View, enum Backend backend > - StructuredMatrix< T, TargetStructure, StorageSchemeType, view::Original< StructuredMatrix< T, Structure, StorageSchemeType, View, backend > >, backend > + template< + enum view::Views target_view, + typename T, typename Structure, typename StorageSchemeType, typename View, enum Backend backend > + typename StructuredMatrix< T, Structure, StorageSchemeType, View, backend >::template view_type< target_view >::type get_view( StructuredMatrix< T, Structure, StorageSchemeType, View, backend > &source ) { - static_assert( structures::is_in< Structure, typename TargetStructure::inferred_structures >::value, - "Can only create a view when the target structure is compatible with the source." ); - using source_strmat_t = StructuredMatrix< T, Structure, StorageSchemeType, View, backend >; - using target_strmat_t = StructuredMatrix< T, TargetStructure, StorageSchemeType, view::Original< source_strmat_t >, backend >; + using target_strmat_t = typename source_strmat_t::template view_type< target_view >::type; target_strmat_t target( source ); @@ -918,22 +1003,53 @@ namespace grb { } /** - * @brief Construct a new transpose view. + * + * @brief Generate an original view where the type is compliant with the source StructuredMatrix. + * Version where a target structure is specified. It can only generate a valide type if the target + * structure is the same as the source's + * or a more specialized one that would preserve its static properties (e.g., symmetric reference + * to a square matrix -- any assumption based on symmetry would not break those based on square). + * The function guarantees the created view is non-overlapping with other existing views only when the + * check can be performed in constant time. * - * @tparam StructuredMatrixT The type of the source structured matrix. - * - * @param smat The source structure matrix. + * @tparam TargetStructure The target structure of the new view. It should verify + * grb::is_in . + * @tparam T The matrix's elements type + * @tparam Structure The structure of the source and target matrix view + * @tparam StorageSchemeType The type (i.e., \a grb::storage:Dense or \a grb::storage:Sparse) of storage scheme + * @tparam View The source's View type + * @tparam backend The target backend + * + * @param source The source structured matrix + * + * @return A new original view over the source structured matrix. * - * @return A transposed view of the source matrix. + * \parblock + * \par Performance semantics. + * -# This function performs + * \f$ \Theta(nref) \f$ amount of work where \f$ nref \f$ is the number + * of available views of \a source. + * -# A call to this function may use \f$ \mathcal{O}(1) \f$ bytes + * of memory beyond the memory in use at the function call entry. + * -# This function may make system calls. + * \endparblock * */ - template< typename StructuredMatrixT > - typename StructuredMatrixT::transpose_t - transpose( StructuredMatrixT &smat ) { + template< + typename TargetStructure, + typename T, typename Structure, typename StorageSchemeType, typename View, enum Backend backend > + StructuredMatrix< T, TargetStructure, StorageSchemeType, view::Original< StructuredMatrix< T, Structure, StorageSchemeType, View, backend > >, backend > + get_view( StructuredMatrix< T, Structure, StorageSchemeType, View, backend > &source ) { + + static_assert( structures::is_in< Structure, typename TargetStructure::inferred_structures >::value, + "Can only create a view when the target structure is compatible with the source." ); - typename StructuredMatrixT::transpose_t smat_trans( smat ); + using source_strmat_t = StructuredMatrix< T, Structure, StorageSchemeType, View, backend >; + using target_strmat_t = StructuredMatrix< T, TargetStructure, StorageSchemeType, view::Original< source_strmat_t >, backend >; + + target_strmat_t target( source ); - return smat_trans; + return target; } namespace internal { @@ -942,7 +1058,9 @@ namespace grb { * The compatibility depends on the TargetStructure, SourceStructure and IMFs, and is calculated during runtime. */ - template< typename TargetStructure, typename T, typename Structure, typename StorageSchemeType, typename View, enum Backend backend > + template< + typename TargetStructure, + typename T, typename Structure, typename StorageSchemeType, typename View, enum Backend backend > StructuredMatrix< T, TargetStructure, StorageSchemeType, view::Original< StructuredMatrix< T, Structure, StorageSchemeType, View, backend > >, backend > get_view( StructuredMatrix< T, Structure, StorageSchemeType, View, backend > &source, std::shared_ptr< imf::IMF > imf_r, std::shared_ptr< imf::IMF > imf_c ) { @@ -970,12 +1088,14 @@ namespace grb { * Version where a range of rows and columns are selected to form a new view with specified target * structure. It can only generate a valide type if the target * structure is guaranteed to preserve the static properties of the source's structure. + * A structural check of this kind as well as non-overlapping checks with existing views of \a source + * are guaranteed only when each one of them incurs constant time work. * * @tparam TargetStructure The target structure of the new view. It should verify * grb::is_in . * @tparam T The matrix' elements type * @tparam Structure The structure of the source and target matrix view - * @tparam StorageSchemeType The type (i.e., sparse or dense) of storage scheme + * @tparam StorageSchemeType The type (i.e., \a grb::storage:Dense or \a grb::storage:Sparse) of storage scheme * @tparam View The source's View type * @tparam backend The target backend * @@ -985,8 +1105,20 @@ namespace grb { * * @return A new original view over the source structured matrix. * + * \parblock + * \par Performance semantics. + * -# This function performs + * \f$ \Theta(nref) \f$ amount of work where \f$ nref \f$ is the number + * of available views of \a source. + * -# A call to this function may use \f$ \mathcal{O}(1) \f$ bytes + * of memory beyond the memory in use at the function call entry. + * -# This function may make system calls. + * \endparblock + * */ - template< typename TargetStructure, typename T, typename Structure, typename StorageSchemeType, typename View, enum Backend backend > + template< + typename TargetStructure, + typename T, typename Structure, typename StorageSchemeType, typename View, enum Backend backend > StructuredMatrix< T, TargetStructure, StorageSchemeType, view::Original< StructuredMatrix< T, Structure, StorageSchemeType, View, backend > >, backend > get_view( StructuredMatrix< T, Structure, StorageSchemeType, View, backend > &source, const utils::range& rng_r, const utils::range& rng_c ) { @@ -994,7 +1126,51 @@ namespace grb { auto imf_r = std::make_shared< imf::Strided >( rng_r.count(), nrows(source), rng_r.start, rng_r.stride ); auto imf_c = std::make_shared< imf::Strided >( rng_c.count(), ncols(source), rng_c.start, rng_c.stride ); - return internal::get_view( source, imf_r, imf_c ); + return internal::get_view( source, imf_r, imf_c ); + } + + /** + * + * @brief Generate an original view where the type is compliant with the source StructuredMatrix. + * Version where no target structure is specified (in this case the structure of the source type is assumed as target) + * with row and column selection. + * A structure preserving check as well as non-overlapping checks with existing views of \a source + * are guaranteed only when each one of them incurs constant time work. + * + * @tparam T The matrix' elements type + * @tparam Structure The structure of the source and target matrix view + * @tparam StorageSchemeType The type (i.e., \a grb::storage:Dense or \a grb::storage:Sparse) of storage scheme + * @tparam View The source's View type + * @tparam backend The target backend + * + * @param source The source matrix + * @param rng_r A valid range of rows + * @param rng_c A valid range of columns + * + * @return A new original view over the source structured matrix. + * + * \parblock + * \par Performance semantics. + * -# This function performs + * \f$ \Theta(nref) \f$ amount of work where \f$ nref \f$ is the number + * of available views of \a source. + * -# A call to this function may use \f$ \mathcal{O}(1) \f$ bytes + * of memory beyond the memory in use at the function call entry. + * -# This function may make system calls. + * \endparblock + * + */ + + template< + typename T, typename Structure, typename StorageSchemeType, typename View, enum Backend backend > + StructuredMatrix< T, Structure, StorageSchemeType, view::Original< StructuredMatrix< T, Structure, StorageSchemeType, View, backend > >, backend > + get_view( StructuredMatrix< T, Structure, StorageSchemeType, View, backend > &source, + const utils::range& rng_r, const utils::range& rng_c ) { + + auto imf_r = std::make_shared< imf::Strided >( rng_r.count(), nrows(source), rng_r.start, rng_r.stride ); + auto imf_c = std::make_shared< imf::Strided >( rng_c.count(), ncols(source), rng_c.start, rng_c.stride ); + + return internal::get_view( source, imf_r, imf_c ); } namespace internal { @@ -1022,7 +1198,9 @@ namespace grb { * @return A new original view over the source structured matrix. * */ - template< typename TargetStructure, typename T, typename Structure, typename StorageSchemeType, typename View, enum Backend backend > + template< + typename TargetStructure, + typename T, typename Structure, typename StorageSchemeType, typename View, enum Backend backend > StructuredMatrix< T, TargetStructure, StorageSchemeType, view::Original< StructuredMatrix< T, Structure, StorageSchemeType, View, backend > >, backend > get_view( StructuredMatrix< T, Structure, StorageSchemeType, View, backend > &source, const std::vector< size_t >& sel_r, const std::vector< size_t >& sel_c ) { diff --git a/include/graphblas/denseref/vector.hpp b/include/graphblas/denseref/vector.hpp index 1928c99b5..c9c23b636 100644 --- a/include/graphblas/denseref/vector.hpp +++ b/include/graphblas/denseref/vector.hpp @@ -350,11 +350,6 @@ namespace grb { * Vector View defined as views on other vectors do not instantiate a * new container but refer to the one used by their targets. * - * Finally, a vector view can be declared as temporary, in which case the ALP - * framework has the freedom to decide whether a container should be allocated in practice - * or not. For example, a JIT backend may optimize away the use of such vector which - * would make memory allocation for such vector unnecessary. - * * @tparam T The type of the vector elements. \a T shall not be a GraphBLAS * type. * @tparam Structure Structure introduced to match the template @@ -370,8 +365,6 @@ namespace grb { * accessible via functions. * @tparam StorageSchemeType Either \em enum \a storage::Dense or \em enum * \a storage::Sparse. - * \a VectorView will be allowed to pick storage schemes - * defined within their specified \a StorageSchemeType. * */ template< typename T, typename Structure, typename View > @@ -409,6 +402,14 @@ namespace grb { /** @see Vector::lambda_reference */ typedef T& lambda_reference; + template < view::Views view_tag, bool d=false > + struct view_type; + + template < bool d > + struct view_type< view::original, d > { + using type = VectorView< T, Structure, storage::Dense, view::Original< self_type >, reference_dense >; + }; + VectorView( const size_t length, const size_t cap = 0 ) : v( std::make_unique< Vector< T, reference_dense, internal::DefaultCoordinates > >( length, cap ) ), imf( std::make_shared< imf::Id >( length ) ) {} @@ -452,8 +453,7 @@ namespace grb { friend size_t getLength<>( const self_type & ) noexcept; - /** Reference to a target vector to which this vector view points to */ - // std::shared_ptr< target_type > ref; + /** Reference to VectorView object upon which this view is applied */ target_type & ref; /** Index-mapping function. @see IMF */ @@ -469,6 +469,14 @@ namespace grb { /** @see Vector::lambda_reference */ typedef T& lambda_reference; + + template < view::Views view_tag, bool d=false > + struct view_type; + + template < bool d > + struct view_type< view::original, d > { + using type = VectorView< T, Structure, storage::Dense, view::Original< self_type >, reference_dense >; + }; /** Constructor for creating a view over a given target vector */ VectorView( target_type & vec_view ) : ref( vec_view ), imf( nullptr ) { @@ -520,7 +528,7 @@ namespace grb { friend size_t getLength<>( const self_type & ) noexcept; - /** Pointer to a VectorView object upon which this view is created */ + /** Reference to VectorView object upon which this view is applied */ target_type & ref; /** @see IMF */ @@ -536,6 +544,14 @@ namespace grb { /** @see Vector::lambda_reference */ typedef T& lambda_reference; + + template < view::Views view_tag, bool d=false > + struct view_type; + + template < bool d > + struct view_type< view::original, d > { + using type = VectorView< T, Structure, storage::Dense, view::Original< self_type >, reference_dense >; + }; VectorView( target_type & struct_mat ) : ref( struct_mat ), imf( nullptr ) { @@ -560,55 +576,73 @@ namespace grb { }; // Diagonal Vector view - /** Creates a Diagonal Vector View over a given \a StructuredMatrix - * - * @paramt StructuredMatrixT Type of the StructuredMatrix over which the - * view is created. - * @param[in] smat StructuredMatrix object over which the view - * is created. - * - * @returns A VectorView object. - * */ - template< typename StructuredMatrixT > - VectorView< typename StructuredMatrixT::value_type, typename StructuredMatrixT::structure, storage::Dense, view::Diagonal< StructuredMatrixT >, reference_dense > - diagonal( StructuredMatrixT &smat ) { - - VectorView< typename StructuredMatrixT::value_type, typename StructuredMatrixT::structure, storage::Dense, view::Diagonal< StructuredMatrixT >, reference_dense > smat_diag( smat ); - - return smat_diag; - } - /** - * Generate an original view of a VectorView. - * + * @brief Generate an original view of the input VectorView. The function guarantees + * the created view is non-overlapping with other existing views only when the + * check can be performed in constant time. + * + * @tparam T The vector's elements type + * @tparam Structure The structure of the source and target vector view + * @tparam StorageSchemeType The type (i.e., \a grb::storage:Dense or \a grb::storage:Sparse) of storage scheme + * @tparam View The source's View type + * @tparam backend The target backend + * * @param[in] source The VectorView object over which the view is created. - * - * @returns A VectorView object. + * + * @returns A new vector VectorView object. + * + * \parblock + * \par Performance semantics. + * -# This function performs + * \f$ \Theta(nref) \f$ amount of work where \f$ nref \f$ is the number + * of available views of \a source. + * -# A call to this function may use \f$ \mathcal{O}(1) \f$ bytes + * of memory beyond the memory in use at the function call entry. + * -# This function may make system calls. + * \endparblock + * */ - template< typename T, typename Structure, typename View, typename StorageSchemeType, enum Backend backend > - VectorView< T, Structure, StorageSchemeType, view::Original< VectorView< T, Structure, StorageSchemeType, View, backend > >, backend > - get_view( VectorView< T, Structure, View, StorageSchemeType, backend > &source ) { + template< + typename T, typename Structure, typename StorageSchemeType, typename View, enum Backend backend > + typename VectorView< T, Structure, StorageSchemeType, View, backend >::template view_type< view::original >::type + get_view( VectorView< T, Structure, StorageSchemeType, View, backend > & source ) { + + using source_vec_t = VectorView< T, Structure, StorageSchemeType, View, backend >; + using target_vec_t = typename source_vec_t::template view_type< view::original >::type; - VectorView< T, Structure, StorageSchemeType, view::Original< VectorView< T, Structure, View, StorageSchemeType, backend > >, backend > vec_view( source ); + target_vec_t vec_view( source ); return vec_view; } /** - * Implement a gather through a View over compatible Structure using - * provided Index Mapping Functions. + * @brief Version of get_view over vectors where a range of elements are selected to form a new view. + * The function guarantees the created view is non-overlapping with other existing views only when the + * check can be performed in constant time. * * @param[in] source The VectorView object over which the view is created. - * @param[in] imf Index-mapping function applied to the created view. + * @param[in] rng A valid range of elements * * @returns A VectorView object. + * + * \parblock + * \par Performance semantics. + * -# This function performs + * \f$ \Theta(nref) \f$ amount of work where \f$ nref \f$ is the number + * of available views of \a source. + * -# A call to this function may use \f$ \mathcal{O}(1) \f$ bytes + * of memory beyond the memory in use at the function call entry. + * -# This function may make system calls. + * \endparblock + * */ template< typename T, typename Structure, typename View, typename StorageSchemeType, enum Backend backend > - VectorView< T, Structure, StorageSchemeType, view::Original< VectorView< T, Structure, StorageSchemeType, View, backend > >, backend > - get_view( VectorView< T, Structure, StorageSchemeType, View, backend > &source, std::shared_ptr< imf::IMF > imf ) { + typename VectorView< T, Structure, StorageSchemeType, View, backend >::template view_type< view::original >::type + get_view( VectorView< T, Structure, StorageSchemeType, View, backend > &source, const utils::range& rng ) { - VectorView< T, Structure, StorageSchemeType, view::Original< VectorView< T, Structure, StorageSchemeType, View, backend > >, backend > vec_view( source, imf ); + auto imf_v = std::make_shared< imf::Strided >( rng.count(), getLength( source ), rng.start, rng.stride ); + typename VectorView< T, Structure, StorageSchemeType, View, backend >::template view_type< view::original >::type vec_view( source, imf_v ); return vec_view; } diff --git a/include/graphblas/utils.hpp b/include/graphblas/utils.hpp index 8757e3031..145469221 100644 --- a/include/graphblas/utils.hpp +++ b/include/graphblas/utils.hpp @@ -373,11 +373,22 @@ namespace grb { struct range { size_t start, end, stride; + range(): start( 0 ), end( std::numeric_limits< size_t >::max() ), stride( 1 ) {} + range(size_t start, size_t end, size_t stride=1): start( start ), end( end ), stride( stride ) {} inline size_t count() const { return (end - start)/stride; } + + inline bool is_full() const { + return ( count() == std::numeric_limits< size_t >::max() ); + } + + inline bool is_empty() const { + return ( count() == 0 ); + } + }; } // namespace utils diff --git a/include/graphblas/views.hpp b/include/graphblas/views.hpp index 429f8f66a..b8909b018 100644 --- a/include/graphblas/views.hpp +++ b/include/graphblas/views.hpp @@ -36,6 +36,11 @@ namespace grb { namespace view { + enum Views { + original, + transpose, + diagonal + }; template< typename OriginalType > struct Original { diff --git a/tests/unit/dense_structured_matrix.cpp b/tests/unit/dense_structured_matrix.cpp index fac4f4639..762bcf34f 100644 --- a/tests/unit/dense_structured_matrix.cpp +++ b/tests/unit/dense_structured_matrix.cpp @@ -43,15 +43,14 @@ void grb_program( const size_t & n, grb::RC & rc ) { std::cout << "\tStarting structured matrices test with size: " << n << "\n"; // initialize test - grb::StructuredMatrix< float, grb::structures::General > M( n, 2 * n ); + grb::StructuredMatrix< float, grb::structures::General > M( n, n ); grb::StructuredMatrix< float, grb::structures::Square > A( n ); grb::StructuredMatrix< float, grb::structures::NonSingular > B( n, n ); grb::StructuredMatrix< float, grb::structures::FullRank > C( n, 2 * n ); - auto At = grb::transpose( A ); - auto Mt = grb::transpose( M ); - - auto Mview = grb::get_view( M ); - auto Sq_Mref = grb::get_view< grb::structures::Square > ( A ); + auto At = grb::get_view< grb::view::transpose >( A ); + auto Mt = grb::get_view< grb::view::transpose >( M ); + auto Mview = grb::get_view( M, grb::utils::range(0,4), grb::utils::range(0,4) ); + auto Sq_Mref = grb::get_view< grb::structures::Square > ( M ); ask_questions( M, "M" ); ask_questions( A, "A" ); @@ -61,11 +60,14 @@ void grb_program( const size_t & n, grb::RC & rc ) { ask_questions( At, "At" ); ask_questions( Mt, "Mt" ); ask_questions( Mview, "Mview" ); - - auto v_diag = grb::diagonal( M ); - auto v_view = grb::get_view( v_diag, std::make_shared< grb::imf::Strided >( 2, 5, 1, 1 ) ); + ask_questions( Sq_Mref, "Sq_Mref" ); + + auto v_diag = grb::get_view< grb::view::diagonal >( M ); + auto v_view1 = grb::get_view( v_diag ); + auto v_view2 = grb::get_view( v_diag, grb::utils::range(1,2) ); std::cout << "v_diag( " << grb::getLength( v_diag ) << " )" << std::endl; - std::cout << "v_view( " << grb::getLength( v_view ) << " )" << std::endl; + std::cout << "v_view1( " << grb::getLength( v_view1 ) << " )" << std::endl; + std::cout << "v_view2( " << grb::getLength( v_view2 ) << " )" << std::endl; grb::StructuredMatrix< float, grb::structures::Band< grb::Interval<-2, 5> > > BM0( n, n ); grb::StructuredMatrix< float, grb::structures::Band< grb::RightOpenInterval<-2> > > BM1( n, n ); From 00202da536e8fcd58d35070059296fb163426f2b Mon Sep 17 00:00:00 2001 From: Anonymous Date: Mon, 28 Mar 2022 09:22:31 +0000 Subject: [PATCH 118/282] !23 Resolve internal issue #370: Introduce sort operation on vectors * Move sort to level-1 functions * clean buffer and move to C++ comparators * define sort interface --- include/graphblas/denseref/blas1.hpp | 39 +++++++++++++++++++---- include/graphblas/denseref/vector.hpp | 45 +++++++++++++++------------ 2 files changed, 58 insertions(+), 26 deletions(-) diff --git a/include/graphblas/denseref/blas1.hpp b/include/graphblas/denseref/blas1.hpp index 22a895c0d..d6ac721d6 100644 --- a/include/graphblas/denseref/blas1.hpp +++ b/include/graphblas/denseref/blas1.hpp @@ -48,6 +48,7 @@ "******************************\n" ); #endif + namespace grb { /** @@ -171,8 +172,13 @@ namespace grb { // * \mathit{sizeof}(\mathit{size\_t}) \f$ bytes of data. // * \endparblock */ - template< typename DataType, typename DataStructure, typename DataStorage, typename View > - RC clear( VectorView< DataType, DataStructure, DataStorage, View, reference_dense > & x ) noexcept { + template< + typename DataType, typename DataStructure, typename DataStorage, + typename View + > + RC clear( + VectorView< DataType, DataStructure, DataStorage, View, reference_dense > &x + ) noexcept { throw std::runtime_error( "Needs an implementation" ); return SUCCESS; } @@ -3905,7 +3911,7 @@ namespace grb { if( rc != SUCCESS ) { return rc; } - /** \internal \todo: extract res.value into z */ + /** \internal \todo: extract res.value into z */ return SUCCESS; } @@ -4183,6 +4189,25 @@ namespace grb { return ret; } + /** + * Sort vectors, function available to user, e.g. to sort eigenvectors + * + * @param[in] toSort vector of indices to sort, should not be modified + * @param[in] cmp function with strict weak ordering relation between indices, eg bool cmp(const Type1 &a, const Type2 &b) + * cmp must not modify the objects passed to it + * + * @param[out] permutation iterator over index permutations which sort toSort vector + * + * Complexity should be lower than O(n*log(n)), and space complexity should be lower than \Theta(n+T+P) + */ + template< typename IndexType, typename ValueType, typename Compare > + RC sort( + Vector< IndexType > &permutation, const Vector< ValueType > &toSort, + Compare cmp, PHASE &phase = EXECUTE + ) noexcept { + return SUCCESS; + } + /** C++ scalar version */ template< Descriptor descr = descriptors::no_operation, class Ring, @@ -4190,13 +4215,15 @@ namespace grb { typename InputStructure, typename InputStorage, typename InputView, - Backend backend > - RC norm2( OutputType &x, + Backend backend + > + RC norm2( + OutputType &x, const VectorView< InputType, InputStructure, InputStorage, InputView, backend > &y, const Ring &ring = Ring(), const typename std::enable_if< std::is_floating_point< OutputType >::value, - void >::type * const = NULL + void >::type * const = nullptr ) { Scalar< OutputType, structures::General, reference_dense > res( x ); RC rc = norm2( res, y, ring ); diff --git a/include/graphblas/denseref/vector.hpp b/include/graphblas/denseref/vector.hpp index c9c23b636..7cd7b7400 100644 --- a/include/graphblas/denseref/vector.hpp +++ b/include/graphblas/denseref/vector.hpp @@ -377,6 +377,7 @@ namespace grb { class VectorView< T, Structure, storage::Dense, view::Original< void >, reference_dense > { private: + using self_type = VectorView< T, Structure, storage::Dense, view::Original< void >, reference_dense >; /********************* @@ -395,7 +396,9 @@ namespace grb { return imf->n; } + public: + /** @see Vector::value_type. */ using value_type = T; @@ -444,6 +447,7 @@ namespace grb { class VectorView< T, Structure, storage::Dense, view::Original< VectorViewT >, reference_dense > { private: + using self_type = VectorView< T, Structure, storage::Dense, view::Original< VectorViewT >, reference_dense >; using target_type = VectorViewT; @@ -464,6 +468,7 @@ namespace grb { } public: + /** Exposes the element type. */ using value_type = T; @@ -517,6 +522,7 @@ namespace grb { class VectorView< T, Structure, storage::Dense, view::Diagonal< StructuredMatrixT >, reference_dense > { private: + /** Exposes the own type and the type of the VectorView object over * which this view is created. */ using self_type = VectorView< T, Structure, storage::Dense, view::Diagonal< StructuredMatrixT >, reference_dense >; @@ -539,6 +545,7 @@ namespace grb { } public: + /** Exposes the element type. */ using value_type = T; @@ -591,19 +598,20 @@ namespace grb { * * @returns A new vector VectorView object. * - * \parblock - * \par Performance semantics. - * -# This function performs - * \f$ \Theta(nref) \f$ amount of work where \f$ nref \f$ is the number + * \parblock + * \par Performance semantics. + * -# This function performs + * \f$ \Theta(nref) \f$ amount of work where \f$ nref \f$ is the number * of available views of \a source. - * -# A call to this function may use \f$ \mathcal{O}(1) \f$ bytes - * of memory beyond the memory in use at the function call entry. - * -# This function may make system calls. - * \endparblock + * -# A call to this function may use \f$ \mathcal{O}(1) \f$ bytes + * of memory beyond the memory in use at the function call entry. + * -# This function may make system calls. + * \endparblock * */ template< - typename T, typename Structure, typename StorageSchemeType, typename View, enum Backend backend > + typename T, typename Structure, typename StorageSchemeType, typename View, enum Backend backend + > typename VectorView< T, Structure, StorageSchemeType, View, backend >::template view_type< view::original >::type get_view( VectorView< T, Structure, StorageSchemeType, View, backend > & source ) { @@ -625,18 +633,17 @@ namespace grb { * * @returns A VectorView object. * - * \parblock - * \par Performance semantics. - * -# This function performs - * \f$ \Theta(nref) \f$ amount of work where \f$ nref \f$ is the number + * \parblock + * \par Performance semantics. + * -# This function performs + * \f$ \Theta(nref) \f$ amount of work where \f$ nref \f$ is the number * of available views of \a source. - * -# A call to this function may use \f$ \mathcal{O}(1) \f$ bytes - * of memory beyond the memory in use at the function call entry. - * -# This function may make system calls. - * \endparblock + * -# A call to this function may use \f$ \mathcal{O}(1) \f$ bytes + * of memory beyond the memory in use at the function call entry. + * -# This function may make system calls. + * \endparblock * */ - template< typename T, typename Structure, typename View, typename StorageSchemeType, enum Backend backend > typename VectorView< T, Structure, StorageSchemeType, View, backend >::template view_type< view::original >::type get_view( VectorView< T, Structure, StorageSchemeType, View, backend > &source, const utils::range& rng ) { @@ -647,8 +654,6 @@ namespace grb { return vec_view; } - - } // end namespace ``grb'' #endif // end ``_H_GRB_DENSEREF_VECTOR'' From 0b0d7fb577affb140b0fdcaefa9b11b7476bc2fe Mon Sep 17 00:00:00 2001 From: Anonymous Date: Tue, 29 Mar 2022 08:35:11 +0000 Subject: [PATCH 119/282] !32 Resolve internal issue #378: Convert grb storage from namespace to enum This enum now has two values - Dense and Sparse. The actual implementation of the storage scheme will be handled by the Storage Mapping Functions. --- include/graphblas/base/matrix.hpp | 20 +- include/graphblas/base/vector.hpp | 3 +- include/graphblas/denseref/blas1.hpp | 632 ++++++++++++-------------- include/graphblas/denseref/blas2.hpp | 166 +++---- include/graphblas/denseref/blas3.hpp | 75 ++- include/graphblas/denseref/io.hpp | 4 +- include/graphblas/denseref/matrix.hpp | 327 ++++++------- include/graphblas/denseref/scalar.hpp | 4 +- include/graphblas/denseref/vector.hpp | 86 ++-- include/graphblas/density.hpp | 64 +++ include/graphblas/matrix.hpp | 4 +- include/graphblas/storage.hpp | 92 ---- include/graphblas/vector.hpp | 4 +- 13 files changed, 697 insertions(+), 784 deletions(-) create mode 100644 include/graphblas/density.hpp delete mode 100644 include/graphblas/storage.hpp diff --git a/include/graphblas/base/matrix.hpp b/include/graphblas/base/matrix.hpp index 065203a1e..597ccd468 100644 --- a/include/graphblas/base/matrix.hpp +++ b/include/graphblas/base/matrix.hpp @@ -33,7 +33,7 @@ #include #include #include -#include +#include #include #include #include @@ -437,7 +437,7 @@ RC clear( Matrix< InputType, backend > & A ) noexcept { return UNSUPPORTED; } -template< typename T, typename Structure, typename StorageSchemeType, typename View, enum Backend backend > +template< typename T, typename Structure, enum Density density, typename View, enum Backend backend > class StructuredMatrix { /** @@ -470,10 +470,12 @@ class StructuredMatrix { * If \a backend is set to \a mlir then the scheme could be fixed by the JIT compiler to effectively * support its optimization strategy. * At construction time and until the moment the scheme decision is made it may be set to - * an appropriate default choice, e.g. if \a StorageSchemeType is \a storage::Dense then - * \a storage::Dense::full could be used. + * an appropriate default choice, e.g. if \a density is \a Density::Dense then + * \a Density::Dense::full could be used. + * \internal \todo Revisit this. The change of storage scheme type to enum (dense/sparse) and + * implementing storage mapping functions requires a change of this spec. */ - StorageSchemeType storage_scheme; + // Storage storage_scheme; /** * When a structured matrix defines a View over another matrix, it contains a pointer @@ -486,9 +488,9 @@ class StructuredMatrix { StructuredMatrix( const size_t m, const size_t n ); - StructuredMatrix( const StructuredMatrix< T, Structure, StorageSchemeType, View, backend > & other ); + StructuredMatrix( const StructuredMatrix< T, Structure, density, View, backend > & other ); - StructuredMatrix( StructuredMatrix< T, Structure, StorageSchemeType, View, backend > && other ); + StructuredMatrix( StructuredMatrix< T, Structure, density, View, backend > && other ); ~StructuredMatrix(); @@ -499,8 +501,8 @@ class StructuredMatrix { */ template< typename T > struct is_structured_matrix : std::false_type {}; -template< typename T, typename Structure, typename StorageSchemeType, typename View, enum Backend backend > -struct is_structured_matrix< StructuredMatrix< T, Structure, StorageSchemeType, View, backend > > : std::true_type {}; +template< typename T, typename Structure, enum Density density, typename View, enum Backend backend > +struct is_structured_matrix< StructuredMatrix< T, Structure, density, View, backend > > : std::true_type {}; } // end namespace ``grb'' diff --git a/include/graphblas/base/vector.hpp b/include/graphblas/base/vector.hpp index efdab2dfb..0c6504831 100644 --- a/include/graphblas/base/vector.hpp +++ b/include/graphblas/base/vector.hpp @@ -32,6 +32,7 @@ #include #include #include +#include namespace grb { @@ -900,7 +901,7 @@ namespace grb { } }; - template< typename T, typename Structure, typename StorageSchemeType, typename View, enum Backend backend > + template< typename T, typename Structure, enum Density density, typename View, enum Backend backend > class VectorView { }; } diff --git a/include/graphblas/denseref/blas1.hpp b/include/graphblas/denseref/blas1.hpp index d6ac721d6..fea5e36ca 100644 --- a/include/graphblas/denseref/blas1.hpp +++ b/include/graphblas/denseref/blas1.hpp @@ -27,7 +27,7 @@ #include #include #include -#include +#include #ifndef NO_CAST_ASSERT #define NO_CAST_ASSERT( x, y, z ) \ @@ -173,11 +173,10 @@ namespace grb { // * \endparblock */ template< - typename DataType, typename DataStructure, typename DataStorage, - typename View + typename DataType, typename DataStructure, typename View > RC clear( - VectorView< DataType, DataStructure, DataStorage, View, reference_dense > &x + VectorView< DataType, DataStructure, Density::Dense, View, reference_dense > &x ) noexcept { throw std::runtime_error( "Needs an implementation" ); return SUCCESS; @@ -191,7 +190,6 @@ namespace grb { * * @tparam DataType The type of elements contained in the vector \a x. * @tparam DataStructure The structure of the vector \a x. - * @tparam DataStorage The type of storage of the vector \a x. * @tparam View The view type applied to the vector \a x. * * @param[in] x The VectorView of which to retrieve the size. @@ -207,8 +205,8 @@ namespace grb { // * -# shall not make any system calls. // * \endparblock */ - template< typename DataType, typename DataStructure, typename DataStorage, typename View > - size_t size( const VectorView< DataType, DataStructure, DataStorage, View, reference_dense > & x ) noexcept { + template< typename DataType, typename DataStructure, typename View > + size_t size( const VectorView< DataType, DataStructure, Density::Dense, View, reference_dense > & x ) noexcept { return getLength( x ); } @@ -219,7 +217,6 @@ namespace grb { * * @tparam DataType The type of elements contained in the vector \a x. * @tparam DataStructure The structure of the vector \a x. - * @tparam DataStorage The type of storage of the vector \a x. * @tparam View The view type applied to the vector \a x. * * @param[in] x The VectorView of which to retrieve the number of nonzeroes. @@ -235,8 +232,8 @@ namespace grb { // * -# shall not make any system calls. // * \endparblock */ - template< typename DataType, typename DataStructure, typename DataStorage, typename View > - size_t nnz( const VectorView< DataType, DataStructure, DataStorage, View, reference_dense > & x ) noexcept { + template< typename DataType, typename DataStructure, typename View > + size_t nnz( const VectorView< DataType, DataStructure, Density::Dense, View, reference_dense > & x ) noexcept { throw std::runtime_error( "Needs an implementation." ); return 0; } @@ -270,8 +267,8 @@ namespace grb { * \endparblock * \todo add documentation. In particular, think about the meaning with \a P > 1. */ - template< typename InputType, typename InputStructure, typename InputStorage, typename View, typename length_type > - RC resize( VectorView< InputType, InputStructure, InputStorage, View, reference_dense > & x, const length_type new_nz ) { + template< typename InputType, typename InputStructure, typename View, typename length_type > + RC resize( VectorView< InputType, InputStructure, Density::Dense, View, reference_dense > &x, const length_type new_nz ) { (void)x; (void)new_nz; // TODO implement @@ -299,7 +296,6 @@ namespace grb { * @tparam descr The descriptor used for this operation. * @tparam DataType The type of each element in the vector \a x. * @tparam DataStructure The structure of the vector \a x. - * @tparam DataStorage The type of storage of the vector \a x. * @tparam View The view type applied to the vector \a x. * @tparam T The type of the given value. * @@ -335,8 +331,8 @@ namespace grb { */ template< Descriptor descr = descriptors::no_operation, - typename DataType, typename DataStructure, typename ValStructure, typename DataStorage, typename View, typename T > - RC set( VectorView< DataType, DataStructure, DataStorage, View, reference_dense > & x, + typename DataType, typename DataStructure, typename ValStructure, typename View, typename T > + RC set( VectorView< DataType, DataStructure, Density::Dense, View, reference_dense > & x, const Scalar< T, ValStructure, reference_dense > val, const typename std::enable_if< !grb::is_object< DataType >::value && @@ -373,7 +369,6 @@ namespace grb { * @tparam descr The descriptor used for this operation. * @tparam DataType The type of each element in the given vector. * @tparam DataStructure The Structure of the given vector. - * @tparam DataStorage Storage Scheme type applied in the given vector. * @tparam View The view type applied to the given vector. * @tparam T The type of the given value. * @@ -412,11 +407,11 @@ namespace grb { * @see grb::setElement. */ template< Descriptor descr = descriptors::no_operation, - typename DataType, typename DataView, typename DataStructure, typename DataStorage, - typename MaskStructure, typename MaskStorage, typename MaskType, typename MaskView, + typename DataType, typename DataView, typename DataStructure, + typename MaskStructure, typename MaskType, typename MaskView, typename T, typename ValStructure > - RC set( VectorView< DataType, DataStructure, DataStorage, DataView, reference_dense > & x, - const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense > & m, + RC set( VectorView< DataType, DataStructure, Density::Dense, DataView, reference_dense > & x, + const VectorView< MaskType, MaskStructure, Density::Dense, MaskView, reference_dense > & m, const Scalar< T, ValStructure, reference_dense > val, const typename std::enable_if< ! grb::is_object< DataType >::value && ! grb::is_object< T >::value, void >::type * const = NULL ) { #ifdef _DEBUG @@ -448,11 +443,11 @@ namespace grb { /** C++ scalar variant */ template< Descriptor descr = descriptors::no_operation, - typename DataType, typename DataView, typename DataStructure, typename DataStorage, - typename MaskStructure, typename MaskStorage, typename MaskType, typename MaskView, + typename DataType, typename DataView, typename DataStructure, + typename MaskStructure, typename MaskType, typename MaskView, typename T > - RC set( VectorView< DataType, DataStructure, DataStorage, DataView, reference_dense > & x, - const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense > & m, + RC set( VectorView< DataType, DataStructure, Density::Dense, DataView, reference_dense > & x, + const VectorView< MaskType, MaskStructure, Density::Dense, MaskView, reference_dense > & m, const T val, const typename std::enable_if< ! grb::is_object< DataType >::value && ! grb::is_object< T >::value, void >::type * const = NULL ) { #ifdef _DEBUG @@ -481,7 +476,6 @@ namespace grb { * function. * @tparam DataType The type of the elements of \a x. * @tparam DataStructure The structure of the vector \a x. - * @tparam DataStorage The storage scheme type applied to the vector \a x. * @tparam View The view type applied to the vector \a x. * @tparam T The type of the value to be set. * @@ -511,8 +505,8 @@ namespace grb { // * -# shall not make any system calls. // * \endparblock */ - template< Descriptor descr = descriptors::no_operation, typename DataType, typename DataStructure, typename ValStructure, typename DataStorage, typename View, typename T > - RC setElement( VectorView< DataType, DataStructure, DataStorage, View, reference_dense > & x, + template< Descriptor descr = descriptors::no_operation, typename DataType, typename DataStructure, typename ValStructure, typename View, typename T > + RC setElement( VectorView< DataType, DataStructure, Density::Dense, View, reference_dense > & x, const Scalar< T, ValStructure, reference_dense > val, const size_t i, const typename std::enable_if< ! grb::is_object< DataType >::value && ! grb::is_object< T >::value, void >::type * const = NULL ) { @@ -528,8 +522,8 @@ namespace grb { } /** C++ scalar variant */ - template< Descriptor descr = descriptors::no_operation, typename DataType, typename DataStructure, typename ValStructure, typename DataStorage, typename View, typename T > - RC setElement( VectorView< DataType, DataStructure, DataStorage, View, reference_dense > & x, + template< Descriptor descr = descriptors::no_operation, typename DataType, typename DataStructure, typename ValStructure, typename View, typename T > + RC setElement( VectorView< DataType, DataStructure, Density::Dense, View, reference_dense > & x, const T val, const size_t i, const typename std::enable_if< ! grb::is_object< DataType >::value && ! grb::is_object< T >::value, void >::type * const = NULL ) { @@ -574,8 +568,6 @@ namespace grb { * @tparam InputType The type of each element in the input vector. * @tparam OutputStructure The structure of the ouput vector. * @tparam InputStructure The structure of the input vector. - * @tparam OutputStorage The storage scheme applied to the output vector. - * @tparam InputStorage The storage scheme applied to the input vector. * @tparam OuputView The view applied to the output vector. * @tparam InputView The view applied to the input vector. * @@ -600,8 +592,8 @@ namespace grb { * @see grb::operators::right_assign. * @see grb::setElement. */ - template< Descriptor descr = descriptors::no_operation, typename OutputType, typename InputType, typename OutputStructure, typename OutputStorage, typename InputStructure, typename InputStorage, typename OutputView, typename InputView > - RC set( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > & x, const VectorView< InputType, InputStructure, InputStorage, InputView, reference_dense > & y ) { + template< Descriptor descr = descriptors::no_operation, typename OutputType, typename InputType, typename OutputStructure, typename InputStructure, typename OutputView, typename InputView > + RC set( VectorView< OutputType, OutputStructure, Density::Dense, OutputView, reference_dense > & x, const VectorView< InputType, InputStructure, Density::Dense, InputView, reference_dense > & y ) { // static sanity checks NO_CAST_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< OutputType, InputType >::value ), "grb::copy (Vector)", "called with vector parameters whose element data types do not match" ); @@ -655,9 +647,6 @@ namespace grb { * @tparam OutputStructure The structure of the output vector. * @tparam MaskStructure The structure of the mask vector. * @tparam InputStructure The structure of the input vector. - * @tparam OutputStorage The storage scheme type of the output vector. - * @tparam MaskStorage The storage scheme type of the mask vector. - * @tparam InputStorage The storage scheme type of the input vector. * @tparam OutputView The view applied to the output vector. * @tparam MaskView The view applied to the mask vector. * @tparam InputView The view applied to the input vector. @@ -697,11 +686,11 @@ namespace grb { template< Descriptor descr = descriptors::no_operation, typename OutputType, typename MaskType, typename InputType, typename OutputStructure, typename MaskStructure, typename InputStructure, - typename OutputStorage, typename MaskStorage, typename InputStorage, + typename OutputView, typename MaskView, typename InputView > - RC set( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > & x, - const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense > & mask, - const VectorView< InputType, InputStructure, InputStorage, InputView, reference_dense > & y, + RC set( VectorView< OutputType, OutputStructure, Density::Dense, OutputView, reference_dense > & x, + const VectorView< MaskType, MaskStructure, Density::Dense, MaskView, reference_dense > & mask, + const VectorView< InputType, InputStructure, Density::Dense, InputView, reference_dense > & y, const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType >::value, void >::type * const = NULL ) { // static sanity checks NO_CAST_ASSERT( @@ -745,7 +734,6 @@ namespace grb { * @tparam InputType The type of the elements of \a x. * @tparam IOType The type of the value \a y. * @tparam InputStructure The structure of the vector \a x. - * @tparam InputStorage The type of storage scheme of the vector \a x. * @tparam InputView The view type applied to the vector \a x. * * @param[in] x The input VectorView \a x that will not be modified. @@ -809,8 +797,8 @@ namespace grb { * and/or vectorised operations are used. */ template< Descriptor descr = descriptors::no_operation, class Monoid, - typename InputType, typename InputStructure, typename InputStorage, typename InputView, typename IOType, typename IOStructure > - RC foldr( const VectorView< InputType, InputStructure, InputStorage, InputView, reference_dense > & x, + typename InputType, typename InputStructure, typename InputView, typename IOType, typename IOStructure > + RC foldr( const VectorView< InputType, InputStructure, Density::Dense, InputView, reference_dense > & x, Scalar< IOType, IOStructure, reference_dense > & beta, const Monoid & monoid = Monoid(), const typename std::enable_if< ! grb::is_object< InputType >::value && ! grb::is_object< IOType >::value && grb::is_monoid< Monoid >::value, void >::type * const = NULL ) { @@ -821,8 +809,8 @@ namespace grb { /** C++ scalar variant */ template< Descriptor descr = descriptors::no_operation, class Monoid, - typename InputType, typename InputStructure, typename InputStorage, typename InputView, typename IOType > - RC foldr( const VectorView< InputType, InputStructure, InputStorage, InputView, reference_dense > & x, + typename InputType, typename InputStructure, typename InputView, typename IOType > + RC foldr( const VectorView< InputType, InputStructure, Density::Dense, InputView, reference_dense > & x, IOType & beta, const Monoid & monoid = Monoid(), const typename std::enable_if< ! grb::is_object< InputType >::value && ! grb::is_object< IOType >::value && grb::is_monoid< Monoid >::value, void >::type * const = NULL ) { @@ -848,7 +836,6 @@ namespace grb { * @tparam InputType The type of \a alpha. * @tparam IOType The type of the elements in \a y. * @tparam IOStructure The structure of the vector \a y. - * @tparam IOStorage The type of storage scheme of the vector \a y. * @tparam IOView The view applied to the vector \a y. * * @param[in] alpha The input value to apply as the left-hand side input @@ -902,9 +889,9 @@ namespace grb { * @see grb::operators::internal::Operator for a discussion on when in-place * and/or vectorised operations are used. */ - template< Descriptor descr = descriptors::no_operation, class Monoid, typename IOType, typename InputType, typename IOStructure, typename InputStructure, typename IOStorage, typename IOView > + template< Descriptor descr = descriptors::no_operation, class Monoid, typename IOType, typename InputType, typename IOStructure, typename InputStructure, typename IOView > RC foldr( const Scalar< InputType, InputStructure, reference_dense > & alpha, - VectorView< IOType, IOStructure, IOStorage, IOView, reference_dense > & y, + VectorView< IOType, IOStructure, Density::Dense, IOView, reference_dense > & y, const Monoid & monoid = Monoid(), const typename std::enable_if< ! grb::is_object< InputType >::value && ! grb::is_object< IOType >::value && grb::is_monoid< Monoid >::value, void >::type * const = NULL ) { // static sanity checks @@ -927,9 +914,9 @@ namespace grb { * * Specialisation for scalar \a x. */ - template< Descriptor descr = descriptors::no_operation, class OP, typename IOType, typename InputType, typename IOStructure, typename InputStructure, typename IOStorage, typename IOView > + template< Descriptor descr = descriptors::no_operation, class OP, typename IOType, typename InputType, typename IOStructure, typename InputStructure, typename IOView > RC foldr( const Scalar< InputType, InputStructure, reference_dense > & alpha, - VectorView< IOType, IOStructure, IOStorage, IOView, reference_dense > & y, + VectorView< IOType, IOStructure, Density::Dense, IOView, reference_dense > & y, const OP & op = OP(), const typename std::enable_if< ! grb::is_object< InputType >::value && ! grb::is_object< IOType >::value && grb::is_operator< OP >::value, void >::type * const = NULL ) { // static sanity checks @@ -961,8 +948,6 @@ namespace grb { * @tparam InputType The type of the elements of \a x. * @tparam IOStructure The structure of the vector \a y. * @tparam InputStructure The structure of the vector \a x. - * @tparam IOStorage The type of storage scheme of the vector \a y. - * @tparam InputStorage The type of storage scheme of the vector \a x. * @tparam IOView The View applied on the vector \a y. * @tparam InputView The View applied on the vector \a x. * @@ -1024,10 +1009,10 @@ namespace grb { template< Descriptor descr = descriptors::no_operation, class OP, typename IOType, typename InputType, typename IOStructure, typename InputStructure, - typename IOStorage, typename InputStorage, + typename IOView, typename InputView > - RC foldr( const VectorView< InputType, InputStructure, InputStorage, InputView, reference_dense > & x, - VectorView< IOType, IOStructure, IOStorage, IOView, reference_dense > & y, + RC foldr( const VectorView< InputType, InputStructure, Density::Dense, InputView, reference_dense > & x, + VectorView< IOType, IOStructure, Density::Dense, IOView, reference_dense > & y, const OP & op = OP(), const typename std::enable_if< grb::is_operator< OP >::value && ! grb::is_object< InputType >::value && ! grb::is_object< IOType >::value, void >::type * = NULL ) { // static sanity checks @@ -1057,11 +1042,11 @@ namespace grb { template< Descriptor descr = descriptors::no_operation, class OP, typename IOType, typename MaskType, typename InputType, typename IOStructure, typename MaskStructure, typename InputStructure, - typename IOStorage, typename MaskStorage, typename InputStorage, + typename IOView, typename MaskView, typename InputView > - RC foldr( const VectorView< InputType, InputStructure, InputStorage, InputView, reference_dense > & x, - const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense > & m, - VectorView< IOType, IOStructure, IOStorage, IOView, reference_dense > & y, + RC foldr( const VectorView< InputType, InputStructure, Density::Dense, InputView, reference_dense > & x, + const VectorView< MaskType, MaskStructure, Density::Dense, MaskView, reference_dense > & m, + VectorView< IOType, IOStructure, Density::Dense, IOView, reference_dense > & y, const OP & op = OP(), const typename std::enable_if< grb::is_operator< OP >::value && ! grb::is_object< InputType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< IOType >::value, void >::type * = NULL ) { @@ -1104,8 +1089,6 @@ namespace grb { * @tparam InputType The type of the elements of \a x. * @tparam IOStructure The structure of the vector \a y. * @tparam InputStructure The structure of the vector \a x. - * @tparam IOStorage The type of storage scheme of the vector \a y. - * @tparam InputStorage The type of storage scheme of the vector \a x. * @tparam IOView The view type applied to the vector \a y. * @tparam InputView The view type applied to the vector \a x. * @@ -1167,10 +1150,10 @@ namespace grb { template< Descriptor descr = descriptors::no_operation, class Monoid, typename IOType, typename InputType, typename IOStructure, typename InputStructure, - typename IOStorage, typename InputStorage, + typename IOView, typename InputView > - RC foldr( const VectorView< InputType, InputStructure, InputStorage, InputView, reference_dense > & x, - VectorView< IOType, IOStructure, IOStorage, IOView, reference_dense > & y, + RC foldr( const VectorView< InputType, InputStructure, Density::Dense, InputView, reference_dense > & x, + VectorView< IOType, IOStructure, Density::Dense, IOView, reference_dense > & y, const Monoid & monoid = Monoid(), const typename std::enable_if< grb::is_monoid< Monoid >::value && ! grb::is_object< InputType >::value && ! grb::is_object< IOType >::value, void >::type * = NULL ) { // static sanity checks @@ -1202,11 +1185,11 @@ namespace grb { template< Descriptor descr = descriptors::no_operation, class Monoid, typename IOType, typename MaskType, typename InputType, typename IOStructure, typename MaskStructure, typename InputStructure, - typename IOStorage, typename MaskStorage, typename InputStorage, + typename IOView, typename MaskView, typename InputView > - RC foldr( const VectorView< InputType, InputStructure, InputStorage, InputView, reference_dense > & x, - const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense > & m, - VectorView< IOType, IOStructure, IOStorage, IOView, reference_dense > & y, + RC foldr( const VectorView< InputType, InputStructure, Density::Dense, InputView, reference_dense > & x, + const VectorView< MaskType, MaskStructure, Density::Dense, MaskView, reference_dense > & m, + VectorView< IOType, IOStructure, Density::Dense, IOView, reference_dense > & y, const Monoid & monoid = Monoid(), const typename std::enable_if< grb::is_monoid< Monoid >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType >::value && ! grb::is_object< IOType >::value, void >::type * = NULL ) { @@ -1256,7 +1239,6 @@ namespace grb { * @tparam IOType The type of the value \a beta. * @tparam InputType The type of the elements of \a x. * @tparam IOStructure The structure of the vector \a x. - * @tparam IOStorage The type of storage scheme of the vector \a x. * @tparam IOView The view type applied to the vector \a x. * * @param[in,out] x On function entry: the initial values to be applied as @@ -1314,8 +1296,8 @@ namespace grb { * @see grb::operators::internal::Operator for a discussion on when in-place * and/or vectorised operations are used. */ - template< Descriptor descr = descriptors::no_operation, class Op, typename IOType, typename InputType, typename IOStructure, typename InputStructure, typename IOStorage, typename IOView > - RC foldl( VectorView< IOType, IOStructure, IOStorage, IOView, reference_dense > & x, + template< Descriptor descr = descriptors::no_operation, class Op, typename IOType, typename InputType, typename IOStructure, typename InputStructure, typename IOView > + RC foldl( VectorView< IOType, IOStructure, Density::Dense, IOView, reference_dense > & x, const Scalar< InputType, InputStructure, reference_dense > beta, const Op & op = Op(), const typename std::enable_if< ! grb::is_object< IOType >::value && ! grb::is_object< InputType >::value && grb::is_operator< Op >::value, void >::type * = NULL ) { @@ -1343,10 +1325,10 @@ namespace grb { template< Descriptor descr = descriptors::no_operation, class Op, typename IOType, typename MaskType, typename InputType, typename IOStructure, typename MaskStructure, typename InputStructure, - typename IOStorage, typename MaskStorage, + typename IOView, typename MaskView, typename InputView > - RC foldl( VectorView< IOType, IOStructure, IOStorage, IOView, reference_dense > & x, - const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense > & m, + RC foldl( VectorView< IOType, IOStructure, Density::Dense, IOView, reference_dense > & x, + const VectorView< MaskType, MaskStructure, Density::Dense, MaskView, reference_dense > & m, const Scalar< InputType, InputStructure, reference_dense > &beta, const Op & op = Op(), const typename std::enable_if< ! grb::is_object< IOType >::value && ! grb::is_object< InputType >::value && grb::is_operator< Op >::value, void >::type * = NULL ) { @@ -1388,7 +1370,6 @@ namespace grb { * @tparam IOType The type of the elements of \a x. * @tparam InputType The type of the value \a beta. * @tparam IOStructure The structure of the vector \a x. - * @tparam IOStorage The type of storage scheme of the vector \a x. * @tparam IOView The view type applied to the vector \a x. * * @param[in,out] x On function entry: the initial values to be applied as @@ -1442,8 +1423,8 @@ namespace grb { * @see grb::operators::internal::Operator for a discussion on when in-place * and/or vectorised operations are used. */ - template< Descriptor descr = descriptors::no_operation, class Monoid, typename IOType, typename InputType, typename IOStructure, typename IOStorage, typename IOView > - RC foldl( VectorView< IOType, IOStructure, IOStorage, IOView, reference_dense > & x, + template< Descriptor descr = descriptors::no_operation, class Monoid, typename IOType, typename InputType, typename IOStructure, typename IOView > + RC foldl( VectorView< IOType, IOStructure, Density::Dense, IOView, reference_dense > & x, const InputType beta, const Monoid & monoid = Monoid(), const typename std::enable_if< ! grb::is_object< IOType >::value && ! grb::is_object< InputType >::value && grb::is_monoid< Monoid >::value, void >::type * = NULL ) { @@ -1471,10 +1452,10 @@ namespace grb { template< Descriptor descr = descriptors::no_operation, class Monoid, typename IOType, typename MaskType, typename InputType, typename IOStructure, typename MaskStructure, - typename IOStorage, typename MaskStorage, + typename IOView, typename MaskView > - RC foldl( VectorView< IOType, IOStructure, IOStorage, IOView, reference_dense > & x, - const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense > & m, + RC foldl( VectorView< IOType, IOStructure, Density::Dense, IOView, reference_dense > & x, + const VectorView< MaskType, MaskStructure, Density::Dense, MaskView, reference_dense > & m, const InputType & beta, const Monoid & monoid = Monoid(), const typename std::enable_if< ! grb::is_object< IOType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType >::value && grb::is_monoid< Monoid >::value, void >::type * = @@ -1513,8 +1494,6 @@ namespace grb { * @tparam InputType The type of the elements of \a y. * @tparam IOStructure The structure of the vector \a x. * @tparam InputStructure The structure of the vector \a y. - * @tparam IOStorage The type of storage scheme of the vector \a x. - * @tparam InputStorage The type of storage scheme of the vector \a y. * @tparam IOView The view type applied to the vector \a x. * @tparam InputView The view type applied to the vector \a y. * @@ -1578,10 +1557,9 @@ namespace grb { template< Descriptor descr = descriptors::no_operation, class OP, typename IOType, typename InputType, typename IOStructure, typename InputStructure, - typename IOStorage, typename InputStorage, typename IOView, typename InputView > - RC foldl( VectorView< IOType, IOStructure, IOStorage, IOView, reference_dense > & x, - const VectorView< InputType, InputStructure, InputStorage, InputView, reference_dense > & y, + RC foldl( VectorView< IOType, IOStructure, Density::Dense, IOView, reference_dense > & x, + const VectorView< InputType, InputStructure, Density::Dense, InputView, reference_dense > & y, const OP & op = OP(), const typename std::enable_if< grb::is_operator< OP >::value && ! grb::is_object< IOType >::value && ! grb::is_object< InputType >::value, void >::type * = NULL ) { // static sanity checks @@ -1619,8 +1597,6 @@ namespace grb { * @tparam InputType The type of the elements of \a y. * @tparam IOStructure The structure of the vector \a x. * @tparam InputStructure The structure of the vector \a y. - * @tparam IOStorage The type of storage scheme of the vector \a x. - * @tparam InputStorage The type of storage scheme of the vector \a y. * @tparam IOView The view type applied to the vector \a x. * @tparam InputView The view type applied to the vector \a y. * @@ -1684,10 +1660,10 @@ namespace grb { template< Descriptor descr = descriptors::no_operation, class Monoid, typename IOType, typename InputType, typename IOStructure, typename InputStructure, - typename IOStorage, typename InputStorage, + typename IOView, typename InputView > - RC foldl( VectorView< IOType, IOStructure, IOStorage, IOView, reference_dense > & x, - const VectorView< InputType, InputStructure, InputStorage, InputView, reference_dense > & y, + RC foldl( VectorView< IOType, IOStructure, Density::Dense, IOView, reference_dense > & x, + const VectorView< InputType, InputStructure, Density::Dense, InputView, reference_dense > & y, const Monoid & monoid = Monoid(), const typename std::enable_if< grb::is_monoid< Monoid >::value && ! grb::is_object< IOType >::value && ! grb::is_object< InputType >::value, void >::type * = NULL ) { // static sanity checks @@ -1719,11 +1695,11 @@ namespace grb { template< Descriptor descr = descriptors::no_operation, class OP, typename IOType, typename MaskType, typename InputType, typename IOStructure, typename MaskStructure, typename InputStructure, - typename IOStorage, typename MaskStorage, typename InputStorage, + typename IOView, typename MaskView, typename InputView > - RC foldl( VectorView< IOType, IOStructure, IOStorage, IOView, reference_dense > & x, - const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense > & m, - const VectorView< InputType, InputStructure, InputStorage, InputView, reference_dense > & y, + RC foldl( VectorView< IOType, IOStructure, Density::Dense, IOView, reference_dense > & x, + const VectorView< MaskType, MaskStructure, Density::Dense, MaskView, reference_dense > & m, + const VectorView< InputType, InputStructure, Density::Dense, InputView, reference_dense > & y, const OP & op = OP(), const typename std::enable_if< grb::is_operator< OP >::value && ! grb::is_object< IOType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType >::value, void >::type * = NULL ) { @@ -1762,11 +1738,11 @@ namespace grb { template< Descriptor descr = descriptors::no_operation, class Monoid, typename IOType, typename MaskType, typename InputType, typename IOStructure, typename MaskStructure, typename InputStructure, - typename IOStorage, typename MaskStorage, typename InputStorage, + typename IOView, typename MaskView, typename InputView > - RC foldl( VectorView< IOType, IOStructure, IOStorage, IOView, reference_dense > & x, - const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense > & m, - const VectorView< InputType, InputStructure, InputStorage, InputView, reference_dense > & y, + RC foldl( VectorView< IOType, IOStructure, Density::Dense, IOView, reference_dense > & x, + const VectorView< MaskType, MaskStructure, Density::Dense, MaskView, reference_dense > & m, + const VectorView< InputType, InputStructure, Density::Dense, InputView, reference_dense > & y, const Monoid & monoid = Monoid(), const typename std::enable_if< grb::is_monoid< Monoid >::value && ! grb::is_object< IOType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType >::value, void >::type * = NULL ) { @@ -1832,8 +1808,6 @@ namespace grb { * @tparam OutputType The value type of the ouput vector. * @tparam InputStructure1 The structure of the left-hand vector. * @tparam OutputStructure1 The structure of the output vector. - * @tparam InputStorage1 The storage type of the left-hand vector. - * @tparam OutputStorage1 The storage type of the output vector. * @tparam InputView1 The view type applied to the left-hand vector. * @tparam OutputView1 The view type applied to the output vector. * @@ -1873,10 +1847,10 @@ namespace grb { template< Descriptor descr = descriptors::no_operation, class OP, typename OutputType, typename InputType1, typename InputType2, typename OutputStructure, typename InputStructure1, typename InputStructure2, - typename OutputStorage, typename InputStorage1, + typename OutputView, typename InputView1 > - RC eWiseApply( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > & z, - const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense > & x, + RC eWiseApply( VectorView< OutputType, OutputStructure, Density::Dense, OutputView, reference_dense > & z, + const VectorView< InputType1, InputStructure1, Density::Dense, InputView1, reference_dense > & x, const Scalar< InputType2, InputStructure2, reference_dense > &beta, const OP & op = OP(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_operator< OP >::value, @@ -1896,9 +1870,9 @@ namespace grb { template< Descriptor descr = descriptors::no_operation, class OP, typename OutputType, typename InputType1, typename InputType2, typename OutputStructure, typename InputStructure1, typename InputStructure2, - typename OutputStorage, + typename OutputView > - RC eWiseApply( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > & z, + RC eWiseApply( VectorView< OutputType, OutputStructure, Density::Dense, OutputView, reference_dense > & z, const Scalar< InputType1, InputStructure1, reference_dense> &alpha, const Scalar< InputType2, InputStructure2, reference_dense> &beta, const OP & op = OP(), @@ -1921,9 +1895,9 @@ namespace grb { template< Descriptor descr = descriptors::no_operation, class Monoid, typename OutputType, typename InputType1, typename InputType2, typename OutputStructure, typename InputStructure1, typename InputStructure2, - typename OutputStorage, + typename OutputView > - RC eWiseApply( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > & z, + RC eWiseApply( VectorView< OutputType, OutputStructure, Density::Dense, OutputView, reference_dense > & z, const Scalar< InputType1, InputStructure1, reference_dense> &alpha, const Scalar< InputType2, InputStructure2, reference_dense> &beta, const Monoid & monoid = Monoid(), @@ -1944,11 +1918,11 @@ namespace grb { template< Descriptor descr = descriptors::no_operation, class OP, typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename OutputStructure, typename MaskStructure, typename InputStructure1, typename InputStructure2, - typename OutputStorage, typename MaskStorage, typename InputStorage1, + typename OutputView, typename MaskView, typename InputView1 > - RC eWiseApply( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > & z, - const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense > & mask, - const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense > & x, + RC eWiseApply( VectorView< OutputType, OutputStructure, Density::Dense, OutputView, reference_dense > & z, + const VectorView< MaskType, MaskStructure, Density::Dense, MaskView, reference_dense > & mask, + const VectorView< InputType1, InputStructure1, Density::Dense, InputView1, reference_dense > & x, const Scalar< InputType2, InputStructure2, reference_dense > &beta, const OP & op = OP(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && @@ -1973,11 +1947,11 @@ namespace grb { template< Descriptor descr = descriptors::no_operation, class Monoid, typename OutputType, typename InputType1, typename InputType2, typename OutputStructure, typename InputStructure1, typename InputStructure2, - typename OutputStorage, typename InputStorage1, typename InputStorage2, + typename OutputView, typename InputView1, typename InputView2 > - RC eWiseApply( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > & z, - const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense > & x, - const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > & y, + RC eWiseApply( VectorView< OutputType, OutputStructure, Density::Dense, OutputView, reference_dense > & z, + const VectorView< InputType1, InputStructure1, Density::Dense, InputView1, reference_dense > & x, + const VectorView< InputType2, InputStructure2, Density::Dense, InputView2, reference_dense > & y, const Monoid & monoid = Monoid(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_monoid< Monoid >::value, void >::type * const = NULL ) { @@ -1996,11 +1970,11 @@ namespace grb { template< Descriptor descr = descriptors::no_operation, class Monoid, typename OutputType, typename InputType1, typename InputType2, typename OutputStructure, typename InputStructure1, typename InputStructure2, - typename OutputStorage, typename InputStorage2, + typename OutputView, typename InputView2 > - RC eWiseApply( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > & z, + RC eWiseApply( VectorView< OutputType, OutputStructure, Density::Dense, OutputView, reference_dense > & z, const Scalar< InputType1, InputStructure1, reference_dense> &alpha, - const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > & y, + const VectorView< InputType2, InputStructure2, Density::Dense, InputView2, reference_dense > & y, const Monoid & monoid = Monoid(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_monoid< Monoid >::value, void >::type * const = NULL ) { @@ -2019,10 +1993,10 @@ namespace grb { template< Descriptor descr = descriptors::no_operation, class Monoid, typename OutputType, typename InputType1, typename InputType2, typename OutputStructure, typename InputStructure1, typename InputStructure2, - typename OutputStorage, typename InputStorage1, + typename OutputView, typename InputView1 > - RC eWiseApply( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > & z, - const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense > & x, + RC eWiseApply( VectorView< OutputType, OutputStructure, Density::Dense, OutputView, reference_dense > & z, + const VectorView< InputType1, InputStructure1, Density::Dense, InputView1, reference_dense > & x, const Scalar< InputType2, InputStructure2, reference_dense > &beta, const Monoid & monoid = Monoid(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_monoid< Monoid >::value, @@ -2042,12 +2016,12 @@ namespace grb { template< Descriptor descr = descriptors::no_operation, class Monoid, typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename OutputStructure, typename MaskStructure, typename InputStructure1, typename InputStructure2, - typename OutputStorage, typename MaskStorage, typename InputStorage1, typename InputStorage2, + typename OutputView, typename MaskView, typename InputView1, typename InputView2 > - RC eWiseApply( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > & z, - const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense > & mask, - const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense > & x, - const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > & y, + RC eWiseApply( VectorView< OutputType, OutputStructure, Density::Dense, OutputView, reference_dense > & z, + const VectorView< MaskType, MaskStructure, Density::Dense, MaskView, reference_dense > & mask, + const VectorView< InputType1, InputStructure1, Density::Dense, InputView1, reference_dense > & x, + const VectorView< InputType2, InputStructure2, Density::Dense, InputView2, reference_dense > & y, const Monoid & monoid = Monoid(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_monoid< Monoid >::value, @@ -2067,12 +2041,12 @@ namespace grb { template< Descriptor descr = descriptors::no_operation, class Monoid, typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename OutputStructure, typename MaskStructure, typename InputStructure1, typename InputStructure2, - typename OutputStorage, typename MaskStorage, typename InputStorage2, + typename OutputView, typename MaskView, typename InputView2 > - RC eWiseApply( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > & z, - const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense > & mask, + RC eWiseApply( VectorView< OutputType, OutputStructure, Density::Dense, OutputView, reference_dense > & z, + const VectorView< MaskType, MaskStructure, Density::Dense, MaskView, reference_dense > & mask, const Scalar< InputType1, InputStructure1, reference_dense> &alpha, - const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > & y, + const VectorView< InputType2, InputStructure2, Density::Dense, InputView2, reference_dense > & y, const Monoid & monoid = Monoid(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_monoid< Monoid >::value, @@ -2092,11 +2066,11 @@ namespace grb { template< Descriptor descr = descriptors::no_operation, class Monoid, typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename OutputStructure, typename MaskStructure, typename InputStructure1, typename InputStructure2, - typename OutputStorage, typename MaskStorage, typename InputStorage1, + typename OutputView, typename MaskView, typename InputView1 > - RC eWiseApply( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > & z, - const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense > & mask, - const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense > & x, + RC eWiseApply( VectorView< OutputType, OutputStructure, Density::Dense, OutputView, reference_dense > & z, + const VectorView< MaskType, MaskStructure, Density::Dense, MaskView, reference_dense > & mask, + const VectorView< InputType1, InputStructure1, Density::Dense, InputView1, reference_dense > & x, const Scalar< InputType2, InputStructure2, reference_dense > &beta, const Monoid & monoid = Monoid(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && @@ -2141,8 +2115,6 @@ namespace grb { * @tparam InputType2 The value type of the right-hand side vector. * @tparam OutputStructure The value Structure of the ouput vector. * @tparam InputStructure2 The value Structure of the right-hand side vector. - * @tparam OutputStorage The type of storage of the ouput vector. - * @tparam InputStorage2 The type of storage of the right-hand side vector. * @tparam OutputView The view type of the ouput vector. * @tparam InputView2 The view type of the right-hand side vector. * @@ -2182,11 +2154,11 @@ namespace grb { template< Descriptor descr = descriptors::no_operation, class OP, typename OutputType, typename InputType1, typename InputType2, typename OutputStructure, typename InputStructure1, typename InputStructure2, - typename OutputStorage, typename InputStorage2, + typename OutputView, typename InputView2 > - RC eWiseApply( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > & z, + RC eWiseApply( VectorView< OutputType, OutputStructure, Density::Dense, OutputView, reference_dense > & z, const Scalar< InputType1, InputStructure1, reference_dense > &alpha, - const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > & y, + const VectorView< InputType2, InputStructure2, Density::Dense, InputView2, reference_dense > & y, const OP & op = OP(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_operator< OP >::value, void >::type * const = NULL ) { @@ -2205,12 +2177,12 @@ namespace grb { template< Descriptor descr = descriptors::no_operation, class OP, typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename OutputStructure, typename MaskStructure, typename InputStructure1, typename InputStructure2, - typename OutputStorage, typename MaskStorage, typename InputStorage2, + typename OutputView, typename MaskView, typename InputView2 > - RC eWiseApply( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > & z, - const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense > & mask, + RC eWiseApply( VectorView< OutputType, OutputStructure, Density::Dense, OutputView, reference_dense > & z, + const VectorView< MaskType, MaskStructure, Density::Dense, MaskView, reference_dense > & mask, const Scalar< InputType1, InputStructure1, reference_dense> &alpha, - const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > & y, + const VectorView< InputType2, InputStructure2, Density::Dense, InputView2, reference_dense > & y, const OP & op = OP(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_operator< OP >::value, @@ -2256,9 +2228,6 @@ namespace grb { * @tparam InputStructure1 The structure of the left-hand side vector. * @tparam InputStructure2 The structure of the right-hand side vector. * @tparam OutputStructure The structure of the ouput vector. - * @tparam InputStorage1 The type of storage of the left-hand side vector. - * @tparam InputStorage2 The type of storage of the right-hand side vector. - * @tparam OutputStorage The type of storage of the ouput vector. * @tparam InputView1 The value View of the left-hand side vector. * @tparam InputView2 The value View of the right-hand side vector. * @tparam OutputView The value View of the ouput vector. @@ -2302,11 +2271,11 @@ namespace grb { template< Descriptor descr = descriptors::no_operation, class OP, typename OutputType, typename InputType1, typename InputType2, typename OutputStructure, typename InputStructure1, typename InputStructure2, - typename OutputStorage, typename InputStorage1, typename InputStorage2, + typename OutputView, typename InputView1, typename InputView2 > - RC eWiseApply( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > & z, - const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense > & x, - const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > & y, + RC eWiseApply( VectorView< OutputType, OutputStructure, Density::Dense, OutputView, reference_dense > & z, + const VectorView< InputType1, InputStructure1, Density::Dense, InputView1, reference_dense > & x, + const VectorView< InputType2, InputStructure2, Density::Dense, InputView2, reference_dense > & y, const OP & op = OP(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_operator< OP >::value, void >::type * const = NULL ) { @@ -2325,12 +2294,12 @@ namespace grb { template< Descriptor descr = descriptors::no_operation, class OP, typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename OutputStructure, typename MaskStructure, typename InputStructure1, typename InputStructure2, - typename OutputStorage, typename MaskStorage, typename InputStorage1, typename InputStorage2, + typename OutputView, typename MaskView, typename InputView1, typename InputView2 > - RC eWiseApply( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > & z, - const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense > & mask, - const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense > & x, - const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > & y, + RC eWiseApply( VectorView< OutputType, OutputStructure, Density::Dense, OutputView, reference_dense > & z, + const VectorView< MaskType, MaskStructure, Density::Dense, MaskView, reference_dense > & mask, + const VectorView< InputType1, InputStructure1, Density::Dense, InputView1, reference_dense > & x, + const VectorView< InputType2, InputStructure2, Density::Dense, InputView2, reference_dense > & y, const OP & op = OP(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_operator< OP >::value, @@ -2359,9 +2328,6 @@ namespace grb { * @tparam InputStructure1 The structure of the left-hand vector. * @tparam InputStructure2 The structure of the right-hand vector. * @tparam OutputStructure1 The structure of the output vector. - * @tparam InputStorage1 The type of storage of the left-hand vector. - * @tparam InputStorage2 The type of storage of the right-hand vector. - * @tparam OutputStorage1 The type of storage of the output vector. * @tparam InputView1 The view type applied to the left-hand vector. * @tparam InputView2 The view type applied to the right-hand vector. * @tparam OutputView1 The view type applied to the output vector. @@ -2426,11 +2392,11 @@ namespace grb { template< Descriptor descr = descriptors::no_operation, class Ring, typename OutputType, typename InputType1, typename InputType2, typename OutputStructure, typename InputStructure1, typename InputStructure2, - typename OutputStorage, typename InputStorage1, typename InputStorage2, + typename OutputView, typename InputView1, typename InputView2 > - RC eWiseAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > & z, - const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense > & x, - const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > & y, + RC eWiseAdd( VectorView< OutputType, OutputStructure, Density::Dense, OutputView, reference_dense > & z, + const VectorView< InputType1, InputStructure1, Density::Dense, InputView1, reference_dense > & x, + const VectorView< InputType2, InputStructure2, Density::Dense, InputView2, reference_dense > & y, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_semiring< Ring >::value, void >::type * const = NULL ) { @@ -2459,11 +2425,11 @@ namespace grb { template< Descriptor descr = descriptors::no_operation, class Ring, typename OutputType, typename InputType1, typename InputType2, typename OutputStructure, typename InputStructure1, typename InputStructure2, - typename OutputStorage, typename InputStorage2, + typename OutputView, typename InputView2 > - RC eWiseAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > & z, + RC eWiseAdd( VectorView< OutputType, OutputStructure, Density::Dense, OutputView, reference_dense > & z, const Scalar< InputType1, InputStructure1, reference_dense> &alpha, - const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > & y, + const VectorView< InputType2, InputStructure2, Density::Dense, InputView2, reference_dense > & y, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_semiring< Ring >::value, void >::type * const = NULL ) { @@ -2492,10 +2458,10 @@ namespace grb { template< Descriptor descr = descriptors::no_operation, class Ring, typename OutputType, typename InputType1, typename InputType2, typename OutputStructure, typename InputStructure1, typename InputStructure2, - typename OutputStorage, typename InputStorage1, + typename OutputView, typename InputView1 > - RC eWiseAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > & z, - const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense > & x, + RC eWiseAdd( VectorView< OutputType, OutputStructure, Density::Dense, OutputView, reference_dense > & z, + const VectorView< InputType1, InputStructure1, Density::Dense, InputView1, reference_dense > & x, const Scalar< InputType2, InputStructure2, reference_dense > &beta, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_semiring< Ring >::value, @@ -2525,9 +2491,9 @@ namespace grb { template< Descriptor descr = descriptors::no_operation, class Ring, typename OutputType, typename InputType1, typename InputType2, typename OutputStructure, typename InputStructure1, typename InputStructure2, - typename OutputStorage, + typename OutputView > - RC eWiseAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > & z, + RC eWiseAdd( VectorView< OutputType, OutputStructure, Density::Dense, OutputView, reference_dense > & z, const Scalar< InputType1, InputStructure1, reference_dense > &alpha, const Scalar< InputType2, InputStructure2, reference_dense > &beta, const Ring & ring = Ring(), @@ -2560,12 +2526,12 @@ namespace grb { template< Descriptor descr = descriptors::no_operation, class Ring, typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename OutputStructure, typename MaskStructure, typename InputStructure1, typename InputStructure2, - typename OutputStorage, typename MaskStorage, typename InputStorage1, typename InputStorage2, + typename OutputView, typename MaskView, typename InputView1, typename InputView2 > - RC eWiseAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > & z, - const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense > & m, - const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense > & x, - const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > & y, + RC eWiseAdd( VectorView< OutputType, OutputStructure, Density::Dense, OutputView, reference_dense > & z, + const VectorView< MaskType, MaskStructure, Density::Dense, MaskView, reference_dense > & m, + const VectorView< InputType1, InputStructure1, Density::Dense, InputView1, reference_dense > & x, + const VectorView< InputType2, InputStructure2, Density::Dense, InputView2, reference_dense > & y, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_semiring< Ring >::value, @@ -2597,12 +2563,12 @@ namespace grb { template< Descriptor descr = descriptors::no_operation, class Ring, typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename OutputStructure, typename MaskStructure, typename InputStructure1, typename InputStructure2, - typename OutputStorage, typename MaskStorage, typename InputStorage2, + typename OutputView, typename MaskView, typename InputView2 > - RC eWiseAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > & z, - const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense > & m, + RC eWiseAdd( VectorView< OutputType, OutputStructure, Density::Dense, OutputView, reference_dense > & z, + const VectorView< MaskType, MaskStructure, Density::Dense, MaskView, reference_dense > & m, const Scalar< InputType1, InputStructure1, reference_dense> &alpha, - const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > & y, + const VectorView< InputType2, InputStructure2, Density::Dense, InputView2, reference_dense > & y, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_semiring< Ring >::value, @@ -2634,11 +2600,11 @@ namespace grb { template< Descriptor descr = descriptors::no_operation, class Ring, typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename OutputStructure, typename MaskStructure, typename InputStructure1, typename InputStructure2, - typename OutputStorage, typename MaskStorage, typename InputStorage1, + typename OutputView, typename MaskView, typename InputView1 > - RC eWiseAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > & z, - const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense > & m, - const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense > & x, + RC eWiseAdd( VectorView< OutputType, OutputStructure, Density::Dense, OutputView, reference_dense > & z, + const VectorView< MaskType, MaskStructure, Density::Dense, MaskView, reference_dense > & m, + const VectorView< InputType1, InputStructure1, Density::Dense, InputView1, reference_dense > & x, const Scalar< InputType2, InputStructure2, reference_dense > &beta, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && @@ -2671,10 +2637,10 @@ namespace grb { template< Descriptor descr = descriptors::no_operation, class Ring, typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename OutputStructure, typename MaskStructure, typename InputStructure1, typename InputStructure2, - typename OutputStorage, typename MaskStorage, + typename OutputView, typename MaskView > - RC eWiseAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > & z, - const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense > & m, + RC eWiseAdd( VectorView< OutputType, OutputStructure, Density::Dense, OutputView, reference_dense > & z, + const VectorView< MaskType, MaskStructure, Density::Dense, MaskView, reference_dense > & m, const Scalar< InputType1, InputStructure1, reference_dense > &alpha, const Scalar< InputType2, InputStructure2, reference_dense > &beta, const Ring & ring = Ring(), @@ -2709,12 +2675,12 @@ namespace grb { template< Descriptor descr = descriptors::no_operation, class Ring, typename OutputType, typename InputType1, typename InputType2, typename InputType3, typename OutputStructure, typename InputStructure1, typename InputStructure2, typename InputStructure3, - typename OutputStorage, typename InputStorage2, typename InputStorage3, + typename OutputView, typename InputView2, typename InputView3 > - RC eWiseMulAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > & _z, + RC eWiseMulAdd( VectorView< OutputType, OutputStructure, Density::Dense, OutputView, reference_dense > & _z, const Scalar< InputType1, InputStructure1, reference_dense > &alpha, - const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > & _x, - const VectorView< InputType3, InputStructure3, InputStorage3, InputView3, reference_dense > & _y, + const VectorView< InputType2, InputStructure2, Density::Dense, InputView2, reference_dense > & _x, + const VectorView< InputType3, InputStructure3, Density::Dense, InputView3, reference_dense > & _y, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && grb::is_semiring< Ring >::value, @@ -2745,12 +2711,12 @@ namespace grb { template< Descriptor descr = descriptors::no_operation, class Ring, typename OutputType, typename InputType1, typename InputType2, typename InputType3, typename OutputStructure, typename InputStructure1, typename InputStructure2, typename InputStructure3, - typename OutputStorage, typename InputStorage1, typename InputStorage3, + typename OutputView, typename InputView1, typename InputView3 > - RC eWiseMulAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > & _z, - const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense > & _a, + RC eWiseMulAdd( VectorView< OutputType, OutputStructure, Density::Dense, OutputView, reference_dense > & _z, + const VectorView< InputType1, InputStructure1, Density::Dense, InputView1, reference_dense > & _a, const Scalar< InputType2, InputStructure2, reference_dense> &chi, - const VectorView< InputType3, InputStructure3, InputStorage3, InputView3, reference_dense > & _y, + const VectorView< InputType3, InputStructure3, Density::Dense, InputView3, reference_dense > & _y, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && grb::is_semiring< Ring >::value, @@ -2780,11 +2746,11 @@ namespace grb { template< Descriptor descr = descriptors::no_operation, class Ring, typename OutputType, typename InputType1, typename InputType2, typename InputType3, typename OutputStructure, typename InputStructure1, typename InputStructure2, typename InputStructure3, - typename OutputStorage, typename InputStorage1, typename InputStorage2, + typename OutputView, typename InputView1, typename InputView2 > - RC eWiseMulAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > & _z, - const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense > & _a, - const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > & _x, + RC eWiseMulAdd( VectorView< OutputType, OutputStructure, Density::Dense, OutputView, reference_dense > & _z, + const VectorView< InputType1, InputStructure1, Density::Dense, InputView1, reference_dense > & _a, + const VectorView< InputType2, InputStructure2, Density::Dense, InputView2, reference_dense > & _x, const Scalar< InputType3, InputStructure3, reference_dense > &gamma, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && @@ -2815,10 +2781,10 @@ namespace grb { template< Descriptor descr = descriptors::no_operation, class Ring, typename OutputType, typename InputType1, typename InputType2, typename InputType3, typename OutputStructure, typename InputStructure1, typename InputStructure2, typename InputStructure3, - typename OutputStorage, typename InputStorage1, + typename OutputView, typename InputView1 > - RC eWiseMulAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > & _z, - const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense > & _a, + RC eWiseMulAdd( VectorView< OutputType, OutputStructure, Density::Dense, OutputView, reference_dense > & _z, + const VectorView< InputType1, InputStructure1, Density::Dense, InputView1, reference_dense > & _a, const Scalar< InputType2, InputStructure2, reference_dense> &beta, const Scalar< InputType3, InputStructure3, reference_dense> &gamma, const Ring & ring = Ring(), @@ -2850,11 +2816,11 @@ namespace grb { template< Descriptor descr = descriptors::no_operation, class Ring, typename OutputType, typename InputType1, typename InputType2, typename InputType3, typename OutputStructure, typename InputStructure1, typename InputStructure2, typename InputStructure3, - typename OutputStorage, typename InputStorage2, + typename OutputView, typename InputView2 > - RC eWiseMulAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > & _z, + RC eWiseMulAdd( VectorView< OutputType, OutputStructure, Density::Dense, OutputView, reference_dense > & _z, const Scalar< InputType1, InputStructure1, reference_dense > &alpha, - const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > & _x, + const VectorView< InputType2, InputStructure2, Density::Dense, InputView2, reference_dense > & _x, const Scalar< InputType3, InputStructure3, reference_dense > &gamma, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && @@ -2887,12 +2853,12 @@ namespace grb { template< Descriptor descr = descriptors::no_operation, class Ring, typename OutputType, typename InputType1, typename InputType2, typename InputType3, typename OutputStructure, typename InputStructure1, typename InputStructure2, typename InputStructure3, - typename OutputStorage, typename InputStorage3, + typename OutputView, typename InputView3 > - RC eWiseMulAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > & z, + RC eWiseMulAdd( VectorView< OutputType, OutputStructure, Density::Dense, OutputView, reference_dense > & z, const Scalar< InputType1, InputStructure1, reference_dense> &alpha, const Scalar< InputType2, InputStructure2, reference_dense> &beta, - const VectorView< InputType3, InputStructure3, InputStorage3, InputView3, reference_dense > & y, + const VectorView< InputType3, InputStructure3, Density::Dense, InputView3, reference_dense > & y, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && grb::is_semiring< Ring >::value, @@ -2928,9 +2894,9 @@ namespace grb { template< Descriptor descr = descriptors::no_operation, class Ring, typename OutputType, typename InputType1, typename InputType2, typename InputType3, typename OutputStructure, typename InputStructure1, typename InputStructure2, typename InputStructure3, - typename OutputStorage, + typename OutputView > - RC eWiseMulAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > & z, + RC eWiseMulAdd( VectorView< OutputType, OutputStructure, Density::Dense, OutputView, reference_dense > & z, const Scalar< InputType1, InputStructure1, reference_dense> &alpha, const Scalar< InputType2, InputStructure2, reference_dense> &beta, const Scalar< InputType3, InputStructure3, reference_dense> &gamma, @@ -2996,17 +2962,6 @@ namespace grb { * @tparam OutputStructure1 The structure of the right-hand side input type * to the additive operator of the \a ring \em and * the result of the same operator. - * @tparam InputStorage1 The type of storage of the left-hand side input - * to the multiplicative operator of the \a ring. - * @tparam InputStorage2 The type of storage of the left-hand side input - * to the multiplicative operator of the \a ring. - * @tparam InputStorage3 The type of storage of the output to the - * multiplicative operator of the \a ring \em and - * the left-hand side input to the aditive operator - * of the \a ring. - * @tparam OutputStorage1 The type of storage of the right-hand side input - * type to the additive operator of the \a ring \em - * and the result of the same operator. * @tparam InputView1 The view applied to the left-hand side input to * the multiplicative operator of the \a ring. * @tparam InputView2 The view applied to the left-hand side input to @@ -3078,12 +3033,12 @@ namespace grb { template< Descriptor descr = descriptors::no_operation, class Ring, typename OutputType, typename InputType1, typename InputType2, typename InputType3, typename OutputStructure, typename InputStructure1, typename InputStructure2, typename InputStructure3, - typename OutputStorage, typename InputStorage1, typename InputStorage2, typename InputStorage3, + typename OutputView, typename InputView1, typename InputView2, typename InputView3 > - RC eWiseMulAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > & _z, - const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense > & _a, - const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > & _x, - const VectorView< InputType3, InputStructure3, InputStorage3, InputView3, reference_dense > & _y, + RC eWiseMulAdd( VectorView< OutputType, OutputStructure, Density::Dense, OutputView, reference_dense > & _z, + const VectorView< InputType1, InputStructure1, Density::Dense, InputView1, reference_dense > & _a, + const VectorView< InputType2, InputStructure2, Density::Dense, InputView2, reference_dense > & _x, + const VectorView< InputType3, InputStructure3, Density::Dense, InputView3, reference_dense > & _y, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && grb::is_semiring< Ring >::value, @@ -3127,14 +3082,6 @@ namespace grb { * to the multiplicative operator of the \a ring. * @tparam OutputStructure1 The structure of the output to the * multiplicative operator of the \a ring. - * @tparam InputStorage1 The type of storage type of the left-hand - * side input to the multiplicative operator - * of the \a ring. - * @tparam InputStorage2 The type of storage type of the right-hand - * side input to the multiplicative operator - * of the \a ring. - * @tparam OutputStorage1 The type of storage type of the output to - * the multiplicative operator of the \a ring. * @tparam InputView1 The view type applied to the left-hand side * input to the multiplicative operator * of the \a ring. @@ -3200,11 +3147,11 @@ namespace grb { template< Descriptor descr = descriptors::no_operation, class Ring, typename OutputType, typename InputType1, typename InputType2, typename OutputStructure, typename InputStructure1, typename InputStructure2, - typename OutputStorage, typename InputStorage1, typename InputStorage2, + typename OutputView, typename InputView1, typename InputView2 > - RC eWiseMul( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > & z, - const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense > & x, - const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > & y, + RC eWiseMul( VectorView< OutputType, OutputStructure, Density::Dense, OutputView, reference_dense > & z, + const VectorView< InputType1, InputStructure1, Density::Dense, InputView1, reference_dense > & x, + const VectorView< InputType2, InputStructure2, Density::Dense, InputView2, reference_dense > & y, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_semiring< Ring >::value, void >::type * const = NULL ) { @@ -3232,11 +3179,11 @@ namespace grb { template< Descriptor descr = descriptors::no_operation, class Ring, typename OutputType, typename InputType1, typename InputType2, typename OutputStructure, typename InputStructure1, typename InputStructure2, - typename OutputStorage, typename InputStorage2, + typename OutputView, typename InputView2 > - RC eWiseMul( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > & z, + RC eWiseMul( VectorView< OutputType, OutputStructure, Density::Dense, OutputView, reference_dense > & z, const Scalar< InputType1, InputStructure1, reference_dense > &alpha, - const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > & y, + const VectorView< InputType2, InputStructure2, Density::Dense, InputView2, reference_dense > & y, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_semiring< Ring >::value, void >::type * const = NULL ) { @@ -3264,10 +3211,10 @@ namespace grb { template< Descriptor descr = descriptors::no_operation, class Ring, typename OutputType, typename InputType1, typename InputType2, typename OutputStructure, typename InputStructure1, typename InputStructure2, - typename OutputStorage, typename InputStorage1, + typename OutputView, typename InputView1 > - RC eWiseMul( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > & z, - const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense > & x, + RC eWiseMul( VectorView< OutputType, OutputStructure, Density::Dense, OutputView, reference_dense > & z, + const VectorView< InputType1, InputStructure1, Density::Dense, InputView1, reference_dense > & x, const Scalar< InputType2, InputStructure2, reference_dense > &beta, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_semiring< Ring >::value, @@ -3296,13 +3243,13 @@ namespace grb { template< Descriptor descr = descriptors::no_operation, class Ring, typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename InputType3, typename OutputStructure, typename MaskStructure, typename InputStructure1, typename InputStructure2, typename InputStructure3, - typename OutputStorage, typename MaskStorage, typename InputStorage2, typename InputStorage3, + typename OutputView, typename MaskView, typename InputView2, typename InputView3 > - RC eWiseMulAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > & _z, - const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense > & _m, + RC eWiseMulAdd( VectorView< OutputType, OutputStructure, Density::Dense, OutputView, reference_dense > & _z, + const VectorView< MaskType, MaskStructure, Density::Dense, MaskView, reference_dense > & _m, const Scalar< InputType1, InputStructure1, reference_dense > &alpha, - const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > & _x, - const VectorView< InputType3, InputStructure3, InputStorage3, InputView3, reference_dense > & _y, + const VectorView< InputType2, InputStructure2, Density::Dense, InputView2, reference_dense > & _x, + const VectorView< InputType3, InputStructure3, Density::Dense, InputView3, reference_dense > & _y, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && grb::is_semiring< Ring >::value && ! grb::is_object< MaskType >::value, @@ -3334,13 +3281,13 @@ namespace grb { template< Descriptor descr = descriptors::no_operation, class Ring, typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename InputType3, typename OutputStructure, typename MaskStructure, typename InputStructure1, typename InputStructure2, typename InputStructure3, - typename OutputStorage, typename MaskStorage, typename InputStorage1, typename InputStorage3, + typename OutputView, typename MaskView, typename InputView1, typename InputView3 > - RC eWiseMulAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > & _z, - const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense > & _m, - const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense > & _a, + RC eWiseMulAdd( VectorView< OutputType, OutputStructure, Density::Dense, OutputView, reference_dense > & _z, + const VectorView< MaskType, MaskStructure, Density::Dense, MaskView, reference_dense > & _m, + const VectorView< InputType1, InputStructure1, Density::Dense, InputView1, reference_dense > & _a, const Scalar< InputType2, InputStructure2, reference_dense> &chi, - const VectorView< InputType3, InputStructure3, InputStorage3, InputView3, reference_dense > & _y, + const VectorView< InputType3, InputStructure3, Density::Dense, InputView3, reference_dense > & _y, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && grb::is_semiring< Ring >::value && ! grb::is_object< MaskType >::value, @@ -3371,12 +3318,12 @@ namespace grb { template< Descriptor descr = descriptors::no_operation, class Ring, typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename InputType3, typename OutputStructure, typename MaskStructure, typename InputStructure1, typename InputStructure2, typename InputStructure3, - typename OutputStorage, typename MaskStorage, typename InputStorage1, typename InputStorage2, + typename OutputView, typename MaskView, typename InputView1, typename InputView2 > - RC eWiseMulAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > & _z, - const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense > & _m, - const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense > & _a, - const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > & _x, + RC eWiseMulAdd( VectorView< OutputType, OutputStructure, Density::Dense, OutputView, reference_dense > & _z, + const VectorView< MaskType, MaskStructure, Density::Dense, MaskView, reference_dense > & _m, + const VectorView< InputType1, InputStructure1, Density::Dense, InputView1, reference_dense > & _a, + const VectorView< InputType2, InputStructure2, Density::Dense, InputView2, reference_dense > & _x, const Scalar< InputType3, InputStructure3, reference_dense > &gamma, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && @@ -3408,11 +3355,11 @@ namespace grb { template< Descriptor descr = descriptors::no_operation, class Ring, typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename InputType3, typename OutputStructure, typename MaskStructure, typename InputStructure1, typename InputStructure2, typename InputStructure3, - typename OutputStorage, typename MaskStorage, typename InputStorage1, + typename OutputView, typename MaskView, typename InputView1 > - RC eWiseMulAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > & _z, - const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense > & _m, - const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense > & _a, + RC eWiseMulAdd( VectorView< OutputType, OutputStructure, Density::Dense, OutputView, reference_dense > & _z, + const VectorView< MaskType, MaskStructure, Density::Dense, MaskView, reference_dense > & _m, + const VectorView< InputType1, InputStructure1, Density::Dense, InputView1, reference_dense > & _a, const Scalar< InputType2, InputStructure2, reference_dense> &beta, const Scalar< InputType3, InputStructure3, reference_dense> &gamma, const Ring & ring = Ring(), @@ -3445,12 +3392,12 @@ namespace grb { template< Descriptor descr = descriptors::no_operation, class Ring, typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename InputType3, typename OutputStructure, typename MaskStructure, typename InputStructure1, typename InputStructure2, typename InputStructure3, - typename OutputStorage, typename MaskStorage, typename InputStorage2, + typename OutputView, typename MaskView, typename InputView2 > - RC eWiseMulAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > & _z, - const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense > & _m, + RC eWiseMulAdd( VectorView< OutputType, OutputStructure, Density::Dense, OutputView, reference_dense > & _z, + const VectorView< MaskType, MaskStructure, Density::Dense, MaskView, reference_dense > & _m, const Scalar< InputType1, InputStructure1, reference_dense > &alpha, - const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > & _x, + const VectorView< InputType2, InputStructure2, Density::Dense, InputView2, reference_dense > & _x, const Scalar< InputType3, InputStructure3, reference_dense > &gamma, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && @@ -3482,13 +3429,13 @@ namespace grb { template< Descriptor descr = descriptors::no_operation, class Ring, typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename InputType3, typename OutputStructure, typename MaskStructure, typename InputStructure1, typename InputStructure2, typename InputStructure3, - typename OutputStorage, typename MaskStorage, typename InputStorage1, typename InputStorage2, typename InputStorage3, + typename OutputView, typename MaskView, typename InputView1, typename InputView2, typename InputView3 > - RC eWiseMulAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > & _z, - const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense > & _m, - const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense > & _a, - const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > & _x, - const VectorView< InputType3, InputStructure3, InputStorage3, InputView3, reference_dense > & _y, + RC eWiseMulAdd( VectorView< OutputType, OutputStructure, Density::Dense, OutputView, reference_dense > & _z, + const VectorView< MaskType, MaskStructure, Density::Dense, MaskView, reference_dense > & _m, + const VectorView< InputType1, InputStructure1, Density::Dense, InputView1, reference_dense > & _a, + const VectorView< InputType2, InputStructure2, Density::Dense, InputView2, reference_dense > & _x, + const VectorView< InputType3, InputStructure3, Density::Dense, InputView3, reference_dense > & _y, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && grb::is_semiring< Ring >::value && ! grb::is_object< MaskType >::value, @@ -3524,12 +3471,12 @@ namespace grb { template< Descriptor descr = descriptors::no_operation, class Ring, typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename OutputStructure, typename MaskStructure, typename InputStructure1, typename InputStructure2, typename InputStructure3, - typename OutputStorage, typename MaskStorage, typename InputStorage1, typename InputStorage2, typename InputStorage3, + typename OutputView, typename MaskView, typename InputView1, typename InputView2, typename InputView3 > - RC eWiseMul( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > & z, - const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense > & m, - const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense > & x, - const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > & y, + RC eWiseMul( VectorView< OutputType, OutputStructure, Density::Dense, OutputView, reference_dense > & z, + const VectorView< MaskType, MaskStructure, Density::Dense, MaskView, reference_dense > & m, + const VectorView< InputType1, InputStructure1, Density::Dense, InputView1, reference_dense > & x, + const VectorView< InputType2, InputStructure2, Density::Dense, InputView2, reference_dense > & y, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< MaskType >::value && grb::is_semiring< Ring >::value, @@ -3561,12 +3508,12 @@ namespace grb { template< Descriptor descr = descriptors::no_operation, class Ring, typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename OutputStructure, typename MaskStructure, typename InputStructure2, typename InputStructure3, - typename OutputStorage, typename MaskStorage, typename InputStructure1, typename InputStorage2, typename InputStorage3, + typename InputStructure1, typename OutputView, typename MaskView, typename InputView2, typename InputView3 > - RC eWiseMul( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > & z, - const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense > & m, + RC eWiseMul( VectorView< OutputType, OutputStructure, Density::Dense, OutputView, reference_dense > & z, + const VectorView< MaskType, MaskStructure, Density::Dense, MaskView, reference_dense > & m, const Scalar< InputType1, InputStructure1, reference_dense > &alpha, - const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > & y, + const VectorView< InputType2, InputStructure2, Density::Dense, InputView2, reference_dense > & y, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< MaskType >::value && grb::is_semiring< Ring >::value, @@ -3598,11 +3545,11 @@ namespace grb { template< Descriptor descr = descriptors::no_operation, class Ring, typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename OutputStructure, typename MaskStructure, typename InputStructure1, typename InputStructure2, typename InputStructure3, - typename OutputStorage, typename MaskStorage, typename InputStorage1, typename InputStorage3, + typename OutputView, typename MaskView, typename InputView1, typename InputView3 > - RC eWiseMul( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > & z, - const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense > & m, - const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense > & x, + RC eWiseMul( VectorView< OutputType, OutputStructure, Density::Dense, OutputView, reference_dense > & z, + const VectorView< MaskType, MaskStructure, Density::Dense, MaskView, reference_dense > & m, + const VectorView< InputType1, InputStructure1, Density::Dense, InputView1, reference_dense > & x, const Scalar< InputType2, InputStructure2, reference_dense > &beta, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< MaskType >::value && @@ -3635,13 +3582,13 @@ namespace grb { template< Descriptor descr = descriptors::no_operation, class Ring, typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename InputType3, typename OutputStructure, typename MaskStructure, typename InputStructure1, typename InputStructure2, typename InputStructure3, - typename OutputStorage, typename MaskStorage, typename InputStorage3, + typename OutputView, typename MaskView, typename InputView3 > - RC eWiseMulAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > & z, - const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense > & m, + RC eWiseMulAdd( VectorView< OutputType, OutputStructure, Density::Dense, OutputView, reference_dense > & z, + const VectorView< MaskType, MaskStructure, Density::Dense, MaskView, reference_dense > & m, const Scalar< InputType1, InputStructure1, reference_dense > &alpha, const Scalar< InputType2, InputStructure2, reference_dense > &beta, - const VectorView< InputType3, InputStructure3, InputStorage3, InputView3, reference_dense > & y, + const VectorView< InputType3, InputStructure3, Density::Dense, InputView3, reference_dense > & y, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && grb::is_semiring< Ring >::value && ! grb::is_object< MaskType >::value, @@ -3678,10 +3625,10 @@ namespace grb { template< Descriptor descr = descriptors::no_operation, class Ring, typename OutputType, typename MaskType, typename InputType1, typename InputType2, typename InputType3, typename OutputStructure, typename MaskStructure, typename InputStructure1, typename InputStructure2, typename InputStructure3, - typename OutputStorage, typename MaskStorage, + typename OutputView, typename MaskView > - RC eWiseMulAdd( VectorView< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > & z, - const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense > & m, + RC eWiseMulAdd( VectorView< OutputType, OutputStructure, Density::Dense, OutputView, reference_dense > & z, + const VectorView< MaskType, MaskStructure, Density::Dense, MaskView, reference_dense > & m, const Scalar< InputType1, InputStructure1, reference_dense> &alpha, const Scalar< InputType2, InputStructure2, reference_dense> &beta, const Scalar< InputType3, InputStructure3, reference_dense> &gamma, @@ -3725,11 +3672,11 @@ namespace grb { class AddMonoid, class AnyOp, typename OutputType, typename InputType1, typename InputType2, typename OutputStructure, typename InputStructure1, typename InputStructure2, - typename InputStorage1, typename InputStorage2, + typename InputView1, typename InputView2 > RC dot_generic( Scalar< OutputType, OutputStructure, reference_dense > &z, - const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense > &x, - const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > &y, + const VectorView< InputType1, InputStructure1, Density::Dense, InputView1, reference_dense > &x, + const VectorView< InputType2, InputStructure2, Density::Dense, InputView2, reference_dense > &y, const AddMonoid &addMonoid = AddMonoid(), const AnyOp &anyOp = AnyOp() ) { @@ -3751,8 +3698,6 @@ namespace grb { * @tparam InputType2 The input element type of the right-hand input vector. * @tparam InputStructure1 The structure of the left-hand input vector. * @tparam InputStructure2 The structure of the right-hand input vector. - * @tparam InputStorage1 The type of storage of the left-hand input vector. - * @tparam InputStorage2 The type of storage of the right-hand input vector. * @tparam InputView1 The view type applied to the left-hand input vector. * @tparam InputView2 The view type applied to the right-hand input vector. * @@ -3825,11 +3770,11 @@ namespace grb { class AddMonoid, class AnyOp, typename OutputType, typename InputType1, typename InputType2, typename OutputStructure, typename InputStructure1, typename InputStructure2, - typename InputStorage1, typename InputStorage2, + typename InputView1, typename InputView2 > RC dot( Scalar< OutputType, OutputStructure, reference_dense > &z, - const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense > &x, - const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > &y, + const VectorView< InputType1, InputStructure1, Density::Dense, InputView1, reference_dense > &x, + const VectorView< InputType2, InputStructure2, Density::Dense, InputView2, reference_dense > &y, const AddMonoid &addMonoid = AddMonoid(), const AnyOp &anyOp = AnyOp(), const typename std::enable_if< !grb::is_object< OutputType >::value && @@ -3873,11 +3818,11 @@ namespace grb { class AddMonoid, class AnyOp, typename OutputType, typename InputType1, typename InputType2, typename InputStructure1, typename InputStructure2, - typename InputStorage1, typename InputStorage2, + typename InputView1, typename InputView2 > RC dot( OutputType &z, - const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense > &x, - const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > &y, + const VectorView< InputType1, InputStructure1, Density::Dense, InputView1, reference_dense > &x, + const VectorView< InputType2, InputStructure2, Density::Dense, InputView2, reference_dense > &y, const AddMonoid &addMonoid = AddMonoid(), const AnyOp &anyOp = AnyOp(), const typename std::enable_if< !grb::is_object< OutputType >::value && @@ -3927,12 +3872,11 @@ namespace grb { Descriptor descr = descriptors::no_operation, class Ring, typename IOType, typename InputType1, typename InputType2, typename IOStructure, typename InputStructure1, typename InputStructure2, - typename InputStorage1, typename InputStorage2, typename InputView1, typename InputView2, Backend backend > RC dot( Scalar< IOType, IOStructure, backend > &x, - const VectorView< InputType1, InputStructure1, InputView1, InputStorage1, backend > &left, - const VectorView< InputType2, InputStructure2, InputView2, InputStorage2, backend > &right, + const VectorView< InputType1, InputStructure1, Density::Dense, InputView1, backend > &left, + const VectorView< InputType2, InputStructure2, Density::Dense, InputView2, backend > &right, const Ring &ring = Ring(), const typename std::enable_if< !grb::is_object< InputType1 >::value && @@ -3954,12 +3898,12 @@ namespace grb { Descriptor descr = descriptors::no_operation, class Ring, typename IOType, typename InputType1, typename InputType2, typename InputStructure1, typename InputStructure2, - typename InputStorage1, typename InputStorage2, + typename InputView1, typename InputView2, Backend backend > RC dot( IOType &x, - const VectorView< InputType1, InputStructure1, InputView1, InputStorage1, backend > &left, - const VectorView< InputType2, InputStructure2, InputView2, InputStorage2, backend > &right, + const VectorView< InputType1, InputStructure1, Density::Dense, InputView1, backend > &left, + const VectorView< InputType2, InputStructure2, Density::Dense, InputView2, backend > &right, const Ring &ring = Ring(), const typename std::enable_if< !grb::is_object< InputType1 >::value && @@ -3982,8 +3926,8 @@ namespace grb { } /** No implementation notes. */ - template< typename Func, typename DataType, typename DataStructure, typename DataStorage, typename DataView > - RC eWiseMap( const Func f, VectorView< DataType, DataStructure, DataStorage, DataView, reference_dense > & x ) { + template< typename Func, typename DataType, typename DataStructure, typename DataView > + RC eWiseMap( const Func f, VectorView< DataType, DataStructure, Density::Dense, DataView, reference_dense > & x ) { throw std::runtime_error( "Needs an implementation." ); return SUCCESS; } @@ -4000,12 +3944,11 @@ namespace grb { */ template< typename Func, typename DataType1, typename DataType2, typename DataStructure1, typename DataStructure2, - typename DataStorage1, typename DataStorage2, typename DataView1, typename DataView2, typename... Args > RC eWiseLambda( const Func f, - const VectorView< DataType1, DataStructure1, DataStorage1, DataView1, reference_dense > & x, - const VectorView< DataType2, DataStructure2, DataStorage2, DataView2, reference_dense > & y, + const VectorView< DataType1, DataStructure1, Density::Dense, DataView1, reference_dense > & x, + const VectorView< DataType2, DataStructure2, Density::Dense, DataView2, reference_dense > & y, Args const &... args ) { // catch mismatch if( size( x ) != size( y ) ) { @@ -4022,8 +3965,8 @@ namespace grb { * @see VectorView::operator[]() * @see VectorView::lambda_reference */ - template< typename Func, typename DataType, typename DataStructure, typename DataStorage, typename DataView > - RC eWiseLambda( const Func f, const VectorView< DataType, DataStructure, DataStorage, DataView, reference_dense > & x ) { + template< typename Func, typename DataType, typename DataStructure, typename DataView > + RC eWiseLambda( const Func f, const VectorView< DataType, DataStructure, Density::Dense, DataView, reference_dense > & x ) { #ifdef _DEBUG std::cout << "Info: entering eWiseLambda function on vectors.\n"; #endif @@ -4115,11 +4058,11 @@ namespace grb { template< Descriptor descr = descriptors::no_operation, class Monoid, typename InputType, typename IOType, typename MaskType, typename IOStructure, typename InputStructure, typename MaskStructure, - typename InputStorage, typename MaskStorage, + typename InputView, typename MaskView > RC foldl( Scalar< IOType, IOStructure, reference_dense > &x, - const VectorView< InputType, InputStructure, InputStorage, InputView, reference_dense > & y, - const VectorView< MaskType, MaskStructure, MaskStorage, MaskView, reference_dense > & mask, + const VectorView< InputType, InputStructure, Density::Dense, InputView, reference_dense > & y, + const VectorView< MaskType, MaskStructure, Density::Dense, MaskView, reference_dense > & mask, const Monoid & monoid = Monoid(), const typename std::enable_if< ! grb::is_object< IOType >::value && ! grb::is_object< InputType >::value && ! grb::is_object< MaskType >::value && grb::is_monoid< Monoid >::value, void >::type * const = NULL ) { @@ -4145,6 +4088,30 @@ namespace grb { return SUCCESS; } + /** + * Sort vectors, function available to user, e.g. to sort eigenvectors + * + * @param[in] toSort vector of indices to sort, should not be modified + * @param[in] cmp function with strict weak ordering relation between indices, eg bool cmp(const Type1 &a, const Type2 &b) + * cmp must not modify the objects passed to it + * + * @param[out] permutation iterator over index permutations which sort toSort vector + * + * Complexity should be lower than O(n*log(n)), and space complexity should be lower than \Theta(n+T+P) + */ + template< + typename IndexType, typename IndexStructure, typename IndexView, + typename ValueType, typename ValueStructure, typename ValueView, + typename Compare > + RC sort( + VectorView< IndexType, IndexStructure, Density::Dense, IndexView, reference_dense > &permutation, + const VectorView< ValueType, ValueStructure, Density::Dense, ValueView, reference_dense > &toSort, + Compare cmp + //PHASE &phase = EXECUTE + ) noexcept { + return SUCCESS; + } + /** * Provides a generic implementation of the 2-norm computation. * @@ -4172,11 +4139,11 @@ namespace grb { Descriptor descr = descriptors::no_operation, class Ring, typename OutputType, typename InputType, typename OutputStructure, typename InputStructure, - typename InputStorage, + typename InputView, Backend backend > RC norm2( Scalar< OutputType, OutputStructure, backend > &x, - const VectorView< InputType, InputStructure, InputStorage, InputView, backend > &y, + const VectorView< InputType, InputStructure, Density::Dense, InputView, backend > &y, const Ring &ring = Ring(), const typename std::enable_if< std::is_floating_point< OutputType >::value, @@ -4189,37 +4156,18 @@ namespace grb { return ret; } - /** - * Sort vectors, function available to user, e.g. to sort eigenvectors - * - * @param[in] toSort vector of indices to sort, should not be modified - * @param[in] cmp function with strict weak ordering relation between indices, eg bool cmp(const Type1 &a, const Type2 &b) - * cmp must not modify the objects passed to it - * - * @param[out] permutation iterator over index permutations which sort toSort vector - * - * Complexity should be lower than O(n*log(n)), and space complexity should be lower than \Theta(n+T+P) - */ - template< typename IndexType, typename ValueType, typename Compare > - RC sort( - Vector< IndexType > &permutation, const Vector< ValueType > &toSort, - Compare cmp, PHASE &phase = EXECUTE - ) noexcept { - return SUCCESS; - } - /** C++ scalar version */ template< Descriptor descr = descriptors::no_operation, class Ring, typename OutputType, typename InputType, typename InputStructure, - typename InputStorage, + typename InputView, Backend backend > RC norm2( OutputType &x, - const VectorView< InputType, InputStructure, InputStorage, InputView, backend > &y, + const VectorView< InputType, InputStructure, Density::Dense, InputView, backend > &y, const Ring &ring = Ring(), const typename std::enable_if< std::is_floating_point< OutputType >::value, diff --git a/include/graphblas/denseref/blas2.hpp b/include/graphblas/denseref/blas2.hpp index d73432c81..2b0cb2b0f 100644 --- a/include/graphblas/denseref/blas2.hpp +++ b/include/graphblas/denseref/blas2.hpp @@ -52,8 +52,8 @@ namespace grb { * bytes of memory. * \endparblock */ - template< typename InputType, typename InputStructure, typename InputStorage, typename InputView > - size_t nrows( const StructuredMatrix< InputType, InputStructure, InputStorage, InputView, reference_dense > & A ) noexcept { + template< typename InputType, typename InputStructure, typename InputView > + size_t nrows( const StructuredMatrix< InputType, InputStructure, Density::Dense, InputView, reference_dense > & A ) noexcept { return A.m; } @@ -73,8 +73,8 @@ namespace grb { * bytes of memory. * \endparblock */ - template< typename InputType, typename InputStructure, typename InputStorage, typename InputView > - size_t ncols( const StructuredMatrix< InputType, InputStructure, InputStorage, InputView, reference_dense > & A ) noexcept { + template< typename InputType, typename InputStructure, typename InputView > + size_t ncols( const StructuredMatrix< InputType, InputStructure, Density::Dense, InputView, reference_dense > & A ) noexcept { return A.n; } @@ -95,7 +95,7 @@ namespace grb { * \endparblock */ template< typename InputType > - size_t nnz( const StructuredMatrix< InputType, InputStructure, InputStorage, InputView, reference_dense > & A ) noexcept { + size_t nnz( const StructuredMatrix< InputType, InputStructure, Density::Dense, InputView, reference_dense > & A ) noexcept { return A.nz; } @@ -128,8 +128,8 @@ namespace grb { * -# This function does not make system calls. * \endparblock */ - template< typename InputType > - RC resize( StructuredMatrix< InputType, InputStructure, InputStorage, InputView, reference_dense > & A, const size_t new_nz ) noexcept { + template< typename InputType, typename InputStructure, typename InputView > + RC resize( StructuredMatrix< InputType, InputStructure, Density::Dense, InputView, reference_dense > &A, const size_t new_nz ) noexcept { (void)A; (void)new_nz; // TODO implement @@ -140,14 +140,14 @@ namespace grb { /** \internal Delegates to fully masked variant */ template< Descriptor descr = descriptors::no_operation, class Ring, - typename IOType, typename IOView, typename IOStorage, - typename InputType1, typename InputType1, typename InputView1, typename InputStorage1, - typename InputType2, typename InputStructure2, typename InputStorage2, typename InputView2, + typename IOType, typename IOView, + typename InputType1, typename InputType1, typename InputView1, + typename InputType2, typename InputStructure2, typename InputView2, typename InputType3, typename InputType3, typename InputView3, typename InputStorage3 > - RC vxm( VectorView< IOType, IOStructure, IOStorage, IOView, reference_dense > & u, - const VectorView< InputType3, InputStructure3, InputStorage3, InputView3, reference_dense > & mask, - const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense > & v, - const StructuredMatrix< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > & A, + RC vxm( VectorView< IOType, IOStructure, Density::Dense, IOView, reference_dense > & u, + const VectorView< InputType3, InputStructure3, Density::Dense, InputView3, reference_dense > & mask, + const VectorView< InputType1, InputStructure1, Density::Dense, InputView1, reference_dense > & v, + const StructuredMatrix< InputType2, InputStructure2, Density::Dense, InputView2, reference_dense > & A, const Ring & ring = Ring(), const typename std::enable_if< grb::is_semiring< Ring >::value, void >::type * const = NULL ) { const VectorView< bool, reference, internal::DefaultCoordinates > empty_mask( 0 ); @@ -158,14 +158,14 @@ namespace grb { template< Descriptor descr = descriptors::no_operation, class AdditiveMonoid, class MultiplicativeOperator, - typename IOType, typename IOView, typename IOStorage, - typename InputType1, typename InputView1, typename InputStorage1, - typename InputType2, typename InputStructure2, typename InputStorage2, typename InputView2, + typename IOType, typename IOView, + typename InputType1, typename InputView1, + typename InputType2, typename InputStructure2, typename InputView2, typename InputType3, typename InputView3, typename InputStorage3 > - RC vxm( VectorView< IOType, IOStructure, IOStorage, IOView, reference_dense > & u, - const VectorView< InputType3, InputStructure3, InputStorage3, InputView3, reference_dense > & mask, - const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense > & v, - const StructuredMatrix< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > & A, + RC vxm( VectorView< IOType, IOStructure, Density::Dense, IOView, reference_dense > & u, + const VectorView< InputType3, InputStructure3, Density::Dense, InputView3, reference_dense > & mask, + const VectorView< InputType1, InputStructure1, Density::Dense, InputView1, reference_dense > & v, + const StructuredMatrix< InputType2, InputStructure2, Density::Dense, InputView2, reference_dense > & A, const AdditiveMonoid & add = AdditiveMonoid(), const MultiplicativeOperator & mul = MultiplicativeOperator(), const typename std::enable_if< grb::is_monoid< AdditiveMonoid >::value && grb::is_operator< MultiplicativeOperator >::value && ! grb::is_object< IOType >::value && @@ -180,16 +180,16 @@ namespace grb { bool output_may_be_masked = true, bool input_may_be_masked = true, class Ring, - typename IOType, typename IOView, typename IOStorage, - typename InputType1, typename InputView1, typename InputStorage1, - typename InputType2, typename InputStructure2, typename InputStorage2, typename InputView2, - typename InputType3, typename InputView3, typename InputStorage3, + typename IOType, typename IOView, + typename InputType1, typename InputView1, + typename InputType2, typename InputStructure2, typename InputView2, + typename InputType3, typename InputView3, typename InputType4, typename InputView4, typename InputStorage4 > - RC vxm( VectorView< IOType, IOStructure, IOStorage, IOView, reference_dense > & u, - const VectorView< InputType3, InputStructure3, InputStorage3, InputView3, reference_dense > & mask, - const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense > & v, - const VectorView< InputType4, InputStructure4, InputStorage4, InputView4, reference_dense > & v_mask, - const StructuredMatrix< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > & A, + RC vxm( VectorView< IOType, IOStructure, Density::Dense, IOView, reference_dense > & u, + const VectorView< InputType3, InputStructure3, Density::Dense, InputView3, reference_dense > & mask, + const VectorView< InputType1, InputStructure1, Density::Dense, InputView1, reference_dense > & v, + const VectorView< InputType4, InputStructure4, Density::Dense, InputView4, reference_dense > & v_mask, + const StructuredMatrix< InputType2, InputStructure2, Density::Dense, InputView2, reference_dense > & A, const Ring & ring = Ring(), const typename std::enable_if< grb::is_semiring< Ring >::value, void >::type * const = NULL ) { throw std::runtime_error( "Needs an implementation." ); @@ -199,12 +199,12 @@ namespace grb { /** \internal Delegates to fully masked version */ template< Descriptor descr = descriptors::no_operation, class Ring, - typename IOType = typename Ring::D4, typename IOView, typename IOStorage, - typename InputType1 = typename Ring::D1, typename InputView1, typename InputStorage1, - typename InputType2 = typename Ring::D2, typename InputStructure2, typename InputStorage2, typename InputView2 > - RC vxm( VectorView< IOType, IOStructure, IOStorage, IOView, reference_dense > & u, - const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense > & v, - const StructuredMatrix< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > & A, + typename IOType = typename Ring::D4, typename IOView, + typename InputType1 = typename Ring::D1, typename InputView1, + typename InputType2 = typename Ring::D2, typename InputStructure2, typename InputView2 > + RC vxm( VectorView< IOType, IOStructure, Density::Dense, IOView, reference_dense > & u, + const VectorView< InputType1, InputStructure1, Density::Dense, InputView1, reference_dense > & v, + const StructuredMatrix< InputType2, InputStructure2, Density::Dense, InputView2, reference_dense > & A, const Ring & ring = Ring(), const typename std::enable_if< grb::is_semiring< Ring >::value, void >::type * const = NULL ) { const VectorView< bool, reference_dense, internal::DefaultCoordinates > empty_mask( 0 ); @@ -213,9 +213,9 @@ namespace grb { /** \internal Delegates to fully masked version */ template< Descriptor descr = descriptors::no_operation, class AdditiveMonoid, class MultiplicativeOperator, typename IOType, typename InputType1, typename InputType2 > - RC vxm( VectorView< IOType, IOStructure, IOStorage, IOView, reference_dense > & u, - const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense > & v, - const StructuredMatrix< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > & A, + RC vxm( VectorView< IOType, IOStructure, Density::Dense, IOView, reference_dense > & u, + const VectorView< InputType1, InputStructure1, Density::Dense, InputView1, reference_dense > & v, + const StructuredMatrix< InputType2, InputStructure2, Density::Dense, InputView2, reference_dense > & A, const AdditiveMonoid & add = AdditiveMonoid(), const MultiplicativeOperator & mul = MultiplicativeOperator(), const typename std::enable_if< grb::is_monoid< AdditiveMonoid >::value && grb::is_operator< MultiplicativeOperator >::value && ! grb::is_object< IOType >::value && @@ -228,14 +228,14 @@ namespace grb { /** \internal Delegates to fully masked version */ template< Descriptor descr = descriptors::no_operation, class Ring, - typename IOType, typename IOView, typename IOStorage, - typename InputType1, typename InputView1, typename InputStorage1, - typename InputType2, typename InputStructure2, typename InputStorage2, typename InputView2, + typename IOType, typename IOView, + typename InputType1, typename InputView1, + typename InputType2, typename InputStructure2, typename InputView2, typename InputType3 = bool, typename InputView3, typename InputStorage3 > - RC mxv( VectorView< IOType, IOStructure, IOStorage, IOView, reference_dense > & u, - const VectorView< InputType3, InputStructure3, InputStorage3, InputView3, reference_dense > & mask, - const StructuredMatrix< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > & A, - const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense > & v, + RC mxv( VectorView< IOType, IOStructure, Density::Dense, IOView, reference_dense > & u, + const VectorView< InputType3, InputStructure3, Density::Dense, InputView3, reference_dense > & mask, + const StructuredMatrix< InputType2, InputStructure2, Density::Dense, InputView2, reference_dense > & A, + const VectorView< InputType1, InputStructure1, Density::Dense, InputView1, reference_dense > & v, const Ring & ring, const typename std::enable_if< grb::is_semiring< Ring >::value, void >::type * const = NULL ) { const VectorView< bool, reference_dense, internal::DefaultCoordinates > empty_mask( 0 ); @@ -247,16 +247,16 @@ namespace grb { bool output_may_be_masked = true, bool input_may_be_masked = true, class Ring, - typename IOType, typename IOView, typename IOStorage, - typename InputType1, typename InputView1, typename InputStorage1, - typename InputType2, typename InputStructure2, typename InputStorage2, typename InputView2, - typename InputType3, typename InputView3, typename InputStorage3, + typename IOType, typename IOView, + typename InputType1, typename InputView1, + typename InputType2, typename InputStructure2, typename InputView2, + typename InputType3, typename InputView3, typename InputType4, typename InputView4, typename InputStorage4 > - RC mxv( VectorView< IOType, IOStructure, IOStorage, IOView, reference_dense > & u, - const VectorView< InputType3, InputStructure3, InputStorage3, InputView3, reference_dense > & mask, - const StructuredMatrix< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > & A, - const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense > & v, - const VectorView< InputType4, InputStructure4, InputStorage4, InputView4, reference_dense > & v_mask, + RC mxv( VectorView< IOType, IOStructure, Density::Dense, IOView, reference_dense > & u, + const VectorView< InputType3, InputStructure3, Density::Dense, InputView3, reference_dense > & mask, + const StructuredMatrix< InputType2, InputStructure2, Density::Dense, InputView2, reference_dense > & A, + const VectorView< InputType1, InputStructure1, Density::Dense, InputView1, reference_dense > & v, + const VectorView< InputType4, InputStructure4, Density::Dense, InputView4, reference_dense > & v_mask, const Ring & ring, const typename std::enable_if< grb::is_semiring< Ring >::value, void >::type * const = NULL ) { @@ -269,12 +269,12 @@ namespace grb { */ template< Descriptor descr = descriptors::no_operation, class Ring, - typename IOType = typename Ring::D4, typename IOView, typename IOStorage, - typename InputType1 = typename Ring::D1, typename InputStructure2, typename InputStorage2, typename InputView2, + typename IOType = typename Ring::D4, typename IOView, + typename InputType1 = typename Ring::D1, typename InputStructure2, typename InputView2, typename InputType2 = typename Ring::D2, typename InputView1, typename InputStorage1 > - RC mxv( VectorView< IOType, IOStructure, IOStorage, IOView, reference_dense > & u, - const StructuredMatrix< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > & A, - const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense > & v, + RC mxv( VectorView< IOType, IOStructure, Density::Dense, IOView, reference_dense > & u, + const StructuredMatrix< InputType2, InputStructure2, Density::Dense, InputView2, reference_dense > & A, + const VectorView< InputType1, InputStructure1, Density::Dense, InputView1, reference_dense > & v, const Ring & ring, const typename std::enable_if< grb::is_semiring< Ring >::value, void >::type * const = NULL ) { const VectorView< bool, view::Original< void >, structure::full, reference_dense, internal::DefaultCoordinates > empty_mask( 0 ); @@ -283,9 +283,9 @@ namespace grb { /** \internal Delegates to fully masked version */ template< Descriptor descr = descriptors::no_operation, class AdditiveMonoid, class MultiplicativeOperator, typename IOType, typename InputType1, typename InputType2 > - RC mxv( VectorView< IOType, IOStructure, IOStorage, IOView, reference_dense > & u, - const StructuredMatrix< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > & A, - const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense > & v, + RC mxv( VectorView< IOType, IOStructure, Density::Dense, IOView, reference_dense > & u, + const StructuredMatrix< InputType2, InputStructure2, Density::Dense, InputView2, reference_dense > & A, + const VectorView< InputType1, InputStructure1, Density::Dense, InputView1, reference_dense > & v, const AdditiveMonoid & add = AdditiveMonoid(), const MultiplicativeOperator & mul = MultiplicativeOperator(), const typename std::enable_if< grb::is_monoid< AdditiveMonoid >::value && grb::is_operator< MultiplicativeOperator >::value && ! grb::is_object< IOType >::value && @@ -303,16 +303,16 @@ namespace grb { bool input_may_be_masked = true, class AdditiveMonoid, class MultiplicativeOperator, - typename IOType, typename IOView, typename IOStorage, - typename InputType1, typename InputView1, typename InputStorage1, - typename InputType2, typename InputStructure2, typename InputStorage2, typename InputView2, - typename InputType3, typename InputView3, typename InputStorage3, + typename IOType, typename IOView, + typename InputType1, typename InputView1, + typename InputType2, typename InputStructure2, typename InputView2, + typename InputType3, typename InputView3, typename InputType4, typename InputView4, typename InputStorage4 > - RC vxm( VectorView< IOType, IOStructure, IOStorage, IOView, reference_dense > & u, - const VectorView< InputType3, InputStructure3, InputStorage3, InputView3, reference_dense > & mask, - const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense > & v, - const VectorView< InputType4, InputStructure4, InputStorage4, InputView4, reference_dense > & v_mask, - const StructuredMatrix< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > & A, + RC vxm( VectorView< IOType, IOStructure, Density::Dense, IOView, reference_dense > & u, + const VectorView< InputType3, InputStructure3, Density::Dense, InputView3, reference_dense > & mask, + const VectorView< InputType1, InputStructure1, Density::Dense, InputView1, reference_dense > & v, + const VectorView< InputType4, InputStructure4, Density::Dense, InputView4, reference_dense > & v_mask, + const StructuredMatrix< InputType2, InputStructure2, Density::Dense, InputView2, reference_dense > & A, const AdditiveMonoid & add = AdditiveMonoid(), const MultiplicativeOperator & mul = MultiplicativeOperator(), const typename std::enable_if< grb::is_monoid< AdditiveMonoid >::value && grb::is_operator< MultiplicativeOperator >::value && ! grb::is_object< IOType >::value && @@ -332,14 +332,14 @@ namespace grb { bool input_may_be_masked = true, class AdditiveMonoid, class MultiplicativeOperator, - typename IOType, typename IOView, typename IOStorage, - typename InputType1, typename InputView1, typename InputStorage1, - typename InputType2, typename InputStructure2, typename InputStorage2, typename InputView2, - typename InputType3, typename InputView3, typename InputStorage3, + typename IOType, typename IOView, + typename InputType1, typename InputView1, + typename InputType2, typename InputStructure2, typename InputView2, + typename InputType3, typename InputView3, typename InputType4, typename InputView4, typename InputStorage4 > RC mxv( VectorView< IOType, IOStructure, reference_dense > & u, const VectorView< InputType3, InputStructure3, reference_dense > & mask, - const StructuredMatrix< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > & A, + const StructuredMatrix< InputType2, InputStructure2, Density::Dense, InputView2, reference_dense > & A, const VectorView< InputType1, InputStructure1, reference_dense > & v, const VectorView< InputType4, InputStructure4, reference_dense > & v_mask, const AdditiveMonoid & add = AdditiveMonoid(), @@ -358,9 +358,9 @@ namespace grb { * * @see grb::eWiseLambda for the user-level specification. */ - template< class ActiveDistribution, typename Func, typename DataType, typename Structure, typename Storage, typename View> + template< class ActiveDistribution, typename Func, typename DataType, typename Structure, typename View> RC eWiseLambda( const Func f, - const StructuredMatrix< DataType, Structure, Storage, View, reference_dense > & A, + const StructuredMatrix< DataType, Structure, Density::Dense, View, reference_dense > & A, const size_t s, const size_t P ) { #ifdef _DEBUG @@ -377,11 +377,11 @@ namespace grb { * @see grb::eWiseLambda for the user-level specification. */ template< typename Func, - typename DataType1, typename Structure1, typename Storage1, typename View1, - typename DataType2, typename View2, typename Storage2, typename... Args > + typename DataType1, typename Structure1, typename View1, + typename DataType2, typename View2, typename... Args > RC eWiseLambda( const Func f, - const StructuredMatrix< DataType1, Structure1, Storage1, View1, reference_dense > & A, - const VectorView< DataType2, DataStructure2, Storage2, View2, reference_dense > x, Args... args ) { + const StructuredMatrix< DataType1, Structure1, Density::Dense, View1, reference_dense > & A, + const VectorView< DataType2, DataStructure2, Density::Dense, View2, reference_dense > x, Args... args ) { // do size checking if( ! ( size( x ) == nrows( A ) || size( x ) == ncols( A ) ) ) { std::cerr << "Mismatching dimensions: given vector of size " << size( x ) << " has nothing to do with either matrix dimension (" << nrows( A ) << " nor " << ncols( A ) << ").\n"; diff --git a/include/graphblas/denseref/blas3.hpp b/include/graphblas/denseref/blas3.hpp index 2e55cfcbe..8dde2034a 100644 --- a/include/graphblas/denseref/blas3.hpp +++ b/include/graphblas/denseref/blas3.hpp @@ -140,12 +140,12 @@ namespace grb { typename OutputType, typename InputType1, typename InputType2, class Operator, class Monoid, typename OutputStructure, typename InputStructure1, typename InputStructure2, - typename OutputStorage, typename InputStorage1, typename InputStorage2, + typename OutputView, typename InputView1, typename InputView2 > - RC mxm_generic( StructuredMatrix< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > &C, - const StructuredMatrix< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense > &A, - const StructuredMatrix< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > &B, + RC mxm_generic( StructuredMatrix< OutputType, OutputStructure, Density::Dense, OutputView, reference_dense > &C, + const StructuredMatrix< InputType1, InputStructure1, Density::Dense, InputView1, reference_dense > &A, + const StructuredMatrix< InputType2, InputStructure2, Density::Dense, InputView2, reference_dense > &B, const Operator &oper, const Monoid &monoid, const MulMonoid &mulMonoid, @@ -179,9 +179,9 @@ namespace grb { class Operator, class Monoid, typename OutputView = view::Original< void >, typename InputView1 = view::Original< void >, typename InputView2 = view::Original< void > > - RC mxm_generic( StructuredMatrix< OutputType, structures::General, storage::Dense, OutputView, reference_dense > &C, - const StructuredMatrix< InputType1, structures::General, storage::Dense, InputView1, reference_dense > &A, - const StructuredMatrix< InputType2, structures::General, storage::Dense, InputView2, reference_dense > &B, + RC mxm_generic( StructuredMatrix< OutputType, structures::General, Density::Dense, OutputView, reference_dense > &C, + const StructuredMatrix< InputType1, structures::General, Density::Dense, InputView1, reference_dense > &A, + const StructuredMatrix< InputType2, structures::General, Density::Dense, InputView2, reference_dense > &B, const Operator &oper, const Monoid &monoid, const MulMonoid &mulMonoid, @@ -368,14 +368,14 @@ namespace grb { class MulMonoid, typename OutputType, typename InputType1, typename InputType2, typename OutputStructure, typename InputStructure1, typename InputStructure2, - typename OutputStorage, typename InputStorage1, typename InputStorage2, + typename OutputView, typename InputView1, typename InputView2, class Operator > - RC eWiseApply_matrix_generic( StructuredMatrix< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > *C, - const StructuredMatrix< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense > *A, + RC eWiseApply_matrix_generic( StructuredMatrix< OutputType, OutputStructure, Density::Dense, OutputView, reference_dense > *C, + const StructuredMatrix< InputType1, InputStructure1, Density::Dense, InputView1, reference_dense > *A, const InputType1 *alpha, - const StructuredMatrix< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > *B, + const StructuredMatrix< InputType2, InputStructure2, Density::Dense, InputView2, reference_dense > *B, const InputType1 *beta, const Operator &oper, const MulMonoid &mulMonoid, @@ -456,9 +456,6 @@ namespace grb { * @tparam OutputStructure The structure of the output matrix * @tparam InputStructure1 The structure of the left-hand side matrix * @tparam InputStructure2 The structure of the right-hand matrix - * @tparam OutputStorage The type of storage scheme of the output matrix - * @tparam InputStorage1 The type of storage scheme of the left-hand side matrix - * @tparam InputStorage2 The type of storage scheme of the right-hand side matrix * @tparam OutputView The type of view of the output matrix * @tparam InputView1 The type of view of the left-hand matrix * @tparam InputView2 The type of view of the right-hand matrix @@ -480,12 +477,12 @@ namespace grb { Descriptor descr = descriptors::no_operation, typename OutputType, typename InputType1, typename InputType2, typename OutputStructure, typename InputStructure1, typename InputStructure2, - typename OutputStorage, typename InputStorage1, typename InputStorage2, + typename OutputView, typename InputView1, typename InputView2, class MulMonoid > - RC eWiseApply( StructuredMatrix< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > &C, - const StructuredMatrix< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense > &A, - const StructuredMatrix< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > &B, + RC eWiseApply( StructuredMatrix< OutputType, OutputStructure, Density::Dense, OutputView, reference_dense > &C, + const StructuredMatrix< InputType1, InputStructure1, Density::Dense, InputView1, reference_dense > &A, + const StructuredMatrix< InputType2, InputStructure2, Density::Dense, InputView2, reference_dense > &B, const MulMonoid &mulmono, const PHASE phase = NUMERICAL, const typename std::enable_if< !grb::is_object< OutputType >::value && @@ -533,12 +530,12 @@ namespace grb { Descriptor descr = descriptors::no_operation, typename OutputType, typename InputType1, typename InputType2, typename OutputStructure, typename InputStructure2, - typename OutputStorage, typename InputStorage2, + typename OutputView, typename InputView2, class MulMonoid > - RC eWiseApply( StructuredMatrix< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > &C, + RC eWiseApply( StructuredMatrix< OutputType, OutputStructure, Density::Dense, OutputView, reference_dense > &C, const InputType1 &alpha, - const StructuredMatrix< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > &B, + const StructuredMatrix< InputType2, InputStructure2, Density::Dense, InputView2, reference_dense > &B, const MulMonoid &mulmono, const PHASE phase = NUMERICAL, const typename std::enable_if< !grb::is_object< OutputType >::value && @@ -571,7 +568,7 @@ namespace grb { std::cout << "In grb::eWiseApply_matrix_generic (reference_dense, monoid)\n"; #endif - const StructuredMatrix< InputType1, structures::General, storage::Dense, view::Original< void >, reference_dense > * no_matrix = nullptr; + const StructuredMatrix< InputType1, structures::General, Density::Dense, view::Original< void >, reference_dense > * no_matrix = nullptr; return internal::eWiseApply_matrix_generic< true, true, false, descr >( &C, no_matrix, @@ -591,11 +588,11 @@ namespace grb { Descriptor descr = descriptors::no_operation, typename OutputType, typename InputType1, typename InputType2, typename OutputStructure, typename InputStructure1, - typename OutputStorage, typename InputStorage1, + typename OutputView, typename InputView1, class MulMonoid > - RC eWiseApply( StructuredMatrix< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > &C, - const StructuredMatrix< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense > &A, + RC eWiseApply( StructuredMatrix< OutputType, OutputStructure, Density::Dense, OutputView, reference_dense > &C, + const StructuredMatrix< InputType1, InputStructure1, Density::Dense, InputView1, reference_dense > &A, const InputType2 &beta, const MulMonoid &mulmono, const PHASE phase = NUMERICAL, @@ -629,7 +626,7 @@ namespace grb { std::cout << "In grb::eWiseApply_matrix_generic (reference_dense, monoid)\n"; #endif - const StructuredMatrix< InputType2, structures::General, storage::Dense, view::Original< void >, reference_dense > * no_matrix = nullptr; + const StructuredMatrix< InputType2, structures::General, Density::Dense, view::Original< void >, reference_dense > * no_matrix = nullptr; return internal::eWiseApply_matrix_generic< true, false, true, descr >( &C, &A, @@ -652,9 +649,6 @@ namespace grb { * @tparam OutputStructure The structure of the output matrix * @tparam InputStructure1 The structure of the left-hand side matrix * @tparam InputStructure2 The structure of the right-hand matrix - * @tparam OutputStorage The type of storage scheme of the output matrix - * @tparam InputStorage1 The type of storage scheme of the left-hand side matrix - * @tparam InputStorage2 The type of storage scheme of the right-hand side matrix * @tparam OutputView The type of view of the output matrix * @tparam InputView1 The type of view of the left-hand matrix * @tparam InputView2 The type of view of the right-hand matrix @@ -709,12 +703,12 @@ namespace grb { Descriptor descr = descriptors::no_operation, typename OutputType, typename InputType1, typename InputType2, typename OutputStructure, typename InputStructure1, typename InputStructure2, - typename OutputStorage, typename InputStorage1, typename InputStorage2, + typename OutputView, typename InputView1, typename InputView2, typename Ring> - RC eWiseAdd( StructuredMatrix< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > &C, - const StructuredMatrix< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense > &A, - const StructuredMatrix< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > &B, + RC eWiseAdd( StructuredMatrix< OutputType, OutputStructure, Density::Dense, OutputView, reference_dense > &C, + const StructuredMatrix< InputType1, InputStructure1, Density::Dense, InputView1, reference_dense > &A, + const StructuredMatrix< InputType2, InputStructure2, Density::Dense, InputView2, reference_dense > &B, const Ring & ring = Ring(), const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_semiring< Ring >::value, void >::type * const = NULL ) { @@ -745,9 +739,6 @@ namespace grb { * @tparam InputStructure1 The Structure type applied to the left-hand vector. * @tparam InputStructure2 The Structure type applied to the right-hand vector. * @tparam OutputStructure1 The Structure type applied to the output vector. - * @tparam InputStorage1 The Storage type applied to the left-hand vector. - * @tparam InputStorage2 The Storage type applied to the right-hand vector. - * @tparam OutputStorage1 The Storage type applied to the output vector. * @tparam InputView1 The view type applied to the left-hand vector. * @tparam InputView2 The view type applied to the right-hand vector. * @tparam OutputView1 The view type applied to the output vector. @@ -768,11 +759,11 @@ namespace grb { template< Descriptor descr = descriptors::no_operation, typename OutputType, typename InputType1, typename InputType2, typename OutputStructure, typename InputStructure1, typename InputStructure2, - typename OutputStorage, typename InputStorage1, typename InputStorage2, + typename OutputView, typename InputView1, typename InputView2, class Operator > - RC outer( StructuredMatrix< OutputType, OutputStructure, OutputStorage, OutputView, reference_dense > & A, - const VectorView< InputType1, InputStructure1, InputStorage1, InputView1, reference_dense > & u, - const VectorView< InputType2, InputStructure2, InputStorage2, InputView2, reference_dense > & v, + RC outer( StructuredMatrix< OutputType, OutputStructure, Density::Dense, OutputView, reference_dense > & A, + const VectorView< InputType1, InputStructure1, Density::Dense, InputView1, reference_dense > & u, + const VectorView< InputType2, InputStructure2, Density::Dense, InputView2, reference_dense > & v, const Operator & mul = Operator(), const typename std::enable_if< grb::is_operator< Operator >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< OutputType >::value, void >::type * const = NULL ) { @@ -798,8 +789,8 @@ namespace grb { return MISMATCH; } - grb::StructuredMatrix< InputType1, structures::General, storage::Dense, view::Original< void >, reference_dense > u_matrix( nrows, 1 ); - grb::StructuredMatrix< InputType2, structures::General, storage::Dense, view::Original< void >, reference_dense > v_matrix( 1, ncols ); + grb::StructuredMatrix< InputType1, structures::General, Density::Dense, view::Original< void >, reference_dense > u_matrix( nrows, 1 ); + grb::StructuredMatrix< InputType2, structures::General, Density::Dense, view::Original< void >, reference_dense > v_matrix( 1, ncols ); // auto u_converter = grb::utils::makeVectorToMatrixConverter< InputType1 >( u, []( const size_t & ind, const InputType1 & val ) { // return std::make_pair( std::make_pair( ind, 0 ), val ); diff --git a/include/graphblas/denseref/io.hpp b/include/graphblas/denseref/io.hpp index bbd2131f4..f5926c424 100644 --- a/include/graphblas/denseref/io.hpp +++ b/include/graphblas/denseref/io.hpp @@ -154,8 +154,8 @@ namespace grb { * * @see grb::buildMatrix */ - template< typename InputType, typename Structure, typename Storage, typename View, typename fwd_iterator > - RC buildMatrix( StructuredMatrix< InputType, Structure, Storage, View, reference_dense > & A, const fwd_iterator & start, const fwd_iterator & end ) noexcept { + template< typename InputType, typename Structure, typename View, typename fwd_iterator > + RC buildMatrix( StructuredMatrix< InputType, Structure, Density::Dense, View, reference_dense > & A, const fwd_iterator & start, const fwd_iterator & end ) noexcept { (void)A; (void)start; (void)end; diff --git a/include/graphblas/denseref/matrix.hpp b/include/graphblas/denseref/matrix.hpp index 383eacc78..c0f955025 100644 --- a/include/graphblas/denseref/matrix.hpp +++ b/include/graphblas/denseref/matrix.hpp @@ -39,7 +39,7 @@ //#include //for help with dealing with pattern matrix input #include #include -#include +#include #include #include @@ -339,13 +339,13 @@ namespace grb { Matrix< T, reference_dense > & getContainer( MatrixContainer< T > & A ); /** Container reference getters. Defer the call to base class friend function */ - template< typename T, typename Structure, typename Storage, typename View > - const Matrix< T, reference_dense > & getContainer( const StructuredMatrix< T, Structure, Storage, View, reference_dense > & A ) { + template< typename T, typename Structure, enum Density density, typename View > + const Matrix< T, reference_dense > & getContainer( const StructuredMatrix< T, Structure, density, View, reference_dense > & A ) { return getContainer( A ); } - template< typename T, typename Structure, typename Storage, typename View > - Matrix< T, reference_dense > & getContainer( StructuredMatrix< T, Structure, Storage, View, reference_dense > & A ) { + template< typename T, typename Structure, enum Density density, typename View > + Matrix< T, reference_dense > & getContainer( StructuredMatrix< T, Structure, density, View, reference_dense > & A ) { return getContainer( A ); } @@ -362,29 +362,29 @@ namespace grb { void getInitialized( MatrixBase &, bool ) noexcept; - template< typename T, typename Structure, typename Storage, typename View > - bool getInitialized( StructuredMatrix< T, Structure, Storage, View, reference_dense > & A ) noexcept { + template< typename T, typename Structure, enum Density density, typename View > + bool getInitialized( StructuredMatrix< T, Structure, density, View, reference_dense > & A ) noexcept { return getInitialized( A ); } - template< typename T, typename Structure, typename Storage, typename View > - void setInitialized( StructuredMatrix< T, Structure, Storage, View, reference_dense > & A, bool initialized ) noexcept { + template< typename T, typename Structure, enum Density density, typename View > + void setInitialized( StructuredMatrix< T, Structure, density, View, reference_dense > & A, bool initialized ) noexcept { setInitialized( A, initialized ); } } // namespace internal template< typename D, typename Structure, typename View > - size_t nrows( const StructuredMatrix< D, Structure, storage::Dense, View, reference_dense > & A ) noexcept { + size_t nrows( const StructuredMatrix< D, Structure, Density::Dense, View, reference_dense > & A ) noexcept { return internal::nrows( A ); } template< typename D, typename Structure, typename View > - size_t ncols( const StructuredMatrix< D, Structure, storage::Dense, View, reference_dense > & A ) noexcept { + size_t ncols( const StructuredMatrix< D, Structure, Density::Dense, View, reference_dense > & A ) noexcept { return internal::ncols( A ); } template< typename D, typename Structure, typename View > - std::pair< size_t, size_t > dims( const StructuredMatrix< D, Structure, storage::Dense, View, reference_dense > & A ) noexcept { + std::pair< size_t, size_t > dims( const StructuredMatrix< D, Structure, Density::Dense, View, reference_dense > & A ) noexcept { return internal::dims( A ); } @@ -478,8 +478,9 @@ namespace grb { * made depending on whether a decision about instantiating the matrix is made by the framework. * * The specific storage scheme choice depends on the chosen backend and the structure of the matrix. + * \internal \todo Revisit this when introducing storage mapping functions. */ - storage::Dense storage_scheme; + // Storage storage_scheme; /** * @brief Construct a new structured matrix container object. @@ -494,8 +495,7 @@ namespace grb { */ MatrixContainer( size_t rows, size_t cols, size_t cap = 0 ) : MatrixBase( rows, cols ), - _container( new Matrix< T, reference_dense >( rows, cols, cap ) ), - storage_scheme( storage::full ) {} + _container( new Matrix< T, reference_dense >( rows, cols, cap ) ) {} }; @@ -530,8 +530,13 @@ namespace grb { * The logical layout of a structured matrix maps to a physical counterpart via * a storage scheme which typically depends on the chosen structure and the selected * backend. grb::Matrix and grb::Vector may be used as interfaces to such a physical - * layout, where the interpration of their content is a function of the structure - * information. + * layout. + * To visualize this, you may think of a band matrix. Using a + * full dense or a banded storage schemes would require + * the use of a \a grb::Matrix container (see include/graphblas/density.hpp for + * more details about the supported storage schemes). However, the interpration of its + * content would differ in the two cases being a function of both the Structure + * information and the storage scheme combined. * * Views can be used to create logical \em perspectives on top of a container. * For example, one may decide to refer to the transpose of a matrix or to treat @@ -545,38 +550,36 @@ namespace grb { * Structured matrices defined as views on other matrices do not instantiate a * new container but refer to the one used by their targets. * See the two specializations - * \a StructuredMatrix - * and \a StructuredMatrix, reference_dense > + * \a StructuredMatrix + * and \a StructuredMatrix, reference_dense > * as examples of structured matrix types without and with physical container, respectively. * * - * @tparam T The type of the matrix elements. \a T shall not be a GraphBLAS - * type. - * @tparam Structure One of the matrix structures defined in \a grb::structures. - * @tparam StorageSchemeType Either \em enum \a storage::Dense or \em enum - * \a storage::Sparse. - * \a StructuredMatrix will be allowed to use storage schemes - * defined within their specified \a StorageSchemeType. - * @tparam View One of the matrix views in \a grb::view. - * All static views except for \a view::Original (via - * \a view::Original cannot instantiate a new container - * and only allow to refer to a previously defined - * \a StructuredMatrix. - * The \a View parameter should not be used directly - * by the user but selected via \a get_view function. - * + * @tparam T The type of the matrix elements. \a T shall not be a GraphBLAS + * type. + * @tparam Structure One of the matrix structures defined in \a grb::structures. + * @tparam density Either \em enum \a Density::Dense or \em enum + * \a storage::Sparse. + * @tparam View One of the matrix views in \a grb::view. + * All static views except for \a view::Original (via + * \a view::Original cannot instantiate a new container + * and only allow to refer to a previously defined + * \a StructuredMatrix. + * The \a View parameter should not be used directly + * by the user but selected via \a get_view function. + * * See examples of StructuredMatrix definitions within \a include/graphblas/denseref/matrix.hpp * and the \a dense_structured_matrix.cpp unit test. * */ - template< typename T, typename Structure, typename StorageSchemeType, typename View > - class StructuredMatrix { }; + template< typename T, typename Structure, enum Density density, typename View > + class StructuredMatrix { }; /** * @brief General matrix with physical container. */ template< typename T > - class StructuredMatrix< T, structures::General, storage::Dense, view::Original< void >, reference_dense > : + class StructuredMatrix< T, structures::General, Density::Dense, view::Original< void >, reference_dense > : public internal::MatrixContainer< T > { private: @@ -584,12 +587,12 @@ namespace grb { Storage info friends ******************** */ - using self_type = StructuredMatrix< T, structures::General, storage::Dense, view::Original< void >, reference_dense >; + using self_type = StructuredMatrix< T, structures::General, Density::Dense, view::Original< void >, reference_dense >; // template< typename fwd_iterator > - // friend RC buildMatrix( StructuredMatrix< T, structures::General, storage::Dense, view::Original< void >, reference_dense > &, const fwd_iterator & start, const fwd_iterator & end ); + // friend RC buildMatrix( StructuredMatrix< T, structures::General, Density::Dense, view::Original< void >, reference_dense > &, const fwd_iterator & start, const fwd_iterator & end ); template< typename fwd_iterator > - friend RC buildMatrix( StructuredMatrix< T, structures::General, storage::Dense, view::Original< void >, reference_dense > & A, const fwd_iterator & start, const fwd_iterator & end ); + friend RC buildMatrix( StructuredMatrix< T, structures::General, Density::Dense, view::Original< void >, reference_dense > & A, const fwd_iterator & start, const fwd_iterator & end ); template< typename fwd_iterator > RC buildMatrixUnique( const fwd_iterator & start, const fwd_iterator & end ) { @@ -609,17 +612,17 @@ namespace grb { template < bool d > struct view_type< view::original, d > { - using type = StructuredMatrix< T, structures::General, storage::Dense, view::Original< self_type >, reference_dense >; + using type = StructuredMatrix< T, structures::General, Density::Dense, view::Original< self_type >, reference_dense >; }; template < bool d > struct view_type< view::transpose, d > { - using type = StructuredMatrix< T, structures::General, storage::Dense, view::Transpose< self_type >, reference_dense >; + using type = StructuredMatrix< T, structures::General, Density::Dense, view::Transpose< self_type >, reference_dense >; }; template < bool d > struct view_type< view::diagonal, d > { - using type = VectorView< T, structures::General, storage::Dense, view::Diagonal< self_type >, reference_dense >; + using type = VectorView< T, structures::General, Density::Dense, view::Diagonal< self_type >, reference_dense >; }; StructuredMatrix( const size_t rows, const size_t cols, const size_t cap = 0 ) : @@ -632,11 +635,11 @@ namespace grb { * View of a general Matrix. */ template< typename T, typename View > - class StructuredMatrix< T, structures::General, storage::Dense, View, reference_dense > : + class StructuredMatrix< T, structures::General, Density::Dense, View, reference_dense > : public internal::MatrixReference< typename View::applied_to > { private: - using self_type = StructuredMatrix< T, structures::General, storage::Dense, View, reference_dense >; + using self_type = StructuredMatrix< T, structures::General, Density::Dense, View, reference_dense >; using target_type = typename View::applied_to; public: @@ -649,12 +652,12 @@ namespace grb { template < bool d > struct view_type< view::original, d > { - using type = StructuredMatrix< T, structures::General, storage::Dense, view::Original< self_type >, reference_dense >; + using type = StructuredMatrix< T, structures::General, Density::Dense, view::Original< self_type >, reference_dense >; }; template < bool d > struct view_type< view::transpose, d > { - using type = StructuredMatrix< T, structures::General, storage::Dense, view::Transpose< self_type >, reference_dense >; + using type = StructuredMatrix< T, structures::General, Density::Dense, view::Transpose< self_type >, reference_dense >; }; StructuredMatrix( ) : internal::MatrixBase( 0, 0 ) {} @@ -667,7 +670,7 @@ namespace grb { }; // StructuredMatrix General reference template< typename T, typename Structure > - class StructuredMatrix< T, Structure, storage::Dense, view::Original< void >, reference_dense > : + class StructuredMatrix< T, Structure, Density::Dense, view::Original< void >, reference_dense > : public internal::MatrixContainer< T > { private: @@ -675,10 +678,10 @@ namespace grb { Storage info friends ******************** */ - using self_type = StructuredMatrix< T, Structure, storage::Dense, view::Original< void >, reference_dense >; + using self_type = StructuredMatrix< T, Structure, Density::Dense, view::Original< void >, reference_dense >; template< typename fwd_iterator > - friend RC buildMatrix( StructuredMatrix< T, Structure, storage::Dense, view::Original< void >, reference_dense > &, const fwd_iterator &, const fwd_iterator ) noexcept; + friend RC buildMatrix( StructuredMatrix< T, Structure, Density::Dense, view::Original< void >, reference_dense > &, const fwd_iterator &, const fwd_iterator ) noexcept; public: using value_type = T; @@ -690,7 +693,7 @@ namespace grb { template < bool d > struct view_type< view::original, d > { - using type = StructuredMatrix< T, Structure, storage::Dense, view::Original< self_type >, reference_dense >; + using type = StructuredMatrix< T, Structure, Density::Dense, view::Original< self_type >, reference_dense >; }; StructuredMatrix( const size_t rows, const size_t cols, const size_t cap = 0 ) : @@ -698,14 +701,14 @@ namespace grb { }; // class StructuredMatrix template< typename T > - class StructuredMatrix< T, structures::Square, storage::Dense, view::Original< void >, reference_dense > : + class StructuredMatrix< T, structures::Square, Density::Dense, view::Original< void >, reference_dense > : public internal::MatrixContainer< T > { private: - using self_type = StructuredMatrix< T, structures::Square, storage::Dense, view::Original< void >, reference_dense >; + using self_type = StructuredMatrix< T, structures::Square, Density::Dense, view::Original< void >, reference_dense >; - template< typename InputType, typename Structure, typename Storage, typename View, typename fwd_iterator > - friend RC buildMatrix( StructuredMatrix< InputType, Structure, Storage, View, reference_dense > &, const fwd_iterator & start, const fwd_iterator & end ) noexcept; + template< typename InputType, typename Structure, typename View, typename fwd_iterator > + friend RC buildMatrix( StructuredMatrix< InputType, Structure, Density::Dense, View, reference_dense > &, const fwd_iterator & start, const fwd_iterator & end ) noexcept; template< typename fwd_iterator > RC buildMatrixUnique( const fwd_iterator & start, const fwd_iterator & end ) { @@ -723,12 +726,12 @@ namespace grb { template < bool d > struct view_type< view::original, d > { - using type = StructuredMatrix< T, structures::Square, storage::Dense, view::Original< self_type >, reference_dense >; + using type = StructuredMatrix< T, structures::Square, Density::Dense, view::Original< self_type >, reference_dense >; }; template < bool d > struct view_type< view::transpose, d > { - using type = StructuredMatrix< T, structures::Square, storage::Dense, view::Transpose< self_type >, reference_dense >; + using type = StructuredMatrix< T, structures::Square, Density::Dense, view::Transpose< self_type >, reference_dense >; }; StructuredMatrix( const size_t rows, const size_t cap = 0 ) : @@ -737,11 +740,11 @@ namespace grb { }; // StructuredMatrix Square, container template< typename T, typename View > - class StructuredMatrix< T, structures::Square, storage::Dense, View, reference_dense > : + class StructuredMatrix< T, structures::Square, Density::Dense, View, reference_dense > : public internal::MatrixReference< typename View::applied_to > { private: - using self_type = StructuredMatrix< T, structures::Square, storage::Dense, View, reference_dense >; + using self_type = StructuredMatrix< T, structures::Square, Density::Dense, View, reference_dense >; using target_type = typename View::applied_to; public: @@ -754,12 +757,12 @@ namespace grb { template < bool d > struct view_type< view::original, d > { - using type = StructuredMatrix< T, structures::Square, storage::Dense, view::Original< self_type >, reference_dense >; + using type = StructuredMatrix< T, structures::Square, Density::Dense, view::Original< self_type >, reference_dense >; }; template < bool d > struct view_type< view::transpose, d > { - using type = StructuredMatrix< T, structures::Square, storage::Dense, view::Transpose< self_type >, reference_dense >; + using type = StructuredMatrix< T, structures::Square, Density::Dense, view::Transpose< self_type >, reference_dense >; }; // ref to empty matrix @@ -775,7 +778,7 @@ namespace grb { // StructuredMatrix UpperTriangular, container template< typename T > - class StructuredMatrix< T, structures::UpperTriangular, storage::Dense, view::Original< void >, reference_dense > : + class StructuredMatrix< T, structures::UpperTriangular, Density::Dense, view::Original< void >, reference_dense > : public internal::MatrixContainer< T > { private: @@ -783,10 +786,10 @@ namespace grb { Storage info friends ******************** */ - using self_type = StructuredMatrix< T, structures::UpperTriangular, storage::Dense, view::Original< void >, reference_dense >; + using self_type = StructuredMatrix< T, structures::UpperTriangular, Density::Dense, view::Original< void >, reference_dense >; - template< typename InputType, typename Structure, typename Storage, typename View, typename fwd_iterator > - friend RC buildMatrix( StructuredMatrix< InputType, Structure, Storage, View, reference_dense > &, const fwd_iterator & start, const fwd_iterator & end ) noexcept; + template< typename InputType, typename Structure, typename View, typename fwd_iterator > + friend RC buildMatrix( StructuredMatrix< InputType, Structure, Density::Dense, View, reference_dense > &, const fwd_iterator & start, const fwd_iterator & end ) noexcept; template< typename fwd_iterator > RC buildMatrixUnique( const fwd_iterator & start, const fwd_iterator & end ) { @@ -804,12 +807,12 @@ namespace grb { template < bool d > struct view_type< view::original, d > { - using type = StructuredMatrix< T, structures::UpperTriangular, storage::Dense, view::Original< self_type >, reference_dense >; + using type = StructuredMatrix< T, structures::UpperTriangular, Density::Dense, view::Original< self_type >, reference_dense >; }; template < bool d > struct view_type< view::transpose, d > { - using type = StructuredMatrix< T, structures::LowerTriangular, storage::Dense, view::Transpose< self_type >, reference_dense >; + using type = StructuredMatrix< T, structures::LowerTriangular, Density::Dense, view::Transpose< self_type >, reference_dense >; }; StructuredMatrix( const size_t rows, const size_t cols, const size_t cap = 0 ) : @@ -819,11 +822,11 @@ namespace grb { // StructuredMatrix UpperTriangular, reference template< typename T, typename View > - class StructuredMatrix< T, structures::UpperTriangular, storage::Dense, View, reference_dense > : + class StructuredMatrix< T, structures::UpperTriangular, Density::Dense, View, reference_dense > : public internal::MatrixReference< typename View::applied_to > { private: - using self_type = StructuredMatrix< T, structures::UpperTriangular, storage::Dense, View, reference_dense >; + using self_type = StructuredMatrix< T, structures::UpperTriangular, Density::Dense, View, reference_dense >; using target_type = typename View::applied_to; public: @@ -836,12 +839,12 @@ namespace grb { template < bool d > struct view_type< view::original, d > { - using type = StructuredMatrix< T, structures::UpperTriangular, storage::Dense, view::Original< self_type >, reference_dense >; + using type = StructuredMatrix< T, structures::UpperTriangular, Density::Dense, view::Original< self_type >, reference_dense >; }; template < bool d > struct view_type< view::transpose, d > { - using type = StructuredMatrix< T, structures::LowerTriangular, storage::Dense, view::Transpose< self_type >, reference_dense >; + using type = StructuredMatrix< T, structures::LowerTriangular, Density::Dense, view::Transpose< self_type >, reference_dense >; }; // ref to empty matrix @@ -859,7 +862,7 @@ namespace grb { // StructuredMatrix Identity, container // Should Identity be a MatrixContainer? template< typename T > - class StructuredMatrix< T, structures::Identity, storage::Dense, view::Original< void >, reference_dense > : + class StructuredMatrix< T, structures::Identity, Density::Dense, view::Original< void >, reference_dense > : public internal::MatrixContainer< T > { private: @@ -867,10 +870,10 @@ namespace grb { Storage info friends ******************** */ - using self_type = StructuredMatrix< T, structures::Identity, storage::Dense, view::Original< void >, reference_dense >; + using self_type = StructuredMatrix< T, structures::Identity, Density::Dense, view::Original< void >, reference_dense >; - template< typename InputType, typename Structure, typename Storage, typename View, typename fwd_iterator > - friend RC buildMatrix( StructuredMatrix< InputType, Structure, Storage, View, reference_dense > &, const fwd_iterator & start, const fwd_iterator & end ) noexcept; + template< typename InputType, typename Structure, typename View, typename fwd_iterator > + friend RC buildMatrix( StructuredMatrix< InputType, Structure, Density::Dense, View, reference_dense > &, const fwd_iterator & start, const fwd_iterator & end ) noexcept; template< typename fwd_iterator > RC buildMatrixUnique( const fwd_iterator & start, const fwd_iterator & end ) { @@ -888,12 +891,12 @@ namespace grb { template < bool d > struct view_type< view::original, d > { - using type = StructuredMatrix< T, structures::Identity, storage::Dense, view::Original< self_type >, reference_dense >; + using type = StructuredMatrix< T, structures::Identity, Density::Dense, view::Original< self_type >, reference_dense >; }; template < bool d > struct view_type< view::transpose, d > { - using type = StructuredMatrix< T, structures::Identity, storage::Dense, view::Transpose< self_type >, reference_dense >; + using type = StructuredMatrix< T, structures::Identity, Density::Dense, view::Transpose< self_type >, reference_dense >; }; StructuredMatrix( const size_t rows, const size_t cap = 0 ) : @@ -925,13 +928,13 @@ namespace grb { * The function guarantees the created view is non-overlapping with other * existing views only when the check can be performed in constant time. * - * @tparam T The matrix' elements type - * @tparam Structure The structure of the source and target matrix view - * @tparam StorageSchemeType The type (i.e., \a grb::storage:Dense or \a grb::storage:Sparse) of storage scheme - * @tparam View The source's View type - * @tparam backend The target backend + * @tparam T The matrix' elements type + * @tparam Structure The structure of the source and target matrix view + * @tparam density The type (i.e., sparse or dense) of storage scheme + * @tparam View The source's View type + * @tparam backend The target backend * - * @param source The source matrix + * @param source The source matrix * * @return A new original view over the source structured matrix. * @@ -947,11 +950,11 @@ namespace grb { * */ template< - typename T, typename Structure, typename StorageSchemeType, typename View, enum Backend backend > - typename StructuredMatrix< T, Structure, StorageSchemeType, View, backend >::template view_type< view::original >::type - get_view( StructuredMatrix< T, Structure, StorageSchemeType, View, backend > & source ) { + typename T, typename Structure, enum Density density, typename View, enum Backend backend > + typename StructuredMatrix< T, Structure, density, View, backend >::template view_type< view::original >::type + get_view( StructuredMatrix< T, Structure, density, View, backend > & source ) { - using source_strmat_t = StructuredMatrix< T, Structure, StorageSchemeType, View, backend >; + using source_strmat_t = StructuredMatrix< T, Structure, density, View, backend >; using target_strmat_t = typename source_strmat_t::template view_type< view::original >::type; target_strmat_t target( source ); @@ -966,14 +969,14 @@ namespace grb { * The function guarantees the created view is non-overlapping with other * existing views only when the check can be performed in constant time. * - * @tparam target_view One of the supported views listed in \a view::Views - * @tparam T The matrix' elements type - * @tparam Structure The structure of the source and target matrix view - * @tparam StorageSchemeType The type (i.e., \a grb::storage:Dense or \a grb::storage:Sparse) of storage scheme - * @tparam View The source's View type - * @tparam backend The target backend + * @tparam target_view One of the supported views listed in \a view::Views + * @tparam T The matrix' elements type + * @tparam Structure The structure of the source and target matrix view + * @tparam density The type (i.e., sparse or dense) of storage scheme + * @tparam View The source's View type + * @tparam backend The target backend * - * @param source The source structured matrix + * @param source The source structured matrix * * @return A new \a target_view view over the source matrix. @@ -990,11 +993,11 @@ namespace grb { */ template< enum view::Views target_view, - typename T, typename Structure, typename StorageSchemeType, typename View, enum Backend backend > - typename StructuredMatrix< T, Structure, StorageSchemeType, View, backend >::template view_type< target_view >::type - get_view( StructuredMatrix< T, Structure, StorageSchemeType, View, backend > &source ) { + typename T, typename Structure, enum Density density, typename View, enum Backend backend > + typename StructuredMatrix< T, Structure, density, View, backend >::template view_type< target_view >::type + get_view( StructuredMatrix< T, Structure, density, View, backend > &source ) { - using source_strmat_t = StructuredMatrix< T, Structure, StorageSchemeType, View, backend >; + using source_strmat_t = StructuredMatrix< T, Structure, density, View, backend >; using target_strmat_t = typename source_strmat_t::template view_type< target_view >::type; target_strmat_t target( source ); @@ -1012,15 +1015,15 @@ namespace grb { * The function guarantees the created view is non-overlapping with other existing views only when the * check can be performed in constant time. * - * @tparam TargetStructure The target structure of the new view. It should verify - * grb::is_in . - * @tparam T The matrix's elements type - * @tparam Structure The structure of the source and target matrix view - * @tparam StorageSchemeType The type (i.e., \a grb::storage:Dense or \a grb::storage:Sparse) of storage scheme - * @tparam View The source's View type - * @tparam backend The target backend + * @tparam TargetStructure The target structure of the new view. It should verify + * grb::is_in . + * @tparam T The matrix's elements type + * @tparam Structure The structure of the source and target matrix view + * @tparam density The type (i.e., \a grb::Density:Dense or \a grb::Density:Sparse) of storage scheme + * @tparam View The source's View type + * @tparam backend The target backend * - * @param source The source structured matrix + * @param source The source structured matrix * * @return A new original view over the source structured matrix. * @@ -1037,15 +1040,15 @@ namespace grb { */ template< typename TargetStructure, - typename T, typename Structure, typename StorageSchemeType, typename View, enum Backend backend > - StructuredMatrix< T, TargetStructure, StorageSchemeType, view::Original< StructuredMatrix< T, Structure, StorageSchemeType, View, backend > >, backend > - get_view( StructuredMatrix< T, Structure, StorageSchemeType, View, backend > &source ) { + typename T, typename Structure, enum Density density, typename View, enum Backend backend > + StructuredMatrix< T, TargetStructure, density, view::Original< StructuredMatrix< T, Structure, density, View, backend > >, backend > + get_view( StructuredMatrix< T, Structure, density, View, backend > &source ) { static_assert( structures::is_in< Structure, typename TargetStructure::inferred_structures >::value, "Can only create a view when the target structure is compatible with the source." ); - using source_strmat_t = StructuredMatrix< T, Structure, StorageSchemeType, View, backend >; - using target_strmat_t = StructuredMatrix< T, TargetStructure, StorageSchemeType, view::Original< source_strmat_t >, backend >; + using source_strmat_t = StructuredMatrix< T, Structure, density, View, backend >; + using target_strmat_t = StructuredMatrix< T, TargetStructure, density, view::Original< source_strmat_t >, backend >; target_strmat_t target( source ); @@ -1060,9 +1063,9 @@ namespace grb { template< typename TargetStructure, - typename T, typename Structure, typename StorageSchemeType, typename View, enum Backend backend > - StructuredMatrix< T, TargetStructure, StorageSchemeType, view::Original< StructuredMatrix< T, Structure, StorageSchemeType, View, backend > >, backend > - get_view( StructuredMatrix< T, Structure, StorageSchemeType, View, backend > &source, + typename T, typename Structure, enum Density density, typename View, enum Backend backend > + StructuredMatrix< T, TargetStructure, density, view::Original< StructuredMatrix< T, Structure, density, View, backend > >, backend > + get_view( StructuredMatrix< T, Structure, density, View, backend > &source, std::shared_ptr< imf::IMF > imf_r, std::shared_ptr< imf::IMF > imf_c ) { if( std::dynamic_pointer_cast< imf::Select >( imf_r ) || std::dynamic_pointer_cast< imf::Select >( imf_c ) ) { @@ -1073,8 +1076,8 @@ namespace grb { throw std::runtime_error("Cannot gather into specified TargetStructure from provided SourceStructure and Index Mapping Functions."); } - using source_strmat_t = StructuredMatrix< T, Structure, StorageSchemeType, View, backend >; - using target_strmat_t = StructuredMatrix< T, TargetStructure, StorageSchemeType, view::Original< source_strmat_t >, backend >; + using source_strmat_t = StructuredMatrix< T, Structure, density, View, backend >; + using target_strmat_t = StructuredMatrix< T, TargetStructure, density, view::Original< source_strmat_t >, backend >; target_strmat_t target( source, imf_r, imf_c ); @@ -1091,17 +1094,17 @@ namespace grb { * A structural check of this kind as well as non-overlapping checks with existing views of \a source * are guaranteed only when each one of them incurs constant time work. * - * @tparam TargetStructure The target structure of the new view. It should verify - * grb::is_in . - * @tparam T The matrix' elements type - * @tparam Structure The structure of the source and target matrix view - * @tparam StorageSchemeType The type (i.e., \a grb::storage:Dense or \a grb::storage:Sparse) of storage scheme - * @tparam View The source's View type - * @tparam backend The target backend + * @tparam TargetStructure The target structure of the new view. It should verify + * grb::is_in . + * @tparam T The matrix' elements type + * @tparam Structure The structure of the source and target matrix view + * @tparam density The type (i.e., sparse or dense) of storage scheme + * @tparam View The source's View type + * @tparam backend The target backend * - * @param source The source structured matrix - * @param rng_r A valid range of rows - * @param rng_c A valid range of columns + * @param source The source structured matrix + * @param rng_r A valid range of rows + * @param rng_c A valid range of columns * * @return A new original view over the source structured matrix. * @@ -1118,15 +1121,15 @@ namespace grb { */ template< typename TargetStructure, - typename T, typename Structure, typename StorageSchemeType, typename View, enum Backend backend > - StructuredMatrix< T, TargetStructure, StorageSchemeType, view::Original< StructuredMatrix< T, Structure, StorageSchemeType, View, backend > >, backend > - get_view( StructuredMatrix< T, Structure, StorageSchemeType, View, backend > &source, + typename T, typename Structure, enum Density density, typename View, enum Backend backend > + StructuredMatrix< T, TargetStructure, density, view::Original< StructuredMatrix< T, Structure, density, View, backend > >, backend > + get_view( StructuredMatrix< T, Structure, density, View, backend > &source, const utils::range& rng_r, const utils::range& rng_c ) { auto imf_r = std::make_shared< imf::Strided >( rng_r.count(), nrows(source), rng_r.start, rng_r.stride ); auto imf_c = std::make_shared< imf::Strided >( rng_c.count(), ncols(source), rng_c.start, rng_c.stride ); - return internal::get_view( source, imf_r, imf_c ); + return internal::get_view( source, imf_r, imf_c ); } /** @@ -1137,15 +1140,15 @@ namespace grb { * A structure preserving check as well as non-overlapping checks with existing views of \a source * are guaranteed only when each one of them incurs constant time work. * - * @tparam T The matrix' elements type - * @tparam Structure The structure of the source and target matrix view - * @tparam StorageSchemeType The type (i.e., \a grb::storage:Dense or \a grb::storage:Sparse) of storage scheme - * @tparam View The source's View type - * @tparam backend The target backend + * @tparam T The matrix' elements type + * @tparam Structure The structure of the source and target matrix view + * @tparam density The type (i.e., sparse or dense) of storage scheme + * @tparam View The source's View type + * @tparam backend The target backend * - * @param source The source matrix - * @param rng_r A valid range of rows - * @param rng_c A valid range of columns + * @param source The source matrix + * @param rng_r A valid range of rows + * @param rng_c A valid range of columns * * @return A new original view over the source structured matrix. * @@ -1162,15 +1165,15 @@ namespace grb { */ template< - typename T, typename Structure, typename StorageSchemeType, typename View, enum Backend backend > - StructuredMatrix< T, Structure, StorageSchemeType, view::Original< StructuredMatrix< T, Structure, StorageSchemeType, View, backend > >, backend > - get_view( StructuredMatrix< T, Structure, StorageSchemeType, View, backend > &source, + typename T, typename Structure, enum Density density, typename View, enum Backend backend > + StructuredMatrix< T, Structure, density, view::Original< StructuredMatrix< T, Structure, density, View, backend > >, backend > + get_view( StructuredMatrix< T, Structure, density, View, backend > &source, const utils::range& rng_r, const utils::range& rng_c ) { auto imf_r = std::make_shared< imf::Strided >( rng_r.count(), nrows(source), rng_r.start, rng_r.stride ); auto imf_c = std::make_shared< imf::Strided >( rng_c.count(), ncols(source), rng_c.start, rng_c.stride ); - return internal::get_view( source, imf_r, imf_c ); + return internal::get_view( source, imf_r, imf_c ); } namespace internal { @@ -1183,49 +1186,49 @@ namespace grb { * \warning WIP interface. Checking the structural correctness is a costly runtime operation for a * general vector selection. * - * @tparam TargetStructure The target structure of the new view. It should verify - * grb::is_in . - * @tparam T The matrix' elements type - * @tparam Structure The structure of the source and target matrix view - * @tparam StorageSchemeType The type (i.e., sparse or dense) of storage scheme - * @tparam View The source's View type - * @tparam backend The target backend + * @tparam TargetStructure The target structure of the new view. It should verify + * grb::is_in . + * @tparam T The matrix' elements type + * @tparam Structure The structure of the source and target matrix view + * @tparam density The type (i.e., sparse or dense) of storage scheme + * @tparam View The source's View type + * @tparam backend The target backend * - * @param source The source structured matrix - * @param sel_r A valid vector of row indeces (possibly in any permuted order and with repetition) - * @param sel_c A valid vector of column indeces (possibly in any permuted order and with repetition) + * @param source The source structured matrix + * @param sel_r A valid vector of row indeces (possibly in any permuted order and with repetition) + * @param sel_c A valid vector of column indeces (possibly in any permuted order and with repetition) * * @return A new original view over the source structured matrix. * */ template< typename TargetStructure, - typename T, typename Structure, typename StorageSchemeType, typename View, enum Backend backend > - StructuredMatrix< T, TargetStructure, StorageSchemeType, view::Original< StructuredMatrix< T, Structure, StorageSchemeType, View, backend > >, backend > - get_view( StructuredMatrix< T, Structure, StorageSchemeType, View, backend > &source, + typename T, typename Structure, enum Density density, typename View, enum Backend backend > + StructuredMatrix< T, TargetStructure, density, view::Original< StructuredMatrix< T, Structure, density, View, backend > >, backend > + get_view( StructuredMatrix< T, Structure, density, View, backend > &source, const std::vector< size_t >& sel_r, const std::vector< size_t >& sel_c ) { auto imf_r = std::make_shared< imf::Select >( nrows(source), sel_r ); auto imf_c = std::make_shared< imf::Select >( ncols(source), sel_c ); - return internal::get_view( source, imf_r, imf_c ); + return internal::get_view( source, imf_r, imf_c ); } } //namespace internal /** Returns a constant reference to an Identity matrix of the provided size */ template< typename T > - const StructuredMatrix< T, structures::Identity, storage::Dense, view::Original< void >, reference_dense > & + const StructuredMatrix< T, structures::Identity, Density::Dense, view::Original< void >, reference_dense > & I( const size_t n ) { - using return_type = StructuredMatrix< T, structures::Identity, storage::Dense, view::Original< void >, reference_dense >; + using return_type = StructuredMatrix< T, structures::Identity, Density::Dense, view::Original< void >, reference_dense >; return_type * ret = new return_type( n ); return * ret; } /** Returns a constant reference to a Zero matrix of the provided size */ template< typename T > - const StructuredMatrix< T, structures::Zero, storage::Dense, view::Original< void >, reference_dense > & + const StructuredMatrix< T, structures::Zero, Density::Dense, view::Original< void >, reference_dense > & Zero( const size_t rows, const size_t cols ) { - using return_type = StructuredMatrix< T, structures::Zero, storage::Dense, view::Original< void >, reference_dense >; + using return_type = StructuredMatrix< T, structures::Zero, Density::Dense, view::Original< void >, reference_dense >; return_type * ret = new return_type( rows, cols ); return * ret; } @@ -1235,9 +1238,9 @@ namespace grb { * s = sin( theta ) and c = cos( theta ) */ template< typename T > - const StructuredMatrix< T, structures::Square, storage::Dense, view::Original< void >, reference_dense > & + const StructuredMatrix< T, structures::Square, Density::Dense, view::Original< void >, reference_dense > & Givens( const size_t n, const size_t i, const size_t j, const T s, const T c ) { - using return_type = const StructuredMatrix< T, structures::Square, storage::Dense, view::Original< void >, reference_dense >; + using return_type = const StructuredMatrix< T, structures::Square, Density::Dense, view::Original< void >, reference_dense >; return_type * ret = new return_type( n ); // TODO: initialize matrix values according to the provided parameters return * ret; diff --git a/include/graphblas/denseref/scalar.hpp b/include/graphblas/denseref/scalar.hpp index 0570b49a1..b073f89bc 100644 --- a/include/graphblas/denseref/scalar.hpp +++ b/include/graphblas/denseref/scalar.hpp @@ -27,7 +27,7 @@ #include #include -#include +#include #include #include @@ -162,7 +162,7 @@ namespace grb { Scalar( const Scalar &other ) { // const RC rc = set( *this, other ); // note: initialized will be set as part of this call // if( rc != SUCCESS ) { - // throw std::runtime_error( "grb::Scalar< T, Structure, storage::Dense, View::Original< void >, reference_dense > (copy constructor): error during call to grb::set (" + toString( rc ) + ")" ); + // throw std::runtime_error( "grb::Scalar< T, Structure, Density::Dense, View::Original< void >, reference_dense > (copy constructor): error during call to grb::set (" + toString( rc ) + ")" ); // } } diff --git a/include/graphblas/denseref/vector.hpp b/include/graphblas/denseref/vector.hpp index 7cd7b7400..18469fdff 100644 --- a/include/graphblas/denseref/vector.hpp +++ b/include/graphblas/denseref/vector.hpp @@ -39,7 +39,7 @@ #include #include -#include +#include #include #include @@ -314,18 +314,18 @@ namespace grb { */ template< typename T, typename Structure, typename View > - size_t getLength( const VectorView< T, Structure, storage::Dense, View, reference_dense > &v ) noexcept { + size_t getLength( const VectorView< T, Structure, Density::Dense, View, reference_dense > &v ) noexcept { return v._length(); } namespace internal { template< typename T, typename Structure, typename View > - bool getInitialized( VectorView< T, Structure, storage::Dense, View, reference_dense > & v ) noexcept { + bool getInitialized( VectorView< T, Structure, Density::Dense, View, reference_dense > & v ) noexcept { return getInitialized( v ); } template< typename T, typename Structure, typename View > - void setInitialized( VectorView< T, Structure, storage::Dense, View, reference_dense > & v, bool initialized ) noexcept { + void setInitialized( VectorView< T, Structure, Density::Dense, View, reference_dense > & v, bool initialized ) noexcept { setInitialized( v, initialized ); } } // end namespace ``grb::internal'' @@ -344,41 +344,38 @@ namespace grb { * Views can be used to create logical \em perspectives on top of a container. * For example, one may decide to refer to the part of the vector or * to reference a diagonal of a matrix as a vector. - * See specialization \a VectorView< T, Structure, storage::Dense, view::Diagonal< StructuredMatrixT >, reference_dense > + * See specialization \a VectorView< T, Structure, Density::Dense, view::Diagonal< StructuredMatrixT >, reference_dense > * as an example of such usage. * * Vector View defined as views on other vectors do not instantiate a * new container but refer to the one used by their targets. * - * @tparam T The type of the vector elements. \a T shall not be a GraphBLAS - * type. - * @tparam Structure Structure introduced to match the template - * parameter list of \a StructuredMatrix - * @tparam View One of the vector views. - * All static views except for \a view::Original (via - * \a view::Original cannot instantiate a new container - * and only allow to refer to a previously defined - * \a VectorView. - * The \a View parameter should not be used directly - * by the user but can be set using specific member types - * appropriately defined by each VectorView and - * accessible via functions. - * @tparam StorageSchemeType Either \em enum \a storage::Dense or \em enum - * \a storage::Sparse. + * @tparam T type. + * @tparam Structure Structure introduced to match the template + * parameter list of \a StructuredMatrix + * @tparam View One of the vector views. + * All static views except for \a view::Original (via + * \a view::Original cannot instantiate a new container + * and only allow to refer to a previously defined + * \a VectorView. + * The \a View parameter should not be used directly + * by the user but can be set using specific member types + * appropriately defined by each VectorView and + * accessible via functions. * */ template< typename T, typename Structure, typename View > - class VectorView< T, Structure, storage::Dense, View, reference_dense > { }; + class VectorView< T, Structure, Density::Dense, View, reference_dense > { }; /** * Original View over a vector container. */ template< typename T, typename Structure > - class VectorView< T, Structure, storage::Dense, view::Original< void >, reference_dense > { + class VectorView< T, Structure, Density::Dense, view::Original< void >, reference_dense > { private: - using self_type = VectorView< T, Structure, storage::Dense, view::Original< void >, reference_dense >; + using self_type = VectorView< T, Structure, Density::Dense, view::Original< void >, reference_dense >; /********************* Storage info friends @@ -410,7 +407,7 @@ namespace grb { template < bool d > struct view_type< view::original, d > { - using type = VectorView< T, Structure, storage::Dense, view::Original< self_type >, reference_dense >; + using type = VectorView< T, Structure, Density::Dense, view::Original< self_type >, reference_dense >; }; VectorView( const size_t length, const size_t cap = 0 ) : @@ -434,8 +431,8 @@ namespace grb { }; // class VectorView with physical container /** Identifies any reference_dense vector as an ALP vector. */ - template< typename T, typename Structure, typename Storage, typename View > - struct is_container< VectorView< T, Structure, Storage, View, reference_dense > > { + template< typename T, typename Structure, typename View > + struct is_container< VectorView< T, Structure, Density::Dense, View, reference_dense > > { /** A reference_vector is an ALP object. */ static const constexpr bool value = true; }; @@ -444,11 +441,11 @@ namespace grb { * Vector view of a vector only via \a view::Original of another VectorView. */ template< typename T, typename Structure, typename VectorViewT > - class VectorView< T, Structure, storage::Dense, view::Original< VectorViewT >, reference_dense > { + class VectorView< T, Structure, Density::Dense, view::Original< VectorViewT >, reference_dense > { private: - using self_type = VectorView< T, Structure, storage::Dense, view::Original< VectorViewT >, reference_dense >; + using self_type = VectorView< T, Structure, Density::Dense, view::Original< VectorViewT >, reference_dense >; using target_type = VectorViewT; /********************* @@ -480,7 +477,7 @@ namespace grb { template < bool d > struct view_type< view::original, d > { - using type = VectorView< T, Structure, storage::Dense, view::Original< self_type >, reference_dense >; + using type = VectorView< T, Structure, Density::Dense, view::Original< self_type >, reference_dense >; }; /** Constructor for creating a view over a given target vector */ @@ -519,13 +516,13 @@ namespace grb { * Diagonal Vector View of a structured matrix. */ template< typename T, typename Structure, typename StructuredMatrixT > - class VectorView< T, Structure, storage::Dense, view::Diagonal< StructuredMatrixT >, reference_dense > { + class VectorView< T, Structure, Density::Dense, view::Diagonal< StructuredMatrixT >, reference_dense > { private: /** Exposes the own type and the type of the VectorView object over * which this view is created. */ - using self_type = VectorView< T, Structure, storage::Dense, view::Diagonal< StructuredMatrixT >, reference_dense >; + using self_type = VectorView< T, Structure, Density::Dense, view::Diagonal< StructuredMatrixT >, reference_dense >; using target_type = StructuredMatrixT; /********************* @@ -557,7 +554,7 @@ namespace grb { template < bool d > struct view_type< view::original, d > { - using type = VectorView< T, Structure, storage::Dense, view::Original< self_type >, reference_dense >; + using type = VectorView< T, Structure, Density::Dense, view::Original< self_type >, reference_dense >; }; VectorView( target_type & struct_mat ) : ref( struct_mat ), imf( nullptr ) { @@ -588,11 +585,10 @@ namespace grb { * the created view is non-overlapping with other existing views only when the * check can be performed in constant time. * - * @tparam T The vector's elements type - * @tparam Structure The structure of the source and target vector view - * @tparam StorageSchemeType The type (i.e., \a grb::storage:Dense or \a grb::storage:Sparse) of storage scheme - * @tparam View The source's View type - * @tparam backend The target backend + * @tparam T The vector's elements type + * @tparam Structure The structure of the source and target vector view + * @tparam View The source's View type + * @tparam backend The target backend * * @param[in] source The VectorView object over which the view is created. * @@ -610,12 +606,12 @@ namespace grb { * */ template< - typename T, typename Structure, typename StorageSchemeType, typename View, enum Backend backend + typename T, typename Structure, enum Density density, typename View, enum Backend backend > - typename VectorView< T, Structure, StorageSchemeType, View, backend >::template view_type< view::original >::type - get_view( VectorView< T, Structure, StorageSchemeType, View, backend > & source ) { + typename VectorView< T, Structure, density, View, backend >::template view_type< view::original >::type + get_view( VectorView< T, Structure, density, View, backend > & source ) { - using source_vec_t = VectorView< T, Structure, StorageSchemeType, View, backend >; + using source_vec_t = VectorView< T, Structure, density, View, backend >; using target_vec_t = typename source_vec_t::template view_type< view::original >::type; target_vec_t vec_view( source ); @@ -644,12 +640,12 @@ namespace grb { * \endparblock * */ - template< typename T, typename Structure, typename View, typename StorageSchemeType, enum Backend backend > - typename VectorView< T, Structure, StorageSchemeType, View, backend >::template view_type< view::original >::type - get_view( VectorView< T, Structure, StorageSchemeType, View, backend > &source, const utils::range& rng ) { + template< typename T, typename Structure, enum Density density, typename View, enum Backend backend > + typename VectorView< T, Structure, density, View, backend >::template view_type< view::original >::type + get_view( VectorView< T, Structure, density, View, backend > &source, const utils::range& rng ) { auto imf_v = std::make_shared< imf::Strided >( rng.count(), getLength( source ), rng.start, rng.stride ); - typename VectorView< T, Structure, StorageSchemeType, View, backend >::template view_type< view::original >::type vec_view( source, imf_v ); + typename VectorView< T, Structure, density, View, backend >::template view_type< view::original >::type vec_view( source, imf_v ); return vec_view; } diff --git a/include/graphblas/density.hpp b/include/graphblas/density.hpp new file mode 100644 index 000000000..bce57ad68 --- /dev/null +++ b/include/graphblas/density.hpp @@ -0,0 +1,64 @@ +/* + * Copyright 2021 Huawei Technologies Co., Ltd. + * + * 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. + */ + +/** + * + * @file + * + * This file registers the enum that allows a user to specify the density of a + * given ALP container. + * + */ + +#ifndef _H_GRB_DENSITY +#define _H_GRB_DENSITY + +#include +#include + +namespace grb { + + /** + * Specifies whether an ALP container is dense or sparse. + * + * This is specified by the user and may be used by a backend to drive + * a choice of a storage scheme. + * + */ + enum Density { + /** + * Dense containers do not allow nonzero elements. + * + * Depending on the container's \a Structure, the backend may decide to + * not store all the elements. For example, an upper triangular matrix + * can be stored without the all-zero part below the diagonal. + * + * @see Structure + * + */ + Dense, + /** + * Sparse containers mostly having nonzero elements. + * + * The backend can decide which specific format to use. + * + */ + Sparse + }; // enum Density + +} // namespace grb + +#endif // _H_GRB_DENSITY diff --git a/include/graphblas/matrix.hpp b/include/graphblas/matrix.hpp index 6923162af..907cb1e4e 100644 --- a/include/graphblas/matrix.hpp +++ b/include/graphblas/matrix.hpp @@ -52,9 +52,9 @@ namespace grb { class Matrix; /* - * The default value of \a StorageSchemeType could also be made conditional (Dense or Sparse) depending on \a config::default_backend + * The default value of \a density could also be made conditional (Dense or Sparse) depending on \a config::default_backend */ - template< typename T, typename Structure, typename StorageSchemeType = storage::Dense, typename View = view::Original< void >, enum Backend backend = config::default_backend > + template< typename T, typename Structure, enum Density density = Density::Dense, typename View = view::Original< void >, enum Backend backend = config::default_backend > class StructuredMatrix; } // namespace grb diff --git a/include/graphblas/storage.hpp b/include/graphblas/storage.hpp deleted file mode 100644 index 85edb7483..000000000 --- a/include/graphblas/storage.hpp +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright 2021 Huawei Technologies Co., Ltd. - * - * 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. - */ - -/** - * - * @file - * - * This file registers matrix storage schemes that are either - * implemented, under implementation, or were at any point in time - * conceived and noteworthy enough to be recorded for future consideration. - * - */ - -#ifndef _H_GRB_STORAGE -#define _H_GRB_STORAGE - -#include -#include - -namespace grb { - - namespace storage { - - /** - * WIP. - * Collection of possible storage scheme options for dense matrices. - * - * \note Although the list for now includes classic BLAS/LAPACK storage schemes we may decide to extend or replace - * this list with different schemes. A user should not make any assumptions on which specific scheme is - * selected internally by a backend to to store a given structure. - * - * \note This labelled formulation will be replaced by a more flexible description of the underlying mappings - * associated to each scheme in the spirit of the index mapping functions formualation. - * - * @see \a imf.hpp - */ - enum Dense { - - /** - * Conventional storage in a 2D array. The matrix element \f$A(i,j)\f$ is stored in array element \f$a(i,j)\f$. - * Although some non-general structured matrices may forbid access to part of the array, - * with this storage option a full rectangular array must be allocated. - * This option could also be used as default/initial choice when a storage scheme decision has not yet been made. - */ - full, - - /** - * Compact 2D storage for Band matrices. An \f$m-\times-n\f$ band matrix with \f$kl\f$ subdiagonals - * and \f$ku\f$ superdiagonals may be stored compactly in a 2D array with \f$m\f$ rows and \f$kl+ku+1\f$ columns. - * Rows of the matrix are stored in corresponding rows of the array, and diagonals of the matrix are stored - * in columns of the array. - * This storage scheme should be used in practice only if \f$kl, ku \ll \min(m,n)\f$, although it should work correctly - * for all values of \f$kl\f$ and \f$ku\f$. - */ - band, - - /** - * A tridiagonal matrix of order \f$n\f$ is stored in three 1D arrays, one of length \f$n\f$ - * containing the diagonal elements, and two of length \f$n-1\f$ containing the subdiagonal - * and superdiagonal elements. - * Symmetric tridiagonal and bidiagonal matrices are stored in two 1D arrays, one of length \f$n\f$ - * containing the diagonal elements, and one of length \f$n-1\f$ containing the off-diagonal elements. - * A diagonal matrix is stored as a 1D array of length \f$n\f$. - * Symmetric, Hermitian or triangular matrices store the relevant triangle packed by rows in a 1D array: - * \li \c AlignLeft \f$A(i,j)\f$ is stored in \f$a( j + i*(i + 1)/2 )\f$ for \f$i \leq j\f$ - * \li \c AlignLeft \f$A(i,j)\f$ is stored in \f$a( j + i*(2*n - i - 1)/2 )\f$ for \f$j \leq i\f$ - */ - array1d - }; // Dense - - // enum Sparse { - // ... - // }; - - } // namespace storage - -} // namespace grb - -#endif // _H_GRB_STORAGE diff --git a/include/graphblas/vector.hpp b/include/graphblas/vector.hpp index b7962b9c7..fb5fff59b 100644 --- a/include/graphblas/vector.hpp +++ b/include/graphblas/vector.hpp @@ -55,9 +55,9 @@ namespace grb { class Vector; /* - * The default value of \a StorageSchemeType could also be made conditional (Dense or Sparse) depending on \a config::default_backend + * The default value of \a density could also be made conditional (Dense or Sparse) depending on \a config::default_backend */ - template< typename T, typename Structure = structures::General, typename StorageSchemeType = storage::Dense, typename View = view::Original< void >, enum Backend backend = config::default_backend > + template< typename T, typename Structure = structures::General, enum Density density = Density::Dense, typename View = view::Original< void >, enum Backend backend = config::default_backend > class VectorView; } From f2060782e1ec1d465662c5962fb7d82b6b0fcee6 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Fri, 25 Mar 2022 13:40:48 +0100 Subject: [PATCH 120/282] !35 Resolve internal issue #367: Separate alp and grb This commit is part of two-commit sequence that resolves internal issue #367. The commits are separated to allow for easier tracking of the moved files' history. This includes: - Add alp cmake infrastructure - Add include/alp.hpp - Add necessary cpp files - Introduce include/alp and src/alp subfolders - Move include/graphblas/denseref to include/alp/reference - Move ALP-related root hpp files from include/graphblas to include/alp - Copy needed graphblas files to alp subfolders - some include root files - some include/base files - some include/utils files - Remove reference_dense backend implementation from graphblas as it is now part of ALP --- bootstrap.sh | 14 +- cmake/AddGRBInstall.cmake | 10 +- cmake/AddGRBVars.cmake | 12 +- include/CMakeLists.txt | 86 +- include/alp.hpp | 91 + include/alp/CMakeLists.txt | 96 + include/alp/backends.hpp | 167 + include/alp/base/blas2.hpp | 658 ++++ include/alp/base/blas3.hpp | 167 + include/alp/base/collectives.hpp | 258 ++ include/alp/base/config.hpp | 300 ++ include/alp/base/exec.hpp | 231 ++ include/alp/base/init.hpp | 183 + include/alp/base/internalops.hpp | 3180 +++++++++++++++++ include/alp/base/io.hpp | 373 ++ include/alp/base/matrix.hpp | 512 +++ include/alp/base/scalar.hpp | 228 ++ include/alp/base/vector.hpp | 883 +++++ include/alp/blas0.hpp | 503 +++ include/alp/blas1.hpp | 412 +++ include/alp/blas2.hpp | 47 + include/alp/blas3.hpp | 41 + include/alp/config.hpp | 43 + include/{graphblas => alp}/density.hpp | 0 include/alp/descriptors.hpp | 208 ++ include/alp/exec.hpp | 51 + include/alp/identities.hpp | 197 + include/{graphblas => alp}/imf.hpp | 0 include/alp/init.hpp | 44 + include/alp/internalops.hpp | 36 + include/alp/iomode.hpp | 93 + include/alp/matrix.hpp | 58 + include/alp/monoid.hpp | 138 + include/alp/ops.hpp | 566 +++ include/alp/phase.hpp | 70 + include/alp/rc.hpp | 150 + .../denseref => alp/reference}/alloc.hpp | 0 .../denseref => alp/reference}/benchmark.hpp | 0 .../denseref => alp/reference}/blas0.hpp | 0 .../denseref => alp/reference}/blas1.hpp | 0 .../denseref => alp/reference}/blas2.hpp | 0 .../denseref => alp/reference}/blas3.hpp | 0 .../reference}/collectives.hpp | 0 .../denseref => alp/reference}/config.hpp | 0 .../denseref => alp/reference}/exec.hpp | 0 .../denseref => alp/reference}/init.hpp | 0 .../denseref => alp/reference}/io.hpp | 0 .../denseref => alp/reference}/matrix.hpp | 0 .../reference}/pinnedvector.hpp | 0 .../denseref => alp/reference}/properties.hpp | 0 .../denseref => alp/reference}/scalar.hpp | 0 .../denseref => alp/reference}/spmd.hpp | 0 .../denseref => alp/reference}/vector.hpp | 0 .../reference}/vectoriterator.hpp | 0 include/{graphblas => alp}/scalar.hpp | 0 include/alp/semiring.hpp | 353 ++ include/{graphblas => alp}/smf.hpp | 0 include/{graphblas => alp}/structures.hpp | 0 include/alp/type_traits.hpp | 153 + include/alp/utils.hpp | 303 ++ .../alp/utils/SynchronizedNonzeroIterator.hpp | 356 ++ include/alp/utils/autodeleter.hpp | 192 + include/alp/utils/suppressions.h | 50 + include/alp/vector.hpp | 60 + include/{graphblas => alp}/views.hpp | 0 include/graphblas/CMakeLists.txt | 155 + include/graphblas/backends.hpp | 8 +- include/graphblas/base/matrix.hpp | 70 - include/graphblas/base/vector.hpp | 4 - include/graphblas/benchmark.hpp | 3 - include/graphblas/blas1.hpp | 3 - include/graphblas/blas2.hpp | 3 - include/graphblas/blas3.hpp | 3 - include/graphblas/collectives.hpp | 3 - include/graphblas/exec.hpp | 3 - include/graphblas/init.hpp | 3 - include/graphblas/io.hpp | 3 - include/graphblas/matrix.hpp | 9 - include/graphblas/pinnedvector.hpp | 3 - include/graphblas/properties.hpp | 3 - include/graphblas/spmd.hpp | 3 - include/graphblas/utils/alloc.hpp | 3 - include/graphblas/vector.hpp | 9 - src/CMakeLists.txt | 1 + src/alp/CMakeLists.txt | 38 + src/alp/descriptors.cpp | 58 + src/alp/rc.cpp | 58 + .../denseref => alp/reference}/CMakeLists.txt | 32 +- .../denseref => alp/reference}/init.cpp | 21 +- src/graphblas/CMakeLists.txt | 4 - 90 files changed, 11808 insertions(+), 268 deletions(-) create mode 100644 include/alp.hpp create mode 100644 include/alp/CMakeLists.txt create mode 100644 include/alp/backends.hpp create mode 100644 include/alp/base/blas2.hpp create mode 100644 include/alp/base/blas3.hpp create mode 100644 include/alp/base/collectives.hpp create mode 100644 include/alp/base/config.hpp create mode 100644 include/alp/base/exec.hpp create mode 100644 include/alp/base/init.hpp create mode 100644 include/alp/base/internalops.hpp create mode 100644 include/alp/base/io.hpp create mode 100644 include/alp/base/matrix.hpp create mode 100644 include/alp/base/scalar.hpp create mode 100644 include/alp/base/vector.hpp create mode 100644 include/alp/blas0.hpp create mode 100644 include/alp/blas1.hpp create mode 100644 include/alp/blas2.hpp create mode 100644 include/alp/blas3.hpp create mode 100644 include/alp/config.hpp rename include/{graphblas => alp}/density.hpp (100%) create mode 100644 include/alp/descriptors.hpp create mode 100644 include/alp/exec.hpp create mode 100644 include/alp/identities.hpp rename include/{graphblas => alp}/imf.hpp (100%) create mode 100644 include/alp/init.hpp create mode 100644 include/alp/internalops.hpp create mode 100644 include/alp/iomode.hpp create mode 100644 include/alp/matrix.hpp create mode 100644 include/alp/monoid.hpp create mode 100644 include/alp/ops.hpp create mode 100644 include/alp/phase.hpp create mode 100644 include/alp/rc.hpp rename include/{graphblas/denseref => alp/reference}/alloc.hpp (100%) rename include/{graphblas/denseref => alp/reference}/benchmark.hpp (100%) rename include/{graphblas/denseref => alp/reference}/blas0.hpp (100%) rename include/{graphblas/denseref => alp/reference}/blas1.hpp (100%) rename include/{graphblas/denseref => alp/reference}/blas2.hpp (100%) rename include/{graphblas/denseref => alp/reference}/blas3.hpp (100%) rename include/{graphblas/denseref => alp/reference}/collectives.hpp (100%) rename include/{graphblas/denseref => alp/reference}/config.hpp (100%) rename include/{graphblas/denseref => alp/reference}/exec.hpp (100%) rename include/{graphblas/denseref => alp/reference}/init.hpp (100%) rename include/{graphblas/denseref => alp/reference}/io.hpp (100%) rename include/{graphblas/denseref => alp/reference}/matrix.hpp (100%) rename include/{graphblas/denseref => alp/reference}/pinnedvector.hpp (100%) rename include/{graphblas/denseref => alp/reference}/properties.hpp (100%) rename include/{graphblas/denseref => alp/reference}/scalar.hpp (100%) rename include/{graphblas/denseref => alp/reference}/spmd.hpp (100%) rename include/{graphblas/denseref => alp/reference}/vector.hpp (100%) rename include/{graphblas/denseref => alp/reference}/vectoriterator.hpp (100%) rename include/{graphblas => alp}/scalar.hpp (100%) create mode 100644 include/alp/semiring.hpp rename include/{graphblas => alp}/smf.hpp (100%) rename include/{graphblas => alp}/structures.hpp (100%) create mode 100644 include/alp/type_traits.hpp create mode 100644 include/alp/utils.hpp create mode 100644 include/alp/utils/SynchronizedNonzeroIterator.hpp create mode 100644 include/alp/utils/autodeleter.hpp create mode 100644 include/alp/utils/suppressions.h create mode 100644 include/alp/vector.hpp rename include/{graphblas => alp}/views.hpp (100%) create mode 100644 include/graphblas/CMakeLists.txt create mode 100644 src/alp/CMakeLists.txt create mode 100644 src/alp/descriptors.cpp create mode 100644 src/alp/rc.cpp rename src/{graphblas/denseref => alp/reference}/CMakeLists.txt (53%) rename src/{graphblas/denseref => alp/reference}/init.cpp (66%) diff --git a/bootstrap.sh b/bootstrap.sh index 8a2e7e032..030279452 100755 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -73,7 +73,7 @@ print_help() { the location where LPF is installed" echo " --with-banshee= - path to the the tools to compile the banshee backend" echo " --with-snitch= - path to the tools for Snitch support within the banshee backend" - echo " --no-dense - to compile without support for dense algebraic programming" + echo " --no-alp-reference - to compile without support for dense algebraic programming" echo " --no-reference - disables the reference and reference_omp backends" echo " --debug-build - build the project with debug options (tests will run much slower!)" echo " --generator= - set the generator for CMake (otherwise use CMake's default)" @@ -93,7 +93,7 @@ the location where LPF is installed" reference=yes banshee=no lpf=no -dense=yes +alp_reference=yes show=no FLAGS=$'' LPF_INSTALL_PATH= @@ -145,8 +145,8 @@ or assume default paths (--with-lpf)" SNITCH_PATH="${arg#--with-snitch=}" banshee=yes ;; - --no-dense) - dense=no + --no-alp-reference) + alp_reference=no ;; --no-reference) reference=no @@ -292,10 +292,10 @@ the current directory before invocation or confirm the deletion of its content w if [[ "${reference}" == "no" ]]; then CMAKE_OPTS+=" -DWITH_REFERENCE_BACKEND=OFF -DWITH_OMP_BACKEND=OFF" fi - if [[ "${dense}" == "no" ]]; then - CMAKE_OPTS+=" -DWITH_DENSEREF_BACKEND=OFF" + if [[ "${alp_reference}" == "no" ]]; then + CMAKE_OPTS+=" -DWITH_ALP_REFERENCE_BACKEND=OFF" else - CMAKE_OPTS+=" -DWITH_DENSEREF_BACKEND=ON" + CMAKE_OPTS+=" -DWITH_ALP_REFERENCE_BACKEND=ON" fi if [[ "${lpf}" == "yes" ]]; then CMAKE_OPTS+=" -DLPF_INSTALL_PATH='${ABSOLUTE_LPF_INSTALL_PATH}'" diff --git a/cmake/AddGRBInstall.cmake b/cmake/AddGRBInstall.cmake index d6bfea317..3d50788a0 100644 --- a/cmake/AddGRBInstall.cmake +++ b/cmake/AddGRBInstall.cmake @@ -44,7 +44,7 @@ install( EXPORT GraphBLASTargets # paths where to install the binaries of the various backends set( ALP_UTILS_INSTALL_DIR "${BINARY_LIBRARIES_INSTALL_DIR}" ) set( SHMEM_BACKEND_INSTALL_DIR "${BINARY_LIBRARIES_INSTALL_DIR}/sequential" ) -set( DENSEREF_BACKEND_INSTALL_DIR "${BINARY_LIBRARIES_INSTALL_DIR}/denseref" ) +set( ALP_REFERENCE_BACKEND_INSTALL_DIR "${BINARY_LIBRARIES_INSTALL_DIR}/alp/reference" ) set( BSP1D_BACKEND_INSTALL_DIR "${BINARY_LIBRARIES_INSTALL_DIR}/spmd" ) set( HYBRID_BACKEND_INSTALL_DIR "${BINARY_LIBRARIES_INSTALL_DIR}/hybrid" ) @@ -121,10 +121,10 @@ if( WITH_REFERENCE_BACKEND ) ) endif() -if( WITH_DENSEREF_BACKEND ) - addBackendWrapperGenOptions( "reference_dense" - COMPILE_DEFINITIONS "DENSEREF_INCLUDE_DEFS" "${DENSEREF_SELECTION_DEFS}" - LINK_FLAGS "${DENSEREF_BACKEND_INSTALL_DIR}/lib${BACKEND_LIBRARY_OUTPUT_NAME}.a" +if( WITH_ALP_REFERENCE_BACKEND ) + addBackendWrapperGenOptions( "alp_reference" + COMPILE_DEFINITIONS "ALP_REFERENCE_INCLUDE_DEFS" "${ALP_REFERENCE_SELECTION_DEFS}" + LINK_FLAGS "${ALP_REFERENCE_BACKEND_INSTALL_DIR}/lib${BACKEND_LIBRARY_OUTPUT_NAME}.a" ) endif() diff --git a/cmake/AddGRBVars.cmake b/cmake/AddGRBVars.cmake index 27d089ab7..2d324b404 100644 --- a/cmake/AddGRBVars.cmake +++ b/cmake/AddGRBVars.cmake @@ -31,7 +31,7 @@ set( REFERENCE_BACKEND_DEFAULT_NAME "backend_reference" ) set( REFERENCE_OMP_BACKEND_DEFAULT_NAME "backend_reference_omp" ) set( BSP1D_BACKEND_DEFAULT_NAME "backend_bsp1d" ) set( HYBRID_BACKEND_DEFAULT_NAME "backend_hybrid" ) -set( DENSEREF_BACKEND_DEFAULT_NAME "backend_reference_dense" ) +set( ALP_REFERENCE_BACKEND_DEFAULT_NAME "backend_alp_reference" ) ### COMPILER DEFINITIONS FOR HEADERS INCLUSION AND FOR BACKEND SELECTION @@ -40,12 +40,12 @@ set( DENSEREF_BACKEND_DEFAULT_NAME "backend_reference_dense" ) set( REFERENCE_INCLUDE_DEFS "_GRB_WITH_REFERENCE" ) set( REFERENCE_OMP_INCLUDE_DEFS "_GRB_WITH_OMP" ) set( LPF_INCLUDE_DEFS "_GRB_WITH_LPF" ) -set( DENSEREF_INCLUDE_DEFS "_GRB_WITH_DENSEREF" ) +set( ALP_REFERENCE_INCLUDE_DEFS "_ALP_WITH_REFERENCE" ) # compiler definitions to select a backend set( REFERENCE_SELECTION_DEFS "_GRB_BACKEND=reference" ) set( REFERENCE_OMP_SELECTION_DEFS "_GRB_BACKEND=reference_omp" ) -set( DENSEREF_SELECTION_DEFS "_GRB_BACKEND=reference_dense" ) +set( ALP_REFERENCE_SELECTION_DEFS "_ALP_BACKEND=reference" ) set( BSP1D_SELECTION_DEFS "_GRB_BACKEND=BSP1D" "_GRB_BSP1D_BACKEND=reference" @@ -59,7 +59,7 @@ set( HYBRID_SELECTION_DEFS set( NO_NUMA_DEF "_GRB_NO_LIBNUMA" ) ### **ALL** BACKENDS, EVEN IF NOT ENABLED BY USER -set( ALL_BACKENDS "reference" "reference_omp" "bsp1d" "hybrid" "reference_dense" ) +set( ALL_BACKENDS "reference" "reference_omp" "bsp1d" "hybrid" "alp_reference" ) # list of user-enabled backends, for tests and wrapper scripts (do not change!) @@ -77,8 +77,8 @@ if( WITH_OMP_BACKEND ) list( APPEND AVAILABLE_BACKENDS "reference_omp" ) endif() -if( WITH_DENSEREF_BACKEND ) - list( APPEND AVAILABLE_BACKENDS "reference_dense" ) +if( WITH_ALP_REFERENCE_BACKEND ) + list( APPEND AVAILABLE_BACKENDS "alp_reference" ) endif() # distributed memory backends diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt index 847d8ca27..7d03b4c89 100644 --- a/include/CMakeLists.txt +++ b/include/CMakeLists.txt @@ -21,9 +21,6 @@ # and definitions to compile against each backend, but MUST explicitly # set a default backend (if they want to do so). # -assert_defined_variables( REFERENCE_INCLUDE_DEFS REFERENCE_OMP_INCLUDE_DEFS LPF_INCLUDE_DEFS - WITH_REFERENCE_BACKEND_HEADERS WITH_OMP_BACKEND_HEADERS WITH_BSP1D_BACKEND WITH_HYBRID_BACKEND -) assert_valid_variables( INCLUDE_INSTALL_DIR NO_NUMA_DEF ) # basic graphblas includes all backends depend on @@ -76,12 +73,6 @@ target_include_directories( alp_utils_headers INTERFACE $ ) -# copy utils headers -install( DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/graphblas/utils/" - DESTINATION "${GRB_INCLUDE_INSTALL_DIR}/utils" - FILES_MATCHING REGEX "${HEADERS_REGEX}" -) - # everybody needs the math library target_link_libraries( backend_headers_nodefs INTERFACE LibM::LibM ) @@ -104,81 +95,12 @@ install( TARGETS alp_utils_headers EXPORT GraphBLASTargets INCLUDES DESTINATION "${INCLUDE_INSTALL_DIR}" ) - -if( WITH_REFERENCE_BACKEND_HEADERS ) - add_library( backend_reference_headers INTERFACE ) - target_link_libraries( backend_reference_headers INTERFACE backend_headers_nodefs ) - target_compile_definitions( backend_reference_headers INTERFACE "${REFERENCE_INCLUDE_DEFS}" ) - # currently, the OMP header files and definitions are required also for the reference backend - # TODO: "dis-entangle" code from OMP backend dependence and remove this - target_compile_definitions( backend_reference_headers INTERFACE "${REFERENCE_OMP_INCLUDE_DEFS}" ) - target_link_libraries( backend_reference_headers INTERFACE OpenMP::OpenMP_CXX ) - - install( TARGETS backend_reference_headers EXPORT GraphBLASTargets ) -endif() - -if( WITH_DENSEREF_BACKEND ) - add_library( backend_reference_dense_headers INTERFACE ) - target_link_libraries( backend_reference_dense_headers INTERFACE backend_headers_nodefs ) - target_compile_definitions( backend_reference_dense_headers INTERFACE "${DENSEREF_INCLUDE_DEFS}" ) - install( TARGETS backend_reference_dense_headers EXPORT GraphBLASTargets ) - install( DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/graphblas/denseref" - DESTINATION "${GRB_INCLUDE_INSTALL_DIR}/denseref" - FILES_MATCHING REGEX "${HEADERS_REGEX}" - ) -endif() - -if( WITH_REFERENCE_BACKEND OR WITH_OMP_BACKEND ) - install( DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/graphblas/reference/" - DESTINATION "${GRB_INCLUDE_INSTALL_DIR}/reference" - FILES_MATCHING REGEX "${HEADERS_REGEX}" - ) -endif() - -if( WITH_OMP_BACKEND_HEADERS ) - add_library( backend_reference_omp_headers INTERFACE ) - target_link_libraries( backend_reference_omp_headers INTERFACE backend_headers_nodefs ) - target_link_libraries( backend_reference_omp_headers INTERFACE OpenMP::OpenMP_CXX ) - target_compile_definitions( backend_reference_omp_headers INTERFACE - "${REFERENCE_INCLUDE_DEFS}" "${REFERENCE_OMP_INCLUDE_DEFS}" - ) - - install( DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/graphblas/omp/" - DESTINATION "${GRB_INCLUDE_INSTALL_DIR}/omp" - FILES_MATCHING REGEX "${HEADERS_REGEX}" - ) - install( TARGETS backend_reference_omp_headers EXPORT GraphBLASTargets ) - -endif() - - -if( WITH_BSP1D_BACKEND OR WITH_HYBRID_BACKEND ) - # copy headers, which are common to both distributed backends - install( DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/graphblas/bsp/" - DESTINATION "${GRB_INCLUDE_INSTALL_DIR}/bsp" - FILES_MATCHING REGEX "${HEADERS_REGEX}" - ) - install( DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/graphblas/bsp1d/" - DESTINATION "${GRB_INCLUDE_INSTALL_DIR}/bsp1d" - FILES_MATCHING REGEX "${HEADERS_REGEX}" - ) +if( WITH_ALP_REFERENCE_BACKEND_HEADERS ) + add_subdirectory( alp ) endif() -if( WITH_BSP1D_BACKEND ) - add_library( backend_bsp1d_headers INTERFACE ) - target_link_libraries( backend_bsp1d_headers INTERFACE Numa::Numa backend_reference_headers ) - target_compile_definitions( backend_bsp1d_headers INTERFACE "${LPF_INCLUDE_DEFS}" ) - - install( TARGETS backend_bsp1d_headers EXPORT GraphBLASTargets ) -endif() - -if( WITH_HYBRID_BACKEND ) - add_library( backend_hybrid_headers INTERFACE ) - # the hybrid backend needs OMP by design - target_link_libraries( backend_hybrid_headers INTERFACE Numa::Numa backend_reference_omp_headers ) - target_compile_definitions( backend_hybrid_headers INTERFACE "${LPF_INCLUDE_DEFS}" ) - - install( TARGETS backend_hybrid_headers EXPORT GraphBLASTargets ) +if( WITH_REFERENCE_BACKEND_HEADERS ) + add_subdirectory( graphblas ) endif() # this target lists the algorithms implemented on top of the generic functionalities, diff --git a/include/alp.hpp b/include/alp.hpp new file mode 100644 index 000000000..7ba83b1e9 --- /dev/null +++ b/include/alp.hpp @@ -0,0 +1,91 @@ + +/* + * Copyright 2021 Huawei Technologies Co., Ltd. + * + * 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. + */ + +#ifdef __DOXYGEN__ +/** + * Define this macro to disable libnuma use. + */ +#define _ALP_NO_LIBNUMA + +/** + * Define this macro to disable thread pinning. + */ +#define _ALP_NO_PINNING + +/** + * Defie this macro to compile with PlatformBSP support. + */ +#define _ALP_WITH_LPF + +/** + * Which GraphBLAS backend should be default. + * + * Known single user-process options: + * -# reference + * -# reference_omp + * + * Known multiple user-process options: + * -# BSP1D + */ +#define _ALP_BACKEND reference + +/** + * Which GraphBLAS backend the BSP1D backend should use within a single user + * process. For possible values, see the single user process options for + * #_ALP_BACKEND. + */ +#define _ALP_BSP1D_BACKEND +#endif + +#ifndef _H_ALP +#define _H_ALP + +// do NOT remove this #if, in order to protect this header from +// clang-format re-ordering +#if 1 +// load active configuration +// #include //defines _ALP_BACKEND and _WITH_BSP +#endif + +// #pragma message "Included ALP.hpp" + +// collects the user-level includes +// #include +#include +#include +#include +#include +// #include +#include +#include +// #include +// #include +// #include +// #include +// #include +// #include + +#ifdef _ALP_BACKEND +// #pragma message "_ALP_BACKEND defined" +// include also the main data types in order to have the default definitions +// but ONLY if a default backend is define; otherwise, the previous headers +// contain the relevant definitions (without defaults) +#include +#include +#endif + +#endif // end ``_H_ALP'' diff --git a/include/alp/CMakeLists.txt b/include/alp/CMakeLists.txt new file mode 100644 index 000000000..84ab0b038 --- /dev/null +++ b/include/alp/CMakeLists.txt @@ -0,0 +1,96 @@ +# +# Copyright 2021 Huawei Technologies Co., Ltd. +# +# 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. +# + +# +# Definition of GraphBLAS include targets: all targets here defined +# are interface targets for headers and basic definitions required to build +# GraphBLAS backends and tests. Importing targets have all basic dependencies +# and definitions to compile against each backend, but MUST explicitly +# set a default backend (if they want to do so). +# +assert_defined_variables( ALP_REFERENCE_INCLUDE_DEFS WITH_ALP_REFERENCE_BACKEND_HEADERS ) +assert_valid_variables( INCLUDE_INSTALL_DIR ) + +# to avoid flaky acrobatics with regex or glob expressions, copy main files directly +install( FILES "../alp.hpp" DESTINATION "${INCLUDE_INSTALL_DIR}" ) +set( root_files + "../alp.hpp" "backends.hpp" "benchmark.hpp" + "blas0.hpp" "blas1.hpp" "blas2.hpp" + "blas3.hpp" "collectives.hpp" "config.hpp" + "descriptors.hpp" "distribution.hpp" + "exec.hpp" "identities.hpp" "init.hpp" + "internalops.hpp" "io.hpp" "iomode.hpp" + "matrix.hpp" "monoid.hpp" "ops.hpp" + "phase.hpp" "pinnedvector.hpp" "properties.hpp" + "rc.hpp" "semiring.hpp" "spmd.hpp" + "tags.hpp" "type_traits.hpp" "utils.hpp" + "vector.hpp" +) +set( ALP_INCLUDE_INSTALL_DIR "${INCLUDE_INSTALL_DIR}/alp") +install( FILES ${root_files} DESTINATION "${ALP_INCLUDE_INSTALL_DIR}" ) + +# copy base headers and all its subdirectories (if any) +# note: leave the slash "/" at the end of the DIRECTORY path, +# othwerise CMake will create a "graphblas/base" directory inside DESTINATION !!! +# https://cmake.org/cmake/help/latest/command/install.html#installing-directories +install( DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/base/" + DESTINATION "${ALP_INCLUDE_INSTALL_DIR}/base" + FILES_MATCHING REGEX "${HEADERS_REGEX}" +) + +# copy utils headers +install( DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/utils/" + DESTINATION "${ALP_INCLUDE_INSTALL_DIR}/utils" + FILES_MATCHING REGEX "${HEADERS_REGEX}" +) + +if( WITH_ALP_REFERENCE_BACKEND_HEADERS ) + add_library( backend_alp_reference_headers INTERFACE ) + target_link_libraries( backend_alp_reference_headers INTERFACE backend_headers_nodefs ) + target_compile_definitions( backend_alp_reference_headers INTERFACE "${ALP_REFERENCE_INCLUDE_DEFS}" ) + + install( TARGETS backend_reference_headers EXPORT GraphBLASTargets ) +endif() + +if( WITH_ALP_REFERENCE_BACKEND ) + add_library( backend_alp_reference_headers INTERFACE ) + target_link_libraries( backend_alp_reference_headers INTERFACE backend_headers_nodefs ) + target_compile_definitions( backend_alp_reference_headers INTERFACE "${ALP_REFERENCE_INCLUDE_DEFS}" ) + install( TARGETS backend_alp_reference_headers EXPORT GraphBLASTargets ) + install( DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/alp/reference" + DESTINATION "${ALP_INCLUDE_INSTALL_DIR}/alp_reference" + FILES_MATCHING REGEX "${HEADERS_REGEX}" + ) +endif() + +# this target lists the algorithms implemented on top of the generic functionalities, +# hence it depends only on backend_headers_nodefs +add_library( algorithms INTERFACE ) +target_link_libraries( algorithms INTERFACE backend_headers_nodefs ) + +target_include_directories( + algorithms INTERFACE + + $ + $ +) + +install( DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/algorithms/" + DESTINATION "${ALP_INCLUDE_INSTALL_DIR}/algorithms" + FILES_MATCHING REGEX "${HEADERS_REGEX}" +) + +install( TARGETS algorithms EXPORT GraphBLASTargets ) diff --git a/include/alp/backends.hpp b/include/alp/backends.hpp new file mode 100644 index 000000000..9e36122a7 --- /dev/null +++ b/include/alp/backends.hpp @@ -0,0 +1,167 @@ + +/* + * Copyright 2021 Huawei Technologies Co., Ltd. + * + * 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. + */ + +/** + * @author: A. N. Yzelman + * @date 21st of December, 2016 + * + * @file This file contains a register of all backends that are either + * implemented, under implementation, or were at any point in time + * conceived and noteworthy enough to be recorded for future + * consideration to implement. It does so via the grb::Backend + * enum. + */ + +#ifndef _H_GRB_BACKENDS +#define _H_GRB_BACKENDS + +namespace grb { + + /** + * This enum collects all implemented backends. Depending on compile flags, + * some of these options may be disabled. + */ + enum Backend { + + /** + * The sequential reference implementation. Supports fast operations with + * both sparse and dense vectors. + */ + reference, + + /** + * The threaded reference implementation. Supports fast operations with both + * sparse and dense vectors. + */ + reference_omp, + + /** + * A shared-memory parallel distribution based on a row-wise 1D data + * distribution using shared vector data. + */ + shmem1D, + + /** + * Like shmem1D, but using interleaved vector allocation. Useful for multi- + * socket single-node targets. From experience, this is a good choice for up + * to four sockets-- after which BSP2D becomes preferred. + */ + NUMA1D, + + /** + * A superclass of all BSP-based implementations. + */ + GENERIC_BSP, + + /** + * A parallel implementation based on a row-wise 1D data distribution, + * implemented using PlatformBSP. + */ + BSP1D, + + /** + * Like BSP1D, but stores each matrix twice. Combined with the normal + * reference implementation, this actually stores all matrices four times + * This implementation is useful for maximum performance, at the cost of + * the additional memory usage. + */ + doublyBSP1D, + + /** + * A parallel implementation based on a block-cyclic 2D data distribution, + * implemented using PlatformBSP. This implementation will likely outperform + * BSP1D and doublyBSP1D as the number of nodes involved in the computation + * increases with the problem sizes. + */ + BSP2D, + + /** + * Like BSP2D, but automatically improves the distribution while executing + * user code-- while initial computations are slowed down, the user + * application will speed up as this GraphBLAS implementation infers more + * information about the best data distribution. + * When enough statistics are gathered, data is redistributed and all future + * operations execute much faster than with BSP2D alone. + */ + autoBSP, + + /** + * Like autoBSP, except that the best distribution is precomputed whenever a + * matrix is read in. This pre-processing step is very expensive. Use autoBSP + * when unsure if the costs of a full preprocessing stage is worth it. + */ + optBSP, + + /** + * A hybrid that uses shmem1D within each socket and BSP1D between sockets. + * Recommended for a limited number of sockets and a limited amount of nodes, + * i.e., for a small cluster. + */ + hybridSmall, + + /** + * A hybrid that uses numa1D within each socket and BSP1D between sockets. + * Recommended for a limited number of nodes with up to two sockets each. + * + * This variant is expected to perform better than hybrid1D for middle-sized + * clusters. + */ + hybridMid, + + /** + * A hybrid that uses numa1D within each socket and autoBSP between sockets. + * Recommended for a large number of nodes with up to two sockets each. + * + * This variant is expected to perform better than hybridSmall and hybridMid + * for larger clusters. + * + * If there are many nodes each with many sockets (four or more) each, then + * the use of flat (non-hybrid) #BSP2D or #autoBSP is recommended instead. + */ + hybridLarge, + + /** + * A hybrid variant that is optimised for a minimal memory footprint. + */ + minFootprint, + + /** + * A variant for RISC-V processors. + * + * Collaboration with ETH Zurich (ongoing). + */ + banshee, + + /** + * A variant for RISC-V processors with (I)SSR extensions + * + * Collaboration with ETH Zurich (ongoing). + */ + banshee_ssr, + + /** + * The ALP/Dense backend. This is no longer a proper GraphBLAS implementation, as it assumes + * all containers are dense. No ``missing'' entries in containers are allowed. + */ + reference_dense + + }; + +} // namespace grb + +#endif + diff --git a/include/alp/base/blas2.hpp b/include/alp/base/blas2.hpp new file mode 100644 index 000000000..958655123 --- /dev/null +++ b/include/alp/base/blas2.hpp @@ -0,0 +1,658 @@ + +/* + * Copyright 2021 Huawei Technologies Co., Ltd. + * + * 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. + */ + +/** + * @file + * + * Defines the GraphBLAS level 2 API. + * + * @author A. N. Yzelman + * @date 30th of March 2017 + */ + +#ifndef _H_GRB_BLAS2_BASE +#define _H_GRB_BLAS2_BASE + +#include + +#include +#include +#include +#include +#include + +#include "config.hpp" +#include "matrix.hpp" +#include "vector.hpp" + +namespace grb { + + /** + * \defgroup BLAS2 The Level-2 Basic Linear Algebra Subroutines (BLAS) + * + * A collection of functions that allow GraphBLAS operators, monoids, and + * semirings work on a mix of zero-dimensional, one-dimensional, and + * two-dimensional containers. + * + * That is, these functions allow various linear algebra operations on + * scalars, objects of type grb::Vector, and objects of type grb::Matrix. + * + * \note The backends of each opaque data type should match. + * + * @{ + */ + + /** + * Right-handed sparse matrix times vector multiplication, \f$ u = Av \f$. + * + * Let \f$ u \f$ and \f$ \mathit{mask} \f$ each be a #grb::Vector of #grb::size + * \f$ m \f$, \f$ v \f$ be a #grb::Vector of #grb::size \f$ n \f$, and let + * \f$ A \f$ be a #Matrix with #grb::nrows \f$ m \f$ and #grb::ncols \f$ n \f$. + * Let furthermore \f$ z \f$ be an interal vector of size \f$ m \f$. + * A call to this function first computes \f$ z = Av \f$ over the provided + * \a ring. It then left-folds \f$ z \f$ into \f$ u \f$ using the provided + * \a accumulator. + * + * @see Vector for an in-depth description of a GraphBLAS vector. + * @see size for retrieving the length of a given GraphBLAS vector. + * @see Matrix for an in-depth description of a GraphBLAS matrix. + * @see nrows for retrieving the number of rows of a given GraphBLAS matrix. + * @see ncols for retrieving the number of columns of a given GraphBLAS + * vector. + * + * Formally, the exact operation executed is + * \f$ u_i^\mathit{out} = u_i^\mathit{in} \bigodot z_i, \f$ + * for all \f$ i \in \{ 0, 1, \ldots, m-1 \} \f$ for which + * \f$ \mathit{mask}_i \f$ evaluates true. If there is a nonzero at + * \f$ z_i \f$ but no nonzero at \f$ u_i^\mathit{in} \f$ then the latter is interpreted as the additive + * identity \f$ \mathbf{0} \f$ of the given \a ring. + * For \f$ z \f$, we formally have: + * \f$ z_i = \bigoplus{i=0}^{m-1} \left( A_{ij} \bigotimes v_j \right), \f$ + * where \f$ \bigodot \f$ represents the \a accumulator, \f$ \bigoplus \f$ + * represents the additive operator of the provided \a ring, and + * \f$ \bigotimes \f$ represents the multiplicative operator of \a ring. If here + * \f$ v_j \f$ does not exist, it is considered to be equal to the additive + * identity of the given \a ring. + * + * \note The additive identity of a given \a ring is an annihilator of + * nonzeroes from \f$ A \f$ under the multiplicative operator of \a ring; + * that is, \f$ z_i \f$ will be \f$ \mathbf{0} \f$ always. This can, of + * course, be exploited during sparse matrix--sparse vector (SpMSpV) + * multiplication. + * + * \note A good implementation is very careful about forming \f$ z \f$ + * explicitly and, even if it is formed already, is very careful about + * making use of \f$ z \f$. Making use of an explicit buffer will result + * in \f$ \Theta(m) \f$ data movement and may only be warrented when + * \f$ A \f$ has many nonzeroes per row and \f$ v \f$ is dense. + * + * @tparam descr Any combination of one or more #grb::descriptors. When + * ommitted, the default #grb::descriptors:no_operation will + * be assumed. + * @tparam Ring The generalised semi-ring the matrix--vector multiplication + * is to be executed under. + * @tparam IOType The type of the elements of the output vector \a u. + * @tparam InputType1 The type of the elements of the input vector \a v. + * @tparam InputType2 The type of the elements of the input matrix \a A. + * @tparam Operator The type of the \a accumulator. Must be a GraphBLAS + * operator; see also #grb::operators. + * @tparam InputType3 The type of the elements of the mask vector \a mask. + * @tparam implementation Which back-end the given vectors and matrices belong + * to. These must all belong to the same back-end. + * + * @param[in,out] u The output vector. Depending on the provided + * \a accumulator, old vector values may affect new values. + * @param[in] mask The mask vector. The vector #grb::size must be equal to + * that of \a u, \em or it must be equal to zero. A \a mask + * of grb::size zero will be ignored (assumed true + * always. + * @param[in] accumulator The operator \f$ \bigodot \f$ in the above + * description. + * @param[in] A The input matrix. Its #grb::nrows must equal the + * #grb::size of \a u. + * @param[in] v The input vector. Its #grb::size must equal the + * #grb::ncols of \a A. + * @param[in] ring The semiring to perform the matrix--vector multiplication + * under. Unless #grb::descriptors::no_casting is defined, + * elements from \a u, \a A, and \a v will be cast to the + * domains of the additive and multiplicative operators of + * \a ring as they are applied during the multiplication. + * + * \warning Even if #grb::operators::right_assign is provided as accumulator, + * old values of \a u may \em not be overwritten if the computation + * ends up not writing any new values to those values. To throw away + * old vector values use grb::descriptors::explicit_zero (for dense + * vectors only if you wish to retain sparsity of the output vector), + * or first simply use grb::clear on \a u. + * + * The above semantics may be changed by the following descriptors: + * * #descriptors::invert_mask: \f$ u_i^\mathit{out} \f$ will be written to + * if and only if \f$ \mathit{mask}_i \f$ evaluates false. + * * #descriptors::transpose_matrix: \f$ A \f$ is interpreted as \f$ A^T \f$ + * instead. + * * #descriptors::structural: when evaluating \f$ \mathit{mask}_i \f$, only + * the structure of \f$ \mathit{mask} \f$ is considered (as opposed to its + * elements); if \f$ \mathit{mask} \f$ has a nonzero at its \f$ i \f$th + * index, it is considered to evaluate true no matter what the + * actual value of \f$ \mathit{mask}_i \f$ was. + * * #descriptors::structural_complement: a combination of two descriptors: + * #descriptors::structural and #descriptors::invert_mask (and thus + * equivalent to structural | invert_mask). Its net effect is if + * \f$ \mathit{mask} \f$ does \em not have a nonzero at the \f$ i \f$th + * index, the mask is considered to evaluate true. + * * #descriptors::add_identity: the matrix \f$ A \f$ is instead interpreted + * as \f$ A + \mathbf{1} \f$, where \f$ \mathbf{1} \f$ is the + * multiplicative identity of the given ring. + * * #descriptors::use_index: when referencing \f$ v_i \f$, if assigned, then + * instead of using the value itself, its index \f$ i \f$ is used instead. + * * #descriptors::in_place: the \a accumulator is ignored; the additive + * operator of the given \a ring is used in its place. Under certain + * conditions, an implementation can exploit this semantic to active + * faster computations. + * * #descriptors::explicit_zero: if \f$ \mathbf{0} \f$ would be assigned to + * a previously unassigned index, assign \f$ \mathbf{0} \f$ explicitly to + * that index. Here, \f$ \mathbf{0} \f$ is the additive identity of the + * provided \a ring. + * + * \parblock + * \par Performance semantics + * Performance semantics vary depending on whether a mask was provided, and on + * whether the input vector is sparse or dense. If the input vector \f$ v \f$ + * is sparse, let \f$ J \f$ be its set of assigned indices. If a non-trivial + * mask \f$ \mathit{mask} \f$ is given, let \f$ I \f$ be the set of indices for + * which the corresponding \f$ \mathit{mask}_i \f$ evaluate true. Then: + * -# For the performance guarantee on the amount of work this function + * entails the following table applies:
+ * \f$ \begin{tabular}{cccc} + * Masked & Dense input & Sparse input \\ + * \noalign{\smallskip} + * no & $\Theta(2\mathit{nnz}(A))$ & $\Theta(2\mathit{nnz}(A_{:,J}))$ \\ + * yes & $\Theta(2\mathit{nnz}(A_{I,:})$ & $\Theta(\min\{2\mathit{nnz}(A_{I,:}),2\mathit{nnz}(A_{:,J})\})$ + * \end{tabular}. \f$ + * -# For the amount of data movements, the following table applies:
+ * \f$ \begin{tabular}{cccc} + * Masked & Dense input & Sparse input \\ + * \noalign{\smallskip} + * no & $\Theta(\mathit{nnz}(A)+\min\{m,n\}+m+n)$ & $\Theta(\mathit{nnz}(A_{:,J}+\min\{m,2|J|\}+|J|)+\mathcal{O}(2m)$ \\ + * yes & $\Theta(\mathit{nnz}(A_{I,:})+\min\{|I|,n\}+2|I|)+\mathcal{O}(n)$ & + * $\Theta(\min\{\Theta(\mathit{nnz}(A_{I,:})+\min\{|I|,n\}+2|I|)+\mathcal{O}(n),\mathit{nnz}(A_{:,J}+\min\{m,|J|\}+2|J|)+\mathcal{O}(2m))$ \end{tabular}. \f$ + * -# A call to this function under no circumstance will allocate nor free + * dynamic memory. + * -# A call to this function under no circumstance will make system calls. + * The above performance bounds may be changed by the following desciptors: + * * #descriptors::invert_mask: replaces \f$ \Theta(|I|) \f$ data movement + * costs with a \f$ \mathcal{O}(2m) \f$ cost instead, or a + * \f$ \mathcal{O}(m) \f$ cost if #descriptors::structural was defined as + * well (see below). In other words, implementations are not required to + * implement inverted operations efficiently (\f$ 2\Theta(m-|I|) \f$ data + * movements would be optimal but costs another \f$ \Theta(m) \f$ memory + * to maintain). + * * #descriptors::structural: removes \f$ \Theta(|I|) \f$ data movement + * costs as the mask values need no longer be touched. + * * #descriptors::add_identity: adds, at most, the costs of grb::foldl + * (on vectors) to all performance metrics. + * * #descriptors::use_index: removes \f$ \Theta(n) \f$ or + * \f$ \Theta(|J|) \f$ data movement costs as the input vector values need + * no longer be touched. + * * #descriptors::in_place (see also above): turns \f$ \mathcal{O}(2m) \f$ + * data movements into \f$ \mathcal{O}(m) \f$ instead; i.e., it halves the + * amount of data movements for writing the output. + * * #descriptors::dense: the input, output, and mask vectors are assumed to + * be dense. This allows the implementation to skip checks or other code + * blocks related to handling of sparse vectors. This may result in use of + * unitialised memory if any of the provided vectors were, in fact, + * sparse. + * Implementations that support multiple user processes must characterise data + * movement between then. + * \endparblock + * + * @returns grb::SUCCESS If the computation completed successfully. + * @returns grb::MISMATCH If there is at least one mismatch between vector + * dimensions or between vectors and the given matrix. + * @returns grb::OVERLAP If two or more provided vectors refer to the same + * vector. + * + * When a non-SUCCESS error code is returned, it shall be as though the call + * was never made. Note that all GraphBLAS functions may additionally return + * #grb::PANIC, which indicates the library has entered an undefined state; if + * this error code is returned, the only sensible thing a user can do is exit, + * or at least refrain from using any GraphBLAS functions for the remainder of + * the application. + */ + template< Descriptor descr = descriptors::no_operation, + class Ring, + typename IOType, + typename InputType1, + typename InputType2, + typename InputType3, + typename Coords, + enum Backend implementation = config::default_backend > + RC mxv( Vector< IOType, implementation, Coords > & u, + const Vector< InputType3, implementation, Coords > & mask, + const Matrix< InputType2, implementation > & A, + const Vector< InputType1, implementation, Coords > & v, + const Ring & ring, + typename std::enable_if< grb::is_semiring< Ring >::value, void >::type * = NULL ) { +#ifdef _DEBUG + #ifndef _GRB_NO_STDIO + std::cerr << "Selected backend does not implement grb::mxv (output-masked)\n"; + #endif +#endif + (void)u; + (void)mask; + (void)A; + (void)v; + (void)ring; + return UNSUPPORTED; + } + + /** + * A short-hand for an unmasked #grb::mxv. + * + * @see grb::mxv for the full documentation. + */ + template< Descriptor descr = descriptors::no_operation, class Ring, typename IOType, typename InputType1, typename InputType2, typename Coords, Backend implementation = config::default_backend > + RC mxv( Vector< IOType, implementation, Coords > & u, + const Matrix< InputType2, implementation > & A, + const Vector< InputType1, implementation, Coords > & v, + const Ring & ring, + typename std::enable_if< grb::is_semiring< Ring >::value, void >::type * = NULL ) { +#ifdef _DEBUG +#ifndef _GRB_NO_STDIO + std::cerr << "Selected backend does not implement grb::mxv\n"; +#else + printf( "Selected backend does not implement grb::mxv\n" ); +#endif +#endif + (void)u; + (void)A; + (void)v; + (void)ring; + return UNSUPPORTED; + } + + /** + * Left-handed sparse matrix times vector multiplication, \f$ u = vA \f$. + * + * If \a descr does not have #grb::descriptors::transpose_matrix defined, the + * semantics and performance semantics of this function are exactly that of + * grb::mxv with the #grb::descriptors::transpose_matrix set. + * In the other case, the functional and performance semantics of this function + * are exactly that of grb::mxv without the #grb::descriptors::transpose_matrix + * set. + * + * @see grb::mxv for the full documentation. + */ + template< Descriptor descr = descriptors::no_operation, + class Ring, + typename IOType, + typename InputType1, + typename InputType2, + typename InputType3, + typename Coords, + enum Backend implementation = config::default_backend > + RC vxm( Vector< IOType, implementation, Coords > & u, + const Vector< InputType3, implementation, Coords > & mask, + const Vector< InputType1, implementation, Coords > & v, + const Matrix< InputType2, implementation > & A, + const Ring & ring, + typename std::enable_if< grb::is_semiring< Ring >::value, void >::type * = NULL ) { +#ifdef _DEBUG + #ifndef _GRB_NO_STDIO + std::cerr << "Selected backend does not implement grb::vxm (output-masked)\n"; + #endif +#endif + (void)u; + (void)mask; + (void)v; + (void)A; + (void)ring; + return UNSUPPORTED; + } + + /** + * A short-hand for an unmasked grb::vxm. + * + * @see grb::vxm for the full documentation. + */ + template< Descriptor descr = descriptors::no_operation, + class Ring, + typename IOType, + typename InputType1, + typename InputType2, + typename Coords, + enum Backend implementation = config::default_backend > + RC vxm( Vector< IOType, implementation, Coords > & u, + const Vector< InputType1, implementation, Coords > & v, + const Matrix< InputType2, implementation > & A, + const Ring & ring, + typename std::enable_if< grb::is_semiring< Ring >::value, void >::type * = NULL ) { +#ifdef _DEBUG + #ifndef _GRB_NO_STDIO + std::cerr << "Selected backend does not implement grb::vxm\n"; + #endif +#endif + (void)u; + (void)v; + (void)A; + (void)ring; + return UNSUPPORTED; + } + + /** TODO documentation */ + template< Descriptor descr = descriptors::no_operation, + class AdditiveMonoid, + class MultiplicativeOperator, + typename IOType, + typename InputType1, + typename InputType2, + typename InputType3, + typename InputType4, + typename Coords, + Backend backend > + RC vxm( Vector< IOType, backend, Coords > & u, + const Vector< InputType3, backend, Coords > & mask, + const Vector< InputType1, backend, Coords > & v, + const Vector< InputType4, backend, Coords > & v_mask, + const Matrix< InputType2, backend > & A, + const AdditiveMonoid & add = AdditiveMonoid(), + const MultiplicativeOperator & mul = MultiplicativeOperator(), + const typename std::enable_if< grb::is_monoid< AdditiveMonoid >::value && grb::is_operator< MultiplicativeOperator >::value && ! grb::is_object< IOType >::value && + ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && ! grb::is_object< InputType4 >::value && + ! std::is_same< InputType2, void >::value, + void >::type * const = NULL ) { +#ifdef _DEBUG + #ifndef _GRB_NO_STDIO + std::cerr << "Selected backend does not implement vxm (doubly-masked)\n"; + #endif +#endif + (void)u; + (void)mask; + (void)v; + (void)v_mask; + (void)A; + (void)add; + (void)mul; + return UNSUPPORTED; + } + + /** TODO documentation */ + template< Descriptor descr = descriptors::no_operation, + class AdditiveMonoid, + class MultiplicativeOperator, + typename IOType, + typename InputType1, + typename InputType2, + typename InputType3, + typename InputType4, + typename Coords, + Backend backend > + RC mxv( Vector< IOType, backend, Coords > & u, + const Vector< InputType3, backend, Coords > & mask, + const Matrix< InputType2, backend > & A, + const Vector< InputType1, backend, Coords > & v, + const Vector< InputType4, backend, Coords > & v_mask, + const AdditiveMonoid & add = AdditiveMonoid(), + const MultiplicativeOperator & mul = MultiplicativeOperator(), + const typename std::enable_if< grb::is_monoid< AdditiveMonoid >::value && grb::is_operator< MultiplicativeOperator >::value && ! grb::is_object< IOType >::value && + ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && ! grb::is_object< InputType4 >::value && + ! std::is_same< InputType2, void >::value, + void >::type * const = NULL ) { +#ifdef _DEBUG + #ifndef _GRB_NO_STDIO + std::cerr << "Selected backend does not implement mxv (doubly-masked)\n"; + #endif +#endif + (void)u; + (void)mask; + (void)A; + (void)v; + (void)v_mask; + (void)add; + (void)mul; + return UNSUPPORTED; + } + + /** TODO documentation */ + template< Descriptor descr = descriptors::no_operation, + class AdditiveMonoid, + class MultiplicativeOperator, + typename IOType, + typename InputType1, + typename InputType2, + typename InputType3, + typename Coords, + Backend backend > + RC mxv( Vector< IOType, backend, Coords > & u, + const Vector< InputType3, backend, Coords > & mask, + const Matrix< InputType2, backend > & A, + const Vector< InputType1, backend, Coords > & v, + const AdditiveMonoid & add = AdditiveMonoid(), + const MultiplicativeOperator & mul = MultiplicativeOperator(), + const typename std::enable_if< grb::is_monoid< AdditiveMonoid >::value && grb::is_operator< MultiplicativeOperator >::value && ! grb::is_object< IOType >::value && + ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && ! std::is_same< InputType2, void >::value, + void >::type * const = NULL ) { + (void)u; + (void)mask; + (void)A; + (void)v; + (void)add; + (void)mul; + return UNSUPPORTED; + } + + /** TODO documentation */ + template< Descriptor descr = descriptors::no_operation, + class AdditiveMonoid, + class MultiplicativeOperator, + typename IOType, + typename InputType1, + typename InputType2, + typename Coords, + Backend backend > + RC vxm( Vector< IOType, backend, Coords > & u, + const Vector< InputType1, backend, Coords > & v, + const Matrix< InputType2, backend > & A, + const AdditiveMonoid & add = AdditiveMonoid(), + const MultiplicativeOperator & mul = MultiplicativeOperator(), + const typename std::enable_if< grb::is_monoid< AdditiveMonoid >::value && grb::is_operator< MultiplicativeOperator >::value && ! grb::is_object< IOType >::value && + ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! std::is_same< InputType2, void >::value, + void >::type * const = NULL ) { +#ifdef _DEBUG + #ifndef _GRB_NO_STDIO + std::cerr << "Selected backend does not implement vxm (unmasked)\n"; + #endif +#endif + (void)u; + (void)v; + (void)A; + (void)add; + (void)mul; + return UNSUPPORTED; + } + + /** TODO documentation */ + template< Descriptor descr = descriptors::no_operation, + class AdditiveMonoid, + class MultiplicativeOperator, + typename IOType, + typename InputType1, + typename InputType2, + typename InputType3, + typename Coords, + Backend implementation > + RC vxm( Vector< IOType, implementation, Coords > & u, + const Vector< InputType3, implementation, Coords > & mask, + const Vector< InputType1, implementation, Coords > & v, + const Matrix< InputType2, implementation > & A, + const AdditiveMonoid & add = AdditiveMonoid(), + const MultiplicativeOperator & mul = MultiplicativeOperator(), + typename std::enable_if< grb::is_monoid< AdditiveMonoid >::value && grb::is_operator< MultiplicativeOperator >::value && ! grb::is_object< IOType >::value && + ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! std::is_same< InputType2, void >::value, + void >::type * = NULL ) { +#ifdef _DEBUG + #ifndef _GRB_NO_STDIO + std::cerr << "Selected backend does not implement grb::vxm (output-masked)\n"; + #endif +#endif + (void)u; + (void)mask; + (void)v; + (void)A; + (void)add; + (void)mul; + return UNSUPPORTED; + } + + /** TODO documentation */ + template< Descriptor descr = descriptors::no_operation, + class AdditiveMonoid, + class MultiplicativeOperator, + typename IOType, + typename InputType1, + typename InputType2, + typename Coords, + Backend backend > + RC mxv( Vector< IOType, backend, Coords > & u, + const Matrix< InputType2, backend > & A, + const Vector< InputType1, backend, Coords > & v, + const AdditiveMonoid & add = AdditiveMonoid(), + const MultiplicativeOperator & mul = MultiplicativeOperator(), + const typename std::enable_if< grb::is_monoid< AdditiveMonoid >::value && grb::is_operator< MultiplicativeOperator >::value && ! grb::is_object< IOType >::value && + ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! std::is_same< InputType2, void >::value, + void >::type * const = NULL ) { +#ifdef _DEBUG + #ifndef _GRB_NO_STDIO + std::cerr << "Selected backend does not implement grb::mxv (unmasked)\n"; + #endif +#endif + (void)u; + (void)A; + (void)v; + (void)add; + (void)mul; + return UNSUPPORTED; + } + + /** + * Executes an arbitrary element-wise user-defined function \a f on all + * nonzero elements of a given matrix \a A. + * + * The user-defined function is passed as a lambda which can capture whatever + * the user would like, including one or multiple grb::Vector instances, or + * multiple scalars. When capturing vectors, these should also be passed as a + * additional arguments to this functions so to make sure those vectors are + * synchronised for access on all row- and column- indices corresponding to + * locally stored nonzeroes of \a A. + * + * Only the elements of a single matrix may be iterated upon. + * + * \note Rationale: while it is reasonable to expect an implementation be able + * to synchronise vector elements, it may be unreasonable to expect two + * different matrices can be jointly accessed via arbitrary lambda + * functions. + * + * \warning The lambda shall only be executed on the data local to the user + * process calling this function! This is different from the various + * fold functions, or grb::dot, in that the semantics of those + * functions always result in globally synchronised result. To + * achieve the same effect with user-defined lambdas, the users + * should manually prescribe how to combine the local results into + * global ones, for instance, by subsequent calls to + * grb::collectives. + * + * \note This is an addition to the GraphBLAS. It is alike user-defined + * operators, monoids, and semirings, except it allows execution on + * arbitrarily many inputs and arbitrarily many outputs. + * + * @tparam Func the user-defined lambda function type. + * @tparam DataType the type of the user-supplied matrix. + * @tparam backend the backend type of the user-supplied vector example. + * + * @param[in] f The user-supplied lambda. This lambda should only capture + * and reference vectors of the same length as either the row or + * column dimension length of \a A. The lambda function should + * prescribe the operations required to execute on a given + * reference to a matrix nonzero of \a A (of type \a DataType) at + * a given index \f$ (i,j) \f$. Captured GraphBLAS vectors can + * access corresponding elements via Vector::operator[] or + * Vector::operator(). It is illegal to access any element not at + * position \a i if the vector length is equal to the row + * dimension. It is illegal to access any element not at position + * \a j if the vector length is equal to the column dimension. + * Vectors of length neither equal to the column or row dimension + * may \em not be referenced or undefined behaviour will occur. The + * reference to the matrix nonzero is non \a const and may thus be + * modified. New nonzeroes may \em not be added through this lambda + * functionality. The function \a f must have the following + * signature: + * (DataType &nz, const size_t i, const size_t j). + * The GraphBLAS implementation decides which nonzeroes of \a A are + * dereferenced, and thus also decides the values \a i and \a j the + * user function is evaluated on. + * @param[in] A The matrix the lambda is to access the elements of. + * @param[in] args All vectors the lambda is to access elements of. Must be of + * the same length as \a nrows(A) or \a ncols(A). If this + * constraint is violated, grb::MISMATCH shall be returned. If + * the vector length equals \a nrows(A), the vector shall be + * synchronized for access on \a i. If the vector length equals + * \a ncols(A), the vector shall be synchronized for access on + * \a j. If \a A is square, the vectors will be synchronised for + * access on both \a x and \a y. This is a variadic argument + * and can contain any number of containers of type grb::Vector, + * passed as though they were separate arguments. + * + * \warning Using a grb::Vector inside a lambda passed to this function while + * not passing that same vector into \a args, will result in undefined + * behaviour. + * + * \warning Due to the constraints on \a f described above, it is illegal to + * capture some vector \a y and have the following line in the body + * of \a f: x[i] += x[i+1]. Vectors can only be + * dereferenced at position \a i and \a i alone, and similarly for + * access using \a j. For square matrices, however, the following + * code in the body is accepted, however: x[i] += x[j]. + * + * @return grb::SUCCESS When the lambda is successfully executed. + * @return grb::MISMATCH When two or more vectors passed to \a args are not of + * appropriate length. + * + * \warning Captured scalars will be local to the user process executing the + * lambda. To retrieve the global dot product, an allreduce must + * explicitly be called. + * + * @see Vector::operator[]() + * @see Vector::operator()() + * @see Vector::lambda_reference + */ + template< typename Func, typename DataType, Backend implementation = config::default_backend, typename... Args > + RC eWiseLambda( const Func f, const Matrix< DataType, implementation > & A, Args... /*args*/ ) { +#ifdef _DEBUG + #ifndef _GRB_NO_STDIO + std::cerr << "Selected backend does not implement grb::eWiseLambda (matrices)\n"; + #endif +#endif + (void)f; + (void)A; + return UNSUPPORTED; + } + + /** @} */ + +} // namespace grb + +#endif // end _H_GRB_BLAS2_BASE diff --git a/include/alp/base/blas3.hpp b/include/alp/base/blas3.hpp new file mode 100644 index 000000000..d3367c6eb --- /dev/null +++ b/include/alp/base/blas3.hpp @@ -0,0 +1,167 @@ + +/* + * Copyright 2021 Huawei Technologies Co., Ltd. + * + * 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. + */ + +/* + * @author A. N. Yzelman + */ + +#ifndef _H_GRB_BLAS3_BASE +#define _H_GRB_BLAS3_BASE + +#include +#include + +#include "matrix.hpp" +#include "vector.hpp" + +namespace grb { + + /** + * \defgroup BLAS3 The Level-3 Basic Linear Algebra Subroutines (BLAS) + * + * A collection of functions that allow GraphBLAS semirings to work on + * one or more two-dimensional sparse containers (i.e, sparse matrices). + * + * @{ + */ + + /** + * Unmaked sparse matrix--sparse matrix multiplication (SpMSpM). + * + * @tparam descr The descriptors under which to perform the computation. + * @tparam OutputType The type of elements in the output matrix. + * @tparam InputType1 The type of elements in the left-hand side input + * matrix. + * @tparam InputType2 The type of elements in the right-hand side input + * matrix. + * @tparam Semiring The semiring under which to perform the + * multiplication. + * @tparam Backend The backend that should perform the computation. + * + * @returns SUCCESS If the computation completed as intended. + * @returns FAILED If the call was not not preceded by one to + * #grb::resize( C, A, B ); \em and the current capacity of + * \a C was insufficient to store the multiplication of \a A + * and \a B. The contents of \a C shall be undefined (which + * is why #FAILED is returned instead of #ILLEGAL-- this + * error has side effects). + * + * @param[out] C The output matrix \f$ C = AB \f$ when the function returns + * #SUCCESS. + * @param[in] A The left-hand side input matrix \f$ A \f$. + * @param[in] B The left-hand side input matrix \f$ B \f$. + * + * @param[in] ring (Optional.) The semiring under which the computation should + * proceed. + */ + template< + Descriptor descr = descriptors::no_operation, + typename OutputType, typename InputType1, typename InputType2, + class Semiring, + Backend backend + > + RC mxm( Matrix< OutputType, backend > &C, + const Matrix< InputType1, backend > &A, const Matrix< InputType2, backend > &B, + const Semiring &ring = Semiring(), + const PHASE &phase = NUMERICAL + ) { +#ifdef _DEBUG + #ifndef _GRB_NO_STDIO + std::cerr << "Selected backend does not implement grb::mxm (semiring version)\n"; + #endif +#endif + (void)C; + (void)A; + (void)B; + (void)ring; + (void)phase; + // this is the generic stub implementation + return UNSUPPORTED; + } + + /** + * Interprets three vectors x, y, and z as a series of row coordinates, + * column coordinates, and nonzeroes, respectively, and stores the thus + * defined nonzeroes in a given output matrix A. + * + * If this function does not return SUCCESS, A will have been cleared. + * + * A must have been pre-allocated to store the nonzero pattern the three + * given vectors x, y, and z encode, or ILLEGAL shall be returned. + * + * \note A call to this function hence must be preceded by a successful + * call to grb::resize( matrix, nnz ); + * + * @param[out] A The output matrix + * @param[in] x A vector of row indices. + * @param[in] y A vector of column indices. + * @param[in] z A vector of nonzero values. + * + * If x, y, and z are sparse, they must have the exact same sparsity + * structure. + * + * \par Descriptors + * + * None allowed. + * + * @returns SUCCESS If A was constructed successfully. + * @returns MISMATCH If y or z does not match the size of x. + * @returns ILLEGAL If y or z do not have the same number of nonzeroes + * as x. + * @returns ILLEGAL If y or z has a different sparsity pattern from x. + * @returns ILLEGAL If the capacity of A was insufficient to store the + * given sparsity pattern. + * + * @see grb::resize + */ + template< Descriptor descr = descriptors::no_operation, typename OutputType, typename InputType1, typename InputType2, typename InputType3, Backend backend, typename Coords > + RC zip( Matrix< OutputType, backend > & A, const Vector< InputType1, backend, Coords > & x, const Vector< InputType2, backend, Coords > & y, const Vector< InputType3, backend, Coords > & z ) { + (void)x; + (void)y; + (void)z; +#ifdef _DEBUG + #ifndef _GRB_NO_STDIO + std::cerr << "Selected backend does not implement grb::zip (vectors into matrices, non-void)\n"; + #endif +#endif + const RC ret = grb::clear( A ); + return ret == SUCCESS ? UNSUPPORTED : ret; + } + + /** + * Specialisation of grb::zip for void output matrices. + */ + template< Descriptor descr = descriptors::no_operation, typename InputType1, typename InputType2, typename InputType3, Backend backend, typename Coords > + RC zip( Matrix< void, backend > & A, const Vector< InputType1, backend, Coords > & x, const Vector< InputType2, backend, Coords > & y ) { + (void)x; + (void)y; +#ifdef _DEBUG + #ifndef _GRB_NO_STDIO + std::cerr << "Selected backend does not implement grb::zip (vectors into matrices, void)\n"; + #endif +#endif + const RC ret = grb::clear( A ); + return ret == SUCCESS ? UNSUPPORTED : ret; + } + + /** + * @} + */ + +} // namespace grb + +#endif // end _H_GRB_BLAS3_BASE diff --git a/include/alp/base/collectives.hpp b/include/alp/base/collectives.hpp new file mode 100644 index 000000000..7c94c8c9c --- /dev/null +++ b/include/alp/base/collectives.hpp @@ -0,0 +1,258 @@ + +/* + * Copyright 2021 Huawei Technologies Co., Ltd. + * + * 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. + */ + +/* + * @author A. N. Yzelman & J. M. Nash + * @date 20th of February, 2017 + */ + +#ifndef _H_GRB_COLL_BASE +#define _H_GRB_COLL_BASE + +#include +#include +#include + +namespace grb { + + /** + * A static class defining various collective operations on scalars. This + * class is templated in terms of the backends that are implemented-- each + * implementation provides its own mechanisms to handle collective + * communications. These are required for users employing grb::eWiseLambda, + * or for users who perform explicit SPMD programming. + */ + template< enum Backend implementation > + class collectives { + + private: + /** Disallow creating an instance. */ + collectives() {} + + public: + /** + * Schedules an allreduce operation of a single object of type IOType per + * process. The allreduce shall be complete by the end of the call. This is a + * collective graphBLAS operation. After the collective call finishes, each + * user process will locally have available the allreduced value. + * + * Since this is a collective call, there are \a P values \a inout spread over + * all user processes. Let these values be denoted by \f$ x_s \f$, with + * \f$ s \in \{ 0, 1, \ldots, P-1 \}, \f$ such that \f$ x_s \f$ equals the + * argument \a inout on input at the user process with ID \a s. Let + * \f$ \pi:\ \{ 0, 1, \ldots, P-1 \} \to \{ 0, 1, \ldots, P-1 \} \f$ be a + * bijection, some unknown permutation of the process ID. This permutation is + * must be fixed for any given combination of GraphBLAS implementation and value + * \a P. Let the binary operator \a op be denoted by \f$ \odot \f$. + * + * This function computes \f$ \odot_{i=0}^{P-1} x_{\pi(i)} \f$ and writes the + * exact same result to \a inout at each of the \a P user processes. + * + * In summary, this means 1) this operation is coherent across all processes and + * produces bit-wise equivalent output on all user processes, and 2) the result + * is reproducible across different runs using the same input and \a P. Yet it + * does \em not mean that the order of addition is fixed. + * + * Since each user process supplies but one value, there is no difference + * between a reduce-to-the-left versus a reduce-to-the-right (see grb::reducel + * and grb::reducer). + * + * @tparam descr The GraphBLAS descriptor. + * Default is grb::descriptors::no_operation. + * @tparam Operator Which operator to use for reduction. + * @tparam IOType The type of the to-be reduced value. + * + * @param[in,out] inout On input: the value at the calling process to be + * reduced. On output: the reduced value. + * @param[in] op The associative operator to reduce by. + * + * \note If \op is commutative, the implementation free to employ a different + * allreduce algorithm, as long as it is documented well enough so that + * its cost can be quantified. + * + * @returns grb::SUCCESS When the operation succeeds as planned. + * @returns grb::PANIC When the communication layer unexpectedly fails. When + * this error code is returned, the library enters an + * undefined state. + * + * \parblock + * \par Valid descriptors: + * -# grb::descriptors::no_operation + * -# grb::descriptors::no_casting + * Any other descriptors will be ignored. + * \endparblock + * + * \parblock + * \par Performance semantics: + * -# Problem size N: \f$ P * \mathit{sizeof}(\mathit{IOType}) \f$ + * -# local work: \f$ N*Operator \f$ ; + * -# transferred bytes: \f$ N \f$ ; + * -# BSP cost: \f$ Ng + N*Operator + l \f$; + * \endparblock + */ + template< Descriptor descr = descriptors::no_operation, typename Operator, typename IOType > + static RC allreduce( IOType & inout, const Operator op = Operator() ) { + (void)inout; + (void)op; + return UNSUPPORTED; + } + + /** + * Schedules a reduce operation of a single object of type IOType per process. + * The reduce shall be complete by the end of the call. This is a collective + * graphBLAS operation. The BSP costs are as for the PlatformBSP #reduce. + * + * Since this is a collective call, there are \a P values \a inout spread over + * all user processes. Let these values be denoted by \f$ x_s \f$, with + * \f$ s \in \{ 0, 1, \ldots, P-1 \}, \f$ such that \f$ x_s \f$ equals the + * argument \a inout on input at the user process with ID \a s. Let + * \f$ \pi:\ \{ 0, 1, \ldots, P-1 \} \to \{ 0, 1, \ldots, P-1 \} \f$ be a + * bijection, some unknown permutation of the process ID. This permutation is + * must be fixed for any given combination of GraphBLAS implementation and value + * \a P. Let the binary operator \a op be denoted by \f$ \odot \f$. + * + * This function computes \f$ \odot_{i=0}^{P-1} x_{\pi(i)} \f$ and writes the + * result to \a inout at the user process with ID \a root. + * + * In summary, this the result is reproducible across different runs using the + * same input and \a P. Yet it does \em not mean that the order of addition is + * fixed. + * + * Since each user process supplies but one value, there is no difference + * between a reduce-to-the-left versus a reduce-to-the-right (see grb::reducel + * and grb::reducer). + * + * @tparam descr The GraphBLAS descriptor. + * Default is grb::descriptors::no_operation. + * @tparam Operator Which operator to use for reduction. + * @tparam IOType The type of the to-be reduced value. + * + * @param[in,out] inout On input: the value at the calling process to be + * reduced. On output at process \a root: the reduced value. + * On output as non-root processes: same value as on input. + * @param[in] op The associative operator to reduce by. + * @param[in] root Which process should hold the reduced value. This + * number must be larger or equal to zero, and must be + * strictly smaller than the number of user processes + * \a P. + * + * @return SUCCESS When the function completes successfully. + * @return ILLEGAL When root is larger or equal than \a P. When this code is + * returned, the state of the GraphBLAS shall be as though + * this call was never made. + * @return PANIC When an unmitigable error within the GraphBLAS occurs. + * Upon returning this error, the GraphBLAS enters an + * undefined state. + * + * \note If \op is commutative, the implementation free to employ a different + * allreduce algorithm, as long as it is documented well enough so that + * its cost can be quantified. + * + * \parblock + * \par Performance semantics: + * -# Problem size N: \f$ P * \mathit{sizeof}(\mathit{IOType}) \f$ + * -# local work: \f$ N*Operator \f$ ; + * -# transferred bytes: \f$ N \f$ ; + * -# BSP cost: \f$ Ng + N*Operator + l \f$; + * \endparblock + */ + template< Descriptor descr = descriptors::no_operation, typename Operator, typename IOType > + static RC reduce( IOType & inout, const size_t root = 0, const Operator op = Operator() ) { + (void)inout; + (void)op; + (void)root; + return UNSUPPORTED; + } + + /** + * Schedules a broadcast operation of a single object of type IOType per + * process. The broadcast shall be complete by the end of the call. This is + * a collective graphBLAS operation. The BSP costs are as for the PlatformBSP + * #broadcast. + * + * @tparam IOType The type of the to-be broadcast value. + * + * @param[in,out] inout On input at process \a root: the value to be + * broadcast. + * On input at non-root processes: initial values are + * ignored. + * On output at process \a root: the input value remains + * unchanged. + * On output at non-root processes: the same value held + * at process ID \a root. + * @param[in] root The user process which is to send out the given input + * value \a inout so that it becomes available at all + * \a P user processes. This value must be larger or + * equal to zero and must be smaller than the total + * number of user processes \a P. + * + * @return SUCCESS On the successful completion of this function. + * @return ILLEGAL When \a root is larger or equal to \a P. If this code is + * returned, it shall be as though the call to this function + * had never occurred. + * return PANIC When the function fails and the library enters an + * undefined state. + * + * \parblock + * \par Performance semantics: serial + * -# Problem size N: \f$ \mathit{sizeof}(\mathit{IOType}) \f$ + * -# local work: \f$ 0 \f$ ; + * -# transferred bytes: \f$ NP \f$ ; + * -# BSP cost: \f$ NPg + l \f$; + * \endparblock + * + * \par Performance semantics: two phase + * -# Problem size N: \f$ \mathit{sizeof}(\mathit{IOType}) \f$ + * -# local work: \f$ 0 \f$ ; + * -# transferred bytes: \f$ 2N \f$ ; + * -# BSP cost: \f$ 2(Ng + l) \f$; + * \endparblock + * + * \par Performance semantics: two level tree + * -# Problem size N: \f$ \mathit{sizeof}(\mathit{IOType}) \f$ + * -# local work: \f$ 0 \f$ ; + * -# transferred bytes: \f$ 2\sqrt{P}N \f$ ; + * -# BSP cost: \f$ 2(\sqrt{P}Ng + l) \f$; + * \endparblock + */ + template< typename IOType > + static RC broadcast( IOType &inout, const size_t root = 0 ) { + (void)inout; + (void)root; + return UNSUPPORTED; + } + + /** + * Broadcast on an array of \a IOType. + * + * The above documentation applies with \a size times sizeof(IOType) + * substituted in. + */ + template< Descriptor descr = descriptors::no_operation, typename IOType > + static RC broadcast( IOType * inout, const size_t size, const size_t root = 0 ) { + (void)inout; + (void)size; + (void)root; + return UNSUPPORTED; + } + + }; // end class ``collectives'' + +} // end namespace grb + +#endif // end _H_GRB_COLL_BASE + diff --git a/include/alp/base/config.hpp b/include/alp/base/config.hpp new file mode 100644 index 000000000..7e00e2dbd --- /dev/null +++ b/include/alp/base/config.hpp @@ -0,0 +1,300 @@ + +/* + * Copyright 2021 Huawei Technologies Co., Ltd. + * + * 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. + */ + +/* + * @author A. N. Yzelman + * @date 8th of August, 2016 + */ + +#ifndef _H_GRB_CONFIG_BASE +#define _H_GRB_CONFIG_BASE + +#include //size_t +#include + +#include +#include //sysconf + +#include + +#ifndef _GRB_NO_STDIO + #include //std::cout +#endif + +// if the user did not define _GRB_BACKEND, set it to the default sequential +// implementation +#ifndef _GRB_BACKEND + #define _GRB_BACKEND reference +#endif + +/** + * The main GraphBLAS namespace. + * + * All GraphBLAS functions and objects are defined within. + */ +namespace grb { + + /** Contains compile-time configuration constants. */ + namespace config { + + /** The default backend to be selected for an end user. */ + static constexpr grb::Backend default_backend = _GRB_BACKEND; + + /** The cache line size, in bytes. */ + class CACHE_LINE_SIZE { + + private: + /** + * The cache line size in bytes. Update this value at compile time to + * reflect the target architecture. + */ + static constexpr size_t bytes = 64; + + public: + /** + * @return The cache line size in bytes. + * @see grb::config::CACHE_LINE_SIZE::bytes + */ + static constexpr size_t value() { + return bytes; + } + }; + + /** The SIMD size, in bytes. */ + class SIMD_SIZE { + + private: + /** + * The SIMD size, in bytes. Update this value at compile time to reflect + * the target architecture. + */ + static constexpr size_t bytes = 32; + + public: + /** + * @return The SIMD size in bytes. + * @see grb::config::SIMD_SIZE::bytes + */ + static constexpr size_t value() { + return bytes; + } + }; + + /** How many elements of a given data type fit into a SIMD register. */ + template< typename T > + class SIMD_BLOCKSIZE { + public: + /** + * Calculates the block size this operator should use. + * + * \warning This rounds down. If instances of T are too large, this could + * result in a zero value. See #value for a correction. + */ + static constexpr size_t unsafe_value() { + return SIMD_SIZE::value() / sizeof( T ); + } + + /** + * The maximum of one and the number of elements that fit into a single + * cache line. + */ + static constexpr size_t value() { + return unsafe_value() > 0 ? unsafe_value() : 1; + } + }; + + /** + * How many hardware threads the operating system exposes. + * + * \warning On contemporary x86-based hardware, the reported number by + * value() will include that of each hyper-thread. This number + * thus does not necessarily equal the number of cores available. + */ + class HARDWARE_THREADS { + public: + /** + * Returns the number of online hardware threads as reported by the OS. + * + * \warning This is a UNIX system call. + * + * @returns The number of hardware threads currently online. The return + * type is specified by the UNIX standard. + */ + static long value() { + return sysconf( _SC_NPROCESSORS_ONLN ); + } + }; + + /** Benchmarking defaults. */ + class BENCHMARKING { + public: + /** The default number of inner repititions. */ + static constexpr size_t inner() { + return 1; + } + + /** The default number of outer repititions. */ + static constexpr size_t outer() { + return 10; + } + }; + + /** Memory defaults. */ + class MEMORY { + public: + + /** The private L1 data cache size, in bytes. */ + static constexpr size_t l1_cache_size() { + return 32768; + } + + /** What is considered a lot of memory, in 2-log of bytes. */ + static constexpr size_t big_memory() { + return 31; + } // 2GB + + /** + * The memory speed under random accesses of 8-byte words. + * + * @returns The requested speed in MiB/s/process. + * + * @note The default value was measured on a two-socket Ivy Bridge node + * with 128GB quad-channel DDR4 memory at 1600 MHz per socket. + * + * @note In the intended use of these variables, it is the ratio between + * #stream_memspeed and #random_access_memspeed that matters. While + * untested, it is reasonable to think the ratios do not change too + * much between architectures. Nevertheless, for best results, these + * numbers are best set to benchmarked values on the deployment + * hardware. + */ + static constexpr double random_access_memspeed() { + return 147.298; + } + + /** + * The memory speed under a limited number of streams of uncached data. + * + * @returns The requested speed in MiB/s/process. + * + * @note The default value was measured on a two-socket Ivy Bridge node + * with 128GB quad-channel DDR4 memory at 1600 MHz per socket. + * + * @note In the intended use of these variables, it is the ratio between + * #stream_memspeed and #random_access_memspeed that matters. While + * untested, it is reasonable to think the ratios do not change too + * much between architectures. Nevertheless, for best results, these + * numbers are best set to benchmarked values on the deployment + * hardware. + */ + static constexpr double stream_memspeed() { + return 1931.264; + } + + /** + * Prints memory usage info to stdout, but only for big memory allocations. + * + * @returns true if and only if this function printed information to stdout. + */ + static bool report( const std::string prefix, const std::string action, const size_t size, const bool printNewline = true ) { +#ifdef _GRB_NO_STDIO + (void)prefix; + (void)action; + (void)size; + (void)printNewline; + return false; +#else + constexpr size_t big = + #ifdef _DEBUG + true; + #else + ( 1ul << big_memory() ); + #endif + if( size >= big ) { + std::cout << "Info: "; + std::cout << prefix << " "; + std::cout << action << " "; + if( sizeof( size_t ) * 8 > 40 && ( size >> 40 ) > 2 ) { + std::cout << ( size >> 40 ) << " TB of memory"; + } else if( sizeof( size_t ) * 8 > 30 && ( size >> 30 ) > 2 ) { + std::cout << ( size >> 30 ) << " GB of memory"; + } else if( sizeof( size_t ) * 8 > 20 && ( size >> 20 ) > 2 ) { + std::cout << ( size >> 20 ) << " MB of memory"; + } else if( sizeof( size_t ) * 8 > 10 && ( size >> 10 ) > 2 ) { + std::cout << ( size >> 10 ) << " kB of memory"; + } else { + std::cout << size << " bytes of memory"; + } + if( printNewline ) { + std::cout << ".\n"; + } + return true; + } + return false; +#endif + } + }; + + /** + * What data type should be used to store row indices. + * + * Some uses cases may require this to be set to size_t-- others may + * do with (much) smaller data types instead. + * + * \note The data type for indices of general arrays is not configurable. This + * set of implementations use size_t for those. + */ + typedef unsigned int RowIndexType; + + /** + * What data type should be used to store column indices. + * + * Some uses cases may require this to be set to size_t-- others may + * do with (much) smaller data types instead. + * + * \note The data type for indices of general arrays is not configurable. This + * set of implementations use size_t for those. + */ + typedef unsigned int ColIndexType; + + /** + * What data type should be used to refer to an array containing nonzeroes. + * + * Some uses cases may require this to be set to size_t-- others may + * do with (much) smaller data types instead. + * + * \note The data type for indices of general arrays is not configurable. This + * set of implementations use size_t for those. + */ + typedef size_t NonzeroIndexType; + + /** + * What data type should be used to store vector indices. + * + * Some uses cases may require this to be set to size_t-- others may + * do with (much) smaller data types instead. + * + * \note The data type for indices of general arrays is not configurable. This + * set of implementations use size_t for those. + */ + typedef unsigned int VectorIndexType; + + } // namespace config + +} // namespace grb + +#endif // end _H_GRB_CONFIG_BASE diff --git a/include/alp/base/exec.hpp b/include/alp/base/exec.hpp new file mode 100644 index 000000000..19e800e80 --- /dev/null +++ b/include/alp/base/exec.hpp @@ -0,0 +1,231 @@ + +/* + * Copyright 2021 Huawei Technologies Co., Ltd. + * + * 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. + */ + +/* + * @author A. N. Yzelman + * @date 17th of April, 2017 + */ + +#ifndef _H_GRB_EXEC_BASE +#define _H_GRB_EXEC_BASE + +#include +#include + +#include +#include +#ifndef _GRB_NO_STDIO +#include +#endif + +namespace grb { + + /** + * The various ways in which the #Launcher can be used + * to execute a GraphBLAS program. + * + * \warning An implementation may require different linker commands + * when using different modes. This is OK, since a call to + * the #Launcher is required to be quite different + * depending on which mode is used. The portability is in + * the GraphBLAS program being launched-- that one should + * never change depending on whichever mode it is used. + */ + enum EXEC_MODE { + + /** + * Automatic mode. The #Launcher can spawn user processes + * which will execute a given program. + */ + AUTOMATIC = 0, + + /** + * Manual mode. The user controls \a nprocs user processes + * which together should execute a given program, by, for + * example, using the #Launcher. + */ + MANUAL, + + /** + * When running from an MPI program. The user controls + * \a nprocs MPI programs, which, together, should execute + * a given GraphBLAS program. + */ + FROM_MPI + + }; + + /** + * Allows an auxiliary program to run any GraphBLAS program. Input data may be + * passed through a user-defined type. Output data will be retrieved via the + * same type. For implementations that support multiple user processes, the + * caller may explicitly set the process ID and total number of user processes. + * + * The intended use is to `just call' grb::exec which should, in its most + * trivial form, compile regardless of which backend is selected. + * + * @tparam mode Which #EXEC_MODE the Launcher should adhere to. + * @tparam implementation Which GraphBLAS implementation is to be used. + */ + template< enum EXEC_MODE mode, enum Backend implementation > + class Launcher { + + public : + + /** + * Constructs a new Launcher. This constructor is a collective + * call; all \a nprocs processes that form a single Launcher + * group must make a call to this constructor at roughly the + * same time. There is an implementation-defined time-out for + * the creation of a Launcher group. + * + * @param[in] process_id The user process ID of the calling process. + * The value must be larger or equal to 0. This + * value must be strictly smaller than \a nprocs. + * This value must be unique to the calling + * process within this collective call across + * \em all \a nprocs user processes. This number + * \em must be strictly smaller than \a nprocs. + * Optional: the default is 0. + * @param[in] nprocs The total number of user processes making a + * collective call to this function. Optional: the + * default is 1. + * @param[in] hostname The hostname of one of the user processes. + * Optional: the default is `localhost'. + * @param[in] port A free port number at \a hostname. This port + * will be used for TCP connections to \a hostname + * if and only if \a nprocs is larger than one. + * Optional: the default value is `0'. + * + * @throws invalid_argument If #nprocs is zero. + * @throws invalid_argument If #process_id is greater than or + * equal to \a nprocs. + * + * \note An implementation may define further constraints on + * the input arguments, such as, obviously, on \a hostname + * and \a port, but also on \a nprocs and, as a result, on + * \a process_id. + */ + Launcher( const size_t process_id = 0, // user process ID + const size_t nprocs = 1, // total number of user processes + const std::string hostname = "localhost", // one of the user process hostnames + const std::string port = "0" // a free port at hostname + ) { // standard does not specify any constrants on hostname and port + // so accept (and ignore) anything + (void)hostname; (void)port; + +#ifndef _GRB_NO_EXCEPTIONS + // sanity checks on process_id and nprocs + if( nprocs == 0 ) { throw std::invalid_argument( "Total number of user " + "processes must be " + "strictly larger than " + "zero." ); } + if( process_id >= nprocs ) { + throw std::invalid_argument( "Process ID must be strictly smaller than " + "total number of user processes." ); + } +#endif +} // namespace grb + +/** + * Executes the given GraphBLAS program. This function, depending on whether + * GraphBLAS is compiled in automatic or in manual mode, will either + * \em spawn the maximum number of available user processes or will connect + * exactly \a nprocs existing processes, respectively, to execute the given + * \a grb_program. + * + * This is a collective function call. + * + * @tparam T The type of the data to pass to the GraphBLAS program. + * @tparam U The type of the output data to pass back to the user. + * + * @param[in] grb_program User GraphBLAS program to be executed. + * @param[in] data_in Input data of user-defined type \a T. + * When in automatic mode, the data will only be + * available at user process 0 only. When in + * manual mode, the data will be available to + * this user process (with the below given + * \a process_id) only. + * @param[out] data_out Output data of user-defined type \a U. The output + * data should be available at user process with ID + * zero. + * @param[in] broadcast Whether the input should be broadcast from user + * process 0 to all other user processes. Optional; + * the default value is \a false. + * + * @return SUCCESS If the execution proceeded as intended. + * @return PANIC If an unrecoverable error was encountered while trying to + * execute the given GraphBLAS program. + * + * \warning An implementation can define further constraints on the validity + * of input arguments. The most obvious is that implementations + * supporting only one user process will not accept \a nprocs larger + * than 1. + * + * All aforementioned default values shall always be legal. + */ +template< typename T, typename U > +RC exec( void ( *grb_program )( const T &, U & ), // user GraphBLAS program + const T & data_in, + U & data_out, // input & output data + const bool broadcast = false ) const { + (void)grb_program; + (void)data_in; + (void)data_out; + (void)broadcast; + // stub implementation, should be overridden by specialised implementation, + // so return error code + return PANIC; +} + +/** + * Variable size version of the above function. + * + * @param[in] broadcast Whether the input should be broadcast from user + * process 0 to all other user processes. Optional; + * the default value is \a false. This will let user + * processes with ID larger than zero allocate + * \a in_size bytes of memory into which the data at + * process 0 will be copied. + * + * \todo more documentation + */ +template< typename U > +RC exec( void ( *grb_program )( const void *, const size_t, U & ), const void * data_in, const size_t in_size, U & data_out, const bool broadcast = false ) const { + (void)grb_program; + (void)data_in; + (void)in_size; + (void)data_out; + (void)broadcast; + return PANIC; +} + +/** + * Releases all GraphBLAS resources. After a call to this function, no + * GraphBLAS library functions may be called any longer. + * + * @return SUCCESS A call to this function may never fail. + */ +static RC finalize() { + return PANIC; +} +} +; // end class `Launcher' + +} // end namespace ``grb'' + +#endif // end _H_GRB_EXEC_BASE diff --git a/include/alp/base/init.hpp b/include/alp/base/init.hpp new file mode 100644 index 000000000..1c7efd9e8 --- /dev/null +++ b/include/alp/base/init.hpp @@ -0,0 +1,183 @@ + +/* + * Copyright 2021 Huawei Technologies Co., Ltd. + * + * 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. + */ + +/* + * @author A. N. Yzelman + * @date 24th of January, 2017 + */ + +#ifndef _H_GRB_INIT_BASE +#define _H_GRB_INIT_BASE + +#include + +#include "config.hpp" + +namespace grb { + + /** + * Initialises the calling user process. + * + * If the backend supports multiple user processes, the user can invoke this + * function with \a P equal to one or higher; if the backend supports only a + * single user process, then \a P must equal one. + * The value for the user process ID \a s must be larger or equal to zero and + * must be strictly smaller than \a P. If \a P > 1, each user process must + * call this function collectively, each user process should pass the same + * value for \a P, and each user process should pass a unique value for \a s + * amongst all \a P collective calls made. + * + * An implementation may define that additional data is required for a call to + * this function to complete successfully. Such data may be passed via the + * final argument to this function, \a implementation_data. + * + * If the implementation does not support multiple user processes, then a + * value for \a implementation_data shall not be required. In parcticular, a + * call to this function with an empty parameter list shall then be legal + * and infer the following default arguments: zero for \a s, one for \a P, + * and \a NULL for \a implementation_data. When such an implementation is + * requested to initialise multiple user processes, the grb::UNSUPPORTED + * error code shall be returned. + * + * A call to this function must be matched with a call to grb::finalize(). + * After a successful call to this function, a new call to grb::init() without + * first calling grb::finalize() shall incur undefined behaviour. The + * construction of GraphBLAS containers without a preceding successful call + * to grb::init() will result in invalid GraphBLAS objects. Any valid + * GraphBLAS containers will become invalid after a call to grb::finalize(). + * Any use of GraphBLAS functions on invalid containers will result in + * undefined behaviour. + * + * @tparam backend Which GraphBLAS backend this call to init initialises. + * + * @param[in] s The ID of this user process. + * @param[in] P The total number of user processes. + * @param[in] implementation_data Any implementation-defined data structure + * required for successful completion of this + * call. + * + * \note For a pure MPI implementation, for instance, \a implementation_data + * may be a pointer to the MPI communicator corresponding to these user + * processes. + * + * \note The implementations based on PlatformBSP require direct passing of + * the \a bsp_t corresponding to the BSP context of the user processes; + * this is legal since the PlatformBSP specification defines the + * \a bsp_t type as a void pointer. + * + * @return SUCCESS If the initialisation was successful. + * @return UNSUPPORTED When the implementation does not support multiple + * user processes (\a P larger than 1). After a call to + * this function exits with this error code the library + * state shall be as though the call never were made. + * @return PANIC If this function fails, the state of this GraphBLAS + * implementation becomes undefined. + * + * \note There is no argument checking. If \a s is larger or equal to \a P, + * undefined behaviour occurs. If \a implementation_data was invalid + * or corrupted, undefined behaviour occurs. + * + * \par Performance semantics + * None. Implementations are encouraged to specify the complexity of + * their implementation of this function in terms of \a P. + * + * \note Compared to the GraphBLAS C specification, this function lacks a + * choice whether to execute in `blocking' or `non-blocking' mode. + * All functions in the Huawei GraphBLAS are blocking. A choice + * between blocking and non-blocking execution may be added later. + * \note Note that a blocking mode is a valid implementation of a non- + * blocking mode, as specified in the GraphBLAS C API. Therefore + * this specification will still yield a valid implementation of + * the C API when properly wrapped. + * \note Non-blocking mode with clear performance semantics are possible via + * carefully designed algorithmic skeletons. This is future work. + * \note This specification allows for grb::init() to be called multiple + * times from the same process and the same thread, as long as all the + * above requirements are met at each call. The parameters \a s and + * \a P (and \a implementation_data) may differ each time. + * \note This is an extension of the GraphBLAS C API, whom only allow a + * single initialisation and a single matching finalisation. + * \note The GraphBLAS C API does not have the notion of user processes. We + * believe this notion is necessary to properly integrate into parallel + * frameworks, and also to affect proper and efficient parallel I/O. + */ + template< enum Backend backend = config::default_backend > + RC init( const size_t s, const size_t P, void * const implementation_data ) { + (void)s; + (void)P; + (void)implementation_data; + return PANIC; + } + + /** + * Implementations must ensure that initialisation without explicitly given + * values regarding user processes etc. should still result in a successful + * initialisation in all cases except where it cannot initialise due to + * external factors. + * A call to this function could, for instance, reduce to a full grb::init() + * while using the default parameters 0 for \a s, 1 for \a P, and \a NULL for + * \a implementation_data: + * \code + * return init< backend >( 0, 1, NULL ); + * \endcode + * + * @tparam backend The backend implementation to initialise. + * + * @return SUCCESS If the initialisation was successful. + * @return PANIC If this function fails, the state of this GraphBLAS + * implementation becomes undefined. + */ + template< enum Backend backend = config::default_backend > + RC init() { + return grb::init< backend >( 0, 1, NULL ); + } + + /** + * Finalises a graphBLAS context opened by the last call to grb::init(). + * + * This function must be called collectively and must follow a call to + * grb::init(). After successful execution of this function, a new call + * to grb::init() may be made. + * After a call to this function, any graphBLAS objects that remain in scope + * are invalid. The only graphBLAS functions on invalid containers which + * shall \em not incur undefined behaviour are their destructors. + * + * \warning Invalid GraphBLAS containers will remain invalid no matter if a + * next call to grb::init() is made. + * + * @tparam backend Which GraphBLAS backend this call to init initialises. + * + * @return SUCCESS If the initialisation was successful. + * @return PANIC If this function fails, the state of the GraphBLAS + * implementation becomes undefined. This means none of its + * functions should be called during the remainder program + * execution; in particular this means a new call to + * grb::init() will not remedy the situaiton. + * + * \par Performance semantics + * None. Implementations are encouraged to specify the complexity of + * their implementation of this function in terms of the parameter + * \a P the matching call to grb::init() was called with. + */ + template< enum Backend backend = config::default_backend > + RC finalize() { + return PANIC; + } + +} // namespace grb + +#endif // end _H_GRB_INIT_BASE diff --git a/include/alp/base/internalops.hpp b/include/alp/base/internalops.hpp new file mode 100644 index 000000000..5c236de86 --- /dev/null +++ b/include/alp/base/internalops.hpp @@ -0,0 +1,3180 @@ + +/* + * Copyright 2021 Huawei Technologies Co., Ltd. + * + * 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. + */ + +/* + * @author A. N. Yzelman + * @date 8th of August, 2016 + */ + +#ifndef _H_GRB_INTERNAL_OPERATORS_BASE +#define _H_GRB_INTERNAL_OPERATORS_BASE + +#include + +#include +#include + +#include +#include + +#include "config.hpp" + + +namespace grb { + + namespace operators { + + /** Core implementations of the standard operators in #grb::operators. */ + namespace internal { + + /** + * Standard argmin operator. + * + * Takes std::pair< index, value > domains only. + * + * Given two pairs (i1,v1), (i2,v2) + * - returns (i1,v1) if v1 + class argmin { + + static_assert( std::is_integral< IType >::value, + "Argmin operator may only be constructed using integral index " + "types." ); + + public: + /** Alias to the left-hand input data type. */ + typedef std::pair< IType, VType > left_type; + + /** Alias to the right-hand input data type. */ + typedef std::pair< IType, VType > right_type; + + /** Alias to the output data type. */ + typedef std::pair< IType, VType > result_type; + + /** Whether this operator has an inplace foldl. */ + static constexpr bool has_foldl = true; + + /** Whether this operator has an inplace foldr. */ + static constexpr bool has_foldr = true; + + /** + * Whether this operator is \em mathematically associative; that is, + * associative when assuming equivalent data types for \a IN1, \a IN2, + * and \a OUT, as well as assuming exact arithmetic, no overflows, etc. + */ + static constexpr bool is_associative = true; + + /** + * Whether this operator is \em mathematically commutative; that is, + * commutative when assuming equivalent data types for \a IN1, \a IN2, + * and \a OUT, as well as assuming exact arithmetic, no overflows, etc. + */ + static constexpr bool is_commutative = true; + + /** + * Out-of-place application of the operator. + * + * @param[in] a The left-hand side input. Must be pre-allocated and initialised. + * @param[in] b The right-hand side input. Must be pre-allocated and initialised. + * @param[out] c The output. Must be pre-allocated. + */ + static void apply( const left_type * __restrict__ const a, const right_type * __restrict__ const b, result_type * __restrict__ const c ) { + if( a->second < b->second ) { + c->first = a->first; + c->second = a->second; + } + } + + /** + * In-place left-to-right folding. + * + * @param[in] a Pointer to the left-hand side input data. + * @param[in,out] c Pointer to the right-hand side input data. This also + * dubs as the output memory area. + */ + static void foldr( const left_type * __restrict__ const a, result_type * __restrict__ const c ) { + if( a->second < c->second ) { + c->first = a->first; + c->second = a->second; + } + } + + /** + * In-place right-to-left folding. + * + * @param[in,out] c Pointer to the left-hand side input data. This also + * dubs as the output memory area. + * @param[in] b Pointer to the right-hand side input data. + */ + static void foldl( result_type * __restrict__ const c, const right_type * __restrict__ const b ) { + if( b->second <= c->second ) { + c->first = b->first; + c->second = b->second; + } + } + }; + + /** + * Standard argmax operator. + * + * Takes std::pair< index, value > domains only. + * + * Given two pairs (i1,v1), (i2,v2) + * - returns (i1,v1) if v1>v2, OR + * - returns (i2,v2) otherwise. + */ + template< typename IType, typename VType > + class argmax { + + static_assert( std::is_integral< IType >::value, + "Argmin operator may only be constructed using integral index " + "types." ); + + public: + /** Alias to the left-hand input data type. */ + typedef std::pair< IType, VType > left_type; + + /** Alias to the right-hand input data type. */ + typedef std::pair< IType, VType > right_type; + + /** Alias to the output data type. */ + typedef std::pair< IType, VType > result_type; + + /** Whether this operator has an inplace foldl. */ + static constexpr bool has_foldl = true; + + /** Whether this operator has an inplace foldr. */ + static constexpr bool has_foldr = true; + + /** + * Whether this operator is \em mathematically associative; that is, + * associative when assuming equivalent data types for \a IN1, \a IN2, + * and \a OUT, as well as assuming exact arithmetic, no overflows, etc. + */ + static constexpr bool is_associative = true; + + /** + * Whether this operator is \em mathematically commutative; that is, + * commutative when assuming equivalent data types for \a IN1, \a IN2, + * and \a OUT, as well as assuming exact arithmetic, no overflows, etc. + */ + static constexpr bool is_commutative = true; + + /** + * Out-of-place application of the operator. + * + * @param[in] a The left-hand side input. Must be pre-allocated and initialised. + * @param[in] b The right-hand side input. Must be pre-allocated and initialised. + * @param[out] c The output. Must be pre-allocated. + */ + static void apply( const left_type * __restrict__ const a, const right_type * __restrict__ const b, result_type * __restrict__ const c ) { + if( a->second > b->second ) { + c->first = a->first; + c->second = a->second; + } + } + + /** + * In-place left-to-right folding. + * + * @param[in] a Pointer to the left-hand side input data. + * @param[in,out] c Pointer to the right-hand side input data. This also + * dubs as the output memory area. + */ + static void foldr( const left_type * __restrict__ const a, result_type * __restrict__ const c ) { + if( a->second > c->second ) { + c->first = a->first; + c->second = a->second; + } + } + + /** + * In-place right-to-left folding. + * + * @param[in,out] c Pointer to the left-hand side input data. This also + * dubs as the output memory area. + * @param[in] b Pointer to the right-hand side input data. + */ + static void foldl( result_type * __restrict__ const c, const right_type * __restrict__ const b ) { + if( b->second >= c->second ) { + c->first = b->first; + c->second = b->second; + } + } + }; + + /** + * Standard left-hand side assignment operator. + * + * Takes binary input, but ignores the right-hand side input and simply + * assigns the left-hand side input to the output variable. + * + * Assumes native availability of = on the given data types, or assumes + * the relevant operators are properly overloaded. + * + * Assumes a binary operator defined using the =-operator in the following + * way, is \em associative: + * \code + * void left_assign( const IN1 x, const IN2 y, OUT &out ) { + * (void)y; + * out = x; + * } + * \endcode + * + * Non-standard or non-matching data types, or non-standard (overloaded) = + * operators should be used with caution and may necessitate an explicit + * definition as a GraphBLAS operator with the #has_foldl, #has_foldr, and + * the other fields, set as required. + * + * @tparam IN1 The left-hand input data type. + * @tparam IN2 The right-hand input data type. + * @tparam OUT The output data type. + */ + template< typename IN1, typename IN2, typename OUT, enum Backend implementation = config::default_backend > + class left_assign { + + public: + /** Alias to the left-hand input data type. */ + typedef IN1 left_type; + + /** Alias to the right-hand input data type. */ + typedef IN2 right_type; + + /** Alias to the output data type. */ + typedef OUT result_type; + + /** Whether this operator has an inplace foldl. */ + static constexpr bool has_foldl = true; + + /** Whether this operator has an inplace foldr. */ + static constexpr bool has_foldr = true; + + /** + * Whether this operator is \em mathematically associative; that is, + * associative when assuming equivalent data types for \a IN1, \a IN2, + * and \a OUT, as well as assuming exact arithmetic, no overflows, etc. + */ + static constexpr bool is_associative = true; + + /** + * Whether this operator is \em mathematically commutative; that is, + * commutative when assuming equivalent data types for \a IN1, \a IN2, + * and \a OUT, as well as assuming exact arithmetic, no overflows, etc. + */ + static constexpr bool is_commutative = false; + + /** + * Out-of-place application of the addition c = a. + * + * @param[in] a The left-hand side input. Must be pre-allocated and initialised. + * @param[in] b The right-hand side input. Must be pre-allocated and initialised. + * @param[out] c The output. Must be pre-allocated. + */ + static void apply( const left_type * __restrict__ const a, const right_type * __restrict__ const b, result_type * __restrict__ const c ) { + (void)b; + *c = static_cast< result_type >( *a ); + } + + /** + * In-place left-to-right folding. + * + * @param[in] a Pointer to the left-hand side input data. + * @param[in,out] c Pointer to the right-hand side input data. This also + * dubs as the output memory area. + */ + static void foldr( const left_type * __restrict__ const a, result_type * __restrict__ const c ) { + *c = static_cast< result_type >( *a ); + } + + /** + * In-place right-to-left folding. + * + * @param[in,out] c Pointer to the left-hand side input data. This also + * dubs as the output memory area. + * @param[in] b Pointer to the right-hand side input data. + */ + static void foldl( result_type * __restrict__ const c, const right_type * __restrict__ const b ) { + (void)b; + (void)c; + } + }; + + /** + * Standard right-hand side assignment operator. + * + * Takes binary input, but ignores the right-hand side input and simply + * assigns the left-hand side input to the output variable. + * + * Assumes native availability of = on the given data types, or assumes + * the relevant operators are properly overloaded. + * + * Assumes a binary operator defined using the =-operator in the following + * way, is \em associative: + * \code + * void right_assign( const IN1 x, const IN2 y, OUT &out ) { + * (void)x; + * out = y; + * } + * \endcode + * + * Non-standard or non-matching data types, or non-standard (overloaded) = + * operators should be used with caution and may necessitate an explicit + * definition as a GraphBLAS operator with the #has_foldl, #has_foldr, and + * the other fields, set as required. + * + * @tparam IN1 The left-hand input data type. + * @tparam IN2 The right-hand input data type. + * @tparam OUT The output data type. + */ + template< typename IN1, typename IN2, typename OUT, enum Backend implementation = config::default_backend > + class right_assign { + + public: + /** Alias to the left-hand input data type. */ + typedef IN1 left_type; + + /** Alias to the right-hand input data type. */ + typedef IN2 right_type; + + /** Alias to the output data type. */ + typedef OUT result_type; + + /** Whether this operator has an inplace foldl. */ + static constexpr bool has_foldl = true; + + /** Whether this operator has an inplace foldr. */ + static constexpr bool has_foldr = true; + + /** + * Whether this operator is \em mathematically associative; that is, + * associative when assuming equivalent data types for \a IN1, \a IN2, + * and \a OUT, as well as assuming exact arithmetic, no overflows, etc. + */ + static constexpr bool is_associative = true; + + /** + * Whether this operator is \em mathematically commutative; that is, + * commutative when assuming equivalent data types for \a IN1, \a IN2, + * and \a OUT, as well as assuming exact arithmetic, no overflows, etc. + */ + static constexpr bool is_commutative = false; + + /** + * Out-of-place application of the addition c = a. + * + * @param[in] a The left-hand side input. Must be pre-allocated and initialised. + * @param[in] b The right-hand side input. Must be pre-allocated and initialised. + * @param[out] c The output. Must be pre-allocated. + */ + static void apply( const left_type * __restrict__ const a, const right_type * __restrict__ const b, result_type * __restrict__ const c ) { + (void)a; + *c = *b; + } + + /** + * In-place left-to-right folding. + * + * @param[in] a Pointer to the left-hand side input data. + * @param[in,out] c Pointer to the right-hand side input data. This also + * dubs as the output memory area. + */ + static void foldr( const left_type * __restrict__ const a, result_type * __restrict__ const c ) { + (void)a; + (void)c; + } + + /** + * In-place right-to-left folding. + * + * @param[in,out] c Pointer to the left-hand side input data. This also + * dubs as the output memory area. + * @param[in] b Pointer to the right-hand side input data. + */ + static void foldl( result_type * __restrict__ const c, const right_type * __restrict__ const b ) { + *c = static_cast< result_type >( *b ); + } + }; + + /** + * Left-sided operator that combines an indicator and an identity function + * as follows: + * + * \f$ z = x \odot y = x \text{ if } y \text{evaluates true}. \f$ + * + * If \f$ x \f$ does not evaluate true the operator shall have no effect. + */ + template< typename D1, typename D2, typename D3, enum Backend implementation = config::default_backend > + class left_assign_if { + + public: + /** Alias to the left-hand input data type. */ + typedef D1 left_type; + + /** Alias to the right-hand input data type. */ + typedef D2 right_type; + + /** Alias to the output data type. */ + typedef D3 result_type; + + /** Whether this operator has an inplace foldl. */ + static constexpr bool has_foldl = true; + + /** Whether this operator has an inplace foldr. */ + static constexpr bool has_foldr = true; + + /** + * Whether this operator is \em mathematically associative; that is, + * associative when assuming equivalent data types for \a IN1, \a IN2, + * and \a OUT, as well as assuming exact arithmetic, no overflows, etc. + */ + static constexpr bool is_associative = true; + + /** + * Whether this operator is \em mathematically commutative; that is, + * commutative when assuming equivalent data types for \a IN1, \a IN2, + * and \a OUT, as well as assuming exact arithmetic, no overflows, etc. + */ + static constexpr bool is_commutative = true; + + /** + * Out-of-place application of the addition c = a. + * + * @param[in] a The left-hand side input. Must be pre-allocated and initialised. + * @param[in] b The right-hand side input. Must be pre-allocated and initialised. + * @param[out] c The output. Must be pre-allocated. + */ + static void apply( const D1 * __restrict__ const a, const D2 * __restrict__ const b, D3 * __restrict__ const c ) { + if( static_cast< const bool >( *b ) ) { + *c = *a; + } + } + + /** + * In-place left-to-right folding. + * + * @param[in] a Pointer to the left-hand side input data. + * @param[in,out] c Pointer to the right-hand side input data. This also + * dubs as the output memory area. + */ + static void foldr( const D1 * __restrict__ const a, D3 * __restrict__ const c ) { + if( static_cast< const bool >( *c ) ) { + *c = static_cast< D3 >( *a ); + } + } + + /** + * In-place right-to-left folding. + * + * @param[in,out] c Pointer to the left-hand side input data. This also + * dubs as the output memory area. + * @param[in] b Pointer to the right-hand side input data. + */ + static void foldl( D3 * __restrict__ const c, const D2 * __restrict__ const b ) { + if( static_cast< bool >( *b ) ) { + *c = static_cast< D3 >( static_cast< D1 >( *c ) ); + } + } + }; + + /** + * Right-sided operator that combines an indicator and an identity function + * as follows: + * + * \f$ z = x \odot y = y \text{ if } x \text{evaluates true}. \f$ + * + * If \f$ x \f$ does not evaluate true the operator shall have no effect. + */ + template< typename D1, typename D2, typename D3, enum Backend implementation = config::default_backend > + class right_assign_if { + + public: + /** Alias to the left-hand input data type. */ + typedef D1 left_type; + + /** Alias to the right-hand input data type. */ + typedef D2 right_type; + + /** Alias to the output data type. */ + typedef D3 result_type; + + /** Whether this operator has an inplace foldl. */ + static constexpr bool has_foldl = true; + + /** Whether this operator has an inplace foldr. */ + static constexpr bool has_foldr = true; + + /** + * Whether this operator is \em mathematically associative; that is, + * associative when assuming equivalent data types for \a IN1, \a IN2, + * and \a OUT, as well as assuming exact arithmetic, no overflows, etc. + */ + static constexpr bool is_associative = true; + + /** + * Whether this operator is \em mathematically commutative; that is, + * commutative when assuming equivalent data types for \a IN1, \a IN2, + * and \a OUT, as well as assuming exact arithmetic, no overflows, etc. + */ + static constexpr bool is_commutative = true; + + /** + * Out-of-place application of the addition c = a. + * + * @param[in] a The left-hand side input. Must be pre-allocated and initialised. + * @param[in] b The right-hand side input. Must be pre-allocated and initialised. + * @param[out] c The output. Must be pre-allocated. + */ + static void apply( const D1 * __restrict__ const a, const D2 * __restrict__ const b, D3 * __restrict__ const c ) { + if( static_cast< const bool >( *a ) ) { + *c = *b; + } + } + + /** + * In-place left-to-right folding. + * + * @param[in] a Pointer to the left-hand side input data. + * @param[in,out] c Pointer to the right-hand side input data. This also + * dubs as the output memory area. + */ + static void foldr( const D1 * __restrict__ const a, D3 * __restrict__ const c ) { + if( static_cast< const bool >( *a ) ) { + *c = static_cast< D3 >( static_cast< D2 >( *c ) ); + } + } + + /** + * In-place right-to-left folding. + * + * @param[in,out] c Pointer to the left-hand side input data. This also + * dubs as the output memory area. + * @param[in] b Pointer to the right-hand side input data. + */ + static void foldl( D3 * __restrict__ const c, const D2 * __restrict__ const b ) { + if( static_cast< bool >( *c ) ) { + *c = static_cast< D3 >( *b ); + } + } + }; + + /** + * Standard additive operator. + * + * Assumes native availability of + on the given data types or assumes that + * the relevant operators are properly overloaded. + * + * Assumes that the + operator is associative \em and commutative when + * assuming perfect arithmetic and equal data types for \a IN1, \a IN2, and + * \a OUT. + * + * Non-standard or non-matching data types or non-standard (overloaded) + + * operators, should therefore be used with caution and may necessitate an + * explicit definition as a GraphBLAS operator with the #is_associative and + * #is_commutative fields, and others, set as required. + * + * @tparam IN1 The left-hand input data type. + * @tparam IN2 The right-hand input data type. + * @tparam OUT The output data type. + */ + // [Example Base Operator Implementation] + template< typename IN1, typename IN2, typename OUT, enum Backend implementation = config::default_backend > + class add { + + public: + /** Alias to the left-hand input data type. */ + typedef IN1 left_type; + + /** Alias to the right-hand input data type. */ + typedef IN2 right_type; + + /** Alias to the output data type. */ + typedef OUT result_type; + + /** Whether this operator has an inplace foldl. */ + static constexpr bool has_foldl = true; + + /** Whether this operator has an inplace foldr. */ + static constexpr bool has_foldr = true; + + /** + * Whether this operator is \em mathematically associative; that is, + * associative when assuming equivalent data types for \a IN1, \a IN2, + * and \a OUT, as well as assuming exact arithmetic, no overflows, etc. + */ + static constexpr bool is_associative = true; + + /** + * Whether this operator is \em mathematically commutative; that is, + * commutative when assuming equivalent data types for \a IN1, \a IN2, + * and \a OUT, as well as assuming exact arithmetic, no overflows, etc. + */ + static constexpr bool is_commutative = true; + + /** + * Out-of-place application of the addition c = a + b. + * + * @param[in] a The left-hand side input. Must be pre-allocated and initialised. + * @param[in] b The right-hand side input. Must be pre-allocated and initialised. + * @param[out] c The output. Must be pre-allocated. + * + * \warning Passing invalid pointers will result in UB. + */ + static void apply( const left_type * __restrict__ const a, + const right_type * __restrict__ const b, + result_type * __restrict__ const c + ) { + GRB_UTIL_IGNORE_MAYBE_UNINITIALIZED // this is a (too) broad suppression-- + // see internal issue 306 for rationale + *c = *a + *b; + GRB_UTIL_RESTORE_WARNINGS + } + + /** + * In-place left-to-right folding. + * + * @param[in] a Pointer to the left-hand side input data. + * @param[in,out] c Pointer to the right-hand side input data. This also + * dubs as the output memory area. + * + * \warning Passing invalid pointers will result in UB. + */ + static void foldr( const left_type * __restrict__ const a, result_type * __restrict__ const c ) { + *c += *a; + } + + /** + * In-place right-to-left folding. + * + * @param[in,out] c Pointer to the left-hand side input data. This also + * dubs as the output memory area. + * @param[in] b Pointer to the right-hand side input data. + * + * \warning Passing invalid pointers will result in UB. + */ + static void foldl( result_type * __restrict__ const c, const right_type * __restrict__ const b ) { + *c += *b; + } + }; + // [Example Base Operator Implementation] + + /** + * Standard multiplicative operator. + * + * Assumes native availability * on the given data types, or assumes + * the relevant operators are properly overloaded. + * + * Assumes that the * operator is associative \em and commutative when + * assuming perfect arithmetic and equal data types for \a IN1, \a IN2, and + * \a OUT. + * + * Non-standard or non-matching data types or non-standard (overloaded) * + * operators, should therefore be used with caution and may necessitate an + * explicit definition as a GraphBLAS operator with the #is_associative and + * #is_commutative fields, and others, set as required. + * + * @tparam IN1 The left-hand input data type. + * @tparam IN2 The right-hand input data type. + * @tparam OUT The output data type. + */ + template< + typename IN1, typename IN2, typename OUT, + enum Backend implementation = config::default_backend + > + class mul { + + public: + + /** Alias to the left-hand input data type. */ + typedef IN1 left_type; + + /** Alias to the right-hand input data type. */ + typedef IN2 right_type; + + /** Alias to the output data type. */ + typedef OUT result_type; + + /** Whether this operator has an in-place foldl. */ + static constexpr bool has_foldl = true; + + /** Whether this operator has an in-place foldr. */ + static constexpr bool has_foldr = true; + + /** + * Whether this operator is \em mathematically associative; that is, + * associative when assuming equivalent data types for \a IN1, \a IN2, + * and \a OUT, as well as assuming exact arithmetic, no overflows, etc. + */ + static constexpr bool is_associative = true; + + /** + * Whether this operator is \em mathematically commutative; that is, + * commutative when assuming equivalent data types for \a IN1, \a IN2, + * and \a OUT, as well as assuming exact arithmetic, no overflows, etc. + */ + static constexpr bool is_commutative = true; + + /** + * Out-of-place application of the multiplication c = a * b. + * + * @param[in] a Pointer to the left-hand side input. Must be initialised. + * @param[in] b Pointer to the right-hand side input. Must be initialised. + * @param[out] c Pointer to where to compute the output. + * + * \warning All pointers must be valid or UB occurs. + */ + static void apply( + const left_type * __restrict__ const a, + const right_type * __restrict__ const b, + result_type * __restrict__ const c + ) { + GRB_UTIL_IGNORE_MAYBE_UNINITIALIZED // this is a (too) broad suppression-- + // see internal issue 306 for rationale + *c = *a * *b; + GRB_UTIL_RESTORE_WARNINGS + } + + /** + * In-place left-to-right folding. + * + * @param[in] a Pointer to the left-hand side input data. + * @param[in,out] c Pointer to the right-hand side input data. This also + * dubs as the output memory area. + */ + static void foldr( const left_type * __restrict__ const a, result_type * __restrict__ const c ) { + *c *= *a; + } + + /** + * In-place right-to-left folding. + * + * @param[in,out] c Pointer to the left-hand side input data. This also + * dubs as the output memory area. + * @param[in] b Pointer to the right-hand side input data. + */ + static void foldl( result_type * __restrict__ const c, const right_type * __restrict__ const b ) { + *c *= *b; + } + }; + + /** + * Standard max operator. + * + * Assumes native availability of < on the given data types, or assumes + * the relevant operators are properly overloaded. + * + * Non-standard or non-matching data types, or non-standard (overloaded) < + * operators, should be used with caution and may necessitate an explicit + * definition as a GraphBLAS operator with the #is_associative and + * #is_commutative fields, and others, set as required. + * + * @tparam IN1 The left-hand input data type. + * @tparam IN2 The right-hand input data type. + * @tparam OUT The output data type. + */ + template< typename IN1, typename IN2, typename OUT, enum Backend implementation = config::default_backend > + class max { + public: + /** Alias to the left-hand input data type. */ + typedef IN1 left_type; + + /** Alias to the right-hand input data type. */ + typedef IN2 right_type; + + /** Alias to the output data type. */ + typedef OUT result_type; + + /** Whether this operator has an in-place foldl. */ + static constexpr bool has_foldl = true; + + /** Whether this operator has an in-place foldr. */ + static constexpr bool has_foldr = true; + + /** + * Whether this operator is \em mathematically associative; that is, + * associative when assuming equivalent data types for \a IN1, \a IN2, + * and \a OUT, as well as assuming exact arithmetic, no overflows, etc. + */ + static constexpr bool is_associative = true; + + /** + * Whether this operator is \em mathematically commutative; that is, + * commutative when assuming equivalent data types for \a IN1, \a IN2, + * and \a OUT, as well as assuming exact arithmetic, no overflows, etc. + */ + static constexpr bool is_commutative = true; + + /** + * Out-of-place application of the max operator. + * + * @param[in] a The left-hand side input. Must be pre-allocated and initialised. + * @param[in] b The right-hand side input. Must be pre-allocated and initialised. + * @param[out] c The output. Must be pre-allocated. + * + * At the end of the operation, \f$ c = \max\{a,b\} \f$. + */ + static void apply( const left_type * __restrict__ const a, const right_type * __restrict__ const b, result_type * __restrict__ const c ) { + if( *a < *b ) { + *c = static_cast< OUT >( *b ); + } else { + *c = static_cast< OUT >( *a ); + } + } + + /** + * In-place left-to-right folding. + * + * @param[in] a Pointer to the left-hand side input data. + * @param[in,out] c Pointer to the right-hand side input data. This also + * dubs as the output memory area. + */ + static void foldr( const left_type * __restrict__ const a, result_type * __restrict__ const c ) { + if( *a > *c ) { + *c = *a; + } + } + + /** + * In-place right-to-left folding. + * + * @param[in,out] c Pointer to the left-hand side input data. This also + * dubs as the output memory area. + * @param[in] b Pointer to the right-hand side input data. + */ + static void foldl( result_type * __restrict__ const c, const right_type * __restrict__ const b ) { + if( *b > *c ) { + *c = *b; + } + } + }; + + /** + * Standard min operator. + * + * Assumes native availability of > on the given data types, or assumes + * the relevant operators are properly overloaded. + * + * Non-standard or non-matching data types, or non-standard (overloaded) > + * operators, should be used with caution and may necessitate an explicit + * definition as a GraphBLAS operator with the #is_associative and + * #is_commutative fields, and others, set as required. + * + * @tparam IN1 The left-hand input data type. + * @tparam IN2 The right-hand input data type. + * @tparam OUT The output data type. + */ + template< typename IN1, typename IN2, typename OUT, enum Backend implementation = config::default_backend > + class min { + public: + /** Alias to the left-hand input data type. */ + typedef IN1 left_type; + + /** Alias to the right-hand input data type. */ + typedef IN2 right_type; + + /** Alias to the output data type. */ + typedef OUT result_type; + + /** Whether this operator has an in-place foldl. */ + static constexpr bool has_foldl = true; + + /** Whether this operator has an in-place foldr. */ + static constexpr bool has_foldr = true; + + /** + * Whether this operator is \em mathematically associative; that is, + * associative when assuming equivalent data types for \a IN1, \a IN2, + * and \a OUT, as well as assuming exact arithmetic, no overflows, etc. + */ + static constexpr bool is_associative = true; + + /** + * Whether this operator is \em mathematically commutative; that is, + * commutative when assuming equivalent data types for \a IN1, \a IN2, + * and \a OUT, as well as assuming exact arithmetic, no overflows, etc. + */ + static constexpr bool is_commutative = true; + + /** + * Out-of-place application of the min operator. + * + * @param[in] a The left-hand side input. Must be pre-allocated and initialised. + * @param[in] b The right-hand side input. Must be pre-allocated and initialised. + * @param[out] c The output. Must be pre-allocated. + * + * At the end of the operation, \f$ c = \min\{a,b\} \f$. + */ + static void apply( const left_type * __restrict__ const a, const right_type * __restrict__ const b, result_type * __restrict__ const c ) { + if( *a > *b ) { + *c = static_cast< OUT >( *b ); + } else { + *c = static_cast< OUT >( *a ); + } + } + + /** + * In-place left-to-right folding. + * + * @param[in] a Pointer to the left-hand side input data. + * @param[in,out] c Pointer to the right-hand side input data. This also + * dubs as the output memory area. + */ + static void foldr( const left_type * __restrict__ const a, result_type * __restrict__ const c ) { + if( *a < *c ) { + *c = *a; + } + } + + /** + * In-place right-to-left folding. + * + * @param[in,out] c Pointer to the left-hand side input data. This also + * dubs as the output memory area. + * @param[in] b Pointer to the right-hand side input data. + */ + static void foldl( result_type * __restrict__ const c, const right_type * __restrict__ const b ) { + if( *b < *c ) { + *c = *b; + } + } + }; + + /** \todo add documentation */ + template< typename IN1, typename IN2, typename OUT, enum Backend implementation = config::default_backend > + class substract { + public: + /** Alias to the left-hand input data type. */ + typedef IN1 left_type; + + /** Alias to the right-hand input data type. */ + typedef IN2 right_type; + + /** Alias to the output data type. */ + typedef OUT result_type; + + /** Whether this operator has an in-place foldl. */ + static constexpr bool has_foldl = true; + + /** Whether this operator has an in-place foldr. */ + static constexpr bool has_foldr = true; + + /** + * Whether this operator is \em mathematically associative; that is, + * associative when assuming equivalent data types for \a IN1, \a IN2, + * and \a OUT, as well as assuming exact arithmetic, no overflows, etc. + */ + static constexpr bool is_associative = false; + + /** + * Whether this operator is \em mathematically commutative; that is, + * commutative when assuming equivalent data types for \a IN1, \a IN2, + * and \a OUT, as well as assuming exact arithmetic, no overflows, etc. + */ + static constexpr bool is_commutative = false; + + /** + * Out-of-place application of this operator. + * + * @param[in] a The left-hand side input. Must be pre-allocated and initialised. + * @param[in] b The right-hand side input. Must be pre-allocated and initialised. + * @param[out] c The output. Must be pre-allocated. + * + * At the end of the operation, \f$ c = \min\{a,b\} \f$. + */ + static void apply( const left_type * __restrict__ const a, const right_type * __restrict__ const b, result_type * __restrict__ const c ) { + *c = *a - *b; + } + + /** + * In-place left-to-right folding. + * + * @param[in] a Pointer to the left-hand side input data. + * @param[in,out] c Pointer to the right-hand side input data. This also + * dubs as the output memory area. + */ + static void foldr( const left_type * __restrict__ const a, result_type * __restrict__ const c ) { + *c = *a - *c; + } + + /** + * In-place right-to-left folding. + * + * @param[in,out] c Pointer to the left-hand side input data. This also + * dubs as the output memory area. + * @param[in] b Pointer to the right-hand side input data. + */ + static void foldl( result_type * __restrict__ const c, const right_type * __restrict__ const b ) { + *c -= *b; + } + }; + + /** \todo add documentation */ + template< typename IN1, typename IN2, typename OUT, enum Backend implementation = config::default_backend > + class divide { + public: + /** Alias to the left-hand input data type. */ + typedef IN1 left_type; + + /** Alias to the right-hand input data type. */ + typedef IN2 right_type; + + /** Alias to the output data type. */ + typedef OUT result_type; + + /** Whether this operator has an in-place foldl. */ + static constexpr bool has_foldl = true; + + /** Whether this operator has an in-place foldr. */ + static constexpr bool has_foldr = true; + + /** + * Whether this operator is \em mathematically associative; that is, + * associative when assuming equivalent data types for \a IN1, \a IN2, + * and \a OUT, as well as assuming exact arithmetic, no overflows, etc. + */ + static constexpr bool is_associative = false; + + /** + * Whether this operator is \em mathematically commutative; that is, + * commutative when assuming equivalent data types for \a IN1, \a IN2, + * and \a OUT, as well as assuming exact arithmetic, no overflows, etc. + */ + static constexpr bool is_commutative = false; + + /** + * Out-of-place application of this operator. + * + * @param[in] a The left-hand side input. Must be pre-allocated and initialised. + * @param[in] b The right-hand side input. Must be pre-allocated and initialised. + * @param[out] c The output. Must be pre-allocated. + * + * At the end of the operation, \f$ c = a/b \f$. + */ + static void apply( const left_type * __restrict__ const a, const right_type * __restrict__ const b, result_type * __restrict__ const c ) { + *c = *a / *b; + } + + /** + * In-place left-to-right folding. + * + * @param[in] a Pointer to the left-hand side input data. + * @param[in,out] c Pointer to the right-hand side input data. This also + * dubs as the output memory area. + */ + static void foldr( const left_type * __restrict__ const a, result_type * __restrict__ const c ) { + *c = *a / *c; + } + + /** + * In-place right-to-left folding. + * + * @param[in,out] c Pointer to the left-hand side input data. This also + * dubs as the output memory area. + * @param[in] b Pointer to the right-hand side input data. + */ + static void foldl( result_type * __restrict__ const c, const right_type * __restrict__ const b ) { + *c /= *b; + } + }; + + /** \todo add documentation */ + template< typename IN1, typename IN2, typename OUT, enum Backend implementation = config::default_backend > + class divide_reverse { + public: + /** Alias to the left-hand input data type. */ + typedef IN1 left_type; + + /** Alias to the right-hand input data type. */ + typedef IN2 right_type; + + /** Alias to the output data type. */ + typedef OUT result_type; + + /** Whether this operator has an in-place foldl. */ + static constexpr bool has_foldl = true; + + /** Whether this operator has an in-place foldr. */ + static constexpr bool has_foldr = true; + + /** + * Whether this operator is \em mathematically associative; that is, + * associative when assuming equivalent data types for \a IN1, \a IN2, + * and \a OUT, as well as assuming exact arithmetic, no overflows, etc. + */ + static constexpr bool is_associative = false; + + /** + * Whether this operator is \em mathematically commutative; that is, + * commutative when assuming equivalent data types for \a IN1, \a IN2, + * and \a OUT, as well as assuming exact arithmetic, no overflows, etc. + */ + static constexpr bool is_commutative = false; + + /** + * Out-of-place application of this operator. + * + * @param[in] a The left-hand side input. Must be pre-allocated and initialised. + * @param[in] b The right-hand side input. Must be pre-allocated and initialised. + * @param[out] c The output. Must be pre-allocated. + * + * At the end of the operation, \f$ c = b/a \f$. + */ + static void apply( const left_type * __restrict__ const a, const right_type * __restrict__ const b, result_type * __restrict__ const c ) { + *c = *b / *a; + } + + /** + * In-place left-to-right folding. + * + * @param[in] a Pointer to the left-hand side input data. + * @param[in,out] c Pointer to the right-hand side input data. This also + * dubs as the output memory area. + */ + static void foldr( const left_type * __restrict__ const a, result_type * __restrict__ const c ) { + *c /= *a; + } + + /** + * In-place right-to-left folding. + * + * @param[in,out] c Pointer to the left-hand side input data. This also + * dubs as the output memory area. + * @param[in] b Pointer to the right-hand side input data. + */ + static void foldl( result_type * __restrict__ const c, const right_type * __restrict__ const b ) { + *c = *b / *c; + } + }; + + /** \todo add documentation */ + template< typename IN1, typename IN2, typename OUT, enum Backend implementation = config::default_backend > + class equal { + public: + /** Alias to the left-hand input data type. */ + typedef IN1 left_type; + + /** Alias to the right-hand input data type. */ + typedef IN2 right_type; + + /** Alias to the output data type. */ + typedef OUT result_type; + + /** Whether this operator has an in-place foldl. */ + static constexpr bool has_foldl = true; + + /** Whether this operator has an in-place foldr. */ + static constexpr bool has_foldr = true; + + /** + * Whether this operator is \em mathematically associative; that is, + * associative when assuming equivalent data types for \a IN1, \a IN2, + * and \a OUT, as well as assuming exact arithmetic, no overflows, etc. + */ + static constexpr bool is_associative = true; + + /** + * Whether this operator is \em mathematically commutative; that is, + * commutative when assuming equivalent data types for \a IN1, \a IN2, + * and \a OUT, as well as assuming exact arithmetic, no overflows, etc. + */ + static constexpr bool is_commutative = true; + + /** + * Out-of-place application of this operator. + * + * @param[in] a The left-hand side input. Must be pre-allocated and initialised. + * @param[in] b The right-hand side input. Must be pre-allocated and initialised. + * @param[out] c The output. Must be pre-allocated. + * + * At the end of the operation, \f$ c = \min\{a,b\} \f$. + */ + static void apply( const left_type * __restrict__ const a, const right_type * __restrict__ const b, result_type * __restrict__ const c ) { + if( *a == *b ) { + *c = static_cast< OUT >( true ); + } else { + *c = static_cast< OUT >( false ); + } + } + + /** + * In-place left-to-right folding. + * + * @param[in] a Pointer to the left-hand side input data. + * @param[in,out] c Pointer to the right-hand side input data. This also + * dubs as the output memory area. + */ + static void foldr( const left_type * __restrict__ const a, result_type * __restrict__ const c ) { + if( *a == *c ) { + *c = static_cast< result_type >( true ); + } else { + *c = static_cast< result_type >( false ); + } + } + + /** + * In-place right-to-left folding. + * + * @param[in,out] c Pointer to the left-hand side input data. This also + * dubs as the output memory area. + * @param[in] b Pointer to the right-hand side input data. + */ + static void foldl( result_type * __restrict__ const c, const right_type * __restrict__ const b ) { + if( *b == *c ) { + *c = static_cast< result_type >( true ); + } else { + *c = static_cast< result_type >( false ); + } + } + }; + + /** \todo add documentation */ + template< typename IN1, typename IN2, typename OUT, enum Backend implementation = config::default_backend > + class not_equal { + public: + /** Alias to the left-hand input data type. */ + typedef IN1 left_type; + + /** Alias to the right-hand input data type. */ + typedef IN2 right_type; + + /** Alias to the output data type. */ + typedef OUT result_type; + + /** Whether this operator has an in-place foldl. */ + static constexpr bool has_foldl = true; + + /** Whether this operator has an in-place foldr. */ + static constexpr bool has_foldr = true; + + /** + * Whether this operator is \em mathematically associative; that is, + * associative when assuming equivalent data types for \a IN1, \a IN2, + * and \a OUT, as well as assuming exact arithmetic, no overflows, etc. + */ + static constexpr bool is_associative = true; + + /** + * Whether this operator is \em mathematically commutative; that is, + * commutative when assuming equivalent data types for \a IN1, \a IN2, + * and \a OUT, as well as assuming exact arithmetic, no overflows, etc. + */ + static constexpr bool is_commutative = true; + + /** + * Out-of-place application of this operator. + * + * @param[in] a The left-hand side input. Must be pre-allocated and initialised. + * @param[in] b The right-hand side input. Must be pre-allocated and initialised. + * @param[out] c The output. Must be pre-allocated. + * + * At the end of the operation, \f$ c = \min\{a,b\} \f$. + */ + static void apply( const left_type * __restrict__ const a, const right_type * __restrict__ const b, result_type * __restrict__ const c ) { + GRB_UTIL_IGNORE_MAYBE_UNINITIALIZED // this is a (too) broad suppression-- + // see internal issue 306 for rationale + if( *a != *b ) { + *c = static_cast< OUT >( true ); + } else { + *c = static_cast< OUT >( false ); + } + GRB_UTIL_RESTORE_WARNINGS + } + + /** + * In-place left-to-right folding. + * + * @param[in] a Pointer to the left-hand side input data. + * @param[in,out] c Pointer to the right-hand side input data. This also + * dubs as the output memory area. + */ + static void foldr( const left_type * __restrict__ const a, result_type * __restrict__ const c ) { + if( *a != *c ) { + *c = static_cast< result_type >( true ); + } else { + *c = static_cast< result_type >( false ); + } + } + + /** + * In-place right-to-left folding. + * + * @param[in,out] c Pointer to the left-hand side input data. This also + * dubs as the output memory area. + * @param[in] b Pointer to the right-hand side input data. + */ + static void foldl( result_type * __restrict__ const c, const right_type * __restrict__ const b ) { + if( *b != *c ) { + *c = static_cast< result_type >( true ); + } else { + *c = static_cast< result_type >( false ); + } + } + }; + + /** \todo add documentation */ + template< typename IN1, typename IN2, typename OUT, enum Backend implementation = config::default_backend > + class any_or { + public: + /** Alias to the left-hand input data type. */ + typedef IN1 left_type; + + /** Alias to the right-hand input data type. */ + typedef IN2 right_type; + + /** Alias to the output data type. */ + typedef OUT result_type; + + /** Whether this operator has an in-place foldl. */ + static constexpr bool has_foldl = true; + + /** Whether this operator has an in-place foldr. */ + static constexpr bool has_foldr = true; + + /** + * Whether this operator is \em mathematically associative; that is, + * associative when assuming equivalent data types for \a IN1, \a IN2, + * and \a OUT, as well as assuming exact arithmetic, no overflows, etc. + */ + static constexpr bool is_associative = true; + + /** + * Whether this operator is \em mathematically commutative; that is, + * commutative when assuming equivalent data types for \a IN1, \a IN2, + * and \a OUT, as well as assuming exact arithmetic, no overflows, etc. + */ + static constexpr bool is_commutative = true; + + /** + * Out-of-place application of this operator. + * + * @param[in] a The left-hand side input. Must be pre-allocated and initialised. + * @param[in] b The right-hand side input. Must be pre-allocated and initialised. + * @param[out] c The output. Must be pre-allocated. + * + * At the end of the operation, \f$ c = \min\{a,b\} \f$. + */ + static void apply( const left_type * __restrict__ const a, const right_type * __restrict__ const b, result_type * __restrict__ const c ) { + if( *a ) { + *c = static_cast< OUT >( *a ); + } else if( *b ) { + *c = static_cast< OUT >( *b ); + } else { + assert( ! ( *a ) ); + *c = static_cast< OUT >( *a ); + } + } + + /** + * In-place left-to-right folding. + * + * @param[in] a Pointer to the left-hand side input data. + * @param[in,out] c Pointer to the right-hand side input data. This also + * dubs as the output memory area. + */ + static void foldr( const left_type * __restrict__ const a, result_type * __restrict__ const c ) { + if( *a ) { + *c = static_cast< result_type >( *a ); + } + } + + /** + * In-place right-to-left folding. + * + * @param[in,out] c Pointer to the left-hand side input data. This also + * dubs as the output memory area. + * @param[in] b Pointer to the right-hand side input data. + */ + static void foldl( result_type * __restrict__ const c, const right_type * __restrict__ const b ) { + if( *b ) { + *c = static_cast< result_type >( *b ); + } + } + }; + + /** \todo add documentation */ + template< typename IN1, typename IN2, typename OUT, enum Backend implementation = config::default_backend > + class logical_or { + public: + /** Alias to the left-hand input data type. */ + typedef IN1 left_type; + + /** Alias to the right-hand input data type. */ + typedef IN2 right_type; + + /** Alias to the output data type. */ + typedef OUT result_type; + + /** Whether this operator has an in-place foldl. */ + static constexpr bool has_foldl = true; + + /** Whether this operator has an in-place foldr. */ + static constexpr bool has_foldr = true; + + /** + * Whether this operator is \em mathematically associative; that is, + * associative when assuming equivalent data types for \a IN1, \a IN2, + * and \a OUT, as well as assuming exact arithmetic, no overflows, etc. + */ + static constexpr bool is_associative = true; + + /** + * Whether this operator is \em mathematically commutative; that is, + * commutative when assuming equivalent data types for \a IN1, \a IN2, + * and \a OUT, as well as assuming exact arithmetic, no overflows, etc. + */ + static constexpr bool is_commutative = true; + + /** + * Out-of-place application of this operator. + * + * @param[in] a The left-hand side input. Must be pre-allocated and initialised. + * @param[in] b The right-hand side input. Must be pre-allocated and initialised. + * @param[out] c The output. Must be pre-allocated. + * + * At the end of the operation, \f$ c = \min\{a,b\} \f$. + */ + static void apply( const left_type * __restrict__ const a, const right_type * __restrict__ const b, result_type * __restrict__ const c ) { + printf( "Hello from mul\n" ); + if( *a || *b ) { + *c = static_cast< OUT >( true ); + } else { + *c = static_cast< OUT >( false ); + } + } + + /** + * In-place left-to-right folding. + * + * @param[in] a Pointer to the left-hand side input data. + * @param[in,out] c Pointer to the right-hand side input data. This also + * dubs as the output memory area. + */ + static void foldr( const left_type * __restrict__ const a, result_type * __restrict__ const c ) { + if( *a || *c ) { + *c = static_cast< result_type >( true ); + } else { + *c = static_cast< result_type >( false ); + } + } + + /** + * In-place right-to-left folding. + * + * @param[in,out] c Pointer to the left-hand side input data. This also + * dubs as the output memory area. + * @param[in] b Pointer to the right-hand side input data. + */ + static void foldl( result_type * __restrict__ const c, const right_type * __restrict__ const b ) { + if( *b || *c ) { + *c = static_cast< result_type >( true ); + } else { + *c = static_cast< result_type >( false ); + } + } + }; + + /** \todo add documentation */ + template< typename IN1, typename IN2, typename OUT, enum Backend implementation = config::default_backend > + class logical_and { + public: + /** Alias to the left-hand input data type. */ + typedef IN1 left_type; + + /** Alias to the right-hand input data type. */ + typedef IN2 right_type; + + /** Alias to the output data type. */ + typedef OUT result_type; + + /** Whether this operator has an in-place foldl. */ + static constexpr bool has_foldl = true; + + /** Whether this operator has an in-place foldr. */ + static constexpr bool has_foldr = true; + + /** + * Whether this operator is \em mathematically associative; that is, + * associative when assuming equivalent data types for \a IN1, \a IN2, + * and \a OUT, as well as assuming exact arithmetic, no overflows, etc. + */ + static constexpr bool is_associative = true; + + /** + * Whether this operator is \em mathematically commutative; that is, + * commutative when assuming equivalent data types for \a IN1, \a IN2, + * and \a OUT, as well as assuming exact arithmetic, no overflows, etc. + */ + static constexpr bool is_commutative = true; + + /** + * Out-of-place application of this operator. + * + * @param[in] a The left-hand side input. Must be pre-allocated and initialised. + * @param[in] b The right-hand side input. Must be pre-allocated and initialised. + * @param[out] c The output. Must be pre-allocated. + * + * At the end of the operation, \f$ c = \min\{a,b\} \f$. + */ + static void apply( const left_type * __restrict__ const a, const right_type * __restrict__ const b, result_type * __restrict__ const c ) { + if( *a && *b ) { + *c = static_cast< OUT >( true ); + } else { + *c = static_cast< OUT >( false ); + } + } + + /** + * In-place left-to-right folding. + * + * @param[in] a Pointer to the left-hand side input data. + * @param[in,out] c Pointer to the right-hand side input data. This also + * dubs as the output memory area. + */ + static void foldr( const left_type * __restrict__ const a, result_type * __restrict__ const c ) { + if( *a && *c ) { + *c = static_cast< result_type >( true ); + } else { + *c = static_cast< result_type >( false ); + } + } + + /** + * In-place right-to-left folding. + * + * @param[in,out] c Pointer to the left-hand side input data. This also + * dubs as the output memory area. + * @param[in] b Pointer to the right-hand side input data. + */ + static void foldl( result_type * __restrict__ const c, const right_type * __restrict__ const b ) { + if( *b && *c ) { + *c = static_cast< result_type >( true ); + } else { + *c = static_cast< result_type >( false ); + } + } + }; + + /** \todo add documentation */ + template< typename IN1, typename IN2, typename OUT, enum Backend implementation = config::default_backend > + class abs_diff { + + public: + /** Alias to the left-hand input data type. */ + typedef IN1 left_type; + + /** Alias to the right-hand input data type. */ + typedef IN2 right_type; + + /** Alias to the output data type. */ + typedef OUT result_type; + + /** Whether this operator has an in-place foldl. */ + static constexpr bool has_foldl = true; + + /** Whether this operator has an in-place foldr. */ + static constexpr bool has_foldr = true; + + /** + * Whether this operator is \em mathematically associative; that is, + * associative when assuming equivalent data types for \a IN1, \a IN2, + * and \a OUT, as well as assuming exact arithmetic, no overflows, etc. + */ + static constexpr bool is_associative = false; + + /** + * Whether this operator is \em mathematically commutative; that is, + * commutative when assuming equivalent data types for \a IN1, \a IN2, + * and \a OUT, as well as assuming exact arithmetic, no overflows, etc. + */ + static constexpr bool is_commutative = true; + + /** + * Out-of-place application of this operator. + * + * @param[in] a The left-hand side input. Must be pre-allocated and initialised. + * @param[in] b The right-hand side input. Must be pre-allocated and initialised. + * @param[out] c The output. Must be pre-allocated. + * + * At the end of the operation, \f$ c = \min\{a,b\} \f$. + */ + static void apply( const left_type * __restrict__ const a, const right_type * __restrict__ const b, result_type * __restrict__ const c ) { + if( *a < *b ) { + *c = static_cast< OUT >( *b - *a ); + } else { + *c = static_cast< OUT >( *a - *b ); + } + } + + /** + * In-place left-to-right folding. + * + * @param[in] a Pointer to the left-hand side input data. + * @param[in,out] c Pointer to the right-hand side input data. This also + * dubs as the output memory area. + */ + static void foldr( const left_type * __restrict__ const a, result_type * __restrict__ const c ) { + if( *a < *c ) { + *c -= *a; + } else { + *c = static_cast< OUT >( *a - *c ); + } + } + + /** + * In-place right-to-left folding. + * + * @param[in,out] c Pointer to the left-hand side input data. This also + * dubs as the output memory area. + * @param[in] b Pointer to the right-hand side input data. + */ + static void foldl( result_type * __restrict__ const c, const right_type * __restrict__ const b ) { + if( *b < *c ) { + *c -= *b; + } else { + *c = static_cast< OUT >( *b - *c ); + } + } + }; + + /** \todo add documentation */ + template< typename IN1, typename IN2, typename OUT, enum Backend implementation = config::default_backend > + class relu { + public: + /** Alias to the left-hand input data type. */ + typedef IN1 left_type; + + /** Alias to the right-hand input data type. */ + typedef IN2 right_type; + + /** Alias to the output data type. */ + typedef OUT result_type; + + /** Whether this operator has an in-place foldl. */ + static constexpr bool has_foldl = true; + + /** Whether this operator has an in-place foldr. */ + static constexpr bool has_foldr = true; + + /** + * Whether this operator is \em mathematically associative; that is, + * associative when assuming equivalent data types for \a IN1, \a IN2, + * and \a OUT, as well as assuming exact arithmetic, no overflows, etc. + */ + static constexpr bool is_associative = true; + + /** + * Whether this operator is \em mathematically commutative; that is, + * commutative when assuming equivalent data types for \a IN1, \a IN2, + * and \a OUT, as well as assuming exact arithmetic, no overflows, etc. + */ + static constexpr bool is_commutative = true; + + /** + * Out-of-place application of this operator. + * + * @param[in] a The left-hand side input. Must be pre-allocated and initialised. + * @param[in] b The right-hand side input. Must be pre-allocated and initialised. + * @param[out] c The output. Must be pre-allocated. + * + * At the end of the operation, \f$ c = ReLU\{a,b\} = \begin{cases} + * a \text{, if } a>b \\ + * b \text{, otherwise} + * \end{cases}\f$. + */ + static void apply( const left_type * __restrict__ const a, const right_type * __restrict__ const b, result_type * __restrict__ const c ) { + if( *a < *b ) { + *c = static_cast< OUT >( *b ); + } else { + *c = static_cast< OUT >( *a ); + } + } + + /** + * In-place left-to-right folding. + * + * @param[in] a Pointer to the left-hand side input data. + * @param[in,out] c Pointer to the right-hand side input data. This also + * dubs as the output memory area. + */ + static void foldr( const left_type * __restrict__ const a, result_type * __restrict__ const c ) { + if( *a > *c ) { + *c = *a; + } + } + + /** + * In-place right-to-left folding. + * + * @param[in,out] c Pointer to the left-hand side input data. This also + * dubs as the output memory area. + * @param[in] b Pointer to the right-hand side input data. + */ + static void foldl( result_type * __restrict__ const c, const right_type * __restrict__ const b ) { + if( *b > *c ) { + *c = *b; + } + } + }; + + template< typename D1, typename D2, typename D3, enum Backend implementation = config::default_backend > + class square_diff { + public: + typedef D1 left_type; + typedef D2 right_type; + typedef D3 result_type; + + static constexpr bool has_foldl = true; + static constexpr bool has_foldr = true; + static constexpr bool is_associative = false; + static constexpr bool is_commutative = true; + + static void apply( const left_type * __restrict__ const a, const right_type * __restrict__ const b, result_type * __restrict__ const c ) { + *c = ( *a - *b ) * ( *a - *b ); + } + + static void foldr( const left_type * __restrict__ const a, result_type * __restrict__ const c ) { + *c = ( *a - *c ) * ( *a - *c ); + } + + static void foldl( const right_type * __restrict__ const b, result_type * __restrict__ const c ) { + *c = ( *c - *b ) * ( *c - *b ); + } + }; + + /** + * left operand of type IN1, + * right operand of type IN2 + * result of type std::pair< IN1, IN2 > + * + * for use together with argmin + */ + template< typename IN1, typename IN2, enum Backend implementation = config::default_backend > + class zip { + public: + typedef IN1 left_type; + typedef IN2 right_type; + typedef std::pair< IN1, IN2 > result_type; + + static constexpr bool has_foldl = false; + static constexpr bool has_foldr = false; + static constexpr bool is_associative = false; + static constexpr bool is_commutative = false; + + static void apply( const left_type * __restrict__ const a, const right_type * __restrict__ const b, result_type * __restrict__ const c ) { + *c = std::make_pair( *a, *b ); + } + }; + + /** + * compares the first argument of a pair + */ + template< typename IN1, typename IN2, typename OUT, enum Backend implementation = config::default_backend > + class equal_first { + public: + typedef IN1 left_type; + + typedef IN2 right_type; + + typedef OUT result_type; + + static constexpr bool has_foldl = false; + static constexpr bool has_foldr = false; + static constexpr bool is_associative = false; + static constexpr bool is_commutative = false; + + /** + * Out-of-place application of this operator. + * + * @param[in] a The left-hand side input. Must be pre-allocated and initialised. + * @param[in] b The right-hand side input. Must be pre-allocated and initialised. + * @param[out] c The output. Must be pre-allocated. + * + * At the end of the operation, \f$ c = a->first == b->first \f$. + */ + static void apply( const left_type * __restrict__ const a, const right_type * __restrict__ const b, result_type * __restrict__ const c ) { + if( a->first == b->first ) { + *c = static_cast< OUT >( true ); + } else { + *c = static_cast< OUT >( false ); + } + } + }; + + /** + * This class takes a generic operator implementation and exposes a more + * convenient apply() function based on it. This function allows arbitrary + * data types being passed as parameters, and automatically handles any + * casting required for the raw operator. + * + * @tparam OP The generic operator implementation. + * + * @see Operator for full details. + */ + template< typename OP, enum Backend implementation = config::default_backend > + class OperatorBase { + + protected: + /** The block size that should be used during map-like operations. */ + static constexpr size_t blocksize = grb::utils::static_min( grb::config::SIMD_BLOCKSIZE< typename OP::left_type >::value(), + grb::utils::static_min( grb::config::SIMD_BLOCKSIZE< typename OP::right_type >::value(), grb::config::SIMD_BLOCKSIZE< typename OP::result_type >::value() ) ); + + /** The left-hand side input domain. */ + typedef typename OP::left_type D1; + + /** The right-hand side input domain. */ + typedef typename OP::right_type D2; + + /** The output domain. */ + typedef typename OP::result_type D3; + + public: + /** @return Whether this operator is mathematically associative. */ + static constexpr bool is_associative() { + return OP::is_associative; + } + + /** @return Whether this operator is mathematically commutative. */ + static constexpr bool is_commutative() { + return OP::is_commutative; + } + + /** + * Straightforward application of this operator. Computes \f$ x \odot y \f$ + * and stores the result in \a z. + * + * @tparam InputType1 The type of the input parameter \a x. + * @tparam InputType2 The type of the input parameter \a y. + * @tparam OutputType The type of the output parameter \a z. + * + * \warning If \a InputType1 does not match \a D! \em or \a InputType2 does + * not match \a D2 \em or \a OutputType does not match \a D3, then + * the input will be cast into temporary variables of the correct + * types, while the output will be cast from a temporary variable, + * + * \note Best performance is thus only guaranteed when all domains match. + * + * @param[in] x The left-hand side input. + * @param[in] y The right-hand side input. + * @param[out] z The output element. + */ + template< typename InputType1, typename InputType2, typename OutputType > + static void apply( const InputType1 & x, const InputType2 & y, OutputType & z ) { + const D1 a = static_cast< D1 >( x ); + const D2 b = static_cast< D2 >( y ); + D3 temp; + OP::apply( &a, &b, &temp ); + z = static_cast< OutputType >( temp ); + } + + /** + * This is the high-performance version of apply() in the sense that no + * casting is required. This version will be automatically caled whenever + * possible. + */ + static void apply( const D1 & x, const D2 & y, D3 & out ) { + OP::apply( &x, &y, &out ); + } + }; + + /** + * A class capable of adding an out-of-place \a foldr function for an + * operator that is not fold-right capable, or capable of adding an in- + * place foldr function for an operator that is fold-right capable. For + * fold-right capable operators, this class is also capable of adding + * an efficient eWiseApply function. + * + * An operator is fold-right capable when the Base Operator \a OP + * provides an in-place foldr implementation, \em and whenever \a D1 + * equals \a D3. If one of either requirements is not met, then \a OP + * is not fold-right capable and this class is selected to add an out- + * of-place foldr function. + * + * @tparam OP The generic operator implementation. + * @tparam guard This typename is void if and only if \a OP is not fold- + * right capable. In this case, this class adds an out-of- + * place foldr implementation to the operator. + * If it is not void, then this class defines an + * in-place foldr implementation instead. + * + * \note This specific class corresponds to the \a guard variable equal to + * \a void. + * + * @see Operator for full details. + * @see OperatorBase for additional functions exposed to the final operator. + */ + template< typename OP, typename guard = void, enum Backend implementation = config::default_backend > + class OperatorFR : public OperatorBase< OP > { + + public: + /** + * Emulated in-place application of this operator on two data elements. + * + * Computes \f$ x \odot y \f$ and writes the result into \f$ y \f$. + * + * We wish to call this in-place variant internally for brevity. However, + * if \a OP has no in-place variant, then we must cache the previous + * value of the output element or otherwise we will breach the + * __restrict__ contract of OP::apply. + * The caller must ensure the appropriate domains and casting behaviour + * is applicable. Note that a user is never to call these functions + * explicitly. + * + * @tparam InputType The type of the parameter \a x. + * @tparam IOType The type of the parameter \a y. + * + * \warning Additional casting and use of temporary variables may occur + * when \a InputType does not match \a D1 \em or \a IOType + * does not match \a D3. + * + * \note This implementation relies on apply(). + * + * @param[in] x The value that is to be applied to \a y. + * @param[in,out] y The value \a x is to be applied against. + */ + template< typename InputType, typename IOType > + static void foldr( const InputType & x, IOType & y ) { + typedef typename OperatorBase< OP >::D2 D2; + const D2 cache = static_cast< D2 >( y ); + OperatorBase< OP >::apply( x, cache, y ); + } + + /** + * Out-of-place element-wise foldr function. Calculates + * \f$\forall\ i \in \{ 0, 1, \ldots, n - 1 \}, \f$ + * \f$ x_i \odot z_i \f$ and stores the result into + * \f$ z_i \f$. + * + * @tparam InputType The type of elements in \a x. + * @tparam IOType The type of elements in \a z. + * + * @param x The left-hand side input data. + * @param z Where \a x shall be mapped into. + * @param n How many data elements \a x and \a z contain. + * + * This version requires three buffers, streams \a x once, + * and streams \a z twice (once for reading, once for + * writing. + */ + template< typename InputType, typename IOType > + static void eWiseFoldrAA( const InputType * __restrict__ const x, IOType * __restrict__ const z, const size_t n ) { + // local buffers + typedef typename OperatorBase< OP >::D1 D1; + typedef typename OperatorBase< OP >::D2 D2; + typedef typename OperatorBase< OP >::D3 D3; + D1 left_buffer[ OperatorBase< OP >::blocksize ]; + D2 right_buffer[ OperatorBase< OP >::blocksize ]; + D3 result_buffer[ OperatorBase< OP >::blocksize ]; + + // blockwise application + size_t i = 0; + while( i + OperatorBase< OP >::blocksize <= n ) { + // load into buffers + for( size_t b = 0; b < OperatorBase< OP >::blocksize; ++i, ++b ) { + left_buffer[ b ] = static_cast< D1 >( x[ i ] ); + right_buffer[ b ] = static_cast< D2 >( z[ i ] ); + } + + // rewind source and output + i -= OperatorBase< OP >::blocksize; + + // operate within buffer + for( size_t b = 0; b < OperatorBase< OP >::blocksize; ++b ) { + OP::apply( &( left_buffer[ b ] ), &( right_buffer[ b ] ), &( result_buffer[ b ] ) ); + } + + // write back result + for( size_t b = 0; b < OperatorBase< OP >::blocksize; ++i, ++b ) { + z[ i ] = static_cast< IOType >( result_buffer[ b ] ); + } + } + + // direct application for remainder + for( ; i < n; ++i ) { + left_buffer[ 0 ] = static_cast< D1 >( x[ i ] ); + right_buffer[ 0 ] = static_cast< D2 >( z[ i ] ); + OP::apply( left_buffer, right_buffer, result_buffer ); + z[ i ] = static_cast< IOType >( result_buffer[ 0 ] ); + } + } + + /** + * Out-of-place element-wise foldr function. Calculates + * \f$ \forall\ i \in \{ 0, 1, \ldots, n - 1 \}, \f$ + * \f$ x \odot z_i \f$ and stores the result into + * \f$ z_i \f$. + * + * @tparam InputType The type of elements in \a x. + * @tparam IOType The type of elements in \a z. + * + * @param x The left-hand side input value. + * @param z Where \a x shall be mapped into. + * @param n How many data elements \a z contains. + * + * This version requires two buffers and streams \a z + * twice (once for reading, once for writing). + */ + template< typename InputType, typename IOType > + static void eWiseFoldrSA( const InputType x, IOType * __restrict__ const z, const size_t n ) { + // local buffers + typedef typename OperatorBase< OP >::D1 D1; + typedef typename OperatorBase< OP >::D2 D2; + typedef typename OperatorBase< OP >::D3 D3; + const D1 left_buffer = x; // this is actually mandatory in case x is a temporary + D2 right_buffer[ OperatorBase< OP >::blocksize ]; + D3 result_buffer[ OperatorBase< OP >::blocksize ]; + + // blockwise application + size_t i = 0; + while( i + OperatorBase< OP >::blocksize <= n ) { + // load into buffers + for( size_t b = 0; b < OperatorBase< OP >::blocksize; ++i, ++b ) { + right_buffer[ b ] = static_cast< D2 >( z[ i ] ); + } + + // rewind source and output + i -= OperatorBase< OP >::blocksize; + + // operate within buffer + for( size_t b = 0; b < OperatorBase< OP >::blocksize; ++b ) { + OP::apply( &left_buffer, &( right_buffer[ b ] ), &( result_buffer[ b ] ) ); + } + + // write back result + for( size_t b = 0; b < OperatorBase< OP >::blocksize; ++i, ++b ) { + z[ i ] = static_cast< IOType >( result_buffer[ b ] ); + } + } + + // direct application for remainder + for( ; i < n; ++i ) { + right_buffer[ 0 ] = static_cast< D2 >( z[ i ] ); + OP::apply( &left_buffer, right_buffer, result_buffer ); + z[ i ] = static_cast< IOType >( result_buffer[ 0 ] ); + } + } + }; + + /** + * This class provides an in-place foldr implementation for Base Operators + * that are fold-right capable given its provided domains. It also implements + * an eWiseApply function that requires two buffers by exploiting the + * in-place foldr operator. Without an in-place foldr, it is still possible + * to implement an eWiseApply using two buffers if there is an in-place foldl + * added via OperatorFL. If that also fails, the eWiseApply function will be + * implemented using three buffers via OperatorNoFRFL. + * + * @tparam OP The generic operator implementation. + * + * @see Operator for full details. + * @see OperatorFR for details on fold-right capable operators and behaviour + * for non fold-right capable operators. + * @see OperatorBase for additional functions exposed to the final operator. + */ + template< typename OP > + class OperatorFR< OP, typename std::enable_if< OP::has_foldr && std::is_same< typename OP::right_type, typename OP::result_type >::value >::type > : public OperatorBase< OP > { + + private: + typedef typename OperatorBase< OP >::D1 D1; + typedef typename OperatorBase< OP >::D3 D3; + static constexpr size_t blocksize = OperatorBase< OP >::blocksize; + + public: + /** + * In-place application of this operator on two data elements. + * + * Computes \f$ x \odot y \f$ and writes the result into \f$ y \f$. + * + * \note This variant is only called when the underlying raw operator + * supports in-place operations. + * + * The caller must ensure the appropriate domains and casting behaviour + * is applicable. Note that a user is never to call these functions + * explicitly. + * + * @param[in] x The value that is to be applied to \a y. + * @param[in,out] y The value \a x is to be applied against. + */ + static void foldr( const D1 & x, D3 & y ) { + OP::foldr( &x, &y ); + } + + /** + * In-place element-wise foldr function. Calculates + * \f$\forall\ i \in \{ 0, 1, \ldots, n - 1 \}, \f$ + * \f$ x \odot z_i \f$ and stores the result into \f$ z_i \f$. + * + * @tparam InputType The type of \a x. + * @tparam IOType The type of elements in \a z. + * + * @param[in] x The left-hand side input value. + * @param[in,out] z Where \a x shall be mapped into. + * @param[in] n How many data elements \a z contains. + * + * This implementation requires one buffers only. It streams \a z twice, + * once for reading, once for writing. This function should vectorise. + */ + template< typename InputType, typename IOType > + static void eWiseFoldrSA( const InputType x, IOType * __restrict__ const z, const size_t n ) { + // local buffers + const D1 left_buffer = static_cast< D1 >( x ); + D3 result_buffer[ blocksize ]; + + // blockwise application + size_t i = 0; + while( i + blocksize <= n ) { + // load into buffers + for( size_t b = 0; b < blocksize; ++i, ++b ) { + result_buffer[ b ] = static_cast< D3 >( z[ i ] ); + } + + // rewind source and output + i -= blocksize; + + // operate within buffer + for( size_t b = 0; b < blocksize; ++b ) { + OP::foldr( &left_buffer, &( result_buffer[ b ] ) ); + } + + // write back result + for( size_t b = 0; b < blocksize; ++i, ++b ) { + z[ i ] = static_cast< IOType >( result_buffer[ b ] ); + } + } + + // direct application for remainder + for( ; i < n; ++i ) { + result_buffer[ 0 ] = static_cast< D3 >( z[ i ] ); + OP::foldr( &left_buffer, result_buffer ); + z[ i ] = static_cast< IOType >( result_buffer[ 0 ] ); + } + } + + /** + * In-place element-wise foldr function. Calculates + * \f$\forall\ i \in \{ 0, 1, \ldots, n - 1 \}, \f$ + * \f$ x_i \odot z_i \f$ and stores the result into \f$ z_i \f$. + * + * @tparam InputType The type of elements in \a x. + * @tparam IOType The type of elements in \a z. + * + * @param[in] x The left-hand side input data. + * @param[in,out] z Where \a x shall be mapped into. + * @param[in] n How many data elements \a x and \a z contain. + * + * This implementation requires two buffers only. It streams \a x once, + * while streaming \a z twice (once for reading, once for writing). This + * function should vectorise. + */ + template< typename InputType, typename IOType > + static void eWiseFoldrAA( const InputType * __restrict__ const x, IOType * __restrict__ const z, const size_t n ) { + // local buffers + D1 left_buffer[ blocksize ]; + D3 result_buffer[ blocksize ]; + + // blockwise application + size_t i = 0; + while( i + blocksize <= n ) { + // load into buffers + for( size_t b = 0; b < blocksize; ++i, ++b ) { + left_buffer[ b ] = static_cast< D1 >( x[ i ] ); + result_buffer[ b ] = static_cast< D3 >( z[ i ] ); + } + + // rewind source and output + i -= blocksize; + + // operate within buffer + for( size_t b = 0; b < blocksize; ++b ) { + OP::foldr( &( left_buffer[ b ] ), &( result_buffer[ b ] ) ); + } + + // write back result + for( size_t b = 0; b < blocksize; ++i, ++b ) { + z[ i ] = static_cast< IOType >( result_buffer[ b ] ); + } + } + + // direct application for remainder + for( ; i < n; ++i ) { + left_buffer[ 0 ] = static_cast< D1 >( x[ i ] ); + result_buffer[ 0 ] = static_cast< D3 >( z[ i ] ); + OP::foldr( left_buffer, result_buffer ); + z[ i ] = static_cast< IOType >( result_buffer[ 0 ] ); + } + } + + /** + * In-place element-wise apply function. Calculates + * \f$\forall\ i \in \{ 0, 1, \ldots, n - 1 \}, \f$ + * \f$ z_i = x_i \odot y_i \f$. + * + * @tparam InputType1 The type of elements in \a x. + * @tparam InputType2 The type of elements in \a y. + * @tparam OutputType The type of elements in \a z. + * + * If \a InputType2 and \a D3 are not the same, then the existing data in + * \a y is cast to \a D3 prior to application of this in-place operator. + * If \a InputType1 and \a D1 are not the same, then the existing data in + * \a x are cast to \a D1 prior to application of this in-place operator. + * If \a OutputType and \a D3 are not the same, then the results of + * applying this operator are cast to \a OutputType prior to writing back + * the results. + * + * \warning The first casting behaviour may not be what you want. The two + * other casting behaviours are allowed by the GraphBLAS unless + * the grb::descriptor::no_casting is given. + * + * \note By default, this GraphBLAS implementation will only use this + * code when \a D2 matches \a D3 and OP::has_foldr is \a true. + * + * This implementation relies on an in-place foldr(). + * + * @param[in] x The left-hand side input data. The memory range starting + * at \a x and ending at \a x + n (exclusive) may not + * overlap with the memory area starting at \a z and ending + * at \a z + n (exclusive). + * @param[in] y The right-hand side input data. The memory range starting + * at \a y and ending at \a y + n (exclusive) may not + * overlap with the memory area starting at \a z and ending + * at \a z + n. + * @param[out] z Where the map of \a x into \a y must be stored. This + * pointer is restricted in the sense that its memory may + * never overlap with those pointed to by \a x or \y, as + * detailed above. + * @param[in] n How many data elements \a x, \a y, and \a z contain. + */ + template< typename InputType1, typename InputType2, typename OutputType > + static void eWiseApply( const InputType1 * x, const InputType2 * y, OutputType * __restrict__ z, const size_t n ) { +#ifdef _DEBUG +#ifdef D_GRB_NO_STDIO + std::cout << "In OperatorFR::eWiseApply\n"; +#endif +#endif + // NOTE: this variant is only active when the computation can be done using two buffers only + + // local buffers + D1 left_buffer[ blocksize ]; + D3 result_buffer[ blocksize ]; + + // blockwise application + size_t i = 0; + while( i + blocksize <= n ) { + + // load into buffers + for( size_t b = 0; b < blocksize; ++i, ++b ) { + left_buffer[ b ] = static_cast< D1 >( x[ i ] ); + result_buffer[ b ] = static_cast< D3 >( y[ i ] ); + } + + // rewind source and output + i -= blocksize; + + // operate within buffer + for( size_t b = 0; b < blocksize; ++b ) { + OP::foldr( &( left_buffer[ b ] ), &( result_buffer[ b ] ) ); + } + + // write back result + for( size_t b = 0; b < blocksize; ++i, ++b ) { + z[ i ] = static_cast< OutputType >( result_buffer[ b ] ); + } + } + + // direct application for remainder + for( ; i < n; ++i ) { + left_buffer[ 0 ] = static_cast< typename OP::left_type >( x[ i ] ); + result_buffer[ 0 ] = static_cast< typename OP::result_type >( y[ i ] ); + OP::foldr( left_buffer, result_buffer ); + z[ i ] = static_cast< OutputType >( result_buffer[ 0 ] ); + } + } + }; + + /** + * A class capable of adding an out-of-place \a foldl function for an + * operator that is not fold-left capable, or capable of adding an in- + * place foldl function for an operator that is fold-left capable. + * + * An operator is fold-left capable when the Base Operator \a OP provides + * an in-place foldl implementation, \em and whenever \a D2 equals \a D3. + * If one of either requirements is not met, then \a OP is not fold-left + * capable and this class is selected to add an out-of-place foldl function. + * + * @tparam OP The generic operator implementation. + * @tparam guard This typename is void if and only if \a OP is not fold- + * left capable. In this case, this class adds an + * out-of-place foldl implementation to the operator. + * If \a guard is not void, then this class defines an + * in-place foldr implementation instead. + * + * \note This specific class corresponds to the \a guard variable equal to + * \a void. + * + * @see Operator for full details. + * @see OperatorFR for additional functions exposed to the resulting + * operator. + * @see OperatorBase for additional functions exposed to the resulting + * operator. + */ + template< typename OP, typename guard = void, enum Backend implementation = config::default_backend > + class OperatorFL : public OperatorFR< OP > { + + private: + public: + typedef typename OperatorBase< OP >::D1 D1; + typedef typename OperatorBase< OP >::D2 D2; + typedef typename OperatorBase< OP >::D3 D3; + static constexpr size_t blocksize = OperatorBase< OP >::blocksize; + + /** + * Emulated in-place application of this operator on two data elements. + * + * Computes \f$ x \odot y \f$ and writes the result into \f$ x \f$. + * + * We wish to call this in-place variant internally for brevity. However, + * if \a OP has no in-place variant, then we must cache the previous + * value of the output element or otherwise we will breach the + * __restrict__ contract of OP::apply. + * The caller must ensure the appropriate domains and casting behaviour + * is applicable. Note that a user is never to call these functions + * explicitly. + * + * @tparam InputType The type of the parameter \a x. + * @tparam IOType The type of the parameter \a y. + * + * \warning Additional casting and use of temporary variables may occur + * when \a InputType does not match \a D2 \em or \a IOType + * does not match \a D3. + * + * \note This implementation relies on apply(). + * + * @param[in,out] x The value \a y is to be applied against. + * @param[in] y The value that is to be applied to \a x. + */ + template< typename InputType, typename IOType > + static void foldl( IOType & x, const InputType & y ) { + const D1 cache = static_cast< D1 >( x ); + OperatorBase< OP >::apply( cache, y, x ); + } + + /** + * Out-of-place element-wise foldl function. Calculates + * \f$\forall\ i \in \{ 0, 1, \ldots, n - 1 \}, \f$ + * \f$ x_i \odot y \f$ and stores the result into \f$ x_i \f$. + * + * @tparam IOType The type of elements in \a x. + * @tparam InputType The type of \a y. + * + * @param[in, out] x At function entry, the left-hand side input data. + * At function exit, the output data as defined above. + * @param[in] y The right-hand side input value. + * @param[in] n How many data elements \a x contains. + * + * This version requires two buffers and streams \a x twice (once for + * reading, once for writing). This function should vectorise its + * out-of-place operations. + */ + template< typename IOType, typename InputType > + static void eWiseFoldlAS( IOType * __restrict__ const x, const InputType y, const size_t n ) { + // local buffers + D1 left_buffer[ blocksize ]; + const D2 right_buffer = y; + D3 result_buffer[ blocksize ]; + + // blockwise application + size_t i = 0; + while( i + blocksize <= n ) { + // load into buffers + for( size_t b = 0; b < blocksize; ++i, ++b ) { + left_buffer[ b ] = static_cast< D1 >( x[ i ] ); + } + + // rewind source and output + i -= blocksize; + + // operate within buffer + for( size_t b = 0; b < blocksize; ++b ) { + OP::apply( &( left_buffer[ b ] ), &right_buffer, &( result_buffer[ b ] ) ); + } + + // write back result + for( size_t b = 0; b < blocksize; ++i, ++b ) { + x[ i ] = static_cast< IOType >( result_buffer[ b ] ); + } + } + + // direct application for remainder + for( ; i < n; ++i ) { + left_buffer[ 0 ] = static_cast< D1 >( x[ i ] ); + OP::apply( left_buffer, &right_buffer, result_buffer ); + x[ i ] = static_cast< IOType >( result_buffer[ 0 ] ); + } + } + + /** + * Out-of-place element-wise foldl function. Calculates + * \f$\forall\ i \in \{ 0, 1, \ldots, n - 1 \}, \f$ + * \f$ x_i \odot y_i \f$ and stores the result into \f$ x_i \f$. + * + * @tparam IOType The type of elements in \a x. + * @tparam InputType The type of elements in \a y. + * + * @param[in, out] x At function entry, the left-hand side input data. + * At function exit, the output data as defined above. + * @param[in] y The right-hand side input. + * @param[in] n How many data elements \a x and \a y contain. + * + * This version requires three buffers, streams \a y once, and streams + * \a x twice (once for reading, once for writing). This function should + * vectorise its out-of-place operations. + */ + template< typename IOType, typename InputType > + static void eWiseFoldlAA( IOType * __restrict__ const x, const InputType * __restrict__ const y, const size_t n ) { + // local buffers + D1 left_buffer[ blocksize ]; + D2 right_buffer[ blocksize ]; + D3 result_buffer[ blocksize ]; + + // blockwise application + size_t i = 0; + while( i + blocksize <= n ) { + // load into buffers + for( size_t b = 0; b < blocksize; ++i, ++b ) { + left_buffer[ b ] = static_cast< D1 >( x[ i ] ); + right_buffer[ b ] = static_cast< D2 >( y[ i ] ); + } + + // rewind source and output + i -= blocksize; + + // operate within buffer + for( size_t b = 0; b < blocksize; ++b ) { + OP::apply( &( left_buffer[ b ] ), &( right_buffer[ b ] ), &( result_buffer[ b ] ) ); + } + + // write back result + for( size_t b = 0; b < blocksize; ++i, ++b ) { + x[ i ] = static_cast< IOType >( result_buffer[ b ] ); + } + } + + // direct application for remainder + for( ; i < n; ++i ) { + left_buffer[ 0 ] = static_cast< D1 >( x[ i ] ); + right_buffer[ 0 ] = static_cast< D2 >( y[ i ] ); + OP::apply( left_buffer, right_buffer, result_buffer ); + x[ i ] = static_cast< IOType >( result_buffer[ 0 ] ); + } + } + }; + + /** + * This class provides an in-place foldl implementation for Base Operators + * that are fold-left capable given its provided domains. + * + * @tparam OP The generic operator implementation. + * + * @see Operator for full details. + * @see OperatorFL for details on fold-right capable operators and behaviour + * for non fold-right capable operators. + * @see OperatorFR for additional functions exposed to the resulting + * operator. + * @see OperatorBase for additional functions exposed to the resulting + * operator. + */ + template< typename OP > + class OperatorFL< OP, typename std::enable_if< OP::has_foldl && std::is_same< typename OP::left_type, typename OP::result_type >::value >::type > : public OperatorFR< OP > { + + private: + public: + typedef typename OperatorBase< OP >::D2 D2; + typedef typename OperatorBase< OP >::D3 D3; + static constexpr size_t blocksize = OperatorBase< OP >::blocksize; + + /** + * In-place application of this operator on two data elements. + * + * Computes \f$ x \odot y \f$ and writes the result into \f$ x \f$. + * + * \note This variant is only called when the underlying raw operator + * supports in-place operations. + * + * The caller must ensure the appropriate domains and casting behaviour + * is applicable. Note that a user is never to call these functions + * explicitly. + * + * @param[in,out] x The value \a y is to be applied against. + * @param[in] y The value that is to be applied to \a x. + */ + static void foldl( D3 & x, const D2 & y ) { + OP::foldl( &x, &y ); + } + + /** + * In-place element-wise foldl function. Calculates + * \f$\forall\ i \in \{ 0, 1, \ldots, n - 1 \}, \f$ + * \f$ x_i \odot y_i \f$ and stores the result into \f$ x_i \f$. + * + * @tparam IOType The type of elements in \a x. + * @tparam InputType The type of elements in \a y. + * + * @param[in,out] x At function extry: the left-hand side input data. + * At function exit: the result data. + * @param[in] y The right-hand side input data. + * @param[in] n How many data elements \a x and \a y contain. + * + * This implementation requires two buffers only. It streams \a y once, + * while streaming \a x twice (once for reading, once for writing). This + * function should vectorise. + */ + template< typename InputType, typename IOType > + static void eWiseFoldlAA( IOType * __restrict__ const x, const InputType * __restrict__ const y, const size_t n ) { + // local buffers + D2 right_buffer[ blocksize ]; + D3 result_buffer[ blocksize ]; + + // blockwise application + size_t i = 0; + while( i + blocksize <= n ) { + // load into buffers + for( size_t b = 0; b < blocksize; ++i, ++b ) { + right_buffer[ b ] = static_cast< D2 >( y[ i ] ); + result_buffer[ b ] = static_cast< D3 >( x[ i ] ); + } + + // rewind source and output + i -= blocksize; + + // operate within buffer + for( size_t b = 0; b < blocksize; ++b ) { + OP::foldl( &( result_buffer[ b ] ), &( right_buffer[ b ] ) ); + } + + // write back result + for( size_t b = 0; b < blocksize; ++i, ++b ) { + x[ i ] = static_cast< IOType >( result_buffer[ b ] ); + } + } + + // direct application for remainder + for( ; i < n; ++i ) { + right_buffer[ 0 ] = static_cast< D2 >( y[ i ] ); + result_buffer[ 0 ] = static_cast< D3 >( x[ i ] ); + OP::foldl( result_buffer, right_buffer ); + x[ i ] = static_cast< IOType >( result_buffer[ 0 ] ); + } + } + + /** + * In-place element-wise foldl function. Calculates + * \f$ \forall\ i \in \{ 0, 1, \ldots, n - 1 \}, \f$ + * \f$ x_i \odot y \f$ and stores the result into \f$ x_i \f$. + * + * @tparam IOType The type of elements in \a x. + * @tparam InputType The type of \a y. + * + * @param[in,out] x At function extry: the left-hand side input data. + * At function exit: the result data. + * @param[in] y The right-hand side input value. + * @param[in] n How many data elements \a x contains. + * + * This implementation requires one buffers only. It streams \a x twice + * (once for reading, once for writing). This function should vectorise. + */ + template< typename InputType, typename IOType > + static void eWiseFoldlAS( IOType * __restrict__ const x, const InputType y, const size_t n ) { + // local buffers + const D2 right_buffer = static_cast< D2 >( y ); + D3 result_buffer[ blocksize ]; + + // blockwise application + size_t i = 0; + while( i + blocksize <= n ) { + // load into buffers + for( size_t b = 0; b < blocksize; ++i, ++b ) { + result_buffer[ b ] = static_cast< D3 >( x[ i ] ); + } + + // rewind source and output + i -= blocksize; + + // operate within buffer + for( size_t b = 0; b < blocksize; ++b ) { + OP::foldl( &( result_buffer[ b ] ), &right_buffer ); + } + + // write back result + for( size_t b = 0; b < blocksize; ++i, ++b ) { + x[ i ] = static_cast< IOType >( result_buffer[ b ] ); + } + } + + // direct application for remainder + for( ; i < n; ++i ) { + result_buffer[ 0 ] = static_cast< D3 >( x[ i ] ); + OP::foldl( result_buffer, &right_buffer ); + x[ i ] = static_cast< IOType >( result_buffer[ 0 ] ); + } + } + }; + + /** + * A class capable of adding an in-place \a eWiseApply function for an + * operator that is fold-left capable but not fold-right capable. + * + * Like OperatorFR on an fold-right capable operator, this class is + * capable of providing an eWiseApply function that requires only two + * internal buffers by making use of the in-place foldl. + * + * @tparam OP The generic operator implementation. + * @tparam guard This typename is void if and only if \a OP is fold-left + * capable but \em not fold-right capable. In this case, + * this class adds nothing to the resulting operator. + * If \a guard is not void, however, then this class adds an + * in-place eWiseApply implementation to this operator + * instead. + * + * @see Operator for full details. + * @see OperatorFL for additional functions exposed to the resulting + * operator. + * @see OperatorFR for additional functions exposed to the resulting + * operator and an alternative way of providing a more + * efficient eWiseApply. + * @see OperatorBase for additional functions exposed to the resulting + * operator. + */ + template< typename OP, typename guard = void, enum Backend implementation = config::default_backend > + class OperatorNoFR : public OperatorFL< OP > {}; + + /** + * This class provides an in-place eWiseApply implementation for Base + * Operators that are fold-left capable given its provided domains, but not + * fold-right capable. This implementation uses two internal buffers and + * relies on an in-place foldl. If this were not possible, then the + * eWiseApply will be provided by OperatorNoFRFL in an implementation that + * requires three buffers and out-of-place operations instead. + * + * @tparam OP The generic operator implementation. + * + * @see Operator for full details. + * @see OperatorFL for additional functions exposed to the resulting + * operator. + * @see OperatorFR for additional functions exposed to the resulting + * operator. + * @see OperatorBase for additional functions exposed to the resulting + * operator. + */ + template< typename OP > + class OperatorNoFR< OP, typename std::enable_if< OP::has_foldl && ! ( OP::has_foldr ) && std::is_same< typename OP::left_type, typename OP::result_type >::value >::type > : + public OperatorFL< OP > { + + private: + public: + typedef typename OperatorBase< OP >::D2 D2; + typedef typename OperatorBase< OP >::D3 D3; + static constexpr size_t blocksize = OperatorBase< OP >::blocksize; + + /** + * In-place element-wise apply function. Calculates + * \f$\forall\ i \in \{ 0, 1, \ldots, n - 1 \}, \f$ + * \f$ z_i = x_i \odot y_i \f$. + * + * @tparam InputType1 The type of elements in \a x. + * @tparam InputType2 The type of elements in \a y. + * @tparam OutputType The type of elements in \a z. + * + * If the \a InputType1 and \a D3 are not the same, then the existing data + * in \a x is cast to \a D3 prior to application of this operator. + * If \a InputType2 and \a D2 are not the same, then the existing data in + * \a y is cast to \a D2 prior to application of this operator. + * If \a OutputType and \a D3 are not the same, then the result of + * applications of this operator are cast to \a OutputType prior to + * writing it back to \a z. + * + * \warning The first casting behaviour may not be what you want. The two + * other casting behaviours are allowed by the GraphBLAS unless + * the grb::descriptor::no_casting is given. + * + * \note By default, this GraphBLAS implementation will only use this + * code when \a D1 matches \a D3 and OP::has_foldr is \a true. + * However, this implementation will never be enabled if \a D2 + * equals \a D3 and OP::has_foldl is \a true. + * + * This implementation relies on an in-place foldl(). + * + * @param[in] x The left-hand side input data. The memory range starting + * at \a x and ending at \a x + n (exclusive) may not + * overlap with the memory area starting at \a z and ending + * at \a z + n (exclusive). + * @param[in] y The right-hand side input data. The memory range starting + * at \a y and ending at \a y + n (exclusive) may not + * overlap with the memory area starting at \a z and ending + * at \a z + n. + * @param[out] z Where the map of \a x into \a y must be stored. This + * pointer is restricted in the sense that its memory may + * never overlap with those pointed to by \a x or \y, as + * detailed above. + * @param[in] n How many data elements \a x, \a y, and \a z contain. + */ + template< typename InputType1, typename InputType2, typename OutputType > + static void eWiseApply( const InputType1 * x, const InputType2 * y, OutputType * __restrict__ z, const size_t n ) { +#ifdef _DEBUG +#ifdef D_GRB_NO_STDIO + std::cout << "In OperatorNoFR::eWiseApply\n"; +#endif +#endif + // NOTE: this variant is only active when the computation can be done using two buffers only + + // local buffers + D2 right_buffer[ blocksize ]; + D3 result_buffer[ blocksize ]; + + // blockwise application + size_t i = 0; + while( i + blocksize <= n ) { + + // load into buffers + for( size_t b = 0; b < blocksize; ++i, ++b ) { + right_buffer[ b ] = static_cast< D2 >( y[ i ] ); + result_buffer[ b ] = static_cast< D3 >( x[ i ] ); + } + + // rewind source and output + i -= blocksize; + + // operate within buffer + for( size_t b = 0; b < blocksize; ++b ) { + OP::foldl( &( result_buffer[ b ] ), &( right_buffer[ b ] ) ); + } + + // write back result + for( size_t b = 0; b < blocksize; ++i, ++b ) { + z[ i ] = static_cast< OutputType >( result_buffer[ b ] ); + } + } + + // direct application for remainder + for( ; i < n; ++i ) { + right_buffer[ 0 ] = static_cast< D2 >( y[ i ] ); + result_buffer[ 0 ] = static_cast< D3 >( x[ i ] ); + OP::foldl( result_buffer, right_buffer ); + z[ i ] = static_cast< OutputType >( result_buffer[ 0 ] ); + } + } + }; + + /** + * A class capable of adding an out-of-place \a eWiseApply function for an + * operator that, given its domains, is not fold-left capable \em an not + * fold-right capable. + * + * If the given operator is not fold-left and not fold-right capable, then + * both OperatorFR and OperatorNoFR have not yet added an eWiseApply + * implementation. However, if there was already an in-place foldr or an + * in-place foldl available, then this class will add no new functions to + * the resulting operator. + * A class capable of adding an out-of-place eWiseApply function for an + * operator that is not fold-left capable \em and not fold-right capable. + * + * @tparam OP The generic operator implementation. + * @tparam guard This typename is void if and only if there is already an + * in-place eWiseApply defined by the base OperatorNoFR + * class or by the OperatorFR class. In this case, this + * class does not add any new public methods. + * If it is not void, then this class defines an + * out-of-place eWiseApply function. + * + * \note This specific class corresponds to the \a guard variable equal to + * \a void. + * + * @see Operator for full details. + * @see OperatorNoFR for additional functions exposed to the resulting + * operator. + * @see OperatorFL for additional functions exposed to the resulting + * operator. + * @see OperatorFR for additional functions exposed to the resulting + * operator and an alternative way of providing a more + * efficient eWiseApply. + * @see OperatorBase for additional functions exposed to the resulting + * operator. + */ + template< typename OP, typename guard = void, enum Backend implementation = config::default_backend > + class OperatorNoFRFL : public OperatorNoFR< OP > {}; + + /** + * A class that adds an out-of-place \a eWiseApply function for an operator + * that, given its domains, is not fold-left capable \em and not fold-right + * capable. + * + * Contains further specialisations for an operator that is not fold-left, + * capable \em and not fold-right capable. This means we have to supply an + * eWiseApply function that uses the normal OperatorBase::apply function, + * and thus uses three buffers instead of the two buffers required by its + * in-place counterparts. + * + * @tparam OP The generic operator implementation. + * + * @see Operator for full details. + * @see OperatorNoFR for additional functions exposed to the resulting + * operator. + * @see OperatorFL for additional functions exposed to the resulting + * operator. + * @see OperatorFR for additional functions exposed to the resulting + * operator and an alternative way of providing a more + * efficient eWiseApply. + * @see OperatorBase for additional functions exposed to the resulting + * operator and the OperatorBase::apply function this + * class will use. + */ + template< typename OP > + class OperatorNoFRFL< OP, + typename std::enable_if< ( ! ( OP::has_foldl ) || ! ( std::is_same< typename OP::left_type, typename OP::result_type >::value ) ) && + ( ! ( OP::has_foldr ) || ! ( std::is_same< typename OP::right_type, typename OP::result_type >::value ) ) >::type > : public OperatorNoFR< OP > { + + private: + public: + typedef typename OperatorBase< OP >::D1 D1; + typedef typename OperatorBase< OP >::D2 D2; + typedef typename OperatorBase< OP >::D3 D3; + static constexpr size_t blocksize = OperatorBase< OP >::blocksize; + + /** \anchor OperatorNoFRFLeWiseApply + * + * Standard out-of-place element-wise apply function. Calculates + * \f$\forall\ i \in \{ 0, 1, \ldots, n - 1 \}, \f$ + * \f$ z_i = x_i \odot y_i \f$. + * + * This is the non-public variant that operates on raw arrays. + * + * @tparam InputType1 The type of elements in \a x. + * @tparam InputType2 The type of elements in \a y. + * @tparam OutputType The type of elements in \a z. + * + * If \a InputType1 and \a D1 are not the same, then the existing data in + * \a x will be cast to \a D1 prior to application of this operator. + * If \a InputType2 and \a D2 are not the same, then the existing data in + * \a y will be cast to \a D2 prior to application of this operator. + * If \a OutputType and \a D3 are not the same, then the results of + * applications of this operator are cast to \a OutputType prior to + * writing them back to \a z. + * + * \note The GraphBLAS can explicitly control all \em three of this + * casting behaviours via grb::descriptors::no_casting. + * + * \warning With the in-place variants of this code, unwanted behaviour + * cannot be prevented by use of grb::descriptors::no_casting. + * Therefore the current implementation only calls the in-place + * variants when \a D1 equals \a D3 (for foldl-based in-place), + * or when \a D2 equals \a D3 (for foldr-based ones). + * + * @param[in] x The left-hand side input data. The memory range starting + * at \a x and ending at \a x + n (exclusive) may not + * overlap with the memory area starting at \a z and ending + * at \a z + n (exclusive). + * @param[in] y The right-hand side input data. The memory range starting + * at \a y and ending at \a y + n (exclusive) may not + * overlap with the memory area starting at \a z and ending + * at \a z + n. + * @param[out] z Where the map of \a x into \a y must be stored. This + * pointer is restricted in the sense that its memory may + * never overlap with those pointed to by \a x or \y, as + * detailed above. + * @param[in] n How many data elements \a x, \a y, and \a z contain. + */ + template< typename InputType1, typename InputType2, typename OutputType > + static void eWiseApply( const InputType1 * x, const InputType2 * y, OutputType * __restrict__ z, const size_t n ) { +#ifdef _DEBUG +#ifdef D_GRB_NO_STDIO + std::cout << "In OperatorNoFRFL::eWiseApply\n"; +#endif +#endif + // NOTE: this variant is only active when the computation can NOT be done using two buffers only + + // local buffers + D1 left_buffer[ blocksize ]; + D2 right_buffer[ blocksize ]; + D3 result_buffer[ blocksize ]; + + // blockwise application + size_t i = 0; + while( i + blocksize <= n ) { + + // load into buffers + for( size_t b = 0; b < blocksize; ++i, ++b ) { + left_buffer[ b ] = static_cast< D1 >( x[ i ] ); + right_buffer[ b ] = static_cast< D2 >( y[ i ] ); + } + + // rewind source and output + i -= blocksize; + + // operate within buffer + for( size_t b = 0; b < blocksize; ++b ) { + OP::apply( &( left_buffer[ b ] ), &( right_buffer[ b ] ), &( result_buffer[ b ] ) ); + } + + // write back result + for( size_t b = 0; b < blocksize; ++i, ++b ) { + z[ i ] = static_cast< OutputType >( result_buffer[ b ] ); + } + } + + // direct application for remainder + for( ; i < n; ++i ) { + left_buffer[ 0 ] = static_cast< D1 >( x[ i ] ); + right_buffer[ 0 ] = static_cast< D2 >( y[ i ] ); + OP::apply( left_buffer, right_buffer, result_buffer ); + z[ i ] = static_cast< OutputType >( result_buffer[ 0 ] ); + } + } + }; + + /** + * This is the operator interface exposed to the GraphBLAS implementation. + * + * \warning Note that most GraphBLAS usage requires associative operators. + * While very easily possible to create non-associative operators + * using this interface, passing them to GraphBLAS functions, + * either explicitly or indirectly (by, e.g., including them in a + * grb::Monoid or grb::Semiring), will lead to undefined + * behaviour. + * + * This class wraps around a base operator of type \a OP we denote by + * \f$ \odot:\ D_1\times D_2 \to D_3 \f$. + * + * \parblock + * \par Base Operators + * + * The class \a OP is expected to define the following public function: + * - \a apply, which takes three pointers to parameters \f$ x \in D_1 \f$ + * \f$ y \in D_2 \f$, and \f$ z \in D_3 \f$ and computes + * \f$ z = x \odot y \f$. + * + * It is also expected to define the following types: + * - \a left_type, which corresponds to \f$ D_1 \f$, + * - \a right_type, which corresponds to \f$ D_2 \f$, + * - \a result_type, which corresponds to \f$ D_3 \f$. + * + * It is also expected to define the following two public boolean fields: + * - \a has_foldr + * - \a has_foldl + * + * If \a has_foldr is \a true, then the class \a OP is expected to also + * define the function + * - foldr, which takes two pointers to parameters \f$ x \in D_1 \f$ + * and \f$ z \in D_2 \subseteq D_3 \f$ and stores in \a z the result of + * \f$ x \odot z \f$. + * + * If \a has_foldl is \a true, the the class \a OP is expected to also + * define the function + * - foldl, which takes two pointers to parameters + * \f$ z \in D_1 \subseteq D_3 \f$ and \f$ y \in D_2 \f$ and stores in + * \a z the result of \f$ z \odot y \f$. + * + * For examples of these base operators, see grb::operators::internal::max + * or grb::operators::internal::mul. An example of a full implementation, + * in this case for numerical addition, is the following: + * + * \snippet internalops.hpp Example Base Operator Implementation + * + * \note GraphBLAS users should never call these functions directly. This + * documentation is provided for developers to understand or extend + * the current implementation, for example to include new operators. + * + * \warning When calling these functions directly, note that the pointers + * to the memory areas are declared using the \em restrict key + * word. One of the consequences is that all pointers given in a + * single call may never refer to the same memory area, or + * undefined behaviour is invoked. + * + * \endparblock + * + * \parblock + * \par The exposed GraphBLAS Operator Interface + * + * The Base Operators as illustrated above are wrapped by this class to + * provide a more convient API. It translates the functionality of any Base + * Operator and exposes the following interface instead: + * + * -# apply, which takes three parameters \f$ x, y, z \f$ of arbitrary + * types and computes \f$ z = x \odot y \f$ after performing any + * casting if required. + * -# foldr, which takes two parameters \f$ x, z \f$ of arbitrary types + * and computes \f$ z = x \odot z \f$ after performing any casting if + * required. + * -# foldl, which takes two parameters \f$ z, y \f$ of arbitrary types + * and computes \f$ z = z \odot y \f$ after performing any casting if + * required. + * -# eWiseApply, which takes three pointers to arrays \f$ x, y, z \f$ + * and a size \a n. The arrays can correspond to elements of any type, + * all three with length at least \a n. For every i-th element of the + * three arrays, on the values \f$ x_i, y_i, z_i \f$, \f$ z_i \f$ will + * be set to \f$ x_i \odot y_i \f$. + * -# foldrArray, which takes a pointer to an array \f$ x \f$, a + * parameter \f$ z \f$ of arbitrary type, and a size \n as parameters. + * The value \f$ z \f$ will be overwritten to \f$ x_i \odot z \f$ for + * each of the \f$ i \in \{ 0, 1, \ldots, n-1 \} \f$. The order of + * application, in the sense of which \f$ i \f$ are processed first, + * is undefined. + * -# foldlArray, which takes as parameters: \f$ z \f$ of arbitrary type, + * an array \f$ y \f$, and a size \n. The value \f$ z \f$ will be + * overwritten to \f$ z \odot y_i \f$ for each of the + * \f$ i \in \{ 0, 1, \ldots, n-1 \} \f$. The order of application, in + * the sense of which \f$ i \f$ are processed first, is undefined. + * \endparblock + * + * \note This class only allows wrapping of stateless base operators. This + * GraphBLAS implementation in principle allows for stateful + * operators, though they must be provided by a specialised class + * which directly implements the above public interface. + * + * @see OperatorBase::apply + * @see OperatorFR::foldr + * @see OperatorFL::foldl + * @see \ref OperatorNoFRFLeWiseApply + * @see Operator::foldrArray + * @see Operator::foldlArray + * + * \parblock + * \par Providing New Operators + * + * New operators are easily added to this + * GraphBLAS implementation by providing a base operator and wrapping this + * class around it, as illustrated, e.g., by grb::operators::add as follows: + * + * \snippet ops.hpp Operator Wrapping + * + * This need to be compatible with the GraphBLAS type traits, specifically, + * the #is_operator template. To ensure this, a specialisation of it must be + * privided: + * + * \snippet ops.hpp Operator Type Traits + * \endparblock + */ + template< typename OP, enum Backend implementation = config::default_backend > + class Operator : public OperatorNoFRFL< OP > { + + private: + public: + /** The maximum block size when vectorising this operation. */ + static constexpr size_t blocksize = OperatorBase< OP >::blocksize; + + /** The left-hand side input domain of this operator. */ + typedef typename OperatorBase< OP >::D1 D1; + + /** The right-hand side input domain of this operator. */ + typedef typename OperatorBase< OP >::D2 D2; + + /** The output domain of this operator. */ + typedef typename OperatorBase< OP >::D3 D3; + + /** + * Reduces a vector of type \a InputType into a value in \a IOType + * by repeated application of this operator. The \a IOType is cast + * into \a D3 prior reduction. The \a InputType is cast into \a D1 + * during reduction. The final result is cast to IOType after + * reduction. The reduction happens `right-to-left'. + * + * This implementation relies on the \a foldr, whether it be an + * true in-place or emulated version. + * + * @param[in,out] out On input, the initial value to be used for + * reduction. On output, all elements of \a x + * have been applied to \a out. + * @param[in] x A vector of size \a n with elements of type \a left_type. + * @param[in] n A positive integer (can be 0). + */ + template< typename IOType, typename InputType > + static void foldrArray( const InputType * __restrict__ const x, IOType & out, const size_t n ) { + // prepare scalar buffer + D3 reduced = static_cast< D3 >( out ); + // prepare vectorisation buffer + D1 left_buffer[ blocksize ]; + // blockwise application + size_t i = n - 1; + while( i - blocksize + 1 < n ) { + // load into buffer + for( size_t b = 0; b < blocksize; --i, ++b ) { + left_buffer[ b ] = static_cast< D1 >( x[ i ] ); + } + // do reduce + for( size_t b = 0; b < blocksize; ++b ) { + OP::foldr( &( left_buffer[ b ] ), &reduced ); + } + } + // direct application for remainder + for( ; i < n; --i ) { + left_buffer[ 0 ] = static_cast< D1 >( x[ i ] ); + OP::foldr( left_buffer, &reduced ); + } + // write out + out = static_cast< IOType >( reduced ); + } + + /** + * Reduces a vector of type \a InputType into a value in \a IOType + * by repeated application of this operator. The \a IOType is cast + * into \a D3 prior reduction. The \a InputType is cast into \a D2 + * during reduction. The final result is cast to IOType after + * reduction. The reduction happens `left-to-right'. + * + * This implementation relies on the \a foldr, whether it be an + * true in-place or emulated version. + * + * @param[in,out] out On input, the initial value to be used for + * reduction. On output, all elements of \a x + * have been applied to \a out. + * @param[in] x A vector of size \a n with elements of type \a left_type. + * @param[in] n A positive integer (can be 0). + */ + template< typename IOType, typename InputType > + static void foldlArray( IOType & out, const InputType * __restrict__ const x, const size_t n ) { + // prepare scalar buffer + D3 reduced = static_cast< D3 >( out ); + // prepare vectorisation buffer + D2 right_buffer[ blocksize ]; + // blockwise application + size_t i = 0; + while( i + blocksize <= n ) { + // load into buffer + for( size_t b = 0; b < blocksize; ++i, ++b ) { + right_buffer[ b ] = static_cast< D2 >( x[ i ] ); + } + // do reduce + for( size_t b = 0; b < blocksize; ++b ) { + OP::foldl( &reduced, &( right_buffer[ b ] ) ); + } + } + // direct application for remainder + for( ; i < n; ++i ) { + right_buffer[ 0 ] = static_cast< D2 >( x[ i ] ); + OP::foldl( &reduced, right_buffer ); + } + // write out + out = static_cast< IOType >( reduced ); + } + }; + + } // namespace internal + + } // namespace operators + +} // namespace grb + +#endif // _H_GRB_INTERNAL_OPERATORS_BASE + diff --git a/include/alp/base/io.hpp b/include/alp/base/io.hpp new file mode 100644 index 000000000..8bb2d4c90 --- /dev/null +++ b/include/alp/base/io.hpp @@ -0,0 +1,373 @@ + +/* + * Copyright 2021 Huawei Technologies Co., Ltd. + * + * 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. + */ + +/* + * @author A. N. Yzelman + * @date 21st of February, 2017 + */ + +#ifndef _H_GRB_IO_BASE +#define _H_GRB_IO_BASE + +#include +#include +#include + +#include "matrix.hpp" +#include "vector.hpp" + +namespace grb { + + /** + * \defgroup IO Data Ingestion and Extraction. + * Provides functions for putting user data into opaque GraphBLAS objects, + * and provides functions for extracting data from opaque GraphBLAS objects. + * + * The GraphBLAS operates on opaque data objects. Users can input data using + * grb::buildVector and/or grb::buildMatrixUnique. This group provides free + * functions that automatically dispatch to those variants. + * + * The standard output methods are provided by grb::Vector::cbegin and + * grb::Vector::cend, and similarly for grb::Matrix. Iterators provide + * parallel output (see #IOMode for a discussion on parallel versus + * sequential IO). + * + * Sometimes it is desired to have direct access to a GraphBLAS memory + * area, and to have that memory available even after the GraphBLAS + * context has been closed (via grb::finalize). This functionality is + * provided by grb::pin_memory. + * + * @{ + */ + + /** + * Constructs a dense vector from a container of exactly grb::size(x) + * elements. This function aliases to the buildVector routine that takes + * an accumulator, using grb::operators::right_assign (thus overwriting + * any old contents). + */ + template< + Descriptor descr = descriptors::no_operation, + typename InputType, typename fwd_iterator, + Backend backend, typename Coords + > + RC buildVector( + Vector< InputType, backend, Coords > &x, + fwd_iterator start, const fwd_iterator end, + const IOMode mode + ) { + operators::right_assign< InputType > accum; + return buildVector< descr >( x, accum, start, end, mode ); + } + + /** + * Ingests possibly sparse input from a container to which iterators are + * provided. This function dispatches to the buildVector routine that + * includes an accumulator, here set to grb::operators::right_assign. + * Any existing values in \a x that overlap with newer values will hence + * be overwritten. + */ + template< Descriptor descr = descriptors::no_operation, + typename InputType, + class Merger = operators::right_assign< InputType >, + typename fwd_iterator1, typename fwd_iterator2, + Backend backend, typename Coords + > + RC buildVector( Vector< InputType, backend, Coords > & x, + fwd_iterator1 ind_start, const fwd_iterator1 ind_end, + fwd_iterator2 val_start, const fwd_iterator2 val_end, + const IOMode mode, const Merger & merger = Merger() + ) { + operators::right_assign< InputType > accum; + return buildVector< descr >( x, accum, ind_start, ind_end, val_start, val_end, mode, merger ); + } + + /** + * Ingests a set of nonzeroes into a given vector \a x. + * + * Old values will be overwritten. The given set of nonzeroes must not contain + * duplicate nonzeroes that should be stored at the same index. + * + * \warning Inputs with duplicate nonzeroes when passed into this function will + * invoke undefined behaviour. + * + * @param[in,out] x The vector where to ingest nonzeroes into. + * @param[in] ind_start Start iterator to the nonzero indices. + * @param[in] ind_end End iterator to the nonzero indices. + * @param[in] val_start Start iterator to the nonzero values. + * @param[in] val_end End iterator to the nonzero values. + * @param[in] mode Whether sequential or parallel ingestion is requested. + * + * The containers the two iterator pairs point to must contain an equal number + * of elements. Any pre-existing nonzeroes that do not overlap with any nonzero + * between \a ind_start and \a ind_end will remain unchanged. + * + * \parblock + * \par Performance semantics: + * A call to this function + * -# comprises \f$ \mathcal{O}( n ) \f$ work where \a n is the number of + * elements pointed to by the given iterator pairs. This work may be + * distributed over multiple user processes. + * -# results in at most \f$ n \mathit{sizeof}( T ) + + * n \mathit{sizeof}( U ) + + * n \mathit{sizeof}( \mathit{InputType} ) + + * 2 n \mathit{sizeof}( \mathit{bool} ) \f$ + * bytes of data movement, where \a T and \a U are the underlying data + * types of the input iterators. These costs may be distributed over + * multiple user processes. + * -# inter-process communication costs are \f$ \mathcal{O}(n) g + l \f$. + * -# if the capacity of this vector is not large enough to hold \a n + * elements, a call to this function may allocate + * \f$ \mathcal{O}( n ) \f$ + * new bytes of memory which \em may be distributed over multiple user + * processes. + * -# if the capacity of this vector is not large enough to hold \a n + * elements, a call to this function may result in system calls at any of + * the user processes. + * -# If the IOMode is sequential, then the work and data movement costs are + * incurred per user process and will not be distributed. In this + * case the inter-process communication costs will, however, be zero. + * -# if the IOMode is parallel, then a good implementation under a uniformly + * randomly distributed input incurs an inter-process communication cost + * of expected value \f$ n/p g + l \f$. The best-case inter-process cost + * is \f$ (p-1)g + l \f$. + * \endparblock + * + * @returns grb::SUCCESS When ingestion has completed successfully. + * @returns grb::ILLEGAL When a nonzero has an index larger than grb::size(x). + * @returns grb::PANIC If an unmitigable error has occured during ingestion. + */ + template< Descriptor descr = descriptors::no_operation, + typename InputType, + class Merger = operators::right_assign< InputType >, + typename fwd_iterator1, typename fwd_iterator2, + Backend backend, typename Coords + > + RC buildVectorUnique( Vector< InputType, backend, Coords > & x, + fwd_iterator1 ind_start, const fwd_iterator1 ind_end, + fwd_iterator2 val_start, const fwd_iterator2 val_end, + const IOMode mode + ) { + return buildVector< descr | descriptors::no_duplicates >( x, + ind_start, ind_end, + val_start, val_end, + mode ); + } + + /** + * Assigns nonzeroes to the matrix from a coordinate format. + * + * Invalidates any prior existing content. Disallows different nonzeroes + * to have the same row and column coordinates; input must consist out of + * unique triples. See #buildMatrix for an alternate function that does + * not have these restrictions-- at the cost of lower performance. + * + * \warning Calling this function with duplicate input coordinates will + * lead to undefined behaviour. + * + * @tparam descr The descriptor used. The default is + * #grb::descriptors::no_operation, which means that + * no pre- or post-processing of input or input is + * performed. + * @tparam fwd_iterator1 The type of the row index iterator. + * @tparam fwd_iterator2 The type of the column index iterator. + * @tparam fwd_iterator3 The type of the nonzero value iterator. + * @tparam length_type The type of the number of elements in each iterator. + * + * The iterators will only be used to read from, never to assign to. + * + * @param[in] I A forward iterator to \a cap row indices. + * @param[in] J A forward iterator to \a cap column indices. + * @param[in] V A forward iterator to \a cap nonzero values. + * @param[in] nz The number of items pointed to by \a I, \a J, \em and \a V. + * + * @return grb::MISMATCH -# when an element from \a I dereferences to a value + * larger than the row dimension of this matrix, or + * -# when an element from \a J dereferences to a value + * larger than the column dimension of this matrix. + * When this error code is returned the state of this + * container will be as though this function was never + * called; however, the given forward iterators may + * have been copied and the copied iterators may have + * incurred multiple increments and dereferences. + * @return grb::OVERFLW When the internal data type used for storing the + * number of nonzeroes is not large enough to store + * the number of nonzeroes the user wants to assign. + * When this error code is returned the state of this + * container will be as though this function was never + * called; however, the given forward iterators may + * have been copied and the copied iterators may have + * incurred multiple increments and dereferences. + * @return grb::SUCCESS When the function completes successfully. + * + * \parblock + * \par Performance semantics. + * -# This function contains + * \f$ \Theta(\mathit{nz})+\mathcal{O}(m+n)) \f$ amount of work. + * -# This function may dynamically allocate + * \f$ \Theta(\mathit{nz})+\mathcal{O}(m+n)) \f$ bytes of memory. + * -# A call to this function will use \f$ \mathcal{O}(m+n) \f$ bytes + * of memory beyond the memory in use at the function call entry. + * -# This function will copy each input forward iterator at most + * \em once; the three input iterators \a I, \a J, and \a V thus + * may have exactly one copyeach, meaning that all input may be + * traversed only once. + * -# Each of the at most three iterator copies will be incremented + * at most \f$ \mathit{nz} \f$ times. + * -# Each position of the each of the at most three iterator copies + * will be dereferenced exactly once. + * -# This function moves + * \f$ \Theta(\mathit{nz})+\mathcal{O}(m+n)) \f$ bytes of data. + * -# This function will likely make system calls. + * \endparblock + * + * \warning This is an expensive function. Use sparingly and only when + * absolutely necessary. + * + * \note Streaming input can be implemented by supplying buffered + * iterators to this GraphBLAS implementation. + * + * \note The functionality herein described is exactly that of buildMatrix, + * though with stricter input requirements. These requirements allow + * much faster construction. + * + * \note No masked version of this variant is provided. The use of masks in + * matrix construction is costly and the user is referred to the + * costly buildMatrix() function instead. + */ + template< Descriptor descr = descriptors::no_operation, + typename InputType, + typename fwd_iterator1 = const size_t * __restrict__, + typename fwd_iterator2 = const size_t * __restrict__, + typename fwd_iterator3 = const InputType * __restrict__, + typename length_type = size_t, + Backend implementation = config::default_backend > + RC buildMatrixUnique( + Matrix< InputType, implementation > & A, + fwd_iterator1 I, fwd_iterator1 I_end, + fwd_iterator2 J, fwd_iterator2 J_end, + fwd_iterator3 V, fwd_iterator3 V_end, + const IOMode mode + ) { + // derive synchronized iterator + auto start = utils::makeSynchronized( I, J, V, I_end, J_end, V_end ); + const auto end = utils::makeSynchronized( I_end, J_end, V_end, I_end, J_end, V_end ); + + // defer to other signature + return buildMatrixUnique< descr >( A, start, end, mode ); + } + + /** + * Alias that transforms a set of pointers and an array length to the + * buildMatrixUnique variant based on iterators. + */ + template< Descriptor descr = descriptors::no_operation, + typename InputType, + typename fwd_iterator1 = const size_t * __restrict__, + typename fwd_iterator2 = const size_t * __restrict__, + typename fwd_iterator3 = const InputType * __restrict__, + typename length_type = size_t, + Backend implementation = config::default_backend > + RC buildMatrixUnique( Matrix< InputType, implementation > &A, + fwd_iterator1 I, fwd_iterator2 J, fwd_iterator3 V, + const size_t nz, const IOMode mode + ) { + return buildMatrixUnique< descr >( A, + I, I + nz, + J, J + nz, + V, V + nz, + mode + ); + } + + /** Version of the above #buildMatrixUnique that handles \a NULL value pointers. */ + template< Descriptor descr = descriptors::no_operation, + typename InputType, + typename fwd_iterator1 = const size_t * __restrict__, + typename fwd_iterator2 = const size_t * __restrict__, + typename length_type = size_t, + Backend implementation = config::default_backend > + RC buildMatrixUnique( Matrix< InputType, implementation > & A, fwd_iterator1 I, fwd_iterator2 J, const length_type nz, const IOMode mode ) { + // derive synchronized iterator + auto start = utils::makeSynchronized( I, J, I + nz, J + nz ); + const auto end = utils::makeSynchronized( I + nz, J + nz, I + nz, J + nz ); + + // defer to other signature + return buildMatrixUnique< descr >( A, start, end, mode ); + } + + /** + * Version of buildMatrixUnique that works by supplying a single iterator + * (instead of three). + * + * This is useful in cases where the input is given as a single struct per + * nonzero, whatever this struct may be exactly, as opposed to multiple + * containers for row indices, column indices, and nonzero values. + * + * This GraphBLAS implementation provides both input modes since which one is + * more appropriate (and performant!) depends mostly on how the data happens + * to be stored in practice. + * + * @tparam descr The currently active descriptor. + * @tparam InputType The value type the output matrix expects. + * @tparam fwd_iterator The iterator type. + * @tparam implementation For which backend a matrix is being read. + * + * The iterator \a fwd_iterator, in addition to being STL-compatible, must + * support the following three public functions: + * -# S fwd_iterator.i(); which returns the row index of the current + * nonzero; + * -# S fwd_iterator.j(); which returns the columnindex of the + * current nonzero; + * -# V fwd_iterator.v(); which returns the nonzero value of the + * current nonzero. + * + * It also must provide the following public typedefs: + * -# fwd_iterator::row_coordinate_type + * -# fwd_iterator::column_coordinate_type + * -# fwd_iterator::nonzero_value_type + * + * This means a specialised iterator is required for use with this function. + * See, for example, grb::utils::internal::MatrixFileIterator. + * + * @param[out] A The matrix to be filled with nonzeroes from \a start to + * \a end. + * @param[in] start Iterator pointing to the first nonzero to be added. + * @param[in] end Iterator pointing past the last nonzero to be added. + */ + template< + Descriptor descr = descriptors::no_operation, + typename InputType, typename fwd_iterator, + Backend implementation = config::default_backend + > + RC buildMatrixUnique( Matrix< InputType, implementation > & A, + fwd_iterator start, const fwd_iterator end, + const IOMode mode + ) { + (void)A; + (void)start; + (void)end; + (void)mode; + return PANIC; + } + + /** @} */ + +} // namespace grb + +#endif // end _H_GRB_IO_BASE + diff --git a/include/alp/base/matrix.hpp b/include/alp/base/matrix.hpp new file mode 100644 index 000000000..f0f8b60cc --- /dev/null +++ b/include/alp/base/matrix.hpp @@ -0,0 +1,512 @@ + +/* + * Copyright 2021 Huawei Technologies Co., Ltd. + * + * 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. + */ + +/* + * @author A. N. Yzelman + * @date 10th of August + */ + +#ifndef _H_GRB_MATRIX_BASE +#define _H_GRB_MATRIX_BASE + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace grb { + + /** + * A GraphBLAS matrix. + * + * This is an opaque data type that implements the below functions. + * + * @tparam D The type of a nonzero element. \a D shall not be a GraphBLAS + * type. + * @tparam implementation Allows multiple backends to implement different + * versions of this data type. + * + * \warning Creating a grb::Matrix of other GraphBLAS types is + * not allowed. + * Passing a GraphBLAS type as template parameter will lead to + * undefined behaviour. + */ + template< typename D, enum Backend implementation > + class Matrix { + + typedef Matrix< D, implementation > self_type; + + public : + + /** + * A standard iterator for a GraphBLAS aatrix. + * + * This iterator is used for data extraction only. Hence only this const + * version is specified. + * + * Dereferencing an iterator of this type that is not in end position yields + * a pair \f$ (c,v) \f$. The value \a v is of type \a D and corresponds to + * the value of the dereferenced nonzero. + * The value \a c is another pair \f$ (i,j) \f$. The values \a i and \a j + * are of type size_t and correspond to the coordinate of the + * dereferenced nonzero. + * + * \note `Pair' here corresponds to the regular std::pair. + * + * \warning Comparing two const iterators corresponding to different + * containers leads to undefined behaviour. + * \warning Advancing an iterator past the end iterator of the container + * it corresponds to, leads to undefined behaviour. + * \warning Modifying the contents of a container makes any use of any + * iterator derived from it incur invalid behaviour. + * \note These are standard limitations of STL iterators. + */ + class const_iterator : public std::iterator< std::forward_iterator_tag, std::pair< std::pair< const size_t, const size_t >, const D >, size_t > { + + public : + + /** Standard equals operator. */ + bool + operator==( const const_iterator & other ) const { (void)other; return false; } + + /** @returns The negation of operator==(). */ + bool operator!=( const const_iterator & other ) const { + (void)other; + return true; + } + + /** + * Dereferences the current position of this iterator. + * + * @return If this iterator is valid and not in end position, this returns + * an std::pair with in its first field the position of the + * nonzero value, and in its second field the value of the nonzero. + * The position of a nonzero is another std::pair with both the + * first and second field of type size_t. + * + * \note If this iterator is invalid or in end position, the result is + * undefined. + */ + std::pair< const size_t, const D > operator*() const { + return std::pair< const size_t, const D >(); + } + + /** + * Advances the position of this iterator by one. + * + * If the current position corresponds to the last element in the + * container, the new position of this iterator will be its end + * position. + * + * If the current position of this iterator is already the end + * position, this iterator will become invalid; any use of invalid + * iterators will lead to undefined behaviour. + * + * @return A reference to this iterator. + */ + const_iterator & operator++() { + return *this; + } + +}; // namespace grb + +/** The value type of elements stored in this matrix. */ +typedef D value_type; + +/** + * The main GraphBLAS matrix constructor. + * + * Matrix nonzeroes will be uninitalised after successful construction. + * + * Requesting a matrix with zero \a rows or \a columns will yield an empty + * matrix; i.e., it will be useless but will not result in an error. + * + * @param rows The number of rows in the new matrix. + * @param columns The number of columns in the new matrix. + * + * @return SUCCESS This function never fails. + * + * \parblock + * \par Performance semantics. + * -# This constructor completes in \f$ \Theta(1) \f$ time. + * -# This constructor will not allocate any new dynamic memory. + * -# This constructor will use \f$ \Theta(1) \f$ extra bytes of + * memory beyond that at constructor entry. + * -# This constructor incurs \f$ \Theta(1) \f$ data movement. + * -# This constructor \em may make system calls. + * \endparblock + * + * \warning Avoid the use of this constructor within performance critical + * code sections. + */ +Matrix( const size_t rows, const size_t columns ) { + (void)rows; + (void)columns; +} + +/** + * Copy constructor. + * + * @param other The matrix to copy. + * + * \parblock + * \par Performance semantics. + * Allocates the same capacity as the \a other matrix, even if the + * actual number of nonzeroes contained in \a other is less. + * -# This constructor entails \f$ \Theta(\mathit{nz}) \f$ amount of + * work. + * -# This constructor allocates \f$ \Theta(\mathit{nz}) \f$ bytes + * of dynamic memory. + * -# This constructor incurs \f$ \Theta(\mathit{nz}) \f$ of data + * movement. + * -# This constructor \em may make system calls. + * \endparblock + * + * \warning Avoid the use of this constructor within performance critical + * code sections. + */ +Matrix( const Matrix< D, implementation > & other ) { + (void)other; +} + +/** + * Move constructor. This will make the new matrix equal to the given + * GraphBLAS matrix while destroying the given matrix. + * + * @param[in] other The GraphBLAS matrix to move to this new instance. + * + * \parblock + * \par Performance semantics. + * -# This constructor entails \f$ \Theta(1) \f$ amount of work. + * -# This constructor will not allocate any new dynamic memory. + * -# This constructor will use \f$ \Theta(1) \f$ extra bytes of + * memory beyond that at constructor entry. + * -# This constructor will move \f$ \Theta(1) \f$ bytes of data. + * \endparblock + */ +Matrix( self_type && other ) { + (void)other; +} + +/** + * Matrix destructor. + * + * \parblock + * \par Performance semantics. + * -# This destructor entails \f$ \Theta(1) \f$ amount of work. + * -# This destructor will not perform any memory allocations. + * -# This destructor will use \f$ \mathcal{O}(1) \f$ extra bytes of + * memory beyond that at constructor entry. + * -# This destructor will move \f$ \Theta(1) \f$ bytes of data. + * -# This destructor makes system calls. + * \endparblock + * + * \warning Avoid calling destructors from within performance critical + * code sections. + */ +~Matrix() {} + +/** + * Assigns nonzeroes to the matrix from a coordinate format. + * + * Any prior content may be combined with new input according to the + * user-supplied accumulator operator (\a accum). + * + * Input triplets need not be unique. Input triplets that are written to the + * same row and column coordinates will be combined using the supplied + * duplicate operator (\a dup). + * + * \note Note that \a dup and \a accum may differ. The duplicate operator is + * \em not applied to any pre-existing nonzero values. + * + * \note The order of application of the operators is undefined. + * + * The number of nonzeroes, after reduction by duplicate removals and after + * merger with the existing nonzero structure, must be equal or less than the + * space reserved during the construction of this matrix. The nonzeroes will + * not be stored in a fully sorted fashion-- it will be sorted column-wise, + * but within each column the order can be arbitrary. + * + * @tparam accum How existing entries of this matrix should be + * treated. + * The default is #grb::operators::right_assign, which + * means that any existing values are overwritten with + * the new values. + * @tparam dup How to handle duplicate entries. The default is + * #grb::operators::add, which means that duplicated + * values are combined by addition. + * @tparam descr The descriptor used. The default is + * #grb::descriptors::no_operation, which means that + * no pre- or post-processing of input or input is + * performed. + * @tparam fwd_iterator1 The type of the row index iterator. + * @tparam fwd_iterator2 The type of the column index iterator. + * @tparam fwd_iterator3 The type of the nonzero value iterator. + * @tparam length_type The type of the number of elements in each iterator. + * @tparam T The type of the supplied mask. + * + * \note By default, the iterator types are raw, unaliased, pointers. + * + * \warning This means that by default, input arrays are \em not + * allowed to overlap. + * + * Forward iterators will only be used to read from, never to assign to. + * + * \note It is therefore both legal and preferred to pass constant forward + * iterators, as opposed to mutable ones as \a I, \a J, and \a V. + * + * @param[in] I A forward iterator to \a cap row indices. + * @param[in] J A forward iterator to \a cap column indices. + * @param[in] V A forward iterator to \a cap nonzero values. + * @param[in] nz The number of items pointed to by \a I, \a J, \em and + * \a V. + * @param[in] mask An input element at coordinate \f$ (i,j) \f$ will only be + * added to this matrix if there exists a matching element + * \f$ \mathit{mask}_{ij} \f$ in the given \a mask that + * eveluates true. The matrix in \a mask must be + * of the same dimension as this matrix. + * + * @return grb::MISMATCH -# when an element from \a I dereferences to a value + * larger than the row dimension of this matrix, or + * -# when an element from \a J dereferences to a value + * larger than the column dimension of this matrix. + * When this error code is returned the state of this + * container will be as though this function was never + * called; however, the given forward iterators may + * have been copied and the copied iterators may have + * incurred multiple increments and dereferences. + * @return grb::OVERFLW When the internal data type used for storing the + * number of nonzeroes is not large enough to store + * the number of nonzeroes the user wants to assign. + * When this error code is returned the state of this + * container will be as though this function was never + * called; however, the given forward iterators may + * have been copied and the copied iterators may have + * incurred multiple increments and dereferences. + * @return grb::SUCCESS When the function completes successfully. + * + * \parblock + * \par Performance semantics. + * -# This function contains + * \f$ \Theta(\mathit{nz}\log\mathit{nz})+\mathcal{O}(m+n)) \f$ + * amount of work. + * -# This function may dynamically allocate + * \f$ \Theta(\mathit{nz})+\mathcal{O}(m+n)) \f$ bytes of memory. + * -# A call to this function will use \f$ \mathcal{O}(m+n) \f$ bytes + * of memory beyond the memory in use at the function call entry. + * -# This function will copy each input forward iterator at most + * \em twice; the three input iterators \a I, \a J, and \a V thus + * may have exactly two copies each, meaning that all input may be + * traversed \em twice. + * -# Each of the at most six iterator copies will be incremented at + * most \f$ \mathit{nz} \f$ times. + * -# Each position of the each of the at most six iterator copies + * will be dereferenced exactly once. + * -# This function moves + * \f$ \Theta(\mathit{nz})+\mathcal{O}(m+n)) \f$ bytes of data. + * -# If the mask is nonempty, the performance costs of grb::eWiseMul + * on two matrix arguments must be added to the above costs. + * -# This function will likely make system calls. + * \endparblock + * + * \warning This is an extremely expensive function. Use sparingly and only + * when absolutely necessary + * + * \note Streaming input can be implemented by supplying buffered + * iterators to this GraphBLAS implementation. + */ +template< Descriptor descr = descriptors::no_operation, + template< typename, typename, typename > class accum = operators::right_assign, + template< typename, typename, typename > class dup = operators::add, + typename fwd_iterator1 = const size_t * __restrict__, + typename fwd_iterator2 = const size_t * __restrict__, + typename fwd_iterator3 = const D * __restrict__, + typename length_type = size_t, + typename T > +RC buildMatrix( const fwd_iterator1 I, const fwd_iterator2 J, const fwd_iterator3 V, const length_type nz, const Matrix< T, implementation > & mask ) { + (void)I; + (void)J; + (void)V; + (void)nz; + (void)mask; + return PANIC; +} + +//@{ +/** + * Provides the only mechanism to extract data from a GraphBLAS matrix. + * + * The order in which nonzero elements are returned is undefined. + * + * @return An iterator pointing to the first element of this matrix, if any; + * \em or an iterator in end position if this vector contains no + * nonzeroes. + * + * \note An `iterator in end position' compares equal to the const_iterator + * returned by cend(). + * + * \parblock + * \par Performance semantics + * -# This function contains \f$ \mathcal{O}(1) \f$ work. + * -# This function is allowed allocate dynamic memory. + * -# This function uses up to \f$ \mathcal{O}(1) \f$ more memory + * than already used by this application at entry. + * -# This function shall move at most \f$ \mathcal{O}(1) \f$ bytes + * of data. + * -# This function may make system calls. + * \endparblock + * + * \warning Avoid the use of this function within performance critical code + * sections. + * + * \note This function may make use of a const_iterator that is buffered, + * hence possibly causing its implicitly called constructor to + * allocate dynamic memory. + */ +const_iterator cbegin() const {} + +/** + * Same as cbegin(). + * Since iterators are only supplied as a data extraction mechanism, there + * is no overloaded version of this function that returns a non-const + * iterator. + */ +const_iterator begin() const {} +//@} + +//@{ +/** + * Indicates the end to the elements in this container. + * + * @return An iterator at the end position of this container. + * + * \parblock + * \par Performance semantics + * -# This function contains \f$ \mathcal{O}(1) \f$ work. + * -# This function is not allowed allocate dynamic memory. + * -# This function uses up to \f$ \mathcal{O}(1) \f$ more memory + * than already used by this application at entry. + * -# This function shall move at most \f$ \mathcal{O}(1) \f$ bytes + * of data. + * -# This function shall \em not induce any system calls. + * \endparblock + * + * \note Even if cbegin() returns a buffered const_iterator that may require + * dynamic memory allocation and additional data movement, this + * specification disallows the same to happen for the construction of + * an iterator in end position. + */ +const_iterator cend() const {} + +/** + * Same as cend(). + * Since iterators are only supplied as a data extraction mechanism, there + * is no overloaded version of this function that returns a non-const + * iterator. + */ +const_iterator end() const {} +//@} +} +; + +template< typename InputType, Backend backend > +RC clear( Matrix< InputType, backend > & A ) noexcept { + // this is the generic stub implementation + return UNSUPPORTED; +} + +template< typename T, typename Structure, enum Density density, typename View, enum Backend backend > +class StructuredMatrix { + + /** + * The two following members define the \em logical layout of a structured matrix: + * Its structure and access relations. This is enabled only if the structured matrix + * does not define a View on another matrix. + */ + using structure = Structure; + /** + * A pair of pointers to index mapping functions (see imf.hpp) that express the + * logical access to the structured matrix. + */ + std::shared_ptr imf_l, imf_r; + + /** + * When a structured matrix instanciate a \em container it defines a new \em physical + * (concrete?) layout. This is characterized by an ALP container (aka a \a Matrix) and a + * storage scheme that defines a unique interpretation of its content. + * The combination of the logical and physical layout of a structured matrix enables to + * identify a precise mapping between an element in the structured matrix and a position + * wihtin one or more 1/2D-arrays that store it. + */ + Matrix< T, reference_dense > * _container; + + /** + * A container's storage scheme. \a storage_scheme is not exposed to the user as an option + * but can defined by ALP at different points in the execution depending on the \a backend choice. + * For example, if the container is associated to an I/O matrix, with a reference backend + * it might be set to reflect the storage scheme of the user data as specified at buildMatrix. + * If \a backend is set to \a mlir then the scheme could be fixed by the JIT compiler to effectively + * support its optimization strategy. + * At construction time and until the moment the scheme decision is made it may be set to + * an appropriate default choice, e.g. if \a density is \a Density::Dense then + * \a Density::Dense::full could be used. + * \internal \todo Revisit this. The change of storage scheme type to enum (dense/sparse) and + * implementing storage mapping functions requires a change of this spec. + */ + // Storage storage_scheme; + + /** + * When a structured matrix defines a View over another matrix, it contains a pointer + * to the latter. Its type can be identified via the View parameter. + */ + using target_type = typename std::enable_if >::value, typename View::applied_to>::type; + target_type * ref; + + public : + + StructuredMatrix( const size_t m, const size_t n ); + + StructuredMatrix( const StructuredMatrix< T, Structure, density, View, backend > & other ); + + StructuredMatrix( StructuredMatrix< T, Structure, density, View, backend > && other ); + + ~StructuredMatrix(); + +}; // class StructuredMatrix + +/** + * Check if type \a T is a StructuredMatrix. + */ +template< typename T > +struct is_structured_matrix : std::false_type {}; +template< typename T, typename Structure, enum Density density, typename View, enum Backend backend > +struct is_structured_matrix< StructuredMatrix< T, Structure, density, View, backend > > : std::true_type {}; + +} // end namespace ``grb'' + +#endif // end _H_GRB_MATRIX_BASE diff --git a/include/alp/base/scalar.hpp b/include/alp/base/scalar.hpp new file mode 100644 index 000000000..06075d3e8 --- /dev/null +++ b/include/alp/base/scalar.hpp @@ -0,0 +1,228 @@ + +/* + * Copyright 2021 Huawei Technologies Co., Ltd. + * + * 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. + */ + +#ifndef _H_GRB_SCALAR_BASE +#define _H_GRB_SCALAR_BASE + +#include //size_t +#include + +#include +#include +#include +#include + +namespace grb { + + /** + * \brief An ALP scalar. + * + * This is an opaque data type for scalars. + * + * @tparam T The type of the vector elements. \a T shall not + * be an ALP type. + * @tparam Structure One of the structures. One of possible use cases + * for a structured scalar is a random structure. + * Depending on the backend implementation, this may mean, + * for example, randomizing the scalar value on each + * interaction with the scalar. + * + * \warning Creating a grb::Scalar of other ALP types is + * not allowed. + * Passing a ALP type as template parameter will lead to + * undefined behaviour. + * + */ + template< typename T, typename Structure, enum Backend backend > + class Scalar { + + public: + /** @see Vector::value_type. */ + typedef T value_type; + + /** @see Vector::lambda_reference */ + typedef T& lambda_reference; + + /** + * The default ALP scalar constructor. + * + * The constructed object will be uninitalised after successful construction. + * + * + * \parblock + * \par Performance semantics. + * -# This constructor entails \f$ \Theta(1) \f$ amount of work. + * -# This constructor may allocate \f$ \Theta(1) \f$ bytes + * of dynamic memory. + * -# This constructor will use \f$ \Theta(1) \f$ extra bytes of + * memory beyond that at constructor entry. + * -# This constructor incurs \f$ \Theta(1) \f$ data movement. + * -# This constructor \em may make system calls. + * \endparblock + * + */ + Scalar() {} + + /** + * The ALP scalar constructor for converting a reference to C/C++ scalar + * to ALP scalar. + * + * The constructed object will be initialized after successful construction. + * + * + * \parblock + * \par Performance semantics. + * -# This constructor entails \f$ \Theta(1) \f$ amount of work. + * -# This constructor may allocate \f$ \Theta(1) \f$ bytes + * of dynamic memory. + * -# This constructor will use \f$ \Theta(1) \f$ extra bytes of + * memory beyond that at constructor entry. + * -# This constructor incurs \f$ \Theta(1) \f$ data movement. + * -# This constructor \em may make system calls. + * \endparblock + * + * \warning This constructor saves the reference to the provied value. + * Therefore, the changes to the container or the value will + * be mirrored into each-other. For preserving the separation, + * use Scalar( const T ) version. + * + */ + explicit Scalar( T &value ) { + (void)value; + } + + /** + * The ALP scalar constructor for converting a C/C++ scalar to ALP scalar. + * + * The constructed object will be initialized after successful construction. + * + * + * \parblock + * \par Performance semantics. + * -# This constructor entails \f$ \Theta(1) \f$ amount of work. + * -# This constructor may allocate \f$ \Theta(1) \f$ bytes + * of dynamic memory. + * -# This constructor will use \f$ \Theta(1) \f$ extra bytes of + * memory beyond that at constructor entry. + * -# This constructor incurs \f$ \Theta(1) \f$ data movement. + * -# This constructor \em may make system calls. + * \endparblock + * + */ + explicit Scalar( T value ) { + (void)value; + } + + /** + * Copy constructor. + * + * @param other The scalar to copy. The initialization state of the copy + * reflects the state of \a other. + * + * \parblock + * \par Performance semantics. + * -# This constructor entails \f$ \Theta(1) \f$ amount of work. + * -# This constructor allocates \f$ \Theta(1) \f$ bytes + * of dynamic memory. + * -# This constructor incurs \f$ \Theta(1) \f$ of data + * movement. + * -# This constructor \em may make system calls. + * \endparblock + * + */ + Scalar( const Scalar &other ) noexcept { + (void)other; + } + + /** + * Move constructor. The new scalar equals the given + * scalar. Invalidates the use of the input scalar. + * + * @param[in] other The ALP scalar to move to this new instance. + * + * \parblock + * \par Performance semantics. + * -# This constructor entails \f$ \Theta(1) \f$ amount of work. + * -# This constructor will not allocate any new dynamic memory. + * -# This constructor will use \f$ \Theta(1) \f$ extra bytes of + * memory beyond that at constructor entry. + * -# This constructor will move \f$ \Theta(1) \f$ bytes of data. + * \endparblock + */ + Scalar( Scalar &&other ) noexcept { + (void)other; + } + + /** + * Returns a lambda reference to the value of this Scalar. The user + * ensures that the requested reference only corresponds to a pre-existing + * nonzero in this scalar, or undefined behaviour will occur. + * This addresses the sparse specialization of scalars. In the dense + * context, scalar is considered to have a nonzero value \em iff initialized. + * + * A lambda reference to the value of this scalar is only valid when used + * inside a lambda function evaluated via grb::eWiseLambda. Outside this + * scope the returned reference incurs undefined behaviour. + * + * + * \warning In parallel contexts the use of a returned lambda reference + * outside the context of an eWiseLambda will incur at least one of + * the following ill effects: it may + * -# fail outright, + * -# work on stale data, + * -# work on incorrect data, or + * -# incur high communication costs to guarantee correctness. + * In short, such usage causes undefined behaviour. Implementers are + * \em not advised to provide GAS-like functionality through this + * interface, as it invites bad programming practices and bad + * algorithm design decisions. This operator is instead intended to + * provide for generic BLAS0-type operations only. + * + * \note For I/O, use the iterator retrieved via cbegin() instead of + * relying on a lambda_reference. + * + * @return A lambda reference to the value of this scalar + * + * \par Example. + * See grb::eWiseLambda() for a practical and useful example. + * + * \warning There is no similar concept in the official GraphBLAS specs. + * + * @see lambda_reference For more details on the returned reference type. + * @see grb::eWiseLambda For one legal way in which to use the returned + * #lambda_reference. + */ + lambda_reference operator*() noexcept { +#ifndef _GRB_NO_EXCEPTIONS + assert( false ); // Requesting lambda reference of unimplemented Scalar backend. +#endif + } + + /** Returns a constant reference to the scalar value. + * See the non-constant variant for further details. + */ + const lambda_reference operator*() const noexcept { +#ifndef _GRB_NO_EXCEPTIONS + assert( false ); // Requesting lambda reference of unimplemented Scalar backend. +#endif + } + + }; // class Scalar + +} // namespace grb + +#endif // _H_GRB_SCALAR_BASE diff --git a/include/alp/base/vector.hpp b/include/alp/base/vector.hpp new file mode 100644 index 000000000..62b18f6d3 --- /dev/null +++ b/include/alp/base/vector.hpp @@ -0,0 +1,883 @@ + +/* + * Copyright 2021 Huawei Technologies Co., Ltd. + * + * 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. + */ + +/* + * @author A. N. Yzelman + * @date 10th of August, 2016 + */ + +#ifndef _H_GRB_VECTOR_BASE +#define _H_GRB_VECTOR_BASE + +#include //size_t +#include //std::iterator +#include +#include //pair + +#include +#include +#include +#include +#include + +namespace grb { + + /** + * A GraphBLAS vector. This is an opaque data type that can be provided to + * any GraphBLAS function, such as, grb::eWiseMulAdd, for example. + * + * @tparam D The type of an element of this vector. \a D shall not be a + * GraphBLAS type. + * @tparam implementation Allows different backends to implement different + * versions of this data type. + * @tparam C The type of the class that keeps track of sparsity structure. + * + * \warning Creating a grb::Vector of other GraphBLAS types is + * not allowed. + * Passing a GraphBLAS type as template parameter will lead to + * undefined behaviour. + * + * \note The implementation found in the same file as this documentation + * catches invalid backends only. This class should never compile. + * + * @see grb::Vector< D, reference, C > for an actual implementation example. + */ + template< typename D, enum Backend implementation, typename C > + class Vector { + + public : + + /** The type of elements stored in this vector. */ + typedef D value_type; + + /** + * Defines a reference to a value of type \a D. This reference is only valid + * when used inside a lambda function that is passed to grb::eWiseLambda(). + * + * \warning Any other use of this reference incurs undefined behaviour. + * + * \par Example. + * An example valid use: + * \code + * void f( + * Vector< D >::lambda_reference x, + * const Vector< D >::lambda_reference y, + * const Vector< D > &v + * ) { + * grb::eWiseLambda( [x,y](const size_t i) { + * x += y; + * }, v ); + * } + * \endcode + * This code adds \a y to \a x for every element in \a v. For a more useful + * example, see grb::eWiseLambda. + * + * \warning Note that, unlike the above, this below code is illegal since it + * does not evaluate via a lambda passed to any of the above + * GraphBLAS lambda functions (such as grb::eWiseLambda). + * \code{.cpp} + * void f( + * Vector< D >::lambda_reference x, + * const Vector< D >::lambda_reference y + * ) { + * x += y; + * } + * \endcode + * Also this usage is illegal since it does not rely on any + * GraphBLAS-approved function listed above: + * \code{.cpp} + * void f( + * Vector< D >::lambda_reference x, + * const Vector< D >::lambda_reference y + * ) { + * std::functional< void() > f = + * [x,y](const size_t i) { + * x += y; + * }; + * f(); + * } + * \endcode + * + * \warning There is no similar concept in the official GraphBLAS specs. + * + * @see grb::Vector::operator[]() + * @see grb::eWiseLambda + */ + typedef D & lambda_reference; + + /** + * A standard iterator for the Vector< D > class. + * + * This iterator is used for data extraction only. Hence only this const + * version is supplied. + * + * \warning Comparing two const iterators corresponding to different + * containers leads to undefined behaviour. + * \warning Advancing an iterator past the end iterator of the container + * it corresponds to leads to undefined behaviour. + * \warning Modifying the contents of a container makes any use of any + * iterator derived from it incur invalid behaviour. + * \note These are standard limitations of STL iterators. + */ + class const_iterator : public std::iterator< std::forward_iterator_tag, std::pair< const size_t, const D >, size_t > { + + public : + + /** Standard equals operator. */ + bool + operator==( const const_iterator & other ) const { (void)other; return false; } + + /** @returns The negation of operator==(). */ + bool operator!=( const const_iterator & other ) const { + (void)other; + return true; + } + + /** + * Dereferences the current position of this iterator. + * + * @return If this iterator is valid and not in end position, + * this returns a new std::pair with in its first + * field the position of the nonzero value, and in its + * second field the value of the nonzero. + * + * \note If this iterator is invalid or in end position, the result is, + * undefined. + */ + std::pair< const size_t, const D > operator*() const { + return std::pair< const size_t, const D >(); + } + + /** + * Advances the position of this iterator by one. + * + * If the current position corresponds to the last element in the + * container, the new position of this iterator will be its end + * position. + * + * If the current position of this iterator is already the end + * position, this iterator will become invalid; any use of invalid + * iterators will lead to undefined behaviour. + * + * @return A reference to this iterator. + */ + const_iterator & operator++() { + return *this; + } + + }; + + /** + * The only way to create an empty GraphBLAS vector. The given dimension will + * be fixed throughout the lifetime of this container. + * + * The vector will be empty after successful construction. + * + * @param[in] n The dimension of this vector. + * + * \parblock + * \par Performance semantics + * -# This constructor completes in \f$ \mathcal{O}(n) \f$ time. + * -# This constructor allocates \f$ \mathcal{O}(n) \f$ bytes of + * dynamic memory. + * -# This constructor moves at most \f$ \mathcal{O}( n ) \f$ bytes + * of data. + * -# This constructor may make system calls. + * \endparblock + * + * \warning Avoid the use of this constructor within performance critical + * code sections. + */ + Vector( const size_t n ) { + (void)n; + } + + /** + * Move constructor. + * + * This will make the new vector equal the given GraphBLAS vector while + * destroying the supplied GraphBLAS vector. + * + * This function always succeeds and will not throw exceptions. + * + * @param[in] x The GraphBLAS vector to move to this new container. + * + * \parblock + * \par Performance semantics + * -# This constructor completes in \f$ \Theta(1) \f$ time. + * -# This constructor does not allocate new data on the heap. + * -# This constructor uses \f$ \mathcal{O}(1) \f$ more memory than + * already used by this application at constructor entry. + * -# This constructor incurs at most \f$ \mathcal{O}(1) \f$ bytes of + * data movement. + * \endparblock + */ + Vector( Vector< D, implementation, C > &&x ) noexcept { + (void)x; + } + + /** + * Move-from-temporary assignment. + * + * @param[in,out] x The temporary instance from which this instance shall + * take over its resources. + * + * After a call to this function, \a x shall correspond to an empy vector. + * + * \parblock + * \par Performance semantics + * -# This move assignment completes in \f$ \Theta(1) \f$ time. + * -# This move assignment may not make system calls. + * -# this move assignment moves \f$ \Theta(1) \f$ data only. + * \endparblock + */ + Vector< D, implementation, C >& operator=( Vector< D, implementation, C > &&x ) noexcept { + (void)x; + return *this; + } + + /** + * Default destructor. Frees all associated memory areas. + * + * \parblock + * \par Performance semantics + * -# This destructor contains \f$ \mathcal{O}(n) \f$ work, where + * \f$ n \f$ is the capacity of this vector. + * -# This destructor is only allowed to free memory, not allocate. + * -# This destructor uses \f$ \mathcal{O}(1) \f$ more memory than + * already used by this application at entry. + * -# This destructor shall move at most \f$ \mathcal{O}(n) \f$ bytes + * of data. + * -# This destructor will make system calls. + * \endparblock + * + * \warning Avoid the use of this destructor within performance critical + * code sections. + * + * \note Destruction of this GraphBLAS container is the only way to + * guarantee that any underlying dynamically allocated memory is + * freed. + */ + ~Vector() {} + + //@{ + /** + * Provides the only mechanism to extract data from this GraphBLAS vector. + * + * The order in which nonzero elements are returned is undefined. + * + * @return An iterator pointing to the first element of this vector, if any; + * \em or an iterator in end position if this vector contains no + * nonzeroes. + * + * \note An `iterator in end position' compares equal to the const_iterator + * returned by cend(). + * + * \parblock + * \par Performance semantics + * -# This function contains \f$ \mathcal{O}(1) \f$ work. + * -# This function is allowed allocate dynamic memory. + * -# This function uses up to \f$ \mathcal{O}(1) \f$ more memory + * than already used by this application at entry. + * -# This function shall move at most \f$ \mathcal{O}(1) \f$ bytes + * of data. + * -# This function may make system calls. + * \endparblock + * + * \warning Avoid the use of this function within performance critical code + * sections. + * + * \note This function may make use of a const_iterator that is buffered, + * hence possibly causing its implicitly called constructor to + * allocate dynamic memory. + */ + const_iterator cbegin() const {} + + /** + * Same as cbegin(). + * Since iterators are only supplied as a data extraction mechanism, there + * is no overloaded version of this function that returns a non-const + * iterator. + */ + const_iterator begin() const {} + //@} + + //@{ + /** + * Indicates the end to the elements in this container. + * + * @return An iterator at the end position of this container. + * + * \parblock + * \par Performance semantics + * -# This function contains \f$ \mathcal{O}(1) \f$ work. + * -# This function is not allowed allocate dynamic memory. + * -# This function uses up to \f$ \mathcal{O}(1) \f$ more memory + * than already used by this application at entry. + * -# This function shall move at most \f$ \mathcal{O}(1) \f$ bytes + * of data. + * -# This function shall \em not induce any system calls. + * \endparblock + * + * \note Even if cbegin() returns a buffered const_iterator that may require + * dynamic memory allocation and additional data movement, this + * specification disallows the same to happen for the construction of + * an iterator in end position. + */ + const_iterator cend() const {} + + /** + * Same as cend(). + * Since iterators are only supplied as a data extraction mechanism, there + * is no overloaded version of this function that returns a non-const + * iterator. + */ + const_iterator end() const {} + //@} + + /** + * Copy from raw user-supplied data into a vector. + * + * This is the dense unmasked variant. + * + * @tparam descr The pre-processing descriptor to use. + * @tparam fwd_iterator The type of input iterator. By default, this will be + * a raw \em unaliased pointer. + * @tparam Accum The accumulator type used to merge incoming new + * elements with existing contents, if any. + * + * @param[in] accum The accumulator used to merge incoming new elements with + * existing content, if any. + * @param[in] start The iterator to the first element that should be copied + * into this GraphBLAS vector. + * @param[in] end Iterator shifted exactly one past the last element that + * should be copied into this GraphBLAS vector. + * @param[out] npos The last iterator position after exiting this function. + * In most cases this will equal \a end. This parameter is + * optional. + * + * The first element from \a it will be copied into the element with index + * \f$ 0 \f$ in this vector. The \f$ k \f$-th element will be copied into + * the element with index \f$ k - 1 \f$. The iterator \a start will be + * incremented along with \f$ k \f$ until it compares equal to \a end, or + * until it has been incremented \a n times, where \a n is the dimension of + * this vector. In the latter case, any remaining values are ignored. + * + * @return grb::SUCCESS This function always succeeds. + * + * \note The default accumulator expects \a val to be of the same type + * as nonzero elements in this function, and will cause old + * values to be overwritten by the incoming new values. + * + * \note Previous contents of the vector are retained. If these are to be + * cleared first, see clear(). The default accumulator is NOT an + * alternative since any pre-existing values corresponding to entries + * in the mask that evaluate to false will be retained. + * + * \note The parameter \a n can be used to ingest only a subset of a larger + * data structure pointed to by \a start. At the end of the call, \a + * start will then not be equal to \a end, but instead point to the + * first element of the remainder of the larger data structure. + * + * \par Valid descriptors + * grb::descriptors::no_operation, grb::descriptors::no_casting. + * + * \note Invalid descriptors will be ignored. + * + * If grb::descriptors::no_casting is specified, then 1) the first domain of + * \a accum must match the type of \a val, 2) the second domain must match + * the type \a D of nonzeroes in this vector, and 3) the third domain must + * match \a D. If one of these is not true, the code shall not compile. + * + * \parblock + * \par Performance semantics + * If the capacity of this container is sufficient to perform the + * requested operation, then: + * -# This function contains \f$ \Theta(n) \f$ work. + * -# This function will take at most \f$ \Theta(1) \f$ memory beyond + * the memory already used by the application before the call to + * this function. + * -# This function moves at most \f$ n ( 2\mathit{sizeof}(D) + + * \mathit{sizeof}(\mathit{bool}) ) + \mathcal{O}(1) \f$ bytes of + * data. + * \endparblock + * + * \parblock + * \par Performance exceptions + * If the capacity of this container at function entry is insufficient + * to perform the requested operation, then, in addition to the above: + * -# this function allocates \f$ \Theta(n) \f$ bytes of memory . + * -# this function frees \f$ \mathcal{O}(n) \f$ bytes of memory. + * -# this function will make system calls. + * \endparblock + * + * \note An implementation may ensure that at object construction the + * capacity is maximised. In that case, the above performance + * exceptions will never come to pass. + * + * @see grb::buildVector for the GraphBLAS standard dispatcher to this + * function. + */ + template< Descriptor descr = descriptors::no_operation, class Accum = typename operators::right_assign< D, D, D >, typename fwd_iterator = const D * __restrict__ > + RC build( const Accum & accum, const fwd_iterator start, const fwd_iterator end, fwd_iterator npos ) { + (void)accum; + (void)start; + (void)end; + (void)npos; + return PANIC; + } + + /** + * Copy from raw user-supplied data into a vector. + * + * This is the sparse non-masked variant. + * + * @tparam descr The pre-processing descriptor to use. + * @tparam Accum The type of the operator used to combine newly input + * data with existing data, if any. + * @tparam ind_iterator The type of index input iterator. By default, this + * will be a raw \em unaliased pointer to elements of + * type \a size_t. + * @tparam nnz_iterator The type of nonzero input iterator. By default, this + * will be a raw \em unaliased pointer to elements of + * type \a D. + * @tparam Dup The type of operator used to combine any duplicate + * input values. + * + * @param[in] accum The operator to be used when writing back the result + * of data that was already in this container prior to + * calling this function. + * @param[in] ind_start The iterator to the first index value that should be + * added to this GraphBLAS vector. + * @param[in] ind_end Iterator corresponding to the end position of + * \a ind_start. + * @param[in] nnz_start The iterator to the first nonzero value that should + * be added to this GraphBLAS vector. + * @param[in] nnz_end Iterator corresponding to the end position of + * \a nnz_start. + * @param[in] dup The operator to be used when handling multiple + * nonzero values that are to be mapped to the same + * index position. + * + * The first element from \a nnz_start will be copied into this vector at + * the index corresponding to the first element from \a ind_start. Then, + * both nonzero and index value iterators advance to add the next input + * element and the process repeats until either of the input iterators + * reach \a nnz_end or \a ind_end, respectively. + * If at that point one of the iterators still has remaining elements, then + * those elements are ignored. + * + * @return grb::MISMATCH When attempting to insert a nonzero value at an + * index position that is larger or equal to the + * dimension of this vector. When this code is + * returned, the contents of this container are + * undefined. + * @return grb::SUCCESS When all elements are successfully assigned. + * + * \note The default accumulator expects \a D to be of the same type + * as nonzero elements of this operator, and will cause old + * values to be overwritten by the incoming new values. + * + * \note The default \a dup expects \a D to be of the same type as nonzero + * elements of this operator, and will cause duplicate values to be + * discarded in favour of the last seen value. + * + * \note Previous contents of the vector are retained. If these are to be + * cleared first, see clear(). The default accumulator is NOT an + * alternative since any pre-existing values corresponding to entries + * in the mask that evaluate to false will be retained. + * + * \par Valid descriptors + * grb::descriptors::no_operation, grb::descriptors::no_casting, + * grb::descriptors::no_duplicates. + * + * \note Invalid descriptors will be ignored. + * + * If grb::descriptors::no_casting is specified, then 1) the first domain of + * \a accum must match the type of \a D, 2) the second domain must match + * nnz_iterator::value_type, and 3) the third domain must \a D. If one of + * these is not true, the code shall not compile. + * + * \parblock + * \par Performance semantics. + * -# This function contains \f$ \Theta(n) \f$ work. + * -# This function will take at most \f$ \Theta(1) \f$ memory beyond + * the memory already used by the application before the call to + * this function. + * -# This function moves at most \f$ n ( 2\mathit{sizeof}(D) + + * \mathit{sizeof}(\mathit{bool}) ) + \mathcal{O}(1) \f$ bytes of + * data. + * \endparblock + * + * \parblock + * \par Performance exceptions + * If the capacity of this container at function entry is insufficient + * to perform the requested operation, then, in addition to the above: + * -# this function allocates \f$ \Theta(n) \f$ bytes of memory . + * -# this function frees \f$ \mathcal{O}(n) \f$ bytes of memory. + * -# this function will make system calls. + * \endparblock + * + * \note An implementation may ensure that at object construction the + * capacity is maximised. In that case, the above performance + * exceptions will never come to pass. + * + * @see grb::buildVector for the GraphBLAS standard dispatcher to this + * function. + */ + template< Descriptor descr = descriptors::no_operation, + class Accum = operators::right_assign< D, D, D >, + typename ind_iterator = const size_t * __restrict__, + typename nnz_iterator = const D * __restrict__, + class Dup = operators::right_assign< D, D, D > > + RC build( const Accum & accum, const ind_iterator ind_start, const ind_iterator ind_end, const nnz_iterator nnz_start, const nnz_iterator nnz_end, const Dup & dup = Dup() ) { + (void)accum; + (void)ind_start; + (void)ind_end; + (void)nnz_start; + (void)nnz_end; + (void)dup; + return PANIC; + } + + /** + * Copy from raw user-supplied data into a vector. + * + * This is the sparse masked variant. + * + * @tparam descr The pre-processing descriptor to use. + * @tparam mask_type The value type of the \a mask vector. This type is + * \em not required to be \a bool. + * @tparam Accum The type of the operator used to combine newly input + * data with existing data, if any. + * @tparam ind_iterator The type of index input iterator. By default, this + * will be a raw \em unaliased pointer to elements of + * type \a size_t. + * @tparam nnz_iterator The type of nonzero input iterator. By default, this + * will be a raw \em unaliased pointer to elements of + * type \a D. + * @tparam Dup The type of operator used to combine any duplicate + * input values. + * + * @param[in] mask An element is only added to this container if its + * index \f$ i \f$ has a nonzero at the same position + * in \a mask that evaluates true. + * @param[in] accum The operator to be used when writing back the result + * of data that was already in this container prior to + * calling this function. + * @param[in] ind_start The iterator to the first index value that should be + * added to this GraphBLAS vector. + * @param[in] ind_end Iterator corresponding to the end position of + * \a ind_start. + * @param[in] nnz_start The iterator to the first nonzero value that should + * be added to this GraphBLAS vector. + * @param[in] nnz_end Iterator corresponding to the end position of + * \a nnz_start. + * @param[in] dup The operator to be used when handling multiple + * nonzero values that are to be mapped to the same + * index position. + * + * The first element from \a nnz_start will be copied into this vector at + * the index corresponding to the first element from \a ind_start. Then, + * both nonzero and index value iterators advance to add the next input + * element and the process repeats until either of the input iterators + * reach \a nnz_end or \a ind_end, respectively. + * If at that point one of the iterators still has remaining elements, then + * those elements are ignored. + * + * @return grb::MISMATCH When attempting to insert a nonzero value at an + * index position that is larger or equal to the + * dimension of this vector. When this code is + * returned, the contents of this container are + * undefined. + * @return grb::SUCCESS When all elements are successfully assigned. + * + * \note The default accumulator expects \a D to be of the same type + * as nonzero elements of this operator, and will cause old + * values to be overwritten by the incoming new values. + * + * \note The default \a dup expects \a D to be of the same type as nonzero + * elements of this operator, and will cause duplicate values to be + * discarded in favour of the last seen value. + * + * \note Previous contents of the vector are retained. If these are to be + * cleared first, see clear(). The default accumulator is NOT an + * alternative since any pre-existing values corresponding to entries + * in the mask that evaluate to false will be retained. + * + * \par Valid descriptors + * grb::descriptors::no_operation, grb::descriptors::no_casting, + * grb::descriptors::invert_mask, grb::descriptors::no_duplicates. + * + * \note Invalid descriptors will be ignored. + * + * If grb::descriptors::no_casting is specified, then 1) the first domain of + * \a accum must match the type of \a D, 2) the second domain must match + * nnz_iterator::value_type, and 3) the third domain must \a D. If one of + * these is not true, the code shall not compile. + * + * \parblock + * \par Performance semantics. + * -# This function contains \f$ \Theta(n) \f$ work. + * -# This function will take at most \f$ \Theta(1) \f$ memory beyond + * the memory already used by the application before the call to + * this function. + * -# This function moves at most \f$ n ( 2\mathit{sizeof}(D) + + * \mathit{sizeof}(\mathit{bool}) ) + \mathcal{O}(1) \f$ bytes of + * data. + * \endparblock + * + * \parblock + * \par Performance exceptions + * If the capacity of this container at function entry is insufficient + * to perform the requested operation, then, in addition to the above: + * -# this function allocates \f$ \Theta(n) \f$ bytes of memory . + * -# this function frees \f$ \mathcal{O}(n) \f$ bytes of memory. + * -# this function will make system calls. + * \endparblock + * + * \note An implementation may ensure that at object construction the + * capacity is maximised. In that case, the above performance + * exceptions will never come to pass. + * + * @see grb::buildVector for the GraphBLAS standard dispatcher to this + * function. + */ + template< Descriptor descr = descriptors::no_operation, + typename mask_type, + class Accum, + typename ind_iterator = const size_t * __restrict__, + typename nnz_iterator = const D * __restrict__, + class Dup = operators::right_assign< D, typename nnz_iterator::value_type, D > > + RC build( const Vector< mask_type, implementation, C > mask, + const Accum & accum, + const ind_iterator ind_start, + const ind_iterator ind_end, + const nnz_iterator nnz_start, + const nnz_iterator nnz_end, + const Dup & dup = Dup() ) { + (void)mask; + (void)accum; + (void)ind_start; + (void)ind_end; + (void)nnz_start; + (void)nnz_end; + (void)dup; + return PANIC; + } + + /** + * Return the dimension of this vector. + * + * @tparam T The integral output type. + * + * @param[out] size Where to store the size of this vector. + * The initial value is ignored. + * + * @returns grb::SUCCESS When the function call completes successfully. + * + * \note This function cannot fail. + * + * \parblock + * \par Performance semantics + * This function + * -# contains \f$ \Theta(1) \f$ work, + * -# will not allocate new dynamic memory, + * -# will take at most \f$ \Theta(1) \f$ memory beyond the memory + * already used by the application before the call to this + * function. + * -# will move at most \f$ \mathit{sizeof}(T) + + * \mathit{sizeof}(\mathit{size\_t}) \f$ bytes of data. + * \endparblock + */ + template< typename T > + RC size( T & size ) const { + (void)size; + return PANIC; + } + + /** + * Return the number of nonzeroes in this vector. + * + * @tparam T The integral output type. + * + * @param[out] nnz Where to store the number of nonzeroes contained in this + * vector. Its initial value is ignored. + * + * @returns grb::SUCCESS When the function call completes successfully. + * + * \note This function cannot fail. + * + * \parblock + * \par Performance semantics + * This function + * -# contains \f$ \Theta(1) \f$ work, + * -# will not allocate new dynamic memory, + * -# will take at most \f$ \Theta(1) \f$ memory beyond the memory + * already used by the application before the call to this + * function. + * -# will move at most \f$ \mathit{sizeof}(T) + + * \mathit{sizeof}(\mathit{size\_t}) \f$ bytes of data. + * \endparblock + */ + template< typename T > + RC nnz( T & nnz ) const { + (void)nnz; + return PANIC; + } + + /** + * Returns a lambda reference to an element of this sparse vector. + * + * A lambda reference to an element of this vector is only valid when used + * inside a lambda function evaluated via grb::eWiseLambda. The lambda + * function is called for specific indices only-- that is, the GraphBLAS + * implementation decides at which elements to dereference this container. + * Outside this scope the returned reference incurs undefined behaviour. + * + * \warning In particular, for the given index \a i by the lambda function, + * it shall be \em illegal to refer to indices relative to that + * \a i; including, but not limited to, \f$ i+1 \f$, \f$ i-1 \f$, et + * cetera. + * + * \note As a consequence, this function cannot be used to perform stencil + * or halo based operations. + * + * If a previously non-existing entry of the vector is requested, a new + * nonzero is added at position \a i in this vector. The new element will + * have its initial value equal to the \em identity corresponding to the + * given monoid. + * + * \warning In parallel contexts the use of a returned lambda reference + * outside the context of an eWiseLambda will incur at least one of + * the following ill effects: it may + * -# fail outright, + * -# work on stale data, + * -# work on incorrect data, or + * -# incur high communication costs to guarantee correctness. + * In short, such usage causes undefined behaviour. Implementers are + * \em not advised to provide GAS-like functionality through this + * interface, as it invites bad programming practices and bad + * algorithm design decisions. This operator is instead intended to + * provide for generic BLAS1-type operations only. + * + * \note For I/O, use the iterator retrieved via cbegin() instead of + * relying on a lambda_reference. + * + * @param[in] i Which element to return a lambda reference of. + * @param[in] monoid Under which generalised monoid to interpret the + * requested \f$ i \f$th element of this vector. + * + * \note The \a monoid (or a ring) is required to be able to interpret a + * sparse vector. A user who is sure this vector is dense, or otherwise + * is able to ensure that the a lambda_reference will only be requested + * at elements where nonzeroes already exists, may refer to + * Vector::operator[], + * + * @return A lambda reference to the element \a i of this vector. + * + * \par Example. + * See grb::eWiseLambda() for a practical and useful example. + * + * \warning There is no similar concept in the official GraphBLAS specs. + * + * @see lambda_reference For more details on the returned reference type. + * @see grb::eWiseLambda For one legal way in which to use the returned + * #lambda_reference. + */ + template< class Monoid > + lambda_reference operator()( const size_t i, const Monoid & monoid = Monoid() ) { + (void)i; + (void)monoid; + return PANIC; + } + + /** + * Returns a lambda reference to an element of this vector. The user + * ensures that the requested reference only corresponds to a pre-existing + * nonzero in this vector, or undefined behaviour will occur. + * + * A lambda reference to an element of this vector is only valid when used + * inside a lambda function evaluated via grb::eWiseLambda. The lambda + * function is called for specific indices only-- that is, the GraphBLAS + * implementation decides at which elements to dereference this container. + * Outside this scope the returned reference incurs undefined behaviour. + * + * \warning In particular, for the given index \a i by the lambda function, + * it shall be \em illegal to refer to indices relative to that + * \a i; including, but not limited to, \f$ i+1 \f$, \f$ i-1 \f$, et + * cetera. + * + * \note As a consequence, this function cannot be used to perform stencil + * or halo based operations. + * + * If a previously non-existing entry of the vector is requested, undefined + * behaviour will occur. Functions that are defined to work with references + * of this kind, such as grb::eWiseLambda, define exactly which elements are + * dereferenced. + * + * \warning In parallel contexts the use of a returned lambda reference + * outside the context of an eWiseLambda will incur at least one of + * the following ill effects: it may + * -# fail outright, + * -# work on stale data, + * -# work on incorrect data, or + * -# incur high communication costs to guarantee correctness. + * In short, such usage causes undefined behaviour. Implementers are + * \em not advised to provide GAS-like functionality through this + * interface, as it invites bad programming practices and bad + * algorithm design decisions. This operator is instead intended to + * provide for generic BLAS1-type operations only. + * + * \note For I/O, use the iterator retrieved via cbegin() instead of + * relying on a lambda_reference. + * + * @param[in] i Which element to return a lambda reference of. + * @param[in] ring Under which generalised semiring to interpret the + * requested \f$ i \f$th element of this vector. + * + * \note The \a ring is required to be able to interpret a sparse vector. A + * user who is sure this vector is dense, or otherwise is able to + * ensure that the a lambda_reference will only be requested at + * elements where nonzeroes already exists, may refer to + * Vector::operator[], + * + * @return A lambda reference to the element \a i of this vector. + * + * \par Example. + * See grb::eWiseLambda() for a practical and useful example. + * + * \warning There is no similar concept in the official GraphBLAS specs. + * + * @see lambda_reference For more details on the returned reference type. + * @see grb::eWiseLambda For one legal way in which to use the returned + * #lambda_reference. + */ + lambda_reference operator[]( const size_t i ) { + (void)i; +#ifndef _GRB_NO_EXCEPTIONS + assert( false ); // Requesting lambda reference of unimplemented Vector backend. +#endif + } +}; + + template< typename T, typename Structure, enum Density density, typename View, enum Backend backend > + class VectorView { }; + +} + +#endif // _H_GRB_VECTOR_BASE diff --git a/include/alp/blas0.hpp b/include/alp/blas0.hpp new file mode 100644 index 000000000..96c1551b1 --- /dev/null +++ b/include/alp/blas0.hpp @@ -0,0 +1,503 @@ + +/* + * Copyright 2021 Huawei Technologies Co., Ltd. + * + * 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. + */ + +/* + * @author A. N. Yzelman + * @date 5th of December 2016 + */ + +#ifndef _H_GRB_BLAS0 +#define _H_GRB_BLAS0 + +#include +#include +#include //enable_if + +#include "graphblas/descriptors.hpp" +#include "graphblas/rc.hpp" +#include "graphblas/type_traits.hpp" + +#define NO_CAST_ASSERT( x, y, z ) \ + static_assert( x, \ + "\n\n" \ + "************************************************************************" \ + "************************************************************************" \ + "**********************\n" \ + "* ERROR | " y " " z ".\n" \ + "************************************************************************" \ + "************************************************************************" \ + "**********************\n" \ + "* Possible fix 1 | Remove no_casting from the template parameters in " \ + "this call to " y ".\n" \ + "* Possible fix 2 | Provide a left-hand side input value of the same " \ + "type as the first domain of the given operator.\n" \ + "* Possible fix 3 | Provide a right-hand side input value of the same " \ + "type as the second domain of the given operator.\n" \ + "* Possible fix 4 | Provide an output value of the same type as the " \ + "third domain of the given operator.\n" \ + "* Note that in case of in-place operators the left-hand side input or " \ + "right-hand side input also play the role of the output value.\n" \ + "************************************************************************" \ + "************************************************************************" \ + "**********************\n" ); + +namespace grb { + + /** + * \defgroup BLAS0 The Level-0 Basic Linear Algebra Subroutines (BLAS) + * + * A collection of functions that let GraphBLAS operators work on + * zero-dimensional containers, i.e., on scalars. + * + * The GraphBLAS uses opaque data types and defines several standard functions + * to operate on these data types. Examples types are grb::Vector and + * grb::Matrix, example functions are grb::dot and grb::vxm. + * + * To input data into an opaque GraphBLAS type, each opaque type defines a + * member function \a build: grb::Vector::build() and grb::Matrix::build(). + * + * To extract data from opaque GraphBLAS types, each opaque type provides + * \em iterators that may be obtained via the STL standard \a begin and \a end + * functions: + * - grb::Vector::begin or grb::Vector::cbegin + * - grb::Vector::end or grb::Vector::cend + * - grb::Matrix::begin or grb::Matrix::cbegin + * - grb::Matrix::end or grb::Matrix::cend + * + * Some GraphBLAS functions, however, reduce all elements in a GraphBLAS + * container into a single element of a given type. So for instance, grb::dot + * on two vectors of type grb::Vector using the regular real semiring + * grb::Semiring will store its output in a variable of type \a double. + * + * When parametrising GraphBLAS functions in terms of arbitrary Semirings, + * Monoids, Operators, and object types, it is useful to have a way to apply + * the same operators on whatever type they make functions like grb::dot + * produce-- that is, we require functions that enable the application of + * GraphBLAS operators on single elements. + * + * This group of BLAS level 0 functions provides this functionality. + * + * @{ + */ + + /** + * Out-of-place application of the operator \a OP on two data elements. + * + * The output data will be output to an existing memory location, overwriting + * any existing data. + * + * @tparam descr The descriptor passed to this operator. + * @tparam OP The type of the oparator to apply. + * @tparam InputType1 The left-hand side input argument type. + * @tparam InputType2 The right-hand side input argument type. + * @tparam OutputType The output argument type. + * + * \parblock + * \par Valid descriptors + * -# grb::descriptors::no_operation for default behaviour. + * -# grb::descriptors::no_casting when a call to this function should *not* + * automatically cast input arguments to operator input domain, and *not* + * automatically cast operator output to the output argument domain. + * \endparblock + * + * If \a InputType1 does not match the left-hand side input domain of \a OP, + * or if \a InputType2 does not match the right-hand side input domain of + * \a OP, or if \a OutputType does not match the output domain of \a OP while + * grb::descriptors::no_casting was set, then the code shall not compile. + * + * @param[in] x The left-hand side input data. + * @param[in] y The right-hand side input data. + * @param[out] out Where to store the result of the operator. + * @param[in] op The operator to apply (optional). + * + * \note \a op is optional when the operator type \a OP is explicitly given. + * Thus there are two ways of calling this function: + * -# + * double a, b, c; + * grb::apply< grb::operators::add >( a, b, c ); + * , or + * -# + * double a, b, c; + * grb::operators::add< double > addition_over_doubles; + * grb::apply( a, b, c, addition_over_doubles); + * + * + * \note There should be no performance difference between the two ways of + * calling this function. For compatibility with other GraphBLAS + * implementations, the latter type of call is preferred. + * + * @return grb::SUCCESS A call to this function never fails. + * + * \parblock + * \par Performance semantics. + * -# This call comprises \f$ \Theta(1) \f$ work. The constant factor + * depends on the cost of evaluating the operator. + * -# This call takes \f$ \mathcal{O}(1) \f$ memory beyond the memory + * already used by the application when a call to this function is + * made. + * -# This call incurs at most \f$ \Theta(1) \f$ memory where the + * constant factor depends on the storage requirements of the + * arguments and the temporary storage required for evaluation of + * this operator. + * \endparblock + * + * \warning The use of stateful operators, or even thus use of stateless + * operators that are not included in grb::operators, may cause this + * function to incur performance penalties beyond the worst case + * sketched above. + * + * @see foldr for applying an operator in-place (if allowed). + * @see foldl for applying an operator in-place (if allowed). + * @see grb::operators::internal::Operator for a discussion on when foldr and + * foldl successfully generate in-place code. + */ + template< Descriptor descr = descriptors::no_operation, + class OP, + typename InputType1, typename InputType2, typename OutputType + > + static enum RC apply( OutputType &out, + const InputType1 &x, + const InputType2 &y, + const OP &op = OP(), + const typename std::enable_if< + grb::is_operator< OP >::value && + !grb::is_object< InputType1 >::value && + !grb::is_object< InputType2 >::value && + !grb::is_object< OutputType >::value, + void >::type * = NULL + ) { + // static sanity check + NO_CAST_ASSERT( ( !( descr & descriptors::no_casting ) || ( + std::is_same< InputType1, typename OP::D1 >::value && + std::is_same< InputType2, typename OP::D2 >::value && + std::is_same< OutputType, typename OP::D3 >::value + ) ), + "grb::apply (BLAS level 0)", + "Argument value types do not match operator domains while no_casting " + "descriptor was set" + ); + + // call apply + const typename OP::D1 left = static_cast< typename OP::D1 >( x ); + const typename OP::D2 right = static_cast< typename OP::D2 >( y ); + typename OP::D3 output = static_cast< typename OP::D3 >( out ); + op.apply( left, right, output ); + out = static_cast< OutputType >( output ); + + // done + return SUCCESS; + } + + /** + * Application of the operator \a OP on two data elements. The output data + * will overwrite the right-hand side input element. + * + * In mathematical notation, this function calculates \f$ x \odot y \f$ and + * copies the result into \a y. + * + * @tparam descr The descriptor passed to this operator. + * @tparam OP The type of the operator to apply. + * @tparam InputType The type of the left-hand side input element. This + * element will be accessed read-only. + * @tparam IOType The type of the right-hand side input element, which will + * be overwritten. + * + * \parblock + * \par Valid descriptors + * -# grb::descriptors::no_operation for default behaviour. + * -# grb::descriptors::no_casting when a call to this function should *not* + * automatically cast input arguments to operator input domain, and *not* + * automatically cast operator output to the output argument domain. + * \endparblock + * + * If \a InputType does not match the left-hand side input domain + * (see grb::operators::internal::Operator::D1) corresponding to \a OP, then + * \a x will be temporarily cached and cast into \a D1. + * If \a IOType does not match the right-hand side input domain corresponding + * to \a OP, then \a y will be temporarily cached and cast into \a D2. + * If \a IOType does not match the output domain corresponding to \a OP, then + * the result of \f$ x \odot y \f$ will be temporarily cached before cast to + * \a IOType and written to \a y. + * + * @param[in] x The left-hand side input parameter. + * @param[in,out] y On function entry: the right-hand side input parameter. + * On function exit: the output of the operator. + * @param[in] op The operator to apply (optional). + * + * @return grb::SUCCESS A call to this function never fails. + * + * \parblock + * \par Performance semantics. + * -# This call comprises \f$ \Theta(1) \f$ work. The constant factor + * depends on the cost of evaluating the operator. + * -# This call will not allocate any new dynamic memory. + * -# This call requires at most \f$ \mathit{sizeof}(D_1+D_2+D_3) \f$ + * bytes of temporary storage, plus any temporary requirements for + * evaluating \a op. + * -# This call incurs at most \f$ \mathit{sizeof}(D_1+D_2+D_3) + + * \mathit{sizeof}(\mathit{InputType}+2\mathit{IOType}) \f$ bytes of + * data movement, plus any data movement requirements for evaluating + * \a op. + * \endparblock + * + * \warning The use of stateful operators, or even thus use of stateless + * operators that are not included in grb::operators, may cause this + * function to incur performance penalties beyond the worst case + * sketched above. + * + * \note For the standard stateless operators in grb::operators, there are + * no additional temporary storage requirements nor any additional data + * movement requirements than the ones mentioned above. + * + * \note If \a OP is fold-right capable, the temporary storage and data + * movement requirements are less than reported above. + * + * @see foldl for a left-hand in-place version. + * @see apply for an example of how to call this function without explicitly + * passing \a op. + * @see grb::operators::internal Operator for a discussion on fold-right + * capable operators and on stateful operators. + */ + template< Descriptor descr = descriptors::no_operation, class OP, typename InputType, typename IOType > + static RC foldr( const InputType & x, + IOType & y, + const OP & op = OP(), + const typename std::enable_if< grb::is_operator< OP >::value && ! grb::is_object< InputType >::value && ! grb::is_object< IOType >::value, void >::type * = NULL ) { + // static sanity check + NO_CAST_ASSERT( ( ! ( descr & descriptors::no_casting ) || + ( std::is_same< InputType, typename OP::D1 >::value && std::is_same< IOType, typename OP::D2 >::value && std::is_same< IOType, typename OP::D3 >::value ) ), + "grb::foldr (BLAS level 0)", + "Argument value types do not match operator domains while no_casting " + "descriptor was set" ); + + // call foldr + const typename OP::D1 left = static_cast< typename OP::D1 >( x ); + typename OP::D3 right = static_cast< typename OP::D3 >( y ); + op.foldr( left, right ); + y = static_cast< IOType >( right ); + + // done + return SUCCESS; + } + + /** + * Application of the operator \a OP on two data elements. The output data + * will overwrite the left-hand side input element. + * + * In mathematical notation, this function calculates \f$ x \odot y \f$ and + * copies the result into \a x. + * + * @tparam descr The descriptor passed to this operator. + * @tparam OP The type of the operator to apply. + * @tparam IOType The type of the left-hand side input element, which will + * be overwritten. + * @tparam InputType The type of the right-hand side input element. This + * element will be accessed read-only. + * + * \parblock + * \par Valid descriptors + * -# grb::descriptors::no_operation for default behaviour. + * -# grb::descriptors::no_casting when a call to this function should *not* + * automatically cast input arguments to operator input domain, and *not* + * automatically cast operator output to the output argument domain. + * \endparblock + * + * If \a InputType does not match the right-hand side input domain + * (see grb::operators::internal::Operator::D2) corresponding to \a OP, then + * \a x will be temporarily cached and cast into \a D2. + * If \a IOType does not match the left-hand side input domain corresponding + * to \a OP, then \a y will be temporarily cached and cast into \a D1. + * If \a IOType does not match the output domain corresponding to \a OP, then + * the result of \f$ x \odot y \f$ will be temporarily cached before cast to + * \a IOType and written to \a y. + * + * @param[in,out] x On function entry: the left-hand side input parameter. + * On function exit: the output of the operator. + * @param[in] y The right-hand side input parameter. + * @param[in] op The operator to apply (optional). + * + * @return grb::SUCCESS A call to this function never fails. + * + * \parblock + * \par Performance semantics. + * -# This call comprises \f$ \Theta(1) \f$ work. The constant factor + * depends on the cost of evaluating the operator. + * -# This call will not allocate any new dynamic memory. + * -# This call requires at most \f$ \mathit{sizeof}(D_1+D_2+D_3) \f$ + * bytes of temporary storage, plus any temporary requirements for + * evaluating \a op. + * -# This call incurs at most \f$ \mathit{sizeof}(D_1+D_2+D_3) + + * \mathit{sizeof}(\mathit{InputType}+2\mathit{IOType}) \f$ bytes of + * data movement, plus any data movement requirements for evaluating + * \a op. + * \endparblock + * + * \warning The use of stateful operators, or even thus use of stateless + * operators that are not included in grb::operators, may cause this + * function to incur performance penalties beyond the worst case + * sketched above. + * + * \note For the standard stateless operators in grb::operators, there are + * no additional temporary storage requirements nor any additional data + * movement requirements than the ones mentioned above. + * + * \note If \a OP is fold-left capable, the temporary storage and data + * movement requirements are less than reported above. + * + * @see foldr for a right-hand in-place version. + * @see apply for an example of how to call this function without explicitly + * passing \a op. + * @see grb::operators::internal Operator for a discussion on fold-right + * capable operators and on stateful operators. + */ + template< Descriptor descr = descriptors::no_operation, class OP, typename InputType, typename IOType > + static RC foldl( IOType & x, + const InputType & y, + const OP & op = OP(), + const typename std::enable_if< grb::is_operator< OP >::value && ! grb::is_object< InputType >::value && ! grb::is_object< IOType >::value, void >::type * = NULL ) { + // static sanity check + NO_CAST_ASSERT( ( ! ( descr & descriptors::no_casting ) || + ( std::is_same< IOType, typename OP::D1 >::value && std::is_same< InputType, typename OP::D2 >::value && std::is_same< IOType, typename OP::D3 >::value ) ), + "grb::foldl (BLAS level 0)", + "Argument value types do not match operator domains while no_casting " + "descriptor was set" ); + + // call foldl + typename OP::D1 left = static_cast< typename OP::D1 >( x ); + const typename OP::D3 right = static_cast< typename OP::D3 >( y ); + op.foldl( left, right ); + x = static_cast< IOType >( left ); + + // done + return SUCCESS; + } + + /** @} */ + + namespace internal { + + /** + * Helper class that, depending on a given descriptor, either returns a + * nonzero value from a vector, or its corresponding coordinate. + * + * This class hence makes the use of the following descriptor(s) transparent: + * -# #grb::descriptors::use_index + * + * @tparam descr The descriptor under which to write back either the value or + * the index. + * @tparam OutputType The type of the output to return. + * @tparam D The type of the input. + * @tparam Enabled Controls, through SFINAE, whether the use of the + * #use_index descriptor is allowed at all. + */ + template< grb::Descriptor descr, typename OutputType, typename D, typename Enabled = void > + class ValueOrIndex; + + /* Version where use_index is allowed. */ + template< grb::Descriptor descr, typename OutputType, typename D > + class ValueOrIndex< descr, OutputType, D, typename std::enable_if< std::is_arithmetic< OutputType >::value && ! std::is_same< D, void >::value >::type > { + private: + static constexpr const bool use_index = descr & grb::descriptors::use_index; + static_assert( use_index || std::is_convertible< D, OutputType >::value, "Cannot convert to the requested output type" ); + + public: + static OutputType getFromArray( const D * __restrict__ const x, const std::function< size_t( size_t ) > & src_local_to_global, const size_t index ) noexcept { + if( use_index ) { + return static_cast< OutputType >( src_local_to_global( index ) ); + } else { + return static_cast< OutputType >( x[ index ] ); + } + } + static OutputType getFromScalar( const D &x, const size_t index ) noexcept { + if( use_index ) { + return static_cast< OutputType >( index ); + } else { + return static_cast< OutputType >( x ); + } + } + }; + + /* Version where use_index is not allowed. */ + template< grb::Descriptor descr, typename OutputType, typename D > + class ValueOrIndex< descr, OutputType, D, typename std::enable_if< ! std::is_arithmetic< OutputType >::value && ! std::is_same< OutputType, void >::value >::type > { + static_assert( ! ( descr & descriptors::use_index ), "use_index descriptor given while output type is not numeric" ); + static_assert( std::is_convertible< D, OutputType >::value, "Cannot convert input to the given output type" ); + + public: + static OutputType getFromArray( const D * __restrict__ const x, const std::function< size_t( size_t ) > &, const size_t index ) noexcept { + return static_cast< OutputType >( x[ index ] ); + } + static OutputType getFromScalar( const D &x, const size_t ) noexcept { + return static_cast< OutputType >( x ); + } + }; + + /** + * Helper class that, depending on the type, sets an output value to a given + * input value, either by cast-and-assign (if that is possible), or by + * applying a given operator with a given left- or right-identity to generate + * a matching requested output value. + * + * This transparently `lifts' input arguments to different domains whenever + * required, and allows the use of highly generic semirings. + * + * @tparam identity_left If an identity is applied, whether the left-identity + * must be used. If false, the right-identity will be + * used (if indeed an identity is to be applied). + * @tparam OutputType The type of the output to return. + * @tparam InputType The type of the input. + * @tparam Identity The class that can generate both left- and right- + * identities. + * @tparam Enabled Controls, through SFINAE, whether cast-and-assign or the + * operator version is used instead. + */ + + template< bool identity_left, typename OutputType, typename InputType, template< typename > class Identity, typename Enabled = void > + class CopyOrApplyWithIdentity; + + /* The cast-and-assign version */ + template< bool identity_left, typename OutputType, typename InputType, template< typename > class Identity > + class CopyOrApplyWithIdentity< identity_left, OutputType, InputType, Identity, typename std::enable_if< std::is_convertible< InputType, OutputType >::value >::type > { + public: + template< typename Operator > + static void set( OutputType & out, const InputType & in, const Operator & ) { + out = static_cast< OutputType >( in ); + } + }; + + /* The operator with identity version */ + template< bool identity_left, typename OutputType, typename InputType, template< typename > class Identity > + class CopyOrApplyWithIdentity< identity_left, OutputType, InputType, Identity, typename std::enable_if< ! std::is_convertible< InputType, OutputType >::value >::type > { + public: + template< typename Operator > + static void set( OutputType & out, const InputType & in, const Operator & op ) { + const auto identity = identity_left ? Identity< typename Operator::D1 >::value() : Identity< typename Operator::D2 >::value(); + if( identity_left ) { + (void)grb::apply( out, identity, in, op ); + } else { + (void)grb::apply( out, in, identity, op ); + } + } + }; + + } // namespace internal + +} // namespace grb + +#undef NO_CAST_ASSERT + +#endif // end ``_H_GRB_BLAS0'' diff --git a/include/alp/blas1.hpp b/include/alp/blas1.hpp new file mode 100644 index 000000000..d4fa9b059 --- /dev/null +++ b/include/alp/blas1.hpp @@ -0,0 +1,412 @@ + +/* + * Copyright 2021 Huawei Technologies Co., Ltd. + * + * 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. + */ + +/* + * @author A. N. Yzelman + * @date 29th of March 2017 + */ + +#ifndef _H_GRB_BLAS1 +#define _H_GRB_BLAS1 + +#include +#include +#include +#include + +#include "base/vector.hpp" + +#ifdef _GRB_WITH_REFERENCE + #include +#endif +#ifdef _GRB_WITH_DENSEREF + #include +#endif +#ifdef _GRB_WITH_BANSHEE + #include +#endif +#ifdef _GRB_WITH_LPF + #include +#endif + +// the remainder implements several backend-agnostic short-cuts + +#define NO_CAST_RING_ASSERT( x, y, z ) \ + static_assert( x, \ + "\n\n" \ + "************************************************************************" \ + "************************************************************************" \ + "**********************\n" \ + "* ERROR | " y " " z ".\n" \ + "************************************************************************" \ + "************************************************************************" \ + "**********************\n" \ + "* Possible fix 1 | Remove no_casting from the template parameters in " \ + "this call to " y ".\n" \ + "* Possible fix 2 | For all mismatches in the domains of input " \ + "parameters and the semiring domains, as specified in the documentation " \ + "of the function " y ", supply an input argument of the expected type " \ + "instead.\n" \ + "* Possible fix 3 | Provide a compatible semiring where all domains " \ + "match those of the input parameters, as specified in the documentation " \ + "of the function " y ".\n" \ + "************************************************************************" \ + "************************************************************************" \ + "**********************\n" ); + +namespace grb { + + /** + * A standard vector to use for mask parameters. Indicates no mask shall be + * used. + */ + #define NO_MASK Vector< bool >( 0 ) + + /** + * Executes an arbitrary element-wise user-defined function \a f using any + * number of vectors of equal length, following the nonzero pattern of the + * given vector \a x. + * + * The user-defined function is passed as a lambda which can capture, at + * the very least, other instances of type grb::Vector. Use of this function + * is preferable whenever multiple element-wise operations are requested that + * use one or more identical input vectors. Performing the computation one + * after the other in blocking mode would require the same vector to be + * streamed multiple times, while with this function the operations can be + * fused explicitly instead. + * + * It shall always be legal to capture non-GraphBLAS objects for read access + * only. It shall \em not be legal to capture instances of type grb::Matrix + * for read and/or write access. + * + * If grb::Properties::writableCaptured evaluates true then captured + * non-GraphBLAS objects can also be written to, not just read from. The + * captured variable is, however, completely local to the calling user process + * only-- it will not be synchronised between user processes. + * As a rule of thumb, data-centric GraphBLAS implementations \em cannot + * support this and will thus have grb::Properties::writableCaptured evaluate + * to false. A portable GraphBLAS algorithm should provide a different code + * path to handle this case. + * When it is legal to write to captured scalar, this function can, e.g., be + * used to perform reduction-like operations on any number of equally sized + * input vectors. This would be preferable to a chained number of calls to + * grb::dot in case where some vectors are shared between subsequent calls, + * for example; the shared vectors are streamed only once using this lambda- + * enabled function. + * + * \warning The lambda shall only be executed on the data local to the user + * process calling this function! This is different from the various + * fold functions, or grb::dot, in that the semantics of those + * functions always end with a globally synchronised result. To + * achieve the same effect with user-defined lambdas, the users + * should manually prescribe how to combine the local results into + * global ones, for instance, by a subsequent call to + * grb::collectives<>::allreduce. + * + * \note This is an addition to the GraphBLAS. It is alike user-defined + * operators, monoids, and semirings, except it allows execution on + * arbitrarily many inputs and arbitrarily many outputs. + * + * @tparam Func the user-defined lambda function type. + * @tparam DataType the type of the user-supplied vector example. + * @tparam backend the backend type of the user-supplied vector example. + * + * @param[in] f The user-supplied lambda. This lambda should only capture + * and reference vectors of the same length as \a x. The lambda + * function should prescribe the operations required to execute + * at a given index \a i. Captured GraphBLAS vectors can access + * that element via the operator[]. It is illegal to access any + * element not at position \a i. The lambda takes only the single + * parameter \a i of type const size_t. Captured + * scalars will not be globally updated-- the user must program + * this explicitly. Scalars and other non-GraphBLAS containers + * are always local to their user process. + * @param[in] x The vector the lambda will be executed on. This argument + * determines which indices \a i will be accessed during the + * elementwise operation-- elements with indices \a i that + * do not appear in \a x will be skipped during evaluation of + * \a f. + * @param[in] args All vectors the lambda is to access elements of. Must be of + * the same length as \a x. If this constraint is violated, + * grb::MISMATCH shall be returned. This is a variadic + * argument and can contain any number of containers of type + * grb::Vector, passed as though they were separate + * arguments. + * + * \note In future GraphBLAS implementations, \a args, apart from doing + * dimension checking, should also facilitate any data distribution + * necessary to successfully execute the element-wise operation. Current + * implementations do not require this since they use the same static + * distribution for all containers. + * + * \warning Using a grb::Vector inside a lambda passed to this function while + * not passing that same vector into \a args, will result in undefined + * behaviour. + * + * \note It would be natural to have \a x equal to one of the captured + * GraphBLAS vectors in \a f. + * + * \warning Due to the constraints on \a f described above, it is illegal to + * capture some vector \a y and have the following line in the body + * of \a f: x[i] += x[i+1]. Vectors can only be + * dereferenced at position \a i and \a i alone. + * + * @return grb::SUCCESS When the lambda is successfully executed. + * @return grb::MISMATCH When two or more vectors passed to \a args are not of + * equal length. + * + * \parblock + * \par Example. + * + * An example valid use: + * + * \code + * void f( + * double &alpha, + * grb::Vector< double > &y, + * const double beta, + * const grb::Vector< double > &x, + * const grb::Semiring< double > ring + * ) { + * assert( grb::size(x) == grb::size(y) ); + * assert( grb::nnz(x) == grb::size(x) ); + * assert( grb::nnz(y) == grb::size(y) ); + * alpha = ring.getZero(); + * grb::eWiseLambda( + * [&alpha,beta,&x,&y,ring]( const size_t i ) { + * double mul; + * const auto mul_op = ring.getMultiplicativeOperator(); + * const auto add_op = ring.getAdditiveOperator(); + * grb::apply( y[i], beta, x[i], mul_op ); + * grb::apply( mul, x[i], y[i], mul_op ); + * grb::foldl( alpha, mul, add_op ); + * }, x, y ); + * grb::collectives::allreduce( alpha, add_op ); + * } + * \endcode + * + * This code takes a value \a beta, a vector \a x, and a semiring \a ring and + * computes: + * 1) \a y as the element-wise multiplication (under \a ring) of \a beta and + * \a x; and + * 2) \a alpha as the dot product (under \a ring) of \a x and \a y. + * This function can easily be made agnostic to whatever exact semiring is used + * by templating the type of \a ring. As it is, this code is functionally + * equivalent to: + * + * \code + * grb::eWiseMul( y, beta, x, ring ); + * grb::dot( alpha, x, y, ring ); + * \endcode + * + * The version using the lambdas, however, is expected to execute + * faster as both \a x and \a y are streamed only once, while the + * latter code may stream both vectors twice. + * \endparblock + * + * \warning The following code is invalid: + * \code + * template< class Operator > + * void f( + * grb::Vector< double > &x, + * const Operator op + * ) { + * grb::eWiseLambda( + * [&x,&op]( const size_t i ) { + * grb::apply( x[i], x[i], x[i+1], op ); + * }, x ); + * } + * \endcode + * Only a Vector::lambda_reference to position exactly equal to \a i + * may be used within this function. + * + * \warning There is no similar concept in the official GraphBLAS specs. + * + * \warning Captured scalars will be local to the user process executing the + * lambda. To retrieve the global dot product, an allreduce must + * explicitly be called. + * + * @see Vector::operator[]() + * @see Vector::lambda_reference + */ + template< + typename Func, + typename DataType, + Backend backend, + typename Coords, + typename... Args + > + RC eWiseLambda( + const Func f, + const Vector< DataType, backend, Coords > & x, Args... + ) { + (void)f; + (void)x; + return PANIC; + } + + /** + * Alias for a simple reduce call. + * + * Will use no mask and will set the accumulator to the given Monoid's + * operator. + */ + template< + Descriptor descr = descriptors::no_operation, + class Monoid, + typename IOType, typename InputType, + Backend backend, + typename Coords + > + RC foldl( IOType &x, + const Vector< InputType, backend, Coords > &y, + const Monoid &monoid = Monoid(), + const typename std::enable_if< !grb::is_object< IOType >::value && + grb::is_monoid< Monoid >::value, + void >::type * const = NULL + ) { + // create empty mask + Vector< bool, backend, Coords > mask( 0 ); + // call regular reduce function + return foldl< descr >( x, y, mask, monoid ); + } + + /** + * Alias for a simple reduce call. + * + * Will use no mask and will set the accumulator to the given Monoid's + * operator. + */ + template< + Descriptor descr = descriptors::no_operation, + class OP, + typename IOType, typename InputType, + Backend backend, typename Coords + > + RC foldl( IOType &x, + const Vector< InputType, backend, Coords > &y, + const OP &op = OP(), + const typename std::enable_if< !grb::is_object< IOType >::value && + grb::is_operator< OP >::value, + void >::type * const = NULL + ) { + // create empty mask + Vector< bool, backend, Coords > mask( 0 ); + // call regular reduce function + return foldl< descr >( x, y, mask, op ); + } + + /** + * Provides a generic implementation of the dot computation on semirings by + * translating it into a dot computation on an additive commutative monoid + * with any multiplicative operator. + * + * For return codes, exception behaviour, performance semantics, template + * and non-template arguments, @see grb::dot. + */ + template< + Descriptor descr = descriptors::no_operation, class Ring, + typename IOType, typename InputType1, typename InputType2, + Backend backend, typename Coords + > + RC dot( IOType &x, + const Vector< InputType1, backend, Coords > &left, + const Vector< InputType2, backend, Coords > &right, + const Ring &ring = Ring(), + const typename std::enable_if< + !grb::is_object< InputType1 >::value && + !grb::is_object< InputType2 >::value && + !grb::is_object< IOType >::value && + grb::is_semiring< Ring >::value, + void >::type * const = NULL + ) { + return grb::dot< descr >( x, + left, right, + ring.getAdditiveMonoid(), + ring.getMultiplicativeOperator() + ); + } + + /** + * Provides a generic implementation of the 2-norm computation. + * + * Proceeds by computing a dot-product on itself and then taking the square + * root of the result. + * + * This function is only available when the output type is floating point. + * + * For return codes, exception behaviour, performance semantics, template + * and non-template arguments, @see grb::dot. + * + * @param[out] x The 2-norm of \a y. The input value of \a x will be ignored. + * @param[in] y The vector to compute the norm of. + * @param[in] ring The Semiring under which the 2-norm is to be computed. + * + * \warning This function computes \a x out-of-place. This is contrary to + * standard ALP/GraphBLAS functions that are always in-place. + * + * \warning A \a ring is not sufficient for computing a two-norm. This + * implementation assumes the standard sqrt function + * must be applied on the result of a dot-product of \a y with + * itself under the supplied semiring. + */ + // template< + // Descriptor descr = descriptors::no_operation, class Ring, + // typename InputType, typename OutputType, typename OutputStructure, + // Backend backend, typename Coords + // > + // RC norm2( Scalar< OutputType, OutputStructure, backend > &x, + // const Vector< InputType, backend, Coords > &y, + // const Ring &ring = Ring(), + // const typename std::enable_if< + // std::is_floating_point< OutputType >::value, + // void >::type * const = NULL + // ) { + // RC ret = grb::dot< descr >( x, y, y, ring ); + // if( ret == SUCCESS ) { + // x = sqrt( x ); + // } + // return ret; + // } + + /** Specialization for C++ scalars */ + template< + Descriptor descr = descriptors::no_operation, class Ring, + typename InputType, typename OutputType, + Backend backend, typename Coords + > + RC norm2( OutputType &x, + const Vector< InputType, backend, Coords > &y, + const Ring &ring = Ring(), + const typename std::enable_if< + std::is_floating_point< OutputType >::value, + void >::type * const = NULL + ) { + RC ret = grb::dot< descr >( x, y, y, ring ); + if( ret == SUCCESS ) { + x = sqrt( x ); + } + return ret; + } + + +} // namespace grb + +#undef NO_CAST_RING_ASSERT + +#endif // end ``_H_GRB_BLAS1'' + diff --git a/include/alp/blas2.hpp b/include/alp/blas2.hpp new file mode 100644 index 000000000..7c4e44398 --- /dev/null +++ b/include/alp/blas2.hpp @@ -0,0 +1,47 @@ + +/* + * Copyright 2021 Huawei Technologies Co., Ltd. + * + * 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. + */ + +/** + * @file + * + * Defines the GraphBLAS level 2 API. + * + * @author A. N. Yzelman + * @date: 30th of March 2017. + */ + +#ifndef _H_GRB_BLAS2 +#define _H_GRB_BLAS2 + +#include "base/blas2.hpp" + +// now include all specialisations contained in the backend directories: +#ifdef _GRB_WITH_REFERENCE + #include +#endif +#ifdef _GRB_WITH_DENSE + #include +#endif +#ifdef _GRB_WITH_BANSHEE + #include +#endif +#ifdef _GRB_WITH_LPF + #include +#endif + +#endif // end ``_H_GRB_BLAS2'' + diff --git a/include/alp/blas3.hpp b/include/alp/blas3.hpp new file mode 100644 index 000000000..e6e4d0ae0 --- /dev/null +++ b/include/alp/blas3.hpp @@ -0,0 +1,41 @@ + +/* + * Copyright 2021 Huawei Technologies Co., Ltd. + * + * 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. + */ + +/* + * @author: A. N. Yzelman + */ + +#ifndef _H_GRB_BLAS3 +#define _H_GRB_BLAS3 + +#include "base/blas3.hpp" +#include "config.hpp" +#include "phase.hpp" + +// now include all specialisations contained in the backend directories: +#ifdef _GRB_WITH_REFERENCE + #include +#endif +#ifdef _GRB_WITH_DENSEREF + #include +#endif +#ifdef _GRB_WITH_LPF + #include +#endif + +#endif // end _H_GRB_BLAS3 + diff --git a/include/alp/config.hpp b/include/alp/config.hpp new file mode 100644 index 000000000..adfa261a6 --- /dev/null +++ b/include/alp/config.hpp @@ -0,0 +1,43 @@ + +/* + * Copyright 2021 Huawei Technologies Co., Ltd. + * + * 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. + */ + +/* + * @author A. N. Yzelman + * @date 8th of August, 2016 + */ + +#ifndef _H_GRB_CONFIG +#define _H_GRB_CONFIG + +#include "base/config.hpp" + +// include all active configurations +#ifdef _GRB_WITH_REFERENCE + #include "graphblas/reference/config.hpp" +#endif +#ifdef _GRB_WITH_OMP + #include "graphblas/omp/config.hpp" +#endif +#ifdef _GRB_WITH_LPF + #include "graphblas/bsp1d/config.hpp" +#endif +#ifdef _GRB_WITH_BANSHEE + #include "graphblas/banshee/config.hpp" +#endif + +#endif // end ``_H_GRB_CONFIG'' + diff --git a/include/graphblas/density.hpp b/include/alp/density.hpp similarity index 100% rename from include/graphblas/density.hpp rename to include/alp/density.hpp diff --git a/include/alp/descriptors.hpp b/include/alp/descriptors.hpp new file mode 100644 index 000000000..bbfd385c2 --- /dev/null +++ b/include/alp/descriptors.hpp @@ -0,0 +1,208 @@ + +/* + * Copyright 2021 Huawei Technologies Co., Ltd. + * + * 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. + */ + +/** + * @file + * + * Defines the GraphBLAS various descriptors. + * + * @author A. N. Yzelman + * @date 15 March, 2016 + */ + +#include +#include + +#ifndef _H_GRB_DESCRIPTOR +#define _H_GRB_DESCRIPTOR + +namespace grb { + + /** + * Descriptors indicate pre- or post-processing for some or all of the + * arguments to a GraphBLAS call. + * + * They can be combined using bit-wise operators. For instance, to both + * indicate the matrix needs be transposed and the mask needs be + * inverted, the following descriptor can be passed: + * transpose_matrix | invert_mask + */ + typedef unsigned int Descriptor; + + /** Collection of standard descriptors. */ + namespace descriptors { + + /** + * Indicates no additional pre- or post-processing on any of + * the GraphBLAS function arguments. + */ + static constexpr Descriptor no_operation = 0; + + /** Inverts the mask prior to applying it. */ + static constexpr Descriptor invert_mask = 1; + + /** + * Transposes the input matrix prior to applying it. + */ + static constexpr Descriptor transpose_matrix = 2; + + /** + * For data ingestion methods, such as grb::buildVector or grb::buildMatrix, + * this descriptor indicates that the input shall not contain any duplicate + * entries. + * + * Use of this descriptor will speed up the corresponding function call + * significantly. + * + * A call to buildMatrix with this descriptor set will pass its arguments to + * buildMatrixUnique. + * + * \warning Use of this descriptor while the data to be ingested actually + * \em does contain duplicates will lead to undefined behaviour. + * + * Currently, the reference implementation only supports ingesting data + * using this descriptor. Support for duplicate input is not yet + * implemented everywhere. + */ + static constexpr Descriptor no_duplicates = 4; + + /** + * Uses the structure of a mask vector only. + * + * This ignores the actual values of the mask argument. The i-th element of + * the mask now evaluates true if the mask has \em any value assigned to its + * i-th index, regardless of how that value evaluates. It evaluates false + * if there was no value assigned. + * + * @see structural_complement + */ + static constexpr Descriptor structural = 8; + + /** + * Uses the structural complement of a mask vector. + * + * This is a convenience short-hand for: + * \code + * constexpr Descriptor structural_complement = structural | invert_mask; + * \endcode + * + * This ignores the actual values of the mask argument. The i-th element of + * the mask now evaluates true if the mask has \em no value assigned to its + * i-th index, and evaluates false otherwise. + */ + static constexpr Descriptor structural_complement = structural | invert_mask; + + /** + * Indicates all vectors used in a computation are dense. This is a hint that + * might affect performance but will never affect the semantics of the + * computation. + */ + static constexpr Descriptor dense = 16; + + /** + * For any call to a matrix computation, the input matrix \a A is instead + * interpreted as \f$ A+I \f$, with \a I the identity matrix of dimension + * matching \a A. If \a A is not square, padding zero columns or rows will + * be added to \a I in the largest dimension. + */ + static constexpr Descriptor add_identity = 32; + + /** + * Instead of using input vector elements, use the index of those elements. + * + * Indices are cast from their internal data type (size_t, e.g.) + * to the relevant domain of the operator used. + */ + static constexpr Descriptor use_index = 64; + + /** + * Disallows the standard casting of input parameters to a compatible domain + * in case they did not match exactly. + * + * Setting this descriptor will yield compile-time errors whenever casting + * would have been necessary to successfully compile the requested graphBLAS + * operation. + * + * \warning It is illegal to perform conditional toggling on this descriptor. + * + * \note With conditional toggling, if descr is a descriptor, we + * mean if( descr & descriptors::no_casting ) { + * new_descr = desc - descriptors::no_casting + * //followed by any use of this new descriptor + * } + * + * The reason we cannot allow for this type of toggling is because this + * descriptor makes use of the static_assert C++11 function, + * which is checked regardless of the result of the if-statement. Thus + * the above code actually always throws compile errors on mismatching + * domains, no matter the original value in descr. + * + * \internal Simply making this descriptor the one with the largest integral + * value amongst the various descriptors is enough to guarantee + * nothing bad will happen. A notable exception are underflows, + * which are caught by using internal::MAX_DESCRIPTOR_VALUE. + */ + static constexpr Descriptor no_casting = 256; + + /** + * Computation shall proceed with zeros (according to the current semiring) + * propagating throughout the requested computation. + * + * \warning This may lead to unexpected results if the same output container + * is interpreted under a different semiring-- what is zero for the current + * semiring may not be zero for another. In other words: the concept of + * sparsity will no longer generalise to other semirings. + */ + static constexpr Descriptor explicit_zero = 512; + + /** + * Indicates overlapping input and output vectors is intentional and safe, due + * to, for example, the use of masks. + */ + static constexpr Descriptor safe_overlap = 1024; + + /** + * For operations involving 2 matrices, transposes the left-hand side input + * matrix prior to applying it. + */ + static constexpr Descriptor transpose_left = 2048; + + /** + * For operations involving 2 matrices, transposes the right-hand side input + * matrix prior to applying it. + */ + static constexpr Descriptor transpose_right = 4096; + + /** + * Translates a descriptor into a string. + * + * @param[in] descr The input descriptor. + * + * @returns A detailed English description. + */ + std::string toString( const Descriptor descr ); + + } // namespace descriptors + + namespace internal { + /** A descriptor cannot have a higher value than the below. */ + static constexpr Descriptor MAX_DESCRIPTOR_VALUE = 8191; + } // namespace internal + +} // namespace grb + +#endif diff --git a/include/alp/exec.hpp b/include/alp/exec.hpp new file mode 100644 index 000000000..8bfaa55a3 --- /dev/null +++ b/include/alp/exec.hpp @@ -0,0 +1,51 @@ + +/* + * Copyright 2021 Huawei Technologies Co., Ltd. + * + * 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. + */ + +/* + * @author: A. N. Yzelman + * @date 17th of April, 2017 + */ + +#ifndef _H_GRB_EXEC +#define _H_GRB_EXEC + +#include "base/config.hpp" +#include "base/exec.hpp" + +// include template specialisations +#ifdef _GRB_WITH_REFERENCE + #include "graphblas/reference/exec.hpp" +#endif +#ifdef _GRB_WITH_DENSEREF + #include "graphblas/denseref/exec.hpp" +#endif +#ifdef _GRB_WITH_LPF + #include "graphblas/bsp1d/exec.hpp" +#endif +#ifdef _GRB_WITH_BANSHEE + #include "graphblas/banshee/exec.hpp" +#endif + +#ifdef _GRB_BACKEND +namespace grb { + template< enum EXEC_MODE mode, enum Backend implementation = config::default_backend > + class Launcher; +} +#endif + +#endif // end ``_H_GRB_EXEC'' + diff --git a/include/alp/identities.hpp b/include/alp/identities.hpp new file mode 100644 index 000000000..dd48fcf98 --- /dev/null +++ b/include/alp/identities.hpp @@ -0,0 +1,197 @@ + +/* + * Copyright 2021 Huawei Technologies Co., Ltd. + * + * 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. + */ + +/* + * @author A. N. Yzelman + * @date 11th of August, 2016 + */ + +#ifndef _H_GRB_IDENTITIES +#define _H_GRB_IDENTITIES + +#include + +namespace grb { + + /** + * Standard identities common to many operators. + * + * The most commonly used identities are + * - #grb::identities::zero, and + * - #grb::identities::one. + * + * A stateful identity should expose the same public interface as the + * identities collected here, which is class which exposes at least one public + * templated function named \a value, taking no arguments, returning the + * identity in the domain \a D. This type \a D is the first template parameter + * of the function \a value. If there are other template parameters, those + * template parameters are required to have defaults. + * + * @see operators + * @see Monoid + * @see Semiring + */ + namespace identities { + + /** Standard identity for numerical addition. */ + template< typename D > + class zero { + static_assert( std::is_convertible< int, D >::value, "Cannot form identity under the requested domain" ); + + public: + /** + * @tparam D The domain of the value to return. + * @return The identity under standard addition (i.e., `zero'). + */ + static constexpr D value() { + return static_cast< D >( 0 ); + } + }; + template< typename K, typename V > + class zero< std::pair< K, V > > { + public: + static constexpr std::pair< K, V > value() { + return std::make_pair( zero< K >::value(), zero< V >::value() ); + } + }; + + /** Standard identity for numerical multiplication. */ + template< typename D > + class one { + static_assert( std::is_convertible< int, D >::value, "Cannot form identity under the requested domain" ); + + public: + /** + * @tparam D The domain of the value to return. + * @return The identity under standard multiplication (i.e., `one'). + */ + static constexpr D value() { + return static_cast< D >( 1 ); + } + }; + template< typename K, typename V > + class one< std::pair< K, V > > { + public: + static constexpr std::pair< K, V > value() { + return std::make_pair( one< K >::value(), one< V >::value() ); + } + }; + + /** Standard identity for the minimum operator. */ + template< typename D > + class infinity { + static_assert( std::is_arithmetic< D >::value, "Cannot form identity under the requested domain" ); + + public: + /** + * @tparam D The domain of the value to return. + * @return The identity under the standard min operator (i.e., `infinity'), + * of type \a D. + */ + static constexpr D value() { + return std::numeric_limits< D >::has_infinity ? std::numeric_limits< D >::infinity() : std::numeric_limits< D >::max(); + } + }; + template< typename K, typename V > + class infinity< std::pair< K, V > > { + public: + static constexpr std::pair< K, V > value() { + return std::make_pair( infinity< K >::value(), infinity< V >::value() ); + } + }; + + /** Standard identity for the maximum operator. */ + template< typename D > + class negative_infinity { + static_assert( std::is_arithmetic< D >::value, "Cannot form identity under the requested domain" ); + + public: + /** + * @tparam D The domain of the value to return. + * @return The identity under the standard max operator, i.e., + * `minus infinity'. + */ + static constexpr D value() { + return std::numeric_limits< D >::min() == 0 ? 0 : ( std::numeric_limits< D >::has_infinity ? -std::numeric_limits< D >::infinity() : std::numeric_limits< D >::min() ); + } + }; + template< typename K, typename V > + class negative_infinity< std::pair< K, V > > { + public: + static constexpr std::pair< K, V > value() { + return std::make_pair( negative_infinity< K >::value(), negative_infinity< V >::value() ); + } + }; + + /** + * Standard identitity for the logical or operator. + * + * @see operators::logical_or. + */ + template< typename D > + class logical_false { + static_assert( std::is_convertible< bool, D >::value, "Cannot form identity under the requested domain" ); + + public: + /** + * @tparam D The domain of the value to return. + * @return The identity under the standard logical OR operator, i.e., + * \a false. + */ + static const constexpr D value() { + return static_cast< D >( false ); + } + }; + template< typename K, typename V > + class logical_false< std::pair< K, V > > { + public: + static constexpr std::pair< K, V > value() { + return std::make_pair( logical_false< K >::value(), logical_false< V >::value() ); + } + }; + + /** + * Standard identity for the logical AND operator. + * + * @see operators::logical_and. + */ + template< typename D > + class logical_true { + static_assert( std::is_convertible< bool, D >::value, "Cannot form identity under the requested domain" ); + + public: + /** + * @tparam D The domain of the value to return. + * @return The identity under the standard logical AND operator, i.e., + * \a true. + */ + static constexpr D value() { + return static_cast< D >( true ); + } + }; + template< typename K, typename V > + class logical_true< std::pair< K, V > > { + public: + static constexpr std::pair< K, V > value() { + return std::make_pair( logical_true< K >::value(), logical_true< V >::value() ); + } + }; + + } // namespace identities +} // namespace grb + +#endif diff --git a/include/graphblas/imf.hpp b/include/alp/imf.hpp similarity index 100% rename from include/graphblas/imf.hpp rename to include/alp/imf.hpp diff --git a/include/alp/init.hpp b/include/alp/init.hpp new file mode 100644 index 000000000..2d13801a0 --- /dev/null +++ b/include/alp/init.hpp @@ -0,0 +1,44 @@ + +/* + * Copyright 2021 Huawei Technologies Co., Ltd. + * + * 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. + */ + +/* + * @author A. N. Yzelman + * @date 24th of January, 2017 + */ + +#ifndef _H_GRB_INIT +#define _H_GRB_INIT + +#include "backends.hpp" +#include "base/init.hpp" + +// include all implementations +#ifdef _GRB_WITH_REFERENCE + #include "graphblas/reference/init.hpp" +#endif +#ifdef _GRB_WITH_DENSEREF + #include "graphblas/denseref/init.hpp" +#endif +#ifdef _GRB_WITH_LPF + #include "graphblas/bsp1d/init.hpp" +#endif +#ifdef _GRB_WITH_BANSHEE + #include "graphblas/banshee/init.hpp" +#endif + +#endif // end ``_H_GRB_INIT'' + diff --git a/include/alp/internalops.hpp b/include/alp/internalops.hpp new file mode 100644 index 000000000..d07908e81 --- /dev/null +++ b/include/alp/internalops.hpp @@ -0,0 +1,36 @@ + +/* + * Copyright 2021 Huawei Technologies Co., Ltd. + * + * 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. + */ + +/* + * @author A. N. Yzelman + * @date 8 of August, 2016 + */ + +#ifndef _H_GRB_INTERNAL_OPERATORS +#define _H_GRB_INTERNAL_OPERATORS + +// certain backends may want to specialize these functionalities, +// e.g., for specific targets, e.g. to exploit dedicated hardware +// features +#include "base/internalops.hpp" + +#ifdef _GRB_WITH_BANSHEE + #include +#endif + +#endif + diff --git a/include/alp/iomode.hpp b/include/alp/iomode.hpp new file mode 100644 index 000000000..d93a31c63 --- /dev/null +++ b/include/alp/iomode.hpp @@ -0,0 +1,93 @@ + +/* + * Copyright 2021 Huawei Technologies Co., Ltd. + * + * 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. + */ + +/* + * @author A. N. Yzelman + * @date 21st of February, 2017 + */ + +#ifndef _H_GRB_IOMODE +#define _H_GRB_IOMODE + +namespace grb { + + /** + * The GraphBLAS input and output functionalities can either be used in a + * sequential or parallel fashion. Input functions such as buildVector or + * buildMatrixUnique default to sequential behaviour, which means that the + * collective calls to either function must have the exact same arguments-- + * that is, each user process is passed the exact same input data. + * + * \note This does not necessarily mean that all data is stored in a + * replicated fashion across all user processes. + * + * This default behaviour comes with obvious performance penalties; each user + * process must scan the full input data set, which takes \f$ \Theta( n ) \f$ + * time. Scalable behaviour would instead incur \f$ \Theta( n / P ) \f$ time, + * with \a P the number of user processes. + * Using a parallel IOMode provides exactly this scalable performance. On + * input, this means that each user process can pass different data to the + * same collective call to, e.g., buildVector or buildMatrixUnique. + * + * For output, which GraphBLAS provides via \a const iterators, sequential + * mode means that each user process retrieves an iterator over all output + * elements-- this requires costly all-to-all communication. Parallel mode + * output instead only returns those elements that do not require inter user- + * process communication. + * + * \note It is guaranteed the union of all output over all user processes + * corresponds to all elements in the GraphBLAS container. + * + * See the respective functions and classes for full details: + * -# grb::buildVector; + * -# grb::buildMatrixUnique; + * -# grb::Vector::const_iterator; + * -# grb::Matrix::const_iterator. + */ + enum IOMode { + + /** + * Sequential mode IO. + * + * Use of this mode results in non-scalable input and output. Its use is + * recommended only in case of small data sets or in one-off situations. + */ + SEQUENTIAL = 0, + + /** + * Parallel mode IO. + * + * Use of this mode results in fully scalable input and output. Its use is + * recommended as a default. Note that this does require the user to have + * his or her data distributed over the various user processes on input, + * and requires the user to handle distributed data on output. + * + * This is the default mode on all GraphBLAS IO functions. + * + * \note The parallel mode in situations where the number of user processes + * is one, for instance when choosing a sequential or data-centric + * GraphBLAS implementation, IOMode::parallel is equivalent to + * IOMode::sequential. + */ + PARALLEL + }; + + /** @} */ + +} // namespace grb + +#endif // end ``_H_GRB_IOMODE'' diff --git a/include/alp/matrix.hpp b/include/alp/matrix.hpp new file mode 100644 index 000000000..fec68360f --- /dev/null +++ b/include/alp/matrix.hpp @@ -0,0 +1,58 @@ + +/* + * Copyright 2021 Huawei Technologies Co., Ltd. + * + * 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. + */ + +/* + * @author A. N. Yzelman + * @date 10 of August + */ + +#ifndef _H_GRB_MATRIX +#define _H_GRB_MATRIX + +#include "base/config.hpp" +#include "base/matrix.hpp" + +// now include all specialisations contained in the backend directories: +#ifdef _GRB_WITH_REFERENCE + #include +#endif +#ifdef _GRB_WITH_DENSEREF + #include +#endif +#ifdef _GRB_WITH_LPF +#include +#endif +#ifdef _GRB_WITH_BANSHEE +#include +#endif + +// specify default only if requested during compilation +#ifdef _GRB_BACKEND +namespace grb { + template< typename D, enum Backend implementation = config::default_backend > + class Matrix; + + /* + * The default value of \a density could also be made conditional (Dense or Sparse) depending on \a config::default_backend + */ + template< typename T, typename Structure, enum Density density = Density::Dense, typename View = view::Original< void >, enum Backend backend = config::default_backend > + class StructuredMatrix; + +} // namespace grb +#endif + +#endif // end ``_H_GRB_MATRIX'' diff --git a/include/alp/monoid.hpp b/include/alp/monoid.hpp new file mode 100644 index 000000000..56f21b1a8 --- /dev/null +++ b/include/alp/monoid.hpp @@ -0,0 +1,138 @@ + +/* + * Copyright 2021 Huawei Technologies Co., Ltd. + * + * 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. + */ + +/* + * @author A. N. Yzelman + * @date 15 March, 2016 + */ + +#ifndef _H_GRB_MONOID +#define _H_GRB_MONOID + +#ifdef _DEBUG +#include +#endif + +#include //size_t +#include //posix_memalign, rand +#include + +#include + +#include +#include +#include + +/** + * The main Sparse Library namespace. + * + * All classes, enums, constants, and functions are declared in this namespace. + * This source file only contains testing code outside this namespace. + */ +namespace grb { + + /** + * A generalised monoid. + * + * @tparam _OP The monoid operator. + * @tparam _ID The monoid identity (the `0'). + */ + template< class _OP, template< typename > class _ID > + class Monoid { + + static_assert( grb::is_operator< _OP >::value, "First template argument to Monoid must be a GraphBLAS operator" ); + + static_assert( grb::is_associative< _OP >::value, + "Cannot form a monoid using the given operator since it is not " + "associative" ); + + static_assert( std::is_same< typename _OP::D1, typename _OP::D3 >::value || std::is_same< typename _OP::D2, typename _OP::D3 >::value, + "Cannot form a monoid when the output domain does not match at least " + "one of its input domains" ); + + public: + /** The left-hand side input domain. */ + typedef typename _OP::D1 D1; + + /** The right-hand side input domain. */ + typedef typename _OP::D2 D2; + + /** The output domain. */ + typedef typename _OP::D3 D3; + + /** The type of the underlying operator. */ + typedef _OP Operator; + + /** The underlying identity. */ + template< typename IdentityType > + using Identity = _ID< IdentityType >; + + private: + /** + * The underlying binary operator. + * + * For stateless operators, this field corresponds to empty storage. + */ + Operator op; + + public: + /** + * Constructor that infers a default operator, given the operator type. + * Useful for stateless operators. + */ + Monoid() : op() {} + + /** + * Retrieves the identity corresponding to this monoid. The identity value + * will be cast to the requested domain. + * + * @tparam D The requested domain of the identity. + * + * @returns The identity corresponding to this monoid, cast to the requested + * domain. + */ + template< typename D > + constexpr D getIdentity() const { + return Identity< D >::value(); + } + + /** + * Retrieves the underlying operator. + * + * @return The underlying operator. Any state is copied. + */ + Operator getOperator() const { + return op; + } + }; + + // type traits + template< class _OP, template< typename > class _ID > + struct is_monoid< Monoid< _OP, _ID > > { + /** This is a GraphBLAS monoid. */ + static const constexpr bool value = true; + }; + + template< class OP, template< typename > class ID > + struct has_immutable_nonzeroes< Monoid< OP, ID > > { + static const constexpr bool value = grb::is_monoid< Monoid< OP, ID > >::value && + std::is_same< OP, typename grb::operators::logical_or< typename OP::D1, typename OP::D2, typename OP::D3 > >::value; + }; + +} // namespace grb + +#endif diff --git a/include/alp/ops.hpp b/include/alp/ops.hpp new file mode 100644 index 000000000..918b37db9 --- /dev/null +++ b/include/alp/ops.hpp @@ -0,0 +1,566 @@ + +/* + * Copyright 2021 Huawei Technologies Co., Ltd. + * + * 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. + */ + +/* + * @author A. N. Yzelman + * @date 8th of August, 2016 + */ + +#ifndef _H_GRB_OPERATORS +#define _H_GRB_OPERATORS + +#include "internalops.hpp" +#include "type_traits.hpp" + +namespace grb { + + /** + * This namespace holds various standard operators such as #grb::operators::add + * and #grb::operators::mul. + */ + namespace operators { + + /** + * This operator discards all right-hand side input and simply copies the + * left-hand side input to the output variable. It exposes the complete + * interface detailed in grb::operators::internal::Operator. This operator + * can be passed to any GraphBLAS function or object constructor. + * + * Mathematical notation: \f$ \odot(x,y)\ \to\ x \f$. + * + * \note A proper GraphBLAS program never uses the interface exposed by this + * operator directly, and instead simply passes the operator on to + * GraphBLAS functions. + * + * @tparam D1 The left-hand side input domain. + * @tparam D2 The right-hand side input domain. + * @tparam D3 The output domain. + */ + template< typename D1, typename D2 = D1, typename D3 = D2, enum Backend implementation = config::default_backend > + class left_assign : public internal::Operator< internal::left_assign< D1, D2, D3, implementation > > { + public: + template< typename A, typename B, typename C, enum Backend D > + using GenericOperator = left_assign< A, B, C, D >; + left_assign() {} + }; + + /** TODO documentation. */ + template< typename D1, typename D2 = D1, typename D3 = D2, enum Backend implementation = config::default_backend > + class left_assign_if : public internal::Operator< internal::left_assign_if< D1, D2, D3, implementation > > { + public: + template< typename A, typename B, typename C, enum Backend D > + using GenericOperator = left_assign_if< A, B, C, D >; + left_assign_if() {} + }; + + /** + * This operator discards all left-hand side input and simply copies the + * right-hand side input to the output variable. It exposes the complete + * interface detailed in grb::operators::internal::Operator. This operator + * can be passed to any GraphBLAS function or object constructor. + * + * Mathematical notation: \f$ \odot(x,y)\ \to\ y \f$. + * + * \note A proper GraphBLAS program never uses the interface exposed by this + * operator directly, and instead simply passes the operator on to + * GraphBLAS functions. + * + * @tparam D1 The left-hand side input domain. + * @tparam D2 The right-hand side input domain. + * @tparam D3 The output domain. + */ + template< typename D1, typename D2 = D1, typename D3 = D2, enum Backend implementation = config::default_backend > + class right_assign : public internal::Operator< internal::right_assign< D1, D2, D3, implementation > > { + public: + template< typename A, typename B, typename C, enum Backend D > + using GenericOperator = right_assign< A, B, C, D >; + right_assign() {} + }; + + /** TODO documentation. */ + template< typename D1, typename D2 = D1, typename D3 = D2, enum Backend implementation = config::default_backend > + class right_assign_if : public internal::Operator< internal::right_assign_if< D1, D2, D3, implementation > > { + public: + template< typename A, typename B, typename C, enum Backend D > + using GenericOperator = right_assign_if< A, B, C, D >; + right_assign_if() {} + }; + + /** + * This operator takes the sum of the two input parameters and writes it to + * the output variable. It exposes the complete interface detailed in + * grb::operators::internal::Operator. This operator can be passed to any + * GraphBLAS function or object constructor. + * + * Mathematical notation: \f$ \odot(x,y)\ \to\ x + y \f$. + * + * \note A proper GraphBLAS program never uses the interface exposed by this + * operator directly, and instead simply passes the operator on to + * GraphBLAS functions. + * + * @tparam D1 The left-hand side input domain. + * @tparam D2 The right-hand side input domain. + * @tparam D3 The output domain. + * + * \warning This operator expects numerical types for \a D1, \a D2, and + * \a D3, or types that have the appropriate operator+-functions + * available. + */ + // [Operator Wrapping] + template< typename D1, typename D2 = D1, typename D3 = D2, enum Backend implementation = config::default_backend > + class add : public internal::Operator< internal::add< D1, D2, D3, implementation > > { + public: + template< typename A, typename B, typename C, enum Backend D > + using GenericOperator = add< A, B, C, D >; + add() {} + }; + // [Operator Wrapping] + + /** + * This operator multiplies the two input parameters and writes the result to + * the output variable. It exposes the complete interface detailed in + * grb::operators::internal::Operator. This operator can be passed to any + * GraphBLAS function or object constructor. + * + * Mathematical notation: \f$ \odot(x,y)\ \to\ x \cdot y \f$. + * + * \note A proper GraphBLAS program never uses the interface exposed by this + * operator directly, and instead simply passes the operator on to + * GraphBLAS functions. + * + * @tparam D1 The left-hand side input domain. + * @tparam D2 The right-hand side input domain. + * @tparam D3 The output domain. + * + * \warning This operator expects numerical types for \a D1, \a D2, and + * \a D3, or types that have the appropriate operator*-functions + * available. + */ + template< typename D1, typename D2 = D1, typename D3 = D2, enum Backend implementation = config::default_backend > + class mul : public internal::Operator< internal::mul< D1, D2, D3, implementation > > { + public: + template< typename A, typename B, typename C, enum Backend D > + using GenericOperator = mul< A, B, C, D >; + mul() {} + }; + + /** + * This operator takes the maximum of the two input parameters and writes + * the result to the output variable. It exposes the complete interface + * detailed in grb::operators::internal::Operator. This operator can be + * passed to any GraphBLAS function or object constructor. + * + * Mathematical notation: \f$ \max(x,y)\ \to\ \begin{cases} + * x \text{ if } x > y \\ + * y \text{ otherwise} \end{cases} \f$. + * + * \note A proper GraphBLAS program never uses the interface exposed by this + * operator directly, and instead simply passes the operator on to + * GraphBLAS functions. + * + * @tparam D1 The left-hand side input domain. + * @tparam D2 The right-hand side input domain. + * @tparam D3 The output domain. + * + * \warning This operator expects objects with a partial ordering defined on + * and between elements of types \a D1, \a D2, and \a D3. + */ + template< typename D1, typename D2 = D1, typename D3 = D2, enum Backend implementation = config::default_backend > + class max : public internal::Operator< internal::max< D1, D2, D3, implementation > > { + public: + template< typename A, typename B, typename C, enum Backend D > + using GenericOperator = max< A, B, C, D >; + max() {} + }; + + /** + * This operator takes the minimum of the two input parameters and writes + * the result to the output variable. It exposes the complete interface + * detailed in grb::operators::internal::Operator. This operator can be + * passed to any GraphBLAS function or object constructor. + * + * Mathematical notation: \f$ \max(x,y)\ \to\ \begin{cases} + * x \text{ if } x < y \\ + * y \text{ otherwise} \end{cases} \f$. + * + * \note A proper GraphBLAS program never uses the interface exposed by this + * operator directly, and instead simply passes the operator on to + * GraphBLAS functions. + * + * @tparam D1 The left-hand side input domain. + * @tparam D2 The right-hand side input domain. + * @tparam D3 The output domain. + * + * \warning This operator expects objects with a partial ordering defined on + * and between elements of types \a D1, \a D2, and \a D3. + */ + template< typename D1, typename D2 = D1, typename D3 = D2, enum Backend implementation = config::default_backend > + class min : public internal::Operator< internal::min< D1, D2, D3, implementation > > { + public: + template< typename A, typename B, typename C, enum Backend D > + using GenericOperator = min< A, B, C, D >; + min() {} + }; + + /** \todo add documentation */ + template< typename D1, typename D2 = D1, typename D3 = D2, enum Backend implementation = config::default_backend > + class subtract : public internal::Operator< internal::substract< D1, D2, D3, implementation > > { + public: + template< typename A, typename B, typename C, enum Backend D > + using GenericOperator = subtract< A, B, C, D >; + subtract() {} + }; + + /** \todo add documentation */ + template< typename D1, typename D2 = D1, typename D3 = D2, enum Backend implementation = config::default_backend > + class divide : public internal::Operator< internal::divide< D1, D2, D3, implementation > > { + public: + template< typename A, typename B, typename C, enum Backend D > + using GenericOperator = divide< A, B, C, D >; + divide() {} + }; + + /** \todo add documentation */ + template< typename D1, typename D2 = D1, typename D3 = D2, enum Backend implementation = config::default_backend > + class divide_reverse : public internal::Operator< internal::divide_reverse< D1, D2, D3, implementation > > { + public: + template< typename A, typename B, typename C, enum Backend D > + using GenericOperator = divide_reverse< A, B, C, D >; + divide_reverse() {} + }; + + /** \todo add documentation */ + template< typename D1, typename D2 = D1, typename D3 = D2, enum Backend implementation = config::default_backend > + class equal : public internal::Operator< internal::equal< D1, D2, D3, implementation > > { + public: + template< typename A, typename B, typename C, enum Backend D > + using GenericOperator = equal< A, B, C, D >; + equal() {} + }; + + /** \todo add documentation */ + template< typename D1, typename D2 = D1, typename D3 = D2, enum Backend implementation = config::default_backend > + class not_equal : public internal::Operator< internal::not_equal< D1, D2, D3, implementation > > { + public: + template< typename A, typename B, typename C, enum Backend D > + using GenericOperator = not_equal< A, B, C, D >; + not_equal() {} + }; + + /** \todo add documentation */ + template< typename D1, typename D2 = D1, typename D3 = D2, enum Backend implementation = config::default_backend > + class any_or : public internal::Operator< internal::any_or< D1, D2, D3, implementation > > { + public: + template< typename A, typename B, typename C, enum Backend D > + using GenericOperator = any_or< A, B, C, D >; + any_or() {} + }; + + /** \todo add documentation */ + template< typename D1, typename D2 = D1, typename D3 = D2, enum Backend implementation = config::default_backend > + class logical_or : public internal::Operator< internal::logical_or< D1, D2, D3, implementation > > { + public: + template< typename A, typename B, typename C, enum Backend D > + using GenericOperator = logical_or< A, B, C, D >; + logical_or() {} + }; + + /** \todo add documentation */ + template< typename D1, typename D2 = D1, typename D3 = D2, enum Backend implementation = config::default_backend > + class logical_and : public internal::Operator< internal::logical_and< D1, D2, D3, implementation > > { + public: + template< typename A, typename B, typename C, enum Backend D > + using GenericOperator = logical_and< A, B, C, D >; + logical_and() {} + }; + + /** \todo add documentation */ + template< typename D1, typename D2 = D1, typename D3 = D2, enum Backend implementation = config::default_backend > + class relu : public internal::Operator< internal::relu< D1, D2, D3, implementation > > { + public: + template< typename A, typename B, typename C, enum Backend D > + using GenericOperator = relu< A, B, C, D >; + relu() {} + }; + + /** \todo add documentation */ + template< typename D1, typename D2 = D1, typename D3 = D2, enum Backend implementation = config::default_backend > + class abs_diff : public internal::Operator< internal::abs_diff< D1, D2, D3, implementation > > { + public: + template< typename A, typename B, typename C, enum Backend D > + using GenericOperator = abs_diff< A, B, C, D >; + abs_diff() {} + }; + + /** TODO documentation. */ + template< typename IType, typename VType > + class argmin : public internal::Operator< internal::argmin< IType, VType > > { + public: + argmin() {} + }; + + /** TODO documentation. */ + template< typename IType, typename VType > + class argmax : public internal::Operator< internal::argmax< IType, VType > > { + public: + argmax() {} + }; + + /** \todo add documentation */ + template< typename D1, typename D2, typename D3, enum Backend implementation = config::default_backend > + class square_diff : public internal::Operator< internal::square_diff< D1, D2, D3, implementation > > { + public: + template< typename A, typename B, typename C, enum Backend D > + using GenericOperator = square_diff< A, B, C, D >; + square_diff() {} + }; + + /** \todo add documentation */ + template< typename IN1, typename IN2, enum Backend implementation = config::default_backend > + class zip : public internal::Operator< internal::zip< IN1, IN2, implementation > > { + public: + template< typename A, typename B, enum Backend D > + using GenericOperator = zip< A, B, D >; + zip() {} + }; + + /** \todo add documentation */ + template< typename D1, typename D2 = D1, typename D3 = D2, enum Backend implementation = config::default_backend > + class equal_first : public internal::Operator< internal::equal_first< D1, D2, D3, implementation > > { + public: + template< typename A, typename B, typename C, enum Backend D > + using GenericOperator = equal_first< A, B, C, D >; + equal_first() {} + }; + + } // namespace operators + + template< typename D1, typename D2, typename D3, enum Backend implementation > + struct is_operator< operators::left_assign_if< D1, D2, D3, implementation > > { + static const constexpr bool value = true; + }; + + template< typename D1, typename D2, typename D3, enum Backend implementation > + struct is_operator< operators::right_assign_if< D1, D2, D3, implementation > > { + static const constexpr bool value = true; + }; + + template< typename D1, typename D2, typename D3, enum Backend implementation > + struct is_operator< operators::left_assign< D1, D2, D3, implementation > > { + static const constexpr bool value = true; + }; + + template< typename D1, typename D2, typename D3, enum Backend implementation > + struct is_operator< operators::right_assign< D1, D2, D3, implementation > > { + static const constexpr bool value = true; + }; + + // [Operator Type Traits] + template< typename D1, typename D2, typename D3, enum Backend implementation > + struct is_operator< operators::add< D1, D2, D3, implementation > > { + static const constexpr bool value = true; + }; + // [Operator Type Traits] + + template< typename D1, typename D2, typename D3, enum Backend implementation > + struct is_operator< operators::mul< D1, D2, D3, implementation > > { + static const constexpr bool value = true; + }; + + template< typename D1, typename D2, typename D3, enum Backend implementation > + struct is_operator< operators::max< D1, D2, D3, implementation > > { + static const constexpr bool value = true; + }; + + template< typename D1, typename D2, typename D3, enum Backend implementation > + struct is_operator< operators::min< D1, D2, D3, implementation > > { + static const constexpr bool value = true; + }; + + template< typename D1, typename D2, typename D3, enum Backend implementation > + struct is_operator< operators::subtract< D1, D2, D3, implementation > > { + static const constexpr bool value = true; + }; + + template< typename D1, typename D2, typename D3, enum Backend implementation > + struct is_operator< operators::divide< D1, D2, D3, implementation > > { + static const constexpr bool value = true; + }; + + template< typename D1, typename D2, typename D3, enum Backend implementation > + struct is_operator< operators::divide_reverse< D1, D2, D3, implementation > > { + static const constexpr bool value = true; + }; + + template< typename D1, typename D2, typename D3, enum Backend implementation > + struct is_operator< operators::equal< D1, D2, D3, implementation > > { + static const constexpr bool value = true; + }; + + template< typename D1, typename D2, typename D3, enum Backend implementation > + struct is_operator< operators::not_equal< D1, D2, D3, implementation > > { + static const constexpr bool value = true; + }; + + template< typename D1, typename D2, typename D3, enum Backend implementation > + struct is_operator< operators::any_or< D1, D2, D3, implementation > > { + static const constexpr bool value = true; + }; + + template< typename D1, typename D2, typename D3, enum Backend implementation > + struct is_operator< operators::logical_or< D1, D2, D3, implementation > > { + static const constexpr bool value = true; + }; + + template< typename D1, typename D2, typename D3, enum Backend implementation > + struct is_operator< operators::logical_and< D1, D2, D3, implementation > > { + static const constexpr bool value = true; + }; + + template< typename D1, typename D2, typename D3, enum Backend implementation > + struct is_operator< operators::abs_diff< D1, D2, D3, implementation > > { + static const constexpr bool value = true; + }; + + template< typename D1, typename D2, typename D3, enum Backend implementation > + struct is_operator< operators::relu< D1, D2, D3, implementation > > { + static const constexpr bool value = true; + }; + + template< typename IType, typename VType > + struct is_operator< operators::argmin< IType, VType > > { + static const constexpr bool value = true; + }; + + template< typename IType, typename VType > + struct is_operator< operators::argmax< IType, VType > > { + static const constexpr bool value = true; + }; + + template< typename D1, typename D2, typename D3, enum Backend implementation > + struct is_operator< operators::square_diff< D1, D2, D3, implementation > > { + static const constexpr bool value = true; + }; + + template< typename IN1, typename IN2, enum Backend implementation > + struct is_operator< operators::zip< IN1, IN2, implementation > > { + static const constexpr bool value = true; + }; + + template< typename D1, typename D2, typename D3, enum Backend implementation > + struct is_operator< operators::equal_first< D1, D2, D3, implementation > > { + static const constexpr bool value = true; + }; + + template< typename D1, typename D2, typename D3 > + struct is_idempotent< operators::min< D1, D2, D3 > > { + static const constexpr bool value = true; + }; + + template< typename D1, typename D2, typename D3 > + struct is_idempotent< operators::max< D1, D2, D3 > > { + static const constexpr bool value = true; + }; + + template< typename D1, typename D2, typename D3 > + struct is_idempotent< operators::any_or< D1, D2, D3 > > { + static const constexpr bool value = true; + }; + + template< typename D1, typename D2, typename D3 > + struct is_idempotent< operators::logical_or< D1, D2, D3 > > { + static const constexpr bool value = true; + }; + + template< typename D1, typename D2, typename D3 > + struct is_idempotent< operators::logical_and< D1, D2, D3 > > { + static const constexpr bool value = true; + }; + + template< typename D1, typename D2, typename D3 > + struct is_idempotent< operators::relu< D1, D2, D3 > > { + static const constexpr bool value = true; + }; + + template< typename D1, typename D2, typename D3 > + struct is_idempotent< operators::left_assign_if< D1, D2, D3 > > { + static const constexpr bool value = true; + }; + + template< typename D1, typename D2, typename D3 > + struct is_idempotent< operators::right_assign_if< D1, D2, D3 > > { + static const constexpr bool value = true; + }; + + template< typename IType, typename VType > + struct is_idempotent< operators::argmin< IType, VType > > { + static const constexpr bool value = true; + }; + + template< typename IType, typename VType > + struct is_idempotent< operators::argmax< IType, VType > > { + static const constexpr bool value = true; + }; + + template< typename OP > + struct is_associative { + static constexpr const bool value = is_operator< OP >::value && OP::is_associative(); + }; + + template< typename OP > + struct is_commutative { + static constexpr const bool value = is_operator< OP >::value && OP::is_commutative(); + }; + + // internal type traits follow + + namespace internal { + + template< typename D1, typename D2, typename D3, enum Backend implementation > + struct maybe_noop< operators::left_assign_if< D1, D2, D3, implementation > > { + static const constexpr bool value = true; + }; + + template< typename D1, typename D2, typename D3, enum Backend implementation > + struct maybe_noop< operators::right_assign_if< D1, D2, D3, implementation > > { + static const constexpr bool value = true; + }; + + } // namespace grb::internal + +} // namespace grb + +#ifdef __DOXYGEN__ + /** + * Macro that disables the definition of an operator<< overload for + * instances of std::pair. This overload is only active when the _DEBUG + * macro is defined, but may clash with user-defined overloads. + */ + #define _DEBUG_NO_IOSTREAM_PAIR_CONVERTER +#endif +#ifdef _DEBUG + #ifndef _DEBUG_NO_IOSTREAM_PAIR_CONVERTER + template< typename U, typename V > + std::ostream & operator<<( std::ostream & out, const std::pair< U, V > & pair ) { + out << "( " << pair.first << ", " << pair.second << " )"; + return out; + } + #endif +#endif + +#endif // end ``_H_GRB_OPERATORS'' + diff --git a/include/alp/phase.hpp b/include/alp/phase.hpp new file mode 100644 index 000000000..636ad7d9b --- /dev/null +++ b/include/alp/phase.hpp @@ -0,0 +1,70 @@ + +/* + * Copyright 2021 Huawei Technologies Co., Ltd. + * + * 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. + */ + +/* + * @author A. N. Yzelman + */ + +#ifndef _H_GRB_PHASE +#define _H_GRB_PHASE + +namespace grb { + + /** + * Some primitives may require a symbolic phase prior to executing a numeric + * phase. The symbolic phase may require system calls in order to, for example, + * reallocate storage to account for fill-in. + * + * For vectors, the user usually is able to pass in a reasonable upper bound on + * the number of nonzeroes and as * such, level-1 and level-2 primitives need + * not rely on a symbolic phase. For matrices that act as output on level-3 + * primitives, however, it is instead far more common to not know of a + * reasonable upper bound beforehand; in these cases the use of a symbolic + * phase usually cannot be avoided. + * + * The performance semantics of primitives, which often do not allow system + * calls, are guaranteed only for numeric phases. + */ + enum PHASE { + + /** + * Simulates the operation with the sole purpose of determining the number of + * nonzeroes that the output container should hold. If this should be higher + * than the current capacity, then the output container will be reallocated. + * + * This means the performance costs increase with sum of the container + * dimensions plus the number of output nonzeroes, both in terms of work and + * data movement, whenever the call must reallocate. In that case it will also + * make system calls. + */ + SYMBOLIC, + + /** + * With the numerical phase, the user guarantees (all) output container(s) + * have enough capacity-- including for any newly materialised nonzeroes. + * The user may either give this guarantee through her knowledge of the + * overall computation (e.g., in a Conjugate Gradient solver for linear + * systems the vectors of length n will hold at most n nonzeroes), or may + * ensure sufficient capacity by first calling the primitive using a + * SYMBOLIC phase. + */ + NUMERICAL + }; + +} // namespace grb + +#endif // end ``_H_GRB_PHASE'' diff --git a/include/alp/rc.hpp b/include/alp/rc.hpp new file mode 100644 index 000000000..53f4d974c --- /dev/null +++ b/include/alp/rc.hpp @@ -0,0 +1,150 @@ + +/* + * Copyright 2021 Huawei Technologies Co., Ltd. + * + * 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. + */ + +/** + * @file + * + * Defines all possible GraphBLAS error codes. + * + * @author A. N. Yzelman + * @date 9--11 August, 2016 + */ + +#ifndef _H_GRB_RC +#define _H_GRB_RC + +#include + +namespace grb { + + /** + * Return codes of public functions. + */ + enum RC { + + /** + * Default success code. + * + * All GraphBLAS functions may return this error code even if not explicitly + * documented. Any non-SUCCESS error code shall have no side effects; if a + * call fails, it shall be as though the call was never made. The only + * exception is #grb::PANIC. + */ + SUCCESS = 0, + + /** + * Generic fatal error code. + * + * Signals an illegal state of all GraphBLAS objects connected to the call + * returning this error. Users can only exit gracefully when encoutering + * errors of this type-- after a GraphBLAS function returns this error + * code, the state of the library becomes undefined. + * + * An implementation is encouraged to write clear error messages to stderr + * prior to returning this error code. + * + * Rationale: instead of using assert within GraphBLAS + * implementations which would crash the entire application, implementations + * should instead simply return #grb::PANIC and let the GraphBLAS user shut + * down his or her application as gracefully as possible. + * + * All GraphBLAS functions may return this error code even if not explicitly + * documented. + */ + PANIC, + + /** + * Out of memory error code. + * + * User can mitigate by freeing memory and retrying the call or by reducing + * the amount of memory required by this call. + * + * This error code may only be returned when explicitly documented as such. + */ + OUTOFMEM, + + /** + * One or more of the GraphBLAS objects corresponding to the call returning + * this error have mismatching dimensions. + * + * User can mitigate by reissuing with correct parameters. It is usually not + * possible to mitigate at run-time; usually this signals a logic programming + * error. + * + * This error code may only be returned when explicitly documented as such. + */ + MISMATCH, + + /** + * One or more of the GraphBLAS objects corresponding to the call returning + * this error refer to the same object while this is forbidden. + * + * User can mitigate by reissuing with correct parameters. It is usually not + * possible to mitigate at run-time; usually this signals a logic programming + * error. Implementations are not required to return this error code and may + * incur undefined behaviour instead. + * + * This error code may only be returned when explicitly documented as such. + */ + OVERLAP, + + /** + * One or more output parameters would overflow on this function call. + * + * Users can mitigate by supplying a larger integral types. + * + * This error code may only be returned when explicitly documented as such. + */ + OVERFLW, + + /** + * A bsp::init() assuming multiple user processes while this is not supported + * by the chosen implementation backend will reduce this error code. + * + * @see config::default_backend for a description of how the current backend + * is selected (if not explicitly). + * + * This error code may only be returned when explicitly documented as such. + */ + UNSUPPORTED, + + /** + * A call to a GraphBLAS function with an illegal parameter value might + * return this error code. When returned, no undefined behaviour will occur + * as a result of having passed the illegal argument. + * + * This error code may only be returned when explicitly documented as such. + */ + ILLEGAL, + + /** + * Indicates when one of the grb::algorithms has failed to achieve its + * intended result, for instance, when an iterative method failed to + * converged within its alloted resources. + * + * This error code may only be returned when explicitly documented as such. + */ + FAILED + + }; + + /** @returns A string describing the given error code. */ + std::string toString( const RC code ); + +} // namespace grb + +#endif diff --git a/include/graphblas/denseref/alloc.hpp b/include/alp/reference/alloc.hpp similarity index 100% rename from include/graphblas/denseref/alloc.hpp rename to include/alp/reference/alloc.hpp diff --git a/include/graphblas/denseref/benchmark.hpp b/include/alp/reference/benchmark.hpp similarity index 100% rename from include/graphblas/denseref/benchmark.hpp rename to include/alp/reference/benchmark.hpp diff --git a/include/graphblas/denseref/blas0.hpp b/include/alp/reference/blas0.hpp similarity index 100% rename from include/graphblas/denseref/blas0.hpp rename to include/alp/reference/blas0.hpp diff --git a/include/graphblas/denseref/blas1.hpp b/include/alp/reference/blas1.hpp similarity index 100% rename from include/graphblas/denseref/blas1.hpp rename to include/alp/reference/blas1.hpp diff --git a/include/graphblas/denseref/blas2.hpp b/include/alp/reference/blas2.hpp similarity index 100% rename from include/graphblas/denseref/blas2.hpp rename to include/alp/reference/blas2.hpp diff --git a/include/graphblas/denseref/blas3.hpp b/include/alp/reference/blas3.hpp similarity index 100% rename from include/graphblas/denseref/blas3.hpp rename to include/alp/reference/blas3.hpp diff --git a/include/graphblas/denseref/collectives.hpp b/include/alp/reference/collectives.hpp similarity index 100% rename from include/graphblas/denseref/collectives.hpp rename to include/alp/reference/collectives.hpp diff --git a/include/graphblas/denseref/config.hpp b/include/alp/reference/config.hpp similarity index 100% rename from include/graphblas/denseref/config.hpp rename to include/alp/reference/config.hpp diff --git a/include/graphblas/denseref/exec.hpp b/include/alp/reference/exec.hpp similarity index 100% rename from include/graphblas/denseref/exec.hpp rename to include/alp/reference/exec.hpp diff --git a/include/graphblas/denseref/init.hpp b/include/alp/reference/init.hpp similarity index 100% rename from include/graphblas/denseref/init.hpp rename to include/alp/reference/init.hpp diff --git a/include/graphblas/denseref/io.hpp b/include/alp/reference/io.hpp similarity index 100% rename from include/graphblas/denseref/io.hpp rename to include/alp/reference/io.hpp diff --git a/include/graphblas/denseref/matrix.hpp b/include/alp/reference/matrix.hpp similarity index 100% rename from include/graphblas/denseref/matrix.hpp rename to include/alp/reference/matrix.hpp diff --git a/include/graphblas/denseref/pinnedvector.hpp b/include/alp/reference/pinnedvector.hpp similarity index 100% rename from include/graphblas/denseref/pinnedvector.hpp rename to include/alp/reference/pinnedvector.hpp diff --git a/include/graphblas/denseref/properties.hpp b/include/alp/reference/properties.hpp similarity index 100% rename from include/graphblas/denseref/properties.hpp rename to include/alp/reference/properties.hpp diff --git a/include/graphblas/denseref/scalar.hpp b/include/alp/reference/scalar.hpp similarity index 100% rename from include/graphblas/denseref/scalar.hpp rename to include/alp/reference/scalar.hpp diff --git a/include/graphblas/denseref/spmd.hpp b/include/alp/reference/spmd.hpp similarity index 100% rename from include/graphblas/denseref/spmd.hpp rename to include/alp/reference/spmd.hpp diff --git a/include/graphblas/denseref/vector.hpp b/include/alp/reference/vector.hpp similarity index 100% rename from include/graphblas/denseref/vector.hpp rename to include/alp/reference/vector.hpp diff --git a/include/graphblas/denseref/vectoriterator.hpp b/include/alp/reference/vectoriterator.hpp similarity index 100% rename from include/graphblas/denseref/vectoriterator.hpp rename to include/alp/reference/vectoriterator.hpp diff --git a/include/graphblas/scalar.hpp b/include/alp/scalar.hpp similarity index 100% rename from include/graphblas/scalar.hpp rename to include/alp/scalar.hpp diff --git a/include/alp/semiring.hpp b/include/alp/semiring.hpp new file mode 100644 index 000000000..c1d61830f --- /dev/null +++ b/include/alp/semiring.hpp @@ -0,0 +1,353 @@ + +/* + * Copyright 2021 Huawei Technologies Co., Ltd. + * + * 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. + */ + +/* + * @author A. N. Yzelman + * @date 15th of March, 2016 + */ + +#ifndef _H_GRB_SEMIRING +#define _H_GRB_SEMIRING + +#include +#include +#include + +/** + * The main GraphBLAS namespace. + */ +namespace grb { + + /** + * A generalised semiring. + * + * This semiring works with the standard operators provided in grb::operators + * as well as with standard identities provided in grb::identities. + * + * \par Operators + * + * An operator \a OP here is of the form \f$ f:\ D_1 \times D_2 \to D_3 \f$; + * i.e., it has a fixed left-hand input domain, a fixed right-hand input + * domain, and a fixed output domain. + * + * A generalised semiring must include two operators; an additive operator, + * and a multiplicative one: + * -# \f$ \oplus: \ D_1 \times D_2 \to D_3 \f$, and + * -# \f$ \otimes:\ D_4 \times D_5 \to D_6 \f$. + * + * By convention, primitives such as grb::mxv will feed the output of the + * multiplicative operation to the additive operator as left-hand side input; + * hence, a valid semiring must have \f$ D_6 = D_1 \f$. Should the additive + * operator reduce several multiplicative outputs, the thus-far accumulated + * value will thus be passed as right-hand input to the additive operator; + * hence, a valid semiring must also have \f$ D_2 = D_3 \f$. + * + * If these constraints on the domains do not hold, attempted compilation will + * result in a clear error message. + * + * A semiring, in our definition here, thus in fact only defines four domains. + * We may thus rewrite the above definitions of the additive and multiplicative + * operators as: + * -# \f$ \otimes:\ D_1 \times D_2 \to D_3 \f$, and + * -# \f$ \oplus: \ D_3 \times D_4 \to D_4 \f$. + * + * \par Identities + * + * There are two identities that make up a generalised semiring: the zero- + * identity and the one-identity. These identities must be able to instantiate + * values for different domains, should indeed the four domains a generalised + * semiring operates on differ. + * + * Specifically, the zero-identity may be required for any of the domains the + * additive and multiplicative operators employ, whereas the one-identity may + * only be required for the domains the multiplicative operator employs. + * + * \par Standard examples + * + * An example of the standard semiring would be: + * grb::Semiring< + * grb::operators::add< double, double, double >, + * grb::operators::mul< double, double, double >, + * grb::identities::zero, + * grb::identitites::one + * > realSemiring; + * In this standard case, all domains the operators the semiring comprises are + * equal to one another. GraphBLAS supports the following shorthand for this + * special case: + * grb::Semiring< + * grb::operators::add< double >, + * grb::operators::mul< double >, + * grb::identities::zero, + * grb::identities::one + * > realSemiring; + * + * As another example, consider min-plus algebras. These may be used, for + * example, for deriving shortest paths through an edge-weighted graph: + * grb::Semiring< + * grb::operators::min< unsigned int >, + * grb::operators::add< unsigned int >, + * grb::identities::negative_infinity, + * grb::identities::zero + * > minPlus; + * + * \par CMonoid-categories + * + * While in these standard examples the relation to standard semirings as + * defined in mathematics apply, the possiblity of having differing domains + * that may not even be subsets of one another makes the above sketch + * generalisation incompatible with the standard notion of semirings. + * + * Our notion of a generalised semiring indeed is closer to what one might call + * CMonoid-categories, i.e. categories enriched in commutative monoids. Such + * CMonoid-categories are specified by some data, and are required to satisfy + * certain algebraic (equational) laws, thus being well-specified mathematical + * objects. + * + * Additionally, such CMonoid-categories encapsulate the definition of + * semirings, vector spaces, left modules and right modules. + * + * The full structure of a CMonoid-category C is specified by the data: + * + * -# a set ob(C) of so-called objects, + * -# for each pair of objects a,b in ob(C), a commutative monoid + * (C(a,b), 0_{a,b}, +_{a,b}), + * -# for each triple of objects a,b,c in ob(C), a multiplication operation + * ._{a,b,c} : C(b,c) x C(a,b) -> C(a,c), and + * -# for each object a in ob(C), a multiplicative identity 1_a in C(a,a). + * + * This data is then required to specify a list of algebraic laws that + * essentially capture: + * -# (that the (C(a,b), 0_{a,b}, +_{a,b}) are commutative monoids) + * -# joint associativity of the family of multiplication operators, + * -# that the multiplicative identities 1_a are multiplicative identities, + * -# that the family of multiplication operators ._{a,b,c} distributes over + * the family of addition operators +_{a,b} on the left and on the right + * in an appropriate sense, and + * -# left and right annihilativity of the family of additive zeros 0_{a,b}. + * + * \par Generalised semirings in terms of CMonoid-categories + * + * The current notion of generalised semiring is specified by the following + * data: + * -# operators OP1, OP2, + * -# the four domains those operators are defined on, + * -# an additive identity ID1, and + * -# a multiplicative identity ID2. + * + * The four domains correspond to the choice of a CMonoid-category with two + * objects; e.g., \f$ ob(C)=\{a,b\} \f$. This gives rise to four possible + * pairings of the objects, including self-pairs, that correspond to the + * four different domains. + * + * CMonoid-categories then demand an additive operator must exist that + * operates purely within each of the four domains, when combined with a zero + * identity that likewise must exist in each of the four domains. None of + * these additive operators in fact matches with the generalised semiring's + * additive operator. + * + * CMonoid-categories also demand the existance of six different + * multiplicative operators that operate on three different domains each, that + * the composition of these operators is associative, that these operators + * distribute over the appropriate additive operators, and that there exists + * an multiplicative identity over at least one of the input domains. + * + * One of these six multiplicative operators is what appears in our generalised + * semiring. We seem to select exactly that multiplicative operator for which + * both input domains have an multiplicative identity. + * + * Finally, the identities corresponding to additive operators must act as + * annihilators over the matching multiplicative operators. + * + * Full details can be found in the git repository located here: + * https://gitlab.huaweirc.ch/abooij/semirings + * + * @tparam _OP1 The addition operator. + * @tparam _OP2 The multiplication operator. + * @tparam _ID1 The identity under addition (the `0'). + * @tparam _ID2 The identity under multiplication (the `1'). + */ + template< class _OP1, class _OP2, template< typename > class _ID1, template< typename > class _ID2 > + class Semiring { + + static_assert( std::is_same< typename _OP2::D3, typename _OP1::D1 >::value, + "The multiplicative output type must match the left-hand additive " + "input type" ); + + static_assert( std::is_same< typename _OP1::D2, typename _OP1::D3 >::value, + "The right-hand input type of the additive operator must match its " + "output type" ); + + static_assert( grb::is_associative< _OP1 >::value, + "Cannot construct a semiring using a non-associative additive " + "operator" ); + + static_assert( grb::is_associative< _OP2 >::value, + "Cannot construct a semiring using a non-associative multiplicative " + "operator" ); + + static_assert( grb::is_commutative< _OP1 >::value, + "Cannot construct a semiring using a non-commutative additive " + "operator" ); + + public: + /** The first input domain of the multiplicative operator. */ + typedef typename _OP2::D1 D1; + + /** The second input domain of the multiplicative operator. */ + typedef typename _OP2::D2 D2; + + /** + * The output domain of the multiplicative operator. + * The first input domain of the additive operator. + */ + typedef typename _OP2::D3 D3; + + /** + * The second input domain of the additive operator. + * The output domain of the additive operator. + */ + typedef typename _OP1::D2 D4; + + /** The additive operator type. */ + typedef _OP1 AdditiveOperator; + + /** The multiplicative operator type. */ + typedef _OP2 MultiplicativeOperator; + + /** The additive monoid type. */ + typedef Monoid< _OP1, _ID1 > AdditiveMonoid; + + /** The multiplicative monoid type. */ + typedef Monoid< _OP2, _ID2 > MultiplicativeMonoid; + + /** The identity under addition. */ + template< typename ZeroType > + using Zero = _ID1< ZeroType >; + + /** The identity under multiplication. */ + template< typename OneType > + using One = _ID2< OneType >; + + private: + static constexpr size_t D1_bsz = grb::config::SIMD_BLOCKSIZE< D1 >::value(); + static constexpr size_t D2_bsz = grb::config::SIMD_BLOCKSIZE< D2 >::value(); + static constexpr size_t D3_bsz = grb::config::SIMD_BLOCKSIZE< D3 >::value(); + static constexpr size_t D4_bsz = grb::config::SIMD_BLOCKSIZE< D4 >::value(); + static constexpr size_t mul_input_bsz = D1_bsz < D2_bsz ? D1_bsz : D2_bsz; + + /** The additive monoid. */ + AdditiveMonoid additiveMonoid; + + /** The multiplicative monoid. */ + MultiplicativeMonoid multiplicativeMonoid; + + public: + /** Blocksize for element-wise addition. */ + static constexpr size_t blocksize_add = D3_bsz < D4_bsz ? D3_bsz : D4_bsz; + + /** Blocksize for element-wise multiplication. */ + static constexpr size_t blocksize_mul = mul_input_bsz < D3_bsz ? mul_input_bsz : D3_bsz; + + /** Blocksize for element-wise multiply-adds. */ + static constexpr size_t blocksize = blocksize_mul < blocksize_add ? blocksize_mul : blocksize_add; + + /** + * Retrieves the zero corresponding to this semiring. The zero value will be + * cast to the requested domain. + * + * @tparam D The requested domain of the zero. The arbitrary choice for the + * default return type is \a D1-- inspired by the regularly + * occurring expression \f$ a_{ij}x_j \f$ where often the left- + * hand side is zero. + * + * @returns The zero corresponding to this semiring, cast to the requested + * domain. + */ + template< typename D > + constexpr D getZero() const { + return additiveMonoid.template getIdentity< D >(); + } + + /** + * Sets the given value equal to one, corresponding to this semiring. + * The identity value will be cast to the requested domain. + * + * @tparam D The requested domain of the one. The arbitrary choice for the + * default return type is \a D1-- the reasoning being to simply + * have the same default type as getZero(). + * + * @return The one corresponding to this semiring, cast to the requested + * domain. + */ + template< typename D > + constexpr D getOne() const { + return multiplicativeMonoid.template getIdentity< D >(); + } + + /** + * Retrieves the underlying additive monoid. + * + * @return The underlying monoid. Any state is copied. + */ + AdditiveMonoid getAdditiveMonoid() const { + return additiveMonoid; + } + + /** + * Retrieves the underlying multiplicative monoid. + * + * @return The underlying monoid. Any state is copied. + */ + MultiplicativeMonoid getMultiplicativeMonoid() const { + return multiplicativeMonoid; + } + + /** + * Retrieves the underlying additive operator. + * + * @return The underlying operator. Any state is copied. + */ + AdditiveOperator getAdditiveOperator() const { + return additiveMonoid.getOperator(); + } + + /** + * Retrieves the underlying multiplicative operator. + * + * @return The underlying operator. Any state is copied. + */ + MultiplicativeOperator getMultiplicativeOperator() const { + return multiplicativeMonoid.getOperator(); + } + }; + + // overload for GraphBLAS type traits. + template< class _OP1, class _OP2, template< typename > class _ID1, template< typename > class _ID2 > + struct is_semiring< Semiring< _OP1, _OP2, _ID1, _ID2 > > { + /** This is a GraphBLAS semiring. */ + static const constexpr bool value = true; + }; + + template< class _OP1, class _OP2, template< typename > class _ID1, template< typename > class _ID2 > + struct has_immutable_nonzeroes< Semiring< _OP1, _OP2, _ID1, _ID2 > > { + static const constexpr bool value = grb::is_semiring< Semiring< _OP1, _OP2, _ID1, _ID2 > >::value && + std::is_same< _OP1, typename grb::operators::logical_or< typename _OP1::D1, typename _OP1::D2, typename _OP1::D3 > >::value; + }; + +} // namespace grb + +#endif diff --git a/include/graphblas/smf.hpp b/include/alp/smf.hpp similarity index 100% rename from include/graphblas/smf.hpp rename to include/alp/smf.hpp diff --git a/include/graphblas/structures.hpp b/include/alp/structures.hpp similarity index 100% rename from include/graphblas/structures.hpp rename to include/alp/structures.hpp diff --git a/include/alp/type_traits.hpp b/include/alp/type_traits.hpp new file mode 100644 index 000000000..3c8beaef3 --- /dev/null +++ b/include/alp/type_traits.hpp @@ -0,0 +1,153 @@ + +/* + * Copyright 2021 Huawei Technologies Co., Ltd. + * + * 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. + */ + +/* + * @author A. N. Yzelman + * @date 25th of March, 2019 + */ + +#ifndef _H_GRB_TYPE_TRAITS +#define _H_GRB_TYPE_TRAITS + +namespace grb { + + /** + * Used to inspect whether a given type is a GraphBLAS container. + * + * @tparam T The type to inspect. + * + * There are only two GraphBLAS containers: + * -# grb::Vector, and + * -# grb::Matrix. + */ + template< typename T > + struct is_container { + /** Base case: an arbitrary type is not a GraphBLAS object. */ + static const constexpr bool value = false; + }; + + /** + * Used to inspect whether a given type is a GraphBLAS semiring. + * + * @tparam T The type to inspect. + */ + template< typename T > + struct is_semiring { + /** Base case: an arbitrary type is not a semiring. */ + static const constexpr bool value = false; + }; + + /** + * Used to inspect whether a given type is a GraphBLAS monoid. + * + * @tparam T The type to inspect. + */ + template< typename T > + struct is_monoid { + /** Base case: an arbitrary type is not a monoid. */ + static const constexpr bool value = false; + }; + + /** + * Used to inspect whether a given type is a GraphBLAS operator. + * + * @tparam T The type to inspect. + */ + template< typename T > + struct is_operator { + /** Base case: an arbitrary type is not an operator. */ + static const constexpr bool value = false; + }; + + /** + * Used to inspect whether a given type is a GraphBLAS object. + * + * @tparam T The type to inspect. + * + * A GraphBLAS object is either a container, a semiring, a monoid, or an + * operator. + * + * @see #is_monoid + * @see #is_semiring + * @see #is_operator + * @see #is_container + */ + template< typename T > + struct is_object { + /** A GraphBLAS object is either a container, a semiring, a monoid, or an operator. */ + static const constexpr bool value = is_container< T >::value || + is_semiring< T >::value || + is_monoid< T >::value || + is_operator< T >::value; + }; + + /** + * Used to inspect whether a given operator is idempotent. + * + * @tparam T The operator to inspect. + * + * An example of an idempotent operator is the logical OR, + * #grb::operators::logical_or. + */ + template< typename T > + struct is_idempotent { + static_assert( is_operator< T >::value, "Template argument to grb::is_idempotent must be an operator!" ); + static const constexpr bool value = false; + }; + + /** + * Used to inspect whether a given semiring has immutable nonzeroes under + * addition. + * + * @tparam T The semiring to inspect. + * + * An example of a monoid with an immutable identity is the logical OR, + * #grb::operators::logical_or. + */ + template< typename T > + struct has_immutable_nonzeroes { + static_assert( is_semiring< T >::value, + "Template argument to grb::has_immutable_nonzeroes must be a " + "semiring!" ); + static const constexpr bool value = false; + }; + + namespace internal { + + /** + * Whether or not a given operator could translate to a no-op; + * i.e., leave its outputs unmodified. This can be relevant + * because it indicates situations where grb::apply could leave + * the output uninitialised, which may well not be as intended. + * + * An example of an operator that non-trivially may result in a + * no-op is grb::operators::left_assign_if. Such operators must + * overload this internal type trait. + */ + template< typename OP > + struct maybe_noop { + static_assert( is_operator< OP >::value, + "Argument to internal::maybe_noop must be an operator." + ); + static const constexpr bool value = false; + }; + + } // end namespace grb::internal + +} // namespace grb + +#endif diff --git a/include/alp/utils.hpp b/include/alp/utils.hpp new file mode 100644 index 000000000..c00bb771c --- /dev/null +++ b/include/alp/utils.hpp @@ -0,0 +1,303 @@ + +/* + * Copyright 2021 Huawei Technologies Co., Ltd. + * + * 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. + */ + +/* + * @author A. N. Yzelman + * @date 8th of August, 2016 + */ + +#ifndef _H_GRB_UTILITIES +#define _H_GRB_UTILITIES + +#include + +#include //fabs +#include //numeric_limits +#include + +#include + + +namespace grb { + + /** + * Some utility classes used that may be used throughout this GraphBLAS + * implementation. + * + * Utilities that rely on external libraries or system calls should \em not be + * added here-- those should reside in their own compilation units so that + * backends can decide on an individual basis whether or not to include them. + * This is especially useful when writing a backend for an architecture without + * extensive coverage of standard extensions or libraries. + */ + namespace utils { + + /** + * Checks whether two values are equal. + * + * This function simply performs a bit-wise comparison on native \em integral + * data types, or this function assumes a properly overloaded == operator. + * + * @\tparam T The numerical type. + * + * @param a One of the two values to comare against. + * @param b One of the two values to comare against. + * @returns Whether a == b. + */ + template< typename T > + static bool equals( const T & a, const T & b, typename std::enable_if< ! std::is_floating_point< T >::value >::type * = NULL ) { + // simply do standard compare + return a == b; + } + + /** + * Checks whether two floating point values are equal. + * + * This function takes into account round-off errors due to machine precision. + * + * \warning This does not take into account accumulated numerical errors + * due to previous operations on the given values. + * + * @\tparam T The numerical type. + * + * @param a One of the two values to comare against. + * @param b One of the two values to comare against. + * @param epsilons How many floating point errors may have accumulated. + * Should be chosen larger or equal to one. + * + * @returns Whether a == b. + */ + template< typename T, typename U > + static bool equals( const T &a, const T &b, const U epsilons, + typename std::enable_if< std::is_floating_point< T >::value >::type * = NULL + ) { + assert( epsilons >= 1 ); + + // if they are bit-wise equal, it's easy + if( a == b ) { +#ifdef _DEBUG + #ifndef _GRB_NO_STDIO + std::cout << "\t Bit-wise equal\n"; + #else + printf( "\t Bit-wise equal\n" ); + #endif +#endif + return true; + } + + // if not, we need to look at the absolute values + const T absA = fabs( a ); + const T absB = fabs( b ); + const T absDiff = fabs( a - b ); + const T absPlus = absA + absB; + + // find the effective epsilon + const T eps = static_cast< T >( epsilons ) * std::numeric_limits< T >::epsilon(); + + // find the minimum and maximum *normal* values. + const T min = std::numeric_limits< T >::min(); + const T max = std::numeric_limits< T >::max(); + + // if the difference is a subnormal number, it should be smaller than machine epsilon times min; + // if this is not the case, then we cannot safely conclude anything from this small a difference. + // The same is true if a or b are zero. + if( a == 0 || b == 0 || absPlus < min ) { +#ifdef _DEBUG + #ifndef _GRB_NO_STDIO + std::cout << "\t Zero or close to zero difference\n"; + #else + printf( "\t Zero or close to zero difference\n" ); + #endif +#endif + return absDiff < eps * min; + } + + // we wish to normalise absDiff by (absA + absB), + // However, absA + absB might overflow. + if( absA > absB ) { + if( absB > max - absA ) { +#ifdef _DEBUG + #ifndef _GRB_NO_STDIO + std::cout << "\t Normalising absolute difference by max (I)\n"; + #else + printf( "\t Normalising absolute difference by max (I)\n" ); + #endif +#endif + return absDiff / max < eps; + } + } else { + if( absA > max - absB ) { +#ifdef _DEBUG + #ifndef _GRB_NO_STDIO + std::cout << "\t Normalising absolute difference by max (II)\n"; + #else + printf( "\t Normalising absolute difference by max (II)\n" ); + #endif +#endif + return absDiff / max < eps; + } + } + // use of relative error should be safe +#ifdef _DEBUG + #ifndef _GRB_NO_STDIO + std::cout << "\t Using relative error\n"; + #else + printf( "\t Using relative error\n" ); + #endif +#endif + return absDiff / absPlus < eps; + } + + /** + * A templated max function that is different from std::max in that the + * return value is a constexpr. (This was fixed in C++14.) + */ + template< typename T > + constexpr const T & static_max( const T &a, const T &b ) { + return a > b ? a : b; + } + + /** + * A templated min function that is different from std::min in that the + * return value is a constexpr. (This was fixed in C++14.) + */ + template< typename T > + constexpr const T & static_min( const T & a, const T & b ) { + return a < b ? a : b; + } + + /** + * A sizeof that is safe w.r.t. void types. + * + */ + template< typename T > + class SizeOf { + public: + /** + * If \a T is void, this value equals 0 and + * equal to sizeof(T) otherwise. + */ + static constexpr const size_t value = sizeof( T ); + }; + + // void-specialisation of the above class + template<> + class SizeOf< void > { + public: + static constexpr const size_t value = 0; + }; + + /** + * Given a (combination) of descriptors, evaluates a mask at a given + * position. + * + * @tparam descriptor The given descriptor. + * @tparam T The type of an element of the mask. + * + * @param[in] assigned Whether there was an element in the mask. + * @param[in] val Pointer to memory area where mask elements reside. + * @param[in] offset Offset in \a val to the mask value to be interpreted. + * + * The memory area pointed to by \a val shall not be dereferenced if + * \a assigned is false. + * + * @return If the descriptor includes grb::descriptors::structoral, + * returns \a assigned. If additionally grb::descriptors::invert_mask + * was defined, instead returns the negation of \a assigned. + * @return If the descriptor includes grb::descriptors::structural_complement, + * returns the negation of \a assigned. If additionally + * grb::descriptors::invert_mask was defined, instead returns + * \a assigned. + * @return If the descriptor does not include grb::descriptors::structural + * nor grb::descriptors::structural_complement and if \a assigned + * is false, then the entry is ignored and uninterpreted, thus + * returning \a false. + * @return If the descriptor includes grb::descriptors::invert_mask, + * returns the negation of the dereferenced value of \a val + * which is first cast to a \a bool. + * @return Otherwise, returns the dereferenced value of \a val, + * cast to a \a bool. + * + * If \a descriptor contains both grb::descriptors::structural and + * grb::descriptors::structural_complement, the code shall not + * compile. + */ + template< Descriptor descriptor, typename T > + static bool interpretMask( const bool & assigned, const T * const val, const size_t offset ) { + // set default mask to false + bool ret = false; + // if we request a structural mask, decide only on passed assigned variable + if( descriptor & descriptors::structural ) { + ret = assigned; + } else { + // if based on value, if there is a value, cast it to bool + if( assigned ) { + ret = static_cast< bool >( val[ offset ] ); + } + // otherwise there is no value and false is assumed + } + // check whether we should return the inverted value + if( descriptor & descriptors::invert_mask ) { + return ! ret; + } else { + return ret; + } + } + + /** Specialisation for void-valued masks */ + template< Descriptor descriptor > + static bool interpretMask( const bool & assigned, const void * const, const size_t ) { + // set default mask to false + bool ret = assigned; + // check whether we should return the inverted value + if( descriptor & descriptors::invert_mask ) { + return ! ret; + } else { + return ret; + } + } + + /** + * @brief Simple range [ \a start, \a end) with optional \a stride. + * + */ + struct range { + size_t start, end, stride; + + range(): start( 0 ), end( std::numeric_limits< size_t >::max() ), stride( 1 ) {} + + range(size_t start, size_t end, size_t stride=1): start( start ), end( end ), stride( stride ) {} + + inline size_t count() const { + return (end - start)/stride; + } + + inline bool is_full() const { + return ( count() == std::numeric_limits< size_t >::max() ); + } + + inline bool is_empty() const { + return ( count() == 0 ); + } + + }; + + } // namespace utils + +} // namespace grb + +#endif diff --git a/include/alp/utils/SynchronizedNonzeroIterator.hpp b/include/alp/utils/SynchronizedNonzeroIterator.hpp new file mode 100644 index 000000000..f48f9a909 --- /dev/null +++ b/include/alp/utils/SynchronizedNonzeroIterator.hpp @@ -0,0 +1,356 @@ + +/* + * Copyright 2021 Huawei Technologies Co., Ltd. + * + * 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. + */ + +/* + * @author A. N. Yzelman + * @date 2nd of August, 2017 + */ + +#ifndef _H_SYNCHRONIZEDNONZEROITERATOR +#define _H_SYNCHRONIZEDNONZEROITERATOR + +#include //std::pair + +#include + +#ifdef _DEBUG +#ifndef _GRB_NO_STDIO +#include +#endif +#endif + +namespace grb { + namespace utils { + + template< typename S1, typename S2, typename V, typename fwd_it1, typename fwd_it2, typename fwd_it3 > + class SynchronizedNonzeroIterator { + + template< typename X1, typename X2, typename X3, typename X4, typename X5, typename X6 > + friend std::ostream & operator<<( std::ostream &, const SynchronizedNonzeroIterator< X1, X2, X3, X4, X5, X6 > & ); + + private: + // iterators to synchronise: + fwd_it1 row_it, row_end; + fwd_it2 col_it, col_end; + fwd_it3 val_it, val_end; + + /** The currently active nonzero. */ + mutable std::pair< std::pair< S1, S2 >, V > nonzero; + + /** Whether #nonzero is up to date. */ + mutable bool updated; + + /** Updates the #nonzero fields using the current iterator values. */ + inline void update() const { + assert( row_it != row_end ); + assert( col_it != col_end ); + assert( val_it != val_end ); + nonzero.first.first = *row_it; + nonzero.first.second = *col_it; + nonzero.second = *val_it; + updated = true; + } + + public: + // STL typedefs: + typedef std::ptrdiff_t difference_type; + typedef std::pair< std::pair< S1, S2 >, V > value_type; + typedef value_type & reference; + typedef value_type * pointer; + typedef std::forward_iterator_tag iterator_category; + + // GraphBLAS typedefs: + typedef S1 row_coordinate_type; + typedef S2 column_coordinate_type; + typedef V nonzero_value_type; + + /** Base constructor. Takes three sub-iterators as arguments. */ + SynchronizedNonzeroIterator( fwd_it1 it1, fwd_it2 it2, fwd_it3 it3, fwd_it1 it1_end, fwd_it2 it2_end, fwd_it3 it3_end ) : + row_it( it1 ), row_end( it1_end ), col_it( it2 ), col_end( it2_end ), val_it( it3 ), val_end( it3_end ), updated( false ) { + if( it1 != it1_end && it2 != it2_end && it3 != it3_end ) { + update(); + updated = false; + } + } + + /** Copy constructor. */ + SynchronizedNonzeroIterator( const SynchronizedNonzeroIterator< S1, S2, V, fwd_it1, fwd_it2, fwd_it3 > & other ) : + row_it( other.row_it ), row_end( other.row_end ), col_it( other.col_it ), col_end( other.col_end ), val_it( other.val_it ), val_end( other.val_end ), updated( other.updated ) { + if( updated && row_it != row_end && col_it != col_end && val_it != val_end ) { + update(); + } + } + + /** Assignment operator. */ + SynchronizedNonzeroIterator< S1, S2, V, fwd_it1, fwd_it2, fwd_it3 > & operator=( const SynchronizedNonzeroIterator< S1, S2, V, fwd_it1, fwd_it2, fwd_it3 > & other ) { + row_it = other.row_it; + row_end = other.row_end; + col_it = other.col_it; + col_end = other.col_end; + val_it = other.val_it; + val_end = other.val_end; + updated = other.updated; + if( updated && row_it != row_end && col_it != col_end && val_it != val_end ) { + update(); + } + return *this; + } + + /** Equality check. */ + bool operator==( const SynchronizedNonzeroIterator< S1, S2, V, fwd_it1, fwd_it2, fwd_it3 > & other ) const { + return row_it == other.row_it && col_it == other.col_it && val_it == other.val_it; + } + + /** Inequality check. */ + bool operator!=( const SynchronizedNonzeroIterator< S1, S2, V, fwd_it1, fwd_it2, fwd_it3 > & other ) const { + return row_it != other.row_it || col_it != other.col_it || val_it != other.val_it; + }; + + /** Increment operator. */ + SynchronizedNonzeroIterator< S1, S2, V, fwd_it1, fwd_it2, fwd_it3 > & operator++() { + (void)++row_it; + (void)++col_it; + (void)++val_it; + updated = false; + return *this; + } + + /** Direct derefence operator. */ + reference operator*() const { + if( ! updated ) { + assert( row_it != row_end && col_it != col_end && val_it != val_end ); + update(); + } + return nonzero; + } + + /** Pointer update. */ + const std::pair< std::pair< S1, S2 >, V > * operator->() const { + if( ! updated ) { + assert( row_it != row_end && col_it != col_end && val_it != val_end ); + update(); + } + return &nonzero; + } + + /** Returns the row coordinate. */ + const S1 & i() const { + if( ! updated ) { + assert( row_it != row_end && col_it != col_end && val_it != val_end ); + update(); + } + return nonzero.first.first; + } + + /** Returns the column coordinate. */ + const S2 & j() const { + if( ! updated ) { + assert( row_it != row_end && col_it != col_end && val_it != val_end ); + update(); + } + return nonzero.first.second; + } + + /** Returns the nonzero coordinate. */ + const V & v() const { + if( ! updated ) { + assert( row_it != row_end && col_it != col_end && val_it != val_end ); + update(); + } + return nonzero.second; + } + }; + + template< typename S1, typename S2, typename fwd_it1, typename fwd_it2 > + class SynchronizedNonzeroIterator< S1, S2, void, fwd_it1, fwd_it2, void > { + + template< typename X1, typename X2, typename X3, typename X4 > + friend std::ostream & operator<<( std::ostream &, const SynchronizedNonzeroIterator< X1, X2, void, X3, X4, void > & ); + + private: + // iterators to synchronise: + fwd_it1 row_it, row_end; + fwd_it2 col_it, col_end; + + /** The currently active nonzero. */ + mutable std::pair< S1, S2 > nonzero; + + /** Whether #nonzero is up to date. */ + mutable bool updated; + + /** Updates the #nonzero fields using the current iterator values. */ + inline void update() const { + assert( row_it != row_end ); + assert( col_it != col_end ); + nonzero.first = *row_it; + nonzero.second = *col_it; + updated = true; + } + + public: + // STL typedefs: + typedef std::ptrdiff_t difference_type; + typedef std::pair< S1, S2 > value_type; + typedef value_type & reference; + typedef value_type * pointer; + typedef std::forward_iterator_tag iterator_category; + + // GraphBLAS typedefs: + typedef S1 row_coordinate_type; + typedef S2 column_coordinate_type; + typedef void nonzero_value_type; + + /** Base constructor. Takes two sub-iterators as arguments. */ + SynchronizedNonzeroIterator( fwd_it1 it1, fwd_it2 it2, fwd_it1 it1_end, fwd_it2 it2_end ) : row_it( it1 ), row_end( it1_end ), col_it( it2 ), col_end( it2_end ), updated( false ) { + if( it1 != it1_end && it2 != it2_end ) { + update(); + } + } + + /** Copy constructor. */ + SynchronizedNonzeroIterator( const SynchronizedNonzeroIterator< S1, S2, void, fwd_it1, fwd_it2, void > & other ) : + row_it( other.row_it ), row_end( other.row_end ), col_it( other.col_it ), col_end( other.col_end ), updated( other.updated ) { + if( updated && row_it != row_end && col_it != col_end ) { + update(); + } + } + + /** Assignment operator. */ + SynchronizedNonzeroIterator< S1, S2, void, fwd_it1, fwd_it2, void > & operator=( const SynchronizedNonzeroIterator< S1, S2, void, fwd_it1, fwd_it2, void > & other ) { + row_it = other.row_it; + row_end = other.row_end; + col_it = other.col_it; + col_end = other.col_end; + updated = other.updated; + if( updated && row_it != row_end && col_it != col_end ) { + update(); + } + return *this; + } + + /** Equality check. */ + bool operator==( const SynchronizedNonzeroIterator< S1, S2, void, fwd_it1, fwd_it2, void > & other ) const { + return row_it == other.row_it && col_it == other.col_it; + } + + /** Inequality check. */ + bool operator!=( const SynchronizedNonzeroIterator< S1, S2, void, fwd_it1, fwd_it2, void > & other ) const { + return row_it != other.row_it || col_it != other.col_it; + }; + + /** Increment operator. */ + SynchronizedNonzeroIterator< S1, S2, void, fwd_it1, fwd_it2, void > & operator++() { + (void)++row_it; + (void)++col_it; + updated = false; + return *this; + } + + /** Direct derefence operator. */ + reference operator*() const { + if( ! updated ) { + assert( row_it != row_end && col_it != col_end ); + update(); + } + return nonzero; + } + + /** Pointer update. */ + const std::pair< S1, S2 > * operator->() const { + if( ! updated ) { + assert( row_it != row_end && col_it != col_end ); + update(); + } + return &nonzero; + } + + /** Returns the row coordinate. */ + const S1 & i() const { + if( ! updated ) { + assert( row_it != row_end && col_it != col_end ); + update(); + } + return nonzero.first; + } + + /** Returns the column coordinate. */ + const S2 & j() const { + if( ! updated ) { + assert( row_it != row_end && col_it != col_end ); + update(); + } + return nonzero.second; + } + }; + + template< typename S1, typename S2, typename V, typename fwd_it1, typename fwd_it2, typename fwd_it3 > + std::ostream & operator<<( std::ostream & os, const SynchronizedNonzeroIterator< S1, S2, V, fwd_it1, fwd_it2, fwd_it3 > & it ) { + if( ! it.updated ) { + it.update(); + } + os << it.nonzero.first.first << ", " << it.nonzero.first.second << ", " << it.nonzero.second; + return os; + } + + template< typename S1, typename S2, typename fwd_it1, typename fwd_it2 > + std::ostream & operator<<( std::ostream & os, const SynchronizedNonzeroIterator< S1, S2, void, fwd_it1, fwd_it2, void > & it ) { + if( ! it.updated ) { + it.update(); + } + os << it.nonzero.first << ", " << it.nonzero.second; + return os; + } + + template< typename S1, typename S2 > + SynchronizedNonzeroIterator< S1, S2, void, const S1 *, const S2 *, void > makeSynchronized( const S1 * const it1, const S2 * const it2, const S1 * const it1_end, const S2 * const it2_end ) { +#ifdef _DEBUG +#ifndef _GRB_NO_STDIO + std::cout << "SynchronizedNonzeroIterator::makeSynchronized " + "received iterators " + << it1 << " (start) and " << it2 << " (end)\n"; +#else + printf( "SynchronizedNonzeroIterator::makeSynchronized received " + "iterators %p (start) and %p (end)\n", + it1, it2 ); +#endif +#endif + return SynchronizedNonzeroIterator< S1, S2, void, const S1 *, const S2 *, void >( it1, it2, it1_end, it2_end ); + } + + template< typename fwd_it1, typename fwd_it2 > + SynchronizedNonzeroIterator< typename fwd_it1::value_type, typename fwd_it2::value_type, void, fwd_it1, fwd_it2, void > + makeSynchronized( const fwd_it1 it1, const fwd_it2 it2, const fwd_it1 it1_end, const fwd_it2 it2_end ) { + return SynchronizedNonzeroIterator< typename fwd_it1::value_type, typename fwd_it2::value_type, void, fwd_it1, fwd_it2, void >( it1, it2, it1_end, it2_end ); + } + + template< typename S1, typename S2, typename V > + SynchronizedNonzeroIterator< S1, S2, V, const S1 *, const S2 *, const V * > + makeSynchronized( const S1 * const it1, const S2 * const it2, const V * const it3, const S1 * const it1_end, const S2 * const it2_end, const V * const it3_end ) { + return SynchronizedNonzeroIterator< S1, S2, V, const S1 *, const S2 *, const V * >( it1, it2, it3, it1_end, it2_end, it3_end ); + } + + template< typename fwd_it1, typename fwd_it2, typename fwd_it3 > + SynchronizedNonzeroIterator< typename fwd_it1::value_type, typename fwd_it2::value_type, typename fwd_it3::value_type, fwd_it1, fwd_it2, fwd_it3 > + makeSynchronized( const fwd_it1 it1, const fwd_it2 it2, const fwd_it3 it3, const fwd_it1 it1_end, const fwd_it2 it2_end, const fwd_it3 it3_end ) { + return SynchronizedNonzeroIterator< typename fwd_it1::value_type, typename fwd_it2::value_type, typename fwd_it3::value_type, fwd_it1, fwd_it2, fwd_it3 >( + it1, it2, it3, it1_end, it2_end, it3_end ); + } + + } // namespace utils +} // namespace grb + +#endif // end ``_H_SYNCHRONIZEDNONZEROITERATOR'' diff --git a/include/alp/utils/autodeleter.hpp b/include/alp/utils/autodeleter.hpp new file mode 100644 index 000000000..3386e5ff6 --- /dev/null +++ b/include/alp/utils/autodeleter.hpp @@ -0,0 +1,192 @@ + +/* + * Copyright 2021 Huawei Technologies Co., Ltd. + * + * 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. + */ + +/** + * @file + * + * Collection of helper functions to deal with deleting shared pointers. + * + * @author A. N. Yzelman + * @date 22nd of April, 2017 + */ + +#ifndef _H_GRB_UTILS_AUTO_DELETER +#define _H_GRB_UTILS_AUTO_DELETER + +#ifndef _GRB_NO_LIBNUMA +#include +#endif + +#include + +#include "graphblas/config.hpp" + +namespace grb { + + namespace utils { + + namespace internal { + + template< enum Backend implementation > + class DeleterFunctions { + private: + /** Prevent instantiation. */ + DeleterFunctions() {} + + public: + /** \todo documentation */ + template< typename T > + static void safe_free( T * const pointer ) { + if( pointer != NULL ) { + free( pointer ); + } + } + +#ifndef _GRB_NO_LIBNUMA + /** \todo documentation */ + template< typename T > + class safe_numa_free { + private: + size_t size; + + public: + safe_numa_free( const size_t size_in ) : size( size_in ) {} + void operator()( T * const pointer ) { + numa_free( pointer, size ); + } + }; +#endif + }; + + } // namespace internal + + } // namespace utils + +} // namespace grb + +// now define user API: +namespace grb { + + namespace utils { + + /** + * This function is compatible with \a posix_memalign and the standard + * practice to allow \a NULL pointers for empty arrays. + * + * \todo expand documentation + * + * \warning This function is \em not thread safe! + * + * \note The difference between this class and the std::shared_ptr< T > is + * the deleter wrapper. This class also provides no way to reference + * the underlying pointer, nor is functionality provided to access + * the underlying type instance. This class thus only provides a + * means to easily delete memory areas that are shared between owners + * (which is in fact quite different from the philosophy of a + * \a shared_ptr which were introduced to `forget' about deletes.) + */ + template< typename T, enum Backend implementation = config::default_backend > + class AutoDeleter { + + private: + /** Where the implementation of the free function(s) reside. */ + typedef typename internal::DeleterFunctions< implementation > functions; + + /** Functionality is provided by shared pointer. */ + std::shared_ptr< T > _shPtr; + + public: + /** + * Constructs a new AutoDeleter from a pointer. When this instance and all + * instances copied from this one are destroyed, the pointer will be freed + * if and only if it is not equal to \a NULL. + * + * The pointer is assumed to be allocated using \a posix_memalign, which is + * compitable with the C-standard \a free. Thus pointers that cannot be + * free'd in this manner should never be passed to this AutoDeleter + * constructor. + * + * @throws std::bad_alloc If the system cannot allocate enough memory. + */ + AutoDeleter( T * const pointer = NULL, const size_t size = 0 ) { +#ifdef _GRB_NO_LIBNUMA + (void)size; + const auto free_p = &( functions::template safe_free< T > ); + _shPtr = std::shared_ptr< T >( pointer, free_p ); +#else + if( size > 0 ) { + typedef typename functions::template safe_numa_free< T > FreeFunctor; + const FreeFunctor free_f( size ); + _shPtr = std::shared_ptr< T >( pointer, free_f ); + } else { + const auto free_p = &( functions::template safe_free< T > ); + _shPtr = std::shared_ptr< T >( pointer, free_p ); + } +#endif + }; + + /** + * Copies an \a other AutoDeleter. The underlying pointer will only be freed + * if at least this new AutoDeleter and the \a other AutoDeleter are + * destroyed. (The preceding says `at least' because other copies may have + * been made previously.) + * + * @throws std::bad_alloc If the system cannot allocate enough memory. + */ + AutoDeleter( const AutoDeleter< T > &other ) : _shPtr( other._shPtr ) {} + + /** + * Creates an AutoDeleter from a temporary instance by stealing its + * resources. + */ + AutoDeleter( AutoDeleter< T > &&other ) noexcept { + _shPtr = std::move( other._shPtr ); + } + + /** Signals auto-deletion no longer is necessary. */ + void clear() noexcept { + _shPtr.reset(); + } + + /** + * Relies on std::move. Equals-operator only works on temporary RHS. + */ + AutoDeleter< T > & operator=( AutoDeleter< T > &&other ) { + _shPtr = std::move( other._shPtr ); + return *this; + } + + /** + * Relies on copying the underlying shared pointer. + */ + AutoDeleter< T > & operator=( const AutoDeleter< T > &other ) { + _shPtr = other._shPtr; + return *this; + } + }; + + } // namespace utils + +} // namespace grb + +// include specialised DeleterFunctions +#ifdef _GRB_WITH_BANSHEE + #include "graphblas/banshee/deleters.hpp" +#endif + +#endif + diff --git a/include/alp/utils/suppressions.h b/include/alp/utils/suppressions.h new file mode 100644 index 000000000..653679530 --- /dev/null +++ b/include/alp/utils/suppressions.h @@ -0,0 +1,50 @@ + +/* + * Copyright 2021 Huawei Technologies Co., Ltd. + * + * 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. + */ + +/** + * @file + * + * Supresses warnings that may be unnecessarily emitted by various compilers. + * + * Use of the macros defined in this file should always be accompanied with an + * explanation why it is safe to ignore the compiler warnings that the macro + * suppresses. + * + * @author A. N. Yzelman + * @date 19th of January 2022 + */ + +#ifndef _H_GRB_UTILS_SUPRESSIONS +#define _H_GRB_UTILS_SUPRESSIONS + +#if defined(__GNUC__) && __GNUC__ >= 4 + // here are the macros for GCC + #define GRB_UTIL_IGNORE_MAYBE_UNINITIALIZED \ + _Pragma( "GCC diagnostic push" ) ;\ + _Pragma( "GCC diagnostic ignored \"-Wmaybe-uninitialized\"" );\ + + #define GRB_UTIL_RESTORE_WARNINGS \ + _Pragma( "GCC diagnostic pop" );\ + +#else + // here are empty default macros + #define GRB_UTIL_IGNORE_MAYBE_UNINITIALIZED + #define GRB_UTIL_RESTORE_WARNINGS +#endif + +#endif // end ``_H_GRB_REFERENCE_BLAS2'' + diff --git a/include/alp/vector.hpp b/include/alp/vector.hpp new file mode 100644 index 000000000..cb1c734d4 --- /dev/null +++ b/include/alp/vector.hpp @@ -0,0 +1,60 @@ + +/* + * Copyright 2021 Huawei Technologies Co., Ltd. + * + * 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. + */ + +/* + * @author A. N. Yzelman + * @date 10th of August, 2016 + */ + +#ifndef _H_GRB_VECTOR +#define _H_GRB_VECTOR + +#include "base/config.hpp" +#include "base/vector.hpp" +#include "coordinates.hpp" + +// now include all specialisations contained in the backend directories: +#ifdef _GRB_WITH_REFERENCE + #include +#endif +#ifdef _GRB_WITH_DENSEREF + #include +#endif +#ifdef _GRB_WITH_LPF + #include +#endif +#ifdef _GRB_WITH_BANSHEE + #include +#endif + +// specify default only if requested during compilation +#ifdef _GRB_BACKEND +namespace grb { + template< typename D, Backend implementation = config::default_backend, typename C = internal::DefaultCoordinates > + class Vector; + + /* + * The default value of \a density could also be made conditional (Dense or Sparse) depending on \a config::default_backend + */ + template< typename T, typename Structure = structures::General, enum Density density = Density::Dense, typename View = view::Original< void >, enum Backend backend = config::default_backend > + class VectorView; + +} +#endif + +#endif + diff --git a/include/graphblas/views.hpp b/include/alp/views.hpp similarity index 100% rename from include/graphblas/views.hpp rename to include/alp/views.hpp diff --git a/include/graphblas/CMakeLists.txt b/include/graphblas/CMakeLists.txt new file mode 100644 index 000000000..ffbda04de --- /dev/null +++ b/include/graphblas/CMakeLists.txt @@ -0,0 +1,155 @@ +# +# Copyright 2021 Huawei Technologies Co., Ltd. +# +# 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. +# + +# +# Definition of GraphBLAS include targets: all targets here defined +# are interface targets for headers and basic definitions required to build +# GraphBLAS backends and tests. Importing targets have all basic dependencies +# and definitions to compile against each backend, but MUST explicitly +# set a default backend (if they want to do so). +# +assert_defined_variables( REFERENCE_INCLUDE_DEFS REFERENCE_OMP_INCLUDE_DEFS LPF_INCLUDE_DEFS + WITH_REFERENCE_BACKEND_HEADERS WITH_OMP_BACKEND_HEADERS WITH_BSP1D_BACKEND WITH_HYBRID_BACKEND +) +assert_valid_variables( INCLUDE_INSTALL_DIR ) + +# to avoid flaky acrobatics with regex or glob expressions, copy main files directly +install( FILES "../graphblas.hpp" DESTINATION "${INCLUDE_INSTALL_DIR}" ) +set( root_files + "../graphblas.hpp" "backends.hpp" "benchmark.hpp" + "blas0.hpp" "blas1.hpp" "blas2.hpp" + "blas3.hpp" "collectives.hpp" "config.hpp" + "coordinates.hpp" "descriptors.hpp" "distribution.hpp" + "exec.hpp" "identities.hpp" "init.hpp" + "internalops.hpp" "io.hpp" "iomode.hpp" + "matrix.hpp" "monoid.hpp" "ops.hpp" + "phase.hpp" "pinnedvector.hpp" "properties.hpp" + "rc.hpp" "semiring.hpp" "spmd.hpp" + "tags.hpp" "type_traits.hpp" "utils.hpp" + "vector.hpp" +) +set( GRB_INCLUDE_INSTALL_DIR "${INCLUDE_INSTALL_DIR}/graphblas") +install( FILES ${root_files} DESTINATION "${GRB_INCLUDE_INSTALL_DIR}" ) + +# copy base headers and all its subdirectories (if any) +# note: leave the slash "/" at the end of the DIRECTORY path, +# othwerise CMake will create a "graphblas/base" directory inside DESTINATION !!! +# https://cmake.org/cmake/help/latest/command/install.html#installing-directories +install( DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/base/" + DESTINATION "${GRB_INCLUDE_INSTALL_DIR}/base" + FILES_MATCHING REGEX "${HEADERS_REGEX}" +) + +# copy utils headers +install( DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/utils/" + DESTINATION "${GRB_INCLUDE_INSTALL_DIR}/utils" + FILES_MATCHING REGEX "${HEADERS_REGEX}" +) + +if( WITH_REFERENCE_BACKEND_HEADERS ) + add_library( backend_reference_headers INTERFACE ) + target_link_libraries( backend_reference_headers INTERFACE backend_headers_nodefs ) + target_compile_definitions( backend_reference_headers INTERFACE "${REFERENCE_INCLUDE_DEFS}" ) + # currently, the OMP header files and definitions are required also for the reference backend + # TODO: "dis-entangle" code from OMP backend dependence and remove this + target_compile_definitions( backend_reference_headers INTERFACE "${REFERENCE_OMP_INCLUDE_DEFS}" ) + target_link_libraries( backend_reference_headers INTERFACE OpenMP::OpenMP_CXX ) + + install( TARGETS backend_reference_headers EXPORT GraphBLASTargets ) +endif() + +if( WITH_ALP_REFERENCE_BACKEND ) + add_library( backend_alp_reference_headers INTERFACE ) + target_link_libraries( backend_alp_reference_headers INTERFACE backend_headers_nodefs ) + target_compile_definitions( backend_alp_reference_headers INTERFACE "${ALP_REFERENCE_INCLUDE_DEFS}" ) + install( TARGETS backend_alp_reference_headers EXPORT GraphBLASTargets ) + install( DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/alp/reference" + DESTINATION "${GRB_INCLUDE_INSTALL_DIR}/alp_reference" + FILES_MATCHING REGEX "${HEADERS_REGEX}" + ) +endif() + +if( WITH_REFERENCE_BACKEND OR WITH_OMP_BACKEND ) + install( DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/reference/" + DESTINATION "${GRB_INCLUDE_INSTALL_DIR}/reference" + FILES_MATCHING REGEX "${HEADERS_REGEX}" + ) +endif() + +if( WITH_OMP_BACKEND_HEADERS ) + add_library( backend_reference_omp_headers INTERFACE ) + target_link_libraries( backend_reference_omp_headers INTERFACE backend_headers_nodefs ) + target_link_libraries( backend_reference_omp_headers INTERFACE OpenMP::OpenMP_CXX ) + target_compile_definitions( backend_reference_omp_headers INTERFACE + "${REFERENCE_INCLUDE_DEFS}" "${REFERENCE_OMP_INCLUDE_DEFS}" + ) + + install( DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/omp/" + DESTINATION "${GRB_INCLUDE_INSTALL_DIR}/omp" + FILES_MATCHING REGEX "${HEADERS_REGEX}" + ) + install( TARGETS backend_reference_omp_headers EXPORT GraphBLASTargets ) + +endif() + + +if( WITH_BSP1D_BACKEND OR WITH_HYBRID_BACKEND ) + # copy headers, which are common to both distributed backends + install( DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/bsp/" + DESTINATION "${GRB_INCLUDE_INSTALL_DIR}/bsp" + FILES_MATCHING REGEX "${HEADERS_REGEX}" + ) + install( DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/bsp1d/" + DESTINATION "${GRB_INCLUDE_INSTALL_DIR}/bsp1d" + FILES_MATCHING REGEX "${HEADERS_REGEX}" + ) +endif() + +if( WITH_BSP1D_BACKEND ) + add_library( backend_bsp1d_headers INTERFACE ) + target_link_libraries( backend_bsp1d_headers INTERFACE Numa::Numa backend_reference_headers ) + target_compile_definitions( backend_bsp1d_headers INTERFACE "${LPF_INCLUDE_DEFS}" ) + + install( TARGETS backend_bsp1d_headers EXPORT GraphBLASTargets ) +endif() + +if( WITH_HYBRID_BACKEND ) + add_library( backend_hybrid_headers INTERFACE ) + # the hybrid backend needs OMP by design + target_link_libraries( backend_hybrid_headers INTERFACE Numa::Numa backend_reference_omp_headers ) + target_compile_definitions( backend_hybrid_headers INTERFACE "${LPF_INCLUDE_DEFS}" ) + + install( TARGETS backend_hybrid_headers EXPORT GraphBLASTargets ) +endif() + +# this target lists the algorithms implemented on top of the generic functionalities, +# hence it depends only on backend_headers_nodefs +add_library( algorithms INTERFACE ) +target_link_libraries( algorithms INTERFACE backend_headers_nodefs ) + +target_include_directories( + algorithms INTERFACE + + $ + $ +) + +install( DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/algorithms/" + DESTINATION "${GRB_INCLUDE_INSTALL_DIR}/algorithms" + FILES_MATCHING REGEX "${HEADERS_REGEX}" +) + +install( TARGETS algorithms EXPORT GraphBLASTargets ) diff --git a/include/graphblas/backends.hpp b/include/graphblas/backends.hpp index 3acee4fd5..72f1bcec1 100644 --- a/include/graphblas/backends.hpp +++ b/include/graphblas/backends.hpp @@ -151,13 +151,7 @@ namespace grb { * * Collaboration with ETH Zurich (ongoing). */ - banshee_ssr, - - /** - * The ALP/Dense backend. This is no longer a proper GraphBLAS implementation, as it assumes - * all containers are dense. No ``missing'' entries in containers are allowed. - */ - reference_dense + banshee_ssr }; diff --git a/include/graphblas/base/matrix.hpp b/include/graphblas/base/matrix.hpp index 597ccd468..aaf983b1d 100644 --- a/include/graphblas/base/matrix.hpp +++ b/include/graphblas/base/matrix.hpp @@ -33,11 +33,7 @@ #include #include #include -#include -#include #include -#include -#include namespace grb { @@ -437,72 +433,6 @@ RC clear( Matrix< InputType, backend > & A ) noexcept { return UNSUPPORTED; } -template< typename T, typename Structure, enum Density density, typename View, enum Backend backend > -class StructuredMatrix { - - /** - * The two following members define the \em logical layout of a structured matrix: - * Its structure and access relations. This is enabled only if the structured matrix - * does not define a View on another matrix. - */ - using structure = Structure; - /** - * A pair of pointers to index mapping functions (see imf.hpp) that express the - * logical access to the structured matrix. - */ - std::shared_ptr imf_l, imf_r; - - /** - * When a structured matrix instanciate a \em container it defines a new \em physical - * (concrete?) layout. This is characterized by an ALP container (aka a \a Matrix) and a - * storage scheme that defines a unique interpretation of its content. - * The combination of the logical and physical layout of a structured matrix enables to - * identify a precise mapping between an element in the structured matrix and a position - * wihtin one or more 1/2D-arrays that store it. - */ - Matrix< T, reference_dense > * _container; - - /** - * A container's storage scheme. \a storage_scheme is not exposed to the user as an option - * but can defined by ALP at different points in the execution depending on the \a backend choice. - * For example, if the container is associated to an I/O matrix, with a reference backend - * it might be set to reflect the storage scheme of the user data as specified at buildMatrix. - * If \a backend is set to \a mlir then the scheme could be fixed by the JIT compiler to effectively - * support its optimization strategy. - * At construction time and until the moment the scheme decision is made it may be set to - * an appropriate default choice, e.g. if \a density is \a Density::Dense then - * \a Density::Dense::full could be used. - * \internal \todo Revisit this. The change of storage scheme type to enum (dense/sparse) and - * implementing storage mapping functions requires a change of this spec. - */ - // Storage storage_scheme; - - /** - * When a structured matrix defines a View over another matrix, it contains a pointer - * to the latter. Its type can be identified via the View parameter. - */ - using target_type = typename std::enable_if >::value, typename View::applied_to>::type; - target_type * ref; - - public : - - StructuredMatrix( const size_t m, const size_t n ); - - StructuredMatrix( const StructuredMatrix< T, Structure, density, View, backend > & other ); - - StructuredMatrix( StructuredMatrix< T, Structure, density, View, backend > && other ); - - ~StructuredMatrix(); - -}; // class StructuredMatrix - -/** - * Check if type \a T is a StructuredMatrix. - */ -template< typename T > -struct is_structured_matrix : std::false_type {}; -template< typename T, typename Structure, enum Density density, typename View, enum Backend backend > -struct is_structured_matrix< StructuredMatrix< T, Structure, density, View, backend > > : std::true_type {}; } // end namespace ``grb'' diff --git a/include/graphblas/base/vector.hpp b/include/graphblas/base/vector.hpp index 0c6504831..68a4a60ba 100644 --- a/include/graphblas/base/vector.hpp +++ b/include/graphblas/base/vector.hpp @@ -32,7 +32,6 @@ #include #include #include -#include namespace grb { @@ -901,9 +900,6 @@ namespace grb { } }; - template< typename T, typename Structure, enum Density density, typename View, enum Backend backend > - class VectorView { }; - } #endif // _H_GRB_VECTOR_BASE diff --git a/include/graphblas/benchmark.hpp b/include/graphblas/benchmark.hpp index 536ecc360..f28970ce2 100644 --- a/include/graphblas/benchmark.hpp +++ b/include/graphblas/benchmark.hpp @@ -30,9 +30,6 @@ #ifdef _GRB_WITH_REFERENCE #include "graphblas/reference/benchmark.hpp" #endif -// #ifdef _GRB_WITH_DENSE -// #include "graphblas/denseref/benchmark.hpp" -// #endif #ifdef _GRB_WITH_BANSHEE #include "graphblas/banshee/benchmark.hpp" #endif diff --git a/include/graphblas/blas1.hpp b/include/graphblas/blas1.hpp index 9f035e776..ef0eef507 100644 --- a/include/graphblas/blas1.hpp +++ b/include/graphblas/blas1.hpp @@ -28,9 +28,6 @@ #ifdef _GRB_WITH_REFERENCE #include #endif -#ifdef _GRB_WITH_DENSEREF - #include -#endif #ifdef _GRB_WITH_BANSHEE #include #endif diff --git a/include/graphblas/blas2.hpp b/include/graphblas/blas2.hpp index 7c4e44398..e44d311a1 100644 --- a/include/graphblas/blas2.hpp +++ b/include/graphblas/blas2.hpp @@ -33,9 +33,6 @@ #ifdef _GRB_WITH_REFERENCE #include #endif -#ifdef _GRB_WITH_DENSE - #include -#endif #ifdef _GRB_WITH_BANSHEE #include #endif diff --git a/include/graphblas/blas3.hpp b/include/graphblas/blas3.hpp index a6d3eae8c..d96649bc8 100644 --- a/include/graphblas/blas3.hpp +++ b/include/graphblas/blas3.hpp @@ -30,9 +30,6 @@ #ifdef _GRB_WITH_REFERENCE #include #endif -#ifdef _GRB_WITH_DENSEREF - #include -#endif #ifdef _GRB_WITH_LPF #include #endif diff --git a/include/graphblas/collectives.hpp b/include/graphblas/collectives.hpp index e541e317c..bc5e8d9cc 100644 --- a/include/graphblas/collectives.hpp +++ b/include/graphblas/collectives.hpp @@ -30,9 +30,6 @@ #ifdef _GRB_WITH_REFERENCE #include #endif -// #ifdef _GRB_WITH_DENSE -// #include -// #endif #ifdef _GRB_WITH_LPF #include #endif diff --git a/include/graphblas/exec.hpp b/include/graphblas/exec.hpp index 95b8e325d..5f39263fd 100644 --- a/include/graphblas/exec.hpp +++ b/include/graphblas/exec.hpp @@ -30,9 +30,6 @@ #ifdef _GRB_WITH_REFERENCE #include "graphblas/reference/exec.hpp" #endif -#ifdef _GRB_WITH_DENSEREF - #include "graphblas/denseref/exec.hpp" -#endif #ifdef _GRB_WITH_LPF #include "graphblas/bsp1d/exec.hpp" #endif diff --git a/include/graphblas/init.hpp b/include/graphblas/init.hpp index 8fb5377c5..2b1af0a52 100644 --- a/include/graphblas/init.hpp +++ b/include/graphblas/init.hpp @@ -31,9 +31,6 @@ #ifdef _GRB_WITH_REFERENCE #include "graphblas/reference/init.hpp" #endif -#ifdef _GRB_WITH_DENSEREF - #include "graphblas/denseref/init.hpp" -#endif #ifdef _GRB_WITH_LPF #include "graphblas/bsp1d/init.hpp" #endif diff --git a/include/graphblas/io.hpp b/include/graphblas/io.hpp index c0ee2f932..9d09b95d2 100644 --- a/include/graphblas/io.hpp +++ b/include/graphblas/io.hpp @@ -29,9 +29,6 @@ #ifdef _GRB_WITH_REFERENCE #include #endif -#ifdef _GRB_WITH_DENSEREF - #include -#endif #ifdef _GRB_WITH_LPF #include #endif diff --git a/include/graphblas/matrix.hpp b/include/graphblas/matrix.hpp index 907cb1e4e..c8e4a8b35 100644 --- a/include/graphblas/matrix.hpp +++ b/include/graphblas/matrix.hpp @@ -30,9 +30,6 @@ #ifdef _GRB_WITH_REFERENCE #include #endif -#ifdef _GRB_WITH_DENSEREF - #include -#endif #ifdef _GRB_WITH_LPF #include #endif @@ -51,12 +48,6 @@ namespace grb { > class Matrix; - /* - * The default value of \a density could also be made conditional (Dense or Sparse) depending on \a config::default_backend - */ - template< typename T, typename Structure, enum Density density = Density::Dense, typename View = view::Original< void >, enum Backend backend = config::default_backend > - class StructuredMatrix; - } // namespace grb #endif diff --git a/include/graphblas/pinnedvector.hpp b/include/graphblas/pinnedvector.hpp index b27dba86f..8f783c2d3 100644 --- a/include/graphblas/pinnedvector.hpp +++ b/include/graphblas/pinnedvector.hpp @@ -34,9 +34,6 @@ #ifdef _GRB_WITH_REFERENCE #include #endif -#ifdef _GRB_WITH_DENSE - #include -#endif #ifdef _GRB_WITH_LPF #include #endif diff --git a/include/graphblas/properties.hpp b/include/graphblas/properties.hpp index c8b099101..c04fba3d6 100644 --- a/include/graphblas/properties.hpp +++ b/include/graphblas/properties.hpp @@ -30,9 +30,6 @@ #ifdef _GRB_WITH_REFERENCE #include #endif -#ifdef _GRB_WITH_DENSE - #include -#endif #ifdef _GRB_WITH_LPF #include #endif diff --git a/include/graphblas/spmd.hpp b/include/graphblas/spmd.hpp index e9aee3f55..4a6e7dbae 100644 --- a/include/graphblas/spmd.hpp +++ b/include/graphblas/spmd.hpp @@ -29,9 +29,6 @@ #ifdef _GRB_WITH_REFERENCE #include "graphblas/reference/spmd.hpp" #endif -// #ifdef _GRB_WITH_DENSE -// #include "graphblas/denseref/spmd.hpp" -// #endif #ifdef _GRB_WITH_LPF #include "graphblas/bsp1d/spmd.hpp" #endif diff --git a/include/graphblas/utils/alloc.hpp b/include/graphblas/utils/alloc.hpp index 4c67eb4ce..d673c26ed 100644 --- a/include/graphblas/utils/alloc.hpp +++ b/include/graphblas/utils/alloc.hpp @@ -49,9 +49,6 @@ namespace grb { #ifdef _GRB_WITH_REFERENCE #include "graphblas/reference/alloc.hpp" #endif -#ifdef _GRB_WITH_DENSEREF - #include "graphblas/denseref/alloc.hpp" -#endif #ifdef _GRB_WITH_LPF #include "graphblas/bsp1d/alloc.hpp" #endif diff --git a/include/graphblas/vector.hpp b/include/graphblas/vector.hpp index fb5fff59b..26a88fb00 100644 --- a/include/graphblas/vector.hpp +++ b/include/graphblas/vector.hpp @@ -31,9 +31,6 @@ #ifdef _GRB_WITH_REFERENCE #include #endif -#ifdef _GRB_WITH_DENSEREF - #include -#endif #ifdef _GRB_WITH_LPF #include #endif @@ -54,12 +51,6 @@ namespace grb { > class Vector; - /* - * The default value of \a density could also be made conditional (Dense or Sparse) depending on \a config::default_backend - */ - template< typename T, typename Structure = structures::General, enum Density density = Density::Dense, typename View = view::Original< void >, enum Backend backend = config::default_backend > - class VectorView; - } #endif diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 6ba2932ae..6870c802e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -21,6 +21,7 @@ ### ADD BACKENDS add_subdirectory( graphblas ) +add_subdirectory( alp ) ### Add transition path targets add_subdirectory( transition ) diff --git a/src/alp/CMakeLists.txt b/src/alp/CMakeLists.txt new file mode 100644 index 000000000..29cc55f2c --- /dev/null +++ b/src/alp/CMakeLists.txt @@ -0,0 +1,38 @@ +# +# Copyright 2021 Huawei Technologies Co., Ltd. +# +# 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. +# + +# +# This file creates the basic target(s) needed by all backends +# + +assert_defined_targets( backend_headers_nodefs backend_flags ) + +### ACTUAL BACKEND IMPLEMENTATIONS + +# target to compile all backend libraries +# add_custom_target( libs ALL ) + +# these sources are common to all backends, although some are in reference +set( backend_alp_reference_srcs + ${CMAKE_CURRENT_SOURCE_DIR}/descriptors.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/rc.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/reference/init.cpp + # ${CMAKE_CURRENT_SOURCE_DIR}/reference/config.cpp +) + +if( WITH_ALP_REFERENCE_BACKEND ) + add_subdirectory( reference ) +endif() diff --git a/src/alp/descriptors.cpp b/src/alp/descriptors.cpp new file mode 100644 index 000000000..a3308b7c5 --- /dev/null +++ b/src/alp/descriptors.cpp @@ -0,0 +1,58 @@ + +/* + * Copyright 2021 Huawei Technologies Co., Ltd. + * + * 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. + */ + +#include + +std::string alp::descriptors::toString( const alp::Descriptor descr ) { + std::ostringstream os; + if( descr == 0 ) { + os << "no-op descriptor\n"; + } else { + os << "specialised descriptor:\n"; + if( descr & invert_mask ) { + os << " inverted mask\n"; + } + if( descr & transpose_matrix ) { + os << " transpose input matrix\n"; + } + if( descr & no_duplicates ) { + os << " user guarantees no duplicate coordinate on input\n"; + } + if( descr & structural ) { + os << " mask must be interpreted structurally, and not by value\n"; + } + if( descr & dense ) { + os << " user guarantees all vectors in this call are dense\n"; + } + if( descr & add_identity ) { + os << " an identity matrix is added to the input matrix\n"; + } + if( descr & use_index ) { + os << " instead of using input vector elements, use their index " + "instead\n"; + } + if( descr & explicit_zero ) { + os << " the operation should take zeroes into account explicitly " + "when computing output\n"; + } + if( descr & no_casting ) { + os << " disallow casting between types during the requested " + "computation\n"; + } + } + return os.str(); +} diff --git a/src/alp/rc.cpp b/src/alp/rc.cpp new file mode 100644 index 000000000..f15b9b178 --- /dev/null +++ b/src/alp/rc.cpp @@ -0,0 +1,58 @@ + +/* + * Copyright 2021 Huawei Technologies Co., Ltd. + * + * 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. + */ + +#include "alp/rc.hpp" + +std::string alp::toString( const alp::RC code ) { + std::string ret; + switch( code ) { + case alp::SUCCESS: + ret = "Success"; + break; + case alp::PANIC: + ret = "Panic (unrecoverable)"; + break; + case alp::OUTOFMEM: + ret = "Out-of-memory"; + break; + case alp::MISMATCH: + ret = "Mismatching dimensions during call"; + break; + case alp::OVERLAP: + ret = "Overlapping containers given while this defined to be " + "illegal"; + break; + case alp::OVERFLW: + ret = "A cast of a given argument to a given smaller data type " + "would result in overflow"; + break; + case alp::UNSUPPORTED: + ret = "The chosen backend does not support the requested call"; + break; + case alp::ILLEGAL: + ret = "An illegal user argument was detected"; + break; + case alp::FAILED: + ret = "A GraphBLAS algorithm has failed to achieve its intended " + "result (e.g., has not converged)"; + break; + default: + ret = "Uninterpretable error code detected, please notify the " + "developers."; + } + return ret; +} diff --git a/src/graphblas/denseref/CMakeLists.txt b/src/alp/reference/CMakeLists.txt similarity index 53% rename from src/graphblas/denseref/CMakeLists.txt rename to src/alp/reference/CMakeLists.txt index d78119234..96024c903 100644 --- a/src/graphblas/denseref/CMakeLists.txt +++ b/src/alp/reference/CMakeLists.txt @@ -15,40 +15,40 @@ # assert_valid_variables( BACKEND_LIBRARY_OUTPUT_NAME VERSION - DENSEREF_BACKEND_INSTALL_DIR INCLUDE_INSTALL_DIR - DENSEREF_BACKEND_DEFAULT_NAME - DENSEREF_SELECTION_DEFS + ALP_REFERENCE_BACKEND_INSTALL_DIR INCLUDE_INSTALL_DIR + ALP_REFERENCE_BACKEND_DEFAULT_NAME + ALP_REFERENCE_SELECTION_DEFS ) -# sources for dense reference backend -set( backend_reference_dense_srcs +# sources for ALP reference backend +set( backend_alp_reference_srcs ${CMAKE_CURRENT_SOURCE_DIR}/../descriptors.cpp ${CMAKE_CURRENT_SOURCE_DIR}/../rc.cpp ${CMAKE_CURRENT_SOURCE_DIR}/init.cpp ) -add_library( backend_reference_dense_static STATIC "${backend_reference_dense_srcs}" ) +add_library( backend_alp_reference_static STATIC "${backend_alp_reference_srcs}" ) -target_link_libraries( backend_reference_dense_static PUBLIC backend_reference_dense_headers ) +target_link_libraries( backend_alp_reference_static PUBLIC backend_alp_reference_headers ) -set_target_properties( backend_reference_dense_static PROPERTIES +set_target_properties( backend_alp_reference_static PROPERTIES OUTPUT_NAME "${BACKEND_LIBRARY_OUTPUT_NAME}" ) -set_target_properties( backend_reference_dense_static PROPERTIES - ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/reference_dense" +set_target_properties( backend_alp_reference_static PROPERTIES + ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/reference" ) -target_compile_definitions( backend_reference_dense_static PUBLIC "${DENSEREF_SELECTION_DEFS}" ) -target_link_libraries( backend_reference_dense_static PRIVATE backend_flags ) +target_compile_definitions( backend_alp_reference_static PUBLIC "${ALP_REFERENCE_SELECTION_DEFS}" ) +target_link_libraries( backend_alp_reference_static PRIVATE backend_flags ) -add_dependencies( libs backend_reference_dense_static ) +add_dependencies( libs backend_alp_reference_static ) -install( TARGETS backend_reference_dense_static +install( TARGETS backend_alp_reference_static EXPORT GraphBLASTargets - ARCHIVE DESTINATION "${DENSEREF_BACKEND_INSTALL_DIR}" + ARCHIVE DESTINATION "${ALP_REFERENCE_BACKEND_INSTALL_DIR}" ) # this is an alias for add_grb_executables() to select the backend to link against # DO NOT CHANGE THE ALIAS NAME! -add_library( "${DENSEREF_BACKEND_DEFAULT_NAME}" ALIAS backend_reference_dense_static ) +add_library( "${ALP_REFERENCE_BACKEND_DEFAULT_NAME}" ALIAS backend_alp_reference_static ) diff --git a/src/graphblas/denseref/init.cpp b/src/alp/reference/init.cpp similarity index 66% rename from src/graphblas/denseref/init.cpp rename to src/alp/reference/init.cpp index 00090bae2..865b1fc3e 100644 --- a/src/graphblas/denseref/init.cpp +++ b/src/alp/reference/init.cpp @@ -15,32 +15,27 @@ * limitations under the License. */ -/* - * @author A. N. Yzelman - * @date 2nd of February, 2017 - */ - -#include +#include template<> -grb::RC grb::init< grb::reference_dense >( const size_t s, const size_t P, void * const data ) { +alp::RC alp::init< alp::reference >( const size_t s, const size_t P, void * const data ) { // we don't use any implementation-specific init data (void)data; // print output - std::cerr << "Info: grb::init (reference_dense) called.\n"; + std::cerr << "Info: alp::init (reference) called.\n"; // sanity checks if( P > 1 ) { - return grb::UNSUPPORTED; + return alp::UNSUPPORTED; } if( s > 0 ) { - return grb::PANIC; + return alp::PANIC; } // done - return grb::SUCCESS; + return alp::SUCCESS; } template<> -grb::RC grb::finalize< grb::reference_dense >() { - return grb::SUCCESS; +alp::RC alp::finalize< alp::reference >() { + return alp::SUCCESS; } diff --git a/src/graphblas/CMakeLists.txt b/src/graphblas/CMakeLists.txt index 6e2ffe06f..c751a64ab 100644 --- a/src/graphblas/CMakeLists.txt +++ b/src/graphblas/CMakeLists.txt @@ -83,10 +83,6 @@ if( WITH_REFERENCE_BACKEND OR WITH_OMP_BACKEND ) add_subdirectory( reference ) endif() -if( WITH_DENSEREF_BACKEND ) - add_subdirectory( denseref ) -endif() - if( WITH_BSP1D_BACKEND OR WITH_HYBRID_BACKEND ) add_subdirectory( bsp1d ) endif() From cde0f999e8c1863cc83dee9bd130ee7d8e253554 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Fri, 25 Mar 2022 14:39:43 +0100 Subject: [PATCH 121/282] !35 Resolve internal issue #367: Refactor grb to alp This commit is part of two-commit sequence that resolves internal issue #367. The commits are separated to allow for easier tracking of the moved files' history. This includes the following changes in relevant files (include, src and tests): - Rename namespace from grb to alp - Rename backend from reference_dense to reference - Rename include guards - Remove graphblas specific backends from alp - Other minor related changes - Fix previously undiscovered compilation issues - Unrelated: Remove nrows/ncols from blas2. Move its doxygen to matrix.hpp In addition, refactor naming of ALP containers - Rename Matrix -> internal::Matrix - Rename StructuredMatrix -> Matrix - Rename Vector -> internal::Vector - Rename VectorView -> Vector - Modifications incorrporating the above-mentioned renames - Minor coding style fixes where appropriate (mainly indentations) --- CMakeLists.txt | 2 +- include/alp/backends.hpp | 128 +- include/alp/base/blas2.hpp | 256 ++- include/alp/base/blas3.hpp | 50 +- include/alp/base/collectives.hpp | 38 +- include/alp/base/config.hpp | 28 +- include/alp/base/exec.hpp | 34 +- include/alp/base/init.hpp | 42 +- include/alp/base/internalops.hpp | 56 +- include/alp/base/io.hpp | 62 +- include/alp/base/matrix.hpp | 940 ++++----- include/alp/base/scalar.hpp | 30 +- include/alp/base/vector.hpp | 1698 ++++++++--------- include/alp/blas0.hpp | 116 +- include/alp/blas1.hpp | 145 +- include/alp/blas2.hpp | 19 +- include/alp/blas3.hpp | 16 +- include/alp/config.hpp | 19 +- include/alp/density.hpp | 10 +- include/alp/descriptors.hpp | 8 +- include/alp/exec.hpp | 23 +- include/alp/identities.hpp | 12 +- include/alp/imf.hpp | 10 +- include/alp/init.hpp | 19 +- include/alp/internalops.hpp | 8 +- include/alp/iomode.hpp | 18 +- include/alp/matrix.hpp | 33 +- include/alp/monoid.hpp | 22 +- include/alp/ops.hpp | 28 +- include/alp/phase.hpp | 10 +- include/alp/rc.hpp | 14 +- include/alp/reference/alloc.hpp | 8 +- include/alp/reference/benchmark.hpp | 14 +- include/alp/reference/blas0.hpp | 42 +- include/alp/reference/blas1.hpp | 1618 ++++++++-------- include/alp/reference/blas2.hpp | 300 ++- include/alp/reference/blas3.hpp | 292 +-- include/alp/reference/collectives.hpp | 12 +- include/alp/reference/config.hpp | 12 +- include/alp/reference/exec.hpp | 26 +- include/alp/reference/init.hpp | 16 +- include/alp/reference/io.hpp | 40 +- include/alp/reference/matrix.hpp | 807 ++++---- include/alp/reference/pinnedvector.hpp | 10 +- include/alp/reference/properties.hpp | 14 +- include/alp/reference/scalar.hpp | 46 +- include/alp/reference/spmd.hpp | 18 +- include/alp/reference/vector.hpp | 575 +++--- include/alp/reference/vectoriterator.hpp | 18 +- include/alp/scalar.hpp | 14 +- include/alp/semiring.hpp | 68 +- include/alp/smf.hpp | 10 +- include/alp/structures.hpp | 28 +- include/alp/type_traits.hpp | 26 +- include/alp/utils.hpp | 38 +- .../alp/utils/SynchronizedNonzeroIterator.hpp | 14 +- include/alp/utils/autodeleter.hpp | 25 +- include/alp/utils/suppressions.h | 14 +- include/alp/vector.hpp | 30 +- include/alp/views.hpp | 10 +- src/alp/reference/init.cpp | 1 + tests/unit/CMakeLists.txt | 14 +- tests/unit/dense_constant_matrices.cpp | 30 +- tests/unit/dense_dot_norm2.cpp | 68 +- tests/unit/dense_matrix_eWiseApply.cpp | 44 +- tests/unit/dense_matrix_imf.cpp | 48 +- tests/unit/dense_mxm.cpp | 50 +- tests/unit/dense_outer.cpp | 42 +- tests/unit/dense_structured_matrix.cpp | 66 +- 69 files changed, 4093 insertions(+), 4309 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6ae7b8f90..fb428e81f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -50,7 +50,7 @@ endif() ### CONFIGURATION OPTIONS # to choose backends and dependencies option( WITH_REFERENCE_BACKEND "With Reference backend" ON ) -option( WITH_DENSEREF_BACKEND "With Reference Dense backend" ON ) +option( WITH_ALP_REFERENCE_BACKEND "With Reference Dense backend" ON ) option( WITH_OMP_BACKEND "With OMP backend" ON ) option( WITH_NUMA "With NUMA support" ON ) option( LPF_INSTALL_PATH "Path to the LPF tools for the BSP1D and Hybrid backends" OFF ) diff --git a/include/alp/backends.hpp b/include/alp/backends.hpp index 9e36122a7..4aba1cfac 100644 --- a/include/alp/backends.hpp +++ b/include/alp/backends.hpp @@ -22,14 +22,14 @@ * @file This file contains a register of all backends that are either * implemented, under implementation, or were at any point in time * conceived and noteworthy enough to be recorded for future - * consideration to implement. It does so via the grb::Backend + * consideration to implement. It does so via the alp::Backend * enum. */ -#ifndef _H_GRB_BACKENDS -#define _H_GRB_BACKENDS +#ifndef _H_ALP_BACKENDS +#define _H_ALP_BACKENDS -namespace grb { +namespace alp { /** * This enum collects all implemented backends. Depending on compile flags, @@ -37,131 +37,15 @@ namespace grb { */ enum Backend { - /** - * The sequential reference implementation. Supports fast operations with - * both sparse and dense vectors. - */ - reference, - - /** - * The threaded reference implementation. Supports fast operations with both - * sparse and dense vectors. - */ - reference_omp, - - /** - * A shared-memory parallel distribution based on a row-wise 1D data - * distribution using shared vector data. - */ - shmem1D, - - /** - * Like shmem1D, but using interleaved vector allocation. Useful for multi- - * socket single-node targets. From experience, this is a good choice for up - * to four sockets-- after which BSP2D becomes preferred. - */ - NUMA1D, - - /** - * A superclass of all BSP-based implementations. - */ - GENERIC_BSP, - - /** - * A parallel implementation based on a row-wise 1D data distribution, - * implemented using PlatformBSP. - */ - BSP1D, - - /** - * Like BSP1D, but stores each matrix twice. Combined with the normal - * reference implementation, this actually stores all matrices four times - * This implementation is useful for maximum performance, at the cost of - * the additional memory usage. - */ - doublyBSP1D, - - /** - * A parallel implementation based on a block-cyclic 2D data distribution, - * implemented using PlatformBSP. This implementation will likely outperform - * BSP1D and doublyBSP1D as the number of nodes involved in the computation - * increases with the problem sizes. - */ - BSP2D, - - /** - * Like BSP2D, but automatically improves the distribution while executing - * user code-- while initial computations are slowed down, the user - * application will speed up as this GraphBLAS implementation infers more - * information about the best data distribution. - * When enough statistics are gathered, data is redistributed and all future - * operations execute much faster than with BSP2D alone. - */ - autoBSP, - - /** - * Like autoBSP, except that the best distribution is precomputed whenever a - * matrix is read in. This pre-processing step is very expensive. Use autoBSP - * when unsure if the costs of a full preprocessing stage is worth it. - */ - optBSP, - - /** - * A hybrid that uses shmem1D within each socket and BSP1D between sockets. - * Recommended for a limited number of sockets and a limited amount of nodes, - * i.e., for a small cluster. - */ - hybridSmall, - - /** - * A hybrid that uses numa1D within each socket and BSP1D between sockets. - * Recommended for a limited number of nodes with up to two sockets each. - * - * This variant is expected to perform better than hybrid1D for middle-sized - * clusters. - */ - hybridMid, - - /** - * A hybrid that uses numa1D within each socket and autoBSP between sockets. - * Recommended for a large number of nodes with up to two sockets each. - * - * This variant is expected to perform better than hybridSmall and hybridMid - * for larger clusters. - * - * If there are many nodes each with many sockets (four or more) each, then - * the use of flat (non-hybrid) #BSP2D or #autoBSP is recommended instead. - */ - hybridLarge, - - /** - * A hybrid variant that is optimised for a minimal memory footprint. - */ - minFootprint, - - /** - * A variant for RISC-V processors. - * - * Collaboration with ETH Zurich (ongoing). - */ - banshee, - - /** - * A variant for RISC-V processors with (I)SSR extensions - * - * Collaboration with ETH Zurich (ongoing). - */ - banshee_ssr, - /** * The ALP/Dense backend. This is no longer a proper GraphBLAS implementation, as it assumes * all containers are dense. No ``missing'' entries in containers are allowed. */ - reference_dense + reference }; -} // namespace grb +} // namespace alp #endif diff --git a/include/alp/base/blas2.hpp b/include/alp/base/blas2.hpp index 958655123..c1b87765e 100644 --- a/include/alp/base/blas2.hpp +++ b/include/alp/base/blas2.hpp @@ -24,22 +24,22 @@ * @date 30th of March 2017 */ -#ifndef _H_GRB_BLAS2_BASE -#define _H_GRB_BLAS2_BASE +#ifndef _H_ALP_BLAS2_BASE +#define _H_ALP_BLAS2_BASE #include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include #include "config.hpp" #include "matrix.hpp" #include "vector.hpp" -namespace grb { +namespace alp { /** * \defgroup BLAS2 The Level-2 Basic Linear Algebra Subroutines (BLAS) @@ -49,7 +49,7 @@ namespace grb { * two-dimensional containers. * * That is, these functions allow various linear algebra operations on - * scalars, objects of type grb::Vector, and objects of type grb::Matrix. + * scalars, objects of type alp::Vector, and objects of type alp::Matrix. * * \note The backends of each opaque data type should match. * @@ -59,9 +59,9 @@ namespace grb { /** * Right-handed sparse matrix times vector multiplication, \f$ u = Av \f$. * - * Let \f$ u \f$ and \f$ \mathit{mask} \f$ each be a #grb::Vector of #grb::size - * \f$ m \f$, \f$ v \f$ be a #grb::Vector of #grb::size \f$ n \f$, and let - * \f$ A \f$ be a #Matrix with #grb::nrows \f$ m \f$ and #grb::ncols \f$ n \f$. + * Let \f$ u \f$ and \f$ \mathit{mask} \f$ each be a #alp::Vector of #alp::size + * \f$ m \f$, \f$ v \f$ be a #alp::Vector of #alp::size \f$ n \f$, and let + * \f$ A \f$ be a #Matrix with #alp::nrows \f$ m \f$ and #alp::ncols \f$ n \f$. * Let furthermore \f$ z \f$ be an interal vector of size \f$ m \f$. * A call to this function first computes \f$ z = Av \f$ over the provided * \a ring. It then left-folds \f$ z \f$ into \f$ u \f$ using the provided @@ -100,8 +100,8 @@ namespace grb { * in \f$ \Theta(m) \f$ data movement and may only be warrented when * \f$ A \f$ has many nonzeroes per row and \f$ v \f$ is dense. * - * @tparam descr Any combination of one or more #grb::descriptors. When - * ommitted, the default #grb::descriptors:no_operation will + * @tparam descr Any combination of one or more #alp::descriptors. When + * ommitted, the default #alp::descriptors:no_operation will * be assumed. * @tparam Ring The generalised semi-ring the matrix--vector multiplication * is to be executed under. @@ -109,35 +109,35 @@ namespace grb { * @tparam InputType1 The type of the elements of the input vector \a v. * @tparam InputType2 The type of the elements of the input matrix \a A. * @tparam Operator The type of the \a accumulator. Must be a GraphBLAS - * operator; see also #grb::operators. + * operator; see also #alp::operators. * @tparam InputType3 The type of the elements of the mask vector \a mask. * @tparam implementation Which back-end the given vectors and matrices belong * to. These must all belong to the same back-end. * * @param[in,out] u The output vector. Depending on the provided * \a accumulator, old vector values may affect new values. - * @param[in] mask The mask vector. The vector #grb::size must be equal to + * @param[in] mask The mask vector. The vector #alp::size must be equal to * that of \a u, \em or it must be equal to zero. A \a mask - * of grb::size zero will be ignored (assumed true + * of alp::size zero will be ignored (assumed true * always. * @param[in] accumulator The operator \f$ \bigodot \f$ in the above * description. - * @param[in] A The input matrix. Its #grb::nrows must equal the - * #grb::size of \a u. - * @param[in] v The input vector. Its #grb::size must equal the - * #grb::ncols of \a A. + * @param[in] A The input matrix. Its #alp::nrows must equal the + * #alp::size of \a u. + * @param[in] v The input vector. Its #alp::size must equal the + * #alp::ncols of \a A. * @param[in] ring The semiring to perform the matrix--vector multiplication - * under. Unless #grb::descriptors::no_casting is defined, + * under. Unless #alp::descriptors::no_casting is defined, * elements from \a u, \a A, and \a v will be cast to the * domains of the additive and multiplicative operators of * \a ring as they are applied during the multiplication. * - * \warning Even if #grb::operators::right_assign is provided as accumulator, + * \warning Even if #alp::operators::right_assign is provided as accumulator, * old values of \a u may \em not be overwritten if the computation * ends up not writing any new values to those values. To throw away - * old vector values use grb::descriptors::explicit_zero (for dense + * old vector values use alp::descriptors::explicit_zero (for dense * vectors only if you wish to retain sparsity of the output vector), - * or first simply use grb::clear on \a u. + * or first simply use alp::clear on \a u. * * The above semantics may be changed by the following descriptors: * * #descriptors::invert_mask: \f$ u_i^\mathit{out} \f$ will be written to @@ -203,7 +203,7 @@ namespace grb { * to maintain). * * #descriptors::structural: removes \f$ \Theta(|I|) \f$ data movement * costs as the mask values need no longer be touched. - * * #descriptors::add_identity: adds, at most, the costs of grb::foldl + * * #descriptors::add_identity: adds, at most, the costs of alp::foldl * (on vectors) to all performance metrics. * * #descriptors::use_index: removes \f$ \Theta(n) \f$ or * \f$ \Theta(|J|) \f$ data movement costs as the input vector values need @@ -220,36 +220,36 @@ namespace grb { * movement between then. * \endparblock * - * @returns grb::SUCCESS If the computation completed successfully. - * @returns grb::MISMATCH If there is at least one mismatch between vector + * @returns alp::SUCCESS If the computation completed successfully. + * @returns alp::MISMATCH If there is at least one mismatch between vector * dimensions or between vectors and the given matrix. - * @returns grb::OVERLAP If two or more provided vectors refer to the same + * @returns alp::OVERLAP If two or more provided vectors refer to the same * vector. * * When a non-SUCCESS error code is returned, it shall be as though the call * was never made. Note that all GraphBLAS functions may additionally return - * #grb::PANIC, which indicates the library has entered an undefined state; if + * #alp::PANIC, which indicates the library has entered an undefined state; if * this error code is returned, the only sensible thing a user can do is exit, * or at least refrain from using any GraphBLAS functions for the remainder of * the application. */ - template< Descriptor descr = descriptors::no_operation, + template< class Ring, typename IOType, typename InputType1, typename InputType2, typename InputType3, - typename Coords, + Descriptor descr = descriptors::no_operation, enum Backend implementation = config::default_backend > - RC mxv( Vector< IOType, implementation, Coords > & u, - const Vector< InputType3, implementation, Coords > & mask, - const Matrix< InputType2, implementation > & A, - const Vector< InputType1, implementation, Coords > & v, + RC mxv( internal::Vector< IOType, implementation > & u, + const internal::Vector< InputType3, implementation > & mask, + const internal::Matrix< InputType2, implementation > & A, + const internal::Vector< InputType1, implementation > & v, const Ring & ring, - typename std::enable_if< grb::is_semiring< Ring >::value, void >::type * = NULL ) { + typename std::enable_if< alp::is_semiring< Ring >::value, void >::type * = NULL ) { #ifdef _DEBUG - #ifndef _GRB_NO_STDIO - std::cerr << "Selected backend does not implement grb::mxv (output-masked)\n"; + #ifndef _ALP_NO_STDIO + std::cerr << "Selected backend does not implement alp::mxv (output-masked)\n"; #endif #endif (void)u; @@ -261,21 +261,21 @@ namespace grb { } /** - * A short-hand for an unmasked #grb::mxv. + * A short-hand for an unmasked #alp::mxv. * - * @see grb::mxv for the full documentation. + * @see alp::mxv for the full documentation. */ - template< Descriptor descr = descriptors::no_operation, class Ring, typename IOType, typename InputType1, typename InputType2, typename Coords, Backend implementation = config::default_backend > - RC mxv( Vector< IOType, implementation, Coords > & u, - const Matrix< InputType2, implementation > & A, - const Vector< InputType1, implementation, Coords > & v, + template< Descriptor descr = descriptors::no_operation, class Ring, typename IOType, typename InputType1, typename InputType2, Backend implementation = config::default_backend > + RC mxv( internal::Vector< IOType, implementation > & u, + const internal::Matrix< InputType2, implementation > & A, + const internal::Vector< InputType1, implementation > & v, const Ring & ring, - typename std::enable_if< grb::is_semiring< Ring >::value, void >::type * = NULL ) { + typename std::enable_if< alp::is_semiring< Ring >::value, void >::type * = NULL ) { #ifdef _DEBUG -#ifndef _GRB_NO_STDIO - std::cerr << "Selected backend does not implement grb::mxv\n"; +#ifndef _ALP_NO_STDIO + std::cerr << "Selected backend does not implement alp::mxv\n"; #else - printf( "Selected backend does not implement grb::mxv\n" ); + printf( "Selected backend does not implement alp::mxv\n" ); #endif #endif (void)u; @@ -288,14 +288,14 @@ namespace grb { /** * Left-handed sparse matrix times vector multiplication, \f$ u = vA \f$. * - * If \a descr does not have #grb::descriptors::transpose_matrix defined, the + * If \a descr does not have #alp::descriptors::transpose_matrix defined, the * semantics and performance semantics of this function are exactly that of - * grb::mxv with the #grb::descriptors::transpose_matrix set. + * alp::mxv with the #alp::descriptors::transpose_matrix set. * In the other case, the functional and performance semantics of this function - * are exactly that of grb::mxv without the #grb::descriptors::transpose_matrix + * are exactly that of alp::mxv without the #alp::descriptors::transpose_matrix * set. * - * @see grb::mxv for the full documentation. + * @see alp::mxv for the full documentation. */ template< Descriptor descr = descriptors::no_operation, class Ring, @@ -303,17 +303,16 @@ namespace grb { typename InputType1, typename InputType2, typename InputType3, - typename Coords, enum Backend implementation = config::default_backend > - RC vxm( Vector< IOType, implementation, Coords > & u, - const Vector< InputType3, implementation, Coords > & mask, - const Vector< InputType1, implementation, Coords > & v, - const Matrix< InputType2, implementation > & A, + RC vxm( internal::Vector< IOType, implementation > & u, + const internal::Vector< InputType3, implementation > & mask, + const internal::Vector< InputType1, implementation > & v, + const internal::Matrix< InputType2, implementation > & A, const Ring & ring, - typename std::enable_if< grb::is_semiring< Ring >::value, void >::type * = NULL ) { + typename std::enable_if< alp::is_semiring< Ring >::value, void >::type * = NULL ) { #ifdef _DEBUG - #ifndef _GRB_NO_STDIO - std::cerr << "Selected backend does not implement grb::vxm (output-masked)\n"; + #ifndef _ALP_NO_STDIO + std::cerr << "Selected backend does not implement alp::vxm (output-masked)\n"; #endif #endif (void)u; @@ -325,25 +324,24 @@ namespace grb { } /** - * A short-hand for an unmasked grb::vxm. + * A short-hand for an unmasked alp::vxm. * - * @see grb::vxm for the full documentation. + * @see alp::vxm for the full documentation. */ template< Descriptor descr = descriptors::no_operation, class Ring, typename IOType, typename InputType1, typename InputType2, - typename Coords, enum Backend implementation = config::default_backend > - RC vxm( Vector< IOType, implementation, Coords > & u, - const Vector< InputType1, implementation, Coords > & v, - const Matrix< InputType2, implementation > & A, + RC vxm( internal::Vector< IOType, implementation > & u, + const internal::Vector< InputType1, implementation > & v, + const internal::Matrix< InputType2, implementation > & A, const Ring & ring, - typename std::enable_if< grb::is_semiring< Ring >::value, void >::type * = NULL ) { + typename std::enable_if< alp::is_semiring< Ring >::value, void >::type * = NULL ) { #ifdef _DEBUG - #ifndef _GRB_NO_STDIO - std::cerr << "Selected backend does not implement grb::vxm\n"; + #ifndef _ALP_NO_STDIO + std::cerr << "Selected backend does not implement alp::vxm\n"; #endif #endif (void)u; @@ -362,21 +360,20 @@ namespace grb { typename InputType2, typename InputType3, typename InputType4, - typename Coords, Backend backend > - RC vxm( Vector< IOType, backend, Coords > & u, - const Vector< InputType3, backend, Coords > & mask, - const Vector< InputType1, backend, Coords > & v, - const Vector< InputType4, backend, Coords > & v_mask, - const Matrix< InputType2, backend > & A, + RC vxm( internal::Vector< IOType, backend > & u, + const internal::Vector< InputType3, backend > & mask, + const internal::Vector< InputType1, backend > & v, + const internal::Vector< InputType4, backend > & v_mask, + const internal::Matrix< InputType2, backend > & A, const AdditiveMonoid & add = AdditiveMonoid(), const MultiplicativeOperator & mul = MultiplicativeOperator(), - const typename std::enable_if< grb::is_monoid< AdditiveMonoid >::value && grb::is_operator< MultiplicativeOperator >::value && ! grb::is_object< IOType >::value && - ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && ! grb::is_object< InputType4 >::value && + const typename std::enable_if< alp::is_monoid< AdditiveMonoid >::value && alp::is_operator< MultiplicativeOperator >::value && ! alp::is_object< IOType >::value && + ! alp::is_object< InputType1 >::value && ! alp::is_object< InputType2 >::value && ! alp::is_object< InputType3 >::value && ! alp::is_object< InputType4 >::value && ! std::is_same< InputType2, void >::value, void >::type * const = NULL ) { #ifdef _DEBUG - #ifndef _GRB_NO_STDIO + #ifndef _ALP_NO_STDIO std::cerr << "Selected backend does not implement vxm (doubly-masked)\n"; #endif #endif @@ -399,21 +396,20 @@ namespace grb { typename InputType2, typename InputType3, typename InputType4, - typename Coords, Backend backend > - RC mxv( Vector< IOType, backend, Coords > & u, - const Vector< InputType3, backend, Coords > & mask, - const Matrix< InputType2, backend > & A, - const Vector< InputType1, backend, Coords > & v, - const Vector< InputType4, backend, Coords > & v_mask, + RC mxv( internal::Vector< IOType, backend > & u, + const internal::Vector< InputType3, backend > & mask, + const internal::Matrix< InputType2, backend > & A, + const internal::Vector< InputType1, backend > & v, + const internal::Vector< InputType4, backend > & v_mask, const AdditiveMonoid & add = AdditiveMonoid(), const MultiplicativeOperator & mul = MultiplicativeOperator(), - const typename std::enable_if< grb::is_monoid< AdditiveMonoid >::value && grb::is_operator< MultiplicativeOperator >::value && ! grb::is_object< IOType >::value && - ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && ! grb::is_object< InputType4 >::value && + const typename std::enable_if< alp::is_monoid< AdditiveMonoid >::value && alp::is_operator< MultiplicativeOperator >::value && ! alp::is_object< IOType >::value && + ! alp::is_object< InputType1 >::value && ! alp::is_object< InputType2 >::value && ! alp::is_object< InputType3 >::value && ! alp::is_object< InputType4 >::value && ! std::is_same< InputType2, void >::value, void >::type * const = NULL ) { #ifdef _DEBUG - #ifndef _GRB_NO_STDIO + #ifndef _ALP_NO_STDIO std::cerr << "Selected backend does not implement mxv (doubly-masked)\n"; #endif #endif @@ -435,16 +431,15 @@ namespace grb { typename InputType1, typename InputType2, typename InputType3, - typename Coords, Backend backend > - RC mxv( Vector< IOType, backend, Coords > & u, - const Vector< InputType3, backend, Coords > & mask, - const Matrix< InputType2, backend > & A, - const Vector< InputType1, backend, Coords > & v, + RC mxv( internal::Vector< IOType, backend > & u, + const internal::Vector< InputType3, backend > & mask, + const internal::Matrix< InputType2, backend > & A, + const internal::Vector< InputType1, backend > & v, const AdditiveMonoid & add = AdditiveMonoid(), const MultiplicativeOperator & mul = MultiplicativeOperator(), - const typename std::enable_if< grb::is_monoid< AdditiveMonoid >::value && grb::is_operator< MultiplicativeOperator >::value && ! grb::is_object< IOType >::value && - ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && ! std::is_same< InputType2, void >::value, + const typename std::enable_if< alp::is_monoid< AdditiveMonoid >::value && alp::is_operator< MultiplicativeOperator >::value && ! alp::is_object< IOType >::value && + ! alp::is_object< InputType1 >::value && ! alp::is_object< InputType2 >::value && ! alp::is_object< InputType3 >::value && ! std::is_same< InputType2, void >::value, void >::type * const = NULL ) { (void)u; (void)mask; @@ -462,18 +457,17 @@ namespace grb { typename IOType, typename InputType1, typename InputType2, - typename Coords, Backend backend > - RC vxm( Vector< IOType, backend, Coords > & u, - const Vector< InputType1, backend, Coords > & v, - const Matrix< InputType2, backend > & A, + RC vxm( internal::Vector< IOType, backend > & u, + const internal::Vector< InputType1, backend > & v, + const internal::Matrix< InputType2, backend > & A, const AdditiveMonoid & add = AdditiveMonoid(), const MultiplicativeOperator & mul = MultiplicativeOperator(), - const typename std::enable_if< grb::is_monoid< AdditiveMonoid >::value && grb::is_operator< MultiplicativeOperator >::value && ! grb::is_object< IOType >::value && - ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! std::is_same< InputType2, void >::value, + const typename std::enable_if< alp::is_monoid< AdditiveMonoid >::value && alp::is_operator< MultiplicativeOperator >::value && ! alp::is_object< IOType >::value && + ! alp::is_object< InputType1 >::value && ! alp::is_object< InputType2 >::value && ! std::is_same< InputType2, void >::value, void >::type * const = NULL ) { #ifdef _DEBUG - #ifndef _GRB_NO_STDIO + #ifndef _ALP_NO_STDIO std::cerr << "Selected backend does not implement vxm (unmasked)\n"; #endif #endif @@ -493,20 +487,19 @@ namespace grb { typename InputType1, typename InputType2, typename InputType3, - typename Coords, Backend implementation > - RC vxm( Vector< IOType, implementation, Coords > & u, - const Vector< InputType3, implementation, Coords > & mask, - const Vector< InputType1, implementation, Coords > & v, - const Matrix< InputType2, implementation > & A, + RC vxm( internal::Vector< IOType, implementation > & u, + const internal::Vector< InputType3, implementation > & mask, + const internal::Vector< InputType1, implementation > & v, + const internal::Matrix< InputType2, implementation > & A, const AdditiveMonoid & add = AdditiveMonoid(), const MultiplicativeOperator & mul = MultiplicativeOperator(), - typename std::enable_if< grb::is_monoid< AdditiveMonoid >::value && grb::is_operator< MultiplicativeOperator >::value && ! grb::is_object< IOType >::value && - ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! std::is_same< InputType2, void >::value, + typename std::enable_if< alp::is_monoid< AdditiveMonoid >::value && alp::is_operator< MultiplicativeOperator >::value && ! alp::is_object< IOType >::value && + ! alp::is_object< InputType1 >::value && ! alp::is_object< InputType2 >::value && ! std::is_same< InputType2, void >::value, void >::type * = NULL ) { #ifdef _DEBUG - #ifndef _GRB_NO_STDIO - std::cerr << "Selected backend does not implement grb::vxm (output-masked)\n"; + #ifndef _ALP_NO_STDIO + std::cerr << "Selected backend does not implement alp::vxm (output-masked)\n"; #endif #endif (void)u; @@ -525,19 +518,18 @@ namespace grb { typename IOType, typename InputType1, typename InputType2, - typename Coords, Backend backend > - RC mxv( Vector< IOType, backend, Coords > & u, - const Matrix< InputType2, backend > & A, - const Vector< InputType1, backend, Coords > & v, + RC mxv( internal::Vector< IOType, backend > & u, + const internal::Matrix< InputType2, backend > & A, + const internal::Vector< InputType1, backend > & v, const AdditiveMonoid & add = AdditiveMonoid(), const MultiplicativeOperator & mul = MultiplicativeOperator(), - const typename std::enable_if< grb::is_monoid< AdditiveMonoid >::value && grb::is_operator< MultiplicativeOperator >::value && ! grb::is_object< IOType >::value && - ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! std::is_same< InputType2, void >::value, + const typename std::enable_if< alp::is_monoid< AdditiveMonoid >::value && alp::is_operator< MultiplicativeOperator >::value && ! alp::is_object< IOType >::value && + ! alp::is_object< InputType1 >::value && ! alp::is_object< InputType2 >::value && ! std::is_same< InputType2, void >::value, void >::type * const = NULL ) { #ifdef _DEBUG - #ifndef _GRB_NO_STDIO - std::cerr << "Selected backend does not implement grb::mxv (unmasked)\n"; + #ifndef _ALP_NO_STDIO + std::cerr << "Selected backend does not implement alp::mxv (unmasked)\n"; #endif #endif (void)u; @@ -553,7 +545,7 @@ namespace grb { * nonzero elements of a given matrix \a A. * * The user-defined function is passed as a lambda which can capture whatever - * the user would like, including one or multiple grb::Vector instances, or + * the user would like, including one or multiple alp::Vector instances, or * multiple scalars. When capturing vectors, these should also be passed as a * additional arguments to this functions so to make sure those vectors are * synchronised for access on all row- and column- indices corresponding to @@ -568,12 +560,12 @@ namespace grb { * * \warning The lambda shall only be executed on the data local to the user * process calling this function! This is different from the various - * fold functions, or grb::dot, in that the semantics of those + * fold functions, or alp::dot, in that the semantics of those * functions always result in globally synchronised result. To * achieve the same effect with user-defined lambdas, the users * should manually prescribe how to combine the local results into * global ones, for instance, by subsequent calls to - * grb::collectives. + * alp::collectives. * * \note This is an addition to the GraphBLAS. It is alike user-defined * operators, monoids, and semirings, except it allows execution on @@ -607,16 +599,16 @@ namespace grb { * @param[in] A The matrix the lambda is to access the elements of. * @param[in] args All vectors the lambda is to access elements of. Must be of * the same length as \a nrows(A) or \a ncols(A). If this - * constraint is violated, grb::MISMATCH shall be returned. If + * constraint is violated, alp::MISMATCH shall be returned. If * the vector length equals \a nrows(A), the vector shall be * synchronized for access on \a i. If the vector length equals * \a ncols(A), the vector shall be synchronized for access on * \a j. If \a A is square, the vectors will be synchronised for * access on both \a x and \a y. This is a variadic argument - * and can contain any number of containers of type grb::Vector, + * and can contain any number of containers of type alp::Vector, * passed as though they were separate arguments. * - * \warning Using a grb::Vector inside a lambda passed to this function while + * \warning Using a alp::Vector inside a lambda passed to this function while * not passing that same vector into \a args, will result in undefined * behaviour. * @@ -627,8 +619,8 @@ namespace grb { * access using \a j. For square matrices, however, the following * code in the body is accepted, however: x[i] += x[j]. * - * @return grb::SUCCESS When the lambda is successfully executed. - * @return grb::MISMATCH When two or more vectors passed to \a args are not of + * @return alp::SUCCESS When the lambda is successfully executed. + * @return alp::MISMATCH When two or more vectors passed to \a args are not of * appropriate length. * * \warning Captured scalars will be local to the user process executing the @@ -640,10 +632,10 @@ namespace grb { * @see Vector::lambda_reference */ template< typename Func, typename DataType, Backend implementation = config::default_backend, typename... Args > - RC eWiseLambda( const Func f, const Matrix< DataType, implementation > & A, Args... /*args*/ ) { + RC eWiseLambda( const Func f, const internal::Matrix< DataType, implementation > & A, Args... /*args*/ ) { #ifdef _DEBUG - #ifndef _GRB_NO_STDIO - std::cerr << "Selected backend does not implement grb::eWiseLambda (matrices)\n"; + #ifndef _ALP_NO_STDIO + std::cerr << "Selected backend does not implement alp::eWiseLambda (matrices)\n"; #endif #endif (void)f; @@ -653,6 +645,6 @@ namespace grb { /** @} */ -} // namespace grb +} // namespace alp -#endif // end _H_GRB_BLAS2_BASE +#endif // end _H_ALP_BLAS2_BASE diff --git a/include/alp/base/blas3.hpp b/include/alp/base/blas3.hpp index d3367c6eb..99e648b64 100644 --- a/include/alp/base/blas3.hpp +++ b/include/alp/base/blas3.hpp @@ -19,16 +19,16 @@ * @author A. N. Yzelman */ -#ifndef _H_GRB_BLAS3_BASE -#define _H_GRB_BLAS3_BASE +#ifndef _H_ALP_BLAS3_BASE +#define _H_ALP_BLAS3_BASE -#include -#include +#include +#include #include "matrix.hpp" #include "vector.hpp" -namespace grb { +namespace alp { /** * \defgroup BLAS3 The Level-3 Basic Linear Algebra Subroutines (BLAS) @@ -54,7 +54,7 @@ namespace grb { * * @returns SUCCESS If the computation completed as intended. * @returns FAILED If the call was not not preceded by one to - * #grb::resize( C, A, B ); \em and the current capacity of + * #alp::resize( C, A, B ); \em and the current capacity of * \a C was insufficient to store the multiplication of \a A * and \a B. The contents of \a C shall be undefined (which * is why #FAILED is returned instead of #ILLEGAL-- this @@ -74,14 +74,14 @@ namespace grb { class Semiring, Backend backend > - RC mxm( Matrix< OutputType, backend > &C, - const Matrix< InputType1, backend > &A, const Matrix< InputType2, backend > &B, + RC mxm( internal::Matrix< OutputType, backend > &C, + const internal::Matrix< InputType1, backend > &A, const internal::Matrix< InputType2, backend > &B, const Semiring &ring = Semiring(), const PHASE &phase = NUMERICAL ) { #ifdef _DEBUG - #ifndef _GRB_NO_STDIO - std::cerr << "Selected backend does not implement grb::mxm (semiring version)\n"; + #ifndef _ALP_NO_STDIO + std::cerr << "Selected backend does not implement alp::mxm (semiring version)\n"; #endif #endif (void)C; @@ -104,7 +104,7 @@ namespace grb { * given vectors x, y, and z encode, or ILLEGAL shall be returned. * * \note A call to this function hence must be preceded by a successful - * call to grb::resize( matrix, nnz ); + * call to alp::resize( matrix, nnz ); * * @param[out] A The output matrix * @param[in] x A vector of row indices. @@ -126,35 +126,35 @@ namespace grb { * @returns ILLEGAL If the capacity of A was insufficient to store the * given sparsity pattern. * - * @see grb::resize + * @see alp::resize */ - template< Descriptor descr = descriptors::no_operation, typename OutputType, typename InputType1, typename InputType2, typename InputType3, Backend backend, typename Coords > - RC zip( Matrix< OutputType, backend > & A, const Vector< InputType1, backend, Coords > & x, const Vector< InputType2, backend, Coords > & y, const Vector< InputType3, backend, Coords > & z ) { + template< Descriptor descr = descriptors::no_operation, typename OutputType, typename InputType1, typename InputType2, typename InputType3, Backend backend > + RC zip( internal::Matrix< OutputType, backend > & A, const internal::Vector< InputType1, backend > & x, const internal::Vector< InputType2, backend > & y, const internal::Vector< InputType3, backend > & z ) { (void)x; (void)y; (void)z; #ifdef _DEBUG - #ifndef _GRB_NO_STDIO - std::cerr << "Selected backend does not implement grb::zip (vectors into matrices, non-void)\n"; + #ifndef _ALP_NO_STDIO + std::cerr << "Selected backend does not implement alp::zip (vectors into matrices, non-void)\n"; #endif #endif - const RC ret = grb::clear( A ); + const RC ret = alp::clear( A ); return ret == SUCCESS ? UNSUPPORTED : ret; } /** - * Specialisation of grb::zip for void output matrices. + * Specialisation of alp::zip for void output matrices. */ - template< Descriptor descr = descriptors::no_operation, typename InputType1, typename InputType2, typename InputType3, Backend backend, typename Coords > - RC zip( Matrix< void, backend > & A, const Vector< InputType1, backend, Coords > & x, const Vector< InputType2, backend, Coords > & y ) { + template< Descriptor descr = descriptors::no_operation, typename InputType1, typename InputType2, typename InputType3, Backend backend > + RC zip( internal::Matrix< void, backend > & A, const internal::Vector< InputType1, backend > & x, const internal::Vector< InputType2, backend > & y ) { (void)x; (void)y; #ifdef _DEBUG - #ifndef _GRB_NO_STDIO - std::cerr << "Selected backend does not implement grb::zip (vectors into matrices, void)\n"; + #ifndef _ALP_NO_STDIO + std::cerr << "Selected backend does not implement alp::zip (vectors into matrices, void)\n"; #endif #endif - const RC ret = grb::clear( A ); + const RC ret = alp::clear( A ); return ret == SUCCESS ? UNSUPPORTED : ret; } @@ -162,6 +162,6 @@ namespace grb { * @} */ -} // namespace grb +} // namespace alp -#endif // end _H_GRB_BLAS3_BASE +#endif // end _H_ALP_BLAS3_BASE diff --git a/include/alp/base/collectives.hpp b/include/alp/base/collectives.hpp index 7c94c8c9c..e4e055bc4 100644 --- a/include/alp/base/collectives.hpp +++ b/include/alp/base/collectives.hpp @@ -20,20 +20,20 @@ * @date 20th of February, 2017 */ -#ifndef _H_GRB_COLL_BASE -#define _H_GRB_COLL_BASE +#ifndef _H_ALP_COLL_BASE +#define _H_ALP_COLL_BASE -#include -#include -#include +#include +#include +#include -namespace grb { +namespace alp { /** * A static class defining various collective operations on scalars. This * class is templated in terms of the backends that are implemented-- each * implementation provides its own mechanisms to handle collective - * communications. These are required for users employing grb::eWiseLambda, + * communications. These are required for users employing alp::eWiseLambda, * or for users who perform explicit SPMD programming. */ template< enum Backend implementation > @@ -68,11 +68,11 @@ namespace grb { * does \em not mean that the order of addition is fixed. * * Since each user process supplies but one value, there is no difference - * between a reduce-to-the-left versus a reduce-to-the-right (see grb::reducel - * and grb::reducer). + * between a reduce-to-the-left versus a reduce-to-the-right (see alp::reducel + * and alp::reducer). * * @tparam descr The GraphBLAS descriptor. - * Default is grb::descriptors::no_operation. + * Default is alp::descriptors::no_operation. * @tparam Operator Which operator to use for reduction. * @tparam IOType The type of the to-be reduced value. * @@ -84,15 +84,15 @@ namespace grb { * allreduce algorithm, as long as it is documented well enough so that * its cost can be quantified. * - * @returns grb::SUCCESS When the operation succeeds as planned. - * @returns grb::PANIC When the communication layer unexpectedly fails. When + * @returns alp::SUCCESS When the operation succeeds as planned. + * @returns alp::PANIC When the communication layer unexpectedly fails. When * this error code is returned, the library enters an * undefined state. * * \parblock * \par Valid descriptors: - * -# grb::descriptors::no_operation - * -# grb::descriptors::no_casting + * -# alp::descriptors::no_operation + * -# alp::descriptors::no_casting * Any other descriptors will be ignored. * \endparblock * @@ -133,11 +133,11 @@ namespace grb { * fixed. * * Since each user process supplies but one value, there is no difference - * between a reduce-to-the-left versus a reduce-to-the-right (see grb::reducel - * and grb::reducer). + * between a reduce-to-the-left versus a reduce-to-the-right (see alp::reducel + * and alp::reducer). * * @tparam descr The GraphBLAS descriptor. - * Default is grb::descriptors::no_operation. + * Default is alp::descriptors::no_operation. * @tparam Operator Which operator to use for reduction. * @tparam IOType The type of the to-be reduced value. * @@ -252,7 +252,7 @@ namespace grb { }; // end class ``collectives'' -} // end namespace grb +} // end namespace alp -#endif // end _H_GRB_COLL_BASE +#endif // end _H_ALP_COLL_BASE diff --git a/include/alp/base/config.hpp b/include/alp/base/config.hpp index 7e00e2dbd..8417f64c9 100644 --- a/include/alp/base/config.hpp +++ b/include/alp/base/config.hpp @@ -20,8 +20,8 @@ * @date 8th of August, 2016 */ -#ifndef _H_GRB_CONFIG_BASE -#define _H_GRB_CONFIG_BASE +#ifndef _H_ALP_CONFIG_BASE +#define _H_ALP_CONFIG_BASE #include //size_t #include @@ -29,16 +29,16 @@ #include #include //sysconf -#include +#include -#ifndef _GRB_NO_STDIO +#ifndef _ALP_NO_STDIO #include //std::cout #endif -// if the user did not define _GRB_BACKEND, set it to the default sequential +// if the user did not define _ALP_BACKEND, set it to the default sequential // implementation -#ifndef _GRB_BACKEND - #define _GRB_BACKEND reference +#ifndef _ALP_BACKEND + #define _ALP_BACKEND reference #endif /** @@ -46,13 +46,13 @@ * * All GraphBLAS functions and objects are defined within. */ -namespace grb { +namespace alp { /** Contains compile-time configuration constants. */ namespace config { /** The default backend to be selected for an end user. */ - static constexpr grb::Backend default_backend = _GRB_BACKEND; + static constexpr alp::Backend default_backend = _ALP_BACKEND; /** The cache line size, in bytes. */ class CACHE_LINE_SIZE { @@ -67,7 +67,7 @@ namespace grb { public: /** * @return The cache line size in bytes. - * @see grb::config::CACHE_LINE_SIZE::bytes + * @see alp::config::CACHE_LINE_SIZE::bytes */ static constexpr size_t value() { return bytes; @@ -87,7 +87,7 @@ namespace grb { public: /** * @return The SIMD size in bytes. - * @see grb::config::SIMD_SIZE::bytes + * @see alp::config::SIMD_SIZE::bytes */ static constexpr size_t value() { return bytes; @@ -211,7 +211,7 @@ namespace grb { * @returns true if and only if this function printed information to stdout. */ static bool report( const std::string prefix, const std::string action, const size_t size, const bool printNewline = true ) { -#ifdef _GRB_NO_STDIO +#ifdef _ALP_NO_STDIO (void)prefix; (void)action; (void)size; @@ -295,6 +295,6 @@ namespace grb { } // namespace config -} // namespace grb +} // namespace alp -#endif // end _H_GRB_CONFIG_BASE +#endif // end _H_ALP_CONFIG_BASE diff --git a/include/alp/base/exec.hpp b/include/alp/base/exec.hpp index 19e800e80..a79a1578c 100644 --- a/include/alp/base/exec.hpp +++ b/include/alp/base/exec.hpp @@ -20,19 +20,19 @@ * @date 17th of April, 2017 */ -#ifndef _H_GRB_EXEC_BASE -#define _H_GRB_EXEC_BASE +#ifndef _H_ALP_EXEC_BASE +#define _H_ALP_EXEC_BASE #include #include -#include -#include -#ifndef _GRB_NO_STDIO +#include +#include +#ifndef _ALP_NO_STDIO #include #endif -namespace grb { +namespace alp { /** * The various ways in which the #Launcher can be used @@ -75,7 +75,7 @@ namespace grb { * same type. For implementations that support multiple user processes, the * caller may explicitly set the process ID and total number of user processes. * - * The intended use is to `just call' grb::exec which should, in its most + * The intended use is to `just call' alp::exec which should, in its most * trivial form, compile regardless of which backend is selected. * * @tparam mode Which #EXEC_MODE the Launcher should adhere to. @@ -128,7 +128,7 @@ namespace grb { // so accept (and ignore) anything (void)hostname; (void)port; -#ifndef _GRB_NO_EXCEPTIONS +#ifndef _ALP_NO_EXCEPTIONS // sanity checks on process_id and nprocs if( nprocs == 0 ) { throw std::invalid_argument( "Total number of user " "processes must be " @@ -139,21 +139,21 @@ namespace grb { "total number of user processes." ); } #endif -} // namespace grb +} // namespace alp /** * Executes the given GraphBLAS program. This function, depending on whether * GraphBLAS is compiled in automatic or in manual mode, will either * \em spawn the maximum number of available user processes or will connect * exactly \a nprocs existing processes, respectively, to execute the given - * \a grb_program. + * \a alp_program. * * This is a collective function call. * * @tparam T The type of the data to pass to the GraphBLAS program. * @tparam U The type of the output data to pass back to the user. * - * @param[in] grb_program User GraphBLAS program to be executed. + * @param[in] alp_program User GraphBLAS program to be executed. * @param[in] data_in Input data of user-defined type \a T. * When in automatic mode, the data will only be * available at user process 0 only. When in @@ -179,11 +179,11 @@ namespace grb { * All aforementioned default values shall always be legal. */ template< typename T, typename U > -RC exec( void ( *grb_program )( const T &, U & ), // user GraphBLAS program +RC exec( void ( *alp_program )( const T &, U & ), // user GraphBLAS program const T & data_in, U & data_out, // input & output data const bool broadcast = false ) const { - (void)grb_program; + (void)alp_program; (void)data_in; (void)data_out; (void)broadcast; @@ -205,8 +205,8 @@ RC exec( void ( *grb_program )( const T &, U & ), // user GraphBLAS program * \todo more documentation */ template< typename U > -RC exec( void ( *grb_program )( const void *, const size_t, U & ), const void * data_in, const size_t in_size, U & data_out, const bool broadcast = false ) const { - (void)grb_program; +RC exec( void ( *alp_program )( const void *, const size_t, U & ), const void * data_in, const size_t in_size, U & data_out, const bool broadcast = false ) const { + (void)alp_program; (void)data_in; (void)in_size; (void)data_out; @@ -226,6 +226,6 @@ static RC finalize() { } ; // end class `Launcher' -} // end namespace ``grb'' +} // end namespace ``alp'' -#endif // end _H_GRB_EXEC_BASE +#endif // end _H_ALP_EXEC_BASE diff --git a/include/alp/base/init.hpp b/include/alp/base/init.hpp index 1c7efd9e8..b40093cf2 100644 --- a/include/alp/base/init.hpp +++ b/include/alp/base/init.hpp @@ -20,14 +20,14 @@ * @date 24th of January, 2017 */ -#ifndef _H_GRB_INIT_BASE -#define _H_GRB_INIT_BASE +#ifndef _H_ALP_INIT_BASE +#define _H_ALP_INIT_BASE -#include +#include #include "config.hpp" -namespace grb { +namespace alp { /** * Initialises the calling user process. @@ -50,15 +50,15 @@ namespace grb { * call to this function with an empty parameter list shall then be legal * and infer the following default arguments: zero for \a s, one for \a P, * and \a NULL for \a implementation_data. When such an implementation is - * requested to initialise multiple user processes, the grb::UNSUPPORTED + * requested to initialise multiple user processes, the alp::UNSUPPORTED * error code shall be returned. * - * A call to this function must be matched with a call to grb::finalize(). - * After a successful call to this function, a new call to grb::init() without - * first calling grb::finalize() shall incur undefined behaviour. The + * A call to this function must be matched with a call to alp::finalize(). + * After a successful call to this function, a new call to alp::init() without + * first calling alp::finalize() shall incur undefined behaviour. The * construction of GraphBLAS containers without a preceding successful call - * to grb::init() will result in invalid GraphBLAS objects. Any valid - * GraphBLAS containers will become invalid after a call to grb::finalize(). + * to alp::init() will result in invalid GraphBLAS objects. Any valid + * GraphBLAS containers will become invalid after a call to alp::finalize(). * Any use of GraphBLAS functions on invalid containers will result in * undefined behaviour. * @@ -105,7 +105,7 @@ namespace grb { * the C API when properly wrapped. * \note Non-blocking mode with clear performance semantics are possible via * carefully designed algorithmic skeletons. This is future work. - * \note This specification allows for grb::init() to be called multiple + * \note This specification allows for alp::init() to be called multiple * times from the same process and the same thread, as long as all the * above requirements are met at each call. The parameters \a s and * \a P (and \a implementation_data) may differ each time. @@ -128,7 +128,7 @@ namespace grb { * values regarding user processes etc. should still result in a successful * initialisation in all cases except where it cannot initialise due to * external factors. - * A call to this function could, for instance, reduce to a full grb::init() + * A call to this function could, for instance, reduce to a full alp::init() * while using the default parameters 0 for \a s, 1 for \a P, and \a NULL for * \a implementation_data: * \code @@ -143,21 +143,21 @@ namespace grb { */ template< enum Backend backend = config::default_backend > RC init() { - return grb::init< backend >( 0, 1, NULL ); + return alp::init< backend >( 0, 1, NULL ); } /** - * Finalises a graphBLAS context opened by the last call to grb::init(). + * Finalises a graphBLAS context opened by the last call to alp::init(). * * This function must be called collectively and must follow a call to - * grb::init(). After successful execution of this function, a new call - * to grb::init() may be made. + * alp::init(). After successful execution of this function, a new call + * to alp::init() may be made. * After a call to this function, any graphBLAS objects that remain in scope * are invalid. The only graphBLAS functions on invalid containers which * shall \em not incur undefined behaviour are their destructors. * * \warning Invalid GraphBLAS containers will remain invalid no matter if a - * next call to grb::init() is made. + * next call to alp::init() is made. * * @tparam backend Which GraphBLAS backend this call to init initialises. * @@ -166,18 +166,18 @@ namespace grb { * implementation becomes undefined. This means none of its * functions should be called during the remainder program * execution; in particular this means a new call to - * grb::init() will not remedy the situaiton. + * alp::init() will not remedy the situaiton. * * \par Performance semantics * None. Implementations are encouraged to specify the complexity of * their implementation of this function in terms of the parameter - * \a P the matching call to grb::init() was called with. + * \a P the matching call to alp::init() was called with. */ template< enum Backend backend = config::default_backend > RC finalize() { return PANIC; } -} // namespace grb +} // namespace alp -#endif // end _H_GRB_INIT_BASE +#endif // end _H_ALP_INIT_BASE diff --git a/include/alp/base/internalops.hpp b/include/alp/base/internalops.hpp index 5c236de86..f44c7ad4d 100644 --- a/include/alp/base/internalops.hpp +++ b/include/alp/base/internalops.hpp @@ -20,25 +20,25 @@ * @date 8th of August, 2016 */ -#ifndef _H_GRB_INTERNAL_OPERATORS_BASE -#define _H_GRB_INTERNAL_OPERATORS_BASE +#ifndef _H_ALP_INTERNAL_OPERATORS_BASE +#define _H_ALP_INTERNAL_OPERATORS_BASE -#include +#include #include #include -#include -#include +#include +#include #include "config.hpp" -namespace grb { +namespace alp { namespace operators { - /** Core implementations of the standard operators in #grb::operators. */ + /** Core implementations of the standard operators in #alp::operators. */ namespace internal { /** @@ -639,10 +639,10 @@ namespace grb { const right_type * __restrict__ const b, result_type * __restrict__ const c ) { - GRB_UTIL_IGNORE_MAYBE_UNINITIALIZED // this is a (too) broad suppression-- + ALP_UTIL_IGNORE_MAYBE_UNINITIALIZED // this is a (too) broad suppression-- // see internal issue 306 for rationale *c = *a + *b; - GRB_UTIL_RESTORE_WARNINGS + ALP_UTIL_RESTORE_WARNINGS } /** @@ -743,10 +743,10 @@ namespace grb { const right_type * __restrict__ const b, result_type * __restrict__ const c ) { - GRB_UTIL_IGNORE_MAYBE_UNINITIALIZED // this is a (too) broad suppression-- + ALP_UTIL_IGNORE_MAYBE_UNINITIALIZED // this is a (too) broad suppression-- // see internal issue 306 for rationale *c = *a * *b; - GRB_UTIL_RESTORE_WARNINGS + ALP_UTIL_RESTORE_WARNINGS } /** @@ -1285,14 +1285,14 @@ namespace grb { * At the end of the operation, \f$ c = \min\{a,b\} \f$. */ static void apply( const left_type * __restrict__ const a, const right_type * __restrict__ const b, result_type * __restrict__ const c ) { - GRB_UTIL_IGNORE_MAYBE_UNINITIALIZED // this is a (too) broad suppression-- + ALP_UTIL_IGNORE_MAYBE_UNINITIALIZED // this is a (too) broad suppression-- // see internal issue 306 for rationale if( *a != *b ) { *c = static_cast< OUT >( true ); } else { *c = static_cast< OUT >( false ); } - GRB_UTIL_RESTORE_WARNINGS + ALP_UTIL_RESTORE_WARNINGS } /** @@ -1830,8 +1830,8 @@ namespace grb { protected: /** The block size that should be used during map-like operations. */ - static constexpr size_t blocksize = grb::utils::static_min( grb::config::SIMD_BLOCKSIZE< typename OP::left_type >::value(), - grb::utils::static_min( grb::config::SIMD_BLOCKSIZE< typename OP::right_type >::value(), grb::config::SIMD_BLOCKSIZE< typename OP::result_type >::value() ) ); + static constexpr size_t blocksize = alp::utils::static_min( alp::config::SIMD_BLOCKSIZE< typename OP::left_type >::value(), + alp::utils::static_min( alp::config::SIMD_BLOCKSIZE< typename OP::right_type >::value(), alp::config::SIMD_BLOCKSIZE< typename OP::result_type >::value() ) ); /** The left-hand side input domain. */ typedef typename OP::left_type D1; @@ -2237,7 +2237,7 @@ namespace grb { * * \warning The first casting behaviour may not be what you want. The two * other casting behaviours are allowed by the GraphBLAS unless - * the grb::descriptor::no_casting is given. + * the alp::descriptor::no_casting is given. * * \note By default, this GraphBLAS implementation will only use this * code when \a D2 matches \a D3 and OP::has_foldr is \a true. @@ -2261,7 +2261,7 @@ namespace grb { template< typename InputType1, typename InputType2, typename OutputType > static void eWiseApply( const InputType1 * x, const InputType2 * y, OutputType * __restrict__ z, const size_t n ) { #ifdef _DEBUG -#ifdef D_GRB_NO_STDIO +#ifdef D_ALP_NO_STDIO std::cout << "In OperatorFR::eWiseApply\n"; #endif #endif @@ -2708,7 +2708,7 @@ namespace grb { * * \warning The first casting behaviour may not be what you want. The two * other casting behaviours are allowed by the GraphBLAS unless - * the grb::descriptor::no_casting is given. + * the alp::descriptor::no_casting is given. * * \note By default, this GraphBLAS implementation will only use this * code when \a D1 matches \a D3 and OP::has_foldr is \a true. @@ -2734,7 +2734,7 @@ namespace grb { template< typename InputType1, typename InputType2, typename OutputType > static void eWiseApply( const InputType1 * x, const InputType2 * y, OutputType * __restrict__ z, const size_t n ) { #ifdef _DEBUG -#ifdef D_GRB_NO_STDIO +#ifdef D_ALP_NO_STDIO std::cout << "In OperatorNoFR::eWiseApply\n"; #endif #endif @@ -2874,10 +2874,10 @@ namespace grb { * writing them back to \a z. * * \note The GraphBLAS can explicitly control all \em three of this - * casting behaviours via grb::descriptors::no_casting. + * casting behaviours via alp::descriptors::no_casting. * * \warning With the in-place variants of this code, unwanted behaviour - * cannot be prevented by use of grb::descriptors::no_casting. + * cannot be prevented by use of alp::descriptors::no_casting. * Therefore the current implementation only calls the in-place * variants when \a D1 equals \a D3 (for foldl-based in-place), * or when \a D2 equals \a D3 (for foldr-based ones). @@ -2899,7 +2899,7 @@ namespace grb { template< typename InputType1, typename InputType2, typename OutputType > static void eWiseApply( const InputType1 * x, const InputType2 * y, OutputType * __restrict__ z, const size_t n ) { #ifdef _DEBUG -#ifdef D_GRB_NO_STDIO +#ifdef D_ALP_NO_STDIO std::cout << "In OperatorNoFRFL::eWiseApply\n"; #endif #endif @@ -2951,7 +2951,7 @@ namespace grb { * While very easily possible to create non-associative operators * using this interface, passing them to GraphBLAS functions, * either explicitly or indirectly (by, e.g., including them in a - * grb::Monoid or grb::Semiring), will lead to undefined + * alp::Monoid or alp::Semiring), will lead to undefined * behaviour. * * This class wraps around a base operator of type \a OP we denote by @@ -2986,8 +2986,8 @@ namespace grb { * \f$ z \in D_1 \subseteq D_3 \f$ and \f$ y \in D_2 \f$ and stores in * \a z the result of \f$ z \odot y \f$. * - * For examples of these base operators, see grb::operators::internal::max - * or grb::operators::internal::mul. An example of a full implementation, + * For examples of these base operators, see alp::operators::internal::max + * or alp::operators::internal::mul. An example of a full implementation, * in this case for numerical addition, is the following: * * \snippet internalops.hpp Example Base Operator Implementation @@ -3055,7 +3055,7 @@ namespace grb { * * New operators are easily added to this * GraphBLAS implementation by providing a base operator and wrapping this - * class around it, as illustrated, e.g., by grb::operators::add as follows: + * class around it, as illustrated, e.g., by alp::operators::add as follows: * * \snippet ops.hpp Operator Wrapping * @@ -3174,7 +3174,7 @@ namespace grb { } // namespace operators -} // namespace grb +} // namespace alp -#endif // _H_GRB_INTERNAL_OPERATORS_BASE +#endif // _H_ALP_INTERNAL_OPERATORS_BASE diff --git a/include/alp/base/io.hpp b/include/alp/base/io.hpp index 8bb2d4c90..52cfc3930 100644 --- a/include/alp/base/io.hpp +++ b/include/alp/base/io.hpp @@ -20,17 +20,17 @@ * @date 21st of February, 2017 */ -#ifndef _H_GRB_IO_BASE -#define _H_GRB_IO_BASE +#ifndef _H_ALP_IO_BASE +#define _H_ALP_IO_BASE -#include -#include -#include +#include +#include +#include #include "matrix.hpp" #include "vector.hpp" -namespace grb { +namespace alp { /** * \defgroup IO Data Ingestion and Extraction. @@ -38,26 +38,26 @@ namespace grb { * and provides functions for extracting data from opaque GraphBLAS objects. * * The GraphBLAS operates on opaque data objects. Users can input data using - * grb::buildVector and/or grb::buildMatrixUnique. This group provides free + * alp::buildVector and/or alp::buildMatrixUnique. This group provides free * functions that automatically dispatch to those variants. * - * The standard output methods are provided by grb::Vector::cbegin and - * grb::Vector::cend, and similarly for grb::Matrix. Iterators provide + * The standard output methods are provided by alp::Vector::cbegin and + * alp::Vector::cend, and similarly for alp::Matrix. Iterators provide * parallel output (see #IOMode for a discussion on parallel versus * sequential IO). * * Sometimes it is desired to have direct access to a GraphBLAS memory * area, and to have that memory available even after the GraphBLAS - * context has been closed (via grb::finalize). This functionality is - * provided by grb::pin_memory. + * context has been closed (via alp::finalize). This functionality is + * provided by alp::pin_memory. * * @{ */ /** - * Constructs a dense vector from a container of exactly grb::size(x) + * Constructs a dense vector from a container of exactly alp::size(x) * elements. This function aliases to the buildVector routine that takes - * an accumulator, using grb::operators::right_assign (thus overwriting + * an accumulator, using alp::operators::right_assign (thus overwriting * any old contents). */ template< @@ -66,7 +66,7 @@ namespace grb { Backend backend, typename Coords > RC buildVector( - Vector< InputType, backend, Coords > &x, + internal::Vector< InputType, backend > &x, fwd_iterator start, const fwd_iterator end, const IOMode mode ) { @@ -77,7 +77,7 @@ namespace grb { /** * Ingests possibly sparse input from a container to which iterators are * provided. This function dispatches to the buildVector routine that - * includes an accumulator, here set to grb::operators::right_assign. + * includes an accumulator, here set to alp::operators::right_assign. * Any existing values in \a x that overlap with newer values will hence * be overwritten. */ @@ -87,7 +87,7 @@ namespace grb { typename fwd_iterator1, typename fwd_iterator2, Backend backend, typename Coords > - RC buildVector( Vector< InputType, backend, Coords > & x, + RC buildVector( internal::Vector< InputType, backend > & x, fwd_iterator1 ind_start, const fwd_iterator1 ind_end, fwd_iterator2 val_start, const fwd_iterator2 val_end, const IOMode mode, const Merger & merger = Merger() @@ -147,9 +147,9 @@ namespace grb { * is \f$ (p-1)g + l \f$. * \endparblock * - * @returns grb::SUCCESS When ingestion has completed successfully. - * @returns grb::ILLEGAL When a nonzero has an index larger than grb::size(x). - * @returns grb::PANIC If an unmitigable error has occured during ingestion. + * @returns alp::SUCCESS When ingestion has completed successfully. + * @returns alp::ILLEGAL When a nonzero has an index larger than alp::size(x). + * @returns alp::PANIC If an unmitigable error has occured during ingestion. */ template< Descriptor descr = descriptors::no_operation, typename InputType, @@ -157,7 +157,7 @@ namespace grb { typename fwd_iterator1, typename fwd_iterator2, Backend backend, typename Coords > - RC buildVectorUnique( Vector< InputType, backend, Coords > & x, + RC buildVectorUnique( internal::Vector< InputType, backend > & x, fwd_iterator1 ind_start, const fwd_iterator1 ind_end, fwd_iterator2 val_start, const fwd_iterator2 val_end, const IOMode mode @@ -180,7 +180,7 @@ namespace grb { * lead to undefined behaviour. * * @tparam descr The descriptor used. The default is - * #grb::descriptors::no_operation, which means that + * #alp::descriptors::no_operation, which means that * no pre- or post-processing of input or input is * performed. * @tparam fwd_iterator1 The type of the row index iterator. @@ -195,7 +195,7 @@ namespace grb { * @param[in] V A forward iterator to \a cap nonzero values. * @param[in] nz The number of items pointed to by \a I, \a J, \em and \a V. * - * @return grb::MISMATCH -# when an element from \a I dereferences to a value + * @return alp::MISMATCH -# when an element from \a I dereferences to a value * larger than the row dimension of this matrix, or * -# when an element from \a J dereferences to a value * larger than the column dimension of this matrix. @@ -204,7 +204,7 @@ namespace grb { * called; however, the given forward iterators may * have been copied and the copied iterators may have * incurred multiple increments and dereferences. - * @return grb::OVERFLW When the internal data type used for storing the + * @return alp::OVERFLW When the internal data type used for storing the * number of nonzeroes is not large enough to store * the number of nonzeroes the user wants to assign. * When this error code is returned the state of this @@ -212,7 +212,7 @@ namespace grb { * called; however, the given forward iterators may * have been copied and the copied iterators may have * incurred multiple increments and dereferences. - * @return grb::SUCCESS When the function completes successfully. + * @return alp::SUCCESS When the function completes successfully. * * \parblock * \par Performance semantics. @@ -257,7 +257,7 @@ namespace grb { typename length_type = size_t, Backend implementation = config::default_backend > RC buildMatrixUnique( - Matrix< InputType, implementation > & A, + internal::Matrix< InputType, implementation > & A, fwd_iterator1 I, fwd_iterator1 I_end, fwd_iterator2 J, fwd_iterator2 J_end, fwd_iterator3 V, fwd_iterator3 V_end, @@ -282,7 +282,7 @@ namespace grb { typename fwd_iterator3 = const InputType * __restrict__, typename length_type = size_t, Backend implementation = config::default_backend > - RC buildMatrixUnique( Matrix< InputType, implementation > &A, + RC buildMatrixUnique( internal::Matrix< InputType, implementation > &A, fwd_iterator1 I, fwd_iterator2 J, fwd_iterator3 V, const size_t nz, const IOMode mode ) { @@ -301,7 +301,7 @@ namespace grb { typename fwd_iterator2 = const size_t * __restrict__, typename length_type = size_t, Backend implementation = config::default_backend > - RC buildMatrixUnique( Matrix< InputType, implementation > & A, fwd_iterator1 I, fwd_iterator2 J, const length_type nz, const IOMode mode ) { + RC buildMatrixUnique( internal::Matrix< InputType, implementation > & A, fwd_iterator1 I, fwd_iterator2 J, const length_type nz, const IOMode mode ) { // derive synchronized iterator auto start = utils::makeSynchronized( I, J, I + nz, J + nz ); const auto end = utils::makeSynchronized( I + nz, J + nz, I + nz, J + nz ); @@ -342,7 +342,7 @@ namespace grb { * -# fwd_iterator::nonzero_value_type * * This means a specialised iterator is required for use with this function. - * See, for example, grb::utils::internal::MatrixFileIterator. + * See, for example, alp::utils::internal::MatrixFileIterator. * * @param[out] A The matrix to be filled with nonzeroes from \a start to * \a end. @@ -354,7 +354,7 @@ namespace grb { typename InputType, typename fwd_iterator, Backend implementation = config::default_backend > - RC buildMatrixUnique( Matrix< InputType, implementation > & A, + RC buildMatrixUnique( internal::Matrix< InputType, implementation > & A, fwd_iterator start, const fwd_iterator end, const IOMode mode ) { @@ -367,7 +367,7 @@ namespace grb { /** @} */ -} // namespace grb +} // namespace alp -#endif // end _H_GRB_IO_BASE +#endif // end _H_ALP_IO_BASE diff --git a/include/alp/base/matrix.hpp b/include/alp/base/matrix.hpp index f0f8b60cc..8e125e0c8 100644 --- a/include/alp/base/matrix.hpp +++ b/include/alp/base/matrix.hpp @@ -20,8 +20,8 @@ * @date 10th of August */ -#ifndef _H_GRB_MATRIX_BASE -#define _H_GRB_MATRIX_BASE +#ifndef _H_ALP_MATRIX_BASE +#define _H_ALP_MATRIX_BASE #include #include @@ -29,484 +29,486 @@ #include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace grb { - - /** - * A GraphBLAS matrix. - * - * This is an opaque data type that implements the below functions. - * - * @tparam D The type of a nonzero element. \a D shall not be a GraphBLAS - * type. - * @tparam implementation Allows multiple backends to implement different - * versions of this data type. - * - * \warning Creating a grb::Matrix of other GraphBLAS types is - * not allowed. - * Passing a GraphBLAS type as template parameter will lead to - * undefined behaviour. - */ - template< typename D, enum Backend implementation > +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace alp { + + namespace internal { + /** + * A GraphBLAS matrix. + * + * This is an opaque data type that implements the below functions. + * + * @tparam D The type of a nonzero element. \a D shall not be a GraphBLAS + * type. + * @tparam implementation Allows multiple backends to implement different + * versions of this data type. + * + * \warning Creating a alp::Matrix of other GraphBLAS types is + * not allowed. + * Passing a GraphBLAS type as template parameter will lead to + * undefined behaviour. + */ + template< typename D, enum Backend implementation > + class Matrix { + + typedef Matrix< D, implementation > self_type; + + public : + + /** + * A standard iterator for a GraphBLAS aatrix. + * + * This iterator is used for data extraction only. Hence only this const + * version is specified. + * + * Dereferencing an iterator of this type that is not in end position yields + * a pair \f$ (c,v) \f$. The value \a v is of type \a D and corresponds to + * the value of the dereferenced nonzero. + * The value \a c is another pair \f$ (i,j) \f$. The values \a i and \a j + * are of type size_t and correspond to the coordinate of the + * dereferenced nonzero. + * + * \note `Pair' here corresponds to the regular std::pair. + * + * \warning Comparing two const iterators corresponding to different + * containers leads to undefined behaviour. + * \warning Advancing an iterator past the end iterator of the container + * it corresponds to, leads to undefined behaviour. + * \warning Modifying the contents of a container makes any use of any + * iterator derived from it incur invalid behaviour. + * \note These are standard limitations of STL iterators. + */ + class const_iterator : public std::iterator< std::forward_iterator_tag, std::pair< std::pair< const size_t, const size_t >, const D >, size_t > { + + public : + + /** Standard equals operator. */ + bool + operator==( const const_iterator & other ) const { (void)other; return false; } + + /** @returns The negation of operator==(). */ + bool operator!=( const const_iterator & other ) const { + (void)other; + return true; + } + + /** + * Dereferences the current position of this iterator. + * + * @return If this iterator is valid and not in end position, this returns + * an std::pair with in its first field the position of the + * nonzero value, and in its second field the value of the nonzero. + * The position of a nonzero is another std::pair with both the + * first and second field of type size_t. + * + * \note If this iterator is invalid or in end position, the result is + * undefined. + */ + std::pair< const size_t, const D > operator*() const { + return std::pair< const size_t, const D >(); + } + + /** + * Advances the position of this iterator by one. + * + * If the current position corresponds to the last element in the + * container, the new position of this iterator will be its end + * position. + * + * If the current position of this iterator is already the end + * position, this iterator will become invalid; any use of invalid + * iterators will lead to undefined behaviour. + * + * @return A reference to this iterator. + */ + const_iterator & operator++() { + return *this; + } + + }; // class const_iterator + + /** The value type of elements stored in this matrix. */ + typedef D value_type; + + /** + * The main GraphBLAS matrix constructor. + * + * Matrix nonzeroes will be uninitalised after successful construction. + * + * Requesting a matrix with zero \a rows or \a columns will yield an empty + * matrix; i.e., it will be useless but will not result in an error. + * + * @param rows The number of rows in the new matrix. + * @param columns The number of columns in the new matrix. + * + * @return SUCCESS This function never fails. + * + * \parblock + * \par Performance semantics. + * -# This constructor completes in \f$ \Theta(1) \f$ time. + * -# This constructor will not allocate any new dynamic memory. + * -# This constructor will use \f$ \Theta(1) \f$ extra bytes of + * memory beyond that at constructor entry. + * -# This constructor incurs \f$ \Theta(1) \f$ data movement. + * -# This constructor \em may make system calls. + * \endparblock + * + * \warning Avoid the use of this constructor within performance critical + * code sections. + */ + Matrix( const size_t rows, const size_t columns ) { + (void)rows; + (void)columns; + } + + /** + * Copy constructor. + * + * @param other The matrix to copy. + * + * \parblock + * \par Performance semantics. + * Allocates the same capacity as the \a other matrix, even if the + * actual number of nonzeroes contained in \a other is less. + * -# This constructor entails \f$ \Theta(\mathit{nz}) \f$ amount of + * work. + * -# This constructor allocates \f$ \Theta(\mathit{nz}) \f$ bytes + * of dynamic memory. + * -# This constructor incurs \f$ \Theta(\mathit{nz}) \f$ of data + * movement. + * -# This constructor \em may make system calls. + * \endparblock + * + * \warning Avoid the use of this constructor within performance critical + * code sections. + */ + Matrix( const Matrix< D, implementation > & other ) { + (void)other; + } + + /** + * Move constructor. This will make the new matrix equal to the given + * GraphBLAS matrix while destroying the given matrix. + * + * @param[in] other The GraphBLAS matrix to move to this new instance. + * + * \parblock + * \par Performance semantics. + * -# This constructor entails \f$ \Theta(1) \f$ amount of work. + * -# This constructor will not allocate any new dynamic memory. + * -# This constructor will use \f$ \Theta(1) \f$ extra bytes of + * memory beyond that at constructor entry. + * -# This constructor will move \f$ \Theta(1) \f$ bytes of data. + * \endparblock + */ + Matrix( self_type && other ) { + (void)other; + } + + /** + * Matrix destructor. + * + * \parblock + * \par Performance semantics. + * -# This destructor entails \f$ \Theta(1) \f$ amount of work. + * -# This destructor will not perform any memory allocations. + * -# This destructor will use \f$ \mathcal{O}(1) \f$ extra bytes of + * memory beyond that at constructor entry. + * -# This destructor will move \f$ \Theta(1) \f$ bytes of data. + * -# This destructor makes system calls. + * \endparblock + * + * \warning Avoid calling destructors from within performance critical + * code sections. + */ + ~Matrix() {} + + /** + * Assigns nonzeroes to the matrix from a coordinate format. + * + * Any prior content may be combined with new input according to the + * user-supplied accumulator operator (\a accum). + * + * Input triplets need not be unique. Input triplets that are written to the + * same row and column coordinates will be combined using the supplied + * duplicate operator (\a dup). + * + * \note Note that \a dup and \a accum may differ. The duplicate operator is + * \em not applied to any pre-existing nonzero values. + * + * \note The order of application of the operators is undefined. + * + * The number of nonzeroes, after reduction by duplicate removals and after + * merger with the existing nonzero structure, must be equal or less than the + * space reserved during the construction of this matrix. The nonzeroes will + * not be stored in a fully sorted fashion-- it will be sorted column-wise, + * but within each column the order can be arbitrary. + * + * @tparam accum How existing entries of this matrix should be + * treated. + * The default is #alp::operators::right_assign, which + * means that any existing values are overwritten with + * the new values. + * @tparam dup How to handle duplicate entries. The default is + * #alp::operators::add, which means that duplicated + * values are combined by addition. + * @tparam descr The descriptor used. The default is + * #alp::descriptors::no_operation, which means that + * no pre- or post-processing of input or input is + * performed. + * @tparam fwd_iterator1 The type of the row index iterator. + * @tparam fwd_iterator2 The type of the column index iterator. + * @tparam fwd_iterator3 The type of the nonzero value iterator. + * @tparam length_type The type of the number of elements in each iterator. + * @tparam T The type of the supplied mask. + * + * \note By default, the iterator types are raw, unaliased, pointers. + * + * \warning This means that by default, input arrays are \em not + * allowed to overlap. + * + * Forward iterators will only be used to read from, never to assign to. + * + * \note It is therefore both legal and preferred to pass constant forward + * iterators, as opposed to mutable ones as \a I, \a J, and \a V. + * + * @param[in] I A forward iterator to \a cap row indices. + * @param[in] J A forward iterator to \a cap column indices. + * @param[in] V A forward iterator to \a cap nonzero values. + * @param[in] nz The number of items pointed to by \a I, \a J, \em and + * \a V. + * @param[in] mask An input element at coordinate \f$ (i,j) \f$ will only be + * added to this matrix if there exists a matching element + * \f$ \mathit{mask}_{ij} \f$ in the given \a mask that + * eveluates true. The matrix in \a mask must be + * of the same dimension as this matrix. + * + * @return alp::MISMATCH -# when an element from \a I dereferences to a value + * larger than the row dimension of this matrix, or + * -# when an element from \a J dereferences to a value + * larger than the column dimension of this matrix. + * When this error code is returned the state of this + * container will be as though this function was never + * called; however, the given forward iterators may + * have been copied and the copied iterators may have + * incurred multiple increments and dereferences. + * @return alp::OVERFLW When the internal data type used for storing the + * number of nonzeroes is not large enough to store + * the number of nonzeroes the user wants to assign. + * When this error code is returned the state of this + * container will be as though this function was never + * called; however, the given forward iterators may + * have been copied and the copied iterators may have + * incurred multiple increments and dereferences. + * @return alp::SUCCESS When the function completes successfully. + * + * \parblock + * \par Performance semantics. + * -# This function contains + * \f$ \Theta(\mathit{nz}\log\mathit{nz})+\mathcal{O}(m+n)) \f$ + * amount of work. + * -# This function may dynamically allocate + * \f$ \Theta(\mathit{nz})+\mathcal{O}(m+n)) \f$ bytes of memory. + * -# A call to this function will use \f$ \mathcal{O}(m+n) \f$ bytes + * of memory beyond the memory in use at the function call entry. + * -# This function will copy each input forward iterator at most + * \em twice; the three input iterators \a I, \a J, and \a V thus + * may have exactly two copies each, meaning that all input may be + * traversed \em twice. + * -# Each of the at most six iterator copies will be incremented at + * most \f$ \mathit{nz} \f$ times. + * -# Each position of the each of the at most six iterator copies + * will be dereferenced exactly once. + * -# This function moves + * \f$ \Theta(\mathit{nz})+\mathcal{O}(m+n)) \f$ bytes of data. + * -# If the mask is nonempty, the performance costs of alp::eWiseMul + * on two matrix arguments must be added to the above costs. + * -# This function will likely make system calls. + * \endparblock + * + * \warning This is an extremely expensive function. Use sparingly and only + * when absolutely necessary + * + * \note Streaming input can be implemented by supplying buffered + * iterators to this GraphBLAS implementation. + */ + template< Descriptor descr = descriptors::no_operation, + template< typename, typename, typename > class accum = operators::right_assign, + template< typename, typename, typename > class dup = operators::add, + typename fwd_iterator1 = const size_t * __restrict__, + typename fwd_iterator2 = const size_t * __restrict__, + typename fwd_iterator3 = const D * __restrict__, + typename length_type = size_t, + typename T > + RC buildMatrix( const fwd_iterator1 I, const fwd_iterator2 J, const fwd_iterator3 V, const length_type nz, const Matrix< T, implementation > & mask ) { + (void)I; + (void)J; + (void)V; + (void)nz; + (void)mask; + return PANIC; + } + + //@{ + /** + * Provides the only mechanism to extract data from a GraphBLAS matrix. + * + * The order in which nonzero elements are returned is undefined. + * + * @return An iterator pointing to the first element of this matrix, if any; + * \em or an iterator in end position if this vector contains no + * nonzeroes. + * + * \note An `iterator in end position' compares equal to the const_iterator + * returned by cend(). + * + * \parblock + * \par Performance semantics + * -# This function contains \f$ \mathcal{O}(1) \f$ work. + * -# This function is allowed allocate dynamic memory. + * -# This function uses up to \f$ \mathcal{O}(1) \f$ more memory + * than already used by this application at entry. + * -# This function shall move at most \f$ \mathcal{O}(1) \f$ bytes + * of data. + * -# This function may make system calls. + * \endparblock + * + * \warning Avoid the use of this function within performance critical code + * sections. + * + * \note This function may make use of a const_iterator that is buffered, + * hence possibly causing its implicitly called constructor to + * allocate dynamic memory. + */ + const_iterator cbegin() const {} + + /** + * Same as cbegin(). + * Since iterators are only supplied as a data extraction mechanism, there + * is no overloaded version of this function that returns a non-const + * iterator. + */ + const_iterator begin() const {} + //@} + + //@{ + /** + * Indicates the end to the elements in this container. + * + * @return An iterator at the end position of this container. + * + * \parblock + * \par Performance semantics + * -# This function contains \f$ \mathcal{O}(1) \f$ work. + * -# This function is not allowed allocate dynamic memory. + * -# This function uses up to \f$ \mathcal{O}(1) \f$ more memory + * than already used by this application at entry. + * -# This function shall move at most \f$ \mathcal{O}(1) \f$ bytes + * of data. + * -# This function shall \em not induce any system calls. + * \endparblock + * + * \note Even if cbegin() returns a buffered const_iterator that may require + * dynamic memory allocation and additional data movement, this + * specification disallows the same to happen for the construction of + * an iterator in end position. + */ + const_iterator cend() const {} + + /** + * Same as cend(). + * Since iterators are only supplied as a data extraction mechanism, there + * is no overloaded version of this function that returns a non-const + * iterator. + */ + const_iterator end() const {} + //@} + + template< typename InputType, Backend backend > + RC clear( Matrix< InputType, backend > & A ) noexcept { + // this is the generic stub implementation + return UNSUPPORTED; + } + }; // class Matrix + } // namespace internal + + + template< typename T, typename Structure, enum Density density, typename View, enum Backend backend > class Matrix { - typedef Matrix< D, implementation > self_type; + /** + * The two following members define the \em logical layout of a structured matrix: + * Its structure and access relations. This is enabled only if the structured matrix + * does not define a View on another matrix. + */ + using structure = Structure; + /** + * A pair of pointers to index mapping functions (see imf.hpp) that express the + * logical access to the structured matrix. + */ + std::shared_ptr imf_l, imf_r; + + /** + * When a structured matrix instanciate a \em container it defines a new \em physical + * (concrete?) layout. This is characterized by an ALP container (aka an \a internal::Matrix) and a + * storage scheme that defines a unique interpretation of its content. + * The combination of the logical and physical layout of a structured matrix enables to + * identify a precise mapping between an element in the structured matrix and a position + * wihtin one or more 1/2D-arrays that store it. + */ + internal::Matrix< T, reference > * _container; + + /** + * A container's storage scheme. \a storage_scheme is not exposed to the user as an option + * but can defined by ALP at different points in the execution depending on the \a backend choice. + * For example, if the container is associated to an I/O matrix, with a reference backend + * it might be set to reflect the storage scheme of the user data as specified at buildMatrix. + * If \a backend is set to \a mlir then the scheme could be fixed by the JIT compiler to effectively + * support its optimization strategy. + * At construction time and until the moment the scheme decision is made it may be set to + * an appropriate default choice, e.g. if \a density is \a Density::Dense then + * \a Density::Dense::full could be used. + * \internal \todo Revisit this. The change of storage scheme type to enum (dense/sparse) and + * implementing storage mapping functions requires a change of this spec. + */ + // Storage storage_scheme; + + /** + * When a structured matrix defines a View over another matrix, it contains a pointer + * to the latter. Its type can be identified via the View parameter. + */ + using target_type = typename std::enable_if >::value, typename View::applied_to>::type; + target_type * ref; public : - /** - * A standard iterator for a GraphBLAS aatrix. - * - * This iterator is used for data extraction only. Hence only this const - * version is specified. - * - * Dereferencing an iterator of this type that is not in end position yields - * a pair \f$ (c,v) \f$. The value \a v is of type \a D and corresponds to - * the value of the dereferenced nonzero. - * The value \a c is another pair \f$ (i,j) \f$. The values \a i and \a j - * are of type size_t and correspond to the coordinate of the - * dereferenced nonzero. - * - * \note `Pair' here corresponds to the regular std::pair. - * - * \warning Comparing two const iterators corresponding to different - * containers leads to undefined behaviour. - * \warning Advancing an iterator past the end iterator of the container - * it corresponds to, leads to undefined behaviour. - * \warning Modifying the contents of a container makes any use of any - * iterator derived from it incur invalid behaviour. - * \note These are standard limitations of STL iterators. - */ - class const_iterator : public std::iterator< std::forward_iterator_tag, std::pair< std::pair< const size_t, const size_t >, const D >, size_t > { - - public : - - /** Standard equals operator. */ - bool - operator==( const const_iterator & other ) const { (void)other; return false; } - - /** @returns The negation of operator==(). */ - bool operator!=( const const_iterator & other ) const { - (void)other; - return true; - } - - /** - * Dereferences the current position of this iterator. - * - * @return If this iterator is valid and not in end position, this returns - * an std::pair with in its first field the position of the - * nonzero value, and in its second field the value of the nonzero. - * The position of a nonzero is another std::pair with both the - * first and second field of type size_t. - * - * \note If this iterator is invalid or in end position, the result is - * undefined. - */ - std::pair< const size_t, const D > operator*() const { - return std::pair< const size_t, const D >(); - } - - /** - * Advances the position of this iterator by one. - * - * If the current position corresponds to the last element in the - * container, the new position of this iterator will be its end - * position. - * - * If the current position of this iterator is already the end - * position, this iterator will become invalid; any use of invalid - * iterators will lead to undefined behaviour. - * - * @return A reference to this iterator. - */ - const_iterator & operator++() { - return *this; - } - -}; // namespace grb + Matrix( const size_t m, const size_t n ); -/** The value type of elements stored in this matrix. */ -typedef D value_type; + Matrix( const Matrix< T, Structure, density, View, backend > & other ); -/** - * The main GraphBLAS matrix constructor. - * - * Matrix nonzeroes will be uninitalised after successful construction. - * - * Requesting a matrix with zero \a rows or \a columns will yield an empty - * matrix; i.e., it will be useless but will not result in an error. - * - * @param rows The number of rows in the new matrix. - * @param columns The number of columns in the new matrix. - * - * @return SUCCESS This function never fails. - * - * \parblock - * \par Performance semantics. - * -# This constructor completes in \f$ \Theta(1) \f$ time. - * -# This constructor will not allocate any new dynamic memory. - * -# This constructor will use \f$ \Theta(1) \f$ extra bytes of - * memory beyond that at constructor entry. - * -# This constructor incurs \f$ \Theta(1) \f$ data movement. - * -# This constructor \em may make system calls. - * \endparblock - * - * \warning Avoid the use of this constructor within performance critical - * code sections. - */ -Matrix( const size_t rows, const size_t columns ) { - (void)rows; - (void)columns; -} - -/** - * Copy constructor. - * - * @param other The matrix to copy. - * - * \parblock - * \par Performance semantics. - * Allocates the same capacity as the \a other matrix, even if the - * actual number of nonzeroes contained in \a other is less. - * -# This constructor entails \f$ \Theta(\mathit{nz}) \f$ amount of - * work. - * -# This constructor allocates \f$ \Theta(\mathit{nz}) \f$ bytes - * of dynamic memory. - * -# This constructor incurs \f$ \Theta(\mathit{nz}) \f$ of data - * movement. - * -# This constructor \em may make system calls. - * \endparblock - * - * \warning Avoid the use of this constructor within performance critical - * code sections. - */ -Matrix( const Matrix< D, implementation > & other ) { - (void)other; -} + Matrix( Matrix< T, Structure, density, View, backend > && other ); -/** - * Move constructor. This will make the new matrix equal to the given - * GraphBLAS matrix while destroying the given matrix. - * - * @param[in] other The GraphBLAS matrix to move to this new instance. - * - * \parblock - * \par Performance semantics. - * -# This constructor entails \f$ \Theta(1) \f$ amount of work. - * -# This constructor will not allocate any new dynamic memory. - * -# This constructor will use \f$ \Theta(1) \f$ extra bytes of - * memory beyond that at constructor entry. - * -# This constructor will move \f$ \Theta(1) \f$ bytes of data. - * \endparblock - */ -Matrix( self_type && other ) { - (void)other; -} + ~Matrix(); -/** - * Matrix destructor. - * - * \parblock - * \par Performance semantics. - * -# This destructor entails \f$ \Theta(1) \f$ amount of work. - * -# This destructor will not perform any memory allocations. - * -# This destructor will use \f$ \mathcal{O}(1) \f$ extra bytes of - * memory beyond that at constructor entry. - * -# This destructor will move \f$ \Theta(1) \f$ bytes of data. - * -# This destructor makes system calls. - * \endparblock - * - * \warning Avoid calling destructors from within performance critical - * code sections. - */ -~Matrix() {} - -/** - * Assigns nonzeroes to the matrix from a coordinate format. - * - * Any prior content may be combined with new input according to the - * user-supplied accumulator operator (\a accum). - * - * Input triplets need not be unique. Input triplets that are written to the - * same row and column coordinates will be combined using the supplied - * duplicate operator (\a dup). - * - * \note Note that \a dup and \a accum may differ. The duplicate operator is - * \em not applied to any pre-existing nonzero values. - * - * \note The order of application of the operators is undefined. - * - * The number of nonzeroes, after reduction by duplicate removals and after - * merger with the existing nonzero structure, must be equal or less than the - * space reserved during the construction of this matrix. The nonzeroes will - * not be stored in a fully sorted fashion-- it will be sorted column-wise, - * but within each column the order can be arbitrary. - * - * @tparam accum How existing entries of this matrix should be - * treated. - * The default is #grb::operators::right_assign, which - * means that any existing values are overwritten with - * the new values. - * @tparam dup How to handle duplicate entries. The default is - * #grb::operators::add, which means that duplicated - * values are combined by addition. - * @tparam descr The descriptor used. The default is - * #grb::descriptors::no_operation, which means that - * no pre- or post-processing of input or input is - * performed. - * @tparam fwd_iterator1 The type of the row index iterator. - * @tparam fwd_iterator2 The type of the column index iterator. - * @tparam fwd_iterator3 The type of the nonzero value iterator. - * @tparam length_type The type of the number of elements in each iterator. - * @tparam T The type of the supplied mask. - * - * \note By default, the iterator types are raw, unaliased, pointers. - * - * \warning This means that by default, input arrays are \em not - * allowed to overlap. - * - * Forward iterators will only be used to read from, never to assign to. - * - * \note It is therefore both legal and preferred to pass constant forward - * iterators, as opposed to mutable ones as \a I, \a J, and \a V. - * - * @param[in] I A forward iterator to \a cap row indices. - * @param[in] J A forward iterator to \a cap column indices. - * @param[in] V A forward iterator to \a cap nonzero values. - * @param[in] nz The number of items pointed to by \a I, \a J, \em and - * \a V. - * @param[in] mask An input element at coordinate \f$ (i,j) \f$ will only be - * added to this matrix if there exists a matching element - * \f$ \mathit{mask}_{ij} \f$ in the given \a mask that - * eveluates true. The matrix in \a mask must be - * of the same dimension as this matrix. - * - * @return grb::MISMATCH -# when an element from \a I dereferences to a value - * larger than the row dimension of this matrix, or - * -# when an element from \a J dereferences to a value - * larger than the column dimension of this matrix. - * When this error code is returned the state of this - * container will be as though this function was never - * called; however, the given forward iterators may - * have been copied and the copied iterators may have - * incurred multiple increments and dereferences. - * @return grb::OVERFLW When the internal data type used for storing the - * number of nonzeroes is not large enough to store - * the number of nonzeroes the user wants to assign. - * When this error code is returned the state of this - * container will be as though this function was never - * called; however, the given forward iterators may - * have been copied and the copied iterators may have - * incurred multiple increments and dereferences. - * @return grb::SUCCESS When the function completes successfully. - * - * \parblock - * \par Performance semantics. - * -# This function contains - * \f$ \Theta(\mathit{nz}\log\mathit{nz})+\mathcal{O}(m+n)) \f$ - * amount of work. - * -# This function may dynamically allocate - * \f$ \Theta(\mathit{nz})+\mathcal{O}(m+n)) \f$ bytes of memory. - * -# A call to this function will use \f$ \mathcal{O}(m+n) \f$ bytes - * of memory beyond the memory in use at the function call entry. - * -# This function will copy each input forward iterator at most - * \em twice; the three input iterators \a I, \a J, and \a V thus - * may have exactly two copies each, meaning that all input may be - * traversed \em twice. - * -# Each of the at most six iterator copies will be incremented at - * most \f$ \mathit{nz} \f$ times. - * -# Each position of the each of the at most six iterator copies - * will be dereferenced exactly once. - * -# This function moves - * \f$ \Theta(\mathit{nz})+\mathcal{O}(m+n)) \f$ bytes of data. - * -# If the mask is nonempty, the performance costs of grb::eWiseMul - * on two matrix arguments must be added to the above costs. - * -# This function will likely make system calls. - * \endparblock - * - * \warning This is an extremely expensive function. Use sparingly and only - * when absolutely necessary - * - * \note Streaming input can be implemented by supplying buffered - * iterators to this GraphBLAS implementation. - */ -template< Descriptor descr = descriptors::no_operation, - template< typename, typename, typename > class accum = operators::right_assign, - template< typename, typename, typename > class dup = operators::add, - typename fwd_iterator1 = const size_t * __restrict__, - typename fwd_iterator2 = const size_t * __restrict__, - typename fwd_iterator3 = const D * __restrict__, - typename length_type = size_t, - typename T > -RC buildMatrix( const fwd_iterator1 I, const fwd_iterator2 J, const fwd_iterator3 V, const length_type nz, const Matrix< T, implementation > & mask ) { - (void)I; - (void)J; - (void)V; - (void)nz; - (void)mask; - return PANIC; -} - -//@{ -/** - * Provides the only mechanism to extract data from a GraphBLAS matrix. - * - * The order in which nonzero elements are returned is undefined. - * - * @return An iterator pointing to the first element of this matrix, if any; - * \em or an iterator in end position if this vector contains no - * nonzeroes. - * - * \note An `iterator in end position' compares equal to the const_iterator - * returned by cend(). - * - * \parblock - * \par Performance semantics - * -# This function contains \f$ \mathcal{O}(1) \f$ work. - * -# This function is allowed allocate dynamic memory. - * -# This function uses up to \f$ \mathcal{O}(1) \f$ more memory - * than already used by this application at entry. - * -# This function shall move at most \f$ \mathcal{O}(1) \f$ bytes - * of data. - * -# This function may make system calls. - * \endparblock - * - * \warning Avoid the use of this function within performance critical code - * sections. - * - * \note This function may make use of a const_iterator that is buffered, - * hence possibly causing its implicitly called constructor to - * allocate dynamic memory. - */ -const_iterator cbegin() const {} - -/** - * Same as cbegin(). - * Since iterators are only supplied as a data extraction mechanism, there - * is no overloaded version of this function that returns a non-const - * iterator. - */ -const_iterator begin() const {} -//@} - -//@{ -/** - * Indicates the end to the elements in this container. - * - * @return An iterator at the end position of this container. - * - * \parblock - * \par Performance semantics - * -# This function contains \f$ \mathcal{O}(1) \f$ work. - * -# This function is not allowed allocate dynamic memory. - * -# This function uses up to \f$ \mathcal{O}(1) \f$ more memory - * than already used by this application at entry. - * -# This function shall move at most \f$ \mathcal{O}(1) \f$ bytes - * of data. - * -# This function shall \em not induce any system calls. - * \endparblock - * - * \note Even if cbegin() returns a buffered const_iterator that may require - * dynamic memory allocation and additional data movement, this - * specification disallows the same to happen for the construction of - * an iterator in end position. - */ -const_iterator cend() const {} - -/** - * Same as cend(). - * Since iterators are only supplied as a data extraction mechanism, there - * is no overloaded version of this function that returns a non-const - * iterator. - */ -const_iterator end() const {} -//@} -} -; - -template< typename InputType, Backend backend > -RC clear( Matrix< InputType, backend > & A ) noexcept { - // this is the generic stub implementation - return UNSUPPORTED; -} - -template< typename T, typename Structure, enum Density density, typename View, enum Backend backend > -class StructuredMatrix { - - /** - * The two following members define the \em logical layout of a structured matrix: - * Its structure and access relations. This is enabled only if the structured matrix - * does not define a View on another matrix. - */ - using structure = Structure; - /** - * A pair of pointers to index mapping functions (see imf.hpp) that express the - * logical access to the structured matrix. - */ - std::shared_ptr imf_l, imf_r; - - /** - * When a structured matrix instanciate a \em container it defines a new \em physical - * (concrete?) layout. This is characterized by an ALP container (aka a \a Matrix) and a - * storage scheme that defines a unique interpretation of its content. - * The combination of the logical and physical layout of a structured matrix enables to - * identify a precise mapping between an element in the structured matrix and a position - * wihtin one or more 1/2D-arrays that store it. - */ - Matrix< T, reference_dense > * _container; - - /** - * A container's storage scheme. \a storage_scheme is not exposed to the user as an option - * but can defined by ALP at different points in the execution depending on the \a backend choice. - * For example, if the container is associated to an I/O matrix, with a reference backend - * it might be set to reflect the storage scheme of the user data as specified at buildMatrix. - * If \a backend is set to \a mlir then the scheme could be fixed by the JIT compiler to effectively - * support its optimization strategy. - * At construction time and until the moment the scheme decision is made it may be set to - * an appropriate default choice, e.g. if \a density is \a Density::Dense then - * \a Density::Dense::full could be used. - * \internal \todo Revisit this. The change of storage scheme type to enum (dense/sparse) and - * implementing storage mapping functions requires a change of this spec. - */ - // Storage storage_scheme; + }; // class Matrix /** - * When a structured matrix defines a View over another matrix, it contains a pointer - * to the latter. Its type can be identified via the View parameter. + * Check if type \a T is a Matrix. */ - using target_type = typename std::enable_if >::value, typename View::applied_to>::type; - target_type * ref; - - public : - - StructuredMatrix( const size_t m, const size_t n ); - - StructuredMatrix( const StructuredMatrix< T, Structure, density, View, backend > & other ); - - StructuredMatrix( StructuredMatrix< T, Structure, density, View, backend > && other ); - - ~StructuredMatrix(); - -}; // class StructuredMatrix - -/** - * Check if type \a T is a StructuredMatrix. - */ -template< typename T > -struct is_structured_matrix : std::false_type {}; -template< typename T, typename Structure, enum Density density, typename View, enum Backend backend > -struct is_structured_matrix< StructuredMatrix< T, Structure, density, View, backend > > : std::true_type {}; + template< typename T > + struct is_structured_matrix : std::false_type {}; + template< typename T, typename Structure, enum Density density, typename View, enum Backend backend > + struct is_structured_matrix< Matrix< T, Structure, density, View, backend > > : std::true_type {}; -} // end namespace ``grb'' +} // end namespace ``alp'' -#endif // end _H_GRB_MATRIX_BASE +#endif // end _H_ALP_MATRIX_BASE diff --git a/include/alp/base/scalar.hpp b/include/alp/base/scalar.hpp index 06075d3e8..04f22f165 100644 --- a/include/alp/base/scalar.hpp +++ b/include/alp/base/scalar.hpp @@ -15,18 +15,18 @@ * limitations under the License. */ -#ifndef _H_GRB_SCALAR_BASE -#define _H_GRB_SCALAR_BASE +#ifndef _H_ALP_SCALAR_BASE +#define _H_ALP_SCALAR_BASE #include //size_t #include -#include -#include -#include -#include +#include +#include +#include +#include -namespace grb { +namespace alp { /** * \brief An ALP scalar. @@ -41,7 +41,7 @@ namespace grb { * for example, randomizing the scalar value on each * interaction with the scalar. * - * \warning Creating a grb::Scalar of other ALP types is + * \warning Creating a alp::Scalar of other ALP types is * not allowed. * Passing a ALP type as template parameter will lead to * undefined behaviour. @@ -175,7 +175,7 @@ namespace grb { * context, scalar is considered to have a nonzero value \em iff initialized. * * A lambda reference to the value of this scalar is only valid when used - * inside a lambda function evaluated via grb::eWiseLambda. Outside this + * inside a lambda function evaluated via alp::eWiseLambda. Outside this * scope the returned reference incurs undefined behaviour. * * @@ -198,16 +198,16 @@ namespace grb { * @return A lambda reference to the value of this scalar * * \par Example. - * See grb::eWiseLambda() for a practical and useful example. + * See alp::eWiseLambda() for a practical and useful example. * * \warning There is no similar concept in the official GraphBLAS specs. * * @see lambda_reference For more details on the returned reference type. - * @see grb::eWiseLambda For one legal way in which to use the returned + * @see alp::eWiseLambda For one legal way in which to use the returned * #lambda_reference. */ lambda_reference operator*() noexcept { -#ifndef _GRB_NO_EXCEPTIONS +#ifndef _ALP_NO_EXCEPTIONS assert( false ); // Requesting lambda reference of unimplemented Scalar backend. #endif } @@ -216,13 +216,13 @@ namespace grb { * See the non-constant variant for further details. */ const lambda_reference operator*() const noexcept { -#ifndef _GRB_NO_EXCEPTIONS +#ifndef _ALP_NO_EXCEPTIONS assert( false ); // Requesting lambda reference of unimplemented Scalar backend. #endif } }; // class Scalar -} // namespace grb +} // namespace alp -#endif // _H_GRB_SCALAR_BASE +#endif // _H_ALP_SCALAR_BASE diff --git a/include/alp/base/vector.hpp b/include/alp/base/vector.hpp index 62b18f6d3..fc5085dcc 100644 --- a/include/alp/base/vector.hpp +++ b/include/alp/base/vector.hpp @@ -20,864 +20,864 @@ * @date 10th of August, 2016 */ -#ifndef _H_GRB_VECTOR_BASE -#define _H_GRB_VECTOR_BASE +#ifndef _H_ALP_VECTOR_BASE +#define _H_ALP_VECTOR_BASE #include //size_t #include //std::iterator #include #include //pair -#include -#include -#include -#include -#include - -namespace grb { - - /** - * A GraphBLAS vector. This is an opaque data type that can be provided to - * any GraphBLAS function, such as, grb::eWiseMulAdd, for example. - * - * @tparam D The type of an element of this vector. \a D shall not be a - * GraphBLAS type. - * @tparam implementation Allows different backends to implement different - * versions of this data type. - * @tparam C The type of the class that keeps track of sparsity structure. - * - * \warning Creating a grb::Vector of other GraphBLAS types is - * not allowed. - * Passing a GraphBLAS type as template parameter will lead to - * undefined behaviour. - * - * \note The implementation found in the same file as this documentation - * catches invalid backends only. This class should never compile. - * - * @see grb::Vector< D, reference, C > for an actual implementation example. - */ - template< typename D, enum Backend implementation, typename C > - class Vector { - - public : - - /** The type of elements stored in this vector. */ - typedef D value_type; - - /** - * Defines a reference to a value of type \a D. This reference is only valid - * when used inside a lambda function that is passed to grb::eWiseLambda(). - * - * \warning Any other use of this reference incurs undefined behaviour. - * - * \par Example. - * An example valid use: - * \code - * void f( - * Vector< D >::lambda_reference x, - * const Vector< D >::lambda_reference y, - * const Vector< D > &v - * ) { - * grb::eWiseLambda( [x,y](const size_t i) { - * x += y; - * }, v ); - * } - * \endcode - * This code adds \a y to \a x for every element in \a v. For a more useful - * example, see grb::eWiseLambda. - * - * \warning Note that, unlike the above, this below code is illegal since it - * does not evaluate via a lambda passed to any of the above - * GraphBLAS lambda functions (such as grb::eWiseLambda). - * \code{.cpp} - * void f( - * Vector< D >::lambda_reference x, - * const Vector< D >::lambda_reference y - * ) { - * x += y; - * } - * \endcode - * Also this usage is illegal since it does not rely on any - * GraphBLAS-approved function listed above: - * \code{.cpp} - * void f( - * Vector< D >::lambda_reference x, - * const Vector< D >::lambda_reference y - * ) { - * std::functional< void() > f = - * [x,y](const size_t i) { - * x += y; - * }; - * f(); - * } - * \endcode - * - * \warning There is no similar concept in the official GraphBLAS specs. - * - * @see grb::Vector::operator[]() - * @see grb::eWiseLambda - */ - typedef D & lambda_reference; - - /** - * A standard iterator for the Vector< D > class. - * - * This iterator is used for data extraction only. Hence only this const - * version is supplied. - * - * \warning Comparing two const iterators corresponding to different - * containers leads to undefined behaviour. - * \warning Advancing an iterator past the end iterator of the container - * it corresponds to leads to undefined behaviour. - * \warning Modifying the contents of a container makes any use of any - * iterator derived from it incur invalid behaviour. - * \note These are standard limitations of STL iterators. - */ - class const_iterator : public std::iterator< std::forward_iterator_tag, std::pair< const size_t, const D >, size_t > { - - public : - - /** Standard equals operator. */ - bool - operator==( const const_iterator & other ) const { (void)other; return false; } - - /** @returns The negation of operator==(). */ - bool operator!=( const const_iterator & other ) const { - (void)other; - return true; - } - - /** - * Dereferences the current position of this iterator. - * - * @return If this iterator is valid and not in end position, - * this returns a new std::pair with in its first - * field the position of the nonzero value, and in its - * second field the value of the nonzero. - * - * \note If this iterator is invalid or in end position, the result is, - * undefined. - */ - std::pair< const size_t, const D > operator*() const { - return std::pair< const size_t, const D >(); - } - - /** - * Advances the position of this iterator by one. - * - * If the current position corresponds to the last element in the - * container, the new position of this iterator will be its end - * position. - * - * If the current position of this iterator is already the end - * position, this iterator will become invalid; any use of invalid - * iterators will lead to undefined behaviour. - * - * @return A reference to this iterator. - */ - const_iterator & operator++() { - return *this; - } - - }; - - /** - * The only way to create an empty GraphBLAS vector. The given dimension will - * be fixed throughout the lifetime of this container. - * - * The vector will be empty after successful construction. - * - * @param[in] n The dimension of this vector. - * - * \parblock - * \par Performance semantics - * -# This constructor completes in \f$ \mathcal{O}(n) \f$ time. - * -# This constructor allocates \f$ \mathcal{O}(n) \f$ bytes of - * dynamic memory. - * -# This constructor moves at most \f$ \mathcal{O}( n ) \f$ bytes - * of data. - * -# This constructor may make system calls. - * \endparblock - * - * \warning Avoid the use of this constructor within performance critical - * code sections. - */ - Vector( const size_t n ) { - (void)n; - } - - /** - * Move constructor. - * - * This will make the new vector equal the given GraphBLAS vector while - * destroying the supplied GraphBLAS vector. - * - * This function always succeeds and will not throw exceptions. - * - * @param[in] x The GraphBLAS vector to move to this new container. - * - * \parblock - * \par Performance semantics - * -# This constructor completes in \f$ \Theta(1) \f$ time. - * -# This constructor does not allocate new data on the heap. - * -# This constructor uses \f$ \mathcal{O}(1) \f$ more memory than - * already used by this application at constructor entry. - * -# This constructor incurs at most \f$ \mathcal{O}(1) \f$ bytes of - * data movement. - * \endparblock - */ - Vector( Vector< D, implementation, C > &&x ) noexcept { - (void)x; - } - - /** - * Move-from-temporary assignment. - * - * @param[in,out] x The temporary instance from which this instance shall - * take over its resources. - * - * After a call to this function, \a x shall correspond to an empy vector. - * - * \parblock - * \par Performance semantics - * -# This move assignment completes in \f$ \Theta(1) \f$ time. - * -# This move assignment may not make system calls. - * -# this move assignment moves \f$ \Theta(1) \f$ data only. - * \endparblock - */ - Vector< D, implementation, C >& operator=( Vector< D, implementation, C > &&x ) noexcept { - (void)x; - return *this; - } - - /** - * Default destructor. Frees all associated memory areas. - * - * \parblock - * \par Performance semantics - * -# This destructor contains \f$ \mathcal{O}(n) \f$ work, where - * \f$ n \f$ is the capacity of this vector. - * -# This destructor is only allowed to free memory, not allocate. - * -# This destructor uses \f$ \mathcal{O}(1) \f$ more memory than - * already used by this application at entry. - * -# This destructor shall move at most \f$ \mathcal{O}(n) \f$ bytes - * of data. - * -# This destructor will make system calls. - * \endparblock - * - * \warning Avoid the use of this destructor within performance critical - * code sections. - * - * \note Destruction of this GraphBLAS container is the only way to - * guarantee that any underlying dynamically allocated memory is - * freed. - */ - ~Vector() {} - - //@{ - /** - * Provides the only mechanism to extract data from this GraphBLAS vector. - * - * The order in which nonzero elements are returned is undefined. - * - * @return An iterator pointing to the first element of this vector, if any; - * \em or an iterator in end position if this vector contains no - * nonzeroes. - * - * \note An `iterator in end position' compares equal to the const_iterator - * returned by cend(). - * - * \parblock - * \par Performance semantics - * -# This function contains \f$ \mathcal{O}(1) \f$ work. - * -# This function is allowed allocate dynamic memory. - * -# This function uses up to \f$ \mathcal{O}(1) \f$ more memory - * than already used by this application at entry. - * -# This function shall move at most \f$ \mathcal{O}(1) \f$ bytes - * of data. - * -# This function may make system calls. - * \endparblock - * - * \warning Avoid the use of this function within performance critical code - * sections. - * - * \note This function may make use of a const_iterator that is buffered, - * hence possibly causing its implicitly called constructor to - * allocate dynamic memory. - */ - const_iterator cbegin() const {} - - /** - * Same as cbegin(). - * Since iterators are only supplied as a data extraction mechanism, there - * is no overloaded version of this function that returns a non-const - * iterator. - */ - const_iterator begin() const {} - //@} - - //@{ - /** - * Indicates the end to the elements in this container. - * - * @return An iterator at the end position of this container. - * - * \parblock - * \par Performance semantics - * -# This function contains \f$ \mathcal{O}(1) \f$ work. - * -# This function is not allowed allocate dynamic memory. - * -# This function uses up to \f$ \mathcal{O}(1) \f$ more memory - * than already used by this application at entry. - * -# This function shall move at most \f$ \mathcal{O}(1) \f$ bytes - * of data. - * -# This function shall \em not induce any system calls. - * \endparblock - * - * \note Even if cbegin() returns a buffered const_iterator that may require - * dynamic memory allocation and additional data movement, this - * specification disallows the same to happen for the construction of - * an iterator in end position. - */ - const_iterator cend() const {} - - /** - * Same as cend(). - * Since iterators are only supplied as a data extraction mechanism, there - * is no overloaded version of this function that returns a non-const - * iterator. - */ - const_iterator end() const {} - //@} - - /** - * Copy from raw user-supplied data into a vector. - * - * This is the dense unmasked variant. - * - * @tparam descr The pre-processing descriptor to use. - * @tparam fwd_iterator The type of input iterator. By default, this will be - * a raw \em unaliased pointer. - * @tparam Accum The accumulator type used to merge incoming new - * elements with existing contents, if any. - * - * @param[in] accum The accumulator used to merge incoming new elements with - * existing content, if any. - * @param[in] start The iterator to the first element that should be copied - * into this GraphBLAS vector. - * @param[in] end Iterator shifted exactly one past the last element that - * should be copied into this GraphBLAS vector. - * @param[out] npos The last iterator position after exiting this function. - * In most cases this will equal \a end. This parameter is - * optional. - * - * The first element from \a it will be copied into the element with index - * \f$ 0 \f$ in this vector. The \f$ k \f$-th element will be copied into - * the element with index \f$ k - 1 \f$. The iterator \a start will be - * incremented along with \f$ k \f$ until it compares equal to \a end, or - * until it has been incremented \a n times, where \a n is the dimension of - * this vector. In the latter case, any remaining values are ignored. - * - * @return grb::SUCCESS This function always succeeds. - * - * \note The default accumulator expects \a val to be of the same type - * as nonzero elements in this function, and will cause old - * values to be overwritten by the incoming new values. - * - * \note Previous contents of the vector are retained. If these are to be - * cleared first, see clear(). The default accumulator is NOT an - * alternative since any pre-existing values corresponding to entries - * in the mask that evaluate to false will be retained. - * - * \note The parameter \a n can be used to ingest only a subset of a larger - * data structure pointed to by \a start. At the end of the call, \a - * start will then not be equal to \a end, but instead point to the - * first element of the remainder of the larger data structure. - * - * \par Valid descriptors - * grb::descriptors::no_operation, grb::descriptors::no_casting. - * - * \note Invalid descriptors will be ignored. - * - * If grb::descriptors::no_casting is specified, then 1) the first domain of - * \a accum must match the type of \a val, 2) the second domain must match - * the type \a D of nonzeroes in this vector, and 3) the third domain must - * match \a D. If one of these is not true, the code shall not compile. - * - * \parblock - * \par Performance semantics - * If the capacity of this container is sufficient to perform the - * requested operation, then: - * -# This function contains \f$ \Theta(n) \f$ work. - * -# This function will take at most \f$ \Theta(1) \f$ memory beyond - * the memory already used by the application before the call to - * this function. - * -# This function moves at most \f$ n ( 2\mathit{sizeof}(D) + - * \mathit{sizeof}(\mathit{bool}) ) + \mathcal{O}(1) \f$ bytes of - * data. - * \endparblock - * - * \parblock - * \par Performance exceptions - * If the capacity of this container at function entry is insufficient - * to perform the requested operation, then, in addition to the above: - * -# this function allocates \f$ \Theta(n) \f$ bytes of memory . - * -# this function frees \f$ \mathcal{O}(n) \f$ bytes of memory. - * -# this function will make system calls. - * \endparblock - * - * \note An implementation may ensure that at object construction the - * capacity is maximised. In that case, the above performance - * exceptions will never come to pass. - * - * @see grb::buildVector for the GraphBLAS standard dispatcher to this - * function. - */ - template< Descriptor descr = descriptors::no_operation, class Accum = typename operators::right_assign< D, D, D >, typename fwd_iterator = const D * __restrict__ > - RC build( const Accum & accum, const fwd_iterator start, const fwd_iterator end, fwd_iterator npos ) { - (void)accum; - (void)start; - (void)end; - (void)npos; - return PANIC; - } - - /** - * Copy from raw user-supplied data into a vector. - * - * This is the sparse non-masked variant. - * - * @tparam descr The pre-processing descriptor to use. - * @tparam Accum The type of the operator used to combine newly input - * data with existing data, if any. - * @tparam ind_iterator The type of index input iterator. By default, this - * will be a raw \em unaliased pointer to elements of - * type \a size_t. - * @tparam nnz_iterator The type of nonzero input iterator. By default, this - * will be a raw \em unaliased pointer to elements of - * type \a D. - * @tparam Dup The type of operator used to combine any duplicate - * input values. - * - * @param[in] accum The operator to be used when writing back the result - * of data that was already in this container prior to - * calling this function. - * @param[in] ind_start The iterator to the first index value that should be - * added to this GraphBLAS vector. - * @param[in] ind_end Iterator corresponding to the end position of - * \a ind_start. - * @param[in] nnz_start The iterator to the first nonzero value that should - * be added to this GraphBLAS vector. - * @param[in] nnz_end Iterator corresponding to the end position of - * \a nnz_start. - * @param[in] dup The operator to be used when handling multiple - * nonzero values that are to be mapped to the same - * index position. - * - * The first element from \a nnz_start will be copied into this vector at - * the index corresponding to the first element from \a ind_start. Then, - * both nonzero and index value iterators advance to add the next input - * element and the process repeats until either of the input iterators - * reach \a nnz_end or \a ind_end, respectively. - * If at that point one of the iterators still has remaining elements, then - * those elements are ignored. - * - * @return grb::MISMATCH When attempting to insert a nonzero value at an - * index position that is larger or equal to the - * dimension of this vector. When this code is - * returned, the contents of this container are - * undefined. - * @return grb::SUCCESS When all elements are successfully assigned. - * - * \note The default accumulator expects \a D to be of the same type - * as nonzero elements of this operator, and will cause old - * values to be overwritten by the incoming new values. - * - * \note The default \a dup expects \a D to be of the same type as nonzero - * elements of this operator, and will cause duplicate values to be - * discarded in favour of the last seen value. - * - * \note Previous contents of the vector are retained. If these are to be - * cleared first, see clear(). The default accumulator is NOT an - * alternative since any pre-existing values corresponding to entries - * in the mask that evaluate to false will be retained. - * - * \par Valid descriptors - * grb::descriptors::no_operation, grb::descriptors::no_casting, - * grb::descriptors::no_duplicates. - * - * \note Invalid descriptors will be ignored. - * - * If grb::descriptors::no_casting is specified, then 1) the first domain of - * \a accum must match the type of \a D, 2) the second domain must match - * nnz_iterator::value_type, and 3) the third domain must \a D. If one of - * these is not true, the code shall not compile. - * - * \parblock - * \par Performance semantics. - * -# This function contains \f$ \Theta(n) \f$ work. - * -# This function will take at most \f$ \Theta(1) \f$ memory beyond - * the memory already used by the application before the call to - * this function. - * -# This function moves at most \f$ n ( 2\mathit{sizeof}(D) + - * \mathit{sizeof}(\mathit{bool}) ) + \mathcal{O}(1) \f$ bytes of - * data. - * \endparblock - * - * \parblock - * \par Performance exceptions - * If the capacity of this container at function entry is insufficient - * to perform the requested operation, then, in addition to the above: - * -# this function allocates \f$ \Theta(n) \f$ bytes of memory . - * -# this function frees \f$ \mathcal{O}(n) \f$ bytes of memory. - * -# this function will make system calls. - * \endparblock - * - * \note An implementation may ensure that at object construction the - * capacity is maximised. In that case, the above performance - * exceptions will never come to pass. - * - * @see grb::buildVector for the GraphBLAS standard dispatcher to this - * function. - */ - template< Descriptor descr = descriptors::no_operation, - class Accum = operators::right_assign< D, D, D >, - typename ind_iterator = const size_t * __restrict__, - typename nnz_iterator = const D * __restrict__, - class Dup = operators::right_assign< D, D, D > > - RC build( const Accum & accum, const ind_iterator ind_start, const ind_iterator ind_end, const nnz_iterator nnz_start, const nnz_iterator nnz_end, const Dup & dup = Dup() ) { - (void)accum; - (void)ind_start; - (void)ind_end; - (void)nnz_start; - (void)nnz_end; - (void)dup; - return PANIC; - } - - /** - * Copy from raw user-supplied data into a vector. - * - * This is the sparse masked variant. - * - * @tparam descr The pre-processing descriptor to use. - * @tparam mask_type The value type of the \a mask vector. This type is - * \em not required to be \a bool. - * @tparam Accum The type of the operator used to combine newly input - * data with existing data, if any. - * @tparam ind_iterator The type of index input iterator. By default, this - * will be a raw \em unaliased pointer to elements of - * type \a size_t. - * @tparam nnz_iterator The type of nonzero input iterator. By default, this - * will be a raw \em unaliased pointer to elements of - * type \a D. - * @tparam Dup The type of operator used to combine any duplicate - * input values. - * - * @param[in] mask An element is only added to this container if its - * index \f$ i \f$ has a nonzero at the same position - * in \a mask that evaluates true. - * @param[in] accum The operator to be used when writing back the result - * of data that was already in this container prior to - * calling this function. - * @param[in] ind_start The iterator to the first index value that should be - * added to this GraphBLAS vector. - * @param[in] ind_end Iterator corresponding to the end position of - * \a ind_start. - * @param[in] nnz_start The iterator to the first nonzero value that should - * be added to this GraphBLAS vector. - * @param[in] nnz_end Iterator corresponding to the end position of - * \a nnz_start. - * @param[in] dup The operator to be used when handling multiple - * nonzero values that are to be mapped to the same - * index position. - * - * The first element from \a nnz_start will be copied into this vector at - * the index corresponding to the first element from \a ind_start. Then, - * both nonzero and index value iterators advance to add the next input - * element and the process repeats until either of the input iterators - * reach \a nnz_end or \a ind_end, respectively. - * If at that point one of the iterators still has remaining elements, then - * those elements are ignored. - * - * @return grb::MISMATCH When attempting to insert a nonzero value at an - * index position that is larger or equal to the - * dimension of this vector. When this code is - * returned, the contents of this container are - * undefined. - * @return grb::SUCCESS When all elements are successfully assigned. - * - * \note The default accumulator expects \a D to be of the same type - * as nonzero elements of this operator, and will cause old - * values to be overwritten by the incoming new values. - * - * \note The default \a dup expects \a D to be of the same type as nonzero - * elements of this operator, and will cause duplicate values to be - * discarded in favour of the last seen value. - * - * \note Previous contents of the vector are retained. If these are to be - * cleared first, see clear(). The default accumulator is NOT an - * alternative since any pre-existing values corresponding to entries - * in the mask that evaluate to false will be retained. - * - * \par Valid descriptors - * grb::descriptors::no_operation, grb::descriptors::no_casting, - * grb::descriptors::invert_mask, grb::descriptors::no_duplicates. - * - * \note Invalid descriptors will be ignored. - * - * If grb::descriptors::no_casting is specified, then 1) the first domain of - * \a accum must match the type of \a D, 2) the second domain must match - * nnz_iterator::value_type, and 3) the third domain must \a D. If one of - * these is not true, the code shall not compile. - * - * \parblock - * \par Performance semantics. - * -# This function contains \f$ \Theta(n) \f$ work. - * -# This function will take at most \f$ \Theta(1) \f$ memory beyond - * the memory already used by the application before the call to - * this function. - * -# This function moves at most \f$ n ( 2\mathit{sizeof}(D) + - * \mathit{sizeof}(\mathit{bool}) ) + \mathcal{O}(1) \f$ bytes of - * data. - * \endparblock - * - * \parblock - * \par Performance exceptions - * If the capacity of this container at function entry is insufficient - * to perform the requested operation, then, in addition to the above: - * -# this function allocates \f$ \Theta(n) \f$ bytes of memory . - * -# this function frees \f$ \mathcal{O}(n) \f$ bytes of memory. - * -# this function will make system calls. - * \endparblock - * - * \note An implementation may ensure that at object construction the - * capacity is maximised. In that case, the above performance - * exceptions will never come to pass. - * - * @see grb::buildVector for the GraphBLAS standard dispatcher to this - * function. - */ - template< Descriptor descr = descriptors::no_operation, - typename mask_type, - class Accum, - typename ind_iterator = const size_t * __restrict__, - typename nnz_iterator = const D * __restrict__, - class Dup = operators::right_assign< D, typename nnz_iterator::value_type, D > > - RC build( const Vector< mask_type, implementation, C > mask, - const Accum & accum, - const ind_iterator ind_start, - const ind_iterator ind_end, - const nnz_iterator nnz_start, - const nnz_iterator nnz_end, - const Dup & dup = Dup() ) { - (void)mask; - (void)accum; - (void)ind_start; - (void)ind_end; - (void)nnz_start; - (void)nnz_end; - (void)dup; - return PANIC; - } - - /** - * Return the dimension of this vector. - * - * @tparam T The integral output type. - * - * @param[out] size Where to store the size of this vector. - * The initial value is ignored. - * - * @returns grb::SUCCESS When the function call completes successfully. - * - * \note This function cannot fail. - * - * \parblock - * \par Performance semantics - * This function - * -# contains \f$ \Theta(1) \f$ work, - * -# will not allocate new dynamic memory, - * -# will take at most \f$ \Theta(1) \f$ memory beyond the memory - * already used by the application before the call to this - * function. - * -# will move at most \f$ \mathit{sizeof}(T) + - * \mathit{sizeof}(\mathit{size\_t}) \f$ bytes of data. - * \endparblock - */ - template< typename T > - RC size( T & size ) const { - (void)size; - return PANIC; - } - - /** - * Return the number of nonzeroes in this vector. - * - * @tparam T The integral output type. - * - * @param[out] nnz Where to store the number of nonzeroes contained in this - * vector. Its initial value is ignored. - * - * @returns grb::SUCCESS When the function call completes successfully. - * - * \note This function cannot fail. - * - * \parblock - * \par Performance semantics - * This function - * -# contains \f$ \Theta(1) \f$ work, - * -# will not allocate new dynamic memory, - * -# will take at most \f$ \Theta(1) \f$ memory beyond the memory - * already used by the application before the call to this - * function. - * -# will move at most \f$ \mathit{sizeof}(T) + - * \mathit{sizeof}(\mathit{size\_t}) \f$ bytes of data. - * \endparblock - */ - template< typename T > - RC nnz( T & nnz ) const { - (void)nnz; - return PANIC; - } - - /** - * Returns a lambda reference to an element of this sparse vector. - * - * A lambda reference to an element of this vector is only valid when used - * inside a lambda function evaluated via grb::eWiseLambda. The lambda - * function is called for specific indices only-- that is, the GraphBLAS - * implementation decides at which elements to dereference this container. - * Outside this scope the returned reference incurs undefined behaviour. - * - * \warning In particular, for the given index \a i by the lambda function, - * it shall be \em illegal to refer to indices relative to that - * \a i; including, but not limited to, \f$ i+1 \f$, \f$ i-1 \f$, et - * cetera. - * - * \note As a consequence, this function cannot be used to perform stencil - * or halo based operations. - * - * If a previously non-existing entry of the vector is requested, a new - * nonzero is added at position \a i in this vector. The new element will - * have its initial value equal to the \em identity corresponding to the - * given monoid. - * - * \warning In parallel contexts the use of a returned lambda reference - * outside the context of an eWiseLambda will incur at least one of - * the following ill effects: it may - * -# fail outright, - * -# work on stale data, - * -# work on incorrect data, or - * -# incur high communication costs to guarantee correctness. - * In short, such usage causes undefined behaviour. Implementers are - * \em not advised to provide GAS-like functionality through this - * interface, as it invites bad programming practices and bad - * algorithm design decisions. This operator is instead intended to - * provide for generic BLAS1-type operations only. - * - * \note For I/O, use the iterator retrieved via cbegin() instead of - * relying on a lambda_reference. - * - * @param[in] i Which element to return a lambda reference of. - * @param[in] monoid Under which generalised monoid to interpret the - * requested \f$ i \f$th element of this vector. - * - * \note The \a monoid (or a ring) is required to be able to interpret a - * sparse vector. A user who is sure this vector is dense, or otherwise - * is able to ensure that the a lambda_reference will only be requested - * at elements where nonzeroes already exists, may refer to - * Vector::operator[], - * - * @return A lambda reference to the element \a i of this vector. - * - * \par Example. - * See grb::eWiseLambda() for a practical and useful example. - * - * \warning There is no similar concept in the official GraphBLAS specs. - * - * @see lambda_reference For more details on the returned reference type. - * @see grb::eWiseLambda For one legal way in which to use the returned - * #lambda_reference. - */ - template< class Monoid > - lambda_reference operator()( const size_t i, const Monoid & monoid = Monoid() ) { - (void)i; - (void)monoid; - return PANIC; - } - - /** - * Returns a lambda reference to an element of this vector. The user - * ensures that the requested reference only corresponds to a pre-existing - * nonzero in this vector, or undefined behaviour will occur. - * - * A lambda reference to an element of this vector is only valid when used - * inside a lambda function evaluated via grb::eWiseLambda. The lambda - * function is called for specific indices only-- that is, the GraphBLAS - * implementation decides at which elements to dereference this container. - * Outside this scope the returned reference incurs undefined behaviour. - * - * \warning In particular, for the given index \a i by the lambda function, - * it shall be \em illegal to refer to indices relative to that - * \a i; including, but not limited to, \f$ i+1 \f$, \f$ i-1 \f$, et - * cetera. - * - * \note As a consequence, this function cannot be used to perform stencil - * or halo based operations. - * - * If a previously non-existing entry of the vector is requested, undefined - * behaviour will occur. Functions that are defined to work with references - * of this kind, such as grb::eWiseLambda, define exactly which elements are - * dereferenced. - * - * \warning In parallel contexts the use of a returned lambda reference - * outside the context of an eWiseLambda will incur at least one of - * the following ill effects: it may - * -# fail outright, - * -# work on stale data, - * -# work on incorrect data, or - * -# incur high communication costs to guarantee correctness. - * In short, such usage causes undefined behaviour. Implementers are - * \em not advised to provide GAS-like functionality through this - * interface, as it invites bad programming practices and bad - * algorithm design decisions. This operator is instead intended to - * provide for generic BLAS1-type operations only. - * - * \note For I/O, use the iterator retrieved via cbegin() instead of - * relying on a lambda_reference. - * - * @param[in] i Which element to return a lambda reference of. - * @param[in] ring Under which generalised semiring to interpret the - * requested \f$ i \f$th element of this vector. - * - * \note The \a ring is required to be able to interpret a sparse vector. A - * user who is sure this vector is dense, or otherwise is able to - * ensure that the a lambda_reference will only be requested at - * elements where nonzeroes already exists, may refer to - * Vector::operator[], - * - * @return A lambda reference to the element \a i of this vector. - * - * \par Example. - * See grb::eWiseLambda() for a practical and useful example. - * - * \warning There is no similar concept in the official GraphBLAS specs. - * - * @see lambda_reference For more details on the returned reference type. - * @see grb::eWiseLambda For one legal way in which to use the returned - * #lambda_reference. - */ - lambda_reference operator[]( const size_t i ) { - (void)i; -#ifndef _GRB_NO_EXCEPTIONS - assert( false ); // Requesting lambda reference of unimplemented Vector backend. +#include +#include +#include +#include +#include + +namespace alp { + namespace internal { + /** + * A GraphBLAS vector. This is an opaque data type that can be provided to + * any GraphBLAS function, such as, alp::eWiseMulAdd, for example. + * + * @tparam D The type of an element of this vector. \a D shall not be a + * GraphBLAS type. + * @tparam implementation Allows different backends to implement different + * versions of this data type. + * + * \warning Creating a alp::Vector of other GraphBLAS types is + * not allowed. + * Passing a GraphBLAS type as template parameter will lead to + * undefined behaviour. + * + * \note The implementation found in the same file as this documentation + * catches invalid backends only. This class should never compile. + * + * @see alp::Vector< D, reference > for an actual implementation example. + */ + template< typename D, enum Backend implementation > + class Vector { + + public : + + /** The type of elements stored in this vector. */ + typedef D value_type; + + /** + * Defines a reference to a value of type \a D. This reference is only valid + * when used inside a lambda function that is passed to alp::eWiseLambda(). + * + * \warning Any other use of this reference incurs undefined behaviour. + * + * \par Example. + * An example valid use: + * \code + * void f( + * Vector< D >::lambda_reference x, + * const Vector< D >::lambda_reference y, + * const Vector< D > &v + * ) { + * alp::eWiseLambda( [x,y](const size_t i) { + * x += y; + * }, v ); + * } + * \endcode + * This code adds \a y to \a x for every element in \a v. For a more useful + * example, see alp::eWiseLambda. + * + * \warning Note that, unlike the above, this below code is illegal since it + * does not evaluate via a lambda passed to any of the above + * GraphBLAS lambda functions (such as alp::eWiseLambda). + * \code{.cpp} + * void f( + * Vector< D >::lambda_reference x, + * const Vector< D >::lambda_reference y + * ) { + * x += y; + * } + * \endcode + * Also this usage is illegal since it does not rely on any + * GraphBLAS-approved function listed above: + * \code{.cpp} + * void f( + * Vector< D >::lambda_reference x, + * const Vector< D >::lambda_reference y + * ) { + * std::functional< void() > f = + * [x,y](const size_t i) { + * x += y; + * }; + * f(); + * } + * \endcode + * + * \warning There is no similar concept in the official GraphBLAS specs. + * + * @see alp::Vector::operator[]() + * @see alp::eWiseLambda + */ + typedef D & lambda_reference; + + /** + * A standard iterator for the Vector< D > class. + * + * This iterator is used for data extraction only. Hence only this const + * version is supplied. + * + * \warning Comparing two const iterators corresponding to different + * containers leads to undefined behaviour. + * \warning Advancing an iterator past the end iterator of the container + * it corresponds to leads to undefined behaviour. + * \warning Modifying the contents of a container makes any use of any + * iterator derived from it incur invalid behaviour. + * \note These are standard limitations of STL iterators. + */ + class const_iterator : public std::iterator< std::forward_iterator_tag, std::pair< const size_t, const D >, size_t > { + + public : + + /** Standard equals operator. */ + bool + operator==( const const_iterator & other ) const { (void)other; return false; } + + /** @returns The negation of operator==(). */ + bool operator!=( const const_iterator & other ) const { + (void)other; + return true; + } + + /** + * Dereferences the current position of this iterator. + * + * @return If this iterator is valid and not in end position, + * this returns a new std::pair with in its first + * field the position of the nonzero value, and in its + * second field the value of the nonzero. + * + * \note If this iterator is invalid or in end position, the result is, + * undefined. + */ + std::pair< const size_t, const D > operator*() const { + return std::pair< const size_t, const D >(); + } + + /** + * Advances the position of this iterator by one. + * + * If the current position corresponds to the last element in the + * container, the new position of this iterator will be its end + * position. + * + * If the current position of this iterator is already the end + * position, this iterator will become invalid; any use of invalid + * iterators will lead to undefined behaviour. + * + * @return A reference to this iterator. + */ + const_iterator & operator++() { + return *this; + } + + }; // class const_iterator + + /** + * The only way to create an empty GraphBLAS vector. The given dimension will + * be fixed throughout the lifetime of this container. + * + * The vector will be empty after successful construction. + * + * @param[in] n The dimension of this vector. + * + * \parblock + * \par Performance semantics + * -# This constructor completes in \f$ \mathcal{O}(n) \f$ time. + * -# This constructor allocates \f$ \mathcal{O}(n) \f$ bytes of + * dynamic memory. + * -# This constructor moves at most \f$ \mathcal{O}( n ) \f$ bytes + * of data. + * -# This constructor may make system calls. + * \endparblock + * + * \warning Avoid the use of this constructor within performance critical + * code sections. + */ + Vector( const size_t n ) { + (void)n; + } + + /** + * Move constructor. + * + * This will make the new vector equal the given GraphBLAS vector while + * destroying the supplied GraphBLAS vector. + * + * This function always succeeds and will not throw exceptions. + * + * @param[in] x The GraphBLAS vector to move to this new container. + * + * \parblock + * \par Performance semantics + * -# This constructor completes in \f$ \Theta(1) \f$ time. + * -# This constructor does not allocate new data on the heap. + * -# This constructor uses \f$ \mathcal{O}(1) \f$ more memory than + * already used by this application at constructor entry. + * -# This constructor incurs at most \f$ \mathcal{O}(1) \f$ bytes of + * data movement. + * \endparblock + */ + Vector( Vector< D, implementation > &&x ) noexcept { + (void)x; + } + + /** + * Move-from-temporary assignment. + * + * @param[in,out] x The temporary instance from which this instance shall + * take over its resources. + * + * After a call to this function, \a x shall correspond to an empy vector. + * + * \parblock + * \par Performance semantics + * -# This move assignment completes in \f$ \Theta(1) \f$ time. + * -# This move assignment may not make system calls. + * -# this move assignment moves \f$ \Theta(1) \f$ data only. + * \endparblock + */ + Vector< D, implementation >& operator=( Vector< D, implementation > &&x ) noexcept { + (void)x; + return *this; + } + + /** + * Default destructor. Frees all associated memory areas. + * + * \parblock + * \par Performance semantics + * -# This destructor contains \f$ \mathcal{O}(n) \f$ work, where + * \f$ n \f$ is the capacity of this vector. + * -# This destructor is only allowed to free memory, not allocate. + * -# This destructor uses \f$ \mathcal{O}(1) \f$ more memory than + * already used by this application at entry. + * -# This destructor shall move at most \f$ \mathcal{O}(n) \f$ bytes + * of data. + * -# This destructor will make system calls. + * \endparblock + * + * \warning Avoid the use of this destructor within performance critical + * code sections. + * + * \note Destruction of this GraphBLAS container is the only way to + * guarantee that any underlying dynamically allocated memory is + * freed. + */ + ~Vector() {} + + //@{ + /** + * Provides the only mechanism to extract data from this GraphBLAS vector. + * + * The order in which nonzero elements are returned is undefined. + * + * @return An iterator pointing to the first element of this vector, if any; + * \em or an iterator in end position if this vector contains no + * nonzeroes. + * + * \note An `iterator in end position' compares equal to the const_iterator + * returned by cend(). + * + * \parblock + * \par Performance semantics + * -# This function contains \f$ \mathcal{O}(1) \f$ work. + * -# This function is allowed allocate dynamic memory. + * -# This function uses up to \f$ \mathcal{O}(1) \f$ more memory + * than already used by this application at entry. + * -# This function shall move at most \f$ \mathcal{O}(1) \f$ bytes + * of data. + * -# This function may make system calls. + * \endparblock + * + * \warning Avoid the use of this function within performance critical code + * sections. + * + * \note This function may make use of a const_iterator that is buffered, + * hence possibly causing its implicitly called constructor to + * allocate dynamic memory. + */ + const_iterator cbegin() const {} + + /** + * Same as cbegin(). + * Since iterators are only supplied as a data extraction mechanism, there + * is no overloaded version of this function that returns a non-const + * iterator. + */ + const_iterator begin() const {} + //@} + + //@{ + /** + * Indicates the end to the elements in this container. + * + * @return An iterator at the end position of this container. + * + * \parblock + * \par Performance semantics + * -# This function contains \f$ \mathcal{O}(1) \f$ work. + * -# This function is not allowed allocate dynamic memory. + * -# This function uses up to \f$ \mathcal{O}(1) \f$ more memory + * than already used by this application at entry. + * -# This function shall move at most \f$ \mathcal{O}(1) \f$ bytes + * of data. + * -# This function shall \em not induce any system calls. + * \endparblock + * + * \note Even if cbegin() returns a buffered const_iterator that may require + * dynamic memory allocation and additional data movement, this + * specification disallows the same to happen for the construction of + * an iterator in end position. + */ + const_iterator cend() const {} + + /** + * Same as cend(). + * Since iterators are only supplied as a data extraction mechanism, there + * is no overloaded version of this function that returns a non-const + * iterator. + */ + const_iterator end() const {} + //@} + + /** + * Copy from raw user-supplied data into a vector. + * + * This is the dense unmasked variant. + * + * @tparam descr The pre-processing descriptor to use. + * @tparam fwd_iterator The type of input iterator. By default, this will be + * a raw \em unaliased pointer. + * @tparam Accum The accumulator type used to merge incoming new + * elements with existing contents, if any. + * + * @param[in] accum The accumulator used to merge incoming new elements with + * existing content, if any. + * @param[in] start The iterator to the first element that should be copied + * into this GraphBLAS vector. + * @param[in] end Iterator shifted exactly one past the last element that + * should be copied into this GraphBLAS vector. + * @param[out] npos The last iterator position after exiting this function. + * In most cases this will equal \a end. This parameter is + * optional. + * + * The first element from \a it will be copied into the element with index + * \f$ 0 \f$ in this vector. The \f$ k \f$-th element will be copied into + * the element with index \f$ k - 1 \f$. The iterator \a start will be + * incremented along with \f$ k \f$ until it compares equal to \a end, or + * until it has been incremented \a n times, where \a n is the dimension of + * this vector. In the latter case, any remaining values are ignored. + * + * @return alp::SUCCESS This function always succeeds. + * + * \note The default accumulator expects \a val to be of the same type + * as nonzero elements in this function, and will cause old + * values to be overwritten by the incoming new values. + * + * \note Previous contents of the vector are retained. If these are to be + * cleared first, see clear(). The default accumulator is NOT an + * alternative since any pre-existing values corresponding to entries + * in the mask that evaluate to false will be retained. + * + * \note The parameter \a n can be used to ingest only a subset of a larger + * data structure pointed to by \a start. At the end of the call, \a + * start will then not be equal to \a end, but instead point to the + * first element of the remainder of the larger data structure. + * + * \par Valid descriptors + * alp::descriptors::no_operation, alp::descriptors::no_casting. + * + * \note Invalid descriptors will be ignored. + * + * If alp::descriptors::no_casting is specified, then 1) the first domain of + * \a accum must match the type of \a val, 2) the second domain must match + * the type \a D of nonzeroes in this vector, and 3) the third domain must + * match \a D. If one of these is not true, the code shall not compile. + * + * \parblock + * \par Performance semantics + * If the capacity of this container is sufficient to perform the + * requested operation, then: + * -# This function contains \f$ \Theta(n) \f$ work. + * -# This function will take at most \f$ \Theta(1) \f$ memory beyond + * the memory already used by the application before the call to + * this function. + * -# This function moves at most \f$ n ( 2\mathit{sizeof}(D) + + * \mathit{sizeof}(\mathit{bool}) ) + \mathcal{O}(1) \f$ bytes of + * data. + * \endparblock + * + * \parblock + * \par Performance exceptions + * If the capacity of this container at function entry is insufficient + * to perform the requested operation, then, in addition to the above: + * -# this function allocates \f$ \Theta(n) \f$ bytes of memory . + * -# this function frees \f$ \mathcal{O}(n) \f$ bytes of memory. + * -# this function will make system calls. + * \endparblock + * + * \note An implementation may ensure that at object construction the + * capacity is maximised. In that case, the above performance + * exceptions will never come to pass. + * + * @see alp::buildVector for the GraphBLAS standard dispatcher to this + * function. + */ + template< Descriptor descr = descriptors::no_operation, class Accum = typename operators::right_assign< D, D, D >, typename fwd_iterator = const D * __restrict__ > + RC build( const Accum & accum, const fwd_iterator start, const fwd_iterator end, fwd_iterator npos ) { + (void)accum; + (void)start; + (void)end; + (void)npos; + return PANIC; + } + + /** + * Copy from raw user-supplied data into a vector. + * + * This is the sparse non-masked variant. + * + * @tparam descr The pre-processing descriptor to use. + * @tparam Accum The type of the operator used to combine newly input + * data with existing data, if any. + * @tparam ind_iterator The type of index input iterator. By default, this + * will be a raw \em unaliased pointer to elements of + * type \a size_t. + * @tparam nnz_iterator The type of nonzero input iterator. By default, this + * will be a raw \em unaliased pointer to elements of + * type \a D. + * @tparam Dup The type of operator used to combine any duplicate + * input values. + * + * @param[in] accum The operator to be used when writing back the result + * of data that was already in this container prior to + * calling this function. + * @param[in] ind_start The iterator to the first index value that should be + * added to this GraphBLAS vector. + * @param[in] ind_end Iterator corresponding to the end position of + * \a ind_start. + * @param[in] nnz_start The iterator to the first nonzero value that should + * be added to this GraphBLAS vector. + * @param[in] nnz_end Iterator corresponding to the end position of + * \a nnz_start. + * @param[in] dup The operator to be used when handling multiple + * nonzero values that are to be mapped to the same + * index position. + * + * The first element from \a nnz_start will be copied into this vector at + * the index corresponding to the first element from \a ind_start. Then, + * both nonzero and index value iterators advance to add the next input + * element and the process repeats until either of the input iterators + * reach \a nnz_end or \a ind_end, respectively. + * If at that point one of the iterators still has remaining elements, then + * those elements are ignored. + * + * @return alp::MISMATCH When attempting to insert a nonzero value at an + * index position that is larger or equal to the + * dimension of this vector. When this code is + * returned, the contents of this container are + * undefined. + * @return alp::SUCCESS When all elements are successfully assigned. + * + * \note The default accumulator expects \a D to be of the same type + * as nonzero elements of this operator, and will cause old + * values to be overwritten by the incoming new values. + * + * \note The default \a dup expects \a D to be of the same type as nonzero + * elements of this operator, and will cause duplicate values to be + * discarded in favour of the last seen value. + * + * \note Previous contents of the vector are retained. If these are to be + * cleared first, see clear(). The default accumulator is NOT an + * alternative since any pre-existing values corresponding to entries + * in the mask that evaluate to false will be retained. + * + * \par Valid descriptors + * alp::descriptors::no_operation, alp::descriptors::no_casting, + * alp::descriptors::no_duplicates. + * + * \note Invalid descriptors will be ignored. + * + * If alp::descriptors::no_casting is specified, then 1) the first domain of + * \a accum must match the type of \a D, 2) the second domain must match + * nnz_iterator::value_type, and 3) the third domain must \a D. If one of + * these is not true, the code shall not compile. + * + * \parblock + * \par Performance semantics. + * -# This function contains \f$ \Theta(n) \f$ work. + * -# This function will take at most \f$ \Theta(1) \f$ memory beyond + * the memory already used by the application before the call to + * this function. + * -# This function moves at most \f$ n ( 2\mathit{sizeof}(D) + + * \mathit{sizeof}(\mathit{bool}) ) + \mathcal{O}(1) \f$ bytes of + * data. + * \endparblock + * + * \parblock + * \par Performance exceptions + * If the capacity of this container at function entry is insufficient + * to perform the requested operation, then, in addition to the above: + * -# this function allocates \f$ \Theta(n) \f$ bytes of memory . + * -# this function frees \f$ \mathcal{O}(n) \f$ bytes of memory. + * -# this function will make system calls. + * \endparblock + * + * \note An implementation may ensure that at object construction the + * capacity is maximised. In that case, the above performance + * exceptions will never come to pass. + * + * @see alp::buildVector for the GraphBLAS standard dispatcher to this + * function. + */ + template< Descriptor descr = descriptors::no_operation, + class Accum = operators::right_assign< D, D, D >, + typename ind_iterator = const size_t * __restrict__, + typename nnz_iterator = const D * __restrict__, + class Dup = operators::right_assign< D, D, D > > + RC build( const Accum & accum, const ind_iterator ind_start, const ind_iterator ind_end, const nnz_iterator nnz_start, const nnz_iterator nnz_end, const Dup & dup = Dup() ) { + (void)accum; + (void)ind_start; + (void)ind_end; + (void)nnz_start; + (void)nnz_end; + (void)dup; + return PANIC; + } + + /** + * Copy from raw user-supplied data into a vector. + * + * This is the sparse masked variant. + * + * @tparam descr The pre-processing descriptor to use. + * @tparam mask_type The value type of the \a mask vector. This type is + * \em not required to be \a bool. + * @tparam Accum The type of the operator used to combine newly input + * data with existing data, if any. + * @tparam ind_iterator The type of index input iterator. By default, this + * will be a raw \em unaliased pointer to elements of + * type \a size_t. + * @tparam nnz_iterator The type of nonzero input iterator. By default, this + * will be a raw \em unaliased pointer to elements of + * type \a D. + * @tparam Dup The type of operator used to combine any duplicate + * input values. + * + * @param[in] mask An element is only added to this container if its + * index \f$ i \f$ has a nonzero at the same position + * in \a mask that evaluates true. + * @param[in] accum The operator to be used when writing back the result + * of data that was already in this container prior to + * calling this function. + * @param[in] ind_start The iterator to the first index value that should be + * added to this GraphBLAS vector. + * @param[in] ind_end Iterator corresponding to the end position of + * \a ind_start. + * @param[in] nnz_start The iterator to the first nonzero value that should + * be added to this GraphBLAS vector. + * @param[in] nnz_end Iterator corresponding to the end position of + * \a nnz_start. + * @param[in] dup The operator to be used when handling multiple + * nonzero values that are to be mapped to the same + * index position. + * + * The first element from \a nnz_start will be copied into this vector at + * the index corresponding to the first element from \a ind_start. Then, + * both nonzero and index value iterators advance to add the next input + * element and the process repeats until either of the input iterators + * reach \a nnz_end or \a ind_end, respectively. + * If at that point one of the iterators still has remaining elements, then + * those elements are ignored. + * + * @return alp::MISMATCH When attempting to insert a nonzero value at an + * index position that is larger or equal to the + * dimension of this vector. When this code is + * returned, the contents of this container are + * undefined. + * @return alp::SUCCESS When all elements are successfully assigned. + * + * \note The default accumulator expects \a D to be of the same type + * as nonzero elements of this operator, and will cause old + * values to be overwritten by the incoming new values. + * + * \note The default \a dup expects \a D to be of the same type as nonzero + * elements of this operator, and will cause duplicate values to be + * discarded in favour of the last seen value. + * + * \note Previous contents of the vector are retained. If these are to be + * cleared first, see clear(). The default accumulator is NOT an + * alternative since any pre-existing values corresponding to entries + * in the mask that evaluate to false will be retained. + * + * \par Valid descriptors + * alp::descriptors::no_operation, alp::descriptors::no_casting, + * alp::descriptors::invert_mask, alp::descriptors::no_duplicates. + * + * \note Invalid descriptors will be ignored. + * + * If alp::descriptors::no_casting is specified, then 1) the first domain of + * \a accum must match the type of \a D, 2) the second domain must match + * nnz_iterator::value_type, and 3) the third domain must \a D. If one of + * these is not true, the code shall not compile. + * + * \parblock + * \par Performance semantics. + * -# This function contains \f$ \Theta(n) \f$ work. + * -# This function will take at most \f$ \Theta(1) \f$ memory beyond + * the memory already used by the application before the call to + * this function. + * -# This function moves at most \f$ n ( 2\mathit{sizeof}(D) + + * \mathit{sizeof}(\mathit{bool}) ) + \mathcal{O}(1) \f$ bytes of + * data. + * \endparblock + * + * \parblock + * \par Performance exceptions + * If the capacity of this container at function entry is insufficient + * to perform the requested operation, then, in addition to the above: + * -# this function allocates \f$ \Theta(n) \f$ bytes of memory . + * -# this function frees \f$ \mathcal{O}(n) \f$ bytes of memory. + * -# this function will make system calls. + * \endparblock + * + * \note An implementation may ensure that at object construction the + * capacity is maximised. In that case, the above performance + * exceptions will never come to pass. + * + * @see alp::buildVector for the GraphBLAS standard dispatcher to this + * function. + */ + template< Descriptor descr = descriptors::no_operation, + typename mask_type, + class Accum, + typename ind_iterator = const size_t * __restrict__, + typename nnz_iterator = const D * __restrict__, + class Dup = operators::right_assign< D, typename nnz_iterator::value_type, D > > + RC build( const Vector< mask_type, implementation > mask, + const Accum & accum, + const ind_iterator ind_start, + const ind_iterator ind_end, + const nnz_iterator nnz_start, + const nnz_iterator nnz_end, + const Dup & dup = Dup() ) { + (void)mask; + (void)accum; + (void)ind_start; + (void)ind_end; + (void)nnz_start; + (void)nnz_end; + (void)dup; + return PANIC; + } + + /** + * Return the dimension of this vector. + * + * @tparam T The integral output type. + * + * @param[out] size Where to store the size of this vector. + * The initial value is ignored. + * + * @returns alp::SUCCESS When the function call completes successfully. + * + * \note This function cannot fail. + * + * \parblock + * \par Performance semantics + * This function + * -# contains \f$ \Theta(1) \f$ work, + * -# will not allocate new dynamic memory, + * -# will take at most \f$ \Theta(1) \f$ memory beyond the memory + * already used by the application before the call to this + * function. + * -# will move at most \f$ \mathit{sizeof}(T) + + * \mathit{sizeof}(\mathit{size\_t}) \f$ bytes of data. + * \endparblock + */ + template< typename T > + RC size( T & size ) const { + (void)size; + return PANIC; + } + + /** + * Return the number of nonzeroes in this vector. + * + * @tparam T The integral output type. + * + * @param[out] nnz Where to store the number of nonzeroes contained in this + * vector. Its initial value is ignored. + * + * @returns alp::SUCCESS When the function call completes successfully. + * + * \note This function cannot fail. + * + * \parblock + * \par Performance semantics + * This function + * -# contains \f$ \Theta(1) \f$ work, + * -# will not allocate new dynamic memory, + * -# will take at most \f$ \Theta(1) \f$ memory beyond the memory + * already used by the application before the call to this + * function. + * -# will move at most \f$ \mathit{sizeof}(T) + + * \mathit{sizeof}(\mathit{size\_t}) \f$ bytes of data. + * \endparblock + */ + template< typename T > + RC nnz( T & nnz ) const { + (void)nnz; + return PANIC; + } + + /** + * Returns a lambda reference to an element of this sparse vector. + * + * A lambda reference to an element of this vector is only valid when used + * inside a lambda function evaluated via alp::eWiseLambda. The lambda + * function is called for specific indices only-- that is, the GraphBLAS + * implementation decides at which elements to dereference this container. + * Outside this scope the returned reference incurs undefined behaviour. + * + * \warning In particular, for the given index \a i by the lambda function, + * it shall be \em illegal to refer to indices relative to that + * \a i; including, but not limited to, \f$ i+1 \f$, \f$ i-1 \f$, et + * cetera. + * + * \note As a consequence, this function cannot be used to perform stencil + * or halo based operations. + * + * If a previously non-existing entry of the vector is requested, a new + * nonzero is added at position \a i in this vector. The new element will + * have its initial value equal to the \em identity corresponding to the + * given monoid. + * + * \warning In parallel contexts the use of a returned lambda reference + * outside the context of an eWiseLambda will incur at least one of + * the following ill effects: it may + * -# fail outright, + * -# work on stale data, + * -# work on incorrect data, or + * -# incur high communication costs to guarantee correctness. + * In short, such usage causes undefined behaviour. Implementers are + * \em not advised to provide GAS-like functionality through this + * interface, as it invites bad programming practices and bad + * algorithm design decisions. This operator is instead intended to + * provide for generic BLAS1-type operations only. + * + * \note For I/O, use the iterator retrieved via cbegin() instead of + * relying on a lambda_reference. + * + * @param[in] i Which element to return a lambda reference of. + * @param[in] monoid Under which generalised monoid to interpret the + * requested \f$ i \f$th element of this vector. + * + * \note The \a monoid (or a ring) is required to be able to interpret a + * sparse vector. A user who is sure this vector is dense, or otherwise + * is able to ensure that the a lambda_reference will only be requested + * at elements where nonzeroes already exists, may refer to + * Vector::operator[], + * + * @return A lambda reference to the element \a i of this vector. + * + * \par Example. + * See alp::eWiseLambda() for a practical and useful example. + * + * \warning There is no similar concept in the official GraphBLAS specs. + * + * @see lambda_reference For more details on the returned reference type. + * @see alp::eWiseLambda For one legal way in which to use the returned + * #lambda_reference. + */ + template< class Monoid > + lambda_reference operator()( const size_t i, const Monoid & monoid = Monoid() ) { + (void)i; + (void)monoid; + return PANIC; + } + + /** + * Returns a lambda reference to an element of this vector. The user + * ensures that the requested reference only corresponds to a pre-existing + * nonzero in this vector, or undefined behaviour will occur. + * + * A lambda reference to an element of this vector is only valid when used + * inside a lambda function evaluated via alp::eWiseLambda. The lambda + * function is called for specific indices only-- that is, the GraphBLAS + * implementation decides at which elements to dereference this container. + * Outside this scope the returned reference incurs undefined behaviour. + * + * \warning In particular, for the given index \a i by the lambda function, + * it shall be \em illegal to refer to indices relative to that + * \a i; including, but not limited to, \f$ i+1 \f$, \f$ i-1 \f$, et + * cetera. + * + * \note As a consequence, this function cannot be used to perform stencil + * or halo based operations. + * + * If a previously non-existing entry of the vector is requested, undefined + * behaviour will occur. Functions that are defined to work with references + * of this kind, such as alp::eWiseLambda, define exactly which elements are + * dereferenced. + * + * \warning In parallel contexts the use of a returned lambda reference + * outside the context of an eWiseLambda will incur at least one of + * the following ill effects: it may + * -# fail outright, + * -# work on stale data, + * -# work on incorrect data, or + * -# incur high communication costs to guarantee correctness. + * In short, such usage causes undefined behaviour. Implementers are + * \em not advised to provide GAS-like functionality through this + * interface, as it invites bad programming practices and bad + * algorithm design decisions. This operator is instead intended to + * provide for generic BLAS1-type operations only. + * + * \note For I/O, use the iterator retrieved via cbegin() instead of + * relying on a lambda_reference. + * + * @param[in] i Which element to return a lambda reference of. + * @param[in] ring Under which generalised semiring to interpret the + * requested \f$ i \f$th element of this vector. + * + * \note The \a ring is required to be able to interpret a sparse vector. A + * user who is sure this vector is dense, or otherwise is able to + * ensure that the a lambda_reference will only be requested at + * elements where nonzeroes already exists, may refer to + * Vector::operator[], + * + * @return A lambda reference to the element \a i of this vector. + * + * \par Example. + * See alp::eWiseLambda() for a practical and useful example. + * + * \warning There is no similar concept in the official GraphBLAS specs. + * + * @see lambda_reference For more details on the returned reference type. + * @see alp::eWiseLambda For one legal way in which to use the returned + * #lambda_reference. + */ + lambda_reference operator[]( const size_t i ) { + (void)i; +#ifndef _ALP_NO_EXCEPTIONS + assert( false ); // Requesting lambda reference of unimplemented Vector backend. #endif - } -}; + } + }; // class Vector + } // namespace internal template< typename T, typename Structure, enum Density density, typename View, enum Backend backend > - class VectorView { }; + class Vector { }; } -#endif // _H_GRB_VECTOR_BASE +#endif // _H_ALP_VECTOR_BASE diff --git a/include/alp/blas0.hpp b/include/alp/blas0.hpp index 96c1551b1..ed2cb0bef 100644 --- a/include/alp/blas0.hpp +++ b/include/alp/blas0.hpp @@ -20,16 +20,16 @@ * @date 5th of December 2016 */ -#ifndef _H_GRB_BLAS0 -#define _H_GRB_BLAS0 +#ifndef _H_ALP_BLAS0 +#define _H_ALP_BLAS0 #include #include #include //enable_if -#include "graphblas/descriptors.hpp" -#include "graphblas/rc.hpp" -#include "graphblas/type_traits.hpp" +#include "alp/descriptors.hpp" +#include "alp/rc.hpp" +#include "alp/type_traits.hpp" #define NO_CAST_ASSERT( x, y, z ) \ static_assert( x, \ @@ -55,7 +55,7 @@ "************************************************************************" \ "**********************\n" ); -namespace grb { +namespace alp { /** * \defgroup BLAS0 The Level-0 Basic Linear Algebra Subroutines (BLAS) @@ -64,28 +64,28 @@ namespace grb { * zero-dimensional containers, i.e., on scalars. * * The GraphBLAS uses opaque data types and defines several standard functions - * to operate on these data types. Examples types are grb::Vector and - * grb::Matrix, example functions are grb::dot and grb::vxm. + * to operate on these data types. Examples types are alp::Vector and + * alp::Matrix, example functions are alp::dot and alp::vxm. * * To input data into an opaque GraphBLAS type, each opaque type defines a - * member function \a build: grb::Vector::build() and grb::Matrix::build(). + * member function \a build: alp::Vector::build() and alp::Matrix::build(). * * To extract data from opaque GraphBLAS types, each opaque type provides * \em iterators that may be obtained via the STL standard \a begin and \a end * functions: - * - grb::Vector::begin or grb::Vector::cbegin - * - grb::Vector::end or grb::Vector::cend - * - grb::Matrix::begin or grb::Matrix::cbegin - * - grb::Matrix::end or grb::Matrix::cend + * - alp::Vector::begin or alp::Vector::cbegin + * - alp::Vector::end or alp::Vector::cend + * - alp::Matrix::begin or alp::Matrix::cbegin + * - alp::Matrix::end or alp::Matrix::cend * * Some GraphBLAS functions, however, reduce all elements in a GraphBLAS - * container into a single element of a given type. So for instance, grb::dot - * on two vectors of type grb::Vector using the regular real semiring - * grb::Semiring will store its output in a variable of type \a double. + * container into a single element of a given type. So for instance, alp::dot + * on two vectors of type alp::Vector using the regular real semiring + * alp::Semiring will store its output in a variable of type \a double. * * When parametrising GraphBLAS functions in terms of arbitrary Semirings, * Monoids, Operators, and object types, it is useful to have a way to apply - * the same operators on whatever type they make functions like grb::dot + * the same operators on whatever type they make functions like alp::dot * produce-- that is, we require functions that enable the application of * GraphBLAS operators on single elements. * @@ -108,8 +108,8 @@ namespace grb { * * \parblock * \par Valid descriptors - * -# grb::descriptors::no_operation for default behaviour. - * -# grb::descriptors::no_casting when a call to this function should *not* + * -# alp::descriptors::no_operation for default behaviour. + * -# alp::descriptors::no_casting when a call to this function should *not* * automatically cast input arguments to operator input domain, and *not* * automatically cast operator output to the output argument domain. * \endparblock @@ -117,7 +117,7 @@ namespace grb { * If \a InputType1 does not match the left-hand side input domain of \a OP, * or if \a InputType2 does not match the right-hand side input domain of * \a OP, or if \a OutputType does not match the output domain of \a OP while - * grb::descriptors::no_casting was set, then the code shall not compile. + * alp::descriptors::no_casting was set, then the code shall not compile. * * @param[in] x The left-hand side input data. * @param[in] y The right-hand side input data. @@ -128,19 +128,19 @@ namespace grb { * Thus there are two ways of calling this function: * -# * double a, b, c; - * grb::apply< grb::operators::add >( a, b, c ); + * alp::apply< alp::operators::add >( a, b, c ); * , or * -# * double a, b, c; - * grb::operators::add< double > addition_over_doubles; - * grb::apply( a, b, c, addition_over_doubles); + * alp::operators::add< double > addition_over_doubles; + * alp::apply( a, b, c, addition_over_doubles); * * * \note There should be no performance difference between the two ways of * calling this function. For compatibility with other GraphBLAS * implementations, the latter type of call is preferred. * - * @return grb::SUCCESS A call to this function never fails. + * @return alp::SUCCESS A call to this function never fails. * * \parblock * \par Performance semantics. @@ -156,13 +156,13 @@ namespace grb { * \endparblock * * \warning The use of stateful operators, or even thus use of stateless - * operators that are not included in grb::operators, may cause this + * operators that are not included in alp::operators, may cause this * function to incur performance penalties beyond the worst case * sketched above. * * @see foldr for applying an operator in-place (if allowed). * @see foldl for applying an operator in-place (if allowed). - * @see grb::operators::internal::Operator for a discussion on when foldr and + * @see alp::operators::internal::Operator for a discussion on when foldr and * foldl successfully generate in-place code. */ template< Descriptor descr = descriptors::no_operation, @@ -174,10 +174,10 @@ namespace grb { const InputType2 &y, const OP &op = OP(), const typename std::enable_if< - grb::is_operator< OP >::value && - !grb::is_object< InputType1 >::value && - !grb::is_object< InputType2 >::value && - !grb::is_object< OutputType >::value, + alp::is_operator< OP >::value && + !alp::is_object< InputType1 >::value && + !alp::is_object< InputType2 >::value && + !alp::is_object< OutputType >::value, void >::type * = NULL ) { // static sanity check @@ -186,7 +186,7 @@ namespace grb { std::is_same< InputType2, typename OP::D2 >::value && std::is_same< OutputType, typename OP::D3 >::value ) ), - "grb::apply (BLAS level 0)", + "alp::apply (BLAS level 0)", "Argument value types do not match operator domains while no_casting " "descriptor was set" ); @@ -218,14 +218,14 @@ namespace grb { * * \parblock * \par Valid descriptors - * -# grb::descriptors::no_operation for default behaviour. - * -# grb::descriptors::no_casting when a call to this function should *not* + * -# alp::descriptors::no_operation for default behaviour. + * -# alp::descriptors::no_casting when a call to this function should *not* * automatically cast input arguments to operator input domain, and *not* * automatically cast operator output to the output argument domain. * \endparblock * * If \a InputType does not match the left-hand side input domain - * (see grb::operators::internal::Operator::D1) corresponding to \a OP, then + * (see alp::operators::internal::Operator::D1) corresponding to \a OP, then * \a x will be temporarily cached and cast into \a D1. * If \a IOType does not match the right-hand side input domain corresponding * to \a OP, then \a y will be temporarily cached and cast into \a D2. @@ -238,7 +238,7 @@ namespace grb { * On function exit: the output of the operator. * @param[in] op The operator to apply (optional). * - * @return grb::SUCCESS A call to this function never fails. + * @return alp::SUCCESS A call to this function never fails. * * \parblock * \par Performance semantics. @@ -255,11 +255,11 @@ namespace grb { * \endparblock * * \warning The use of stateful operators, or even thus use of stateless - * operators that are not included in grb::operators, may cause this + * operators that are not included in alp::operators, may cause this * function to incur performance penalties beyond the worst case * sketched above. * - * \note For the standard stateless operators in grb::operators, there are + * \note For the standard stateless operators in alp::operators, there are * no additional temporary storage requirements nor any additional data * movement requirements than the ones mentioned above. * @@ -269,18 +269,18 @@ namespace grb { * @see foldl for a left-hand in-place version. * @see apply for an example of how to call this function without explicitly * passing \a op. - * @see grb::operators::internal Operator for a discussion on fold-right + * @see alp::operators::internal Operator for a discussion on fold-right * capable operators and on stateful operators. */ template< Descriptor descr = descriptors::no_operation, class OP, typename InputType, typename IOType > static RC foldr( const InputType & x, IOType & y, const OP & op = OP(), - const typename std::enable_if< grb::is_operator< OP >::value && ! grb::is_object< InputType >::value && ! grb::is_object< IOType >::value, void >::type * = NULL ) { + const typename std::enable_if< alp::is_operator< OP >::value && ! alp::is_object< InputType >::value && ! alp::is_object< IOType >::value, void >::type * = NULL ) { // static sanity check NO_CAST_ASSERT( ( ! ( descr & descriptors::no_casting ) || ( std::is_same< InputType, typename OP::D1 >::value && std::is_same< IOType, typename OP::D2 >::value && std::is_same< IOType, typename OP::D3 >::value ) ), - "grb::foldr (BLAS level 0)", + "alp::foldr (BLAS level 0)", "Argument value types do not match operator domains while no_casting " "descriptor was set" ); @@ -310,14 +310,14 @@ namespace grb { * * \parblock * \par Valid descriptors - * -# grb::descriptors::no_operation for default behaviour. - * -# grb::descriptors::no_casting when a call to this function should *not* + * -# alp::descriptors::no_operation for default behaviour. + * -# alp::descriptors::no_casting when a call to this function should *not* * automatically cast input arguments to operator input domain, and *not* * automatically cast operator output to the output argument domain. * \endparblock * * If \a InputType does not match the right-hand side input domain - * (see grb::operators::internal::Operator::D2) corresponding to \a OP, then + * (see alp::operators::internal::Operator::D2) corresponding to \a OP, then * \a x will be temporarily cached and cast into \a D2. * If \a IOType does not match the left-hand side input domain corresponding * to \a OP, then \a y will be temporarily cached and cast into \a D1. @@ -330,7 +330,7 @@ namespace grb { * @param[in] y The right-hand side input parameter. * @param[in] op The operator to apply (optional). * - * @return grb::SUCCESS A call to this function never fails. + * @return alp::SUCCESS A call to this function never fails. * * \parblock * \par Performance semantics. @@ -347,11 +347,11 @@ namespace grb { * \endparblock * * \warning The use of stateful operators, or even thus use of stateless - * operators that are not included in grb::operators, may cause this + * operators that are not included in alp::operators, may cause this * function to incur performance penalties beyond the worst case * sketched above. * - * \note For the standard stateless operators in grb::operators, there are + * \note For the standard stateless operators in alp::operators, there are * no additional temporary storage requirements nor any additional data * movement requirements than the ones mentioned above. * @@ -361,18 +361,18 @@ namespace grb { * @see foldr for a right-hand in-place version. * @see apply for an example of how to call this function without explicitly * passing \a op. - * @see grb::operators::internal Operator for a discussion on fold-right + * @see alp::operators::internal Operator for a discussion on fold-right * capable operators and on stateful operators. */ template< Descriptor descr = descriptors::no_operation, class OP, typename InputType, typename IOType > static RC foldl( IOType & x, const InputType & y, const OP & op = OP(), - const typename std::enable_if< grb::is_operator< OP >::value && ! grb::is_object< InputType >::value && ! grb::is_object< IOType >::value, void >::type * = NULL ) { + const typename std::enable_if< alp::is_operator< OP >::value && ! alp::is_object< InputType >::value && ! alp::is_object< IOType >::value, void >::type * = NULL ) { // static sanity check NO_CAST_ASSERT( ( ! ( descr & descriptors::no_casting ) || ( std::is_same< IOType, typename OP::D1 >::value && std::is_same< InputType, typename OP::D2 >::value && std::is_same< IOType, typename OP::D3 >::value ) ), - "grb::foldl (BLAS level 0)", + "alp::foldl (BLAS level 0)", "Argument value types do not match operator domains while no_casting " "descriptor was set" ); @@ -395,7 +395,7 @@ namespace grb { * nonzero value from a vector, or its corresponding coordinate. * * This class hence makes the use of the following descriptor(s) transparent: - * -# #grb::descriptors::use_index + * -# #alp::descriptors::use_index * * @tparam descr The descriptor under which to write back either the value or * the index. @@ -404,14 +404,14 @@ namespace grb { * @tparam Enabled Controls, through SFINAE, whether the use of the * #use_index descriptor is allowed at all. */ - template< grb::Descriptor descr, typename OutputType, typename D, typename Enabled = void > + template< alp::Descriptor descr, typename OutputType, typename D, typename Enabled = void > class ValueOrIndex; /* Version where use_index is allowed. */ - template< grb::Descriptor descr, typename OutputType, typename D > + template< alp::Descriptor descr, typename OutputType, typename D > class ValueOrIndex< descr, OutputType, D, typename std::enable_if< std::is_arithmetic< OutputType >::value && ! std::is_same< D, void >::value >::type > { private: - static constexpr const bool use_index = descr & grb::descriptors::use_index; + static constexpr const bool use_index = descr & alp::descriptors::use_index; static_assert( use_index || std::is_convertible< D, OutputType >::value, "Cannot convert to the requested output type" ); public: @@ -432,7 +432,7 @@ namespace grb { }; /* Version where use_index is not allowed. */ - template< grb::Descriptor descr, typename OutputType, typename D > + template< alp::Descriptor descr, typename OutputType, typename D > class ValueOrIndex< descr, OutputType, D, typename std::enable_if< ! std::is_arithmetic< OutputType >::value && ! std::is_same< OutputType, void >::value >::type > { static_assert( ! ( descr & descriptors::use_index ), "use_index descriptor given while output type is not numeric" ); static_assert( std::is_convertible< D, OutputType >::value, "Cannot convert input to the given output type" ); @@ -487,17 +487,17 @@ namespace grb { static void set( OutputType & out, const InputType & in, const Operator & op ) { const auto identity = identity_left ? Identity< typename Operator::D1 >::value() : Identity< typename Operator::D2 >::value(); if( identity_left ) { - (void)grb::apply( out, identity, in, op ); + (void)alp::apply( out, identity, in, op ); } else { - (void)grb::apply( out, in, identity, op ); + (void)alp::apply( out, in, identity, op ); } } }; } // namespace internal -} // namespace grb +} // namespace alp #undef NO_CAST_ASSERT -#endif // end ``_H_GRB_BLAS0'' +#endif // end ``_H_ALP_BLAS0'' diff --git a/include/alp/blas1.hpp b/include/alp/blas1.hpp index d4fa9b059..374d19d43 100644 --- a/include/alp/blas1.hpp +++ b/include/alp/blas1.hpp @@ -20,27 +20,18 @@ * @date 29th of March 2017 */ -#ifndef _H_GRB_BLAS1 -#define _H_GRB_BLAS1 +#ifndef _H_ALP_BLAS1 +#define _H_ALP_BLAS1 -#include -#include -#include -#include +#include +#include +#include +#include #include "base/vector.hpp" -#ifdef _GRB_WITH_REFERENCE - #include -#endif -#ifdef _GRB_WITH_DENSEREF - #include -#endif -#ifdef _GRB_WITH_BANSHEE - #include -#endif -#ifdef _GRB_WITH_LPF - #include +#ifdef _ALP_WITH_REFERENCE + #include #endif // the remainder implements several backend-agnostic short-cuts @@ -68,13 +59,13 @@ "************************************************************************" \ "**********************\n" ); -namespace grb { +namespace alp { /** * A standard vector to use for mask parameters. Indicates no mask shall be * used. */ - #define NO_MASK Vector< bool >( 0 ) + #define NO_MASK internal::Vector< bool >( 0 ) /** * Executes an arbitrary element-wise user-defined function \a f using any @@ -82,7 +73,7 @@ namespace grb { * given vector \a x. * * The user-defined function is passed as a lambda which can capture, at - * the very least, other instances of type grb::Vector. Use of this function + * the very least, other instances of type alp::Vector. Use of this function * is preferable whenever multiple element-wise operations are requested that * use one or more identical input vectors. Performing the computation one * after the other in blocking mode would require the same vector to be @@ -90,32 +81,32 @@ namespace grb { * fused explicitly instead. * * It shall always be legal to capture non-GraphBLAS objects for read access - * only. It shall \em not be legal to capture instances of type grb::Matrix + * only. It shall \em not be legal to capture instances of type alp::Matrix * for read and/or write access. * - * If grb::Properties::writableCaptured evaluates true then captured + * If alp::Properties::writableCaptured evaluates true then captured * non-GraphBLAS objects can also be written to, not just read from. The * captured variable is, however, completely local to the calling user process * only-- it will not be synchronised between user processes. * As a rule of thumb, data-centric GraphBLAS implementations \em cannot - * support this and will thus have grb::Properties::writableCaptured evaluate + * support this and will thus have alp::Properties::writableCaptured evaluate * to false. A portable GraphBLAS algorithm should provide a different code * path to handle this case. * When it is legal to write to captured scalar, this function can, e.g., be * used to perform reduction-like operations on any number of equally sized * input vectors. This would be preferable to a chained number of calls to - * grb::dot in case where some vectors are shared between subsequent calls, + * alp::dot in case where some vectors are shared between subsequent calls, * for example; the shared vectors are streamed only once using this lambda- * enabled function. * * \warning The lambda shall only be executed on the data local to the user * process calling this function! This is different from the various - * fold functions, or grb::dot, in that the semantics of those + * fold functions, or alp::dot, in that the semantics of those * functions always end with a globally synchronised result. To * achieve the same effect with user-defined lambdas, the users * should manually prescribe how to combine the local results into * global ones, for instance, by a subsequent call to - * grb::collectives<>::allreduce. + * alp::collectives<>::allreduce. * * \note This is an addition to the GraphBLAS. It is alike user-defined * operators, monoids, and semirings, except it allows execution on @@ -142,9 +133,9 @@ namespace grb { * \a f. * @param[in] args All vectors the lambda is to access elements of. Must be of * the same length as \a x. If this constraint is violated, - * grb::MISMATCH shall be returned. This is a variadic + * alp::MISMATCH shall be returned. This is a variadic * argument and can contain any number of containers of type - * grb::Vector, passed as though they were separate + * alp::Vector, passed as though they were separate * arguments. * * \note In future GraphBLAS implementations, \a args, apart from doing @@ -153,7 +144,7 @@ namespace grb { * implementations do not require this since they use the same static * distribution for all containers. * - * \warning Using a grb::Vector inside a lambda passed to this function while + * \warning Using a alp::Vector inside a lambda passed to this function while * not passing that same vector into \a args, will result in undefined * behaviour. * @@ -165,8 +156,8 @@ namespace grb { * of \a f: x[i] += x[i+1]. Vectors can only be * dereferenced at position \a i and \a i alone. * - * @return grb::SUCCESS When the lambda is successfully executed. - * @return grb::MISMATCH When two or more vectors passed to \a args are not of + * @return alp::SUCCESS When the lambda is successfully executed. + * @return alp::MISMATCH When two or more vectors passed to \a args are not of * equal length. * * \parblock @@ -177,25 +168,25 @@ namespace grb { * \code * void f( * double &alpha, - * grb::Vector< double > &y, + * alp::Vector< double > &y, * const double beta, - * const grb::Vector< double > &x, - * const grb::Semiring< double > ring + * const alp::Vector< double > &x, + * const alp::Semiring< double > ring * ) { - * assert( grb::size(x) == grb::size(y) ); - * assert( grb::nnz(x) == grb::size(x) ); - * assert( grb::nnz(y) == grb::size(y) ); + * assert( alp::size(x) == alp::size(y) ); + * assert( alp::nnz(x) == alp::size(x) ); + * assert( alp::nnz(y) == alp::size(y) ); * alpha = ring.getZero(); - * grb::eWiseLambda( + * alp::eWiseLambda( * [&alpha,beta,&x,&y,ring]( const size_t i ) { * double mul; * const auto mul_op = ring.getMultiplicativeOperator(); * const auto add_op = ring.getAdditiveOperator(); - * grb::apply( y[i], beta, x[i], mul_op ); - * grb::apply( mul, x[i], y[i], mul_op ); - * grb::foldl( alpha, mul, add_op ); + * alp::apply( y[i], beta, x[i], mul_op ); + * alp::apply( mul, x[i], y[i], mul_op ); + * alp::foldl( alpha, mul, add_op ); * }, x, y ); - * grb::collectives::allreduce( alpha, add_op ); + * alp::collectives::allreduce( alpha, add_op ); * } * \endcode * @@ -209,8 +200,8 @@ namespace grb { * equivalent to: * * \code - * grb::eWiseMul( y, beta, x, ring ); - * grb::dot( alpha, x, y, ring ); + * alp::eWiseMul( y, beta, x, ring ); + * alp::dot( alpha, x, y, ring ); * \endcode * * The version using the lambdas, however, is expected to execute @@ -222,12 +213,12 @@ namespace grb { * \code * template< class Operator > * void f( - * grb::Vector< double > &x, + * alp::Vector< double > &x, * const Operator op * ) { - * grb::eWiseLambda( + * alp::eWiseLambda( * [&x,&op]( const size_t i ) { - * grb::apply( x[i], x[i], x[i+1], op ); + * alp::apply( x[i], x[i], x[i+1], op ); * }, x ); * } * \endcode @@ -247,12 +238,11 @@ namespace grb { typename Func, typename DataType, Backend backend, - typename Coords, typename... Args > RC eWiseLambda( const Func f, - const Vector< DataType, backend, Coords > & x, Args... + const internal::Vector< DataType, backend > & x, Args... ) { (void)f; (void)x; @@ -269,18 +259,17 @@ namespace grb { Descriptor descr = descriptors::no_operation, class Monoid, typename IOType, typename InputType, - Backend backend, - typename Coords + Backend backend > RC foldl( IOType &x, - const Vector< InputType, backend, Coords > &y, + const internal::Vector< InputType, backend > &y, const Monoid &monoid = Monoid(), - const typename std::enable_if< !grb::is_object< IOType >::value && - grb::is_monoid< Monoid >::value, + const typename std::enable_if< !alp::is_object< IOType >::value && + alp::is_monoid< Monoid >::value, void >::type * const = NULL ) { // create empty mask - Vector< bool, backend, Coords > mask( 0 ); + internal::Vector< bool, backend > mask( 0 ); // call regular reduce function return foldl< descr >( x, y, mask, monoid ); } @@ -295,17 +284,17 @@ namespace grb { Descriptor descr = descriptors::no_operation, class OP, typename IOType, typename InputType, - Backend backend, typename Coords + Backend backend > RC foldl( IOType &x, - const Vector< InputType, backend, Coords > &y, + const internal::Vector< InputType, backend > &y, const OP &op = OP(), - const typename std::enable_if< !grb::is_object< IOType >::value && - grb::is_operator< OP >::value, + const typename std::enable_if< !alp::is_object< IOType >::value && + alp::is_operator< OP >::value, void >::type * const = NULL ) { // create empty mask - Vector< bool, backend, Coords > mask( 0 ); + internal::Vector< bool, backend > mask( 0 ); // call regular reduce function return foldl< descr >( x, y, mask, op ); } @@ -316,25 +305,25 @@ namespace grb { * with any multiplicative operator. * * For return codes, exception behaviour, performance semantics, template - * and non-template arguments, @see grb::dot. + * and non-template arguments, @see alp::dot. */ template< Descriptor descr = descriptors::no_operation, class Ring, typename IOType, typename InputType1, typename InputType2, - Backend backend, typename Coords + Backend backend > RC dot( IOType &x, - const Vector< InputType1, backend, Coords > &left, - const Vector< InputType2, backend, Coords > &right, + const internal::Vector< InputType1, backend > &left, + const internal::Vector< InputType2, backend > &right, const Ring &ring = Ring(), const typename std::enable_if< - !grb::is_object< InputType1 >::value && - !grb::is_object< InputType2 >::value && - !grb::is_object< IOType >::value && - grb::is_semiring< Ring >::value, + !alp::is_object< InputType1 >::value && + !alp::is_object< InputType2 >::value && + !alp::is_object< IOType >::value && + alp::is_semiring< Ring >::value, void >::type * const = NULL ) { - return grb::dot< descr >( x, + return alp::dot< descr >( x, left, right, ring.getAdditiveMonoid(), ring.getMultiplicativeOperator() @@ -350,7 +339,7 @@ namespace grb { * This function is only available when the output type is floating point. * * For return codes, exception behaviour, performance semantics, template - * and non-template arguments, @see grb::dot. + * and non-template arguments, @see alp::dot. * * @param[out] x The 2-norm of \a y. The input value of \a x will be ignored. * @param[in] y The vector to compute the norm of. @@ -367,16 +356,16 @@ namespace grb { // template< // Descriptor descr = descriptors::no_operation, class Ring, // typename InputType, typename OutputType, typename OutputStructure, - // Backend backend, typename Coords + // Backend backend // > // RC norm2( Scalar< OutputType, OutputStructure, backend > &x, - // const Vector< InputType, backend, Coords > &y, + // const internal::Vector< InputType, backend > &y, // const Ring &ring = Ring(), // const typename std::enable_if< // std::is_floating_point< OutputType >::value, // void >::type * const = NULL // ) { - // RC ret = grb::dot< descr >( x, y, y, ring ); + // RC ret = alp::dot< descr >( x, y, y, ring ); // if( ret == SUCCESS ) { // x = sqrt( x ); // } @@ -387,16 +376,16 @@ namespace grb { template< Descriptor descr = descriptors::no_operation, class Ring, typename InputType, typename OutputType, - Backend backend, typename Coords + Backend backend > RC norm2( OutputType &x, - const Vector< InputType, backend, Coords > &y, + const internal::Vector< InputType, backend > &y, const Ring &ring = Ring(), const typename std::enable_if< std::is_floating_point< OutputType >::value, void >::type * const = NULL ) { - RC ret = grb::dot< descr >( x, y, y, ring ); + RC ret = alp::dot< descr >( x, y, y, ring ); if( ret == SUCCESS ) { x = sqrt( x ); } @@ -404,9 +393,9 @@ namespace grb { } -} // namespace grb +} // namespace alp #undef NO_CAST_RING_ASSERT -#endif // end ``_H_GRB_BLAS1'' +#endif // end ``_H_ALP_BLAS1'' diff --git a/include/alp/blas2.hpp b/include/alp/blas2.hpp index 7c4e44398..50ff131c7 100644 --- a/include/alp/blas2.hpp +++ b/include/alp/blas2.hpp @@ -24,24 +24,15 @@ * @date: 30th of March 2017. */ -#ifndef _H_GRB_BLAS2 -#define _H_GRB_BLAS2 +#ifndef _H_ALP_BLAS2 +#define _H_ALP_BLAS2 #include "base/blas2.hpp" // now include all specialisations contained in the backend directories: -#ifdef _GRB_WITH_REFERENCE - #include -#endif -#ifdef _GRB_WITH_DENSE - #include -#endif -#ifdef _GRB_WITH_BANSHEE - #include -#endif -#ifdef _GRB_WITH_LPF - #include +#ifdef _ALP_WITH_REFERENCE + #include #endif -#endif // end ``_H_GRB_BLAS2'' +#endif // end ``_H_ALP_BLAS2'' diff --git a/include/alp/blas3.hpp b/include/alp/blas3.hpp index e6e4d0ae0..369703821 100644 --- a/include/alp/blas3.hpp +++ b/include/alp/blas3.hpp @@ -19,23 +19,17 @@ * @author: A. N. Yzelman */ -#ifndef _H_GRB_BLAS3 -#define _H_GRB_BLAS3 +#ifndef _H_ALP_BLAS3 +#define _H_ALP_BLAS3 #include "base/blas3.hpp" #include "config.hpp" #include "phase.hpp" // now include all specialisations contained in the backend directories: -#ifdef _GRB_WITH_REFERENCE - #include -#endif -#ifdef _GRB_WITH_DENSEREF - #include -#endif -#ifdef _GRB_WITH_LPF - #include +#ifdef _ALP_WITH_REFERENCE + #include #endif -#endif // end _H_GRB_BLAS3 +#endif // end _H_ALP_BLAS3 diff --git a/include/alp/config.hpp b/include/alp/config.hpp index adfa261a6..19840b4df 100644 --- a/include/alp/config.hpp +++ b/include/alp/config.hpp @@ -20,24 +20,15 @@ * @date 8th of August, 2016 */ -#ifndef _H_GRB_CONFIG -#define _H_GRB_CONFIG +#ifndef _H_ALP_CONFIG +#define _H_ALP_CONFIG #include "base/config.hpp" // include all active configurations -#ifdef _GRB_WITH_REFERENCE - #include "graphblas/reference/config.hpp" -#endif -#ifdef _GRB_WITH_OMP - #include "graphblas/omp/config.hpp" -#endif -#ifdef _GRB_WITH_LPF - #include "graphblas/bsp1d/config.hpp" -#endif -#ifdef _GRB_WITH_BANSHEE - #include "graphblas/banshee/config.hpp" +#ifdef _ALP_WITH_REFERENCE + #include "alp/reference/config.hpp" #endif -#endif // end ``_H_GRB_CONFIG'' +#endif // end ``_H_ALP_CONFIG'' diff --git a/include/alp/density.hpp b/include/alp/density.hpp index bce57ad68..061a5e9e6 100644 --- a/include/alp/density.hpp +++ b/include/alp/density.hpp @@ -23,13 +23,13 @@ * */ -#ifndef _H_GRB_DENSITY -#define _H_GRB_DENSITY +#ifndef _H_ALP_DENSITY +#define _H_ALP_DENSITY #include #include -namespace grb { +namespace alp { /** * Specifies whether an ALP container is dense or sparse. @@ -59,6 +59,6 @@ namespace grb { Sparse }; // enum Density -} // namespace grb +} // namespace alp -#endif // _H_GRB_DENSITY +#endif // _H_ALP_DENSITY diff --git a/include/alp/descriptors.hpp b/include/alp/descriptors.hpp index bbfd385c2..e698e757c 100644 --- a/include/alp/descriptors.hpp +++ b/include/alp/descriptors.hpp @@ -27,10 +27,10 @@ #include #include -#ifndef _H_GRB_DESCRIPTOR -#define _H_GRB_DESCRIPTOR +#ifndef _H_ALP_DESCRIPTOR +#define _H_ALP_DESCRIPTOR -namespace grb { +namespace alp { /** * Descriptors indicate pre- or post-processing for some or all of the @@ -203,6 +203,6 @@ namespace grb { static constexpr Descriptor MAX_DESCRIPTOR_VALUE = 8191; } // namespace internal -} // namespace grb +} // namespace alp #endif diff --git a/include/alp/exec.hpp b/include/alp/exec.hpp index 8bfaa55a3..c01922692 100644 --- a/include/alp/exec.hpp +++ b/include/alp/exec.hpp @@ -20,32 +20,23 @@ * @date 17th of April, 2017 */ -#ifndef _H_GRB_EXEC -#define _H_GRB_EXEC +#ifndef _H_ALP_EXEC +#define _H_ALP_EXEC #include "base/config.hpp" #include "base/exec.hpp" // include template specialisations -#ifdef _GRB_WITH_REFERENCE - #include "graphblas/reference/exec.hpp" -#endif -#ifdef _GRB_WITH_DENSEREF - #include "graphblas/denseref/exec.hpp" -#endif -#ifdef _GRB_WITH_LPF - #include "graphblas/bsp1d/exec.hpp" -#endif -#ifdef _GRB_WITH_BANSHEE - #include "graphblas/banshee/exec.hpp" +#ifdef _ALP_WITH_REFERENCE + #include "alp/reference/exec.hpp" #endif -#ifdef _GRB_BACKEND -namespace grb { +#ifdef _ALP_BACKEND +namespace alp { template< enum EXEC_MODE mode, enum Backend implementation = config::default_backend > class Launcher; } #endif -#endif // end ``_H_GRB_EXEC'' +#endif // end ``_H_ALP_EXEC'' diff --git a/include/alp/identities.hpp b/include/alp/identities.hpp index dd48fcf98..4bcbeabc5 100644 --- a/include/alp/identities.hpp +++ b/include/alp/identities.hpp @@ -20,19 +20,19 @@ * @date 11th of August, 2016 */ -#ifndef _H_GRB_IDENTITIES -#define _H_GRB_IDENTITIES +#ifndef _H_ALP_IDENTITIES +#define _H_ALP_IDENTITIES #include -namespace grb { +namespace alp { /** * Standard identities common to many operators. * * The most commonly used identities are - * - #grb::identities::zero, and - * - #grb::identities::one. + * - #alp::identities::zero, and + * - #alp::identities::one. * * A stateful identity should expose the same public interface as the * identities collected here, which is class which exposes at least one public @@ -192,6 +192,6 @@ namespace grb { }; } // namespace identities -} // namespace grb +} // namespace alp #endif diff --git a/include/alp/imf.hpp b/include/alp/imf.hpp index 58897ef55..7ee434c70 100644 --- a/include/alp/imf.hpp +++ b/include/alp/imf.hpp @@ -42,8 +42,8 @@ * */ -#ifndef _H_GRB_IMF -#define _H_GRB_IMF +#ifndef _H_ALP_IMF +#define _H_ALP_IMF #include #include @@ -51,7 +51,7 @@ #include -namespace grb { +namespace alp { namespace imf { @@ -154,6 +154,6 @@ namespace grb { }; // namespace imf -} // namespace grb +} // namespace alp -#endif // _H_GRB_IMF +#endif // _H_ALP_IMF diff --git a/include/alp/init.hpp b/include/alp/init.hpp index 2d13801a0..0fb40b2f3 100644 --- a/include/alp/init.hpp +++ b/include/alp/init.hpp @@ -20,25 +20,16 @@ * @date 24th of January, 2017 */ -#ifndef _H_GRB_INIT -#define _H_GRB_INIT +#ifndef _H_ALP_INIT +#define _H_ALP_INIT #include "backends.hpp" #include "base/init.hpp" // include all implementations -#ifdef _GRB_WITH_REFERENCE - #include "graphblas/reference/init.hpp" -#endif -#ifdef _GRB_WITH_DENSEREF - #include "graphblas/denseref/init.hpp" -#endif -#ifdef _GRB_WITH_LPF - #include "graphblas/bsp1d/init.hpp" -#endif -#ifdef _GRB_WITH_BANSHEE - #include "graphblas/banshee/init.hpp" +#ifdef _ALP_WITH_REFERENCE + #include "alp/reference/init.hpp" #endif -#endif // end ``_H_GRB_INIT'' +#endif // end ``_H_ALP_INIT'' diff --git a/include/alp/internalops.hpp b/include/alp/internalops.hpp index d07908e81..e9dddba0a 100644 --- a/include/alp/internalops.hpp +++ b/include/alp/internalops.hpp @@ -20,17 +20,13 @@ * @date 8 of August, 2016 */ -#ifndef _H_GRB_INTERNAL_OPERATORS -#define _H_GRB_INTERNAL_OPERATORS +#ifndef _H_ALP_INTERNAL_OPERATORS +#define _H_ALP_INTERNAL_OPERATORS // certain backends may want to specialize these functionalities, // e.g., for specific targets, e.g. to exploit dedicated hardware // features #include "base/internalops.hpp" -#ifdef _GRB_WITH_BANSHEE - #include -#endif - #endif diff --git a/include/alp/iomode.hpp b/include/alp/iomode.hpp index d93a31c63..17c29a34d 100644 --- a/include/alp/iomode.hpp +++ b/include/alp/iomode.hpp @@ -20,10 +20,10 @@ * @date 21st of February, 2017 */ -#ifndef _H_GRB_IOMODE -#define _H_GRB_IOMODE +#ifndef _H_ALP_IOMODE +#define _H_ALP_IOMODE -namespace grb { +namespace alp { /** * The GraphBLAS input and output functionalities can either be used in a @@ -53,10 +53,10 @@ namespace grb { * corresponds to all elements in the GraphBLAS container. * * See the respective functions and classes for full details: - * -# grb::buildVector; - * -# grb::buildMatrixUnique; - * -# grb::Vector::const_iterator; - * -# grb::Matrix::const_iterator. + * -# alp::buildVector; + * -# alp::buildMatrixUnique; + * -# alp::Vector::const_iterator; + * -# alp::Matrix::const_iterator. */ enum IOMode { @@ -88,6 +88,6 @@ namespace grb { /** @} */ -} // namespace grb +} // namespace alp -#endif // end ``_H_GRB_IOMODE'' +#endif // end ``_H_ALP_IOMODE'' diff --git a/include/alp/matrix.hpp b/include/alp/matrix.hpp index fec68360f..4ae3edb05 100644 --- a/include/alp/matrix.hpp +++ b/include/alp/matrix.hpp @@ -20,39 +20,32 @@ * @date 10 of August */ -#ifndef _H_GRB_MATRIX -#define _H_GRB_MATRIX +#ifndef _H_ALP_MATRIX +#define _H_ALP_MATRIX #include "base/config.hpp" #include "base/matrix.hpp" // now include all specialisations contained in the backend directories: -#ifdef _GRB_WITH_REFERENCE - #include -#endif -#ifdef _GRB_WITH_DENSEREF - #include -#endif -#ifdef _GRB_WITH_LPF -#include -#endif -#ifdef _GRB_WITH_BANSHEE -#include +#ifdef _ALP_WITH_REFERENCE + #include #endif // specify default only if requested during compilation -#ifdef _GRB_BACKEND -namespace grb { - template< typename D, enum Backend implementation = config::default_backend > - class Matrix; +#ifdef _ALP_BACKEND +namespace alp { + namespace internal { + template< typename D, enum Backend implementation = config::default_backend > + class Matrix; + } /* * The default value of \a density could also be made conditional (Dense or Sparse) depending on \a config::default_backend */ template< typename T, typename Structure, enum Density density = Density::Dense, typename View = view::Original< void >, enum Backend backend = config::default_backend > - class StructuredMatrix; + class Matrix; -} // namespace grb +} // namespace alp #endif -#endif // end ``_H_GRB_MATRIX'' +#endif // end ``_H_ALP_MATRIX'' diff --git a/include/alp/monoid.hpp b/include/alp/monoid.hpp index 56f21b1a8..a7248385b 100644 --- a/include/alp/monoid.hpp +++ b/include/alp/monoid.hpp @@ -20,8 +20,8 @@ * @date 15 March, 2016 */ -#ifndef _H_GRB_MONOID -#define _H_GRB_MONOID +#ifndef _H_ALP_MONOID +#define _H_ALP_MONOID #ifdef _DEBUG #include @@ -33,9 +33,9 @@ #include -#include -#include -#include +#include +#include +#include /** * The main Sparse Library namespace. @@ -43,7 +43,7 @@ * All classes, enums, constants, and functions are declared in this namespace. * This source file only contains testing code outside this namespace. */ -namespace grb { +namespace alp { /** * A generalised monoid. @@ -54,9 +54,9 @@ namespace grb { template< class _OP, template< typename > class _ID > class Monoid { - static_assert( grb::is_operator< _OP >::value, "First template argument to Monoid must be a GraphBLAS operator" ); + static_assert( alp::is_operator< _OP >::value, "First template argument to Monoid must be a GraphBLAS operator" ); - static_assert( grb::is_associative< _OP >::value, + static_assert( alp::is_associative< _OP >::value, "Cannot form a monoid using the given operator since it is not " "associative" ); @@ -129,10 +129,10 @@ namespace grb { template< class OP, template< typename > class ID > struct has_immutable_nonzeroes< Monoid< OP, ID > > { - static const constexpr bool value = grb::is_monoid< Monoid< OP, ID > >::value && - std::is_same< OP, typename grb::operators::logical_or< typename OP::D1, typename OP::D2, typename OP::D3 > >::value; + static const constexpr bool value = alp::is_monoid< Monoid< OP, ID > >::value && + std::is_same< OP, typename alp::operators::logical_or< typename OP::D1, typename OP::D2, typename OP::D3 > >::value; }; -} // namespace grb +} // namespace alp #endif diff --git a/include/alp/ops.hpp b/include/alp/ops.hpp index 918b37db9..e6bdddeb4 100644 --- a/include/alp/ops.hpp +++ b/include/alp/ops.hpp @@ -20,24 +20,24 @@ * @date 8th of August, 2016 */ -#ifndef _H_GRB_OPERATORS -#define _H_GRB_OPERATORS +#ifndef _H_ALP_OPERATORS +#define _H_ALP_OPERATORS #include "internalops.hpp" #include "type_traits.hpp" -namespace grb { +namespace alp { /** - * This namespace holds various standard operators such as #grb::operators::add - * and #grb::operators::mul. + * This namespace holds various standard operators such as #alp::operators::add + * and #alp::operators::mul. */ namespace operators { /** * This operator discards all right-hand side input and simply copies the * left-hand side input to the output variable. It exposes the complete - * interface detailed in grb::operators::internal::Operator. This operator + * interface detailed in alp::operators::internal::Operator. This operator * can be passed to any GraphBLAS function or object constructor. * * Mathematical notation: \f$ \odot(x,y)\ \to\ x \f$. @@ -70,7 +70,7 @@ namespace grb { /** * This operator discards all left-hand side input and simply copies the * right-hand side input to the output variable. It exposes the complete - * interface detailed in grb::operators::internal::Operator. This operator + * interface detailed in alp::operators::internal::Operator. This operator * can be passed to any GraphBLAS function or object constructor. * * Mathematical notation: \f$ \odot(x,y)\ \to\ y \f$. @@ -103,7 +103,7 @@ namespace grb { /** * This operator takes the sum of the two input parameters and writes it to * the output variable. It exposes the complete interface detailed in - * grb::operators::internal::Operator. This operator can be passed to any + * alp::operators::internal::Operator. This operator can be passed to any * GraphBLAS function or object constructor. * * Mathematical notation: \f$ \odot(x,y)\ \to\ x + y \f$. @@ -133,7 +133,7 @@ namespace grb { /** * This operator multiplies the two input parameters and writes the result to * the output variable. It exposes the complete interface detailed in - * grb::operators::internal::Operator. This operator can be passed to any + * alp::operators::internal::Operator. This operator can be passed to any * GraphBLAS function or object constructor. * * Mathematical notation: \f$ \odot(x,y)\ \to\ x \cdot y \f$. @@ -161,7 +161,7 @@ namespace grb { /** * This operator takes the maximum of the two input parameters and writes * the result to the output variable. It exposes the complete interface - * detailed in grb::operators::internal::Operator. This operator can be + * detailed in alp::operators::internal::Operator. This operator can be * passed to any GraphBLAS function or object constructor. * * Mathematical notation: \f$ \max(x,y)\ \to\ \begin{cases} @@ -190,7 +190,7 @@ namespace grb { /** * This operator takes the minimum of the two input parameters and writes * the result to the output variable. It exposes the complete interface - * detailed in grb::operators::internal::Operator. This operator can be + * detailed in alp::operators::internal::Operator. This operator can be * passed to any GraphBLAS function or object constructor. * * Mathematical notation: \f$ \max(x,y)\ \to\ \begin{cases} @@ -540,9 +540,9 @@ namespace grb { static const constexpr bool value = true; }; - } // namespace grb::internal + } // namespace alp::internal -} // namespace grb +} // namespace alp #ifdef __DOXYGEN__ /** @@ -562,5 +562,5 @@ namespace grb { #endif #endif -#endif // end ``_H_GRB_OPERATORS'' +#endif // end ``_H_ALP_OPERATORS'' diff --git a/include/alp/phase.hpp b/include/alp/phase.hpp index 636ad7d9b..3da83e312 100644 --- a/include/alp/phase.hpp +++ b/include/alp/phase.hpp @@ -19,10 +19,10 @@ * @author A. N. Yzelman */ -#ifndef _H_GRB_PHASE -#define _H_GRB_PHASE +#ifndef _H_ALP_PHASE +#define _H_ALP_PHASE -namespace grb { +namespace alp { /** * Some primitives may require a symbolic phase prior to executing a numeric @@ -65,6 +65,6 @@ namespace grb { NUMERICAL }; -} // namespace grb +} // namespace alp -#endif // end ``_H_GRB_PHASE'' +#endif // end ``_H_ALP_PHASE'' diff --git a/include/alp/rc.hpp b/include/alp/rc.hpp index 53f4d974c..ce94a7a42 100644 --- a/include/alp/rc.hpp +++ b/include/alp/rc.hpp @@ -24,12 +24,12 @@ * @date 9--11 August, 2016 */ -#ifndef _H_GRB_RC -#define _H_GRB_RC +#ifndef _H_ALP_RC +#define _H_ALP_RC #include -namespace grb { +namespace alp { /** * Return codes of public functions. @@ -42,7 +42,7 @@ namespace grb { * All GraphBLAS functions may return this error code even if not explicitly * documented. Any non-SUCCESS error code shall have no side effects; if a * call fails, it shall be as though the call was never made. The only - * exception is #grb::PANIC. + * exception is #alp::PANIC. */ SUCCESS = 0, @@ -59,7 +59,7 @@ namespace grb { * * Rationale: instead of using assert within GraphBLAS * implementations which would crash the entire application, implementations - * should instead simply return #grb::PANIC and let the GraphBLAS user shut + * should instead simply return #alp::PANIC and let the GraphBLAS user shut * down his or her application as gracefully as possible. * * All GraphBLAS functions may return this error code even if not explicitly @@ -132,7 +132,7 @@ namespace grb { ILLEGAL, /** - * Indicates when one of the grb::algorithms has failed to achieve its + * Indicates when one of the alp::algorithms has failed to achieve its * intended result, for instance, when an iterative method failed to * converged within its alloted resources. * @@ -145,6 +145,6 @@ namespace grb { /** @returns A string describing the given error code. */ std::string toString( const RC code ); -} // namespace grb +} // namespace alp #endif diff --git a/include/alp/reference/alloc.hpp b/include/alp/reference/alloc.hpp index e5cf3d14e..d45ac8873 100644 --- a/include/alp/reference/alloc.hpp +++ b/include/alp/reference/alloc.hpp @@ -20,12 +20,12 @@ * @date 22nd of January, 2021 */ -#ifndef _H_GRB_DENSEREF_ALLOC -#define _H_GRB_DENSEREF_ALLOC +#ifndef _H_ALP_REFERENCE_ALLOC +#define _H_ALP_REFERENCE_ALLOC -namespace grb { +namespace alp { -} // namespace grb +} // namespace alp #endif diff --git a/include/alp/reference/benchmark.hpp b/include/alp/reference/benchmark.hpp index d3c162cb9..fcf48c1af 100644 --- a/include/alp/reference/benchmark.hpp +++ b/include/alp/reference/benchmark.hpp @@ -20,15 +20,15 @@ * @date 14th of January, 2022 */ -#ifndef _H_GRB_DENSEREF_BENCH -#define _H_GRB_DENSEREF_BENCH +#ifndef _H_ALP_REFERENCE_BENCH +#define _H_ALP_REFERENCE_BENCH -#include -#include +#include +#include -namespace grb { +namespace alp { -} // end namespace ``grb'' +} // end namespace ``alp'' -#endif // end ``_H_GRB_DENSEREF_BENCH'' +#endif // end ``_H_ALP_REFERENCE_BENCH'' diff --git a/include/alp/reference/blas0.hpp b/include/alp/reference/blas0.hpp index e95b89f23..081d96c98 100644 --- a/include/alp/reference/blas0.hpp +++ b/include/alp/reference/blas0.hpp @@ -20,13 +20,13 @@ * @date 14th of January 2022 */ -#ifndef _H_GRB_DENSEREF_BLAS0 -#define _H_GRB_DENSEREF_BLAS0 +#ifndef _H_ALP_REFERENCE_BLAS0 +#define _H_ALP_REFERENCE_BLAS0 -#include -#include -#include -#include +#include +#include +#include +#include #ifndef NO_CAST_ASSERT #define NO_CAST_ASSERT( x, y, z ) \ @@ -47,7 +47,7 @@ "******************************\n" ); #endif -namespace grb { +namespace alp { /** * \defgroup BLAS0 The Level-0 Basic Linear Algebra Subroutines (BLAS) @@ -56,28 +56,28 @@ namespace grb { * zero-dimensional containers, i.e., on scalars. * * The GraphBLAS uses opaque data types and defines several standard functions - * to operate on these data types. Examples types are grb::Vector and - * grb::Matrix, example functions are grb::dot and grb::vxm. + * to operate on these data types. Examples types are alp::Vector and + * alp::Matrix, example functions are alp::dot and alp::vxm. * * To input data into an opaque GraphBLAS type, each opaque type defines a - * member function \a build: grb::Vector::build() and grb::Matrix::build(). + * member function \a build: alp::Vector::build() and alp::Matrix::build(). * * To extract data from opaque GraphBLAS types, each opaque type provides * \em iterators that may be obtained via the STL standard \a begin and \a end * functions: - * - grb::Vector::begin or grb::Vector::cbegin - * - grb::Vector::end or grb::Vector::cend - * - grb::Matrix::begin or grb::Matrix::cbegin - * - grb::Matrix::end or grb::Matrix::cend + * - alp::Vector::begin or alp::Vector::cbegin + * - alp::Vector::end or alp::Vector::cend + * - alp::Matrix::begin or alp::Matrix::cbegin + * - alp::Matrix::end or alp::Matrix::cend * * Some GraphBLAS functions, however, reduce all elements in a GraphBLAS - * container into a single element of a given type. So for instance, grb::dot - * on two vectors of type grb::Vector using the regular real semiring - * grb::Semiring will store its output in a variable of type \a double. + * container into a single element of a given type. So for instance, alp::dot + * on two vectors of type alp::Vector using the regular real semiring + * alp::Semiring will store its output in a variable of type \a double. * * When parametrising GraphBLAS functions in terms of arbitrary Semirings, * Monoids, Operators, and object types, it is useful to have a way to apply - * the same operators on whatever type they make functions like grb::dot + * the same operators on whatever type they make functions like alp::dot * produce-- that is, we require functions that enable the application of * GraphBLAS operators on single elements. * @@ -117,7 +117,7 @@ namespace grb { * \todo add documentation. In particular, think about the meaning with \a P > 1. */ template< typename InputType, typename InputStructure, typename length_type > - RC resize( Scalar< InputType, InputStructure, reference_dense > & s, const length_type new_nz ) { + RC resize( Scalar< InputType, InputStructure, reference > & s, const length_type new_nz ) { if( new_nz <= 1 ) { setInitialized( s, false ); return SUCCESS; @@ -128,7 +128,7 @@ namespace grb { /** @} */ -} // end namespace ``grb'' +} // end namespace ``alp'' -#endif // end ``_H_GRB_DENSEREF_BLAS0'' +#endif // end ``_H_ALP_REFERENCE_BLAS0'' diff --git a/include/alp/reference/blas1.hpp b/include/alp/reference/blas1.hpp index fea5e36ca..4d782f0ad 100644 --- a/include/alp/reference/blas1.hpp +++ b/include/alp/reference/blas1.hpp @@ -20,14 +20,14 @@ * @date 14th of January 2022 */ -#ifndef _H_GRB_DENSEREF_BLAS1 -#define _H_GRB_DENSEREF_BLAS1 +#ifndef _H_ALP_REFERENCE_BLAS1 +#define _H_ALP_REFERENCE_BLAS1 -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include #ifndef NO_CAST_ASSERT #define NO_CAST_ASSERT( x, y, z ) \ @@ -49,7 +49,7 @@ #endif -namespace grb { +namespace alp { /** * \defgroup BLAS1 The Level-1 Basic Linear Algebra Subroutines (BLAS) @@ -57,8 +57,8 @@ namespace grb { * A collection of functions that allow ALP/GraphBLAS operators, monoids, and * semirings work on a mix of zero-dimensional and one-dimensional containers; * i.e., allows various linear algebra operations on scalars (both built-in - * C++ scalars and objects of type grb::Scalar) and objects of type - * grb::VectorView. + * C++ scalars and objects of type alp::Scalar) and objects of type + * alp::Vector. * * C++ built-in scalars are all scalar types that can be * passed to BLAS functions. This includes simple types (e.g. double) and @@ -66,52 +66,52 @@ namespace grb { * Such types are referred to as C++ scalars or built-in scalars. * * Operations producing scalars are specialized to both C++ built-in scalars - * and grb::Scalars. Functions taking scalars as inputs are specialized only - * to grb::Scalars. Depending on backend's Scalar implementation, the - * conversion from C++ scalar to grb::Scalar can be implicit or explicit. + * and alp::Scalars. Functions taking scalars as inputs are specialized only + * to alp::Scalars. Depending on backend's Scalar implementation, the + * conversion from C++ scalar to alp::Scalar can be implicit or explicit. * - * All functions except for grb::size and grb::nnz return an error code of - * the enum-type grb::RC. The two functions for retrieving the size and the + * All functions except for alp::size and alp::nnz return an error code of + * the enum-type alp::RC. The two functions for retrieving the size and the * nonzeroes of two vectors are excluded from this because they are never * allowed to fail. * * Operations which require a single input vector only and produce scalar * output: - * -# grb::size, - * -# grb::nnz, and - * -# grb::set (three variants). + * -# alp::size, + * -# alp::nnz, and + * -# alp::set (three variants). * These do not require an operator, monoid, nor semiring. The following * require an operator: - * -# grb::foldr (reduction to the right), - * -# grb::foldl (reduction to the left). + * -# alp::foldr (reduction to the right), + * -# alp::foldl (reduction to the left). * Operators can only be applied on \em dense vectors. Operations on sparse * vectors require a well-defined way to handle missing vector elements. The * following functions require a monoid instead of an operator and are able * to handle sparse vectors by interpreting missing items as an identity * value: - * -# grb::reducer (reduction to the right), - * -# grb::reducel (reduction to the left). + * -# alp::reducer (reduction to the right), + * -# alp::reducel (reduction to the left). * * Operations which require two input vectors and produce scalar output: - * -# grb::dot (dot product-- requires a semiring). + * -# alp::dot (dot product-- requires a semiring). // * Sparse vectors under a semiring have their missing values interpreted as a // * zero element under the given semiring; i.e., the identity of the additive // * operator. * * Operations which require one input vector and one input/output vector for * full and efficient in-place operations: - * -# grb::foldr (reduction to the right-- requires an operator), - * -# grb::foldl (reduction to the left-- requires an operator). - * For grb::foldr, the left-hand side input vector may be replaced by an - * input scalar. For grb::foldl, the right-hand side input vector may be + * -# alp::foldr (reduction to the right-- requires an operator), + * -# alp::foldl (reduction to the left-- requires an operator). + * For alp::foldr, the left-hand side input vector may be replaced by an + * input scalar. For alp::foldl, the right-hand side input vector may be * replaced by an input scalar. In either of those cases, the reduction * is equivalent to an in-place vector scaling. * * Operations which require two input vectors and one output vector for * out-of-place operations: - * -# grb::eWiseApply (requires an operator), - * -# grb::eWiseMul (requires a semiring), - * -# grb::eWiseAdd (requires a semiring). + * -# alp::eWiseApply (requires an operator), + * -# alp::eWiseMul (requires a semiring), + * -# alp::eWiseAdd (requires a semiring). * Note that multiplication will consider any zero elements as an annihilator * to the multiplicative operator. Therefore, the operator will only be * applied at vector indices where both input vectors have nonzeroes. This is @@ -121,27 +121,27 @@ namespace grb { * * Operations which require three input vectors and one output vector for * out-of-place operations: - * -# grb::eWiseMulAdd (requires a semiring). - * This function can be emulated by first successive calls to grb::eWiseMul - * and grb::eWiseAdd. This specialised function, however, has better + * -# alp::eWiseMulAdd (requires a semiring). + * This function can be emulated by first successive calls to alp::eWiseMul + * and alp::eWiseAdd. This specialised function, however, has better * performance semantics. This function is closest to the standard axpy * BLAS1 call, with out-of-place semantics. The first input vector may be * replaced by a scalar. * - * Again, each of grb::eWiseMul, grb::eWiseAdd, grb::eWiseMulAdd accept sparse + * Again, each of alp::eWiseMul, alp::eWiseAdd, alp::eWiseMulAdd accept sparse * vectors as input and output (since they operate on semirings), while - * grb::eWiseApply. + * alp::eWiseApply. * * For fusing multiple BLAS-1 style operations on any number of inputs and * outputs, users can pass their own operator function to be executed for * every index \a i. - * -# grb::eWiseLambda. + * -# alp::eWiseLambda. * This requires manual application of operators, monoids, and/or semirings - * via the BLAS-0 interface (see grb::apply, grb::foldl, and grb::foldr). + * via the BLAS-0 interface (see alp::apply, alp::foldl, and alp::foldr). * * For all of these functions, the element types of input and output types * do not have to match the domains of the given operator, monoid, or - * semiring unless the grb::descriptors::no_casting descriptor was passed. + * semiring unless the alp::descriptors::no_casting descriptor was passed. * * An implementation, whether blocking or non-blocking, should have clear * performance semantics for every sequence of graphBLAS calls, no matter @@ -156,7 +156,7 @@ namespace grb { * At the end of this operation, the number of nonzero elements in this vector * will be zero. The size of the vector remains unchanged. * - * @return grb::SUCCESS When the vector is successfully cleared. + * @return alp::SUCCESS When the vector is successfully cleared. * * \note This function cannot fail. * @@ -173,28 +173,28 @@ namespace grb { // * \endparblock */ template< - typename DataType, typename DataStructure, typename View + typename DataType, typename DataStructure, typename View > RC clear( - VectorView< DataType, DataStructure, Density::Dense, View, reference_dense > &x + Vector< DataType, DataStructure, Density::Dense, View, reference > & x ) noexcept { throw std::runtime_error( "Needs an implementation" ); return SUCCESS; } /** - * Request the size (dimension) of a given VectorView. + * Request the size (dimension) of a given Vector. * - * The dimension is set at construction of the given VectorView and cannot + * The dimension is set at construction of the given Vector and cannot * be changed. A call to this function shall always succeed. * * @tparam DataType The type of elements contained in the vector \a x. * @tparam DataStructure The structure of the vector \a x. * @tparam View The view type applied to the vector \a x. * - * @param[in] x The VectorView of which to retrieve the size. + * @param[in] x The Vector of which to retrieve the size. * - * @return The size of the VectorView \a x. + * @return The size of the Vector \a x. * // * \parblock // * \par Performance semantics @@ -206,12 +206,12 @@ namespace grb { // * \endparblock */ template< typename DataType, typename DataStructure, typename View > - size_t size( const VectorView< DataType, DataStructure, Density::Dense, View, reference_dense > & x ) noexcept { + size_t size( const Vector< DataType, DataStructure, Density::Dense, View, reference > & x ) noexcept { return getLength( x ); } /** - * Request the number of nonzeroes in a given VectorView. + * Request the number of nonzeroes in a given Vector. * * A call to this function always succeeds. * @@ -219,7 +219,7 @@ namespace grb { * @tparam DataStructure The structure of the vector \a x. * @tparam View The view type applied to the vector \a x. * - * @param[in] x The VectorView of which to retrieve the number of nonzeroes. + * @param[in] x The Vector of which to retrieve the number of nonzeroes. * * @return The number of nonzeroes in \a x. * @@ -233,7 +233,7 @@ namespace grb { // * \endparblock */ template< typename DataType, typename DataStructure, typename View > - size_t nnz( const VectorView< DataType, DataStructure, Density::Dense, View, reference_dense > & x ) noexcept { + size_t nnz( const Vector< DataType, DataStructure, Density::Dense, View, reference > & x ) noexcept { throw std::runtime_error( "Needs an implementation." ); return 0; } @@ -250,7 +250,7 @@ namespace grb { * However, the actual memory will not be reallocated. Rather, the vector * will be marked as uninitialized. * - * @param[in] x The VectorView to be resized. + * @param[in] x The Vector to be resized. * @param[in] new_nz The number of nonzeroes this vector is to contain. * * @return SUCCESS If \a new_nz is not larger than the current capacity @@ -268,7 +268,7 @@ namespace grb { * \todo add documentation. In particular, think about the meaning with \a P > 1. */ template< typename InputType, typename InputStructure, typename View, typename length_type > - RC resize( VectorView< InputType, InputStructure, Density::Dense, View, reference_dense > &x, const length_type new_nz ) { + RC resize( Vector< InputType, InputStructure, Density::Dense, View, reference > &x, const length_type new_nz ) { (void)x; (void)new_nz; // TODO implement @@ -277,15 +277,15 @@ namespace grb { } /** - * Sets all elements of a VectorView to the given value. Can be masked. + * Sets all elements of a Vector to the given value. Can be masked. * * This function is functionally equivalent to * \code - * grb::operators::right_assign< DataType > op; + * alp::operators::right_assign< DataType > op; * return foldl< descr >( x, val, op ); * \endcode, * \code - * grb::operators::left_assign< DataType > op; + * alp::operators::left_assign< DataType > op; * return foldr< descr >( val, x, op ); * \endcode, and the following pseudocode * \code @@ -301,17 +301,17 @@ namespace grb { * * \parblock * \par Accepted descriptors - * -# grb::descriptors::no_operation - * -# grb::descriptors::no_casting + * -# alp::descriptors::no_operation + * -# alp::descriptors::no_casting * \endparblock * - * @param[in,out] x The VectorView of which every element is to be set to equal + * @param[in,out] x The Vector of which every element is to be set to equal * \a val. * @param[in] val The value to set each element of \a x equal to. * * @returns SUCCESS When the call completes successfully. * - * When \a descr includes grb::descriptors::no_casting and if \a T does not + * When \a descr includes alp::descriptors::no_casting and if \a T does not * match \a DataType, the code shall not compile. * // * \parblock @@ -323,24 +323,24 @@ namespace grb { // * -# shall not make any system calls. // * \endparblock * - * @see grb::foldl. - * @see grb::foldr. - * @see grb::operators::left_assign. - * @see grb::operators::right_assign. - * @see grb::setElement. + * @see alp::foldl. + * @see alp::foldr. + * @see alp::operators::left_assign. + * @see alp::operators::right_assign. + * @see alp::setElement. */ template< Descriptor descr = descriptors::no_operation, typename DataType, typename DataStructure, typename ValStructure, typename View, typename T > - RC set( VectorView< DataType, DataStructure, Density::Dense, View, reference_dense > & x, - const Scalar< T, ValStructure, reference_dense > val, + RC set( Vector< DataType, DataStructure, Density::Dense, View, reference > & x, + const Scalar< T, ValStructure, reference > val, const typename std::enable_if< - !grb::is_object< DataType >::value && - !grb::is_object< T >::value, + !alp::is_object< DataType >::value && + !alp::is_object< T >::value, void >::type * const = NULL ) { // static sanity checks - NO_CAST_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< DataType, T >::value ), "grb::set (Vector, unmasked)", + NO_CAST_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< DataType, T >::value ), "alp::set (Vector, unmasked)", "called with a value type that does not match that of the given " "vector" ); throw std::runtime_error( "Needs an implementation." ); @@ -350,15 +350,15 @@ namespace grb { } /** - * Sets all elements of a VectorView to the given value. Masked variant. + * Sets all elements of a Vector to the given value. Masked variant. * * This function is functionally equivalent to * \code - * grb::operators::right_assign< DataType > op; + * alp::operators::right_assign< DataType > op; * return foldl< descr >( x, mask, val, op ); * \endcode, * \code - * grb::operators::left_assign< DataType > op; + * alp::operators::left_assign< DataType > op; * return foldr< descr >( val, x, mask, op ); * \endcode, and the following pseudocode * \code @@ -374,19 +374,19 @@ namespace grb { * * \parblock * \par Accepted descriptors - * -# grb::descriptors::no_operation - * -# grb::descriptors::no_casting - * -# grb::descriptors::invert_mask - * -# grb::descriptors::structural_mask + * -# alp::descriptors::no_operation + * -# alp::descriptors::no_casting + * -# alp::descriptors::invert_mask + * -# alp::descriptors::structural_mask * \endparblock * - * @param[in,out] x The VectorView of which every element is to be set to equal + * @param[in,out] x The Vector of which every element is to be set to equal * \a val. * @param[in] val The value to set each element of \a x equal to. * * @returns SUCCESS When the call completes successfully. * - * When \a descr includes grb::descriptors::no_casting and if \a T does not + * When \a descr includes alp::descriptors::no_casting and if \a T does not * match \a DataType, the code shall not compile. * // * \parblock @@ -396,29 +396,29 @@ namespace grb { // * -# moves \f$ \Theta( nnz( m ) ) \f$ bytes of memory; // * -# does not allocate nor free any dynamic memory; // * -# shall not make any system calls. - // * If grb::descriptors::invert_mask is given, then \f$ nnz( m ) \f$ in the + // * If alp::descriptors::invert_mask is given, then \f$ nnz( m ) \f$ in the // * above shall be interpreted as \f$ size( m ) \f$ instead. // * \endparblock * - * @see grb::foldl. - * @see grb::foldr. - * @see grb::operators::left_assign. - * @see grb::operators::right_assign. - * @see grb::setElement. + * @see alp::foldl. + * @see alp::foldr. + * @see alp::operators::left_assign. + * @see alp::operators::right_assign. + * @see alp::setElement. */ template< Descriptor descr = descriptors::no_operation, typename DataType, typename DataView, typename DataStructure, typename MaskStructure, typename MaskType, typename MaskView, typename T, typename ValStructure > - RC set( VectorView< DataType, DataStructure, Density::Dense, DataView, reference_dense > & x, - const VectorView< MaskType, MaskStructure, Density::Dense, MaskView, reference_dense > & m, - const Scalar< T, ValStructure, reference_dense > val, - const typename std::enable_if< ! grb::is_object< DataType >::value && ! grb::is_object< T >::value, void >::type * const = NULL ) { + RC set( Vector< DataType, DataStructure, Density::Dense, DataView, reference > & x, + const Vector< MaskType, MaskStructure, Density::Dense, MaskView, reference > & m, + const Scalar< T, ValStructure, reference > val, + const typename std::enable_if< ! alp::is_object< DataType >::value && ! alp::is_object< T >::value, void >::type * const = NULL ) { #ifdef _DEBUG - std::cout << "In grb::set (vector-to-value, masked)\n"; + std::cout << "In alp::set (vector-to-value, masked)\n"; #endif // static sanity checks - NO_CAST_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< DataType, T >::value ), "grb::set (Vector to scalar, masked)", + NO_CAST_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< DataType, T >::value ), "alp::set (Vector to scalar, masked)", "called with a value type that does not match that of the given " "vector" ); @@ -446,26 +446,26 @@ namespace grb { typename DataType, typename DataView, typename DataStructure, typename MaskStructure, typename MaskType, typename MaskView, typename T > - RC set( VectorView< DataType, DataStructure, Density::Dense, DataView, reference_dense > & x, - const VectorView< MaskType, MaskStructure, Density::Dense, MaskView, reference_dense > & m, + RC set( Vector< DataType, DataStructure, Density::Dense, DataView, reference > & x, + const Vector< MaskType, MaskStructure, Density::Dense, MaskView, reference > & m, const T val, - const typename std::enable_if< ! grb::is_object< DataType >::value && ! grb::is_object< T >::value, void >::type * const = NULL ) { + const typename std::enable_if< ! alp::is_object< DataType >::value && ! alp::is_object< T >::value, void >::type * const = NULL ) { #ifdef _DEBUG - std::cout << "In grb::set (vector-to-value, masked)\n"; + std::cout << "In alp::set (vector-to-value, masked)\n"; #endif // static sanity checks - NO_CAST_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< DataType, T >::value ), "grb::set (Vector to scalar, masked)", + NO_CAST_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< DataType, T >::value ), "alp::set (Vector to scalar, masked)", "called with a value type that does not match that of the given " "vector" ); - // delegate to grb::Scalar version + // delegate to alp::Scalar version return set( x, m, Scalar< T >( val ) ); } /** - * Sets the element of a given VectorView at a given position to a given value. + * Sets the element of a given Vector at a given position to a given value. * - * If the input VectorView \a x already has an element \f$ x_i \f$, that element + * If the input Vector \a x already has an element \f$ x_i \f$, that element * is overwritten to the given value \a val. If no such element existed, it * is added and set equal to \a val. The number of nonzeroes in \a x may thus * be increased by one due to a call to this function. @@ -483,17 +483,17 @@ namespace grb { * @param[in] val The value \f$ x_i \f$ should read after function exit. * @param[in] i The index of the element of \a x to set. * - * @return grb::SUCCESS Upon successful execution of this operation. - * @return grb::MISMATCH If \a i is greater or equal than the dimension of + * @return alp::SUCCESS Upon successful execution of this operation. + * @return alp::MISMATCH If \a i is greater or equal than the dimension of * \a x. * * \parblock * \par Accepted descriptors - * -# grb::descriptors::no_operation - * -# grb::descriptors::no_casting + * -# alp::descriptors::no_operation + * -# alp::descriptors::no_casting * \endparblock * - * When \a descr includes grb::descriptors::no_casting and if \a T does not + * When \a descr includes alp::descriptors::no_casting and if \a T does not * match \a DataType, the code shall not compile. * // * \parblock @@ -506,14 +506,14 @@ namespace grb { // * \endparblock */ template< Descriptor descr = descriptors::no_operation, typename DataType, typename DataStructure, typename ValStructure, typename View, typename T > - RC setElement( VectorView< DataType, DataStructure, Density::Dense, View, reference_dense > & x, - const Scalar< T, ValStructure, reference_dense > val, + RC setElement( Vector< DataType, DataStructure, Density::Dense, View, reference > & x, + const Scalar< T, ValStructure, reference > val, const size_t i, - const typename std::enable_if< ! grb::is_object< DataType >::value && ! grb::is_object< T >::value, void >::type * const = NULL ) { + const typename std::enable_if< ! alp::is_object< DataType >::value && ! alp::is_object< T >::value, void >::type * const = NULL ) { // static sanity checks - NO_CAST_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< DataType, T >::value ), "grb::set (VectorView, at index)", + NO_CAST_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< DataType, T >::value ), "alp::set (Vector, at index)", "called with a value type that does not match that of the given " - "VectorView" ); + "Vector" ); throw std::runtime_error( "Needs an implementation." ); @@ -523,14 +523,14 @@ namespace grb { /** C++ scalar variant */ template< Descriptor descr = descriptors::no_operation, typename DataType, typename DataStructure, typename ValStructure, typename View, typename T > - RC setElement( VectorView< DataType, DataStructure, Density::Dense, View, reference_dense > & x, + RC setElement( Vector< DataType, DataStructure, Density::Dense, View, reference > & x, const T val, const size_t i, - const typename std::enable_if< ! grb::is_object< DataType >::value && ! grb::is_object< T >::value, void >::type * const = NULL ) { + const typename std::enable_if< ! alp::is_object< DataType >::value && ! alp::is_object< T >::value, void >::type * const = NULL ) { // static sanity checks - NO_CAST_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< DataType, T >::value ), "grb::set (VectorView, at index)", + NO_CAST_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< DataType, T >::value ), "alp::set (Vector, at index)", "called with a value type that does not match that of the given " - "VectorView" ); + "Vector" ); // delegate return setElement( x, Scalar< T >( val ), i ); @@ -542,12 +542,12 @@ namespace grb { * * This operation is functionally equivalent to * \code - * grb::operators::right_assign< T > op; - * grb::foldl( x, y, op ); + * alp::operators::right_assign< T > op; + * alp::foldl( x, y, op ); * \endcode, * \code - * grb::operators::left_assign < T > op; - * grb::foldr( y, x, op ); + * alp::operators::left_assign < T > op; + * alp::foldr( y, x, op ); * \endcode, as well as the following pseudocode * \code * for( each nonzero in y ) { @@ -559,8 +559,8 @@ namespace grb { * * \parblock * \par Accepted descriptors - * -# grb::descriptors::no_operation - * -# grb::descriptors::no_casting + * -# alp::descriptors::no_operation + * -# alp::descriptors::no_casting * \endparblock * * @tparam descr The descriptor of the operation. @@ -574,7 +574,7 @@ namespace grb { * @param[in,out] x The vector to be set. * @param[in] y The source vector. * - * When \a descr includes grb::descriptors::no_casting and if \a InputType + * When \a descr includes alp::descriptors::no_casting and if \a InputType * does not match \a OutputType, the code shall not compile. * // * \parblock @@ -586,24 +586,24 @@ namespace grb { // * -# shall not make any system calls. // * \endparblock * - * @see grb::foldl. - * @see grb::foldr. - * @see grb::operators::left_assign. - * @see grb::operators::right_assign. - * @see grb::setElement. + * @see alp::foldl. + * @see alp::foldr. + * @see alp::operators::left_assign. + * @see alp::operators::right_assign. + * @see alp::setElement. */ template< Descriptor descr = descriptors::no_operation, typename OutputType, typename InputType, typename OutputStructure, typename InputStructure, typename OutputView, typename InputView > - RC set( VectorView< OutputType, OutputStructure, Density::Dense, OutputView, reference_dense > & x, const VectorView< InputType, InputStructure, Density::Dense, InputView, reference_dense > & y ) { + RC set( Vector< OutputType, OutputStructure, Density::Dense, OutputView, reference > & x, const Vector< InputType, InputStructure, Density::Dense, InputView, reference > & y ) { // static sanity checks NO_CAST_ASSERT( - ( ! ( descr & descriptors::no_casting ) || std::is_same< OutputType, InputType >::value ), "grb::copy (Vector)", "called with vector parameters whose element data types do not match" ); + ( ! ( descr & descriptors::no_casting ) || std::is_same< OutputType, InputType >::value ), "alp::copy (Vector)", "called with vector parameters whose element data types do not match" ); constexpr bool out_is_void = std::is_void< OutputType >::value; constexpr bool in_is_void = std::is_void< OutputType >::value; static_assert( ! in_is_void || out_is_void, - "grb::set (reference, VectorView <- VectorView, masked): " + "alp::set (reference, Vector <- Vector, masked): " "if input is void, then the output must be also" ); static_assert( ! ( descr & descriptors::use_index ) || ! out_is_void, - "grb::set (reference, VectorView <- VectorView, masked): " + "alp::set (reference, Vector <- Vector, masked): " "use_index descriptor cannot be set if output vector is void" ); // check contract @@ -623,12 +623,12 @@ namespace grb { * * This operation is functionally equivalent to * \code - * grb::operators::right_assign< T > op; - * grb::foldl( x, mask, y, op ); + * alp::operators::right_assign< T > op; + * alp::foldl( x, mask, y, op ); * \endcode, * \code - * grb::operators::left_assign < T > op; - * grb::foldr( y, x, mask, op ); + * alp::operators::left_assign < T > op; + * alp::foldr( y, x, mask, op ); * \endcode, as well as the following pseudocode * \code * for( each nonzero in y ) { @@ -653,17 +653,17 @@ namespace grb { * * \parblock * \par Accepted descriptors - * -# grb::descriptors::no_operation - * -# grb::descriptors::no_casting - * -# grb::descriptors::invert_mask - * -# grb::descriptors::structural_mask + * -# alp::descriptors::no_operation + * -# alp::descriptors::no_casting + * -# alp::descriptors::invert_mask + * -# alp::descriptors::structural_mask * \endparblock * * @param[in,out] x The vector to be set. * @param[in] mask The output mask. * @param[in] y The source vector. * - * When \a descr includes grb::descriptors::no_casting and if \a InputType + * When \a descr includes alp::descriptors::no_casting and if \a InputType * does not match \a OutputType, the code shall not compile. * // * \parblock @@ -673,37 +673,37 @@ namespace grb { // * -# moves \f$ \Theta( \min\{ nnz( mask ), nnz( y ) \} ) \f$ bytes of memory; // * -# does not allocate nor free any dynamic memory; // * -# shall not make any system calls. - // * If grb::descriptors::invert_mask is given, then \f$ nnz( mask ) \f$ in the + // * If alp::descriptors::invert_mask is given, then \f$ nnz( mask ) \f$ in the // * above shall be considered equal to \f$ nnz( y ) \f$. // * \endparblock * - * @see grb::foldl. - * @see grb::foldr. - * @see grb::operators::left_assign. - * @see grb::operators::right_assign. - * @see grb::setElement. + * @see alp::foldl. + * @see alp::foldr. + * @see alp::operators::left_assign. + * @see alp::operators::right_assign. + * @see alp::setElement. */ template< Descriptor descr = descriptors::no_operation, typename OutputType, typename MaskType, typename InputType, typename OutputStructure, typename MaskStructure, typename InputStructure, typename OutputView, typename MaskView, typename InputView > - RC set( VectorView< OutputType, OutputStructure, Density::Dense, OutputView, reference_dense > & x, - const VectorView< MaskType, MaskStructure, Density::Dense, MaskView, reference_dense > & mask, - const VectorView< InputType, InputStructure, Density::Dense, InputView, reference_dense > & y, - const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType >::value, void >::type * const = NULL ) { + RC set( Vector< OutputType, OutputStructure, Density::Dense, OutputView, reference > & x, + const Vector< MaskType, MaskStructure, Density::Dense, MaskView, reference > & mask, + const Vector< InputType, InputStructure, Density::Dense, InputView, reference > & y, + const typename std::enable_if< ! alp::is_object< OutputType >::value && ! alp::is_object< MaskType >::value && ! alp::is_object< InputType >::value, void >::type * const = NULL ) { // static sanity checks NO_CAST_ASSERT( - ( ! ( descr & descriptors::no_casting ) || std::is_same< OutputType, InputType >::value ), "grb::set (VectorView)", "called with vector parameters whose element data types do not match" ); - NO_CAST_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< MaskType, bool >::value ), "grb::set (VectorView)", "called with non-bool mask element types" ); + ( ! ( descr & descriptors::no_casting ) || std::is_same< OutputType, InputType >::value ), "alp::set (Vector)", "called with vector parameters whose element data types do not match" ); + NO_CAST_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< MaskType, bool >::value ), "alp::set (Vector)", "called with non-bool mask element types" ); constexpr bool out_is_void = std::is_void< OutputType >::value; constexpr bool in_is_void = std::is_void< OutputType >::value; static_assert( ! in_is_void || out_is_void, - "grb::set (reference, VectorView <- VectorView, masked): " + "alp::set (reference, Vector <- Vector, masked): " "if input is void, then the output must be also" ); static_assert( ! ( descr & descriptors::use_index ) || ! out_is_void, - "grb::set (reference, VectorView <- VectorView, masked): " - "use_index descriptor cannot be set if output VectorView is void" ); + "alp::set (reference, Vector <- Vector, masked): " + "use_index descriptor cannot be set if output Vector is void" ); // catch contract violations if( reinterpret_cast< void * >( &x ) == reinterpret_cast< const void * >( &y ) ) { @@ -717,18 +717,18 @@ namespace grb { } /** - * Folds all elements in a ALP VectorView \a x into a single value \a beta. + * Folds all elements in a ALP Vector \a x into a single value \a beta. * * The original value of \a beta is used as the right-hand side input of the * operator \a op. A left-hand side input for \a op is retrieved from the - * input VectorView \a x. The result of the operation is stored in \a beta. + * input Vector \a x. The result of the operation is stored in \a beta. * This process is repeated for every element in \a x. * * At function exit, \a beta will equal * \f$ \beta \odot x_0 \odot x_1 \odot \ldots x_{n-1} \f$. * * @tparam descr The descriptor used for evaluating this function. By - * default, this is grb::descriptors::no_operation. + * default, this is alp::descriptors::no_operation. * @tparam OP The type of the operator to be applied. * The operator must be associative. * @tparam InputType The type of the elements of \a x. @@ -736,8 +736,8 @@ namespace grb { * @tparam InputStructure The structure of the vector \a x. * @tparam InputView The view type applied to the vector \a x. * - * @param[in] x The input VectorView \a x that will not be modified. - * This input VectorView must be dense. + * @param[in] x The input Vector \a x that will not be modified. + * This input Vector must be dense. * @param[in,out] beta On function entry: the initial value to be applied to * \a op from the right-hand side. * On function exit: the result of repeated applications @@ -746,22 +746,22 @@ namespace grb { * * \note We only define fold under monoids, not under plain operators. * - * @returns grb::SUCCESS This function always succeeds. - * @returns grb::ILLEGAL When a sparse VectorView is passed. In this case, the + * @returns alp::SUCCESS This function always succeeds. + * @returns alp::ILLEGAL When a sparse Vector is passed. In this case, the * call to this function will have no other effects. * * \warning Since this function folds from left-to-right using binary * operators, this function \em cannot take sparse vectors as input-- * a monoid is required to give meaning to missing vector entries. - * See grb::reducer for use with sparse vectors instead. + * See alp::reducer for use with sparse vectors instead. * * \parblock * \par Valid descriptors - * grb::descriptors::no_operation, grb::descriptors::no_casting. + * alp::descriptors::no_operation, alp::descriptors::no_casting. * * \note Invalid descriptors will be ignored. * - * If grb::descriptors::no_casting is specified, then 1) the first domain of + * If alp::descriptors::no_casting is specified, then 1) the first domain of * \a op must match \a IOType, 2) the second domain of \a op must match * \a InputType, and 3) the third domain must match \a IOType. If one of these * is not true, the code shall not compile. @@ -793,15 +793,15 @@ namespace grb { // * operators. // * \endparblock * - * @see grb::operators::internal::Operator for a discussion on when in-place + * @see alp::operators::internal::Operator for a discussion on when in-place * and/or vectorised operations are used. */ template< Descriptor descr = descriptors::no_operation, class Monoid, typename InputType, typename InputStructure, typename InputView, typename IOType, typename IOStructure > - RC foldr( const VectorView< InputType, InputStructure, Density::Dense, InputView, reference_dense > & x, - Scalar< IOType, IOStructure, reference_dense > & beta, + RC foldr( const Vector< InputType, InputStructure, Density::Dense, InputView, reference > & x, + Scalar< IOType, IOStructure, reference > & beta, const Monoid & monoid = Monoid(), - const typename std::enable_if< ! grb::is_object< InputType >::value && ! grb::is_object< IOType >::value && grb::is_monoid< Monoid >::value, void >::type * const = NULL ) { + const typename std::enable_if< ! alp::is_object< InputType >::value && ! alp::is_object< IOType >::value && alp::is_monoid< Monoid >::value, void >::type * const = NULL ) { throw std::runtime_error( "Needs an implementation." ); return SUCCESS; @@ -810,16 +810,16 @@ namespace grb { /** C++ scalar variant */ template< Descriptor descr = descriptors::no_operation, class Monoid, typename InputType, typename InputStructure, typename InputView, typename IOType > - RC foldr( const VectorView< InputType, InputStructure, Density::Dense, InputView, reference_dense > & x, + RC foldr( const Vector< InputType, InputStructure, Density::Dense, InputView, reference > & x, IOType & beta, const Monoid & monoid = Monoid(), - const typename std::enable_if< ! grb::is_object< InputType >::value && ! grb::is_object< IOType >::value && grb::is_monoid< Monoid >::value, void >::type * const = NULL ) { + const typename std::enable_if< ! alp::is_object< InputType >::value && ! alp::is_object< IOType >::value && alp::is_monoid< Monoid >::value, void >::type * const = NULL ) { return foldr( x, Scalar< IOType >( beta ), monoid ); } /** - * For all elements in a ALP VectorView \a y, fold the value \f$ \alpha \f$ + * For all elements in a ALP Vector \a y, fold the value \f$ \alpha \f$ * into each element. * * The original value of \f$ \alpha \f$ is used as the left-hand side input @@ -831,7 +831,7 @@ namespace grb { * \f$ \alpha \odot y_i \f$, for all \f$ i \in \{ 0, 1, \dots, n - 1 \} \f$. * * @tparam descr The descriptor used for evaluating this function. - * By default, this is grb::descriptors::no_operation. + * By default, this is alp::descriptors::no_operation. * @tparam OP The type of the operator to be applied. * @tparam InputType The type of \a alpha. * @tparam IOType The type of the elements in \a y. @@ -845,17 +845,17 @@ namespace grb { * On function exit: the output data. * @param[in] op The monoid under which to perform this left-folding. * - * @returns grb::SUCCESS This function always succeeds. + * @returns alp::SUCCESS This function always succeeds. * * \note We only define fold under monoids, not under plain operators. * * \parblock * \par Valid descriptors - * grb::descriptors::no_operation, grb::descriptors::no_casting. + * alp::descriptors::no_operation, alp::descriptors::no_casting. * * \note Invalid descriptors will be ignored. * - * If grb::descriptors::no_casting is specified, then 1) the first domain of + * If alp::descriptors::no_casting is specified, then 1) the first domain of * \a op must match \a IOType, 2) the second domain of \a op must match * \a InputType, and 3) the third domain must match \a IOType. If one of these * is not true, the code shall not compile. @@ -886,22 +886,22 @@ namespace grb { // * bytes of data movement. // * \endparblock * - * @see grb::operators::internal::Operator for a discussion on when in-place + * @see alp::operators::internal::Operator for a discussion on when in-place * and/or vectorised operations are used. */ template< Descriptor descr = descriptors::no_operation, class Monoid, typename IOType, typename InputType, typename IOStructure, typename InputStructure, typename IOView > - RC foldr( const Scalar< InputType, InputStructure, reference_dense > & alpha, - VectorView< IOType, IOStructure, Density::Dense, IOView, reference_dense > & y, + RC foldr( const Scalar< InputType, InputStructure, reference > & alpha, + Vector< IOType, IOStructure, Density::Dense, IOView, reference > & y, const Monoid & monoid = Monoid(), - const typename std::enable_if< ! grb::is_object< InputType >::value && ! grb::is_object< IOType >::value && grb::is_monoid< Monoid >::value, void >::type * const = NULL ) { + const typename std::enable_if< ! alp::is_object< InputType >::value && ! alp::is_object< IOType >::value && alp::is_monoid< Monoid >::value, void >::type * const = NULL ) { // static sanity checks - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Monoid::D1, IOType >::value ), "grb::foldl", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Monoid::D1, IOType >::value ), "alp::foldl", "called with a vector x of a type that does not match the first domain " "of the given operator" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Monoid::D2, InputType >::value ), "grb::foldl", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Monoid::D2, InputType >::value ), "alp::foldl", "called on a vector y of a type that does not match the second domain " "of the given operator" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Monoid::D3, IOType >::value ), "grb::foldl", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Monoid::D3, IOType >::value ), "alp::foldl", "called on a vector x of a type that does not match the third domain " "of the given operator" ); @@ -915,18 +915,18 @@ namespace grb { * Specialisation for scalar \a x. */ template< Descriptor descr = descriptors::no_operation, class OP, typename IOType, typename InputType, typename IOStructure, typename InputStructure, typename IOView > - RC foldr( const Scalar< InputType, InputStructure, reference_dense > & alpha, - VectorView< IOType, IOStructure, Density::Dense, IOView, reference_dense > & y, + RC foldr( const Scalar< InputType, InputStructure, reference > & alpha, + Vector< IOType, IOStructure, Density::Dense, IOView, reference > & y, const OP & op = OP(), - const typename std::enable_if< ! grb::is_object< InputType >::value && ! grb::is_object< IOType >::value && grb::is_operator< OP >::value, void >::type * const = NULL ) { + const typename std::enable_if< ! alp::is_object< InputType >::value && ! alp::is_object< IOType >::value && alp::is_operator< OP >::value, void >::type * const = NULL ) { // static sanity checks - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename OP::D1, IOType >::value ), "grb::foldl", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename OP::D1, IOType >::value ), "alp::foldl", "called with a vector x of a type that does not match the first domain " "of the given operator" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename OP::D2, InputType >::value ), "grb::foldl", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename OP::D2, InputType >::value ), "alp::foldl", "called on a vector y of a type that does not match the second domain " "of the given operator" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename OP::D3, IOType >::value ), "grb::foldl", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename OP::D3, IOType >::value ), "alp::foldl", "called on a vector x of a type that does not match the third domain " "of the given operator" ); @@ -935,14 +935,14 @@ namespace grb { } /** - * Folds all elements in a ALP VectorView \a x into the corresponding + * Folds all elements in a ALP Vector \a x into the corresponding * elements from an input/output vector \a y. The vectors must be of equal * size \f$ n \f$. For all \f$ i \in \{0,1,\ldots,n-1\} \f$, the new value * of at the i-th index of \a y after a call to this function thus equals * \f$ x_i \odot y_i \f$. * * @tparam descr The descriptor used for evaluating this function. By - * default, this is grb::descriptors::no_operation. + * default, this is alp::descriptors::no_operation. * @tparam OP The type of the operator to be applied. * @tparam IOType The type of the elements of \a y. * @tparam InputType The type of the elements of \a x. @@ -958,17 +958,17 @@ namespace grb { * from the right-hand side using elements from \a y. * @param[in] op The operator under which to perform this right-folding. * - * @returns grb::SUCCESS This function always succeeds. + * @returns alp::SUCCESS This function always succeeds. * * \note The element-wise fold is also defined for monoids. * * \parblock * \par Valid descriptors - * grb::descriptors::no_operation, grb::descriptors::no_casting. + * alp::descriptors::no_operation, alp::descriptors::no_casting. * * \note Invalid descriptors will be ignored. * - * If grb::descriptors::no_casting is specified, then 1) the first domain of + * If alp::descriptors::no_casting is specified, then 1) the first domain of * \a op must match \a InputType, 2) the second domain of \a op must match * \a IOType, and 3) the third domain must match \a IOType. If one of these * is not true, the code shall not compile. @@ -1003,7 +1003,7 @@ namespace grb { // * operators whenever allowed. // * \endparblock * - * @see grb::operators::internal::Operator for a discussion on when in-place + * @see alp::operators::internal::Operator for a discussion on when in-place * and/or vectorised operations are used. */ template< Descriptor descr = descriptors::no_operation, class OP, @@ -1011,18 +1011,18 @@ namespace grb { typename IOStructure, typename InputStructure, typename IOView, typename InputView > - RC foldr( const VectorView< InputType, InputStructure, Density::Dense, InputView, reference_dense > & x, - VectorView< IOType, IOStructure, Density::Dense, IOView, reference_dense > & y, + RC foldr( const Vector< InputType, InputStructure, Density::Dense, InputView, reference > & x, + Vector< IOType, IOStructure, Density::Dense, IOView, reference > & y, const OP & op = OP(), - const typename std::enable_if< grb::is_operator< OP >::value && ! grb::is_object< InputType >::value && ! grb::is_object< IOType >::value, void >::type * = NULL ) { + const typename std::enable_if< alp::is_operator< OP >::value && ! alp::is_object< InputType >::value && ! alp::is_object< IOType >::value, void >::type * = NULL ) { // static sanity checks - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename OP::D1, InputType >::value ), "grb::eWiseFoldr", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename OP::D1, InputType >::value ), "alp::eWiseFoldr", "called with a vector x of a type that does not match the first domain " "of the given operator" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename OP::D2, IOType >::value ), "grb::eWiseFoldr", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename OP::D2, IOType >::value ), "alp::eWiseFoldr", "called on a vector y of a type that does not match the second domain " "of the given operator" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename OP::D3, IOType >::value ), "grb::eWiseFoldr", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename OP::D3, IOType >::value ), "alp::eWiseFoldr", "called on a vector y of a type that does not match the third domain " "of the given operator" ); @@ -1044,23 +1044,23 @@ namespace grb { typename IOStructure, typename MaskStructure, typename InputStructure, typename IOView, typename MaskView, typename InputView > - RC foldr( const VectorView< InputType, InputStructure, Density::Dense, InputView, reference_dense > & x, - const VectorView< MaskType, MaskStructure, Density::Dense, MaskView, reference_dense > & m, - VectorView< IOType, IOStructure, Density::Dense, IOView, reference_dense > & y, + RC foldr( const Vector< InputType, InputStructure, Density::Dense, InputView, reference > & x, + const Vector< MaskType, MaskStructure, Density::Dense, MaskView, reference > & m, + Vector< IOType, IOStructure, Density::Dense, IOView, reference > & y, const OP & op = OP(), - const typename std::enable_if< grb::is_operator< OP >::value && ! grb::is_object< InputType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< IOType >::value, void >::type * = + const typename std::enable_if< alp::is_operator< OP >::value && ! alp::is_object< InputType >::value && ! alp::is_object< MaskType >::value && ! alp::is_object< IOType >::value, void >::type * = NULL ) { // static sanity checks - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename OP::D1, InputType >::value ), "grb::eWiseFoldr", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename OP::D1, InputType >::value ), "alp::eWiseFoldr", "called with a vector x of a type that does not match the first domain " "of the given operator" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename OP::D2, IOType >::value ), "grb::eWiseFoldr", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename OP::D2, IOType >::value ), "alp::eWiseFoldr", "called on a vector y of a type that does not match the second domain " "of the given operator" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename OP::D3, IOType >::value ), "grb::eWiseFoldr", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename OP::D3, IOType >::value ), "alp::eWiseFoldr", "called on a vector y of a type that does not match the third domain " "of the given operator" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< bool, MaskType >::value ), "grb::eWiseFoldr", "called with a non-Boolean mask" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< bool, MaskType >::value ), "alp::eWiseFoldr", "called with a non-Boolean mask" ); if( size( m ) == 0 ) { return foldr< descr >( x, y, op ); @@ -1076,14 +1076,14 @@ namespace grb { } /** - * Folds all elements in a ALP VectorView \a x into the corresponding + * Folds all elements in a ALP Vector \a x into the corresponding * elements from an input/output vector \a y. The vectors must be of equal * size \f$ n \f$. For all \f$ i \in \{0,1,\ldots,n-1\} \f$, the new value * of at the i-th index of \a y after a call to this function thus equals * \f$ x_i \odot y_i \f$. * * @tparam descr The descriptor used for evaluating this function. By - * default, this is grb::descriptors::no_operation. + * default, this is alp::descriptors::no_operation. * @tparam Monoid The type of the monoid to be applied. * @tparam IOType The type of the elements of \a y. * @tparam InputType The type of the elements of \a x. @@ -1099,17 +1099,17 @@ namespace grb { * from the right-hand side using elements from \a y. * @param[in] monoid The monoid under which to perform this right-folding. * - * @returns grb::SUCCESS This function always succeeds. + * @returns alp::SUCCESS This function always succeeds. * * \note The element-wise fold is also defined for operators. * * \parblock * \par Valid descriptors - * grb::descriptors::no_operation, grb::descriptors::no_casting. + * alp::descriptors::no_operation, alp::descriptors::no_casting. * * \note Invalid descriptors will be ignored. * - * If grb::descriptors::no_casting is specified, then 1) the first domain of + * If alp::descriptors::no_casting is specified, then 1) the first domain of * \a op must match \a InputType, 2) the second domain of \a op must match * \a IOType, and 3) the third domain must match \a IOType. If one of these * is not true, the code shall not compile. @@ -1144,7 +1144,7 @@ namespace grb { // * operators whenever allowed. // * \endparblock * - * @see grb::operators::internal::Operator for a discussion on when in-place + * @see alp::operators::internal::Operator for a discussion on when in-place * and/or vectorised operations are used. */ template< Descriptor descr = descriptors::no_operation, class Monoid, @@ -1152,18 +1152,18 @@ namespace grb { typename IOStructure, typename InputStructure, typename IOView, typename InputView > - RC foldr( const VectorView< InputType, InputStructure, Density::Dense, InputView, reference_dense > & x, - VectorView< IOType, IOStructure, Density::Dense, IOView, reference_dense > & y, + RC foldr( const Vector< InputType, InputStructure, Density::Dense, InputView, reference > & x, + Vector< IOType, IOStructure, Density::Dense, IOView, reference > & y, const Monoid & monoid = Monoid(), - const typename std::enable_if< grb::is_monoid< Monoid >::value && ! grb::is_object< InputType >::value && ! grb::is_object< IOType >::value, void >::type * = NULL ) { + const typename std::enable_if< alp::is_monoid< Monoid >::value && ! alp::is_object< InputType >::value && ! alp::is_object< IOType >::value, void >::type * = NULL ) { // static sanity checks - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Monoid::D1, InputType >::value ), "grb::eWiseFoldr", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Monoid::D1, InputType >::value ), "alp::eWiseFoldr", "called with a vector x of a type that does not match the first domain " "of the given monoid" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Monoid::D2, IOType >::value ), "grb::eWiseFoldr", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Monoid::D2, IOType >::value ), "alp::eWiseFoldr", "called on a vector y of a type that does not match the second domain " "of the given monoid" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Monoid::D3, IOType >::value ), "grb::eWiseFoldr", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Monoid::D3, IOType >::value ), "alp::eWiseFoldr", "called on a vector y of a type that does not match the third domain " "of the given monoid" ); @@ -1187,23 +1187,23 @@ namespace grb { typename IOStructure, typename MaskStructure, typename InputStructure, typename IOView, typename MaskView, typename InputView > - RC foldr( const VectorView< InputType, InputStructure, Density::Dense, InputView, reference_dense > & x, - const VectorView< MaskType, MaskStructure, Density::Dense, MaskView, reference_dense > & m, - VectorView< IOType, IOStructure, Density::Dense, IOView, reference_dense > & y, + RC foldr( const Vector< InputType, InputStructure, Density::Dense, InputView, reference > & x, + const Vector< MaskType, MaskStructure, Density::Dense, MaskView, reference > & m, + Vector< IOType, IOStructure, Density::Dense, IOView, reference > & y, const Monoid & monoid = Monoid(), - const typename std::enable_if< grb::is_monoid< Monoid >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType >::value && ! grb::is_object< IOType >::value, void >::type * = + const typename std::enable_if< alp::is_monoid< Monoid >::value && ! alp::is_object< MaskType >::value && ! alp::is_object< InputType >::value && ! alp::is_object< IOType >::value, void >::type * = NULL ) { // static sanity checks - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Monoid::D1, InputType >::value ), "grb::eWiseFoldr", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Monoid::D1, InputType >::value ), "alp::eWiseFoldr", "called with a vector x of a type that does not match the first domain " "of the given monoid" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Monoid::D2, IOType >::value ), "grb::eWiseFoldr", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Monoid::D2, IOType >::value ), "alp::eWiseFoldr", "called on a vector y of a type that does not match the second domain " "of the given monoid" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Monoid::D3, IOType >::value ), "grb::eWiseFoldr", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Monoid::D3, IOType >::value ), "alp::eWiseFoldr", "called on a vector y of a type that does not match the third domain " "of the given monoid" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< bool, MaskType >::value ), "grb::eWiseFoldr", "called with a mask of non-Boolean type" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< bool, MaskType >::value ), "alp::eWiseFoldr", "called with a mask of non-Boolean type" ); // check empty mask if( size( m ) == 0 ) { @@ -1221,7 +1221,7 @@ namespace grb { } /** - * For all elements in a ALP VectorView \a x, fold the value \f$ \beta \f$ + * For all elements in a ALP Vector \a x, fold the value \f$ \beta \f$ * into each element. * * The original value of \f$ \beta \f$ is used as the right-hand side input @@ -1234,7 +1234,7 @@ namespace grb { * \f$ x_i \odot \beta \f$, for all \f$ i \in \{ 0, 1, \dots, n - 1 \} \f$. * * @tparam descr The descriptor used for evaluating this function. By - * default, this is grb::descriptors::no_operation. + * default, this is alp::descriptors::no_operation. * @tparam OP The type of the operator to be applied. * @tparam IOType The type of the value \a beta. * @tparam InputType The type of the elements of \a x. @@ -1249,7 +1249,7 @@ namespace grb { * to \a op. * @param[in] op The operator under which to perform this left-folding. * - * @returns grb::SUCCESS This function always succeeds. + * @returns alp::SUCCESS This function always succeeds. * * \note This function is also defined for monoids. * @@ -1258,11 +1258,11 @@ namespace grb { * * \parblock * \par Valid descriptors - * grb::descriptors::no_operation, grb::descriptors::no_casting. + * alp::descriptors::no_operation, alp::descriptors::no_casting. * * \note Invalid descriptors will be ignored. * - * If grb::descriptors::no_casting is specified, then 1) the first domain of + * If alp::descriptors::no_casting is specified, then 1) the first domain of * \a op must match \a IOType, 2) the second domain of \a op must match * \a InputType, and 3) the third domain must match \a IOType. If one of these * is not true, the code shall not compile. @@ -1293,22 +1293,22 @@ namespace grb { // * bytes of data movement. // * \endparblock * - * @see grb::operators::internal::Operator for a discussion on when in-place + * @see alp::operators::internal::Operator for a discussion on when in-place * and/or vectorised operations are used. */ template< Descriptor descr = descriptors::no_operation, class Op, typename IOType, typename InputType, typename IOStructure, typename InputStructure, typename IOView > - RC foldl( VectorView< IOType, IOStructure, Density::Dense, IOView, reference_dense > & x, - const Scalar< InputType, InputStructure, reference_dense > beta, + RC foldl( Vector< IOType, IOStructure, Density::Dense, IOView, reference > & x, + const Scalar< InputType, InputStructure, reference > beta, const Op & op = Op(), - const typename std::enable_if< ! grb::is_object< IOType >::value && ! grb::is_object< InputType >::value && grb::is_operator< Op >::value, void >::type * = NULL ) { + const typename std::enable_if< ! alp::is_object< IOType >::value && ! alp::is_object< InputType >::value && alp::is_operator< Op >::value, void >::type * = NULL ) { // static sanity checks - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Op::D1, IOType >::value ), "grb::foldl", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Op::D1, IOType >::value ), "alp::foldl", "called with a vector x of a type that does not match the first domain " "of the given operator" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Op::D2, InputType >::value ), "grb::foldl", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Op::D2, InputType >::value ), "alp::foldl", "called on a vector y of a type that does not match the second domain " "of the given operator" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Op::D3, IOType >::value ), "grb::foldl", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Op::D3, IOType >::value ), "alp::foldl", "called on a vector x of a type that does not match the third domain " "of the given operator" ); @@ -1317,7 +1317,7 @@ namespace grb { } /** - * For all elements in a ALP VectorView \a x, fold the value \f$ \beta \f$ + * For all elements in a ALP Vector \a x, fold the value \f$ \beta \f$ * into each element. * * Masked operator variant. @@ -1327,23 +1327,23 @@ namespace grb { typename IOStructure, typename MaskStructure, typename InputStructure, typename IOView, typename MaskView, typename InputView > - RC foldl( VectorView< IOType, IOStructure, Density::Dense, IOView, reference_dense > & x, - const VectorView< MaskType, MaskStructure, Density::Dense, MaskView, reference_dense > & m, - const Scalar< InputType, InputStructure, reference_dense > &beta, + RC foldl( Vector< IOType, IOStructure, Density::Dense, IOView, reference > & x, + const Vector< MaskType, MaskStructure, Density::Dense, MaskView, reference > & m, + const Scalar< InputType, InputStructure, reference > &beta, const Op & op = Op(), - const typename std::enable_if< ! grb::is_object< IOType >::value && ! grb::is_object< InputType >::value && grb::is_operator< Op >::value, void >::type * = NULL ) { + const typename std::enable_if< ! alp::is_object< IOType >::value && ! alp::is_object< InputType >::value && alp::is_operator< Op >::value, void >::type * = NULL ) { // static sanity checks - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Op::D1, IOType >::value ), "grb::foldl", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Op::D1, IOType >::value ), "alp::foldl", "called with a vector x of a type that does not match the first domain " "of the given operator" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Op::D2, InputType >::value ), "grb::foldl", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Op::D2, InputType >::value ), "alp::foldl", "called on a vector y of a type that does not match the second domain " "of the given operator" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Op::D3, IOType >::value ), "grb::foldl", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Op::D3, IOType >::value ), "alp::foldl", "called on a vector x of a type that does not match the third domain " "of the given operator" ); NO_CAST_OP_ASSERT( - ( ! ( descr & descriptors::no_casting ) || std::is_same< bool, MaskType >::value ), "grb::foldl (reference_dense, vector <- scalar, masked)", "provided mask does not have boolean entries" ); + ( ! ( descr & descriptors::no_casting ) || std::is_same< bool, MaskType >::value ), "alp::foldl (reference, vector <- scalar, masked)", "provided mask does not have boolean entries" ); if( size( m ) == 0 ) { return foldl< descr >( x, beta, op ); } @@ -1352,7 +1352,7 @@ namespace grb { } /** - * For all elements in a ALP VectorView \a x, fold the value \f$ \beta \f$ + * For all elements in a ALP Vector \a x, fold the value \f$ \beta \f$ * into each element. * * The original value of \f$ \beta \f$ is used as the right-hand side input @@ -1365,7 +1365,7 @@ namespace grb { * \f$ x_i \odot \beta \f$, for all \f$ i \in \{ 0, 1, \dots, n - 1 \} \f$. * * @tparam descr The descriptor used for evaluating this function. By - * default, this is grb::descriptors::no_operation. + * default, this is alp::descriptors::no_operation. * @tparam Monoid The type of the monoid to be applied. * @tparam IOType The type of the elements of \a x. * @tparam InputType The type of the value \a beta. @@ -1379,17 +1379,17 @@ namespace grb { * to \a op. * @param[in] monoid The monoid under which to perform this left-folding. * - * @returns grb::SUCCESS This function always succeeds. + * @returns alp::SUCCESS This function always succeeds. * * \note This function is also defined for operators. * * \parblock * \par Valid descriptors - * grb::descriptors::no_operation, grb::descriptors::no_casting. + * alp::descriptors::no_operation, alp::descriptors::no_casting. * * \note Invalid descriptors will be ignored. * - * If grb::descriptors::no_casting is specified, then 1) the first domain of + * If alp::descriptors::no_casting is specified, then 1) the first domain of * \a op must match \a IOType, 2) the second domain of \a op must match * \a InputType, and 3) the third domain must match \a IOType. If one of these * is not true, the code shall not compile. @@ -1420,22 +1420,22 @@ namespace grb { // * bytes of data movement. // * \endparblock * - * @see grb::operators::internal::Operator for a discussion on when in-place + * @see alp::operators::internal::Operator for a discussion on when in-place * and/or vectorised operations are used. */ template< Descriptor descr = descriptors::no_operation, class Monoid, typename IOType, typename InputType, typename IOStructure, typename IOView > - RC foldl( VectorView< IOType, IOStructure, Density::Dense, IOView, reference_dense > & x, + RC foldl( Vector< IOType, IOStructure, Density::Dense, IOView, reference > & x, const InputType beta, const Monoid & monoid = Monoid(), - const typename std::enable_if< ! grb::is_object< IOType >::value && ! grb::is_object< InputType >::value && grb::is_monoid< Monoid >::value, void >::type * = NULL ) { + const typename std::enable_if< ! alp::is_object< IOType >::value && ! alp::is_object< InputType >::value && alp::is_monoid< Monoid >::value, void >::type * = NULL ) { // static sanity checks - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Monoid::D1, IOType >::value ), "grb::foldl", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Monoid::D1, IOType >::value ), "alp::foldl", "called with a vector x of a type that does not match the first domain " "of the given monoid" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Monoid::D2, InputType >::value ), "grb::foldl", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Monoid::D2, InputType >::value ), "alp::foldl", "called on a vector y of a type that does not match the second domain " "of the given monoid" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Monoid::D3, IOType >::value ), "grb::foldl", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Monoid::D3, IOType >::value ), "alp::foldl", "called on a vector x of a type that does not match the third domain " "of the given monoid" ); @@ -1444,7 +1444,7 @@ namespace grb { } /** - * For all elements in a ALP VectorView \a x, fold the value \f$ \beta \f$ + * For all elements in a ALP Vector \a x, fold the value \f$ \beta \f$ * into each element. * * Masked monoid variant. @@ -1454,24 +1454,24 @@ namespace grb { typename IOStructure, typename MaskStructure, typename IOView, typename MaskView > - RC foldl( VectorView< IOType, IOStructure, Density::Dense, IOView, reference_dense > & x, - const VectorView< MaskType, MaskStructure, Density::Dense, MaskView, reference_dense > & m, + RC foldl( Vector< IOType, IOStructure, Density::Dense, IOView, reference > & x, + const Vector< MaskType, MaskStructure, Density::Dense, MaskView, reference > & m, const InputType & beta, const Monoid & monoid = Monoid(), - const typename std::enable_if< ! grb::is_object< IOType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType >::value && grb::is_monoid< Monoid >::value, void >::type * = + const typename std::enable_if< ! alp::is_object< IOType >::value && ! alp::is_object< MaskType >::value && ! alp::is_object< InputType >::value && alp::is_monoid< Monoid >::value, void >::type * = NULL ) { // static sanity checks - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Monoid::D1, IOType >::value ), "grb::foldl", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Monoid::D1, IOType >::value ), "alp::foldl", "called with a vector x of a type that does not match the first domain " "of the given monoid" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Monoid::D2, InputType >::value ), "grb::foldl", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Monoid::D2, InputType >::value ), "alp::foldl", "called on a vector y of a type that does not match the second domain " "of the given monoid" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Monoid::D3, IOType >::value ), "grb::foldl", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Monoid::D3, IOType >::value ), "alp::foldl", "called on a vector x of a type that does not match the third domain " "of the given monoid" ); NO_CAST_OP_ASSERT( - ( ! ( descr & descriptors::no_casting ) || std::is_same< bool, MaskType >::value ), "grb::foldl (reference_dense, vector <- scalar, masked, monoid)", "provided mask does not have boolean entries" ); + ( ! ( descr & descriptors::no_casting ) || std::is_same< bool, MaskType >::value ), "alp::foldl (reference, vector <- scalar, masked, monoid)", "provided mask does not have boolean entries" ); if( size( m ) == 0 ) { return foldl< descr >( x, beta, monoid ); } @@ -1481,14 +1481,14 @@ namespace grb { } /** - * Folds all elements in a ALP VectorView \a y into the corresponding + * Folds all elements in a ALP Vector \a y into the corresponding * elements from an input/output vector \a x. The vectors must be of equal * size \f$ n \f$. For all \f$ i \in \{0,1,\ldots,n-1\} \f$, the new value * of at the i-th index of \a x after a call to this function thus equals * \f$ x_i \odot y_i \f$. * * @tparam descr The descriptor used for evaluating this function. By - * default, this is grb::descriptors::no_operation. + * default, this is alp::descriptors::no_operation. * @tparam OP The type of the operator to be applied. * @tparam IOType The type of the value \a x. * @tparam InputType The type of the elements of \a y. @@ -1505,17 +1505,17 @@ namespace grb { * to \a op as right-hand side input. * @param[in] op The operator under which to perform this left-folding. * - * @returns grb::SUCCESS This function always succeeds. + * @returns alp::SUCCESS This function always succeeds. * * \note This function is also defined for monoids. * * \parblock * \par Valid descriptors - * grb::descriptors::no_operation, grb::descriptors::no_casting. + * alp::descriptors::no_operation, alp::descriptors::no_casting. * * \note Invalid descriptors will be ignored. * - * If grb::descriptors::no_casting is specified, then 1) the first domain of + * If alp::descriptors::no_casting is specified, then 1) the first domain of * \a op must match \a IOType, 2) the second domain of \a op must match * \a InputType, and 3) the third domain must match \a IOType. If one of these * is not true, the code shall not compile. @@ -1551,25 +1551,25 @@ namespace grb { // * domain, and the operator used allow for this. // * \endparblock * - * @see grb::operators::internal::Operator for a discussion on when in-place + * @see alp::operators::internal::Operator for a discussion on when in-place * and/or vectorised operations are used. */ template< Descriptor descr = descriptors::no_operation, class OP, typename IOType, typename InputType, typename IOStructure, typename InputStructure, typename IOView, typename InputView > - RC foldl( VectorView< IOType, IOStructure, Density::Dense, IOView, reference_dense > & x, - const VectorView< InputType, InputStructure, Density::Dense, InputView, reference_dense > & y, + RC foldl( Vector< IOType, IOStructure, Density::Dense, IOView, reference > & x, + const Vector< InputType, InputStructure, Density::Dense, InputView, reference > & y, const OP & op = OP(), - const typename std::enable_if< grb::is_operator< OP >::value && ! grb::is_object< IOType >::value && ! grb::is_object< InputType >::value, void >::type * = NULL ) { + const typename std::enable_if< alp::is_operator< OP >::value && ! alp::is_object< IOType >::value && ! alp::is_object< InputType >::value, void >::type * = NULL ) { // static sanity checks - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename OP::D1, IOType >::value ), "grb::foldl", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename OP::D1, IOType >::value ), "alp::foldl", "called with a vector x of a type that does not match the first domain " "of the given operator" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename OP::D2, InputType >::value ), "grb::foldl", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename OP::D2, InputType >::value ), "alp::foldl", "called on a vector y of a type that does not match the second domain " "of the given operator" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename OP::D3, IOType >::value ), "grb::foldl", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename OP::D3, IOType >::value ), "alp::foldl", "called on a vector x of a type that does not match the third domain " "of the given operator" ); @@ -1584,14 +1584,14 @@ namespace grb { } /** - * Folds all elements in a ALP VectorView \a y into the corresponding + * Folds all elements in a ALP Vector \a y into the corresponding * elements from an input/output vector \a x. The vectors must be of equal * size \f$ n \f$. For all \f$ i \in \{0,1,\ldots,n-1\} \f$, the new value * of at the i-th index of \a x after a call to this function thus equals * \f$ x_i \odot y_i \f$. * * @tparam descr The descriptor used for evaluating this function. By - * default, this is grb::descriptors::no_operation. + * default, this is alp::descriptors::no_operation. * @tparam Monoid The type of the monoid to be applied. * @tparam IOType The type of the value \a x. * @tparam InputType The type of the elements of \a y. @@ -1608,17 +1608,17 @@ namespace grb { * to \a op as right-hand side input. * @param[in] monoid The operator under which to perform this left-folding. * - * @returns grb::SUCCESS This function always succeeds. + * @returns alp::SUCCESS This function always succeeds. * * \note This function is also defined for operators. * * \parblock * \par Valid descriptors - * grb::descriptors::no_operation, grb::descriptors::no_casting. + * alp::descriptors::no_operation, alp::descriptors::no_casting. * * \note Invalid descriptors will be ignored. * - * If grb::descriptors::no_casting is specified, then 1) the first domain of + * If alp::descriptors::no_casting is specified, then 1) the first domain of * \a op must match \a IOType, 2) the second domain of \a op must match * \a InputType, and 3) the third domain must match \a IOType. If one of these * is not true, the code shall not compile. @@ -1654,7 +1654,7 @@ namespace grb { // * domain, and the operator used allow for this. // * \endparblock * - * @see grb::operators::internal::Operator for a discussion on when in-place + * @see alp::operators::internal::Operator for a discussion on when in-place * and/or vectorised operations are used. */ template< Descriptor descr = descriptors::no_operation, class Monoid, @@ -1662,18 +1662,18 @@ namespace grb { typename IOStructure, typename InputStructure, typename IOView, typename InputView > - RC foldl( VectorView< IOType, IOStructure, Density::Dense, IOView, reference_dense > & x, - const VectorView< InputType, InputStructure, Density::Dense, InputView, reference_dense > & y, + RC foldl( Vector< IOType, IOStructure, Density::Dense, IOView, reference > & x, + const Vector< InputType, InputStructure, Density::Dense, InputView, reference > & y, const Monoid & monoid = Monoid(), - const typename std::enable_if< grb::is_monoid< Monoid >::value && ! grb::is_object< IOType >::value && ! grb::is_object< InputType >::value, void >::type * = NULL ) { + const typename std::enable_if< alp::is_monoid< Monoid >::value && ! alp::is_object< IOType >::value && ! alp::is_object< InputType >::value, void >::type * = NULL ) { // static sanity checks - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Monoid::D1, IOType >::value ), "grb::foldl", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Monoid::D1, IOType >::value ), "alp::foldl", "called with a vector x of a type that does not match the first domain " "of the given operator" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Monoid::D2, InputType >::value ), "grb::foldl", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Monoid::D2, InputType >::value ), "alp::foldl", "called on a vector y of a type that does not match the second domain " "of the given operator" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Monoid::D3, IOType >::value ), "grb::foldl", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Monoid::D3, IOType >::value ), "alp::foldl", "called on a vector x of a type that does not match the third domain " "of the given operator" ); @@ -1697,23 +1697,23 @@ namespace grb { typename IOStructure, typename MaskStructure, typename InputStructure, typename IOView, typename MaskView, typename InputView > - RC foldl( VectorView< IOType, IOStructure, Density::Dense, IOView, reference_dense > & x, - const VectorView< MaskType, MaskStructure, Density::Dense, MaskView, reference_dense > & m, - const VectorView< InputType, InputStructure, Density::Dense, InputView, reference_dense > & y, + RC foldl( Vector< IOType, IOStructure, Density::Dense, IOView, reference > & x, + const Vector< MaskType, MaskStructure, Density::Dense, MaskView, reference > & m, + const Vector< InputType, InputStructure, Density::Dense, InputView, reference > & y, const OP & op = OP(), - const typename std::enable_if< grb::is_operator< OP >::value && ! grb::is_object< IOType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType >::value, void >::type * = + const typename std::enable_if< alp::is_operator< OP >::value && ! alp::is_object< IOType >::value && ! alp::is_object< MaskType >::value && ! alp::is_object< InputType >::value, void >::type * = NULL ) { // static sanity checks - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename OP::D1, IOType >::value ), "grb::foldl", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename OP::D1, IOType >::value ), "alp::foldl", "called with a vector x of a type that does not match the first domain " "of the given operator" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename OP::D2, InputType >::value ), "grb::foldl", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename OP::D2, InputType >::value ), "alp::foldl", "called on a vector y of a type that does not match the second domain " "of the given operator" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename OP::D3, IOType >::value ), "grb::foldl", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename OP::D3, IOType >::value ), "alp::foldl", "called on a vector x of a type that does not match the third domain " "of the given operator" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< bool, MaskType >::value ), "grb::foldl", "called with a mask that does not have boolean entries " ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< bool, MaskType >::value ), "alp::foldl", "called with a mask that does not have boolean entries " ); // catch empty mask if( size( m ) == 0 ) { @@ -1740,23 +1740,23 @@ namespace grb { typename IOStructure, typename MaskStructure, typename InputStructure, typename IOView, typename MaskView, typename InputView > - RC foldl( VectorView< IOType, IOStructure, Density::Dense, IOView, reference_dense > & x, - const VectorView< MaskType, MaskStructure, Density::Dense, MaskView, reference_dense > & m, - const VectorView< InputType, InputStructure, Density::Dense, InputView, reference_dense > & y, + RC foldl( Vector< IOType, IOStructure, Density::Dense, IOView, reference > & x, + const Vector< MaskType, MaskStructure, Density::Dense, MaskView, reference > & m, + const Vector< InputType, InputStructure, Density::Dense, InputView, reference > & y, const Monoid & monoid = Monoid(), - const typename std::enable_if< grb::is_monoid< Monoid >::value && ! grb::is_object< IOType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType >::value, void >::type * = + const typename std::enable_if< alp::is_monoid< Monoid >::value && ! alp::is_object< IOType >::value && ! alp::is_object< MaskType >::value && ! alp::is_object< InputType >::value, void >::type * = NULL ) { // static sanity checks - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Monoid::D1, IOType >::value ), "grb::foldl", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Monoid::D1, IOType >::value ), "alp::foldl", "called with a vector x of a type that does not match the first domain " "of the given operator" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Monoid::D2, InputType >::value ), "grb::foldl", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Monoid::D2, InputType >::value ), "alp::foldl", "called on a vector y of a type that does not match the second domain " "of the given operator" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Monoid::D3, IOType >::value ), "grb::foldl", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Monoid::D3, IOType >::value ), "alp::foldl", "called on a vector x of a type that does not match the third domain " "of the given operator" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< bool, MaskType >::value ), "grb::foldl", "called with a mask that does not have boolean entries " ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< bool, MaskType >::value ), "alp::foldl", "called with a mask that does not have boolean entries " ); // catch empty mask if( size( m ) == 0 ) { @@ -1816,11 +1816,11 @@ namespace grb { * @param[out] z The pre-allocated output vector. * @param[in] op The operator to use. * - * @return grb::MISMATCH Whenever the dimensions of \a x and \a z do not + * @return alp::MISMATCH Whenever the dimensions of \a x and \a z do not * match. All input data containers are left untouched * if this exit code is returned; it will be as though * this call was never made. - * @return grb::SUCCESS On successful completion of this call. + * @return alp::SUCCESS On successful completion of this call. * // * \parblock // * \par Performance semantics @@ -1849,11 +1849,11 @@ namespace grb { typename OutputStructure, typename InputStructure1, typename InputStructure2, typename OutputView, typename InputView1 > - RC eWiseApply( VectorView< OutputType, OutputStructure, Density::Dense, OutputView, reference_dense > & z, - const VectorView< InputType1, InputStructure1, Density::Dense, InputView1, reference_dense > & x, - const Scalar< InputType2, InputStructure2, reference_dense > &beta, + RC eWiseApply( Vector< OutputType, OutputStructure, Density::Dense, OutputView, reference > & z, + const Vector< InputType1, InputStructure1, Density::Dense, InputView1, reference > & x, + const Scalar< InputType2, InputStructure2, reference > &beta, const OP & op = OP(), - const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_operator< OP >::value, + const typename std::enable_if< ! alp::is_object< OutputType >::value && ! alp::is_object< InputType1 >::value && ! alp::is_object< InputType2 >::value && alp::is_operator< OP >::value, void >::type * const = NULL ) { #ifdef _DEBUG std::cout << "In eWiseApply ([T1]<-[T2]<-T3), operator variant\n"; @@ -1872,11 +1872,11 @@ namespace grb { typename OutputStructure, typename InputStructure1, typename InputStructure2, typename OutputView > - RC eWiseApply( VectorView< OutputType, OutputStructure, Density::Dense, OutputView, reference_dense > & z, - const Scalar< InputType1, InputStructure1, reference_dense> &alpha, - const Scalar< InputType2, InputStructure2, reference_dense> &beta, + RC eWiseApply( Vector< OutputType, OutputStructure, Density::Dense, OutputView, reference > & z, + const Scalar< InputType1, InputStructure1, reference> &alpha, + const Scalar< InputType2, InputStructure2, reference> &beta, const OP & op = OP(), - const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_operator< OP >::value, + const typename std::enable_if< ! alp::is_object< OutputType >::value && ! alp::is_object< InputType1 >::value && ! alp::is_object< InputType2 >::value && alp::is_operator< OP >::value, void >::type * const = NULL ) { #ifdef _DEBUG std::cout << "In eWiseApply ([T1]<-T2<-T3), operator variant\n"; @@ -1897,11 +1897,11 @@ namespace grb { typename OutputStructure, typename InputStructure1, typename InputStructure2, typename OutputView > - RC eWiseApply( VectorView< OutputType, OutputStructure, Density::Dense, OutputView, reference_dense > & z, - const Scalar< InputType1, InputStructure1, reference_dense> &alpha, - const Scalar< InputType2, InputStructure2, reference_dense> &beta, + RC eWiseApply( Vector< OutputType, OutputStructure, Density::Dense, OutputView, reference > & z, + const Scalar< InputType1, InputStructure1, reference> &alpha, + const Scalar< InputType2, InputStructure2, reference> &beta, const Monoid & monoid = Monoid(), - const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_monoid< Monoid >::value, + const typename std::enable_if< ! alp::is_object< OutputType >::value && ! alp::is_object< InputType1 >::value && ! alp::is_object< InputType2 >::value && alp::is_monoid< Monoid >::value, void >::type * const = NULL ) { #ifdef _DEBUG std::cout << "In eWiseApply ([T1]<-T2<-T3), monoid variant\n"; @@ -1920,13 +1920,13 @@ namespace grb { typename OutputStructure, typename MaskStructure, typename InputStructure1, typename InputStructure2, typename OutputView, typename MaskView, typename InputView1 > - RC eWiseApply( VectorView< OutputType, OutputStructure, Density::Dense, OutputView, reference_dense > & z, - const VectorView< MaskType, MaskStructure, Density::Dense, MaskView, reference_dense > & mask, - const VectorView< InputType1, InputStructure1, Density::Dense, InputView1, reference_dense > & x, - const Scalar< InputType2, InputStructure2, reference_dense > &beta, + RC eWiseApply( Vector< OutputType, OutputStructure, Density::Dense, OutputView, reference > & z, + const Vector< MaskType, MaskStructure, Density::Dense, MaskView, reference > & mask, + const Vector< InputType1, InputStructure1, Density::Dense, InputView1, reference > & x, + const Scalar< InputType2, InputStructure2, reference > &beta, const OP & op = OP(), - const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && - grb::is_operator< OP >::value, + const typename std::enable_if< ! alp::is_object< OutputType >::value && ! alp::is_object< MaskType >::value && ! alp::is_object< InputType1 >::value && ! alp::is_object< InputType2 >::value && + alp::is_operator< OP >::value, void >::type * const = NULL ) { #ifdef _DEBUG std::cout << "In masked eWiseApply ([T1]<-[T2]<-T3, using operator)\n"; @@ -1949,11 +1949,11 @@ namespace grb { typename OutputStructure, typename InputStructure1, typename InputStructure2, typename OutputView, typename InputView1, typename InputView2 > - RC eWiseApply( VectorView< OutputType, OutputStructure, Density::Dense, OutputView, reference_dense > & z, - const VectorView< InputType1, InputStructure1, Density::Dense, InputView1, reference_dense > & x, - const VectorView< InputType2, InputStructure2, Density::Dense, InputView2, reference_dense > & y, + RC eWiseApply( Vector< OutputType, OutputStructure, Density::Dense, OutputView, reference > & z, + const Vector< InputType1, InputStructure1, Density::Dense, InputView1, reference > & x, + const Vector< InputType2, InputStructure2, Density::Dense, InputView2, reference > & y, const Monoid & monoid = Monoid(), - const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_monoid< Monoid >::value, + const typename std::enable_if< ! alp::is_object< OutputType >::value && ! alp::is_object< InputType1 >::value && ! alp::is_object< InputType2 >::value && alp::is_monoid< Monoid >::value, void >::type * const = NULL ) { #ifdef _DEBUG std::cout << "In unmasked eWiseApply ([T1]<-[T2]<-[T3], using monoid)\n"; @@ -1972,11 +1972,11 @@ namespace grb { typename OutputStructure, typename InputStructure1, typename InputStructure2, typename OutputView, typename InputView2 > - RC eWiseApply( VectorView< OutputType, OutputStructure, Density::Dense, OutputView, reference_dense > & z, - const Scalar< InputType1, InputStructure1, reference_dense> &alpha, - const VectorView< InputType2, InputStructure2, Density::Dense, InputView2, reference_dense > & y, + RC eWiseApply( Vector< OutputType, OutputStructure, Density::Dense, OutputView, reference > & z, + const Scalar< InputType1, InputStructure1, reference> &alpha, + const Vector< InputType2, InputStructure2, Density::Dense, InputView2, reference > & y, const Monoid & monoid = Monoid(), - const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_monoid< Monoid >::value, + const typename std::enable_if< ! alp::is_object< OutputType >::value && ! alp::is_object< InputType1 >::value && ! alp::is_object< InputType2 >::value && alp::is_monoid< Monoid >::value, void >::type * const = NULL ) { #ifdef _DEBUG std::cout << "In unmasked eWiseApply ([T1]<-T2<-[T3], using monoid)\n"; @@ -1995,11 +1995,11 @@ namespace grb { typename OutputStructure, typename InputStructure1, typename InputStructure2, typename OutputView, typename InputView1 > - RC eWiseApply( VectorView< OutputType, OutputStructure, Density::Dense, OutputView, reference_dense > & z, - const VectorView< InputType1, InputStructure1, Density::Dense, InputView1, reference_dense > & x, - const Scalar< InputType2, InputStructure2, reference_dense > &beta, + RC eWiseApply( Vector< OutputType, OutputStructure, Density::Dense, OutputView, reference > & z, + const Vector< InputType1, InputStructure1, Density::Dense, InputView1, reference > & x, + const Scalar< InputType2, InputStructure2, reference > &beta, const Monoid & monoid = Monoid(), - const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_monoid< Monoid >::value, + const typename std::enable_if< ! alp::is_object< OutputType >::value && ! alp::is_object< InputType1 >::value && ! alp::is_object< InputType2 >::value && alp::is_monoid< Monoid >::value, void >::type * const = NULL ) { #ifdef _DEBUG std::cout << "In unmasked eWiseApply ([T1]<-T2<-[T3], using monoid)\n"; @@ -2018,13 +2018,13 @@ namespace grb { typename OutputStructure, typename MaskStructure, typename InputStructure1, typename InputStructure2, typename OutputView, typename MaskView, typename InputView1, typename InputView2 > - RC eWiseApply( VectorView< OutputType, OutputStructure, Density::Dense, OutputView, reference_dense > & z, - const VectorView< MaskType, MaskStructure, Density::Dense, MaskView, reference_dense > & mask, - const VectorView< InputType1, InputStructure1, Density::Dense, InputView1, reference_dense > & x, - const VectorView< InputType2, InputStructure2, Density::Dense, InputView2, reference_dense > & y, + RC eWiseApply( Vector< OutputType, OutputStructure, Density::Dense, OutputView, reference > & z, + const Vector< MaskType, MaskStructure, Density::Dense, MaskView, reference > & mask, + const Vector< InputType1, InputStructure1, Density::Dense, InputView1, reference > & x, + const Vector< InputType2, InputStructure2, Density::Dense, InputView2, reference > & y, const Monoid & monoid = Monoid(), - const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && - grb::is_monoid< Monoid >::value, + const typename std::enable_if< ! alp::is_object< OutputType >::value && ! alp::is_object< MaskType >::value && ! alp::is_object< InputType1 >::value && ! alp::is_object< InputType2 >::value && + alp::is_monoid< Monoid >::value, void >::type * const = NULL ) { #ifdef _DEBUG std::cout << "In masked eWiseApply ([T1]<-[T2]<-[T3], using monoid)\n"; @@ -2043,13 +2043,13 @@ namespace grb { typename OutputStructure, typename MaskStructure, typename InputStructure1, typename InputStructure2, typename OutputView, typename MaskView, typename InputView2 > - RC eWiseApply( VectorView< OutputType, OutputStructure, Density::Dense, OutputView, reference_dense > & z, - const VectorView< MaskType, MaskStructure, Density::Dense, MaskView, reference_dense > & mask, - const Scalar< InputType1, InputStructure1, reference_dense> &alpha, - const VectorView< InputType2, InputStructure2, Density::Dense, InputView2, reference_dense > & y, + RC eWiseApply( Vector< OutputType, OutputStructure, Density::Dense, OutputView, reference > & z, + const Vector< MaskType, MaskStructure, Density::Dense, MaskView, reference > & mask, + const Scalar< InputType1, InputStructure1, reference> &alpha, + const Vector< InputType2, InputStructure2, Density::Dense, InputView2, reference > & y, const Monoid & monoid = Monoid(), - const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && - grb::is_monoid< Monoid >::value, + const typename std::enable_if< ! alp::is_object< OutputType >::value && ! alp::is_object< MaskType >::value && ! alp::is_object< InputType1 >::value && ! alp::is_object< InputType2 >::value && + alp::is_monoid< Monoid >::value, void >::type * const = NULL ) { #ifdef _DEBUG std::cout << "In masked eWiseApply ([T1]<-T2<-[T3], using monoid)\n"; @@ -2068,13 +2068,13 @@ namespace grb { typename OutputStructure, typename MaskStructure, typename InputStructure1, typename InputStructure2, typename OutputView, typename MaskView, typename InputView1 > - RC eWiseApply( VectorView< OutputType, OutputStructure, Density::Dense, OutputView, reference_dense > & z, - const VectorView< MaskType, MaskStructure, Density::Dense, MaskView, reference_dense > & mask, - const VectorView< InputType1, InputStructure1, Density::Dense, InputView1, reference_dense > & x, - const Scalar< InputType2, InputStructure2, reference_dense > &beta, + RC eWiseApply( Vector< OutputType, OutputStructure, Density::Dense, OutputView, reference > & z, + const Vector< MaskType, MaskStructure, Density::Dense, MaskView, reference > & mask, + const Vector< InputType1, InputStructure1, Density::Dense, InputView1, reference > & x, + const Scalar< InputType2, InputStructure2, reference > &beta, const Monoid & monoid = Monoid(), - const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && - grb::is_monoid< Monoid >::value, + const typename std::enable_if< ! alp::is_object< OutputType >::value && ! alp::is_object< MaskType >::value && ! alp::is_object< InputType1 >::value && ! alp::is_object< InputType2 >::value && + alp::is_monoid< Monoid >::value, void >::type * const = NULL ) { #ifdef _DEBUG std::cout << "In masked eWiseApply ([T1]<-[T2]<-T3, using monoid)\n"; @@ -2123,11 +2123,11 @@ namespace grb { * @param[out] z The pre-allocated output vector. * @param[in] op The operator to use. * - * @return grb::MISMATCH Whenever the dimensions of \a y and \a z do not + * @return alp::MISMATCH Whenever the dimensions of \a y and \a z do not * match. All input data containers are left untouched * if this exit code is returned; it will be as though * this call was never made. - * @return grb::SUCCESS On successful completion of this call. + * @return alp::SUCCESS On successful completion of this call. * // * \parblock // * \par Performance semantics @@ -2156,11 +2156,11 @@ namespace grb { typename OutputStructure, typename InputStructure1, typename InputStructure2, typename OutputView, typename InputView2 > - RC eWiseApply( VectorView< OutputType, OutputStructure, Density::Dense, OutputView, reference_dense > & z, - const Scalar< InputType1, InputStructure1, reference_dense > &alpha, - const VectorView< InputType2, InputStructure2, Density::Dense, InputView2, reference_dense > & y, + RC eWiseApply( Vector< OutputType, OutputStructure, Density::Dense, OutputView, reference > & z, + const Scalar< InputType1, InputStructure1, reference > &alpha, + const Vector< InputType2, InputStructure2, Density::Dense, InputView2, reference > & y, const OP & op = OP(), - const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_operator< OP >::value, + const typename std::enable_if< ! alp::is_object< OutputType >::value && ! alp::is_object< InputType1 >::value && ! alp::is_object< InputType2 >::value && alp::is_operator< OP >::value, void >::type * const = NULL ) { #ifdef _DEBUG std::cout << "In eWiseApply ([T1]<-T2<-[T3]), operator variant\n"; @@ -2179,13 +2179,13 @@ namespace grb { typename OutputStructure, typename MaskStructure, typename InputStructure1, typename InputStructure2, typename OutputView, typename MaskView, typename InputView2 > - RC eWiseApply( VectorView< OutputType, OutputStructure, Density::Dense, OutputView, reference_dense > & z, - const VectorView< MaskType, MaskStructure, Density::Dense, MaskView, reference_dense > & mask, - const Scalar< InputType1, InputStructure1, reference_dense> &alpha, - const VectorView< InputType2, InputStructure2, Density::Dense, InputView2, reference_dense > & y, + RC eWiseApply( Vector< OutputType, OutputStructure, Density::Dense, OutputView, reference > & z, + const Vector< MaskType, MaskStructure, Density::Dense, MaskView, reference > & mask, + const Scalar< InputType1, InputStructure1, reference> &alpha, + const Vector< InputType2, InputStructure2, Density::Dense, InputView2, reference > & y, const OP & op = OP(), - const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && - grb::is_operator< OP >::value, + const typename std::enable_if< ! alp::is_object< OutputType >::value && ! alp::is_object< MaskType >::value && ! alp::is_object< InputType1 >::value && ! alp::is_object< InputType2 >::value && + alp::is_operator< OP >::value, void >::type * const = NULL ) { #ifdef _DEBUG std::cout << "In masked eWiseApply ([T1]<-T2<-[T3], operator variant)\n"; @@ -2237,12 +2237,12 @@ namespace grb { * @param[out] z The pre-allocated output vector. * @param[in] op The operator to use. * - * @return grb::ILLEGAL When \a x equals \a y. - * @return grb::MISMATCH Whenever the dimensions of \a x, \a y, and \a z + * @return alp::ILLEGAL When \a x equals \a y. + * @return alp::MISMATCH Whenever the dimensions of \a x, \a y, and \a z * do not match. All input data containers are left * untouched if this exit code is returned; it will * be as though this call was never made. - * @return grb::SUCCESS On successful completion of this call. + * @return alp::SUCCESS On successful completion of this call. * // * \parblock // * \par Performance semantics @@ -2273,11 +2273,11 @@ namespace grb { typename OutputStructure, typename InputStructure1, typename InputStructure2, typename OutputView, typename InputView1, typename InputView2 > - RC eWiseApply( VectorView< OutputType, OutputStructure, Density::Dense, OutputView, reference_dense > & z, - const VectorView< InputType1, InputStructure1, Density::Dense, InputView1, reference_dense > & x, - const VectorView< InputType2, InputStructure2, Density::Dense, InputView2, reference_dense > & y, + RC eWiseApply( Vector< OutputType, OutputStructure, Density::Dense, OutputView, reference > & z, + const Vector< InputType1, InputStructure1, Density::Dense, InputView1, reference > & x, + const Vector< InputType2, InputStructure2, Density::Dense, InputView2, reference > & y, const OP & op = OP(), - const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_operator< OP >::value, + const typename std::enable_if< ! alp::is_object< OutputType >::value && ! alp::is_object< InputType1 >::value && ! alp::is_object< InputType2 >::value && alp::is_operator< OP >::value, void >::type * const = NULL ) { #ifdef _DEBUG std::cout << "In eWiseApply ([T1]<-[T2]<-[T3]), operator variant\n"; @@ -2296,13 +2296,13 @@ namespace grb { typename OutputStructure, typename MaskStructure, typename InputStructure1, typename InputStructure2, typename OutputView, typename MaskView, typename InputView1, typename InputView2 > - RC eWiseApply( VectorView< OutputType, OutputStructure, Density::Dense, OutputView, reference_dense > & z, - const VectorView< MaskType, MaskStructure, Density::Dense, MaskView, reference_dense > & mask, - const VectorView< InputType1, InputStructure1, Density::Dense, InputView1, reference_dense > & x, - const VectorView< InputType2, InputStructure2, Density::Dense, InputView2, reference_dense > & y, + RC eWiseApply( Vector< OutputType, OutputStructure, Density::Dense, OutputView, reference > & z, + const Vector< MaskType, MaskStructure, Density::Dense, MaskView, reference > & mask, + const Vector< InputType1, InputStructure1, Density::Dense, InputView1, reference > & x, + const Vector< InputType2, InputStructure2, Density::Dense, InputView2, reference > & y, const OP & op = OP(), - const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && - grb::is_operator< OP >::value, + const typename std::enable_if< ! alp::is_object< OutputType >::value && ! alp::is_object< MaskType >::value && ! alp::is_object< InputType1 >::value && ! alp::is_object< InputType2 >::value && + alp::is_operator< OP >::value, void >::type * const = NULL ) { #ifdef _DEBUG std::cout << "In masked eWiseApply ([T1]<-[T2]<-[T3], using operator)\n"; @@ -2341,20 +2341,20 @@ namespace grb { * @param[in] ring The generalized semiring under which to perform this * element-wise multiplication. * - * @return grb::MISMATCH Whenever the dimensions of \a x, \a y, and \a z do + * @return alp::MISMATCH Whenever the dimensions of \a x, \a y, and \a z do * not match. All input data containers are left * untouched; it will be as though this call was never * made. - * @return grb::SUCCESS On successful completion of this call. + * @return alp::SUCCESS On successful completion of this call. * * \parblock * \par Valid descriptors - * grb::descriptors::no_operation, grb::descriptors::no_casting, - * grb::descriptors::dense. + * alp::descriptors::no_operation, alp::descriptors::no_casting, + * alp::descriptors::dense. * * \note Invalid descriptors will be ignored. * - * If grb::descriptors::no_casting is specified, then 1) the third domain of + * If alp::descriptors::no_casting is specified, then 1) the third domain of * \a ring must match \a InputType1, 2) the fourth domain of \a ring must match * \a InputType2, 3) the fourth domain of \a ring must match \a OutputType. If * one of these is not true, the code shall not compile. @@ -2394,24 +2394,24 @@ namespace grb { typename OutputStructure, typename InputStructure1, typename InputStructure2, typename OutputView, typename InputView1, typename InputView2 > - RC eWiseAdd( VectorView< OutputType, OutputStructure, Density::Dense, OutputView, reference_dense > & z, - const VectorView< InputType1, InputStructure1, Density::Dense, InputView1, reference_dense > & x, - const VectorView< InputType2, InputStructure2, Density::Dense, InputView2, reference_dense > & y, + RC eWiseAdd( Vector< OutputType, OutputStructure, Density::Dense, OutputView, reference > & z, + const Vector< InputType1, InputStructure1, Density::Dense, InputView1, reference > & x, + const Vector< InputType2, InputStructure2, Density::Dense, InputView2, reference > & y, const Ring & ring = Ring(), - const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_semiring< Ring >::value, + const typename std::enable_if< ! alp::is_object< OutputType >::value && ! alp::is_object< InputType1 >::value && ! alp::is_object< InputType2 >::value && alp::is_semiring< Ring >::value, void >::type * const = NULL ) { // static sanity checks - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, OutputType >::value ), "grb::eWiseAdd", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, OutputType >::value ), "alp::eWiseAdd", "called with an output vector with element type that does not match the " "fourth domain of the given semiring" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D3, InputType1 >::value ), "grb::eWiseAdd", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D3, InputType1 >::value ), "alp::eWiseAdd", "called with a left-hand side input vector with element type that does not " "match the third domain of the given semiring" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, OutputType >::value ), "grb::eWiseAdd", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, OutputType >::value ), "alp::eWiseAdd", "called with a right-hand side input vector with element type that does " "not match the fourth domain of the given semiring" ); #ifdef _DEBUG - std::cout << "eWiseAdd (reference_dense, vector <- vector + vector) dispatches to eWiseApply( reference_dense, vector <- vector . vector ) using additive monoid\n"; + std::cout << "eWiseAdd (reference, vector <- vector + vector) dispatches to eWiseApply( reference, vector <- vector . vector ) using additive monoid\n"; #endif return eWiseApply< descr >( z, x, y, ring.getAdditiveMonoid() ); } @@ -2427,24 +2427,24 @@ namespace grb { typename OutputStructure, typename InputStructure1, typename InputStructure2, typename OutputView, typename InputView2 > - RC eWiseAdd( VectorView< OutputType, OutputStructure, Density::Dense, OutputView, reference_dense > & z, - const Scalar< InputType1, InputStructure1, reference_dense> &alpha, - const VectorView< InputType2, InputStructure2, Density::Dense, InputView2, reference_dense > & y, + RC eWiseAdd( Vector< OutputType, OutputStructure, Density::Dense, OutputView, reference > & z, + const Scalar< InputType1, InputStructure1, reference> &alpha, + const Vector< InputType2, InputStructure2, Density::Dense, InputView2, reference > & y, const Ring & ring = Ring(), - const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_semiring< Ring >::value, + const typename std::enable_if< ! alp::is_object< OutputType >::value && ! alp::is_object< InputType1 >::value && ! alp::is_object< InputType2 >::value && alp::is_semiring< Ring >::value, void >::type * const = NULL ) { // static sanity checks - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D1, InputType1 >::value ), "grb::eWiseAdd", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D1, InputType1 >::value ), "alp::eWiseAdd", "called with a left-hand side input vector with element type that does not " "match the first domain of the given semiring" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D2, InputType2 >::value ), "grb::eWiseAdd", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D2, InputType2 >::value ), "alp::eWiseAdd", "called with a right-hand side input vector with element type that does " "not match the second domain of the given semiring" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D3, OutputType >::value ), "grb::eWiseAdd", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D3, OutputType >::value ), "alp::eWiseAdd", "called with an output vector with element type that does not match the " "third domain of the given semiring" ); #ifdef _DEBUG - std::cout << "eWiseAdd (reference_dense, vector <- scalar + vector) dispatches to eWiseApply with additive monoid\n"; + std::cout << "eWiseAdd (reference, vector <- scalar + vector) dispatches to eWiseApply with additive monoid\n"; #endif return eWiseApply< descr >( z, alpha, y, ring.getAdditiveMonoid() ); } @@ -2460,24 +2460,24 @@ namespace grb { typename OutputStructure, typename InputStructure1, typename InputStructure2, typename OutputView, typename InputView1 > - RC eWiseAdd( VectorView< OutputType, OutputStructure, Density::Dense, OutputView, reference_dense > & z, - const VectorView< InputType1, InputStructure1, Density::Dense, InputView1, reference_dense > & x, - const Scalar< InputType2, InputStructure2, reference_dense > &beta, + RC eWiseAdd( Vector< OutputType, OutputStructure, Density::Dense, OutputView, reference > & z, + const Vector< InputType1, InputStructure1, Density::Dense, InputView1, reference > & x, + const Scalar< InputType2, InputStructure2, reference > &beta, const Ring & ring = Ring(), - const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_semiring< Ring >::value, + const typename std::enable_if< ! alp::is_object< OutputType >::value && ! alp::is_object< InputType1 >::value && ! alp::is_object< InputType2 >::value && alp::is_semiring< Ring >::value, void >::type * const = NULL ) { // static sanity checks - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D1, InputType1 >::value ), "grb::eWiseAdd", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D1, InputType1 >::value ), "alp::eWiseAdd", "called with a left-hand side input vector with element type that does not " "match the first domain of the given semiring" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D2, InputType2 >::value ), "grb::eWiseAdd", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D2, InputType2 >::value ), "alp::eWiseAdd", "called with a right-hand side input vector with element type that does " "not match the second domain of the given semiring" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D3, OutputType >::value ), "grb::eWiseAdd", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D3, OutputType >::value ), "alp::eWiseAdd", "called with an output vector with element type that does not match the " "third domain of the given semiring" ); #ifdef _DEBUG - std::cout << "eWiseAdd (reference_dense, vector <- vector + scalar) dispatches to eWiseApply with additive monoid\n"; + std::cout << "eWiseAdd (reference, vector <- vector + scalar) dispatches to eWiseApply with additive monoid\n"; #endif return eWiseApply< descr >( z, x, beta, ring.getAdditiveMonoid() ); } @@ -2493,24 +2493,24 @@ namespace grb { typename OutputStructure, typename InputStructure1, typename InputStructure2, typename OutputView > - RC eWiseAdd( VectorView< OutputType, OutputStructure, Density::Dense, OutputView, reference_dense > & z, - const Scalar< InputType1, InputStructure1, reference_dense > &alpha, - const Scalar< InputType2, InputStructure2, reference_dense > &beta, + RC eWiseAdd( Vector< OutputType, OutputStructure, Density::Dense, OutputView, reference > & z, + const Scalar< InputType1, InputStructure1, reference > &alpha, + const Scalar< InputType2, InputStructure2, reference > &beta, const Ring & ring = Ring(), - const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_semiring< Ring >::value, + const typename std::enable_if< ! alp::is_object< OutputType >::value && ! alp::is_object< InputType1 >::value && ! alp::is_object< InputType2 >::value && alp::is_semiring< Ring >::value, void >::type * const = NULL ) { // static sanity checks - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D1, InputType1 >::value ), "grb::eWiseAdd", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D1, InputType1 >::value ), "alp::eWiseAdd", "called with a left-hand side input vector with element type that does not " "match the first domain of the given semiring" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D2, InputType2 >::value ), "grb::eWiseAdd", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D2, InputType2 >::value ), "alp::eWiseAdd", "called with a right-hand side input vector with element type that does " "not match the second domain of the given semiring" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D3, OutputType >::value ), "grb::eWiseAdd", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D3, OutputType >::value ), "alp::eWiseAdd", "called with an output vector with element type that does not match the " "third domain of the given semiring" ); #ifdef _DEBUG - std::cout << "eWiseAdd (reference_dense, vector <- scalar + scalar) dispatches to foldl with precomputed scalar and additive monoid\n"; + std::cout << "eWiseAdd (reference, vector <- scalar + scalar) dispatches to foldl with precomputed scalar and additive monoid\n"; #endif const typename Ring::D4 add; (void)apply( add, alpha, beta, ring.getAdditiveOperator() ); @@ -2528,28 +2528,28 @@ namespace grb { typename OutputStructure, typename MaskStructure, typename InputStructure1, typename InputStructure2, typename OutputView, typename MaskView, typename InputView1, typename InputView2 > - RC eWiseAdd( VectorView< OutputType, OutputStructure, Density::Dense, OutputView, reference_dense > & z, - const VectorView< MaskType, MaskStructure, Density::Dense, MaskView, reference_dense > & m, - const VectorView< InputType1, InputStructure1, Density::Dense, InputView1, reference_dense > & x, - const VectorView< InputType2, InputStructure2, Density::Dense, InputView2, reference_dense > & y, + RC eWiseAdd( Vector< OutputType, OutputStructure, Density::Dense, OutputView, reference > & z, + const Vector< MaskType, MaskStructure, Density::Dense, MaskView, reference > & m, + const Vector< InputType1, InputStructure1, Density::Dense, InputView1, reference > & x, + const Vector< InputType2, InputStructure2, Density::Dense, InputView2, reference > & y, const Ring & ring = Ring(), - const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && - grb::is_semiring< Ring >::value, + const typename std::enable_if< ! alp::is_object< OutputType >::value && ! alp::is_object< MaskType >::value && ! alp::is_object< InputType1 >::value && ! alp::is_object< InputType2 >::value && + alp::is_semiring< Ring >::value, void >::type * const = NULL ) { // static sanity checks - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, OutputType >::value ), "grb::eWiseAdd", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, OutputType >::value ), "alp::eWiseAdd", "called with an output vector with element type that does not match the " "fourth domain of the given semiring" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D3, InputType1 >::value ), "grb::eWiseAdd", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D3, InputType1 >::value ), "alp::eWiseAdd", "called with a left-hand side input vector with element type that does not " "match the third domain of the given semiring" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, OutputType >::value ), "grb::eWiseAdd", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, OutputType >::value ), "alp::eWiseAdd", "called with a right-hand side input vector with element type that does " "not match the fourth domain of the given semiring" ); NO_CAST_ASSERT( - ( ! ( descr & descriptors::no_casting ) || std::is_same< MaskType, bool >::value ), "grb::eWiseAdd (vector <- vector + vector, masked)", "called with non-bool mask element types" ); + ( ! ( descr & descriptors::no_casting ) || std::is_same< MaskType, bool >::value ), "alp::eWiseAdd (vector <- vector + vector, masked)", "called with non-bool mask element types" ); #ifdef _DEBUG - std::cout << "eWiseAdd (reference_dense, vector <- vector + vector, masked) dispatches to eWiseApply( reference_dense, vector <- vector . vector ) using additive monoid\n"; + std::cout << "eWiseAdd (reference, vector <- vector + vector, masked) dispatches to eWiseApply( reference, vector <- vector . vector ) using additive monoid\n"; #endif return eWiseApply< descr >( z, m, x, y, ring.getAdditiveMonoid() ); } @@ -2565,28 +2565,28 @@ namespace grb { typename OutputStructure, typename MaskStructure, typename InputStructure1, typename InputStructure2, typename OutputView, typename MaskView, typename InputView2 > - RC eWiseAdd( VectorView< OutputType, OutputStructure, Density::Dense, OutputView, reference_dense > & z, - const VectorView< MaskType, MaskStructure, Density::Dense, MaskView, reference_dense > & m, - const Scalar< InputType1, InputStructure1, reference_dense> &alpha, - const VectorView< InputType2, InputStructure2, Density::Dense, InputView2, reference_dense > & y, + RC eWiseAdd( Vector< OutputType, OutputStructure, Density::Dense, OutputView, reference > & z, + const Vector< MaskType, MaskStructure, Density::Dense, MaskView, reference > & m, + const Scalar< InputType1, InputStructure1, reference> &alpha, + const Vector< InputType2, InputStructure2, Density::Dense, InputView2, reference > & y, const Ring & ring = Ring(), - const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && - grb::is_semiring< Ring >::value, + const typename std::enable_if< ! alp::is_object< OutputType >::value && ! alp::is_object< MaskType >::value && ! alp::is_object< InputType1 >::value && ! alp::is_object< InputType2 >::value && + alp::is_semiring< Ring >::value, void >::type * const = NULL ) { // static sanity checks - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D1, InputType1 >::value ), "grb::eWiseAdd", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D1, InputType1 >::value ), "alp::eWiseAdd", "called with a left-hand side input vector with element type that does not " "match the first domain of the given semiring" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D2, InputType2 >::value ), "grb::eWiseAdd", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D2, InputType2 >::value ), "alp::eWiseAdd", "called with a right-hand side input vector with element type that does " "not match the second domain of the given semiring" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D3, OutputType >::value ), "grb::eWiseAdd", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D3, OutputType >::value ), "alp::eWiseAdd", "called with an output vector with element type that does not match the " "third domain of the given semiring" ); NO_CAST_ASSERT( - ( ! ( descr & descriptors::no_casting ) || std::is_same< MaskType, bool >::value ), "grb::eWiseAdd (vector <- scalar + vector, masked)", "called with non-bool mask element types" ); + ( ! ( descr & descriptors::no_casting ) || std::is_same< MaskType, bool >::value ), "alp::eWiseAdd (vector <- scalar + vector, masked)", "called with non-bool mask element types" ); #ifdef _DEBUG - std::cout << "eWiseAdd (reference_dense, vector <- scalar + vector, masked) dispatches to eWiseApply with additive monoid\n"; + std::cout << "eWiseAdd (reference, vector <- scalar + vector, masked) dispatches to eWiseApply with additive monoid\n"; #endif return eWiseApply< descr >( z, m, alpha, y, ring.getAdditiveMonoid() ); } @@ -2602,28 +2602,28 @@ namespace grb { typename OutputStructure, typename MaskStructure, typename InputStructure1, typename InputStructure2, typename OutputView, typename MaskView, typename InputView1 > - RC eWiseAdd( VectorView< OutputType, OutputStructure, Density::Dense, OutputView, reference_dense > & z, - const VectorView< MaskType, MaskStructure, Density::Dense, MaskView, reference_dense > & m, - const VectorView< InputType1, InputStructure1, Density::Dense, InputView1, reference_dense > & x, - const Scalar< InputType2, InputStructure2, reference_dense > &beta, + RC eWiseAdd( Vector< OutputType, OutputStructure, Density::Dense, OutputView, reference > & z, + const Vector< MaskType, MaskStructure, Density::Dense, MaskView, reference > & m, + const Vector< InputType1, InputStructure1, Density::Dense, InputView1, reference > & x, + const Scalar< InputType2, InputStructure2, reference > &beta, const Ring & ring = Ring(), - const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && - grb::is_semiring< Ring >::value, + const typename std::enable_if< ! alp::is_object< OutputType >::value && ! alp::is_object< MaskType >::value && ! alp::is_object< InputType1 >::value && ! alp::is_object< InputType2 >::value && + alp::is_semiring< Ring >::value, void >::type * const = NULL ) { // static sanity checks - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D1, InputType1 >::value ), "grb::eWiseAdd", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D1, InputType1 >::value ), "alp::eWiseAdd", "called with a left-hand side input vector with element type that does not " "match the first domain of the given semiring" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D2, InputType2 >::value ), "grb::eWiseAdd", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D2, InputType2 >::value ), "alp::eWiseAdd", "called with a right-hand side input vector with element type that does " "not match the second domain of the given semiring" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D3, OutputType >::value ), "grb::eWiseAdd", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D3, OutputType >::value ), "alp::eWiseAdd", "called with an output vector with element type that does not match the " "third domain of the given semiring" ); NO_CAST_ASSERT( - ( ! ( descr & descriptors::no_casting ) || std::is_same< MaskType, bool >::value ), "grb::eWiseAdd (vector <- vector + scalar, masked)", "called with non-bool mask element types" ); + ( ! ( descr & descriptors::no_casting ) || std::is_same< MaskType, bool >::value ), "alp::eWiseAdd (vector <- vector + scalar, masked)", "called with non-bool mask element types" ); #ifdef _DEBUG - std::cout << "eWiseAdd (reference_dense, vector <- vector + scalar, masked) dispatches to eWiseApply with additive monoid\n"; + std::cout << "eWiseAdd (reference, vector <- vector + scalar, masked) dispatches to eWiseApply with additive monoid\n"; #endif return eWiseApply< descr >( z, m, x, beta, ring.getAdditiveMonoid() ); } @@ -2639,28 +2639,28 @@ namespace grb { typename OutputStructure, typename MaskStructure, typename InputStructure1, typename InputStructure2, typename OutputView, typename MaskView > - RC eWiseAdd( VectorView< OutputType, OutputStructure, Density::Dense, OutputView, reference_dense > & z, - const VectorView< MaskType, MaskStructure, Density::Dense, MaskView, reference_dense > & m, - const Scalar< InputType1, InputStructure1, reference_dense > &alpha, - const Scalar< InputType2, InputStructure2, reference_dense > &beta, + RC eWiseAdd( Vector< OutputType, OutputStructure, Density::Dense, OutputView, reference > & z, + const Vector< MaskType, MaskStructure, Density::Dense, MaskView, reference > & m, + const Scalar< InputType1, InputStructure1, reference > &alpha, + const Scalar< InputType2, InputStructure2, reference > &beta, const Ring & ring = Ring(), - const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< MaskType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && - grb::is_semiring< Ring >::value, + const typename std::enable_if< ! alp::is_object< OutputType >::value && ! alp::is_object< MaskType >::value && ! alp::is_object< InputType1 >::value && ! alp::is_object< InputType2 >::value && + alp::is_semiring< Ring >::value, void >::type * const = NULL ) { // static sanity checks - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D1, InputType1 >::value ), "grb::eWiseAdd", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D1, InputType1 >::value ), "alp::eWiseAdd", "called with a left-hand side input vector with element type that does not " "match the first domain of the given semiring" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D2, InputType2 >::value ), "grb::eWiseAdd", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D2, InputType2 >::value ), "alp::eWiseAdd", "called with a right-hand side input vector with element type that does " "not match the second domain of the given semiring" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D3, OutputType >::value ), "grb::eWiseAdd", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D3, OutputType >::value ), "alp::eWiseAdd", "called with an output vector with element type that does not match the " "third domain of the given semiring" ); NO_CAST_ASSERT( - ( ! ( descr & descriptors::no_casting ) || std::is_same< MaskType, bool >::value ), "grb::eWiseAdd (vector <- scalar + scalar, masked)", "called with non-bool mask element types" ); + ( ! ( descr & descriptors::no_casting ) || std::is_same< MaskType, bool >::value ), "alp::eWiseAdd (vector <- scalar + scalar, masked)", "called with non-bool mask element types" ); #ifdef _DEBUG - std::cout << "eWiseAdd (reference_dense, vector <- scalar + scalar, masked) dispatches to foldl with precomputed scalar and additive monoid\n"; + std::cout << "eWiseAdd (reference, vector <- scalar + scalar, masked) dispatches to foldl with precomputed scalar and additive monoid\n"; #endif const typename Ring::D4 add; (void)apply( add, alpha, beta, ring.getAdditiveOperator() ); @@ -2677,25 +2677,25 @@ namespace grb { typename OutputStructure, typename InputStructure1, typename InputStructure2, typename InputStructure3, typename OutputView, typename InputView2, typename InputView3 > - RC eWiseMulAdd( VectorView< OutputType, OutputStructure, Density::Dense, OutputView, reference_dense > & _z, - const Scalar< InputType1, InputStructure1, reference_dense > &alpha, - const VectorView< InputType2, InputStructure2, Density::Dense, InputView2, reference_dense > & _x, - const VectorView< InputType3, InputStructure3, Density::Dense, InputView3, reference_dense > & _y, + RC eWiseMulAdd( Vector< OutputType, OutputStructure, Density::Dense, OutputView, reference > & _z, + const Scalar< InputType1, InputStructure1, reference > &alpha, + const Vector< InputType2, InputStructure2, Density::Dense, InputView2, reference > & _x, + const Vector< InputType3, InputStructure3, Density::Dense, InputView3, reference > & _y, const Ring & ring = Ring(), - const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && - grb::is_semiring< Ring >::value, + const typename std::enable_if< ! alp::is_object< OutputType >::value && ! alp::is_object< InputType1 >::value && ! alp::is_object< InputType2 >::value && ! alp::is_object< InputType3 >::value && + alp::is_semiring< Ring >::value, void >::type * const = NULL ) { // static sanity checks - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D1, InputType1 >::value ), "grb::eWiseMulAdd", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D1, InputType1 >::value ), "alp::eWiseMulAdd", "called with a left-hand scalar alpha of an element type that does not " "match the first domain of the given semiring" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D2, InputType2 >::value ), "grb::eWiseMulAdd", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D2, InputType2 >::value ), "alp::eWiseMulAdd", "called with a right-hand vector _x with an element type that does not " "match the second domain of the given semiring" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, InputType3 >::value ), "grb::eWiseMulAdd", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, InputType3 >::value ), "alp::eWiseMulAdd", "called with an additive vector _y with an element type that does not " "match the fourth domain of the given semiring" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, OutputType >::value ), "grb::eWiseMulAdd", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, OutputType >::value ), "alp::eWiseMulAdd", "called with a result vector _z with an element type that does not match " "the fourth domain of the given semiring" ); throw std::runtime_error( "Needs an implementation." ); @@ -2713,25 +2713,25 @@ namespace grb { typename OutputStructure, typename InputStructure1, typename InputStructure2, typename InputStructure3, typename OutputView, typename InputView1, typename InputView3 > - RC eWiseMulAdd( VectorView< OutputType, OutputStructure, Density::Dense, OutputView, reference_dense > & _z, - const VectorView< InputType1, InputStructure1, Density::Dense, InputView1, reference_dense > & _a, - const Scalar< InputType2, InputStructure2, reference_dense> &chi, - const VectorView< InputType3, InputStructure3, Density::Dense, InputView3, reference_dense > & _y, + RC eWiseMulAdd( Vector< OutputType, OutputStructure, Density::Dense, OutputView, reference > & _z, + const Vector< InputType1, InputStructure1, Density::Dense, InputView1, reference > & _a, + const Scalar< InputType2, InputStructure2, reference> &chi, + const Vector< InputType3, InputStructure3, Density::Dense, InputView3, reference > & _y, const Ring & ring = Ring(), - const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && - grb::is_semiring< Ring >::value, + const typename std::enable_if< ! alp::is_object< OutputType >::value && ! alp::is_object< InputType1 >::value && ! alp::is_object< InputType2 >::value && ! alp::is_object< InputType3 >::value && + alp::is_semiring< Ring >::value, void >::type * const = NULL ) { // static sanity checks - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D1, InputType1 >::value ), "grb::eWiseMulAdd", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D1, InputType1 >::value ), "alp::eWiseMulAdd", "called with a left-hand scalar alpha of an element type that does not " "match the first domain of the given semiring" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D2, InputType2 >::value ), "grb::eWiseMulAdd", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D2, InputType2 >::value ), "alp::eWiseMulAdd", "called with a right-hand vector _x with an element type that does not " "match the second domain of the given semiring" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, InputType3 >::value ), "grb::eWiseMulAdd", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, InputType3 >::value ), "alp::eWiseMulAdd", "called with an additive vector _y with an element type that does not " "match the fourth domain of the given semiring" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, OutputType >::value ), "grb::eWiseMulAdd", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, OutputType >::value ), "alp::eWiseMulAdd", "called with a result vector _z with an element type that does not match " "the fourth domain of the given semiring" ); throw std::runtime_error( "Needs an implementation." ); @@ -2748,25 +2748,25 @@ namespace grb { typename OutputStructure, typename InputStructure1, typename InputStructure2, typename InputStructure3, typename OutputView, typename InputView1, typename InputView2 > - RC eWiseMulAdd( VectorView< OutputType, OutputStructure, Density::Dense, OutputView, reference_dense > & _z, - const VectorView< InputType1, InputStructure1, Density::Dense, InputView1, reference_dense > & _a, - const VectorView< InputType2, InputStructure2, Density::Dense, InputView2, reference_dense > & _x, - const Scalar< InputType3, InputStructure3, reference_dense > &gamma, + RC eWiseMulAdd( Vector< OutputType, OutputStructure, Density::Dense, OutputView, reference > & _z, + const Vector< InputType1, InputStructure1, Density::Dense, InputView1, reference > & _a, + const Vector< InputType2, InputStructure2, Density::Dense, InputView2, reference > & _x, + const Scalar< InputType3, InputStructure3, reference > &gamma, const Ring & ring = Ring(), - const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && - grb::is_semiring< Ring >::value, + const typename std::enable_if< ! alp::is_object< OutputType >::value && ! alp::is_object< InputType1 >::value && ! alp::is_object< InputType2 >::value && ! alp::is_object< InputType3 >::value && + alp::is_semiring< Ring >::value, void >::type * const = NULL ) { // static sanity checks - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D1, InputType1 >::value ), "grb::eWiseMulAdd", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D1, InputType1 >::value ), "alp::eWiseMulAdd", "called with a left-hand scalar alpha of an element type that does not " "match the first domain of the given semiring" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D2, InputType2 >::value ), "grb::eWiseMulAdd", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D2, InputType2 >::value ), "alp::eWiseMulAdd", "called with a right-hand vector _x with an element type that does not " "match the second domain of the given semiring" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, InputType3 >::value ), "grb::eWiseMulAdd", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, InputType3 >::value ), "alp::eWiseMulAdd", "called with an additive vector _y with an element type that does not " "match the fourth domain of the given semiring" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, OutputType >::value ), "grb::eWiseMulAdd", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, OutputType >::value ), "alp::eWiseMulAdd", "called with a result vector _z with an element type that does not match " "the fourth domain of the given semiring" ); throw std::runtime_error( "Needs an implementation." ); @@ -2783,25 +2783,25 @@ namespace grb { typename OutputStructure, typename InputStructure1, typename InputStructure2, typename InputStructure3, typename OutputView, typename InputView1 > - RC eWiseMulAdd( VectorView< OutputType, OutputStructure, Density::Dense, OutputView, reference_dense > & _z, - const VectorView< InputType1, InputStructure1, Density::Dense, InputView1, reference_dense > & _a, - const Scalar< InputType2, InputStructure2, reference_dense> &beta, - const Scalar< InputType3, InputStructure3, reference_dense> &gamma, + RC eWiseMulAdd( Vector< OutputType, OutputStructure, Density::Dense, OutputView, reference > & _z, + const Vector< InputType1, InputStructure1, Density::Dense, InputView1, reference > & _a, + const Scalar< InputType2, InputStructure2, reference> &beta, + const Scalar< InputType3, InputStructure3, reference> &gamma, const Ring & ring = Ring(), - const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && - grb::is_semiring< Ring >::value, + const typename std::enable_if< ! alp::is_object< OutputType >::value && ! alp::is_object< InputType1 >::value && ! alp::is_object< InputType2 >::value && ! alp::is_object< InputType3 >::value && + alp::is_semiring< Ring >::value, void >::type * const = NULL ) { // static sanity checks - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D1, InputType1 >::value ), "grb::eWiseMulAdd", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D1, InputType1 >::value ), "alp::eWiseMulAdd", "called with a left-hand scalar alpha of an element type that does not " "match the first domain of the given semiring" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D2, InputType2 >::value ), "grb::eWiseMulAdd", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D2, InputType2 >::value ), "alp::eWiseMulAdd", "called with a right-hand vector _x with an element type that does not " "match the second domain of the given semiring" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, InputType3 >::value ), "grb::eWiseMulAdd", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, InputType3 >::value ), "alp::eWiseMulAdd", "called with an additive vector _y with an element type that does not " "match the fourth domain of the given semiring" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, OutputType >::value ), "grb::eWiseMulAdd", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, OutputType >::value ), "alp::eWiseMulAdd", "called with a result vector _z with an element type that does not match " "the fourth domain of the given semiring" ); throw std::runtime_error( "Needs an implementation." ); @@ -2818,25 +2818,25 @@ namespace grb { typename OutputStructure, typename InputStructure1, typename InputStructure2, typename InputStructure3, typename OutputView, typename InputView2 > - RC eWiseMulAdd( VectorView< OutputType, OutputStructure, Density::Dense, OutputView, reference_dense > & _z, - const Scalar< InputType1, InputStructure1, reference_dense > &alpha, - const VectorView< InputType2, InputStructure2, Density::Dense, InputView2, reference_dense > & _x, - const Scalar< InputType3, InputStructure3, reference_dense > &gamma, + RC eWiseMulAdd( Vector< OutputType, OutputStructure, Density::Dense, OutputView, reference > & _z, + const Scalar< InputType1, InputStructure1, reference > &alpha, + const Vector< InputType2, InputStructure2, Density::Dense, InputView2, reference > & _x, + const Scalar< InputType3, InputStructure3, reference > &gamma, const Ring & ring = Ring(), - const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && - grb::is_semiring< Ring >::value, + const typename std::enable_if< ! alp::is_object< OutputType >::value && ! alp::is_object< InputType1 >::value && ! alp::is_object< InputType2 >::value && ! alp::is_object< InputType3 >::value && + alp::is_semiring< Ring >::value, void >::type * const = NULL ) { // static sanity checks - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D1, InputType1 >::value ), "grb::eWiseMulAdd", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D1, InputType1 >::value ), "alp::eWiseMulAdd", "called with a left-hand scalar alpha of an element type that does not " "match the first domain of the given semiring" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D2, InputType2 >::value ), "grb::eWiseMulAdd", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D2, InputType2 >::value ), "alp::eWiseMulAdd", "called with a right-hand vector _x with an element type that does not " "match the second domain of the given semiring" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, InputType3 >::value ), "grb::eWiseMulAdd", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, InputType3 >::value ), "alp::eWiseMulAdd", "called with an additive vector _y with an element type that does not " "match the fourth domain of the given semiring" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, OutputType >::value ), "grb::eWiseMulAdd", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, OutputType >::value ), "alp::eWiseMulAdd", "called with a result vector _z with an element type that does not match " "the fourth domain of the given semiring" ); throw std::runtime_error( "Needs an implementation." ); @@ -2855,33 +2855,33 @@ namespace grb { typename OutputStructure, typename InputStructure1, typename InputStructure2, typename InputStructure3, typename OutputView, typename InputView3 > - RC eWiseMulAdd( VectorView< OutputType, OutputStructure, Density::Dense, OutputView, reference_dense > & z, - const Scalar< InputType1, InputStructure1, reference_dense> &alpha, - const Scalar< InputType2, InputStructure2, reference_dense> &beta, - const VectorView< InputType3, InputStructure3, Density::Dense, InputView3, reference_dense > & y, + RC eWiseMulAdd( Vector< OutputType, OutputStructure, Density::Dense, OutputView, reference > & z, + const Scalar< InputType1, InputStructure1, reference> &alpha, + const Scalar< InputType2, InputStructure2, reference> &beta, + const Vector< InputType3, InputStructure3, Density::Dense, InputView3, reference > & y, const Ring & ring = Ring(), - const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && - grb::is_semiring< Ring >::value, + const typename std::enable_if< ! alp::is_object< OutputType >::value && ! alp::is_object< InputType1 >::value && ! alp::is_object< InputType2 >::value && ! alp::is_object< InputType3 >::value && + alp::is_semiring< Ring >::value, void >::type * const = NULL ) { - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D1, InputType1 >::value ), "grb::eWiseMulAdd(vector,scalar,scalar,scalar)", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D1, InputType1 >::value ), "alp::eWiseMulAdd(vector,scalar,scalar,scalar)", "First domain of semiring does not match first input type" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D2, InputType2 >::value ), "grb::eWiseMulAdd(vector,scalar,scalar,scalar)", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D2, InputType2 >::value ), "alp::eWiseMulAdd(vector,scalar,scalar,scalar)", "Second domain of semiring does not match second input type" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, InputType3 >::value ), "grb::eWiseMulAdd(vector,scalar,scalar,scalar)", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, InputType3 >::value ), "alp::eWiseMulAdd(vector,scalar,scalar,scalar)", "Fourth domain of semiring does not match third input type" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, OutputType >::value ), "grb::eWiseMulAdd(vector,scalar,scalar,scalar)", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, OutputType >::value ), "alp::eWiseMulAdd(vector,scalar,scalar,scalar)", "Fourth domain of semiring does not match output type" ); #ifdef _DEBUG - std::cout << "eWiseMulAdd (reference_dense, vector <- scalar x scalar + vector) precomputes scalar multiply and dispatches to eWiseAdd (reference_dense, vector <- scalar + vector)\n"; + std::cout << "eWiseMulAdd (reference, vector <- scalar x scalar + vector) precomputes scalar multiply and dispatches to eWiseAdd (reference, vector <- scalar + vector)\n"; #endif typename Ring::D3 mul_result; - RC rc = grb::apply( mul_result, alpha, beta, ring.getMultiplicativeOperator() ); + RC rc = alp::apply( mul_result, alpha, beta, ring.getMultiplicativeOperator() ); #ifdef NDEBUG (void)rc; #else assert( rc == SUCCESS ); #endif - return grb::eWiseAdd( z, mul_result, y, ring ); + return alp::eWiseAdd( z, mul_result, y, ring ); } /** @@ -2896,38 +2896,38 @@ namespace grb { typename OutputStructure, typename InputStructure1, typename InputStructure2, typename InputStructure3, typename OutputView > - RC eWiseMulAdd( VectorView< OutputType, OutputStructure, Density::Dense, OutputView, reference_dense > & z, - const Scalar< InputType1, InputStructure1, reference_dense> &alpha, - const Scalar< InputType2, InputStructure2, reference_dense> &beta, - const Scalar< InputType3, InputStructure3, reference_dense> &gamma, + RC eWiseMulAdd( Vector< OutputType, OutputStructure, Density::Dense, OutputView, reference > & z, + const Scalar< InputType1, InputStructure1, reference> &alpha, + const Scalar< InputType2, InputStructure2, reference> &beta, + const Scalar< InputType3, InputStructure3, reference> &gamma, const Ring & ring = Ring(), - const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && - grb::is_semiring< Ring >::value, + const typename std::enable_if< ! alp::is_object< OutputType >::value && ! alp::is_object< InputType1 >::value && ! alp::is_object< InputType2 >::value && ! alp::is_object< InputType3 >::value && + alp::is_semiring< Ring >::value, void >::type * const = NULL ) { - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D1, InputType1 >::value ), "grb::eWiseMulAdd(vector,scalar,scalar,scalar)", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D1, InputType1 >::value ), "alp::eWiseMulAdd(vector,scalar,scalar,scalar)", "First domain of semiring does not match first input type" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D2, InputType2 >::value ), "grb::eWiseMulAdd(vector,scalar,scalar,scalar)", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D2, InputType2 >::value ), "alp::eWiseMulAdd(vector,scalar,scalar,scalar)", "Second domain of semiring does not match second input type" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, InputType3 >::value ), "grb::eWiseMulAdd(vector,scalar,scalar,scalar)", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, InputType3 >::value ), "alp::eWiseMulAdd(vector,scalar,scalar,scalar)", "Fourth domain of semiring does not match third input type" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, OutputType >::value ), "grb::eWiseMulAdd(vector,scalar,scalar,scalar)", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, OutputType >::value ), "alp::eWiseMulAdd(vector,scalar,scalar,scalar)", "Fourth domain of semiring does not match output type" ); #ifdef _DEBUG - std::cout << "eWiseMulAdd (reference_dense, vector <- scalar x scalar + scalar) precomputes scalar operations and dispatches to set (reference_dense)\n"; + std::cout << "eWiseMulAdd (reference, vector <- scalar x scalar + scalar) precomputes scalar operations and dispatches to set (reference)\n"; #endif typename Ring::D3 mul_result; - RC rc = grb::apply( mul_result, alpha, beta, ring.getMultiplicativeOperator() ); + RC rc = alp::apply( mul_result, alpha, beta, ring.getMultiplicativeOperator() ); #ifdef NDEBUG (void)rc; #endif assert( rc == SUCCESS ); typename Ring::D4 add_result; - rc = grb::apply( add_result, mul_result, gamma, ring.getAdditiveOperator() ); + rc = alp::apply( add_result, mul_result, gamma, ring.getAdditiveOperator() ); #ifdef NDEBUG (void)rc; #endif assert( rc == SUCCESS ); - return grb::set( z, add_result ); + return alp::set( z, add_result ); } /** @@ -2980,26 +2980,26 @@ namespace grb { * @param[in] _y The elements for right-hand size addition. * @param[in] ring The ring to perform the eWiseMulAdd under. * - * @return grb::MISMATCH Whenever the dimensions of \a _a, \a _x, \a _y, and + * @return alp::MISMATCH Whenever the dimensions of \a _a, \a _x, \a _y, and * \a z do not match. In this case, all input data * containers are left untouched and it will simply be * as though this call was never made. - * @return grb::SUCCESS On successful completion of this call. + * @return alp::SUCCESS On successful completion of this call. * * \warning An implementation is not obligated to detect overlap whenever * it occurs. If part of \a z overlaps with \a x, \a y, or \a a, * undefined behaviour will occur \em unless this function returns - * grb::OVERLAP. In other words: an implementation which returns + * alp::OVERLAP. In other words: an implementation which returns * erroneous results when vectors overlap and still returns - * grb::SUCCESS thus is also a valid GraphBLAS implementation! + * alp::SUCCESS thus is also a valid GraphBLAS implementation! * * \parblock * \par Valid descriptors - * grb::descriptors::no_operation, grb::descriptors::no_casting. + * alp::descriptors::no_operation, alp::descriptors::no_casting. * * \note Invalid descriptors will be ignored. * - * If grb::descriptors::no_casting is specified, then 1) the first domain of + * If alp::descriptors::no_casting is specified, then 1) the first domain of * \a ring must match \a InputType1, 2) the second domain of \a ring must match * \a InputType2, 3) the third domain of \a ring must match \a InputType3, * 4) the fourth domain of \a ring must match \a OutputType. If one of these is @@ -3035,26 +3035,26 @@ namespace grb { typename OutputStructure, typename InputStructure1, typename InputStructure2, typename InputStructure3, typename OutputView, typename InputView1, typename InputView2, typename InputView3 > - RC eWiseMulAdd( VectorView< OutputType, OutputStructure, Density::Dense, OutputView, reference_dense > & _z, - const VectorView< InputType1, InputStructure1, Density::Dense, InputView1, reference_dense > & _a, - const VectorView< InputType2, InputStructure2, Density::Dense, InputView2, reference_dense > & _x, - const VectorView< InputType3, InputStructure3, Density::Dense, InputView3, reference_dense > & _y, + RC eWiseMulAdd( Vector< OutputType, OutputStructure, Density::Dense, OutputView, reference > & _z, + const Vector< InputType1, InputStructure1, Density::Dense, InputView1, reference > & _a, + const Vector< InputType2, InputStructure2, Density::Dense, InputView2, reference > & _x, + const Vector< InputType3, InputStructure3, Density::Dense, InputView3, reference > & _y, const Ring & ring = Ring(), - const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && - grb::is_semiring< Ring >::value, + const typename std::enable_if< ! alp::is_object< OutputType >::value && ! alp::is_object< InputType1 >::value && ! alp::is_object< InputType2 >::value && ! alp::is_object< InputType3 >::value && + alp::is_semiring< Ring >::value, void >::type * const = NULL ) { (void)ring; // static sanity checks - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D1, InputType1 >::value ), "grb::eWiseMulAdd", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D1, InputType1 >::value ), "alp::eWiseMulAdd", "called with a left-hand vector _a with an element type that does not " "match the first domain of the given semiring" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D2, InputType2 >::value ), "grb::eWiseMulAdd", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D2, InputType2 >::value ), "alp::eWiseMulAdd", "called with a right-hand vector _x with an element type that does not " "match the second domain of the given semiring" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, InputType3 >::value ), "grb::eWiseMulAdd", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, InputType3 >::value ), "alp::eWiseMulAdd", "called with an additive vector _y with an element type that does not " "match the fourth domain of the given semiring" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, OutputType >::value ), "grb::eWiseMulAdd", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, OutputType >::value ), "alp::eWiseMulAdd", "called with a result vector _z with an element type that does not match " "the fourth domain of the given semiring" ); throw std::runtime_error( "Needs an implementation." ); @@ -3097,19 +3097,19 @@ namespace grb { * @param[in] ring The generalized semiring under which to perform this * element-wise multiplication. * - * @return grb::MISMATCH Whenever the dimensions of \a x, \a y, and \a z do + * @return alp::MISMATCH Whenever the dimensions of \a x, \a y, and \a z do * not match. All input data containers are left * untouched if this exit code is returned; it will be * as though this call was never made. - * @return grb::SUCCESS On successful completion of this call. + * @return alp::SUCCESS On successful completion of this call. * * \parblock * \par Valid descriptors - * grb::descriptors::no_operation, grb::descriptors::no_casting. + * alp::descriptors::no_operation, alp::descriptors::no_casting. * * \note Invalid descriptors will be ignored. * - * If grb::descriptors::no_casting is specified, then 1) the first domain of + * If alp::descriptors::no_casting is specified, then 1) the first domain of * \a ring must match \a InputType1, 2) the second domain of \a ring must match * \a InputType2, 3) the third domain of \a ring must match \a OutputType. If * one of these is not true, the code shall not compile. @@ -3149,24 +3149,24 @@ namespace grb { typename OutputStructure, typename InputStructure1, typename InputStructure2, typename OutputView, typename InputView1, typename InputView2 > - RC eWiseMul( VectorView< OutputType, OutputStructure, Density::Dense, OutputView, reference_dense > & z, - const VectorView< InputType1, InputStructure1, Density::Dense, InputView1, reference_dense > & x, - const VectorView< InputType2, InputStructure2, Density::Dense, InputView2, reference_dense > & y, + RC eWiseMul( Vector< OutputType, OutputStructure, Density::Dense, OutputView, reference > & z, + const Vector< InputType1, InputStructure1, Density::Dense, InputView1, reference > & x, + const Vector< InputType2, InputStructure2, Density::Dense, InputView2, reference > & y, const Ring & ring = Ring(), - const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_semiring< Ring >::value, + const typename std::enable_if< ! alp::is_object< OutputType >::value && ! alp::is_object< InputType1 >::value && ! alp::is_object< InputType2 >::value && alp::is_semiring< Ring >::value, void >::type * const = NULL ) { // static sanity checks - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D1, InputType1 >::value ), "grb::eWiseMul", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D1, InputType1 >::value ), "alp::eWiseMul", "called with a left-hand side input vector with element type that does not " "match the first domain of the given semiring" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D2, InputType2 >::value ), "grb::eWiseMul", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D2, InputType2 >::value ), "alp::eWiseMul", "called with a right-hand side input vector with element type that does " "not match the second domain of the given semiring" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D3, OutputType >::value ), "grb::eWiseMul", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D3, OutputType >::value ), "alp::eWiseMul", "called with an output vector with element type that does not match the " "third domain of the given semiring" ); #ifdef _DEBUG - std::cout << "eWiseMul (reference_dense, vector <- vector x vector) dispatches to eWiseMulAdd (vector <- vector x vector + 0)\n"; + std::cout << "eWiseMul (reference, vector <- vector x vector) dispatches to eWiseMulAdd (vector <- vector x vector + 0)\n"; #endif return eWiseMulAdd< descr >( z, x, y, ring.template getZero< Ring::D4 >(), ring ); } @@ -3181,24 +3181,24 @@ namespace grb { typename OutputStructure, typename InputStructure1, typename InputStructure2, typename OutputView, typename InputView2 > - RC eWiseMul( VectorView< OutputType, OutputStructure, Density::Dense, OutputView, reference_dense > & z, - const Scalar< InputType1, InputStructure1, reference_dense > &alpha, - const VectorView< InputType2, InputStructure2, Density::Dense, InputView2, reference_dense > & y, + RC eWiseMul( Vector< OutputType, OutputStructure, Density::Dense, OutputView, reference > & z, + const Scalar< InputType1, InputStructure1, reference > &alpha, + const Vector< InputType2, InputStructure2, Density::Dense, InputView2, reference > & y, const Ring & ring = Ring(), - const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_semiring< Ring >::value, + const typename std::enable_if< ! alp::is_object< OutputType >::value && ! alp::is_object< InputType1 >::value && ! alp::is_object< InputType2 >::value && alp::is_semiring< Ring >::value, void >::type * const = NULL ) { // static sanity checks - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D1, InputType1 >::value ), "grb::eWiseMul", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D1, InputType1 >::value ), "alp::eWiseMul", "called with a left-hand side input vector with element type that does not " "match the first domain of the given semiring" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D2, InputType2 >::value ), "grb::eWiseMul", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D2, InputType2 >::value ), "alp::eWiseMul", "called with a right-hand side input vector with element type that does " "not match the second domain of the given semiring" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D3, OutputType >::value ), "grb::eWiseMul", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D3, OutputType >::value ), "alp::eWiseMul", "called with an output vector with element type that does not match the " "third domain of the given semiring" ); #ifdef _DEBUG - std::cout << "eWiseMul (reference_dense, vector <- scalar x vector) dispatches to eWiseMulAdd (vector <- scalar x vector + 0)\n"; + std::cout << "eWiseMul (reference, vector <- scalar x vector) dispatches to eWiseMulAdd (vector <- scalar x vector + 0)\n"; #endif return eWiseMulAdd< descr >( z, alpha, y, ring.template getZero< typename Ring::D4 >(), ring ); } @@ -3213,24 +3213,24 @@ namespace grb { typename OutputStructure, typename InputStructure1, typename InputStructure2, typename OutputView, typename InputView1 > - RC eWiseMul( VectorView< OutputType, OutputStructure, Density::Dense, OutputView, reference_dense > & z, - const VectorView< InputType1, InputStructure1, Density::Dense, InputView1, reference_dense > & x, - const Scalar< InputType2, InputStructure2, reference_dense > &beta, + RC eWiseMul( Vector< OutputType, OutputStructure, Density::Dense, OutputView, reference > & z, + const Vector< InputType1, InputStructure1, Density::Dense, InputView1, reference > & x, + const Scalar< InputType2, InputStructure2, reference > &beta, const Ring & ring = Ring(), - const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_semiring< Ring >::value, + const typename std::enable_if< ! alp::is_object< OutputType >::value && ! alp::is_object< InputType1 >::value && ! alp::is_object< InputType2 >::value && alp::is_semiring< Ring >::value, void >::type * const = NULL ) { // static sanity checks - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D1, InputType1 >::value ), "grb::eWiseMul", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D1, InputType1 >::value ), "alp::eWiseMul", "called with a left-hand side input vector with element type that does not " "match the first domain of the given semiring" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D2, InputType2 >::value ), "grb::eWiseMul", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D2, InputType2 >::value ), "alp::eWiseMul", "called with a right-hand side input vector with element type that does " "not match the second domain of the given semiring" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D3, OutputType >::value ), "grb::eWiseMul", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D3, OutputType >::value ), "alp::eWiseMul", "called with an output vector with element type that does not match the " "third domain of the given semiring" ); #ifdef _DEBUG - std::cout << "eWiseMul (reference_dense) dispatches to eWiseMulAdd with 0.0 as additive scalar\n"; + std::cout << "eWiseMul (reference) dispatches to eWiseMulAdd with 0.0 as additive scalar\n"; #endif return eWiseMulAdd< descr >( z, x, beta, ring.template getZero< typename Ring::D4 >(), ring.getMultiplicativeOperator() ); } @@ -3245,29 +3245,29 @@ namespace grb { typename OutputStructure, typename MaskStructure, typename InputStructure1, typename InputStructure2, typename InputStructure3, typename OutputView, typename MaskView, typename InputView2, typename InputView3 > - RC eWiseMulAdd( VectorView< OutputType, OutputStructure, Density::Dense, OutputView, reference_dense > & _z, - const VectorView< MaskType, MaskStructure, Density::Dense, MaskView, reference_dense > & _m, - const Scalar< InputType1, InputStructure1, reference_dense > &alpha, - const VectorView< InputType2, InputStructure2, Density::Dense, InputView2, reference_dense > & _x, - const VectorView< InputType3, InputStructure3, Density::Dense, InputView3, reference_dense > & _y, + RC eWiseMulAdd( Vector< OutputType, OutputStructure, Density::Dense, OutputView, reference > & _z, + const Vector< MaskType, MaskStructure, Density::Dense, MaskView, reference > & _m, + const Scalar< InputType1, InputStructure1, reference > &alpha, + const Vector< InputType2, InputStructure2, Density::Dense, InputView2, reference > & _x, + const Vector< InputType3, InputStructure3, Density::Dense, InputView3, reference > & _y, const Ring & ring = Ring(), - const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && - grb::is_semiring< Ring >::value && ! grb::is_object< MaskType >::value, + const typename std::enable_if< ! alp::is_object< OutputType >::value && ! alp::is_object< InputType1 >::value && ! alp::is_object< InputType2 >::value && ! alp::is_object< InputType3 >::value && + alp::is_semiring< Ring >::value && ! alp::is_object< MaskType >::value, void >::type * const = NULL ) { // static sanity checks - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D1, InputType1 >::value ), "grb::eWiseMulAdd", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D1, InputType1 >::value ), "alp::eWiseMulAdd", "called with a left-hand scalar alpha of an element type that does not " "match the first domain of the given semiring" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D2, InputType2 >::value ), "grb::eWiseMulAdd", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D2, InputType2 >::value ), "alp::eWiseMulAdd", "called with a right-hand vector _x with an element type that does not " "match the second domain of the given semiring" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, InputType3 >::value ), "grb::eWiseMulAdd", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, InputType3 >::value ), "alp::eWiseMulAdd", "called with an additive vector _y with an element type that does not " "match the fourth domain of the given semiring" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, OutputType >::value ), "grb::eWiseMulAdd", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, OutputType >::value ), "alp::eWiseMulAdd", "called with a result vector _z with an element type that does not match " "the fourth domain of the given semiring" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< bool, MaskType >::value ), "grb::eWiseMulAdd", "called with a mask vector _m with a non-bool element type" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< bool, MaskType >::value ), "alp::eWiseMulAdd", "called with a mask vector _m with a non-bool element type" ); throw std::runtime_error( "Needs an implementation." ); return SUCCESS; } @@ -3283,29 +3283,29 @@ namespace grb { typename OutputStructure, typename MaskStructure, typename InputStructure1, typename InputStructure2, typename InputStructure3, typename OutputView, typename MaskView, typename InputView1, typename InputView3 > - RC eWiseMulAdd( VectorView< OutputType, OutputStructure, Density::Dense, OutputView, reference_dense > & _z, - const VectorView< MaskType, MaskStructure, Density::Dense, MaskView, reference_dense > & _m, - const VectorView< InputType1, InputStructure1, Density::Dense, InputView1, reference_dense > & _a, - const Scalar< InputType2, InputStructure2, reference_dense> &chi, - const VectorView< InputType3, InputStructure3, Density::Dense, InputView3, reference_dense > & _y, + RC eWiseMulAdd( Vector< OutputType, OutputStructure, Density::Dense, OutputView, reference > & _z, + const Vector< MaskType, MaskStructure, Density::Dense, MaskView, reference > & _m, + const Vector< InputType1, InputStructure1, Density::Dense, InputView1, reference > & _a, + const Scalar< InputType2, InputStructure2, reference> &chi, + const Vector< InputType3, InputStructure3, Density::Dense, InputView3, reference > & _y, const Ring & ring = Ring(), - const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && - grb::is_semiring< Ring >::value && ! grb::is_object< MaskType >::value, + const typename std::enable_if< ! alp::is_object< OutputType >::value && ! alp::is_object< InputType1 >::value && ! alp::is_object< InputType2 >::value && ! alp::is_object< InputType3 >::value && + alp::is_semiring< Ring >::value && ! alp::is_object< MaskType >::value, void >::type * const = NULL ) { // static sanity checks - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D1, InputType1 >::value ), "grb::eWiseMulAdd", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D1, InputType1 >::value ), "alp::eWiseMulAdd", "called with a left-hand scalar alpha of an element type that does not " "match the first domain of the given semiring" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D2, InputType2 >::value ), "grb::eWiseMulAdd", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D2, InputType2 >::value ), "alp::eWiseMulAdd", "called with a right-hand vector _x with an element type that does not " "match the second domain of the given semiring" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, InputType3 >::value ), "grb::eWiseMulAdd", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, InputType3 >::value ), "alp::eWiseMulAdd", "called with an additive vector _y with an element type that does not " "match the fourth domain of the given semiring" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, OutputType >::value ), "grb::eWiseMulAdd", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, OutputType >::value ), "alp::eWiseMulAdd", "called with a result vector _z with an element type that does not match " "the fourth domain of the given semiring" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< bool, MaskType >::value ), "grb::eWiseMulAdd", "called with a mask vector _m with a non-bool element type" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< bool, MaskType >::value ), "alp::eWiseMulAdd", "called with a mask vector _m with a non-bool element type" ); throw std::runtime_error( "Needs an implementation." ); return SUCCESS; } @@ -3320,29 +3320,29 @@ namespace grb { typename OutputStructure, typename MaskStructure, typename InputStructure1, typename InputStructure2, typename InputStructure3, typename OutputView, typename MaskView, typename InputView1, typename InputView2 > - RC eWiseMulAdd( VectorView< OutputType, OutputStructure, Density::Dense, OutputView, reference_dense > & _z, - const VectorView< MaskType, MaskStructure, Density::Dense, MaskView, reference_dense > & _m, - const VectorView< InputType1, InputStructure1, Density::Dense, InputView1, reference_dense > & _a, - const VectorView< InputType2, InputStructure2, Density::Dense, InputView2, reference_dense > & _x, - const Scalar< InputType3, InputStructure3, reference_dense > &gamma, + RC eWiseMulAdd( Vector< OutputType, OutputStructure, Density::Dense, OutputView, reference > & _z, + const Vector< MaskType, MaskStructure, Density::Dense, MaskView, reference > & _m, + const Vector< InputType1, InputStructure1, Density::Dense, InputView1, reference > & _a, + const Vector< InputType2, InputStructure2, Density::Dense, InputView2, reference > & _x, + const Scalar< InputType3, InputStructure3, reference > &gamma, const Ring & ring = Ring(), - const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && - grb::is_semiring< Ring >::value && ! grb::is_object< MaskType >::value, + const typename std::enable_if< ! alp::is_object< OutputType >::value && ! alp::is_object< InputType1 >::value && ! alp::is_object< InputType2 >::value && ! alp::is_object< InputType3 >::value && + alp::is_semiring< Ring >::value && ! alp::is_object< MaskType >::value, void >::type * const = NULL ) { // static sanity checks - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D1, InputType1 >::value ), "grb::eWiseMulAdd", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D1, InputType1 >::value ), "alp::eWiseMulAdd", "called with a left-hand scalar alpha of an element type that does not " "match the first domain of the given semiring" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D2, InputType2 >::value ), "grb::eWiseMulAdd", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D2, InputType2 >::value ), "alp::eWiseMulAdd", "called with a right-hand vector _x with an element type that does not " "match the second domain of the given semiring" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, InputType3 >::value ), "grb::eWiseMulAdd", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, InputType3 >::value ), "alp::eWiseMulAdd", "called with an additive vector _y with an element type that does not " "match the fourth domain of the given semiring" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, OutputType >::value ), "grb::eWiseMulAdd", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, OutputType >::value ), "alp::eWiseMulAdd", "called with a result vector _z with an element type that does not match " "the fourth domain of the given semiring" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< bool, MaskType >::value ), "grb::eWiseMulAdd", "called with a mask vector _m with a non-bool element type" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< bool, MaskType >::value ), "alp::eWiseMulAdd", "called with a mask vector _m with a non-bool element type" ); throw std::runtime_error( "Needs an implementation." ); return SUCCESS; } @@ -3357,29 +3357,29 @@ namespace grb { typename OutputStructure, typename MaskStructure, typename InputStructure1, typename InputStructure2, typename InputStructure3, typename OutputView, typename MaskView, typename InputView1 > - RC eWiseMulAdd( VectorView< OutputType, OutputStructure, Density::Dense, OutputView, reference_dense > & _z, - const VectorView< MaskType, MaskStructure, Density::Dense, MaskView, reference_dense > & _m, - const VectorView< InputType1, InputStructure1, Density::Dense, InputView1, reference_dense > & _a, - const Scalar< InputType2, InputStructure2, reference_dense> &beta, - const Scalar< InputType3, InputStructure3, reference_dense> &gamma, + RC eWiseMulAdd( Vector< OutputType, OutputStructure, Density::Dense, OutputView, reference > & _z, + const Vector< MaskType, MaskStructure, Density::Dense, MaskView, reference > & _m, + const Vector< InputType1, InputStructure1, Density::Dense, InputView1, reference > & _a, + const Scalar< InputType2, InputStructure2, reference> &beta, + const Scalar< InputType3, InputStructure3, reference> &gamma, const Ring & ring = Ring(), - const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && - grb::is_semiring< Ring >::value && ! grb::is_object< MaskType >::value, + const typename std::enable_if< ! alp::is_object< OutputType >::value && ! alp::is_object< InputType1 >::value && ! alp::is_object< InputType2 >::value && ! alp::is_object< InputType3 >::value && + alp::is_semiring< Ring >::value && ! alp::is_object< MaskType >::value, void >::type * const = NULL ) { // static sanity checks - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D1, InputType1 >::value ), "grb::eWiseMulAdd", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D1, InputType1 >::value ), "alp::eWiseMulAdd", "called with a left-hand scalar alpha of an element type that does not " "match the first domain of the given semiring" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D2, InputType2 >::value ), "grb::eWiseMulAdd", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D2, InputType2 >::value ), "alp::eWiseMulAdd", "called with a right-hand vector _x with an element type that does not " "match the second domain of the given semiring" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, InputType3 >::value ), "grb::eWiseMulAdd", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, InputType3 >::value ), "alp::eWiseMulAdd", "called with an additive vector _y with an element type that does not " "match the fourth domain of the given semiring" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, OutputType >::value ), "grb::eWiseMulAdd", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, OutputType >::value ), "alp::eWiseMulAdd", "called with a result vector _z with an element type that does not match " "the fourth domain of the given semiring" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< bool, MaskType >::value ), "grb::eWiseMulAdd", "called with a mask vector _m with a non-bool element type" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< bool, MaskType >::value ), "alp::eWiseMulAdd", "called with a mask vector _m with a non-bool element type" ); throw std::runtime_error( "Needs an implementation." ); return SUCCESS; } @@ -3394,29 +3394,29 @@ namespace grb { typename OutputStructure, typename MaskStructure, typename InputStructure1, typename InputStructure2, typename InputStructure3, typename OutputView, typename MaskView, typename InputView2 > - RC eWiseMulAdd( VectorView< OutputType, OutputStructure, Density::Dense, OutputView, reference_dense > & _z, - const VectorView< MaskType, MaskStructure, Density::Dense, MaskView, reference_dense > & _m, - const Scalar< InputType1, InputStructure1, reference_dense > &alpha, - const VectorView< InputType2, InputStructure2, Density::Dense, InputView2, reference_dense > & _x, - const Scalar< InputType3, InputStructure3, reference_dense > &gamma, + RC eWiseMulAdd( Vector< OutputType, OutputStructure, Density::Dense, OutputView, reference > & _z, + const Vector< MaskType, MaskStructure, Density::Dense, MaskView, reference > & _m, + const Scalar< InputType1, InputStructure1, reference > &alpha, + const Vector< InputType2, InputStructure2, Density::Dense, InputView2, reference > & _x, + const Scalar< InputType3, InputStructure3, reference > &gamma, const Ring & ring = Ring(), - const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && - grb::is_semiring< Ring >::value && ! grb::is_object< MaskType >::value, + const typename std::enable_if< ! alp::is_object< OutputType >::value && ! alp::is_object< InputType1 >::value && ! alp::is_object< InputType2 >::value && ! alp::is_object< InputType3 >::value && + alp::is_semiring< Ring >::value && ! alp::is_object< MaskType >::value, void >::type * const = NULL ) { // static sanity checks - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D1, InputType1 >::value ), "grb::eWiseMulAdd", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D1, InputType1 >::value ), "alp::eWiseMulAdd", "called with a left-hand scalar alpha of an element type that does not " "match the first domain of the given semiring" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D2, InputType2 >::value ), "grb::eWiseMulAdd", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D2, InputType2 >::value ), "alp::eWiseMulAdd", "called with a right-hand vector _x with an element type that does not " "match the second domain of the given semiring" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, InputType3 >::value ), "grb::eWiseMulAdd", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, InputType3 >::value ), "alp::eWiseMulAdd", "called with an additive vector _y with an element type that does not " "match the fourth domain of the given semiring" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, OutputType >::value ), "grb::eWiseMulAdd", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, OutputType >::value ), "alp::eWiseMulAdd", "called with a result vector _z with an element type that does not match " "the fourth domain of the given semiring" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< bool, MaskType >::value ), "grb::eWiseMulAdd", "called with a mask vector _m with a non-bool element type" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< bool, MaskType >::value ), "alp::eWiseMulAdd", "called with a mask vector _m with a non-bool element type" ); throw std::runtime_error( "Needs an implementation." ); return SUCCESS; } @@ -3431,30 +3431,30 @@ namespace grb { typename OutputStructure, typename MaskStructure, typename InputStructure1, typename InputStructure2, typename InputStructure3, typename OutputView, typename MaskView, typename InputView1, typename InputView2, typename InputView3 > - RC eWiseMulAdd( VectorView< OutputType, OutputStructure, Density::Dense, OutputView, reference_dense > & _z, - const VectorView< MaskType, MaskStructure, Density::Dense, MaskView, reference_dense > & _m, - const VectorView< InputType1, InputStructure1, Density::Dense, InputView1, reference_dense > & _a, - const VectorView< InputType2, InputStructure2, Density::Dense, InputView2, reference_dense > & _x, - const VectorView< InputType3, InputStructure3, Density::Dense, InputView3, reference_dense > & _y, + RC eWiseMulAdd( Vector< OutputType, OutputStructure, Density::Dense, OutputView, reference > & _z, + const Vector< MaskType, MaskStructure, Density::Dense, MaskView, reference > & _m, + const Vector< InputType1, InputStructure1, Density::Dense, InputView1, reference > & _a, + const Vector< InputType2, InputStructure2, Density::Dense, InputView2, reference > & _x, + const Vector< InputType3, InputStructure3, Density::Dense, InputView3, reference > & _y, const Ring & ring = Ring(), - const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && - grb::is_semiring< Ring >::value && ! grb::is_object< MaskType >::value, + const typename std::enable_if< ! alp::is_object< OutputType >::value && ! alp::is_object< InputType1 >::value && ! alp::is_object< InputType2 >::value && ! alp::is_object< InputType3 >::value && + alp::is_semiring< Ring >::value && ! alp::is_object< MaskType >::value, void >::type * const = NULL ) { (void)ring; // static sanity checks - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D1, InputType1 >::value ), "grb::eWiseMulAdd", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D1, InputType1 >::value ), "alp::eWiseMulAdd", "called with a left-hand vector _a with an element type that does not " "match the first domain of the given semiring" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D2, InputType2 >::value ), "grb::eWiseMulAdd", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D2, InputType2 >::value ), "alp::eWiseMulAdd", "called with a right-hand vector _x with an element type that does not " "match the second domain of the given semiring" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, InputType3 >::value ), "grb::eWiseMulAdd", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, InputType3 >::value ), "alp::eWiseMulAdd", "called with an additive vector _y with an element type that does not " "match the fourth domain of the given semiring" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, OutputType >::value ), "grb::eWiseMulAdd", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, OutputType >::value ), "alp::eWiseMulAdd", "called with a result vector _z with an element type that does not match " "the fourth domain of the given semiring" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< bool, MaskType >::value ), "grb::eWiseMulAdd", "called with a mask vector _m with a non-bool element type" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< bool, MaskType >::value ), "alp::eWiseMulAdd", "called with a mask vector _m with a non-bool element type" ); throw std::runtime_error( "Needs an implementation." ); return SUCCESS; } @@ -3473,27 +3473,27 @@ namespace grb { typename OutputStructure, typename MaskStructure, typename InputStructure1, typename InputStructure2, typename InputStructure3, typename OutputView, typename MaskView, typename InputView1, typename InputView2, typename InputView3 > - RC eWiseMul( VectorView< OutputType, OutputStructure, Density::Dense, OutputView, reference_dense > & z, - const VectorView< MaskType, MaskStructure, Density::Dense, MaskView, reference_dense > & m, - const VectorView< InputType1, InputStructure1, Density::Dense, InputView1, reference_dense > & x, - const VectorView< InputType2, InputStructure2, Density::Dense, InputView2, reference_dense > & y, + RC eWiseMul( Vector< OutputType, OutputStructure, Density::Dense, OutputView, reference > & z, + const Vector< MaskType, MaskStructure, Density::Dense, MaskView, reference > & m, + const Vector< InputType1, InputStructure1, Density::Dense, InputView1, reference > & x, + const Vector< InputType2, InputStructure2, Density::Dense, InputView2, reference > & y, const Ring & ring = Ring(), - const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< MaskType >::value && - grb::is_semiring< Ring >::value, + const typename std::enable_if< ! alp::is_object< OutputType >::value && ! alp::is_object< InputType1 >::value && ! alp::is_object< InputType2 >::value && ! alp::is_object< MaskType >::value && + alp::is_semiring< Ring >::value, void >::type * const = NULL ) { // static sanity checks - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D1, InputType1 >::value ), "grb::eWiseMul", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D1, InputType1 >::value ), "alp::eWiseMul", "called with a left-hand side input vector with element type that does not " "match the first domain of the given semiring" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D2, InputType2 >::value ), "grb::eWiseMul", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D2, InputType2 >::value ), "alp::eWiseMul", "called with a right-hand side input vector with element type that does " "not match the second domain of the given semiring" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D3, OutputType >::value ), "grb::eWiseMul", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D3, OutputType >::value ), "alp::eWiseMul", "called with an output vector with element type that does not match the " "third domain of the given semiring" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< bool, MaskType >::value ), "grb::eWiseMulAdd", "called with a mask vector with a non-bool element type" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< bool, MaskType >::value ), "alp::eWiseMulAdd", "called with a mask vector with a non-bool element type" ); #ifdef _DEBUG - std::cout << "eWiseMul (reference_dense, vector <- vector x vector, masked) dispatches to eWiseMulAdd (vector <- vector x vector + 0, masked)\n"; + std::cout << "eWiseMul (reference, vector <- vector x vector, masked) dispatches to eWiseMulAdd (vector <- vector x vector + 0, masked)\n"; #endif return eWiseMulAdd< descr >( z, m, x, y, ring.template getZero< Ring::D4 >(), ring ); } @@ -3510,27 +3510,27 @@ namespace grb { typename OutputStructure, typename MaskStructure, typename InputStructure2, typename InputStructure3, typename InputStructure1, typename OutputView, typename MaskView, typename InputView2, typename InputView3 > - RC eWiseMul( VectorView< OutputType, OutputStructure, Density::Dense, OutputView, reference_dense > & z, - const VectorView< MaskType, MaskStructure, Density::Dense, MaskView, reference_dense > & m, - const Scalar< InputType1, InputStructure1, reference_dense > &alpha, - const VectorView< InputType2, InputStructure2, Density::Dense, InputView2, reference_dense > & y, + RC eWiseMul( Vector< OutputType, OutputStructure, Density::Dense, OutputView, reference > & z, + const Vector< MaskType, MaskStructure, Density::Dense, MaskView, reference > & m, + const Scalar< InputType1, InputStructure1, reference > &alpha, + const Vector< InputType2, InputStructure2, Density::Dense, InputView2, reference > & y, const Ring & ring = Ring(), - const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< MaskType >::value && - grb::is_semiring< Ring >::value, + const typename std::enable_if< ! alp::is_object< OutputType >::value && ! alp::is_object< InputType1 >::value && ! alp::is_object< InputType2 >::value && ! alp::is_object< MaskType >::value && + alp::is_semiring< Ring >::value, void >::type * const = NULL ) { // static sanity checks - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D1, InputType1 >::value ), "grb::eWiseMul", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D1, InputType1 >::value ), "alp::eWiseMul", "called with a left-hand side input vector with element type that does not " "match the first domain of the given semiring" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D2, InputType2 >::value ), "grb::eWiseMul", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D2, InputType2 >::value ), "alp::eWiseMul", "called with a right-hand side input vector with element type that does " "not match the second domain of the given semiring" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D3, OutputType >::value ), "grb::eWiseMul", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D3, OutputType >::value ), "alp::eWiseMul", "called with an output vector with element type that does not match the " "third domain of the given semiring" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< bool, MaskType >::value ), "grb::eWiseMulAdd", "called with a mask vector _m with a non-bool element type" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< bool, MaskType >::value ), "alp::eWiseMulAdd", "called with a mask vector _m with a non-bool element type" ); #ifdef _DEBUG - std::cout << "eWiseMul (reference_dense, vector <- scalar x vector, masked) dispatches to eWiseMulAdd (vector <- scalar x vector + 0, masked)\n"; + std::cout << "eWiseMul (reference, vector <- scalar x vector, masked) dispatches to eWiseMulAdd (vector <- scalar x vector + 0, masked)\n"; #endif return eWiseMulAdd< descr >( z, m, alpha, y, ring.template getZero< typename Ring::D4 >(), ring ); } @@ -3547,27 +3547,27 @@ namespace grb { typename OutputStructure, typename MaskStructure, typename InputStructure1, typename InputStructure2, typename InputStructure3, typename OutputView, typename MaskView, typename InputView1, typename InputView3 > - RC eWiseMul( VectorView< OutputType, OutputStructure, Density::Dense, OutputView, reference_dense > & z, - const VectorView< MaskType, MaskStructure, Density::Dense, MaskView, reference_dense > & m, - const VectorView< InputType1, InputStructure1, Density::Dense, InputView1, reference_dense > & x, - const Scalar< InputType2, InputStructure2, reference_dense > &beta, + RC eWiseMul( Vector< OutputType, OutputStructure, Density::Dense, OutputView, reference > & z, + const Vector< MaskType, MaskStructure, Density::Dense, MaskView, reference > & m, + const Vector< InputType1, InputStructure1, Density::Dense, InputView1, reference > & x, + const Scalar< InputType2, InputStructure2, reference > &beta, const Ring & ring = Ring(), - const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< MaskType >::value && - grb::is_semiring< Ring >::value, + const typename std::enable_if< ! alp::is_object< OutputType >::value && ! alp::is_object< InputType1 >::value && ! alp::is_object< InputType2 >::value && ! alp::is_object< MaskType >::value && + alp::is_semiring< Ring >::value, void >::type * const = NULL ) { // static sanity checks - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D1, InputType1 >::value ), "grb::eWiseMul", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D1, InputType1 >::value ), "alp::eWiseMul", "called with a left-hand side input vector with element type that does not " "match the first domain of the given semiring" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D2, InputType2 >::value ), "grb::eWiseMul", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D2, InputType2 >::value ), "alp::eWiseMul", "called with a right-hand side input vector with element type that does " "not match the second domain of the given semiring" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D3, OutputType >::value ), "grb::eWiseMul", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D3, OutputType >::value ), "alp::eWiseMul", "called with an output vector with element type that does not match the " "third domain of the given semiring" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< bool, MaskType >::value ), "grb::eWiseMulAdd", "called with a mask vector _m with a non-bool element type" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< bool, MaskType >::value ), "alp::eWiseMulAdd", "called with a mask vector _m with a non-bool element type" ); #ifdef _DEBUG - std::cout << "eWiseMul (reference_dense, masked) dispatches to masked eWiseMulAdd with 0.0 as additive scalar\n"; + std::cout << "eWiseMul (reference, masked) dispatches to masked eWiseMulAdd with 0.0 as additive scalar\n"; #endif return eWiseMulAdd< descr >( z, m, x, beta, ring.template getZero< typename Ring::D4 >(), ring.getMultiplicativeOperator() ); } @@ -3584,35 +3584,35 @@ namespace grb { typename OutputStructure, typename MaskStructure, typename InputStructure1, typename InputStructure2, typename InputStructure3, typename OutputView, typename MaskView, typename InputView3 > - RC eWiseMulAdd( VectorView< OutputType, OutputStructure, Density::Dense, OutputView, reference_dense > & z, - const VectorView< MaskType, MaskStructure, Density::Dense, MaskView, reference_dense > & m, - const Scalar< InputType1, InputStructure1, reference_dense > &alpha, - const Scalar< InputType2, InputStructure2, reference_dense > &beta, - const VectorView< InputType3, InputStructure3, Density::Dense, InputView3, reference_dense > & y, + RC eWiseMulAdd( Vector< OutputType, OutputStructure, Density::Dense, OutputView, reference > & z, + const Vector< MaskType, MaskStructure, Density::Dense, MaskView, reference > & m, + const Scalar< InputType1, InputStructure1, reference > &alpha, + const Scalar< InputType2, InputStructure2, reference > &beta, + const Vector< InputType3, InputStructure3, Density::Dense, InputView3, reference > & y, const Ring & ring = Ring(), - const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && - grb::is_semiring< Ring >::value && ! grb::is_object< MaskType >::value, + const typename std::enable_if< ! alp::is_object< OutputType >::value && ! alp::is_object< InputType1 >::value && ! alp::is_object< InputType2 >::value && ! alp::is_object< InputType3 >::value && + alp::is_semiring< Ring >::value && ! alp::is_object< MaskType >::value, void >::type * const = NULL ) { - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D1, InputType1 >::value ), "grb::eWiseMulAdd(vector,scalar,scalar,scalar)", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D1, InputType1 >::value ), "alp::eWiseMulAdd(vector,scalar,scalar,scalar)", "First domain of semiring does not match first input type" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D2, InputType2 >::value ), "grb::eWiseMulAdd(vector,scalar,scalar,scalar)", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D2, InputType2 >::value ), "alp::eWiseMulAdd(vector,scalar,scalar,scalar)", "Second domain of semiring does not match second input type" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, InputType3 >::value ), "grb::eWiseMulAdd(vector,scalar,scalar,scalar)", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, InputType3 >::value ), "alp::eWiseMulAdd(vector,scalar,scalar,scalar)", "Fourth domain of semiring does not match third input type" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, OutputType >::value ), "grb::eWiseMulAdd(vector,scalar,scalar,scalar)", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, OutputType >::value ), "alp::eWiseMulAdd(vector,scalar,scalar,scalar)", "Fourth domain of semiring does not match output type" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< bool, MaskType >::value ), "grb::eWiseMulAdd", "called with a mask vector with a non-bool element type" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< bool, MaskType >::value ), "alp::eWiseMulAdd", "called with a mask vector with a non-bool element type" ); #ifdef _DEBUG - std::cout << "eWiseMulAdd (reference_dense, vector <- scalar x scalar + vector, masked) precomputes scalar multiply and dispatches to eWiseAdd (reference_dense, vector <- scalar + vector, masked)\n"; + std::cout << "eWiseMulAdd (reference, vector <- scalar x scalar + vector, masked) precomputes scalar multiply and dispatches to eWiseAdd (reference, vector <- scalar + vector, masked)\n"; #endif typename Ring::D3 mul_result; - RC rc = grb::apply( mul_result, alpha, beta, ring.getMultiplicativeOperator() ); + RC rc = alp::apply( mul_result, alpha, beta, ring.getMultiplicativeOperator() ); #ifdef NDEBUG (void)rc; #else assert( rc == SUCCESS ); #endif - return grb::eWiseAdd( z, m, mul_result, y, ring ); + return alp::eWiseAdd( z, m, mul_result, y, ring ); } /** @@ -3627,46 +3627,46 @@ namespace grb { typename OutputStructure, typename MaskStructure, typename InputStructure1, typename InputStructure2, typename InputStructure3, typename OutputView, typename MaskView > - RC eWiseMulAdd( VectorView< OutputType, OutputStructure, Density::Dense, OutputView, reference_dense > & z, - const VectorView< MaskType, MaskStructure, Density::Dense, MaskView, reference_dense > & m, - const Scalar< InputType1, InputStructure1, reference_dense> &alpha, - const Scalar< InputType2, InputStructure2, reference_dense> &beta, - const Scalar< InputType3, InputStructure3, reference_dense> &gamma, + RC eWiseMulAdd( Vector< OutputType, OutputStructure, Density::Dense, OutputView, reference > & z, + const Vector< MaskType, MaskStructure, Density::Dense, MaskView, reference > & m, + const Scalar< InputType1, InputStructure1, reference> &alpha, + const Scalar< InputType2, InputStructure2, reference> &beta, + const Scalar< InputType3, InputStructure3, reference> &gamma, const Ring & ring = Ring(), - const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && - grb::is_semiring< Ring >::value, + const typename std::enable_if< ! alp::is_object< OutputType >::value && ! alp::is_object< InputType1 >::value && ! alp::is_object< InputType2 >::value && ! alp::is_object< InputType3 >::value && + alp::is_semiring< Ring >::value, void >::type * const = NULL ) { - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D1, InputType1 >::value ), "grb::eWiseMulAdd(vector,scalar,scalar,scalar)", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D1, InputType1 >::value ), "alp::eWiseMulAdd(vector,scalar,scalar,scalar)", "First domain of semiring does not match first input type" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D2, InputType2 >::value ), "grb::eWiseMulAdd(vector,scalar,scalar,scalar)", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D2, InputType2 >::value ), "alp::eWiseMulAdd(vector,scalar,scalar,scalar)", "Second domain of semiring does not match second input type" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, InputType3 >::value ), "grb::eWiseMulAdd(vector,scalar,scalar,scalar)", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, InputType3 >::value ), "alp::eWiseMulAdd(vector,scalar,scalar,scalar)", "Fourth domain of semiring does not match third input type" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, OutputType >::value ), "grb::eWiseMulAdd(vector,scalar,scalar,scalar)", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, OutputType >::value ), "alp::eWiseMulAdd(vector,scalar,scalar,scalar)", "Fourth domain of semiring does not match output type" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< bool, MaskType >::value ), "grb::eWiseMulAdd", "called with a mask vector with a non-bool element type" ); + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< bool, MaskType >::value ), "alp::eWiseMulAdd", "called with a mask vector with a non-bool element type" ); #ifdef _DEBUG - std::cout << "eWiseMulAdd (reference_dense, vector <- scalar x scalar + scalar, masked) precomputes scalar operations and dispatches to set (reference_dense, masked)\n"; + std::cout << "eWiseMulAdd (reference, vector <- scalar x scalar + scalar, masked) precomputes scalar operations and dispatches to set (reference, masked)\n"; #endif typename Ring::D3 mul_result; - RC rc = grb::apply( mul_result, alpha, beta, ring.getMultiplicativeOperator() ); + RC rc = alp::apply( mul_result, alpha, beta, ring.getMultiplicativeOperator() ); #ifdef NDEBUG (void)rc; #endif assert( rc == SUCCESS ); typename Ring::D4 add_result; - rc = grb::apply( add_result, mul_result, gamma, ring.getAdditiveOperator() ); + rc = alp::apply( add_result, mul_result, gamma, ring.getAdditiveOperator() ); #ifdef NDEBUG (void)rc; #endif assert( rc == SUCCESS ); - return grb::set( z, m, add_result ); + return alp::set( z, m, add_result ); } - // internal namespace for implementation of grb::dot + // internal namespace for implementation of alp::dot namespace internal { - /** @see grb::dot */ + /** @see alp::dot */ template< Descriptor descr = descriptors::no_operation, class AddMonoid, class AnyOp, @@ -3674,9 +3674,9 @@ namespace grb { typename OutputStructure, typename InputStructure1, typename InputStructure2, typename InputView1, typename InputView2 > - RC dot_generic( Scalar< OutputType, OutputStructure, reference_dense > &z, - const VectorView< InputType1, InputStructure1, Density::Dense, InputView1, reference_dense > &x, - const VectorView< InputType2, InputStructure2, Density::Dense, InputView2, reference_dense > &y, + RC dot_generic( Scalar< OutputType, OutputStructure, reference > &z, + const alp::Vector< InputType1, InputStructure1, Density::Dense, InputView1, reference > &x, + const alp::Vector< InputType2, InputStructure2, Density::Dense, InputView2, reference > &y, const AddMonoid &addMonoid = AddMonoid(), const AnyOp &anyOp = AnyOp() ) { @@ -3715,11 +3715,11 @@ namespace grb { * any binary operator, it follows that a dot-product under any semiring can be * trivially reduced to a call to this version instead. * - * @return grb::MISMATCH When the dimensions of \a x and \a y do not match. All + * @return alp::MISMATCH When the dimensions of \a x and \a y do not match. All * input data containers are left untouched if this exit * code is returned; it will be as though this call was * never made. - * @return grb::SUCCESS On successful completion of this call. + * @return alp::SUCCESS On successful completion of this call. * // * \parblock // * \par Performance semantics @@ -3751,12 +3751,12 @@ namespace grb { * * \parblock * \par Valid descriptors - * -# grb::descriptors::no_operation - * -# grb::descriptors::no_casting - * -# grb::descriptors::dense + * -# alp::descriptors::no_operation + * -# alp::descriptors::no_casting + * -# alp::descriptors::dense * \endparblock * - * If the dense descriptor is set, this implementation returns grb::ILLEGAL if + * If the dense descriptor is set, this implementation returns alp::ILLEGAL if * it was detected that either \a x or \a y was sparse. In this case, it shall * otherwise be as though the call to this function had not occurred (no side * effects). @@ -3772,35 +3772,35 @@ namespace grb { typename OutputStructure, typename InputStructure1, typename InputStructure2, typename InputView1, typename InputView2 > - RC dot( Scalar< OutputType, OutputStructure, reference_dense > &z, - const VectorView< InputType1, InputStructure1, Density::Dense, InputView1, reference_dense > &x, - const VectorView< InputType2, InputStructure2, Density::Dense, InputView2, reference_dense > &y, + RC dot( Scalar< OutputType, OutputStructure, reference > &z, + const Vector< InputType1, InputStructure1, Density::Dense, InputView1, reference > &x, + const Vector< InputType2, InputStructure2, Density::Dense, InputView2, reference > &y, const AddMonoid &addMonoid = AddMonoid(), const AnyOp &anyOp = AnyOp(), - const typename std::enable_if< !grb::is_object< OutputType >::value && - !grb::is_object< InputType1 >::value && - !grb::is_object< InputType2 >::value && - grb::is_monoid< AddMonoid >::value && - grb::is_operator< AnyOp >::value, + const typename std::enable_if< !alp::is_object< OutputType >::value && + !alp::is_object< InputType1 >::value && + !alp::is_object< InputType2 >::value && + alp::is_monoid< AddMonoid >::value && + alp::is_operator< AnyOp >::value, void >::type * const = NULL ) { // static sanity checks - NO_CAST_ASSERT( ( !( descr & descriptors::no_casting ) || std::is_same< InputType1, typename AnyOp::D1 >::value ), "grb::dot", + NO_CAST_ASSERT( ( !( descr & descriptors::no_casting ) || std::is_same< InputType1, typename AnyOp::D1 >::value ), "alp::dot", "called with a left-hand vector value type that does not match the first " "domain of the given multiplicative operator" ); - NO_CAST_ASSERT( ( !( descr & descriptors::no_casting ) || std::is_same< InputType2, typename AnyOp::D2 >::value ), "grb::dot", + NO_CAST_ASSERT( ( !( descr & descriptors::no_casting ) || std::is_same< InputType2, typename AnyOp::D2 >::value ), "alp::dot", "called with a right-hand vector value type that does not match the second " "domain of the given multiplicative operator" ); - NO_CAST_ASSERT( ( !( descr & descriptors::no_casting ) || std::is_same< typename AddMonoid::D3, typename AnyOp::D1 >::value ), "grb::dot", + NO_CAST_ASSERT( ( !( descr & descriptors::no_casting ) || std::is_same< typename AddMonoid::D3, typename AnyOp::D1 >::value ), "alp::dot", "called with a multiplicative operator output domain that does not match " "the first domain of the given additive operator" ); - NO_CAST_ASSERT( ( !( descr & descriptors::no_casting ) || std::is_same< OutputType, typename AddMonoid::D2 >::value ), "grb::dot", + NO_CAST_ASSERT( ( !( descr & descriptors::no_casting ) || std::is_same< OutputType, typename AddMonoid::D2 >::value ), "alp::dot", "called with an output vector value type that does not match the second " "domain of the given additive operator" ); - NO_CAST_ASSERT( ( !( descr & descriptors::no_casting ) || std::is_same< typename AddMonoid::D3, typename AddMonoid::D2 >::value ), "grb::dot", + NO_CAST_ASSERT( ( !( descr & descriptors::no_casting ) || std::is_same< typename AddMonoid::D3, typename AddMonoid::D2 >::value ), "alp::dot", "called with an additive operator whose output domain does not match its " "second input domain" ); - NO_CAST_ASSERT( ( !( descr & descriptors::no_casting ) || std::is_same< OutputType, typename AddMonoid::D3 >::value ), "grb::dot", + NO_CAST_ASSERT( ( !( descr & descriptors::no_casting ) || std::is_same< OutputType, typename AddMonoid::D3 >::value ), "alp::dot", "called with an output vector value type that does not match the third " "domain of the given additive operator" ); (void)z; @@ -3821,37 +3821,37 @@ namespace grb { typename InputView1, typename InputView2 > RC dot( OutputType &z, - const VectorView< InputType1, InputStructure1, Density::Dense, InputView1, reference_dense > &x, - const VectorView< InputType2, InputStructure2, Density::Dense, InputView2, reference_dense > &y, + const Vector< InputType1, InputStructure1, Density::Dense, InputView1, reference > &x, + const Vector< InputType2, InputStructure2, Density::Dense, InputView2, reference > &y, const AddMonoid &addMonoid = AddMonoid(), const AnyOp &anyOp = AnyOp(), - const typename std::enable_if< !grb::is_object< OutputType >::value && - !grb::is_object< InputType1 >::value && - !grb::is_object< InputType2 >::value && - grb::is_monoid< AddMonoid >::value && - grb::is_operator< AnyOp >::value, + const typename std::enable_if< !alp::is_object< OutputType >::value && + !alp::is_object< InputType1 >::value && + !alp::is_object< InputType2 >::value && + alp::is_monoid< AddMonoid >::value && + alp::is_operator< AnyOp >::value, void >::type * const = NULL ) { // static sanity checks - NO_CAST_ASSERT( ( !( descr & descriptors::no_casting ) || std::is_same< InputType1, typename AnyOp::D1 >::value ), "grb::dot", + NO_CAST_ASSERT( ( !( descr & descriptors::no_casting ) || std::is_same< InputType1, typename AnyOp::D1 >::value ), "alp::dot", "called with a left-hand vector value type that does not match the first " "domain of the given multiplicative operator" ); - NO_CAST_ASSERT( ( !( descr & descriptors::no_casting ) || std::is_same< InputType2, typename AnyOp::D2 >::value ), "grb::dot", + NO_CAST_ASSERT( ( !( descr & descriptors::no_casting ) || std::is_same< InputType2, typename AnyOp::D2 >::value ), "alp::dot", "called with a right-hand vector value type that does not match the second " "domain of the given multiplicative operator" ); - NO_CAST_ASSERT( ( !( descr & descriptors::no_casting ) || std::is_same< typename AddMonoid::D3, typename AnyOp::D1 >::value ), "grb::dot", + NO_CAST_ASSERT( ( !( descr & descriptors::no_casting ) || std::is_same< typename AddMonoid::D3, typename AnyOp::D1 >::value ), "alp::dot", "called with a multiplicative operator output domain that does not match " "the first domain of the given additive operator" ); - NO_CAST_ASSERT( ( !( descr & descriptors::no_casting ) || std::is_same< OutputType, typename AddMonoid::D2 >::value ), "grb::dot", + NO_CAST_ASSERT( ( !( descr & descriptors::no_casting ) || std::is_same< OutputType, typename AddMonoid::D2 >::value ), "alp::dot", "called with an output vector value type that does not match the second " "domain of the given additive operator" ); - NO_CAST_ASSERT( ( !( descr & descriptors::no_casting ) || std::is_same< typename AddMonoid::D3, typename AddMonoid::D2 >::value ), "grb::dot", + NO_CAST_ASSERT( ( !( descr & descriptors::no_casting ) || std::is_same< typename AddMonoid::D3, typename AddMonoid::D2 >::value ), "alp::dot", "called with an additive operator whose output domain does not match its " "second input domain" ); - NO_CAST_ASSERT( ( !( descr & descriptors::no_casting ) || std::is_same< OutputType, typename AddMonoid::D3 >::value ), "grb::dot", + NO_CAST_ASSERT( ( !( descr & descriptors::no_casting ) || std::is_same< OutputType, typename AddMonoid::D3 >::value ), "alp::dot", "called with an output vector value type that does not match the third " "domain of the given additive operator" ); - Scalar< OutputType, structures::General, reference_dense > res( z ); + Scalar< OutputType, structures::General, reference > res( z ); RC rc = dot( res, x, y, addMonoid, anyOp ); if( rc != SUCCESS ) { return rc; @@ -3866,7 +3866,7 @@ namespace grb { * with any multiplicative operator. * * For return codes, exception behaviour, performance semantics, template - * and non-template arguments, @see grb::dot. + * and non-template arguments, @see alp::dot. */ template< Descriptor descr = descriptors::no_operation, class Ring, @@ -3875,18 +3875,18 @@ namespace grb { typename InputView1, typename InputView2, Backend backend > RC dot( Scalar< IOType, IOStructure, backend > &x, - const VectorView< InputType1, InputStructure1, Density::Dense, InputView1, backend > &left, - const VectorView< InputType2, InputStructure2, Density::Dense, InputView2, backend > &right, + const Vector< InputType1, InputStructure1, Density::Dense, InputView1, backend > &left, + const Vector< InputType2, InputStructure2, Density::Dense, InputView2, backend > &right, const Ring &ring = Ring(), const typename std::enable_if< - !grb::is_object< InputType1 >::value && - !grb::is_object< InputType2 >::value && - !grb::is_object< IOType >::value && - grb::is_semiring< Ring >::value, + !alp::is_object< InputType1 >::value && + !alp::is_object< InputType2 >::value && + !alp::is_object< IOType >::value && + alp::is_semiring< Ring >::value, void >::type * const = NULL ) { - return grb::dot< descr >( x, - // return grb::dot( x, + return alp::dot< descr >( x, + // return alp::dot( x, left, right, ring.getAdditiveMonoid(), ring.getMultiplicativeOperator() @@ -3902,18 +3902,18 @@ namespace grb { typename InputView1, typename InputView2, Backend backend > RC dot( IOType &x, - const VectorView< InputType1, InputStructure1, Density::Dense, InputView1, backend > &left, - const VectorView< InputType2, InputStructure2, Density::Dense, InputView2, backend > &right, + const Vector< InputType1, InputStructure1, Density::Dense, InputView1, backend > &left, + const Vector< InputType2, InputStructure2, Density::Dense, InputView2, backend > &right, const Ring &ring = Ring(), const typename std::enable_if< - !grb::is_object< InputType1 >::value && - !grb::is_object< InputType2 >::value && - !grb::is_object< IOType >::value && - grb::is_semiring< Ring >::value, + !alp::is_object< InputType1 >::value && + !alp::is_object< InputType2 >::value && + !alp::is_object< IOType >::value && + alp::is_semiring< Ring >::value, void >::type * const = NULL ) { Scalar< IOType, structures::General, backend > res( x ); - RC rc = grb::dot< descr >( x, + RC rc = alp::dot< descr >( x, left, right, ring.getAdditiveMonoid(), ring.getMultiplicativeOperator() @@ -3927,7 +3927,7 @@ namespace grb { /** No implementation notes. */ template< typename Func, typename DataType, typename DataStructure, typename DataView > - RC eWiseMap( const Func f, VectorView< DataType, DataStructure, Density::Dense, DataView, reference_dense > & x ) { + RC eWiseMap( const Func f, Vector< DataType, DataStructure, Density::Dense, DataView, reference > & x ) { throw std::runtime_error( "Needs an implementation." ); return SUCCESS; } @@ -3935,20 +3935,20 @@ namespace grb { /** * This is the eWiseLambda that performs length checking by recursion. * - * in the reference_dense implementation all vectors are distributed equally, so no + * in the reference implementation all vectors are distributed equally, so no * need to synchronise any data structures. We do need to do error checking - * though, to see when to return grb::MISMATCH. That's this function. + * though, to see when to return alp::MISMATCH. That's this function. * - * @see VectorView::operator[]() - * @see VectorView::lambda_reference + * @see Vector::operator[]() + * @see Vector::lambda_reference */ template< typename Func, typename DataType1, typename DataType2, typename DataStructure1, typename DataStructure2, typename DataView1, typename DataView2, typename... Args > RC eWiseLambda( const Func f, - const VectorView< DataType1, DataStructure1, Density::Dense, DataView1, reference_dense > & x, - const VectorView< DataType2, DataStructure2, Density::Dense, DataView2, reference_dense > & y, + const Vector< DataType1, DataStructure1, Density::Dense, DataView1, reference > & x, + const Vector< DataType2, DataStructure2, Density::Dense, DataView2, reference > & y, Args const &... args ) { // catch mismatch if( size( x ) != size( y ) ) { @@ -3959,14 +3959,14 @@ namespace grb { } /** - * No implementation notes. This is the `real' implementation on reference_dense + * No implementation notes. This is the `real' implementation on reference * vectors. * - * @see VectorView::operator[]() - * @see VectorView::lambda_reference + * @see Vector::operator[]() + * @see Vector::lambda_reference */ template< typename Func, typename DataType, typename DataStructure, typename DataView > - RC eWiseLambda( const Func f, const VectorView< DataType, DataStructure, Density::Dense, DataView, reference_dense > & x ) { + RC eWiseLambda( const Func f, const Vector< DataType, DataStructure, Density::Dense, DataView, reference > & x ) { #ifdef _DEBUG std::cout << "Info: entering eWiseLambda function on vectors.\n"; #endif @@ -4015,18 +4015,18 @@ namespace grb { * @param[in] y A valid GraphBLAS vector. This vector may be sparse. * @param[in] monoid The monoid under which to perform this reduction. * - * @return grb::SUCCESS When the call completed successfully. - * @return grb::ILLEGAL If the provided input vector \a y was not dense. - * @return grb::ILLEGAL If the provided input vector \a y was empty. + * @return alp::SUCCESS When the call completed successfully. + * @return alp::ILLEGAL If the provided input vector \a y was not dense. + * @return alp::ILLEGAL If the provided input vector \a y was empty. * * \parblock * \par Valid descriptors - * grb::descriptors::no_operation, grb::descriptors::no_casting, - * grb::descriptors::dense + * alp::descriptors::no_operation, alp::descriptors::no_casting, + * alp::descriptors::dense * * \note Invalid descriptors will be ignored. * - * If grb::descriptors::no_casting is specified, then 1) the first domain of + * If alp::descriptors::no_casting is specified, then 1) the first domain of * \a monoid must match \a InputType, 2) the second domain of \a op must match * \a IOType, and 3) the third domain must match \a IOType. If one of * these is not true, the code shall not compile. @@ -4053,18 +4053,18 @@ namespace grb { // * bytes of data movement. // * \endparblock * - * @see grb::foldl provides similar functionality. + * @see alp::foldl provides similar functionality. */ template< Descriptor descr = descriptors::no_operation, class Monoid, typename InputType, typename IOType, typename MaskType, typename IOStructure, typename InputStructure, typename MaskStructure, typename InputView, typename MaskView > - RC foldl( Scalar< IOType, IOStructure, reference_dense > &x, - const VectorView< InputType, InputStructure, Density::Dense, InputView, reference_dense > & y, - const VectorView< MaskType, MaskStructure, Density::Dense, MaskView, reference_dense > & mask, + RC foldl( Scalar< IOType, IOStructure, reference > &x, + const Vector< InputType, InputStructure, Density::Dense, InputView, reference > & y, + const Vector< MaskType, MaskStructure, Density::Dense, MaskView, reference > & mask, const Monoid & monoid = Monoid(), - const typename std::enable_if< ! grb::is_object< IOType >::value && ! grb::is_object< InputType >::value && ! grb::is_object< MaskType >::value && grb::is_monoid< Monoid >::value, + const typename std::enable_if< ! alp::is_object< IOType >::value && ! alp::is_object< InputType >::value && ! alp::is_object< MaskType >::value && alp::is_monoid< Monoid >::value, void >::type * const = NULL ) { #ifdef _DEBUG std::cout << "foldl: IOType <- [InputType] with a monoid called. Array has size " << size( y ) << " with " << nnz( y ) << " nonzeroes. It has a mask of size " << size( mask ) << " with " @@ -4072,17 +4072,17 @@ namespace grb { #endif // static sanity checks - NO_CAST_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< IOType, InputType >::value ), "grb::reduce", "called with a scalar IO type that does not match the input vector type" ); - NO_CAST_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< InputType, typename Monoid::D1 >::value ), "grb::reduce", + NO_CAST_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< IOType, InputType >::value ), "alp::reduce", "called with a scalar IO type that does not match the input vector type" ); + NO_CAST_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< InputType, typename Monoid::D1 >::value ), "alp::reduce", "called with an input vector value type that does not match the first " "domain of the given monoid" ); - NO_CAST_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< InputType, typename Monoid::D2 >::value ), "grb::reduce", + NO_CAST_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< InputType, typename Monoid::D2 >::value ), "alp::reduce", "called with an input vector type that does not match the second domain of " "the given monoid" ); - NO_CAST_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< InputType, typename Monoid::D3 >::value ), "grb::reduce", + NO_CAST_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< InputType, typename Monoid::D3 >::value ), "alp::reduce", "called with an input vector type that does not match the third domain of " "the given monoid" ); - NO_CAST_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< bool, MaskType >::value ), "grb::reduce", "called with a vector mask type that is not boolean" ); + NO_CAST_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< bool, MaskType >::value ), "alp::reduce", "called with a vector mask type that is not boolean" ); throw std::runtime_error( "Needs an implementation." ); return SUCCESS; @@ -4104,8 +4104,8 @@ namespace grb { typename ValueType, typename ValueStructure, typename ValueView, typename Compare > RC sort( - VectorView< IndexType, IndexStructure, Density::Dense, IndexView, reference_dense > &permutation, - const VectorView< ValueType, ValueStructure, Density::Dense, ValueView, reference_dense > &toSort, + Vector< IndexType, IndexStructure, Density::Dense, IndexView, reference > &permutation, + const Vector< ValueType, ValueStructure, Density::Dense, ValueView, reference > &toSort, Compare cmp //PHASE &phase = EXECUTE ) noexcept { @@ -4121,7 +4121,7 @@ namespace grb { * This function is only available when the output type is floating point. * * For return codes, exception behaviour, performance semantics, template - * and non-template arguments, @see grb::dot. + * and non-template arguments, @see alp::dot. * * @param[out] x The 2-norm of \a y. The input value of \a x will be ignored. * @param[in] y The vector to compute the norm of. @@ -4143,13 +4143,13 @@ namespace grb { typename InputView, Backend backend > RC norm2( Scalar< OutputType, OutputStructure, backend > &x, - const VectorView< InputType, InputStructure, Density::Dense, InputView, backend > &y, + const Vector< InputType, InputStructure, Density::Dense, InputView, backend > &y, const Ring &ring = Ring(), const typename std::enable_if< std::is_floating_point< OutputType >::value, void >::type * const = NULL ) { - RC ret = grb::dot< descr >( x, y, y, ring ); + RC ret = alp::dot< descr >( x, y, y, ring ); if( ret == SUCCESS ) { x = sqrt( x ); } @@ -4167,13 +4167,13 @@ namespace grb { > RC norm2( OutputType &x, - const VectorView< InputType, InputStructure, Density::Dense, InputView, backend > &y, + const Vector< InputType, InputStructure, Density::Dense, InputView, backend > &y, const Ring &ring = Ring(), const typename std::enable_if< std::is_floating_point< OutputType >::value, void >::type * const = nullptr ) { - Scalar< OutputType, structures::General, reference_dense > res( x ); + Scalar< OutputType, structures::General, reference > res( x ); RC rc = norm2( res, y, ring ); if( rc != SUCCESS ) { return rc; @@ -4182,7 +4182,7 @@ namespace grb { return SUCCESS; } -} // end namespace ``grb'' +} // end namespace ``alp'' -#endif // end ``_H_GRB_DENSEREF_BLAS1'' +#endif // end ``_H_ALP_REFERENCE_BLAS1'' diff --git a/include/alp/reference/blas2.hpp b/include/alp/reference/blas2.hpp index 2b0cb2b0f..a6c9cb8f1 100644 --- a/include/alp/reference/blas2.hpp +++ b/include/alp/reference/blas2.hpp @@ -20,64 +20,22 @@ * @date 14th of January 2022 */ -#ifndef _H_GRB_DENSEREF_BLAS2 -#define _H_GRB_DENSEREF_BLAS2 +#ifndef _H_ALP_REFERENCE_BLAS2 +#define _H_ALP_REFERENCE_BLAS2 #include -#include -#include -#include +#include +#include +#include -namespace grb { +namespace alp { /** - * \addtogroup reference_dense + * \addtogroup reference * @{ */ - /** - * Retrieve the row dimension size of this matrix. - * - * @returns The number of rows the current matrix contains. - * - * \parblock - * \par Performance semantics. - * -# This function consitutes \f$ \Theta(1) \f$ work. - * -# This function allocates no additional dynamic memory. - * -# This function uses \f$ \mathcal{O}(1) \f$ memory - * beyond that which was already used at function entry. - * -# This function will move - * \f$ \mathit{sizeof}( size\_t ) \f$ - * bytes of memory. - * \endparblock - */ - template< typename InputType, typename InputStructure, typename InputView > - size_t nrows( const StructuredMatrix< InputType, InputStructure, Density::Dense, InputView, reference_dense > & A ) noexcept { - return A.m; - } - - /** - * Retrieve the column dimension size of this matrix. - * - * @returns The number of columns the current matrix contains. - * - * \parblock - * \par Performance semantics. - * -# This function consitutes \f$ \Theta(1) \f$ work. - * -# This function allocates no additional dynamic memory. - * -# This function uses \f$ \mathcal{O}(1) \f$ memory - * beyond that which was already used at function entry. - * -# This function will move - * \f$ \mathit{sizeof}( size\_t ) \f$ - * bytes of memory. - * \endparblock - */ - template< typename InputType, typename InputStructure, typename InputView > - size_t ncols( const StructuredMatrix< InputType, InputStructure, Density::Dense, InputView, reference_dense > & A ) noexcept { - return A.n; - } - /** * Retrieve the number of nonzeroes contained in this matrix. * @@ -94,8 +52,8 @@ namespace grb { * bytes of memory. * \endparblock */ - template< typename InputType > - size_t nnz( const StructuredMatrix< InputType, InputStructure, Density::Dense, InputView, reference_dense > & A ) noexcept { + template< typename InputType, typename InputStructure, typename InputView > + size_t nnz( const Matrix< InputType, InputStructure, Density::Dense, InputView, reference > & A ) noexcept { return A.nz; } @@ -129,7 +87,7 @@ namespace grb { * \endparblock */ template< typename InputType, typename InputStructure, typename InputView > - RC resize( StructuredMatrix< InputType, InputStructure, Density::Dense, InputView, reference_dense > &A, const size_t new_nz ) noexcept { + RC resize( Matrix< InputType, InputStructure, Density::Dense, InputView, reference > &A, const size_t new_nz ) noexcept { (void)A; (void)new_nz; // TODO implement @@ -140,17 +98,17 @@ namespace grb { /** \internal Delegates to fully masked variant */ template< Descriptor descr = descriptors::no_operation, class Ring, - typename IOType, typename IOView, - typename InputType1, typename InputType1, typename InputView1, + typename IOType, typename IOStructure, typename IOView, + typename InputType1, typename InputStructure1, typename InputView1, typename InputType2, typename InputStructure2, typename InputView2, - typename InputType3, typename InputType3, typename InputView3, typename InputStorage3 > - RC vxm( VectorView< IOType, IOStructure, Density::Dense, IOView, reference_dense > & u, - const VectorView< InputType3, InputStructure3, Density::Dense, InputView3, reference_dense > & mask, - const VectorView< InputType1, InputStructure1, Density::Dense, InputView1, reference_dense > & v, - const StructuredMatrix< InputType2, InputStructure2, Density::Dense, InputView2, reference_dense > & A, + typename InputType3, typename InputStructure3, typename InputView3 > + RC vxm( Vector< IOType, IOStructure, Density::Dense, IOView, reference > & u, + const Vector< InputType3, InputStructure3, Density::Dense, InputView3, reference > & mask, + const Vector< InputType1, InputStructure1, Density::Dense, InputView1, reference > & v, + const Matrix< InputType2, InputStructure2, Density::Dense, InputView2, reference > & A, const Ring & ring = Ring(), - const typename std::enable_if< grb::is_semiring< Ring >::value, void >::type * const = NULL ) { - const VectorView< bool, reference, internal::DefaultCoordinates > empty_mask( 0 ); + const typename std::enable_if< alp::is_semiring< Ring >::value, void >::type * const = NULL ) { + const Vector< bool, structures::General, Density::Dense, view::Original< void >, reference > empty_mask( 0 ); return vxm< descr, true, false >( u, mask, v, empty_mask, A, ring ); } @@ -158,20 +116,20 @@ namespace grb { template< Descriptor descr = descriptors::no_operation, class AdditiveMonoid, class MultiplicativeOperator, - typename IOType, typename IOView, - typename InputType1, typename InputView1, - typename InputType2, typename InputStructure2, typename InputView2, - typename InputType3, typename InputView3, typename InputStorage3 > - RC vxm( VectorView< IOType, IOStructure, Density::Dense, IOView, reference_dense > & u, - const VectorView< InputType3, InputStructure3, Density::Dense, InputView3, reference_dense > & mask, - const VectorView< InputType1, InputStructure1, Density::Dense, InputView1, reference_dense > & v, - const StructuredMatrix< InputType2, InputStructure2, Density::Dense, InputView2, reference_dense > & A, + typename IOType, typename IOStructure, typename IOView, + typename InputType1, typename InputStructure1, typename InputView1, + typename InputType2, typename InputStructure2, typename InputView2, + typename InputType3, typename InputStructure3, typename InputView3 > + RC vxm( Vector< IOType, IOStructure, Density::Dense, IOView, reference > & u, + const Vector< InputType3, InputStructure3, Density::Dense, InputView3, reference > & mask, + const Vector< InputType1, InputStructure1, Density::Dense, InputView1, reference > & v, + const Matrix< InputType2, InputStructure2, Density::Dense, InputView2, reference > & A, const AdditiveMonoid & add = AdditiveMonoid(), const MultiplicativeOperator & mul = MultiplicativeOperator(), - const typename std::enable_if< grb::is_monoid< AdditiveMonoid >::value && grb::is_operator< MultiplicativeOperator >::value && ! grb::is_object< IOType >::value && - ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && ! std::is_same< InputType2, void >::value, + const typename std::enable_if< alp::is_monoid< AdditiveMonoid >::value && alp::is_operator< MultiplicativeOperator >::value && ! alp::is_object< IOType >::value && + ! alp::is_object< InputType1 >::value && ! alp::is_object< InputType2 >::value && ! alp::is_object< InputType3 >::value && ! std::is_same< InputType2, void >::value, void >::type * const = NULL ) { - const grb::VectorView< bool, reference, internal::DefaultCoordinates > empty_mask( 0 ); + const alp::Vector< bool, structures::General, Density::Dense, view::Original< void >, reference > empty_mask( 0 ); return vxm< descr, true, false >( u, mask, v, empty_mask, A, add, mul ); } @@ -180,18 +138,18 @@ namespace grb { bool output_may_be_masked = true, bool input_may_be_masked = true, class Ring, - typename IOType, typename IOView, - typename InputType1, typename InputView1, - typename InputType2, typename InputStructure2, typename InputView2, - typename InputType3, typename InputView3, - typename InputType4, typename InputView4, typename InputStorage4 > - RC vxm( VectorView< IOType, IOStructure, Density::Dense, IOView, reference_dense > & u, - const VectorView< InputType3, InputStructure3, Density::Dense, InputView3, reference_dense > & mask, - const VectorView< InputType1, InputStructure1, Density::Dense, InputView1, reference_dense > & v, - const VectorView< InputType4, InputStructure4, Density::Dense, InputView4, reference_dense > & v_mask, - const StructuredMatrix< InputType2, InputStructure2, Density::Dense, InputView2, reference_dense > & A, + typename IOType, typename IOStructure, typename IOView, + typename InputType1, typename InputStructure1, typename InputView1, + typename InputType2, typename InputStructure2, typename InputView2, + typename InputType3, typename InputStructure3, typename InputView3, + typename InputType4, typename InputStructure4, typename InputView4 > + RC vxm( Vector< IOType, IOStructure, Density::Dense, IOView, reference > & u, + const Vector< InputType3, InputStructure3, Density::Dense, InputView3, reference > & mask, + const Vector< InputType1, InputStructure1, Density::Dense, InputView1, reference > & v, + const Vector< InputType4, InputStructure4, Density::Dense, InputView4, reference > & v_mask, + const Matrix< InputType2, InputStructure2, Density::Dense, InputView2, reference > & A, const Ring & ring = Ring(), - const typename std::enable_if< grb::is_semiring< Ring >::value, void >::type * const = NULL ) { + const typename std::enable_if< alp::is_semiring< Ring >::value, void >::type * const = NULL ) { throw std::runtime_error( "Needs an implementation." ); return SUCCESS; } @@ -199,46 +157,49 @@ namespace grb { /** \internal Delegates to fully masked version */ template< Descriptor descr = descriptors::no_operation, class Ring, - typename IOType = typename Ring::D4, typename IOView, - typename InputType1 = typename Ring::D1, typename InputView1, - typename InputType2 = typename Ring::D2, typename InputStructure2, typename InputView2 > - RC vxm( VectorView< IOType, IOStructure, Density::Dense, IOView, reference_dense > & u, - const VectorView< InputType1, InputStructure1, Density::Dense, InputView1, reference_dense > & v, - const StructuredMatrix< InputType2, InputStructure2, Density::Dense, InputView2, reference_dense > & A, + typename IOType = typename Ring::D4, typename IOStructure, typename IOView, + typename InputType1 = typename Ring::D1, typename InputStructure1, typename InputView1, + typename InputType2 = typename Ring::D2, typename InputStructure2, typename InputView2 > + RC vxm( Vector< IOType, IOStructure, Density::Dense, IOView, reference > & u, + const Vector< InputType1, InputStructure1, Density::Dense, InputView1, reference > & v, + const Matrix< InputType2, InputStructure2, Density::Dense, InputView2, reference > & A, const Ring & ring = Ring(), - const typename std::enable_if< grb::is_semiring< Ring >::value, void >::type * const = NULL ) { - const VectorView< bool, reference_dense, internal::DefaultCoordinates > empty_mask( 0 ); + const typename std::enable_if< alp::is_semiring< Ring >::value, void >::type * const = NULL ) { + const Vector< bool, structures::General, Density::Dense, view::Original< void >, reference > empty_mask( 0 ); return vxm< descr, false, false >( u, empty_mask, v, empty_mask, A, ring ); } /** \internal Delegates to fully masked version */ - template< Descriptor descr = descriptors::no_operation, class AdditiveMonoid, class MultiplicativeOperator, typename IOType, typename InputType1, typename InputType2 > - RC vxm( VectorView< IOType, IOStructure, Density::Dense, IOView, reference_dense > & u, - const VectorView< InputType1, InputStructure1, Density::Dense, InputView1, reference_dense > & v, - const StructuredMatrix< InputType2, InputStructure2, Density::Dense, InputView2, reference_dense > & A, + template< Descriptor descr = descriptors::no_operation, class AdditiveMonoid, class MultiplicativeOperator, + typename IOType, typename IOStructure, typename IOView, + typename InputType1, typename InputStructure1, typename InputView1, + typename InputType2, typename InputStructure2, typename InputView2 > + RC vxm( Vector< IOType, IOStructure, Density::Dense, IOView, reference > & u, + const Vector< InputType1, InputStructure1, Density::Dense, InputView1, reference > & v, + const Matrix< InputType2, InputStructure2, Density::Dense, InputView2, reference > & A, const AdditiveMonoid & add = AdditiveMonoid(), const MultiplicativeOperator & mul = MultiplicativeOperator(), - const typename std::enable_if< grb::is_monoid< AdditiveMonoid >::value && grb::is_operator< MultiplicativeOperator >::value && ! grb::is_object< IOType >::value && - ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! std::is_same< InputType2, void >::value, + const typename std::enable_if< alp::is_monoid< AdditiveMonoid >::value && alp::is_operator< MultiplicativeOperator >::value && ! alp::is_object< IOType >::value && + ! alp::is_object< InputType1 >::value && ! alp::is_object< InputType2 >::value && ! std::is_same< InputType2, void >::value, void >::type * const = NULL ) { - const grb::VectorView< bool, reference_dense, internal::DefaultCoordinates > empty_mask( 0 ); + const alp::Vector< bool, structures::General, Density::Dense, view::Original< void >, reference > empty_mask( 0 ); return vxm< descr, false, false >( u, empty_mask, v, empty_mask, A, add, mul ); } /** \internal Delegates to fully masked version */ template< Descriptor descr = descriptors::no_operation, class Ring, - typename IOType, typename IOView, - typename InputType1, typename InputView1, - typename InputType2, typename InputStructure2, typename InputView2, - typename InputType3 = bool, typename InputView3, typename InputStorage3 > - RC mxv( VectorView< IOType, IOStructure, Density::Dense, IOView, reference_dense > & u, - const VectorView< InputType3, InputStructure3, Density::Dense, InputView3, reference_dense > & mask, - const StructuredMatrix< InputType2, InputStructure2, Density::Dense, InputView2, reference_dense > & A, - const VectorView< InputType1, InputStructure1, Density::Dense, InputView1, reference_dense > & v, + typename IOType, typename IOStructure, typename IOView, + typename InputType1, typename InputStructure1, typename InputView1, + typename InputType2, typename InputStructure2, typename InputView2, + typename InputType3 = bool, typename InputStructure3, typename InputView3 > + RC mxv( Vector< IOType, IOStructure, Density::Dense, IOView, reference > & u, + const Vector< InputType3, InputStructure3, Density::Dense, InputView3, reference > & mask, + const Matrix< InputType2, InputStructure2, Density::Dense, InputView2, reference > & A, + const Vector< InputType1, InputStructure1, Density::Dense, InputView1, reference > & v, const Ring & ring, - const typename std::enable_if< grb::is_semiring< Ring >::value, void >::type * const = NULL ) { - const VectorView< bool, reference_dense, internal::DefaultCoordinates > empty_mask( 0 ); + const typename std::enable_if< alp::is_semiring< Ring >::value, void >::type * const = NULL ) { + const Vector< bool, structures::General, Density::Dense, view::Original< void >, reference > empty_mask( 0 ); return mxv< descr, true, false >( u, mask, A, v, empty_mask, ring ); } @@ -247,18 +208,18 @@ namespace grb { bool output_may_be_masked = true, bool input_may_be_masked = true, class Ring, - typename IOType, typename IOView, - typename InputType1, typename InputView1, - typename InputType2, typename InputStructure2, typename InputView2, - typename InputType3, typename InputView3, - typename InputType4, typename InputView4, typename InputStorage4 > - RC mxv( VectorView< IOType, IOStructure, Density::Dense, IOView, reference_dense > & u, - const VectorView< InputType3, InputStructure3, Density::Dense, InputView3, reference_dense > & mask, - const StructuredMatrix< InputType2, InputStructure2, Density::Dense, InputView2, reference_dense > & A, - const VectorView< InputType1, InputStructure1, Density::Dense, InputView1, reference_dense > & v, - const VectorView< InputType4, InputStructure4, Density::Dense, InputView4, reference_dense > & v_mask, + typename IOType, typename IOStructure, typename IOView, + typename InputType1, typename InputStructure1, typename InputView1, + typename InputType2, typename InputStructure2, typename InputView2, + typename InputType3, typename InputStructure3, typename InputView3, + typename InputType4, typename InputStructure4, typename InputView4 > + RC mxv( Vector< IOType, IOStructure, Density::Dense, IOView, reference > & u, + const Vector< InputType3, InputStructure3, Density::Dense, InputView3, reference > & mask, + const Matrix< InputType2, InputStructure2, Density::Dense, InputView2, reference > & A, + const Vector< InputType1, InputStructure1, Density::Dense, InputView1, reference > & v, + const Vector< InputType4, InputStructure4, Density::Dense, InputView4, reference > & v_mask, const Ring & ring, - const typename std::enable_if< grb::is_semiring< Ring >::value, void >::type * const = NULL ) { + const typename std::enable_if< alp::is_semiring< Ring >::value, void >::type * const = NULL ) { throw std::runtime_error( "Needs an implementation." ); return SUCCESS; @@ -269,29 +230,32 @@ namespace grb { */ template< Descriptor descr = descriptors::no_operation, class Ring, - typename IOType = typename Ring::D4, typename IOView, - typename InputType1 = typename Ring::D1, typename InputStructure2, typename InputView2, - typename InputType2 = typename Ring::D2, typename InputView1, typename InputStorage1 > - RC mxv( VectorView< IOType, IOStructure, Density::Dense, IOView, reference_dense > & u, - const StructuredMatrix< InputType2, InputStructure2, Density::Dense, InputView2, reference_dense > & A, - const VectorView< InputType1, InputStructure1, Density::Dense, InputView1, reference_dense > & v, + typename IOType = typename Ring::D4, typename IOStructure, typename IOView, + typename InputType1 = typename Ring::D1, typename InputStructure1, typename InputView1, + typename InputType2 = typename Ring::D2, typename InputStructure2, typename InputView2 > + RC mxv( Vector< IOType, IOStructure, Density::Dense, IOView, reference > & u, + const Matrix< InputType2, InputStructure2, Density::Dense, InputView2, reference > & A, + const Vector< InputType1, InputStructure1, Density::Dense, InputView1, reference > & v, const Ring & ring, - const typename std::enable_if< grb::is_semiring< Ring >::value, void >::type * const = NULL ) { - const VectorView< bool, view::Original< void >, structure::full, reference_dense, internal::DefaultCoordinates > empty_mask( 0 ); + const typename std::enable_if< alp::is_semiring< Ring >::value, void >::type * const = NULL ) { + const Vector< bool, structures::General, Density::Dense, view::Original< void >, reference > empty_mask( 0 ); return mxv< descr, false, false >( u, empty_mask, A, v, empty_mask, ring ); } /** \internal Delegates to fully masked version */ - template< Descriptor descr = descriptors::no_operation, class AdditiveMonoid, class MultiplicativeOperator, typename IOType, typename InputType1, typename InputType2 > - RC mxv( VectorView< IOType, IOStructure, Density::Dense, IOView, reference_dense > & u, - const StructuredMatrix< InputType2, InputStructure2, Density::Dense, InputView2, reference_dense > & A, - const VectorView< InputType1, InputStructure1, Density::Dense, InputView1, reference_dense > & v, + template< Descriptor descr = descriptors::no_operation, class AdditiveMonoid, class MultiplicativeOperator, + typename IOType, typename IOStructure, typename IOView, + typename InputType1, typename InputStructure1, typename InputView1, + typename InputType2, typename InputStructure2, typename InputView2 > + RC mxv( Vector< IOType, IOStructure, Density::Dense, IOView, reference > & u, + const Matrix< InputType2, InputStructure2, Density::Dense, InputView2, reference > & A, + const Vector< InputType1, InputStructure1, Density::Dense, InputView1, reference > & v, const AdditiveMonoid & add = AdditiveMonoid(), const MultiplicativeOperator & mul = MultiplicativeOperator(), - const typename std::enable_if< grb::is_monoid< AdditiveMonoid >::value && grb::is_operator< MultiplicativeOperator >::value && ! grb::is_object< IOType >::value && - ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! std::is_same< InputType2, void >::value, + const typename std::enable_if< alp::is_monoid< AdditiveMonoid >::value && alp::is_operator< MultiplicativeOperator >::value && ! alp::is_object< IOType >::value && + ! alp::is_object< InputType1 >::value && ! alp::is_object< InputType2 >::value && ! std::is_same< InputType2, void >::value, void >::type * const = NULL ) { - const grb::VectorView< bool, view::Original< void >, structure::full, reference_dense, internal::DefaultCoordinates > empty_mask( 0 ); + const alp::Vector< bool, structures::General, Density::Dense, view::Original< void >, reference > empty_mask( 0 ); return mxv< descr, false, false >( u, empty_mask, A, v, empty_mask, add, mul ); } @@ -303,20 +267,20 @@ namespace grb { bool input_may_be_masked = true, class AdditiveMonoid, class MultiplicativeOperator, - typename IOType, typename IOView, - typename InputType1, typename InputView1, - typename InputType2, typename InputStructure2, typename InputView2, - typename InputType3, typename InputView3, - typename InputType4, typename InputView4, typename InputStorage4 > - RC vxm( VectorView< IOType, IOStructure, Density::Dense, IOView, reference_dense > & u, - const VectorView< InputType3, InputStructure3, Density::Dense, InputView3, reference_dense > & mask, - const VectorView< InputType1, InputStructure1, Density::Dense, InputView1, reference_dense > & v, - const VectorView< InputType4, InputStructure4, Density::Dense, InputView4, reference_dense > & v_mask, - const StructuredMatrix< InputType2, InputStructure2, Density::Dense, InputView2, reference_dense > & A, + typename IOType, typename IOStructure, typename IOView, + typename InputType1, typename InputStructure1, typename InputView1, + typename InputType2, typename InputStructure2, typename InputView2, + typename InputType3, typename InputStructure3, typename InputView3, + typename InputType4, typename InputStructure4, typename InputView4 > + RC vxm( Vector< IOType, IOStructure, Density::Dense, IOView, reference > & u, + const Vector< InputType3, InputStructure3, Density::Dense, InputView3, reference > & mask, + const Vector< InputType1, InputStructure1, Density::Dense, InputView1, reference > & v, + const Vector< InputType4, InputStructure4, Density::Dense, InputView4, reference > & v_mask, + const Matrix< InputType2, InputStructure2, Density::Dense, InputView2, reference > & A, const AdditiveMonoid & add = AdditiveMonoid(), const MultiplicativeOperator & mul = MultiplicativeOperator(), - const typename std::enable_if< grb::is_monoid< AdditiveMonoid >::value && grb::is_operator< MultiplicativeOperator >::value && ! grb::is_object< IOType >::value && - ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && ! grb::is_object< InputType4 >::value && + const typename std::enable_if< alp::is_monoid< AdditiveMonoid >::value && alp::is_operator< MultiplicativeOperator >::value && ! alp::is_object< IOType >::value && + ! alp::is_object< InputType1 >::value && ! alp::is_object< InputType2 >::value && ! alp::is_object< InputType3 >::value && ! alp::is_object< InputType4 >::value && ! std::is_same< InputType2, void >::value, void >::type * const = NULL ) { @@ -332,20 +296,20 @@ namespace grb { bool input_may_be_masked = true, class AdditiveMonoid, class MultiplicativeOperator, - typename IOType, typename IOView, - typename InputType1, typename InputView1, - typename InputType2, typename InputStructure2, typename InputView2, - typename InputType3, typename InputView3, - typename InputType4, typename InputView4, typename InputStorage4 > - RC mxv( VectorView< IOType, IOStructure, reference_dense > & u, - const VectorView< InputType3, InputStructure3, reference_dense > & mask, - const StructuredMatrix< InputType2, InputStructure2, Density::Dense, InputView2, reference_dense > & A, - const VectorView< InputType1, InputStructure1, reference_dense > & v, - const VectorView< InputType4, InputStructure4, reference_dense > & v_mask, + typename IOType, typename IOStructure, typename IOView, + typename InputType1, typename InputStructure1, typename InputView1, + typename InputType2, typename InputStructure2, typename InputView2, + typename InputType3, typename InputStructure3, typename InputView3, + typename InputType4, typename InputStructure4, typename InputView4 > + RC mxv( Vector< IOType, IOStructure, Density::Dense, IOView, reference > & u, + const Vector< InputType3, InputStructure3, Density::Dense, InputView3, reference > & mask, + const Matrix< InputType2, InputStructure2, Density::Dense, InputView2, reference > & A, + const Vector< InputType1, InputStructure1, Density::Dense, InputView1, reference > & v, + const Vector< InputType4, InputStructure4, Density::Dense, InputView4, reference > & v_mask, const AdditiveMonoid & add = AdditiveMonoid(), const MultiplicativeOperator & mul = MultiplicativeOperator(), - const typename std::enable_if< grb::is_monoid< AdditiveMonoid >::value && grb::is_operator< MultiplicativeOperator >::value && ! grb::is_object< IOType >::value && - ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< InputType3 >::value && ! grb::is_object< InputType4 >::value && + const typename std::enable_if< alp::is_monoid< AdditiveMonoid >::value && alp::is_operator< MultiplicativeOperator >::value && ! alp::is_object< IOType >::value && + ! alp::is_object< InputType1 >::value && ! alp::is_object< InputType2 >::value && ! alp::is_object< InputType3 >::value && ! alp::is_object< InputType4 >::value && ! std::is_same< InputType2, void >::value, void >::type * const = NULL ) { @@ -356,15 +320,15 @@ namespace grb { /** * Straightforward implementation using the column-major layout. * - * @see grb::eWiseLambda for the user-level specification. + * @see alp::eWiseLambda for the user-level specification. */ template< class ActiveDistribution, typename Func, typename DataType, typename Structure, typename View> RC eWiseLambda( const Func f, - const StructuredMatrix< DataType, Structure, Density::Dense, View, reference_dense > & A, + const Matrix< DataType, Structure, Density::Dense, View, reference > & A, const size_t s, const size_t P ) { #ifdef _DEBUG - std::cout << "entering grb::eWiseLambda (matrices, reference ). A is " << grb::nrows( A ) << " by " << grb::ncols( A ) << " and holds " << grb::nnz( A ) << " nonzeroes.\n"; + std::cout << "entering alp::eWiseLambda (matrices, reference ). A is " << alp::nrows( A ) << " by " << alp::ncols( A ) << " and holds " << alp::nnz( A ) << " nonzeroes.\n"; #endif throw std::runtime_error( "Needs an implementation." ); return SUCCESS; @@ -374,14 +338,14 @@ namespace grb { * This function provides dimension checking and will defer to the below * function for the actual implementation. * - * @see grb::eWiseLambda for the user-level specification. + * @see alp::eWiseLambda for the user-level specification. */ template< typename Func, - typename DataType1, typename Structure1, typename View1, - typename DataType2, typename View2, typename... Args > + typename DataType1, typename DataStructure1, typename DataView1, + typename DataType2, typename DataStructure2, typename DataView2, typename... Args > RC eWiseLambda( const Func f, - const StructuredMatrix< DataType1, Structure1, Density::Dense, View1, reference_dense > & A, - const VectorView< DataType2, DataStructure2, Density::Dense, View2, reference_dense > x, Args... args ) { + const Matrix< DataType1, DataStructure1, Density::Dense, DataView1, reference > & A, + const Vector< DataType2, DataStructure2, Density::Dense, DataView2, reference > x, Args... args ) { // do size checking if( ! ( size( x ) == nrows( A ) || size( x ) == ncols( A ) ) ) { std::cerr << "Mismatching dimensions: given vector of size " << size( x ) << " has nothing to do with either matrix dimension (" << nrows( A ) << " nor " << ncols( A ) << ").\n"; @@ -393,7 +357,7 @@ namespace grb { /** @} */ -} // end namespace ``grb'' +} // end namespace ``alp'' -#endif // end ``_H_GRB_DENSEREF_BLAS2'' +#endif // end ``_H_ALP_REFERENCE_BLAS2'' diff --git a/include/alp/reference/blas3.hpp b/include/alp/reference/blas3.hpp index 8dde2034a..d8388660f 100644 --- a/include/alp/reference/blas3.hpp +++ b/include/alp/reference/blas3.hpp @@ -20,13 +20,13 @@ * @date 14th of January 2022 */ -#ifndef _H_GRB_DENSEREF_BLAS3 -#define _H_GRB_DENSEREF_BLAS3 +#ifndef _H_ALP_REFERENCE_BLAS3 +#define _H_ALP_REFERENCE_BLAS3 #include //for std::enable_if -#include -#include +#include +#include #include "io.hpp" #include "matrix.hpp" @@ -57,7 +57,7 @@ "******************************\n" ); #endif -namespace grb { +namespace alp { namespace internal { /** @@ -69,17 +69,17 @@ namespace grb { typename OutputType, typename InputType1, typename InputType2, class Operator, class Monoid > - RC mxm_generic( Matrix< OutputType, reference_dense > &C, - const Matrix< InputType1, reference_dense > &A, - const Matrix< InputType2, reference_dense > &B, + RC mxm_generic( Matrix< OutputType, reference > &C, + const Matrix< InputType1, reference > &A, + const Matrix< InputType2, reference > &B, const Operator &oper, const Monoid &monoid, const MulMonoid &mulMonoid, - const typename std::enable_if< !grb::is_object< OutputType >::value && - !grb::is_object< InputType1 >::value && ! - grb::is_object< InputType2 >::value && - grb::is_operator< Operator >::value && - grb::is_monoid< Monoid >::value, + const typename std::enable_if< !alp::is_object< OutputType >::value && + !alp::is_object< InputType1 >::value && ! + alp::is_object< InputType2 >::value && + alp::is_operator< Operator >::value && + alp::is_monoid< Monoid >::value, void >::type * const = NULL ) { (void)oper; @@ -89,30 +89,30 @@ namespace grb { ( !( std::is_same< InputType1, void >::value || std::is_same< InputType2, void >::value ) ), - "grb::mxm_generic: the operator-monoid version of mxm cannot be " + "alp::mxm_generic: the operator-monoid version of mxm cannot be " "used if either of the input matrices is a pattern matrix (of type " "void)" ); #ifdef _DEBUG - std::cout << "In grb::internal::mxm_generic (reference_dense, unmasked)\n"; + std::cout << "In alp::internal::mxm_generic (reference, unmasked)\n"; #endif // run-time checks - const size_t m = grb::nrows( C ); - const size_t n = grb::ncols( C ); - const size_t m_A = grb::nrows( A ); - const size_t k = grb::ncols( A ); - const size_t k_B = grb::nrows( B ); - const size_t n_B = grb::ncols( B ); + const size_t m = nrows( C ); + const size_t n = ncols( C ); + const size_t m_A = nrows( A ); + const size_t k = ncols( A ); + const size_t k_B = nrows( B ); + const size_t n_B = ncols( B ); if( m != m_A || k != k_B || n != n_B ) { return MISMATCH; } - const auto A_raw = grb::internal::getRaw( A ); - const auto B_raw = grb::internal::getRaw( B ); - auto C_raw = grb::internal::getRaw( C ); + const auto A_raw = getRaw( A ); + const auto B_raw = getRaw( B ); + auto C_raw = getRaw( C ); std::cout << "Multiplying dense matrices.\n"; @@ -121,12 +121,12 @@ namespace grb { C_raw[ row * k + col] = monoid.template getIdentity< OutputType >(); for( size_t i = 0; i < k; ++ i ) { OutputType temp = monoid.template getIdentity< OutputType >(); - (void)grb::apply( temp, A_raw[ row * k + i ], B_raw[ i * n_B + col ], oper ); - (void)grb::foldl( C_raw[ row * k + col], temp, monoid.getOperator() ); + (void)alp::apply( temp, A_raw[ row * k + i ], B_raw[ i * n_B + col ], oper ); + (void)alp::foldl( C_raw[ row * k + col], temp, monoid.getOperator() ); } } } - grb::internal::setInitialized( C, true ); + alp::internal::setInitialized( C, true ); // done return SUCCESS; } @@ -143,17 +143,17 @@ namespace grb { typename OutputView, typename InputView1, typename InputView2 > - RC mxm_generic( StructuredMatrix< OutputType, OutputStructure, Density::Dense, OutputView, reference_dense > &C, - const StructuredMatrix< InputType1, InputStructure1, Density::Dense, InputView1, reference_dense > &A, - const StructuredMatrix< InputType2, InputStructure2, Density::Dense, InputView2, reference_dense > &B, + RC mxm_generic( alp::Matrix< OutputType, OutputStructure, Density::Dense, OutputView, reference > &C, + const alp::Matrix< InputType1, InputStructure1, Density::Dense, InputView1, reference > &A, + const alp::Matrix< InputType2, InputStructure2, Density::Dense, InputView2, reference > &B, const Operator &oper, const Monoid &monoid, const MulMonoid &mulMonoid, - const typename std::enable_if< !grb::is_object< OutputType >::value && - !grb::is_object< InputType1 >::value && ! - grb::is_object< InputType2 >::value && - grb::is_operator< Operator >::value && - grb::is_monoid< Monoid >::value, + const typename std::enable_if< !alp::is_object< OutputType >::value && + !alp::is_object< InputType1 >::value && ! + alp::is_object< InputType2 >::value && + alp::is_operator< Operator >::value && + alp::is_monoid< Monoid >::value, void >::type * const = NULL ) { (void)C; @@ -165,7 +165,7 @@ namespace grb { // TODO; Implement this as a backup version that works for any structure and storage. // Even though the performance does not have to be optimal, we guarantee that any two matrices can be multiplied // To provide better performing mxm, one should implement a function with specialized template elements - // This currently cannot work as we do not have a generic way to access elements in a given StructuredMatrix + // This currently cannot work as we do not have a generic way to access elements in a given Matrix return UNSUPPORTED; } @@ -179,17 +179,17 @@ namespace grb { class Operator, class Monoid, typename OutputView = view::Original< void >, typename InputView1 = view::Original< void >, typename InputView2 = view::Original< void > > - RC mxm_generic( StructuredMatrix< OutputType, structures::General, Density::Dense, OutputView, reference_dense > &C, - const StructuredMatrix< InputType1, structures::General, Density::Dense, InputView1, reference_dense > &A, - const StructuredMatrix< InputType2, structures::General, Density::Dense, InputView2, reference_dense > &B, + RC mxm_generic( alp::Matrix< OutputType, structures::General, Density::Dense, OutputView, reference > &C, + const alp::Matrix< InputType1, structures::General, Density::Dense, InputView1, reference > &A, + const alp::Matrix< InputType2, structures::General, Density::Dense, InputView2, reference > &B, const Operator &oper, const Monoid &monoid, const MulMonoid &mulMonoid, - const typename std::enable_if< !grb::is_object< OutputType >::value && - !grb::is_object< InputType1 >::value && ! - grb::is_object< InputType2 >::value && - grb::is_operator< Operator >::value && - grb::is_monoid< Monoid >::value, + const typename std::enable_if< !alp::is_object< OutputType >::value && + !alp::is_object< InputType1 >::value && ! + alp::is_object< InputType2 >::value && + alp::is_operator< Operator >::value && + alp::is_monoid< Monoid >::value, void >::type * const = NULL ) { (void)oper; @@ -199,40 +199,40 @@ namespace grb { ( !( std::is_same< InputType1, void >::value || std::is_same< InputType2, void >::value ) ), - "grb::mxm_generic: the operator-monoid version of mxm cannot be " + "alp::mxm_generic: the operator-monoid version of mxm cannot be " "used if either of the input matrices is a pattern matrix (of type " "void)" ); #ifdef _DEBUG - std::cout << "In grb::internal::mxm_generic (reference_dense, unmasked)\n"; + std::cout << "In alp::internal::mxm_generic (reference, unmasked)\n"; #endif // How to handle combinations of different storage schemes? // For example for C = A * B we can directly call mxm for Matrix<> containers // run-time checks - const size_t m = grb::nrows( C ); - const size_t n = grb::ncols( C ); - const size_t m_A = grb::nrows( A ); - const size_t k = grb::ncols( A ); - const size_t k_B = grb::nrows( B ); - const size_t n_B = grb::ncols( B ); + const size_t m = alp::nrows( C ); + const size_t n = alp::ncols( C ); + const size_t m_A = alp::nrows( A ); + const size_t k = alp::ncols( A ); + const size_t k_B = alp::nrows( B ); + const size_t n_B = alp::ncols( B ); // Maybe we can offload these checks to mxm call later in this function if( m != m_A || k != k_B || n != n_B ) { return MISMATCH; } - const auto A_container = grb::internal::getContainer( A ); - const auto B_container = grb::internal::getContainer( B ); - auto C_container = grb::internal::getContainer( C ); + const auto A_container = alp::internal::getContainer( A ); + const auto B_container = alp::internal::getContainer( B ); + auto C_container = alp::internal::getContainer( C ); std::cout << "Multiplying dense matrices.\n"; RC rc = mxm_generic< true >( C_container, A_container, B_container, oper, monoid, mulMonoid ); if ( rc == SUCCESS ) { - // grb::internal::setInitialized( C, true ); + // alp::internal::setInitialized( C, true ); } // done @@ -257,7 +257,7 @@ namespace grb { * * @returns SUCCESS If the computation completed as intended. * @returns FAILED If the call was not not preceded by one to - * #grb::resize( C, A, B ); \em and the current capacity of + * #alp::resize( C, A, B ); \em and the current capacity of * \a C was insufficient to store the multiplication of \a A * and \a B. The contents of \a C shall be undefined (which * is why #FAILED is returned instead of #ILLEGAL-- this @@ -274,16 +274,16 @@ namespace grb { template< Descriptor descr = descriptors::no_operation, typename OutputType, typename InputType1, typename InputType2, class Semiring > - RC mxm( Matrix< OutputType, reference_dense > & C, - const Matrix< InputType1, reference_dense > & A, - const Matrix< InputType2, reference_dense > & B, + RC mxm( internal::Matrix< OutputType, reference > & C, + const internal::Matrix< InputType1, reference > & A, + const internal::Matrix< InputType2, reference > & B, const Semiring & ring = Semiring(), const PHASE &phase = NUMERICAL, - const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_semiring< Semiring >::value, + const typename std::enable_if< ! alp::is_object< OutputType >::value && ! alp::is_object< InputType1 >::value && ! alp::is_object< InputType2 >::value && alp::is_semiring< Semiring >::value, void >::type * const = NULL ) { #ifdef _DEBUG - std::cout << "In grb::mxm (reference_dense, unmasked, semiring)\n"; + std::cout << "In alp::mxm (reference, unmasked, semiring)\n"; #endif return internal::mxm_generic< true >( C, A, B, ring.getMultiplicativeOperator(), ring.getAdditiveMonoid(), ring.getMultiplicativeMonoid() ); @@ -326,7 +326,7 @@ namespace grb { const InputStructMatT2 & B, const Semiring & ring = Semiring(), const PHASE &phase = NUMERICAL, - const typename std::enable_if< ! grb::is_object< typename OutputStructMatT::value_type >::value && ! grb::is_object< typename InputStructMatT1::value_type >::value && ! grb::is_object< typename InputStructMatT2::value_type >::value && grb::is_semiring< Semiring >::value, + const typename std::enable_if< ! alp::is_object< typename OutputStructMatT::value_type >::value && ! alp::is_object< typename InputStructMatT1::value_type >::value && ! alp::is_object< typename InputStructMatT2::value_type >::value && alp::is_semiring< Semiring >::value, void >::type * const = NULL ) { (void)phase; // TODO: How should we handle multiplication of combinations of Structures and Storage schemes? @@ -347,8 +347,8 @@ namespace grb { const Operator & mulOp, const Monoid & addM, const PHASE &phase = NUMERICAL, - const typename std::enable_if< ! grb::is_object< typename OutputStructMatT::value_type >::value && ! grb::is_object< typename InputStructMatT1::value_type >::value && ! grb::is_object< typename InputStructMatT2::value_type >::value && - grb::is_operator< Operator >::value && grb::is_monoid< Monoid >::value, + const typename std::enable_if< ! alp::is_object< typename OutputStructMatT::value_type >::value && ! alp::is_object< typename InputStructMatT1::value_type >::value && ! alp::is_object< typename InputStructMatT2::value_type >::value && + alp::is_operator< Operator >::value && alp::is_monoid< Monoid >::value, void >::type * const = NULL ) { (void)phase; // TODO: How should we handle multiplication of combinations of Structures and Storage schemes? @@ -372,19 +372,19 @@ namespace grb { typename OutputView, typename InputView1, typename InputView2, class Operator > - RC eWiseApply_matrix_generic( StructuredMatrix< OutputType, OutputStructure, Density::Dense, OutputView, reference_dense > *C, - const StructuredMatrix< InputType1, InputStructure1, Density::Dense, InputView1, reference_dense > *A, + RC eWiseApply_matrix_generic( alp::Matrix< OutputType, OutputStructure, Density::Dense, OutputView, reference > *C, + const alp::Matrix< InputType1, InputStructure1, Density::Dense, InputView1, reference > *A, const InputType1 *alpha, - const StructuredMatrix< InputType2, InputStructure2, Density::Dense, InputView2, reference_dense > *B, + const alp::Matrix< InputType2, InputStructure2, Density::Dense, InputView2, reference > *B, const InputType1 *beta, const Operator &oper, const MulMonoid &mulMonoid, const PHASE &phase, const typename std::enable_if< - !grb::is_object< OutputType >::value && - !grb::is_object< InputType1 >::value && - !grb::is_object< InputType2 >::value && - grb::is_operator< Operator >::value, + !alp::is_object< OutputType >::value && + !alp::is_object< InputType1 >::value && + !alp::is_object< InputType2 >::value && + alp::is_operator< Operator >::value, void >::type * const = NULL ) { (void)C; @@ -399,12 +399,12 @@ namespace grb { std::is_same< InputType1, void >::value || std::is_same< InputType2, void >::value ) ), - "grb::internal::eWiseApply_matrix_generic: the non-monoid version of " + "alp::internal::eWiseApply_matrix_generic: the non-monoid version of " "elementwise mxm can only be used if neither of the input matrices " "is a pattern matrix (of type void)" ); #ifdef _DEBUG - std::cout << "In grb::internal::eWiseApply_matrix_generic\n"; + std::cout << "In alp::internal::eWiseApply_matrix_generic\n"; #endif // get whether the matrices should be transposed prior to execution @@ -413,12 +413,12 @@ namespace grb { // run-time checks // TODO: support left/right_scalar - // const size_t m = grb::nrows( *C ); - // const size_t n = grb::ncols( *C ); - // const size_t m_A = !trans_left ? grb::nrows( *A ) : grb::ncols( *A ); - // const size_t n_A = !trans_left ? grb::ncols( *A ) : grb::nrows( *A ); - // const size_t m_B = !trans_right ? grb::nrows( *B ) : grb::ncols( *B ); - // const size_t n_B = !trans_right ? grb::ncols( *B ) : grb::nrows( *B ); + // const size_t m = alp::nrows( *C ); + // const size_t n = alp::ncols( *C ); + // const size_t m_A = !trans_left ? alp::nrows( *A ) : alp::ncols( *A ); + // const size_t n_A = !trans_left ? alp::ncols( *A ) : alp::nrows( *A ); + // const size_t m_B = !trans_right ? alp::nrows( *B ) : alp::ncols( *B ); + // const size_t n_B = !trans_right ? alp::ncols( *B ) : alp::nrows( *B ); // if( m != m_A || m != m_B || n != n_A || n != n_B ) { // return MISMATCH; @@ -467,11 +467,11 @@ namespace grb { * @param mulmono The monoid used in the element-wise operation * @param phase The execution phase * - * @return grb::MISMATCH Whenever the structures or dimensions of \a A, \a B, and \a C do + * @return alp::MISMATCH Whenever the structures or dimensions of \a A, \a B, and \a C do * not match. All input data containers are left * untouched if this exit code is returned; it will be * as though this call was never made. - * @return grb::SUCCESS On successful completion of this call. + * @return alp::SUCCESS On successful completion of this call. */ template< Descriptor descr = descriptors::no_operation, @@ -480,39 +480,39 @@ namespace grb { typename OutputView, typename InputView1, typename InputView2, class MulMonoid > - RC eWiseApply( StructuredMatrix< OutputType, OutputStructure, Density::Dense, OutputView, reference_dense > &C, - const StructuredMatrix< InputType1, InputStructure1, Density::Dense, InputView1, reference_dense > &A, - const StructuredMatrix< InputType2, InputStructure2, Density::Dense, InputView2, reference_dense > &B, + RC eWiseApply( Matrix< OutputType, OutputStructure, Density::Dense, OutputView, reference > &C, + const Matrix< InputType1, InputStructure1, Density::Dense, InputView1, reference > &A, + const Matrix< InputType2, InputStructure2, Density::Dense, InputView2, reference > &B, const MulMonoid &mulmono, const PHASE phase = NUMERICAL, - const typename std::enable_if< !grb::is_object< OutputType >::value && - !grb::is_object< InputType1 >::value && - !grb::is_object< InputType2 >::value && - grb::is_monoid< MulMonoid >::value, + const typename std::enable_if< !alp::is_object< OutputType >::value && + !alp::is_object< InputType1 >::value && + !alp::is_object< InputType2 >::value && + alp::is_monoid< MulMonoid >::value, void >::type * const = NULL ) { // static checks NO_CAST_ASSERT( ( !( descr & descriptors::no_casting ) || std::is_same< typename MulMonoid::D1, InputType1 >::value ), - "grb::eWiseApply (reference_dense, matrix <- matrix x matrix, monoid)", + "alp::eWiseApply (reference, matrix <- matrix x matrix, monoid)", "called with a prefactor input matrix A that does not match the first " "domain of the monoid operator" ); NO_CAST_ASSERT( ( !( descr & descriptors::no_casting ) || std::is_same< typename MulMonoid::D2, InputType2 >::value ), - "grb::eWiseApply (reference_dense, matrix <- matrix x matrix, monoid)", + "alp::eWiseApply (reference, matrix <- matrix x matrix, monoid)", "called with a postfactor input matrix B that does not match the " "second domain of the monoid operator" ); NO_CAST_ASSERT( ( !( descr & descriptors::no_casting ) || std::is_same< typename MulMonoid::D3, OutputType >::value ), - "grb::eWiseApply (reference_dense, matrix <- matrix x matrix, monoid)", + "alp::eWiseApply (reference, matrix <- matrix x matrix, monoid)", "called with an output matrix C that does not match the output domain " "of the monoid operator" ); #ifdef _DEBUG - std::cout << "In grb::eWiseApply_matrix_generic (reference_dense, monoid)\n"; + std::cout << "In alp::eWiseApply_matrix_generic (reference, monoid)\n"; #endif return internal::eWiseApply_matrix_generic< true, false, false, descr >( @@ -533,42 +533,42 @@ namespace grb { typename OutputView, typename InputView2, class MulMonoid > - RC eWiseApply( StructuredMatrix< OutputType, OutputStructure, Density::Dense, OutputView, reference_dense > &C, + RC eWiseApply( Matrix< OutputType, OutputStructure, Density::Dense, OutputView, reference > &C, const InputType1 &alpha, - const StructuredMatrix< InputType2, InputStructure2, Density::Dense, InputView2, reference_dense > &B, + const Matrix< InputType2, InputStructure2, Density::Dense, InputView2, reference > &B, const MulMonoid &mulmono, const PHASE phase = NUMERICAL, - const typename std::enable_if< !grb::is_object< OutputType >::value && - !grb::is_object< InputType1 >::value && - !grb::is_object< InputType2 >::value && - grb::is_monoid< MulMonoid >::value, + const typename std::enable_if< !alp::is_object< OutputType >::value && + !alp::is_object< InputType1 >::value && + !alp::is_object< InputType2 >::value && + alp::is_monoid< MulMonoid >::value, void >::type * const = NULL ) { // static checks NO_CAST_ASSERT( ( !( descr & descriptors::no_casting ) || std::is_same< typename MulMonoid::D1, InputType1 >::value ), - "grb::eWiseApply (reference, matrix <- matrix x matrix, monoid)", + "alp::eWiseApply (reference, matrix <- matrix x matrix, monoid)", "called with a prefactor input matrix A that does not match the first " "domain of the monoid operator" ); NO_CAST_ASSERT( ( !( descr & descriptors::no_casting ) || std::is_same< typename MulMonoid::D2, InputType2 >::value ), - "grb::eWiseApply (reference, matrix <- matrix x matrix, monoid)", + "alp::eWiseApply (reference, matrix <- matrix x matrix, monoid)", "called with a postfactor input matrix B that does not match the " "second domain of the monoid operator" ); NO_CAST_ASSERT( ( !( descr & descriptors::no_casting ) || std::is_same< typename MulMonoid::D3, OutputType >::value ), - "grb::eWiseApply (reference, matrix <- matrix x matrix, monoid)", + "alp::eWiseApply (reference, matrix <- matrix x matrix, monoid)", "called with an output matrix C that does not match the output domain " "of the monoid operator" ); #ifdef _DEBUG - std::cout << "In grb::eWiseApply_matrix_generic (reference_dense, monoid)\n"; + std::cout << "In alp::eWiseApply_matrix_generic (reference, monoid)\n"; #endif - const StructuredMatrix< InputType1, structures::General, Density::Dense, view::Original< void >, reference_dense > * no_matrix = nullptr; + const Matrix< InputType1, structures::General, Density::Dense, view::Original< void >, reference > * no_matrix = nullptr; return internal::eWiseApply_matrix_generic< true, true, false, descr >( &C, no_matrix, @@ -591,42 +591,42 @@ namespace grb { typename OutputView, typename InputView1, class MulMonoid > - RC eWiseApply( StructuredMatrix< OutputType, OutputStructure, Density::Dense, OutputView, reference_dense > &C, - const StructuredMatrix< InputType1, InputStructure1, Density::Dense, InputView1, reference_dense > &A, + RC eWiseApply( Matrix< OutputType, OutputStructure, Density::Dense, OutputView, reference > &C, + const Matrix< InputType1, InputStructure1, Density::Dense, InputView1, reference > &A, const InputType2 &beta, const MulMonoid &mulmono, const PHASE phase = NUMERICAL, - const typename std::enable_if< !grb::is_object< OutputType >::value && - !grb::is_object< InputType1 >::value && - !grb::is_object< InputType2 >::value && - grb::is_monoid< MulMonoid >::value, + const typename std::enable_if< !alp::is_object< OutputType >::value && + !alp::is_object< InputType1 >::value && + !alp::is_object< InputType2 >::value && + alp::is_monoid< MulMonoid >::value, void >::type * const = NULL ) { // static checks NO_CAST_ASSERT( ( !( descr & descriptors::no_casting ) || std::is_same< typename MulMonoid::D1, InputType1 >::value ), - "grb::eWiseApply (reference, matrix <- matrix x matrix, monoid)", + "alp::eWiseApply (reference, matrix <- matrix x matrix, monoid)", "called with a prefactor input matrix A that does not match the first " "domain of the monoid operator" ); NO_CAST_ASSERT( ( !( descr & descriptors::no_casting ) || std::is_same< typename MulMonoid::D2, InputType2 >::value ), - "grb::eWiseApply (reference, matrix <- matrix x matrix, monoid)", + "alp::eWiseApply (reference, matrix <- matrix x matrix, monoid)", "called with a postfactor input matrix B that does not match the " "second domain of the monoid operator" ); NO_CAST_ASSERT( ( !( descr & descriptors::no_casting ) || std::is_same< typename MulMonoid::D3, OutputType >::value ), - "grb::eWiseApply (reference, matrix <- matrix x matrix, monoid)", + "alp::eWiseApply (reference, matrix <- matrix x matrix, monoid)", "called with an output matrix C that does not match the output domain " "of the monoid operator" ); #ifdef _DEBUG - std::cout << "In grb::eWiseApply_matrix_generic (reference_dense, monoid)\n"; + std::cout << "In alp::eWiseApply_matrix_generic (reference, monoid)\n"; #endif - const StructuredMatrix< InputType2, structures::General, Density::Dense, view::Original< void >, reference_dense > * no_matrix = nullptr; + const Matrix< InputType2, structures::General, Density::Dense, view::Original< void >, reference > * no_matrix = nullptr; return internal::eWiseApply_matrix_generic< true, false, true, descr >( &C, &A, @@ -664,11 +664,11 @@ namespace grb { * @param[in] ring The generalized semiring under which to perform this * element-wise operation. * - * @return grb::MISMATCH Whenever the dimensions of \a x, \a y, and \a z do + * @return alp::MISMATCH Whenever the dimensions of \a x, \a y, and \a z do * not match. All input data containers are left * untouched; it will be as though this call was never * made. - * @return grb::SUCCESS On successful completion of this call. + * @return alp::SUCCESS On successful completion of this call. * * \note Invalid descriptors will be ignored. * @@ -706,24 +706,24 @@ namespace grb { typename OutputView, typename InputView1, typename InputView2, typename Ring> - RC eWiseAdd( StructuredMatrix< OutputType, OutputStructure, Density::Dense, OutputView, reference_dense > &C, - const StructuredMatrix< InputType1, InputStructure1, Density::Dense, InputView1, reference_dense > &A, - const StructuredMatrix< InputType2, InputStructure2, Density::Dense, InputView2, reference_dense > &B, + RC eWiseAdd( Matrix< OutputType, OutputStructure, Density::Dense, OutputView, reference > &C, + const Matrix< InputType1, InputStructure1, Density::Dense, InputView1, reference > &A, + const Matrix< InputType2, InputStructure2, Density::Dense, InputView2, reference > &B, const Ring & ring = Ring(), - const typename std::enable_if< ! grb::is_object< OutputType >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && grb::is_semiring< Ring >::value, + const typename std::enable_if< ! alp::is_object< OutputType >::value && ! alp::is_object< InputType1 >::value && ! alp::is_object< InputType2 >::value && alp::is_semiring< Ring >::value, void >::type * const = NULL ) { // static sanity checks - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, OutputType >::value ), "grb::eWiseAdd", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, OutputType >::value ), "alp::eWiseAdd", "called with an output vector with element type that does not match the " "fourth domain of the given semiring" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D3, InputType1 >::value ), "grb::eWiseAdd", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D3, InputType1 >::value ), "alp::eWiseAdd", "called with a left-hand side input vector with element type that does not " "match the third domain of the given semiring" ); - NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, OutputType >::value ), "grb::eWiseAdd", + NO_CAST_OP_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Ring::D4, OutputType >::value ), "alp::eWiseAdd", "called with a right-hand side input vector with element type that does " "not match the fourth domain of the given semiring" ); #ifdef _DEBUG - std::cout << "eWiseAdd (reference_dense, StrMat <- StrMat + StrMat) dispatches to eWiseApply( reference_dense, StrMat <- StrMat . StrMat ) using additive monoid\n"; + std::cout << "eWiseAdd (reference, StrMat <- StrMat + StrMat) dispatches to eWiseApply( reference, StrMat <- StrMat . StrMat ) using additive monoid\n"; #endif return eWiseApply< descr >( C, A, B, ring.getAdditiveMonoid() ); } @@ -750,65 +750,65 @@ namespace grb { * @param mul The operator * @param phase The execution phase * - * @return grb::MISMATCH Whenever the structures or dimensions of \a A, \a u, and \a v do + * @return alp::MISMATCH Whenever the structures or dimensions of \a A, \a u, and \a v do * not match. All input data containers are left * untouched if this exit code is returned; it will be * as though this call was never made. - * @return grb::SUCCESS On successful completion of this call. + * @return alp::SUCCESS On successful completion of this call. */ template< Descriptor descr = descriptors::no_operation, typename OutputType, typename InputType1, typename InputType2, typename OutputStructure, typename InputStructure1, typename InputStructure2, typename OutputView, typename InputView1, typename InputView2, class Operator > - RC outer( StructuredMatrix< OutputType, OutputStructure, Density::Dense, OutputView, reference_dense > & A, - const VectorView< InputType1, InputStructure1, Density::Dense, InputView1, reference_dense > & u, - const VectorView< InputType2, InputStructure2, Density::Dense, InputView2, reference_dense > & v, + RC outer( Matrix< OutputType, OutputStructure, Density::Dense, OutputView, reference > & A, + const Vector< InputType1, InputStructure1, Density::Dense, InputView1, reference > & u, + const Vector< InputType2, InputStructure2, Density::Dense, InputView2, reference > & v, const Operator & mul = Operator(), - const typename std::enable_if< grb::is_operator< Operator >::value && ! grb::is_object< InputType1 >::value && ! grb::is_object< InputType2 >::value && ! grb::is_object< OutputType >::value, + const typename std::enable_if< alp::is_operator< Operator >::value && ! alp::is_object< InputType1 >::value && ! alp::is_object< InputType2 >::value && ! alp::is_object< OutputType >::value, void >::type * const = NULL ) { // static checks - NO_CAST_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Operator::D1, InputType1 >::value ), "grb::outerProduct", + NO_CAST_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Operator::D1, InputType1 >::value ), "alp::outerProduct", "called with a prefactor vector that does not match the first domain " "of the given multiplication operator" ); - NO_CAST_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Operator::D2, InputType2 >::value ), "grb::outerProduct", + NO_CAST_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Operator::D2, InputType2 >::value ), "alp::outerProduct", "called with a postfactor vector that does not match the first domain " "of the given multiplication operator" ); - NO_CAST_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Operator::D3, OutputType >::value ), "grb::outerProduct", + NO_CAST_ASSERT( ( ! ( descr & descriptors::no_casting ) || std::is_same< typename Operator::D3, OutputType >::value ), "alp::outerProduct", "called with an output matrix that does not match the output domain of " "the given multiplication operator" ); const size_t nrows = getLength( u ); const size_t ncols = getLength( v ); - if( nrows != grb::nrows( A ) ) { + if( nrows != alp::nrows( A ) ) { return MISMATCH; } - if( ncols != grb::ncols( A ) ) { + if( ncols != alp::ncols( A ) ) { return MISMATCH; } - grb::StructuredMatrix< InputType1, structures::General, Density::Dense, view::Original< void >, reference_dense > u_matrix( nrows, 1 ); - grb::StructuredMatrix< InputType2, structures::General, Density::Dense, view::Original< void >, reference_dense > v_matrix( 1, ncols ); + alp::Matrix< InputType1, structures::General, Density::Dense, view::Original< void >, reference > u_matrix( nrows, 1 ); + alp::Matrix< InputType2, structures::General, Density::Dense, view::Original< void >, reference > v_matrix( 1, ncols ); - // auto u_converter = grb::utils::makeVectorToMatrixConverter< InputType1 >( u, []( const size_t & ind, const InputType1 & val ) { + // auto u_converter = alp::utils::makeVectorToMatrixConverter< InputType1 >( u, []( const size_t & ind, const InputType1 & val ) { // return std::make_pair( std::make_pair( ind, 0 ), val ); // } ); - // grb::buildMatrixUnique( u_matrix, u_converter.begin(), u_converter.end(), PARALLEL ); + // alp::buildMatrixUnique( u_matrix, u_converter.begin(), u_converter.end(), PARALLEL ); - // auto v_converter = grb::utils::makeVectorToMatrixConverter< InputType2 >( v, []( const size_t & ind, const InputType2 & val ) { + // auto v_converter = alp::utils::makeVectorToMatrixConverter< InputType2 >( v, []( const size_t & ind, const InputType2 & val ) { // return std::make_pair( std::make_pair( 0, ind ), val ); // } ); - // grb::buildMatrixUnique( v_matrix, v_converter.begin(), v_converter.end(), PARALLEL ); + // alp::buildMatrixUnique( v_matrix, v_converter.begin(), v_converter.end(), PARALLEL ); - grb::Monoid< grb::operators::left_assign< OutputType >, grb::identities::zero > mono; + alp::Monoid< alp::operators::left_assign< OutputType >, alp::identities::zero > mono; - return grb::mxm( A, u_matrix, v_matrix, mul, mono ); + return alp::mxm( A, u_matrix, v_matrix, mul, mono ); } -} // end namespace ``grb'' +} // end namespace ``alp'' -#endif // end ``_H_GRB_DENSEREF_BLAS3'' +#endif // end ``_H_ALP_REFERENCE_BLAS3'' diff --git a/include/alp/reference/collectives.hpp b/include/alp/reference/collectives.hpp index 5f2efa170..0812031fa 100644 --- a/include/alp/reference/collectives.hpp +++ b/include/alp/reference/collectives.hpp @@ -20,17 +20,17 @@ * @date 14th of January 2022 */ -#ifndef _H_GRB_DENSEREF_COLL -#define _H_GRB_DENSEREF_COLL +#ifndef _H_ALP_REFERENCE_COLL +#define _H_ALP_REFERENCE_COLL -namespace grb { +namespace alp { /** * \internal Since this backend only has a single user process, the below only * contains trivial implementations. */ template<> - class collectives< reference_dense > { + class collectives< reference > { private: @@ -70,7 +70,7 @@ namespace grb { }; -} // end namespace ``grb'' +} // end namespace ``alp'' -#endif // end ``_H_GRB_DENSEREF_COLL'' +#endif // end ``_H_ALP_REFERENCE_COLL'' diff --git a/include/alp/reference/config.hpp b/include/alp/reference/config.hpp index 309920340..725d85f02 100644 --- a/include/alp/reference/config.hpp +++ b/include/alp/reference/config.hpp @@ -25,12 +25,12 @@ * @date 14th of January 2022. */ -#ifndef _H_GRB_DENSEREF_CONFIG -#define _H_GRB_DENSEREF_CONFIG +#ifndef _H_ALP_REFERENCE_CONFIG +#define _H_ALP_REFERENCE_CONFIG -#include +#include -namespace grb { +namespace alp { /** * \defgroup reference The reference backend implementation @@ -48,7 +48,7 @@ namespace grb { /** @} */ -} // namespace grb +} // namespace alp -#endif // end ``_H_GRB_DENSEREF_CONFIG'' +#endif // end ``_H_ALP_REFERENCE_CONFIG'' diff --git a/include/alp/reference/exec.hpp b/include/alp/reference/exec.hpp index 248e345a6..b96fabec3 100644 --- a/include/alp/reference/exec.hpp +++ b/include/alp/reference/exec.hpp @@ -20,20 +20,20 @@ * @date 14th of January 2022 */ -#ifndef _H_GRB_DENSEREF_EXEC -#define _H_GRB_DENSEREF_EXEC +#ifndef _H_ALP_REFERENCE_EXEC +#define _H_ALP_REFERENCE_EXEC -#include -#include -#include +#include +#include +#include -namespace grb { +namespace alp { /** * \internal No implementation notes. */ template< EXEC_MODE mode > - class Launcher< mode, reference_dense > { + class Launcher< mode, reference > { public: @@ -58,7 +58,7 @@ namespace grb { /** \internal No implementation notes. */ template< typename U > RC exec( - void ( *grb_program )( const void *, const size_t, U & ), + void ( *alp_program )( const void *, const size_t, U & ), const void *data_in, const size_t in_size, U &data_out, const bool broadcast = false @@ -68,7 +68,7 @@ namespace grb { RC ret = init(); // call graphBLAS algo if( ret == SUCCESS ) { - ( *grb_program )( data_in, in_size, data_out ); + ( *alp_program )( data_in, in_size, data_out ); } // finalise the GraphBLAS if( ret == SUCCESS ) { @@ -81,7 +81,7 @@ namespace grb { /** \internal No implementation notes. */ template< typename T, typename U > RC exec( - void ( *grb_program )( const T &, U & ), + void ( *alp_program )( const T &, U & ), const T &data_in, U &data_out, const bool broadcast = false ) { @@ -90,7 +90,7 @@ namespace grb { RC ret = init(); // call graphBLAS algo if( ret == SUCCESS ) { - ( *grb_program )( data_in, data_out ); + ( *alp_program )( data_in, data_out ); } // finalise the GraphBLAS if( ret == SUCCESS ) { @@ -107,7 +107,7 @@ namespace grb { }; -} // end namespace ``grb'' +} // end namespace ``alp'' -#endif // end ``_H_GRB_DENSEREF_EXEC'' +#endif // end ``_H_ALP_REFERENCE_EXEC'' diff --git a/include/alp/reference/init.hpp b/include/alp/reference/init.hpp index a3156a490..f7df92e49 100644 --- a/include/alp/reference/init.hpp +++ b/include/alp/reference/init.hpp @@ -20,22 +20,22 @@ * @date 14th of January 2022 */ -#ifndef _H_GRB_DENSEREF_INIT -#define _H_GRB_DENSEREF_INIT +#ifndef _H_ALP_REFERENCE_INIT +#define _H_ALP_REFERENCE_INIT -#include +#include -namespace grb { +namespace alp { /** \internal No-op init */ template<> - RC init< reference_dense >( const size_t, const size_t, void * const ); + RC init< reference >( const size_t, const size_t, void * const ); /** \internal No-op init */ template<> - RC finalize< reference_dense >(); + RC finalize< reference >(); -} // end namespace ``grb'' +} // end namespace ``alp'' -#endif // end ``_H_GRB_DENSEREF_INIT'' +#endif // end ``_H_ALP_REFERENCE_INIT'' diff --git a/include/alp/reference/io.hpp b/include/alp/reference/io.hpp index f5926c424..755091a87 100644 --- a/include/alp/reference/io.hpp +++ b/include/alp/reference/io.hpp @@ -20,13 +20,13 @@ * @date 14th of January 2022 */ -#ifndef _H_GRB_DENSEREF_IO -#define _H_GRB_DENSEREF_IO +#ifndef _H_ALP_REFERENCE_IO +#define _H_ALP_REFERENCE_IO -#include +#include #include "matrix.hpp" -namespace grb { +namespace alp { /** * Assigns elements to a matrix from an iterator. @@ -51,14 +51,14 @@ namespace grb { * @param[in] _start Iterator pointing to the first element to be added. * @param[in] _end Iterator pointing past the last element to be added. * - * @return grb::MISMATCH -# the dimension of the input and output containers + * @return alp::MISMATCH -# the dimension of the input and output containers * do not match. * When this error code is returned the state of this * container will be as though this function was never * called; however, the given forward iterators may * have been copied and the copied iterators may have * incurred multiple increments and dereferences. - * @return grb::SUCCESS When the function completes successfully. + * @return alp::SUCCESS When the function completes successfully. * * \parblock * \par Performance semantics. @@ -76,18 +76,18 @@ namespace grb { * */ template< typename InputType, typename fwd_iterator > - RC buildMatrixUnique( Matrix< InputType, reference_dense > & A, fwd_iterator start, const fwd_iterator end ) { + RC buildMatrixUnique( internal::Matrix< InputType, reference > & A, fwd_iterator start, const fwd_iterator end ) { return A.template buildMatrixUnique( start, end ); } /** * @brief \a buildMatrix version. The semantics of this function equals the one of - * \a buildMatrixUnique for the \a reference_dense backend. + * \a buildMatrixUnique for the \a reference backend. * - * @see grb::buildMatrix + * @see alp::buildMatrix */ template< typename InputType, typename fwd_iterator > - RC buildMatrix( Matrix< InputType, reference_dense > & A, fwd_iterator start, const fwd_iterator end ) { + RC buildMatrix( internal::Matrix< InputType, reference > & A, fwd_iterator start, const fwd_iterator end ) { return A.template buildMatrixUnique( start, end ); } @@ -95,7 +95,7 @@ namespace grb { /** * Assigns elements to a structured matrix from an iterator. * - * @tparam StructuredMatrixT The structured matrix type. + * @tparam MatrixT The structured matrix type. * @tparam fwd_iterator The source iterator type. * * The iterator \a fwd_iterator must be STL-compatible, may @@ -115,14 +115,14 @@ namespace grb { * @param[in] _start Iterator pointing to the first element to be added. * @param[in] _end Iterator pointing past the last element to be added. * - * @return grb::MISMATCH -# the dimension of the input and output containers + * @return alp::MISMATCH -# the dimension of the input and output containers * do not match. * When this error code is returned the state of this * container will be as though this function was never * called; however, the given forward iterators may * have been copied and the copied iterators may have * incurred multiple increments and dereferences. - * @return grb::SUCCESS When the function completes successfully. + * @return alp::SUCCESS When the function completes successfully. * * \parblock * \par Performance semantics. @@ -139,8 +139,8 @@ namespace grb { * absolutely necessary. * */ - template< typename StructuredMatrixT, typename fwd_iterator > - RC buildMatrixUnique( StructuredMatrixT & A, const fwd_iterator & start, const fwd_iterator & end ) noexcept { + template< typename MatrixT, typename fwd_iterator > + RC buildMatrixUnique( MatrixT & A, const fwd_iterator & start, const fwd_iterator & end ) noexcept { (void)A; (void)start; (void)end; @@ -150,12 +150,12 @@ namespace grb { /** * @brief \a buildMatrix version. The semantics of this function equals the one of - * \a buildMatrixUnique for the \a reference_dense backend. + * \a buildMatrixUnique for the \a reference backend. * - * @see grb::buildMatrix + * @see alp::buildMatrix */ template< typename InputType, typename Structure, typename View, typename fwd_iterator > - RC buildMatrix( StructuredMatrix< InputType, Structure, Density::Dense, View, reference_dense > & A, const fwd_iterator & start, const fwd_iterator & end ) noexcept { + RC buildMatrix( Matrix< InputType, Structure, Density::Dense, View, reference > & A, const fwd_iterator & start, const fwd_iterator & end ) noexcept { (void)A; (void)start; (void)end; @@ -163,7 +163,7 @@ namespace grb { // return A.template buildMatrixUnique( start, end ); } -} // end namespace ``grb'' +} // end namespace ``alp'' -#endif // end ``_H_GRB_DENSEREF_IO'' +#endif // end ``_H_ALP_REFERENCE_IO'' diff --git a/include/alp/reference/matrix.hpp b/include/alp/reference/matrix.hpp index c0f955025..fb36a1c6d 100644 --- a/include/alp/reference/matrix.hpp +++ b/include/alp/reference/matrix.hpp @@ -20,332 +20,361 @@ * @date 14th of January 2022 */ -#ifndef _H_GRB_DENSEREF_MATRIX -#define _H_GRB_DENSEREF_MATRIX +#ifndef _H_ALP_REFERENCE_MATRIX +#define _H_ALP_REFERENCE_MATRIX #include #include #include #include -#include -#include -#include -#include -#include -#include -#include -#include -//#include //for help with dealing with pattern matrix input -#include -#include -#include -#include -#include - -namespace grb { - - template< typename D > - size_t nrows( const Matrix< D, reference_dense > & ) noexcept; - - template< typename D > - size_t ncols( const Matrix< D, reference_dense > & ) noexcept; - +#include +#include +#include +#include +#include +#include +#include +#include +//#include //for help with dealing with pattern matrix input +#include +#include +#include +#include +#include + +namespace alp { namespace internal { + /** + * Retrieve the row dimension size of this matrix. + * + * @returns The number of rows the current matrix contains. + * + * \parblock + * \par Performance semantics. + * -# This function consitutes \f$ \Theta(1) \f$ work. + * -# This function allocates no additional dynamic memory. + * -# This function uses \f$ \mathcal{O}(1) \f$ memory + * beyond that which was already used at function entry. + * -# This function will move + * \f$ \mathit{sizeof}( size\_t ) \f$ + * bytes of memory. + * \endparblock + */ + template< typename D > + size_t nrows( const Matrix< D, reference > & ) noexcept; + + /** + * Retrieve the column dimension size of this matrix. + * + * @returns The number of columns the current matrix contains. + * + * \parblock + * \par Performance semantics. + * -# This function consitutes \f$ \Theta(1) \f$ work. + * -# This function allocates no additional dynamic memory. + * -# This function uses \f$ \mathcal{O}(1) \f$ memory + * beyond that which was already used at function entry. + * -# This function will move + * \f$ \mathit{sizeof}( size\_t ) \f$ + * bytes of memory. + * \endparblock + */ + template< typename D > + size_t ncols( const Matrix< D, reference > & ) noexcept; + + template< typename D > - D * getRaw( Matrix< D, reference_dense > & ) noexcept; + D * getRaw( Matrix< D, reference > & ) noexcept; template< typename D > - const D * getRaw( const Matrix< D, reference_dense > & ) noexcept; + const D * getRaw( const Matrix< D, reference > & ) noexcept; template< typename D > - const bool & getInitialized( const grb::Matrix< D, reference_dense > & A ) noexcept { + const bool & getInitialized( const alp::internal::Matrix< D, reference > & A ) noexcept { return A.initialized; } template< typename D > - void setInitialized( grb::Matrix< D, reference_dense > & A, bool initialized ) noexcept { + void setInitialized( alp::internal::Matrix< D, reference > & A, bool initialized ) noexcept { A.initialized = initialized; } - } // namespace internal - /** - * ALP/Dense matrix container. - * - * A matrix is stored in full format. - * \a Matrix may be used by \a StructuredMatrix as a raw container. - * - * @tparam D The element type. - */ - template< typename D > - class Matrix< D, reference_dense > { + /** + * ALP/Dense matrix container. + * + * A matrix is stored in full format. + * \a Matrix may be used by \a Matrix as a raw container. + * + * @tparam D The element type. + */ + template< typename D > + class Matrix< D, reference > { - private: - /* ********************* - BLAS2 friends - ********************* */ + private: + /* ********************* + BLAS2 friends + ********************* */ - template< typename DataType > - friend size_t nrows( const Matrix< DataType, reference_dense > & m ) noexcept; + template< typename DataType > + friend size_t nrows( const Matrix< DataType, reference > & m ) noexcept; - template< typename DataType > - friend size_t ncols( const Matrix< DataType, reference_dense > & m ) noexcept; + template< typename DataType > + friend size_t ncols( const Matrix< DataType, reference > & m ) noexcept; - /* ********************* - `Getter' friends - ********************* */ + /* ********************* + `Getter' friends + ********************* */ - friend D * internal::getRaw< D >( Matrix< D, reference_dense > & ) noexcept; + friend D * internal::getRaw< D >( Matrix< D, reference > & ) noexcept; - friend const D * internal::getRaw< D >( const Matrix< D, reference_dense > & ) noexcept; + friend const D * internal::getRaw< D >( const Matrix< D, reference > & ) noexcept; - /* ******************** - IO friends - ******************** */ + /* ******************** + IO friends + ******************** */ - template< typename InputType, typename fwd_iterator > - friend RC buildMatrix( Matrix< InputType, reference_dense > &, fwd_iterator, const fwd_iterator ); + template< typename InputType, typename fwd_iterator > + friend RC buildMatrix( Matrix< InputType, reference > &, fwd_iterator, const fwd_iterator ); - template< typename DataType > - friend const bool & internal::getInitialized( const grb::Matrix< DataType, reference_dense > & ) noexcept; + template< typename DataType > + friend const bool & internal::getInitialized( const alp::internal::Matrix< DataType, reference > & ) noexcept; - template< typename DataType > - friend void internal::setInitialized( grb::Matrix< DataType, reference_dense > & , bool ) noexcept; + template< typename DataType > + friend void internal::setInitialized( alp::internal::Matrix< DataType, reference > & , bool ) noexcept; - typedef Matrix< D, reference_dense > self_type; + typedef Matrix< D, reference > self_type; - /** - * The number of rows. - */ - size_t m; + /** + * The number of rows. + */ + size_t m; - /** - * The number of columns. - */ - size_t n; + /** + * The number of columns. + */ + size_t n; - /** The container capacity (in elements). */ - size_t cap; + /** The container capacity (in elements). */ + size_t cap; - /** The matrix data. */ - D * __restrict__ data; + /** The matrix data. */ + D * __restrict__ data; - /** - * Whether the container presently is initialized or not. - * We differentiate the concept of empty matrix (matrix of size \f$0\times 0\f$) - * from the one of uninitialized (matrix of size \f$m\times n\f$ which was never set) - * and that of zero matrix (matrix with all zero elements). - * \note in sparse format a zero matrix result in an ampty data structure. Is this - * used to refer to uninitialized matrix in ALP/GraphBLAS? - **/ - bool initialized; + /** + * Whether the container presently is initialized or not. + * We differentiate the concept of empty matrix (matrix of size \f$0\times 0\f$) + * from the one of uninitialized (matrix of size \f$m\times n\f$ which was never set) + * and that of zero matrix (matrix with all zero elements). + * \note in sparse format a zero matrix result in an ampty data structure. Is this + * used to refer to uninitialized matrix in ALP/GraphBLAS? + **/ + bool initialized; - /** - * @see grb::buildMatrixUnique - */ - template< typename fwd_iterator > - RC buildMatrixUnique( const fwd_iterator & _start, const fwd_iterator & _end ) { - // detect trivial case - if ( _start == _end || m == 0 || n == 0) { - return SUCCESS; - } + /** + * @see alp::buildMatrixUnique + */ + template< typename fwd_iterator > + RC buildMatrixUnique( const fwd_iterator & _start, const fwd_iterator & _end ) { + // detect trivial case + if ( _start == _end || m == 0 || n == 0) { + return SUCCESS; + } - if ( (size_t)( _end - _start ) != ( m * n ) ) { - return MISMATCH; - } + if ( (size_t)( _end - _start ) != ( m * n ) ) { + return MISMATCH; + } + + // TODO: Add more sanity checks (e.g. overflow) - // TODO: Add more sanity checks (e.g. overflow) + for( auto it = _start; it != _end; ++it ) { + data[ it - _start ] = *it; + } - for( auto it = _start; it != _end; ++it ) { - data[ it - _start ] = *it; + initialized = true; + + // done + return RC::SUCCESS; } - initialized = true; + public: + /** @see Matrix::value_type */ + typedef D value_type; - // done - return RC::SUCCESS; - } + /** + * The main ALP/Dense matrix constructor. + * + * The constructed object will be uninitalised after successful construction. + * + * Requesting a matrix with zero \a rows or \a columns will yield an empty + * matrix. + * + * @param rows The number of rows in the new matrix. + * @param columns The number of columns in the new matrix. + * @param cap The capacity in terms of elements of the new matrix. Optional. + * + * @return SUCCESS This function never fails. + * + * \parblock + * \par Performance semantics. + * -# This constructor entails \f$ \Theta(1) \f$ amount of work. + * -# This constructor may allocate \f$ \Theta( \max{mn, cap} ) \f$ bytes + * of dynamic memory. + * -# This constructor will use \f$ \Theta(1) \f$ extra bytes of + * memory beyond that at constructor entry. + * -# This constructor incurs \f$ \Theta(1) \f$ data movement. + * -# This constructor \em may make system calls. + * \endparblock + * + * \warning Avoid the use of this constructor within performance critical + * code sections. + * \warning \a cap is present for compatibility with other matrix specializations. + * In reference backend, the number of non-zeros (i.e. capacity) + * depends on the used storage scheme. Therefore, this parameter is + * ignored. + */ + Matrix( const size_t rows, const size_t columns, const size_t cap = 0 ): m( rows ), n( columns ), cap( std::max( m*n, cap ) ), initialized( false ) { + // TODO Implement allocation properly + if( m > 0 && n > 0) { + data = new (std::nothrow) D[ m * n ]; + } else { + data = nullptr; + } + + if ( m > 0 && n > 0 && data == nullptr ) { + throw std::runtime_error( "Could not allocate memory during alp::Matrix construction." ); + } - public: - /** @see Matrix::value_type */ - typedef D value_type; + } - /** - * The main ALP/Dense matrix constructor. - * - * The constructed object will be uninitalised after successful construction. - * - * Requesting a matrix with zero \a rows or \a columns will yield an empty - * matrix. - * - * @param rows The number of rows in the new matrix. - * @param columns The number of columns in the new matrix. - * @param cap The capacity in terms of elements of the new matrix. Optional. - * - * @return SUCCESS This function never fails. - * - * \parblock - * \par Performance semantics. - * -# This constructor entails \f$ \Theta(1) \f$ amount of work. - * -# This constructor may allocate \f$ \Theta( \max{mn, cap} ) \f$ bytes - * of dynamic memory. - * -# This constructor will use \f$ \Theta(1) \f$ extra bytes of - * memory beyond that at constructor entry. - * -# This constructor incurs \f$ \Theta(1) \f$ data movement. - * -# This constructor \em may make system calls. - * \endparblock - * - * \warning Avoid the use of this constructor within performance critical - * code sections. - * \warning \a cap is present for compatibility with other matrix specializations. - * In reference_dense backend, the number of non-zeros (i.e. capacity) - * depends on the used storage scheme. Therefore, this parameter is - * ignored. - */ - Matrix( const size_t rows, const size_t columns, const size_t cap = 0 ): m( rows ), n( columns ), cap( std::max( m*n, cap ) ), initialized( false ) { - // TODO Implement allocation properly - if( m > 0 && n > 0) { - data = new (std::nothrow) D[ m * n ]; - } else { - data = nullptr; + /** + * Copy constructor. + * + * @param other The matrix to copy. The initialization state of the copy + * reflects the state of \a other. + * + * \parblock + * \par Performance semantics. + * Allocates the same capacity as the \a other matrix, even if the + * actual number of elements contained in \a other is less. + * -# This constructor entails \f$ \Theta(1) \f$ amount of work. + * -# This constructor allocates \f$ \Theta(\max{mn, cap} ) \f$ bytes + * of dynamic memory. + * -# This constructor incurs \f$ \Theta(mn) \f$ of data + * movement. + * -# This constructor \em may make system calls. + * \endparblock + * + * \warning Avoid the use of this constructor within performance critical + * code sections. + */ + Matrix( const Matrix< D, reference > & other ) : Matrix( other.m, other.n ) { + initialized = other.initialized; } - if ( m > 0 && n > 0 && data == nullptr ) { - throw std::runtime_error( "Could not allocate memory during grb::Matrix construction." ); + /** + * Move constructor. The new matrix equal the given + * matrix. Invalidates the use of the input matrix. + * + * @param[in] other The GraphBLAS matrix to move to this new instance. + * + * \parblock + * \par Performance semantics. + * -# This constructor entails \f$ \Theta(1) \f$ amount of work. + * -# This constructor will not allocate any new dynamic memory. + * -# This constructor will use \f$ \Theta(1) \f$ extra bytes of + * memory beyond that at constructor entry. + * -# This constructor will move \f$ \Theta(1) \f$ bytes of data. + * \endparblock + */ + // Matrix( self_type && other ) noexcept { + // moveFromOther( std::forward< self_type >( other ) ); + // } + + /** + * Move assignment operator. + * @see Matrix::Matrix( Matrix && ) + */ + // self_type & operator=( self_type && other ) noexcept { + // moveFromOther( std::forward< self_type >( other ) ); + // return *this; + // } + + /** + * Matrix destructor. + * + * \parblock + * \par Performance semantics. + * -# This destructor entails \f$ \Theta(1) \f$ amount of work. + * -# This destructor will not perform any memory allocations. + * -# This destructor will use \f$ \mathcal{O}(1) \f$ extra bytes of + * memory beyond that at constructor entry. + * -# This destructor will move \f$ \Theta(1) \f$ bytes of data. + * -# This destructor makes system calls. + * \endparblock + * + * \warning Avoid calling destructors from within performance critical + * code sections. + */ + ~Matrix() { + if( data != nullptr ) { + delete [] data; + } } + }; + template< typename T > + T * getRaw( Matrix< T, reference > & m ) noexcept { + return m.data; } - /** - * Copy constructor. - * - * @param other The matrix to copy. The initialization state of the copy - * reflects the state of \a other. - * - * \parblock - * \par Performance semantics. - * Allocates the same capacity as the \a other matrix, even if the - * actual number of elements contained in \a other is less. - * -# This constructor entails \f$ \Theta(1) \f$ amount of work. - * -# This constructor allocates \f$ \Theta(\max{mn, cap} ) \f$ bytes - * of dynamic memory. - * -# This constructor incurs \f$ \Theta(mn) \f$ of data - * movement. - * -# This constructor \em may make system calls. - * \endparblock - * - * \warning Avoid the use of this constructor within performance critical - * code sections. - */ - Matrix( const Matrix< D, reference_dense > & other ) : Matrix( other.m, other.n ) { - initialized = other.initialized; + template< typename T > + const T * getRaw( const Matrix< T, reference > & m ) noexcept { + return m.data; } - /** - * Move constructor. The new matrix equal the given - * matrix. Invalidates the use of the input matrix. - * - * @param[in] other The GraphBLAS matrix to move to this new instance. - * - * \parblock - * \par Performance semantics. - * -# This constructor entails \f$ \Theta(1) \f$ amount of work. - * -# This constructor will not allocate any new dynamic memory. - * -# This constructor will use \f$ \Theta(1) \f$ extra bytes of - * memory beyond that at constructor entry. - * -# This constructor will move \f$ \Theta(1) \f$ bytes of data. - * \endparblock - */ - // Matrix( self_type && other ) noexcept { - // moveFromOther( std::forward< self_type >( other ) ); - // } - - /** - * Move assignment operator. - * @see Matrix::Matrix( Matrix && ) - */ - // self_type & operator=( self_type && other ) noexcept { - // moveFromOther( std::forward< self_type >( other ) ); - // return *this; - // } + template< typename T > + size_t nrows( const Matrix< T, reference > & m ) noexcept { + return m.m; + } - /** - * Matrix destructor. - * - * \parblock - * \par Performance semantics. - * -# This destructor entails \f$ \Theta(1) \f$ amount of work. - * -# This destructor will not perform any memory allocations. - * -# This destructor will use \f$ \mathcal{O}(1) \f$ extra bytes of - * memory beyond that at constructor entry. - * -# This destructor will move \f$ \Theta(1) \f$ bytes of data. - * -# This destructor makes system calls. - * \endparblock - * - * \warning Avoid calling destructors from within performance critical - * code sections. - */ - ~Matrix() { - if( data != nullptr ) { - delete [] data; - } + template< typename T > + size_t ncols( const Matrix< T, reference > & m ) noexcept { + return m.n; } - }; + } // namespace internal /** - * @brief A reference_dense Matrix is an ALP object. + * @brief A reference Matrix is an ALP object. */ template< typename T > - struct is_container< Matrix< T, reference_dense > > { + struct is_container< internal::Matrix< T, reference > > { static const constexpr bool value = true; }; - template< typename T > - T * internal::getRaw( Matrix< T, reference_dense > & m ) noexcept { - return m.data; - } - - template< typename T > - const T * internal::getRaw( const Matrix< T, reference_dense > & m ) noexcept { - return m.data; - } - - template< typename T > - size_t nrows( const Matrix< T, reference_dense > & m ) noexcept { - return m.m; - } - - template< typename T > - size_t ncols( const Matrix< T, reference_dense > & m ) noexcept { - return m.n; - } - - - - // StructuredMatrix-related implementation - + // Matrix-related implementation namespace internal { /** Forward declaration */ template< typename T > class MatrixContainer; - /** Container reference getters used by friend functions of specialized StructuredMatrix */ + /** Container reference getters used by friend functions of specialized Matrix */ template< typename T > - const Matrix< T, reference_dense > & getContainer( const MatrixContainer< T > & A ); + const Matrix< T, reference > & getContainer( const MatrixContainer< T > & A ); template< typename T > - Matrix< T, reference_dense > & getContainer( MatrixContainer< T > & A ); + Matrix< T, reference > & getContainer( MatrixContainer< T > & A ); /** Container reference getters. Defer the call to base class friend function */ template< typename T, typename Structure, enum Density density, typename View > - const Matrix< T, reference_dense > & getContainer( const StructuredMatrix< T, Structure, density, View, reference_dense > & A ) { + const Matrix< T, reference > & getContainer( const alp::Matrix< T, Structure, density, View, reference > & A ) { return getContainer( A ); } template< typename T, typename Structure, enum Density density, typename View > - Matrix< T, reference_dense > & getContainer( StructuredMatrix< T, Structure, density, View, reference_dense > & A ) { + Matrix< T, reference > & getContainer( alp::Matrix< T, Structure, density, View, reference > & A ) { return getContainer( A ); } @@ -361,36 +390,36 @@ namespace grb { bool getInitialized( MatrixBase & ) noexcept; void getInitialized( MatrixBase &, bool ) noexcept; + } // namespace internal - template< typename T, typename Structure, enum Density density, typename View > - bool getInitialized( StructuredMatrix< T, Structure, density, View, reference_dense > & A ) noexcept { - return getInitialized( A ); - } + template< typename T, typename Structure, enum Density density, typename View > + bool getInitialized( Matrix< T, Structure, density, View, reference > & A ) noexcept { + return getInitialized( A ); + } - template< typename T, typename Structure, enum Density density, typename View > - void setInitialized( StructuredMatrix< T, Structure, density, View, reference_dense > & A, bool initialized ) noexcept { - setInitialized( A, initialized ); - } - } // namespace internal + template< typename T, typename Structure, enum Density density, typename View > + void setInitialized( Matrix< T, Structure, density, View, reference > & A, bool initialized ) noexcept { + setInitialized( A, initialized ); + } template< typename D, typename Structure, typename View > - size_t nrows( const StructuredMatrix< D, Structure, Density::Dense, View, reference_dense > & A ) noexcept { + size_t nrows( const Matrix< D, Structure, Density::Dense, View, reference > & A ) noexcept { return internal::nrows( A ); } template< typename D, typename Structure, typename View > - size_t ncols( const StructuredMatrix< D, Structure, Density::Dense, View, reference_dense > & A ) noexcept { + size_t ncols( const Matrix< D, Structure, Density::Dense, View, reference > & A ) noexcept { return internal::ncols( A ); } template< typename D, typename Structure, typename View > - std::pair< size_t, size_t > dims( const StructuredMatrix< D, Structure, Density::Dense, View, reference_dense > & A ) noexcept { + std::pair< size_t, size_t > dims( const Matrix< D, Structure, Density::Dense, View, reference > & A ) noexcept { return internal::dims( A ); } namespace internal { /** - * Base StructuredMatrix class containing attributes common to all StructuredMatrix specialization + * Base Matrix class containing attributes common to all Matrix specialization * \internal Maybe this class can be inherited by Container and Reference classes below */ @@ -442,19 +471,19 @@ namespace grb { imf_l( imf_l ), imf_r( imf_r ) {} - }; + }; // class MatrixBase /** - * Base class with container-related attributes, used in container-type StructuredMatrix specializations + * Base class with container-related attributes, used in container-type Matrix specializations */ template< typename T > class MatrixContainer : public MatrixBase { protected: - friend const Matrix< T, reference_dense > & getContainer( const MatrixContainer< T > & A ) { + friend const Matrix< T, reference > & getContainer( const MatrixContainer< T > & A ) { return *( A._container ); } - friend Matrix< T, reference_dense > & getContainer( MatrixContainer< T > & A ) { + friend Matrix< T, reference > & getContainer( MatrixContainer< T > & A ) { return *( A._container ); } @@ -467,7 +496,7 @@ namespace grb { } /** A container-type view is characterized by its association with a physical container */ - Matrix< T, reference_dense > * _container; + Matrix< T, reference > * _container; /** * The container's storage scheme. \a storage_scheme is not exposed to the user as an option @@ -486,7 +515,7 @@ namespace grb { * @brief Construct a new structured matrix container object. * * \warning \a cap is present for compatibility with other matrix specializations. - * In reference_dense backend, the number of non-zeros (i.e. capacity) + * In reference backend, the number of non-zeros (i.e. capacity) * depends on the used storage scheme. Therefore, this parameter is * ignored. * @@ -495,12 +524,12 @@ namespace grb { */ MatrixContainer( size_t rows, size_t cols, size_t cap = 0 ) : MatrixBase( rows, cols ), - _container( new Matrix< T, reference_dense >( rows, cols, cap ) ) {} + _container( new Matrix< T, reference >( rows, cols, cap ) ) {} - }; + }; // class MatrixContainer /** - * Base class with reference-related attributes, used in Views on container-type StructuredMatrix specializations + * Base class with reference-related attributes, used in Views on container-type Matrix specializations * */ template< typename TargetType > @@ -515,8 +544,8 @@ namespace grb { MatrixReference( TargetType & struct_mat ) : MatrixBase( nrows( struct_mat ), ncols( struct_mat ) ), ref( struct_mat ) {} MatrixReference( TargetType & struct_mat, std::shared_ptr< imf::IMF > imf_l, std::shared_ptr< imf::IMF > imf_r ) : - MatrixBase( imf_l, imf_r ), ref( struct_mat ) {} - }; + MatrixBase( imf_l, imf_r ), ref( struct_mat ) {} + }; // class MatrixReference } // namespace internal /** @@ -529,11 +558,11 @@ namespace grb { * including the matrix structure itself and \em views on the matrix. * The logical layout of a structured matrix maps to a physical counterpart via * a storage scheme which typically depends on the chosen structure and the selected - * backend. grb::Matrix and grb::Vector may be used as interfaces to such a physical + * backend. alp::Matrix and alp::Vector may be used as interfaces to such a physical * layout. * To visualize this, you may think of a band matrix. Using a * full dense or a banded storage schemes would require - * the use of a \a grb::Matrix container (see include/graphblas/density.hpp for + * the use of a \a alp::Matrix container (see include/alp/density.hpp for * more details about the supported storage schemes). However, the interpration of its * content would differ in the two cases being a function of both the Structure * information and the storage scheme combined. @@ -550,36 +579,36 @@ namespace grb { * Structured matrices defined as views on other matrices do not instantiate a * new container but refer to the one used by their targets. * See the two specializations - * \a StructuredMatrix - * and \a StructuredMatrix, reference_dense > + * \a Matrix + * and \a Matrix, reference > * as examples of structured matrix types without and with physical container, respectively. * * * @tparam T The type of the matrix elements. \a T shall not be a GraphBLAS * type. - * @tparam Structure One of the matrix structures defined in \a grb::structures. + * @tparam Structure One of the matrix structures defined in \a alp::structures. * @tparam density Either \em enum \a Density::Dense or \em enum * \a storage::Sparse. - * @tparam View One of the matrix views in \a grb::view. + * @tparam View One of the matrix views in \a alp::view. * All static views except for \a view::Original (via * \a view::Original cannot instantiate a new container * and only allow to refer to a previously defined - * \a StructuredMatrix. + * \a Matrix. * The \a View parameter should not be used directly * by the user but selected via \a get_view function. * - * See examples of StructuredMatrix definitions within \a include/graphblas/denseref/matrix.hpp + * See examples of Matrix definitions within \a include/alp/reference/matrix.hpp * and the \a dense_structured_matrix.cpp unit test. * */ template< typename T, typename Structure, enum Density density, typename View > - class StructuredMatrix { }; + class Matrix { }; /** * @brief General matrix with physical container. */ template< typename T > - class StructuredMatrix< T, structures::General, Density::Dense, view::Original< void >, reference_dense > : + class Matrix< T, structures::General, Density::Dense, view::Original< void >, reference > : public internal::MatrixContainer< T > { private: @@ -587,16 +616,16 @@ namespace grb { Storage info friends ******************** */ - using self_type = StructuredMatrix< T, structures::General, Density::Dense, view::Original< void >, reference_dense >; + using self_type = Matrix< T, structures::General, Density::Dense, view::Original< void >, reference >; // template< typename fwd_iterator > - // friend RC buildMatrix( StructuredMatrix< T, structures::General, Density::Dense, view::Original< void >, reference_dense > &, const fwd_iterator & start, const fwd_iterator & end ); + // friend RC buildMatrix( Matrix< T, structures::General, Density::Dense, view::Original< void >, reference > &, const fwd_iterator & start, const fwd_iterator & end ); template< typename fwd_iterator > - friend RC buildMatrix( StructuredMatrix< T, structures::General, Density::Dense, view::Original< void >, reference_dense > & A, const fwd_iterator & start, const fwd_iterator & end ); + friend RC buildMatrix( Matrix< T, structures::General, Density::Dense, view::Original< void >, reference > & A, const fwd_iterator & start, const fwd_iterator & end ); template< typename fwd_iterator > RC buildMatrixUnique( const fwd_iterator & start, const fwd_iterator & end ) { - std::cout << "Building StructuredMatrix<>; calling buildMatrix( Matrix<> )\n"; + std::cout << "Building Matrix<>; calling buildMatrix( Matrix<> )\n"; return buildMatrix( *(this->_container), start, end ); } @@ -612,34 +641,34 @@ namespace grb { template < bool d > struct view_type< view::original, d > { - using type = StructuredMatrix< T, structures::General, Density::Dense, view::Original< self_type >, reference_dense >; + using type = Matrix< T, structures::General, Density::Dense, view::Original< self_type >, reference >; }; template < bool d > struct view_type< view::transpose, d > { - using type = StructuredMatrix< T, structures::General, Density::Dense, view::Transpose< self_type >, reference_dense >; + using type = Matrix< T, structures::General, Density::Dense, view::Transpose< self_type >, reference >; }; template < bool d > struct view_type< view::diagonal, d > { - using type = VectorView< T, structures::General, Density::Dense, view::Diagonal< self_type >, reference_dense >; + using type = Vector< T, structures::General, Density::Dense, view::Diagonal< self_type >, reference >; }; - StructuredMatrix( const size_t rows, const size_t cols, const size_t cap = 0 ) : + Matrix( const size_t rows, const size_t cols, const size_t cap = 0 ) : internal::MatrixContainer< T >( rows, cols, cap ) { } - }; // StructuredMatrix General, container + }; // Matrix General, container /** * View of a general Matrix. */ template< typename T, typename View > - class StructuredMatrix< T, structures::General, Density::Dense, View, reference_dense > : + class Matrix< T, structures::General, Density::Dense, View, reference > : public internal::MatrixReference< typename View::applied_to > { private: - using self_type = StructuredMatrix< T, structures::General, Density::Dense, View, reference_dense >; + using self_type = Matrix< T, structures::General, Density::Dense, View, reference >; using target_type = typename View::applied_to; public: @@ -652,25 +681,25 @@ namespace grb { template < bool d > struct view_type< view::original, d > { - using type = StructuredMatrix< T, structures::General, Density::Dense, view::Original< self_type >, reference_dense >; + using type = Matrix< T, structures::General, Density::Dense, view::Original< self_type >, reference >; }; template < bool d > struct view_type< view::transpose, d > { - using type = StructuredMatrix< T, structures::General, Density::Dense, view::Transpose< self_type >, reference_dense >; + using type = Matrix< T, structures::General, Density::Dense, view::Transpose< self_type >, reference >; }; - StructuredMatrix( ) : internal::MatrixBase( 0, 0 ) {} + Matrix( ) : internal::MatrixBase( 0, 0 ) {} - StructuredMatrix( target_type & struct_mat ) : internal::MatrixReference< target_type >( struct_mat ) {} + Matrix( target_type & struct_mat ) : internal::MatrixReference< target_type >( struct_mat ) {} - StructuredMatrix( target_type & struct_mat, std::shared_ptr< imf::IMF > imf_l, std::shared_ptr< imf::IMF > imf_r ) : + Matrix( target_type & struct_mat, std::shared_ptr< imf::IMF > imf_l, std::shared_ptr< imf::IMF > imf_r ) : internal::MatrixReference< target_type >( struct_mat, imf_l, imf_r ) {} - }; // StructuredMatrix General reference + }; // Matrix General reference template< typename T, typename Structure > - class StructuredMatrix< T, Structure, Density::Dense, view::Original< void >, reference_dense > : + class Matrix< T, Structure, Density::Dense, view::Original< void >, reference > : public internal::MatrixContainer< T > { private: @@ -678,10 +707,10 @@ namespace grb { Storage info friends ******************** */ - using self_type = StructuredMatrix< T, Structure, Density::Dense, view::Original< void >, reference_dense >; + using self_type = Matrix< T, Structure, Density::Dense, view::Original< void >, reference >; template< typename fwd_iterator > - friend RC buildMatrix( StructuredMatrix< T, Structure, Density::Dense, view::Original< void >, reference_dense > &, const fwd_iterator &, const fwd_iterator ) noexcept; + friend RC buildMatrix( Matrix< T, Structure, Density::Dense, view::Original< void >, reference > &, const fwd_iterator &, const fwd_iterator ) noexcept; public: using value_type = T; @@ -693,26 +722,26 @@ namespace grb { template < bool d > struct view_type< view::original, d > { - using type = StructuredMatrix< T, Structure, Density::Dense, view::Original< self_type >, reference_dense >; + using type = Matrix< T, Structure, Density::Dense, view::Original< self_type >, reference >; }; - StructuredMatrix( const size_t rows, const size_t cols, const size_t cap = 0 ) : + Matrix( const size_t rows, const size_t cols, const size_t cap = 0 ) : internal::MatrixContainer< T >( rows, cols, cap ) {} - }; // class StructuredMatrix + }; // class Matrix template< typename T > - class StructuredMatrix< T, structures::Square, Density::Dense, view::Original< void >, reference_dense > : + class Matrix< T, structures::Square, Density::Dense, view::Original< void >, reference > : public internal::MatrixContainer< T > { private: - using self_type = StructuredMatrix< T, structures::Square, Density::Dense, view::Original< void >, reference_dense >; + using self_type = Matrix< T, structures::Square, Density::Dense, view::Original< void >, reference >; template< typename InputType, typename Structure, typename View, typename fwd_iterator > - friend RC buildMatrix( StructuredMatrix< InputType, Structure, Density::Dense, View, reference_dense > &, const fwd_iterator & start, const fwd_iterator & end ) noexcept; + friend RC buildMatrix( Matrix< InputType, Structure, Density::Dense, View, reference > &, const fwd_iterator & start, const fwd_iterator & end ) noexcept; template< typename fwd_iterator > RC buildMatrixUnique( const fwd_iterator & start, const fwd_iterator & end ) { - std::cout << "Building StructuredMatrix<>; calling buildMatrix( Matrix<> )\n"; + std::cout << "Building Matrix<>; calling buildMatrix( Matrix<> )\n"; return buildMatrix( *(this->_container), start, end ); } @@ -726,25 +755,25 @@ namespace grb { template < bool d > struct view_type< view::original, d > { - using type = StructuredMatrix< T, structures::Square, Density::Dense, view::Original< self_type >, reference_dense >; + using type = Matrix< T, structures::Square, Density::Dense, view::Original< self_type >, reference >; }; template < bool d > struct view_type< view::transpose, d > { - using type = StructuredMatrix< T, structures::Square, Density::Dense, view::Transpose< self_type >, reference_dense >; + using type = Matrix< T, structures::Square, Density::Dense, view::Transpose< self_type >, reference >; }; - StructuredMatrix( const size_t rows, const size_t cap = 0 ) : + Matrix( const size_t rows, const size_t cap = 0 ) : internal::MatrixContainer< T >( rows, rows, cap ) {} - }; // StructuredMatrix Square, container + }; // Matrix Square, container template< typename T, typename View > - class StructuredMatrix< T, structures::Square, Density::Dense, View, reference_dense > : + class Matrix< T, structures::Square, Density::Dense, View, reference > : public internal::MatrixReference< typename View::applied_to > { private: - using self_type = StructuredMatrix< T, structures::Square, Density::Dense, View, reference_dense >; + using self_type = Matrix< T, structures::Square, Density::Dense, View, reference >; using target_type = typename View::applied_to; public: @@ -757,28 +786,28 @@ namespace grb { template < bool d > struct view_type< view::original, d > { - using type = StructuredMatrix< T, structures::Square, Density::Dense, view::Original< self_type >, reference_dense >; + using type = Matrix< T, structures::Square, Density::Dense, view::Original< self_type >, reference >; }; template < bool d > struct view_type< view::transpose, d > { - using type = StructuredMatrix< T, structures::Square, Density::Dense, view::Transpose< self_type >, reference_dense >; + using type = Matrix< T, structures::Square, Density::Dense, view::Transpose< self_type >, reference >; }; // ref to empty matrix - StructuredMatrix( ) : internal::MatrixReference< target_type >() {} + Matrix( ) : internal::MatrixReference< target_type >() {} - StructuredMatrix( target_type & struct_mat ) : internal::MatrixReference< target_type >( struct_mat ) { + Matrix( target_type & struct_mat ) : internal::MatrixReference< target_type >( struct_mat ) { if( nrows( struct_mat ) != ncols( struct_mat ) ) { - throw std::length_error( "Square StructuredMatrix reference to non-square target." ); + throw std::length_error( "Square Matrix reference to non-square target." ); } } - }; // StructuredMatrix Square reference + }; // Matrix Square reference - // StructuredMatrix UpperTriangular, container + // Matrix UpperTriangular, container template< typename T > - class StructuredMatrix< T, structures::UpperTriangular, Density::Dense, view::Original< void >, reference_dense > : + class Matrix< T, structures::UpperTriangular, Density::Dense, view::Original< void >, reference > : public internal::MatrixContainer< T > { private: @@ -786,14 +815,14 @@ namespace grb { Storage info friends ******************** */ - using self_type = StructuredMatrix< T, structures::UpperTriangular, Density::Dense, view::Original< void >, reference_dense >; + using self_type = Matrix< T, structures::UpperTriangular, Density::Dense, view::Original< void >, reference >; template< typename InputType, typename Structure, typename View, typename fwd_iterator > - friend RC buildMatrix( StructuredMatrix< InputType, Structure, Density::Dense, View, reference_dense > &, const fwd_iterator & start, const fwd_iterator & end ) noexcept; + friend RC buildMatrix( Matrix< InputType, Structure, Density::Dense, View, reference > &, const fwd_iterator & start, const fwd_iterator & end ) noexcept; template< typename fwd_iterator > RC buildMatrixUnique( const fwd_iterator & start, const fwd_iterator & end ) { - std::cout << "Building StructuredMatrix<>; calling buildMatrix( Matrix<> )\n"; + std::cout << "Building Matrix<>; calling buildMatrix( Matrix<> )\n"; return buildMatrix( *(this->_container), start, end ); } @@ -807,26 +836,26 @@ namespace grb { template < bool d > struct view_type< view::original, d > { - using type = StructuredMatrix< T, structures::UpperTriangular, Density::Dense, view::Original< self_type >, reference_dense >; + using type = Matrix< T, structures::UpperTriangular, Density::Dense, view::Original< self_type >, reference >; }; template < bool d > struct view_type< view::transpose, d > { - using type = StructuredMatrix< T, structures::LowerTriangular, Density::Dense, view::Transpose< self_type >, reference_dense >; + using type = Matrix< T, structures::LowerTriangular, Density::Dense, view::Transpose< self_type >, reference >; }; - StructuredMatrix( const size_t rows, const size_t cols, const size_t cap = 0 ) : + Matrix( const size_t rows, const size_t cols, const size_t cap = 0 ) : internal::MatrixContainer< T >( rows, cols, cap ) {} - }; // StructuredMatrix UpperTriangular, container + }; // Matrix UpperTriangular, container - // StructuredMatrix UpperTriangular, reference + // Matrix UpperTriangular, reference template< typename T, typename View > - class StructuredMatrix< T, structures::UpperTriangular, Density::Dense, View, reference_dense > : + class Matrix< T, structures::UpperTriangular, Density::Dense, View, reference > : public internal::MatrixReference< typename View::applied_to > { private: - using self_type = StructuredMatrix< T, structures::UpperTriangular, Density::Dense, View, reference_dense >; + using self_type = Matrix< T, structures::UpperTriangular, Density::Dense, View, reference >; using target_type = typename View::applied_to; public: @@ -839,30 +868,30 @@ namespace grb { template < bool d > struct view_type< view::original, d > { - using type = StructuredMatrix< T, structures::UpperTriangular, Density::Dense, view::Original< self_type >, reference_dense >; + using type = Matrix< T, structures::UpperTriangular, Density::Dense, view::Original< self_type >, reference >; }; template < bool d > struct view_type< view::transpose, d > { - using type = StructuredMatrix< T, structures::LowerTriangular, Density::Dense, view::Transpose< self_type >, reference_dense >; + using type = Matrix< T, structures::LowerTriangular, Density::Dense, view::Transpose< self_type >, reference >; }; // ref to empty matrix - StructuredMatrix( ) : internal::MatrixReference< target_type >() {} + Matrix( ) : internal::MatrixReference< target_type >() {} - StructuredMatrix( target_type & struct_mat ) : internal::MatrixReference< target_type >( struct_mat ) { + Matrix( target_type & struct_mat ) : internal::MatrixReference< target_type >( struct_mat ) { // No matter the view it has to be a square matrix } - StructuredMatrix( target_type & struct_mat, std::shared_ptr< imf::IMF > imf_l, std::shared_ptr< imf::IMF > imf_r ) : + Matrix( target_type & struct_mat, std::shared_ptr< imf::IMF > imf_l, std::shared_ptr< imf::IMF > imf_r ) : internal::MatrixReference< target_type >( struct_mat, imf_l, imf_r ) {} - }; // StructuredMatrix UpperTriangular, reference + }; // Matrix UpperTriangular, reference - // StructuredMatrix Identity, container + // Matrix Identity, container // Should Identity be a MatrixContainer? template< typename T > - class StructuredMatrix< T, structures::Identity, Density::Dense, view::Original< void >, reference_dense > : + class Matrix< T, structures::Identity, Density::Dense, view::Original< void >, reference > : public internal::MatrixContainer< T > { private: @@ -870,14 +899,14 @@ namespace grb { Storage info friends ******************** */ - using self_type = StructuredMatrix< T, structures::Identity, Density::Dense, view::Original< void >, reference_dense >; + using self_type = Matrix< T, structures::Identity, Density::Dense, view::Original< void >, reference >; template< typename InputType, typename Structure, typename View, typename fwd_iterator > - friend RC buildMatrix( StructuredMatrix< InputType, Structure, Density::Dense, View, reference_dense > &, const fwd_iterator & start, const fwd_iterator & end ) noexcept; + friend RC buildMatrix( Matrix< InputType, Structure, Density::Dense, View, reference > &, const fwd_iterator & start, const fwd_iterator & end ) noexcept; template< typename fwd_iterator > RC buildMatrixUnique( const fwd_iterator & start, const fwd_iterator & end ) { - std::cout << "Building StructuredMatrix<>; calling buildMatrix( Matrix<> )\n"; + std::cout << "Building Matrix<>; calling buildMatrix( Matrix<> )\n"; return buildMatrix( *(this->_container), start, end ); } @@ -891,33 +920,33 @@ namespace grb { template < bool d > struct view_type< view::original, d > { - using type = StructuredMatrix< T, structures::Identity, Density::Dense, view::Original< self_type >, reference_dense >; + using type = Matrix< T, structures::Identity, Density::Dense, view::Original< self_type >, reference >; }; template < bool d > struct view_type< view::transpose, d > { - using type = StructuredMatrix< T, structures::Identity, Density::Dense, view::Transpose< self_type >, reference_dense >; + using type = Matrix< T, structures::Identity, Density::Dense, view::Transpose< self_type >, reference >; }; - StructuredMatrix( const size_t rows, const size_t cap = 0 ) : + Matrix( const size_t rows, const size_t cap = 0 ) : internal::MatrixContainer< T >( rows, rows, cap ) {} - }; // StructuredMatrix Identity, container + }; // Matrix Identity, container namespace structures { /** * @brief Checks if a structured matrix has structure \a Structure. * - * @tparam StructuredMatrixT The structured matrix type to be tested. - * @tparam Structure The structure type which should be implied by \a StructuredMatrixT::structure. + * @tparam MatrixT The structured matrix type to be tested. + * @tparam Structure The structure type which should be implied by \a MatrixT::structure. */ - template< typename StructuredMatrixT, typename Structure > + template< typename MatrixT, typename Structure > struct is_a { /** - * \a value is true iff \a Structure is implied by \a StructuredMatrixT::structure. + * \a value is true iff \a Structure is implied by \a MatrixT::structure. */ - static constexpr bool value = is_in< Structure, typename StructuredMatrixT::structure::inferred_structures >::value; + static constexpr bool value = is_in< Structure, typename MatrixT::structure::inferred_structures >::value; }; } // namespace structures @@ -951,10 +980,10 @@ namespace grb { */ template< typename T, typename Structure, enum Density density, typename View, enum Backend backend > - typename StructuredMatrix< T, Structure, density, View, backend >::template view_type< view::original >::type - get_view( StructuredMatrix< T, Structure, density, View, backend > & source ) { + typename Matrix< T, Structure, density, View, backend >::template view_type< view::original >::type + get_view( Matrix< T, Structure, density, View, backend > & source ) { - using source_strmat_t = StructuredMatrix< T, Structure, density, View, backend >; + using source_strmat_t = Matrix< T, Structure, density, View, backend >; using target_strmat_t = typename source_strmat_t::template view_type< view::original >::type; target_strmat_t target( source ); @@ -994,10 +1023,10 @@ namespace grb { template< enum view::Views target_view, typename T, typename Structure, enum Density density, typename View, enum Backend backend > - typename StructuredMatrix< T, Structure, density, View, backend >::template view_type< target_view >::type - get_view( StructuredMatrix< T, Structure, density, View, backend > &source ) { + typename Matrix< T, Structure, density, View, backend >::template view_type< target_view >::type + get_view( Matrix< T, Structure, density, View, backend > &source ) { - using source_strmat_t = StructuredMatrix< T, Structure, density, View, backend >; + using source_strmat_t = Matrix< T, Structure, density, View, backend >; using target_strmat_t = typename source_strmat_t::template view_type< target_view >::type; target_strmat_t target( source ); @@ -1007,7 +1036,7 @@ namespace grb { /** * - * @brief Generate an original view where the type is compliant with the source StructuredMatrix. + * @brief Generate an original view where the type is compliant with the source Matrix. * Version where a target structure is specified. It can only generate a valide type if the target * structure is the same as the source's * or a more specialized one that would preserve its static properties (e.g., symmetric reference @@ -1016,10 +1045,10 @@ namespace grb { * check can be performed in constant time. * * @tparam TargetStructure The target structure of the new view. It should verify - * grb::is_in . + * alp::is_in . * @tparam T The matrix's elements type * @tparam Structure The structure of the source and target matrix view - * @tparam density The type (i.e., \a grb::Density:Dense or \a grb::Density:Sparse) of storage scheme + * @tparam density The type (i.e., \a alp::Density:Dense or \a alp::Density:Sparse) of storage scheme * @tparam View The source's View type * @tparam backend The target backend * @@ -1041,14 +1070,14 @@ namespace grb { template< typename TargetStructure, typename T, typename Structure, enum Density density, typename View, enum Backend backend > - StructuredMatrix< T, TargetStructure, density, view::Original< StructuredMatrix< T, Structure, density, View, backend > >, backend > - get_view( StructuredMatrix< T, Structure, density, View, backend > &source ) { + Matrix< T, TargetStructure, density, view::Original< Matrix< T, Structure, density, View, backend > >, backend > + get_view( Matrix< T, Structure, density, View, backend > &source ) { static_assert( structures::is_in< Structure, typename TargetStructure::inferred_structures >::value, "Can only create a view when the target structure is compatible with the source." ); - using source_strmat_t = StructuredMatrix< T, Structure, density, View, backend >; - using target_strmat_t = StructuredMatrix< T, TargetStructure, density, view::Original< source_strmat_t >, backend >; + using source_strmat_t = Matrix< T, Structure, density, View, backend >; + using target_strmat_t = Matrix< T, TargetStructure, density, view::Original< source_strmat_t >, backend >; target_strmat_t target( source ); @@ -1064,8 +1093,8 @@ namespace grb { template< typename TargetStructure, typename T, typename Structure, enum Density density, typename View, enum Backend backend > - StructuredMatrix< T, TargetStructure, density, view::Original< StructuredMatrix< T, Structure, density, View, backend > >, backend > - get_view( StructuredMatrix< T, Structure, density, View, backend > &source, + alp::Matrix< T, TargetStructure, density, view::Original< alp::Matrix< T, Structure, density, View, backend > >, backend > + get_view( alp::Matrix< T, Structure, density, View, backend > &source, std::shared_ptr< imf::IMF > imf_r, std::shared_ptr< imf::IMF > imf_c ) { if( std::dynamic_pointer_cast< imf::Select >( imf_r ) || std::dynamic_pointer_cast< imf::Select >( imf_c ) ) { @@ -1076,8 +1105,8 @@ namespace grb { throw std::runtime_error("Cannot gather into specified TargetStructure from provided SourceStructure and Index Mapping Functions."); } - using source_strmat_t = StructuredMatrix< T, Structure, density, View, backend >; - using target_strmat_t = StructuredMatrix< T, TargetStructure, density, view::Original< source_strmat_t >, backend >; + using source_strmat_t = alp::Matrix< T, Structure, density, View, backend >; + using target_strmat_t = alp::Matrix< T, TargetStructure, density, view::Original< source_strmat_t >, backend >; target_strmat_t target( source, imf_r, imf_c ); @@ -1087,7 +1116,7 @@ namespace grb { /** * - * @brief Generate an original view where the type is compliant with the source StructuredMatrix. + * @brief Generate an original view where the type is compliant with the source Matrix. * Version where a range of rows and columns are selected to form a new view with specified target * structure. It can only generate a valide type if the target * structure is guaranteed to preserve the static properties of the source's structure. @@ -1095,7 +1124,7 @@ namespace grb { * are guaranteed only when each one of them incurs constant time work. * * @tparam TargetStructure The target structure of the new view. It should verify - * grb::is_in . + * alp::is_in . * @tparam T The matrix' elements type * @tparam Structure The structure of the source and target matrix view * @tparam density The type (i.e., sparse or dense) of storage scheme @@ -1122,8 +1151,8 @@ namespace grb { template< typename TargetStructure, typename T, typename Structure, enum Density density, typename View, enum Backend backend > - StructuredMatrix< T, TargetStructure, density, view::Original< StructuredMatrix< T, Structure, density, View, backend > >, backend > - get_view( StructuredMatrix< T, Structure, density, View, backend > &source, + Matrix< T, TargetStructure, density, view::Original< Matrix< T, Structure, density, View, backend > >, backend > + get_view( Matrix< T, Structure, density, View, backend > &source, const utils::range& rng_r, const utils::range& rng_c ) { auto imf_r = std::make_shared< imf::Strided >( rng_r.count(), nrows(source), rng_r.start, rng_r.stride ); @@ -1134,7 +1163,7 @@ namespace grb { /** * - * @brief Generate an original view where the type is compliant with the source StructuredMatrix. + * @brief Generate an original view where the type is compliant with the source Matrix. * Version where no target structure is specified (in this case the structure of the source type is assumed as target) * with row and column selection. * A structure preserving check as well as non-overlapping checks with existing views of \a source @@ -1166,8 +1195,8 @@ namespace grb { template< typename T, typename Structure, enum Density density, typename View, enum Backend backend > - StructuredMatrix< T, Structure, density, view::Original< StructuredMatrix< T, Structure, density, View, backend > >, backend > - get_view( StructuredMatrix< T, Structure, density, View, backend > &source, + Matrix< T, Structure, density, view::Original< Matrix< T, Structure, density, View, backend > >, backend > + get_view( Matrix< T, Structure, density, View, backend > &source, const utils::range& rng_r, const utils::range& rng_c ) { auto imf_r = std::make_shared< imf::Strided >( rng_r.count(), nrows(source), rng_r.start, rng_r.stride ); @@ -1179,7 +1208,7 @@ namespace grb { namespace internal { /** * - * @brief Generate an original view where the type is compliant with the source StructuredMatrix. + * @brief Generate an original view where the type is compliant with the source Matrix. * Version where a selection of rows and columns expressed as vectors of positions * form a new view with specified target structure. * @@ -1187,7 +1216,7 @@ namespace grb { * general vector selection. * * @tparam TargetStructure The target structure of the new view. It should verify - * grb::is_in . + * alp::is_in . * @tparam T The matrix' elements type * @tparam Structure The structure of the source and target matrix view * @tparam density The type (i.e., sparse or dense) of storage scheme @@ -1204,8 +1233,8 @@ namespace grb { template< typename TargetStructure, typename T, typename Structure, enum Density density, typename View, enum Backend backend > - StructuredMatrix< T, TargetStructure, density, view::Original< StructuredMatrix< T, Structure, density, View, backend > >, backend > - get_view( StructuredMatrix< T, Structure, density, View, backend > &source, + alp::Matrix< T, TargetStructure, density, view::Original< alp::Matrix< T, Structure, density, View, backend > >, backend > + get_view( alp::Matrix< T, Structure, density, View, backend > &source, const std::vector< size_t >& sel_r, const std::vector< size_t >& sel_c ) { auto imf_r = std::make_shared< imf::Select >( nrows(source), sel_r ); @@ -1217,18 +1246,18 @@ namespace grb { /** Returns a constant reference to an Identity matrix of the provided size */ template< typename T > - const StructuredMatrix< T, structures::Identity, Density::Dense, view::Original< void >, reference_dense > & + const Matrix< T, structures::Identity, Density::Dense, view::Original< void >, reference > & I( const size_t n ) { - using return_type = StructuredMatrix< T, structures::Identity, Density::Dense, view::Original< void >, reference_dense >; + using return_type = Matrix< T, structures::Identity, Density::Dense, view::Original< void >, reference >; return_type * ret = new return_type( n ); return * ret; } /** Returns a constant reference to a Zero matrix of the provided size */ template< typename T > - const StructuredMatrix< T, structures::Zero, Density::Dense, view::Original< void >, reference_dense > & + const Matrix< T, structures::Zero, Density::Dense, view::Original< void >, reference > & Zero( const size_t rows, const size_t cols ) { - using return_type = StructuredMatrix< T, structures::Zero, Density::Dense, view::Original< void >, reference_dense >; + using return_type = Matrix< T, structures::Zero, Density::Dense, view::Original< void >, reference >; return_type * ret = new return_type( rows, cols ); return * ret; } @@ -1238,14 +1267,14 @@ namespace grb { * s = sin( theta ) and c = cos( theta ) */ template< typename T > - const StructuredMatrix< T, structures::Square, Density::Dense, view::Original< void >, reference_dense > & + const Matrix< T, structures::Square, Density::Dense, view::Original< void >, reference > & Givens( const size_t n, const size_t i, const size_t j, const T s, const T c ) { - using return_type = const StructuredMatrix< T, structures::Square, Density::Dense, view::Original< void >, reference_dense >; + using return_type = const Matrix< T, structures::Square, Density::Dense, view::Original< void >, reference >; return_type * ret = new return_type( n ); // TODO: initialize matrix values according to the provided parameters return * ret; } -} // namespace grb +} // namespace alp -#endif // end ``_H_GRB_DENSEREF_MATRIX'' +#endif // end ``_H_ALP_REFERENCE_MATRIX'' diff --git a/include/alp/reference/pinnedvector.hpp b/include/alp/reference/pinnedvector.hpp index 8636cf52d..4ba35fddc 100644 --- a/include/alp/reference/pinnedvector.hpp +++ b/include/alp/reference/pinnedvector.hpp @@ -20,12 +20,12 @@ * @date 14th of January 2022 */ -#ifndef _H_GRB_DENSEREF_PINNEDVECTOR -#define _H_GRB_DENSEREF_PINNEDVECTOR +#ifndef _H_ALP_REFERENCE_PINNEDVECTOR +#define _H_ALP_REFERENCE_PINNEDVECTOR -namespace grb { +namespace alp { -} // end namespace ``grb'' +} // end namespace ``alp'' -#endif // end ``_H_GRB_DENSEREF_PINNEDVECTOR'' +#endif // end ``_H_ALP_REFERENCE_PINNEDVECTOR'' diff --git a/include/alp/reference/properties.hpp b/include/alp/reference/properties.hpp index 03ae2df95..9fb982714 100644 --- a/include/alp/reference/properties.hpp +++ b/include/alp/reference/properties.hpp @@ -20,22 +20,22 @@ * @date 14th of January 2022 */ -#ifndef _H_GRB_DENSEREF_PROPERTIES -#define _H_GRB_DENSEREF_PROPERTIES +#ifndef _H_ALP_REFERENCE_PROPERTIES +#define _H_ALP_REFERENCE_PROPERTIES -#include +#include -namespace grb { +namespace alp { /** \internal No implementation notes. */ template<> - class Properties< reference_dense > { + class Properties< reference > { public: /** No implementation notes. */ constexpr static bool writableCaptured = true; }; -} // namespace grb +} // namespace alp -#endif // end `_H_GRB_DENSEREF_PROPERTIES'' +#endif // end `_H_ALP_REFERENCE_PROPERTIES'' diff --git a/include/alp/reference/scalar.hpp b/include/alp/reference/scalar.hpp index b073f89bc..204d7893d 100644 --- a/include/alp/reference/scalar.hpp +++ b/include/alp/reference/scalar.hpp @@ -15,8 +15,8 @@ * limitations under the License. */ -#ifndef _H_GRB_DENSEREF_SCALAR -#define _H_GRB_DENSEREF_SCALAR +#ifndef _H_ALP_REFERENCE_SCALAR +#define _H_ALP_REFERENCE_SCALAR #include @@ -24,24 +24,24 @@ #include -#include -#include +#include +#include -#include -#include -#include +#include +#include +#include -#include +#include -namespace grb { +namespace alp { namespace internal { template< typename T, typename Structure > - bool getInitialized( Scalar< T, Structure, reference_dense > & ) noexcept; + bool getInitialized( Scalar< T, Structure, reference > & ) noexcept; template< typename T, typename Structure > - void setInitialized( Scalar< T, Structure, reference_dense > &, bool ) noexcept; - } // end namespace ``grb::internal'' + void setInitialized( Scalar< T, Structure, reference > &, bool ) noexcept; + } // end namespace ``alp::internal'' /** * \brief An ALP scalar. @@ -52,16 +52,16 @@ namespace grb { * be a ALP type. * @tparam Structure One of the structures. * - * \warning Creating a grb::Scalar of other ALP types is + * \warning Creating a alp::Scalar of other ALP types is * not allowed. * Passing a ALP type as template parameter will lead to * undefined behaviour. * */ template< typename T, typename Structure > - class Scalar< T, Structure, reference_dense > { + class Scalar< T, Structure, reference > { private: - typedef Scalar< T, Structure, reference_dense > self_type; + typedef Scalar< T, Structure, reference > self_type; friend bool internal::getInitialized<>( self_type & ) noexcept; @@ -162,7 +162,7 @@ namespace grb { Scalar( const Scalar &other ) { // const RC rc = set( *this, other ); // note: initialized will be set as part of this call // if( rc != SUCCESS ) { - // throw std::runtime_error( "grb::Scalar< T, Structure, Density::Dense, View::Original< void >, reference_dense > (copy constructor): error during call to grb::set (" + toString( rc ) + ")" ); + // throw std::runtime_error( "alp::Scalar< T, Structure, Density::Dense, View::Original< void >, reference > (copy constructor): error during call to alp::set (" + toString( rc ) + ")" ); // } } @@ -199,26 +199,26 @@ namespace grb { }; // class Scalar with physical container - /** Identifies any reference_dense scalar as an ALP scalar. */ + /** Identifies any reference scalar as an ALP scalar. */ template< typename T, typename Structure > - struct is_container< Scalar< T, Structure, reference_dense > > { + struct is_container< Scalar< T, Structure, reference > > { /** A scalar is an ALP object. */ static const constexpr bool value = true; }; namespace internal { template< typename T, typename Structure > - bool getInitialized( Scalar< T, Structure, reference_dense > &s ) noexcept { + bool getInitialized( Scalar< T, Structure, reference > &s ) noexcept { return s.initialized; } template< typename T, typename Structure > - void setInitialized( Scalar< T, Structure, reference_dense > &s, bool initialized ) noexcept { + void setInitialized( Scalar< T, Structure, reference > &s, bool initialized ) noexcept { s.initialized = s; } - } // end namespace ``grb::internal'' + } // end namespace ``alp::internal'' -} // end namespace ``grb'' +} // end namespace ``alp'' -#endif // end ``_H_GRB_DENSEREF_SCALAR'' +#endif // end ``_H_ALP_REFERENCE_SCALAR'' diff --git a/include/alp/reference/spmd.hpp b/include/alp/reference/spmd.hpp index dacb5fae1..3bae30777 100644 --- a/include/alp/reference/spmd.hpp +++ b/include/alp/reference/spmd.hpp @@ -20,18 +20,18 @@ * @date 14th of January, 2022 */ -#ifndef _H_GRB_DENSEREF_SPMD -#define _H_GRB_DENSEREF_SPMD +#ifndef _H_ALP_REFERENCE_SPMD +#define _H_ALP_REFERENCE_SPMD #include //size_t -#include +#include -namespace grb { +namespace alp { /** \internal This is a single-process back-end. */ template<> - class spmd< reference_dense > { + class spmd< reference > { public: @@ -56,15 +56,15 @@ namespace grb { /** * In this backend, corresponds to a no-op. * - * @return grb::SUCCESS. + * @return alp::SUCCESS. */ static RC barrier() noexcept { return SUCCESS; } - }; // end class ``spmd'' reference_dense implementation + }; // end class ``spmd'' reference implementation -} // namespace grb +} // namespace alp -#endif // end _H_GRB_DENSEREF_SPMD +#endif // end _H_ALP_REFERENCE_SPMD diff --git a/include/alp/reference/vector.hpp b/include/alp/reference/vector.hpp index 18469fdff..d8cdf1ff2 100644 --- a/include/alp/reference/vector.hpp +++ b/include/alp/reference/vector.hpp @@ -20,8 +20,8 @@ * @date 14th of January 2022 */ -#ifndef _H_GRB_DENSEREF_VECTOR -#define _H_GRB_DENSEREF_VECTOR +#ifndef _H_ALP_REFERENCE_VECTOR +#define _H_ALP_REFERENCE_VECTOR #include @@ -29,283 +29,282 @@ #include -#include -#include -#include +#include +#include -// #include -// #include -// #include +// #include +// #include +// #include -#include -#include -#include -#include +#include +#include +#include +#include -#include +#include -namespace grb { +namespace alp { namespace internal { - template< typename T, typename C > - T * getRaw( Vector< T, reference_dense, C > & ) noexcept; - - template< typename T, typename C > - const T * getRaw( const Vector< T, reference_dense, C > & ) noexcept; - - template< typename T, typename C > - size_t getLength( const Vector< T, reference_dense, C > & ) noexcept; + template< typename T > + T * getRaw( Vector< T, reference > & ) noexcept; + + template< typename T > + const T * getRaw( const Vector< T, reference > & ) noexcept; + + template< typename T > + size_t getLength( const Vector< T, reference > & ) noexcept; + + template< typename T > + const bool & getInitialized( const Vector< T, reference > & v ) noexcept; + + template< typename T > + void setInitialized( Vector< T, reference > & v, bool initialized ) noexcept; + + + /** + * The reference implementation of the ALP/Dense vector. + * + * @tparam T The type of an element of this vector. \a T shall not be a + * GraphBLAS type. + * + * \warning Creating a alp::Vector of other GraphBLAS types is + * not allowed. + * Passing a GraphBLAS type as template parameter will lead to + * undefined behaviour. + */ + template< typename T > + class Vector< T, reference > { + + friend T * internal::getRaw< T >( Vector< T, reference > & ) noexcept; + friend const T * internal::getRaw< T >( const Vector< T, reference > & ) noexcept; + friend size_t internal::getLength< T >( const Vector< T, reference > & ) noexcept; + + /* ******************** + IO friends + ******************** */ + + friend const bool & internal::getInitialized< T >( const Vector< T, reference > & ) noexcept; + + friend void internal::setInitialized< T >( Vector< T, reference > & , bool ) noexcept; + + private: + + /** The length of the vector. */ + size_t n; + + /** The container capacity (in elements). + * + * \warning \a cap is present for compatibility with other vector specializations. + * In reference backend, the number of non-zeros (i.e. capacity) + * depends on the used storage scheme. Therefore, this parameter is + * ignored when provided by user. + */ + size_t cap; + + /** The vector data. */ + T *__restrict__ data; + + /** Whether the container presently is uninitialized. */ + bool initialized; + + + public: + + /** Exposes the element type. */ + typedef T value_type; + + /** The return type of #operator[](). */ + typedef T& lambda_reference; + + /** + * The main ALP/Dense vector constructor. + * + * The constructed object will be uninitalised after successful construction. + * + * + * @param length The number of elements in the new vector. + * + * @return SUCCESS This function never fails. + * + * \parblock + * \par Performance semantics. + * -# This constructor entails \f$ \Theta(1) \f$ amount of work. + * -# This constructor may allocate \f$ \Theta( length ) \f$ bytes + * of dynamic memory. + * -# This constructor will use \f$ \Theta(1) \f$ extra bytes of + * memory beyond that at constructor entry. + * -# This constructor incurs \f$ \Theta(1) \f$ data movement. + * -# This constructor \em may make system calls. + * \endparblock + * + * \warning Avoid the use of this constructor within performance critical + * code sections. + */ + Vector( const size_t length, const size_t cap = 0 ) : n( length ), cap( std::max( length, cap ) ), initialized( false ) { + // TODO: Implement allocation properly + if( n > 0) { + data = new (std::nothrow) T[ n ]; + } else { + data = nullptr; + } + + if ( n > 0 && data == nullptr ) { + throw std::runtime_error( "Could not allocate memory during alp::Vector construction." ); + } + } - template< typename T, typename C > - const bool & getInitialized( const Vector< T, reference_dense, C > & v ) noexcept; + /** + * Copy constructor. + * + * @param other The vector to copy. The initialization state of the copy + * reflects the state of \a other. + * + * \parblock + * \par Performance semantics. + * Allocates the same capacity as the \a other vector, even if the + * actual number of elements contained in \a other is less. + * -# This constructor entails \f$ \Theta(1) \f$ amount of work. + * -# This constructor allocates \f$ \Theta(\max{mn, cap} ) \f$ bytes + * of dynamic memory. + * -# This constructor incurs \f$ \Theta(mn) \f$ of data + * movement. + * -# This constructor \em may make system calls. + * \endparblock + * + * \warning Avoid the use of this constructor within performance critical + * code sections. + */ + Vector( const Vector< T, reference > &other ) : Vector( other.n, other.cap ) { + initialized = other.initialized; + // const RC rc = set( *this, other ); // note: initialized will be set as part of this call + // if( rc != SUCCESS ) { + // throw std::runtime_error( "alp::Vector< T, reference > (copy constructor): error during call to alp::set (" + toString( rc ) + ")" ); + // } + } - template< typename T, typename C > - void setInitialized( Vector< T, reference_dense, C > & v, bool initialized ) noexcept; + /** + * Move constructor. The new vector equal the given + * vector. Invalidates the use of the input vector. + * + * @param[in] other The GraphBLAS vector to move to this new instance. + * + * \parblock + * \par Performance semantics. + * -# This constructor entails \f$ \Theta(1) \f$ amount of work. + * -# This constructor will not allocate any new dynamic memory. + * -# This constructor will use \f$ \Theta(1) \f$ extra bytes of + * memory beyond that at constructor entry. + * -# This constructor will move \f$ \Theta(1) \f$ bytes of data. + * \endparblock + */ + Vector( Vector< T, reference > &&other ) : n( other.n ), cap( other.cap ), data( other.data ) { + other.n = 0; + other.cap = 0; + other.data = 0; + // data_deleter = std::move( other.data_deleter ); + // initialized = other.initialized; other.initialized = false; + } - } // end namespace ``grb::internal'' + /** + * Vector destructor. + * + * \parblock + * \par Performance semantics. + * -# This destructor entails \f$ \Theta(1) \f$ amount of work. + * -# This destructor will not perform any memory allocations. + * -# This destructor will use \f$ \mathcal{O}(1) \f$ extra bytes of + * memory beyond that at constructor entry. + * -# This destructor will move \f$ \Theta(1) \f$ bytes of data. + * -# This destructor makes system calls. + * \endparblock + * + * \warning Avoid calling destructors from within performance critical + * code sections. + */ + ~Vector() { + if( data != nullptr ) { + delete [] data; + } + } - /** - * The reference implementation of the ALP/Dense vector. - * - * @tparam T The type of an element of this vector. \a T shall not be a - * GraphBLAS type. - * - * \warning Creating a grb::Vector of other GraphBLAS types is - * not allowed. - * Passing a GraphBLAS type as template parameter will lead to - * undefined behaviour. - */ - template< typename T, typename C > - class Vector< T, reference_dense, C > { - - friend T * internal::getRaw< T >( Vector< T, reference_dense, C > & ) noexcept; - friend const T * internal::getRaw< T >( const Vector< T, reference_dense, C > & ) noexcept; - friend size_t internal::getLength< T >( const Vector< T, reference_dense, C > & ) noexcept; - - /* ******************** - IO friends - ******************** */ - - friend const bool & internal::getInitialized< T >( const Vector< T, reference_dense, C > & ) noexcept; - - friend void internal::setInitialized< T >( Vector< T, reference_dense, C > & , bool ) noexcept; - - private: - - /** The length of the vector. */ - size_t n; - - /** The container capacity (in elements). - * - * \warning \a cap is present for compatibility with other vector specializations. - * In reference_dense backend, the number of non-zeros (i.e. capacity) - * depends on the used storage scheme. Therefore, this parameter is - * ignored when provided by user. - */ - size_t cap; - - /** The vector data. */ - T *__restrict__ data; - - /** Whether the container presently is uninitialized. */ - bool initialized; - - - public: - - /** Exposes the element type. */ - typedef T value_type; - - /** The return type of #operator[](). */ - typedef T& lambda_reference; - - /** - * The main ALP/Dense vector constructor. - * - * The constructed object will be uninitalised after successful construction. - * - * - * @param length The number of elements in the new vector. - * - * @return SUCCESS This function never fails. - * - * \parblock - * \par Performance semantics. - * -# This constructor entails \f$ \Theta(1) \f$ amount of work. - * -# This constructor may allocate \f$ \Theta( length ) \f$ bytes - * of dynamic memory. - * -# This constructor will use \f$ \Theta(1) \f$ extra bytes of - * memory beyond that at constructor entry. - * -# This constructor incurs \f$ \Theta(1) \f$ data movement. - * -# This constructor \em may make system calls. - * \endparblock - * - * \warning Avoid the use of this constructor within performance critical - * code sections. - */ - Vector( const size_t length, const size_t cap = 0 ) : n( length ), cap( std::max( length, cap ) ), initialized( false ) { - // TODO: Implement allocation properly - if( n > 0) { - data = new (std::nothrow) T[ n ]; - } else { - data = nullptr; + /** \internal No implementation notes. */ + lambda_reference operator[]( const size_t i ) noexcept { + assert( i < n ); + assert( initialized ); + return data[ i ]; } - if ( n > 0 && data == nullptr ) { - throw std::runtime_error( "Could not allocate memory during grb::Vector construction." ); + /** \internal No implementation notes. */ + const lambda_reference operator[]( const size_t i ) const noexcept { + assert( i < n ); + assert( initialized ); + return data[ i ]; } - } - /** - * Copy constructor. - * - * @param other The vector to copy. The initialization state of the copy - * reflects the state of \a other. - * - * \parblock - * \par Performance semantics. - * Allocates the same capacity as the \a other vector, even if the - * actual number of elements contained in \a other is less. - * -# This constructor entails \f$ \Theta(1) \f$ amount of work. - * -# This constructor allocates \f$ \Theta(\max{mn, cap} ) \f$ bytes - * of dynamic memory. - * -# This constructor incurs \f$ \Theta(mn) \f$ of data - * movement. - * -# This constructor \em may make system calls. - * \endparblock - * - * \warning Avoid the use of this constructor within performance critical - * code sections. - */ - Vector( const Vector< T, reference_dense, void > &other ) : Vector( other.n, other.cap ) { - initialized = other.initialized; - // const RC rc = set( *this, other ); // note: initialized will be set as part of this call - // if( rc != SUCCESS ) { - // throw std::runtime_error( "grb::Vector< T, reference_dense > (copy constructor): error during call to grb::set (" + toString( rc ) + ")" ); + // /** \internal Relies on #internal::ConstDenserefVectorIterator. */ + // const_iterator cbegin() const noexcept { + // return initialized ? + // const_iterator( data, n, false ) : + // const_iterator( nullptr, 0, false ); // } - } - /** - * Move constructor. The new vector equal the given - * vector. Invalidates the use of the input vector. - * - * @param[in] other The GraphBLAS vector to move to this new instance. - * - * \parblock - * \par Performance semantics. - * -# This constructor entails \f$ \Theta(1) \f$ amount of work. - * -# This constructor will not allocate any new dynamic memory. - * -# This constructor will use \f$ \Theta(1) \f$ extra bytes of - * memory beyond that at constructor entry. - * -# This constructor will move \f$ \Theta(1) \f$ bytes of data. - * \endparblock - */ - Vector( Vector< T, reference_dense, void > &&other ) : n( other.n ), cap( other.cap ), data( other.data ) { - other.n = 0; - other.cap = 0; - other.data = 0; - // data_deleter = std::move( other.data_deleter ); - // initialized = other.initialized; other.initialized = false; - } - - /** - * Vector destructor. - * - * \parblock - * \par Performance semantics. - * -# This destructor entails \f$ \Theta(1) \f$ amount of work. - * -# This destructor will not perform any memory allocations. - * -# This destructor will use \f$ \mathcal{O}(1) \f$ extra bytes of - * memory beyond that at constructor entry. - * -# This destructor will move \f$ \Theta(1) \f$ bytes of data. - * -# This destructor makes system calls. - * \endparblock - * - * \warning Avoid calling destructors from within performance critical - * code sections. - */ - ~Vector() { - if( data != nullptr ) { - delete [] data; - } - } - - /** \internal No implementation notes. */ - lambda_reference operator[]( const size_t i ) noexcept { - assert( i < n ); - assert( initialized ); - return data[ i ]; - } + // /** \internal Relies on #internal::ConstDenserefVectorIterator. */ + // const_iterator begin() const noexcept { + // return cbegin(); + // } - /** \internal No implementation notes. */ - const lambda_reference operator[]( const size_t i ) const noexcept { - assert( i < n ); - assert( initialized ); - return data[ i ]; - } + // /** \internal Relies on #internal::ConstDenserefVectorIterator. */ + // const_iterator cend() const noexcept { + // return initialized ? + // const_iterator( data, n, true ) : + // const_iterator( nullptr, 0, true ); + // } - // /** \internal Relies on #internal::ConstDenserefVectorIterator. */ - // const_iterator cbegin() const noexcept { - // return initialized ? - // const_iterator( data, n, false ) : - // const_iterator( nullptr, 0, false ); - // } - - // /** \internal Relies on #internal::ConstDenserefVectorIterator. */ - // const_iterator begin() const noexcept { - // return cbegin(); - // } - - // /** \internal Relies on #internal::ConstDenserefVectorIterator. */ - // const_iterator cend() const noexcept { - // return initialized ? - // const_iterator( data, n, true ) : - // const_iterator( nullptr, 0, true ); - // } - - // /** \internal Relies on #internal::ConstDenserefVectorIterator. */ - // const_iterator end() const noexcept { - // return cend(); - // } + // /** \internal Relies on #internal::ConstDenserefVectorIterator. */ + // const_iterator end() const noexcept { + // return cend(); + // } - }; + }; + } // end namespace ``alp::internal'' - /** Identifies any reference_dense vector as an ALP vector. */ - template< typename T, typename C > - struct is_container< Vector< T, reference_dense, C > > { + /** Identifies any reference vector as an ALP vector. */ + template< typename T > + struct is_container< internal::Vector< T, reference > > { /** A reference_vector is an ALP object. */ static const constexpr bool value = true; }; namespace internal { - template< typename T, typename C > - T * getRaw( Vector< T, reference_dense, C > &v ) noexcept { + template< typename T > + T * getRaw( Vector< T, reference > &v ) noexcept { return v.data; } - template< typename T, typename C > - const T * getRaw( Vector< T, reference_dense, C > &v ) noexcept { + template< typename T > + const T * getRaw( Vector< T, reference > &v ) noexcept { return v.data; } - template< typename T, typename C > - size_t getLength( const Vector< T, reference_dense, C > &v ) noexcept { + template< typename T > + size_t getLength( const Vector< T, reference > &v ) noexcept { return v.n; } - template< typename T, typename C > - const bool & getInitialized( const Vector< T, reference_dense, C > & v ) noexcept { + template< typename T > + const bool & getInitialized( const Vector< T, reference > & v ) noexcept { return v.initialized; } - template< typename T, typename C > - void setInitialized( Vector< T, reference_dense, C > & v, bool initialized ) noexcept { + template< typename T > + void setInitialized( Vector< T, reference > & v, bool initialized ) noexcept { v.initialized = initialized; } - } // end namespace ``grb::internal'' + } // end namespace ``alp::internal'' @@ -314,21 +313,21 @@ namespace grb { */ template< typename T, typename Structure, typename View > - size_t getLength( const VectorView< T, Structure, Density::Dense, View, reference_dense > &v ) noexcept { + size_t getLength( const Vector< T, Structure, Density::Dense, View, reference > &v ) noexcept { return v._length(); } namespace internal { template< typename T, typename Structure, typename View > - bool getInitialized( VectorView< T, Structure, Density::Dense, View, reference_dense > & v ) noexcept { + bool getInitialized( alp::Vector< T, Structure, Density::Dense, View, reference > & v ) noexcept { return getInitialized( v ); } template< typename T, typename Structure, typename View > - void setInitialized( VectorView< T, Structure, Density::Dense, View, reference_dense > & v, bool initialized ) noexcept { + void setInitialized( alp::Vector< T, Structure, Density::Dense, View, reference > & v, bool initialized ) noexcept { setInitialized( v, initialized ); } - } // end namespace ``grb::internal'' + } // end namespace ``alp::internal'' /** * \brief An ALP vector view. @@ -339,12 +338,12 @@ namespace grb { * express implementation-oblivious concepts such as \em views on the vector. * The logical layout of a vector view maps to a physical counterpart via * a storage scheme which typically depends on the selected backend. - * grb::Vector may be used as an interface to such a physical layout. + * alp::Vector may be used as an interface to such a physical layout. * * Views can be used to create logical \em perspectives on top of a container. * For example, one may decide to refer to the part of the vector or * to reference a diagonal of a matrix as a vector. - * See specialization \a VectorView< T, Structure, Density::Dense, view::Diagonal< StructuredMatrixT >, reference_dense > + * See specialization \a Vector< T, Structure, Density::Dense, view::Diagonal< MatrixT >, reference > * as an example of such usage. * * Vector View defined as views on other vectors do not instantiate a @@ -352,30 +351,30 @@ namespace grb { * * @tparam T type. * @tparam Structure Structure introduced to match the template - * parameter list of \a StructuredMatrix + * parameter list of \a Matrix * @tparam View One of the vector views. * All static views except for \a view::Original (via * \a view::Original cannot instantiate a new container * and only allow to refer to a previously defined - * \a VectorView. + * \a Vector. * The \a View parameter should not be used directly * by the user but can be set using specific member types - * appropriately defined by each VectorView and + * appropriately defined by each Vector and * accessible via functions. * */ template< typename T, typename Structure, typename View > - class VectorView< T, Structure, Density::Dense, View, reference_dense > { }; + class Vector< T, Structure, Density::Dense, View, reference > { }; /** * Original View over a vector container. */ template< typename T, typename Structure > - class VectorView< T, Structure, Density::Dense, view::Original< void >, reference_dense > { + class Vector< T, Structure, Density::Dense, view::Original< void >, reference > { private: - using self_type = VectorView< T, Structure, Density::Dense, view::Original< void >, reference_dense >; + using self_type = Vector< T, Structure, Density::Dense, view::Original< void >, reference >; /********************* Storage info friends @@ -384,7 +383,7 @@ namespace grb { friend size_t getLength<>( const self_type & ) noexcept; // Physical layout - std::unique_ptr< Vector< T, reference_dense, internal::DefaultCoordinates > > v; + std::unique_ptr< internal::Vector< T, reference > > v; std::shared_ptr imf; @@ -407,11 +406,11 @@ namespace grb { template < bool d > struct view_type< view::original, d > { - using type = VectorView< T, Structure, Density::Dense, view::Original< self_type >, reference_dense >; + using type = Vector< T, Structure, Density::Dense, view::Original< self_type >, reference >; }; - VectorView( const size_t length, const size_t cap = 0 ) : - v( std::make_unique< Vector< T, reference_dense, internal::DefaultCoordinates > >( length, cap ) ), + Vector( const size_t length, const size_t cap = 0 ) : + v( std::make_unique< internal::Vector< T, reference > >( length, cap ) ), imf( std::make_shared< imf::Id >( length ) ) {} /** \internal No implementation notes. */ @@ -428,25 +427,25 @@ namespace grb { // TODO implement; } - }; // class VectorView with physical container + }; // class Vector with physical container - /** Identifies any reference_dense vector as an ALP vector. */ + /** Identifies any reference vector as an ALP vector. */ template< typename T, typename Structure, typename View > - struct is_container< VectorView< T, Structure, Density::Dense, View, reference_dense > > { + struct is_container< Vector< T, Structure, Density::Dense, View, reference > > { /** A reference_vector is an ALP object. */ static const constexpr bool value = true; }; /** - * Vector view of a vector only via \a view::Original of another VectorView. + * Vector view of a vector only via \a view::Original of another Vector. */ - template< typename T, typename Structure, typename VectorViewT > - class VectorView< T, Structure, Density::Dense, view::Original< VectorViewT >, reference_dense > { + template< typename T, typename Structure, typename VectorT > + class Vector< T, Structure, Density::Dense, view::Original< VectorT >, reference > { private: - using self_type = VectorView< T, Structure, Density::Dense, view::Original< VectorViewT >, reference_dense >; - using target_type = VectorViewT; + using self_type = Vector< T, Structure, Density::Dense, view::Original< VectorT >, reference >; + using target_type = VectorT; /********************* Storage info friends @@ -454,7 +453,7 @@ namespace grb { friend size_t getLength<>( const self_type & ) noexcept; - /** Reference to VectorView object upon which this view is applied */ + /** Reference to Vector object upon which this view is applied */ target_type & ref; /** Index-mapping function. @see IMF */ @@ -477,11 +476,11 @@ namespace grb { template < bool d > struct view_type< view::original, d > { - using type = VectorView< T, Structure, Density::Dense, view::Original< self_type >, reference_dense >; + using type = Vector< T, Structure, Density::Dense, view::Original< self_type >, reference >; }; /** Constructor for creating a view over a given target vector */ - VectorView( target_type & vec_view ) : ref( vec_view ), imf( nullptr ) { + Vector( target_type & vec_view ) : ref( vec_view ), imf( nullptr ) { imf = std::make_shared< imf::Id >( getLength( ref ) ); @@ -489,9 +488,9 @@ namespace grb { /** Constructor for creating a view over a given target vector and * applying the given index mapping function */ - VectorView( target_type & vec_view, std::shared_ptr< imf::IMF > imf ) : ref( vec_view ), imf( imf ) { + Vector( target_type & vec_view, std::shared_ptr< imf::IMF > imf ) : ref( vec_view ), imf( imf ) { if( getLength( vec_view ) != imf->N ) { - throw std::length_error( "VectorView(vec_view, * imf): IMF range differs from target's vector length." ); + throw std::length_error( "Vector(vec_view, * imf): IMF range differs from target's vector length." ); } } @@ -509,21 +508,21 @@ namespace grb { // TODO implement; } - }; // Original VectorView + }; // Original Vector /** * Diagonal Vector View of a structured matrix. */ - template< typename T, typename Structure, typename StructuredMatrixT > - class VectorView< T, Structure, Density::Dense, view::Diagonal< StructuredMatrixT >, reference_dense > { + template< typename T, typename Structure, typename MatrixT > + class Vector< T, Structure, Density::Dense, view::Diagonal< MatrixT >, reference > { private: - /** Exposes the own type and the type of the VectorView object over + /** Exposes the own type and the type of the Vector object over * which this view is created. */ - using self_type = VectorView< T, Structure, Density::Dense, view::Diagonal< StructuredMatrixT >, reference_dense >; - using target_type = StructuredMatrixT; + using self_type = Vector< T, Structure, Density::Dense, view::Diagonal< MatrixT >, reference >; + using target_type = MatrixT; /********************* Storage info friends @@ -531,7 +530,7 @@ namespace grb { friend size_t getLength<>( const self_type & ) noexcept; - /** Reference to VectorView object upon which this view is applied */ + /** Reference to Vector object upon which this view is applied */ target_type & ref; /** @see IMF */ @@ -554,10 +553,10 @@ namespace grb { template < bool d > struct view_type< view::original, d > { - using type = VectorView< T, Structure, Density::Dense, view::Original< self_type >, reference_dense >; + using type = Vector< T, Structure, Density::Dense, view::Original< self_type >, reference >; }; - VectorView( target_type & struct_mat ) : ref( struct_mat ), imf( nullptr ) { + Vector( target_type & struct_mat ) : ref( struct_mat ), imf( nullptr ) { size_t _length = view::Diagonal< target_type >::getLength( dims( ref ) ); imf = std::make_shared< imf::Id >( _length ); @@ -581,7 +580,7 @@ namespace grb { }; // Diagonal Vector view /** - * @brief Generate an original view of the input VectorView. The function guarantees + * @brief Generate an original view of the input Vector. The function guarantees * the created view is non-overlapping with other existing views only when the * check can be performed in constant time. * @@ -590,9 +589,9 @@ namespace grb { * @tparam View The source's View type * @tparam backend The target backend * - * @param[in] source The VectorView object over which the view is created. + * @param[in] source The Vector object over which the view is created. * - * @returns A new vector VectorView object. + * @returns A new vector Vector object. * * \parblock * \par Performance semantics. @@ -608,10 +607,10 @@ namespace grb { template< typename T, typename Structure, enum Density density, typename View, enum Backend backend > - typename VectorView< T, Structure, density, View, backend >::template view_type< view::original >::type - get_view( VectorView< T, Structure, density, View, backend > & source ) { + typename Vector< T, Structure, density, View, backend >::template view_type< view::original >::type + get_view( Vector< T, Structure, density, View, backend > & source ) { - using source_vec_t = VectorView< T, Structure, density, View, backend >; + using source_vec_t = Vector< T, Structure, density, View, backend >; using target_vec_t = typename source_vec_t::template view_type< view::original >::type; target_vec_t vec_view( source ); @@ -624,10 +623,10 @@ namespace grb { * The function guarantees the created view is non-overlapping with other existing views only when the * check can be performed in constant time. * - * @param[in] source The VectorView object over which the view is created. + * @param[in] source The Vector object over which the view is created. * @param[in] rng A valid range of elements * - * @returns A VectorView object. + * @returns A Vector object. * * \parblock * \par Performance semantics. @@ -641,16 +640,16 @@ namespace grb { * */ template< typename T, typename Structure, enum Density density, typename View, enum Backend backend > - typename VectorView< T, Structure, density, View, backend >::template view_type< view::original >::type - get_view( VectorView< T, Structure, density, View, backend > &source, const utils::range& rng ) { + typename Vector< T, Structure, density, View, backend >::template view_type< view::original >::type + get_view( Vector< T, Structure, density, View, backend > &source, const utils::range& rng ) { auto imf_v = std::make_shared< imf::Strided >( rng.count(), getLength( source ), rng.start, rng.stride ); - typename VectorView< T, Structure, density, View, backend >::template view_type< view::original >::type vec_view( source, imf_v ); + typename Vector< T, Structure, density, View, backend >::template view_type< view::original >::type vec_view( source, imf_v ); return vec_view; } -} // end namespace ``grb'' +} // end namespace ``alp'' -#endif // end ``_H_GRB_DENSEREF_VECTOR'' +#endif // end ``_H_ALP_REFERENCE_VECTOR'' diff --git a/include/alp/reference/vectoriterator.hpp b/include/alp/reference/vectoriterator.hpp index 868290a87..121e86ae7 100644 --- a/include/alp/reference/vectoriterator.hpp +++ b/include/alp/reference/vectoriterator.hpp @@ -20,25 +20,25 @@ * @date 17th of January, 2022 */ -#ifndef _H_GRB_DENSEREF_VECTOR_ITERATOR -#define _H_GRB_DENSEREF_VECTOR_ITERATOR +#ifndef _H_ALP_REFERENCE_VECTOR_ITERATOR +#define _H_ALP_REFERENCE_VECTOR_ITERATOR -#include +#include #include -namespace grb { +namespace alp { namespace internal { - template< typename T, Backend spmd_backend = reference_dense > + template< typename T, Backend spmd_backend = reference > class ConstDenserefVectorIterator : public std::iterator< std::random_access_iterator_tag, std::pair< const size_t, const T >, size_t > { - friend class Vector< T, reference_dense, void >; + friend class Vector< T, reference, void >; private: @@ -220,9 +220,9 @@ namespace grb { }; - } // end namespace ``grb::internal'' + } // end namespace ``alp::internal'' -} // end namespace ``grb'' +} // end namespace ``alp'' -#endif // end ``_H_GRB_DENSEREF_VECTOR_ITERATOR'' +#endif // end ``_H_ALP_REFERENCE_VECTOR_ITERATOR'' diff --git a/include/alp/scalar.hpp b/include/alp/scalar.hpp index ac2c5cb44..482c7907c 100644 --- a/include/alp/scalar.hpp +++ b/include/alp/scalar.hpp @@ -15,20 +15,20 @@ * limitations under the License. */ -#ifndef _H_GRB_SCALAR -#define _H_GRB_SCALAR +#ifndef _H_ALP_SCALAR +#define _H_ALP_SCALAR #include "base/config.hpp" #include "base/scalar.hpp" // now include all specialisations contained in the backend directories: -#ifdef _GRB_WITH_DENSEREF - #include +#ifdef _ALP_WITH_REFERENCE + #include #endif // specify default only if requested during compilation -#ifdef _GRB_BACKEND -namespace grb { +#ifdef _ALP_BACKEND +namespace alp { template< typename T, typename Structure = structures::General, enum Backend backend = config::default_backend > class Scalar; @@ -36,5 +36,5 @@ namespace grb { } #endif -#endif // end ``_H_GRB_SCALAR'' +#endif // end ``_H_ALP_SCALAR'' diff --git a/include/alp/semiring.hpp b/include/alp/semiring.hpp index c1d61830f..69de9835f 100644 --- a/include/alp/semiring.hpp +++ b/include/alp/semiring.hpp @@ -20,23 +20,23 @@ * @date 15th of March, 2016 */ -#ifndef _H_GRB_SEMIRING -#define _H_GRB_SEMIRING +#ifndef _H_ALP_SEMIRING +#define _H_ALP_SEMIRING -#include -#include -#include +#include +#include +#include /** * The main GraphBLAS namespace. */ -namespace grb { +namespace alp { /** * A generalised semiring. * - * This semiring works with the standard operators provided in grb::operators - * as well as with standard identities provided in grb::identities. + * This semiring works with the standard operators provided in alp::operators + * as well as with standard identities provided in alp::identities. * * \par Operators * @@ -49,7 +49,7 @@ namespace grb { * -# \f$ \oplus: \ D_1 \times D_2 \to D_3 \f$, and * -# \f$ \otimes:\ D_4 \times D_5 \to D_6 \f$. * - * By convention, primitives such as grb::mxv will feed the output of the + * By convention, primitives such as alp::mxv will feed the output of the * multiplicative operation to the additive operator as left-hand side input; * hence, a valid semiring must have \f$ D_6 = D_1 \f$. Should the additive * operator reduce several multiplicative outputs, the thus-far accumulated @@ -79,29 +79,29 @@ namespace grb { * \par Standard examples * * An example of the standard semiring would be: - * grb::Semiring< - * grb::operators::add< double, double, double >, - * grb::operators::mul< double, double, double >, - * grb::identities::zero, - * grb::identitites::one + * alp::Semiring< + * alp::operators::add< double, double, double >, + * alp::operators::mul< double, double, double >, + * alp::identities::zero, + * alp::identitites::one * > realSemiring; * In this standard case, all domains the operators the semiring comprises are * equal to one another. GraphBLAS supports the following shorthand for this * special case: - * grb::Semiring< - * grb::operators::add< double >, - * grb::operators::mul< double >, - * grb::identities::zero, - * grb::identities::one + * alp::Semiring< + * alp::operators::add< double >, + * alp::operators::mul< double >, + * alp::identities::zero, + * alp::identities::one * > realSemiring; * * As another example, consider min-plus algebras. These may be used, for * example, for deriving shortest paths through an edge-weighted graph: - * grb::Semiring< - * grb::operators::min< unsigned int >, - * grb::operators::add< unsigned int >, - * grb::identities::negative_infinity, - * grb::identities::zero + * alp::Semiring< + * alp::operators::min< unsigned int >, + * alp::operators::add< unsigned int >, + * alp::identities::negative_infinity, + * alp::identities::zero * > minPlus; * * \par CMonoid-categories @@ -191,15 +191,15 @@ namespace grb { "The right-hand input type of the additive operator must match its " "output type" ); - static_assert( grb::is_associative< _OP1 >::value, + static_assert( alp::is_associative< _OP1 >::value, "Cannot construct a semiring using a non-associative additive " "operator" ); - static_assert( grb::is_associative< _OP2 >::value, + static_assert( alp::is_associative< _OP2 >::value, "Cannot construct a semiring using a non-associative multiplicative " "operator" ); - static_assert( grb::is_commutative< _OP1 >::value, + static_assert( alp::is_commutative< _OP1 >::value, "Cannot construct a semiring using a non-commutative additive " "operator" ); @@ -243,10 +243,10 @@ namespace grb { using One = _ID2< OneType >; private: - static constexpr size_t D1_bsz = grb::config::SIMD_BLOCKSIZE< D1 >::value(); - static constexpr size_t D2_bsz = grb::config::SIMD_BLOCKSIZE< D2 >::value(); - static constexpr size_t D3_bsz = grb::config::SIMD_BLOCKSIZE< D3 >::value(); - static constexpr size_t D4_bsz = grb::config::SIMD_BLOCKSIZE< D4 >::value(); + static constexpr size_t D1_bsz = alp::config::SIMD_BLOCKSIZE< D1 >::value(); + static constexpr size_t D2_bsz = alp::config::SIMD_BLOCKSIZE< D2 >::value(); + static constexpr size_t D3_bsz = alp::config::SIMD_BLOCKSIZE< D3 >::value(); + static constexpr size_t D4_bsz = alp::config::SIMD_BLOCKSIZE< D4 >::value(); static constexpr size_t mul_input_bsz = D1_bsz < D2_bsz ? D1_bsz : D2_bsz; /** The additive monoid. */ @@ -344,10 +344,10 @@ namespace grb { template< class _OP1, class _OP2, template< typename > class _ID1, template< typename > class _ID2 > struct has_immutable_nonzeroes< Semiring< _OP1, _OP2, _ID1, _ID2 > > { - static const constexpr bool value = grb::is_semiring< Semiring< _OP1, _OP2, _ID1, _ID2 > >::value && - std::is_same< _OP1, typename grb::operators::logical_or< typename _OP1::D1, typename _OP1::D2, typename _OP1::D3 > >::value; + static const constexpr bool value = alp::is_semiring< Semiring< _OP1, _OP2, _ID1, _ID2 > >::value && + std::is_same< _OP1, typename alp::operators::logical_or< typename _OP1::D1, typename _OP1::D2, typename _OP1::D3 > >::value; }; -} // namespace grb +} // namespace alp #endif diff --git a/include/alp/smf.hpp b/include/alp/smf.hpp index c028d10c6..eba609fdc 100644 --- a/include/alp/smf.hpp +++ b/include/alp/smf.hpp @@ -23,12 +23,12 @@ * */ -#ifndef _H_GRB_SMF -#define _H_GRB_SMF +#ifndef _H_ALP_SMF +#define _H_ALP_SMF #include -namespace grb { +namespace alp { namespace smf { @@ -51,6 +51,6 @@ namespace grb { }; // namespace smf -} // namespace grb +} // namespace alp -#endif // _H_GRB_SMF +#endif // _H_ALP_SMF diff --git a/include/alp/structures.hpp b/include/alp/structures.hpp index b09134a32..de1de649e 100644 --- a/include/alp/structures.hpp +++ b/include/alp/structures.hpp @@ -26,15 +26,15 @@ * A structure */ -#ifndef _H_GRB_STRUCTURES -#define _H_GRB_STRUCTURES +#ifndef _H_ALP_STRUCTURES +#define _H_ALP_STRUCTURES #include #include #include "imf.hpp" -namespace grb { +namespace alp { /** * @brief Compile-time interval [ _left, _right ) @@ -182,18 +182,18 @@ namespace grb { */ template< typename SrcStructure > - static bool isInstantiableFrom( grb::imf::IMF & imf_l, grb::imf::IMF & imf_r ) { + static bool isInstantiableFrom( alp::imf::IMF & imf_l, alp::imf::IMF & imf_r ) { return false; } }; template<> - inline bool General::isInstantiableFrom< UpperTriangular >( grb::imf::IMF & imf_l, grb::imf::IMF & imf_r ) { + inline bool General::isInstantiableFrom< UpperTriangular >( alp::imf::IMF & imf_l, alp::imf::IMF & imf_r ) { return imf_l.map( imf_l.n - 1 ) <= imf_r.map( 0 ); } template<> - inline bool General::isInstantiableFrom< General >( grb::imf::IMF & imf_l, grb::imf::IMF & imf_r ) { + inline bool General::isInstantiableFrom< General >( alp::imf::IMF & imf_l, alp::imf::IMF & imf_r ) { (void)imf_l; (void)imf_r; return true; @@ -215,11 +215,11 @@ namespace grb { * main diagonal the smaller the position) while superdiagonals * have positive ones (the farer from the main diagonal the * larger the position). - * E.g., Band< grb::Interval<-1, 2> > is a band + * E.g., Band< alp::Interval<-1, 2> > is a band * structure that can be used to describe a tridiagonal matrix. * - * \note grb::Interval uses a past-the-end - * notation for the intervals [a, b). @see grb::Interval. + * \note alp::Interval uses a past-the-end + * notation for the intervals [a, b). @see alp::Interval. * * The first value of the left-most (second value of the right- * most) interval in the sequence is the lower (upper, resp.) @@ -236,12 +236,12 @@ namespace grb { * (e.g., checking if a matrix is a Band matrix irrespective * of specific bands in the structure). * - * @tparam Intervals One or more \a grb::Interval types specifying the + * @tparam Intervals One or more \a alp::Interval types specifying the * bands of the structure. These intervals should be * non-overlapping and sorted according to the above * assumption that all intervals are defined assuming * the main diagonal has position zero. - * \a grb::LeftOpenInterval ( \a grb::RightOpenInterval) + * \a alp::LeftOpenInterval ( \a alp::RightOpenInterval) * can be used to indicate that the left bandwidth * (right bandwidth, respectively) is defined by the * size of the matrix at runtime. @@ -252,7 +252,7 @@ namespace grb { typedef std::tuple< Intervals... > band_intervals; - static_assert( grb::internal::is_tuple_sorted_non_overlapping< band_intervals >::value ); + static_assert( alp::internal::is_tuple_sorted_non_overlapping< band_intervals >::value ); typedef typename structures::tuple_cat< std::tuple< Band< Intervals... > >, General::inferred_structures >::type inferred_structures; }; @@ -283,7 +283,7 @@ namespace grb { // For example, in all cases we should check if IMFs do not overflow the original container. // (if it is actually necessary. Maybe we want to assume that the user knows what he is doing) template< typename SrcStructure > - static bool isInstantiableFrom( const grb::imf::IMF & imf_l, const grb::imf::IMF & imf_r ) { + static bool isInstantiableFrom( const alp::imf::IMF & imf_l, const alp::imf::IMF & imf_r ) { static_assert( std::is_same< SrcStructure, UpperTriangular >::value ); @@ -357,6 +357,6 @@ namespace grb { } // namespace structures -} // namespace grb +} // namespace alp #endif diff --git a/include/alp/type_traits.hpp b/include/alp/type_traits.hpp index 3c8beaef3..1973dcae3 100644 --- a/include/alp/type_traits.hpp +++ b/include/alp/type_traits.hpp @@ -20,10 +20,10 @@ * @date 25th of March, 2019 */ -#ifndef _H_GRB_TYPE_TRAITS -#define _H_GRB_TYPE_TRAITS +#ifndef _H_ALP_TYPE_TRAITS +#define _H_ALP_TYPE_TRAITS -namespace grb { +namespace alp { /** * Used to inspect whether a given type is a GraphBLAS container. @@ -31,8 +31,8 @@ namespace grb { * @tparam T The type to inspect. * * There are only two GraphBLAS containers: - * -# grb::Vector, and - * -# grb::Matrix. + * -# alp::Vector, and + * -# alp::Matrix. */ template< typename T > struct is_container { @@ -101,11 +101,11 @@ namespace grb { * @tparam T The operator to inspect. * * An example of an idempotent operator is the logical OR, - * #grb::operators::logical_or. + * #alp::operators::logical_or. */ template< typename T > struct is_idempotent { - static_assert( is_operator< T >::value, "Template argument to grb::is_idempotent must be an operator!" ); + static_assert( is_operator< T >::value, "Template argument to alp::is_idempotent must be an operator!" ); static const constexpr bool value = false; }; @@ -116,12 +116,12 @@ namespace grb { * @tparam T The semiring to inspect. * * An example of a monoid with an immutable identity is the logical OR, - * #grb::operators::logical_or. + * #alp::operators::logical_or. */ template< typename T > struct has_immutable_nonzeroes { static_assert( is_semiring< T >::value, - "Template argument to grb::has_immutable_nonzeroes must be a " + "Template argument to alp::has_immutable_nonzeroes must be a " "semiring!" ); static const constexpr bool value = false; }; @@ -131,11 +131,11 @@ namespace grb { /** * Whether or not a given operator could translate to a no-op; * i.e., leave its outputs unmodified. This can be relevant - * because it indicates situations where grb::apply could leave + * because it indicates situations where alp::apply could leave * the output uninitialised, which may well not be as intended. * * An example of an operator that non-trivially may result in a - * no-op is grb::operators::left_assign_if. Such operators must + * no-op is alp::operators::left_assign_if. Such operators must * overload this internal type trait. */ template< typename OP > @@ -146,8 +146,8 @@ namespace grb { static const constexpr bool value = false; }; - } // end namespace grb::internal + } // end namespace alp::internal -} // namespace grb +} // namespace alp #endif diff --git a/include/alp/utils.hpp b/include/alp/utils.hpp index c00bb771c..7ac504a15 100644 --- a/include/alp/utils.hpp +++ b/include/alp/utils.hpp @@ -20,8 +20,8 @@ * @date 8th of August, 2016 */ -#ifndef _H_GRB_UTILITIES -#define _H_GRB_UTILITIES +#ifndef _H_ALP_UTILITIES +#define _H_ALP_UTILITIES #include @@ -29,10 +29,10 @@ #include //numeric_limits #include -#include +#include -namespace grb { +namespace alp { /** * Some utility classes used that may be used throughout this GraphBLAS @@ -90,7 +90,7 @@ namespace grb { // if they are bit-wise equal, it's easy if( a == b ) { #ifdef _DEBUG - #ifndef _GRB_NO_STDIO + #ifndef _ALP_NO_STDIO std::cout << "\t Bit-wise equal\n"; #else printf( "\t Bit-wise equal\n" ); @@ -117,7 +117,7 @@ namespace grb { // The same is true if a or b are zero. if( a == 0 || b == 0 || absPlus < min ) { #ifdef _DEBUG - #ifndef _GRB_NO_STDIO + #ifndef _ALP_NO_STDIO std::cout << "\t Zero or close to zero difference\n"; #else printf( "\t Zero or close to zero difference\n" ); @@ -131,7 +131,7 @@ namespace grb { if( absA > absB ) { if( absB > max - absA ) { #ifdef _DEBUG - #ifndef _GRB_NO_STDIO + #ifndef _ALP_NO_STDIO std::cout << "\t Normalising absolute difference by max (I)\n"; #else printf( "\t Normalising absolute difference by max (I)\n" ); @@ -142,7 +142,7 @@ namespace grb { } else { if( absA > max - absB ) { #ifdef _DEBUG - #ifndef _GRB_NO_STDIO + #ifndef _ALP_NO_STDIO std::cout << "\t Normalising absolute difference by max (II)\n"; #else printf( "\t Normalising absolute difference by max (II)\n" ); @@ -153,7 +153,7 @@ namespace grb { } // use of relative error should be safe #ifdef _DEBUG - #ifndef _GRB_NO_STDIO + #ifndef _ALP_NO_STDIO std::cout << "\t Using relative error\n"; #else printf( "\t Using relative error\n" ); @@ -215,25 +215,25 @@ namespace grb { * The memory area pointed to by \a val shall not be dereferenced if * \a assigned is false. * - * @return If the descriptor includes grb::descriptors::structoral, - * returns \a assigned. If additionally grb::descriptors::invert_mask + * @return If the descriptor includes alp::descriptors::structoral, + * returns \a assigned. If additionally alp::descriptors::invert_mask * was defined, instead returns the negation of \a assigned. - * @return If the descriptor includes grb::descriptors::structural_complement, + * @return If the descriptor includes alp::descriptors::structural_complement, * returns the negation of \a assigned. If additionally - * grb::descriptors::invert_mask was defined, instead returns + * alp::descriptors::invert_mask was defined, instead returns * \a assigned. - * @return If the descriptor does not include grb::descriptors::structural - * nor grb::descriptors::structural_complement and if \a assigned + * @return If the descriptor does not include alp::descriptors::structural + * nor alp::descriptors::structural_complement and if \a assigned * is false, then the entry is ignored and uninterpreted, thus * returning \a false. - * @return If the descriptor includes grb::descriptors::invert_mask, + * @return If the descriptor includes alp::descriptors::invert_mask, * returns the negation of the dereferenced value of \a val * which is first cast to a \a bool. * @return Otherwise, returns the dereferenced value of \a val, * cast to a \a bool. * - * If \a descriptor contains both grb::descriptors::structural and - * grb::descriptors::structural_complement, the code shall not + * If \a descriptor contains both alp::descriptors::structural and + * alp::descriptors::structural_complement, the code shall not * compile. */ template< Descriptor descriptor, typename T > @@ -298,6 +298,6 @@ namespace grb { } // namespace utils -} // namespace grb +} // namespace alp #endif diff --git a/include/alp/utils/SynchronizedNonzeroIterator.hpp b/include/alp/utils/SynchronizedNonzeroIterator.hpp index f48f9a909..4d57628d8 100644 --- a/include/alp/utils/SynchronizedNonzeroIterator.hpp +++ b/include/alp/utils/SynchronizedNonzeroIterator.hpp @@ -20,20 +20,20 @@ * @date 2nd of August, 2017 */ -#ifndef _H_SYNCHRONIZEDNONZEROITERATOR -#define _H_SYNCHRONIZEDNONZEROITERATOR +#ifndef _H_ALP_SYNCHRONIZEDNONZEROITERATOR +#define _H_ALP_SYNCHRONIZEDNONZEROITERATOR #include //std::pair #include #ifdef _DEBUG -#ifndef _GRB_NO_STDIO +#ifndef _ALP_NO_STDIO #include #endif #endif -namespace grb { +namespace alp { namespace utils { template< typename S1, typename S2, typename V, typename fwd_it1, typename fwd_it2, typename fwd_it3 > @@ -318,7 +318,7 @@ namespace grb { template< typename S1, typename S2 > SynchronizedNonzeroIterator< S1, S2, void, const S1 *, const S2 *, void > makeSynchronized( const S1 * const it1, const S2 * const it2, const S1 * const it1_end, const S2 * const it2_end ) { #ifdef _DEBUG -#ifndef _GRB_NO_STDIO +#ifndef _ALP_NO_STDIO std::cout << "SynchronizedNonzeroIterator::makeSynchronized " "received iterators " << it1 << " (start) and " << it2 << " (end)\n"; @@ -351,6 +351,6 @@ namespace grb { } } // namespace utils -} // namespace grb +} // namespace alp -#endif // end ``_H_SYNCHRONIZEDNONZEROITERATOR'' +#endif // end ``_H_ALP_SYNCHRONIZEDNONZEROITERATOR'' diff --git a/include/alp/utils/autodeleter.hpp b/include/alp/utils/autodeleter.hpp index 3386e5ff6..1cde7b3ec 100644 --- a/include/alp/utils/autodeleter.hpp +++ b/include/alp/utils/autodeleter.hpp @@ -24,18 +24,18 @@ * @date 22nd of April, 2017 */ -#ifndef _H_GRB_UTILS_AUTO_DELETER -#define _H_GRB_UTILS_AUTO_DELETER +#ifndef _H_ALP_UTILS_AUTO_DELETER +#define _H_ALP_UTILS_AUTO_DELETER -#ifndef _GRB_NO_LIBNUMA +#ifndef _ALP_NO_LIBNUMA #include #endif #include -#include "graphblas/config.hpp" +#include "alp/config.hpp" -namespace grb { +namespace alp { namespace utils { @@ -56,7 +56,7 @@ namespace grb { } } -#ifndef _GRB_NO_LIBNUMA +#ifndef _ALP_NO_LIBNUMA /** \todo documentation */ template< typename T > class safe_numa_free { @@ -76,10 +76,10 @@ namespace grb { } // namespace utils -} // namespace grb +} // namespace alp // now define user API: -namespace grb { +namespace alp { namespace utils { @@ -123,7 +123,7 @@ namespace grb { * @throws std::bad_alloc If the system cannot allocate enough memory. */ AutoDeleter( T * const pointer = NULL, const size_t size = 0 ) { -#ifdef _GRB_NO_LIBNUMA +#ifdef _ALP_NO_LIBNUMA (void)size; const auto free_p = &( functions::template safe_free< T > ); _shPtr = std::shared_ptr< T >( pointer, free_p ); @@ -181,12 +181,7 @@ namespace grb { } // namespace utils -} // namespace grb - -// include specialised DeleterFunctions -#ifdef _GRB_WITH_BANSHEE - #include "graphblas/banshee/deleters.hpp" -#endif +} // namespace alp #endif diff --git a/include/alp/utils/suppressions.h b/include/alp/utils/suppressions.h index 653679530..71cbda591 100644 --- a/include/alp/utils/suppressions.h +++ b/include/alp/utils/suppressions.h @@ -28,23 +28,23 @@ * @date 19th of January 2022 */ -#ifndef _H_GRB_UTILS_SUPRESSIONS -#define _H_GRB_UTILS_SUPRESSIONS +#ifndef _H_ALP_UTILS_SUPRESSIONS +#define _H_ALP_UTILS_SUPRESSIONS #if defined(__GNUC__) && __GNUC__ >= 4 // here are the macros for GCC - #define GRB_UTIL_IGNORE_MAYBE_UNINITIALIZED \ + #define ALP_UTIL_IGNORE_MAYBE_UNINITIALIZED \ _Pragma( "GCC diagnostic push" ) ;\ _Pragma( "GCC diagnostic ignored \"-Wmaybe-uninitialized\"" );\ - #define GRB_UTIL_RESTORE_WARNINGS \ + #define ALP_UTIL_RESTORE_WARNINGS \ _Pragma( "GCC diagnostic pop" );\ #else // here are empty default macros - #define GRB_UTIL_IGNORE_MAYBE_UNINITIALIZED - #define GRB_UTIL_RESTORE_WARNINGS + #define ALP_UTIL_IGNORE_MAYBE_UNINITIALIZED + #define ALP_UTIL_RESTORE_WARNINGS #endif -#endif // end ``_H_GRB_REFERENCE_BLAS2'' +#endif // end ``_H_ALP_REFERENCE_BLAS2'' diff --git a/include/alp/vector.hpp b/include/alp/vector.hpp index cb1c734d4..8ad5b585d 100644 --- a/include/alp/vector.hpp +++ b/include/alp/vector.hpp @@ -20,38 +20,30 @@ * @date 10th of August, 2016 */ -#ifndef _H_GRB_VECTOR -#define _H_GRB_VECTOR +#ifndef _H_ALP_VECTOR +#define _H_ALP_VECTOR #include "base/config.hpp" #include "base/vector.hpp" -#include "coordinates.hpp" // now include all specialisations contained in the backend directories: -#ifdef _GRB_WITH_REFERENCE - #include -#endif -#ifdef _GRB_WITH_DENSEREF - #include -#endif -#ifdef _GRB_WITH_LPF - #include -#endif -#ifdef _GRB_WITH_BANSHEE - #include +#ifdef _ALP_WITH_REFERENCE + #include #endif // specify default only if requested during compilation -#ifdef _GRB_BACKEND -namespace grb { - template< typename D, Backend implementation = config::default_backend, typename C = internal::DefaultCoordinates > - class Vector; +#ifdef _ALP_BACKEND +namespace alp { + namespace internal { + template< typename D, Backend implementation = config::default_backend > + class Vector; + } // namespace internal /* * The default value of \a density could also be made conditional (Dense or Sparse) depending on \a config::default_backend */ template< typename T, typename Structure = structures::General, enum Density density = Density::Dense, typename View = view::Original< void >, enum Backend backend = config::default_backend > - class VectorView; + class Vector; } #endif diff --git a/include/alp/views.hpp b/include/alp/views.hpp index b8909b018..d31ef68ce 100644 --- a/include/alp/views.hpp +++ b/include/alp/views.hpp @@ -26,13 +26,13 @@ * including its type (member type \a applied_to), or how read its dimensions. */ -#ifndef _H_GRB_VIEWS -#define _H_GRB_VIEWS +#ifndef _H_ALP_VIEWS +#define _H_ALP_VIEWS #include #include -namespace grb { +namespace alp { namespace view { @@ -73,6 +73,6 @@ namespace grb { }; // namespace view -} // namespace grb +} // namespace alp -#endif // _H_GRB_VIEWS +#endif // _H_ALP_VIEWS diff --git a/src/alp/reference/init.cpp b/src/alp/reference/init.cpp index 865b1fc3e..079579c56 100644 --- a/src/alp/reference/init.cpp +++ b/src/alp/reference/init.cpp @@ -16,6 +16,7 @@ */ #include +#include template<> alp::RC alp::init< alp::reference >( const size_t s, const size_t P, void * const data ) { diff --git a/tests/unit/CMakeLists.txt b/tests/unit/CMakeLists.txt index 68db94bf4..54dffd0ef 100644 --- a/tests/unit/CMakeLists.txt +++ b/tests/unit/CMakeLists.txt @@ -205,31 +205,31 @@ add_grb_executables( spy spy.cpp ) add_grb_executables( dense_constant_matrices dense_constant_matrices.cpp - BACKENDS reference_dense + BACKENDS alp_reference ) add_grb_executables( dense_dot_norm2 dense_dot_norm2.cpp - BACKENDS reference_dense + BACKENDS alp_reference ) add_grb_executables( dense_matrix_imf dense_matrix_imf.cpp - BACKENDS reference_dense + BACKENDS alp_reference ) add_grb_executables( dense_matrix_eWiseApply dense_matrix_eWiseApply.cpp - BACKENDS reference_dense + BACKENDS alp_reference ) add_grb_executables( dense_mxm dense_mxm.cpp - BACKENDS reference_dense + BACKENDS alp_reference ) add_grb_executables( dense_outer dense_outer.cpp - BACKENDS reference_dense + BACKENDS alp_reference ) add_grb_executables( dense_structured_matrix dense_structured_matrix.cpp - BACKENDS reference_dense + BACKENDS alp_reference ) add_grb_executables( dense_spmv dense_spmv.cpp diff --git a/tests/unit/dense_constant_matrices.cpp b/tests/unit/dense_constant_matrices.cpp index db561128e..93e99feb0 100644 --- a/tests/unit/dense_constant_matrices.cpp +++ b/tests/unit/dense_constant_matrices.cpp @@ -19,31 +19,31 @@ #include #include -#include +#include -using namespace grb; +using namespace alp; -void grb_program( const size_t & n, grb::RC & rc ) { - grb::Semiring< grb::operators::add< double >, grb::operators::mul< double >, grb::identities::zero, grb::identities::one > ring; +void alp_program( const size_t & n, alp::RC & rc ) { + alp::Semiring< alp::operators::add< double >, alp::operators::mul< double >, alp::identities::zero, alp::identities::one > ring; std::cout << "\tTesting dense Identity and Zero matrices\n"; // initialize test - grb::StructuredMatrix< double, structures::Square > A( n ); - grb::StructuredMatrix< double, structures::Square > C( n ); - auto I = grb::I< double >( n ); - auto Zero = grb::Zero< double >( n, n ); + alp::Matrix< double, structures::Square > A( n ); + alp::Matrix< double, structures::Square > C( n ); + auto I = alp::I< double >( n ); + auto Zero = alp::Zero< double >( n, n ); // Initialize input matrix std::vector< double > A_data( n * n, 1 ); - rc = grb::buildMatrix( A, A_data.begin(), A_data.end() ); + rc = alp::buildMatrix( A, A_data.begin(), A_data.end() ); if( rc == SUCCESS ) { - grb::mxm( C, A, I, ring ); + alp::mxm( C, A, I, ring ); // C should be equal to A } if (rc == SUCCESS ) { - grb::mxm( C, A, Zero, ring ); + alp::mxm( C, A, Zero, ring ); // C should be a zero } } @@ -82,14 +82,14 @@ int main( int argc, char ** argv ) { } std::cout << "This is functional test " << argv[ 0 ] << "\n"; - grb::Launcher< AUTOMATIC > launcher; - grb::RC out; - if( launcher.exec( &grb_program, in, out, true ) != SUCCESS ) { + alp::Launcher< AUTOMATIC > launcher; + alp::RC out; + if( launcher.exec( &alp_program, in, out, true ) != SUCCESS ) { std::cerr << "Launching test FAILED\n"; return 255; } if( out != SUCCESS ) { - std::cerr << "Test FAILED (" << grb::toString( out ) << ")" << std::endl; + std::cerr << "Test FAILED (" << alp::toString( out ) << ")" << std::endl; } else { std::cout << "Test OK" << std::endl; } diff --git a/tests/unit/dense_dot_norm2.cpp b/tests/unit/dense_dot_norm2.cpp index f73902f5c..02f40ac2c 100644 --- a/tests/unit/dense_dot_norm2.cpp +++ b/tests/unit/dense_dot_norm2.cpp @@ -18,23 +18,23 @@ #include #include -#include +#include -using namespace grb; +using namespace alp; -void grb_program( const size_t &n, grb::RC &rc ) { +void alp_program( const size_t &n, alp::RC &rc ) { // repeatedly used containers - grb::VectorView< double > left( n ); - grb::VectorView< double > right( n ); + alp::Vector< double > left( n ); + alp::Vector< double > right( n ); // test 1, init - grb::Semiring< - grb::operators::add< double >, grb::operators::mul< double >, - grb::identities::zero, grb::identities::one + alp::Semiring< + alp::operators::add< double >, alp::operators::mul< double >, + alp::identities::zero, alp::identities::one > ring; - // rc = grb::set( left, 1.5 ); // left = 1.5 everywhere - // rc = rc ? rc : grb::set( right, -1.0 ); + // rc = alp::set( left, 1.5 ); // left = 1.5 everywhere + // rc = rc ? rc : alp::set( right, -1.0 ); // if( rc != SUCCESS ) { // std::cerr << "\t test 1 (dense, regular semiring): initialisation FAILED\n"; // return; @@ -42,7 +42,7 @@ void grb_program( const size_t &n, grb::RC &rc ) { Scalar< double > out( 2.55 ); // test 1, exec - rc = grb::dot( out, left, right, ring ); + rc = alp::dot( out, left, right, ring ); if( rc != SUCCESS ) { std::cerr << "\t test 1 (dense, regular semiring): dot FAILED\n"; return; @@ -62,15 +62,15 @@ void grb_program( const size_t &n, grb::RC &rc ) { // } // test 2, init - // grb::Semiring< - // grb::operators::add< double >, grb::operators::left_assign_if< double, bool, double >, - // grb::identities::zero, grb::identities::logical_true + // alp::Semiring< + // alp::operators::add< double >, alp::operators::left_assign_if< double, bool, double >, + // alp::identities::zero, alp::identities::logical_true // > pattern_sum_if; - // rc = grb::clear( left ); - // rc = rc ? rc : grb::clear( right ); + // rc = alp::clear( left ); + // rc = rc ? rc : alp::clear( right ); // for( size_t i = 0; 2 * i < n; ++i ) { - // rc = rc ? rc : grb::setElement( left, 2.0, 2 * i ); - // rc = rc ? rc : grb::setElement( right, 1.0, 2 * i ); + // rc = rc ? rc : alp::setElement( left, 2.0, 2 * i ); + // rc = rc ? rc : alp::setElement( right, 1.0, 2 * i ); // } // if( rc != SUCCESS ) { // std::cerr << "\t test 2 (sparse, non-standard semiring) initialisation FAILED\n"; @@ -79,7 +79,7 @@ void grb_program( const size_t &n, grb::RC &rc ) { // out = 0; // // test 2, exec - // rc = grb::dot( out, left, right, pattern_sum_if ); + // rc = alp::dot( out, left, right, pattern_sum_if ); // if( rc != SUCCESS ) { // std::cerr << "\t test 2 (sparse, non-standard semiring) dot FAILED\n"; // return; @@ -95,22 +95,22 @@ void grb_program( const size_t &n, grb::RC &rc ) { // } // // test 3, init - // grb::Semiring< - // grb::operators::add< int >, grb::operators::mul< int >, - // grb::identities::zero, grb::identities::one + // alp::Semiring< + // alp::operators::add< int >, alp::operators::mul< int >, + // alp::identities::zero, alp::identities::one // > intRing; - // grb::Vector< int > x( n ), y( n ); - // rc = grb::set( x, 1 ); - // rc = rc ? rc : grb::set( y, 2 ); - // if( rc != grb::SUCCESS ) { + // alp::Vector< int > x( n ), y( n ); + // rc = alp::set( x, 1 ); + // rc = rc ? rc : alp::set( y, 2 ); + // if( rc != alp::SUCCESS ) { // std::cerr << "\t test 3 (dense integer vectors) initialisation FAILED\n"; // return; // } // int alpha = 0; // // test 3, exec - // rc = grb::dot( alpha, x, y, intRing ); - // if( rc != grb::SUCCESS ) { + // rc = alp::dot( alpha, x, y, intRing ); + // if( rc != alp::SUCCESS ) { // std::cerr << "\t test 3 (dense integer vectors) dot FAILED\n"; // return; // } @@ -124,11 +124,11 @@ void grb_program( const size_t &n, grb::RC &rc ) { // } // // test 4, init - // grb::Vector< int > empty_left( 0 ), empty_right( 0 ); + // alp::Vector< int > empty_left( 0 ), empty_right( 0 ); // // retain old value of alpha // // test 4, exec - // rc = grb::dot( alpha, empty_left, empty_right, intRing ); + // rc = alp::dot( alpha, empty_left, empty_right, intRing ); // if( rc != SUCCESS ) { // std::cerr << "\t test 4 (empty vectors) dot FAILED\n"; // return; @@ -178,14 +178,14 @@ int main( int argc, char ** argv ) { } std::cout << "This is functional test " << argv[ 0 ] << "\n"; - grb::Launcher< AUTOMATIC > launcher; - grb::RC out; - if( launcher.exec( &grb_program, in, out, true ) != SUCCESS ) { + alp::Launcher< AUTOMATIC > launcher; + alp::RC out; + if( launcher.exec( &alp_program, in, out, true ) != SUCCESS ) { std::cerr << "Launching test FAILED\n"; return 255; } if( out != SUCCESS ) { - std::cerr << "Test FAILED (" << grb::toString( out ) << ")" << std::endl; + std::cerr << "Test FAILED (" << alp::toString( out ) << ")" << std::endl; } else { std::cout << "Test OK" << std::endl; } diff --git a/tests/unit/dense_matrix_eWiseApply.cpp b/tests/unit/dense_matrix_eWiseApply.cpp index 85832dc41..a2c7ea0d2 100644 --- a/tests/unit/dense_matrix_eWiseApply.cpp +++ b/tests/unit/dense_matrix_eWiseApply.cpp @@ -19,34 +19,34 @@ #include #include -#include +#include -using namespace grb; +using namespace alp; template< typename Structure > -void print_matrix( const grb::StructuredMatrix< double, Structure > & A) { +void print_matrix( const alp::Matrix< double, Structure > & A) { (void)A; - // if( ! grb::internal::getInitialized< double >( A ) ) { + // if( ! alp::internal::getInitialized< double >( A ) ) { // std::cout << "Matrix is uninitialized, nothing to print.\n"; // return; // } - // const double * Araw = grb::getRaw( internal::getContainer( A ) ); - // for( size_t row = 0; row < grb::nrows( A ); ++row ) { - // for( size_t col = 0; col < grb::ncols( A ); ++col ) { - // std::cout << Araw[row * grb::ncols( A ) + col] << " "; + // const double * Araw = alp::getRaw( internal::getContainer( A ) ); + // for( size_t row = 0; row < alp::nrows( A ); ++row ) { + // for( size_t col = 0; col < alp::ncols( A ); ++col ) { + // std::cout << Araw[row * alp::ncols( A ) + col] << " "; // } // std::cout << "\n"; // } } -void grb_program( const size_t & n, grb::RC & rc ) { - grb::Semiring< grb::operators::add< double >, grb::operators::mul< double >, grb::identities::zero, grb::identities::one > ring; +void alp_program( const size_t & n, alp::RC & rc ) { + alp::Semiring< alp::operators::add< double >, alp::operators::mul< double >, alp::identities::zero, alp::identities::one > ring; std::cout << "\tTesting dense mxm\n"; // initialize test - grb::StructuredMatrix< double, structures::General > A( n, n ); - grb::StructuredMatrix< double, structures::General > B( n, n ); - grb::StructuredMatrix< double, structures::General > C( n, n ); + alp::Matrix< double, structures::General > A( n, n ); + alp::Matrix< double, structures::General > B( n, n ); + alp::Matrix< double, structures::General > C( n, n ); std::vector< double > A_data( n * n, 1 ); std::vector< double > B_data( n * n, 2 ); @@ -54,9 +54,9 @@ void grb_program( const size_t & n, grb::RC & rc ) { double beta = 20; // Initialize input matrices - rc = grb::buildMatrix( A, A_data.begin(), A_data.end() ); + rc = alp::buildMatrix( A, A_data.begin(), A_data.end() ); if( rc == SUCCESS ) { - rc = grb::buildMatrix( B, B_data.begin(), B_data.end() ); + rc = alp::buildMatrix( B, B_data.begin(), B_data.end() ); } @@ -64,17 +64,17 @@ void grb_program( const size_t & n, grb::RC & rc ) { // C = A + B if( rc == SUCCESS ) { - rc = grb::eWiseApply( C, A, B, ring.getAdditiveMonoid()); + rc = alp::eWiseApply( C, A, B, ring.getAdditiveMonoid()); } // C = alpha . B if ( rc == SUCCESS ) { - rc = grb::eWiseApply( C, alpha, B, ring.getMultiplicativeMonoid()); + rc = alp::eWiseApply( C, alpha, B, ring.getMultiplicativeMonoid()); } // C = A . beta if( rc == SUCCESS ) { - rc = grb::eWiseApply( C, A, beta, ring.getMultiplicativeMonoid()); + rc = alp::eWiseApply( C, A, beta, ring.getMultiplicativeMonoid()); } } @@ -113,14 +113,14 @@ int main( int argc, char ** argv ) { } std::cout << "This is functional test " << argv[ 0 ] << "\n"; - grb::Launcher< AUTOMATIC > launcher; - grb::RC out; - if( launcher.exec( &grb_program, in, out, true ) != SUCCESS ) { + alp::Launcher< AUTOMATIC > launcher; + alp::RC out; + if( launcher.exec( &alp_program, in, out, true ) != SUCCESS ) { std::cerr << "Launching test FAILED\n"; return 255; } if( out != SUCCESS ) { - std::cerr << "Test FAILED (" << grb::toString( out ) << ")" << std::endl; + std::cerr << "Test FAILED (" << alp::toString( out ) << ")" << std::endl; } else { std::cout << "Test OK" << std::endl; } diff --git a/tests/unit/dense_matrix_imf.cpp b/tests/unit/dense_matrix_imf.cpp index 02e03fedb..5f839e572 100644 --- a/tests/unit/dense_matrix_imf.cpp +++ b/tests/unit/dense_matrix_imf.cpp @@ -21,7 +21,7 @@ #include #include -#include +#include void buildUpperTriangularRawArray( std::vector< double > & v, int n ) { for (int i = 0; i < n; ++i ) { @@ -35,15 +35,15 @@ void buildUpperTriangularRawArray( std::vector< double > & v, int n ) { } } -void grb_program( const size_t & n, grb::RC & rc ) { +void alp_program( const size_t & n, alp::RC & rc ) { // initialize test // using General Views over General Structured Matrix - grb::StructuredMatrix< double, grb::structures::General > A( n, n ); - std::cout << "General gather from a general StructuredMatrix (expect success)\n"; + alp::Matrix< double, alp::structures::General > A( n, n ); + std::cout << "General gather from a general Matrix (expect success)\n"; try { - auto Aview = grb::get_view< grb::structures::General >( + auto Aview = alp::get_view< alp::structures::General >( A, - grb::utils::range(1,3), grb::utils::range(1,5) + alp::utils::range(1,3), alp::utils::range(1,5) ); std::cout << "\tSUCCESS\n"; } catch( const std::exception & e ) { @@ -52,13 +52,13 @@ void grb_program( const size_t & n, grb::RC & rc ) { // using Upper Triangular Structured Matrix - grb::StructuredMatrix< double, grb::structures::UpperTriangular > U( n, n ); + alp::Matrix< double, alp::structures::UpperTriangular > U( n, n ); - // Initialize StructuredMatrix + // Initialize Matrix std::vector< double > Mdata ( n * n, 1 ); buildUpperTriangularRawArray( Mdata, n ); - rc = grb::buildMatrix( U, Mdata.begin(), Mdata.end() ); - if( rc != grb::SUCCESS ) { + rc = alp::buildMatrix( U, Mdata.begin(), Mdata.end() ); + if( rc != alp::SUCCESS ) { return; } @@ -71,9 +71,9 @@ void grb_program( const size_t & n, grb::RC & rc ) { "|. . . . x x|\n" "|. . . . . x|\n"; try { - auto Uview1 = grb::get_view< grb::structures::UpperTriangular >( + auto Uview1 = alp::get_view< alp::structures::UpperTriangular >( U, - grb::utils::range(1,3), grb::utils::range(1,3) + alp::utils::range(1,3), alp::utils::range(1,3) ); std::cout << "\tSUCCESS\n"; } catch( const std::exception & e ) { @@ -89,9 +89,9 @@ void grb_program( const size_t & n, grb::RC & rc ) { "|. . . . x x|\n" "|. . . . . x|\n"; try { - auto Uview2 = grb::get_view< grb::structures::General >( + auto Uview2 = alp::get_view< alp::structures::General >( U, - grb::utils::range(0,2), grb::utils::range(3,5) + alp::utils::range(0,2), alp::utils::range(3,5) ); std::cout << "\tSUCCESS\n"; } catch( const std::exception & e ) { @@ -107,9 +107,9 @@ void grb_program( const size_t & n, grb::RC & rc ) { "|. . . . x x|\n" "|. . . . . x|\n"; try { - auto Uview3 = grb::get_view< grb::structures::UpperTriangular >( + auto Uview3 = alp::get_view< alp::structures::UpperTriangular >( U, - grb::utils::range(1,3), grb::utils::range(1,5) + alp::utils::range(1,3), alp::utils::range(1,5) ); std::cout << "\tSUCCESS\n"; } catch( const std::exception & e ) { @@ -125,16 +125,16 @@ void grb_program( const size_t & n, grb::RC & rc ) { "|A A . . x x|\n" "|A A . . . x|\n"; try { - auto Uview4 = grb::get_view< grb::structures::General >( + auto Uview4 = alp::get_view< alp::structures::General >( U, - grb::utils::range(4,n), grb::utils::range(0,2) + alp::utils::range(4,n), alp::utils::range(0,2) ); std::cout << "\tSUCCESS\n"; } catch( const std::exception & e ) { std::cerr << e.what() << "\n"; } - rc = grb::SUCCESS; + rc = alp::SUCCESS; } int main( int argc, char ** argv ) { @@ -174,14 +174,14 @@ int main( int argc, char ** argv ) { } std::cout << "This is functional test " << argv[ 0 ] << "\n"; - grb::Launcher< grb::AUTOMATIC > launcher; - grb::RC out; - if( launcher.exec( &grb_program, in, out, true ) != grb::SUCCESS ) { + alp::Launcher< alp::AUTOMATIC > launcher; + alp::RC out; + if( launcher.exec( &alp_program, in, out, true ) != alp::SUCCESS ) { std::cerr << "Launching test FAILED\n"; return 255; } - if( out != grb::SUCCESS ) { - std::cerr << "Test FAILED (" << grb::toString( out ) << ")" << std::endl; + if( out != alp::SUCCESS ) { + std::cerr << "Test FAILED (" << alp::toString( out ) << ")" << std::endl; } else { std::cout << "Test OK" << std::endl; } diff --git a/tests/unit/dense_mxm.cpp b/tests/unit/dense_mxm.cpp index df6425e0d..dffa0c0a8 100644 --- a/tests/unit/dense_mxm.cpp +++ b/tests/unit/dense_mxm.cpp @@ -19,51 +19,41 @@ #include #include -#include +#include -using namespace grb; +using namespace alp; template< typename Structure > -void print_matrix( const grb::StructuredMatrix< double, Structure > & A) { +void print_matrix( const alp::Matrix< double, Structure > & A) { (void)A; - // if( ! grb::internal::getInitialized< double >( A ) ) { + // if( ! alp::internal::getInitialized< double >( A ) ) { // std::cout << "Matrix is uninitialized, nothing to print.\n"; // return; // } - // const double * Araw = grb::getRaw( internal::getContainer( A ) ); - // for( size_t row = 0; row < grb::nrows( A ); ++row ) { - // for( size_t col = 0; col < grb::ncols( A ); ++col ) { - // std::cout << Araw[row * grb::ncols( A ) + col] << " "; + // const double * Araw = alp::getRaw( internal::getContainer( A ) ); + // for( size_t row = 0; row < alp::nrows( A ); ++row ) { + // for( size_t col = 0; col < alp::ncols( A ); ++col ) { + // std::cout << Araw[row * alp::ncols( A ) + col] << " "; // } // std::cout << "\n"; // } } -void grb_program( const size_t & n, grb::RC & rc ) { - grb::Semiring< grb::operators::add< double >, grb::operators::mul< double >, grb::identities::zero, grb::identities::one > ring; +void alp_program( const size_t & n, alp::RC & rc ) { + alp::Semiring< alp::operators::add< double >, alp::operators::mul< double >, alp::identities::zero, alp::identities::one > ring; std::cout << "\tTesting dense mxm\n"; // initialize test - grb::StructuredMatrix< double, structures::General > A( n, n ); - grb::StructuredMatrix< double, structures::General > B( n, n ); - grb::StructuredMatrix< double, structures::General > C( n, n ); + alp::Matrix< double, structures::General > A( n, n ); + alp::Matrix< double, structures::General > B( n, n ); + alp::Matrix< double, structures::General > C( n, n ); std::vector< double > A_data( n * n, 1 ); std::vector< double > B_data( n * n, 1 ); - std::cout << "_GRB_BACKEND = " << _GRB_BACKEND << "\n"; - - #ifdef _GRB_WITH_REFERENCE - std::cout << "_GRB_WITH_REFERENCE defined\n"; - #endif - - #ifdef _GRB_WITH_DENSEREF - std::cout << "_GRB_WITH_DENSEREF defined\n"; - #endif - // Initialize input matrices - rc = grb::buildMatrix( A, A_data.begin(), A_data.end() ); + rc = alp::buildMatrix( A, A_data.begin(), A_data.end() ); if( rc == SUCCESS ) { - rc = grb::buildMatrix( B, B_data.begin(), B_data.end() ); + rc = alp::buildMatrix( B, B_data.begin(), B_data.end() ); } @@ -73,7 +63,7 @@ void grb_program( const size_t & n, grb::RC & rc ) { print_matrix( C ); if( rc == SUCCESS ) { - rc = grb::mxm( C, A, B, ring ); + rc = alp::mxm( C, A, B, ring ); } print_matrix( C ); @@ -114,14 +104,14 @@ int main( int argc, char ** argv ) { } std::cout << "This is functional test " << argv[ 0 ] << "\n"; - grb::Launcher< AUTOMATIC > launcher; - grb::RC out; - if( launcher.exec( &grb_program, in, out, true ) != SUCCESS ) { + alp::Launcher< AUTOMATIC > launcher; + alp::RC out; + if( launcher.exec( &alp_program, in, out, true ) != SUCCESS ) { std::cerr << "Launching test FAILED\n"; return 255; } if( out != SUCCESS ) { - std::cerr << "Test FAILED (" << grb::toString( out ) << ")" << std::endl; + std::cerr << "Test FAILED (" << alp::toString( out ) << ")" << std::endl; } else { std::cout << "Test OK" << std::endl; } diff --git a/tests/unit/dense_outer.cpp b/tests/unit/dense_outer.cpp index 3e9b6fbc7..66fe53008 100644 --- a/tests/unit/dense_outer.cpp +++ b/tests/unit/dense_outer.cpp @@ -18,10 +18,10 @@ #include #include -#include "graphblas.hpp" +#include "alp.hpp" -using namespace grb; +using namespace alp; // sample data static const double vec1_vals[ 3 ] = { 1, 2, 3 }; @@ -35,8 +35,8 @@ static const double test1_expect[ 3 ] = { 24, 30, 36 }; static const double test2_in[ 3 ] = { 1, 1, 1 }; static const double test2_expect[ 3 ] = { 15, 30, 45 }; -// graphblas program -void grbProgram( const void *, const size_t in_size, int &error ) { +// alp program +void alpProgram( const void *, const size_t in_size, int &error ) { /** \internal TODO: Implement initialization and result checking. * Currently only serves as the interface showcase. * */ @@ -49,25 +49,25 @@ void grbProgram( const void *, const size_t in_size, int &error ) { } // allocate - grb::VectorView< double > u( 3 ); - grb::VectorView< double > v( 3 ); - grb::StructuredMatrix< double, structures::General > M( 3, 3 ); - // grb::Vector< double > test1( 3 ); - // grb::Vector< double > out1( 3 ); - // grb::Vector< double > test2( 3 ); - // grb::Vector< double > out2( 3 ); + alp::Vector< double > u( 3 ); + alp::Vector< double > v( 3 ); + alp::Matrix< double, structures::General > M( 3, 3 ); + // alp::Vector< double > test1( 3 ); + // alp::Vector< double > out1( 3 ); + // alp::Vector< double > test2( 3 ); + // alp::Vector< double > out2( 3 ); // semiring - grb::Semiring< - grb::operators::add< double >, grb::operators::mul< double >, - grb::identities::zero, grb::identities::one + alp::Semiring< + alp::operators::add< double >, alp::operators::mul< double >, + alp::identities::zero, alp::identities::one > ring; - grb::RC rc; + alp::RC rc; // initialise vec // const double * vec_iter = &(vec1_vals[ 0 ]); - // grb::RC rc = grb::buildVector( u, vec_iter, vec_iter + 3, SEQUENTIAL ); + // alp::RC rc = alp::buildVector( u, vec_iter, vec_iter + 3, SEQUENTIAL ); // if( rc != SUCCESS ) { // std::cerr << "\t initial buildVector FAILED\n"; // error = 5; @@ -75,7 +75,7 @@ void grbProgram( const void *, const size_t in_size, int &error ) { // if( !error ) { // vec_iter = &(vec2_vals[ 0 ]); - // rc = grb::buildVector( v, vec_iter, vec_iter + 3, SEQUENTIAL ); + // rc = alp::buildVector( v, vec_iter, vec_iter + 3, SEQUENTIAL ); // } // if( rc != SUCCESS ) { // std::cerr << "\t initial buildVector FAILED\n"; @@ -83,8 +83,8 @@ void grbProgram( const void *, const size_t in_size, int &error ) { // } if( !error ) { - rc = grb::outer( M, u, v, ring.getMultiplicativeOperator()); - rc = rc ? rc : grb::outer( M, u, v, ring.getMultiplicativeOperator() ); + rc = alp::outer( M, u, v, ring.getMultiplicativeOperator()); + rc = rc ? rc : alp::outer( M, u, v, ring.getMultiplicativeOperator() ); } } @@ -94,8 +94,8 @@ int main( int argc, char ** argv ) { std::cout << "Functional test executable: " << argv[ 0 ] << "\n"; int error; - grb::Launcher< AUTOMATIC > launcher; - if( launcher.exec( &grbProgram, NULL, 0, error ) != SUCCESS ) { + alp::Launcher< AUTOMATIC > launcher; + if( launcher.exec( &alpProgram, NULL, 0, error ) != SUCCESS ) { std::cerr << "Test failed to launch\n"; error = 255; } diff --git a/tests/unit/dense_structured_matrix.cpp b/tests/unit/dense_structured_matrix.cpp index 762bcf34f..9b2be3b84 100644 --- a/tests/unit/dense_structured_matrix.cpp +++ b/tests/unit/dense_structured_matrix.cpp @@ -22,35 +22,35 @@ #include #include -#include +#include template< typename StructuredMat > void ask_questions( const StructuredMat & M, std::string name ) { using M_type = typename std::remove_const< typename std::remove_reference< decltype( M ) >::type >::type; - std::cout << name << "( " << grb::nrows( M ) << ", " << grb::ncols( M ) << " )" << std::endl; + std::cout << name << "( " << alp::nrows( M ) << ", " << alp::ncols( M ) << " )" << std::endl; std::cout << "Is " << name << ":" << std::endl; - std::cout << "\ta structured Matrix? " << grb::is_structured_matrix< M_type >::value << std::endl; - std::cout << "\tgeneral? " << grb::structures::is_a< M_type, grb::structures::General >::value << std::endl; - std::cout << "\tsquare? " << grb::structures::is_a< M_type, grb::structures::Square >::value << std::endl; - std::cout << "\tfull rank? " << grb::structures::is_a< M_type, grb::structures::FullRank >::value << std::endl; - std::cout << "\tnon-singular? " << grb::structures::is_a< M_type, grb::structures::NonSingular >::value << std::endl; + std::cout << "\ta structured Matrix? " << alp::is_structured_matrix< M_type >::value << std::endl; + std::cout << "\tgeneral? " << alp::structures::is_a< M_type, alp::structures::General >::value << std::endl; + std::cout << "\tsquare? " << alp::structures::is_a< M_type, alp::structures::Square >::value << std::endl; + std::cout << "\tfull rank? " << alp::structures::is_a< M_type, alp::structures::FullRank >::value << std::endl; + std::cout << "\tnon-singular? " << alp::structures::is_a< M_type, alp::structures::NonSingular >::value << std::endl; } -void grb_program( const size_t & n, grb::RC & rc ) { +void alp_program( const size_t & n, alp::RC & rc ) { std::cout << "\tStarting structured matrices test with size: " << n << "\n"; // initialize test - grb::StructuredMatrix< float, grb::structures::General > M( n, n ); - grb::StructuredMatrix< float, grb::structures::Square > A( n ); - grb::StructuredMatrix< float, grb::structures::NonSingular > B( n, n ); - grb::StructuredMatrix< float, grb::structures::FullRank > C( n, 2 * n ); - auto At = grb::get_view< grb::view::transpose >( A ); - auto Mt = grb::get_view< grb::view::transpose >( M ); - auto Mview = grb::get_view( M, grb::utils::range(0,4), grb::utils::range(0,4) ); - auto Sq_Mref = grb::get_view< grb::structures::Square > ( M ); + alp::Matrix< float, alp::structures::General > M( n, n ); + alp::Matrix< float, alp::structures::Square > A( n ); + alp::Matrix< float, alp::structures::NonSingular > B( n, n ); + alp::Matrix< float, alp::structures::FullRank > C( n, 2 * n ); + auto At = alp::get_view< alp::view::transpose >( A ); + auto Mt = alp::get_view< alp::view::transpose >( M ); + auto Mview = alp::get_view( M, alp::utils::range(0,4), alp::utils::range(0,4) ); + auto Sq_Mref = alp::get_view< alp::structures::Square > ( M ); ask_questions( M, "M" ); ask_questions( A, "A" ); @@ -62,18 +62,18 @@ void grb_program( const size_t & n, grb::RC & rc ) { ask_questions( Mview, "Mview" ); ask_questions( Sq_Mref, "Sq_Mref" ); - auto v_diag = grb::get_view< grb::view::diagonal >( M ); - auto v_view1 = grb::get_view( v_diag ); - auto v_view2 = grb::get_view( v_diag, grb::utils::range(1,2) ); - std::cout << "v_diag( " << grb::getLength( v_diag ) << " )" << std::endl; - std::cout << "v_view1( " << grb::getLength( v_view1 ) << " )" << std::endl; - std::cout << "v_view2( " << grb::getLength( v_view2 ) << " )" << std::endl; - - grb::StructuredMatrix< float, grb::structures::Band< grb::Interval<-2, 5> > > BM0( n, n ); - grb::StructuredMatrix< float, grb::structures::Band< grb::RightOpenInterval<-2> > > BM1( n, n ); - grb::StructuredMatrix< float, grb::structures::Band< grb::LeftOpenInterval<-2> > > BM2( n, n ); - grb::StructuredMatrix< double, grb::structures::Band< grb::Interval<-2>, grb::Interval<1>, grb::Interval<3> > > BM3( n, n ); - rc = grb::SUCCESS; + auto v_diag = alp::get_view< alp::view::diagonal >( M ); + auto v_view1 = alp::get_view( v_diag ); + auto v_view2 = alp::get_view( v_diag, alp::utils::range(1,2) ); + std::cout << "v_diag( " << alp::getLength( v_diag ) << " )" << std::endl; + std::cout << "v_view1( " << alp::getLength( v_view1 ) << " )" << std::endl; + std::cout << "v_view2( " << alp::getLength( v_view2 ) << " )" << std::endl; + + alp::Matrix< float, alp::structures::Band< alp::Interval<-2, 5> > > BM0( n, n ); + alp::Matrix< float, alp::structures::Band< alp::RightOpenInterval<-2> > > BM1( n, n ); + alp::Matrix< float, alp::structures::Band< alp::LeftOpenInterval<-2> > > BM2( n, n ); + alp::Matrix< double, alp::structures::Band< alp::Interval<-2>, alp::Interval<1>, alp::Interval<3> > > BM3( n, n ); + rc = alp::SUCCESS; } int main( int argc, char ** argv ) { @@ -110,14 +110,14 @@ int main( int argc, char ** argv ) { } std::cout << "This is functional test " << argv[ 0 ] << "\n"; - grb::Launcher< grb::AUTOMATIC > launcher; - grb::RC out; - if( launcher.exec( &grb_program, in, out, true ) != grb::SUCCESS ) { + alp::Launcher< alp::AUTOMATIC > launcher; + alp::RC out; + if( launcher.exec( &alp_program, in, out, true ) != alp::SUCCESS ) { std::cerr << "Launching test FAILED\n"; return 255; } - if( out != grb::SUCCESS ) { - std::cerr << "Test FAILED (" << grb::toString( out ) << ")" << std::endl; + if( out != alp::SUCCESS ) { + std::cerr << "Test FAILED (" << alp::toString( out ) << ")" << std::endl; } else { std::cout << "Test OK" << std::endl; } From 66b497ead31c6c7c77c0a770ab91745c065fffeb Mon Sep 17 00:00:00 2001 From: Anonymous Date: Mon, 4 Apr 2022 13:30:05 +0200 Subject: [PATCH 122/282] Add doxygen configuration file for public ALP API --- docs/alp-public.conf | 2453 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 2453 insertions(+) create mode 100644 docs/alp-public.conf diff --git a/docs/alp-public.conf b/docs/alp-public.conf new file mode 100644 index 000000000..937501d52 --- /dev/null +++ b/docs/alp-public.conf @@ -0,0 +1,2453 @@ +# Doxyfile 1.8.14 + +# +# Copyright 2021 Huawei Technologies Co., Ltd. +# +# 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. +# + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project. +# +# All text after a double hash (##) is considered a comment and is placed in +# front of the TAG it is preceding. +# +# All text after a single hash (#) is considered a comment and will be ignored. +# The format is: +# TAG = value [value, ...] +# For lists, items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (\" \"). + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the config file +# that follow. The default is UTF-8 which is also the encoding used for all text +# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv +# built into libc) for the transcoding. See +# https://www.gnu.org/software/libiconv/ for the list of possible encodings. +# The default value is: UTF-8. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by +# double-quotes, unless you are using Doxywizard) that should identify the +# project for which the documentation is generated. This name is used in the +# title of most generated pages and in a few other places. +# The default value is: My Project. + +PROJECT_NAME = "ALP Public API" + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. This +# could be handy for archiving the generated documentation or if some version +# control system is used. + +PROJECT_NUMBER = alpha + +# Using the PROJECT_BRIEF tag one can provide an optional one line description +# for a project that appears at the top of each page and should give viewer a +# quick idea about the purpose of the project. Keep the description short. + +PROJECT_BRIEF = + +# With the PROJECT_LOGO tag one can specify a logo or an icon that is included +# in the documentation. The maximum height of the logo should not exceed 55 +# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy +# the logo to the output directory. + +PROJECT_LOGO = + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path +# into which the generated documentation will be written. If a relative path is +# entered, it will be relative to the location where doxygen was started. If +# left blank the current directory will be used. + +OUTPUT_DIRECTORY = docs/alp-public + +# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub- +# directories (in 2 levels) under the output directory of each output format and +# will distribute the generated files over these directories. Enabling this +# option can be useful when feeding doxygen a huge amount of source files, where +# putting all generated files in the same directory would otherwise causes +# performance problems for the file system. +# The default value is: NO. + +CREATE_SUBDIRS = NO + +# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII +# characters to appear in the names of generated files. If set to NO, non-ASCII +# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode +# U+3044. +# The default value is: NO. + +ALLOW_UNICODE_NAMES = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese, +# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States), +# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian, +# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages), +# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian, +# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian, +# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish, +# Ukrainian and Vietnamese. +# The default value is: English. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member +# descriptions after the members that are listed in the file and class +# documentation (similar to Javadoc). Set to NO to disable this. +# The default value is: YES. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief +# description of a member or function before the detailed description +# +# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. +# The default value is: YES. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator that is +# used to form the text in various listings. Each string in this list, if found +# as the leading text of the brief description, will be stripped from the text +# and the result, after processing the whole list, is used as the annotated +# text. Otherwise, the brief description is used as-is. If left blank, the +# following values are used ($name is automatically replaced with the name of +# the entity):The $name class, The $name widget, The $name file, is, provides, +# specifies, contains, represents, a, an and the. + +ABBREVIATE_BRIEF = + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# doxygen will generate a detailed section even if there is only a brief +# description. +# The default value is: NO. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. +# The default value is: NO. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path +# before files name in the file list and in the header files. If set to NO the +# shortest path that makes the file name unique will be used +# The default value is: YES. + +FULL_PATH_NAMES = YES + +# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. +# Stripping is only done if one of the specified strings matches the left-hand +# part of the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the path to +# strip. +# +# Note that you can specify absolute paths here, but also relative paths, which +# will be relative from the directory where doxygen is started. +# This tag requires that the tag FULL_PATH_NAMES is set to YES. + +STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the +# path mentioned in the documentation of a class, which tells the reader which +# header file to include in order to use a class. If left blank only the name of +# the header file containing the class definition is used. Otherwise one should +# specify the list of include paths that are normally passed to the compiler +# using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but +# less readable) file names. This can be useful is your file systems doesn't +# support long names like on DOS, Mac, or CD-ROM. +# The default value is: NO. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the +# first line (until the first dot) of a Javadoc-style comment as the brief +# description. If set to NO, the Javadoc-style will behave just like regular Qt- +# style comments (thus requiring an explicit @brief command for a brief +# description.) +# The default value is: NO. + +JAVADOC_AUTOBRIEF = YES + +# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first +# line (until the first dot) of a Qt-style comment as the brief description. If +# set to NO, the Qt-style will behave just like regular Qt-style comments (thus +# requiring an explicit \brief command for a brief description.) +# The default value is: NO. + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a +# multi-line C++ special comment block (i.e. a block of //! or /// comments) as +# a brief description. This used to be the default behavior. The new default is +# to treat a multi-line C++ comment block as a detailed description. Set this +# tag to YES if you prefer the old behavior instead. +# +# Note that setting this tag to YES also means that rational rose comments are +# not recognized any more. +# The default value is: NO. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the +# documentation from any documented member that it re-implements. +# The default value is: YES. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new +# page for each member. If set to NO, the documentation of a member will be part +# of the file/class/namespace that contains it. +# The default value is: NO. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen +# uses this value to replace tabs by spaces in code fragments. +# Minimum value: 1, maximum value: 16, default value: 4. + +TAB_SIZE = 4 + +# This tag can be used to specify a number of aliases that act as commands in +# the documentation. An alias has the form: +# name=value +# For example adding +# "sideeffect=@par Side Effects:\n" +# will allow you to put the command \sideeffect (or @sideeffect) in the +# documentation, which will result in a user-defined paragraph with heading +# "Side Effects:". You can put \n's in the value part of an alias to insert +# newlines (in the resulting output). You can put ^^ in the value part of an +# alias to insert a newline as if a physical newline was in the original file. + +ALIASES = + +# This tag can be used to specify a number of word-keyword mappings (TCL only). +# A mapping has the form "name=value". For example adding "class=itcl::class" +# will allow you to use the command class in the itcl::class meaning. + +TCL_SUBST = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources +# only. Doxygen will then generate output that is more tailored for C. For +# instance, some of the names that are used will be different. The list of all +# members will be omitted, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_FOR_C = NO + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or +# Python sources only. Doxygen will then generate output that is more tailored +# for that language. For instance, namespaces will be presented as packages, +# qualified scopes will look different, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources. Doxygen will then generate output that is tailored for Fortran. +# The default value is: NO. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for VHDL. +# The default value is: NO. + +OPTIMIZE_OUTPUT_VHDL = NO + +# Doxygen selects the parser to use depending on the extension of the files it +# parses. With this tag you can assign which parser to use for a given +# extension. Doxygen has a built-in mapping, but you can override or extend it +# using this tag. The format is ext=language, where ext is a file extension, and +# language is one of the parsers supported by doxygen: IDL, Java, Javascript, +# C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran: +# FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran: +# Fortran. In the later case the parser tries to guess whether the code is fixed +# or free formatted code, this is the default for Fortran type files), VHDL. For +# instance to make doxygen treat .inc files as Fortran files (default is PHP), +# and .f files as C (default is Fortran), use: inc=Fortran f=C. +# +# Note: For files without extension you can use no_extension as a placeholder. +# +# Note that for custom extensions you also need to set FILE_PATTERNS otherwise +# the files are not read by doxygen. + +EXTENSION_MAPPING = + +# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments +# according to the Markdown format, which allows for more readable +# documentation. See http://daringfireball.net/projects/markdown/ for details. +# The output of markdown processing is further processed by doxygen, so you can +# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in +# case of backward compatibilities issues. +# The default value is: YES. + +MARKDOWN_SUPPORT = YES + +# When the TOC_INCLUDE_HEADINGS tag is set to a non-zero value, all headings up +# to that level are automatically included in the table of contents, even if +# they do not have an id attribute. +# Note: This feature currently applies only to Markdown headings. +# Minimum value: 0, maximum value: 99, default value: 0. +# This tag requires that the tag MARKDOWN_SUPPORT is set to YES. + +TOC_INCLUDE_HEADINGS = 0 + +# When enabled doxygen tries to link words that correspond to documented +# classes, or namespaces to their corresponding documentation. Such a link can +# be prevented in individual cases by putting a % sign in front of the word or +# globally by setting AUTOLINK_SUPPORT to NO. +# The default value is: YES. + +AUTOLINK_SUPPORT = YES + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should set this +# tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); +# versus func(std::string) {}). This also make the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. +# The default value is: NO. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. +# The default value is: NO. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip (see: +# https://www.riverbankcomputing.com/software/sip/intro) sources only. Doxygen +# will parse them like normal C++ but will assume all classes use public instead +# of private inheritance when no explicit protection keyword is present. +# The default value is: NO. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate +# getter and setter methods for a property. Setting this option to YES will make +# doxygen to replace the get and set methods by a property in the documentation. +# This will only work if the methods are indeed getting or setting a simple +# type. If this is not the case, or you want to show the methods anyway, you +# should set this option to NO. +# The default value is: YES. + +IDL_PROPERTY_SUPPORT = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. +# The default value is: NO. + +DISTRIBUTE_GROUP_DOC = NO + +# If one adds a struct or class to a group and this option is enabled, then also +# any nested class or struct is added to the same group. By default this option +# is disabled and one has to add nested compounds explicitly via \ingroup. +# The default value is: NO. + +GROUP_NESTED_COMPOUNDS = NO + +# Set the SUBGROUPING tag to YES to allow class member groups of the same type +# (for instance a group of public functions) to be put as a subgroup of that +# type (e.g. under the Public Functions section). Set it to NO to prevent +# subgrouping. Alternatively, this can be done per class using the +# \nosubgrouping command. +# The default value is: YES. + +SUBGROUPING = YES + +# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions +# are shown inside the group in which they are included (e.g. using \ingroup) +# instead of on a separate page (for HTML and Man pages) or section (for LaTeX +# and RTF). +# +# Note that this feature does not work in combination with +# SEPARATE_MEMBER_PAGES. +# The default value is: NO. + +INLINE_GROUPED_CLASSES = NO + +# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions +# with only public data fields or simple typedef fields will be shown inline in +# the documentation of the scope in which they are defined (i.e. file, +# namespace, or group documentation), provided this scope is documented. If set +# to NO, structs, classes, and unions are shown on a separate page (for HTML and +# Man pages) or section (for LaTeX and RTF). +# The default value is: NO. + +INLINE_SIMPLE_STRUCTS = NO + +# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or +# enum is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically be +# useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. +# The default value is: NO. + +TYPEDEF_HIDES_STRUCT = NO + +# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This +# cache is used to resolve symbols given their name and scope. Since this can be +# an expensive process and often the same symbol appears multiple times in the +# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small +# doxygen will become slower. If the cache is too large, memory is wasted. The +# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range +# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 +# symbols. At the end of a run doxygen will report the cache usage and suggest +# the optimal cache size from a speed point of view. +# Minimum value: 0, maximum value: 9, default value: 0. + +LOOKUP_CACHE_SIZE = 0 + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in +# documentation are documented, even if no documentation was available. Private +# class members and static file members will be hidden unless the +# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. +# Note: This will also disable the warnings about undocumented members that are +# normally produced when WARNINGS is set to YES. +# The default value is: NO. + +EXTRACT_ALL = NO + +# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will +# be included in the documentation. +# The default value is: NO. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal +# scope will be included in the documentation. +# The default value is: NO. + +EXTRACT_PACKAGE = NO + +# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be +# included in the documentation. +# The default value is: NO. + +EXTRACT_STATIC = YES + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined +# locally in source files will be included in the documentation. If set to NO, +# only classes defined in header files are included. Does not have any effect +# for Java sources. +# The default value is: YES. + +EXTRACT_LOCAL_CLASSES = NO + +# This flag is only useful for Objective-C code. If set to YES, local methods, +# which are defined in the implementation section but not in the interface are +# included in the documentation. If set to NO, only methods in the interface are +# included. +# The default value is: NO. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base name of +# the file that contains the anonymous namespace. By default anonymous namespace +# are hidden. +# The default value is: NO. + +EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all +# undocumented members inside documented classes or files. If set to NO these +# members will be included in the various overviews, but no documentation +# section is generated. This option has no effect if EXTRACT_ALL is enabled. +# The default value is: NO. + +HIDE_UNDOC_MEMBERS = YES + +# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. If set +# to NO, these classes will be included in the various overviews. This option +# has no effect if EXTRACT_ALL is enabled. +# The default value is: NO. + +HIDE_UNDOC_CLASSES = YES + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend +# (class|struct|union) declarations. If set to NO, these declarations will be +# included in the documentation. +# The default value is: NO. + +HIDE_FRIEND_COMPOUNDS = YES + +# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any +# documentation blocks found inside the body of a function. If set to NO, these +# blocks will be appended to the function's detailed documentation block. +# The default value is: NO. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation that is typed after a +# \internal command is included. If the tag is set to NO then the documentation +# will be excluded. Set it to YES to include the internal documentation. +# The default value is: NO. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file +# names in lower-case letters. If set to YES, upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. +# The default value is: system dependent. + +CASE_SENSE_NAMES = YES + +# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with +# their full class and namespace scopes in the documentation. If set to YES, the +# scope will be hidden. +# The default value is: NO. + +HIDE_SCOPE_NAMES = YES + +# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will +# append additional text to a page's title, such as Class Reference. If set to +# YES the compound reference will be hidden. +# The default value is: NO. + +HIDE_COMPOUND_REFERENCE= NO + +# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of +# the files that are included by a file in the documentation of that file. +# The default value is: YES. + +SHOW_INCLUDE_FILES = NO + +# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each +# grouped member an include statement to the documentation, telling the reader +# which file to include in order to use the member. +# The default value is: NO. + +SHOW_GROUPED_MEMB_INC = NO + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include +# files with double quotes in the documentation rather than with sharp brackets. +# The default value is: NO. + +FORCE_LOCAL_INCLUDES = NO + +# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the +# documentation for inline members. +# The default value is: YES. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the +# (detailed) documentation of file and class members alphabetically by member +# name. If set to NO, the members will appear in declaration order. +# The default value is: YES. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief +# descriptions of file, namespace and class members alphabetically by member +# name. If set to NO, the members will appear in declaration order. Note that +# this will also influence the order of the classes in the class list. +# The default value is: NO. + +SORT_BRIEF_DOCS = YES + +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the +# (brief and detailed) documentation of class members so that constructors and +# destructors are listed first. If set to NO the constructors will appear in the +# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. +# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief +# member documentation. +# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting +# detailed member documentation. +# The default value is: NO. + +SORT_MEMBERS_CTORS_1ST = NO + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy +# of group names into alphabetical order. If set to NO the group names will +# appear in their defined order. +# The default value is: NO. + +SORT_GROUP_NAMES = YES + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by +# fully-qualified names, including namespaces. If set to NO, the class list will +# be sorted only by class name, not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the alphabetical +# list. +# The default value is: NO. + +SORT_BY_SCOPE_NAME = NO + +# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper +# type resolution of all parameters of a function it will reject a match between +# the prototype and the implementation of a member function even if there is +# only one candidate or it is obvious which candidate to choose by doing a +# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still +# accept a match between prototype and implementation in such cases. +# The default value is: NO. + +STRICT_PROTO_MATCHING = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo +# list. This list is created by putting \todo commands in the documentation. +# The default value is: YES. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test +# list. This list is created by putting \test commands in the documentation. +# The default value is: YES. + +GENERATE_TESTLIST = NO + +# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug +# list. This list is created by putting \bug commands in the documentation. +# The default value is: YES. + +GENERATE_BUGLIST = NO + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO) +# the deprecated list. This list is created by putting \deprecated commands in +# the documentation. +# The default value is: YES. + +GENERATE_DEPRECATEDLIST= NO + +# The ENABLED_SECTIONS tag can be used to enable conditional documentation +# sections, marked by \if ... \endif and \cond +# ... \endcond blocks. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the +# initial value of a variable or macro / define can have for it to appear in the +# documentation. If the initializer consists of more lines than specified here +# it will be hidden. Use a value of 0 to hide initializers completely. The +# appearance of the value of individual variables and macros / defines can be +# controlled using \showinitializer or \hideinitializer command in the +# documentation regardless of this setting. +# Minimum value: 0, maximum value: 10000, default value: 30. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at +# the bottom of the documentation of classes and structs. If set to YES, the +# list will mention the files that were used to generate the documentation. +# The default value is: YES. + +SHOW_USED_FILES = NO + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This +# will remove the Files entry from the Quick Index and from the Folder Tree View +# (if specified). +# The default value is: YES. + +SHOW_FILES = NO + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces +# page. This will remove the Namespaces entry from the Quick Index and from the +# Folder Tree View (if specified). +# The default value is: YES. + +SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command command input-file, where command is the value of the +# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided +# by doxygen. Whatever the program writes to standard output is used as the file +# version. For an example see the documentation. + +FILE_VERSION_FILTER = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed +# by doxygen. The layout file controls the global structure of the generated +# output files in an output format independent way. To create the layout file +# that represents doxygen's defaults, run doxygen with the -l option. You can +# optionally specify a file name after the option, if omitted DoxygenLayout.xml +# will be used as the name of the layout file. +# +# Note that if you run doxygen from a directory containing a file called +# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE +# tag is left empty. + +LAYOUT_FILE = + +# The CITE_BIB_FILES tag can be used to specify one or more bib files containing +# the reference definitions. This must be a list of .bib files. The .bib +# extension is automatically appended if omitted. This requires the bibtex tool +# to be installed. See also https://en.wikipedia.org/wiki/BibTeX for more info. +# For LaTeX the style of the bibliography can be controlled using +# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the +# search path. See also \cite for info how to create references. + +CITE_BIB_FILES = + +#--------------------------------------------------------------------------- +# Configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated to +# standard output by doxygen. If QUIET is set to YES this implies that the +# messages are off. +# The default value is: NO. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES +# this implies that the warnings are on. +# +# Tip: Turn warnings on while writing the documentation. +# The default value is: YES. + +WARNINGS = YES + +# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate +# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag +# will automatically be disabled. +# The default value is: YES. + +WARN_IF_UNDOCUMENTED = YES + +# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some parameters +# in a documented function, or documenting parameters that don't exist or using +# markup commands wrongly. +# The default value is: YES. + +WARN_IF_DOC_ERROR = YES + +# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that +# are documented, but have no documentation for their parameters or return +# value. If set to NO, doxygen will only warn about wrong or incomplete +# parameter documentation, but not about the absence of documentation. +# The default value is: NO. + +WARN_NO_PARAMDOC = NO + +# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when +# a warning is encountered. +# The default value is: NO. + +WARN_AS_ERROR = NO + +# The WARN_FORMAT tag determines the format of the warning messages that doxygen +# can produce. The string should contain the $file, $line, and $text tags, which +# will be replaced by the file and line number from which the warning originated +# and the warning text. Optionally the format may contain $version, which will +# be replaced by the version of the file (if it could be obtained via +# FILE_VERSION_FILTER) +# The default value is: $file:$line: $text. + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning and error +# messages should be written. If left blank the output is written to standard +# error (stderr). + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# Configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag is used to specify the files and/or directories that contain +# documented source files. You may enter file names like myfile.cpp or +# directories like /usr/src/myproject. Separate the files or directories with +# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING +# Note: If this tag is empty the current directory is searched. + +INPUT = include/alp.hpp \ + include/alp/ + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses +# libiconv (or the iconv built into libc) for the transcoding. See the libiconv +# documentation (see: https://www.gnu.org/software/libiconv/) for the list of +# possible encodings. +# The default value is: UTF-8. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and +# *.h) to filter out the source-files in the directories. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# read by doxygen. +# +# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp, +# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, +# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, +# *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, +# *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf and *.qsf. + +FILE_PATTERNS = *.hpp \ + *.cpp \ + *.h \ + *.c + +# The RECURSIVE tag can be used to specify whether or not subdirectories should +# be searched for input files as well. +# The default value is: NO. + +RECURSIVE = YES + +# The EXCLUDE tag can be used to specify files and/or directories that should be +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. +# +# Note that relative paths are relative to the directory from which doxygen is +# run. + +EXCLUDE = include/alp/base + +# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or +# directories that are symbolic links (a Unix file system feature) are excluded +# from the input. +# The default value is: NO. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories for example use the pattern */test/* + +EXCLUDE_PATTERNS = + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories use the pattern */test/* + +EXCLUDE_SYMBOLS = internal \ + IMF \ + imf \ + AutoDeleter \ + SizeOf + +# The EXAMPLE_PATH tag can be used to specify one or more files or directories +# that contain example code fragments that are included (see the \include +# command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and +# *.h) to filter out the source-files in the directories. If left blank all +# files are included. + +EXAMPLE_PATTERNS = + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude commands +# irrespective of the value of the RECURSIVE tag. +# The default value is: NO. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or directories +# that contain images that are to be included in the documentation (see the +# \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command: +# +# +# +# where is the value of the INPUT_FILTER tag, and is the +# name of an input file. Doxygen will then use the output that the filter +# program writes to standard output. If FILTER_PATTERNS is specified, this tag +# will be ignored. +# +# Note that the filter must not add or remove lines; it is applied before the +# code is scanned, but not when the output code is generated. If lines are added +# or removed, the anchors will not be placed correctly. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# properly processed by doxygen. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: pattern=filter +# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how +# filters are used. If the FILTER_PATTERNS tag is empty or if none of the +# patterns match the file name, INPUT_FILTER is applied. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# properly processed by doxygen. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will also be used to filter the input files that are used for +# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). +# The default value is: NO. + +FILTER_SOURCE_FILES = NO + +# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file +# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and +# it is also possible to disable source filtering for a specific pattern using +# *.ext= (so without naming a filter). +# This tag requires that the tag FILTER_SOURCE_FILES is set to YES. + +FILTER_SOURCE_PATTERNS = + +# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that +# is part of the input, its contents will be placed on the main page +# (index.html). This can be useful if you have a project on for instance GitHub +# and want to reuse the introduction page also for the doxygen output. + +USE_MDFILE_AS_MAINPAGE = + +#--------------------------------------------------------------------------- +# Configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will be +# generated. Documented entities will be cross-referenced with these sources. +# +# Note: To get rid of all source code in the generated output, make sure that +# also VERBATIM_HEADERS is set to NO. +# The default value is: NO. + +SOURCE_BROWSER = NO + +# Setting the INLINE_SOURCES tag to YES will include the body of functions, +# classes and enums directly into the documentation. +# The default value is: NO. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any +# special comment blocks from generated source code fragments. Normal C, C++ and +# Fortran comments will always remain visible. +# The default value is: YES. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES then for each documented +# function all documented functions referencing it will be listed. +# The default value is: NO. + +REFERENCED_BY_RELATION = NO + +# If the REFERENCES_RELATION tag is set to YES then for each documented function +# all documented entities called/used by that function will be listed. +# The default value is: NO. + +REFERENCES_RELATION = NO + +# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set +# to YES then the hyperlinks from functions in REFERENCES_RELATION and +# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will +# link to the documentation. +# The default value is: YES. + +REFERENCES_LINK_SOURCE = YES + +# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the +# source code will show a tooltip with additional information such as prototype, +# brief description and links to the definition and documentation. Since this +# will make the HTML file larger and loading of large files a bit slower, you +# can opt to disable this feature. +# The default value is: YES. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +SOURCE_TOOLTIPS = YES + +# If the USE_HTAGS tag is set to YES then the references to source code will +# point to the HTML generated by the htags(1) tool instead of doxygen built-in +# source browser. The htags tool is part of GNU's global source tagging system +# (see https://www.gnu.org/software/global/global.html). You will need version +# 4.8.6 or higher. +# +# To use it do the following: +# - Install the latest version of global +# - Enable SOURCE_BROWSER and USE_HTAGS in the config file +# - Make sure the INPUT points to the root of the source tree +# - Run doxygen as normal +# +# Doxygen will invoke htags (and that will in turn invoke gtags), so these +# tools must be available from the command line (i.e. in the search path). +# +# The result: instead of the source browser generated by doxygen, the links to +# source code will now point to the output of htags. +# The default value is: NO. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a +# verbatim copy of the header file for each class for which an include is +# specified. Set to NO to disable this. +# See also: Section \class. +# The default value is: YES. + +VERBATIM_HEADERS = YES + +#--------------------------------------------------------------------------- +# Configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all +# compounds will be generated. Enable this if the project contains a lot of +# classes, structs, unions or interfaces. +# The default value is: YES. + +ALPHABETICAL_INDEX = YES + +# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in +# which the alphabetical index list will be split. +# Minimum value: 1, maximum value: 20, default value: 5. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all classes will +# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag +# can be used to specify a prefix (or a list of prefixes) that should be ignored +# while generating the index headers. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output +# The default value is: YES. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a +# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of +# it. +# The default directory is: html. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each +# generated HTML page (for example: .htm, .php, .asp). +# The default value is: .html. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a user-defined HTML header file for +# each generated HTML page. If the tag is left blank doxygen will generate a +# standard header. +# +# To get valid HTML the header file that includes any scripts and style sheets +# that doxygen needs, which is dependent on the configuration options used (e.g. +# the setting GENERATE_TREEVIEW). It is highly recommended to start with a +# default header using +# doxygen -w html new_header.html new_footer.html new_stylesheet.css +# YourConfigFile +# and then modify the file new_header.html. See also section "Doxygen usage" +# for information on how to generate the default header that doxygen normally +# uses. +# Note: The header is subject to change so you typically have to regenerate the +# default header when upgrading to a newer version of doxygen. For a description +# of the possible markers and block names see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each +# generated HTML page. If the tag is left blank doxygen will generate a standard +# footer. See HTML_HEADER for more information on how to generate a default +# footer and what special commands can be used inside the footer. See also +# section "Doxygen usage" for information on how to generate the default footer +# that doxygen normally uses. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style +# sheet that is used by each HTML page. It can be used to fine-tune the look of +# the HTML output. If left blank doxygen will generate a default style sheet. +# See also section "Doxygen usage" for information on how to generate the style +# sheet that doxygen normally uses. +# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as +# it is more robust and this tag (HTML_STYLESHEET) will in the future become +# obsolete. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_STYLESHEET = + +# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined +# cascading style sheets that are included after the standard style sheets +# created by doxygen. Using this option one can overrule certain style aspects. +# This is preferred over using HTML_STYLESHEET since it does not replace the +# standard style sheet and is therefore more robust against future updates. +# Doxygen will copy the style sheet files to the output directory. +# Note: The order of the extra style sheet files is of importance (e.g. the last +# style sheet in the list overrules the setting of the previous ones in the +# list). For an example see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_STYLESHEET = + +# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or +# other source files which should be copied to the HTML output directory. Note +# that these files will be copied to the base HTML output directory. Use the +# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these +# files. In the HTML_STYLESHEET file, use the file name only. Also note that the +# files will be copied as-is; there are no commands or markers available. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_FILES = + +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen +# will adjust the colors in the style sheet and background images according to +# this color. Hue is specified as an angle on a colorwheel, see +# https://en.wikipedia.org/wiki/Hue for more information. For instance the value +# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 +# purple, and 360 is red again. +# Minimum value: 0, maximum value: 359, default value: 220. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_HUE = 220 + +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors +# in the HTML output. For a value of 0 the output will use grayscales only. A +# value of 255 will produce the most vivid colors. +# Minimum value: 0, maximum value: 255, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_SAT = 100 + +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the +# luminance component of the colors in the HTML output. Values below 100 +# gradually make the output lighter, whereas values above 100 make the output +# darker. The value divided by 100 is the actual gamma applied, so 80 represents +# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not +# change the gamma. +# Minimum value: 40, maximum value: 240, default value: 80. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_GAMMA = 80 + +# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML +# page will contain the date and time when the page was generated. Setting this +# to YES can help to show when doxygen was last run and thus if the +# documentation is up to date. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_TIMESTAMP = YES + +# If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML +# documentation will contain a main index with vertical navigation menus that +# are dynamically created via Javascript. If disabled, the navigation index will +# consists of multiple levels of tabs that are statically embedded in every HTML +# page. Disable this option to support browsers that do not have Javascript, +# like the Qt help browser. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_DYNAMIC_MENUS = YES + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_DYNAMIC_SECTIONS = NO + +# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries +# shown in the various tree structured indices initially; the user can expand +# and collapse entries dynamically later on. Doxygen will expand the tree to +# such a level that at most the specified number of entries are visible (unless +# a fully collapsed tree already exceeds this amount). So setting the number of +# entries 1 will produce a full collapsed tree by default. 0 is a special value +# representing an infinite number of entries and will result in a full expanded +# tree by default. +# Minimum value: 0, maximum value: 9999, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_INDEX_NUM_ENTRIES = 100 + +# If the GENERATE_DOCSET tag is set to YES, additional index files will be +# generated that can be used as input for Apple's Xcode 3 integrated development +# environment (see: https://developer.apple.com/tools/xcode/), introduced with +# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a +# Makefile in the HTML output directory. Running make will produce the docset in +# that directory and running make install will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at +# startup. See https://developer.apple.com/tools/creatingdocsetswithdoxygen.html +# for more information. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_DOCSET = NO + +# This tag determines the name of the docset feed. A documentation feed provides +# an umbrella under which multiple documentation sets from a single provider +# (such as a company or product suite) can be grouped. +# The default value is: Doxygen generated docs. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# This tag specifies a string that should uniquely identify the documentation +# set bundle. This should be a reverse domain-name style string, e.g. +# com.mycompany.MyDocSet. Doxygen will append .docset to the name. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify +# the documentation publisher. This should be a reverse domain-name style +# string, e.g. com.mycompany.MyDocSet.documentation. +# The default value is: org.doxygen.Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_ID = org.doxygen.Publisher + +# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. +# The default value is: Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_NAME = Publisher + +# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three +# additional HTML index files: index.hhp, index.hhc, and index.hhk. The +# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop +# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on +# Windows. +# +# The HTML Help Workshop contains a compiler that can convert all HTML output +# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML +# files are now used as the Windows 98 help format, and will replace the old +# Windows help format (.hlp) on all Windows platforms in the future. Compressed +# HTML files also contain an index, a table of contents, and you can search for +# words in the documentation. The HTML workshop also contains a viewer for +# compressed HTML files. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_HTMLHELP = NO + +# The CHM_FILE tag can be used to specify the file name of the resulting .chm +# file. You can add a path in front of the file if the result should not be +# written to the html output directory. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +CHM_FILE = + +# The HHC_LOCATION tag can be used to specify the location (absolute path +# including file name) of the HTML help compiler (hhc.exe). If non-empty, +# doxygen will try to run the HTML help compiler on the generated index.hhp. +# The file has to be specified with full path. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +HHC_LOCATION = + +# The GENERATE_CHI flag controls if a separate .chi index file is generated +# (YES) or that it should be included in the master .chm file (NO). +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +GENERATE_CHI = NO + +# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc) +# and project file content. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +CHM_INDEX_ENCODING = + +# The BINARY_TOC flag controls whether a binary table of contents is generated +# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it +# enables the Previous and Next buttons. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members to +# the table of contents of the HTML help documentation and to the tree view. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +TOC_EXPAND = NO + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that +# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help +# (.qch) of the generated HTML documentation. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify +# the file name of the resulting .qch file. The path specified is relative to +# the HTML output folder. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help +# Project output. For more information please see Qt Help Project / Namespace +# (see: http://doc.qt.io/qt-4.8/qthelpproject.html#namespace). +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_NAMESPACE = org.doxygen.Project + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt +# Help Project output. For more information please see Qt Help Project / Virtual +# Folders (see: http://doc.qt.io/qt-4.8/qthelpproject.html#virtual-folders). +# The default value is: doc. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_VIRTUAL_FOLDER = doc + +# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom +# filter to add. For more information please see Qt Help Project / Custom +# Filters (see: http://doc.qt.io/qt-4.8/qthelpproject.html#custom-filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the +# custom filter to add. For more information please see Qt Help Project / Custom +# Filters (see: http://doc.qt.io/qt-4.8/qthelpproject.html#custom-filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this +# project's filter section matches. Qt Help Project / Filter Attributes (see: +# http://doc.qt.io/qt-4.8/qthelpproject.html#filter-attributes). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_SECT_FILTER_ATTRS = + +# The QHG_LOCATION tag can be used to specify the location of Qt's +# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the +# generated .qhp file. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHG_LOCATION = + +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be +# generated, together with the HTML files, they form an Eclipse help plugin. To +# install this plugin and make it available under the help contents menu in +# Eclipse, the contents of the directory containing the HTML and XML files needs +# to be copied into the plugins directory of eclipse. The name of the directory +# within the plugins directory should be the same as the ECLIPSE_DOC_ID value. +# After copying Eclipse needs to be restarted before the help appears. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_ECLIPSEHELP = NO + +# A unique identifier for the Eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have this +# name. Each documentation set should have its own identifier. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES. + +ECLIPSE_DOC_ID = org.doxygen.Project + +# If you want full control over the layout of the generated HTML pages it might +# be necessary to disable the index and replace it with your own. The +# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top +# of each HTML page. A value of NO enables the index and the value YES disables +# it. Since the tabs in the index contain the same information as the navigation +# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +DISABLE_INDEX = NO + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. If the tag +# value is set to YES, a side panel will be generated containing a tree-like +# index structure (just like the one that is generated for HTML Help). For this +# to work a browser that supports JavaScript, DHTML, CSS and frames is required +# (i.e. any modern browser). Windows users are probably better off using the +# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can +# further fine-tune the look of the index. As an example, the default style +# sheet generated by doxygen has an example that shows how to put an image at +# the root of the tree instead of the PROJECT_NAME. Since the tree basically has +# the same information as the tab index, you could consider setting +# DISABLE_INDEX to YES when enabling this option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_TREEVIEW = NO + +# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that +# doxygen will group on one line in the generated HTML documentation. +# +# Note that a value of 0 will completely suppress the enum values from appearing +# in the overview section. +# Minimum value: 0, maximum value: 20, default value: 4. +# This tag requires that the tag GENERATE_HTML is set to YES. + +ENUM_VALUES_PER_LINE = 4 + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used +# to set the initial width (in pixels) of the frame in which the tree is shown. +# Minimum value: 0, maximum value: 1500, default value: 250. +# This tag requires that the tag GENERATE_HTML is set to YES. + +TREEVIEW_WIDTH = 250 + +# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to +# external symbols imported via tag files in a separate window. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +EXT_LINKS_IN_WINDOW = NO + +# Use this tag to change the font size of LaTeX formulas included as images in +# the HTML documentation. When you change the font size after a successful +# doxygen run you need to manually remove any form_*.png images from the HTML +# output directory to force them to be regenerated. +# Minimum value: 8, maximum value: 50, default value: 10. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FORMULA_FONTSIZE = 10 + +# Use the FORMULA_TRANSPARENT tag to determine whether or not the images +# generated for formulas are transparent PNGs. Transparent PNGs are not +# supported properly for IE 6.0, but are supported on all modern browsers. +# +# Note that when changing this option you need to delete any form_*.png files in +# the HTML output directory before the changes have effect. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FORMULA_TRANSPARENT = YES + +# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see +# https://www.mathjax.org) which uses client side Javascript for the rendering +# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX +# installed or if you want to formulas look prettier in the HTML output. When +# enabled you may also need to install MathJax separately and configure the path +# to it using the MATHJAX_RELPATH option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +USE_MATHJAX = NO + +# When MathJax is enabled you can set the default output format to be used for +# the MathJax output. See the MathJax site (see: +# http://docs.mathjax.org/en/latest/output.html) for more details. +# Possible values are: HTML-CSS (which is slower, but has the best +# compatibility), NativeMML (i.e. MathML) and SVG. +# The default value is: HTML-CSS. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_FORMAT = HTML-CSS + +# When MathJax is enabled you need to specify the location relative to the HTML +# output directory using the MATHJAX_RELPATH option. The destination directory +# should contain the MathJax.js script. For instance, if the mathjax directory +# is located at the same level as the HTML output directory, then +# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax +# Content Delivery Network so you can quickly see the result without installing +# MathJax. However, it is strongly recommended to install a local copy of +# MathJax from https://www.mathjax.org before deployment. +# The default value is: https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.2/. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest + +# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax +# extension names that should be enabled during MathJax rendering. For example +# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_EXTENSIONS = + +# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces +# of code that will be used on startup of the MathJax code. See the MathJax site +# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an +# example see the documentation. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_CODEFILE = + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box for +# the HTML output. The underlying search engine uses javascript and DHTML and +# should work on any modern browser. Note that when using HTML help +# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) +# there is already a search function so this one should typically be disabled. +# For large projects the javascript based search engine can be slow, then +# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to +# search using the keyboard; to jump to the search box use + S +# (what the is depends on the OS and browser, but it is typically +# , /