mirror of
https://gitlab.kitware.com/vtk/vtk-m
synced 2024-09-08 13:23:51 +00:00
Merge branch 'upstream-diy' into diy-mpi-nompi
* upstream-diy: diy 2020-06-05 (b62915aa)
This commit is contained in:
commit
f0a37ac6aa
257
vtkm/thirdparty/diy/vtkmdiy/CMakeLists.txt
vendored
Normal file
257
vtkm/thirdparty/diy/vtkmdiy/CMakeLists.txt
vendored
Normal file
@ -0,0 +1,257 @@
|
||||
#=============================================================================
|
||||
# Adds the following DIY library targets:
|
||||
# 1. diy: The main diy interface library and the only target for
|
||||
# header-only mode.
|
||||
# 2. diympi: Generated when `build_diy_mpi_lib` and `mpi` are turned on.
|
||||
# Isolates the MPI dependent part of diy into a library.
|
||||
# 3. diympi_nompi: Generated when `build_diy_mpi_lib` is on and either `mpi`
|
||||
# is off or `build_diy_nompi_lib` is on.
|
||||
#
|
||||
# Both mpi and non-mpi libraries can be generated by turning on `build_diy_mpi_lib`
|
||||
# and `build_diy_nompi_lib`. In this case, one of these targets must be explicitly
|
||||
# specified when linking againts diy.
|
||||
#=============================================================================
|
||||
|
||||
project (DIY)
|
||||
cmake_minimum_required (VERSION 3.9)
|
||||
|
||||
list (APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)
|
||||
|
||||
include(CMakeDependentOption)
|
||||
|
||||
# Provides an option if it is not already defined.
|
||||
# This can be replaced when CMake 3.13 is our cmake_minimum_required
|
||||
macro (diy_option variable)
|
||||
if (NOT DEFINED "${variable}")
|
||||
option("${variable}" ${ARGN})
|
||||
endif ()
|
||||
endmacro ()
|
||||
|
||||
macro (diy_dependent_option variable)
|
||||
if (NOT DEFINED "${variable}")
|
||||
cmake_dependent_option("${variable}" ${ARGN})
|
||||
endif ()
|
||||
endmacro ()
|
||||
|
||||
diy_option (threads "Build DIY with threading" ON)
|
||||
diy_option (log "Build DIY with logging" OFF)
|
||||
diy_option (profile "Build DIY with profiling" OFF)
|
||||
diy_option (caliper "Build DIY with caliper" OFF)
|
||||
diy_option (mpi "Build DIY with mpi" ON)
|
||||
diy_option (wrapped_mpi "MPI compiler wrapper requires no further MPI libraries" OFF)
|
||||
diy_option (build_diy_mpi_lib "Build diy::mpi as a library" OFF)
|
||||
diy_dependent_option (BUILD_SHARED_LIBS "Create shared libraries if on" ON "build_diy_mpi_lib" OFF)
|
||||
diy_dependent_option (build_diy_nompi_lib "Also build the nompi version of diy::mpi" OFF "mpi;build_diy_mpi_lib" OFF)
|
||||
diy_option (build_examples "Build DIY examples" ON)
|
||||
diy_option (build_tests "Build DIY tests" ON)
|
||||
|
||||
# Default to Release
|
||||
if (NOT CMAKE_BUILD_TYPE)
|
||||
set (CMAKE_BUILD_TYPE "Release" CACHE STRING "Choose the type of build, options are: Debug Release RelWithDebInfo MinSizeRel." FORCE)
|
||||
set_property (CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" "MinSizeRel" "RelWithDebInfo")
|
||||
endif (NOT CMAKE_BUILD_TYPE)
|
||||
|
||||
set (diy_definitions "")
|
||||
set (diy_include_directories "")
|
||||
set (diy_include_thirdparty_directories "")
|
||||
set (diy_libraries "")
|
||||
|
||||
# Debugging
|
||||
if (${CMAKE_BUILD_TYPE} STREQUAL "Debug" OR
|
||||
${CMAKE_BUILD_TYPE} STREQUAL "RelWithDebInfo")
|
||||
list (APPEND diy_definitions "-DDEBUG")
|
||||
endif ()
|
||||
|
||||
# Logging
|
||||
if (log)
|
||||
list (APPEND diy_definitions "-DVTKMDIY_USE_SPDLOG")
|
||||
find_path (SPDLOG_INCLUDE_DIR spdlog/spdlog.h)
|
||||
list (APPEND diy_include_thirdparty_directories $<BUILD_INTERFACE:${SPDLOG_INCLUDE_DIR}>)
|
||||
endif()
|
||||
|
||||
# Profiling
|
||||
if (profile)
|
||||
list (APPEND diy_definitions "-DVTKMDIY_PROFILE")
|
||||
endif()
|
||||
|
||||
if (caliper)
|
||||
list (APPEND diy_definitions "-DVTKMDIY_USE_CALIPER")
|
||||
|
||||
find_package (caliper)
|
||||
list (APPEND diy_include_thirdparty_directories $<BUILD_INTERFACE:${caliper_INCLUDE_DIR}>)
|
||||
list (APPEND diy_libraries caliper caliper-mpi)
|
||||
endif()
|
||||
|
||||
# Threads
|
||||
if (NOT threads)
|
||||
list (APPEND diy_definitions "-DVTKMDIY_NO_THREADS")
|
||||
else (NOT threads)
|
||||
find_package (Threads)
|
||||
list (APPEND diy_libraries ${CMAKE_THREAD_LIBS_INIT})
|
||||
endif (NOT threads)
|
||||
|
||||
# MPI
|
||||
if (mpi AND NOT wrapped_mpi)
|
||||
find_package(MPI REQUIRED)
|
||||
endif()
|
||||
|
||||
# configuration variables for diy build and install
|
||||
# if diy is a sub-project, the following variables allow the parent project to
|
||||
# easily customize the library
|
||||
if (NOT DEFINED diy_prefix)
|
||||
set(diy_prefix "diy")
|
||||
endif()
|
||||
if (NOT DEFINED diy_install_include_dir)
|
||||
set(diy_install_include_dir "include")
|
||||
endif()
|
||||
if (NOT DEFINED diy_install_lib_dir)
|
||||
set(diy_install_lib_dir "lib")
|
||||
endif()
|
||||
if (NOT DEFINED diy_export_name)
|
||||
set(diy_export_name "diy_targets")
|
||||
endif()
|
||||
|
||||
set (CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/lib")
|
||||
set (CMAKE_LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/lib")
|
||||
|
||||
# for diy_developer_flags
|
||||
include(DIYCompilerFlags)
|
||||
|
||||
function(add_diy_mpi_library use_mpi)
|
||||
set (sources
|
||||
"include/${diy_prefix}/mpi/collectives.cpp"
|
||||
"include/${diy_prefix}/mpi/communicator.cpp"
|
||||
"include/${diy_prefix}/mpi/datatypes.cpp"
|
||||
"include/${diy_prefix}/mpi/environment.cpp"
|
||||
"include/${diy_prefix}/mpi/io.cpp"
|
||||
"include/${diy_prefix}/mpi/operations.cpp"
|
||||
"include/${diy_prefix}/mpi/point-to-point.cpp"
|
||||
"include/${diy_prefix}/mpi/request.cpp"
|
||||
"include/${diy_prefix}/mpi/status.cpp"
|
||||
"include/${diy_prefix}/mpi/window.cpp")
|
||||
|
||||
if (use_mpi)
|
||||
set (lib_name ${diy_prefix}mpi)
|
||||
set (has_mpi_val 1)
|
||||
else()
|
||||
set (lib_name ${diy_prefix}mpi_nompi)
|
||||
set (has_mpi_val 0)
|
||||
endif()
|
||||
|
||||
add_library(${lib_name} ${sources})
|
||||
target_compile_features(${lib_name} PRIVATE cxx_std_11)
|
||||
target_compile_definitions(${lib_name}
|
||||
PRIVATE -DVTKMDIY_HAS_MPI=${has_mpi_val}
|
||||
PRIVATE -Ddiy=${diy_prefix} # mangle diy namespace
|
||||
PRIVATE ${diy_definitions})
|
||||
target_include_directories(${lib_name} SYSTEM PRIVATE ${PROJECT_SOURCE_DIR}/include) # for types.hpp
|
||||
target_include_directories(${lib_name} SYSTEM PRIVATE ${diy_include_directories}) # for mpitypes.hpp
|
||||
target_include_directories(${lib_name} SYSTEM PRIVATE ${diy_include_thirdparty_directories})
|
||||
target_link_libraries(${lib_name} PRIVATE diy_developer_flags)
|
||||
if (use_mpi AND TARGET MPI::MPI_CXX)
|
||||
target_link_libraries(${lib_name} PRIVATE MPI::MPI_CXX)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
# create the targets
|
||||
set (diy_targets)
|
||||
|
||||
if (build_diy_mpi_lib)
|
||||
include(DIYConfigureMPI)
|
||||
|
||||
# To be interchangeable, these libraries should only have PRIVATE properties.
|
||||
# Properties that should be public should also be part of the core diy target.
|
||||
list(APPEND diy_definitions -DVTKMDIY_MPI_AS_LIB)
|
||||
list(APPEND diy_include_directories
|
||||
"$<BUILD_INTERFACE:${PROJECT_BINARY_DIR}/include/${diy_prefix}/mpi>"
|
||||
"$<INSTALL_INTERFACE:${diy_install_include_dir}/${diy_prefix}/mpi>")
|
||||
|
||||
# macro required for proper export macros for static vs shared builds
|
||||
if (NOT BUILD_SHARED_LIBS)
|
||||
list(APPEND diy_definitions -DVTKMDIY_MPI_STATIC_BUILD)
|
||||
endif()
|
||||
|
||||
if (mpi)
|
||||
add_diy_mpi_library(ON)
|
||||
list(APPEND diy_targets ${diy_prefix}mpi)
|
||||
endif()
|
||||
if ((NOT mpi) OR build_diy_nompi_lib)
|
||||
add_diy_mpi_library(OFF)
|
||||
list(APPEND diy_targets ${diy_prefix}mpi_nompi)
|
||||
endif()
|
||||
endif() # build_diy_mpi_lib
|
||||
|
||||
add_library(${diy_prefix} INTERFACE)
|
||||
target_compile_features(${diy_prefix} INTERFACE cxx_std_11)
|
||||
target_compile_definitions(${diy_prefix} INTERFACE ${diy_definitions})
|
||||
target_include_directories(${diy_prefix} SYSTEM INTERFACE
|
||||
"$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>"
|
||||
"$<INSTALL_INTERFACE:${diy_install_include_dir}>")
|
||||
target_include_directories(${diy_prefix} SYSTEM INTERFACE ${diy_include_thirdparty_directories})
|
||||
if (diy_include_directories)
|
||||
target_include_directories(${diy_prefix} SYSTEM INTERFACE ${diy_include_directories})
|
||||
endif()
|
||||
target_link_libraries(${diy_prefix} INTERFACE ${diy_libraries})
|
||||
if (NOT build_diy_mpi_lib)
|
||||
if (mpi)
|
||||
target_compile_definitions(${diy_prefix} INTERFACE -DVTKMDIY_HAS_MPI=1)
|
||||
if (TARGET MPI::MPI_CXX)
|
||||
target_link_libraries(${diy_prefix} INTERFACE MPI::MPI_CXX)
|
||||
endif()
|
||||
else()
|
||||
target_compile_definitions(${diy_prefix} INTERFACE -DVTKMDIY_HAS_MPI=0)
|
||||
endif()
|
||||
elseif (NOT build_diy_nompi_lib)
|
||||
if (mpi)
|
||||
target_link_libraries(${diy_prefix} INTERFACE ${diy_prefix}mpi)
|
||||
else()
|
||||
target_link_libraries(${diy_prefix} INTERFACE ${diy_prefix}mpi_nompi)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
list(APPEND diy_targets ${diy_prefix} diy_developer_flags)
|
||||
|
||||
# libraries used by examples and tests
|
||||
set(libraries ${diy_prefix})
|
||||
if (${diy_prefix}mpi IN_LIST diy_targets)
|
||||
list(APPEND libraries ${diy_prefix}mpi)
|
||||
elseif (${diy_prefix}mpi_nompi IN_LIST diy_targets)
|
||||
list(APPEND libraries ${diy_prefix}mpi_nompi)
|
||||
endif()
|
||||
list(APPEND libraries diy_developer_flags)
|
||||
|
||||
# enable testing and CDash dashboard submission
|
||||
enable_testing ()
|
||||
include (CTest)
|
||||
|
||||
if (build_examples)
|
||||
add_subdirectory (examples)
|
||||
endif (build_examples)
|
||||
|
||||
if (build_tests)
|
||||
add_subdirectory (tests)
|
||||
endif (build_tests)
|
||||
|
||||
# configure find_package script
|
||||
include(CMakePackageConfigHelpers)
|
||||
configure_package_config_file(
|
||||
"${PROJECT_SOURCE_DIR}/cmake/diy-config.cmake.in"
|
||||
"${PROJECT_BINARY_DIR}/diy-config.cmake"
|
||||
INSTALL_DESTINATION ".")
|
||||
|
||||
# install targets
|
||||
if (NOT DEFINED diy_install_only_libraries) # defined by parent project if building for binary distribution
|
||||
install(DIRECTORY ${PROJECT_SOURCE_DIR}/include/${diy_prefix} DESTINATION ${diy_install_include_dir})
|
||||
|
||||
if (build_diy_mpi_lib)
|
||||
install(FILES ${PROJECT_BINARY_DIR}/include/${diy_prefix}/mpi/mpitypes.hpp DESTINATION ${diy_install_include_dir}/${diy_prefix}/mpi)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
install(TARGETS ${diy_targets} EXPORT ${diy_export_name} DESTINATION ${diy_install_lib_dir})
|
||||
|
||||
export(EXPORT ${diy_export_name} NAMESPACE DIY:: FILE "${PROJECT_BINARY_DIR}/diy-targets.cmake")
|
||||
if (CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR) # Only generate these files when diy is the main project
|
||||
install(EXPORT ${diy_export_name} NAMESPACE DIY:: DESTINATION "." FILE diy-targets.cmake)
|
||||
install(FILES "${PROJECT_BINARY_DIR}/diy-config.cmake" DESTINATION ".")
|
||||
endif()
|
76
vtkm/thirdparty/diy/vtkmdiy/cmake/DIYCompilerFlags.cmake
vendored
Normal file
76
vtkm/thirdparty/diy/vtkmdiy/cmake/DIYCompilerFlags.cmake
vendored
Normal file
@ -0,0 +1,76 @@
|
||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC" OR
|
||||
CMAKE_CXX_SIMULATE_ID STREQUAL "MSVC")
|
||||
set(DIY_COMPILER_IS_MSVC 1)
|
||||
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "PGI")
|
||||
set(DIY_COMPILER_IS_PGI 1)
|
||||
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Intel")
|
||||
set(DIY_COMPILER_IS_ICC 1)
|
||||
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang")
|
||||
set(DIY_COMPILER_IS_CLANG 1)
|
||||
set(DIY_COMPILER_IS_APPLECLANG 1)
|
||||
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
||||
set(DIY_COMPILER_IS_CLANG 1)
|
||||
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||
set(DIY_COMPILER_IS_GNU 1)
|
||||
endif()
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
add_library(diy_developer_flags INTERFACE)
|
||||
|
||||
if(DIY_COMPILER_IS_MSVC)
|
||||
target_compile_definitions(diy_developer_flags INTERFACE
|
||||
"_SCL_SECURE_NO_WARNINGS" "_CRT_SECURE_NO_WARNINGS")
|
||||
|
||||
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.15)
|
||||
set(cxx_flags "-W3")
|
||||
endif()
|
||||
#list(APPEND cxx_flags -wd4702 -wd4505)
|
||||
|
||||
if(MSVC_VERSION LESS 1900)
|
||||
# In VS2013 the C4127 warning has a bug in the implementation and
|
||||
# generates false positive warnings for lots of template code
|
||||
#list(APPEND cxx_flags -wd4127)
|
||||
endif()
|
||||
|
||||
target_compile_options(diy_developer_flags INTERFACE $<$<COMPILE_LANGUAGE:CXX>:${cxx_flags}>)
|
||||
|
||||
elseif(DIY_COMPILER_IS_ICC)
|
||||
# dissable some false positive warnings
|
||||
set(cxx_flags -wd186 -wd3280)
|
||||
list(APPEND cxx_flags -diag-disable=11074 -diag-disable=11076)
|
||||
#list(APPEND cxx_flags -wd1478 -wd 13379)
|
||||
target_compile_options(diy_developer_flags INTERFACE $<$<COMPILE_LANGUAGE:CXX>:${cxx_flags}>)
|
||||
|
||||
elseif(DIY_COMPILER_IS_GNU OR DIY_COMPILER_IS_CLANG)
|
||||
set(cxx_flags -Wall -Wcast-align -Wchar-subscripts -Wextra -Wpointer-arith -Wformat -Wformat-security -Wshadow -Wunused -fno-common)
|
||||
|
||||
#Only add float-conversion warnings for gcc as the integer warnigns in GCC
|
||||
#include the implicit casting of all types smaller than int to ints.
|
||||
if (DIY_COMPILER_IS_GNU AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 4.99)
|
||||
list(APPEND cxx_flags -Wfloat-conversion)
|
||||
elseif (DIY_COMPILER_IS_CLANG)
|
||||
list(APPEND cxx_flags -Wconversion)
|
||||
endif()
|
||||
|
||||
# TODO: remove after resolving these warnings
|
||||
# temporarily disable the following warnings as we will need a well thought out plan for fixing these
|
||||
list(APPEND cxx_flags -Wno-sign-conversion -Wno-sign-compare -Wno-cast-align)
|
||||
|
||||
#Add in the -Wodr warning for GCC versions 5.2+
|
||||
if (DIY_COMPILER_IS_CLANG OR (DIY_COMPILER_IS_GNU AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 5.1))
|
||||
list(APPEND cxx_flags -Wodr)
|
||||
endif()
|
||||
|
||||
#GCC 5, 6 don't properly handle strict-overflow suppression through pragma's.
|
||||
#Instead of suppressing around the location of the strict-overflow you
|
||||
#have to suppress around the entry point, or in vtk-m case the worklet
|
||||
#invocation site. This is incredibly tedious and has been fixed in gcc 7
|
||||
#
|
||||
if(DIY_COMPILER_IS_GNU AND
|
||||
(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 4.99) AND
|
||||
(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 6.99) )
|
||||
list(APPEND cxx_flags -Wno-strict-overflow)
|
||||
endif()
|
||||
|
||||
target_compile_options(diy_developer_flags INTERFACE $<$<COMPILE_LANGUAGE:CXX>:${cxx_flags}>)
|
||||
endif()
|
51
vtkm/thirdparty/diy/vtkmdiy/cmake/DIYConfigureMPI.cmake
vendored
Normal file
51
vtkm/thirdparty/diy/vtkmdiy/cmake/DIYConfigureMPI.cmake
vendored
Normal file
@ -0,0 +1,51 @@
|
||||
cmake_policy(PUSH)
|
||||
if (POLICY CMP0075)
|
||||
cmake_policy(SET CMP0075 NEW)
|
||||
endif()
|
||||
|
||||
include (CheckTypeSize)
|
||||
|
||||
if (mpi)
|
||||
find_package(MPI REQUIRED)
|
||||
list(APPEND CMAKE_REQUIRED_INCLUDES ${MPI_CXX_INCLUDE_PATH})
|
||||
list(APPEND CMAKE_EXTRA_INCLUDE_FILES "mpi.h")
|
||||
list(APPEND CMAKE_REQUIRED_LIBRARIES ${MPI_CXX_LIBRARIES})
|
||||
else()
|
||||
list(APPEND CMAKE_REQUIRED_INCLUDES ${PROJECT_SOURCE_DIR}/include)
|
||||
list(APPEND CMAKE_EXTRA_INCLUDE_FILES "${diy_prefix}/mpi/no-mpi.hpp")
|
||||
endif()
|
||||
|
||||
list(APPEND CMAKE_REQUIRED_INCLUDES ${PROJECT_SOURCE_DIR}/cmake)
|
||||
list(APPEND CMAKE_EXTRA_INCLUDE_FILES "mpi_types.h")
|
||||
|
||||
if (NOT (DEFINED CACHE{previous_mpi} AND ((previous_mpi AND mpi) OR (NOT(previous_mpi OR mpi)))))
|
||||
unset(TYPESIZE_MPI_Comm CACHE)
|
||||
unset(HAVE_TYPESIZE_MPI_Comm CACHE)
|
||||
unset(TYPESIZE_MPI_Datatype CACHE)
|
||||
unset(HAVE_TYPESIZE_MPI_Datatype CACHE)
|
||||
unset(TYPESIZE_MPI_Status CACHE)
|
||||
unset(HAVE_TYPESIZE_MPI_Status CACHE)
|
||||
unset(TYPESIZE_MPI_Request CACHE)
|
||||
unset(HAVE_TYPESIZE_MPI_Request CACHE)
|
||||
unset(TYPESIZE_MPI_Op CACHE)
|
||||
unset(HAVE_TYPESIZE_MPI_Op CACHE)
|
||||
unset(TYPESIZE_MPI_File CACHE)
|
||||
unset(HAVE_TYPESIZE_MPI_File CACHE)
|
||||
unset(TYPESIZE_MPI_Win CACHE)
|
||||
unset(HAVE_TYPESIZE_MPI_Win CACHE)
|
||||
|
||||
set (previous_mpi ${mpi} CACHE INTERNAL "" FORCE)
|
||||
endif()
|
||||
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
|
||||
check_type_size("Wrapped_MPI_Comm" TYPESIZE_MPI_Comm LANGUAGE CXX)
|
||||
check_type_size("Wrapped_MPI_Datatype" TYPESIZE_MPI_Datatype LANGUAGE CXX)
|
||||
check_type_size("Wrapped_MPI_Status" TYPESIZE_MPI_Status LANGUAGE CXX)
|
||||
check_type_size("Wrapped_MPI_Request" TYPESIZE_MPI_Request LANGUAGE CXX)
|
||||
check_type_size("Wrapped_MPI_Op" TYPESIZE_MPI_Op LANGUAGE CXX)
|
||||
check_type_size("Wrapped_MPI_File" TYPESIZE_MPI_File LANGUAGE CXX)
|
||||
check_type_size("Wrapped_MPI_Win" TYPESIZE_MPI_Win LANGUAGE CXX)
|
||||
configure_file("include/${diy_prefix}/mpi/mpitypes.hpp.in" "include/${diy_prefix}/mpi/mpitypes.hpp" @ONLY)
|
||||
|
||||
cmake_policy(POP)
|
57
vtkm/thirdparty/diy/vtkmdiy/cmake/diy-config.cmake.in
vendored
Normal file
57
vtkm/thirdparty/diy/vtkmdiy/cmake/diy-config.cmake.in
vendored
Normal file
@ -0,0 +1,57 @@
|
||||
if (CMAKE_VERSION VERSION_LESS "3.9")
|
||||
message(FATAL_ERROR "Diy requires CMake 3.9+")
|
||||
endif()
|
||||
|
||||
@PACKAGE_INIT@
|
||||
|
||||
set(threads "@threads@")
|
||||
set(log "@log@")
|
||||
set(caliper "@caliper@")
|
||||
set(mpi "@mpi@")
|
||||
|
||||
include("${CMAKE_CURRENT_LIST_DIR}/diy-targets.cmake")
|
||||
|
||||
set(_diy_find_quietly)
|
||||
if (${CMAKE_FIND_PACKAGE_NAME}_FIND_QUIETLY)
|
||||
set(_diy_find_quietly QUIET)
|
||||
endif()
|
||||
|
||||
if (threads)
|
||||
find_package(Threads ${_diy_find_quietly})
|
||||
if (NOT Threads_FOUND)
|
||||
list(APPEND "${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE" "Threads not found")
|
||||
set("${CMAKE_FIND_PACKAGE_NAME}_FOUND" 0)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (log)
|
||||
find_path(SPDLOG_INCLUDE_DIR "spdlog/spdlog.h")
|
||||
if (SPDLOG_INCLUDE_DIR STREQUAL "SPDLOG_INCLUDE_DIR-NOTFOUND")
|
||||
list(APPEND "${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE" "SPDLOG not found")
|
||||
set("${CMAKE_FIND_PACKAGE_NAME}_FOUND" 0)
|
||||
else()
|
||||
target_include_directories(DIY::@diy_prefix@ INTERFACE $<INSTALL_INTERFACE:${SPDLOG_INCLUDE_DIR}>)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (caliper)
|
||||
find_package(caliper ${_diy_find_quietly})
|
||||
if (NOT caliper_FOUND)
|
||||
list(APPEND "${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE" "Caliper not found")
|
||||
set("${CMAKE_FIND_PACKAGE_NAME}_FOUND" 0)
|
||||
else()
|
||||
target_include_directories(DIY::@diy_prefix@ INTERFACE $<INSTALL_INTERFACE:${caliper_INCLUDE_DIR}>)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (mpi)
|
||||
find_package(MPI ${_diy_find_quietly})
|
||||
if (NOT MPI_FOUND)
|
||||
list(APPEND "${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE" "MPI not found")
|
||||
set("${CMAKE_FIND_PACKAGE_NAME}_FOUND" 0)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (NOT DEFINED "${CMAKE_FIND_PACKAGE_NAME}_FOUND")
|
||||
set("${CMAKE_FIND_PACKAGE_NAME}_FOUND" 1)
|
||||
endif ()
|
9
vtkm/thirdparty/diy/vtkmdiy/cmake/mpi_types.h
vendored
Normal file
9
vtkm/thirdparty/diy/vtkmdiy/cmake/mpi_types.h
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
// Wrap the mpi types in structs as they can be macros in some implementations,
|
||||
// causing `check_type_size` to fail.
|
||||
struct Wrapped_MPI_Comm { MPI_Comm obj; };
|
||||
struct Wrapped_MPI_Datatype { MPI_Datatype obj; };
|
||||
struct Wrapped_MPI_Status { MPI_Status obj; };
|
||||
struct Wrapped_MPI_Request { MPI_Request obj; };
|
||||
struct Wrapped_MPI_Op { MPI_Op obj; };
|
||||
struct Wrapped_MPI_File { MPI_File obj; };
|
||||
struct Wrapped_MPI_Win { MPI_Win obj; };
|
@ -86,7 +86,7 @@ namespace diy
|
||||
|
||||
typedef diy::RegularContinuousLink RCLink;
|
||||
|
||||
for (size_t i = 0; i < master.size(); ++i)
|
||||
for (int i = 0; i < static_cast<int>(master.size()); ++i)
|
||||
{
|
||||
RCLink* link = static_cast<RCLink*>(master.link(i));
|
||||
*link = RCLink(dim, domain, domain);
|
||||
@ -96,7 +96,7 @@ namespace diy
|
||||
diy::BlockID self = { master.gid(i), master.communicator().rank() };
|
||||
for (int j = 0; j < dim; ++j)
|
||||
{
|
||||
diy::Direction dir, wrap_dir;
|
||||
diy::Direction dir(dim,0), wrap_dir(dim,0);
|
||||
|
||||
// left
|
||||
dir[j] = -1; wrap_dir[j] = -1;
|
||||
@ -122,7 +122,7 @@ namespace diy
|
||||
|
||||
// update master.expected to match the links
|
||||
int expected = 0;
|
||||
for (size_t i = 0; i < master.size(); ++i)
|
||||
for (int i = 0; i < static_cast<int>(master.size()); ++i)
|
||||
expected += master.link(i)->size_unique();
|
||||
master.set_expected(expected);
|
||||
}
|
||||
@ -146,7 +146,7 @@ namespace diy
|
||||
|
||||
typedef diy::RegularContinuousLink RCLink;
|
||||
|
||||
for (size_t i = 0; i < master.size(); ++i)
|
||||
for (int i = 0; i < static_cast<int>(master.size()); ++i)
|
||||
{
|
||||
RCLink* link = static_cast<RCLink*>(master.link(i));
|
||||
*link = RCLink(dim, domain, domain);
|
||||
@ -156,7 +156,7 @@ namespace diy
|
||||
diy::BlockID self = { master.gid(i), master.communicator().rank() };
|
||||
for (int j = 0; j < dim; ++j)
|
||||
{
|
||||
diy::Direction dir, wrap_dir;
|
||||
diy::Direction dir(dim,0), wrap_dir(dim,0);
|
||||
|
||||
// left
|
||||
dir[j] = -1; wrap_dir[j] = -1;
|
||||
@ -182,7 +182,7 @@ namespace diy
|
||||
|
||||
// update master.expected to match the links
|
||||
int expected = 0;
|
||||
for (size_t i = 0; i < master.size(); ++i)
|
||||
for (int i = 0; i < static_cast<int>(master.size()); ++i)
|
||||
expected += master.link(i)->size_unique();
|
||||
master.set_expected(expected);
|
||||
}
|
||||
|
@ -22,6 +22,7 @@ namespace diy
|
||||
int nblocks__ //!< total (global) number of blocks
|
||||
):
|
||||
size_(size__), nblocks_(nblocks__) {}
|
||||
virtual ~Assigner() {}
|
||||
|
||||
//! returns the total number of process ranks
|
||||
int size() const { return size_; }
|
||||
@ -36,6 +37,7 @@ namespace diy
|
||||
virtual std::vector<int>
|
||||
ranks(const std::vector<int>& gids) const;
|
||||
|
||||
|
||||
private:
|
||||
int size_; // total number of ranks
|
||||
int nblocks_; // total number of blocks
|
||||
@ -107,7 +109,7 @@ namespace diy
|
||||
Assigner(size__, nblocks__),
|
||||
comm_(comm),
|
||||
div_(nblocks__ / size__ + ((nblocks__ % size__) == 0 ? 0 : 1)), // NB: same size window everywhere means the last rank may allocate extra space
|
||||
rank_map_(comm_, div_) { rank_map_.lock_all(MPI_MODE_NOCHECK); }
|
||||
rank_map_(comm_, div_) { rank_map_.lock_all(mpi::nocheck); }
|
||||
~DynamicAssigner() { rank_map_.unlock_all(); }
|
||||
|
||||
inline
|
||||
@ -187,7 +189,7 @@ set_nblocks(int nblocks__)
|
||||
|
||||
rank_map_.unlock_all();
|
||||
rank_map_ = mpi::window<int>(comm_, div_);
|
||||
rank_map_.lock_all(MPI_MODE_NOCHECK);
|
||||
rank_map_.lock_all(mpi::nocheck);
|
||||
}
|
||||
|
||||
std::tuple<bool,int>
|
||||
|
@ -1,26 +1,39 @@
|
||||
#ifndef VTKMDIY_CONSTANTS_H
|
||||
#define VTKMDIY_CONSTANTS_H
|
||||
|
||||
// Default DIY_MAX_DIM to 4, unless provided by the user
|
||||
// Default VTKMDIY_MAX_DIM to 4, unless provided by the user
|
||||
// (used for static min/max size in various Bounds)
|
||||
#ifndef DIY_MAX_DIM
|
||||
#define DIY_MAX_DIM 4
|
||||
#ifndef VTKMDIY_MAX_DIM
|
||||
#define VTKMDIY_MAX_DIM 4
|
||||
#endif
|
||||
|
||||
enum
|
||||
{
|
||||
DIY_X0 = 0x01, /* minimum-side x (left) neighbor */
|
||||
DIY_X1 = 0x02, /* maximum-side x (right) neighbor */
|
||||
DIY_Y0 = 0x04, /* minimum-side y (bottom) neighbor */
|
||||
DIY_Y1 = 0x08, /* maximum-side y (top) neighbor */
|
||||
DIY_Z0 = 0x10, /* minimum-side z (back) neighbor */
|
||||
DIY_Z1 = 0x20, /* maximum-side z (front)neighbor */
|
||||
DIY_T0 = 0x40, /* minimum-side t (earlier) neighbor */
|
||||
DIY_T1 = 0x80 /* maximum-side t (later) neighbor */
|
||||
VTKMDIY_X0 = 0x01, /* minimum-side x (left) neighbor */
|
||||
VTKMDIY_X1 = 0x02, /* maximum-side x (right) neighbor */
|
||||
VTKMDIY_Y0 = 0x04, /* minimum-side y (bottom) neighbor */
|
||||
VTKMDIY_Y1 = 0x08, /* maximum-side y (top) neighbor */
|
||||
VTKMDIY_Z0 = 0x10, /* minimum-side z (back) neighbor */
|
||||
VTKMDIY_Z1 = 0x20, /* maximum-side z (front)neighbor */
|
||||
VTKMDIY_T0 = 0x40, /* minimum-side t (earlier) neighbor */
|
||||
VTKMDIY_T1 = 0x80 /* maximum-side t (later) neighbor */
|
||||
};
|
||||
|
||||
#ifndef DIY_UNUSED
|
||||
#define DIY_UNUSED(expr) do { (void)(expr); } while (0)
|
||||
#define VTKMDIY_UNUSED(expr) do { (void)(expr); } while (0)
|
||||
|
||||
// From https://stackoverflow.com/a/21265197/44738
|
||||
#if defined(__cplusplus) && (__cplusplus >= 201402L)
|
||||
# define DEPRECATED(msg) [[deprecated(#msg)]]
|
||||
#else
|
||||
# if defined(__GNUC__) || defined(__clang__)
|
||||
# define DEPRECATED(msg) __attribute__((deprecated(#msg)))
|
||||
# elif defined(_MSC_VER)
|
||||
# define DEPRECATED(msg) __declspec(deprecated(#msg))
|
||||
# else
|
||||
# pragma message("WARNING: You need to implement DEPRECATED for this compiler")
|
||||
# define DEPRECATED(msg)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -17,6 +17,9 @@ namespace diy
|
||||
const T& operator*() const { return x_; }
|
||||
const T* operator->() const { return &x_; }
|
||||
|
||||
void lock() { lock_.lock(); }
|
||||
void unlock() { lock_.unlock(); }
|
||||
|
||||
private:
|
||||
T& x_;
|
||||
lock_guard<Mutex> lock_;
|
||||
@ -33,6 +36,8 @@ namespace diy
|
||||
critical_resource() {}
|
||||
critical_resource(const T& x):
|
||||
x_(x) {}
|
||||
critical_resource(T&& x):
|
||||
x_(std::move(x)) {}
|
||||
|
||||
accessor access() { return accessor(x_, m_); }
|
||||
const_accessor const_access() const { return const_accessor(x_, m_); }
|
||||
|
@ -63,8 +63,8 @@ namespace detail
|
||||
static Coordinate from(int i, int n, Coordinate min, Coordinate max, bool) { return min + (max - min)/n * i; }
|
||||
static Coordinate to (int i, int n, Coordinate min, Coordinate max, bool) { return min + (max - min)/n * (i+1); }
|
||||
|
||||
static int lower(Coordinate x, int n, Coordinate min, Coordinate max, bool) { Coordinate width = (max - min)/n; Coordinate res = std::floor((x - min)/width); if (min + res*width == x) return (res - 1); else return res; }
|
||||
static int upper(Coordinate x, int n, Coordinate min, Coordinate max, bool) { Coordinate width = (max - min)/n; Coordinate res = std::ceil ((x - min)/width); if (min + res*width == x) return (res + 1); else return res; }
|
||||
static int lower(Coordinate x, int n, Coordinate min, Coordinate max, bool) { Coordinate width = (max - min)/n; auto res = static_cast<int>(std::floor((x - min)/width)); if (min + res*width == x) return (res - 1); else return res; }
|
||||
static int upper(Coordinate x, int n, Coordinate min, Coordinate max, bool) { Coordinate width = (max - min)/n; auto res = static_cast<int>(std::ceil ((x - min)/width)); if (min + res*width == x) return (res + 1); else return res; }
|
||||
};
|
||||
}
|
||||
|
||||
@ -74,9 +74,9 @@ namespace detail
|
||||
template<class Bounds_>
|
||||
struct RegularDecomposer
|
||||
{
|
||||
typedef Bounds_ Bounds;
|
||||
typedef typename BoundsValue<Bounds>::type Coordinate;
|
||||
typedef typename RegularLinkSelector<Bounds>::type Link;
|
||||
using Bounds = Bounds_;
|
||||
using Coordinate = typename BoundsValue<Bounds>::type;
|
||||
using Link = RegularLink<Bounds>;
|
||||
|
||||
using Creator = std::function<void(int, Bounds, Bounds, Bounds, Link)>;
|
||||
using Updater = std::function<void(int, int, Bounds, Bounds, Bounds, Link)>;
|
||||
@ -123,6 +123,7 @@ namespace detail
|
||||
template<class Point>
|
||||
int lowest_gid(const Point& p) const;
|
||||
|
||||
DivisionsVector gid_to_coords(int gid) const { DivisionsVector coords; gid_to_coords(gid, coords); return coords; }
|
||||
void gid_to_coords(int gid, DivisionsVector& coords) const { gid_to_coords(gid, coords, divisions); }
|
||||
int coords_to_gid(const DivisionsVector& coords) const { return coords_to_gid(coords, divisions); }
|
||||
void fill_divisions(std::vector<int>& divisions) const;
|
||||
@ -131,8 +132,8 @@ namespace detail
|
||||
void fill_bounds(Bounds& bounds, int gid, bool add_ghosts = false) const;
|
||||
|
||||
static bool all(const std::vector<int>& v, int x);
|
||||
static void gid_to_coords(int gid, DivisionsVector& coords, const DivisionsVector& divisions);
|
||||
static int coords_to_gid(const DivisionsVector& coords, const DivisionsVector& divisions);
|
||||
static void gid_to_coords(int gid, DivisionsVector& coords, const DivisionsVector& divs);
|
||||
static int coords_to_gid(const DivisionsVector& coords, const DivisionsVector& divs);
|
||||
|
||||
static void factor(std::vector<unsigned>& factors, int n);
|
||||
|
||||
@ -303,7 +304,7 @@ decompose(int rank, const StaticAssigner& assigner, const Creator& create)
|
||||
DivisionsVector coords;
|
||||
gid_to_coords(gid, coords);
|
||||
|
||||
Bounds core, bounds;
|
||||
Bounds core(dim), bounds(dim);
|
||||
fill_bounds(core, coords);
|
||||
fill_bounds(bounds, coords, true);
|
||||
|
||||
@ -325,7 +326,7 @@ decompose(int rank, const StaticAssigner& assigner, const Creator& create)
|
||||
if (all(offsets, 0)) continue; // skip ourselves
|
||||
|
||||
DivisionsVector nhbr_coords(dim);
|
||||
Direction dir, wrap_dir;
|
||||
Direction dir(dim,0), wrap_dir(dim,0);
|
||||
bool inbounds = true;
|
||||
for (int k = 0; k < dim; ++k)
|
||||
{
|
||||
@ -364,8 +365,12 @@ decompose(int rank, const StaticAssigner& assigner, const Creator& create)
|
||||
BlockID bid; bid.gid = nhbr_gid; bid.proc = assigner.rank(nhbr_gid);
|
||||
link.add_neighbor(bid);
|
||||
|
||||
Bounds nhbr_bounds;
|
||||
fill_bounds(nhbr_bounds, nhbr_coords);
|
||||
Bounds nhbr_core(dim);
|
||||
fill_bounds(nhbr_core, nhbr_coords);
|
||||
link.add_core(nhbr_core);
|
||||
|
||||
Bounds nhbr_bounds(dim);
|
||||
fill_bounds(nhbr_bounds, nhbr_coords, true);
|
||||
link.add_bounds(nhbr_bounds);
|
||||
|
||||
link.add_direction(dir);
|
||||
@ -405,25 +410,25 @@ all(const std::vector<int>& v, int x)
|
||||
template<class Bounds>
|
||||
void
|
||||
diy::RegularDecomposer<Bounds>::
|
||||
gid_to_coords(int gid, DivisionsVector& coords, const DivisionsVector& divisions)
|
||||
gid_to_coords(int gid, DivisionsVector& coords, const DivisionsVector& divs)
|
||||
{
|
||||
int dim = static_cast<int>(divisions.size());
|
||||
for (int i = 0; i < dim; ++i)
|
||||
coords.clear();
|
||||
for (int i = 0; i < static_cast<int>(divs.size()); ++i)
|
||||
{
|
||||
coords.push_back(gid % divisions[i]);
|
||||
gid /= divisions[i];
|
||||
coords.push_back(gid % divs[i]);
|
||||
gid /= divs[i];
|
||||
}
|
||||
}
|
||||
|
||||
template<class Bounds>
|
||||
int
|
||||
diy::RegularDecomposer<Bounds>::
|
||||
coords_to_gid(const DivisionsVector& coords, const DivisionsVector& divisions)
|
||||
coords_to_gid(const DivisionsVector& coords, const DivisionsVector& divs)
|
||||
{
|
||||
int gid = 0;
|
||||
for (int i = static_cast<int>(coords.size()) - 1; i >= 0; --i)
|
||||
{
|
||||
gid *= divisions[i];
|
||||
gid *= divs[i];
|
||||
gid += coords[i];
|
||||
}
|
||||
return gid;
|
||||
@ -445,12 +450,6 @@ fill_bounds(Bounds& bounds, //!< (output) bounds
|
||||
bounds.max[i] = detail::BoundsHelper<Bounds>::to (coords[i], divisions[i], domain.min[i], domain.max[i], share_face[i]);
|
||||
}
|
||||
|
||||
for (int i = dim; i < DIY_MAX_DIM; ++i) // set the unused dimension to 0
|
||||
{
|
||||
bounds.min[i] = 0;
|
||||
bounds.max[i] = 0;
|
||||
}
|
||||
|
||||
if (!add_ghosts)
|
||||
return;
|
||||
|
||||
@ -554,8 +553,7 @@ fill_divisions(std::vector<int>& divisions_) const
|
||||
}
|
||||
|
||||
// iterate over factorization of number of blocks (factors are sorted smallest to largest)
|
||||
// NB: using int instead of size_t because must be negative in order to break out of loop
|
||||
for (int i = factors.size() - 1; i >= 0; --i)
|
||||
for (auto f = factors.rbegin(); f != factors.rend(); ++f)
|
||||
{
|
||||
// fill in missing divs by dividing dimension w/ largest block size
|
||||
// except when this would be illegal (resulting in bounds.max < bounds.min;
|
||||
@ -567,19 +565,19 @@ fill_divisions(std::vector<int>& divisions_) const
|
||||
// split the dimension with the largest block size (first element in vector)
|
||||
Coordinate min =
|
||||
detail::BoundsHelper<Bounds>::from(0,
|
||||
missing_divs[0].nb * factors[i],
|
||||
missing_divs[0].nb * (*f),
|
||||
domain.min[missing_divs[0].dim],
|
||||
domain.max[missing_divs[0].dim],
|
||||
share_face[missing_divs[0].dim]);
|
||||
Coordinate max =
|
||||
detail::BoundsHelper<Bounds>::to(0,
|
||||
missing_divs[0].nb * factors[i],
|
||||
missing_divs[0].nb * (*f),
|
||||
domain.min[missing_divs[0].dim],
|
||||
domain.max[missing_divs[0].dim],
|
||||
share_face[missing_divs[0].dim]);
|
||||
if (max >= min)
|
||||
{
|
||||
missing_divs[0].nb *= factors[i];
|
||||
missing_divs[0].nb *= (*f);
|
||||
missing_divs[0].b_size = max - min;
|
||||
}
|
||||
else
|
||||
|
@ -74,7 +74,7 @@ operator()(Block* b, const diy::ReduceProxy& srp, const KDTreePartners& partners
|
||||
dim = partners.dim(srp.round() - 1);
|
||||
|
||||
if (srp.round() == partners.rounds())
|
||||
update_links(b, srp, dim, partners.sub_round(srp.round() - 2), partners.swap_rounds(), partners.wrap, partners.domain); // -1 would be the "uninformative" link round
|
||||
update_links(b, srp, dim, partners.sub_round((int)srp.round() - 2), (int)partners.swap_rounds(), partners.wrap, partners.domain); // -1 would be the "uninformative" link round
|
||||
else if (partners.swap_round(srp.round()) && partners.sub_round(srp.round()) < 0) // link round
|
||||
{
|
||||
dequeue_exchange(b, srp, dim); // from the swap round
|
||||
@ -92,7 +92,7 @@ operator()(Block* b, const diy::ReduceProxy& srp, const KDTreePartners& partners
|
||||
int prev_dim = dim - 1;
|
||||
if (prev_dim < 0)
|
||||
prev_dim += dim_;
|
||||
update_links(b, srp, prev_dim, partners.sub_round(srp.round() - 2), partners.swap_rounds(), partners.wrap, partners.domain); // -1 would be the "uninformative" link round
|
||||
update_links(b, srp, prev_dim, partners.sub_round((int)srp.round() - 2), (int)partners.swap_rounds(), partners.wrap, partners.domain); // -1 would be the "uninformative" link round
|
||||
}
|
||||
|
||||
compute_local_samples(b, srp, dim);
|
||||
@ -134,7 +134,7 @@ divide_gid(int gid, bool lower, int round, int rounds) const
|
||||
template<class Block, class Point>
|
||||
void
|
||||
diy::detail::KDTreeSamplingPartition<Block,Point>::
|
||||
update_links(Block* b, const diy::ReduceProxy& srp, int dim, int round, int rounds, bool wrap, const Bounds& domain) const
|
||||
update_links(Block*, const diy::ReduceProxy& srp, int dim, int round, int rounds, bool wrap, const Bounds& domain) const
|
||||
{
|
||||
auto log = get_logger();
|
||||
int gid = srp.gid();
|
||||
@ -150,7 +150,7 @@ update_links(Block* b, const diy::ReduceProxy& srp, int dim, int round, int roun
|
||||
std::vector<float> splits(link->size());
|
||||
for (int i = 0; i < link->size(); ++i)
|
||||
{
|
||||
float split; diy::Direction dir;
|
||||
float split; diy::Direction dir(dim_,0);
|
||||
|
||||
int in_gid = link->target(i).gid;
|
||||
while(srp.incoming(in_gid))
|
||||
@ -194,7 +194,7 @@ update_links(Block* b, const diy::ReduceProxy& srp, int dim, int round, int roun
|
||||
if (wrap)
|
||||
new_link.add_wrap(find_wrap(new_link.bounds(), bounds, domain));
|
||||
else
|
||||
new_link.add_wrap(diy::Direction());
|
||||
new_link.add_wrap(diy::Direction(dim_,0));
|
||||
}
|
||||
} else // non-aligned side
|
||||
{
|
||||
@ -215,7 +215,7 @@ update_links(Block* b, const diy::ReduceProxy& srp, int dim, int round, int roun
|
||||
if (wrap)
|
||||
new_link.add_wrap(find_wrap(new_link.bounds(), bounds, domain));
|
||||
else
|
||||
new_link.add_wrap(diy::Direction());
|
||||
new_link.add_wrap(diy::Direction(dim_,0));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -230,16 +230,16 @@ update_links(Block* b, const diy::ReduceProxy& srp, int dim, int round, int roun
|
||||
update_neighbor_bounds(nbr_bounds, find_split(new_link.bounds(), nbr_bounds), dim, !lower);
|
||||
new_link.add_bounds(nbr_bounds);
|
||||
|
||||
new_link.add_wrap(diy::Direction()); // dual block cannot be wrapped
|
||||
new_link.add_wrap(diy::Direction(dim_,0)); // dual block cannot be wrapped
|
||||
|
||||
if (lower)
|
||||
{
|
||||
diy::Direction right;
|
||||
diy::Direction right(dim_,0);
|
||||
right[dim] = 1;
|
||||
new_link.add_direction(right);
|
||||
} else
|
||||
{
|
||||
diy::Direction left;
|
||||
diy::Direction left(dim_,0);
|
||||
left[dim] = -1;
|
||||
new_link.add_direction(left);
|
||||
}
|
||||
@ -253,7 +253,7 @@ update_links(Block* b, const diy::ReduceProxy& srp, int dim, int round, int roun
|
||||
template<class Block, class Point>
|
||||
void
|
||||
diy::detail::KDTreeSamplingPartition<Block,Point>::
|
||||
split_to_neighbors(Block* b, const diy::ReduceProxy& srp, int dim) const
|
||||
split_to_neighbors(Block*, const diy::ReduceProxy& srp, int) const
|
||||
{
|
||||
int lid = srp.master()->lid(srp.gid());
|
||||
RCLink* link = static_cast<RCLink*>(srp.master()->link(lid));
|
||||
@ -290,7 +290,7 @@ compute_local_samples(Block* b, const diy::ReduceProxy& srp, int dim) const
|
||||
template<class Block, class Point>
|
||||
void
|
||||
diy::detail::KDTreeSamplingPartition<Block,Point>::
|
||||
add_samples(Block* b, const diy::ReduceProxy& srp, Samples& samples) const
|
||||
add_samples(Block*, const diy::ReduceProxy& srp, Samples& samples) const
|
||||
{
|
||||
// dequeue and combine the samples
|
||||
for (int i = 0; i < srp.in_link().size(); ++i)
|
||||
@ -307,7 +307,7 @@ add_samples(Block* b, const diy::ReduceProxy& srp, Samples& samples) const
|
||||
template<class Block, class Point>
|
||||
void
|
||||
diy::detail::KDTreeSamplingPartition<Block,Point>::
|
||||
receive_samples(Block* b, const diy::ReduceProxy& srp, Samples& samples) const
|
||||
receive_samples(Block*, const diy::ReduceProxy& srp, Samples& samples) const
|
||||
{
|
||||
srp.dequeue(srp.in_link().target(0).gid, samples);
|
||||
}
|
||||
@ -315,7 +315,7 @@ receive_samples(Block* b, const diy::ReduceProxy& srp, Samples& samples) const
|
||||
template<class Block, class Point>
|
||||
void
|
||||
diy::detail::KDTreeSamplingPartition<Block,Point>::
|
||||
forward_samples(Block* b, const diy::ReduceProxy& srp, const Samples& samples) const
|
||||
forward_samples(Block*, const diy::ReduceProxy& srp, const Samples& samples) const
|
||||
{
|
||||
for (int i = 0; i < srp.out_link().size(); ++i)
|
||||
srp.enqueue(srp.out_link().target(i), samples);
|
||||
@ -435,7 +435,7 @@ diy::Direction
|
||||
diy::detail::KDTreeSamplingPartition<Block,Point>::
|
||||
find_wrap(const Bounds& bounds, const Bounds& nbr_bounds, const Bounds& domain) const
|
||||
{
|
||||
diy::Direction wrap;
|
||||
diy::Direction wrap(dim_,0);
|
||||
for (int i = 0; i < dim_; ++i)
|
||||
{
|
||||
if (bounds.min[i] == domain.min[i] && nbr_bounds.max[i] == domain.max[i])
|
||||
|
@ -68,10 +68,10 @@ struct diy::detail::KDTreePartners
|
||||
wrap(wrap_),
|
||||
domain(domain_)
|
||||
{
|
||||
for (unsigned i = 0; i < swap.rounds(); ++i)
|
||||
for (int i = 0; i < swap.rounds(); ++i)
|
||||
{
|
||||
// fill histogram rounds
|
||||
for (unsigned j = 0; j < histogram.rounds(); ++j)
|
||||
for (int j = 0; j < histogram.rounds(); ++j)
|
||||
{
|
||||
rounds_.push_back(std::make_pair(false, j));
|
||||
dim_.push_back(i % dim);
|
||||
@ -115,7 +115,7 @@ struct diy::detail::KDTreePartners
|
||||
else if (swap_round(round) && sub_round(round) < 0) // link round
|
||||
swap.incoming(sub_round(round - 1) + 1, gid, partners, m);
|
||||
else if (swap_round(round))
|
||||
histogram.incoming(histogram.rounds(), gid, partners, m);
|
||||
histogram.incoming(static_cast<int>(histogram.rounds()), gid, partners, m);
|
||||
else
|
||||
{
|
||||
if (round > 0 && sub_round(round) == 0)
|
||||
@ -177,7 +177,7 @@ operator()(Block* b, const diy::ReduceProxy& srp, const KDTreePartners& partners
|
||||
dim = partners.dim(srp.round() - 1);
|
||||
|
||||
if (srp.round() == partners.rounds())
|
||||
update_links(b, srp, dim, partners.sub_round(srp.round() - 2), partners.swap_rounds(), partners.wrap, partners.domain); // -1 would be the "uninformative" link round
|
||||
update_links(b, srp, dim, partners.sub_round((int)srp.round() - 2), (int)partners.swap_rounds(), partners.wrap, partners.domain); // -1 would be the "uninformative" link round
|
||||
else if (partners.swap_round(srp.round()) && partners.sub_round(srp.round()) < 0) // link round
|
||||
{
|
||||
dequeue_exchange(b, srp, dim); // from the swap round
|
||||
@ -195,7 +195,7 @@ operator()(Block* b, const diy::ReduceProxy& srp, const KDTreePartners& partners
|
||||
int prev_dim = dim - 1;
|
||||
if (prev_dim < 0)
|
||||
prev_dim += dim_;
|
||||
update_links(b, srp, prev_dim, partners.sub_round(srp.round() - 2), partners.swap_rounds(), partners.wrap, partners.domain); // -1 would be the "uninformative" link round
|
||||
update_links(b, srp, prev_dim, partners.sub_round((int)srp.round() - 2), (int)partners.swap_rounds(), partners.wrap, partners.domain); // -1 would be the "uninformative" link round
|
||||
}
|
||||
|
||||
compute_local_histogram(b, srp, dim);
|
||||
@ -229,7 +229,7 @@ divide_gid(int gid, bool lower, int round, int rounds) const
|
||||
template<class Block, class Point>
|
||||
void
|
||||
diy::detail::KDTreePartition<Block,Point>::
|
||||
update_links(Block* b, const diy::ReduceProxy& srp, int dim, int round, int rounds, bool wrap, const Bounds& domain) const
|
||||
update_links(Block*, const diy::ReduceProxy& srp, int dim, int round, int rounds, bool wrap, const Bounds& domain) const
|
||||
{
|
||||
int gid = srp.gid();
|
||||
int lid = srp.master()->lid(gid);
|
||||
@ -244,7 +244,7 @@ update_links(Block* b, const diy::ReduceProxy& srp, int dim, int round, int roun
|
||||
std::vector<float> splits(link->size());
|
||||
for (int i = 0; i < link->size(); ++i)
|
||||
{
|
||||
float split; diy::Direction dir;
|
||||
float split; diy::Direction dir(dim_,0);
|
||||
|
||||
int in_gid = link->target(i).gid;
|
||||
while(srp.incoming(in_gid))
|
||||
@ -287,7 +287,7 @@ update_links(Block* b, const diy::ReduceProxy& srp, int dim, int round, int roun
|
||||
if (wrap)
|
||||
new_link.add_wrap(find_wrap(new_link.bounds(), bounds, domain));
|
||||
else
|
||||
new_link.add_wrap(diy::Direction());
|
||||
new_link.add_wrap(diy::Direction(dim_,0));
|
||||
}
|
||||
} else // non-aligned side
|
||||
{
|
||||
@ -308,7 +308,7 @@ update_links(Block* b, const diy::ReduceProxy& srp, int dim, int round, int roun
|
||||
if (wrap)
|
||||
new_link.add_wrap(find_wrap(new_link.bounds(), bounds, domain));
|
||||
else
|
||||
new_link.add_wrap(diy::Direction());
|
||||
new_link.add_wrap(diy::Direction(dim_, 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -323,16 +323,16 @@ update_links(Block* b, const diy::ReduceProxy& srp, int dim, int round, int roun
|
||||
update_neighbor_bounds(nbr_bounds, find_split(new_link.bounds(), nbr_bounds), dim, !lower);
|
||||
new_link.add_bounds(nbr_bounds);
|
||||
|
||||
new_link.add_wrap(diy::Direction()); // dual block cannot be wrapped
|
||||
new_link.add_wrap(diy::Direction(dim_,0)); // dual block cannot be wrapped
|
||||
|
||||
if (lower)
|
||||
{
|
||||
diy::Direction right;
|
||||
diy::Direction right(dim_,0);
|
||||
right[dim] = 1;
|
||||
new_link.add_direction(right);
|
||||
} else
|
||||
{
|
||||
diy::Direction left;
|
||||
diy::Direction left(dim_,0);
|
||||
left[dim] = -1;
|
||||
new_link.add_direction(left);
|
||||
}
|
||||
@ -346,7 +346,7 @@ update_links(Block* b, const diy::ReduceProxy& srp, int dim, int round, int roun
|
||||
template<class Block, class Point>
|
||||
void
|
||||
diy::detail::KDTreePartition<Block,Point>::
|
||||
split_to_neighbors(Block* b, const diy::ReduceProxy& srp, int dim) const
|
||||
split_to_neighbors(Block*, const diy::ReduceProxy& srp, int) const
|
||||
{
|
||||
int lid = srp.master()->lid(srp.gid());
|
||||
RCLink* link = static_cast<RCLink*>(srp.master()->link(lid));
|
||||
@ -366,20 +366,23 @@ void
|
||||
diy::detail::KDTreePartition<Block,Point>::
|
||||
compute_local_histogram(Block* b, const diy::ReduceProxy& srp, int dim) const
|
||||
{
|
||||
auto udim = static_cast<unsigned>(dim);
|
||||
int lid = srp.master()->lid(srp.gid());
|
||||
RCLink* link = static_cast<RCLink*>(srp.master()->link(lid));
|
||||
|
||||
// compute and enqueue local histogram
|
||||
Histogram histogram(bins_);
|
||||
|
||||
float width = (link->core().max[dim] - link->core().min[dim])/bins_;
|
||||
float width = (link->core().max[udim] - link->core().min[udim])/bins_;
|
||||
for (size_t i = 0; i < (b->*points_).size(); ++i)
|
||||
{
|
||||
float x = (b->*points_)[i][dim];
|
||||
int loc = (x - link->core().min[dim]) / width;
|
||||
if (loc < 0)
|
||||
throw std::runtime_error(fmt::format("{} {} {}", loc, x, link->core().min[dim]));
|
||||
if (loc >= (int) bins_)
|
||||
float x = (b->*points_)[i][udim];
|
||||
float floc = (x - link->core().min[udim]) / width;
|
||||
if (floc < 0)
|
||||
throw std::runtime_error(fmt::format("{} {} {}", floc, x, link->core().min[udim]));
|
||||
|
||||
auto loc = static_cast<size_t>(floc);
|
||||
if (loc >= bins_)
|
||||
loc = bins_ - 1;
|
||||
++(histogram[loc]);
|
||||
}
|
||||
@ -390,7 +393,7 @@ compute_local_histogram(Block* b, const diy::ReduceProxy& srp, int dim) const
|
||||
template<class Block, class Point>
|
||||
void
|
||||
diy::detail::KDTreePartition<Block,Point>::
|
||||
add_histogram(Block* b, const diy::ReduceProxy& srp, Histogram& histogram) const
|
||||
add_histogram(Block*, const diy::ReduceProxy& srp, Histogram& histogram) const
|
||||
{
|
||||
// dequeue and add up the histograms
|
||||
for (int i = 0; i < srp.in_link().size(); ++i)
|
||||
@ -407,7 +410,7 @@ add_histogram(Block* b, const diy::ReduceProxy& srp, Histogram& histogram) const
|
||||
template<class Block, class Point>
|
||||
void
|
||||
diy::detail::KDTreePartition<Block,Point>::
|
||||
receive_histogram(Block* b, const diy::ReduceProxy& srp, Histogram& histogram) const
|
||||
receive_histogram(Block*, const diy::ReduceProxy& srp, Histogram& histogram) const
|
||||
{
|
||||
srp.dequeue(srp.in_link().target(0).gid, histogram);
|
||||
}
|
||||
@ -415,7 +418,7 @@ receive_histogram(Block* b, const diy::ReduceProxy& srp, Histogram& histogram) c
|
||||
template<class Block, class Point>
|
||||
void
|
||||
diy::detail::KDTreePartition<Block,Point>::
|
||||
forward_histogram(Block* b, const diy::ReduceProxy& srp, const Histogram& histogram) const
|
||||
forward_histogram(Block*, const diy::ReduceProxy& srp, const Histogram& histogram) const
|
||||
{
|
||||
for (int i = 0; i < srp.out_link().size(); ++i)
|
||||
srp.enqueue(srp.out_link().target(i), histogram);
|
||||
@ -445,19 +448,26 @@ enqueue_exchange(Block* b, const diy::ReduceProxy& srp, int dim, const Histogram
|
||||
size_t cur = 0;
|
||||
float width = (link->core().max[dim] - link->core().min[dim])/bins_;
|
||||
float split = 0;
|
||||
for (size_t i = 0; i < histogram.size(); ++i)
|
||||
|
||||
// scope-block for variable `i`
|
||||
{
|
||||
if (cur + histogram[i] > total/2)
|
||||
size_t i = 0;
|
||||
for (; i < histogram.size(); ++i)
|
||||
{
|
||||
split = link->core().min[dim] + width*i;
|
||||
break;
|
||||
if (cur + histogram[i] > total/2)
|
||||
break;
|
||||
cur += histogram[i];
|
||||
}
|
||||
cur += histogram[i];
|
||||
if (i == 0)
|
||||
++i;
|
||||
else if (i >= histogram.size() - 1)
|
||||
i = histogram.size() - 2;
|
||||
split = link->core().min[dim] + width*i;
|
||||
log->trace("Found split: {} (dim={}) in {} - {}", split, dim, link->core().min[dim], link->core().max[dim]);
|
||||
}
|
||||
log->trace("Found split: {} (dim={}) in {} - {}", split, dim, link->core().min[dim], link->core().max[dim]);
|
||||
|
||||
// subset and enqueue
|
||||
std::vector< std::vector<Point> > out_points(srp.out_link().size());
|
||||
std::vector< std::vector<Point> > out_points(static_cast<size_t>(srp.out_link().size()));
|
||||
for (size_t i = 0; i < (b->*points_).size(); ++i)
|
||||
{
|
||||
float x = (b->*points_)[i][dim];
|
||||
@ -554,7 +564,7 @@ diy::Direction
|
||||
diy::detail::KDTreePartition<Block,Point>::
|
||||
find_wrap(const Bounds& bounds, const Bounds& nbr_bounds, const Bounds& domain) const
|
||||
{
|
||||
diy::Direction wrap;
|
||||
diy::Direction wrap(dim_,0);
|
||||
for (int i = 0; i < dim_; ++i)
|
||||
{
|
||||
if (bounds.min[i] == domain.min[i] && nbr_bounds.max[i] == domain.max[i])
|
||||
|
@ -85,29 +85,29 @@ struct SampleSort<Block,T,Cmp>::Sampler
|
||||
Sampler(ValuesVector values_, ValuesVector dividers_, const Cmp& cmp_, size_t num_samples_):
|
||||
values(values_), dividers(dividers_), cmp(cmp_), num_samples(num_samples_) {}
|
||||
|
||||
void operator()(Block* b, const ReduceProxy& srp, const RegularSwapPartners& partners) const
|
||||
void operator()(Block* b, const ReduceProxy& srp, const RegularSwapPartners&) const
|
||||
{
|
||||
int k_in = srp.in_link().size();
|
||||
int k_out = srp.out_link().size();
|
||||
|
||||
std::vector<T> samples;
|
||||
std::vector<T> samps;
|
||||
|
||||
if (k_in == 0)
|
||||
{
|
||||
// draw random samples
|
||||
for (size_t i = 0; i < num_samples; ++i)
|
||||
samples.push_back((b->*values)[std::rand() % (b->*values).size()]);
|
||||
samps.push_back((b->*values)[std::rand() % (b->*values).size()]);
|
||||
} else
|
||||
dequeue_values(samples, srp, false);
|
||||
dequeue_values(samps, srp, false);
|
||||
|
||||
if (k_out == 0)
|
||||
{
|
||||
// pick subsamples that separate quantiles
|
||||
std::sort(samples.begin(), samples.end(), cmp);
|
||||
std::sort(samps.begin(), samps.end(), cmp);
|
||||
std::vector<T> subsamples(srp.nblocks() - 1);
|
||||
int step = samples.size() / srp.nblocks(); // NB: subsamples.size() + 1
|
||||
size_t step = samps.size() / srp.nblocks(); // NB: subsamples.size() + 1
|
||||
for (size_t i = 0; i < subsamples.size(); ++i)
|
||||
subsamples[i] = samples[(i+1)*step];
|
||||
subsamples[i] = samps[(i+1)*step];
|
||||
(b->*dividers).swap(subsamples);
|
||||
}
|
||||
else
|
||||
@ -115,7 +115,7 @@ struct SampleSort<Block,T,Cmp>::Sampler
|
||||
for (int i = 0; i < k_out; ++i)
|
||||
{
|
||||
MemoryBuffer& out = srp.outgoing(srp.out_link().target(i));
|
||||
save(out, &samples[0], samples.size());
|
||||
save(out, &samps[0], samps.size());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -139,7 +139,7 @@ struct SampleSort<Block,T,Cmp>::Exchanger
|
||||
// enqueue values to the correct locations
|
||||
for (size_t i = 0; i < (b->*values).size(); ++i)
|
||||
{
|
||||
int to = std::lower_bound((b->*samples).begin(), (b->*samples).end(), (b->*values)[i], cmp) - (b->*samples).begin();
|
||||
int to = static_cast<int>(std::lower_bound((b->*samples).begin(), (b->*samples).end(), (b->*values)[i], cmp) - (b->*samples).begin());
|
||||
rp.enqueue(rp.out_link().target(to), (b->*values)[i]);
|
||||
}
|
||||
(b->*values).clear();
|
||||
|
@ -20,7 +20,7 @@ namespace diy
|
||||
|
||||
void init() { out_ = in_; }
|
||||
void update(const CollectiveOp& other) { out_ = op_(out_, static_cast<const AllReduceOp&>(other).in_); }
|
||||
void global(const mpi::communicator& comm) { T res; mpi::all_reduce(comm, out_, res, op_); out_ = res; }
|
||||
void global(const mpi::communicator& comm) { T res{}; mpi::all_reduce(comm, out_, res, op_); out_ = res; }
|
||||
void copy_from(const CollectiveOp& other) { out_ = static_cast<const AllReduceOp&>(other).out_; }
|
||||
void result_out(void* dest) const { *reinterpret_cast<T*>(dest) = out_; }
|
||||
|
||||
@ -95,7 +95,7 @@ diy::Master::
|
||||
process_collectives()
|
||||
{
|
||||
auto scoped = prof.scoped("collectives");
|
||||
DIY_UNUSED(scoped);
|
||||
VTKMDIY_UNUSED(scoped);
|
||||
|
||||
if (collectives().empty())
|
||||
return;
|
||||
|
@ -1,10 +1,9 @@
|
||||
namespace diy
|
||||
{
|
||||
struct Master::tags { enum { queue, piece }; };
|
||||
|
||||
struct Master::MessageInfo
|
||||
{
|
||||
int from, to;
|
||||
int nparts;
|
||||
int round;
|
||||
};
|
||||
|
||||
@ -19,10 +18,10 @@ namespace diy
|
||||
struct Master::InFlightRecv
|
||||
{
|
||||
MemoryBuffer message;
|
||||
MessageInfo info { -1, -1, -1 };
|
||||
MessageInfo info { -1, -1, -1, -1 };
|
||||
bool done = false;
|
||||
|
||||
inline void recv(mpi::communicator& comm, const mpi::status& status);
|
||||
inline bool recv(mpi::communicator& comm, const mpi::status& status);
|
||||
inline void place(IncomingRound* in, bool unload, ExternalStorage* storage, IExchangeInfo* iexchange);
|
||||
void reset() { *this = InFlightRecv(); }
|
||||
};
|
||||
@ -43,32 +42,6 @@ namespace diy
|
||||
size_t limit = 0;
|
||||
};
|
||||
|
||||
struct Master::IExchangeInfo
|
||||
{
|
||||
IExchangeInfo():
|
||||
n(0) {}
|
||||
IExchangeInfo(size_t n_, mpi::communicator comm_):
|
||||
n(n_),
|
||||
comm(comm_),
|
||||
global_work_(new mpi::window<int>(comm, 1)) { global_work_->lock_all(MPI_MODE_NOCHECK); }
|
||||
~IExchangeInfo() { global_work_->unlock_all(); }
|
||||
|
||||
inline void not_done(int gid);
|
||||
|
||||
inline int global_work(); // get global work status (for debugging)
|
||||
inline bool all_done(); // get global all done status
|
||||
inline void reset_work(); // reset global work counter
|
||||
inline int add_work(int work); // add work to global work counter
|
||||
int inc_work() { return add_work(1); } // increment global work counter
|
||||
int dec_work() { return add_work(-1); } // decremnent global work counter
|
||||
|
||||
size_t n;
|
||||
mpi::communicator comm;
|
||||
std::unordered_map<int, bool> done; // gid -> done
|
||||
std::unique_ptr<mpi::window<int>> global_work_; // global work to do
|
||||
std::shared_ptr<spd::logger> log = get_logger();
|
||||
};
|
||||
|
||||
// VectorWindow is used to send and receive subsets of a contiguous array in-place
|
||||
namespace detail
|
||||
{
|
||||
@ -90,7 +63,7 @@ namespace diy
|
||||
struct mpi_datatype< diy::detail::VectorWindow<T> >
|
||||
{
|
||||
using VecWin = diy::detail::VectorWindow<T>;
|
||||
static MPI_Datatype datatype() { return get_mpi_datatype<T>(); }
|
||||
static diy::mpi::datatype datatype() { return get_mpi_datatype<T>(); }
|
||||
static const void* address(const VecWin& x) { return x.begin; }
|
||||
static void* address(VecWin& x) { return x.begin; }
|
||||
static int count(const VecWin& x) { return static_cast<int>(x.count); }
|
||||
@ -99,18 +72,8 @@ namespace diy
|
||||
} // namespace mpi::detail
|
||||
} // namespace diy
|
||||
|
||||
void
|
||||
diy::Master::IExchangeInfo::
|
||||
not_done(int gid)
|
||||
{
|
||||
if (done[gid])
|
||||
{
|
||||
done[gid] = false;
|
||||
int work = inc_work();
|
||||
log->debug("[{}] Incrementing work when switching done (on receipt): work = {}\n", gid, work);
|
||||
} else
|
||||
log->debug("[{}] Not done, no need to increment work\n", gid);
|
||||
}
|
||||
|
||||
/** InFlightRecv **/
|
||||
|
||||
diy::Master::InFlightRecv&
|
||||
diy::Master::
|
||||
@ -126,28 +89,27 @@ diy::Master::inflight_sends()
|
||||
}
|
||||
|
||||
// receive message described by status
|
||||
void
|
||||
bool
|
||||
diy::Master::InFlightRecv::
|
||||
recv(mpi::communicator& comm, const mpi::status& status)
|
||||
{
|
||||
bool result = false; // indicates whether this is the first (and possibly only) message of a given queue
|
||||
if (info.from == -1) // uninitialized
|
||||
{
|
||||
MemoryBuffer bb;
|
||||
comm.recv(status.source(), status.tag(), bb.buffer);
|
||||
|
||||
if (status.tag() == tags::piece) // first piece is the header
|
||||
diy::load_back(bb, info);
|
||||
info.nparts--;
|
||||
if (info.nparts > 0) // multi-part message
|
||||
{
|
||||
size_t msg_size;
|
||||
diy::load(bb, msg_size);
|
||||
diy::load(bb, info);
|
||||
|
||||
message.buffer.reserve(msg_size);
|
||||
}
|
||||
else // tags::queue
|
||||
{
|
||||
diy::load_back(bb, info);
|
||||
} else
|
||||
message.swap(bb);
|
||||
}
|
||||
|
||||
result = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -160,43 +122,34 @@ recv(mpi::communicator& comm, const mpi::status& status)
|
||||
window.count = count;
|
||||
|
||||
comm.recv(status.source(), status.tag(), window);
|
||||
|
||||
info.nparts--;
|
||||
}
|
||||
|
||||
if (status.tag() == tags::queue)
|
||||
if (info.nparts == 0)
|
||||
done = true;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// once the InFlightRecv is done, place it either out of core or in the appropriate incoming queue
|
||||
void
|
||||
diy::Master::InFlightRecv::
|
||||
place(IncomingRound* in, bool unload, ExternalStorage* storage, IExchangeInfo* iexchange)
|
||||
place(IncomingRound* in, bool unload, ExternalStorage* storage, IExchangeInfo*)
|
||||
{
|
||||
size_t size = message.size();
|
||||
int from = info.from;
|
||||
int to = info.to;
|
||||
int external = -1;
|
||||
|
||||
message.reset();
|
||||
|
||||
auto access = in->map[to][from].access();
|
||||
access->emplace_back(std::move(message));
|
||||
|
||||
if (unload)
|
||||
{
|
||||
get_logger()->debug("Directly unloading queue {} <- {}", to, from);
|
||||
external = storage->put(message); // unload directly
|
||||
access->back().unload(storage);
|
||||
}
|
||||
else if (!iexchange)
|
||||
{
|
||||
in->map[to].queues[from].swap(message);
|
||||
in->map[to].queues[from].reset(); // buffer position = 0
|
||||
}
|
||||
else // iexchange
|
||||
{
|
||||
auto log = get_logger();
|
||||
|
||||
iexchange->not_done(to);
|
||||
in->map[to].queues[from].append_binary(&message.buffer[0], message.size()); // append insted of overwrite
|
||||
|
||||
int work = iexchange->dec_work();
|
||||
log->debug("[{}] Decrementing work after receiving: work = {}\n", to, work);
|
||||
}
|
||||
in->map[to].records[from] = QueueRecord(size, external);
|
||||
|
||||
++(in->received);
|
||||
}
|
||||
|
@ -25,7 +25,10 @@ struct diy::Master::ProcessBlock
|
||||
if ((size_t)cur >= blocks.size())
|
||||
return;
|
||||
|
||||
int i = blocks[cur];
|
||||
int i = blocks[cur];
|
||||
int gid = master.gid(i);
|
||||
stats::Annotation::Guard g( stats::Annotation("diy.block").set(gid) );
|
||||
|
||||
if (master.block(i))
|
||||
{
|
||||
if (local.size() == (size_t)local_limit)
|
||||
@ -33,7 +36,7 @@ struct diy::Master::ProcessBlock
|
||||
local.push_back(i);
|
||||
}
|
||||
|
||||
master.log->debug("Processing block: {}", master.gid(i));
|
||||
master.log->debug("Processing block: {}", gid);
|
||||
|
||||
bool skip = all_skip(i);
|
||||
|
||||
@ -58,8 +61,7 @@ struct diy::Master::ProcessBlock
|
||||
cmd->execute(skip ? 0 : master.block(i), master.proxy(i));
|
||||
|
||||
// no longer need them, so get rid of them
|
||||
current_incoming[master.gid(i)].queues.clear();
|
||||
current_incoming[master.gid(i)].records.clear();
|
||||
current_incoming[gid].clear();
|
||||
}
|
||||
|
||||
if (skip && master.block(i) == 0)
|
||||
@ -93,7 +95,7 @@ execute()
|
||||
{
|
||||
log->debug("Entered execute()");
|
||||
auto scoped = prof.scoped("execute");
|
||||
DIY_UNUSED(scoped);
|
||||
VTKMDIY_UNUSED(scoped);
|
||||
//show_incoming_records();
|
||||
|
||||
// touch the outgoing and incoming queues as well as collectives to make sure they exist
|
||||
|
88
vtkm/thirdparty/diy/vtkmdiy/include/vtkmdiy/detail/master/iexchange-collective.hpp
vendored
Normal file
88
vtkm/thirdparty/diy/vtkmdiy/include/vtkmdiy/detail/master/iexchange-collective.hpp
vendored
Normal file
@ -0,0 +1,88 @@
|
||||
#include <atomic>
|
||||
|
||||
namespace diy
|
||||
{
|
||||
struct Master::IExchangeInfoCollective: public IExchangeInfo
|
||||
{
|
||||
IExchangeInfoCollective(mpi::communicator c, stats::Profiler& p):
|
||||
IExchangeInfo(c, p)
|
||||
{
|
||||
local_work_ = 0;
|
||||
dirty = 0;
|
||||
state = 0;
|
||||
}
|
||||
|
||||
inline bool all_done() override; // get global all done status
|
||||
inline void add_work(int work) override; // add work to global work counter
|
||||
inline void control() override;
|
||||
|
||||
std::atomic<int> local_work_;
|
||||
std::atomic<int> dirty;
|
||||
int local_dirty, all_dirty;
|
||||
|
||||
std::atomic<int> state;
|
||||
mpi::request r;
|
||||
|
||||
// debug
|
||||
bool first_ibarrier = true;
|
||||
|
||||
using IExchangeInfo::prof;
|
||||
};
|
||||
}
|
||||
|
||||
bool
|
||||
diy::Master::IExchangeInfoCollective::
|
||||
all_done()
|
||||
{
|
||||
return state == 3;
|
||||
}
|
||||
|
||||
void
|
||||
diy::Master::IExchangeInfoCollective::
|
||||
add_work(int work)
|
||||
{
|
||||
local_work_ += work;
|
||||
if (local_work_ > 0)
|
||||
dirty = 1;
|
||||
}
|
||||
|
||||
void
|
||||
diy::Master::IExchangeInfoCollective::
|
||||
control()
|
||||
{
|
||||
if (state == 0 && local_work_ == 0)
|
||||
{
|
||||
// debug
|
||||
if (first_ibarrier)
|
||||
{
|
||||
prof >> "iexchange-control"; // consensus-time cannot nest in iexchange-control
|
||||
prof << "consensus-time";
|
||||
prof << "iexchange-control";
|
||||
first_ibarrier = false;
|
||||
}
|
||||
|
||||
r = ibarrier(comm);
|
||||
dirty = 0;
|
||||
state = 1;
|
||||
} else if (state == 1)
|
||||
{
|
||||
mpi::optional<mpi::status> ostatus = r.test();
|
||||
if (ostatus)
|
||||
{
|
||||
local_dirty = dirty;
|
||||
r = mpi::iall_reduce(comm, local_dirty, all_dirty, std::logical_or<int>());
|
||||
state = 2;
|
||||
}
|
||||
} else if (state == 2)
|
||||
{
|
||||
mpi::optional<mpi::status> ostatus = r.test();
|
||||
if (ostatus)
|
||||
{
|
||||
if (all_dirty == 0) // done
|
||||
state = 3;
|
||||
else
|
||||
state = 0; // reset
|
||||
}
|
||||
}
|
||||
}
|
||||
|
28
vtkm/thirdparty/diy/vtkmdiy/include/vtkmdiy/detail/master/iexchange.hpp
vendored
Normal file
28
vtkm/thirdparty/diy/vtkmdiy/include/vtkmdiy/detail/master/iexchange.hpp
vendored
Normal file
@ -0,0 +1,28 @@
|
||||
namespace diy
|
||||
{
|
||||
struct Master::IExchangeInfo
|
||||
{
|
||||
using Clock = std::chrono::high_resolution_clock;
|
||||
using Time = Clock::time_point;
|
||||
|
||||
IExchangeInfo(mpi::communicator c, stats::Profiler& p):
|
||||
comm(c),
|
||||
prof(p) {}
|
||||
virtual ~IExchangeInfo() {}
|
||||
|
||||
virtual bool all_done() =0; // get global all done status
|
||||
virtual void add_work(int work) =0; // add work to global work counter
|
||||
virtual void control() =0;
|
||||
|
||||
void inc_work() { add_work(1); } // increment work counter
|
||||
void dec_work() { add_work(-1); } // decremnent work counter
|
||||
|
||||
mpi::communicator comm;
|
||||
|
||||
std::shared_ptr<spd::logger> log = get_logger();
|
||||
stats::Profiler& prof;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
#include "iexchange-collective.hpp"
|
@ -23,31 +23,38 @@ namespace detail
|
||||
}
|
||||
}
|
||||
|
||||
void operator()(Block* b, const ReduceProxy& srp, const RegularSwapPartners& partners) const
|
||||
void operator()(Block* b, const ReduceProxy& srp, const RegularSwapPartners&) const
|
||||
{
|
||||
int k_in = srp.in_link().size();
|
||||
int k_out = srp.out_link().size();
|
||||
|
||||
if (k_in == 0 && k_out == 0) // special case of a single block
|
||||
{
|
||||
ReduceProxy all_srp_out(srp, srp.block(), 0, srp.assigner(), empty_link, all_neighbors_link);
|
||||
ReduceProxy all_srp_in (srp, srp.block(), 1, srp.assigner(), all_neighbors_link, empty_link);
|
||||
ReduceProxy all_srp(std::move(const_cast<ReduceProxy&>(srp)), srp.block(), 0, srp.assigner(), empty_link, all_neighbors_link);
|
||||
|
||||
op(b, all_srp_out);
|
||||
MemoryBuffer& in_queue = all_srp_in.incoming(all_srp_in.in_link().target(0).gid);
|
||||
in_queue.swap(all_srp_out.outgoing(all_srp_out.out_link().target(0)));
|
||||
op(b, all_srp);
|
||||
|
||||
MemoryBuffer& in_queue = all_srp.incoming(all_srp.in_link().target(0).gid);
|
||||
in_queue.swap(all_srp.outgoing(all_srp.out_link().target(0)));
|
||||
in_queue.reset();
|
||||
all_srp.outgoing()->clear();
|
||||
|
||||
op(b, all_srp_in);
|
||||
// change to incoming proxy
|
||||
all_srp.set_round(1);
|
||||
auto& in_link = const_cast<Link&>(all_srp.in_link());
|
||||
auto& out_link = const_cast<Link&>(all_srp.out_link());
|
||||
in_link.swap(out_link);
|
||||
|
||||
op(b, all_srp);
|
||||
return;
|
||||
}
|
||||
|
||||
if (k_in == 0) // initial round
|
||||
{
|
||||
ReduceProxy all_srp(srp, srp.block(), 0, srp.assigner(), empty_link, all_neighbors_link);
|
||||
ReduceProxy all_srp(std::move(const_cast<ReduceProxy&>(srp)), srp.block(), 0, srp.assigner(), empty_link, all_neighbors_link);
|
||||
op(b, all_srp);
|
||||
|
||||
Master::OutgoingQueues all_queues;
|
||||
Master::Proxy::OutgoingQueues all_queues;
|
||||
all_queues.swap(*all_srp.outgoing()); // clears out the queues and stores them locally
|
||||
|
||||
// enqueue outgoing
|
||||
@ -67,10 +74,10 @@ namespace detail
|
||||
} else if (k_out == 0) // final round
|
||||
{
|
||||
// dequeue incoming + reorder into the correct order
|
||||
ReduceProxy all_srp(srp, srp.block(), 1, srp.assigner(), all_neighbors_link, empty_link);
|
||||
ReduceProxy all_srp(std::move(const_cast<ReduceProxy&>(srp)), srp.block(), 1, srp.assigner(), all_neighbors_link, empty_link);
|
||||
|
||||
Master::IncomingQueues all_incoming;
|
||||
all_incoming.swap(*srp.incoming());
|
||||
Master::Proxy::IncomingQueues all_incoming;
|
||||
all_incoming.swap(*all_srp.incoming());
|
||||
|
||||
std::pair<int, int> range; // all the ranges should be the same
|
||||
for (int i = 0; i < k_in; ++i)
|
||||
|
158
vtkm/thirdparty/diy/vtkmdiy/include/vtkmdiy/dynamic-point.hpp
vendored
Normal file
158
vtkm/thirdparty/diy/vtkmdiy/include/vtkmdiy/dynamic-point.hpp
vendored
Normal file
@ -0,0 +1,158 @@
|
||||
#ifndef VTKMDIY_DYNAMIC_POINT_HPP
|
||||
#define VTKMDIY_DYNAMIC_POINT_HPP
|
||||
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
#include "constants.h"
|
||||
#include "thirdparty/chobo/small_vector.hpp"
|
||||
|
||||
namespace diy
|
||||
{
|
||||
|
||||
template<class Coordinate_, size_t static_size = VTKMDIY_MAX_DIM>
|
||||
class DynamicPoint: public chobo::small_vector<Coordinate_, static_size>
|
||||
{
|
||||
public:
|
||||
using Coordinate = Coordinate_;
|
||||
using Parent = chobo::small_vector<Coordinate_, static_size>;
|
||||
|
||||
template<class U>
|
||||
struct rebind { typedef DynamicPoint<U> type; };
|
||||
|
||||
public:
|
||||
DynamicPoint(size_t dim, Coordinate x = 0):
|
||||
Parent(dim, x) {}
|
||||
template<class T> DynamicPoint(const DynamicPoint<T>& p) { for (size_t i = 0; i < dimension(); ++i) (*this)[i] = p[i]; }
|
||||
template<class T> DynamicPoint(const T* a, size_t dim) { for (size_t i = 0; i < dim; ++i) (*this)[i] = a[i]; }
|
||||
template<class T> DynamicPoint(const std::vector<T>& a):
|
||||
Parent(a.begin(), a.end()) {}
|
||||
DynamicPoint(std::initializer_list<Coordinate> lst):
|
||||
Parent(lst.size()) { size_t i = 0; for (Coordinate x : lst) (*this)[i++] = x; }
|
||||
|
||||
DynamicPoint(DynamicPoint&&) =default;
|
||||
DynamicPoint(const DynamicPoint&) =default;
|
||||
DynamicPoint& operator=(const DynamicPoint&) =default;
|
||||
|
||||
unsigned dimension() const { return static_cast<unsigned>(Parent::size()); }
|
||||
|
||||
static DynamicPoint zero(size_t dim) { return DynamicPoint(dim, 0); }
|
||||
static DynamicPoint one(size_t dim) { return DynamicPoint(dim, 1); }
|
||||
|
||||
DynamicPoint drop(size_t dim) const { DynamicPoint p(dimension() - 1); size_t c = 0; for (size_t i = 0; i < dimension(); ++i) { if (i == dim) continue; p[c++] = (*this)[i]; } return p; }
|
||||
DynamicPoint lift(size_t dim, Coordinate x) const { DynamicPoint p(dimension() + 1); for (size_t i = 0; i < dimension()+1; ++i) { if (i < dim) p[i] = (*this)[i]; else if (i == dim) p[i] = x; else if (i > dim) p[i] = (*this)[i-1]; } return p; }
|
||||
|
||||
using Parent::operator[];
|
||||
|
||||
DynamicPoint& operator+=(const DynamicPoint& y) { for (size_t i = 0; i < dimension(); ++i) (*this)[i] += y[i]; return *this; }
|
||||
DynamicPoint& operator-=(const DynamicPoint& y) { for (size_t i = 0; i < dimension(); ++i) (*this)[i] -= y[i]; return *this; }
|
||||
DynamicPoint& operator*=(Coordinate a) { for (size_t i = 0; i < dimension(); ++i) (*this)[i] *= a; return *this; }
|
||||
DynamicPoint& operator/=(Coordinate a) { for (size_t i = 0; i < dimension(); ++i) (*this)[i] /= a; return *this; }
|
||||
|
||||
DEPRECATED("Use norm2 instead")
|
||||
Coordinate norm() const { return norm2(); }
|
||||
Coordinate norm2() const { return (*this)*(*this); }
|
||||
|
||||
std::ostream& operator<<(std::ostream& out) const { out << (*this)[0]; for (size_t i = 1; i < dimension(); ++i) out << " " << (*this)[i]; return out; }
|
||||
std::istream& operator>>(std::istream& in);
|
||||
|
||||
friend
|
||||
DynamicPoint operator+(DynamicPoint x, const DynamicPoint& y) { x += y; return x; }
|
||||
|
||||
friend
|
||||
DynamicPoint operator-(DynamicPoint x, const DynamicPoint& y) { x -= y; return x; }
|
||||
|
||||
friend
|
||||
DynamicPoint operator/(DynamicPoint x, Coordinate y) { x /= y; return x; }
|
||||
|
||||
friend
|
||||
DynamicPoint operator*(DynamicPoint x, Coordinate y) { x *= y; return x; }
|
||||
|
||||
friend
|
||||
DynamicPoint operator*(Coordinate y, DynamicPoint x) { x *= y; return x; }
|
||||
|
||||
friend
|
||||
Coordinate operator*(const DynamicPoint& x, const DynamicPoint& y) { Coordinate n = 0; for (size_t i = 0; i < x.dimension(); ++i) n += x[i] * y[i]; return n; }
|
||||
|
||||
friend
|
||||
bool operator<(const DynamicPoint& x, const DynamicPoint& y) { return std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); }
|
||||
|
||||
friend
|
||||
bool operator>(const DynamicPoint& x, const DynamicPoint& y) { return y < x; }
|
||||
|
||||
template<class T, size_t s_>
|
||||
friend
|
||||
Coordinate operator*(const DynamicPoint<T,s_>& x, const DynamicPoint& y) { Coordinate n = 0; for (size_t i = 0; i < x.dimension(); ++i) n += x[i] * y[i]; return n; }
|
||||
};
|
||||
|
||||
template<class C, size_t s_>
|
||||
std::istream&
|
||||
DynamicPoint<C,s_>::
|
||||
operator>>(std::istream& in)
|
||||
{
|
||||
std::string point_str;
|
||||
in >> point_str; // read until ' '
|
||||
std::stringstream ps(point_str);
|
||||
|
||||
char x;
|
||||
for (unsigned i = 0; i < dimension(); ++i)
|
||||
{
|
||||
ps >> (*this)[i];
|
||||
ps >> x;
|
||||
}
|
||||
|
||||
return in;
|
||||
}
|
||||
|
||||
|
||||
template<class Coordinate, size_t s_>
|
||||
Coordinate norm2(const DynamicPoint<Coordinate,s_>& p)
|
||||
{ Coordinate res = 0; for (unsigned i = 0; i < p.dimension(); ++i) res += p[i]*p[i]; return res; }
|
||||
|
||||
template<class C, size_t s_>
|
||||
std::ostream&
|
||||
operator<<(std::ostream& out, const DynamicPoint<C,s_>& p)
|
||||
{ return p.operator<<(out); }
|
||||
|
||||
template<class C, size_t s_>
|
||||
std::istream&
|
||||
operator>>(std::istream& in, DynamicPoint<C,s_>& p)
|
||||
{ return p.operator>>(in); }
|
||||
|
||||
// Serialization
|
||||
template<class T>
|
||||
struct Serialization;
|
||||
struct BinaryBuffer;
|
||||
template<class T> void save(BinaryBuffer&, const T&);
|
||||
template<class T> void load(BinaryBuffer&, T&);
|
||||
template<class T> void save(BinaryBuffer&, const T*, size_t);
|
||||
template<class T> void load(BinaryBuffer&, T*, size_t);
|
||||
|
||||
template<class C, size_t s_>
|
||||
struct Serialization<DynamicPoint<C, s_>>
|
||||
{
|
||||
using Point = DynamicPoint<C,s_>;
|
||||
|
||||
static void save(BinaryBuffer& bb, const Point& p)
|
||||
{
|
||||
size_t s = p.size();
|
||||
diy::save(bb, s);
|
||||
if (s > 0)
|
||||
diy::save(bb, &p[0], p.size());
|
||||
}
|
||||
|
||||
static void load(BinaryBuffer& bb, Point& p)
|
||||
{
|
||||
size_t s;
|
||||
diy::load(bb, s);
|
||||
p.resize(s);
|
||||
if (s > 0)
|
||||
diy::load(bb, &p[0], s);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // VTKMDIY_POINT_HPP
|
84
vtkm/thirdparty/diy/vtkmdiy/include/vtkmdiy/factory.hpp
vendored
Normal file
84
vtkm/thirdparty/diy/vtkmdiy/include/vtkmdiy/factory.hpp
vendored
Normal file
@ -0,0 +1,84 @@
|
||||
#ifndef VTKMDIY_FACTORY_HPP
|
||||
#define VTKMDIY_FACTORY_HPP
|
||||
|
||||
// From http://www.nirfriedman.com/2018/04/29/unforgettable-factory/
|
||||
// with minor changes.
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace diy
|
||||
{
|
||||
|
||||
template <class Base, class... Args>
|
||||
class Factory
|
||||
{
|
||||
public:
|
||||
template <class... T>
|
||||
static Base* make(const std::string &s, T&&... args)
|
||||
{
|
||||
return data().at(s)(std::forward<T>(args)...);
|
||||
}
|
||||
|
||||
virtual std::string id() const { return typeid(Base).name(); }
|
||||
|
||||
template <class T>
|
||||
struct Registrar: Base
|
||||
{
|
||||
static bool registerT()
|
||||
{
|
||||
const auto name = typeid(T).name();
|
||||
Factory::data()[name] = [](Args... args) -> Base*
|
||||
{
|
||||
return new T(std::forward<Args>(args)...);
|
||||
};
|
||||
return true;
|
||||
}
|
||||
static volatile bool registered;
|
||||
|
||||
std::string id() const override { return typeid(T).name(); }
|
||||
|
||||
#if defined(__NVCC__)
|
||||
protected:
|
||||
#else
|
||||
private:
|
||||
friend T;
|
||||
#endif
|
||||
#if defined(__INTEL_COMPILER)
|
||||
__attribute__ ((used))
|
||||
#endif
|
||||
Registrar(): Base(Key{}) { (void)registered; }
|
||||
};
|
||||
|
||||
|
||||
#if defined(__NVCC__)
|
||||
protected:
|
||||
#else
|
||||
private:
|
||||
friend Base;
|
||||
#endif
|
||||
class Key
|
||||
{
|
||||
Key(){};
|
||||
template <class T> friend struct Registrar;
|
||||
};
|
||||
|
||||
using FuncType = Base* (*)(Args...);
|
||||
|
||||
Factory() = default;
|
||||
|
||||
static std::unordered_map<std::string, FuncType>& data()
|
||||
{
|
||||
static std::unordered_map<std::string, FuncType> s;
|
||||
return s;
|
||||
}
|
||||
};
|
||||
|
||||
template <class Base, class... Args>
|
||||
template <class T>
|
||||
volatile bool Factory<Base, Args...>::Registrar<T>::registered = Factory<Base, Args...>::Registrar<T>::registerT();
|
||||
|
||||
}
|
||||
|
||||
#endif
|
@ -1,535 +0,0 @@
|
||||
/*
|
||||
Formatting library for C++
|
||||
|
||||
Copyright (c) 2012 - 2016, Victor Zverovich
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "format.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <cctype>
|
||||
#include <cerrno>
|
||||
#include <climits>
|
||||
#include <cmath>
|
||||
#include <cstdarg>
|
||||
#include <cstddef> // for std::ptrdiff_t
|
||||
|
||||
#if defined(_WIN32) && defined(__MINGW32__)
|
||||
# include <cstring>
|
||||
#endif
|
||||
|
||||
#if FMT_USE_WINDOWS_H
|
||||
# if !defined(FMT_HEADER_ONLY) && !defined(WIN32_LEAN_AND_MEAN)
|
||||
# define WIN32_LEAN_AND_MEAN
|
||||
# endif
|
||||
# if defined(NOMINMAX) || defined(FMT_WIN_MINMAX)
|
||||
# include <windows.h>
|
||||
# else
|
||||
# define NOMINMAX
|
||||
# include <windows.h>
|
||||
# undef NOMINMAX
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if FMT_EXCEPTIONS
|
||||
# define FMT_TRY try
|
||||
# define FMT_CATCH(x) catch (x)
|
||||
#else
|
||||
# define FMT_TRY if (true)
|
||||
# define FMT_CATCH(x) if (false)
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable: 4127) // conditional expression is constant
|
||||
# pragma warning(disable: 4702) // unreachable code
|
||||
// Disable deprecation warning for strerror. The latter is not called but
|
||||
// MSVC fails to detect it.
|
||||
# pragma warning(disable: 4996)
|
||||
#endif
|
||||
|
||||
// Dummy implementations of strerror_r and strerror_s called if corresponding
|
||||
// system functions are not available.
|
||||
static inline fmt::internal::Null<> strerror_r(int, char *, ...) {
|
||||
return fmt::internal::Null<>();
|
||||
}
|
||||
static inline fmt::internal::Null<> strerror_s(char *, std::size_t, ...) {
|
||||
return fmt::internal::Null<>();
|
||||
}
|
||||
|
||||
namespace fmt {
|
||||
|
||||
FMT_FUNC internal::RuntimeError::~RuntimeError() FMT_DTOR_NOEXCEPT {}
|
||||
FMT_FUNC FormatError::~FormatError() FMT_DTOR_NOEXCEPT {}
|
||||
FMT_FUNC SystemError::~SystemError() FMT_DTOR_NOEXCEPT {}
|
||||
|
||||
namespace {
|
||||
|
||||
#ifndef _MSC_VER
|
||||
# define FMT_SNPRINTF snprintf
|
||||
#else // _MSC_VER
|
||||
inline int fmt_snprintf(char *buffer, size_t size, const char *format, ...) {
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
int result = vsnprintf_s(buffer, size, _TRUNCATE, format, args);
|
||||
va_end(args);
|
||||
return result;
|
||||
}
|
||||
# define FMT_SNPRINTF fmt_snprintf
|
||||
#endif // _MSC_VER
|
||||
|
||||
#if defined(_WIN32) && defined(__MINGW32__) && !defined(__NO_ISOCEXT)
|
||||
# define FMT_SWPRINTF snwprintf
|
||||
#else
|
||||
# define FMT_SWPRINTF swprintf
|
||||
#endif // defined(_WIN32) && defined(__MINGW32__) && !defined(__NO_ISOCEXT)
|
||||
|
||||
const char RESET_COLOR[] = "\x1b[0m";
|
||||
|
||||
typedef void (*FormatFunc)(Writer &, int, StringRef);
|
||||
|
||||
// Portable thread-safe version of strerror.
|
||||
// Sets buffer to point to a string describing the error code.
|
||||
// This can be either a pointer to a string stored in buffer,
|
||||
// or a pointer to some static immutable string.
|
||||
// Returns one of the following values:
|
||||
// 0 - success
|
||||
// ERANGE - buffer is not large enough to store the error message
|
||||
// other - failure
|
||||
// Buffer should be at least of size 1.
|
||||
int safe_strerror(
|
||||
int error_code, char *&buffer, std::size_t buffer_size) FMT_NOEXCEPT {
|
||||
FMT_ASSERT(buffer != 0 && buffer_size != 0, "invalid buffer");
|
||||
|
||||
class StrError {
|
||||
private:
|
||||
int error_code_;
|
||||
char *&buffer_;
|
||||
std::size_t buffer_size_;
|
||||
|
||||
// A noop assignment operator to avoid bogus warnings.
|
||||
void operator=(const StrError &) {}
|
||||
|
||||
// Handle the result of XSI-compliant version of strerror_r.
|
||||
int handle(int result) {
|
||||
// glibc versions before 2.13 return result in errno.
|
||||
return result == -1 ? errno : result;
|
||||
}
|
||||
|
||||
// Handle the result of GNU-specific version of strerror_r.
|
||||
int handle(char *message) {
|
||||
// If the buffer is full then the message is probably truncated.
|
||||
if (message == buffer_ && strlen(buffer_) == buffer_size_ - 1)
|
||||
return ERANGE;
|
||||
buffer_ = message;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Handle the case when strerror_r is not available.
|
||||
int handle(internal::Null<>) {
|
||||
return fallback(strerror_s(buffer_, buffer_size_, error_code_));
|
||||
}
|
||||
|
||||
// Fallback to strerror_s when strerror_r is not available.
|
||||
int fallback(int result) {
|
||||
// If the buffer is full then the message is probably truncated.
|
||||
return result == 0 && strlen(buffer_) == buffer_size_ - 1 ?
|
||||
ERANGE : result;
|
||||
}
|
||||
|
||||
// Fallback to strerror if strerror_r and strerror_s are not available.
|
||||
int fallback(internal::Null<>) {
|
||||
errno = 0;
|
||||
buffer_ = strerror(error_code_);
|
||||
return errno;
|
||||
}
|
||||
|
||||
public:
|
||||
StrError(int err_code, char *&buf, std::size_t buf_size)
|
||||
: error_code_(err_code), buffer_(buf), buffer_size_(buf_size) {}
|
||||
|
||||
int run() {
|
||||
// Suppress a warning about unused strerror_r.
|
||||
strerror_r(0, FMT_NULL, "");
|
||||
return handle(strerror_r(error_code_, buffer_, buffer_size_));
|
||||
}
|
||||
};
|
||||
return StrError(error_code, buffer, buffer_size).run();
|
||||
}
|
||||
|
||||
void format_error_code(Writer &out, int error_code,
|
||||
StringRef message) FMT_NOEXCEPT {
|
||||
// Report error code making sure that the output fits into
|
||||
// INLINE_BUFFER_SIZE to avoid dynamic memory allocation and potential
|
||||
// bad_alloc.
|
||||
out.clear();
|
||||
static const char SEP[] = ": ";
|
||||
static const char ERROR_STR[] = "error ";
|
||||
// Subtract 2 to account for terminating null characters in SEP and ERROR_STR.
|
||||
std::size_t error_code_size = sizeof(SEP) + sizeof(ERROR_STR) - 2;
|
||||
typedef internal::IntTraits<int>::MainType MainType;
|
||||
MainType abs_value = static_cast<MainType>(error_code);
|
||||
if (internal::is_negative(error_code)) {
|
||||
abs_value = 0 - abs_value;
|
||||
++error_code_size;
|
||||
}
|
||||
error_code_size += internal::count_digits(abs_value);
|
||||
if (message.size() <= internal::INLINE_BUFFER_SIZE - error_code_size)
|
||||
out << message << SEP;
|
||||
out << ERROR_STR << error_code;
|
||||
assert(out.size() <= internal::INLINE_BUFFER_SIZE);
|
||||
}
|
||||
|
||||
void report_error(FormatFunc func, int error_code,
|
||||
StringRef message) FMT_NOEXCEPT {
|
||||
MemoryWriter full_message;
|
||||
func(full_message, error_code, message);
|
||||
// Use Writer::data instead of Writer::c_str to avoid potential memory
|
||||
// allocation.
|
||||
std::fwrite(full_message.data(), full_message.size(), 1, stderr);
|
||||
std::fputc('\n', stderr);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
FMT_FUNC void SystemError::init(
|
||||
int err_code, CStringRef format_str, ArgList args) {
|
||||
error_code_ = err_code;
|
||||
MemoryWriter w;
|
||||
format_system_error(w, err_code, format(format_str, args));
|
||||
std::runtime_error &base = *this;
|
||||
base = std::runtime_error(w.str());
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
int internal::CharTraits<char>::format_float(
|
||||
char *buffer, std::size_t size, const char *format,
|
||||
unsigned width, int precision, T value) {
|
||||
if (width == 0) {
|
||||
return precision < 0 ?
|
||||
FMT_SNPRINTF(buffer, size, format, value) :
|
||||
FMT_SNPRINTF(buffer, size, format, precision, value);
|
||||
}
|
||||
return precision < 0 ?
|
||||
FMT_SNPRINTF(buffer, size, format, width, value) :
|
||||
FMT_SNPRINTF(buffer, size, format, width, precision, value);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
int internal::CharTraits<wchar_t>::format_float(
|
||||
wchar_t *buffer, std::size_t size, const wchar_t *format,
|
||||
unsigned width, int precision, T value) {
|
||||
if (width == 0) {
|
||||
return precision < 0 ?
|
||||
FMT_SWPRINTF(buffer, size, format, value) :
|
||||
FMT_SWPRINTF(buffer, size, format, precision, value);
|
||||
}
|
||||
return precision < 0 ?
|
||||
FMT_SWPRINTF(buffer, size, format, width, value) :
|
||||
FMT_SWPRINTF(buffer, size, format, width, precision, value);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
const char internal::BasicData<T>::DIGITS[] =
|
||||
"0001020304050607080910111213141516171819"
|
||||
"2021222324252627282930313233343536373839"
|
||||
"4041424344454647484950515253545556575859"
|
||||
"6061626364656667686970717273747576777879"
|
||||
"8081828384858687888990919293949596979899";
|
||||
|
||||
#define FMT_POWERS_OF_10(factor) \
|
||||
factor * 10, \
|
||||
factor * 100, \
|
||||
factor * 1000, \
|
||||
factor * 10000, \
|
||||
factor * 100000, \
|
||||
factor * 1000000, \
|
||||
factor * 10000000, \
|
||||
factor * 100000000, \
|
||||
factor * 1000000000
|
||||
|
||||
template <typename T>
|
||||
const uint32_t internal::BasicData<T>::POWERS_OF_10_32[] = {
|
||||
0, FMT_POWERS_OF_10(1)
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
const uint64_t internal::BasicData<T>::POWERS_OF_10_64[] = {
|
||||
0,
|
||||
FMT_POWERS_OF_10(1),
|
||||
FMT_POWERS_OF_10(ULongLong(1000000000)),
|
||||
// Multiply several constants instead of using a single long long constant
|
||||
// to avoid warnings about C++98 not supporting long long.
|
||||
ULongLong(1000000000) * ULongLong(1000000000) * 10
|
||||
};
|
||||
|
||||
FMT_FUNC void internal::report_unknown_type(char code, const char *type) {
|
||||
(void)type;
|
||||
if (std::isprint(static_cast<unsigned char>(code))) {
|
||||
FMT_THROW(FormatError(
|
||||
format("unknown format code '{}' for {}", code, type)));
|
||||
}
|
||||
FMT_THROW(FormatError(
|
||||
format("unknown format code '\\x{:02x}' for {}",
|
||||
static_cast<unsigned>(code), type)));
|
||||
}
|
||||
|
||||
#if FMT_USE_WINDOWS_H
|
||||
|
||||
FMT_FUNC internal::UTF8ToUTF16::UTF8ToUTF16(StringRef s) {
|
||||
static const char ERROR_MSG[] = "cannot convert string from UTF-8 to UTF-16";
|
||||
if (s.size() > INT_MAX)
|
||||
FMT_THROW(WindowsError(ERROR_INVALID_PARAMETER, ERROR_MSG));
|
||||
int s_size = static_cast<int>(s.size());
|
||||
int length = MultiByteToWideChar(
|
||||
CP_UTF8, MB_ERR_INVALID_CHARS, s.data(), s_size, FMT_NULL, 0);
|
||||
if (length == 0)
|
||||
FMT_THROW(WindowsError(GetLastError(), ERROR_MSG));
|
||||
buffer_.resize(length + 1);
|
||||
length = MultiByteToWideChar(
|
||||
CP_UTF8, MB_ERR_INVALID_CHARS, s.data(), s_size, &buffer_[0], length);
|
||||
if (length == 0)
|
||||
FMT_THROW(WindowsError(GetLastError(), ERROR_MSG));
|
||||
buffer_[length] = 0;
|
||||
}
|
||||
|
||||
FMT_FUNC internal::UTF16ToUTF8::UTF16ToUTF8(WStringRef s) {
|
||||
if (int error_code = convert(s)) {
|
||||
FMT_THROW(WindowsError(error_code,
|
||||
"cannot convert string from UTF-16 to UTF-8"));
|
||||
}
|
||||
}
|
||||
|
||||
FMT_FUNC int internal::UTF16ToUTF8::convert(WStringRef s) {
|
||||
if (s.size() > INT_MAX)
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
int s_size = static_cast<int>(s.size());
|
||||
int length = WideCharToMultiByte(
|
||||
CP_UTF8, 0, s.data(), s_size, FMT_NULL, 0, FMT_NULL, FMT_NULL);
|
||||
if (length == 0)
|
||||
return GetLastError();
|
||||
buffer_.resize(length + 1);
|
||||
length = WideCharToMultiByte(
|
||||
CP_UTF8, 0, s.data(), s_size, &buffer_[0], length, FMT_NULL, FMT_NULL);
|
||||
if (length == 0)
|
||||
return GetLastError();
|
||||
buffer_[length] = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
FMT_FUNC void WindowsError::init(
|
||||
int err_code, CStringRef format_str, ArgList args) {
|
||||
error_code_ = err_code;
|
||||
MemoryWriter w;
|
||||
internal::format_windows_error(w, err_code, format(format_str, args));
|
||||
std::runtime_error &base = *this;
|
||||
base = std::runtime_error(w.str());
|
||||
}
|
||||
|
||||
FMT_FUNC void internal::format_windows_error(
|
||||
Writer &out, int error_code, StringRef message) FMT_NOEXCEPT {
|
||||
FMT_TRY {
|
||||
MemoryBuffer<wchar_t, INLINE_BUFFER_SIZE> buffer;
|
||||
buffer.resize(INLINE_BUFFER_SIZE);
|
||||
for (;;) {
|
||||
wchar_t *system_message = &buffer[0];
|
||||
int result = FormatMessageW(
|
||||
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
FMT_NULL, error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||
system_message, static_cast<uint32_t>(buffer.size()), FMT_NULL);
|
||||
if (result != 0) {
|
||||
UTF16ToUTF8 utf8_message;
|
||||
if (utf8_message.convert(system_message) == ERROR_SUCCESS) {
|
||||
out << message << ": " << utf8_message;
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
|
||||
break; // Can't get error message, report error code instead.
|
||||
buffer.resize(buffer.size() * 2);
|
||||
}
|
||||
} FMT_CATCH(...) {}
|
||||
fmt::format_error_code(out, error_code, message); // 'fmt::' is for bcc32.
|
||||
}
|
||||
|
||||
#endif // FMT_USE_WINDOWS_H
|
||||
|
||||
FMT_FUNC void format_system_error(
|
||||
Writer &out, int error_code, StringRef message) FMT_NOEXCEPT {
|
||||
FMT_TRY {
|
||||
internal::MemoryBuffer<char, internal::INLINE_BUFFER_SIZE> buffer;
|
||||
buffer.resize(internal::INLINE_BUFFER_SIZE);
|
||||
for (;;) {
|
||||
char *system_message = &buffer[0];
|
||||
int result = safe_strerror(error_code, system_message, buffer.size());
|
||||
if (result == 0) {
|
||||
out << message << ": " << system_message;
|
||||
return;
|
||||
}
|
||||
if (result != ERANGE)
|
||||
break; // Can't get error message, report error code instead.
|
||||
buffer.resize(buffer.size() * 2);
|
||||
}
|
||||
} FMT_CATCH(...) {}
|
||||
fmt::format_error_code(out, error_code, message); // 'fmt::' is for bcc32.
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
void internal::ArgMap<Char>::init(const ArgList &args) {
|
||||
if (!map_.empty())
|
||||
return;
|
||||
typedef internal::NamedArg<Char> NamedArg;
|
||||
const NamedArg *named_arg = FMT_NULL;
|
||||
bool use_values =
|
||||
args.type(ArgList::MAX_PACKED_ARGS - 1) == internal::Arg::NONE;
|
||||
if (use_values) {
|
||||
for (unsigned i = 0;/*nothing*/; ++i) {
|
||||
internal::Arg::Type arg_type = args.type(i);
|
||||
switch (arg_type) {
|
||||
case internal::Arg::NONE:
|
||||
return;
|
||||
case internal::Arg::NAMED_ARG:
|
||||
named_arg = static_cast<const NamedArg*>(args.values_[i].pointer);
|
||||
map_.push_back(Pair(named_arg->name, *named_arg));
|
||||
break;
|
||||
default:
|
||||
/*nothing*/;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
for (unsigned i = 0; i != ArgList::MAX_PACKED_ARGS; ++i) {
|
||||
internal::Arg::Type arg_type = args.type(i);
|
||||
if (arg_type == internal::Arg::NAMED_ARG) {
|
||||
named_arg = static_cast<const NamedArg*>(args.args_[i].pointer);
|
||||
map_.push_back(Pair(named_arg->name, *named_arg));
|
||||
}
|
||||
}
|
||||
for (unsigned i = ArgList::MAX_PACKED_ARGS;/*nothing*/; ++i) {
|
||||
switch (args.args_[i].type) {
|
||||
case internal::Arg::NONE:
|
||||
return;
|
||||
case internal::Arg::NAMED_ARG:
|
||||
named_arg = static_cast<const NamedArg*>(args.args_[i].pointer);
|
||||
map_.push_back(Pair(named_arg->name, *named_arg));
|
||||
break;
|
||||
default:
|
||||
/*nothing*/;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
void internal::FixedBuffer<Char>::grow(std::size_t) {
|
||||
FMT_THROW(std::runtime_error("buffer overflow"));
|
||||
}
|
||||
|
||||
FMT_FUNC internal::Arg internal::FormatterBase::do_get_arg(
|
||||
unsigned arg_index, const char *&error) {
|
||||
internal::Arg arg = args_[arg_index];
|
||||
switch (arg.type) {
|
||||
case internal::Arg::NONE:
|
||||
error = "argument index out of range";
|
||||
break;
|
||||
case internal::Arg::NAMED_ARG:
|
||||
arg = *static_cast<const internal::Arg*>(arg.pointer);
|
||||
break;
|
||||
default:
|
||||
/*nothing*/;
|
||||
}
|
||||
return arg;
|
||||
}
|
||||
|
||||
FMT_FUNC void report_system_error(
|
||||
int error_code, fmt::StringRef message) FMT_NOEXCEPT {
|
||||
// 'fmt::' is for bcc32.
|
||||
report_error(format_system_error, error_code, message);
|
||||
}
|
||||
|
||||
#if FMT_USE_WINDOWS_H
|
||||
FMT_FUNC void report_windows_error(
|
||||
int error_code, fmt::StringRef message) FMT_NOEXCEPT {
|
||||
// 'fmt::' is for bcc32.
|
||||
report_error(internal::format_windows_error, error_code, message);
|
||||
}
|
||||
#endif
|
||||
|
||||
FMT_FUNC void print(std::FILE *f, CStringRef format_str, ArgList args) {
|
||||
MemoryWriter w;
|
||||
w.write(format_str, args);
|
||||
std::fwrite(w.data(), 1, w.size(), f);
|
||||
}
|
||||
|
||||
FMT_FUNC void print(CStringRef format_str, ArgList args) {
|
||||
print(stdout, format_str, args);
|
||||
}
|
||||
|
||||
FMT_FUNC void print_colored(Color c, CStringRef format, ArgList args) {
|
||||
char escape[] = "\x1b[30m";
|
||||
escape[3] = static_cast<char>('0' + c);
|
||||
std::fputs(escape, stdout);
|
||||
print(format, args);
|
||||
std::fputs(RESET_COLOR, stdout);
|
||||
}
|
||||
|
||||
#ifndef FMT_HEADER_ONLY
|
||||
|
||||
template struct internal::BasicData<void>;
|
||||
|
||||
// Explicit instantiations for char.
|
||||
|
||||
template void internal::FixedBuffer<char>::grow(std::size_t);
|
||||
|
||||
template void internal::ArgMap<char>::init(const ArgList &args);
|
||||
|
||||
template FMT_API int internal::CharTraits<char>::format_float(
|
||||
char *buffer, std::size_t size, const char *format,
|
||||
unsigned width, int precision, double value);
|
||||
|
||||
template FMT_API int internal::CharTraits<char>::format_float(
|
||||
char *buffer, std::size_t size, const char *format,
|
||||
unsigned width, int precision, long double value);
|
||||
|
||||
// Explicit instantiations for wchar_t.
|
||||
|
||||
template void internal::FixedBuffer<wchar_t>::grow(std::size_t);
|
||||
|
||||
template void internal::ArgMap<wchar_t>::init(const ArgList &args);
|
||||
|
||||
template FMT_API int internal::CharTraits<wchar_t>::format_float(
|
||||
wchar_t *buffer, std::size_t size, const wchar_t *format,
|
||||
unsigned width, int precision, double value);
|
||||
|
||||
template FMT_API int internal::CharTraits<wchar_t>::format_float(
|
||||
wchar_t *buffer, std::size_t size, const wchar_t *format,
|
||||
unsigned width, int precision, long double value);
|
||||
|
||||
#endif // FMT_HEADER_ONLY
|
||||
|
||||
} // namespace fmt
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# pragma warning(pop)
|
||||
#endif
|
4018
vtkm/thirdparty/diy/vtkmdiy/include/vtkmdiy/fmt/format.h
vendored
4018
vtkm/thirdparty/diy/vtkmdiy/include/vtkmdiy/fmt/format.h
vendored
File diff suppressed because it is too large
Load Diff
@ -1,35 +0,0 @@
|
||||
/*
|
||||
Formatting library for C++ - std::ostream support
|
||||
|
||||
Copyright (c) 2012 - 2016, Victor Zverovich
|
||||
All rights reserved.
|
||||
|
||||
For the license information refer to format.h.
|
||||
*/
|
||||
|
||||
#include "ostream.h"
|
||||
|
||||
namespace fmt {
|
||||
|
||||
namespace internal {
|
||||
FMT_FUNC void write(std::ostream &os, Writer &w) {
|
||||
const char *data = w.data();
|
||||
typedef internal::MakeUnsigned<std::streamsize>::Type UnsignedStreamSize;
|
||||
UnsignedStreamSize size = w.size();
|
||||
UnsignedStreamSize max_size =
|
||||
internal::to_unsigned((std::numeric_limits<std::streamsize>::max)());
|
||||
do {
|
||||
UnsignedStreamSize n = size <= max_size ? size : max_size;
|
||||
os.write(data, static_cast<std::streamsize>(n));
|
||||
data += n;
|
||||
size -= n;
|
||||
} while (size != 0);
|
||||
}
|
||||
}
|
||||
|
||||
FMT_FUNC void print(std::ostream &os, CStringRef format_str, ArgList args) {
|
||||
MemoryWriter w;
|
||||
w.write(format_str, args);
|
||||
internal::write(os, w);
|
||||
}
|
||||
} // namespace fmt
|
@ -1,105 +0,0 @@
|
||||
/*
|
||||
Formatting library for C++ - std::ostream support
|
||||
|
||||
Copyright (c) 2012 - 2016, Victor Zverovich
|
||||
All rights reserved.
|
||||
|
||||
For the license information refer to format.h.
|
||||
*/
|
||||
|
||||
#ifndef FMT_OSTREAM_H_
|
||||
#define FMT_OSTREAM_H_
|
||||
|
||||
#include "format.h"
|
||||
#include <ostream>
|
||||
|
||||
namespace fmt {
|
||||
|
||||
namespace internal {
|
||||
|
||||
template <class Char>
|
||||
class FormatBuf : public std::basic_streambuf<Char> {
|
||||
private:
|
||||
typedef typename std::basic_streambuf<Char>::int_type int_type;
|
||||
typedef typename std::basic_streambuf<Char>::traits_type traits_type;
|
||||
|
||||
Buffer<Char> &buffer_;
|
||||
|
||||
public:
|
||||
FormatBuf(Buffer<Char> &buffer) : buffer_(buffer) {}
|
||||
|
||||
protected:
|
||||
// The put-area is actually always empty. This makes the implementation
|
||||
// simpler and has the advantage that the streambuf and the buffer are always
|
||||
// in sync and sputc never writes into uninitialized memory. The obvious
|
||||
// disadvantage is that each call to sputc always results in a (virtual) call
|
||||
// to overflow. There is no disadvantage here for sputn since this always
|
||||
// results in a call to xsputn.
|
||||
|
||||
int_type overflow(int_type ch = traits_type::eof()) FMT_OVERRIDE {
|
||||
if (!traits_type::eq_int_type(ch, traits_type::eof()))
|
||||
buffer_.push_back(static_cast<Char>(ch));
|
||||
return ch;
|
||||
}
|
||||
|
||||
std::streamsize xsputn(const Char *s, std::streamsize count) FMT_OVERRIDE {
|
||||
buffer_.append(s, s + count);
|
||||
return count;
|
||||
}
|
||||
};
|
||||
|
||||
Yes &convert(std::ostream &);
|
||||
|
||||
struct DummyStream : std::ostream {
|
||||
DummyStream(); // Suppress a bogus warning in MSVC.
|
||||
// Hide all operator<< overloads from std::ostream.
|
||||
void operator<<(Null<>);
|
||||
};
|
||||
|
||||
No &operator<<(std::ostream &, int);
|
||||
|
||||
template<typename T>
|
||||
struct ConvertToIntImpl<T, true> {
|
||||
// Convert to int only if T doesn't have an overloaded operator<<.
|
||||
enum {
|
||||
value = sizeof(convert(get<DummyStream>() << get<T>())) == sizeof(No)
|
||||
};
|
||||
};
|
||||
|
||||
// Write the content of w to os.
|
||||
FMT_API void write(std::ostream &os, Writer &w);
|
||||
} // namespace internal
|
||||
|
||||
// Formats a value.
|
||||
template <typename Char, typename ArgFormatter_, typename T>
|
||||
void format_arg(BasicFormatter<Char, ArgFormatter_> &f,
|
||||
const Char *&format_str, const T &value) {
|
||||
internal::MemoryBuffer<Char, internal::INLINE_BUFFER_SIZE> buffer;
|
||||
|
||||
internal::FormatBuf<Char> format_buf(buffer);
|
||||
std::basic_ostream<Char> output(&format_buf);
|
||||
output << value;
|
||||
|
||||
BasicStringRef<Char> str(&buffer[0], buffer.size());
|
||||
typedef internal::MakeArg< BasicFormatter<Char> > MakeArg;
|
||||
format_str = f.format(format_str, MakeArg(str));
|
||||
}
|
||||
|
||||
/**
|
||||
\rst
|
||||
Prints formatted data to the stream *os*.
|
||||
|
||||
**Example**::
|
||||
|
||||
print(cerr, "Don't {}!", "panic");
|
||||
\endrst
|
||||
*/
|
||||
FMT_API void print(std::ostream &os, CStringRef format_str, ArgList args);
|
||||
FMT_VARIADIC(void, print, std::ostream &, CStringRef)
|
||||
} // namespace fmt
|
||||
|
||||
#ifdef FMT_HEADER_ONLY
|
||||
# include "ostream.cc"
|
||||
#endif
|
||||
|
||||
#endif // FMT_OSTREAM_H_
|
@ -55,7 +55,7 @@ struct GridRef
|
||||
inline
|
||||
Vertex vertex(Index idx) const;
|
||||
|
||||
Index index(const Vertex& v) const { Index idx = 0; for (unsigned i = 0; i < D; ++i) { idx += ((Index) v[i]) * ((Index) stride_[i]); } return idx; }
|
||||
Index index(const Vertex& v) const { Index idx = 0; for (unsigned i = 0; i < D; ++i) { idx += ((Index) v[i]) * stride_[i]; } return idx; }
|
||||
|
||||
Index size() const { return size(shape()); }
|
||||
void swap(GridRef& other) { std::swap(data_, other.data_); std::swap(shape_, other.shape_); std::swap(stride_, other.stride_); std::swap(c_order_, other.c_order_); }
|
||||
@ -73,10 +73,9 @@ struct GridRef
|
||||
{
|
||||
Index cur = 1;
|
||||
if (c_order_)
|
||||
for (unsigned i = D; i > 0; --i) { stride_[i-1] = cur; cur *= shape_[i-1]; }
|
||||
for (unsigned i = D; i > 0; --i) { stride_[i-1] = cur; cur *= static_cast<Index>(shape_[i-1]); }
|
||||
else
|
||||
for (unsigned i = 0; i < D; ++i) { stride_[i] = cur; cur *= shape_[i]; }
|
||||
|
||||
for (unsigned i = 0; i < D; ++i) { stride_[i] = cur; cur *= static_cast<Index>(shape_[i]); }
|
||||
}
|
||||
void set_shape(const Vertex& v) { shape_ = v; set_stride(); }
|
||||
void set_data(C* data) { data_ = data; }
|
||||
@ -85,7 +84,7 @@ struct GridRef
|
||||
private:
|
||||
C* data_;
|
||||
Vertex shape_;
|
||||
Vertex stride_;
|
||||
diy::Point<Index, D> stride_;
|
||||
bool c_order_;
|
||||
};
|
||||
|
||||
@ -107,8 +106,8 @@ struct Grid: public GridRef<C,D>
|
||||
Grid():
|
||||
Parent(new C[0], Vertex::zero()) {}
|
||||
template<class Int>
|
||||
Grid(const Point<Int, D>& shape, bool c_order = true):
|
||||
Parent(new C[size(shape)], shape, c_order)
|
||||
Grid(const Point<Int, D>& s, bool c_order = true):
|
||||
Parent(new C[size(s)], s, c_order)
|
||||
{}
|
||||
|
||||
Grid(Grid&& g): Grid() { Parent::swap(g); }
|
||||
@ -147,11 +146,11 @@ struct Grid: public GridRef<C,D>
|
||||
|
||||
private:
|
||||
template<class OC>
|
||||
void copy_data(const OC* data)
|
||||
void copy_data(const OC* data_)
|
||||
{
|
||||
Index s = size(shape());
|
||||
for (Index i = 0; i < s; ++i)
|
||||
Parent::data()[i] = data[i];
|
||||
Parent::data()[i] = data_[i];
|
||||
}
|
||||
};
|
||||
|
||||
@ -181,13 +180,13 @@ vertex(typename GridRef<C, D>::Index idx) const
|
||||
if (c_order())
|
||||
for (unsigned i = 0; i < D; ++i)
|
||||
{
|
||||
v[i] = idx / stride_[i];
|
||||
v[i] = static_cast<int>(idx / stride_[i]);
|
||||
idx %= stride_[i];
|
||||
}
|
||||
else
|
||||
for (int i = D-1; i >= 0; --i)
|
||||
{
|
||||
v[i] = idx / stride_[i];
|
||||
v[i] = static_cast<int>(idx / stride_[i]);
|
||||
idx %= stride_[i];
|
||||
}
|
||||
return v;
|
||||
|
@ -205,12 +205,11 @@ namespace io
|
||||
extra.reset();
|
||||
|
||||
// Get local gids from assigner
|
||||
size_t size = all_offset_counts.size();
|
||||
assigner.set_nblocks(size);
|
||||
assigner.set_nblocks(static_cast<int>(all_offset_counts.size()));
|
||||
std::vector<int> gids;
|
||||
assigner.local_gids(comm.rank(), gids);
|
||||
|
||||
for (unsigned i = 0; i < gids.size(); ++i)
|
||||
for (size_t i = 0; i < gids.size(); ++i)
|
||||
{
|
||||
if (gids[i] != all_offset_counts[gids[i]].gid)
|
||||
get_logger()->warn("gids don't match in diy::io::read_blocks(), {} vs {}",
|
||||
@ -342,7 +341,7 @@ namespace split
|
||||
}
|
||||
|
||||
// Get local gids from assigner
|
||||
assigner.set_nblocks(size);
|
||||
assigner.set_nblocks(static_cast<int>(size));
|
||||
std::vector<int> gids;
|
||||
assigner.local_gids(comm.rank(), gids);
|
||||
|
||||
|
@ -2,11 +2,8 @@
|
||||
#define VTKMDIY_IO_BOV_HPP
|
||||
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <numeric>
|
||||
|
||||
#include "../types.hpp"
|
||||
#include "../mpi.hpp"
|
||||
#include "../mpi/io.hpp"
|
||||
|
||||
namespace diy
|
||||
{
|
||||
@ -39,8 +36,9 @@ namespace io
|
||||
shape_.push_back(shape[i]);
|
||||
stride_.push_back(1);
|
||||
}
|
||||
for (int i = shape_.size() - 2; i >= 0; --i)
|
||||
for (auto i = shape_.size() - 2; i == 0; --i)
|
||||
stride_[i] = stride_[i+1] * shape_[i+1];
|
||||
stride_[0] = stride_[1] * shape_[1];
|
||||
}
|
||||
|
||||
const Shape& shape() const { return shape_; }
|
||||
@ -71,50 +69,7 @@ void
|
||||
diy::io::BOV::
|
||||
read(const DiscreteBounds& bounds, T* buffer, bool collective, int chunk) const
|
||||
{
|
||||
#ifndef VTKM_DIY_NO_MPI
|
||||
int dim = shape_.size();
|
||||
int total = 1;
|
||||
std::vector<int> subsizes;
|
||||
for (int i = 0; i < dim; ++i)
|
||||
{
|
||||
subsizes.push_back(bounds.max[i] - bounds.min[i] + 1);
|
||||
total *= subsizes.back();
|
||||
}
|
||||
|
||||
MPI_Datatype T_type;
|
||||
if (chunk == 1)
|
||||
T_type = mpi::detail::get_mpi_datatype<T>();
|
||||
else
|
||||
{
|
||||
// create an MPI struct of size chunk to read the data in those chunks
|
||||
// (this allows to work around MPI-IO weirdness where crucial quantities
|
||||
// are ints, which are too narrow of a type)
|
||||
int array_of_blocklengths[] = { chunk };
|
||||
MPI_Aint array_of_displacements[] = { 0 };
|
||||
MPI_Datatype array_of_types[] = { mpi::detail::get_mpi_datatype<T>() };
|
||||
MPI_Type_create_struct(1, array_of_blocklengths, array_of_displacements, array_of_types, &T_type);
|
||||
MPI_Type_commit(&T_type);
|
||||
}
|
||||
|
||||
MPI_Datatype fileblk;
|
||||
MPI_Type_create_subarray(dim, (int*) &shape_[0], &subsizes[0], (int*) &bounds.min[0], MPI_ORDER_C, T_type, &fileblk);
|
||||
MPI_Type_commit(&fileblk);
|
||||
|
||||
MPI_File_set_view(f_.handle(), offset_, T_type, fileblk, (char*)"native", MPI_INFO_NULL);
|
||||
|
||||
mpi::status s;
|
||||
if (!collective)
|
||||
MPI_File_read(f_.handle(), buffer, total, T_type, &s.s);
|
||||
else
|
||||
MPI_File_read_all(f_.handle(), buffer, total, T_type, &s.s);
|
||||
|
||||
if (chunk != 1)
|
||||
MPI_Type_free(&T_type);
|
||||
MPI_Type_free(&fileblk);
|
||||
#else
|
||||
(void) bounds; (void) buffer; (void) collective; (void)chunk;
|
||||
DIY_UNSUPPORTED_MPI_CALL(diy::io::BOV::read);
|
||||
#endif
|
||||
f_.read_bov(bounds, static_cast<int>(shape_.size()), shape_.data(), reinterpret_cast<char*>(buffer), offset_, mpi::detail::get_mpi_datatype<T>(), collective, chunk);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
@ -130,52 +85,7 @@ void
|
||||
diy::io::BOV::
|
||||
write(const DiscreteBounds& bounds, const T* buffer, const DiscreteBounds& core, bool collective, int chunk)
|
||||
{
|
||||
#ifndef VTKM_DIY_NO_MPI
|
||||
int dim = shape_.size();
|
||||
std::vector<int> subsizes;
|
||||
std::vector<int> buffer_shape, buffer_start;
|
||||
for (int i = 0; i < dim; ++i)
|
||||
{
|
||||
buffer_shape.push_back(bounds.max[i] - bounds.min[i] + 1);
|
||||
buffer_start.push_back(core.min[i] - bounds.min[i]);
|
||||
subsizes.push_back(core.max[i] - core.min[i] + 1);
|
||||
}
|
||||
|
||||
MPI_Datatype T_type;
|
||||
if (chunk == 1)
|
||||
T_type = mpi::detail::get_mpi_datatype<T>();
|
||||
else
|
||||
{
|
||||
// assume T is a binary block and create an MPI struct of appropriate size
|
||||
int array_of_blocklengths[] = { chunk };
|
||||
MPI_Aint array_of_displacements[] = { 0 };
|
||||
MPI_Datatype array_of_types[] = { mpi::detail::get_mpi_datatype<T>() };
|
||||
MPI_Type_create_struct(1, array_of_blocklengths, array_of_displacements, array_of_types, &T_type);
|
||||
MPI_Type_commit(&T_type);
|
||||
}
|
||||
|
||||
MPI_Datatype fileblk, subbuffer;
|
||||
MPI_Type_create_subarray(dim, (int*) &shape_[0], &subsizes[0], (int*) &core.min[0], MPI_ORDER_C, T_type, &fileblk);
|
||||
MPI_Type_create_subarray(dim, (int*) &buffer_shape[0], &subsizes[0], (int*) &buffer_start[0], MPI_ORDER_C, T_type, &subbuffer);
|
||||
MPI_Type_commit(&fileblk);
|
||||
MPI_Type_commit(&subbuffer);
|
||||
|
||||
MPI_File_set_view(f_.handle(), offset_, T_type, fileblk, (char*)"native", MPI_INFO_NULL);
|
||||
|
||||
mpi::status s;
|
||||
if (!collective)
|
||||
MPI_File_write(f_.handle(), (void*)buffer, 1, subbuffer, &s.s);
|
||||
else
|
||||
MPI_File_write_all(f_.handle(), (void*)buffer, 1, subbuffer, &s.s);
|
||||
|
||||
if (chunk != 1)
|
||||
MPI_Type_free(&T_type);
|
||||
MPI_Type_free(&fileblk);
|
||||
MPI_Type_free(&subbuffer);
|
||||
#else
|
||||
(void) bounds; (void) buffer;(void) core; (void) collective; (void) chunk;
|
||||
DIY_UNSUPPORTED_MPI_CALL(diy::io::bov::write);
|
||||
#endif
|
||||
f_.write_bov(bounds, core, static_cast<int>(shape_.size()), shape_.data(), reinterpret_cast<const char*>(buffer), offset_, mpi::detail::get_mpi_datatype<T>(), collective, chunk);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -79,21 +79,21 @@ parse_npy_header(BOV::Shape& shape, bool& fortran_order)
|
||||
header = header.substr(11, nl - 11 + 1);
|
||||
size_t header_size = nl + 1;
|
||||
|
||||
int loc1, loc2;
|
||||
size_t loc1, loc2;
|
||||
|
||||
//fortran order
|
||||
loc1 = header.find("fortran_order")+16;
|
||||
fortran_order = (header.substr(loc1,4) == "True" ? true : false);
|
||||
|
||||
//shape
|
||||
unsigned ndims;
|
||||
size_t ndims;
|
||||
loc1 = header.find("(");
|
||||
loc2 = header.find(")");
|
||||
std::string str_shape = header.substr(loc1+1,loc2-loc1-1);
|
||||
if(str_shape[str_shape.size()-1] == ',') ndims = 1;
|
||||
else ndims = std::count(str_shape.begin(),str_shape.end(),',')+1;
|
||||
shape.resize(ndims);
|
||||
for(unsigned int i = 0;i < ndims;i++) {
|
||||
for(size_t i = 0;i < ndims;i++) {
|
||||
loc1 = str_shape.find(",");
|
||||
shape[i] = atoi(str_shape.substr(0,loc1).c_str());
|
||||
str_shape = str_shape.substr(loc1+1);
|
||||
|
@ -31,8 +31,8 @@ class SharedOutFile: public std::ostringstream
|
||||
|
||||
// write the file serially
|
||||
std::ofstream out(filename_);
|
||||
for (auto& contents : all_contents)
|
||||
out.write(contents.data(), contents.size());
|
||||
for (auto& cntnts : all_contents)
|
||||
out.write(cntnts.data(), cntnts.size());
|
||||
} else
|
||||
diy::mpi::gather(world_, contents, root_);
|
||||
}
|
||||
|
@ -14,7 +14,7 @@
|
||||
#include <cstdlib> // mkstemp() on Linux
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "../constants.h" // for DIY_UNUSED
|
||||
#include "../constants.h" // for VTKMDIY_UNUSED
|
||||
|
||||
namespace diy
|
||||
{
|
||||
@ -82,8 +82,8 @@ namespace utils
|
||||
_close(fd);
|
||||
}
|
||||
#else
|
||||
auto r = ::truncate(filename.c_str(), static_cast<off_t>(length));
|
||||
(void) r;
|
||||
int error = ::truncate(filename.c_str(), static_cast<off_t>(length));
|
||||
VTKMDIY_UNUSED(error);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -141,7 +141,7 @@ namespace utils
|
||||
inline void sync(int fd)
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
DIY_UNUSED(fd);
|
||||
VTKMDIY_UNUSED(fd);
|
||||
#else
|
||||
fsync(fd);
|
||||
#endif
|
||||
|
193
vtkm/thirdparty/diy/vtkmdiy/include/vtkmdiy/link.hpp
vendored
193
vtkm/thirdparty/diy/vtkmdiy/include/vtkmdiy/link.hpp
vendored
@ -1,5 +1,5 @@
|
||||
#ifndef VTKMDIY_COVER_HPP
|
||||
#define VTKMDIY_COVER_HPP
|
||||
#ifndef VTKMDIY_LINK_HPP
|
||||
#define VTKMDIY_LINK_HPP
|
||||
|
||||
#include <vector>
|
||||
#include <map>
|
||||
@ -9,14 +9,22 @@
|
||||
#include "serialization.hpp"
|
||||
#include "assigner.hpp"
|
||||
|
||||
#include "factory.hpp"
|
||||
|
||||
namespace diy
|
||||
{
|
||||
// Local view of a distributed representation of a cover, a completely unstructured link
|
||||
class Link
|
||||
class Link: public Factory<Link>
|
||||
{
|
||||
public:
|
||||
using Neighbors = std::vector<BlockID>;
|
||||
|
||||
Link(Key) {} // for Factory
|
||||
Link() = default;
|
||||
Link(const Link&) = default;
|
||||
Link(Link&&) = default;
|
||||
Link& operator=(const Link&) = default;
|
||||
Link& operator=(Link&&) = default;
|
||||
virtual ~Link() {} // need to be able to delete derived classes
|
||||
|
||||
int size() const { return static_cast<int>(neighbors_.size()); }
|
||||
@ -38,11 +46,11 @@ namespace diy
|
||||
Neighbors&
|
||||
neighbors() { return neighbors_; }
|
||||
|
||||
virtual Link* clone() const { return new Link(*this); }
|
||||
|
||||
virtual void save(BinaryBuffer& bb) const { diy::save(bb, neighbors_); }
|
||||
virtual void load(BinaryBuffer& bb) { diy::load(bb, neighbors_); }
|
||||
|
||||
virtual size_t id() const { return 0; }
|
||||
|
||||
private:
|
||||
Neighbors neighbors_;
|
||||
};
|
||||
@ -50,32 +58,13 @@ namespace diy
|
||||
template<class Bounds_>
|
||||
class RegularLink;
|
||||
|
||||
typedef RegularLink<DiscreteBounds> RegularGridLink;
|
||||
typedef RegularLink<ContinuousBounds> RegularContinuousLink;
|
||||
|
||||
// Selector between regular discrete and contious links given bounds type
|
||||
template<class Bounds_>
|
||||
struct RegularLinkSelector;
|
||||
|
||||
template<>
|
||||
struct RegularLinkSelector<DiscreteBounds>
|
||||
{
|
||||
typedef RegularGridLink type;
|
||||
static const size_t id = 1;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct RegularLinkSelector<ContinuousBounds>
|
||||
{
|
||||
typedef RegularContinuousLink type;
|
||||
static const size_t id = 2;
|
||||
};
|
||||
|
||||
using RegularGridLink = RegularLink<DiscreteBounds>;
|
||||
using RegularContinuousLink = RegularLink<ContinuousBounds>;
|
||||
|
||||
// for a regular decomposition, it makes sense to address the neighbors by direction
|
||||
// and store local and neighbor bounds
|
||||
template<class Bounds_>
|
||||
class RegularLink: public Link
|
||||
class RegularLink: public Link::Registrar<RegularLink<Bounds_>>
|
||||
{
|
||||
public:
|
||||
typedef Bounds_ Bounds;
|
||||
@ -84,6 +73,8 @@ namespace diy
|
||||
typedef std::vector<Direction> DirVec;
|
||||
|
||||
public:
|
||||
RegularLink():
|
||||
dim_(0), core_(0), bounds_(0) {} // for Factory
|
||||
RegularLink(int dim, const Bounds& core__, const Bounds& bounds__):
|
||||
dim_(dim), core_(core__), bounds_(bounds__) {}
|
||||
|
||||
@ -93,7 +84,7 @@ namespace diy
|
||||
// direction
|
||||
int direction(Direction dir) const; // convert direction to a neighbor (-1 if no neighbor)
|
||||
Direction direction(int i) const { return dir_vec_[i]; }
|
||||
void add_direction(Direction dir) { int c = dir_map_.size(); dir_map_[dir] = c; dir_vec_.push_back(dir); }
|
||||
void add_direction(Direction dir) { auto c = static_cast<int>(dir_map_.size()); dir_map_[dir] = c; dir_vec_.push_back(dir); }
|
||||
|
||||
// wrap
|
||||
void add_wrap(Direction dir) { wrap_.push_back(dir); }
|
||||
@ -105,12 +96,16 @@ namespace diy
|
||||
Bounds& core() { return core_; }
|
||||
const Bounds& bounds() const { return bounds_; }
|
||||
Bounds& bounds() { return bounds_; }
|
||||
const Bounds& core(int i) const { return nbr_cores_[i]; }
|
||||
const Bounds& bounds(int i) const { return nbr_bounds_[i]; }
|
||||
void add_core(const Bounds& core__) { nbr_cores_.push_back(core__); }
|
||||
void add_bounds(const Bounds& bounds__) { nbr_bounds_.push_back(bounds__); }
|
||||
|
||||
void swap(RegularLink& other) { Link::swap(other); dir_map_.swap(other.dir_map_); dir_vec_.swap(other.dir_vec_); nbr_bounds_.swap(other.nbr_bounds_); std::swap(dim_, other.dim_); wrap_.swap(other.wrap_); std::swap(core_, other.core_); std::swap(bounds_, other.bounds_); }
|
||||
|
||||
void save(BinaryBuffer& bb) const
|
||||
Link* clone() const override { return new RegularLink(*this); }
|
||||
|
||||
void save(BinaryBuffer& bb) const override
|
||||
{
|
||||
Link::save(bb);
|
||||
diy::save(bb, dim_);
|
||||
@ -118,11 +113,12 @@ namespace diy
|
||||
diy::save(bb, dir_vec_);
|
||||
diy::save(bb, core_);
|
||||
diy::save(bb, bounds_);
|
||||
diy::save(bb, nbr_cores_);
|
||||
diy::save(bb, nbr_bounds_);
|
||||
diy::save(bb, wrap_);
|
||||
}
|
||||
|
||||
void load(BinaryBuffer& bb)
|
||||
void load(BinaryBuffer& bb) override
|
||||
{
|
||||
Link::load(bb);
|
||||
diy::load(bb, dim_);
|
||||
@ -130,12 +126,11 @@ namespace diy
|
||||
diy::load(bb, dir_vec_);
|
||||
diy::load(bb, core_);
|
||||
diy::load(bb, bounds_);
|
||||
diy::load(bb, nbr_cores_);
|
||||
diy::load(bb, nbr_bounds_);
|
||||
diy::load(bb, wrap_);
|
||||
}
|
||||
|
||||
virtual size_t id() const { return RegularLinkSelector<Bounds>::id; }
|
||||
|
||||
private:
|
||||
int dim_;
|
||||
|
||||
@ -144,31 +139,139 @@ namespace diy
|
||||
|
||||
Bounds core_;
|
||||
Bounds bounds_;
|
||||
std::vector<Bounds> nbr_cores_;
|
||||
std::vector<Bounds> nbr_bounds_;
|
||||
std::vector<Direction> wrap_;
|
||||
};
|
||||
|
||||
// Other cover candidates: KDTreeLink, AMRGridLink
|
||||
struct AMRLink: public Link::Registrar<AMRLink>
|
||||
{
|
||||
public:
|
||||
using Bounds = DiscreteBounds;
|
||||
using Directions = std::vector<Direction>;
|
||||
using Point = Bounds::Point;
|
||||
|
||||
struct Description
|
||||
{
|
||||
int level { -1 };
|
||||
Point refinement { 0 }; // refinement of this level w.r.t. level 0
|
||||
Bounds core { 0 };
|
||||
Bounds bounds { 0 }; // with ghosts
|
||||
|
||||
Description() = default;
|
||||
Description(int level_, Point refinement_, Bounds core_, Bounds bounds_):
|
||||
level(level_), refinement(refinement_), core(core_), bounds(bounds_) {}
|
||||
};
|
||||
using Descriptions = std::vector<Description>;
|
||||
|
||||
public:
|
||||
AMRLink(int dim, int level, Point refinement, const Bounds& core, const Bounds& bounds):
|
||||
dim_(dim), local_ { level, refinement, core, bounds } {}
|
||||
AMRLink(int dim, int level, int refinement, const Bounds& core, const Bounds& bounds):
|
||||
AMRLink(dim, level, refinement * Point::one(dim), core, bounds) {}
|
||||
AMRLink(): AMRLink(0, -1, 0, Bounds(0), Bounds(0)) {} // for Factory
|
||||
|
||||
// dimension
|
||||
int dimension() const { return dim_; }
|
||||
|
||||
// local information
|
||||
int level() const { return local_.level; }
|
||||
int level(int i) const { return nbr_descriptions_[i].level; }
|
||||
Point refinement() const { return local_.refinement; }
|
||||
Point refinement(int i) const { return nbr_descriptions_[i].refinement; }
|
||||
|
||||
// wrap
|
||||
void add_wrap(Direction dir) { wrap_.push_back(dir); }
|
||||
const Directions&
|
||||
wrap() const { return wrap_; }
|
||||
|
||||
// bounds
|
||||
const Bounds& core() const { return local_.core; }
|
||||
Bounds& core() { return local_.core; }
|
||||
const Bounds& bounds() const { return local_.bounds; }
|
||||
Bounds& bounds() { return local_.bounds; }
|
||||
const Bounds& core(int i) const { return nbr_descriptions_[i].core; }
|
||||
const Bounds& bounds(int i) const { return nbr_descriptions_[i].bounds; }
|
||||
void add_bounds(int level_,
|
||||
Point refinement_,
|
||||
const Bounds& core_,
|
||||
const Bounds& bounds_) { nbr_descriptions_.emplace_back(Description {level_, refinement_, core_, bounds_}); }
|
||||
void add_bounds(int level_,
|
||||
int refinement_,
|
||||
const Bounds& core_,
|
||||
const Bounds& bounds_) { add_bounds(level_, refinement_ * Point::one(dim_), core_, bounds_); }
|
||||
|
||||
Link* clone() const override { return new AMRLink(*this); }
|
||||
|
||||
void save(BinaryBuffer& bb) const override
|
||||
{
|
||||
Link::save(bb);
|
||||
diy::save(bb, dim_);
|
||||
diy::save(bb, local_);
|
||||
diy::save(bb, nbr_descriptions_);
|
||||
diy::save(bb, wrap_);
|
||||
}
|
||||
|
||||
void load(BinaryBuffer& bb) override
|
||||
{
|
||||
Link::load(bb);
|
||||
diy::load(bb, dim_);
|
||||
diy::load(bb, local_);
|
||||
diy::load(bb, nbr_descriptions_);
|
||||
diy::load(bb, wrap_);
|
||||
}
|
||||
|
||||
private:
|
||||
int dim_;
|
||||
|
||||
Description local_;
|
||||
Descriptions nbr_descriptions_;
|
||||
Directions wrap_;
|
||||
};
|
||||
|
||||
struct LinkFactory
|
||||
{
|
||||
public:
|
||||
static Link* create(size_t id)
|
||||
static Link* create(std::string name)
|
||||
{
|
||||
// not pretty, but will do for now
|
||||
if (id == 0)
|
||||
return new Link;
|
||||
else if (id == 1)
|
||||
return new RegularGridLink(0, DiscreteBounds(), DiscreteBounds());
|
||||
else if (id == 2)
|
||||
return new RegularContinuousLink(0, ContinuousBounds(), ContinuousBounds());
|
||||
else
|
||||
return 0;
|
||||
return Link::make(name);
|
||||
}
|
||||
|
||||
inline static void save(BinaryBuffer& bb, const Link* l);
|
||||
inline static Link* load(BinaryBuffer& bb);
|
||||
};
|
||||
|
||||
namespace detail
|
||||
{
|
||||
inline void instantiate_common_regular_links()
|
||||
{
|
||||
// Instantiate the common types to register them
|
||||
RegularLink<Bounds<int>> rl_int;
|
||||
RegularLink<Bounds<float>> rl_float;
|
||||
RegularLink<Bounds<double>> rl_double;
|
||||
RegularLink<Bounds<long>> rl_long;
|
||||
}
|
||||
}
|
||||
|
||||
template<>
|
||||
struct Serialization<diy::AMRLink::Description>
|
||||
{
|
||||
static void save(diy::BinaryBuffer& bb, const diy::AMRLink::Description& x)
|
||||
{
|
||||
diy::save(bb, x.level);
|
||||
diy::save(bb, x.refinement);
|
||||
diy::save(bb, x.core);
|
||||
diy::save(bb, x.bounds);
|
||||
}
|
||||
|
||||
static void load(diy::BinaryBuffer& bb, diy::AMRLink::Description& x)
|
||||
{
|
||||
diy::load(bb, x.level);
|
||||
diy::load(bb, x.refinement);
|
||||
diy::load(bb, x.core);
|
||||
diy::load(bb, x.bounds);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -184,7 +287,7 @@ diy::Link*
|
||||
diy::LinkFactory::
|
||||
load(BinaryBuffer& bb)
|
||||
{
|
||||
size_t id;
|
||||
std::string id;
|
||||
diy::load(bb, id);
|
||||
Link* l = create(id);
|
||||
l->load(bb);
|
||||
@ -223,4 +326,4 @@ direction(Direction dir) const
|
||||
return it->second;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif // VTKMDIY_LINK_HPP
|
||||
|
@ -4,8 +4,8 @@
|
||||
#ifndef VTKMDIY_USE_SPDLOG
|
||||
|
||||
#include <memory>
|
||||
#include "fmt/format.h"
|
||||
#include "fmt/ostream.h"
|
||||
#include "thirdparty/fmt/format.h"
|
||||
#include "thirdparty/fmt/ostream.h"
|
||||
|
||||
namespace diy
|
||||
{
|
||||
@ -47,12 +47,13 @@ set_logger(Args...)
|
||||
|
||||
} // diy
|
||||
|
||||
#else // DIY_USE_SPDLOG
|
||||
#else // VTKMDIY_USE_SPDLOG
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <spdlog/spdlog.h>
|
||||
#include <spdlog/sinks/null_sink.h>
|
||||
#include <spdlog/sinks/stdout_sinks.h>
|
||||
|
||||
#include <spdlog/fmt/bundled/format.h>
|
||||
#include <spdlog/fmt/bundled/ostream.h>
|
||||
@ -80,10 +81,7 @@ std::shared_ptr<spd::logger>
|
||||
create_logger(std::string log_level)
|
||||
{
|
||||
auto log = spd::stderr_logger_mt("diy");
|
||||
int lvl;
|
||||
for (lvl = spd::level::trace; lvl < spd::level::off; ++lvl)
|
||||
if (spd::level::level_names[lvl] == log_level)
|
||||
break;
|
||||
int lvl = spd::level::from_str(log_level);
|
||||
log->set_level(static_cast<spd::level::level_enum>(lvl));
|
||||
return log;
|
||||
}
|
||||
@ -100,4 +98,4 @@ set_logger(Args... args)
|
||||
#endif
|
||||
|
||||
|
||||
#endif // DIY_LOG_HPP
|
||||
#endif // VTKMDIY_LOG_HPP
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,14 +1,9 @@
|
||||
#ifndef VTKMDIY_MPI_HPP
|
||||
#define VTKMDIY_MPI_HPP
|
||||
|
||||
#ifndef VTKM_DIY_NO_MPI
|
||||
#include <mpi.h>
|
||||
#else
|
||||
#include "mpi/no-mpi.hpp"
|
||||
#endif
|
||||
|
||||
#include "mpi/constants.hpp"
|
||||
#include "mpi/config.hpp"
|
||||
#include "mpi/datatypes.hpp"
|
||||
#include "mpi/environment.hpp"
|
||||
#include "mpi/optional.hpp"
|
||||
#include "mpi/status.hpp"
|
||||
#include "mpi/request.hpp"
|
||||
@ -18,54 +13,4 @@
|
||||
#include "mpi/io.hpp"
|
||||
#include "mpi/window.hpp"
|
||||
|
||||
namespace diy
|
||||
{
|
||||
namespace mpi
|
||||
{
|
||||
|
||||
//! \ingroup MPI
|
||||
struct environment
|
||||
{
|
||||
inline environment(int threading = MPI_THREAD_FUNNELED);
|
||||
inline environment(int argc, char* argv[], int threading = MPI_THREAD_FUNNELED);
|
||||
inline ~environment();
|
||||
|
||||
int threading() const { return provided_threading; }
|
||||
|
||||
int provided_threading;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
diy::mpi::environment::
|
||||
environment(int threading)
|
||||
{
|
||||
#ifndef VTKM_DIY_NO_MPI
|
||||
int argc = 0; char** argv;
|
||||
MPI_Init_thread(&argc, &argv, threading, &provided_threading);
|
||||
#else
|
||||
provided_threading = threading;
|
||||
#endif
|
||||
}
|
||||
|
||||
diy::mpi::environment::
|
||||
environment(int argc, char* argv[], int threading)
|
||||
{
|
||||
#ifndef VTKM_DIY_NO_MPI
|
||||
MPI_Init_thread(&argc, &argv, threading, &provided_threading);
|
||||
#else
|
||||
(void) argc; (void) argv;
|
||||
provided_threading = threading;
|
||||
#endif
|
||||
}
|
||||
|
||||
diy::mpi::environment::
|
||||
~environment()
|
||||
{
|
||||
#ifndef VTKM_DIY_NO_MPI
|
||||
MPI_Finalize();
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif // VTKMDIY_MPI_HPP
|
||||
|
161
vtkm/thirdparty/diy/vtkmdiy/include/vtkmdiy/mpi/collectives.cpp
vendored
Normal file
161
vtkm/thirdparty/diy/vtkmdiy/include/vtkmdiy/mpi/collectives.cpp
vendored
Normal file
@ -0,0 +1,161 @@
|
||||
#ifdef VTKMDIY_MPI_AS_LIB
|
||||
#include "collectives.hpp"
|
||||
#endif
|
||||
|
||||
namespace diy
|
||||
{
|
||||
namespace mpi
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
|
||||
inline void copy_buffer(const void* src, void* dst, size_t size, int count)
|
||||
{
|
||||
if (src != dst)
|
||||
{
|
||||
std::copy_n(static_cast<const int8_t*>(src),
|
||||
size * static_cast<size_t>(count),
|
||||
static_cast<int8_t*>(dst));
|
||||
}
|
||||
}
|
||||
|
||||
void broadcast(const communicator& comm, void* data, int count, const datatype& type, int root)
|
||||
{
|
||||
#if VTKMDIY_HAS_MPI
|
||||
MPI_Bcast(data, count, mpi_cast(type.handle), root, mpi_cast(comm.handle()));
|
||||
#else
|
||||
(void) comm; (void) data; (void) count; (void) type; (void) root;
|
||||
#endif
|
||||
}
|
||||
|
||||
request ibroadcast(const communicator& comm, void* data, int count, const datatype& type, int root)
|
||||
{
|
||||
request r;
|
||||
#if VTKMDIY_HAS_MPI
|
||||
MPI_Ibcast(data, count, mpi_cast(type.handle), root, mpi_cast(comm.handle()), &mpi_cast(r.handle));
|
||||
#else
|
||||
(void) comm; (void) data; (void) count; (void) type; (void) root;
|
||||
#endif
|
||||
return r;
|
||||
}
|
||||
|
||||
void gather(const communicator& comm,
|
||||
const void* dataIn, int count, const datatype& type, void* dataOut,
|
||||
int root)
|
||||
{
|
||||
#if VTKMDIY_HAS_MPI
|
||||
MPI_Gather(dataIn, count, mpi_cast(type.handle),
|
||||
dataOut, count, mpi_cast(type.handle),
|
||||
root, mpi_cast(comm.handle()));
|
||||
#else
|
||||
copy_buffer(dataIn, dataOut, mpi_cast(type.handle), count);
|
||||
(void)comm; (void)root;
|
||||
#endif
|
||||
}
|
||||
|
||||
void gather_v(const communicator& comm,
|
||||
const void* dataIn, int countIn, const datatype& type,
|
||||
void* dataOut, const int counts[], const int offsets[],
|
||||
int root)
|
||||
{
|
||||
#if VTKMDIY_HAS_MPI
|
||||
MPI_Gatherv(dataIn, countIn, mpi_cast(type.handle),
|
||||
dataOut, counts, offsets, mpi_cast(type.handle),
|
||||
root, mpi_cast(comm.handle()));
|
||||
#else
|
||||
copy_buffer(dataIn, dataOut, mpi_cast(type.handle), countIn);
|
||||
(void)comm; (void)counts, (void)offsets, (void)root;
|
||||
#endif
|
||||
}
|
||||
|
||||
void all_gather(const communicator& comm,
|
||||
const void* dataIn, int count, const datatype& type, void* dataOut)
|
||||
{
|
||||
#if VTKMDIY_HAS_MPI
|
||||
MPI_Allgather(dataIn, count, mpi_cast(type.handle),
|
||||
dataOut, count, mpi_cast(type.handle),
|
||||
mpi_cast(comm.handle()));
|
||||
#else
|
||||
copy_buffer(dataIn, dataOut, mpi_cast(type.handle), count);
|
||||
(void)comm;
|
||||
#endif
|
||||
}
|
||||
|
||||
void all_gather_v(const communicator& comm,
|
||||
const void* dataIn, int countIn, const datatype& type,
|
||||
void* dataOut, const int counts[], const int offsets[])
|
||||
{
|
||||
#if VTKMDIY_HAS_MPI
|
||||
MPI_Allgatherv(dataIn, countIn, mpi_cast(type.handle),
|
||||
dataOut, counts, offsets, mpi_cast(type.handle),
|
||||
mpi_cast(comm.handle()));
|
||||
#else
|
||||
copy_buffer(dataIn, dataOut, mpi_cast(type.handle), countIn);
|
||||
(void)comm; (void)counts; (void)offsets;
|
||||
#endif
|
||||
}
|
||||
|
||||
void reduce(const communicator& comm,
|
||||
const void* dataIn, int count, const datatype& type, void* dataOut,
|
||||
const operation& op, int root)
|
||||
{
|
||||
#if VTKMDIY_HAS_MPI
|
||||
MPI_Reduce(dataIn, dataOut, count, mpi_cast(type.handle), mpi_cast(op.handle), root, mpi_cast(comm.handle()));
|
||||
#else
|
||||
copy_buffer(dataIn, dataOut, mpi_cast(type.handle), count);
|
||||
(void)comm; (void)op; (void)root;
|
||||
#endif
|
||||
}
|
||||
|
||||
void all_reduce(const communicator& comm,
|
||||
const void* dataIn, void* dataOut, int count, const datatype& type,
|
||||
const operation& op)
|
||||
{
|
||||
#if VTKMDIY_HAS_MPI
|
||||
MPI_Allreduce(dataIn, dataOut, count, mpi_cast(type.handle), mpi_cast(op.handle), mpi_cast(comm.handle()));
|
||||
#else
|
||||
copy_buffer(dataIn, dataOut, mpi_cast(type.handle), count);
|
||||
(void)comm; (void)op;
|
||||
#endif
|
||||
}
|
||||
|
||||
request iall_reduce(const communicator& comm,
|
||||
const void* dataIn, void* dataOut, int count, const datatype& type,
|
||||
const operation& op)
|
||||
{
|
||||
request r;
|
||||
#if VTKMDIY_HAS_MPI
|
||||
MPI_Iallreduce(dataIn, dataOut, count, mpi_cast(type.handle), mpi_cast(op.handle), mpi_cast(comm.handle()), &mpi_cast(r.handle));
|
||||
#else
|
||||
copy_buffer(dataIn, dataOut, mpi_cast(type.handle), count);
|
||||
(void)comm; (void)op;
|
||||
#endif
|
||||
return r;
|
||||
}
|
||||
|
||||
void scan(const communicator& comm,
|
||||
const void* dataIn, void* dataOut, int count, const datatype& type,
|
||||
const operation& op)
|
||||
{
|
||||
#if VTKMDIY_HAS_MPI
|
||||
MPI_Scan(dataIn, dataOut, count, mpi_cast(type.handle), mpi_cast(op.handle), mpi_cast(comm.handle()));
|
||||
#else
|
||||
copy_buffer(dataIn, dataOut, mpi_cast(type.handle), count);
|
||||
(void)comm; (void)op;
|
||||
#endif
|
||||
}
|
||||
|
||||
void all_to_all(const communicator& comm,
|
||||
const void* dataIn, int count, const datatype& type, void* dataOut)
|
||||
{
|
||||
#if VTKMDIY_HAS_MPI
|
||||
MPI_Alltoall(dataIn, count, mpi_cast(type.handle), dataOut, count, mpi_cast(type.handle), mpi_cast(comm.handle()));
|
||||
#else
|
||||
copy_buffer(dataIn, dataOut, mpi_cast(type.handle), count);
|
||||
(void)comm;
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
} // diy::mpi::detail
|
@ -1,12 +1,80 @@
|
||||
#include <vector>
|
||||
#ifndef VTKMDIY_MPI_COLLECTIVES_HPP
|
||||
#define VTKMDIY_MPI_COLLECTIVES_HPP
|
||||
|
||||
#include "../constants.h" // for DIY_UNUSED.
|
||||
#include "config.hpp"
|
||||
#include "communicator.hpp"
|
||||
#include "datatypes.hpp"
|
||||
#include "operations.hpp"
|
||||
#include "request.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
#include <numeric>
|
||||
|
||||
namespace diy
|
||||
{
|
||||
namespace mpi
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
VTKMDIY_MPI_EXPORT_FUNCTION
|
||||
void broadcast(const communicator& comm,
|
||||
void* data, int count, const datatype& type,
|
||||
int root);
|
||||
|
||||
VTKMDIY_MPI_EXPORT_FUNCTION
|
||||
request ibroadcast(const communicator& comm,
|
||||
void* data, int count, const datatype& type,
|
||||
int root);
|
||||
|
||||
VTKMDIY_MPI_EXPORT_FUNCTION
|
||||
void gather(const communicator& comm,
|
||||
const void* dataIn, int count, const datatype& type, void* dataOut,
|
||||
int root);
|
||||
|
||||
VTKMDIY_MPI_EXPORT_FUNCTION
|
||||
void gather_v(const communicator& comm,
|
||||
const void* dataIn, int countIn, const datatype& type,
|
||||
void* dataOut, const int counts[], const int offsets[],
|
||||
int root);
|
||||
|
||||
VTKMDIY_MPI_EXPORT_FUNCTION
|
||||
void all_gather(const communicator& comm,
|
||||
const void* dataIn, int count, const datatype& type, void* dataOut);
|
||||
|
||||
VTKMDIY_MPI_EXPORT_FUNCTION
|
||||
void all_gather_v(const communicator& comm,
|
||||
const void* dataIn, int countIn, const datatype& type,
|
||||
void* dataOut, const int counts[], const int offsets[]);
|
||||
|
||||
VTKMDIY_MPI_EXPORT_FUNCTION
|
||||
void reduce(const communicator& comm,
|
||||
const void* dataIn, int count, const datatype& type, void* dataOut,
|
||||
const operation& op, int root);
|
||||
|
||||
VTKMDIY_MPI_EXPORT_FUNCTION
|
||||
void all_reduce(const communicator& comm,
|
||||
const void* dataIn, void* dataOut, int count, const datatype& type,
|
||||
const operation& op);
|
||||
|
||||
VTKMDIY_MPI_EXPORT_FUNCTION
|
||||
request iall_reduce(const communicator& comm,
|
||||
const void* dataIn, void* dataOut, int count, const datatype& type,
|
||||
const operation& op);
|
||||
|
||||
VTKMDIY_MPI_EXPORT_FUNCTION
|
||||
void scan(const communicator& comm,
|
||||
const void* dataIn, void* dataOut, int count, const datatype& type,
|
||||
const operation& op);
|
||||
|
||||
VTKMDIY_MPI_EXPORT_FUNCTION
|
||||
void all_to_all(const communicator& comm,
|
||||
const void* dataIn, int count, const datatype& type, void* dataOut);
|
||||
|
||||
} // detail
|
||||
|
||||
//!\addtogroup MPI
|
||||
//!@{
|
||||
|
||||
@ -15,259 +83,181 @@ namespace mpi
|
||||
{
|
||||
static void broadcast(const communicator& comm, T& x, int root)
|
||||
{
|
||||
#ifndef VTKM_DIY_NO_MPI
|
||||
MPI_Bcast(address(x), count(x), datatype(x), root, comm);
|
||||
#else
|
||||
DIY_UNUSED(comm);
|
||||
DIY_UNUSED(x);
|
||||
DIY_UNUSED(root);
|
||||
#endif
|
||||
detail::broadcast(comm, address(x), count(x), datatype_of(x), root);
|
||||
}
|
||||
|
||||
static void broadcast(const communicator& comm, std::vector<T>& x, int root)
|
||||
{
|
||||
#ifndef VTKM_DIY_NO_MPI
|
||||
size_t sz = x.size();
|
||||
Collectives<size_t, void*>::broadcast(comm, sz, root);
|
||||
detail::broadcast(comm, &sz, 1, datatype_of(sz), root);
|
||||
|
||||
if (comm.rank() != root)
|
||||
x.resize(sz);
|
||||
|
||||
MPI_Bcast(address(x), count(x), datatype(x), root, comm);
|
||||
#else
|
||||
DIY_UNUSED(comm);
|
||||
DIY_UNUSED(x);
|
||||
DIY_UNUSED(root);
|
||||
#endif
|
||||
detail::broadcast(comm, address(x), count(x), datatype_of(x), root);
|
||||
}
|
||||
|
||||
static request ibroadcast(const communicator& comm, T& x, int root)
|
||||
{
|
||||
#ifndef VTKM_DIY_NO_MPI
|
||||
request r;
|
||||
MPI_Ibcast(address(x), count(x), datatype(x), root, comm, &r.r);
|
||||
return r;
|
||||
#else
|
||||
DIY_UNUSED(comm);
|
||||
DIY_UNUSED(x);
|
||||
DIY_UNUSED(root);
|
||||
DIY_UNSUPPORTED_MPI_CALL(MPI_Ibcast);
|
||||
#endif
|
||||
return detail::ibroadcast(comm, address(x), count(x), datatype_of(x), root);
|
||||
}
|
||||
|
||||
static void gather(const communicator& comm, const T& in, std::vector<T>& out, int root)
|
||||
{
|
||||
out.resize(comm.size());
|
||||
#ifndef VTKM_DIY_NO_MPI
|
||||
MPI_Gather(address(in), count(in), datatype(in), address(out), count(in), datatype(out), root, comm);
|
||||
#else
|
||||
DIY_UNUSED(comm);
|
||||
DIY_UNUSED(root);
|
||||
out[0] = in;
|
||||
#endif
|
||||
detail::gather(comm, address(in), count(in), datatype_of(in), address(out), root);
|
||||
}
|
||||
|
||||
static void gather(const communicator& comm, const std::vector<T>& in, std::vector< std::vector<T> >& out, int root)
|
||||
{
|
||||
#ifndef VTKM_DIY_NO_MPI
|
||||
std::vector<int> counts(comm.size());
|
||||
std::vector<int> counts;
|
||||
if (comm.rank() == root)
|
||||
{
|
||||
counts.resize(static_cast<size_t>(comm.size()));
|
||||
}
|
||||
|
||||
Collectives<int,void*>::gather(comm, count(in), counts, root);
|
||||
|
||||
std::vector<int> offsets(comm.size(), 0);
|
||||
for (unsigned i = 1; i < offsets.size(); ++i)
|
||||
offsets[i] = offsets[i-1] + counts[i-1];
|
||||
std::vector<int> offsets;
|
||||
if (comm.rank() == root)
|
||||
{
|
||||
offsets.resize(counts.size());
|
||||
offsets[0] = 0;
|
||||
std::partial_sum(counts.begin(), counts.end() - 1, offsets.begin() + 1);
|
||||
}
|
||||
|
||||
int elem_size = count(in[0]); // size of 1 vector element in units of mpi datatype
|
||||
std::vector<T> buffer((offsets.back() + counts.back()) / elem_size);
|
||||
MPI_Gatherv(address(in), count(in), datatype(in),
|
||||
address(buffer),
|
||||
&counts[0],
|
||||
&offsets[0],
|
||||
datatype(buffer),
|
||||
root, comm);
|
||||
|
||||
out.resize(comm.size());
|
||||
size_t cur = 0;
|
||||
for (unsigned i = 0; i < (unsigned)comm.size(); ++i)
|
||||
std::vector<T> buffer;
|
||||
if (comm.rank() == root)
|
||||
{
|
||||
out[i].reserve(counts[i] / elem_size);
|
||||
for (unsigned j = 0; j < (unsigned)(counts[i] / elem_size); ++j)
|
||||
out[i].push_back(buffer[cur++]);
|
||||
buffer.resize((offsets.back() + counts.back()) / elem_size);
|
||||
}
|
||||
|
||||
detail::gather_v(comm, address(in), count(in), datatype_of(in),
|
||||
address(buffer), counts.data(), offsets.data(),
|
||||
root);
|
||||
|
||||
if (comm.rank() == root)
|
||||
{
|
||||
out.resize(static_cast<size_t>(comm.size()));
|
||||
size_t offset = 0;
|
||||
for (size_t i = 0; i < out.size(); ++i)
|
||||
{
|
||||
auto count = static_cast<size_t>(counts[i] / elem_size);
|
||||
out[i].insert(out[i].end(), buffer.data() + offset, buffer.data() + offset + count);
|
||||
offset += count;
|
||||
}
|
||||
}
|
||||
#else
|
||||
DIY_UNUSED(comm);
|
||||
DIY_UNUSED(root);
|
||||
out.resize(1);
|
||||
out[0] = in;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void gather(const communicator& comm, const T& in, int root)
|
||||
{
|
||||
#ifndef VTKM_DIY_NO_MPI
|
||||
MPI_Gather(address(in), count(in), datatype(in), address(in), count(in), datatype(in), root, comm);
|
||||
#else
|
||||
DIY_UNUSED(comm);
|
||||
DIY_UNUSED(in);
|
||||
DIY_UNUSED(root);
|
||||
DIY_UNSUPPORTED_MPI_CALL("MPI_Gather");
|
||||
#endif
|
||||
detail::gather(comm, address(in), count(in), datatype_of(in), address(in), root);
|
||||
}
|
||||
|
||||
static void gather(const communicator& comm, const std::vector<T>& in, int root)
|
||||
{
|
||||
#ifndef VTKM_DIY_NO_MPI
|
||||
Collectives<int,void*>::gather(comm, count(in), root);
|
||||
|
||||
MPI_Gatherv(address(in), count(in), datatype(in),
|
||||
0, 0, 0,
|
||||
datatype(in),
|
||||
root, comm);
|
||||
#else
|
||||
DIY_UNUSED(comm);
|
||||
DIY_UNUSED(in);
|
||||
DIY_UNUSED(root);
|
||||
DIY_UNSUPPORTED_MPI_CALL("MPI_Gatherv");
|
||||
#endif
|
||||
detail::gather_v(comm, address(in), count(in), datatype_of(in), 0, 0, 0, root);
|
||||
}
|
||||
|
||||
static void all_gather(const communicator& comm, const T& in, std::vector<T>& out)
|
||||
{
|
||||
out.resize(comm.size());
|
||||
#ifndef VTKM_DIY_NO_MPI
|
||||
MPI_Allgather(address(in), count(in), datatype(in),
|
||||
address(out), count(in), datatype(in),
|
||||
comm);
|
||||
#else
|
||||
DIY_UNUSED(comm);
|
||||
out[0] = in;
|
||||
#endif
|
||||
detail::all_gather(comm, address(in), count(in), datatype_of(in), address(out));
|
||||
}
|
||||
|
||||
static void all_gather(const communicator& comm, const std::vector<T>& in, std::vector< std::vector<T> >& out)
|
||||
{
|
||||
#ifndef VTKM_DIY_NO_MPI
|
||||
std::vector<int> counts(comm.size());
|
||||
std::vector<int> counts(static_cast<size_t>(comm.size()));
|
||||
Collectives<int,void*>::all_gather(comm, count(in), counts);
|
||||
|
||||
std::vector<int> offsets(comm.size(), 0);
|
||||
for (unsigned i = 1; i < offsets.size(); ++i)
|
||||
offsets[i] = offsets[i-1] + counts[i-1];
|
||||
std::vector<int> offsets(counts.size());
|
||||
offsets[0] = 0;
|
||||
std::partial_sum(counts.begin(), counts.end() - 1, offsets.begin() + 1);
|
||||
|
||||
int elem_size = count(in[0]); // size of 1 vector element in units of mpi datatype
|
||||
std::vector<T> buffer((offsets.back() + counts.back()) / elem_size);
|
||||
MPI_Allgatherv(address(in), count(in), datatype(in),
|
||||
address(buffer),
|
||||
&counts[0],
|
||||
&offsets[0],
|
||||
datatype(buffer),
|
||||
comm);
|
||||
detail::all_gather_v(comm,
|
||||
address(in), count(in), datatype_of(in),
|
||||
address(buffer),
|
||||
&counts[0],
|
||||
&offsets[0]);
|
||||
|
||||
out.resize(comm.size());
|
||||
size_t cur = 0;
|
||||
for (int i = 0; i < comm.size(); ++i)
|
||||
out.resize(static_cast<size_t>(comm.size()));
|
||||
size_t offset = 0;
|
||||
for (size_t i = 0; i < out.size(); ++i)
|
||||
{
|
||||
out[i].reserve(counts[i] / elem_size);
|
||||
for (int j = 0; j < (int)(counts[i] / elem_size); ++j)
|
||||
out[i].push_back(buffer[cur++]);
|
||||
auto count = static_cast<size_t>(counts[i] / elem_size);
|
||||
out[i].insert(out[i].end(), buffer.data() + offset, buffer.data() + offset + count);
|
||||
offset += count;
|
||||
}
|
||||
#else
|
||||
DIY_UNUSED(comm);
|
||||
out.resize(1);
|
||||
out[0] = in;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void reduce(const communicator& comm, const T& in, T& out, int root, const Op&)
|
||||
{
|
||||
#ifndef VTKM_DIY_NO_MPI
|
||||
MPI_Reduce(address(in), address(out), count(in), datatype(in),
|
||||
detail::mpi_op<Op>::get(),
|
||||
root, comm);
|
||||
#else
|
||||
DIY_UNUSED(comm);
|
||||
DIY_UNUSED(root);
|
||||
out = in;
|
||||
#endif
|
||||
auto op = detail::mpi_op<Op>::get();
|
||||
detail::reduce(comm, address(in), count(in), datatype_of(in), address(out), op, root);
|
||||
}
|
||||
|
||||
static void reduce(const communicator& comm, const T& in, int root, const Op&)
|
||||
{
|
||||
#ifndef VTKM_DIY_NO_MPI
|
||||
MPI_Reduce(address(in), address(in), count(in), datatype(in),
|
||||
detail::mpi_op<Op>::get(),
|
||||
root, comm);
|
||||
#else
|
||||
DIY_UNUSED(comm);
|
||||
DIY_UNUSED(in);
|
||||
DIY_UNUSED(root);
|
||||
DIY_UNSUPPORTED_MPI_CALL("MPI_Reduce");
|
||||
#endif
|
||||
auto op = detail::mpi_op<Op>::get();
|
||||
detail::reduce(comm, address(in), count(in), datatype_of(in), address(in), op, root);
|
||||
}
|
||||
|
||||
static void all_reduce(const communicator& comm, const T& in, T& out, const Op&)
|
||||
{
|
||||
#ifndef VTKM_DIY_NO_MPI
|
||||
MPI_Allreduce(address(in), address(out), count(in), datatype(in),
|
||||
detail::mpi_op<Op>::get(),
|
||||
comm);
|
||||
#else
|
||||
DIY_UNUSED(comm);
|
||||
out = in;
|
||||
#endif
|
||||
auto op = detail::mpi_op<Op>::get();
|
||||
detail::all_reduce(comm, address(in), address(out), count(in), datatype_of(in), op);
|
||||
}
|
||||
|
||||
static void all_reduce(const communicator& comm, const std::vector<T>& in, std::vector<T>& out, const Op&)
|
||||
{
|
||||
#ifndef VTKM_DIY_NO_MPI
|
||||
auto op = detail::mpi_op<Op>::get();
|
||||
out.resize(in.size());
|
||||
MPI_Allreduce(address(in), address(out), count(in),
|
||||
datatype(in),
|
||||
detail::mpi_op<Op>::get(),
|
||||
comm);
|
||||
#else
|
||||
DIY_UNUSED(comm);
|
||||
out = in;
|
||||
#endif
|
||||
detail::all_reduce(comm, address(in), address(out), count(in), datatype_of(in), op);
|
||||
}
|
||||
|
||||
static request iall_reduce(const communicator& comm, const T& in, T& out, const Op&)
|
||||
{
|
||||
auto op = detail::mpi_op<Op>::get();
|
||||
return detail::iall_reduce(comm, address(in), address(out), count(in), datatype_of(in), op);
|
||||
}
|
||||
|
||||
static request iall_reduce(const communicator& comm, const std::vector<T>& in, std::vector<T>& out, const Op&)
|
||||
{
|
||||
auto op = detail::mpi_op<Op>::get();
|
||||
out.resize(in.size());
|
||||
return detail::iall_reduce(comm, address(in), address(out), count(in), datatype_of(in), op);
|
||||
}
|
||||
|
||||
static void scan(const communicator& comm, const T& in, T& out, const Op&)
|
||||
{
|
||||
#ifndef VTKM_DIY_NO_MPI
|
||||
MPI_Scan(address(in), address(out), count(in), datatype(in),
|
||||
detail::mpi_op<Op>::get(),
|
||||
comm);
|
||||
#else
|
||||
DIY_UNUSED(comm);
|
||||
out = in;
|
||||
#endif
|
||||
auto op = detail::mpi_op<Op>::get();
|
||||
detail::scan(comm, address(in), address(out), count(in), datatype_of(in), op);
|
||||
}
|
||||
|
||||
static void all_to_all(const communicator& comm, const std::vector<T>& in, std::vector<T>& out, int n = 1)
|
||||
{
|
||||
#ifndef VTKM_DIY_NO_MPI
|
||||
// n specifies how many elements go to/from every process from every process;
|
||||
// the sizes of in and out are expected to be n * comm.size()
|
||||
|
||||
int elem_size = count(in[0]); // size of 1 vector element in units of mpi datatype
|
||||
// NB: this will fail if T is a vector
|
||||
MPI_Alltoall(address(in),
|
||||
elem_size * n,
|
||||
datatype(in),
|
||||
address(out),
|
||||
elem_size * n,
|
||||
datatype(out),
|
||||
comm);
|
||||
#else
|
||||
DIY_UNUSED(comm);
|
||||
DIY_UNUSED(n);
|
||||
out = in;
|
||||
#endif
|
||||
detail::all_to_all(comm, address(in), elem_size * n, datatype_of(in), address(out));
|
||||
}
|
||||
};
|
||||
|
||||
//! iBarrier; standalone function version for completeness
|
||||
inline request ibarrier(const communicator& comm)
|
||||
{
|
||||
return comm.ibarrier();
|
||||
}
|
||||
|
||||
//! Broadcast to all processes in `comm`.
|
||||
template<class T>
|
||||
inline
|
||||
void broadcast(const communicator& comm, T& x, int root)
|
||||
{
|
||||
Collectives<T,void*>::broadcast(comm, x, root);
|
||||
@ -275,6 +265,7 @@ namespace mpi
|
||||
|
||||
//! Broadcast for vectors
|
||||
template<class T>
|
||||
inline
|
||||
void broadcast(const communicator& comm, std::vector<T>& x, int root)
|
||||
{
|
||||
Collectives<T,void*>::broadcast(comm, x, root);
|
||||
@ -291,6 +282,7 @@ namespace mpi
|
||||
//! On `root` process, `out` is resized to `comm.size()` and filled with
|
||||
//! elements from the respective ranks.
|
||||
template<class T>
|
||||
inline
|
||||
void gather(const communicator& comm, const T& in, std::vector<T>& out, int root)
|
||||
{
|
||||
Collectives<T,void*>::gather(comm, in, out, root);
|
||||
@ -298,6 +290,7 @@ namespace mpi
|
||||
|
||||
//! Same as above, but for vectors.
|
||||
template<class T>
|
||||
inline
|
||||
void gather(const communicator& comm, const std::vector<T>& in, std::vector< std::vector<T> >& out, int root)
|
||||
{
|
||||
Collectives<T,void*>::gather(comm, in, out, root);
|
||||
@ -305,6 +298,7 @@ namespace mpi
|
||||
|
||||
//! Simplified version (without `out`) for use on non-root processes.
|
||||
template<class T>
|
||||
inline
|
||||
void gather(const communicator& comm, const T& in, int root)
|
||||
{
|
||||
Collectives<T,void*>::gather(comm, in, root);
|
||||
@ -312,6 +306,7 @@ namespace mpi
|
||||
|
||||
//! Simplified version (without `out`) for use on non-root processes.
|
||||
template<class T>
|
||||
inline
|
||||
void gather(const communicator& comm, const std::vector<T>& in, int root)
|
||||
{
|
||||
Collectives<T,void*>::gather(comm, in, root);
|
||||
@ -321,6 +316,7 @@ namespace mpi
|
||||
//! `out` is resized to `comm.size()` and filled with
|
||||
//! elements from the respective ranks.
|
||||
template<class T>
|
||||
inline
|
||||
void all_gather(const communicator& comm, const T& in, std::vector<T>& out)
|
||||
{
|
||||
Collectives<T,void*>::all_gather(comm, in, out);
|
||||
@ -328,6 +324,7 @@ namespace mpi
|
||||
|
||||
//! Same as above, but for vectors.
|
||||
template<class T>
|
||||
inline
|
||||
void all_gather(const communicator& comm, const std::vector<T>& in, std::vector< std::vector<T> >& out)
|
||||
{
|
||||
Collectives<T,void*>::all_gather(comm, in, out);
|
||||
@ -335,6 +332,7 @@ namespace mpi
|
||||
|
||||
//! reduce
|
||||
template<class T, class Op>
|
||||
inline
|
||||
void reduce(const communicator& comm, const T& in, T& out, int root, const Op& op)
|
||||
{
|
||||
Collectives<T, Op>::reduce(comm, in, out, root, op);
|
||||
@ -342,6 +340,7 @@ namespace mpi
|
||||
|
||||
//! Simplified version (without `out`) for use on non-root processes.
|
||||
template<class T, class Op>
|
||||
inline
|
||||
void reduce(const communicator& comm, const T& in, int root, const Op& op)
|
||||
{
|
||||
Collectives<T, Op>::reduce(comm, in, root, op);
|
||||
@ -349,6 +348,7 @@ namespace mpi
|
||||
|
||||
//! all_reduce
|
||||
template<class T, class Op>
|
||||
inline
|
||||
void all_reduce(const communicator& comm, const T& in, T& out, const Op& op)
|
||||
{
|
||||
Collectives<T, Op>::all_reduce(comm, in, out, op);
|
||||
@ -356,13 +356,32 @@ namespace mpi
|
||||
|
||||
//! Same as above, but for vectors.
|
||||
template<class T, class Op>
|
||||
inline
|
||||
void all_reduce(const communicator& comm, const std::vector<T>& in, std::vector<T>& out, const Op& op)
|
||||
{
|
||||
Collectives<T, Op>::all_reduce(comm, in, out, op);
|
||||
}
|
||||
|
||||
//! iall_reduce
|
||||
template<class T, class Op>
|
||||
inline
|
||||
request iall_reduce(const communicator& comm, const T& in, T& out, const Op& op)
|
||||
{
|
||||
return Collectives<T, Op>::iall_reduce(comm, in, out, op);
|
||||
}
|
||||
|
||||
//! Same as above, but for vectors.
|
||||
template<class T, class Op>
|
||||
inline
|
||||
request iall_reduce(const communicator& comm, const std::vector<T>& in, std::vector<T>& out, const Op& op)
|
||||
{
|
||||
return Collectives<T, Op>::iall_reduce(comm, in, out, op);
|
||||
}
|
||||
|
||||
|
||||
//! scan
|
||||
template<class T, class Op>
|
||||
inline
|
||||
void scan(const communicator& comm, const T& in, T& out, const Op& op)
|
||||
{
|
||||
Collectives<T, Op>::scan(comm, in, out, op);
|
||||
@ -370,6 +389,7 @@ namespace mpi
|
||||
|
||||
//! all_to_all
|
||||
template<class T>
|
||||
inline
|
||||
void all_to_all(const communicator& comm, const std::vector<T>& in, std::vector<T>& out, int n = 1)
|
||||
{
|
||||
Collectives<T, void*>::all_to_all(comm, in, out, n);
|
||||
@ -378,3 +398,9 @@ namespace mpi
|
||||
//!@}
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef VTKMDIY_MPI_AS_LIB
|
||||
#include "collectives.cpp"
|
||||
#endif
|
||||
|
||||
#endif // VTKMDIY_MPI_COLLECTIVES_HPP
|
||||
|
130
vtkm/thirdparty/diy/vtkmdiy/include/vtkmdiy/mpi/communicator.cpp
vendored
Normal file
130
vtkm/thirdparty/diy/vtkmdiy/include/vtkmdiy/mpi/communicator.cpp
vendored
Normal file
@ -0,0 +1,130 @@
|
||||
#ifdef VTKMDIY_MPI_AS_LIB
|
||||
#include "communicator.hpp"
|
||||
#endif
|
||||
|
||||
diy::mpi::communicator::communicator()
|
||||
: comm_(make_DIY_MPI_Comm(MPI_COMM_WORLD)), rank_(0), size_(1), owner_(false)
|
||||
{
|
||||
#if VTKMDIY_HAS_MPI
|
||||
MPI_Comm_rank(mpi_cast(comm_), &rank_);
|
||||
MPI_Comm_size(mpi_cast(comm_), &size_);
|
||||
#endif
|
||||
}
|
||||
|
||||
diy::mpi::communicator::
|
||||
communicator(DIY_MPI_Comm comm, bool owner):
|
||||
comm_(comm), rank_(0), size_(1), owner_(owner)
|
||||
{
|
||||
#if VTKMDIY_HAS_MPI
|
||||
if (mpi_cast(comm_) != MPI_COMM_NULL)
|
||||
{
|
||||
MPI_Comm_rank(mpi_cast(comm_), &rank_);
|
||||
MPI_Comm_size(mpi_cast(comm_), &size_);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef VTKMDIY_MPI_AS_LIB // only available in header-only mode
|
||||
diy::mpi::communicator::
|
||||
communicator(MPI_Comm comm, bool owner):
|
||||
comm_(comm), rank_(0), size_(1), owner_(owner)
|
||||
{
|
||||
#if VTKMDIY_HAS_MPI
|
||||
if (comm_ != MPI_COMM_NULL)
|
||||
{
|
||||
MPI_Comm_rank(comm_, &rank_);
|
||||
MPI_Comm_size(comm_, &size_);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
diy::mpi::communicator::
|
||||
destroy()
|
||||
{
|
||||
#if VTKMDIY_HAS_MPI
|
||||
if (owner_)
|
||||
MPI_Comm_free(&mpi_cast(comm_));
|
||||
#endif
|
||||
}
|
||||
|
||||
diy::mpi::status
|
||||
diy::mpi::communicator::
|
||||
probe(int source, int tag) const
|
||||
{
|
||||
#if VTKMDIY_HAS_MPI
|
||||
status s;
|
||||
MPI_Probe(source, tag, mpi_cast(comm_), &mpi_cast(s.handle));
|
||||
return s;
|
||||
#else
|
||||
(void) source; (void) tag;
|
||||
VTKMDIY_UNSUPPORTED_MPI_CALL(MPI_Probe);
|
||||
#endif
|
||||
}
|
||||
|
||||
diy::mpi::optional<diy::mpi::status>
|
||||
diy::mpi::communicator::
|
||||
iprobe(int source, int tag) const
|
||||
{
|
||||
(void) source; (void) tag;
|
||||
#if VTKMDIY_HAS_MPI
|
||||
status s;
|
||||
int flag;
|
||||
MPI_Iprobe(source, tag, mpi_cast(comm_), &flag, &mpi_cast(s.handle));
|
||||
if (flag)
|
||||
return s;
|
||||
#endif
|
||||
return optional<status>();
|
||||
}
|
||||
|
||||
void
|
||||
diy::mpi::communicator::
|
||||
barrier() const
|
||||
{
|
||||
#if VTKMDIY_HAS_MPI
|
||||
MPI_Barrier(mpi_cast(comm_));
|
||||
#endif
|
||||
}
|
||||
|
||||
diy::mpi::communicator
|
||||
diy::mpi::communicator::
|
||||
split(int color, int key) const
|
||||
{
|
||||
#if VTKMDIY_HAS_MPI
|
||||
DIY_MPI_Comm newcomm;
|
||||
MPI_Comm_split(mpi_cast(comm_), color, key, &mpi_cast(newcomm));
|
||||
return communicator(newcomm, true);
|
||||
#else
|
||||
(void) color; (void) key;
|
||||
return communicator();
|
||||
#endif
|
||||
}
|
||||
|
||||
diy::mpi::request
|
||||
diy::mpi::communicator::
|
||||
ibarrier() const
|
||||
{
|
||||
#if VTKMDIY_HAS_MPI
|
||||
request r;
|
||||
MPI_Ibarrier(mpi_cast(comm_), &mpi_cast(r.handle));
|
||||
return r;
|
||||
#else
|
||||
// this is not the ideal fix; in principle we should just return a status
|
||||
// that tests true, but this requires redesigning some parts of our no-mpi
|
||||
// handling
|
||||
VTKMDIY_UNSUPPORTED_MPI_CALL(MPI_Ibarrier);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
diy::mpi::communicator::
|
||||
duplicate(const communicator& other)
|
||||
{
|
||||
#if VTKMDIY_HAS_MPI
|
||||
DIY_MPI_Comm newcomm;
|
||||
MPI_Comm_dup(mpi_cast(other.comm_), &mpi_cast(newcomm));
|
||||
(*this) = communicator(newcomm,true);
|
||||
#endif
|
||||
(void) other;
|
||||
}
|
@ -1,3 +1,12 @@
|
||||
#ifndef VTKMDIY_MPI_COMMUNICATOR_HPP
|
||||
#define VTKMDIY_MPI_COMMUNICATOR_HPP
|
||||
|
||||
#include "config.hpp"
|
||||
#include "optional.hpp"
|
||||
#include "point-to-point.hpp"
|
||||
#include "request.hpp"
|
||||
#include "status.hpp"
|
||||
|
||||
namespace diy
|
||||
{
|
||||
namespace mpi
|
||||
@ -8,8 +17,14 @@ namespace mpi
|
||||
class communicator
|
||||
{
|
||||
public:
|
||||
inline
|
||||
communicator(MPI_Comm comm = MPI_COMM_WORLD, bool owner = false);
|
||||
VTKMDIY_MPI_EXPORT_FUNCTION
|
||||
communicator();
|
||||
|
||||
communicator(DIY_MPI_Comm comm):
|
||||
communicator(comm, false) {}
|
||||
|
||||
VTKMDIY_MPI_EXPORT_FUNCTION
|
||||
communicator(DIY_MPI_Comm comm, bool owner);
|
||||
|
||||
~communicator() { destroy(); }
|
||||
|
||||
@ -25,9 +40,19 @@ namespace mpi
|
||||
size_(other.size_),
|
||||
owner_(other.owner_) { other.owner_ = false; }
|
||||
|
||||
communicator&
|
||||
#ifndef VTKMDIY_MPI_AS_LIB // only available in header-only mode
|
||||
communicator(MPI_Comm comm):
|
||||
communicator(comm, false) {}
|
||||
|
||||
VTKMDIY_MPI_EXPORT_FUNCTION
|
||||
communicator(MPI_Comm comm, bool owner);
|
||||
|
||||
operator MPI_Comm() { return comm_; }
|
||||
#endif
|
||||
|
||||
communicator&
|
||||
operator=(const communicator& other) { destroy(); comm_ = other.comm_; rank_ = other.rank_; size_ = other.size_; owner_ = false; return *this; }
|
||||
communicator&
|
||||
communicator&
|
||||
operator=(communicator&& other) { destroy(); comm_ = other.comm_; rank_ = other.rank_; size_ = other.size_; owner_ = other.owner_; other.owner_ = false; return *this; }
|
||||
|
||||
int rank() const { return rank_; }
|
||||
@ -35,193 +60,71 @@ namespace mpi
|
||||
|
||||
//! Send `x` to processor `dest` using `tag` (blocking).
|
||||
template<class T>
|
||||
void send(int dest, int tag, const T& x) const { detail::send<T>()(comm_, dest, tag, x); }
|
||||
void send(int dest, int tag, const T& x) const { detail::send(comm_, dest, tag, x); }
|
||||
|
||||
//! Receive `x` from `dest` using `tag` (blocking).
|
||||
//! If `T` is an `std::vector<...>`, `recv` will resize it to fit exactly the sent number of values.
|
||||
template <class T>
|
||||
status recv(int source, int tag, T &x) const
|
||||
{
|
||||
#if defined(VTKM_DIY_NO_MPI) && defined(__CUDACC_VER_MAJOR__) && __CUDACC_VER_MAJOR__ < 8 // CUDA 7.5 workaround
|
||||
(void) source; (void)tag; (void)x;
|
||||
DIY_UNSUPPORTED_MPI_CALL(MPI_Recv);
|
||||
#else
|
||||
return detail::recv<T>{}(comm_, source, tag, x);
|
||||
#endif
|
||||
}
|
||||
template<class T>
|
||||
status recv(int source, int tag, T& x) const { return detail::recv(comm_, source, tag, x); }
|
||||
|
||||
//! Non-blocking version of `send()`.
|
||||
template <class T>
|
||||
request isend(int dest, int tag, const T &x) const
|
||||
{
|
||||
#if defined(VTKM_DIY_NO_MPI) && defined(__CUDACC_VER_MAJOR__) && __CUDACC_VER_MAJOR__ < 8 // CUDA 7.5 workaround
|
||||
(void) dest; (void)tag; (void)x;
|
||||
DIY_UNSUPPORTED_MPI_CALL(MPI_Send);
|
||||
#else
|
||||
return detail::isend<T>{}(comm_, dest, tag, x);
|
||||
#endif
|
||||
}
|
||||
template<class T>
|
||||
request isend(int dest, int tag, const T& x) const { return detail::isend(comm_, dest, tag, x); }
|
||||
|
||||
//! Non-blocking version of `ssend()`.
|
||||
template<class T>
|
||||
request issend(int dest, int tag, const T& x) const { return detail::issend<T>()(comm_, dest, tag, x); }
|
||||
request issend(int dest, int tag, const T& x) const { return detail::issend(comm_, dest, tag, x); }
|
||||
|
||||
//! Non-blocking version of `recv()`.
|
||||
//! If `T` is an `std::vector<...>`, its size must be big enough to accommodate the sent values.
|
||||
template <class T>
|
||||
request irecv(int source, int tag, T &x) const
|
||||
{
|
||||
#if defined(VTKM_DIY_NO_MPI) && defined(__CUDACC_VER_MAJOR__) && __CUDACC_VER_MAJOR__ < 8 // CUDA 7.5 workaround
|
||||
(void)source; (void)tag; (void)x;
|
||||
DIY_UNSUPPORTED_MPI_CALL(MPI_Irecv);
|
||||
#else
|
||||
return detail::irecv<T>()(comm_, source, tag, x);
|
||||
#endif
|
||||
}
|
||||
template<class T>
|
||||
request irecv(int source, int tag, T& x) const { return detail::irecv(comm_, source, tag, x); }
|
||||
|
||||
//! probe
|
||||
inline
|
||||
VTKMDIY_MPI_EXPORT_FUNCTION
|
||||
status probe(int source, int tag) const;
|
||||
|
||||
//! iprobe
|
||||
inline
|
||||
VTKMDIY_MPI_EXPORT_FUNCTION
|
||||
optional<status>
|
||||
iprobe(int source, int tag) const;
|
||||
|
||||
//! barrier
|
||||
inline
|
||||
VTKMDIY_MPI_EXPORT_FUNCTION
|
||||
void barrier() const;
|
||||
|
||||
//! Nonblocking version of barrier
|
||||
inline
|
||||
VTKMDIY_MPI_EXPORT_FUNCTION
|
||||
request ibarrier() const;
|
||||
|
||||
operator MPI_Comm() const { return comm_; }
|
||||
|
||||
//! split
|
||||
//! When keys are the same, the ties are broken by the rank in the original comm.
|
||||
inline
|
||||
VTKMDIY_MPI_EXPORT_FUNCTION
|
||||
communicator
|
||||
split(int color, int key = 0) const;
|
||||
|
||||
//! duplicate
|
||||
inline
|
||||
VTKMDIY_MPI_EXPORT_FUNCTION
|
||||
void duplicate(const communicator& other);
|
||||
|
||||
DIY_MPI_Comm handle() const { return comm_; }
|
||||
|
||||
private:
|
||||
inline
|
||||
VTKMDIY_MPI_EXPORT_FUNCTION
|
||||
void destroy();
|
||||
|
||||
private:
|
||||
MPI_Comm comm_;
|
||||
int rank_;
|
||||
int size_;
|
||||
bool owner_;
|
||||
DIY_MPI_Comm comm_;
|
||||
int rank_;
|
||||
int size_;
|
||||
bool owner_;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
diy::mpi::communicator::
|
||||
communicator(MPI_Comm comm, bool owner):
|
||||
comm_(comm), rank_(0), size_(1), owner_(owner)
|
||||
{
|
||||
#ifndef VTKM_DIY_NO_MPI
|
||||
if (comm != MPI_COMM_NULL)
|
||||
{
|
||||
MPI_Comm_rank(comm_, &rank_);
|
||||
MPI_Comm_size(comm_, &size_);
|
||||
}
|
||||
}
|
||||
} // diy::mpi
|
||||
|
||||
#ifndef VTKMDIY_MPI_AS_LIB
|
||||
#include "communicator.cpp"
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
diy::mpi::communicator::
|
||||
destroy()
|
||||
{
|
||||
#ifndef VTKM_DIY_NO_MPI
|
||||
if (owner_)
|
||||
MPI_Comm_free(&comm_);
|
||||
#endif
|
||||
}
|
||||
|
||||
diy::mpi::status
|
||||
diy::mpi::communicator::
|
||||
probe(int source, int tag) const
|
||||
{
|
||||
(void) source;
|
||||
(void) tag;
|
||||
|
||||
#ifndef VTKM_DIY_NO_MPI
|
||||
status s;
|
||||
MPI_Probe(source, tag, comm_, &s.s);
|
||||
return s;
|
||||
#else
|
||||
DIY_UNSUPPORTED_MPI_CALL(MPI_Probe);
|
||||
#endif
|
||||
}
|
||||
|
||||
diy::mpi::optional<diy::mpi::status>
|
||||
diy::mpi::communicator::
|
||||
iprobe(int source, int tag) const
|
||||
{
|
||||
(void) source;
|
||||
(void) tag;
|
||||
#ifndef VTKM_DIY_NO_MPI
|
||||
status s;
|
||||
int flag;
|
||||
MPI_Iprobe(source, tag, comm_, &flag, &s.s);
|
||||
if (flag)
|
||||
return s;
|
||||
#endif
|
||||
return optional<status>();
|
||||
}
|
||||
|
||||
void
|
||||
diy::mpi::communicator::
|
||||
barrier() const
|
||||
{
|
||||
#ifndef VTKM_DIY_NO_MPI
|
||||
MPI_Barrier(comm_);
|
||||
#endif
|
||||
}
|
||||
|
||||
diy::mpi::communicator
|
||||
diy::mpi::communicator::
|
||||
split(int color, int key) const
|
||||
{
|
||||
#ifndef VTKM_DIY_NO_MPI
|
||||
MPI_Comm newcomm;
|
||||
MPI_Comm_split(comm_, color, key, &newcomm);
|
||||
return communicator(newcomm, true);
|
||||
#else
|
||||
return communicator();
|
||||
#endif
|
||||
}
|
||||
|
||||
diy::mpi::request
|
||||
diy::mpi::communicator::
|
||||
ibarrier() const
|
||||
{
|
||||
#ifndef VTKM_DIY_NO_MPI
|
||||
request r_;
|
||||
MPI_Ibarrier(comm_, &r_.r);
|
||||
return r_;
|
||||
#else
|
||||
// this is not the ideal fix; in principle we should just return a status
|
||||
// that tests true, but this requires redesigning some parts of our no-mpi
|
||||
// handling
|
||||
DIY_UNSUPPORTED_MPI_CALL(MPI_Ibarrier);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
diy::mpi::communicator::
|
||||
duplicate(const communicator& other)
|
||||
{
|
||||
#ifndef VTKM_DIY_NO_MPI
|
||||
MPI_Comm newcomm;
|
||||
MPI_Comm_dup(other.comm_, &newcomm);
|
||||
(*this) = communicator(newcomm,true);
|
||||
#endif
|
||||
}
|
||||
#endif // VTKMDIY_MPI_COMMUNICATOR_HPP
|
||||
|
70
vtkm/thirdparty/diy/vtkmdiy/include/vtkmdiy/mpi/config.hpp
vendored
Normal file
70
vtkm/thirdparty/diy/vtkmdiy/include/vtkmdiy/mpi/config.hpp
vendored
Normal file
@ -0,0 +1,70 @@
|
||||
#ifndef VTKMDIY_MPI_CONFIG_HPP
|
||||
#define VTKMDIY_MPI_CONFIG_HPP
|
||||
|
||||
/// We want to allow the use of `diy::mpi` in either header-only or library mode.
|
||||
/// VTKMDIY_MPI_AS_LIB is defined when using library mode.
|
||||
/// This file contains some configuration macros. To maintain backwards compatibility
|
||||
/// suitable default values should be defined when using header-only mode.
|
||||
|
||||
/// VTKMDIY_HAS_MPI should always be defined when VTKMDIY_MPI_AS_LIB is defined, but only for
|
||||
/// the compilation units that are part of the library.
|
||||
/// VTKMDIY_HAS_MPI=1 means MPI library is availalbe.
|
||||
/// For header-only, the default is to assume MPI is available
|
||||
#if !defined(VTKMDIY_MPI_AS_LIB) && !defined(VTKMDIY_HAS_MPI)
|
||||
# define VTKMDIY_HAS_MPI 1
|
||||
#endif
|
||||
|
||||
/// Include appropriate mpi header. Since VTKMDIY_HAS_MPI is only defined for
|
||||
/// the compilation units of the library, when in library mode, the header is
|
||||
/// only included for the library's compilation units.
|
||||
#ifdef VTKMDIY_HAS_MPI
|
||||
# if VTKMDIY_HAS_MPI
|
||||
# include <mpi.h>
|
||||
# else
|
||||
# include "no-mpi.hpp"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/// Classes and objects that need to be visible to clients of the library should be
|
||||
/// marked as VTKMDIY_MPI_EXPORT. Similarly API functions should be marked as
|
||||
/// VTKMDIY_MPI_EXPORT_FUNCTION.
|
||||
#include "diy-mpi-export.h" // defines VTKMDIY_MPI_EXPORT and VTKMDIY_MPI_EXPORT_FUNCTION
|
||||
|
||||
/// Define alisases for MPI types
|
||||
#ifdef VTKMDIY_MPI_AS_LIB
|
||||
# include "mpitypes.hpp" // only configured in library mode
|
||||
#else // ifdef VTKMDIY_MPI_AS_LIB
|
||||
|
||||
namespace diy
|
||||
{
|
||||
namespace mpi
|
||||
{
|
||||
|
||||
#define DEFINE_DIY_MPI_TYPE(mpitype) \
|
||||
struct DIY_##mpitype { \
|
||||
DIY_##mpitype() = default; \
|
||||
DIY_##mpitype(const mpitype& obj) : data(obj) {} \
|
||||
DIY_##mpitype& operator=(const mpitype& obj) { data = obj; return *this; } \
|
||||
operator mpitype() { return data; } \
|
||||
mpitype data; \
|
||||
};
|
||||
|
||||
DEFINE_DIY_MPI_TYPE(MPI_Comm)
|
||||
DEFINE_DIY_MPI_TYPE(MPI_Datatype)
|
||||
DEFINE_DIY_MPI_TYPE(MPI_Status)
|
||||
DEFINE_DIY_MPI_TYPE(MPI_Request)
|
||||
DEFINE_DIY_MPI_TYPE(MPI_Op)
|
||||
DEFINE_DIY_MPI_TYPE(MPI_File)
|
||||
DEFINE_DIY_MPI_TYPE(MPI_Win)
|
||||
|
||||
#undef DEFINE_DIY_MPI_TYPE
|
||||
|
||||
}
|
||||
} // diy::mpi
|
||||
#endif // ifdef VTKMDIY_MPI_AS_LIB
|
||||
|
||||
#ifdef VTKMDIY_HAS_MPI
|
||||
# include "mpi_cast.hpp"
|
||||
#endif
|
||||
|
||||
#endif // VTKMDIY_MPI_CONFIG_HPP
|
@ -1,13 +0,0 @@
|
||||
#ifndef VTKMDIY_MPI_CONSTANTS_HPP
|
||||
#define VTKMDIY_MPI_CONSTANTS_HPP
|
||||
|
||||
namespace diy
|
||||
{
|
||||
namespace mpi
|
||||
{
|
||||
const int any_source = MPI_ANY_SOURCE;
|
||||
const int any_tag = MPI_ANY_TAG;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
34
vtkm/thirdparty/diy/vtkmdiy/include/vtkmdiy/mpi/datatypes.cpp
vendored
Normal file
34
vtkm/thirdparty/diy/vtkmdiy/include/vtkmdiy/mpi/datatypes.cpp
vendored
Normal file
@ -0,0 +1,34 @@
|
||||
#ifdef VTKMDIY_MPI_AS_LIB
|
||||
#include "datatypes.hpp"
|
||||
#endif
|
||||
|
||||
namespace diy
|
||||
{
|
||||
namespace mpi
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
#define DIY_MPI_DATATYPE_MAP(cpp_type, mpi_type) \
|
||||
template<> datatype get_mpi_datatype<cpp_type>() { \
|
||||
return datatype(make_DIY_MPI_Datatype(mpi_type)); \
|
||||
}
|
||||
|
||||
DIY_MPI_DATATYPE_MAP(char, MPI_BYTE)
|
||||
DIY_MPI_DATATYPE_MAP(unsigned char, MPI_BYTE)
|
||||
DIY_MPI_DATATYPE_MAP(bool, MPI_BYTE)
|
||||
DIY_MPI_DATATYPE_MAP(int, MPI_INT)
|
||||
DIY_MPI_DATATYPE_MAP(unsigned, MPI_UNSIGNED)
|
||||
DIY_MPI_DATATYPE_MAP(long, MPI_LONG)
|
||||
DIY_MPI_DATATYPE_MAP(unsigned long, MPI_UNSIGNED_LONG)
|
||||
DIY_MPI_DATATYPE_MAP(long long, MPI_LONG_LONG_INT)
|
||||
DIY_MPI_DATATYPE_MAP(unsigned long long, MPI_UNSIGNED_LONG_LONG)
|
||||
DIY_MPI_DATATYPE_MAP(float, MPI_FLOAT)
|
||||
DIY_MPI_DATATYPE_MAP(double, MPI_DOUBLE)
|
||||
|
||||
#undef DIY_MPI_DATATYPE_MAP
|
||||
|
||||
}
|
||||
}
|
||||
} // diy::mpi::detail
|
@ -1,16 +1,31 @@
|
||||
#ifndef VTKMDIY_MPI_DATATYPES_HPP
|
||||
#define VTKMDIY_MPI_DATATYPES_HPP
|
||||
|
||||
#include "config.hpp"
|
||||
|
||||
#include <vector>
|
||||
#include <array>
|
||||
|
||||
namespace diy
|
||||
{
|
||||
namespace mpi
|
||||
{
|
||||
|
||||
struct datatype
|
||||
{
|
||||
datatype() = default;
|
||||
datatype(const DIY_MPI_Datatype& dt) : handle(dt) {}
|
||||
|
||||
#ifndef VTKMDIY_MPI_AS_LIB // only available in header-only mode
|
||||
datatype(const MPI_Datatype& dt) : handle(dt) {}
|
||||
operator MPI_Datatype() { return handle; }
|
||||
#endif
|
||||
|
||||
DIY_MPI_Datatype handle;
|
||||
};
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template<class T> MPI_Datatype get_mpi_datatype();
|
||||
|
||||
struct true_type {};
|
||||
struct false_type {};
|
||||
|
||||
@ -18,28 +33,34 @@ namespace detail
|
||||
template<class T>
|
||||
struct is_mpi_datatype { typedef false_type type; };
|
||||
|
||||
#define VTKMDIY_MPI_DATATYPE_MAP(cpp_type, mpi_type) \
|
||||
template<> inline MPI_Datatype get_mpi_datatype<cpp_type>() { return mpi_type; } \
|
||||
template<> struct is_mpi_datatype<cpp_type> { typedef true_type type; }; \
|
||||
template<> struct is_mpi_datatype< std::vector<cpp_type> > { typedef true_type type; };
|
||||
template<class T> datatype get_mpi_datatype();
|
||||
|
||||
VTKMDIY_MPI_DATATYPE_MAP(char, MPI_BYTE);
|
||||
VTKMDIY_MPI_DATATYPE_MAP(unsigned char, MPI_BYTE);
|
||||
VTKMDIY_MPI_DATATYPE_MAP(bool, MPI_BYTE);
|
||||
VTKMDIY_MPI_DATATYPE_MAP(int, MPI_INT);
|
||||
VTKMDIY_MPI_DATATYPE_MAP(unsigned, MPI_UNSIGNED);
|
||||
VTKMDIY_MPI_DATATYPE_MAP(long, MPI_LONG);
|
||||
VTKMDIY_MPI_DATATYPE_MAP(unsigned long, MPI_UNSIGNED_LONG);
|
||||
VTKMDIY_MPI_DATATYPE_MAP(long long, MPI_LONG_LONG_INT);
|
||||
VTKMDIY_MPI_DATATYPE_MAP(unsigned long long, MPI_UNSIGNED_LONG_LONG);
|
||||
VTKMDIY_MPI_DATATYPE_MAP(float, MPI_FLOAT);
|
||||
VTKMDIY_MPI_DATATYPE_MAP(double, MPI_DOUBLE);
|
||||
#define VTKMDIY_MPI_DATATYPE_DEFAULT(cpp_type) \
|
||||
template<> VTKMDIY_MPI_EXPORT_FUNCTION datatype get_mpi_datatype<cpp_type>(); \
|
||||
template<> struct is_mpi_datatype< cpp_type > { typedef true_type type; }; \
|
||||
template<> struct is_mpi_datatype< std::vector<cpp_type> > { typedef true_type type; }; \
|
||||
template<size_t N> \
|
||||
struct is_mpi_datatype< std::array<cpp_type, N> > { typedef true_type type; };
|
||||
|
||||
/* mpi_datatype: helper routines, specialized for std::vector<...> */
|
||||
VTKMDIY_MPI_DATATYPE_DEFAULT(char)
|
||||
VTKMDIY_MPI_DATATYPE_DEFAULT(unsigned char)
|
||||
VTKMDIY_MPI_DATATYPE_DEFAULT(bool)
|
||||
VTKMDIY_MPI_DATATYPE_DEFAULT(int)
|
||||
VTKMDIY_MPI_DATATYPE_DEFAULT(unsigned)
|
||||
VTKMDIY_MPI_DATATYPE_DEFAULT(long)
|
||||
VTKMDIY_MPI_DATATYPE_DEFAULT(unsigned long)
|
||||
VTKMDIY_MPI_DATATYPE_DEFAULT(long long)
|
||||
VTKMDIY_MPI_DATATYPE_DEFAULT(unsigned long long)
|
||||
VTKMDIY_MPI_DATATYPE_DEFAULT(float)
|
||||
VTKMDIY_MPI_DATATYPE_DEFAULT(double)
|
||||
|
||||
#undef VTKMDIY_MPI_DATATYPE_DEFAULT
|
||||
|
||||
/* mpi_datatype: helper routines, specialized for std::vector<...>, std::array<...> */
|
||||
template<class T>
|
||||
struct mpi_datatype
|
||||
{
|
||||
static MPI_Datatype datatype() { return get_mpi_datatype<T>(); }
|
||||
static diy::mpi::datatype datatype() { return get_mpi_datatype<T>(); }
|
||||
static const void* address(const T& x) { return &x; }
|
||||
static void* address(T& x) { return &x; }
|
||||
static int count(const T&) { return 1; }
|
||||
@ -50,44 +71,53 @@ namespace detail
|
||||
{
|
||||
typedef std::vector<U> VecU;
|
||||
|
||||
static MPI_Datatype datatype() { return mpi_datatype<U>::datatype(); }
|
||||
static diy::mpi::datatype datatype() { return mpi_datatype<U>::datatype(); }
|
||||
static const void* address(const VecU& x) { return x.data(); }
|
||||
static void* address(VecU& x) { return x.data(); }
|
||||
static int count(const VecU& x) { return x.empty() ? 0 : (static_cast<int>(x.size()) * mpi_datatype<U>::count(x[0])); }
|
||||
};
|
||||
|
||||
template<class U, size_t D>
|
||||
struct mpi_datatype< std::array<U,D> >
|
||||
{
|
||||
typedef std::array<U,D> ArrayU;
|
||||
|
||||
static diy::mpi::datatype datatype() { return mpi_datatype<U>::datatype(); }
|
||||
static const void* address(const ArrayU& x) { return x.data(); }
|
||||
static void* address(ArrayU& x) { return x.data(); }
|
||||
static int count(const ArrayU& x) { return x.empty() ? 0 : (static_cast<int>(x.size()) * mpi_datatype<U>::count(x[0])); }
|
||||
};
|
||||
} // detail
|
||||
|
||||
template<class U>
|
||||
static MPI_Datatype datatype(const U&)
|
||||
static datatype datatype_of(const U&)
|
||||
{
|
||||
using Datatype = detail::mpi_datatype<U>;
|
||||
return Datatype::datatype();
|
||||
return detail::mpi_datatype<U>::datatype();
|
||||
}
|
||||
|
||||
template<class U>
|
||||
static void* address(const U& x)
|
||||
{
|
||||
using Datatype = detail::mpi_datatype<U>;
|
||||
return const_cast<void*>(Datatype::address(x));
|
||||
return const_cast<void*>(detail::mpi_datatype<U>::address(x));
|
||||
}
|
||||
|
||||
template<class U>
|
||||
static void* address(U& x)
|
||||
{
|
||||
using Datatype = detail::mpi_datatype<U>;
|
||||
return Datatype::address(x);
|
||||
return detail::mpi_datatype<U>::address(x);
|
||||
}
|
||||
|
||||
template<class U>
|
||||
static int count(const U& x)
|
||||
{
|
||||
using Datatype = detail::mpi_datatype<U>;
|
||||
return Datatype::count(x);
|
||||
return detail::mpi_datatype<U>::count(x);
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // mpi
|
||||
} // diy
|
||||
|
||||
#ifndef VTKMDIY_MPI_AS_LIB
|
||||
#include "datatypes.cpp"
|
||||
#endif
|
||||
|
||||
#endif // VTKMDIY_MPI_DATATYPES_HPP
|
||||
|
49
vtkm/thirdparty/diy/vtkmdiy/include/vtkmdiy/mpi/diy-mpi-export.h
vendored
Normal file
49
vtkm/thirdparty/diy/vtkmdiy/include/vtkmdiy/mpi/diy-mpi-export.h
vendored
Normal file
@ -0,0 +1,49 @@
|
||||
#ifndef VTKMDIY_MPI_EXPORT_H
|
||||
#define VTKMDIY_MPI_EXPORT_H
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
# ifdef VTKMDIY_MPI_STATIC_BUILD
|
||||
/* This is a static component and has no need for exports
|
||||
elf based static libraries are able to have hidden/default visibility
|
||||
controls on symbols so we should propagate this information in that
|
||||
use case
|
||||
*/
|
||||
# define VTKMDIY_MPI_EXPORT_DEFINE
|
||||
# define VTKMDIY_MPI_IMPORT_DEFINE
|
||||
# define VTKMDIY_MPI_NO_EXPORT_DEFINE
|
||||
# else
|
||||
# define VTKMDIY_MPI_EXPORT_DEFINE __declspec(dllexport)
|
||||
# define VTKMDIY_MPI_IMPORT_DEFINE __declspec(dllimport)
|
||||
# define VTKMDIY_MPI_NO_EXPORT_DEFINE
|
||||
# endif
|
||||
#else
|
||||
# define VTKMDIY_MPI_EXPORT_DEFINE __attribute__((visibility("default")))
|
||||
# define VTKMDIY_MPI_IMPORT_DEFINE __attribute__((visibility("default")))
|
||||
# define VTKMDIY_MPI_NO_EXPORT_DEFINE __attribute__((visibility("hidden")))
|
||||
#endif
|
||||
|
||||
#ifndef VTKMDIY_MPI_EXPORT
|
||||
# if !defined(VTKMDIY_MPI_AS_LIB)
|
||||
# define VTKMDIY_MPI_EXPORT
|
||||
# define VTKMDIY_MPI_EXPORT_FUNCTION inline
|
||||
# else
|
||||
# if defined(VTKMDIY_HAS_MPI)
|
||||
/* We are building this library */
|
||||
# define VTKMDIY_MPI_EXPORT VTKMDIY_MPI_EXPORT_DEFINE
|
||||
# else
|
||||
/* We are using this library */
|
||||
# define VTKMDIY_MPI_EXPORT VTKMDIY_MPI_IMPORT_DEFINE
|
||||
# endif
|
||||
# define VTKMDIY_MPI_EXPORT_FUNCTION VTKMDIY_MPI_EXPORT
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef VTKMDIY_MPI_EXPORT_FUNCTION
|
||||
#error "VTKMDIY_MPI_EXPORT_FUNCTION not defined"
|
||||
#endif
|
||||
|
||||
#ifndef VTKMDIY_MPI_NO_EXPORT
|
||||
# define VTKMDIY_MPI_NO_EXPORT VTKMDIY_MPI_NO_EXPORT_DEFINE
|
||||
#endif
|
||||
|
||||
#endif // VTKMDIY_MPI_EXPORT_H
|
62
vtkm/thirdparty/diy/vtkmdiy/include/vtkmdiy/mpi/environment.cpp
vendored
Normal file
62
vtkm/thirdparty/diy/vtkmdiy/include/vtkmdiy/mpi/environment.cpp
vendored
Normal file
@ -0,0 +1,62 @@
|
||||
#ifdef VTKMDIY_MPI_AS_LIB
|
||||
#include "environment.hpp"
|
||||
#endif
|
||||
|
||||
bool diy::mpi::environment::initialized()
|
||||
{
|
||||
#if VTKMDIY_HAS_MPI
|
||||
int flag;
|
||||
MPI_Initialized(&flag);
|
||||
return flag != 0;
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
diy::mpi::environment::environment()
|
||||
{
|
||||
#if VTKMDIY_HAS_MPI
|
||||
int argc = 0; char** argv = nullptr;
|
||||
MPI_Init_thread(&argc, &argv, MPI_THREAD_FUNNELED, &provided_threading);
|
||||
#else
|
||||
provided_threading = MPI_THREAD_FUNNELED;
|
||||
#endif
|
||||
}
|
||||
|
||||
diy::mpi::environment::environment(int requested_threading)
|
||||
{
|
||||
#if VTKMDIY_HAS_MPI
|
||||
int argc = 0; char** argv = nullptr;
|
||||
MPI_Init_thread(&argc, &argv, requested_threading, &provided_threading);
|
||||
#else
|
||||
provided_threading = requested_threading;
|
||||
#endif
|
||||
}
|
||||
|
||||
diy::mpi::environment::environment(int argc, char* argv[])
|
||||
{
|
||||
#if VTKMDIY_HAS_MPI
|
||||
MPI_Init_thread(&argc, &argv, MPI_THREAD_FUNNELED, &provided_threading);
|
||||
#else
|
||||
(void) argc; (void) argv;
|
||||
provided_threading = MPI_THREAD_FUNNELED;
|
||||
#endif
|
||||
}
|
||||
|
||||
diy::mpi::environment::environment(int argc, char* argv[], int requested_threading)
|
||||
{
|
||||
#if VTKMDIY_HAS_MPI
|
||||
MPI_Init_thread(&argc, &argv, requested_threading, &provided_threading);
|
||||
#else
|
||||
(void) argc; (void) argv;
|
||||
provided_threading = requested_threading;
|
||||
#endif
|
||||
}
|
||||
|
||||
diy::mpi::environment::
|
||||
~environment()
|
||||
{
|
||||
#if VTKMDIY_HAS_MPI
|
||||
MPI_Finalize();
|
||||
#endif
|
||||
}
|
35
vtkm/thirdparty/diy/vtkmdiy/include/vtkmdiy/mpi/environment.hpp
vendored
Normal file
35
vtkm/thirdparty/diy/vtkmdiy/include/vtkmdiy/mpi/environment.hpp
vendored
Normal file
@ -0,0 +1,35 @@
|
||||
#ifndef VTKMDIY_MPI_ENVIRONMENT_HPP
|
||||
#define VTKMDIY_MPI_ENVIRONMENT_HPP
|
||||
|
||||
#include "config.hpp"
|
||||
|
||||
namespace diy
|
||||
{
|
||||
namespace mpi
|
||||
{
|
||||
|
||||
//! \ingroup MPI
|
||||
struct environment
|
||||
{
|
||||
VTKMDIY_MPI_EXPORT_FUNCTION static bool initialized();
|
||||
|
||||
VTKMDIY_MPI_EXPORT_FUNCTION environment();
|
||||
VTKMDIY_MPI_EXPORT_FUNCTION environment(int requested_threading);
|
||||
VTKMDIY_MPI_EXPORT_FUNCTION environment(int argc, char* argv[]);
|
||||
VTKMDIY_MPI_EXPORT_FUNCTION environment(int argc, char* argv[], int requested_threading);
|
||||
|
||||
VTKMDIY_MPI_EXPORT_FUNCTION ~environment();
|
||||
|
||||
int threading() const { return provided_threading; }
|
||||
|
||||
int provided_threading;
|
||||
};
|
||||
|
||||
}
|
||||
} // diy::mpi
|
||||
|
||||
#ifndef VTKMDIY_MPI_AS_LIB
|
||||
#include "environment.cpp"
|
||||
#endif
|
||||
|
||||
#endif // VTKMDIY_MPI_ENVIRONMENT_HPP
|
222
vtkm/thirdparty/diy/vtkmdiy/include/vtkmdiy/mpi/io.cpp
vendored
Normal file
222
vtkm/thirdparty/diy/vtkmdiy/include/vtkmdiy/mpi/io.cpp
vendored
Normal file
@ -0,0 +1,222 @@
|
||||
#ifdef VTKMDIY_MPI_AS_LIB
|
||||
#include "io.hpp"
|
||||
#endif
|
||||
|
||||
#include "status.hpp"
|
||||
|
||||
#ifdef VTKMDIY_MPI_AS_LIB
|
||||
const int diy::mpi::io::file::rdonly = MPI_MODE_RDONLY;
|
||||
const int diy::mpi::io::file::rdwr = MPI_MODE_RDWR;
|
||||
const int diy::mpi::io::file::wronly = MPI_MODE_WRONLY;
|
||||
const int diy::mpi::io::file::create = MPI_MODE_CREATE;
|
||||
const int diy::mpi::io::file::exclusive = MPI_MODE_EXCL;
|
||||
const int diy::mpi::io::file::delete_on_close = MPI_MODE_DELETE_ON_CLOSE;
|
||||
const int diy::mpi::io::file::unique_open = MPI_MODE_UNIQUE_OPEN;
|
||||
const int diy::mpi::io::file::sequential = MPI_MODE_SEQUENTIAL;
|
||||
const int diy::mpi::io::file::append = MPI_MODE_APPEND;
|
||||
#endif
|
||||
|
||||
diy::mpi::io::file::
|
||||
file(const communicator& comm__, const std::string& filename, int mode)
|
||||
: comm_(comm__)
|
||||
{
|
||||
#if VTKMDIY_HAS_MPI
|
||||
int ret = MPI_File_open(diy::mpi::mpi_cast(comm__.handle()), const_cast<char*>(filename.c_str()), mode, MPI_INFO_NULL, &diy::mpi::mpi_cast(fh));
|
||||
if (ret)
|
||||
throw std::runtime_error("DIY cannot open file: " + filename);
|
||||
#else
|
||||
(void)comm__; (void)filename; (void)mode;
|
||||
VTKMDIY_UNSUPPORTED_MPI_CALL(MPI_File_open);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
diy::mpi::io::file::
|
||||
close()
|
||||
{
|
||||
#if VTKMDIY_HAS_MPI
|
||||
if (diy::mpi::mpi_cast(fh) != MPI_FILE_NULL)
|
||||
MPI_File_close(&diy::mpi::mpi_cast(fh));
|
||||
#endif
|
||||
}
|
||||
|
||||
diy::mpi::io::offset
|
||||
diy::mpi::io::file::
|
||||
size() const
|
||||
{
|
||||
#if VTKMDIY_HAS_MPI
|
||||
MPI_Offset sz;
|
||||
MPI_File_get_size(diy::mpi::mpi_cast(fh), &sz);
|
||||
return static_cast<offset>(sz);
|
||||
#else
|
||||
VTKMDIY_UNSUPPORTED_MPI_CALL(MPI_File_get_size);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
diy::mpi::io::file::
|
||||
resize(diy::mpi::io::offset size_)
|
||||
{
|
||||
#if VTKMDIY_HAS_MPI
|
||||
MPI_File_set_size(diy::mpi::mpi_cast(fh), static_cast<MPI_Offset>(size_));
|
||||
#else
|
||||
(void)size_;
|
||||
VTKMDIY_UNSUPPORTED_MPI_CALL(MPI_File_set_size);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
diy::mpi::io::file::
|
||||
read_at(offset o, char* buffer, size_t size_)
|
||||
{
|
||||
#if VTKMDIY_HAS_MPI
|
||||
status s;
|
||||
MPI_File_read_at(diy::mpi::mpi_cast(fh), static_cast<MPI_Offset>(o), buffer, static_cast<int>(size_), MPI_BYTE, &diy::mpi::mpi_cast(s.handle));
|
||||
#else
|
||||
(void)o; (void)buffer; (void)size_;
|
||||
VTKMDIY_UNSUPPORTED_MPI_CALL(MPI_File_read_at);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
diy::mpi::io::file::
|
||||
read_at_all(offset o, char* buffer, size_t size_)
|
||||
{
|
||||
#if VTKMDIY_HAS_MPI
|
||||
status s;
|
||||
MPI_File_read_at_all(diy::mpi::mpi_cast(fh), static_cast<MPI_Offset>(o), buffer, static_cast<int>(size_), MPI_BYTE, &diy::mpi::mpi_cast(s.handle));
|
||||
#else
|
||||
(void)o; (void)buffer; (void)size_;
|
||||
VTKMDIY_UNSUPPORTED_MPI_CALL(MPI_File_read_at_all);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
diy::mpi::io::file::
|
||||
write_at(offset o, const char* buffer, size_t size_)
|
||||
{
|
||||
#if VTKMDIY_HAS_MPI
|
||||
status s;
|
||||
MPI_File_write_at(diy::mpi::mpi_cast(fh), static_cast<MPI_Offset>(o), (void *)buffer, static_cast<int>(size_), MPI_BYTE, &diy::mpi::mpi_cast(s.handle));
|
||||
#else
|
||||
(void)o; (void)buffer; (void)size_;
|
||||
VTKMDIY_UNSUPPORTED_MPI_CALL(MPI_File_write_at);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
diy::mpi::io::file::
|
||||
write_at_all(offset o, const char* buffer, size_t size_)
|
||||
{
|
||||
#if VTKMDIY_HAS_MPI
|
||||
status s;
|
||||
MPI_File_write_at_all(diy::mpi::mpi_cast(fh), static_cast<MPI_Offset>(o), (void *)buffer, static_cast<int>(size_), MPI_BYTE, &diy::mpi::mpi_cast(s.handle));
|
||||
#else
|
||||
(void)o; (void)buffer; (void)size_;
|
||||
VTKMDIY_UNSUPPORTED_MPI_CALL(MPI_File_write_at_all);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
diy::mpi::io::file::
|
||||
read_bov(const DiscreteBounds& bounds, int ndims, const int dims[], char* buffer, size_t offset, const datatype& dt, bool collective, int chunk)
|
||||
{
|
||||
#if VTKMDIY_HAS_MPI
|
||||
int total = 1;
|
||||
std::vector<int> subsizes;
|
||||
for (unsigned i = 0; i < static_cast<unsigned>(ndims); ++i)
|
||||
{
|
||||
subsizes.push_back(bounds.max[i] - bounds.min[i] + 1);
|
||||
total *= subsizes.back();
|
||||
}
|
||||
|
||||
MPI_Datatype T_type;
|
||||
if (chunk == 1)
|
||||
{
|
||||
T_type = diy::mpi::mpi_cast(dt.handle);
|
||||
}
|
||||
else
|
||||
{
|
||||
// create an MPI struct of size chunk to read the data in those chunks
|
||||
// (this allows to work around MPI-IO weirdness where crucial quantities
|
||||
// are ints, which are too narrow of a type)
|
||||
int array_of_blocklengths[] = { chunk };
|
||||
MPI_Aint array_of_displacements[] = { 0 };
|
||||
MPI_Datatype array_of_types[] = { diy::mpi::mpi_cast(dt.handle) };
|
||||
MPI_Type_create_struct(1, array_of_blocklengths, array_of_displacements, array_of_types, &T_type);
|
||||
MPI_Type_commit(&T_type);
|
||||
}
|
||||
|
||||
MPI_Datatype fileblk;
|
||||
MPI_Type_create_subarray(ndims, dims, subsizes.data(), (int*) &bounds.min[0], MPI_ORDER_C, T_type, &fileblk);
|
||||
MPI_Type_commit(&fileblk);
|
||||
|
||||
MPI_File_set_view(diy::mpi::mpi_cast(fh), static_cast<MPI_Offset>(offset), T_type, fileblk, (char*)"native", MPI_INFO_NULL);
|
||||
|
||||
mpi::status s;
|
||||
if (!collective)
|
||||
MPI_File_read(diy::mpi::mpi_cast(fh), buffer, total, T_type, &mpi_cast(s.handle));
|
||||
else
|
||||
MPI_File_read_all(diy::mpi::mpi_cast(fh), buffer, total, T_type, &mpi_cast(s.handle));
|
||||
|
||||
if (chunk != 1)
|
||||
MPI_Type_free(&T_type);
|
||||
MPI_Type_free(&fileblk);
|
||||
#else
|
||||
(void) bounds; (void) ndims; (void) dims, (void) buffer; (void) offset, (void) dt, (void) collective; (void) chunk;
|
||||
VTKMDIY_UNSUPPORTED_MPI_CALL(diy::mpi::io::file::read_bov);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
diy::mpi::io::file::
|
||||
write_bov(const DiscreteBounds& bounds, const DiscreteBounds& core, int ndims, const int dims[], const char* buffer, size_t offset, const datatype& dt, bool collective, int chunk)
|
||||
{
|
||||
#if VTKMDIY_HAS_MPI
|
||||
std::vector<int> subsizes;
|
||||
std::vector<int> buffer_shape, buffer_start;
|
||||
for (unsigned i = 0; i < static_cast<unsigned>(ndims); ++i)
|
||||
{
|
||||
buffer_shape.push_back(bounds.max[i] - bounds.min[i] + 1);
|
||||
buffer_start.push_back(core.min[i] - bounds.min[i]);
|
||||
subsizes.push_back(core.max[i] - core.min[i] + 1);
|
||||
}
|
||||
|
||||
MPI_Datatype T_type;
|
||||
if (chunk == 1)
|
||||
{
|
||||
T_type = diy::mpi::mpi_cast(dt.handle);
|
||||
}
|
||||
else
|
||||
{
|
||||
// assume T is a binary block and create an MPI struct of appropriate size
|
||||
int array_of_blocklengths[] = { chunk };
|
||||
MPI_Aint array_of_displacements[] = { 0 };
|
||||
MPI_Datatype array_of_types[] = { diy::mpi::mpi_cast(dt.handle) };
|
||||
MPI_Type_create_struct(1, array_of_blocklengths, array_of_displacements, array_of_types, &T_type);
|
||||
MPI_Type_commit(&T_type);
|
||||
}
|
||||
|
||||
MPI_Datatype fileblk, subbuffer;
|
||||
MPI_Type_create_subarray(ndims, dims, subsizes.data(), (int*) &core.min[0], MPI_ORDER_C, T_type, &fileblk);
|
||||
MPI_Type_create_subarray(ndims, buffer_shape.data(), subsizes.data(), buffer_start.data(), MPI_ORDER_C, T_type, &subbuffer);
|
||||
MPI_Type_commit(&fileblk);
|
||||
MPI_Type_commit(&subbuffer);
|
||||
|
||||
MPI_File_set_view(diy::mpi::mpi_cast(fh), static_cast<MPI_Offset>(offset), T_type, fileblk, (char*)"native", MPI_INFO_NULL);
|
||||
|
||||
mpi::status s;
|
||||
if (!collective)
|
||||
MPI_File_write(diy::mpi::mpi_cast(fh), (void*)buffer, 1, subbuffer, &mpi_cast(s.handle));
|
||||
else
|
||||
MPI_File_write_all(diy::mpi::mpi_cast(fh), (void*)buffer, 1, subbuffer, &mpi_cast(s.handle));
|
||||
|
||||
if (chunk != 1)
|
||||
MPI_Type_free(&T_type);
|
||||
MPI_Type_free(&fileblk);
|
||||
MPI_Type_free(&subbuffer);
|
||||
#else
|
||||
(void) bounds; (void) core, (void) ndims; (void) dims, (void) buffer; (void) offset, (void) dt, (void) collective; (void) chunk;
|
||||
VTKMDIY_UNSUPPORTED_MPI_CALL(diy::mpi::io::file::write_bov);
|
||||
#endif
|
||||
}
|
@ -1,139 +1,82 @@
|
||||
#ifndef VTKMDIY_MPI_IO_HPP
|
||||
#define VTKMDIY_MPI_IO_HPP
|
||||
|
||||
#include "../constants.h"
|
||||
#include "config.hpp"
|
||||
#include "communicator.hpp"
|
||||
|
||||
#include <vtkmdiy/types.hpp>
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace diy
|
||||
{
|
||||
namespace mpi
|
||||
{
|
||||
|
||||
namespace io
|
||||
{
|
||||
typedef MPI_Offset offset;
|
||||
#if !defined(VTKMDIY_MPI_AS_LIB) && VTKMDIY_HAS_MPI
|
||||
using offset = MPI_Offset;
|
||||
#else
|
||||
using offset = long long;
|
||||
#endif
|
||||
|
||||
//! Wraps MPI file IO. \ingroup MPI
|
||||
class file
|
||||
{
|
||||
public:
|
||||
enum
|
||||
{
|
||||
rdonly = MPI_MODE_RDONLY,
|
||||
rdwr = MPI_MODE_RDWR,
|
||||
wronly = MPI_MODE_WRONLY,
|
||||
create = MPI_MODE_CREATE,
|
||||
exclusive = MPI_MODE_EXCL,
|
||||
delete_on_close = MPI_MODE_DELETE_ON_CLOSE,
|
||||
unique_open = MPI_MODE_UNIQUE_OPEN,
|
||||
sequential = MPI_MODE_SEQUENTIAL,
|
||||
append = MPI_MODE_APPEND
|
||||
};
|
||||
#ifndef VTKMDIY_MPI_AS_LIB
|
||||
static constexpr int rdonly = MPI_MODE_RDONLY;
|
||||
static constexpr int rdwr = MPI_MODE_RDWR;
|
||||
static constexpr int wronly = MPI_MODE_WRONLY;
|
||||
static constexpr int create = MPI_MODE_CREATE;
|
||||
static constexpr int exclusive = MPI_MODE_EXCL;
|
||||
static constexpr int delete_on_close = MPI_MODE_DELETE_ON_CLOSE;
|
||||
static constexpr int unique_open = MPI_MODE_UNIQUE_OPEN;
|
||||
static constexpr int sequential = MPI_MODE_SEQUENTIAL;
|
||||
static constexpr int append = MPI_MODE_APPEND;
|
||||
#else
|
||||
static const int rdonly, rdwr, wronly, create, exclusive, delete_on_close, unique_open, sequential, append;
|
||||
#endif
|
||||
|
||||
public:
|
||||
inline file(const communicator& comm, const std::string& filename, int mode);
|
||||
~file() { close(); }
|
||||
inline void close();
|
||||
VTKMDIY_MPI_EXPORT_FUNCTION file(const communicator& comm, const std::string& filename, int mode);
|
||||
~file() { close(); }
|
||||
VTKMDIY_MPI_EXPORT_FUNCTION void close();
|
||||
|
||||
inline offset size() const;
|
||||
inline void resize(offset size);
|
||||
VTKMDIY_MPI_EXPORT_FUNCTION offset size() const;
|
||||
VTKMDIY_MPI_EXPORT_FUNCTION void resize(offset size);
|
||||
|
||||
inline void read_at(offset o, char* buffer, size_t size);
|
||||
inline void read_at_all(offset o, char* buffer, size_t size);
|
||||
inline void write_at(offset o, const char* buffer, size_t size);
|
||||
inline void write_at_all(offset o, const char* buffer, size_t size);
|
||||
VTKMDIY_MPI_EXPORT_FUNCTION void read_at(offset o, char* buffer, size_t size);
|
||||
VTKMDIY_MPI_EXPORT_FUNCTION void read_at_all(offset o, char* buffer, size_t size);
|
||||
VTKMDIY_MPI_EXPORT_FUNCTION void write_at(offset o, const char* buffer, size_t size);
|
||||
VTKMDIY_MPI_EXPORT_FUNCTION void write_at_all(offset o, const char* buffer, size_t size);
|
||||
|
||||
template<class T>
|
||||
inline void read_at(offset o, std::vector<T>& data);
|
||||
inline void read_at(offset o, std::vector<T>& data);
|
||||
|
||||
template<class T>
|
||||
inline void read_at_all(offset o, std::vector<T>& data);
|
||||
inline void read_at_all(offset o, std::vector<T>& data);
|
||||
|
||||
template<class T>
|
||||
inline void write_at(offset o, const std::vector<T>& data);
|
||||
inline void write_at(offset o, const std::vector<T>& data);
|
||||
|
||||
template<class T>
|
||||
inline void write_at_all(offset o, const std::vector<T>& data);
|
||||
inline void write_at_all(offset o, const std::vector<T>& data);
|
||||
|
||||
const communicator&
|
||||
comm() const { return comm_; }
|
||||
VTKMDIY_MPI_EXPORT_FUNCTION void read_bov(const DiscreteBounds& bounds, int ndims, const int dims[], char* buffer, size_t offset, const datatype& dt, bool collective, int chunk);
|
||||
VTKMDIY_MPI_EXPORT_FUNCTION void write_bov(const DiscreteBounds& bounds, const DiscreteBounds& core, int ndims, const int dims[], const char* buffer, size_t offset, const datatype& dt, bool collective, int chunk);
|
||||
|
||||
MPI_File& handle() { return fh; }
|
||||
const communicator& comm() const { return comm_; }
|
||||
|
||||
private:
|
||||
const communicator& comm_;
|
||||
MPI_File fh;
|
||||
communicator comm_;
|
||||
protected: // mark protected to avoid the "unused private field" warning
|
||||
DIY_MPI_File fh;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
diy::mpi::io::file::
|
||||
file(const communicator& comm__, const std::string& filename, int mode)
|
||||
: comm_(comm__)
|
||||
{
|
||||
#ifndef VTKM_DIY_NO_MPI
|
||||
int ret = MPI_File_open(comm__, const_cast<char*>(filename.c_str()), mode, MPI_INFO_NULL, &fh);
|
||||
if (ret)
|
||||
throw std::runtime_error("DIY cannot open file: " + filename);
|
||||
#else
|
||||
DIY_UNUSED(comm__);
|
||||
DIY_UNUSED(filename);
|
||||
DIY_UNUSED(mode);
|
||||
DIY_UNSUPPORTED_MPI_CALL(MPI_File_open);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
diy::mpi::io::file::
|
||||
close()
|
||||
{
|
||||
#ifndef VTKM_DIY_NO_MPI
|
||||
if (fh != MPI_FILE_NULL)
|
||||
MPI_File_close(&fh);
|
||||
#endif
|
||||
}
|
||||
|
||||
diy::mpi::io::offset
|
||||
diy::mpi::io::file::
|
||||
size() const
|
||||
{
|
||||
#ifndef VTKM_DIY_NO_MPI
|
||||
offset sz;
|
||||
MPI_File_get_size(fh, &sz);
|
||||
return sz;
|
||||
#else
|
||||
DIY_UNSUPPORTED_MPI_CALL(MPI_File_get_size);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
diy::mpi::io::file::
|
||||
resize(diy::mpi::io::offset size_)
|
||||
{
|
||||
#ifndef VTKM_DIY_NO_MPI
|
||||
MPI_File_set_size(fh, size_);
|
||||
#else
|
||||
DIY_UNUSED(size_);
|
||||
DIY_UNSUPPORTED_MPI_CALL(MPI_File_set_size);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
diy::mpi::io::file::
|
||||
read_at(offset o, char* buffer, size_t size_)
|
||||
{
|
||||
#ifndef VTKM_DIY_NO_MPI
|
||||
status s;
|
||||
MPI_File_read_at(fh, o, buffer, static_cast<int>(size_), detail::get_mpi_datatype<char>(), &s.s);
|
||||
#else
|
||||
DIY_UNUSED(o);
|
||||
DIY_UNUSED(buffer);
|
||||
DIY_UNUSED(size_);
|
||||
DIY_UNSUPPORTED_MPI_CALL(MPI_File_read_at);
|
||||
#endif
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void
|
||||
@ -143,21 +86,6 @@ read_at(offset o, std::vector<T>& data)
|
||||
read_at(o, &data[0], data.size()*sizeof(T));
|
||||
}
|
||||
|
||||
void
|
||||
diy::mpi::io::file::
|
||||
read_at_all(offset o, char* buffer, size_t size_)
|
||||
{
|
||||
#ifndef VTKM_DIY_NO_MPI
|
||||
status s;
|
||||
MPI_File_read_at_all(fh, o, buffer, static_cast<int>(size_), detail::get_mpi_datatype<char>(), &s.s);
|
||||
#else
|
||||
DIY_UNUSED(o);
|
||||
DIY_UNUSED(buffer);
|
||||
DIY_UNUSED(size_);
|
||||
DIY_UNSUPPORTED_MPI_CALL(MPI_File_read_at_all);
|
||||
#endif
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void
|
||||
diy::mpi::io::file::
|
||||
@ -166,21 +94,6 @@ read_at_all(offset o, std::vector<T>& data)
|
||||
read_at_all(o, (char*) &data[0], data.size()*sizeof(T));
|
||||
}
|
||||
|
||||
void
|
||||
diy::mpi::io::file::
|
||||
write_at(offset o, const char* buffer, size_t size_)
|
||||
{
|
||||
#ifndef VTKM_DIY_NO_MPI
|
||||
status s;
|
||||
MPI_File_write_at(fh, o, (void *)buffer, static_cast<int>(size_), detail::get_mpi_datatype<char>(), &s.s);
|
||||
#else
|
||||
DIY_UNUSED(o);
|
||||
DIY_UNUSED(buffer);
|
||||
DIY_UNUSED(size_);
|
||||
DIY_UNSUPPORTED_MPI_CALL(MPI_File_write_at);
|
||||
#endif
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void
|
||||
diy::mpi::io::file::
|
||||
@ -189,21 +102,6 @@ write_at(offset o, const std::vector<T>& data)
|
||||
write_at(o, (const char*) &data[0], data.size()*sizeof(T));
|
||||
}
|
||||
|
||||
void
|
||||
diy::mpi::io::file::
|
||||
write_at_all(offset o, const char* buffer, size_t size_)
|
||||
{
|
||||
#ifndef VTKM_DIY_NO_MPI
|
||||
status s;
|
||||
MPI_File_write_at_all(fh, o, (void *)buffer, static_cast<int>(size_), detail::get_mpi_datatype<char>(), &s.s);
|
||||
#else
|
||||
DIY_UNUSED(o);
|
||||
DIY_UNUSED(buffer);
|
||||
DIY_UNUSED(size_);
|
||||
DIY_UNSUPPORTED_MPI_CALL(MPI_File_write_at_all);
|
||||
#endif
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void
|
||||
diy::mpi::io::file::
|
||||
@ -212,4 +110,11 @@ write_at_all(offset o, const std::vector<T>& data)
|
||||
write_at_all(o, &data[0], data.size()*sizeof(T));
|
||||
}
|
||||
|
||||
}
|
||||
} // diy::mpi::io
|
||||
|
||||
#ifndef VTKMDIY_MPI_AS_LIB
|
||||
#include "io.cpp"
|
||||
#endif
|
||||
|
||||
#endif // VTKMDIY_MPI_IO_HPP
|
||||
|
34
vtkm/thirdparty/diy/vtkmdiy/include/vtkmdiy/mpi/mpi_cast.hpp
vendored
Normal file
34
vtkm/thirdparty/diy/vtkmdiy/include/vtkmdiy/mpi/mpi_cast.hpp
vendored
Normal file
@ -0,0 +1,34 @@
|
||||
#ifndef VTKMDIY_MPI_MPICAST_HPP
|
||||
#define VTKMDIY_MPI_MPICAST_HPP
|
||||
|
||||
/// This header provides convinience functions to cast from diy's type erased MPI objects
|
||||
/// to thier correct types.
|
||||
|
||||
#ifndef VTKMDIY_HAS_MPI
|
||||
# include <mpi.h>
|
||||
#endif
|
||||
|
||||
namespace diy
|
||||
{
|
||||
namespace mpi
|
||||
{
|
||||
|
||||
#define DEFINE_MPI_CAST(mpitype) \
|
||||
inline mpitype& mpi_cast(DIY_##mpitype& obj) { return *reinterpret_cast<mpitype*>(&obj); } \
|
||||
inline const mpitype& mpi_cast(const DIY_##mpitype& obj) { return *reinterpret_cast<const mpitype*>(&obj); } \
|
||||
inline DIY_##mpitype make_DIY_##mpitype(const mpitype& obj) { DIY_##mpitype ret; mpi_cast(ret) = obj; return ret; }
|
||||
|
||||
DEFINE_MPI_CAST(MPI_Comm)
|
||||
DEFINE_MPI_CAST(MPI_Datatype)
|
||||
DEFINE_MPI_CAST(MPI_Status)
|
||||
DEFINE_MPI_CAST(MPI_Request)
|
||||
DEFINE_MPI_CAST(MPI_Op)
|
||||
DEFINE_MPI_CAST(MPI_File)
|
||||
DEFINE_MPI_CAST(MPI_Win)
|
||||
|
||||
#undef DEFINE_MPI_CAST
|
||||
|
||||
}
|
||||
} // diy::mpi
|
||||
|
||||
#endif // VTKMDIY_MPI_MPICAST_HPP
|
51
vtkm/thirdparty/diy/vtkmdiy/include/vtkmdiy/mpi/mpitypes.hpp.in
vendored
Normal file
51
vtkm/thirdparty/diy/vtkmdiy/include/vtkmdiy/mpi/mpitypes.hpp.in
vendored
Normal file
@ -0,0 +1,51 @@
|
||||
#ifndef VTKMDIY_MPI_MPITYPES_H
|
||||
#define VTKMDIY_MPI_MPITYPES_H
|
||||
|
||||
#cmakedefine TYPESIZE_MPI_Comm @TYPESIZE_MPI_Comm@
|
||||
#cmakedefine TYPESIZE_MPI_Datatype @TYPESIZE_MPI_Datatype@
|
||||
#cmakedefine TYPESIZE_MPI_Status @TYPESIZE_MPI_Status@
|
||||
#cmakedefine TYPESIZE_MPI_Request @TYPESIZE_MPI_Request@
|
||||
#cmakedefine TYPESIZE_MPI_Op @TYPESIZE_MPI_Op@
|
||||
#cmakedefine TYPESIZE_MPI_File @TYPESIZE_MPI_File@
|
||||
#cmakedefine TYPESIZE_MPI_Win @TYPESIZE_MPI_Win@
|
||||
|
||||
namespace diy
|
||||
{
|
||||
namespace mpi
|
||||
{
|
||||
|
||||
#if defined(VTKMDIY_HAS_MPI)
|
||||
# define ASSERT_MPI_TYPE_SIZE(mpitype) static_assert(sizeof(mpitype) <= sizeof(DIY_##mpitype), "");
|
||||
#else
|
||||
# define ASSERT_MPI_TYPE_SIZE(mpitype)
|
||||
#endif
|
||||
|
||||
#define DEFINE_DIY_MPI_TYPE(mpitype) \
|
||||
struct DIY_##mpitype { \
|
||||
void* data[((TYPESIZE_##mpitype) + sizeof(void*) - 1)/sizeof(void*)]; \
|
||||
}; \
|
||||
ASSERT_MPI_TYPE_SIZE(mpitype)
|
||||
|
||||
DEFINE_DIY_MPI_TYPE(MPI_Comm)
|
||||
DEFINE_DIY_MPI_TYPE(MPI_Datatype)
|
||||
DEFINE_DIY_MPI_TYPE(MPI_Status)
|
||||
DEFINE_DIY_MPI_TYPE(MPI_Request)
|
||||
DEFINE_DIY_MPI_TYPE(MPI_Op)
|
||||
DEFINE_DIY_MPI_TYPE(MPI_File)
|
||||
DEFINE_DIY_MPI_TYPE(MPI_Win)
|
||||
|
||||
#undef DEFINE_DIY_MPI_TYPE
|
||||
#undef ASSERT_MPI_TYPE_SIZE
|
||||
|
||||
}
|
||||
} // diy::mpi
|
||||
|
||||
#undef TYPESIZE_MPI_Comm
|
||||
#undef TYPESIZE_MPI_Datatype
|
||||
#undef TYPESIZE_MPI_Status
|
||||
#undef TYPESIZE_MPI_Request
|
||||
#undef TYPESIZE_MPI_Op
|
||||
#undef TYPESIZE_MPI_File
|
||||
#undef TYPESIZE_MPI_Win
|
||||
|
||||
#endif // VTKMDIY_MPI_MPITYPES_H
|
@ -22,18 +22,17 @@ static const int MPI_THREAD_MULTIPLE = 3;
|
||||
/* define datatypes */
|
||||
using MPI_Datatype = size_t;
|
||||
|
||||
#define VTKM_DIY_NO_MPI_DATATYPE(cpp_type, mpi_type) \
|
||||
#define VTKMDIY_NO_MPI_DATATYPE(cpp_type, mpi_type) \
|
||||
static const MPI_Datatype mpi_type = sizeof(cpp_type);
|
||||
VTKM_DIY_NO_MPI_DATATYPE(char, MPI_BYTE);
|
||||
VTKM_DIY_NO_MPI_DATATYPE(int, MPI_INT);
|
||||
VTKM_DIY_NO_MPI_DATATYPE(unsigned, MPI_UNSIGNED);
|
||||
VTKM_DIY_NO_MPI_DATATYPE(long, MPI_LONG);
|
||||
VTKM_DIY_NO_MPI_DATATYPE(unsigned long, MPI_UNSIGNED_LONG);
|
||||
VTKM_DIY_NO_MPI_DATATYPE(long long, MPI_LONG_LONG_INT);
|
||||
VTKM_DIY_NO_MPI_DATATYPE(unsigned long long, MPI_UNSIGNED_LONG_LONG);
|
||||
VTKM_DIY_NO_MPI_DATATYPE(float, MPI_FLOAT);
|
||||
VTKM_DIY_NO_MPI_DATATYPE(double, MPI_DOUBLE);
|
||||
#endif
|
||||
VTKMDIY_NO_MPI_DATATYPE(char, MPI_BYTE);
|
||||
VTKMDIY_NO_MPI_DATATYPE(int, MPI_INT);
|
||||
VTKMDIY_NO_MPI_DATATYPE(unsigned, MPI_UNSIGNED);
|
||||
VTKMDIY_NO_MPI_DATATYPE(long, MPI_LONG);
|
||||
VTKMDIY_NO_MPI_DATATYPE(unsigned long, MPI_UNSIGNED_LONG);
|
||||
VTKMDIY_NO_MPI_DATATYPE(long long, MPI_LONG_LONG_INT);
|
||||
VTKMDIY_NO_MPI_DATATYPE(unsigned long long, MPI_UNSIGNED_LONG_LONG);
|
||||
VTKMDIY_NO_MPI_DATATYPE(float, MPI_FLOAT);
|
||||
VTKMDIY_NO_MPI_DATATYPE(double, MPI_DOUBLE);
|
||||
|
||||
/* status type */
|
||||
struct MPI_Status
|
||||
@ -48,10 +47,8 @@ struct MPI_Status
|
||||
/* define MPI_Request */
|
||||
using MPI_Request = int;
|
||||
|
||||
#ifndef DIY_UNSUPPORTED_MPI_CALL
|
||||
#define DIY_UNSUPPORTED_MPI_CALL(name) \
|
||||
throw std::runtime_error("`" #name "` not supported when VTKM_DIY_NO_MPI is defined.");
|
||||
#endif
|
||||
#define VTKMDIY_UNSUPPORTED_MPI_CALL(name) \
|
||||
throw std::runtime_error("`" #name "` not supported when VTKMDIY_HAS_MPI is false.");
|
||||
|
||||
/* define operations */
|
||||
using MPI_Op = int;
|
||||
@ -63,7 +60,7 @@ static const MPI_Op MPI_LAND = 0;
|
||||
static const MPI_Op MPI_LOR = 0;
|
||||
|
||||
/* mpi i/o stuff */
|
||||
using MPI_Offset = size_t;
|
||||
using MPI_Offset = long long;
|
||||
using MPI_File = int;
|
||||
static const MPI_File MPI_FILE_NULL = 0;
|
||||
|
||||
@ -78,7 +75,7 @@ static const int MPI_MODE_APPEND = 128;
|
||||
static const int MPI_MODE_SEQUENTIAL = 256;
|
||||
|
||||
/* define window type */
|
||||
using MPI_Win = int;
|
||||
using MPI_Win = void*;
|
||||
|
||||
/* window fence assertions */
|
||||
static const int MPI_MODE_NOSTORE = 1;
|
||||
@ -90,3 +87,5 @@ static const int MPI_MODE_NOCHECK = 16;
|
||||
/* window lock types */
|
||||
static const int MPI_LOCK_SHARED = 1;
|
||||
static const int MPI_LOCK_EXCLUSIVE = 2;
|
||||
|
||||
#endif // VTKMDIY_MPI_NO_MPI_HPP
|
||||
|
33
vtkm/thirdparty/diy/vtkmdiy/include/vtkmdiy/mpi/operations.cpp
vendored
Normal file
33
vtkm/thirdparty/diy/vtkmdiy/include/vtkmdiy/mpi/operations.cpp
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
#ifdef VTKMDIY_MPI_AS_LIB
|
||||
#include "operations.hpp"
|
||||
#endif
|
||||
|
||||
#include <functional>
|
||||
|
||||
namespace diy
|
||||
{
|
||||
namespace mpi
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
operation get_builtin_operation(BuiltinOperation id)
|
||||
{
|
||||
operation op{};
|
||||
switch(id)
|
||||
{
|
||||
case OP_MAXIMUM: op.handle = make_DIY_MPI_Op(MPI_MAX); break;
|
||||
case OP_MINIMUM: op.handle = make_DIY_MPI_Op(MPI_MIN); break;
|
||||
case OP_PLUS: op.handle = make_DIY_MPI_Op(MPI_SUM); break;
|
||||
case OP_MULTIPLIES: op.handle = make_DIY_MPI_Op(MPI_PROD); break;
|
||||
case OP_LOGICAL_AND: op.handle = make_DIY_MPI_Op(MPI_LAND); break;
|
||||
case OP_LOGICAL_OR: op.handle = make_DIY_MPI_Op(MPI_LOR); break;
|
||||
default: break;
|
||||
}
|
||||
return op;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
} // diy::mpi::detail
|
@ -1,3 +1,8 @@
|
||||
#ifndef VTKMDIY_MPI_OPERATIONS_HPP
|
||||
#define VTKMDIY_MPI_OPERATIONS_HPP
|
||||
|
||||
#include "config.hpp"
|
||||
|
||||
#include <algorithm> // for std::min/max
|
||||
#include <functional>
|
||||
|
||||
@ -7,6 +12,19 @@ namespace mpi
|
||||
{
|
||||
//! \addtogroup MPI
|
||||
//!@{
|
||||
struct operation
|
||||
{
|
||||
operation() = default;
|
||||
operation(const DIY_MPI_Op& op) : handle(op) {}
|
||||
|
||||
#ifndef VTKMDIY_MPI_AS_LIB // only available in header-only mode
|
||||
operation(const MPI_Op& op) : handle(op) {}
|
||||
operator MPI_Op() { return handle; }
|
||||
#endif
|
||||
|
||||
DIY_MPI_Op handle;
|
||||
};
|
||||
|
||||
template<class U>
|
||||
struct maximum { const U& operator()(const U& x, const U& y) const { return std::max(x,y); } };
|
||||
template<class U>
|
||||
@ -15,13 +33,32 @@ namespace mpi
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template<class T> struct mpi_op { static MPI_Op get(); };
|
||||
template<class U> struct mpi_op< maximum<U> > { static MPI_Op get() { return MPI_MAX; } };
|
||||
template<class U> struct mpi_op< minimum<U> > { static MPI_Op get() { return MPI_MIN; } };
|
||||
template<class U> struct mpi_op< std::plus<U> > { static MPI_Op get() { return MPI_SUM; } };
|
||||
template<class U> struct mpi_op< std::multiplies<U> > { static MPI_Op get() { return MPI_PROD; } };
|
||||
template<class U> struct mpi_op< std::logical_and<U> > { static MPI_Op get() { return MPI_LAND; } };
|
||||
template<class U> struct mpi_op< std::logical_or<U> > { static MPI_Op get() { return MPI_LOR; } };
|
||||
}
|
||||
enum BuiltinOperation {
|
||||
OP_MAXIMUM = 0,
|
||||
OP_MINIMUM,
|
||||
OP_PLUS,
|
||||
OP_MULTIPLIES,
|
||||
OP_LOGICAL_AND,
|
||||
OP_LOGICAL_OR
|
||||
};
|
||||
|
||||
VTKMDIY_MPI_EXPORT_FUNCTION operation get_builtin_operation(BuiltinOperation id);
|
||||
|
||||
template<class T> struct mpi_op;
|
||||
|
||||
template<class U> struct mpi_op< maximum<U> > { static operation get() { return get_builtin_operation(OP_MAXIMUM); } };
|
||||
template<class U> struct mpi_op< minimum<U> > { static operation get() { return get_builtin_operation(OP_MINIMUM); } };
|
||||
template<class U> struct mpi_op< std::plus<U> > { static operation get() { return get_builtin_operation(OP_PLUS); } };
|
||||
template<class U> struct mpi_op< std::multiplies<U> > { static operation get() { return get_builtin_operation(OP_MULTIPLIES); } };
|
||||
template<class U> struct mpi_op< std::logical_and<U> > { static operation get() { return get_builtin_operation(OP_LOGICAL_AND); } };
|
||||
template<class U> struct mpi_op< std::logical_or<U> > { static operation get() { return get_builtin_operation(OP_LOGICAL_OR); } };
|
||||
}
|
||||
|
||||
}
|
||||
} // diy::mpi
|
||||
|
||||
#ifndef VTKMDIY_MPI_AS_LIB
|
||||
#include "operations.cpp"
|
||||
#endif
|
||||
|
||||
#endif // VTKMDIY_MPI_OPERATIONS_HPP
|
||||
|
@ -1,3 +1,6 @@
|
||||
#ifndef VTKMDIY_MPI_OPTIONAL_HPP
|
||||
#define VTKMDIY_MPI_OPTIONAL_HPP
|
||||
|
||||
namespace diy
|
||||
{
|
||||
namespace mpi
|
||||
@ -53,3 +56,5 @@ operator=(const optional& o)
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
#endif // VTKMDIY_MPI_OPTIONAL_HPP
|
||||
|
96
vtkm/thirdparty/diy/vtkmdiy/include/vtkmdiy/mpi/point-to-point.cpp
vendored
Normal file
96
vtkm/thirdparty/diy/vtkmdiy/include/vtkmdiy/mpi/point-to-point.cpp
vendored
Normal file
@ -0,0 +1,96 @@
|
||||
#ifdef VTKMDIY_MPI_AS_LIB
|
||||
#include "point-to-point.hpp"
|
||||
#endif
|
||||
|
||||
namespace diy
|
||||
{
|
||||
namespace mpi
|
||||
{
|
||||
|
||||
#ifdef VTKMDIY_MPI_AS_LIB
|
||||
# ifdef _MSC_VER
|
||||
# define EXPORT_MACRO VTKMDIY_MPI_EXPORT
|
||||
# else
|
||||
# define EXPORT_MACRO
|
||||
# endif
|
||||
EXPORT_MACRO const int any_source = MPI_ANY_SOURCE;
|
||||
EXPORT_MACRO const int any_tag = MPI_ANY_TAG;
|
||||
# undef EXPORT_MACRO
|
||||
#endif
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
void send(DIY_MPI_Comm comm, int dest, int tag, const void* data, int count, const datatype& type)
|
||||
{
|
||||
#if VTKMDIY_HAS_MPI
|
||||
MPI_Send(data, count, mpi_cast(type.handle), dest, tag, mpi_cast(comm));
|
||||
#else
|
||||
(void) comm; (void) dest; (void) tag; (void) data; (void) count; (void) type;
|
||||
VTKMDIY_UNSUPPORTED_MPI_CALL(MPI_Send);
|
||||
#endif
|
||||
}
|
||||
|
||||
status probe(DIY_MPI_Comm comm, int source, int tag)
|
||||
{
|
||||
#if VTKMDIY_HAS_MPI
|
||||
status s;
|
||||
MPI_Probe(source, tag, mpi_cast(comm), &mpi_cast(s.handle));
|
||||
return s;
|
||||
#else
|
||||
(void) comm; (void) source; (void) tag;
|
||||
VTKMDIY_UNSUPPORTED_MPI_CALL(MPI_Probe);
|
||||
#endif
|
||||
}
|
||||
|
||||
status recv(DIY_MPI_Comm comm, int source, int tag, void* data, int count, const datatype& type)
|
||||
{
|
||||
#if VTKMDIY_HAS_MPI
|
||||
status s;
|
||||
MPI_Recv(data, count, mpi_cast(type.handle), source, tag, mpi_cast(comm), &mpi_cast(s.handle));
|
||||
return s;
|
||||
#else
|
||||
(void) comm; (void) source; (void) tag; (void) data; (void) count; (void) type;
|
||||
VTKMDIY_UNSUPPORTED_MPI_CALL(MPI_Recv);
|
||||
#endif
|
||||
}
|
||||
|
||||
request isend(DIY_MPI_Comm comm, int dest, int tag, const void* data, int count, const datatype& type)
|
||||
{
|
||||
#if VTKMDIY_HAS_MPI
|
||||
request r;
|
||||
MPI_Isend(data, count, mpi_cast(type.handle), dest, tag, mpi_cast(comm), &mpi_cast(r.handle));
|
||||
return r;
|
||||
#else
|
||||
(void) comm; (void) dest; (void) tag; (void) data; (void) count; (void) type;
|
||||
VTKMDIY_UNSUPPORTED_MPI_CALL(MPI_Isend);
|
||||
#endif
|
||||
}
|
||||
|
||||
request issend(DIY_MPI_Comm comm, int dest, int tag, const void* data, int count, const datatype& type)
|
||||
{
|
||||
#if VTKMDIY_HAS_MPI
|
||||
request r;
|
||||
MPI_Issend(data, count, mpi_cast(type.handle), dest, tag, mpi_cast(comm), &mpi_cast(r.handle));
|
||||
return r;
|
||||
#else
|
||||
(void) comm; (void) dest; (void) tag; (void) data; (void) count; (void) type;
|
||||
VTKMDIY_UNSUPPORTED_MPI_CALL(MPI_Issend);
|
||||
#endif
|
||||
}
|
||||
|
||||
request irecv(DIY_MPI_Comm comm, int source, int tag, void* data, int count, const datatype& type)
|
||||
{
|
||||
#if VTKMDIY_HAS_MPI
|
||||
request r;
|
||||
MPI_Irecv(data, count, mpi_cast(type.handle), source, tag, mpi_cast(comm), &mpi_cast(r.handle));
|
||||
return r;
|
||||
#else
|
||||
(void) comm; (void) source; (void) tag; (void) data; (void) count; (void) type;
|
||||
VTKMDIY_UNSUPPORTED_MPI_CALL(MPI_Irecv);
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
} // diy::mpi::detail
|
@ -1,147 +1,84 @@
|
||||
#ifndef VTKMDIY_MPI_POINT_TO_POINT_HPP
|
||||
#define VTKMDIY_MPI_POINT_TO_POINT_HPP
|
||||
|
||||
#include "config.hpp"
|
||||
#include "datatypes.hpp"
|
||||
#include "request.hpp"
|
||||
#include "status.hpp"
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace diy
|
||||
{
|
||||
namespace mpi
|
||||
{
|
||||
|
||||
#ifndef VTKMDIY_MPI_AS_LIB
|
||||
constexpr int any_source = MPI_ANY_SOURCE;
|
||||
constexpr int any_tag = MPI_ANY_TAG;
|
||||
#else
|
||||
VTKMDIY_MPI_EXPORT extern const int any_source;
|
||||
VTKMDIY_MPI_EXPORT extern const int any_tag;
|
||||
#endif
|
||||
|
||||
namespace detail
|
||||
{
|
||||
// send
|
||||
template< class T, class is_mpi_datatype_ = typename is_mpi_datatype<T>::type >
|
||||
struct send;
|
||||
VTKMDIY_MPI_EXPORT_FUNCTION void send(DIY_MPI_Comm comm, int dest, int tag, const void* data, int count, const datatype& type);
|
||||
VTKMDIY_MPI_EXPORT_FUNCTION request isend(DIY_MPI_Comm comm, int dest, int tag, const void* data, int count, const datatype& type);
|
||||
VTKMDIY_MPI_EXPORT_FUNCTION request issend(DIY_MPI_Comm comm, int dest, int tag, const void* data, int count, const datatype& type);
|
||||
VTKMDIY_MPI_EXPORT_FUNCTION status probe(DIY_MPI_Comm comm, int source, int tag);
|
||||
VTKMDIY_MPI_EXPORT_FUNCTION status recv(DIY_MPI_Comm comm, int source, int tag, void* data, int count, const datatype& type);
|
||||
VTKMDIY_MPI_EXPORT_FUNCTION request irecv(DIY_MPI_Comm comm, int source, int tag, void* data, int count, const datatype& type);
|
||||
|
||||
template<class T>
|
||||
struct send<T, true_type>
|
||||
template <class T>
|
||||
inline void send(DIY_MPI_Comm comm, int dest, int tag, const T& x)
|
||||
{
|
||||
void operator()(MPI_Comm comm, int dest, int tag, const T& x) const
|
||||
{
|
||||
#ifndef VTKM_DIY_NO_MPI
|
||||
typedef mpi_datatype<T> Datatype;
|
||||
MPI_Send((void*) Datatype::address(x),
|
||||
Datatype::count(x),
|
||||
Datatype::datatype(),
|
||||
dest, tag, comm);
|
||||
#else
|
||||
(void) comm; (void) dest; (void) tag; (void) x;
|
||||
DIY_UNSUPPORTED_MPI_CALL(MPI_Send);
|
||||
#endif
|
||||
}
|
||||
};
|
||||
static_assert(std::is_same<typename is_mpi_datatype<T>::type, true_type>::value, "is_mpi_datatype<T>::type must be true_type");
|
||||
send(comm, dest, tag, address(x), count(x), datatype_of(x));
|
||||
}
|
||||
|
||||
// recv
|
||||
template< class T, class is_mpi_datatype_ = typename is_mpi_datatype<T>::type >
|
||||
struct recv;
|
||||
|
||||
template<class T>
|
||||
struct recv<T, true_type>
|
||||
template <class T>
|
||||
status recv(DIY_MPI_Comm comm, int source, int tag, T& x)
|
||||
{
|
||||
status operator()(MPI_Comm comm, int source, int tag, T& x) const
|
||||
{
|
||||
#ifndef VTKM_DIY_NO_MPI
|
||||
typedef mpi_datatype<T> Datatype;
|
||||
status s;
|
||||
MPI_Recv((void*) Datatype::address(x),
|
||||
Datatype::count(x),
|
||||
Datatype::datatype(),
|
||||
source, tag, comm, &s.s);
|
||||
return s;
|
||||
#else
|
||||
(void) comm; (void) source; (void) tag; (void) x;
|
||||
DIY_UNSUPPORTED_MPI_CALL(MPI_Recv);
|
||||
#endif
|
||||
}
|
||||
};
|
||||
static_assert(std::is_same<typename is_mpi_datatype<T>::type, true_type>::value, "is_mpi_datatype<T>::type must be true_type");
|
||||
return recv(comm, source, tag, address(x), count(x), datatype_of(x));
|
||||
}
|
||||
|
||||
template<class U>
|
||||
struct recv<std::vector<U>, true_type>
|
||||
template <class T>
|
||||
status recv(DIY_MPI_Comm comm, int source, int tag, std::vector<T>& x)
|
||||
{
|
||||
status operator()(MPI_Comm comm, int source, int tag, std::vector<U>& x) const
|
||||
{
|
||||
#ifndef VTKM_DIY_NO_MPI
|
||||
status s;
|
||||
auto s = probe(comm, source, tag);
|
||||
x.resize(static_cast<size_t>(s.count<T>()));
|
||||
return recv(comm, source, tag, address(x), count(x), datatype_of(x));
|
||||
}
|
||||
|
||||
MPI_Probe(source, tag, comm, &s.s);
|
||||
x.resize(s.count<U>());
|
||||
MPI_Recv(&x[0], static_cast<int>(x.size()), get_mpi_datatype<U>(), source, tag, comm, &s.s);
|
||||
return s;
|
||||
#else
|
||||
(void) comm; (void) source; (void) tag; (void) x;
|
||||
DIY_UNSUPPORTED_MPI_CALL(MPI_Recv);
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
// isend
|
||||
template< class T, class is_mpi_datatype_ = typename is_mpi_datatype<T>::type >
|
||||
struct isend;
|
||||
|
||||
template<class T>
|
||||
struct isend<T, true_type>
|
||||
template <class T>
|
||||
request isend(DIY_MPI_Comm comm, int dest, int tag, const T& x)
|
||||
{
|
||||
request operator()(MPI_Comm comm, int dest, int tag, const T& x) const
|
||||
{
|
||||
#ifndef VTKM_DIY_NO_MPI
|
||||
request r;
|
||||
typedef mpi_datatype<T> Datatype;
|
||||
MPI_Isend((void*) Datatype::address(x),
|
||||
Datatype::count(x),
|
||||
Datatype::datatype(),
|
||||
dest, tag, comm, &r.r);
|
||||
return r;
|
||||
#else
|
||||
(void) comm; (void) dest; (void) tag; (void) x;
|
||||
DIY_UNSUPPORTED_MPI_CALL(MPI_Isend);
|
||||
#endif
|
||||
}
|
||||
};
|
||||
static_assert(std::is_same<typename is_mpi_datatype<T>::type, true_type>::value, "is_mpi_datatype<T>::type must be true_type");
|
||||
return isend(comm, dest, tag, address(x), count(x), datatype_of(x));
|
||||
}
|
||||
|
||||
// issend
|
||||
template< class T, class is_mpi_datatype_ = typename is_mpi_datatype<T>::type >
|
||||
struct issend;
|
||||
|
||||
template<class T>
|
||||
struct issend<T, true_type>
|
||||
template <class T>
|
||||
request issend(DIY_MPI_Comm comm, int dest, int tag, const T& x)
|
||||
{
|
||||
request operator()(MPI_Comm comm, int dest, int tag, const T& x) const
|
||||
{
|
||||
#ifndef VTKM_DIY_NO_MPI
|
||||
request r;
|
||||
typedef mpi_datatype<T> Datatype;
|
||||
MPI_Issend((void*) Datatype::address(x),
|
||||
Datatype::count(x),
|
||||
Datatype::datatype(),
|
||||
dest, tag, comm, &r.r);
|
||||
return r;
|
||||
#else
|
||||
(void) comm; (void) dest; (void) tag; (void) x;
|
||||
DIY_UNSUPPORTED_MPI_CALL(MPI_Issend);
|
||||
#endif
|
||||
}
|
||||
};
|
||||
static_assert(std::is_same<typename is_mpi_datatype<T>::type, true_type>::value, "is_mpi_datatype<T>::type must be true_type");
|
||||
return issend(comm, dest, tag, address(x), count(x), datatype_of(x));
|
||||
}
|
||||
|
||||
// irecv
|
||||
template< class T, class is_mpi_datatype_ = typename is_mpi_datatype<T>::type >
|
||||
struct irecv;
|
||||
|
||||
template<class T>
|
||||
struct irecv<T, true_type>
|
||||
template <class T>
|
||||
request irecv(DIY_MPI_Comm comm, int source, int tag, T& x)
|
||||
{
|
||||
request operator()(MPI_Comm comm, int source, int tag, T& x) const
|
||||
{
|
||||
#ifndef VTKM_DIY_NO_MPI
|
||||
request r;
|
||||
typedef mpi_datatype<T> Datatype;
|
||||
MPI_Irecv(Datatype::address(x),
|
||||
Datatype::count(x),
|
||||
Datatype::datatype(),
|
||||
source, tag, comm, &r.r);
|
||||
return r;
|
||||
#else
|
||||
(void) comm; (void) source; (void) tag; (void) x;
|
||||
DIY_UNSUPPORTED_MPI_CALL(MPI_Irecv);
|
||||
#endif
|
||||
}
|
||||
};
|
||||
}
|
||||
static_assert(std::is_same<typename is_mpi_datatype<T>::type, true_type>::value, "is_mpi_datatype<T>::type must be true_type");
|
||||
return irecv(comm, source, tag, address(x), count(x), datatype_of(x));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
} // diy::mpi::detail
|
||||
|
||||
#ifndef VTKMDIY_MPI_AS_LIB
|
||||
#include "point-to-point.cpp"
|
||||
#endif
|
||||
|
||||
#endif // VTKMDIY_MPI_POINT_TO_POINT_HPP
|
||||
|
45
vtkm/thirdparty/diy/vtkmdiy/include/vtkmdiy/mpi/request.cpp
vendored
Normal file
45
vtkm/thirdparty/diy/vtkmdiy/include/vtkmdiy/mpi/request.cpp
vendored
Normal file
@ -0,0 +1,45 @@
|
||||
#ifdef VTKMDIY_MPI_AS_LIB
|
||||
#include "request.hpp"
|
||||
#endif
|
||||
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
|
||||
#if defined(VTKMDIY_MPI_AS_LIB) && !VTKMDIY_HAS_MPI
|
||||
diy::mpi::request::request()
|
||||
{
|
||||
std::fill(std::begin(this->handle.data), std::end(this->handle.data), nullptr);
|
||||
}
|
||||
#else
|
||||
diy::mpi::request::request() = default;
|
||||
#endif
|
||||
|
||||
diy::mpi::status diy::mpi::request::wait()
|
||||
{
|
||||
#if VTKMDIY_HAS_MPI
|
||||
status s;
|
||||
MPI_Wait(&mpi_cast(handle), &mpi_cast(s.handle));
|
||||
return s;
|
||||
#else
|
||||
VTKMDIY_UNSUPPORTED_MPI_CALL(diy::mpi::request::wait);
|
||||
#endif
|
||||
}
|
||||
|
||||
diy::mpi::optional<diy::mpi::status> diy::mpi::request::test()
|
||||
{
|
||||
#if VTKMDIY_HAS_MPI
|
||||
status s;
|
||||
int flag;
|
||||
MPI_Test(&mpi_cast(handle), &flag, &mpi_cast(s.handle));
|
||||
if (flag)
|
||||
return s;
|
||||
#endif
|
||||
return optional<status>();
|
||||
}
|
||||
|
||||
void diy::mpi::request::cancel()
|
||||
{
|
||||
#if VTKMDIY_HAS_MPI
|
||||
MPI_Cancel(&mpi_cast(handle));
|
||||
#endif
|
||||
}
|
@ -1,50 +1,29 @@
|
||||
#ifndef VTKMDIY_MPI_REQUEST_HPP
|
||||
#define VTKMDIY_MPI_REQUEST_HPP
|
||||
|
||||
#include "config.hpp"
|
||||
#include "status.hpp"
|
||||
#include "optional.hpp"
|
||||
|
||||
namespace diy
|
||||
{
|
||||
namespace mpi
|
||||
{
|
||||
struct request
|
||||
{
|
||||
inline
|
||||
status wait();
|
||||
inline
|
||||
optional<status> test();
|
||||
inline
|
||||
void cancel();
|
||||
VTKMDIY_MPI_EXPORT_FUNCTION request();
|
||||
VTKMDIY_MPI_EXPORT_FUNCTION status wait();
|
||||
VTKMDIY_MPI_EXPORT_FUNCTION optional<status> test();
|
||||
VTKMDIY_MPI_EXPORT_FUNCTION void cancel();
|
||||
|
||||
MPI_Request r;
|
||||
DIY_MPI_Request handle;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
diy::mpi::status
|
||||
diy::mpi::request::wait()
|
||||
{
|
||||
#ifndef VTKM_DIY_NO_MPI
|
||||
status s;
|
||||
MPI_Wait(&r, &s.s);
|
||||
return s;
|
||||
#else
|
||||
DIY_UNSUPPORTED_MPI_CALL(diy::mpi::request::wait);
|
||||
#endif
|
||||
}
|
||||
} // diy::mpi
|
||||
|
||||
diy::mpi::optional<diy::mpi::status>
|
||||
diy::mpi::request::test()
|
||||
{
|
||||
#ifndef VTKM_DIY_NO_MPI
|
||||
status s;
|
||||
int flag;
|
||||
MPI_Test(&r, &flag, &s.s);
|
||||
if (flag)
|
||||
return s;
|
||||
#ifndef VTKMDIY_MPI_AS_LIB
|
||||
#include "request.cpp"
|
||||
#endif
|
||||
return optional<status>();
|
||||
}
|
||||
|
||||
void
|
||||
diy::mpi::request::cancel()
|
||||
{
|
||||
#ifndef VTKM_DIY_NO_MPI
|
||||
MPI_Cancel(&r);
|
||||
#endif
|
||||
}
|
||||
#endif // VTKMDIY_MPI_REQUEST_HPP
|
||||
|
30
vtkm/thirdparty/diy/vtkmdiy/include/vtkmdiy/mpi/status.cpp
vendored
Normal file
30
vtkm/thirdparty/diy/vtkmdiy/include/vtkmdiy/mpi/status.cpp
vendored
Normal file
@ -0,0 +1,30 @@
|
||||
#ifdef VTKMDIY_MPI_AS_LIB
|
||||
#include "status.hpp"
|
||||
#endif
|
||||
|
||||
int diy::mpi::status::source() const { return mpi_cast(handle).MPI_SOURCE; }
|
||||
int diy::mpi::status::tag() const { return mpi_cast(handle).MPI_TAG; }
|
||||
int diy::mpi::status::error() const { return mpi_cast(handle).MPI_ERROR; }
|
||||
|
||||
bool diy::mpi::status::cancelled() const
|
||||
{
|
||||
#if VTKMDIY_HAS_MPI
|
||||
int flag;
|
||||
MPI_Test_cancelled(&mpi_cast(handle), &flag);
|
||||
return flag;
|
||||
#else
|
||||
VTKMDIY_UNSUPPORTED_MPI_CALL(diy::mpi::status::cancelled);
|
||||
#endif
|
||||
}
|
||||
|
||||
int diy::mpi::status::count(const diy::mpi::datatype& type) const
|
||||
{
|
||||
#if VTKMDIY_HAS_MPI
|
||||
int c;
|
||||
MPI_Get_count(&mpi_cast(handle), mpi_cast(type.handle), &c);
|
||||
return c;
|
||||
#else
|
||||
(void) type;
|
||||
VTKMDIY_UNSUPPORTED_MPI_CALL(diy::mpi::status::count);
|
||||
#endif
|
||||
}
|
@ -1,49 +1,42 @@
|
||||
#ifndef VTKMDIY_MPI_STATUS_HPP
|
||||
#define VTKMDIY_MPI_STATUS_HPP
|
||||
|
||||
#include "config.hpp"
|
||||
#include "datatypes.hpp"
|
||||
|
||||
namespace diy
|
||||
{
|
||||
namespace mpi
|
||||
{
|
||||
struct status
|
||||
{
|
||||
int source() const { return s.MPI_SOURCE; }
|
||||
int tag() const { return s.MPI_TAG; }
|
||||
int error() const { return s.MPI_ERROR; }
|
||||
status() = default;
|
||||
status(const DIY_MPI_Status& s) : handle(s) {}
|
||||
|
||||
inline
|
||||
bool cancelled() const;
|
||||
#ifndef VTKMDIY_MPI_AS_LIB // only available in header-only mode
|
||||
status(const MPI_Status& s) : handle(s) {}
|
||||
operator MPI_Status() { return handle; }
|
||||
#endif
|
||||
|
||||
template<class T>
|
||||
int count() const;
|
||||
VTKMDIY_MPI_EXPORT_FUNCTION int source() const;
|
||||
VTKMDIY_MPI_EXPORT_FUNCTION int tag() const;
|
||||
VTKMDIY_MPI_EXPORT_FUNCTION int error() const;
|
||||
VTKMDIY_MPI_EXPORT_FUNCTION bool cancelled() const;
|
||||
VTKMDIY_MPI_EXPORT_FUNCTION int count(const datatype& type) const;
|
||||
|
||||
operator MPI_Status&() { return s; }
|
||||
operator const MPI_Status&() const { return s; }
|
||||
template<class T> int count() const
|
||||
{
|
||||
return this->count(detail::get_mpi_datatype<T>());
|
||||
}
|
||||
|
||||
MPI_Status s;
|
||||
DIY_MPI_Status handle;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
} // diy::mpi
|
||||
|
||||
bool
|
||||
diy::mpi::status::cancelled() const
|
||||
{
|
||||
#ifndef VTKM_DIY_NO_MPI
|
||||
int flag;
|
||||
MPI_Test_cancelled(const_cast<MPI_Status*>(&s), &flag);
|
||||
return flag;
|
||||
#else
|
||||
DIY_UNSUPPORTED_MPI_CALL(diy::mpi::status::cancelled);
|
||||
#ifndef VTKMDIY_MPI_AS_LIB
|
||||
#include "status.cpp"
|
||||
#endif
|
||||
}
|
||||
|
||||
template<class T>
|
||||
int
|
||||
diy::mpi::status::count() const
|
||||
{
|
||||
#ifndef VTKM_DIY_NO_MPI
|
||||
int c;
|
||||
MPI_Get_count(const_cast<MPI_Status*>(&s), detail::get_mpi_datatype<T>(), &c);
|
||||
return c;
|
||||
#else
|
||||
DIY_UNSUPPORTED_MPI_CALL(diy::mpi::status::count);
|
||||
#endif
|
||||
}
|
||||
#endif // VTKMDIY_MPI_STATUS_HPP
|
||||
|
208
vtkm/thirdparty/diy/vtkmdiy/include/vtkmdiy/mpi/window.cpp
vendored
Normal file
208
vtkm/thirdparty/diy/vtkmdiy/include/vtkmdiy/mpi/window.cpp
vendored
Normal file
@ -0,0 +1,208 @@
|
||||
#ifdef VTKMDIY_MPI_AS_LIB
|
||||
#include "window.hpp"
|
||||
#endif
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace diy
|
||||
{
|
||||
namespace mpi
|
||||
{
|
||||
|
||||
#ifdef VTKMDIY_MPI_AS_LIB
|
||||
# ifdef _MSC_VER
|
||||
# define EXPORT_MACRO VTKMDIY_MPI_EXPORT
|
||||
# else
|
||||
# define EXPORT_MACRO
|
||||
# endif
|
||||
EXPORT_MACRO const int nocheck = MPI_MODE_NOCHECK;
|
||||
# undef EXPORT_MACRO
|
||||
#endif
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
DIY_MPI_Win win_create(const communicator& comm, void* base, unsigned size, int disp)
|
||||
{
|
||||
#if VTKMDIY_HAS_MPI
|
||||
DIY_MPI_Win win;
|
||||
MPI_Win_create(base, size, disp, MPI_INFO_NULL, mpi_cast(comm.handle()), &mpi_cast(win));
|
||||
return win;
|
||||
#else
|
||||
(void)comm; (void)size; (void)disp;
|
||||
auto win = make_DIY_MPI_Win(base);
|
||||
return win;
|
||||
#endif
|
||||
}
|
||||
|
||||
void win_free(DIY_MPI_Win& win)
|
||||
{
|
||||
#if VTKMDIY_HAS_MPI
|
||||
MPI_Win_free(&mpi_cast(win));
|
||||
#else
|
||||
(void)win;
|
||||
#endif
|
||||
}
|
||||
|
||||
void put(const DIY_MPI_Win& win, const void* data, int count, const datatype& type, int rank, unsigned offset)
|
||||
{
|
||||
#if VTKMDIY_HAS_MPI
|
||||
MPI_Put(data, count, mpi_cast(type.handle), rank, offset, count, mpi_cast(type.handle), mpi_cast(win));
|
||||
#else
|
||||
void* buffer = mpi_cast(win);
|
||||
size_t size = mpi_cast(type.handle);
|
||||
std::copy_n(static_cast<const int8_t*>(data),
|
||||
size * static_cast<size_t>(count),
|
||||
static_cast<int8_t*>(buffer) + (offset * size));
|
||||
(void)rank;
|
||||
#endif
|
||||
}
|
||||
|
||||
void get(const DIY_MPI_Win& win, void* data, int count, const datatype& type, int rank, unsigned offset)
|
||||
{
|
||||
#if VTKMDIY_HAS_MPI
|
||||
MPI_Get(data, count, mpi_cast(type.handle), rank, offset, count, mpi_cast(type.handle), mpi_cast(win));
|
||||
#else
|
||||
const void* buffer = mpi_cast(win);
|
||||
size_t size = mpi_cast(type.handle);
|
||||
std::copy_n(static_cast<const int8_t*>(buffer) + (offset * size),
|
||||
size * static_cast<size_t>(count),
|
||||
static_cast<int8_t*>(data));
|
||||
(void)rank;
|
||||
#endif
|
||||
}
|
||||
|
||||
void fence(const DIY_MPI_Win& win, int assert)
|
||||
{
|
||||
#if VTKMDIY_HAS_MPI
|
||||
MPI_Win_fence(assert, mpi_cast(win));
|
||||
#else
|
||||
(void) win; (void) assert;
|
||||
#endif
|
||||
}
|
||||
|
||||
void lock(const DIY_MPI_Win& win, int lock_type, int rank, int assert)
|
||||
{
|
||||
#if VTKMDIY_HAS_MPI
|
||||
MPI_Win_lock(lock_type, rank, assert, mpi_cast(win));
|
||||
#else
|
||||
(void) win; (void) lock_type; (void) rank; (void) assert;
|
||||
#endif
|
||||
}
|
||||
|
||||
void unlock(const DIY_MPI_Win& win, int rank)
|
||||
{
|
||||
#if VTKMDIY_HAS_MPI
|
||||
MPI_Win_unlock(rank, mpi_cast(win));
|
||||
#else
|
||||
(void) win; (void) rank;
|
||||
#endif
|
||||
}
|
||||
|
||||
void lock_all(const DIY_MPI_Win& win, int assert)
|
||||
{
|
||||
#if VTKMDIY_HAS_MPI
|
||||
MPI_Win_lock_all(assert, mpi_cast(win));
|
||||
#else
|
||||
(void) win; (void) assert;
|
||||
#endif
|
||||
}
|
||||
|
||||
void unlock_all(const DIY_MPI_Win& win)
|
||||
{
|
||||
#if VTKMDIY_HAS_MPI
|
||||
MPI_Win_unlock_all(mpi_cast(win));
|
||||
#else
|
||||
(void) win;
|
||||
#endif
|
||||
}
|
||||
|
||||
void fetch_and_op(const DIY_MPI_Win& win,
|
||||
const void* origin, void* result, const datatype& type,
|
||||
int rank, unsigned offset,
|
||||
const operation& op)
|
||||
{
|
||||
#if VTKMDIY_HAS_MPI
|
||||
MPI_Fetch_and_op(origin, result, mpi_cast(type.handle), rank, offset, mpi_cast(op.handle), mpi_cast(win));
|
||||
#else
|
||||
(void) win; (void) origin; (void) result; (void) type; (void) rank; (void) offset; (void) op;
|
||||
VTKMDIY_UNSUPPORTED_MPI_CALL(MPI_Fetch_and_op);
|
||||
#endif
|
||||
}
|
||||
|
||||
void fetch(const DIY_MPI_Win& win, void* result, const datatype& type, int rank, unsigned offset)
|
||||
{
|
||||
#if VTKMDIY_HAS_MPI
|
||||
MPI_Fetch_and_op(nullptr, result, mpi_cast(type.handle), rank, offset, MPI_NO_OP, mpi_cast(win));
|
||||
#else
|
||||
(void) rank;
|
||||
const void* buffer = mpi_cast(win);
|
||||
size_t size = mpi_cast(type.handle);
|
||||
std::copy_n(static_cast<const int8_t*>(buffer) + (offset * size),
|
||||
size,
|
||||
static_cast<int8_t*>(result));
|
||||
#endif
|
||||
}
|
||||
|
||||
void replace(const DIY_MPI_Win& win, const void* value, const datatype& type, int rank, unsigned offset)
|
||||
{
|
||||
#if VTKMDIY_HAS_MPI
|
||||
MPI_Fetch_and_op(value, nullptr, mpi_cast(type.handle), rank, offset, MPI_REPLACE, mpi_cast(win));
|
||||
#else
|
||||
(void) rank;
|
||||
void* buffer = mpi_cast(win);
|
||||
size_t size = mpi_cast(type.handle);
|
||||
std::copy_n(static_cast<const int8_t*>(value),
|
||||
size,
|
||||
static_cast<int8_t*>(buffer) + (offset * size));
|
||||
#endif
|
||||
}
|
||||
|
||||
void sync(const DIY_MPI_Win& win)
|
||||
{
|
||||
#if VTKMDIY_HAS_MPI
|
||||
MPI_Win_sync(mpi_cast(win));
|
||||
#else
|
||||
(void) win;
|
||||
#endif
|
||||
}
|
||||
|
||||
void flush(const DIY_MPI_Win& win, int rank)
|
||||
{
|
||||
#if VTKMDIY_HAS_MPI
|
||||
MPI_Win_flush(rank, mpi_cast(win));
|
||||
#else
|
||||
(void) win; (void) rank;
|
||||
#endif
|
||||
}
|
||||
|
||||
void flush_all(const DIY_MPI_Win& win)
|
||||
{
|
||||
#if VTKMDIY_HAS_MPI
|
||||
MPI_Win_flush_all(mpi_cast(win));
|
||||
#else
|
||||
(void) win;
|
||||
#endif
|
||||
}
|
||||
|
||||
void flush_local(const DIY_MPI_Win& win, int rank)
|
||||
{
|
||||
#if VTKMDIY_HAS_MPI
|
||||
MPI_Win_flush_local(rank, mpi_cast(win));
|
||||
#else
|
||||
(void) win; (void) rank;
|
||||
#endif
|
||||
}
|
||||
|
||||
void flush_local_all(const DIY_MPI_Win& win)
|
||||
{
|
||||
#if VTKMDIY_HAS_MPI
|
||||
MPI_Win_flush_local_all(mpi_cast(win));
|
||||
#else
|
||||
(void) win;
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
} // diy::mpi::detail
|
@ -1,10 +1,89 @@
|
||||
#ifndef VTKMDIY_MPI_WINODW_HPP
|
||||
#define VTKMDIY_MPI_WINODW_HPP
|
||||
|
||||
#include "config.hpp"
|
||||
#include "communicator.hpp"
|
||||
#include "operations.hpp"
|
||||
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
|
||||
namespace diy
|
||||
{
|
||||
namespace mpi
|
||||
{
|
||||
|
||||
#ifndef VTKMDIY_MPI_AS_LIB
|
||||
constexpr int nocheck = MPI_MODE_NOCHECK;
|
||||
#else
|
||||
VTKMDIY_MPI_EXPORT extern const int nocheck;
|
||||
#endif
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
VTKMDIY_MPI_EXPORT_FUNCTION
|
||||
DIY_MPI_Win win_create(const communicator& comm, void* base, unsigned size, int disp);
|
||||
|
||||
VTKMDIY_MPI_EXPORT_FUNCTION
|
||||
void win_free(DIY_MPI_Win& win);
|
||||
|
||||
VTKMDIY_MPI_EXPORT_FUNCTION
|
||||
void put(const DIY_MPI_Win& win,
|
||||
const void* data, int count, const datatype& type,
|
||||
int rank, unsigned offset);
|
||||
|
||||
VTKMDIY_MPI_EXPORT_FUNCTION
|
||||
void get(const DIY_MPI_Win& win,
|
||||
void* data, int count, const datatype& type,
|
||||
int rank, unsigned offset);
|
||||
|
||||
VTKMDIY_MPI_EXPORT_FUNCTION
|
||||
void fence(const DIY_MPI_Win& win, int assert);
|
||||
|
||||
VTKMDIY_MPI_EXPORT_FUNCTION
|
||||
void lock(const DIY_MPI_Win& win, int lock_type, int rank, int assert);
|
||||
|
||||
VTKMDIY_MPI_EXPORT_FUNCTION
|
||||
void unlock(const DIY_MPI_Win& win, int rank);
|
||||
|
||||
VTKMDIY_MPI_EXPORT_FUNCTION
|
||||
void lock_all(const DIY_MPI_Win& win, int assert);
|
||||
|
||||
VTKMDIY_MPI_EXPORT_FUNCTION
|
||||
void unlock_all(const DIY_MPI_Win& win);
|
||||
|
||||
VTKMDIY_MPI_EXPORT_FUNCTION
|
||||
void fetch_and_op(const DIY_MPI_Win& win,
|
||||
const void* origin, void* result, const datatype& type,
|
||||
int rank, unsigned offset,
|
||||
const operation& op);
|
||||
|
||||
VTKMDIY_MPI_EXPORT_FUNCTION
|
||||
void fetch(const DIY_MPI_Win& win, void* result, const datatype& type, int rank, unsigned offset);
|
||||
|
||||
VTKMDIY_MPI_EXPORT_FUNCTION
|
||||
void replace(const DIY_MPI_Win& win,
|
||||
const void* value, const datatype& type,
|
||||
int rank, unsigned offset);
|
||||
|
||||
VTKMDIY_MPI_EXPORT_FUNCTION
|
||||
void sync(const DIY_MPI_Win& win);
|
||||
|
||||
VTKMDIY_MPI_EXPORT_FUNCTION
|
||||
void flush(const DIY_MPI_Win& win, int rank);
|
||||
|
||||
VTKMDIY_MPI_EXPORT_FUNCTION
|
||||
void flush_all(const DIY_MPI_Win& win);
|
||||
|
||||
VTKMDIY_MPI_EXPORT_FUNCTION
|
||||
void flush_local(const DIY_MPI_Win& win, int rank);
|
||||
|
||||
VTKMDIY_MPI_EXPORT_FUNCTION
|
||||
void flush_local_all(const DIY_MPI_Win& win);
|
||||
|
||||
} // detail
|
||||
|
||||
//! \ingroup MPI
|
||||
//! Simple wrapper around MPI window functions.
|
||||
template<class T>
|
||||
@ -38,7 +117,7 @@ namespace mpi
|
||||
inline void lock_all(int assert = 0);
|
||||
inline void unlock_all();
|
||||
|
||||
inline void fetch_and_op(const T* origin, T* result, int rank, unsigned offset, MPI_Op op);
|
||||
inline void fetch_and_op(const T* origin, T* result, int rank, unsigned offset, const operation& op);
|
||||
inline void fetch(T& result, int rank, unsigned offset);
|
||||
inline void replace(const T& value, int rank, unsigned offset);
|
||||
|
||||
@ -52,30 +131,25 @@ namespace mpi
|
||||
private:
|
||||
std::vector<T> buffer_;
|
||||
int rank_;
|
||||
#ifndef VTKM_DIY_NO_MPI
|
||||
MPI_Win window_;
|
||||
#endif
|
||||
DIY_MPI_Win window_;
|
||||
};
|
||||
|
||||
} // mpi
|
||||
} // diy
|
||||
|
||||
template<class T>
|
||||
diy::mpi::window<T>::
|
||||
window(const communicator& comm, unsigned size):
|
||||
window(const diy::mpi::communicator& comm, unsigned size):
|
||||
buffer_(size), rank_(comm.rank())
|
||||
{
|
||||
#ifndef VTKM_DIY_NO_MPI
|
||||
MPI_Win_create(buffer_.data(), buffer_.size()*sizeof(T), sizeof(T), MPI_INFO_NULL, comm, &window_);
|
||||
#endif
|
||||
window_ = detail::win_create(comm, buffer_.data(), static_cast<unsigned>(buffer_.size()*sizeof(T)), static_cast<int>(sizeof(T)));
|
||||
}
|
||||
|
||||
template<class T>
|
||||
diy::mpi::window<T>::
|
||||
~window()
|
||||
{
|
||||
#ifndef VTKM_DIY_NO_MPI
|
||||
MPI_Win_free(&window_);
|
||||
#endif
|
||||
detail::win_free(window_);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
@ -83,15 +157,7 @@ void
|
||||
diy::mpi::window<T>::
|
||||
put(const T& x, int rank, unsigned offset)
|
||||
{
|
||||
#ifndef VTKM_DIY_NO_MPI
|
||||
MPI_Put(address(x), count(x), datatype(x),
|
||||
rank,
|
||||
offset,
|
||||
count(x), datatype(x),
|
||||
window_);
|
||||
#else
|
||||
buffer_[offset] = x;
|
||||
#endif
|
||||
detail::put(window_, address(x), count(x), datatype_of(x), rank, offset);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
@ -99,16 +165,7 @@ void
|
||||
diy::mpi::window<T>::
|
||||
put(const std::vector<T>& x, int rank, unsigned offset)
|
||||
{
|
||||
#ifndef VTKM_DIY_NO_MPI
|
||||
MPI_Put(address(x), count(x), datatype(x),
|
||||
rank,
|
||||
offset,
|
||||
count(x), datatype(x),
|
||||
window_);
|
||||
#else
|
||||
for (size_t i = 0; i < x.size(); ++i)
|
||||
buffer_[offset + i] = x[i];
|
||||
#endif
|
||||
detail::put(window_, address(x), count(x), datatype_of(x), rank, offset);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
@ -116,15 +173,7 @@ void
|
||||
diy::mpi::window<T>::
|
||||
get(T& x, int rank, unsigned offset)
|
||||
{
|
||||
#ifndef VTKM_DIY_NO_MPI
|
||||
MPI_Get(address(x), count(x), datatype(x),
|
||||
rank,
|
||||
offset,
|
||||
count(x), datatype(x),
|
||||
window_);
|
||||
#else
|
||||
x = buffer_[offset];
|
||||
#endif
|
||||
detail::get(window_, address(x), count(x), datatype_of(x), rank, offset);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
@ -132,16 +181,7 @@ void
|
||||
diy::mpi::window<T>::
|
||||
get(std::vector<T>& x, int rank, unsigned offset)
|
||||
{
|
||||
#ifndef VTKM_DIY_NO_MPI
|
||||
MPI_Get(address(x), count(x), datatype(x),
|
||||
rank,
|
||||
offset,
|
||||
count(x), datatype(x),
|
||||
window_);
|
||||
#else
|
||||
for (size_t i = 0; i < x.size(); ++i)
|
||||
x[i] = buffer_[offset + i];
|
||||
#endif
|
||||
detail::get(window_, address(x), count(x), datatype_of(x), rank, offset);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
@ -149,9 +189,7 @@ void
|
||||
diy::mpi::window<T>::
|
||||
fence(int assert)
|
||||
{
|
||||
#ifndef VTKM_DIY_NO_MPI
|
||||
MPI_Win_fence(assert, window_);
|
||||
#endif
|
||||
detail::fence(window_, assert);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
@ -159,9 +197,7 @@ void
|
||||
diy::mpi::window<T>::
|
||||
lock(int lock_type, int rank, int assert)
|
||||
{
|
||||
#ifndef VTKM_DIY_NO_MPI
|
||||
MPI_Win_lock(lock_type, rank, assert, window_);
|
||||
#endif
|
||||
detail::lock(window_, lock_type, rank, assert);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
@ -169,9 +205,7 @@ void
|
||||
diy::mpi::window<T>::
|
||||
unlock(int rank)
|
||||
{
|
||||
#ifndef VTKM_DIY_NO_MPI
|
||||
MPI_Win_unlock(rank, window_);
|
||||
#endif
|
||||
detail::unlock(window_, rank);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
@ -179,9 +213,7 @@ void
|
||||
diy::mpi::window<T>::
|
||||
lock_all(int assert)
|
||||
{
|
||||
#ifndef VTKM_DIY_NO_MPI
|
||||
MPI_Win_lock_all(assert, window_);
|
||||
#endif
|
||||
detail::lock_all(window_, assert);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
@ -189,20 +221,15 @@ void
|
||||
diy::mpi::window<T>::
|
||||
unlock_all()
|
||||
{
|
||||
#ifndef VTKM_DIY_NO_MPI
|
||||
MPI_Win_unlock_all(window_);
|
||||
#endif
|
||||
detail::unlock_all(window_);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void
|
||||
diy::mpi::window<T>::
|
||||
fetch_and_op(const T* origin, T* result, int rank, unsigned offset, MPI_Op op)
|
||||
fetch_and_op(const T* origin, T* result, int rank, unsigned offset, const diy::mpi::operation& op)
|
||||
{
|
||||
#ifndef VTKM_DIY_NO_MPI
|
||||
MPI_Fetch_and_op(origin, result, datatype(*origin), rank, offset, op, window_);
|
||||
#else
|
||||
DIY_UNSUPPORTED_MPI_CALL(MPI_Fetch_and_op);
|
||||
#endif
|
||||
detail::fetch_and_op(window_, origin, result, datatype_of(*origin), rank, offset, op);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
@ -210,12 +237,7 @@ void
|
||||
diy::mpi::window<T>::
|
||||
fetch(T& result, int rank, unsigned offset)
|
||||
{
|
||||
#ifndef VTKM_DIY_NO_MPI
|
||||
T unused;
|
||||
fetch_and_op(&unused, &result, rank, offset, MPI_NO_OP);
|
||||
#else
|
||||
result = buffer_[offset];
|
||||
#endif
|
||||
detail::fetch(window_, &result, datatype_of(result), rank, offset);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
@ -223,12 +245,7 @@ void
|
||||
diy::mpi::window<T>::
|
||||
replace(const T& value, int rank, unsigned offset)
|
||||
{
|
||||
#ifndef VTKM_DIY_NO_MPI
|
||||
T unused;
|
||||
fetch_and_op(&value, &unused, rank, offset, MPI_REPLACE);
|
||||
#else
|
||||
buffer_[offset] = value;
|
||||
#endif
|
||||
detail::replace(window_, &value, datatype_of(value), rank, offset);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
@ -236,9 +253,7 @@ void
|
||||
diy::mpi::window<T>::
|
||||
sync()
|
||||
{
|
||||
#ifndef VTKM_DIY_NO_MPI
|
||||
MPI_Win_sync(window_);
|
||||
#endif
|
||||
detail::sync(window_);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
@ -246,9 +261,7 @@ void
|
||||
diy::mpi::window<T>::
|
||||
flush(int rank)
|
||||
{
|
||||
#ifndef VTKM_DIY_NO_MPI
|
||||
MPI_Win_flush(rank, window_);
|
||||
#endif
|
||||
detail::flush(window_, rank);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
@ -256,9 +269,7 @@ void
|
||||
diy::mpi::window<T>::
|
||||
flush_all()
|
||||
{
|
||||
#ifndef VTKM_DIY_NO_MPI
|
||||
MPI_Win_flush_all(window_);
|
||||
#endif
|
||||
detail::flush_all(window_);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
@ -266,9 +277,7 @@ void
|
||||
diy::mpi::window<T>::
|
||||
flush_local(int rank)
|
||||
{
|
||||
#ifndef VTKM_DIY_NO_MPI
|
||||
MPI_Win_flush_local(rank, window_);
|
||||
#endif
|
||||
detail::flush_local(window_, rank);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
@ -276,7 +285,11 @@ void
|
||||
diy::mpi::window<T>::
|
||||
flush_local_all()
|
||||
{
|
||||
#ifndef VTKM_DIY_NO_MPI
|
||||
MPI_Win_flush_local_all(window_);
|
||||
#endif
|
||||
detail::flush_local_all(window_);
|
||||
}
|
||||
|
||||
#ifndef VTKMDIY_MPI_AS_LIB
|
||||
#include "window.cpp"
|
||||
#endif
|
||||
|
||||
#endif // VTKMDIY_MPI_WINODW_HPP
|
||||
|
@ -18,6 +18,8 @@ namespace diy
|
||||
template<class Function, class... Args>
|
||||
explicit thread(Function&& f, Args&&... args) { f(args...); } // not ideal, since it doesn't support member functions
|
||||
|
||||
thread& operator=(thread&&) = default;
|
||||
|
||||
void join() {}
|
||||
|
||||
static unsigned hardware_concurrency() { return 1; }
|
||||
@ -31,8 +33,13 @@ namespace diy
|
||||
struct lock_guard
|
||||
{
|
||||
lock_guard(T&) {}
|
||||
void lock() {}
|
||||
void unlock() {}
|
||||
};
|
||||
|
||||
template<class T, class U>
|
||||
using concurrent_map = std::map<T,U>;
|
||||
|
||||
namespace this_thread
|
||||
{
|
||||
inline unsigned long int get_id() { return 0; }
|
||||
|
145
vtkm/thirdparty/diy/vtkmdiy/include/vtkmdiy/pick.hpp
vendored
145
vtkm/thirdparty/diy/vtkmdiy/include/vtkmdiy/pick.hpp
vendored
@ -2,63 +2,74 @@
|
||||
#define VTKMDIY_PICK_HPP
|
||||
|
||||
#include "link.hpp"
|
||||
#include "constants.h" // for DEPRECATED
|
||||
|
||||
namespace diy
|
||||
{
|
||||
template<class Bounds, class Point, class OutIter>
|
||||
void near(const RegularLink<Bounds>& link, const Point& p, float r, OutIter out,
|
||||
const Bounds& domain);
|
||||
template<class Bounds, class Point, class OutIter, class Coordinate>
|
||||
void near(const RegularLink<Bounds>& link, const Point& p, Coordinate r, OutIter out, const Bounds& domain);
|
||||
|
||||
template<class Bounds, class Point, class OutIter>
|
||||
void in(const RegularLink<Bounds>& link, const Point& p, OutIter out, const Bounds& domain);
|
||||
void in(const RegularLink<Bounds>& link, const Point& p, OutIter out, const Bounds& domain, bool core = true);
|
||||
|
||||
template<class Point, class Bounds>
|
||||
float distance(int dim, const Bounds& bounds, const Point& p);
|
||||
template<class Point, class Bounds, class Out = double>
|
||||
Out distance(const Bounds& bounds, const Point& p);
|
||||
|
||||
template<class Point, class Bounds, class Out = double>
|
||||
DEPRECATED("Use distance(const Bounds& bounds, const Point& p) instead.")
|
||||
Out distance(int dim, const Bounds& bounds, const Point& p);
|
||||
|
||||
template<class Bounds, class Out = double>
|
||||
Out distance(const Bounds& bounds1, const Bounds& bounds2);
|
||||
|
||||
template<class Bounds, class Out = double>
|
||||
DEPRECATED("Use distance(const Bounds& bounds1, const Bounds& bounds2) instead.")
|
||||
Out distance(int dim, const Bounds& bounds1, const Bounds& bounds2);
|
||||
|
||||
template<class Bounds>
|
||||
inline
|
||||
float distance(int dim, const Bounds& bounds1, const Bounds& bounds2);
|
||||
void wrap_bounds(Bounds& bounds, Direction wrap_dir, const Bounds& domain);
|
||||
|
||||
template<class Bounds>
|
||||
DEPRECATED("Use wrap_bounds(Bounds& bounds, Direction wrap_dir, const Bounds& domain) instead.")
|
||||
void wrap_bounds(Bounds& bounds, Direction wrap_dir, const Bounds& domain, int dim);
|
||||
}
|
||||
|
||||
//! Finds the neighbors within radius r of a target point.
|
||||
template<class Bounds, class Point, class OutIter>
|
||||
template<class Bounds, class Point, class OutIter, class Coordinate>
|
||||
void
|
||||
diy::
|
||||
near(const RegularLink<Bounds>& link, //!< neighbors
|
||||
const Point& p, //!< target point (must be in current block)
|
||||
float r, //!< target radius (>= 0.0)
|
||||
Coordinate r, //!< target radius (>= 0.0)
|
||||
OutIter out, //!< insert iterator for output set of neighbors
|
||||
const Bounds& domain) //!< global domain bounds
|
||||
{
|
||||
Bounds neigh_bounds; // neighbor block bounds
|
||||
Bounds neigh_bounds {0}; // neighbor block bounds
|
||||
|
||||
// for all neighbors of this block
|
||||
for (int n = 0; n < link.size(); n++)
|
||||
{
|
||||
// wrap neighbor bounds, if necessary, otherwise bounds will be unchanged
|
||||
neigh_bounds = link.bounds(n);
|
||||
wrap_bounds(neigh_bounds, link.wrap(n), domain, link.dimension());
|
||||
wrap_bounds(neigh_bounds, link.wrap(n), domain);
|
||||
|
||||
if (distance(link.dimension(), neigh_bounds, p) <= r)
|
||||
if (distance(neigh_bounds, p) <= r)
|
||||
*out++ = n;
|
||||
} // for all neighbors
|
||||
}
|
||||
|
||||
//! Find the distance between point `p` and box `bounds`.
|
||||
template<class Point, class Bounds>
|
||||
float
|
||||
template<class Point, class Bounds, class Out>
|
||||
Out
|
||||
diy::
|
||||
distance(int dim, const Bounds& bounds, const Point& p)
|
||||
distance(const Bounds& bounds, const Point& p)
|
||||
{
|
||||
float res = 0;
|
||||
for (int i = 0; i < dim; ++i)
|
||||
Out res = 0;
|
||||
for (int i = 0; i < p.size(); ++i)
|
||||
{
|
||||
// avoids all the annoying case logic by finding
|
||||
// diff = max(bounds.min[i] - p[i], 0, p[i] - bounds.max[i])
|
||||
float diff = 0, d;
|
||||
Out diff = 0, d;
|
||||
|
||||
d = bounds.min[i] - p[i];
|
||||
if (d > diff) diff = d;
|
||||
@ -70,18 +81,68 @@ distance(int dim, const Bounds& bounds, const Point& p)
|
||||
return sqrt(res);
|
||||
}
|
||||
|
||||
template<class Bounds>
|
||||
float
|
||||
// DEPRECATED
|
||||
//! Find the distance between point `p` and box `bounds`.
|
||||
template<class Point, class Bounds, class Out>
|
||||
Out
|
||||
diy::
|
||||
distance(int dim, const Bounds& bounds, const Point& p)
|
||||
{
|
||||
Out res = 0;
|
||||
for (int i = 0; i < dim; ++i)
|
||||
{
|
||||
// avoids all the annoying case logic by finding
|
||||
// diff = max(bounds.min[i] - p[i], 0, p[i] - bounds.max[i])
|
||||
Out diff = 0, d;
|
||||
|
||||
d = bounds.min[i] - p[i];
|
||||
if (d > diff) diff = d;
|
||||
d = p[i] - bounds.max[i];
|
||||
if (d > diff) diff = d;
|
||||
|
||||
res += diff*diff;
|
||||
}
|
||||
return sqrt(res);
|
||||
}
|
||||
|
||||
template<class Bounds, class Out>
|
||||
Out
|
||||
diy::
|
||||
distance(const Bounds& bounds1, const Bounds& bounds2)
|
||||
{
|
||||
Out res = 0;
|
||||
for (int i = 0; i < bounds1.min.size(); ++i) // assume min, max of both bounds have same size
|
||||
{
|
||||
Out diff = 0, d;
|
||||
|
||||
Out d1 = bounds1.max[i] - bounds2.min[i];
|
||||
Out d2 = bounds2.max[i] - bounds1.min[i];
|
||||
|
||||
if (d1 > 0 && d2 > 0)
|
||||
diff = 0;
|
||||
else if (d1 <= 0)
|
||||
diff = -d1;
|
||||
else if (d2 <= 0)
|
||||
diff = -d2;
|
||||
|
||||
res += diff*diff;
|
||||
}
|
||||
return sqrt(res);
|
||||
}
|
||||
|
||||
// DEPRECATED
|
||||
template<class Bounds, class Out>
|
||||
Out
|
||||
diy::
|
||||
distance(int dim, const Bounds& bounds1, const Bounds& bounds2)
|
||||
{
|
||||
float res = 0;
|
||||
Out res = 0;
|
||||
for (int i = 0; i < dim; ++i)
|
||||
{
|
||||
float diff = 0, d;
|
||||
Out diff = 0, d;
|
||||
|
||||
float d1 = bounds1.max[i] - bounds2.min[i];
|
||||
float d2 = bounds2.max[i] - bounds1.min[i];
|
||||
Out d1 = bounds1.max[i] - bounds2.min[i];
|
||||
Out d2 = bounds2.max[i] - bounds1.min[i];
|
||||
|
||||
if (d1 > 0 && d2 > 0)
|
||||
diff = 0;
|
||||
@ -102,22 +163,43 @@ diy::
|
||||
in(const RegularLink<Bounds>& link, //!< neighbors
|
||||
const Point& p, //!< target point
|
||||
OutIter out, //!< insert iterator for output set of neighbors
|
||||
const Bounds& domain) //!< global domain bounds
|
||||
const Bounds& domain, //!< global domain bounds
|
||||
bool core) //!< check against core (or bounds, if false)
|
||||
{
|
||||
Bounds neigh_bounds; // neighbor block bounds
|
||||
Bounds neigh_bounds {0}; // neighbor block bounds
|
||||
|
||||
// for all neighbors of this block
|
||||
for (int n = 0; n < link.size(); n++)
|
||||
{
|
||||
// wrap neighbor bounds, if necessary, otherwise bounds will be unchanged
|
||||
neigh_bounds = link.bounds(n);
|
||||
wrap_bounds(neigh_bounds, link.wrap(n), domain, link.dimension());
|
||||
if (core)
|
||||
neigh_bounds = link.core(n);
|
||||
else
|
||||
neigh_bounds = link.bounds(n);
|
||||
|
||||
if (distance(link.dimension(), neigh_bounds, p) == 0)
|
||||
// wrap neighbor bounds, if necessary, otherwise bounds will be unchanged
|
||||
wrap_bounds(neigh_bounds, link.wrap(n), domain);
|
||||
|
||||
if (distance(neigh_bounds, p) == 0)
|
||||
*out++ = n;
|
||||
} // for all neighbors
|
||||
}
|
||||
|
||||
// wraps block bounds
|
||||
// wrap dir is the wrapping direction from original block to wrapped neighbor block
|
||||
// overall domain bounds and dimensionality are also needed
|
||||
template<class Bounds>
|
||||
void
|
||||
diy::
|
||||
wrap_bounds(Bounds& bounds, Direction wrap_dir, const Bounds& domain)
|
||||
{
|
||||
for (int i = 0; i < bounds.min.size(); ++i) // assume min, max of bounds, domain have same size
|
||||
{
|
||||
bounds.min[i] += wrap_dir[i] * (domain.max[i] - domain.min[i]);
|
||||
bounds.max[i] += wrap_dir[i] * (domain.max[i] - domain.min[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// DEPRECATED
|
||||
// wraps block bounds
|
||||
// wrap dir is the wrapping direction from original block to wrapped neighbor block
|
||||
// overall domain bounds and dimensionality are also needed
|
||||
@ -133,5 +215,4 @@ wrap_bounds(Bounds& bounds, Direction wrap_dir, const Bounds& domain, int dim)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -8,6 +8,8 @@
|
||||
|
||||
#include <array>
|
||||
|
||||
#include "constants.h" // for DEPRECATED
|
||||
|
||||
namespace diy
|
||||
{
|
||||
|
||||
@ -53,7 +55,9 @@ class Point: public std::array<Coordinate_, D>
|
||||
Point& operator*=(Coordinate a) { for (unsigned i = 0; i < D; ++i) (*this)[i] *= a; return *this; }
|
||||
Point& operator/=(Coordinate a) { for (unsigned i = 0; i < D; ++i) (*this)[i] /= a; return *this; }
|
||||
|
||||
Coordinate norm() const { return (*this)*(*this); }
|
||||
DEPRECATED("Use norm2 instead")
|
||||
Coordinate norm() const { return norm2(); }
|
||||
Coordinate norm2() const { return (*this)*(*this); }
|
||||
|
||||
std::ostream& operator<<(std::ostream& out) const { out << (*this)[0]; for (unsigned i = 1; i < D; ++i) out << " " << (*this)[i]; return out; }
|
||||
std::istream& operator>>(std::istream& in);
|
||||
@ -117,4 +121,4 @@ operator>>(std::istream& in, Point<C,D>& p)
|
||||
|
||||
}
|
||||
|
||||
#endif // DIY_POINT_HPP
|
||||
#endif // VTKMDIY_POINT_HPP
|
||||
|
@ -10,29 +10,99 @@ namespace diy
|
||||
template <class T>
|
||||
struct EnqueueIterator;
|
||||
|
||||
Proxy(Master* master__, int gid__):
|
||||
using IncomingQueues = std::map<int, MemoryBuffer>;
|
||||
using OutgoingQueues = std::map<BlockID, MemoryBuffer>;
|
||||
|
||||
Proxy(Master* master__, int gid__,
|
||||
IExchangeInfo* iexchange__ = 0):
|
||||
gid_(gid__),
|
||||
master_(master__),
|
||||
incoming_(&master__->incoming(gid__)),
|
||||
outgoing_(&master__->outgoing(gid__)),
|
||||
collectives_(&master__->collectives(gid__)) {}
|
||||
iexchange_(iexchange__),
|
||||
collectives_(&master__->collectives(gid__))
|
||||
{
|
||||
fill_incoming();
|
||||
|
||||
// move outgoing_ back into proxy, in case it's a multi-foreach round
|
||||
if (!iexchange_)
|
||||
for (auto& x : master_->outgoing(gid_))
|
||||
{
|
||||
auto access = x.second.access();
|
||||
if (!access->empty())
|
||||
{
|
||||
outgoing_.emplace(x.first, access->back().move());
|
||||
access->pop_back();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// delete copy constructor to avoid coping incoming_ and outgoing_ (plus it
|
||||
// won't work otherwise because MemoryBuffer has a deleted copy
|
||||
// constructor)
|
||||
Proxy(const Proxy&) =delete;
|
||||
Proxy(Proxy&&) =default;
|
||||
Proxy& operator=(const Proxy&) =delete;
|
||||
Proxy& operator=(Proxy&&) =default;
|
||||
|
||||
~Proxy()
|
||||
{
|
||||
auto& outgoing = master_->outgoing(gid_);
|
||||
auto& incoming = master_->incoming(gid_);
|
||||
|
||||
// copy out outgoing_
|
||||
for (auto& x : outgoing_)
|
||||
{
|
||||
outgoing[x.first].access()->emplace_back(std::move(x.second));
|
||||
if (iexchange_)
|
||||
iexchange_->inc_work();
|
||||
}
|
||||
|
||||
// move incoming_ back into master, in case it's a multi-foreach round
|
||||
if (!iexchange_)
|
||||
for (auto& x : incoming_)
|
||||
incoming[x.first].access()->emplace_front(std::move(x.second));
|
||||
}
|
||||
|
||||
int gid() const { return gid_; }
|
||||
|
||||
bool fill_incoming() const
|
||||
{
|
||||
bool exists = false;
|
||||
|
||||
incoming_.clear();
|
||||
|
||||
// fill incoming_
|
||||
for (auto& x : master_->incoming(gid_))
|
||||
{
|
||||
auto access = x.second.access();
|
||||
if (!access->empty())
|
||||
{
|
||||
exists = true;
|
||||
incoming_.emplace(x.first, access->front().move());
|
||||
access->pop_front();
|
||||
if (iexchange_)
|
||||
iexchange_->dec_work();
|
||||
}
|
||||
}
|
||||
|
||||
return exists;
|
||||
}
|
||||
|
||||
//! Enqueue data whose size can be determined automatically, e.g., an STL vector.
|
||||
template<class T>
|
||||
void enqueue(const BlockID& to, //!< target block (gid,proc)
|
||||
const T& x, //!< data (eg. STL vector)
|
||||
void (*save)(BinaryBuffer&, const T&) = &::diy::save<T> //!< optional serialization function
|
||||
void (*save)(BinaryBuffer&, const T&) = &::diy::save //!< optional serialization function
|
||||
) const
|
||||
{ OutgoingQueues& out = *outgoing_; save(out[to], x); }
|
||||
{
|
||||
save(outgoing_[to], x);
|
||||
}
|
||||
|
||||
//! Enqueue data whose size is given explicitly by the user, e.g., an array.
|
||||
template<class T>
|
||||
void enqueue(const BlockID& to, //!< target block (gid,proc)
|
||||
const T* x, //!< pointer to the data (eg. address of start of vector)
|
||||
size_t n, //!< size in data elements (eg. ints)
|
||||
void (*save)(BinaryBuffer&, const T&) = &::diy::save<T> //!< optional serialization function
|
||||
void (*save)(BinaryBuffer&, const T&) = &::diy::save //!< optional serialization function
|
||||
) const;
|
||||
|
||||
//! Dequeue data whose size can be determined automatically (e.g., STL vector) and that was
|
||||
@ -41,9 +111,9 @@ namespace diy
|
||||
template<class T>
|
||||
void dequeue(int from, //!< target block gid
|
||||
T& x, //!< data (eg. STL vector)
|
||||
void (*load)(BinaryBuffer&, T&) = &::diy::load<T> //!< optional serialization function
|
||||
void (*load)(BinaryBuffer&, T&) = &::diy::load //!< optional serialization function
|
||||
) const
|
||||
{ IncomingQueues& in = *incoming_; load(in[from], x); }
|
||||
{ load(incoming_[from], x); }
|
||||
|
||||
//! Dequeue an array of data whose size is given explicitly by the user.
|
||||
//! In this case, the user needs to allocate the receive buffer prior to calling dequeue.
|
||||
@ -51,7 +121,7 @@ namespace diy
|
||||
void dequeue(int from, //!< target block gid
|
||||
T* x, //!< pointer to the data (eg. address of start of vector)
|
||||
size_t n, //!< size in data elements (eg. ints)
|
||||
void (*load)(BinaryBuffer&, T&) = &::diy::load<T> //!< optional serialization function
|
||||
void (*load)(BinaryBuffer&, T&) = &::diy::load //!< optional serialization function
|
||||
) const;
|
||||
|
||||
//! Dequeue data whose size can be determined automatically (e.g., STL vector) and that was
|
||||
@ -60,7 +130,7 @@ namespace diy
|
||||
template<class T>
|
||||
void dequeue(const BlockID& from, //!< target block (gid,proc)
|
||||
T& x, //!< data (eg. STL vector)
|
||||
void (*load)(BinaryBuffer&, T&) = &::diy::load<T> //!< optional serialization function
|
||||
void (*load)(BinaryBuffer&, T&) = &::diy::load //!< optional serialization function
|
||||
) const { dequeue(from.gid, x, load); }
|
||||
|
||||
//! Dequeue an array of data whose size is given explicitly by the user.
|
||||
@ -69,20 +139,24 @@ namespace diy
|
||||
void dequeue(const BlockID& from, //!< target block (gid,proc)
|
||||
T* x, //!< pointer to the data (eg. address of start of vector)
|
||||
size_t n, //!< size in data elements (eg. ints)
|
||||
void (*load)(BinaryBuffer&, T&) = &::diy::load<T> //!< optional serialization function
|
||||
void (*load)(BinaryBuffer&, T&) = &::diy::load //!< optional serialization function
|
||||
) const { dequeue(from.gid, x, n, load); }
|
||||
|
||||
template<class T>
|
||||
EnqueueIterator<T> enqueuer(const T& x,
|
||||
void (*save)(BinaryBuffer&, const T&) = &::diy::save<T>) const
|
||||
void (*save)(BinaryBuffer&, const T&) = &::diy::save ) const
|
||||
{ return EnqueueIterator<T>(this, x, save); }
|
||||
|
||||
IncomingQueues* incoming() const { return incoming_; }
|
||||
MemoryBuffer& incoming(int from) const { return (*incoming_)[from]; }
|
||||
IncomingQueues* incoming() const { return &incoming_; }
|
||||
MemoryBuffer& incoming(int from) const { return incoming_[from]; }
|
||||
inline void incoming(std::vector<int>& v) const; // fill v with every gid from which we have a message
|
||||
|
||||
OutgoingQueues* outgoing() const { return outgoing_; }
|
||||
MemoryBuffer& outgoing(const BlockID& to) const { return (*outgoing_)[to]; }
|
||||
OutgoingQueues* outgoing() const { return &outgoing_; }
|
||||
MemoryBuffer& outgoing(const BlockID& to) const { return outgoing_[to]; }
|
||||
|
||||
inline bool empty_incoming_queues() const;
|
||||
inline bool empty_outgoing_queues() const;
|
||||
inline bool empty_queues() const;
|
||||
|
||||
/**
|
||||
* \ingroup Communication
|
||||
@ -118,12 +192,18 @@ namespace diy
|
||||
CollectivesList* collectives() const { return collectives_; }
|
||||
|
||||
Master* master() const { return master_; }
|
||||
IExchangeInfo* iexchange() const { return iexchange_; }
|
||||
|
||||
private:
|
||||
int gid_;
|
||||
Master* master_;
|
||||
IncomingQueues* incoming_;
|
||||
OutgoingQueues* outgoing_;
|
||||
IExchangeInfo* iexchange_;
|
||||
|
||||
// TODO: these are marked mutable to not have to undo consts on enqueue/dequeue, in case it breaks things;
|
||||
// eventually, implement this change
|
||||
mutable IncomingQueues incoming_;
|
||||
mutable OutgoingQueues outgoing_;
|
||||
|
||||
CollectivesList* collectives_;
|
||||
};
|
||||
|
||||
@ -151,14 +231,12 @@ namespace diy
|
||||
|
||||
struct Master::ProxyWithLink: public Master::Proxy
|
||||
{
|
||||
ProxyWithLink(const Proxy& proxy,
|
||||
ProxyWithLink(Proxy&& proxy,
|
||||
void* block__,
|
||||
Link* link__,
|
||||
IExchangeInfo* iexchange__ = 0):
|
||||
Proxy(proxy),
|
||||
Link* link__):
|
||||
Proxy(std::move(proxy)),
|
||||
block_(block__),
|
||||
link_(link__),
|
||||
iexchange_(iexchange__) {}
|
||||
link_(link__) {}
|
||||
|
||||
Link* link() const { return link_; }
|
||||
void* block() const { return block_; }
|
||||
@ -166,52 +244,6 @@ namespace diy
|
||||
private:
|
||||
void* block_;
|
||||
Link* link_;
|
||||
IExchangeInfo* iexchange_; // not used for iexchange presently, but later could trigger some special behavior
|
||||
|
||||
public:
|
||||
template<class T>
|
||||
void enqueue(const BlockID& to,
|
||||
const T& x,
|
||||
void (*save)(BinaryBuffer&, const T&) = &::diy::save<T>) const
|
||||
{
|
||||
diy::Master::Proxy::enqueue(to, x, save);
|
||||
if (iexchange_)
|
||||
master()->icommunicate(iexchange_);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void enqueue(const BlockID& to,
|
||||
const T* x,
|
||||
size_t n,
|
||||
void (*save)(BinaryBuffer&, const T&) = &::diy::save<T>) const
|
||||
{
|
||||
diy::Master::Proxy::enqueue(to, x, n, save);
|
||||
if (iexchange_)
|
||||
master()->icommunicate(iexchange_);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void dequeue(int from,
|
||||
T& x,
|
||||
void (*load)(BinaryBuffer&, T&) = &::diy::load<T>) const
|
||||
{
|
||||
// TODO: uncomment if necessary, try first without icommunicating on dequeue
|
||||
// if (iexchange_)
|
||||
// master()->icommunicate(iexchange_);
|
||||
diy::Master::Proxy::dequeue(from, x, load);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void dequeue(int from,
|
||||
T* x,
|
||||
size_t n,
|
||||
void (*load)(BinaryBuffer&, T&) = &::diy::load<T>) const
|
||||
{
|
||||
// TODO: uncomment if necessary, try first without icommunicating on dequeue
|
||||
// if (iexchange_)
|
||||
// master()->icommunicate(iexchange_);
|
||||
diy::Master::Proxy::dequeue(from, x, n, load);
|
||||
}
|
||||
};
|
||||
} // diy namespace
|
||||
|
||||
@ -219,10 +251,38 @@ void
|
||||
diy::Master::Proxy::
|
||||
incoming(std::vector<int>& v) const
|
||||
{
|
||||
for (IncomingQueues::const_iterator it = incoming_->begin(); it != incoming_->end(); ++it)
|
||||
v.push_back(it->first);
|
||||
for (auto& x : incoming_)
|
||||
v.push_back(x.first);
|
||||
}
|
||||
|
||||
bool
|
||||
diy::Master::Proxy::
|
||||
empty_incoming_queues() const
|
||||
{
|
||||
for (auto& x : *incoming())
|
||||
if (x.second)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
diy::Master::Proxy::
|
||||
empty_outgoing_queues() const
|
||||
{
|
||||
for (auto& x : *outgoing())
|
||||
if (x.second.size())
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
diy::Master::Proxy::
|
||||
empty_queues() const
|
||||
{
|
||||
return empty_incoming_queues() && empty_outgoing_queues();
|
||||
}
|
||||
|
||||
|
||||
template<class T, class Op>
|
||||
void
|
||||
diy::Master::Proxy::
|
||||
@ -265,8 +325,7 @@ diy::Master::Proxy::
|
||||
enqueue(const BlockID& to, const T* x, size_t n,
|
||||
void (*save)(BinaryBuffer&, const T&)) const
|
||||
{
|
||||
OutgoingQueues& out = *outgoing_;
|
||||
BinaryBuffer& bb = out[to];
|
||||
BinaryBuffer& bb = outgoing_[to];
|
||||
if (save == (void (*)(BinaryBuffer&, const T&)) &::diy::save<T>)
|
||||
diy::save(bb, x, n); // optimized for unspecialized types
|
||||
else
|
||||
@ -280,8 +339,7 @@ diy::Master::Proxy::
|
||||
dequeue(int from, T* x, size_t n,
|
||||
void (*load)(BinaryBuffer&, T&)) const
|
||||
{
|
||||
IncomingQueues& in = *incoming_;
|
||||
BinaryBuffer& bb = in[from];
|
||||
BinaryBuffer& bb = incoming_[from];
|
||||
if (load == (void (*)(BinaryBuffer&, T&)) &::diy::load<T>)
|
||||
diy::load(bb, x, n); // optimized for unspecialized types
|
||||
else
|
||||
|
@ -16,13 +16,13 @@ struct ReduceProxy: public Master::Proxy
|
||||
{
|
||||
typedef std::vector<int> GIDVector;
|
||||
|
||||
ReduceProxy(const Master::Proxy& proxy, //!< parent proxy
|
||||
ReduceProxy(Master::Proxy&& proxy, //!< parent proxy
|
||||
void* block, //!< diy block
|
||||
unsigned round, //!< current round
|
||||
const Assigner& assigner, //!< assigner
|
||||
const GIDVector& incoming_gids, //!< incoming gids in this group
|
||||
const GIDVector& outgoing_gids): //!< outgoing gids in this group
|
||||
Master::Proxy(proxy),
|
||||
Master::Proxy(std::move(proxy)),
|
||||
block_(block),
|
||||
round_(round),
|
||||
assigner_(assigner)
|
||||
@ -46,13 +46,13 @@ struct ReduceProxy: public Master::Proxy
|
||||
}
|
||||
}
|
||||
|
||||
ReduceProxy(const Master::Proxy& proxy, //!< parent proxy
|
||||
ReduceProxy(Master::Proxy&& proxy, //!< parent proxy
|
||||
void* block, //!< diy block
|
||||
unsigned round, //!< current round
|
||||
const Assigner& assigner,
|
||||
const Link& in_link,
|
||||
const Link& out_link):
|
||||
Master::Proxy(proxy),
|
||||
Master::Proxy(std::move(proxy)),
|
||||
block_(block),
|
||||
round_(round),
|
||||
assigner_(assigner),
|
||||
@ -170,7 +170,7 @@ namespace detail
|
||||
{
|
||||
using Callback = std::function<void(Block*, const ReduceProxy&, const Partners&)>;
|
||||
|
||||
ReductionFunctor(unsigned round_, const Callback& reduce_, const Partners& partners_, const Assigner& assigner_):
|
||||
ReductionFunctor(int round_, const Callback& reduce_, const Partners& partners_, const Assigner& assigner_):
|
||||
round(round_), reduce(reduce_), partners(partners_), assigner(assigner_) {}
|
||||
|
||||
void operator()(Block* b, const Master::ProxyWithLink& cp) const
|
||||
@ -180,20 +180,20 @@ namespace detail
|
||||
std::vector<int> incoming_gids, outgoing_gids;
|
||||
if (round > 0)
|
||||
partners.incoming(round, cp.gid(), incoming_gids, *cp.master()); // receive from the previous round
|
||||
if (round < partners.rounds())
|
||||
if (round < static_cast<int>(partners.rounds()))
|
||||
partners.outgoing(round, cp.gid(), outgoing_gids, *cp.master()); // send to the next round
|
||||
|
||||
ReduceProxy rp(cp, b, round, assigner, incoming_gids, outgoing_gids);
|
||||
ReduceProxy rp(std::move(const_cast<Master::ProxyWithLink&>(cp)), b, round, assigner, incoming_gids, outgoing_gids);
|
||||
reduce(b, rp, partners);
|
||||
|
||||
// touch the outgoing queues to make sure they exist
|
||||
Master::OutgoingQueues& outgoing = *cp.outgoing();
|
||||
if (outgoing.size() < (size_t) rp.out_link().size())
|
||||
for (int j = 0; j < rp.out_link().size(); ++j)
|
||||
outgoing[rp.out_link().target(j)]; // touch the outgoing queue, creating it if necessary
|
||||
Master::Proxy::OutgoingQueues& outgoing = *rp.outgoing();
|
||||
if (outgoing.size() < static_cast<size_t>(rp.out_link().size()))
|
||||
for (BlockID target : rp.out_link().neighbors())
|
||||
outgoing[target]; // touch the outgoing queue, creating it if necessary
|
||||
}
|
||||
|
||||
unsigned round;
|
||||
int round;
|
||||
Callback reduce;
|
||||
Partners partners;
|
||||
const Assigner& assigner;
|
||||
@ -213,4 +213,4 @@ namespace detail
|
||||
|
||||
} // diy
|
||||
|
||||
#endif // DIY_REDUCE_HPP
|
||||
#endif // VTKMDIY_REDUCE_HPP
|
||||
|
@ -13,6 +13,8 @@
|
||||
#include <unordered_set>
|
||||
#include <type_traits> // this is used for a safety check for default serialization
|
||||
|
||||
#include <cassert>
|
||||
|
||||
namespace diy
|
||||
{
|
||||
//! A serialization buffer. \ingroup Serialization
|
||||
@ -30,6 +32,11 @@ namespace diy
|
||||
MemoryBuffer(size_t position_ = 0):
|
||||
position(position_) {}
|
||||
|
||||
MemoryBuffer(MemoryBuffer&&) =default;
|
||||
MemoryBuffer(const MemoryBuffer&) =delete;
|
||||
MemoryBuffer& operator=(MemoryBuffer&&) =default;
|
||||
MemoryBuffer& operator=(const MemoryBuffer&) =delete;
|
||||
|
||||
virtual inline void save_binary(const char* x, size_t count) override; //!< copy `count` bytes from `x` into the buffer
|
||||
virtual inline void append_binary(const char* x, size_t count) override; //!< append `count` bytes from `x` to end of buffer
|
||||
virtual inline void load_binary(char* x, size_t count) override; //!< copy `count` bytes into `x` from the buffer
|
||||
@ -52,7 +59,7 @@ namespace diy
|
||||
static float growth_multiplier() { return 1.5; }
|
||||
|
||||
// simple file IO
|
||||
void write(const std::string& fn) const { std::ofstream out(fn.c_str()); out.write(&buffer[0], size()); }
|
||||
void write(const std::string& fn) const { std::ofstream out(fn.c_str()); out.write(&buffer[0], static_cast<std::streamsize>(size())); }
|
||||
void read(const std::string& fn)
|
||||
{
|
||||
std::ifstream in(fn.c_str(), std::ios::binary | std::ios::ate);
|
||||
@ -99,22 +106,16 @@ namespace diy
|
||||
// 20150422 == 5.1
|
||||
// 20141030 == 4.9.2
|
||||
// See https://gcc.gnu.org/onlinedocs/libstdc++/manual/abi.html#abi.versioning.__GLIBCXX__
|
||||
#if defined(__GLIBCXX__) && \
|
||||
#if !(defined(__GLIBCXX__) && \
|
||||
(__GLIBCXX__ < 20150422 || __GLIBCXX__ == 20160726 || __GLIBCXX__ == 20150626 || \
|
||||
__GLIBCXX__ == 20150623)
|
||||
#define VTKMDIY_USING_GLIBCXX_4
|
||||
#endif
|
||||
|
||||
#if !defined(VTKMDIY_USING_GLIBCXX_4)
|
||||
__GLIBCXX__ == 20150623))
|
||||
//exempt glibcxx-4 variants as they don't have is_trivially_copyable implemented
|
||||
static_assert(std::is_trivially_copyable<T>::value, "Default serialization works only for trivially copyable types");
|
||||
#else
|
||||
# undef VTKMDIY_USING_GLIBCXX_4
|
||||
#endif
|
||||
|
||||
static void save(BinaryBuffer& bb, const T& x) { bb.save_binary((const char*) &x, sizeof(T)); }
|
||||
static void load(BinaryBuffer& bb, T& x) { bb.load_binary((char*) &x, sizeof(T)); }
|
||||
static size_t size(const T& x) { return sizeof(T); }
|
||||
static size_t size(const T&) { return sizeof(T); }
|
||||
};
|
||||
|
||||
//! Saves `x` to `bb` by calling `diy::Serialization<T>::save(bb,x)`.
|
||||
@ -185,14 +186,16 @@ namespace diy
|
||||
static void save(BinaryBuffer& bb, const MemoryBuffer& x)
|
||||
{
|
||||
diy::save(bb, x.position);
|
||||
diy::save(bb, &x.buffer[0], x.position);
|
||||
if (x.position > 0)
|
||||
diy::save(bb, &x.buffer[0], x.position);
|
||||
}
|
||||
|
||||
static void load(BinaryBuffer& bb, MemoryBuffer& x)
|
||||
{
|
||||
diy::load(bb, x.position);
|
||||
x.buffer.resize(x.position);
|
||||
diy::load(bb, &x.buffer[0], x.position);
|
||||
if (x.position > 0)
|
||||
diy::load(bb, &x.buffer[0], x.position);
|
||||
}
|
||||
|
||||
static size_t size(const MemoryBuffer& x)
|
||||
@ -219,7 +222,7 @@ namespace diy
|
||||
{
|
||||
size_t s;
|
||||
diy::load(bb, s);
|
||||
v.resize(s);
|
||||
v.resize(s, U());
|
||||
if (s > 0)
|
||||
diy::load(bb, &v[0], s);
|
||||
}
|
||||
@ -242,7 +245,7 @@ namespace diy
|
||||
{
|
||||
size_t s;
|
||||
diy::load(bb, s);
|
||||
v.resize(s);
|
||||
v.resize(s, U());
|
||||
if (s > 0)
|
||||
diy::load(bb, &v[0], s);
|
||||
}
|
||||
|
@ -4,15 +4,83 @@
|
||||
#include <chrono>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "log.hpp" // need this for format
|
||||
#include "log.hpp"
|
||||
|
||||
#if defined(VTKMDIY_USE_CALIPER)
|
||||
#include <caliper/cali.h>
|
||||
#include <caliper/common/Variant.h>
|
||||
#endif
|
||||
|
||||
namespace diy
|
||||
{
|
||||
namespace stats
|
||||
{
|
||||
|
||||
#if defined(DIY_PROFILE)
|
||||
inline
|
||||
std::ostream&
|
||||
operator<<(std::ostream& out, const std::chrono::high_resolution_clock::duration& d)
|
||||
{
|
||||
auto time = std::chrono::duration_cast<std::chrono::microseconds>(d).count();
|
||||
fmt::print(out, "{:02d}:{:02d}:{:02d}.{:06d}",
|
||||
time/1000000/60/60,
|
||||
time/1000000/60 % 60,
|
||||
time/1000000 % 60,
|
||||
time % 1000000);
|
||||
return out;
|
||||
}
|
||||
|
||||
struct DurationAccumulator
|
||||
{
|
||||
using Clock = std::chrono::high_resolution_clock;
|
||||
using Time = Clock::time_point;
|
||||
using Duration = Clock::duration;
|
||||
|
||||
void operator<<(std::string name) { last[name] = Clock::now(); }
|
||||
void operator>>(std::string name) { duration[name] += Clock::now() - last[name]; }
|
||||
|
||||
void clear() { last.clear(); duration.clear(); }
|
||||
|
||||
std::unordered_map<std::string, Time> last;
|
||||
std::unordered_map<std::string, Duration> duration;
|
||||
|
||||
void output(std::ostream& out, std::string prefix = "") const
|
||||
{
|
||||
if (!prefix.empty())
|
||||
prefix += " ";
|
||||
|
||||
for (auto& x : duration)
|
||||
out << prefix << x.second << ' ' << x.first << '\n';
|
||||
}
|
||||
};
|
||||
|
||||
template<class Profiler>
|
||||
struct ScopedProfile
|
||||
{
|
||||
ScopedProfile(Profiler& prof_, std::string name_):
|
||||
prof(prof_), name(name_), active(true) { prof << name; }
|
||||
~ScopedProfile() { if (active) prof >> name; }
|
||||
|
||||
ScopedProfile(ScopedProfile&& other):
|
||||
prof(other.prof),
|
||||
name(other.name),
|
||||
active(other.active) { other.active = false; }
|
||||
|
||||
ScopedProfile&
|
||||
operator=(ScopedProfile&& other) = delete;
|
||||
ScopedProfile(const ScopedProfile&) = delete;
|
||||
ScopedProfile&
|
||||
operator=(const ScopedProfile&) = delete;
|
||||
|
||||
Profiler& prof;
|
||||
std::string name;
|
||||
bool active;
|
||||
};
|
||||
|
||||
|
||||
#if !defined(VTKMDIY_USE_CALIPER)
|
||||
#if defined(VTKMDIY_PROFILE)
|
||||
struct Profiler
|
||||
{
|
||||
using Clock = std::chrono::high_resolution_clock;
|
||||
@ -32,28 +100,7 @@ struct Profiler
|
||||
};
|
||||
|
||||
using EventsVector = std::vector<Event>;
|
||||
|
||||
struct Scoped
|
||||
{
|
||||
Scoped(Profiler& prof_, std::string name_):
|
||||
prof(prof_), name(name_), active(true) { prof << name; }
|
||||
~Scoped() { if (active) prof >> name; }
|
||||
|
||||
Scoped(Scoped&& other):
|
||||
prof(other.prof),
|
||||
name(other.name),
|
||||
active(other.active) { other.active = false; }
|
||||
|
||||
Scoped&
|
||||
operator=(Scoped&& other) = delete;
|
||||
Scoped(const Scoped&) = delete;
|
||||
Scoped&
|
||||
operator=(const Scoped&) = delete;
|
||||
|
||||
Profiler& prof;
|
||||
std::string name;
|
||||
bool active;
|
||||
};
|
||||
using Scoped = ScopedProfile<Profiler>;
|
||||
|
||||
Profiler() { reset_time(); }
|
||||
|
||||
@ -62,10 +109,10 @@ struct Profiler
|
||||
void operator<<(std::string name) { enter(name); }
|
||||
void operator>>(std::string name) { exit(name); }
|
||||
|
||||
void enter(std::string name) { events.push_back(Event(name, true)); }
|
||||
void exit(std::string name) { events.push_back(Event(name, false)); }
|
||||
void enter(std::string name) { events.push_back(Event(name, true)); total << name; }
|
||||
void exit(std::string name) { events.push_back(Event(name, false)); total >> name; }
|
||||
|
||||
void output(std::ostream& out, std::string prefix = "")
|
||||
void output(std::ostream& out, std::string prefix = "") const
|
||||
{
|
||||
if (!prefix.empty())
|
||||
prefix += " ";
|
||||
@ -73,44 +120,103 @@ struct Profiler
|
||||
for (size_t i = 0; i < events.size(); ++i)
|
||||
{
|
||||
const Event& e = events[i];
|
||||
auto time = std::chrono::duration_cast<std::chrono::microseconds>(e.stamp - start).count();
|
||||
|
||||
fmt::print(out, "{}{:02d}:{:02d}:{:02d}.{:06d} {}{}\n",
|
||||
prefix,
|
||||
time/1000000/60/60,
|
||||
time/1000000/60 % 60,
|
||||
time/1000000 % 60,
|
||||
time % 1000000,
|
||||
(e.begin ? '<' : '>'),
|
||||
e.name);
|
||||
out << prefix << (e.stamp - start) << ' ' << (e.begin ? '<' : '>') << e.name << '\n';
|
||||
}
|
||||
|
||||
out << "# Total times:\n";
|
||||
total.output(out, "# ");
|
||||
}
|
||||
|
||||
Scoped scoped(std::string name) { return Scoped(*this, name); }
|
||||
|
||||
void clear() { events.clear(); }
|
||||
void clear() { events.clear(); total.clear(); }
|
||||
|
||||
const DurationAccumulator& totals() const { return total; }
|
||||
|
||||
private:
|
||||
Time start;
|
||||
EventsVector events;
|
||||
Time start;
|
||||
EventsVector events;
|
||||
DurationAccumulator total;
|
||||
};
|
||||
#else
|
||||
#else // VTKMDIY_PROFILE
|
||||
struct Profiler
|
||||
{
|
||||
struct Scoped {};
|
||||
using Scoped = ScopedProfile<Profiler>;
|
||||
|
||||
void reset_time() {}
|
||||
void reset_time() {}
|
||||
|
||||
void operator<<(std::string) {}
|
||||
void operator>>(std::string) {}
|
||||
void operator<<(std::string name) { enter(name); }
|
||||
void operator>>(std::string name) { exit(name); }
|
||||
|
||||
void enter(const std::string&) {}
|
||||
void exit(const std::string&) {}
|
||||
void enter(std::string) {}
|
||||
void exit(std::string) {}
|
||||
|
||||
void output(std::ostream&, std::string = "") {}
|
||||
void clear() {}
|
||||
void output(std::ostream& out, std::string = "") const
|
||||
{
|
||||
out << "# Total times:\n";
|
||||
total.output(out, "# ");
|
||||
}
|
||||
void clear() { total.clear(); }
|
||||
|
||||
Scoped scoped(std::string) { return Scoped(); }
|
||||
Scoped scoped(std::string name) { return Scoped(*this, name); }
|
||||
|
||||
const DurationAccumulator&
|
||||
totals() const { return total; }
|
||||
|
||||
private:
|
||||
DurationAccumulator total;
|
||||
};
|
||||
#endif // VTKMDIY_PROFILE
|
||||
|
||||
// Annotations don't do anything without Caliper
|
||||
struct Annotation
|
||||
{
|
||||
struct Guard
|
||||
{
|
||||
Guard(Annotation&) {}
|
||||
};
|
||||
|
||||
Annotation(const char*) {}
|
||||
|
||||
template<class T>
|
||||
Annotation& set(T) { return *this; }
|
||||
};
|
||||
|
||||
struct Variant
|
||||
{
|
||||
template<class T>
|
||||
Variant(T) {}
|
||||
|
||||
};
|
||||
|
||||
#else // VTKMDIY_USE_CALIPER
|
||||
|
||||
using Annotation = cali::Annotation;
|
||||
using Variant = cali::Variant;
|
||||
|
||||
struct Profiler
|
||||
{
|
||||
using Scoped = ScopedProfile<Profiler>;
|
||||
|
||||
void reset_time() {}
|
||||
|
||||
void operator<<(std::string name) { enter(name); }
|
||||
void operator>>(std::string name) { exit(name); }
|
||||
|
||||
void enter(std::string name) { CALI_MARK_BEGIN(name.c_str()); }
|
||||
void exit(std::string name) { CALI_MARK_END(name.c_str()); }
|
||||
|
||||
void output(std::ostream& out, std::string = "") const {}
|
||||
void clear() {}
|
||||
|
||||
Scoped scoped(std::string name) { return Scoped(*this, name); }
|
||||
|
||||
// unused
|
||||
const DurationAccumulator&
|
||||
totals() const { return total; }
|
||||
|
||||
private:
|
||||
DurationAccumulator total;
|
||||
};
|
||||
#endif
|
||||
}
|
||||
|
@ -26,14 +26,14 @@ namespace diy
|
||||
virtual inline void save_binary(const char* x, size_t count) override { fwrite(x, 1, count, file); head += count; }
|
||||
virtual inline void append_binary(const char* x, size_t count) override
|
||||
{
|
||||
size_t temp_pos = ftell(file);
|
||||
auto temp_pos = ftell(file);
|
||||
fseek(file, static_cast<long>(tail), SEEK_END);
|
||||
fwrite(x, 1, count, file);
|
||||
tail += count;
|
||||
fseek(file, temp_pos, SEEK_SET);
|
||||
}
|
||||
virtual inline void load_binary(char* x, size_t count) override { auto n = fread(x, 1, count, file); (void) n;}
|
||||
virtual inline void load_binary_back(char* x, size_t count) override { fseek(file, static_cast<long>(tail), SEEK_END); auto n = fread(x, 1, count, file); tail += count; fseek(file, static_cast<long>(head), SEEK_SET); (void) n;}
|
||||
virtual inline void load_binary(char* x, size_t count) override { auto n = fread(x, 1, count, file); VTKMDIY_UNUSED(n);}
|
||||
virtual inline void load_binary_back(char* x, size_t count) override { fseek(file, static_cast<long>(tail), SEEK_END); auto n = fread(x, 1, count, file); tail += count; fseek(file, static_cast<long>(head), SEEK_SET); VTKMDIY_UNUSED(n);}
|
||||
|
||||
size_t size() const { return head; }
|
||||
|
||||
@ -135,7 +135,8 @@ namespace diy
|
||||
_read(fh, &bb.buffer[0], static_cast<unsigned int>(fr.size));
|
||||
#else
|
||||
int fh = open(fr.name.c_str(), O_RDONLY | O_SYNC, 0600);
|
||||
auto n = read(fh, &bb.buffer[0], fr.size); (void) n;
|
||||
auto n = read(fh, &bb.buffer[0], fr.size);
|
||||
VTKMDIY_UNUSED(n);
|
||||
#endif
|
||||
io::utils::close(fh);
|
||||
remove_file(fr);
|
||||
|
1716
vtkm/thirdparty/diy/vtkmdiy/include/vtkmdiy/thirdparty/chobo/small_vector.hpp
vendored
Normal file
1716
vtkm/thirdparty/diy/vtkmdiy/include/vtkmdiy/thirdparty/chobo/small_vector.hpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
829
vtkm/thirdparty/diy/vtkmdiy/include/vtkmdiy/thirdparty/fmt/chrono.h
vendored
Normal file
829
vtkm/thirdparty/diy/vtkmdiy/include/vtkmdiy/thirdparty/fmt/chrono.h
vendored
Normal file
@ -0,0 +1,829 @@
|
||||
// Formatting library for C++ - chrono support
|
||||
//
|
||||
// Copyright (c) 2012 - present, Victor Zverovich
|
||||
// All rights reserved.
|
||||
//
|
||||
// For the license information refer to format.h.
|
||||
|
||||
#ifndef FMT_CHRONO_H_
|
||||
#define FMT_CHRONO_H_
|
||||
|
||||
#include "format.h"
|
||||
#include "locale.h"
|
||||
|
||||
#include <chrono>
|
||||
#include <ctime>
|
||||
#include <locale>
|
||||
#include <sstream>
|
||||
|
||||
// enable safe chrono durations, unless explicitly disabled
|
||||
#ifndef FMT_SAFE_DURATION_CAST
|
||||
# define FMT_SAFE_DURATION_CAST 1
|
||||
#endif
|
||||
|
||||
#if FMT_SAFE_DURATION_CAST
|
||||
# include "safe-duration-cast.h"
|
||||
#endif
|
||||
|
||||
FMT_BEGIN_NAMESPACE
|
||||
|
||||
// Prevents expansion of a preceding token as a function-style macro.
|
||||
// Usage: f FMT_NOMACRO()
|
||||
#define FMT_NOMACRO
|
||||
|
||||
namespace internal {
|
||||
inline null<> localtime_r FMT_NOMACRO(...) { return null<>(); }
|
||||
inline null<> localtime_s(...) { return null<>(); }
|
||||
inline null<> gmtime_r(...) { return null<>(); }
|
||||
inline null<> gmtime_s(...) { return null<>(); }
|
||||
} // namespace internal
|
||||
|
||||
// Thread-safe replacement for std::localtime
|
||||
inline std::tm localtime(std::time_t time) {
|
||||
struct dispatcher {
|
||||
std::time_t time_;
|
||||
std::tm tm_;
|
||||
|
||||
dispatcher(std::time_t t) : time_(t) {}
|
||||
|
||||
bool run() {
|
||||
using namespace fmt::internal;
|
||||
return handle(localtime_r(&time_, &tm_));
|
||||
}
|
||||
|
||||
bool handle(std::tm* tm) { return tm != nullptr; }
|
||||
|
||||
bool handle(internal::null<>) {
|
||||
using namespace fmt::internal;
|
||||
return fallback(localtime_s(&tm_, &time_));
|
||||
}
|
||||
|
||||
bool fallback(int res) { return res == 0; }
|
||||
|
||||
#if !FMT_MSC_VER
|
||||
bool fallback(internal::null<>) {
|
||||
using namespace fmt::internal;
|
||||
std::tm* tm = std::localtime(&time_);
|
||||
if (tm) tm_ = *tm;
|
||||
return tm != nullptr;
|
||||
}
|
||||
#endif
|
||||
};
|
||||
dispatcher lt(time);
|
||||
// Too big time values may be unsupported.
|
||||
if (!lt.run()) FMT_THROW(format_error("time_t value out of range"));
|
||||
return lt.tm_;
|
||||
}
|
||||
|
||||
// Thread-safe replacement for std::gmtime
|
||||
inline std::tm gmtime(std::time_t time) {
|
||||
struct dispatcher {
|
||||
std::time_t time_;
|
||||
std::tm tm_;
|
||||
|
||||
dispatcher(std::time_t t) : time_(t) {}
|
||||
|
||||
bool run() {
|
||||
using namespace fmt::internal;
|
||||
return handle(gmtime_r(&time_, &tm_));
|
||||
}
|
||||
|
||||
bool handle(std::tm* tm) { return tm != nullptr; }
|
||||
|
||||
bool handle(internal::null<>) {
|
||||
using namespace fmt::internal;
|
||||
return fallback(gmtime_s(&tm_, &time_));
|
||||
}
|
||||
|
||||
bool fallback(int res) { return res == 0; }
|
||||
|
||||
#if !FMT_MSC_VER
|
||||
bool fallback(internal::null<>) {
|
||||
std::tm* tm = std::gmtime(&time_);
|
||||
if (tm) tm_ = *tm;
|
||||
return tm != nullptr;
|
||||
}
|
||||
#endif
|
||||
};
|
||||
dispatcher gt(time);
|
||||
// Too big time values may be unsupported.
|
||||
if (!gt.run()) FMT_THROW(format_error("time_t value out of range"));
|
||||
return gt.tm_;
|
||||
}
|
||||
|
||||
namespace internal {
|
||||
inline std::size_t strftime(char* str, std::size_t count, const char* format,
|
||||
const std::tm* time) {
|
||||
return std::strftime(str, count, format, time);
|
||||
}
|
||||
|
||||
inline std::size_t strftime(wchar_t* str, std::size_t count,
|
||||
const wchar_t* format, const std::tm* time) {
|
||||
return std::wcsftime(str, count, format, time);
|
||||
}
|
||||
} // namespace internal
|
||||
|
||||
template <typename Char> struct formatter<std::tm, Char> {
|
||||
template <typename ParseContext>
|
||||
auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
|
||||
auto it = ctx.begin();
|
||||
if (it != ctx.end() && *it == ':') ++it;
|
||||
auto end = it;
|
||||
while (end != ctx.end() && *end != '}') ++end;
|
||||
tm_format.reserve(internal::to_unsigned(end - it + 1));
|
||||
tm_format.append(it, end);
|
||||
tm_format.push_back('\0');
|
||||
return end;
|
||||
}
|
||||
|
||||
template <typename FormatContext>
|
||||
auto format(const std::tm& tm, FormatContext& ctx) -> decltype(ctx.out()) {
|
||||
basic_memory_buffer<Char> buf;
|
||||
std::size_t start = buf.size();
|
||||
for (;;) {
|
||||
std::size_t size = buf.capacity() - start;
|
||||
std::size_t count =
|
||||
internal::strftime(&buf[start], size, &tm_format[0], &tm);
|
||||
if (count != 0) {
|
||||
buf.resize(start + count);
|
||||
break;
|
||||
}
|
||||
if (size >= tm_format.size() * 256) {
|
||||
// If the buffer is 256 times larger than the format string, assume
|
||||
// that `strftime` gives an empty result. There doesn't seem to be a
|
||||
// better way to distinguish the two cases:
|
||||
// https://github.com/fmtlib/fmt/issues/367
|
||||
break;
|
||||
}
|
||||
const std::size_t MIN_GROWTH = 10;
|
||||
buf.reserve(buf.capacity() + (size > MIN_GROWTH ? size : MIN_GROWTH));
|
||||
}
|
||||
return std::copy(buf.begin(), buf.end(), ctx.out());
|
||||
}
|
||||
|
||||
basic_memory_buffer<Char> tm_format;
|
||||
};
|
||||
|
||||
namespace internal {
|
||||
template <typename Period> FMT_CONSTEXPR const char* get_units() {
|
||||
return nullptr;
|
||||
}
|
||||
template <> FMT_CONSTEXPR const char* get_units<std::atto>() { return "as"; }
|
||||
template <> FMT_CONSTEXPR const char* get_units<std::femto>() { return "fs"; }
|
||||
template <> FMT_CONSTEXPR const char* get_units<std::pico>() { return "ps"; }
|
||||
template <> FMT_CONSTEXPR const char* get_units<std::nano>() { return "ns"; }
|
||||
template <> FMT_CONSTEXPR const char* get_units<std::micro>() { return "µs"; }
|
||||
template <> FMT_CONSTEXPR const char* get_units<std::milli>() { return "ms"; }
|
||||
template <> FMT_CONSTEXPR const char* get_units<std::centi>() { return "cs"; }
|
||||
template <> FMT_CONSTEXPR const char* get_units<std::deci>() { return "ds"; }
|
||||
template <> FMT_CONSTEXPR const char* get_units<std::ratio<1>>() { return "s"; }
|
||||
template <> FMT_CONSTEXPR const char* get_units<std::deca>() { return "das"; }
|
||||
template <> FMT_CONSTEXPR const char* get_units<std::hecto>() { return "hs"; }
|
||||
template <> FMT_CONSTEXPR const char* get_units<std::kilo>() { return "ks"; }
|
||||
template <> FMT_CONSTEXPR const char* get_units<std::mega>() { return "Ms"; }
|
||||
template <> FMT_CONSTEXPR const char* get_units<std::giga>() { return "Gs"; }
|
||||
template <> FMT_CONSTEXPR const char* get_units<std::tera>() { return "Ts"; }
|
||||
template <> FMT_CONSTEXPR const char* get_units<std::peta>() { return "Ps"; }
|
||||
template <> FMT_CONSTEXPR const char* get_units<std::exa>() { return "Es"; }
|
||||
template <> FMT_CONSTEXPR const char* get_units<std::ratio<60>>() {
|
||||
return "m";
|
||||
}
|
||||
template <> FMT_CONSTEXPR const char* get_units<std::ratio<3600>>() {
|
||||
return "h";
|
||||
}
|
||||
|
||||
enum class numeric_system {
|
||||
standard,
|
||||
// Alternative numeric system, e.g. 十二 instead of 12 in ja_JP locale.
|
||||
alternative
|
||||
};
|
||||
|
||||
// Parses a put_time-like format string and invokes handler actions.
|
||||
template <typename Char, typename Handler>
|
||||
FMT_CONSTEXPR const Char* parse_chrono_format(const Char* begin,
|
||||
const Char* end,
|
||||
Handler&& handler) {
|
||||
auto ptr = begin;
|
||||
while (ptr != end) {
|
||||
auto c = *ptr;
|
||||
if (c == '}') break;
|
||||
if (c != '%') {
|
||||
++ptr;
|
||||
continue;
|
||||
}
|
||||
if (begin != ptr) handler.on_text(begin, ptr);
|
||||
++ptr; // consume '%'
|
||||
if (ptr == end) FMT_THROW(format_error("invalid format"));
|
||||
c = *ptr++;
|
||||
switch (c) {
|
||||
case '%':
|
||||
handler.on_text(ptr - 1, ptr);
|
||||
break;
|
||||
case 'n': {
|
||||
const char newline[] = "\n";
|
||||
handler.on_text(newline, newline + 1);
|
||||
break;
|
||||
}
|
||||
case 't': {
|
||||
const char tab[] = "\t";
|
||||
handler.on_text(tab, tab + 1);
|
||||
break;
|
||||
}
|
||||
// Day of the week:
|
||||
case 'a':
|
||||
handler.on_abbr_weekday();
|
||||
break;
|
||||
case 'A':
|
||||
handler.on_full_weekday();
|
||||
break;
|
||||
case 'w':
|
||||
handler.on_dec0_weekday(numeric_system::standard);
|
||||
break;
|
||||
case 'u':
|
||||
handler.on_dec1_weekday(numeric_system::standard);
|
||||
break;
|
||||
// Month:
|
||||
case 'b':
|
||||
handler.on_abbr_month();
|
||||
break;
|
||||
case 'B':
|
||||
handler.on_full_month();
|
||||
break;
|
||||
// Hour, minute, second:
|
||||
case 'H':
|
||||
handler.on_24_hour(numeric_system::standard);
|
||||
break;
|
||||
case 'I':
|
||||
handler.on_12_hour(numeric_system::standard);
|
||||
break;
|
||||
case 'M':
|
||||
handler.on_minute(numeric_system::standard);
|
||||
break;
|
||||
case 'S':
|
||||
handler.on_second(numeric_system::standard);
|
||||
break;
|
||||
// Other:
|
||||
case 'c':
|
||||
handler.on_datetime(numeric_system::standard);
|
||||
break;
|
||||
case 'x':
|
||||
handler.on_loc_date(numeric_system::standard);
|
||||
break;
|
||||
case 'X':
|
||||
handler.on_loc_time(numeric_system::standard);
|
||||
break;
|
||||
case 'D':
|
||||
handler.on_us_date();
|
||||
break;
|
||||
case 'F':
|
||||
handler.on_iso_date();
|
||||
break;
|
||||
case 'r':
|
||||
handler.on_12_hour_time();
|
||||
break;
|
||||
case 'R':
|
||||
handler.on_24_hour_time();
|
||||
break;
|
||||
case 'T':
|
||||
handler.on_iso_time();
|
||||
break;
|
||||
case 'p':
|
||||
handler.on_am_pm();
|
||||
break;
|
||||
case 'Q':
|
||||
handler.on_duration_value();
|
||||
break;
|
||||
case 'q':
|
||||
handler.on_duration_unit();
|
||||
break;
|
||||
case 'z':
|
||||
handler.on_utc_offset();
|
||||
break;
|
||||
case 'Z':
|
||||
handler.on_tz_name();
|
||||
break;
|
||||
// Alternative representation:
|
||||
case 'E': {
|
||||
if (ptr == end) FMT_THROW(format_error("invalid format"));
|
||||
c = *ptr++;
|
||||
switch (c) {
|
||||
case 'c':
|
||||
handler.on_datetime(numeric_system::alternative);
|
||||
break;
|
||||
case 'x':
|
||||
handler.on_loc_date(numeric_system::alternative);
|
||||
break;
|
||||
case 'X':
|
||||
handler.on_loc_time(numeric_system::alternative);
|
||||
break;
|
||||
default:
|
||||
FMT_THROW(format_error("invalid format"));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'O':
|
||||
if (ptr == end) FMT_THROW(format_error("invalid format"));
|
||||
c = *ptr++;
|
||||
switch (c) {
|
||||
case 'w':
|
||||
handler.on_dec0_weekday(numeric_system::alternative);
|
||||
break;
|
||||
case 'u':
|
||||
handler.on_dec1_weekday(numeric_system::alternative);
|
||||
break;
|
||||
case 'H':
|
||||
handler.on_24_hour(numeric_system::alternative);
|
||||
break;
|
||||
case 'I':
|
||||
handler.on_12_hour(numeric_system::alternative);
|
||||
break;
|
||||
case 'M':
|
||||
handler.on_minute(numeric_system::alternative);
|
||||
break;
|
||||
case 'S':
|
||||
handler.on_second(numeric_system::alternative);
|
||||
break;
|
||||
default:
|
||||
FMT_THROW(format_error("invalid format"));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
FMT_THROW(format_error("invalid format"));
|
||||
}
|
||||
begin = ptr;
|
||||
}
|
||||
if (begin != ptr) handler.on_text(begin, ptr);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
struct chrono_format_checker {
|
||||
FMT_NORETURN void report_no_date() { FMT_THROW(format_error("no date")); }
|
||||
|
||||
template <typename Char> void on_text(const Char*, const Char*) {}
|
||||
FMT_NORETURN void on_abbr_weekday() { report_no_date(); }
|
||||
FMT_NORETURN void on_full_weekday() { report_no_date(); }
|
||||
FMT_NORETURN void on_dec0_weekday(numeric_system) { report_no_date(); }
|
||||
FMT_NORETURN void on_dec1_weekday(numeric_system) { report_no_date(); }
|
||||
FMT_NORETURN void on_abbr_month() { report_no_date(); }
|
||||
FMT_NORETURN void on_full_month() { report_no_date(); }
|
||||
void on_24_hour(numeric_system) {}
|
||||
void on_12_hour(numeric_system) {}
|
||||
void on_minute(numeric_system) {}
|
||||
void on_second(numeric_system) {}
|
||||
FMT_NORETURN void on_datetime(numeric_system) { report_no_date(); }
|
||||
FMT_NORETURN void on_loc_date(numeric_system) { report_no_date(); }
|
||||
FMT_NORETURN void on_loc_time(numeric_system) { report_no_date(); }
|
||||
FMT_NORETURN void on_us_date() { report_no_date(); }
|
||||
FMT_NORETURN void on_iso_date() { report_no_date(); }
|
||||
void on_12_hour_time() {}
|
||||
void on_24_hour_time() {}
|
||||
void on_iso_time() {}
|
||||
void on_am_pm() {}
|
||||
void on_duration_value() {}
|
||||
void on_duration_unit() {}
|
||||
FMT_NORETURN void on_utc_offset() { report_no_date(); }
|
||||
FMT_NORETURN void on_tz_name() { report_no_date(); }
|
||||
};
|
||||
|
||||
template <typename T, FMT_ENABLE_IF(std::is_integral<T>::value)>
|
||||
inline bool isnan(T) {
|
||||
return false;
|
||||
}
|
||||
template <typename T, FMT_ENABLE_IF(std::is_floating_point<T>::value)>
|
||||
inline bool isnan(T value) {
|
||||
return std::isnan(value);
|
||||
}
|
||||
|
||||
template <typename T, FMT_ENABLE_IF(std::is_integral<T>::value)>
|
||||
inline bool isfinite(T) {
|
||||
return true;
|
||||
}
|
||||
template <typename T, FMT_ENABLE_IF(std::is_floating_point<T>::value)>
|
||||
inline bool isfinite(T value) {
|
||||
return std::isfinite(value);
|
||||
}
|
||||
|
||||
// Converts value to int and checks that it's in the range [0, upper).
|
||||
template <typename T, FMT_ENABLE_IF(std::is_integral<T>::value)>
|
||||
inline int to_nonnegative_int(T value, int upper) {
|
||||
FMT_ASSERT(value >= 0 && value <= upper, "invalid value");
|
||||
(void)upper;
|
||||
return static_cast<int>(value);
|
||||
}
|
||||
template <typename T, FMT_ENABLE_IF(!std::is_integral<T>::value)>
|
||||
inline int to_nonnegative_int(T value, int upper) {
|
||||
FMT_ASSERT(
|
||||
std::isnan(value) || (value >= 0 && value <= static_cast<T>(upper)),
|
||||
"invalid value");
|
||||
(void)upper;
|
||||
return static_cast<int>(value);
|
||||
}
|
||||
|
||||
template <typename T, FMT_ENABLE_IF(std::is_integral<T>::value)>
|
||||
inline T mod(T x, int y) {
|
||||
return x % y;
|
||||
}
|
||||
template <typename T, FMT_ENABLE_IF(std::is_floating_point<T>::value)>
|
||||
inline T mod(T x, int y) {
|
||||
return std::fmod(x, static_cast<T>(y));
|
||||
}
|
||||
|
||||
// If T is an integral type, maps T to its unsigned counterpart, otherwise
|
||||
// leaves it unchanged (unlike std::make_unsigned).
|
||||
template <typename T, bool INTEGRAL = std::is_integral<T>::value>
|
||||
struct make_unsigned_or_unchanged {
|
||||
using type = T;
|
||||
};
|
||||
|
||||
template <typename T> struct make_unsigned_or_unchanged<T, true> {
|
||||
using type = typename std::make_unsigned<T>::type;
|
||||
};
|
||||
|
||||
#if FMT_SAFE_DURATION_CAST
|
||||
// throwing version of safe_duration_cast
|
||||
template <typename To, typename FromRep, typename FromPeriod>
|
||||
To fmt_safe_duration_cast(std::chrono::duration<FromRep, FromPeriod> from) {
|
||||
int ec;
|
||||
To to = safe_duration_cast::safe_duration_cast<To>(from, ec);
|
||||
if (ec) FMT_THROW(format_error("cannot format duration"));
|
||||
return to;
|
||||
}
|
||||
#endif
|
||||
|
||||
template <typename Rep, typename Period,
|
||||
FMT_ENABLE_IF(std::is_integral<Rep>::value)>
|
||||
inline std::chrono::duration<Rep, std::milli> get_milliseconds(
|
||||
std::chrono::duration<Rep, Period> d) {
|
||||
// this may overflow and/or the result may not fit in the
|
||||
// target type.
|
||||
#if FMT_SAFE_DURATION_CAST
|
||||
using CommonSecondsType =
|
||||
typename std::common_type<decltype(d), std::chrono::seconds>::type;
|
||||
const auto d_as_common = fmt_safe_duration_cast<CommonSecondsType>(d);
|
||||
const auto d_as_whole_seconds =
|
||||
fmt_safe_duration_cast<std::chrono::seconds>(d_as_common);
|
||||
// this conversion should be nonproblematic
|
||||
const auto diff = d_as_common - d_as_whole_seconds;
|
||||
const auto ms =
|
||||
fmt_safe_duration_cast<std::chrono::duration<Rep, std::milli>>(diff);
|
||||
return ms;
|
||||
#else
|
||||
auto s = std::chrono::duration_cast<std::chrono::seconds>(d);
|
||||
return std::chrono::duration_cast<std::chrono::milliseconds>(d - s);
|
||||
#endif
|
||||
}
|
||||
|
||||
template <typename Rep, typename Period,
|
||||
FMT_ENABLE_IF(std::is_floating_point<Rep>::value)>
|
||||
inline std::chrono::duration<Rep, std::milli> get_milliseconds(
|
||||
std::chrono::duration<Rep, Period> d) {
|
||||
using common_type = typename std::common_type<Rep, std::intmax_t>::type;
|
||||
auto ms = mod(d.count() * static_cast<common_type>(Period::num) /
|
||||
static_cast<common_type>(Period::den) * 1000,
|
||||
1000);
|
||||
return std::chrono::duration<Rep, std::milli>(static_cast<Rep>(ms));
|
||||
}
|
||||
|
||||
template <typename Rep, typename OutputIt>
|
||||
OutputIt format_chrono_duration_value(OutputIt out, Rep val, int precision) {
|
||||
if (precision >= 0) return format_to(out, "{:.{}f}", val, precision);
|
||||
return format_to(out, std::is_floating_point<Rep>::value ? "{:g}" : "{}",
|
||||
val);
|
||||
}
|
||||
|
||||
template <typename Period, typename OutputIt>
|
||||
static OutputIt format_chrono_duration_unit(OutputIt out) {
|
||||
if (const char* unit = get_units<Period>()) return format_to(out, "{}", unit);
|
||||
if (Period::den == 1) return format_to(out, "[{}]s", Period::num);
|
||||
return format_to(out, "[{}/{}]s", Period::num, Period::den);
|
||||
}
|
||||
|
||||
template <typename FormatContext, typename OutputIt, typename Rep,
|
||||
typename Period>
|
||||
struct chrono_formatter {
|
||||
FormatContext& context;
|
||||
OutputIt out;
|
||||
int precision;
|
||||
// rep is unsigned to avoid overflow.
|
||||
using rep =
|
||||
conditional_t<std::is_integral<Rep>::value && sizeof(Rep) < sizeof(int),
|
||||
unsigned, typename make_unsigned_or_unchanged<Rep>::type>;
|
||||
rep val;
|
||||
using seconds = std::chrono::duration<rep>;
|
||||
seconds s;
|
||||
using milliseconds = std::chrono::duration<rep, std::milli>;
|
||||
bool negative;
|
||||
|
||||
using char_type = typename FormatContext::char_type;
|
||||
|
||||
explicit chrono_formatter(FormatContext& ctx, OutputIt o,
|
||||
std::chrono::duration<Rep, Period> d)
|
||||
: context(ctx), out(o), val(d.count()), negative(false) {
|
||||
if (d.count() < 0) {
|
||||
val = 0 - val;
|
||||
negative = true;
|
||||
}
|
||||
|
||||
// this may overflow and/or the result may not fit in the
|
||||
// target type.
|
||||
#if FMT_SAFE_DURATION_CAST
|
||||
// might need checked conversion (rep!=Rep)
|
||||
auto tmpval = std::chrono::duration<rep, Period>(val);
|
||||
s = fmt_safe_duration_cast<seconds>(tmpval);
|
||||
#else
|
||||
s = std::chrono::duration_cast<seconds>(
|
||||
std::chrono::duration<rep, Period>(val));
|
||||
#endif
|
||||
}
|
||||
|
||||
// returns true if nan or inf, writes to out.
|
||||
bool handle_nan_inf() {
|
||||
if (isfinite(val)) {
|
||||
return false;
|
||||
}
|
||||
if (isnan(val)) {
|
||||
write_nan();
|
||||
return true;
|
||||
}
|
||||
// must be +-inf
|
||||
if (val > 0) {
|
||||
write_pinf();
|
||||
} else {
|
||||
write_ninf();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
Rep hour() const { return static_cast<Rep>(mod((s.count() / 3600), 24)); }
|
||||
|
||||
Rep hour12() const {
|
||||
Rep hour = static_cast<Rep>(mod((s.count() / 3600), 12));
|
||||
return hour <= 0 ? 12 : hour;
|
||||
}
|
||||
|
||||
Rep minute() const { return static_cast<Rep>(mod((s.count() / 60), 60)); }
|
||||
Rep second() const { return static_cast<Rep>(mod(s.count(), 60)); }
|
||||
|
||||
std::tm time() const {
|
||||
auto time = std::tm();
|
||||
time.tm_hour = to_nonnegative_int(hour(), 24);
|
||||
time.tm_min = to_nonnegative_int(minute(), 60);
|
||||
time.tm_sec = to_nonnegative_int(second(), 60);
|
||||
return time;
|
||||
}
|
||||
|
||||
void write_sign() {
|
||||
if (negative) {
|
||||
*out++ = '-';
|
||||
negative = false;
|
||||
}
|
||||
}
|
||||
|
||||
void write(Rep value, int width) {
|
||||
write_sign();
|
||||
if (isnan(value)) return write_nan();
|
||||
uint32_or_64_t<int> n = to_unsigned(
|
||||
to_nonnegative_int(value, (std::numeric_limits<int>::max)()));
|
||||
int num_digits = internal::count_digits(n);
|
||||
if (width > num_digits) out = std::fill_n(out, width - num_digits, '0');
|
||||
out = format_decimal<char_type>(out, n, num_digits);
|
||||
}
|
||||
|
||||
void write_nan() { std::copy_n("nan", 3, out); }
|
||||
void write_pinf() { std::copy_n("inf", 3, out); }
|
||||
void write_ninf() { std::copy_n("-inf", 4, out); }
|
||||
|
||||
void format_localized(const tm& time, const char* format) {
|
||||
if (isnan(val)) return write_nan();
|
||||
auto locale = context.locale().template get<std::locale>();
|
||||
auto& facet = std::use_facet<std::time_put<char_type>>(locale);
|
||||
std::basic_ostringstream<char_type> os;
|
||||
os.imbue(locale);
|
||||
facet.put(os, os, ' ', &time, format, format + std::strlen(format));
|
||||
auto str = os.str();
|
||||
std::copy(str.begin(), str.end(), out);
|
||||
}
|
||||
|
||||
void on_text(const char_type* begin, const char_type* end) {
|
||||
std::copy(begin, end, out);
|
||||
}
|
||||
|
||||
// These are not implemented because durations don't have date information.
|
||||
void on_abbr_weekday() {}
|
||||
void on_full_weekday() {}
|
||||
void on_dec0_weekday(numeric_system) {}
|
||||
void on_dec1_weekday(numeric_system) {}
|
||||
void on_abbr_month() {}
|
||||
void on_full_month() {}
|
||||
void on_datetime(numeric_system) {}
|
||||
void on_loc_date(numeric_system) {}
|
||||
void on_loc_time(numeric_system) {}
|
||||
void on_us_date() {}
|
||||
void on_iso_date() {}
|
||||
void on_utc_offset() {}
|
||||
void on_tz_name() {}
|
||||
|
||||
void on_24_hour(numeric_system ns) {
|
||||
if (handle_nan_inf()) return;
|
||||
|
||||
if (ns == numeric_system::standard) return write(hour(), 2);
|
||||
auto time = tm();
|
||||
time.tm_hour = to_nonnegative_int(hour(), 24);
|
||||
format_localized(time, "%OH");
|
||||
}
|
||||
|
||||
void on_12_hour(numeric_system ns) {
|
||||
if (handle_nan_inf()) return;
|
||||
|
||||
if (ns == numeric_system::standard) return write(hour12(), 2);
|
||||
auto time = tm();
|
||||
time.tm_hour = to_nonnegative_int(hour12(), 12);
|
||||
format_localized(time, "%OI");
|
||||
}
|
||||
|
||||
void on_minute(numeric_system ns) {
|
||||
if (handle_nan_inf()) return;
|
||||
|
||||
if (ns == numeric_system::standard) return write(minute(), 2);
|
||||
auto time = tm();
|
||||
time.tm_min = to_nonnegative_int(minute(), 60);
|
||||
format_localized(time, "%OM");
|
||||
}
|
||||
|
||||
void on_second(numeric_system ns) {
|
||||
if (handle_nan_inf()) return;
|
||||
|
||||
if (ns == numeric_system::standard) {
|
||||
write(second(), 2);
|
||||
#if FMT_SAFE_DURATION_CAST
|
||||
// convert rep->Rep
|
||||
using duration_rep = std::chrono::duration<rep, Period>;
|
||||
using duration_Rep = std::chrono::duration<Rep, Period>;
|
||||
auto tmpval = fmt_safe_duration_cast<duration_Rep>(duration_rep{val});
|
||||
#else
|
||||
auto tmpval = std::chrono::duration<Rep, Period>(val);
|
||||
#endif
|
||||
auto ms = get_milliseconds(tmpval);
|
||||
if (ms != std::chrono::milliseconds(0)) {
|
||||
*out++ = '.';
|
||||
write(ms.count(), 3);
|
||||
}
|
||||
return;
|
||||
}
|
||||
auto time = tm();
|
||||
time.tm_sec = to_nonnegative_int(second(), 60);
|
||||
format_localized(time, "%OS");
|
||||
}
|
||||
|
||||
void on_12_hour_time() {
|
||||
if (handle_nan_inf()) return;
|
||||
|
||||
format_localized(time(), "%r");
|
||||
}
|
||||
|
||||
void on_24_hour_time() {
|
||||
if (handle_nan_inf()) {
|
||||
*out++ = ':';
|
||||
handle_nan_inf();
|
||||
return;
|
||||
}
|
||||
|
||||
write(hour(), 2);
|
||||
*out++ = ':';
|
||||
write(minute(), 2);
|
||||
}
|
||||
|
||||
void on_iso_time() {
|
||||
on_24_hour_time();
|
||||
*out++ = ':';
|
||||
if (handle_nan_inf()) return;
|
||||
write(second(), 2);
|
||||
}
|
||||
|
||||
void on_am_pm() {
|
||||
if (handle_nan_inf()) return;
|
||||
format_localized(time(), "%p");
|
||||
}
|
||||
|
||||
void on_duration_value() {
|
||||
if (handle_nan_inf()) return;
|
||||
write_sign();
|
||||
out = format_chrono_duration_value(out, val, precision);
|
||||
}
|
||||
|
||||
void on_duration_unit() { out = format_chrono_duration_unit<Period>(out); }
|
||||
};
|
||||
} // namespace internal
|
||||
|
||||
template <typename Rep, typename Period, typename Char>
|
||||
struct formatter<std::chrono::duration<Rep, Period>, Char> {
|
||||
private:
|
||||
basic_format_specs<Char> specs;
|
||||
int precision;
|
||||
using arg_ref_type = internal::arg_ref<Char>;
|
||||
arg_ref_type width_ref;
|
||||
arg_ref_type precision_ref;
|
||||
mutable basic_string_view<Char> format_str;
|
||||
using duration = std::chrono::duration<Rep, Period>;
|
||||
|
||||
struct spec_handler {
|
||||
formatter& f;
|
||||
basic_parse_context<Char>& context;
|
||||
basic_string_view<Char> format_str;
|
||||
|
||||
template <typename Id> FMT_CONSTEXPR arg_ref_type make_arg_ref(Id arg_id) {
|
||||
context.check_arg_id(arg_id);
|
||||
return arg_ref_type(arg_id);
|
||||
}
|
||||
|
||||
FMT_CONSTEXPR arg_ref_type make_arg_ref(basic_string_view<Char> arg_id) {
|
||||
context.check_arg_id(arg_id);
|
||||
const auto str_val = internal::string_view_metadata(format_str, arg_id);
|
||||
return arg_ref_type(str_val);
|
||||
}
|
||||
|
||||
FMT_CONSTEXPR arg_ref_type make_arg_ref(internal::auto_id) {
|
||||
return arg_ref_type(context.next_arg_id());
|
||||
}
|
||||
|
||||
void on_error(const char* msg) { FMT_THROW(format_error(msg)); }
|
||||
void on_fill(Char fill) { f.specs.fill[0] = fill; }
|
||||
void on_align(align_t align) { f.specs.align = align; }
|
||||
void on_width(unsigned width) { f.specs.width = width; }
|
||||
void on_precision(unsigned precision) { f.precision = precision; }
|
||||
void end_precision() {}
|
||||
|
||||
template <typename Id> void on_dynamic_width(Id arg_id) {
|
||||
f.width_ref = make_arg_ref(arg_id);
|
||||
}
|
||||
|
||||
template <typename Id> void on_dynamic_precision(Id arg_id) {
|
||||
f.precision_ref = make_arg_ref(arg_id);
|
||||
}
|
||||
};
|
||||
|
||||
using iterator = typename basic_parse_context<Char>::iterator;
|
||||
struct parse_range {
|
||||
iterator begin;
|
||||
iterator end;
|
||||
};
|
||||
|
||||
FMT_CONSTEXPR parse_range do_parse(basic_parse_context<Char>& ctx) {
|
||||
auto begin = ctx.begin(), end = ctx.end();
|
||||
if (begin == end || *begin == '}') return {begin, begin};
|
||||
spec_handler handler{*this, ctx, format_str};
|
||||
begin = internal::parse_align(begin, end, handler);
|
||||
if (begin == end) return {begin, begin};
|
||||
begin = internal::parse_width(begin, end, handler);
|
||||
if (begin == end) return {begin, begin};
|
||||
if (*begin == '.') {
|
||||
if (std::is_floating_point<Rep>::value)
|
||||
begin = internal::parse_precision(begin, end, handler);
|
||||
else
|
||||
handler.on_error("precision not allowed for this argument type");
|
||||
}
|
||||
end = parse_chrono_format(begin, end, internal::chrono_format_checker());
|
||||
return {begin, end};
|
||||
}
|
||||
|
||||
public:
|
||||
formatter() : precision(-1) {}
|
||||
|
||||
FMT_CONSTEXPR auto parse(basic_parse_context<Char>& ctx)
|
||||
-> decltype(ctx.begin()) {
|
||||
auto range = do_parse(ctx);
|
||||
format_str = basic_string_view<Char>(
|
||||
&*range.begin, internal::to_unsigned(range.end - range.begin));
|
||||
return range.end;
|
||||
}
|
||||
|
||||
template <typename FormatContext>
|
||||
auto format(const duration& d, FormatContext& ctx) -> decltype(ctx.out()) {
|
||||
auto begin = format_str.begin(), end = format_str.end();
|
||||
// As a possible future optimization, we could avoid extra copying if width
|
||||
// is not specified.
|
||||
basic_memory_buffer<Char> buf;
|
||||
auto out = std::back_inserter(buf);
|
||||
using range = internal::output_range<decltype(ctx.out()), Char>;
|
||||
internal::basic_writer<range> w(range(ctx.out()));
|
||||
internal::handle_dynamic_spec<internal::width_checker>(
|
||||
specs.width, width_ref, ctx, format_str.begin());
|
||||
internal::handle_dynamic_spec<internal::precision_checker>(
|
||||
precision, precision_ref, ctx, format_str.begin());
|
||||
if (begin == end || *begin == '}') {
|
||||
out = internal::format_chrono_duration_value(out, d.count(), precision);
|
||||
internal::format_chrono_duration_unit<Period>(out);
|
||||
} else {
|
||||
internal::chrono_formatter<FormatContext, decltype(out), Rep, Period> f(
|
||||
ctx, out, d);
|
||||
f.precision = precision;
|
||||
parse_chrono_format(begin, end, f);
|
||||
}
|
||||
w.write(buf.data(), buf.size(), specs);
|
||||
return w.out();
|
||||
}
|
||||
};
|
||||
|
||||
FMT_END_NAMESPACE
|
||||
|
||||
#endif // FMT_CHRONO_H_
|
585
vtkm/thirdparty/diy/vtkmdiy/include/vtkmdiy/thirdparty/fmt/color.h
vendored
Normal file
585
vtkm/thirdparty/diy/vtkmdiy/include/vtkmdiy/thirdparty/fmt/color.h
vendored
Normal file
@ -0,0 +1,585 @@
|
||||
// Formatting library for C++ - color support
|
||||
//
|
||||
// Copyright (c) 2018 - present, Victor Zverovich and fmt contributors
|
||||
// All rights reserved.
|
||||
//
|
||||
// For the license information refer to format.h.
|
||||
|
||||
#ifndef FMT_COLOR_H_
|
||||
#define FMT_COLOR_H_
|
||||
|
||||
#include "format.h"
|
||||
|
||||
FMT_BEGIN_NAMESPACE
|
||||
|
||||
enum class color : uint32_t {
|
||||
alice_blue = 0xF0F8FF, // rgb(240,248,255)
|
||||
antique_white = 0xFAEBD7, // rgb(250,235,215)
|
||||
aqua = 0x00FFFF, // rgb(0,255,255)
|
||||
aquamarine = 0x7FFFD4, // rgb(127,255,212)
|
||||
azure = 0xF0FFFF, // rgb(240,255,255)
|
||||
beige = 0xF5F5DC, // rgb(245,245,220)
|
||||
bisque = 0xFFE4C4, // rgb(255,228,196)
|
||||
black = 0x000000, // rgb(0,0,0)
|
||||
blanched_almond = 0xFFEBCD, // rgb(255,235,205)
|
||||
blue = 0x0000FF, // rgb(0,0,255)
|
||||
blue_violet = 0x8A2BE2, // rgb(138,43,226)
|
||||
brown = 0xA52A2A, // rgb(165,42,42)
|
||||
burly_wood = 0xDEB887, // rgb(222,184,135)
|
||||
cadet_blue = 0x5F9EA0, // rgb(95,158,160)
|
||||
chartreuse = 0x7FFF00, // rgb(127,255,0)
|
||||
chocolate = 0xD2691E, // rgb(210,105,30)
|
||||
coral = 0xFF7F50, // rgb(255,127,80)
|
||||
cornflower_blue = 0x6495ED, // rgb(100,149,237)
|
||||
cornsilk = 0xFFF8DC, // rgb(255,248,220)
|
||||
crimson = 0xDC143C, // rgb(220,20,60)
|
||||
cyan = 0x00FFFF, // rgb(0,255,255)
|
||||
dark_blue = 0x00008B, // rgb(0,0,139)
|
||||
dark_cyan = 0x008B8B, // rgb(0,139,139)
|
||||
dark_golden_rod = 0xB8860B, // rgb(184,134,11)
|
||||
dark_gray = 0xA9A9A9, // rgb(169,169,169)
|
||||
dark_green = 0x006400, // rgb(0,100,0)
|
||||
dark_khaki = 0xBDB76B, // rgb(189,183,107)
|
||||
dark_magenta = 0x8B008B, // rgb(139,0,139)
|
||||
dark_olive_green = 0x556B2F, // rgb(85,107,47)
|
||||
dark_orange = 0xFF8C00, // rgb(255,140,0)
|
||||
dark_orchid = 0x9932CC, // rgb(153,50,204)
|
||||
dark_red = 0x8B0000, // rgb(139,0,0)
|
||||
dark_salmon = 0xE9967A, // rgb(233,150,122)
|
||||
dark_sea_green = 0x8FBC8F, // rgb(143,188,143)
|
||||
dark_slate_blue = 0x483D8B, // rgb(72,61,139)
|
||||
dark_slate_gray = 0x2F4F4F, // rgb(47,79,79)
|
||||
dark_turquoise = 0x00CED1, // rgb(0,206,209)
|
||||
dark_violet = 0x9400D3, // rgb(148,0,211)
|
||||
deep_pink = 0xFF1493, // rgb(255,20,147)
|
||||
deep_sky_blue = 0x00BFFF, // rgb(0,191,255)
|
||||
dim_gray = 0x696969, // rgb(105,105,105)
|
||||
dodger_blue = 0x1E90FF, // rgb(30,144,255)
|
||||
fire_brick = 0xB22222, // rgb(178,34,34)
|
||||
floral_white = 0xFFFAF0, // rgb(255,250,240)
|
||||
forest_green = 0x228B22, // rgb(34,139,34)
|
||||
fuchsia = 0xFF00FF, // rgb(255,0,255)
|
||||
gainsboro = 0xDCDCDC, // rgb(220,220,220)
|
||||
ghost_white = 0xF8F8FF, // rgb(248,248,255)
|
||||
gold = 0xFFD700, // rgb(255,215,0)
|
||||
golden_rod = 0xDAA520, // rgb(218,165,32)
|
||||
gray = 0x808080, // rgb(128,128,128)
|
||||
green = 0x008000, // rgb(0,128,0)
|
||||
green_yellow = 0xADFF2F, // rgb(173,255,47)
|
||||
honey_dew = 0xF0FFF0, // rgb(240,255,240)
|
||||
hot_pink = 0xFF69B4, // rgb(255,105,180)
|
||||
indian_red = 0xCD5C5C, // rgb(205,92,92)
|
||||
indigo = 0x4B0082, // rgb(75,0,130)
|
||||
ivory = 0xFFFFF0, // rgb(255,255,240)
|
||||
khaki = 0xF0E68C, // rgb(240,230,140)
|
||||
lavender = 0xE6E6FA, // rgb(230,230,250)
|
||||
lavender_blush = 0xFFF0F5, // rgb(255,240,245)
|
||||
lawn_green = 0x7CFC00, // rgb(124,252,0)
|
||||
lemon_chiffon = 0xFFFACD, // rgb(255,250,205)
|
||||
light_blue = 0xADD8E6, // rgb(173,216,230)
|
||||
light_coral = 0xF08080, // rgb(240,128,128)
|
||||
light_cyan = 0xE0FFFF, // rgb(224,255,255)
|
||||
light_golden_rod_yellow = 0xFAFAD2, // rgb(250,250,210)
|
||||
light_gray = 0xD3D3D3, // rgb(211,211,211)
|
||||
light_green = 0x90EE90, // rgb(144,238,144)
|
||||
light_pink = 0xFFB6C1, // rgb(255,182,193)
|
||||
light_salmon = 0xFFA07A, // rgb(255,160,122)
|
||||
light_sea_green = 0x20B2AA, // rgb(32,178,170)
|
||||
light_sky_blue = 0x87CEFA, // rgb(135,206,250)
|
||||
light_slate_gray = 0x778899, // rgb(119,136,153)
|
||||
light_steel_blue = 0xB0C4DE, // rgb(176,196,222)
|
||||
light_yellow = 0xFFFFE0, // rgb(255,255,224)
|
||||
lime = 0x00FF00, // rgb(0,255,0)
|
||||
lime_green = 0x32CD32, // rgb(50,205,50)
|
||||
linen = 0xFAF0E6, // rgb(250,240,230)
|
||||
magenta = 0xFF00FF, // rgb(255,0,255)
|
||||
maroon = 0x800000, // rgb(128,0,0)
|
||||
medium_aquamarine = 0x66CDAA, // rgb(102,205,170)
|
||||
medium_blue = 0x0000CD, // rgb(0,0,205)
|
||||
medium_orchid = 0xBA55D3, // rgb(186,85,211)
|
||||
medium_purple = 0x9370DB, // rgb(147,112,219)
|
||||
medium_sea_green = 0x3CB371, // rgb(60,179,113)
|
||||
medium_slate_blue = 0x7B68EE, // rgb(123,104,238)
|
||||
medium_spring_green = 0x00FA9A, // rgb(0,250,154)
|
||||
medium_turquoise = 0x48D1CC, // rgb(72,209,204)
|
||||
medium_violet_red = 0xC71585, // rgb(199,21,133)
|
||||
midnight_blue = 0x191970, // rgb(25,25,112)
|
||||
mint_cream = 0xF5FFFA, // rgb(245,255,250)
|
||||
misty_rose = 0xFFE4E1, // rgb(255,228,225)
|
||||
moccasin = 0xFFE4B5, // rgb(255,228,181)
|
||||
navajo_white = 0xFFDEAD, // rgb(255,222,173)
|
||||
navy = 0x000080, // rgb(0,0,128)
|
||||
old_lace = 0xFDF5E6, // rgb(253,245,230)
|
||||
olive = 0x808000, // rgb(128,128,0)
|
||||
olive_drab = 0x6B8E23, // rgb(107,142,35)
|
||||
orange = 0xFFA500, // rgb(255,165,0)
|
||||
orange_red = 0xFF4500, // rgb(255,69,0)
|
||||
orchid = 0xDA70D6, // rgb(218,112,214)
|
||||
pale_golden_rod = 0xEEE8AA, // rgb(238,232,170)
|
||||
pale_green = 0x98FB98, // rgb(152,251,152)
|
||||
pale_turquoise = 0xAFEEEE, // rgb(175,238,238)
|
||||
pale_violet_red = 0xDB7093, // rgb(219,112,147)
|
||||
papaya_whip = 0xFFEFD5, // rgb(255,239,213)
|
||||
peach_puff = 0xFFDAB9, // rgb(255,218,185)
|
||||
peru = 0xCD853F, // rgb(205,133,63)
|
||||
pink = 0xFFC0CB, // rgb(255,192,203)
|
||||
plum = 0xDDA0DD, // rgb(221,160,221)
|
||||
powder_blue = 0xB0E0E6, // rgb(176,224,230)
|
||||
purple = 0x800080, // rgb(128,0,128)
|
||||
rebecca_purple = 0x663399, // rgb(102,51,153)
|
||||
red = 0xFF0000, // rgb(255,0,0)
|
||||
rosy_brown = 0xBC8F8F, // rgb(188,143,143)
|
||||
royal_blue = 0x4169E1, // rgb(65,105,225)
|
||||
saddle_brown = 0x8B4513, // rgb(139,69,19)
|
||||
salmon = 0xFA8072, // rgb(250,128,114)
|
||||
sandy_brown = 0xF4A460, // rgb(244,164,96)
|
||||
sea_green = 0x2E8B57, // rgb(46,139,87)
|
||||
sea_shell = 0xFFF5EE, // rgb(255,245,238)
|
||||
sienna = 0xA0522D, // rgb(160,82,45)
|
||||
silver = 0xC0C0C0, // rgb(192,192,192)
|
||||
sky_blue = 0x87CEEB, // rgb(135,206,235)
|
||||
slate_blue = 0x6A5ACD, // rgb(106,90,205)
|
||||
slate_gray = 0x708090, // rgb(112,128,144)
|
||||
snow = 0xFFFAFA, // rgb(255,250,250)
|
||||
spring_green = 0x00FF7F, // rgb(0,255,127)
|
||||
steel_blue = 0x4682B4, // rgb(70,130,180)
|
||||
tan = 0xD2B48C, // rgb(210,180,140)
|
||||
teal = 0x008080, // rgb(0,128,128)
|
||||
thistle = 0xD8BFD8, // rgb(216,191,216)
|
||||
tomato = 0xFF6347, // rgb(255,99,71)
|
||||
turquoise = 0x40E0D0, // rgb(64,224,208)
|
||||
violet = 0xEE82EE, // rgb(238,130,238)
|
||||
wheat = 0xF5DEB3, // rgb(245,222,179)
|
||||
white = 0xFFFFFF, // rgb(255,255,255)
|
||||
white_smoke = 0xF5F5F5, // rgb(245,245,245)
|
||||
yellow = 0xFFFF00, // rgb(255,255,0)
|
||||
yellow_green = 0x9ACD32 // rgb(154,205,50)
|
||||
}; // enum class color
|
||||
|
||||
enum class terminal_color : uint8_t {
|
||||
black = 30,
|
||||
red,
|
||||
green,
|
||||
yellow,
|
||||
blue,
|
||||
magenta,
|
||||
cyan,
|
||||
white,
|
||||
bright_black = 90,
|
||||
bright_red,
|
||||
bright_green,
|
||||
bright_yellow,
|
||||
bright_blue,
|
||||
bright_magenta,
|
||||
bright_cyan,
|
||||
bright_white
|
||||
};
|
||||
|
||||
enum class emphasis : uint8_t {
|
||||
bold = 1,
|
||||
italic = 1 << 1,
|
||||
underline = 1 << 2,
|
||||
strikethrough = 1 << 3
|
||||
};
|
||||
|
||||
// rgb is a struct for red, green and blue colors.
|
||||
// Using the name "rgb" makes some editors show the color in a tooltip.
|
||||
struct rgb {
|
||||
FMT_CONSTEXPR rgb() : r(0), g(0), b(0) {}
|
||||
FMT_CONSTEXPR rgb(uint8_t r_, uint8_t g_, uint8_t b_) : r(r_), g(g_), b(b_) {}
|
||||
FMT_CONSTEXPR rgb(uint32_t hex)
|
||||
: r((hex >> 16) & 0xFF), g((hex >> 8) & 0xFF), b(hex & 0xFF) {}
|
||||
FMT_CONSTEXPR rgb(color hex)
|
||||
: r((uint32_t(hex) >> 16) & 0xFF),
|
||||
g((uint32_t(hex) >> 8) & 0xFF),
|
||||
b(uint32_t(hex) & 0xFF) {}
|
||||
uint8_t r;
|
||||
uint8_t g;
|
||||
uint8_t b;
|
||||
};
|
||||
|
||||
namespace internal {
|
||||
|
||||
// color is a struct of either a rgb color or a terminal color.
|
||||
struct color_type {
|
||||
FMT_CONSTEXPR color_type() FMT_NOEXCEPT : is_rgb(), value{} {}
|
||||
FMT_CONSTEXPR color_type(color rgb_color) FMT_NOEXCEPT : is_rgb(true),
|
||||
value{} {
|
||||
value.rgb_color = static_cast<uint32_t>(rgb_color);
|
||||
}
|
||||
FMT_CONSTEXPR color_type(rgb rgb_color) FMT_NOEXCEPT : is_rgb(true), value{} {
|
||||
value.rgb_color = (static_cast<uint32_t>(rgb_color.r) << 16) |
|
||||
(static_cast<uint32_t>(rgb_color.g) << 8) | rgb_color.b;
|
||||
}
|
||||
FMT_CONSTEXPR color_type(terminal_color term_color) FMT_NOEXCEPT : is_rgb(),
|
||||
value{} {
|
||||
value.term_color = static_cast<uint8_t>(term_color);
|
||||
}
|
||||
bool is_rgb;
|
||||
union color_union {
|
||||
uint8_t term_color;
|
||||
uint32_t rgb_color;
|
||||
} value;
|
||||
};
|
||||
} // namespace internal
|
||||
|
||||
// Experimental text formatting support.
|
||||
class text_style {
|
||||
public:
|
||||
FMT_CONSTEXPR text_style(emphasis em = emphasis()) FMT_NOEXCEPT
|
||||
: set_foreground_color(),
|
||||
set_background_color(),
|
||||
ems(em) {}
|
||||
|
||||
FMT_CONSTEXPR text_style& operator|=(const text_style& rhs) {
|
||||
if (!set_foreground_color) {
|
||||
set_foreground_color = rhs.set_foreground_color;
|
||||
foreground_color = rhs.foreground_color;
|
||||
} else if (rhs.set_foreground_color) {
|
||||
if (!foreground_color.is_rgb || !rhs.foreground_color.is_rgb)
|
||||
FMT_THROW(format_error("can't OR a terminal color"));
|
||||
foreground_color.value.rgb_color |= rhs.foreground_color.value.rgb_color;
|
||||
}
|
||||
|
||||
if (!set_background_color) {
|
||||
set_background_color = rhs.set_background_color;
|
||||
background_color = rhs.background_color;
|
||||
} else if (rhs.set_background_color) {
|
||||
if (!background_color.is_rgb || !rhs.background_color.is_rgb)
|
||||
FMT_THROW(format_error("can't OR a terminal color"));
|
||||
background_color.value.rgb_color |= rhs.background_color.value.rgb_color;
|
||||
}
|
||||
|
||||
ems = static_cast<emphasis>(static_cast<uint8_t>(ems) |
|
||||
static_cast<uint8_t>(rhs.ems));
|
||||
return *this;
|
||||
}
|
||||
|
||||
friend FMT_CONSTEXPR text_style operator|(text_style lhs,
|
||||
const text_style& rhs) {
|
||||
return lhs |= rhs;
|
||||
}
|
||||
|
||||
FMT_CONSTEXPR text_style& operator&=(const text_style& rhs) {
|
||||
if (!set_foreground_color) {
|
||||
set_foreground_color = rhs.set_foreground_color;
|
||||
foreground_color = rhs.foreground_color;
|
||||
} else if (rhs.set_foreground_color) {
|
||||
if (!foreground_color.is_rgb || !rhs.foreground_color.is_rgb)
|
||||
FMT_THROW(format_error("can't AND a terminal color"));
|
||||
foreground_color.value.rgb_color &= rhs.foreground_color.value.rgb_color;
|
||||
}
|
||||
|
||||
if (!set_background_color) {
|
||||
set_background_color = rhs.set_background_color;
|
||||
background_color = rhs.background_color;
|
||||
} else if (rhs.set_background_color) {
|
||||
if (!background_color.is_rgb || !rhs.background_color.is_rgb)
|
||||
FMT_THROW(format_error("can't AND a terminal color"));
|
||||
background_color.value.rgb_color &= rhs.background_color.value.rgb_color;
|
||||
}
|
||||
|
||||
ems = static_cast<emphasis>(static_cast<uint8_t>(ems) &
|
||||
static_cast<uint8_t>(rhs.ems));
|
||||
return *this;
|
||||
}
|
||||
|
||||
friend FMT_CONSTEXPR text_style operator&(text_style lhs,
|
||||
const text_style& rhs) {
|
||||
return lhs &= rhs;
|
||||
}
|
||||
|
||||
FMT_CONSTEXPR bool has_foreground() const FMT_NOEXCEPT {
|
||||
return set_foreground_color;
|
||||
}
|
||||
FMT_CONSTEXPR bool has_background() const FMT_NOEXCEPT {
|
||||
return set_background_color;
|
||||
}
|
||||
FMT_CONSTEXPR bool has_emphasis() const FMT_NOEXCEPT {
|
||||
return static_cast<uint8_t>(ems) != 0;
|
||||
}
|
||||
FMT_CONSTEXPR internal::color_type get_foreground() const FMT_NOEXCEPT {
|
||||
assert(has_foreground() && "no foreground specified for this style");
|
||||
return foreground_color;
|
||||
}
|
||||
FMT_CONSTEXPR internal::color_type get_background() const FMT_NOEXCEPT {
|
||||
assert(has_background() && "no background specified for this style");
|
||||
return background_color;
|
||||
}
|
||||
FMT_CONSTEXPR emphasis get_emphasis() const FMT_NOEXCEPT {
|
||||
assert(has_emphasis() && "no emphasis specified for this style");
|
||||
return ems;
|
||||
}
|
||||
|
||||
private:
|
||||
FMT_CONSTEXPR text_style(bool is_foreground,
|
||||
internal::color_type text_color) FMT_NOEXCEPT
|
||||
: set_foreground_color(),
|
||||
set_background_color(),
|
||||
ems() {
|
||||
if (is_foreground) {
|
||||
foreground_color = text_color;
|
||||
set_foreground_color = true;
|
||||
} else {
|
||||
background_color = text_color;
|
||||
set_background_color = true;
|
||||
}
|
||||
}
|
||||
|
||||
friend FMT_CONSTEXPR_DECL text_style fg(internal::color_type foreground)
|
||||
FMT_NOEXCEPT;
|
||||
friend FMT_CONSTEXPR_DECL text_style bg(internal::color_type background)
|
||||
FMT_NOEXCEPT;
|
||||
|
||||
internal::color_type foreground_color;
|
||||
internal::color_type background_color;
|
||||
bool set_foreground_color;
|
||||
bool set_background_color;
|
||||
emphasis ems;
|
||||
};
|
||||
|
||||
FMT_CONSTEXPR text_style fg(internal::color_type foreground) FMT_NOEXCEPT {
|
||||
return text_style(/*is_foreground=*/true, foreground);
|
||||
}
|
||||
|
||||
FMT_CONSTEXPR text_style bg(internal::color_type background) FMT_NOEXCEPT {
|
||||
return text_style(/*is_foreground=*/false, background);
|
||||
}
|
||||
|
||||
FMT_CONSTEXPR text_style operator|(emphasis lhs, emphasis rhs) FMT_NOEXCEPT {
|
||||
return text_style(lhs) | rhs;
|
||||
}
|
||||
|
||||
namespace internal {
|
||||
|
||||
template <typename Char> struct ansi_color_escape {
|
||||
FMT_CONSTEXPR ansi_color_escape(internal::color_type text_color,
|
||||
const char* esc) FMT_NOEXCEPT {
|
||||
// If we have a terminal color, we need to output another escape code
|
||||
// sequence.
|
||||
if (!text_color.is_rgb) {
|
||||
bool is_background = esc == internal::data::background_color;
|
||||
uint32_t value = text_color.value.term_color;
|
||||
// Background ASCII codes are the same as the foreground ones but with
|
||||
// 10 more.
|
||||
if (is_background) value += 10u;
|
||||
|
||||
std::size_t index = 0;
|
||||
buffer[index++] = static_cast<Char>('\x1b');
|
||||
buffer[index++] = static_cast<Char>('[');
|
||||
|
||||
if (value >= 100u) {
|
||||
buffer[index++] = static_cast<Char>('1');
|
||||
value %= 100u;
|
||||
}
|
||||
buffer[index++] = static_cast<Char>('0' + value / 10u);
|
||||
buffer[index++] = static_cast<Char>('0' + value % 10u);
|
||||
|
||||
buffer[index++] = static_cast<Char>('m');
|
||||
buffer[index++] = static_cast<Char>('\0');
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 7; i++) {
|
||||
buffer[i] = static_cast<Char>(esc[i]);
|
||||
}
|
||||
rgb color(text_color.value.rgb_color);
|
||||
to_esc(color.r, buffer + 7, ';');
|
||||
to_esc(color.g, buffer + 11, ';');
|
||||
to_esc(color.b, buffer + 15, 'm');
|
||||
buffer[19] = static_cast<Char>(0);
|
||||
}
|
||||
FMT_CONSTEXPR ansi_color_escape(emphasis em) FMT_NOEXCEPT {
|
||||
uint8_t em_codes[4] = {};
|
||||
uint8_t em_bits = static_cast<uint8_t>(em);
|
||||
if (em_bits & static_cast<uint8_t>(emphasis::bold)) em_codes[0] = 1;
|
||||
if (em_bits & static_cast<uint8_t>(emphasis::italic)) em_codes[1] = 3;
|
||||
if (em_bits & static_cast<uint8_t>(emphasis::underline)) em_codes[2] = 4;
|
||||
if (em_bits & static_cast<uint8_t>(emphasis::strikethrough))
|
||||
em_codes[3] = 9;
|
||||
|
||||
std::size_t index = 0;
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
if (!em_codes[i]) continue;
|
||||
buffer[index++] = static_cast<Char>('\x1b');
|
||||
buffer[index++] = static_cast<Char>('[');
|
||||
buffer[index++] = static_cast<Char>('0' + em_codes[i]);
|
||||
buffer[index++] = static_cast<Char>('m');
|
||||
}
|
||||
buffer[index++] = static_cast<Char>(0);
|
||||
}
|
||||
FMT_CONSTEXPR operator const Char*() const FMT_NOEXCEPT { return buffer; }
|
||||
|
||||
FMT_CONSTEXPR const Char* begin() const FMT_NOEXCEPT { return buffer; }
|
||||
FMT_CONSTEXPR const Char* end() const FMT_NOEXCEPT {
|
||||
return buffer + std::strlen(buffer);
|
||||
}
|
||||
|
||||
private:
|
||||
Char buffer[7u + 3u * 4u + 1u];
|
||||
|
||||
static FMT_CONSTEXPR void to_esc(uint8_t c, Char* out,
|
||||
char delimiter) FMT_NOEXCEPT {
|
||||
out[0] = static_cast<Char>('0' + c / 100);
|
||||
out[1] = static_cast<Char>('0' + c / 10 % 10);
|
||||
out[2] = static_cast<Char>('0' + c % 10);
|
||||
out[3] = static_cast<Char>(delimiter);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Char>
|
||||
FMT_CONSTEXPR ansi_color_escape<Char> make_foreground_color(
|
||||
internal::color_type foreground) FMT_NOEXCEPT {
|
||||
return ansi_color_escape<Char>(foreground, internal::data::foreground_color);
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
FMT_CONSTEXPR ansi_color_escape<Char> make_background_color(
|
||||
internal::color_type background) FMT_NOEXCEPT {
|
||||
return ansi_color_escape<Char>(background, internal::data::background_color);
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
FMT_CONSTEXPR ansi_color_escape<Char> make_emphasis(emphasis em) FMT_NOEXCEPT {
|
||||
return ansi_color_escape<Char>(em);
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
inline void fputs(const Char* chars, FILE* stream) FMT_NOEXCEPT {
|
||||
std::fputs(chars, stream);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline void fputs<wchar_t>(const wchar_t* chars, FILE* stream) FMT_NOEXCEPT {
|
||||
std::fputws(chars, stream);
|
||||
}
|
||||
|
||||
template <typename Char> inline void reset_color(FILE* stream) FMT_NOEXCEPT {
|
||||
fputs(internal::data::reset_color, stream);
|
||||
}
|
||||
|
||||
template <> inline void reset_color<wchar_t>(FILE* stream) FMT_NOEXCEPT {
|
||||
fputs(internal::data::wreset_color, stream);
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
inline void reset_color(basic_memory_buffer<Char>& buffer) FMT_NOEXCEPT {
|
||||
const char* begin = data::reset_color;
|
||||
const char* end = begin + sizeof(data::reset_color) - 1;
|
||||
buffer.append(begin, end);
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
std::basic_string<Char> vformat(const text_style& ts,
|
||||
basic_string_view<Char> format_str,
|
||||
basic_format_args<buffer_context<Char> > args) {
|
||||
basic_memory_buffer<Char> buffer;
|
||||
bool has_style = false;
|
||||
if (ts.has_emphasis()) {
|
||||
has_style = true;
|
||||
ansi_color_escape<Char> escape = make_emphasis<Char>(ts.get_emphasis());
|
||||
buffer.append(escape.begin(), escape.end());
|
||||
}
|
||||
if (ts.has_foreground()) {
|
||||
has_style = true;
|
||||
ansi_color_escape<Char> escape =
|
||||
make_foreground_color<Char>(ts.get_foreground());
|
||||
buffer.append(escape.begin(), escape.end());
|
||||
}
|
||||
if (ts.has_background()) {
|
||||
has_style = true;
|
||||
ansi_color_escape<Char> escape =
|
||||
make_background_color<Char>(ts.get_background());
|
||||
buffer.append(escape.begin(), escape.end());
|
||||
}
|
||||
internal::vformat_to(buffer, format_str, args);
|
||||
if (has_style) {
|
||||
reset_color<Char>(buffer);
|
||||
}
|
||||
return fmt::to_string(buffer);
|
||||
}
|
||||
} // namespace internal
|
||||
|
||||
template <typename S, typename Char = char_t<S> >
|
||||
void vprint(std::FILE* f, const text_style& ts, const S& format,
|
||||
basic_format_args<buffer_context<Char> > args) {
|
||||
bool has_style = false;
|
||||
if (ts.has_emphasis()) {
|
||||
has_style = true;
|
||||
internal::fputs<Char>(internal::make_emphasis<Char>(ts.get_emphasis()), f);
|
||||
}
|
||||
if (ts.has_foreground()) {
|
||||
has_style = true;
|
||||
internal::fputs<Char>(
|
||||
internal::make_foreground_color<Char>(ts.get_foreground()), f);
|
||||
}
|
||||
if (ts.has_background()) {
|
||||
has_style = true;
|
||||
internal::fputs<Char>(
|
||||
internal::make_background_color<Char>(ts.get_background()), f);
|
||||
}
|
||||
vprint(f, format, args);
|
||||
if (has_style) {
|
||||
internal::reset_color<Char>(f);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Formats a string and prints it to the specified file stream using ANSI
|
||||
escape sequences to specify text formatting.
|
||||
Example:
|
||||
fmt::print(fmt::emphasis::bold | fg(fmt::color::red),
|
||||
"Elapsed time: {0:.2f} seconds", 1.23);
|
||||
*/
|
||||
template <typename S, typename... Args,
|
||||
FMT_ENABLE_IF(internal::is_string<S>::value)>
|
||||
void print(std::FILE* f, const text_style& ts, const S& format_str,
|
||||
const Args&... args) {
|
||||
internal::check_format_string<Args...>(format_str);
|
||||
using context = buffer_context<char_t<S> >;
|
||||
format_arg_store<context, Args...> as{args...};
|
||||
vprint(f, ts, format_str, basic_format_args<context>(as));
|
||||
}
|
||||
|
||||
/**
|
||||
Formats a string and prints it to stdout using ANSI escape sequences to
|
||||
specify text formatting.
|
||||
Example:
|
||||
fmt::print(fmt::emphasis::bold | fg(fmt::color::red),
|
||||
"Elapsed time: {0:.2f} seconds", 1.23);
|
||||
*/
|
||||
template <typename S, typename... Args,
|
||||
FMT_ENABLE_IF(internal::is_string<S>::value)>
|
||||
void print(const text_style& ts, const S& format_str, const Args&... args) {
|
||||
return print(stdout, ts, format_str, args...);
|
||||
}
|
||||
|
||||
template <typename S, typename Char = char_t<S> >
|
||||
inline std::basic_string<Char> vformat(
|
||||
const text_style& ts, const S& format_str,
|
||||
basic_format_args<buffer_context<Char> > args) {
|
||||
return internal::vformat(ts, to_string_view(format_str), args);
|
||||
}
|
||||
|
||||
/**
|
||||
\rst
|
||||
Formats arguments and returns the result as a string using ANSI
|
||||
escape sequences to specify text formatting.
|
||||
|
||||
**Example**::
|
||||
|
||||
#include <fmt/color.h>
|
||||
std::string message = fmt::format(fmt::emphasis::bold | fg(fmt::color::red),
|
||||
"The answer is {}", 42);
|
||||
\endrst
|
||||
*/
|
||||
template <typename S, typename... Args, typename Char = char_t<S> >
|
||||
inline std::basic_string<Char> format(const text_style& ts, const S& format_str,
|
||||
const Args&... args) {
|
||||
return internal::vformat(ts, to_string_view(format_str),
|
||||
{internal::make_args_checked(format_str, args...)});
|
||||
}
|
||||
|
||||
FMT_END_NAMESPACE
|
||||
|
||||
#endif // FMT_COLOR_H_
|
466
vtkm/thirdparty/diy/vtkmdiy/include/vtkmdiy/thirdparty/fmt/compile.h
vendored
Normal file
466
vtkm/thirdparty/diy/vtkmdiy/include/vtkmdiy/thirdparty/fmt/compile.h
vendored
Normal file
@ -0,0 +1,466 @@
|
||||
// Formatting library for C++ - experimental format string compilation
|
||||
//
|
||||
// Copyright (c) 2012 - present, Victor Zverovich and fmt contributors
|
||||
// All rights reserved.
|
||||
//
|
||||
// For the license information refer to format.h.
|
||||
|
||||
#ifndef FMT_COMPILE_H_
|
||||
#define FMT_COMPILE_H_
|
||||
|
||||
#include <vector>
|
||||
#include "format.h"
|
||||
|
||||
FMT_BEGIN_NAMESPACE
|
||||
namespace internal {
|
||||
|
||||
template <typename Char> struct format_part {
|
||||
public:
|
||||
struct named_argument_id {
|
||||
FMT_CONSTEXPR named_argument_id(internal::string_view_metadata id)
|
||||
: id(id) {}
|
||||
internal::string_view_metadata id;
|
||||
};
|
||||
|
||||
struct argument_id {
|
||||
FMT_CONSTEXPR argument_id() : argument_id(0u) {}
|
||||
|
||||
FMT_CONSTEXPR argument_id(unsigned id)
|
||||
: which(which_arg_id::index), val(id) {}
|
||||
|
||||
FMT_CONSTEXPR argument_id(internal::string_view_metadata id)
|
||||
: which(which_arg_id::named_index), val(id) {}
|
||||
|
||||
enum class which_arg_id { index, named_index };
|
||||
|
||||
which_arg_id which;
|
||||
|
||||
union value {
|
||||
FMT_CONSTEXPR value() : index(0u) {}
|
||||
FMT_CONSTEXPR value(unsigned id) : index(id) {}
|
||||
FMT_CONSTEXPR value(internal::string_view_metadata id)
|
||||
: named_index(id) {}
|
||||
|
||||
unsigned index;
|
||||
internal::string_view_metadata named_index;
|
||||
} val;
|
||||
};
|
||||
|
||||
struct specification {
|
||||
FMT_CONSTEXPR specification() : arg_id(0u) {}
|
||||
FMT_CONSTEXPR specification(unsigned id) : arg_id(id) {}
|
||||
|
||||
FMT_CONSTEXPR specification(internal::string_view_metadata id)
|
||||
: arg_id(id) {}
|
||||
|
||||
argument_id arg_id;
|
||||
internal::dynamic_format_specs<Char> parsed_specs;
|
||||
};
|
||||
|
||||
FMT_CONSTEXPR format_part()
|
||||
: which(kind::argument_id), end_of_argument_id(0u), val(0u) {}
|
||||
|
||||
FMT_CONSTEXPR format_part(internal::string_view_metadata text)
|
||||
: which(kind::text), end_of_argument_id(0u), val(text) {}
|
||||
|
||||
FMT_CONSTEXPR format_part(unsigned id)
|
||||
: which(kind::argument_id), end_of_argument_id(0u), val(id) {}
|
||||
|
||||
FMT_CONSTEXPR format_part(named_argument_id arg_id)
|
||||
: which(kind::named_argument_id), end_of_argument_id(0u), val(arg_id) {}
|
||||
|
||||
FMT_CONSTEXPR format_part(specification spec)
|
||||
: which(kind::specification), end_of_argument_id(0u), val(spec) {}
|
||||
|
||||
enum class kind { argument_id, named_argument_id, text, specification };
|
||||
|
||||
kind which;
|
||||
std::size_t end_of_argument_id;
|
||||
union value {
|
||||
FMT_CONSTEXPR value() : arg_id(0u) {}
|
||||
FMT_CONSTEXPR value(unsigned id) : arg_id(id) {}
|
||||
FMT_CONSTEXPR value(named_argument_id named_id)
|
||||
: named_arg_id(named_id.id) {}
|
||||
FMT_CONSTEXPR value(internal::string_view_metadata t) : text(t) {}
|
||||
FMT_CONSTEXPR value(specification s) : spec(s) {}
|
||||
unsigned arg_id;
|
||||
internal::string_view_metadata named_arg_id;
|
||||
internal::string_view_metadata text;
|
||||
specification spec;
|
||||
} val;
|
||||
};
|
||||
|
||||
template <typename Char, typename PartsContainer>
|
||||
class format_preparation_handler : public internal::error_handler {
|
||||
private:
|
||||
using part = format_part<Char>;
|
||||
|
||||
public:
|
||||
using iterator = typename basic_string_view<Char>::iterator;
|
||||
|
||||
FMT_CONSTEXPR format_preparation_handler(basic_string_view<Char> format,
|
||||
PartsContainer& parts)
|
||||
: parts_(parts), format_(format), parse_context_(format) {}
|
||||
|
||||
FMT_CONSTEXPR void on_text(const Char* begin, const Char* end) {
|
||||
if (begin == end) return;
|
||||
const auto offset = begin - format_.data();
|
||||
const auto size = end - begin;
|
||||
parts_.push_back(part(string_view_metadata(offset, size)));
|
||||
}
|
||||
|
||||
FMT_CONSTEXPR void on_arg_id() {
|
||||
parts_.push_back(part(parse_context_.next_arg_id()));
|
||||
}
|
||||
|
||||
FMT_CONSTEXPR void on_arg_id(unsigned id) {
|
||||
parse_context_.check_arg_id(id);
|
||||
parts_.push_back(part(id));
|
||||
}
|
||||
|
||||
FMT_CONSTEXPR void on_arg_id(basic_string_view<Char> id) {
|
||||
const auto view = string_view_metadata(format_, id);
|
||||
const auto arg_id = typename part::named_argument_id(view);
|
||||
parts_.push_back(part(arg_id));
|
||||
}
|
||||
|
||||
FMT_CONSTEXPR void on_replacement_field(const Char* ptr) {
|
||||
parts_.back().end_of_argument_id = ptr - format_.begin();
|
||||
}
|
||||
|
||||
FMT_CONSTEXPR const Char* on_format_specs(const Char* begin,
|
||||
const Char* end) {
|
||||
const auto specs_offset = to_unsigned(begin - format_.begin());
|
||||
|
||||
using parse_context = basic_parse_context<Char>;
|
||||
internal::dynamic_format_specs<Char> parsed_specs;
|
||||
dynamic_specs_handler<parse_context> handler(parsed_specs, parse_context_);
|
||||
begin = parse_format_specs(begin, end, handler);
|
||||
|
||||
if (*begin != '}') on_error("missing '}' in format string");
|
||||
|
||||
auto& last_part = parts_.back();
|
||||
auto specs = last_part.which == part::kind::argument_id
|
||||
? typename part::specification(last_part.val.arg_id)
|
||||
: typename part::specification(last_part.val.named_arg_id);
|
||||
specs.parsed_specs = parsed_specs;
|
||||
last_part = part(specs);
|
||||
last_part.end_of_argument_id = specs_offset;
|
||||
return begin;
|
||||
}
|
||||
|
||||
private:
|
||||
PartsContainer& parts_;
|
||||
basic_string_view<Char> format_;
|
||||
basic_parse_context<Char> parse_context_;
|
||||
};
|
||||
|
||||
template <typename Format, typename PreparedPartsProvider, typename... Args>
|
||||
class prepared_format {
|
||||
public:
|
||||
using char_type = char_t<Format>;
|
||||
using format_part_t = format_part<char_type>;
|
||||
|
||||
constexpr prepared_format(Format f)
|
||||
: format_(std::move(f)), parts_provider_(to_string_view(format_)) {}
|
||||
|
||||
prepared_format() = delete;
|
||||
|
||||
using context = buffer_context<char_type>;
|
||||
|
||||
template <typename Range, typename Context>
|
||||
auto vformat_to(Range out, basic_format_args<Context> args) const ->
|
||||
typename Context::iterator {
|
||||
const auto format_view = internal::to_string_view(format_);
|
||||
basic_parse_context<char_type> parse_ctx(format_view);
|
||||
Context ctx(out.begin(), args);
|
||||
|
||||
const auto& parts = parts_provider_.parts();
|
||||
for (auto part_it = parts.begin(); part_it != parts.end(); ++part_it) {
|
||||
const auto& part = *part_it;
|
||||
const auto& value = part.val;
|
||||
|
||||
switch (part.which) {
|
||||
case format_part_t::kind::text: {
|
||||
const auto text = value.text.to_view(format_view.data());
|
||||
auto output = ctx.out();
|
||||
auto&& it = internal::reserve(output, text.size());
|
||||
it = std::copy_n(text.begin(), text.size(), it);
|
||||
ctx.advance_to(output);
|
||||
} break;
|
||||
|
||||
case format_part_t::kind::argument_id: {
|
||||
advance_parse_context_to_specification(parse_ctx, part);
|
||||
format_arg<Range>(parse_ctx, ctx, value.arg_id);
|
||||
} break;
|
||||
|
||||
case format_part_t::kind::named_argument_id: {
|
||||
advance_parse_context_to_specification(parse_ctx, part);
|
||||
const auto named_arg_id =
|
||||
value.named_arg_id.to_view(format_view.data());
|
||||
format_arg<Range>(parse_ctx, ctx, named_arg_id);
|
||||
} break;
|
||||
case format_part_t::kind::specification: {
|
||||
const auto& arg_id_value = value.spec.arg_id.val;
|
||||
const auto arg = value.spec.arg_id.which ==
|
||||
format_part_t::argument_id::which_arg_id::index
|
||||
? ctx.arg(arg_id_value.index)
|
||||
: ctx.arg(arg_id_value.named_index.to_view(
|
||||
to_string_view(format_).data()));
|
||||
|
||||
auto specs = value.spec.parsed_specs;
|
||||
|
||||
handle_dynamic_spec<internal::width_checker>(
|
||||
specs.width, specs.width_ref, ctx, format_view.begin());
|
||||
handle_dynamic_spec<internal::precision_checker>(
|
||||
specs.precision, specs.precision_ref, ctx, format_view.begin());
|
||||
|
||||
check_prepared_specs(specs, arg.type());
|
||||
advance_parse_context_to_specification(parse_ctx, part);
|
||||
ctx.advance_to(
|
||||
visit_format_arg(arg_formatter<Range>(ctx, nullptr, &specs), arg));
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
return ctx.out();
|
||||
}
|
||||
|
||||
private:
|
||||
void advance_parse_context_to_specification(
|
||||
basic_parse_context<char_type>& parse_ctx,
|
||||
const format_part_t& part) const {
|
||||
const auto view = to_string_view(format_);
|
||||
const auto specification_begin = view.data() + part.end_of_argument_id;
|
||||
advance_to(parse_ctx, specification_begin);
|
||||
}
|
||||
|
||||
template <typename Range, typename Context, typename Id>
|
||||
void format_arg(basic_parse_context<char_type>& parse_ctx, Context& ctx,
|
||||
Id arg_id) const {
|
||||
parse_ctx.check_arg_id(arg_id);
|
||||
const auto stopped_at =
|
||||
visit_format_arg(arg_formatter<Range>(ctx), ctx.arg(arg_id));
|
||||
ctx.advance_to(stopped_at);
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
void check_prepared_specs(const basic_format_specs<Char>& specs,
|
||||
internal::type arg_type) const {
|
||||
internal::error_handler h;
|
||||
numeric_specs_checker<internal::error_handler> checker(h, arg_type);
|
||||
if (specs.align == align::numeric) checker.require_numeric_argument();
|
||||
if (specs.sign != sign::none) checker.check_sign();
|
||||
if (specs.alt) checker.require_numeric_argument();
|
||||
if (specs.precision >= 0) checker.check_precision();
|
||||
}
|
||||
|
||||
private:
|
||||
Format format_;
|
||||
PreparedPartsProvider parts_provider_;
|
||||
};
|
||||
|
||||
template <typename Char> struct part_counter {
|
||||
unsigned num_parts = 0;
|
||||
|
||||
FMT_CONSTEXPR void on_text(const Char* begin, const Char* end) {
|
||||
if (begin != end) ++num_parts;
|
||||
}
|
||||
|
||||
FMT_CONSTEXPR void on_arg_id() { ++num_parts; }
|
||||
FMT_CONSTEXPR void on_arg_id(unsigned) { ++num_parts; }
|
||||
FMT_CONSTEXPR void on_arg_id(basic_string_view<Char>) { ++num_parts; }
|
||||
|
||||
FMT_CONSTEXPR void on_replacement_field(const Char*) {}
|
||||
|
||||
FMT_CONSTEXPR const Char* on_format_specs(const Char* begin,
|
||||
const Char* end) {
|
||||
// Find the matching brace.
|
||||
unsigned braces_counter = 0;
|
||||
for (; begin != end; ++begin) {
|
||||
if (*begin == '{') {
|
||||
++braces_counter;
|
||||
} else if (*begin == '}') {
|
||||
if (braces_counter == 0u) break;
|
||||
--braces_counter;
|
||||
}
|
||||
}
|
||||
return begin;
|
||||
}
|
||||
|
||||
FMT_CONSTEXPR void on_error(const char*) {}
|
||||
};
|
||||
|
||||
template <typename Format> class compiletime_prepared_parts_type_provider {
|
||||
private:
|
||||
using char_type = char_t<Format>;
|
||||
|
||||
static FMT_CONSTEXPR unsigned count_parts() {
|
||||
FMT_CONSTEXPR_DECL const auto text = to_string_view(Format{});
|
||||
part_counter<char_type> counter;
|
||||
internal::parse_format_string</*IS_CONSTEXPR=*/true>(text, counter);
|
||||
return counter.num_parts;
|
||||
}
|
||||
|
||||
// Workaround for old compilers. Compiletime parts preparation will not be
|
||||
// performed with them anyway.
|
||||
#if FMT_USE_CONSTEXPR
|
||||
static FMT_CONSTEXPR_DECL const unsigned number_of_format_parts =
|
||||
compiletime_prepared_parts_type_provider::count_parts();
|
||||
#else
|
||||
static const unsigned number_of_format_parts = 0u;
|
||||
#endif
|
||||
|
||||
public:
|
||||
template <unsigned N> struct format_parts_array {
|
||||
using value_type = format_part<char_type>;
|
||||
|
||||
FMT_CONSTEXPR format_parts_array() : arr{} {}
|
||||
|
||||
FMT_CONSTEXPR value_type& operator[](unsigned ind) { return arr[ind]; }
|
||||
|
||||
FMT_CONSTEXPR const value_type* begin() const { return arr; }
|
||||
FMT_CONSTEXPR const value_type* end() const { return begin() + N; }
|
||||
|
||||
private:
|
||||
value_type arr[N];
|
||||
};
|
||||
|
||||
struct empty {
|
||||
// Parts preparator will search for it
|
||||
using value_type = format_part<char_type>;
|
||||
};
|
||||
|
||||
using type = conditional_t<number_of_format_parts != 0,
|
||||
format_parts_array<number_of_format_parts>, empty>;
|
||||
};
|
||||
|
||||
template <typename Parts> class compiletime_prepared_parts_collector {
|
||||
private:
|
||||
using format_part = typename Parts::value_type;
|
||||
|
||||
public:
|
||||
FMT_CONSTEXPR explicit compiletime_prepared_parts_collector(Parts& parts)
|
||||
: parts_{parts}, counter_{0u} {}
|
||||
|
||||
FMT_CONSTEXPR void push_back(format_part part) { parts_[counter_++] = part; }
|
||||
|
||||
FMT_CONSTEXPR format_part& back() { return parts_[counter_ - 1]; }
|
||||
|
||||
private:
|
||||
Parts& parts_;
|
||||
unsigned counter_;
|
||||
};
|
||||
|
||||
template <typename PartsContainer, typename Char>
|
||||
FMT_CONSTEXPR PartsContainer prepare_parts(basic_string_view<Char> format) {
|
||||
PartsContainer parts;
|
||||
internal::parse_format_string</*IS_CONSTEXPR=*/false>(
|
||||
format, format_preparation_handler<Char, PartsContainer>(format, parts));
|
||||
return parts;
|
||||
}
|
||||
|
||||
template <typename PartsContainer, typename Char>
|
||||
FMT_CONSTEXPR PartsContainer
|
||||
prepare_compiletime_parts(basic_string_view<Char> format) {
|
||||
using collector = compiletime_prepared_parts_collector<PartsContainer>;
|
||||
|
||||
PartsContainer parts;
|
||||
collector c(parts);
|
||||
internal::parse_format_string</*IS_CONSTEXPR=*/true>(
|
||||
format, format_preparation_handler<Char, collector>(format, c));
|
||||
return parts;
|
||||
}
|
||||
|
||||
template <typename PartsContainer> class runtime_parts_provider {
|
||||
public:
|
||||
runtime_parts_provider() = delete;
|
||||
template <typename Char>
|
||||
runtime_parts_provider(basic_string_view<Char> format)
|
||||
: parts_(prepare_parts<PartsContainer>(format)) {}
|
||||
|
||||
const PartsContainer& parts() const { return parts_; }
|
||||
|
||||
private:
|
||||
PartsContainer parts_;
|
||||
};
|
||||
|
||||
template <typename Format, typename PartsContainer>
|
||||
struct compiletime_parts_provider {
|
||||
compiletime_parts_provider() = delete;
|
||||
template <typename Char>
|
||||
FMT_CONSTEXPR compiletime_parts_provider(basic_string_view<Char>) {}
|
||||
|
||||
const PartsContainer& parts() const {
|
||||
static FMT_CONSTEXPR_DECL const PartsContainer prepared_parts =
|
||||
prepare_compiletime_parts<PartsContainer>(
|
||||
internal::to_string_view(Format{}));
|
||||
|
||||
return prepared_parts;
|
||||
}
|
||||
};
|
||||
} // namespace internal
|
||||
|
||||
#if FMT_USE_CONSTEXPR
|
||||
template <typename... Args, typename S,
|
||||
FMT_ENABLE_IF(is_compile_string<S>::value)>
|
||||
FMT_CONSTEXPR auto compile(S format_str) -> internal::prepared_format<
|
||||
S,
|
||||
internal::compiletime_parts_provider<
|
||||
S,
|
||||
typename internal::compiletime_prepared_parts_type_provider<S>::type>,
|
||||
Args...> {
|
||||
return format_str;
|
||||
}
|
||||
#endif
|
||||
|
||||
template <typename... Args, typename Char, size_t N>
|
||||
auto compile(const Char (&format_str)[N]) -> internal::prepared_format<
|
||||
std::basic_string<Char>,
|
||||
internal::runtime_parts_provider<std::vector<internal::format_part<Char>>>,
|
||||
Args...> {
|
||||
return std::basic_string<Char>(format_str, N - 1);
|
||||
}
|
||||
|
||||
template <typename CompiledFormat, typename... Args,
|
||||
typename Char = typename CompiledFormat::char_type>
|
||||
std::basic_string<Char> format(const CompiledFormat& cf, const Args&... args) {
|
||||
basic_memory_buffer<Char> buffer;
|
||||
using range = internal::buffer_range<Char>;
|
||||
using context = buffer_context<Char>;
|
||||
cf.template vformat_to<range, context>(range(buffer),
|
||||
{make_format_args<context>(args...)});
|
||||
return to_string(buffer);
|
||||
}
|
||||
|
||||
template <typename OutputIt, typename CompiledFormat, typename... Args>
|
||||
OutputIt format_to(OutputIt out, const CompiledFormat& cf,
|
||||
const Args&... args) {
|
||||
using char_type = typename CompiledFormat::char_type;
|
||||
using range = internal::output_range<OutputIt, char_type>;
|
||||
using context = format_context_t<OutputIt, char_type>;
|
||||
return cf.template vformat_to<range, context>(
|
||||
range(out), {make_format_args<context>(args...)});
|
||||
}
|
||||
|
||||
template <typename OutputIt, typename CompiledFormat, typename... Args,
|
||||
FMT_ENABLE_IF(internal::is_output_iterator<OutputIt>::value)>
|
||||
format_to_n_result<OutputIt> format_to_n(OutputIt out, size_t n,
|
||||
const CompiledFormat& cf,
|
||||
const Args&... args) {
|
||||
auto it =
|
||||
format_to(internal::truncating_iterator<OutputIt>(out, n), cf, args...);
|
||||
return {it.base(), it.count()};
|
||||
}
|
||||
|
||||
template <typename CompiledFormat, typename... Args>
|
||||
std::size_t formatted_size(const CompiledFormat& cf, const Args&... args) {
|
||||
return fmt::format_to(
|
||||
internal::counting_iterator<typename CompiledFormat::char_type>(),
|
||||
cf, args...)
|
||||
.count();
|
||||
}
|
||||
|
||||
FMT_END_NAMESPACE
|
||||
|
||||
#endif // FMT_COMPILE_H_
|
1420
vtkm/thirdparty/diy/vtkmdiy/include/vtkmdiy/thirdparty/fmt/core.h
vendored
Normal file
1420
vtkm/thirdparty/diy/vtkmdiy/include/vtkmdiy/thirdparty/fmt/core.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1000
vtkm/thirdparty/diy/vtkmdiy/include/vtkmdiy/thirdparty/fmt/format-inl.h
vendored
Normal file
1000
vtkm/thirdparty/diy/vtkmdiy/include/vtkmdiy/thirdparty/fmt/format-inl.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
57
vtkm/thirdparty/diy/vtkmdiy/include/vtkmdiy/thirdparty/fmt/format.cc
vendored
Normal file
57
vtkm/thirdparty/diy/vtkmdiy/include/vtkmdiy/thirdparty/fmt/format.cc
vendored
Normal file
@ -0,0 +1,57 @@
|
||||
// Formatting library for C++
|
||||
//
|
||||
// Copyright (c) 2012 - 2016, Victor Zverovich
|
||||
// All rights reserved.
|
||||
//
|
||||
// For the license information refer to format.h.
|
||||
|
||||
#include "format-inl.h"
|
||||
|
||||
FMT_BEGIN_NAMESPACE
|
||||
template struct FMT_API internal::basic_data<void>;
|
||||
|
||||
// Workaround a bug in MSVC2013 that prevents instantiation of grisu_format.
|
||||
bool (*instantiate_grisu_format)(double, internal::buffer<char>&, int, unsigned,
|
||||
int&) = internal::grisu_format;
|
||||
|
||||
#ifndef FMT_STATIC_THOUSANDS_SEPARATOR
|
||||
template FMT_API internal::locale_ref::locale_ref(const std::locale& loc);
|
||||
template FMT_API std::locale internal::locale_ref::get<std::locale>() const;
|
||||
#endif
|
||||
|
||||
// Explicit instantiations for char.
|
||||
|
||||
template FMT_API char internal::thousands_sep_impl(locale_ref);
|
||||
template FMT_API char internal::decimal_point_impl(locale_ref);
|
||||
|
||||
template FMT_API void internal::buffer<char>::append(const char*, const char*);
|
||||
|
||||
template FMT_API void internal::arg_map<format_context>::init(
|
||||
const basic_format_args<format_context>& args);
|
||||
|
||||
template FMT_API std::string internal::vformat<char>(
|
||||
string_view, basic_format_args<format_context>);
|
||||
|
||||
template FMT_API format_context::iterator internal::vformat_to(
|
||||
internal::buffer<char>&, string_view, basic_format_args<format_context>);
|
||||
|
||||
template FMT_API char* internal::sprintf_format(double, internal::buffer<char>&,
|
||||
sprintf_specs);
|
||||
template FMT_API char* internal::sprintf_format(long double,
|
||||
internal::buffer<char>&,
|
||||
sprintf_specs);
|
||||
|
||||
// Explicit instantiations for wchar_t.
|
||||
|
||||
template FMT_API wchar_t internal::thousands_sep_impl(locale_ref);
|
||||
template FMT_API wchar_t internal::decimal_point_impl(locale_ref);
|
||||
|
||||
template FMT_API void internal::buffer<wchar_t>::append(const wchar_t*,
|
||||
const wchar_t*);
|
||||
|
||||
template FMT_API void internal::arg_map<wformat_context>::init(
|
||||
const basic_format_args<wformat_context>&);
|
||||
|
||||
template FMT_API std::wstring internal::vformat<wchar_t>(
|
||||
wstring_view, basic_format_args<wformat_context>);
|
||||
FMT_END_NAMESPACE
|
3602
vtkm/thirdparty/diy/vtkmdiy/include/vtkmdiy/thirdparty/fmt/format.h
vendored
Normal file
3602
vtkm/thirdparty/diy/vtkmdiy/include/vtkmdiy/thirdparty/fmt/format.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
77
vtkm/thirdparty/diy/vtkmdiy/include/vtkmdiy/thirdparty/fmt/locale.h
vendored
Normal file
77
vtkm/thirdparty/diy/vtkmdiy/include/vtkmdiy/thirdparty/fmt/locale.h
vendored
Normal file
@ -0,0 +1,77 @@
|
||||
// Formatting library for C++ - std::locale support
|
||||
//
|
||||
// Copyright (c) 2012 - present, Victor Zverovich
|
||||
// All rights reserved.
|
||||
//
|
||||
// For the license information refer to format.h.
|
||||
|
||||
#ifndef FMT_LOCALE_H_
|
||||
#define FMT_LOCALE_H_
|
||||
|
||||
#include <locale>
|
||||
#include "format.h"
|
||||
|
||||
FMT_BEGIN_NAMESPACE
|
||||
|
||||
namespace internal {
|
||||
template <typename Char>
|
||||
typename buffer_context<Char>::iterator vformat_to(
|
||||
const std::locale& loc, buffer<Char>& buf,
|
||||
basic_string_view<Char> format_str,
|
||||
basic_format_args<buffer_context<Char>> args) {
|
||||
using range = buffer_range<Char>;
|
||||
return vformat_to<arg_formatter<range>>(buf, to_string_view(format_str), args,
|
||||
internal::locale_ref(loc));
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
std::basic_string<Char> vformat(const std::locale& loc,
|
||||
basic_string_view<Char> format_str,
|
||||
basic_format_args<buffer_context<Char>> args) {
|
||||
basic_memory_buffer<Char> buffer;
|
||||
internal::vformat_to(loc, buffer, format_str, args);
|
||||
return fmt::to_string(buffer);
|
||||
}
|
||||
} // namespace internal
|
||||
|
||||
template <typename S, typename Char = char_t<S>>
|
||||
inline std::basic_string<Char> vformat(
|
||||
const std::locale& loc, const S& format_str,
|
||||
basic_format_args<buffer_context<Char>> args) {
|
||||
return internal::vformat(loc, to_string_view(format_str), args);
|
||||
}
|
||||
|
||||
template <typename S, typename... Args, typename Char = char_t<S>>
|
||||
inline std::basic_string<Char> format(const std::locale& loc,
|
||||
const S& format_str, Args&&... args) {
|
||||
return internal::vformat(
|
||||
loc, to_string_view(format_str),
|
||||
{internal::make_args_checked<Args...>(format_str, args...)});
|
||||
}
|
||||
|
||||
template <typename S, typename OutputIt, typename... Args,
|
||||
typename Char = enable_if_t<
|
||||
internal::is_output_iterator<OutputIt>::value, char_t<S>>>
|
||||
inline OutputIt vformat_to(OutputIt out, const std::locale& loc,
|
||||
const S& format_str,
|
||||
format_args_t<OutputIt, Char> args) {
|
||||
using range = internal::output_range<OutputIt, Char>;
|
||||
return vformat_to<arg_formatter<range>>(
|
||||
range(out), to_string_view(format_str), args, internal::locale_ref(loc));
|
||||
}
|
||||
|
||||
template <typename OutputIt, typename S, typename... Args,
|
||||
FMT_ENABLE_IF(internal::is_output_iterator<OutputIt>::value&&
|
||||
internal::is_string<S>::value)>
|
||||
inline OutputIt format_to(OutputIt out, const std::locale& loc,
|
||||
const S& format_str, Args&&... args) {
|
||||
internal::check_format_string<Args...>(format_str);
|
||||
using context = format_context_t<OutputIt, char_t<S>>;
|
||||
format_arg_store<context, Args...> as{args...};
|
||||
return vformat_to(out, loc, to_string_view(format_str),
|
||||
basic_format_args<context>(as));
|
||||
}
|
||||
|
||||
FMT_END_NAMESPACE
|
||||
|
||||
#endif // FMT_LOCALE_H_
|
136
vtkm/thirdparty/diy/vtkmdiy/include/vtkmdiy/thirdparty/fmt/ostream.h
vendored
Normal file
136
vtkm/thirdparty/diy/vtkmdiy/include/vtkmdiy/thirdparty/fmt/ostream.h
vendored
Normal file
@ -0,0 +1,136 @@
|
||||
// Formatting library for C++ - std::ostream support
|
||||
//
|
||||
// Copyright (c) 2012 - present, Victor Zverovich
|
||||
// All rights reserved.
|
||||
//
|
||||
// For the license information refer to format.h.
|
||||
|
||||
#ifndef FMT_OSTREAM_H_
|
||||
#define FMT_OSTREAM_H_
|
||||
|
||||
#include <ostream>
|
||||
#include "format.h"
|
||||
|
||||
FMT_BEGIN_NAMESPACE
|
||||
namespace internal {
|
||||
|
||||
template <class Char> class formatbuf : public std::basic_streambuf<Char> {
|
||||
private:
|
||||
using int_type = typename std::basic_streambuf<Char>::int_type;
|
||||
using traits_type = typename std::basic_streambuf<Char>::traits_type;
|
||||
|
||||
buffer<Char>& buffer_;
|
||||
|
||||
public:
|
||||
formatbuf(buffer<Char>& buf) : buffer_(buf) {}
|
||||
|
||||
protected:
|
||||
// The put-area is actually always empty. This makes the implementation
|
||||
// simpler and has the advantage that the streambuf and the buffer are always
|
||||
// in sync and sputc never writes into uninitialized memory. The obvious
|
||||
// disadvantage is that each call to sputc always results in a (virtual) call
|
||||
// to overflow. There is no disadvantage here for sputn since this always
|
||||
// results in a call to xsputn.
|
||||
|
||||
int_type overflow(int_type ch = traits_type::eof()) FMT_OVERRIDE {
|
||||
if (!traits_type::eq_int_type(ch, traits_type::eof()))
|
||||
buffer_.push_back(static_cast<Char>(ch));
|
||||
return ch;
|
||||
}
|
||||
|
||||
std::streamsize xsputn(const Char* s, std::streamsize count) FMT_OVERRIDE {
|
||||
buffer_.append(s, s + count);
|
||||
return count;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Char> struct test_stream : std::basic_ostream<Char> {
|
||||
private:
|
||||
struct null;
|
||||
// Hide all operator<< from std::basic_ostream<Char>.
|
||||
void operator<<(null);
|
||||
};
|
||||
|
||||
// Checks if T has a user-defined operator<< (e.g. not a member of
|
||||
// std::ostream).
|
||||
template <typename T, typename Char> class is_streamable {
|
||||
private:
|
||||
template <typename U>
|
||||
static decltype((void)(std::declval<test_stream<Char>&>()
|
||||
<< std::declval<U>()),
|
||||
std::true_type())
|
||||
test(int);
|
||||
|
||||
template <typename> static std::false_type test(...);
|
||||
|
||||
using result = decltype(test<T>(0));
|
||||
|
||||
public:
|
||||
static const bool value = result::value;
|
||||
};
|
||||
|
||||
// Write the content of buf to os.
|
||||
template <typename Char>
|
||||
void write(std::basic_ostream<Char>& os, buffer<Char>& buf) {
|
||||
const Char* buf_data = buf.data();
|
||||
using unsigned_streamsize = std::make_unsigned<std::streamsize>::type;
|
||||
unsigned_streamsize size = buf.size();
|
||||
unsigned_streamsize max_size =
|
||||
to_unsigned((std::numeric_limits<std::streamsize>::max)());
|
||||
do {
|
||||
unsigned_streamsize n = size <= max_size ? size : max_size;
|
||||
os.write(buf_data, static_cast<std::streamsize>(n));
|
||||
buf_data += n;
|
||||
size -= n;
|
||||
} while (size != 0);
|
||||
}
|
||||
|
||||
template <typename Char, typename T>
|
||||
void format_value(buffer<Char>& buf, const T& value) {
|
||||
formatbuf<Char> format_buf(buf);
|
||||
std::basic_ostream<Char> output(&format_buf);
|
||||
output.exceptions(std::ios_base::failbit | std::ios_base::badbit);
|
||||
output << value;
|
||||
buf.resize(buf.size());
|
||||
}
|
||||
|
||||
// Formats an object of type T that has an overloaded ostream operator<<.
|
||||
template <typename T, typename Char>
|
||||
struct fallback_formatter<T, Char, enable_if_t<is_streamable<T, Char>::value>>
|
||||
: formatter<basic_string_view<Char>, Char> {
|
||||
template <typename Context>
|
||||
auto format(const T& value, Context& ctx) -> decltype(ctx.out()) {
|
||||
basic_memory_buffer<Char> buffer;
|
||||
format_value(buffer, value);
|
||||
basic_string_view<Char> str(buffer.data(), buffer.size());
|
||||
return formatter<basic_string_view<Char>, Char>::format(str, ctx);
|
||||
}
|
||||
};
|
||||
} // namespace internal
|
||||
|
||||
template <typename Char>
|
||||
void vprint(std::basic_ostream<Char>& os, basic_string_view<Char> format_str,
|
||||
basic_format_args<buffer_context<Char>> args) {
|
||||
basic_memory_buffer<Char> buffer;
|
||||
internal::vformat_to(buffer, format_str, args);
|
||||
internal::write(os, buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
\rst
|
||||
Prints formatted data to the stream *os*.
|
||||
|
||||
**Example**::
|
||||
|
||||
fmt::print(cerr, "Don't {}!", "panic");
|
||||
\endrst
|
||||
*/
|
||||
template <typename S, typename... Args,
|
||||
typename Char = enable_if_t<internal::is_string<S>::value, char_t<S>>>
|
||||
void print(std::basic_ostream<Char>& os, const S& format_str, Args&&... args) {
|
||||
vprint(os, to_string_view(format_str),
|
||||
{internal::make_args_checked<Args...>(format_str, args...)});
|
||||
}
|
||||
FMT_END_NAMESPACE
|
||||
|
||||
#endif // FMT_OSTREAM_H_
|
233
vtkm/thirdparty/diy/vtkmdiy/include/vtkmdiy/thirdparty/fmt/posix.cc
vendored
Normal file
233
vtkm/thirdparty/diy/vtkmdiy/include/vtkmdiy/thirdparty/fmt/posix.cc
vendored
Normal file
@ -0,0 +1,233 @@
|
||||
// A C++ interface to POSIX functions.
|
||||
//
|
||||
// Copyright (c) 2012 - 2016, Victor Zverovich
|
||||
// All rights reserved.
|
||||
//
|
||||
// For the license information refer to format.h.
|
||||
|
||||
// Disable bogus MSVC warnings.
|
||||
#if !defined(_CRT_SECURE_NO_WARNINGS) && defined(_MSC_VER)
|
||||
# define _CRT_SECURE_NO_WARNINGS
|
||||
#endif
|
||||
|
||||
#include "posix.h"
|
||||
|
||||
#include <limits.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#ifndef _WIN32
|
||||
# include <unistd.h>
|
||||
#else
|
||||
# ifndef WIN32_LEAN_AND_MEAN
|
||||
# define WIN32_LEAN_AND_MEAN
|
||||
# endif
|
||||
# include <io.h>
|
||||
# include <windows.h>
|
||||
|
||||
# define O_CREAT _O_CREAT
|
||||
# define O_TRUNC _O_TRUNC
|
||||
|
||||
# ifndef S_IRUSR
|
||||
# define S_IRUSR _S_IREAD
|
||||
# endif
|
||||
|
||||
# ifndef S_IWUSR
|
||||
# define S_IWUSR _S_IWRITE
|
||||
# endif
|
||||
|
||||
# ifdef __MINGW32__
|
||||
# define _SH_DENYNO 0x40
|
||||
# endif
|
||||
|
||||
#endif // _WIN32
|
||||
|
||||
#ifdef fileno
|
||||
# undef fileno
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
#ifdef _WIN32
|
||||
// Return type of read and write functions.
|
||||
typedef int RWResult;
|
||||
|
||||
// On Windows the count argument to read and write is unsigned, so convert
|
||||
// it from size_t preventing integer overflow.
|
||||
inline unsigned convert_rwcount(std::size_t count) {
|
||||
return count <= UINT_MAX ? static_cast<unsigned>(count) : UINT_MAX;
|
||||
}
|
||||
#else
|
||||
// Return type of read and write functions.
|
||||
typedef ssize_t RWResult;
|
||||
|
||||
inline std::size_t convert_rwcount(std::size_t count) { return count; }
|
||||
#endif
|
||||
} // namespace
|
||||
|
||||
FMT_BEGIN_NAMESPACE
|
||||
|
||||
buffered_file::~buffered_file() FMT_NOEXCEPT {
|
||||
if (file_ && FMT_SYSTEM(fclose(file_)) != 0)
|
||||
report_system_error(errno, "cannot close file");
|
||||
}
|
||||
|
||||
buffered_file::buffered_file(cstring_view filename, cstring_view mode) {
|
||||
FMT_RETRY_VAL(file_, FMT_SYSTEM(fopen(filename.c_str(), mode.c_str())),
|
||||
nullptr);
|
||||
if (!file_)
|
||||
FMT_THROW(system_error(errno, "cannot open file {}", filename.c_str()));
|
||||
}
|
||||
|
||||
void buffered_file::close() {
|
||||
if (!file_) return;
|
||||
int result = FMT_SYSTEM(fclose(file_));
|
||||
file_ = nullptr;
|
||||
if (result != 0) FMT_THROW(system_error(errno, "cannot close file"));
|
||||
}
|
||||
|
||||
// A macro used to prevent expansion of fileno on broken versions of MinGW.
|
||||
#define FMT_ARGS
|
||||
|
||||
int buffered_file::fileno() const {
|
||||
int fd = FMT_POSIX_CALL(fileno FMT_ARGS(file_));
|
||||
if (fd == -1) FMT_THROW(system_error(errno, "cannot get file descriptor"));
|
||||
return fd;
|
||||
}
|
||||
|
||||
file::file(cstring_view path, int oflag) {
|
||||
int mode = S_IRUSR | S_IWUSR;
|
||||
#if defined(_WIN32) && !defined(__MINGW32__)
|
||||
fd_ = -1;
|
||||
FMT_POSIX_CALL(sopen_s(&fd_, path.c_str(), oflag, _SH_DENYNO, mode));
|
||||
#else
|
||||
FMT_RETRY(fd_, FMT_POSIX_CALL(open(path.c_str(), oflag, mode)));
|
||||
#endif
|
||||
if (fd_ == -1)
|
||||
FMT_THROW(system_error(errno, "cannot open file {}", path.c_str()));
|
||||
}
|
||||
|
||||
file::~file() FMT_NOEXCEPT {
|
||||
// Don't retry close in case of EINTR!
|
||||
// See http://linux.derkeiler.com/Mailing-Lists/Kernel/2005-09/3000.html
|
||||
if (fd_ != -1 && FMT_POSIX_CALL(close(fd_)) != 0)
|
||||
report_system_error(errno, "cannot close file");
|
||||
}
|
||||
|
||||
void file::close() {
|
||||
if (fd_ == -1) return;
|
||||
// Don't retry close in case of EINTR!
|
||||
// See http://linux.derkeiler.com/Mailing-Lists/Kernel/2005-09/3000.html
|
||||
int result = FMT_POSIX_CALL(close(fd_));
|
||||
fd_ = -1;
|
||||
if (result != 0) FMT_THROW(system_error(errno, "cannot close file"));
|
||||
}
|
||||
|
||||
long long file::size() const {
|
||||
#ifdef _WIN32
|
||||
// Use GetFileSize instead of GetFileSizeEx for the case when _WIN32_WINNT
|
||||
// is less than 0x0500 as is the case with some default MinGW builds.
|
||||
// Both functions support large file sizes.
|
||||
DWORD size_upper = 0;
|
||||
HANDLE handle = reinterpret_cast<HANDLE>(_get_osfhandle(fd_));
|
||||
DWORD size_lower = FMT_SYSTEM(GetFileSize(handle, &size_upper));
|
||||
if (size_lower == INVALID_FILE_SIZE) {
|
||||
DWORD error = GetLastError();
|
||||
if (error != NO_ERROR)
|
||||
FMT_THROW(windows_error(GetLastError(), "cannot get file size"));
|
||||
}
|
||||
unsigned long long long_size = size_upper;
|
||||
return (long_size << sizeof(DWORD) * CHAR_BIT) | size_lower;
|
||||
#else
|
||||
typedef struct stat Stat;
|
||||
Stat file_stat = Stat();
|
||||
if (FMT_POSIX_CALL(fstat(fd_, &file_stat)) == -1)
|
||||
FMT_THROW(system_error(errno, "cannot get file attributes"));
|
||||
static_assert(sizeof(long long) >= sizeof(file_stat.st_size),
|
||||
"return type of file::size is not large enough");
|
||||
return file_stat.st_size;
|
||||
#endif
|
||||
}
|
||||
|
||||
std::size_t file::read(void* buffer, std::size_t count) {
|
||||
RWResult result = 0;
|
||||
FMT_RETRY(result, FMT_POSIX_CALL(read(fd_, buffer, convert_rwcount(count))));
|
||||
if (result < 0) FMT_THROW(system_error(errno, "cannot read from file"));
|
||||
return internal::to_unsigned(result);
|
||||
}
|
||||
|
||||
std::size_t file::write(const void* buffer, std::size_t count) {
|
||||
RWResult result = 0;
|
||||
FMT_RETRY(result, FMT_POSIX_CALL(write(fd_, buffer, convert_rwcount(count))));
|
||||
if (result < 0) FMT_THROW(system_error(errno, "cannot write to file"));
|
||||
return internal::to_unsigned(result);
|
||||
}
|
||||
|
||||
file file::dup(int fd) {
|
||||
// Don't retry as dup doesn't return EINTR.
|
||||
// http://pubs.opengroup.org/onlinepubs/009695399/functions/dup.html
|
||||
int new_fd = FMT_POSIX_CALL(dup(fd));
|
||||
if (new_fd == -1)
|
||||
FMT_THROW(system_error(errno, "cannot duplicate file descriptor {}", fd));
|
||||
return file(new_fd);
|
||||
}
|
||||
|
||||
void file::dup2(int fd) {
|
||||
int result = 0;
|
||||
FMT_RETRY(result, FMT_POSIX_CALL(dup2(fd_, fd)));
|
||||
if (result == -1) {
|
||||
FMT_THROW(system_error(errno, "cannot duplicate file descriptor {} to {}",
|
||||
fd_, fd));
|
||||
}
|
||||
}
|
||||
|
||||
void file::dup2(int fd, error_code& ec) FMT_NOEXCEPT {
|
||||
int result = 0;
|
||||
FMT_RETRY(result, FMT_POSIX_CALL(dup2(fd_, fd)));
|
||||
if (result == -1) ec = error_code(errno);
|
||||
}
|
||||
|
||||
void file::pipe(file& read_end, file& write_end) {
|
||||
// Close the descriptors first to make sure that assignments don't throw
|
||||
// and there are no leaks.
|
||||
read_end.close();
|
||||
write_end.close();
|
||||
int fds[2] = {};
|
||||
#ifdef _WIN32
|
||||
// Make the default pipe capacity same as on Linux 2.6.11+.
|
||||
enum { DEFAULT_CAPACITY = 65536 };
|
||||
int result = FMT_POSIX_CALL(pipe(fds, DEFAULT_CAPACITY, _O_BINARY));
|
||||
#else
|
||||
// Don't retry as the pipe function doesn't return EINTR.
|
||||
// http://pubs.opengroup.org/onlinepubs/009696799/functions/pipe.html
|
||||
int result = FMT_POSIX_CALL(pipe(fds));
|
||||
#endif
|
||||
if (result != 0) FMT_THROW(system_error(errno, "cannot create pipe"));
|
||||
// The following assignments don't throw because read_fd and write_fd
|
||||
// are closed.
|
||||
read_end = file(fds[0]);
|
||||
write_end = file(fds[1]);
|
||||
}
|
||||
|
||||
buffered_file file::fdopen(const char* mode) {
|
||||
// Don't retry as fdopen doesn't return EINTR.
|
||||
FILE* f = FMT_POSIX_CALL(fdopen(fd_, mode));
|
||||
if (!f)
|
||||
FMT_THROW(
|
||||
system_error(errno, "cannot associate stream with file descriptor"));
|
||||
buffered_file bf(f);
|
||||
fd_ = -1;
|
||||
return bf;
|
||||
}
|
||||
|
||||
long getpagesize() {
|
||||
#ifdef _WIN32
|
||||
SYSTEM_INFO si;
|
||||
GetSystemInfo(&si);
|
||||
return si.dwPageSize;
|
||||
#else
|
||||
long size = FMT_POSIX_CALL(sysconf(_SC_PAGESIZE));
|
||||
if (size < 0) FMT_THROW(system_error(errno, "cannot get memory page size"));
|
||||
return size;
|
||||
#endif
|
||||
}
|
||||
FMT_END_NAMESPACE
|
311
vtkm/thirdparty/diy/vtkmdiy/include/vtkmdiy/thirdparty/fmt/posix.h
vendored
Normal file
311
vtkm/thirdparty/diy/vtkmdiy/include/vtkmdiy/thirdparty/fmt/posix.h
vendored
Normal file
@ -0,0 +1,311 @@
|
||||
// A C++ interface to POSIX functions.
|
||||
//
|
||||
// Copyright (c) 2012 - 2016, Victor Zverovich
|
||||
// All rights reserved.
|
||||
//
|
||||
// For the license information refer to format.h.
|
||||
|
||||
#ifndef FMT_POSIX_H_
|
||||
#define FMT_POSIX_H_
|
||||
|
||||
#if defined(__MINGW32__) || defined(__CYGWIN__)
|
||||
// Workaround MinGW bug https://sourceforge.net/p/mingw/bugs/2024/.
|
||||
# undef __STRICT_ANSI__
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h> // for O_RDONLY
|
||||
#include <locale.h> // for locale_t
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h> // for strtod_l
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#if defined __APPLE__ || defined(__FreeBSD__)
|
||||
# include <xlocale.h> // for LC_NUMERIC_MASK on OS X
|
||||
#endif
|
||||
|
||||
#include "format.h"
|
||||
|
||||
#ifndef FMT_POSIX
|
||||
# if defined(_WIN32) && !defined(__MINGW32__)
|
||||
// Fix warnings about deprecated symbols.
|
||||
# define FMT_POSIX(call) _##call
|
||||
# else
|
||||
# define FMT_POSIX(call) call
|
||||
# endif
|
||||
#endif
|
||||
|
||||
// Calls to system functions are wrapped in FMT_SYSTEM for testability.
|
||||
#ifdef FMT_SYSTEM
|
||||
# define FMT_POSIX_CALL(call) FMT_SYSTEM(call)
|
||||
#else
|
||||
# define FMT_SYSTEM(call) call
|
||||
# ifdef _WIN32
|
||||
// Fix warnings about deprecated symbols.
|
||||
# define FMT_POSIX_CALL(call) ::_##call
|
||||
# else
|
||||
# define FMT_POSIX_CALL(call) ::call
|
||||
# endif
|
||||
#endif
|
||||
|
||||
// Retries the expression while it evaluates to error_result and errno
|
||||
// equals to EINTR.
|
||||
#ifndef _WIN32
|
||||
# define FMT_RETRY_VAL(result, expression, error_result) \
|
||||
do { \
|
||||
result = (expression); \
|
||||
} while (result == error_result && errno == EINTR)
|
||||
#else
|
||||
# define FMT_RETRY_VAL(result, expression, error_result) result = (expression)
|
||||
#endif
|
||||
|
||||
#define FMT_RETRY(result, expression) FMT_RETRY_VAL(result, expression, -1)
|
||||
|
||||
FMT_BEGIN_NAMESPACE
|
||||
|
||||
/**
|
||||
\rst
|
||||
A reference to a null-terminated string. It can be constructed from a C
|
||||
string or ``std::string``.
|
||||
|
||||
You can use one of the following type aliases for common character types:
|
||||
|
||||
+---------------+-----------------------------+
|
||||
| Type | Definition |
|
||||
+===============+=============================+
|
||||
| cstring_view | basic_cstring_view<char> |
|
||||
+---------------+-----------------------------+
|
||||
| wcstring_view | basic_cstring_view<wchar_t> |
|
||||
+---------------+-----------------------------+
|
||||
|
||||
This class is most useful as a parameter type to allow passing
|
||||
different types of strings to a function, for example::
|
||||
|
||||
template <typename... Args>
|
||||
std::string format(cstring_view format_str, const Args & ... args);
|
||||
|
||||
format("{}", 42);
|
||||
format(std::string("{}"), 42);
|
||||
\endrst
|
||||
*/
|
||||
template <typename Char> class basic_cstring_view {
|
||||
private:
|
||||
const Char* data_;
|
||||
|
||||
public:
|
||||
/** Constructs a string reference object from a C string. */
|
||||
basic_cstring_view(const Char* s) : data_(s) {}
|
||||
|
||||
/**
|
||||
\rst
|
||||
Constructs a string reference from an ``std::string`` object.
|
||||
\endrst
|
||||
*/
|
||||
basic_cstring_view(const std::basic_string<Char>& s) : data_(s.c_str()) {}
|
||||
|
||||
/** Returns the pointer to a C string. */
|
||||
const Char* c_str() const { return data_; }
|
||||
};
|
||||
|
||||
using cstring_view = basic_cstring_view<char>;
|
||||
using wcstring_view = basic_cstring_view<wchar_t>;
|
||||
|
||||
// An error code.
|
||||
class error_code {
|
||||
private:
|
||||
int value_;
|
||||
|
||||
public:
|
||||
explicit error_code(int value = 0) FMT_NOEXCEPT : value_(value) {}
|
||||
|
||||
int get() const FMT_NOEXCEPT { return value_; }
|
||||
};
|
||||
|
||||
// A buffered file.
|
||||
class buffered_file {
|
||||
private:
|
||||
FILE* file_;
|
||||
|
||||
friend class file;
|
||||
|
||||
explicit buffered_file(FILE* f) : file_(f) {}
|
||||
|
||||
public:
|
||||
// Constructs a buffered_file object which doesn't represent any file.
|
||||
buffered_file() FMT_NOEXCEPT : file_(nullptr) {}
|
||||
|
||||
// Destroys the object closing the file it represents if any.
|
||||
FMT_API ~buffered_file() FMT_NOEXCEPT;
|
||||
|
||||
private:
|
||||
buffered_file(const buffered_file&) = delete;
|
||||
void operator=(const buffered_file&) = delete;
|
||||
|
||||
public:
|
||||
buffered_file(buffered_file&& other) FMT_NOEXCEPT : file_(other.file_) {
|
||||
other.file_ = nullptr;
|
||||
}
|
||||
|
||||
buffered_file& operator=(buffered_file&& other) {
|
||||
close();
|
||||
file_ = other.file_;
|
||||
other.file_ = nullptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Opens a file.
|
||||
FMT_API buffered_file(cstring_view filename, cstring_view mode);
|
||||
|
||||
// Closes the file.
|
||||
FMT_API void close();
|
||||
|
||||
// Returns the pointer to a FILE object representing this file.
|
||||
FILE* get() const FMT_NOEXCEPT { return file_; }
|
||||
|
||||
// We place parentheses around fileno to workaround a bug in some versions
|
||||
// of MinGW that define fileno as a macro.
|
||||
FMT_API int(fileno)() const;
|
||||
|
||||
void vprint(string_view format_str, format_args args) {
|
||||
fmt::vprint(file_, format_str, args);
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
inline void print(string_view format_str, const Args&... args) {
|
||||
vprint(format_str, make_format_args(args...));
|
||||
}
|
||||
};
|
||||
|
||||
// A file. Closed file is represented by a file object with descriptor -1.
|
||||
// Methods that are not declared with FMT_NOEXCEPT may throw
|
||||
// fmt::system_error in case of failure. Note that some errors such as
|
||||
// closing the file multiple times will cause a crash on Windows rather
|
||||
// than an exception. You can get standard behavior by overriding the
|
||||
// invalid parameter handler with _set_invalid_parameter_handler.
|
||||
class file {
|
||||
private:
|
||||
int fd_; // File descriptor.
|
||||
|
||||
// Constructs a file object with a given descriptor.
|
||||
explicit file(int fd) : fd_(fd) {}
|
||||
|
||||
public:
|
||||
// Possible values for the oflag argument to the constructor.
|
||||
enum {
|
||||
RDONLY = FMT_POSIX(O_RDONLY), // Open for reading only.
|
||||
WRONLY = FMT_POSIX(O_WRONLY), // Open for writing only.
|
||||
RDWR = FMT_POSIX(O_RDWR) // Open for reading and writing.
|
||||
};
|
||||
|
||||
// Constructs a file object which doesn't represent any file.
|
||||
file() FMT_NOEXCEPT : fd_(-1) {}
|
||||
|
||||
// Opens a file and constructs a file object representing this file.
|
||||
FMT_API file(cstring_view path, int oflag);
|
||||
|
||||
private:
|
||||
file(const file&) = delete;
|
||||
void operator=(const file&) = delete;
|
||||
|
||||
public:
|
||||
file(file&& other) FMT_NOEXCEPT : fd_(other.fd_) { other.fd_ = -1; }
|
||||
|
||||
file& operator=(file&& other) {
|
||||
close();
|
||||
fd_ = other.fd_;
|
||||
other.fd_ = -1;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Destroys the object closing the file it represents if any.
|
||||
FMT_API ~file() FMT_NOEXCEPT;
|
||||
|
||||
// Returns the file descriptor.
|
||||
int descriptor() const FMT_NOEXCEPT { return fd_; }
|
||||
|
||||
// Closes the file.
|
||||
FMT_API void close();
|
||||
|
||||
// Returns the file size. The size has signed type for consistency with
|
||||
// stat::st_size.
|
||||
FMT_API long long size() const;
|
||||
|
||||
// Attempts to read count bytes from the file into the specified buffer.
|
||||
FMT_API std::size_t read(void* buffer, std::size_t count);
|
||||
|
||||
// Attempts to write count bytes from the specified buffer to the file.
|
||||
FMT_API std::size_t write(const void* buffer, std::size_t count);
|
||||
|
||||
// Duplicates a file descriptor with the dup function and returns
|
||||
// the duplicate as a file object.
|
||||
FMT_API static file dup(int fd);
|
||||
|
||||
// Makes fd be the copy of this file descriptor, closing fd first if
|
||||
// necessary.
|
||||
FMT_API void dup2(int fd);
|
||||
|
||||
// Makes fd be the copy of this file descriptor, closing fd first if
|
||||
// necessary.
|
||||
FMT_API void dup2(int fd, error_code& ec) FMT_NOEXCEPT;
|
||||
|
||||
// Creates a pipe setting up read_end and write_end file objects for reading
|
||||
// and writing respectively.
|
||||
FMT_API static void pipe(file& read_end, file& write_end);
|
||||
|
||||
// Creates a buffered_file object associated with this file and detaches
|
||||
// this file object from the file.
|
||||
FMT_API buffered_file fdopen(const char* mode);
|
||||
};
|
||||
|
||||
// Returns the memory page size.
|
||||
long getpagesize();
|
||||
|
||||
#ifdef FMT_LOCALE
|
||||
// A "C" numeric locale.
|
||||
class Locale {
|
||||
private:
|
||||
# ifdef _WIN32
|
||||
using locale_t = _locale_t;
|
||||
|
||||
enum { LC_NUMERIC_MASK = LC_NUMERIC };
|
||||
|
||||
static locale_t newlocale(int category_mask, const char* locale, locale_t) {
|
||||
return _create_locale(category_mask, locale);
|
||||
}
|
||||
|
||||
static void freelocale(locale_t locale) { _free_locale(locale); }
|
||||
|
||||
static double strtod_l(const char* nptr, char** endptr, _locale_t locale) {
|
||||
return _strtod_l(nptr, endptr, locale);
|
||||
}
|
||||
# endif
|
||||
|
||||
locale_t locale_;
|
||||
|
||||
Locale(const Locale&) = delete;
|
||||
void operator=(const Locale&) = delete;
|
||||
|
||||
public:
|
||||
using type = locale_t;
|
||||
|
||||
Locale() : locale_(newlocale(LC_NUMERIC_MASK, "C", nullptr)) {
|
||||
if (!locale_) FMT_THROW(system_error(errno, "cannot create locale"));
|
||||
}
|
||||
~Locale() { freelocale(locale_); }
|
||||
|
||||
type get() const { return locale_; }
|
||||
|
||||
// Converts string to floating-point number and advances str past the end
|
||||
// of the parsed input.
|
||||
double strtod(const char*& str) const {
|
||||
char* end = nullptr;
|
||||
double result = strtod_l(str, &end, locale_);
|
||||
str = end;
|
||||
return result;
|
||||
}
|
||||
};
|
||||
#endif // FMT_LOCALE
|
||||
FMT_END_NAMESPACE
|
||||
|
||||
#endif // FMT_POSIX_H_
|
715
vtkm/thirdparty/diy/vtkmdiy/include/vtkmdiy/thirdparty/fmt/printf.h
vendored
Normal file
715
vtkm/thirdparty/diy/vtkmdiy/include/vtkmdiy/thirdparty/fmt/printf.h
vendored
Normal file
@ -0,0 +1,715 @@
|
||||
// Formatting library for C++
|
||||
//
|
||||
// Copyright (c) 2012 - 2016, Victor Zverovich
|
||||
// All rights reserved.
|
||||
//
|
||||
// For the license information refer to format.h.
|
||||
|
||||
#ifndef FMT_PRINTF_H_
|
||||
#define FMT_PRINTF_H_
|
||||
|
||||
#include <algorithm> // std::fill_n
|
||||
#include <limits> // std::numeric_limits
|
||||
|
||||
#include "ostream.h"
|
||||
|
||||
FMT_BEGIN_NAMESPACE
|
||||
namespace internal {
|
||||
|
||||
// A helper function to suppress bogus "conditional expression is constant"
|
||||
// warnings.
|
||||
template <typename T> inline T const_check(T value) { return value; }
|
||||
|
||||
// Checks if a value fits in int - used to avoid warnings about comparing
|
||||
// signed and unsigned integers.
|
||||
template <bool IsSigned> struct int_checker {
|
||||
template <typename T> static bool fits_in_int(T value) {
|
||||
unsigned max = std::numeric_limits<int>::max();
|
||||
return value <= max;
|
||||
}
|
||||
static bool fits_in_int(bool) { return true; }
|
||||
};
|
||||
|
||||
template <> struct int_checker<true> {
|
||||
template <typename T> static bool fits_in_int(T value) {
|
||||
return value >= std::numeric_limits<int>::min() &&
|
||||
value <= std::numeric_limits<int>::max();
|
||||
}
|
||||
static bool fits_in_int(int) { return true; }
|
||||
};
|
||||
|
||||
class printf_precision_handler {
|
||||
public:
|
||||
template <typename T, FMT_ENABLE_IF(std::is_integral<T>::value)>
|
||||
int operator()(T value) {
|
||||
if (!int_checker<std::numeric_limits<T>::is_signed>::fits_in_int(value))
|
||||
FMT_THROW(format_error("number is too big"));
|
||||
return (std::max)(static_cast<int>(value), 0);
|
||||
}
|
||||
|
||||
template <typename T, FMT_ENABLE_IF(!std::is_integral<T>::value)>
|
||||
int operator()(T) {
|
||||
FMT_THROW(format_error("precision is not integer"));
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
// An argument visitor that returns true iff arg is a zero integer.
|
||||
class is_zero_int {
|
||||
public:
|
||||
template <typename T, FMT_ENABLE_IF(std::is_integral<T>::value)>
|
||||
bool operator()(T value) {
|
||||
return value == 0;
|
||||
}
|
||||
|
||||
template <typename T, FMT_ENABLE_IF(!std::is_integral<T>::value)>
|
||||
bool operator()(T) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T> struct make_unsigned_or_bool : std::make_unsigned<T> {};
|
||||
|
||||
template <> struct make_unsigned_or_bool<bool> { using type = bool; };
|
||||
|
||||
template <typename T, typename Context> class arg_converter {
|
||||
private:
|
||||
using char_type = typename Context::char_type;
|
||||
|
||||
basic_format_arg<Context>& arg_;
|
||||
char_type type_;
|
||||
|
||||
public:
|
||||
arg_converter(basic_format_arg<Context>& arg, char_type type)
|
||||
: arg_(arg), type_(type) {}
|
||||
|
||||
void operator()(bool value) {
|
||||
if (type_ != 's') operator()<bool>(value);
|
||||
}
|
||||
|
||||
template <typename U, FMT_ENABLE_IF(std::is_integral<U>::value)>
|
||||
void operator()(U value) {
|
||||
bool is_signed = type_ == 'd' || type_ == 'i';
|
||||
using target_type = conditional_t<std::is_same<T, void>::value, U, T>;
|
||||
if (const_check(sizeof(target_type) <= sizeof(int))) {
|
||||
// Extra casts are used to silence warnings.
|
||||
if (is_signed) {
|
||||
arg_ = internal::make_arg<Context>(
|
||||
static_cast<int>(static_cast<target_type>(value)));
|
||||
} else {
|
||||
using unsigned_type = typename make_unsigned_or_bool<target_type>::type;
|
||||
arg_ = internal::make_arg<Context>(
|
||||
static_cast<unsigned>(static_cast<unsigned_type>(value)));
|
||||
}
|
||||
} else {
|
||||
if (is_signed) {
|
||||
// glibc's printf doesn't sign extend arguments of smaller types:
|
||||
// std::printf("%lld", -42); // prints "4294967254"
|
||||
// but we don't have to do the same because it's a UB.
|
||||
arg_ = internal::make_arg<Context>(static_cast<long long>(value));
|
||||
} else {
|
||||
arg_ = internal::make_arg<Context>(
|
||||
static_cast<typename make_unsigned_or_bool<U>::type>(value));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename U, FMT_ENABLE_IF(!std::is_integral<U>::value)>
|
||||
void operator()(U) {} // No conversion needed for non-integral types.
|
||||
};
|
||||
|
||||
// Converts an integer argument to T for printf, if T is an integral type.
|
||||
// If T is void, the argument is converted to corresponding signed or unsigned
|
||||
// type depending on the type specifier: 'd' and 'i' - signed, other -
|
||||
// unsigned).
|
||||
template <typename T, typename Context, typename Char>
|
||||
void convert_arg(basic_format_arg<Context>& arg, Char type) {
|
||||
visit_format_arg(arg_converter<T, Context>(arg, type), arg);
|
||||
}
|
||||
|
||||
// Converts an integer argument to char for printf.
|
||||
template <typename Context> class char_converter {
|
||||
private:
|
||||
basic_format_arg<Context>& arg_;
|
||||
|
||||
public:
|
||||
explicit char_converter(basic_format_arg<Context>& arg) : arg_(arg) {}
|
||||
|
||||
template <typename T, FMT_ENABLE_IF(std::is_integral<T>::value)>
|
||||
void operator()(T value) {
|
||||
arg_ = internal::make_arg<Context>(
|
||||
static_cast<typename Context::char_type>(value));
|
||||
}
|
||||
|
||||
template <typename T, FMT_ENABLE_IF(!std::is_integral<T>::value)>
|
||||
void operator()(T) {} // No conversion needed for non-integral types.
|
||||
};
|
||||
|
||||
// Checks if an argument is a valid printf width specifier and sets
|
||||
// left alignment if it is negative.
|
||||
template <typename Char> class printf_width_handler {
|
||||
private:
|
||||
using format_specs = basic_format_specs<Char>;
|
||||
|
||||
format_specs& specs_;
|
||||
|
||||
public:
|
||||
explicit printf_width_handler(format_specs& specs) : specs_(specs) {}
|
||||
|
||||
template <typename T, FMT_ENABLE_IF(std::is_integral<T>::value)>
|
||||
unsigned operator()(T value) {
|
||||
auto width = static_cast<uint32_or_64_t<T>>(value);
|
||||
if (internal::is_negative(value)) {
|
||||
specs_.align = align::left;
|
||||
width = 0 - width;
|
||||
}
|
||||
unsigned int_max = std::numeric_limits<int>::max();
|
||||
if (width > int_max) FMT_THROW(format_error("number is too big"));
|
||||
return static_cast<unsigned>(width);
|
||||
}
|
||||
|
||||
template <typename T, FMT_ENABLE_IF(!std::is_integral<T>::value)>
|
||||
unsigned operator()(T) {
|
||||
FMT_THROW(format_error("width is not integer"));
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Char, typename Context>
|
||||
void printf(buffer<Char>& buf, basic_string_view<Char> format,
|
||||
basic_format_args<Context> args) {
|
||||
Context(std::back_inserter(buf), format, args).format();
|
||||
}
|
||||
|
||||
template <typename OutputIt, typename Char, typename Context>
|
||||
internal::truncating_iterator<OutputIt> printf(
|
||||
internal::truncating_iterator<OutputIt> it, basic_string_view<Char> format,
|
||||
basic_format_args<Context> args) {
|
||||
return Context(it, format, args).format();
|
||||
}
|
||||
} // namespace internal
|
||||
|
||||
using internal::printf; // For printing into memory_buffer.
|
||||
|
||||
template <typename Range> class printf_arg_formatter;
|
||||
|
||||
template <typename OutputIt, typename Char> class basic_printf_context;
|
||||
|
||||
/**
|
||||
\rst
|
||||
The ``printf`` argument formatter.
|
||||
\endrst
|
||||
*/
|
||||
template <typename Range>
|
||||
class printf_arg_formatter : public internal::arg_formatter_base<Range> {
|
||||
public:
|
||||
using iterator = typename Range::iterator;
|
||||
|
||||
private:
|
||||
using char_type = typename Range::value_type;
|
||||
using base = internal::arg_formatter_base<Range>;
|
||||
using context_type = basic_printf_context<iterator, char_type>;
|
||||
|
||||
context_type& context_;
|
||||
|
||||
void write_null_pointer(char) {
|
||||
this->specs()->type = 0;
|
||||
this->write("(nil)");
|
||||
}
|
||||
|
||||
void write_null_pointer(wchar_t) {
|
||||
this->specs()->type = 0;
|
||||
this->write(L"(nil)");
|
||||
}
|
||||
|
||||
public:
|
||||
using format_specs = typename base::format_specs;
|
||||
|
||||
/**
|
||||
\rst
|
||||
Constructs an argument formatter object.
|
||||
*buffer* is a reference to the output buffer and *specs* contains format
|
||||
specifier information for standard argument types.
|
||||
\endrst
|
||||
*/
|
||||
printf_arg_formatter(iterator iter, format_specs& specs, context_type& ctx)
|
||||
: base(Range(iter), &specs, internal::locale_ref()), context_(ctx) {}
|
||||
|
||||
template <typename T, FMT_ENABLE_IF(std::is_integral<T>::value)>
|
||||
iterator operator()(T value) {
|
||||
// MSVC2013 fails to compile separate overloads for bool and char_type so
|
||||
// use std::is_same instead.
|
||||
if (std::is_same<T, bool>::value) {
|
||||
format_specs& fmt_specs = *this->specs();
|
||||
if (fmt_specs.type != 's') return base::operator()(value ? 1 : 0);
|
||||
fmt_specs.type = 0;
|
||||
this->write(value != 0);
|
||||
} else if (std::is_same<T, char_type>::value) {
|
||||
format_specs& fmt_specs = *this->specs();
|
||||
if (fmt_specs.type && fmt_specs.type != 'c')
|
||||
return (*this)(static_cast<int>(value));
|
||||
fmt_specs.sign = sign::none;
|
||||
fmt_specs.alt = false;
|
||||
fmt_specs.align = align::right;
|
||||
return base::operator()(value);
|
||||
} else {
|
||||
return base::operator()(value);
|
||||
}
|
||||
return this->out();
|
||||
}
|
||||
|
||||
template <typename T, FMT_ENABLE_IF(std::is_floating_point<T>::value)>
|
||||
iterator operator()(T value) {
|
||||
return base::operator()(value);
|
||||
}
|
||||
|
||||
/** Formats a null-terminated C string. */
|
||||
iterator operator()(const char* value) {
|
||||
if (value)
|
||||
base::operator()(value);
|
||||
else if (this->specs()->type == 'p')
|
||||
write_null_pointer(char_type());
|
||||
else
|
||||
this->write("(null)");
|
||||
return this->out();
|
||||
}
|
||||
|
||||
/** Formats a null-terminated wide C string. */
|
||||
iterator operator()(const wchar_t* value) {
|
||||
if (value)
|
||||
base::operator()(value);
|
||||
else if (this->specs()->type == 'p')
|
||||
write_null_pointer(char_type());
|
||||
else
|
||||
this->write(L"(null)");
|
||||
return this->out();
|
||||
}
|
||||
|
||||
iterator operator()(basic_string_view<char_type> value) {
|
||||
return base::operator()(value);
|
||||
}
|
||||
|
||||
iterator operator()(monostate value) { return base::operator()(value); }
|
||||
|
||||
/** Formats a pointer. */
|
||||
iterator operator()(const void* value) {
|
||||
if (value) return base::operator()(value);
|
||||
this->specs()->type = 0;
|
||||
write_null_pointer(char_type());
|
||||
return this->out();
|
||||
}
|
||||
|
||||
/** Formats an argument of a custom (user-defined) type. */
|
||||
iterator operator()(typename basic_format_arg<context_type>::handle handle) {
|
||||
handle.format(context_.parse_context(), context_);
|
||||
return this->out();
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T> struct printf_formatter {
|
||||
template <typename ParseContext>
|
||||
auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
|
||||
return ctx.begin();
|
||||
}
|
||||
|
||||
template <typename FormatContext>
|
||||
auto format(const T& value, FormatContext& ctx) -> decltype(ctx.out()) {
|
||||
internal::format_value(internal::get_container(ctx.out()), value);
|
||||
return ctx.out();
|
||||
}
|
||||
};
|
||||
|
||||
/** This template formats data and writes the output to a writer. */
|
||||
template <typename OutputIt, typename Char> class basic_printf_context {
|
||||
public:
|
||||
/** The character type for the output. */
|
||||
using char_type = Char;
|
||||
using format_arg = basic_format_arg<basic_printf_context>;
|
||||
template <typename T> using formatter_type = printf_formatter<T>;
|
||||
|
||||
private:
|
||||
using format_specs = basic_format_specs<char_type>;
|
||||
|
||||
OutputIt out_;
|
||||
basic_format_args<basic_printf_context> args_;
|
||||
basic_parse_context<Char> parse_ctx_;
|
||||
|
||||
static void parse_flags(format_specs& specs, const Char*& it,
|
||||
const Char* end);
|
||||
|
||||
// Returns the argument with specified index or, if arg_index is equal
|
||||
// to the maximum unsigned value, the next argument.
|
||||
format_arg get_arg(unsigned arg_index = std::numeric_limits<unsigned>::max());
|
||||
|
||||
// Parses argument index, flags and width and returns the argument index.
|
||||
unsigned parse_header(const Char*& it, const Char* end, format_specs& specs);
|
||||
|
||||
public:
|
||||
/**
|
||||
\rst
|
||||
Constructs a ``printf_context`` object. References to the arguments and
|
||||
the writer are stored in the context object so make sure they have
|
||||
appropriate lifetimes.
|
||||
\endrst
|
||||
*/
|
||||
basic_printf_context(OutputIt out, basic_string_view<char_type> format_str,
|
||||
basic_format_args<basic_printf_context> args)
|
||||
: out_(out), args_(args), parse_ctx_(format_str) {}
|
||||
|
||||
OutputIt out() { return out_; }
|
||||
void advance_to(OutputIt it) { out_ = it; }
|
||||
|
||||
format_arg arg(unsigned id) const { return args_.get(id); }
|
||||
|
||||
basic_parse_context<Char>& parse_context() { return parse_ctx_; }
|
||||
|
||||
FMT_CONSTEXPR void on_error(const char* message) {
|
||||
parse_ctx_.on_error(message);
|
||||
}
|
||||
|
||||
/** Formats stored arguments and writes the output to the range. */
|
||||
template <typename ArgFormatter =
|
||||
printf_arg_formatter<internal::buffer_range<Char>>>
|
||||
OutputIt format();
|
||||
};
|
||||
|
||||
template <typename OutputIt, typename Char>
|
||||
void basic_printf_context<OutputIt, Char>::parse_flags(format_specs& specs,
|
||||
const Char*& it,
|
||||
const Char* end) {
|
||||
for (; it != end; ++it) {
|
||||
switch (*it) {
|
||||
case '-':
|
||||
specs.align = align::left;
|
||||
break;
|
||||
case '+':
|
||||
specs.sign = sign::plus;
|
||||
break;
|
||||
case '0':
|
||||
specs.fill[0] = '0';
|
||||
break;
|
||||
case ' ':
|
||||
specs.sign = sign::space;
|
||||
break;
|
||||
case '#':
|
||||
specs.alt = true;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename OutputIt, typename Char>
|
||||
typename basic_printf_context<OutputIt, Char>::format_arg
|
||||
basic_printf_context<OutputIt, Char>::get_arg(unsigned arg_index) {
|
||||
if (arg_index == std::numeric_limits<unsigned>::max())
|
||||
arg_index = parse_ctx_.next_arg_id();
|
||||
else
|
||||
parse_ctx_.check_arg_id(--arg_index);
|
||||
return internal::get_arg(*this, arg_index);
|
||||
}
|
||||
|
||||
template <typename OutputIt, typename Char>
|
||||
unsigned basic_printf_context<OutputIt, Char>::parse_header(
|
||||
const Char*& it, const Char* end, format_specs& specs) {
|
||||
unsigned arg_index = std::numeric_limits<unsigned>::max();
|
||||
char_type c = *it;
|
||||
if (c >= '0' && c <= '9') {
|
||||
// Parse an argument index (if followed by '$') or a width possibly
|
||||
// preceded with '0' flag(s).
|
||||
internal::error_handler eh;
|
||||
unsigned value = parse_nonnegative_int(it, end, eh);
|
||||
if (it != end && *it == '$') { // value is an argument index
|
||||
++it;
|
||||
arg_index = value;
|
||||
} else {
|
||||
if (c == '0') specs.fill[0] = '0';
|
||||
if (value != 0) {
|
||||
// Nonzero value means that we parsed width and don't need to
|
||||
// parse it or flags again, so return now.
|
||||
specs.width = value;
|
||||
return arg_index;
|
||||
}
|
||||
}
|
||||
}
|
||||
parse_flags(specs, it, end);
|
||||
// Parse width.
|
||||
if (it != end) {
|
||||
if (*it >= '0' && *it <= '9') {
|
||||
internal::error_handler eh;
|
||||
specs.width = parse_nonnegative_int(it, end, eh);
|
||||
} else if (*it == '*') {
|
||||
++it;
|
||||
specs.width = visit_format_arg(
|
||||
internal::printf_width_handler<char_type>(specs), get_arg());
|
||||
}
|
||||
}
|
||||
return arg_index;
|
||||
}
|
||||
|
||||
template <typename OutputIt, typename Char>
|
||||
template <typename ArgFormatter>
|
||||
OutputIt basic_printf_context<OutputIt, Char>::format() {
|
||||
auto out = this->out();
|
||||
const Char* start = parse_ctx_.begin();
|
||||
const Char* end = parse_ctx_.end();
|
||||
auto it = start;
|
||||
while (it != end) {
|
||||
char_type c = *it++;
|
||||
if (c != '%') continue;
|
||||
if (it != end && *it == c) {
|
||||
out = std::copy(start, it, out);
|
||||
start = ++it;
|
||||
continue;
|
||||
}
|
||||
out = std::copy(start, it - 1, out);
|
||||
|
||||
format_specs specs;
|
||||
specs.align = align::right;
|
||||
|
||||
// Parse argument index, flags and width.
|
||||
unsigned arg_index = parse_header(it, end, specs);
|
||||
|
||||
// Parse precision.
|
||||
if (it != end && *it == '.') {
|
||||
++it;
|
||||
c = it != end ? *it : 0;
|
||||
if ('0' <= c && c <= '9') {
|
||||
internal::error_handler eh;
|
||||
specs.precision = static_cast<int>(parse_nonnegative_int(it, end, eh));
|
||||
} else if (c == '*') {
|
||||
++it;
|
||||
specs.precision =
|
||||
visit_format_arg(internal::printf_precision_handler(), get_arg());
|
||||
} else {
|
||||
specs.precision = 0;
|
||||
}
|
||||
}
|
||||
|
||||
format_arg arg = get_arg(arg_index);
|
||||
if (specs.alt && visit_format_arg(internal::is_zero_int(), arg))
|
||||
specs.alt = false;
|
||||
if (specs.fill[0] == '0') {
|
||||
if (arg.is_arithmetic())
|
||||
specs.align = align::numeric;
|
||||
else
|
||||
specs.fill[0] = ' '; // Ignore '0' flag for non-numeric types.
|
||||
}
|
||||
|
||||
// Parse length and convert the argument to the required type.
|
||||
c = it != end ? *it++ : 0;
|
||||
char_type t = it != end ? *it : 0;
|
||||
using internal::convert_arg;
|
||||
switch (c) {
|
||||
case 'h':
|
||||
if (t == 'h') {
|
||||
++it;
|
||||
t = it != end ? *it : 0;
|
||||
convert_arg<signed char>(arg, t);
|
||||
} else {
|
||||
convert_arg<short>(arg, t);
|
||||
}
|
||||
break;
|
||||
case 'l':
|
||||
if (t == 'l') {
|
||||
++it;
|
||||
t = it != end ? *it : 0;
|
||||
convert_arg<long long>(arg, t);
|
||||
} else {
|
||||
convert_arg<long>(arg, t);
|
||||
}
|
||||
break;
|
||||
case 'j':
|
||||
convert_arg<intmax_t>(arg, t);
|
||||
break;
|
||||
case 'z':
|
||||
convert_arg<std::size_t>(arg, t);
|
||||
break;
|
||||
case 't':
|
||||
convert_arg<std::ptrdiff_t>(arg, t);
|
||||
break;
|
||||
case 'L':
|
||||
// printf produces garbage when 'L' is omitted for long double, no
|
||||
// need to do the same.
|
||||
break;
|
||||
default:
|
||||
--it;
|
||||
convert_arg<void>(arg, c);
|
||||
}
|
||||
|
||||
// Parse type.
|
||||
if (it == end) FMT_THROW(format_error("invalid format string"));
|
||||
specs.type = static_cast<char>(*it++);
|
||||
if (arg.is_integral()) {
|
||||
// Normalize type.
|
||||
switch (specs.type) {
|
||||
case 'i':
|
||||
case 'u':
|
||||
specs.type = 'd';
|
||||
break;
|
||||
case 'c':
|
||||
visit_format_arg(internal::char_converter<basic_printf_context>(arg),
|
||||
arg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
start = it;
|
||||
|
||||
// Format argument.
|
||||
visit_format_arg(ArgFormatter(out, specs, *this), arg);
|
||||
}
|
||||
return std::copy(start, it, out);
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
using basic_printf_context_t =
|
||||
basic_printf_context<std::back_insert_iterator<internal::buffer<Char>>,
|
||||
Char>;
|
||||
|
||||
using printf_context = basic_printf_context_t<char>;
|
||||
using wprintf_context = basic_printf_context_t<wchar_t>;
|
||||
|
||||
using printf_args = basic_format_args<printf_context>;
|
||||
using wprintf_args = basic_format_args<wprintf_context>;
|
||||
|
||||
/**
|
||||
\rst
|
||||
Constructs an `~fmt::format_arg_store` object that contains references to
|
||||
arguments and can be implicitly converted to `~fmt::printf_args`.
|
||||
\endrst
|
||||
*/
|
||||
template <typename... Args>
|
||||
inline format_arg_store<printf_context, Args...> make_printf_args(
|
||||
const Args&... args) {
|
||||
return {args...};
|
||||
}
|
||||
|
||||
/**
|
||||
\rst
|
||||
Constructs an `~fmt::format_arg_store` object that contains references to
|
||||
arguments and can be implicitly converted to `~fmt::wprintf_args`.
|
||||
\endrst
|
||||
*/
|
||||
template <typename... Args>
|
||||
inline format_arg_store<wprintf_context, Args...> make_wprintf_args(
|
||||
const Args&... args) {
|
||||
return {args...};
|
||||
}
|
||||
|
||||
template <typename S, typename Char = char_t<S>>
|
||||
inline std::basic_string<Char> vsprintf(
|
||||
const S& format, basic_format_args<basic_printf_context_t<Char>> args) {
|
||||
basic_memory_buffer<Char> buffer;
|
||||
printf(buffer, to_string_view(format), args);
|
||||
return to_string(buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
\rst
|
||||
Formats arguments and returns the result as a string.
|
||||
|
||||
**Example**::
|
||||
|
||||
std::string message = fmt::sprintf("The answer is %d", 42);
|
||||
\endrst
|
||||
*/
|
||||
template <typename S, typename... Args,
|
||||
typename Char = enable_if_t<internal::is_string<S>::value, char_t<S>>>
|
||||
inline std::basic_string<Char> sprintf(const S& format, const Args&... args) {
|
||||
using context = basic_printf_context_t<Char>;
|
||||
return vsprintf(to_string_view(format), {make_format_args<context>(args...)});
|
||||
}
|
||||
|
||||
template <typename S, typename Char = char_t<S>>
|
||||
inline int vfprintf(std::FILE* f, const S& format,
|
||||
basic_format_args<basic_printf_context_t<Char>> args) {
|
||||
basic_memory_buffer<Char> buffer;
|
||||
printf(buffer, to_string_view(format), args);
|
||||
std::size_t size = buffer.size();
|
||||
return std::fwrite(buffer.data(), sizeof(Char), size, f) < size
|
||||
? -1
|
||||
: static_cast<int>(size);
|
||||
}
|
||||
|
||||
/**
|
||||
\rst
|
||||
Prints formatted data to the file *f*.
|
||||
|
||||
**Example**::
|
||||
|
||||
fmt::fprintf(stderr, "Don't %s!", "panic");
|
||||
\endrst
|
||||
*/
|
||||
template <typename S, typename... Args,
|
||||
typename Char = enable_if_t<internal::is_string<S>::value, char_t<S>>>
|
||||
inline int fprintf(std::FILE* f, const S& format, const Args&... args) {
|
||||
using context = basic_printf_context_t<Char>;
|
||||
return vfprintf(f, to_string_view(format),
|
||||
{make_format_args<context>(args...)});
|
||||
}
|
||||
|
||||
template <typename S, typename Char = char_t<S>>
|
||||
inline int vprintf(const S& format,
|
||||
basic_format_args<basic_printf_context_t<Char>> args) {
|
||||
return vfprintf(stdout, to_string_view(format), args);
|
||||
}
|
||||
|
||||
/**
|
||||
\rst
|
||||
Prints formatted data to ``stdout``.
|
||||
|
||||
**Example**::
|
||||
|
||||
fmt::printf("Elapsed time: %.2f seconds", 1.23);
|
||||
\endrst
|
||||
*/
|
||||
template <typename S, typename... Args,
|
||||
FMT_ENABLE_IF(internal::is_string<S>::value)>
|
||||
inline int printf(const S& format_str, const Args&... args) {
|
||||
using context = basic_printf_context_t<char_t<S>>;
|
||||
return vprintf(to_string_view(format_str),
|
||||
{make_format_args<context>(args...)});
|
||||
}
|
||||
|
||||
template <typename S, typename Char = char_t<S>>
|
||||
inline int vfprintf(std::basic_ostream<Char>& os, const S& format,
|
||||
basic_format_args<basic_printf_context_t<Char>> args) {
|
||||
basic_memory_buffer<Char> buffer;
|
||||
printf(buffer, to_string_view(format), args);
|
||||
internal::write(os, buffer);
|
||||
return static_cast<int>(buffer.size());
|
||||
}
|
||||
|
||||
/** Formats arguments and writes the output to the range. */
|
||||
template <typename ArgFormatter, typename Char,
|
||||
typename Context =
|
||||
basic_printf_context<typename ArgFormatter::iterator, Char>>
|
||||
typename ArgFormatter::iterator vprintf(internal::buffer<Char>& out,
|
||||
basic_string_view<Char> format_str,
|
||||
basic_format_args<Context> args) {
|
||||
typename ArgFormatter::iterator iter(out);
|
||||
Context(iter, format_str, args).template format<ArgFormatter>();
|
||||
return iter;
|
||||
}
|
||||
|
||||
/**
|
||||
\rst
|
||||
Prints formatted data to the stream *os*.
|
||||
|
||||
**Example**::
|
||||
|
||||
fmt::fprintf(cerr, "Don't %s!", "panic");
|
||||
\endrst
|
||||
*/
|
||||
template <typename S, typename... Args, typename Char = char_t<S>>
|
||||
inline int fprintf(std::basic_ostream<Char>& os, const S& format_str,
|
||||
const Args&... args) {
|
||||
using context = basic_printf_context_t<Char>;
|
||||
return vfprintf(os, to_string_view(format_str),
|
||||
{make_format_args<context>(args...)});
|
||||
}
|
||||
FMT_END_NAMESPACE
|
||||
|
||||
#endif // FMT_PRINTF_H_
|
288
vtkm/thirdparty/diy/vtkmdiy/include/vtkmdiy/thirdparty/fmt/ranges.h
vendored
Normal file
288
vtkm/thirdparty/diy/vtkmdiy/include/vtkmdiy/thirdparty/fmt/ranges.h
vendored
Normal file
@ -0,0 +1,288 @@
|
||||
// Formatting library for C++ - experimental range support
|
||||
//
|
||||
// Copyright (c) 2012 - present, Victor Zverovich
|
||||
// All rights reserved.
|
||||
//
|
||||
// For the license information refer to format.h.
|
||||
//
|
||||
// Copyright (c) 2018 - present, Remotion (Igor Schulz)
|
||||
// All Rights Reserved
|
||||
// {fmt} support for ranges, containers and types tuple interface.
|
||||
|
||||
#ifndef FMT_RANGES_H_
|
||||
#define FMT_RANGES_H_
|
||||
|
||||
#include <type_traits>
|
||||
#include "format.h"
|
||||
|
||||
// output only up to N items from the range.
|
||||
#ifndef FMT_RANGE_OUTPUT_LENGTH_LIMIT
|
||||
# define FMT_RANGE_OUTPUT_LENGTH_LIMIT 256
|
||||
#endif
|
||||
|
||||
FMT_BEGIN_NAMESPACE
|
||||
|
||||
template <typename Char> struct formatting_base {
|
||||
template <typename ParseContext>
|
||||
FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
|
||||
return ctx.begin();
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Char, typename Enable = void>
|
||||
struct formatting_range : formatting_base<Char> {
|
||||
static FMT_CONSTEXPR_DECL const std::size_t range_length_limit =
|
||||
FMT_RANGE_OUTPUT_LENGTH_LIMIT; // output only up to N items from the
|
||||
// range.
|
||||
Char prefix;
|
||||
Char delimiter;
|
||||
Char postfix;
|
||||
formatting_range() : prefix('{'), delimiter(','), postfix('}') {}
|
||||
static FMT_CONSTEXPR_DECL const bool add_delimiter_spaces = true;
|
||||
static FMT_CONSTEXPR_DECL const bool add_prepostfix_space = false;
|
||||
};
|
||||
|
||||
template <typename Char, typename Enable = void>
|
||||
struct formatting_tuple : formatting_base<Char> {
|
||||
Char prefix;
|
||||
Char delimiter;
|
||||
Char postfix;
|
||||
formatting_tuple() : prefix('('), delimiter(','), postfix(')') {}
|
||||
static FMT_CONSTEXPR_DECL const bool add_delimiter_spaces = true;
|
||||
static FMT_CONSTEXPR_DECL const bool add_prepostfix_space = false;
|
||||
};
|
||||
|
||||
namespace internal {
|
||||
|
||||
template <typename RangeT, typename OutputIterator>
|
||||
OutputIterator copy(const RangeT& range, OutputIterator out) {
|
||||
for (auto it = range.begin(), end = range.end(); it != end; ++it)
|
||||
*out++ = *it;
|
||||
return out;
|
||||
}
|
||||
|
||||
template <typename OutputIterator>
|
||||
OutputIterator copy(const char* str, OutputIterator out) {
|
||||
while (*str) *out++ = *str++;
|
||||
return out;
|
||||
}
|
||||
|
||||
template <typename OutputIterator>
|
||||
OutputIterator copy(char ch, OutputIterator out) {
|
||||
*out++ = ch;
|
||||
return out;
|
||||
}
|
||||
|
||||
/// Return true value if T has std::string interface, like std::string_view.
|
||||
template <typename T> class is_like_std_string {
|
||||
template <typename U>
|
||||
static auto check(U* p)
|
||||
-> decltype((void)p->find('a'), p->length(), (void)p->data(), int());
|
||||
template <typename> static void check(...);
|
||||
|
||||
public:
|
||||
static FMT_CONSTEXPR_DECL const bool value =
|
||||
is_string<T>::value || !std::is_void<decltype(check<T>(nullptr))>::value;
|
||||
};
|
||||
|
||||
template <typename Char>
|
||||
struct is_like_std_string<fmt::basic_string_view<Char>> : std::true_type {};
|
||||
|
||||
template <typename... Ts> struct conditional_helper {};
|
||||
|
||||
template <typename T, typename _ = void> struct is_range_ : std::false_type {};
|
||||
|
||||
#if !FMT_MSC_VER || FMT_MSC_VER > 1800
|
||||
template <typename T>
|
||||
struct is_range_<
|
||||
T, conditional_t<false,
|
||||
conditional_helper<decltype(std::declval<T>().begin()),
|
||||
decltype(std::declval<T>().end())>,
|
||||
void>> : std::true_type {};
|
||||
#endif
|
||||
|
||||
/// tuple_size and tuple_element check.
|
||||
template <typename T> class is_tuple_like_ {
|
||||
template <typename U>
|
||||
static auto check(U* p)
|
||||
-> decltype(std::tuple_size<U>::value,
|
||||
(void)std::declval<typename std::tuple_element<0, U>::type>(),
|
||||
int());
|
||||
template <typename> static void check(...);
|
||||
|
||||
public:
|
||||
static FMT_CONSTEXPR_DECL const bool value =
|
||||
!std::is_void<decltype(check<T>(nullptr))>::value;
|
||||
};
|
||||
|
||||
// Check for integer_sequence
|
||||
#if defined(__cpp_lib_integer_sequence) || FMT_MSC_VER >= 1900
|
||||
template <typename T, T... N>
|
||||
using integer_sequence = std::integer_sequence<T, N...>;
|
||||
template <std::size_t... N> using index_sequence = std::index_sequence<N...>;
|
||||
template <std::size_t N>
|
||||
using make_index_sequence = std::make_index_sequence<N>;
|
||||
#else
|
||||
template <typename T, T... N> struct integer_sequence {
|
||||
using value_type = T;
|
||||
|
||||
static FMT_CONSTEXPR std::size_t size() { return sizeof...(N); }
|
||||
};
|
||||
|
||||
template <std::size_t... N>
|
||||
using index_sequence = integer_sequence<std::size_t, N...>;
|
||||
|
||||
template <typename T, std::size_t N, T... Ns>
|
||||
struct make_integer_sequence : make_integer_sequence<T, N - 1, N - 1, Ns...> {};
|
||||
template <typename T, T... Ns>
|
||||
struct make_integer_sequence<T, 0, Ns...> : integer_sequence<T, Ns...> {};
|
||||
|
||||
template <std::size_t N>
|
||||
using make_index_sequence = make_integer_sequence<std::size_t, N>;
|
||||
#endif
|
||||
|
||||
template <class Tuple, class F, size_t... Is>
|
||||
void for_each(index_sequence<Is...>, Tuple&& tup, F&& f) FMT_NOEXCEPT {
|
||||
using std::get;
|
||||
// using free function get<I>(T) now.
|
||||
const int _[] = {0, ((void)f(get<Is>(tup)), 0)...};
|
||||
(void)_; // blocks warnings
|
||||
}
|
||||
|
||||
template <class T>
|
||||
FMT_CONSTEXPR make_index_sequence<std::tuple_size<T>::value> get_indexes(
|
||||
T const&) {
|
||||
return {};
|
||||
}
|
||||
|
||||
template <class Tuple, class F> void for_each(Tuple&& tup, F&& f) {
|
||||
const auto indexes = get_indexes(tup);
|
||||
for_each(indexes, std::forward<Tuple>(tup), std::forward<F>(f));
|
||||
}
|
||||
|
||||
template <typename Arg, FMT_ENABLE_IF(!is_like_std_string<
|
||||
typename std::decay<Arg>::type>::value)>
|
||||
FMT_CONSTEXPR const char* format_str_quoted(bool add_space, const Arg&) {
|
||||
return add_space ? " {}" : "{}";
|
||||
}
|
||||
|
||||
template <typename Arg, FMT_ENABLE_IF(is_like_std_string<
|
||||
typename std::decay<Arg>::type>::value)>
|
||||
FMT_CONSTEXPR const char* format_str_quoted(bool add_space, const Arg&) {
|
||||
return add_space ? " \"{}\"" : "\"{}\"";
|
||||
}
|
||||
|
||||
FMT_CONSTEXPR const char* format_str_quoted(bool add_space, const char*) {
|
||||
return add_space ? " \"{}\"" : "\"{}\"";
|
||||
}
|
||||
FMT_CONSTEXPR const wchar_t* format_str_quoted(bool add_space, const wchar_t*) {
|
||||
return add_space ? L" \"{}\"" : L"\"{}\"";
|
||||
}
|
||||
|
||||
FMT_CONSTEXPR const char* format_str_quoted(bool add_space, const char) {
|
||||
return add_space ? " '{}'" : "'{}'";
|
||||
}
|
||||
FMT_CONSTEXPR const wchar_t* format_str_quoted(bool add_space, const wchar_t) {
|
||||
return add_space ? L" '{}'" : L"'{}'";
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
||||
template <typename T> struct is_tuple_like {
|
||||
static FMT_CONSTEXPR_DECL const bool value =
|
||||
internal::is_tuple_like_<T>::value && !internal::is_range_<T>::value;
|
||||
};
|
||||
|
||||
template <typename TupleT, typename Char>
|
||||
struct formatter<TupleT, Char, enable_if_t<fmt::is_tuple_like<TupleT>::value>> {
|
||||
private:
|
||||
// C++11 generic lambda for format()
|
||||
template <typename FormatContext> struct format_each {
|
||||
template <typename T> void operator()(const T& v) {
|
||||
if (i > 0) {
|
||||
if (formatting.add_prepostfix_space) {
|
||||
*out++ = ' ';
|
||||
}
|
||||
out = internal::copy(formatting.delimiter, out);
|
||||
}
|
||||
out = format_to(out,
|
||||
internal::format_str_quoted(
|
||||
(formatting.add_delimiter_spaces && i > 0), v),
|
||||
v);
|
||||
++i;
|
||||
}
|
||||
|
||||
formatting_tuple<Char>& formatting;
|
||||
std::size_t& i;
|
||||
typename std::add_lvalue_reference<decltype(
|
||||
std::declval<FormatContext>().out())>::type out;
|
||||
};
|
||||
|
||||
public:
|
||||
formatting_tuple<Char> formatting;
|
||||
|
||||
template <typename ParseContext>
|
||||
FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
|
||||
return formatting.parse(ctx);
|
||||
}
|
||||
|
||||
template <typename FormatContext = format_context>
|
||||
auto format(const TupleT& values, FormatContext& ctx) -> decltype(ctx.out()) {
|
||||
auto out = ctx.out();
|
||||
std::size_t i = 0;
|
||||
internal::copy(formatting.prefix, out);
|
||||
|
||||
internal::for_each(values, format_each<FormatContext>{formatting, i, out});
|
||||
if (formatting.add_prepostfix_space) {
|
||||
*out++ = ' ';
|
||||
}
|
||||
internal::copy(formatting.postfix, out);
|
||||
|
||||
return ctx.out();
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, typename Char> struct is_range {
|
||||
static FMT_CONSTEXPR_DECL const bool value =
|
||||
internal::is_range_<T>::value &&
|
||||
!internal::is_like_std_string<T>::value &&
|
||||
!std::is_convertible<T, std::basic_string<Char>>::value;
|
||||
};
|
||||
|
||||
template <typename RangeT, typename Char>
|
||||
struct formatter<RangeT, Char,
|
||||
enable_if_t<fmt::is_range<RangeT, Char>::value>> {
|
||||
formatting_range<Char> formatting;
|
||||
|
||||
template <typename ParseContext>
|
||||
FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
|
||||
return formatting.parse(ctx);
|
||||
}
|
||||
|
||||
template <typename FormatContext>
|
||||
typename FormatContext::iterator format(const RangeT& values,
|
||||
FormatContext& ctx) {
|
||||
auto out = internal::copy(formatting.prefix, ctx.out());
|
||||
std::size_t i = 0;
|
||||
for (auto it = values.begin(), end = values.end(); it != end; ++it) {
|
||||
if (i > 0) {
|
||||
if (formatting.add_prepostfix_space) *out++ = ' ';
|
||||
out = internal::copy(formatting.delimiter, out);
|
||||
}
|
||||
out = format_to(out,
|
||||
internal::format_str_quoted(
|
||||
(formatting.add_delimiter_spaces && i > 0), *it),
|
||||
*it);
|
||||
if (++i > formatting.range_length_limit) {
|
||||
out = format_to(out, " ... <other elements>");
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (formatting.add_prepostfix_space) *out++ = ' ';
|
||||
return internal::copy(formatting.postfix, out);
|
||||
}
|
||||
};
|
||||
|
||||
FMT_END_NAMESPACE
|
||||
|
||||
#endif // FMT_RANGES_H_
|
293
vtkm/thirdparty/diy/vtkmdiy/include/vtkmdiy/thirdparty/fmt/safe-duration-cast.h
vendored
Normal file
293
vtkm/thirdparty/diy/vtkmdiy/include/vtkmdiy/thirdparty/fmt/safe-duration-cast.h
vendored
Normal file
@ -0,0 +1,293 @@
|
||||
/*
|
||||
* For conversion between std::chrono::durations without undefined
|
||||
* behaviour or erroneous results.
|
||||
* This is a stripped down version of duration_cast, for inclusion in fmt.
|
||||
* See https://github.com/pauldreik/safe_duration_cast
|
||||
*
|
||||
* Copyright Paul Dreik 2019
|
||||
*
|
||||
* This file is licensed under the fmt license, see format.h
|
||||
*/
|
||||
|
||||
#include <chrono>
|
||||
#include <cmath>
|
||||
#include <limits>
|
||||
#include <type_traits>
|
||||
|
||||
#include "format.h"
|
||||
|
||||
FMT_BEGIN_NAMESPACE
|
||||
|
||||
namespace safe_duration_cast {
|
||||
|
||||
template <typename To, typename From,
|
||||
FMT_ENABLE_IF(!std::is_same<From, To>::value &&
|
||||
std::numeric_limits<From>::is_signed ==
|
||||
std::numeric_limits<To>::is_signed)>
|
||||
FMT_CONSTEXPR To lossless_integral_conversion(const From from, int& ec) {
|
||||
ec = 0;
|
||||
using F = std::numeric_limits<From>;
|
||||
using T = std::numeric_limits<To>;
|
||||
static_assert(F::is_integer, "From must be integral");
|
||||
static_assert(T::is_integer, "To must be integral");
|
||||
|
||||
// A and B are both signed, or both unsigned.
|
||||
if (F::digits <= T::digits) {
|
||||
// From fits in To without any problem.
|
||||
} else {
|
||||
// From does not always fit in To, resort to a dynamic check.
|
||||
if (from < T::min() || from > T::max()) {
|
||||
// outside range.
|
||||
ec = 1;
|
||||
return {};
|
||||
}
|
||||
}
|
||||
return static_cast<To>(from);
|
||||
}
|
||||
|
||||
/**
|
||||
* converts From to To, without loss. If the dynamic value of from
|
||||
* can't be converted to To without loss, ec is set.
|
||||
*/
|
||||
template <typename To, typename From,
|
||||
FMT_ENABLE_IF(!std::is_same<From, To>::value &&
|
||||
std::numeric_limits<From>::is_signed !=
|
||||
std::numeric_limits<To>::is_signed)>
|
||||
FMT_CONSTEXPR To lossless_integral_conversion(const From from, int& ec) {
|
||||
ec = 0;
|
||||
using F = std::numeric_limits<From>;
|
||||
using T = std::numeric_limits<To>;
|
||||
static_assert(F::is_integer, "From must be integral");
|
||||
static_assert(T::is_integer, "To must be integral");
|
||||
|
||||
if (F::is_signed && !T::is_signed) {
|
||||
// From may be negative, not allowed!
|
||||
if (from < 0) {
|
||||
ec = 1;
|
||||
return {};
|
||||
}
|
||||
|
||||
// From is positive. Can it always fit in To?
|
||||
if (F::digits <= T::digits) {
|
||||
// yes, From always fits in To.
|
||||
} else {
|
||||
// from may not fit in To, we have to do a dynamic check
|
||||
if (from > static_cast<From>(T::max())) {
|
||||
ec = 1;
|
||||
return {};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!F::is_signed && T::is_signed) {
|
||||
// can from be held in To?
|
||||
if (F::digits < T::digits) {
|
||||
// yes, From always fits in To.
|
||||
} else {
|
||||
// from may not fit in To, we have to do a dynamic check
|
||||
if (from > static_cast<From>(T::max())) {
|
||||
// outside range.
|
||||
ec = 1;
|
||||
return {};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// reaching here means all is ok for lossless conversion.
|
||||
return static_cast<To>(from);
|
||||
|
||||
} // function
|
||||
|
||||
template <typename To, typename From,
|
||||
FMT_ENABLE_IF(std::is_same<From, To>::value)>
|
||||
FMT_CONSTEXPR To lossless_integral_conversion(const From from, int& ec) {
|
||||
ec = 0;
|
||||
return from;
|
||||
} // function
|
||||
|
||||
// clang-format off
|
||||
/**
|
||||
* converts From to To if possible, otherwise ec is set.
|
||||
*
|
||||
* input | output
|
||||
* ---------------------------------|---------------
|
||||
* NaN | NaN
|
||||
* Inf | Inf
|
||||
* normal, fits in output | converted (possibly lossy)
|
||||
* normal, does not fit in output | ec is set
|
||||
* subnormal | best effort
|
||||
* -Inf | -Inf
|
||||
*/
|
||||
// clang-format on
|
||||
template <typename To, typename From,
|
||||
FMT_ENABLE_IF(!std::is_same<From, To>::value)>
|
||||
FMT_CONSTEXPR To safe_float_conversion(const From from, int& ec) {
|
||||
ec = 0;
|
||||
using T = std::numeric_limits<To>;
|
||||
static_assert(std::is_floating_point<From>::value, "From must be floating");
|
||||
static_assert(std::is_floating_point<To>::value, "To must be floating");
|
||||
|
||||
// catch the only happy case
|
||||
if (std::isfinite(from)) {
|
||||
if (from >= T::lowest() && from <= T::max()) {
|
||||
return static_cast<To>(from);
|
||||
}
|
||||
// not within range.
|
||||
ec = 1;
|
||||
return {};
|
||||
}
|
||||
|
||||
// nan and inf will be preserved
|
||||
return static_cast<To>(from);
|
||||
} // function
|
||||
|
||||
template <typename To, typename From,
|
||||
FMT_ENABLE_IF(std::is_same<From, To>::value)>
|
||||
FMT_CONSTEXPR To safe_float_conversion(const From from, int& ec) {
|
||||
ec = 0;
|
||||
static_assert(std::is_floating_point<From>::value, "From must be floating");
|
||||
return from;
|
||||
}
|
||||
|
||||
/**
|
||||
* safe duration cast between integral durations
|
||||
*/
|
||||
template <typename To, typename FromRep, typename FromPeriod,
|
||||
FMT_ENABLE_IF(std::is_integral<FromRep>::value),
|
||||
FMT_ENABLE_IF(std::is_integral<typename To::rep>::value)>
|
||||
To safe_duration_cast(std::chrono::duration<FromRep, FromPeriod> from,
|
||||
int& ec) {
|
||||
using From = std::chrono::duration<FromRep, FromPeriod>;
|
||||
ec = 0;
|
||||
// the basic idea is that we need to convert from count() in the from type
|
||||
// to count() in the To type, by multiplying it with this:
|
||||
using Factor = std::ratio_divide<typename From::period, typename To::period>;
|
||||
|
||||
static_assert(Factor::num > 0, "num must be positive");
|
||||
static_assert(Factor::den > 0, "den must be positive");
|
||||
|
||||
// the conversion is like this: multiply from.count() with Factor::num
|
||||
// /Factor::den and convert it to To::rep, all this without
|
||||
// overflow/underflow. let's start by finding a suitable type that can hold
|
||||
// both To, From and Factor::num
|
||||
using IntermediateRep =
|
||||
typename std::common_type<typename From::rep, typename To::rep,
|
||||
decltype(Factor::num)>::type;
|
||||
|
||||
// safe conversion to IntermediateRep
|
||||
IntermediateRep count =
|
||||
lossless_integral_conversion<IntermediateRep>(from.count(), ec);
|
||||
if (ec) {
|
||||
return {};
|
||||
}
|
||||
// multiply with Factor::num without overflow or underflow
|
||||
if (Factor::num != 1) {
|
||||
constexpr auto max1 =
|
||||
std::numeric_limits<IntermediateRep>::max() / Factor::num;
|
||||
if (count > max1) {
|
||||
ec = 1;
|
||||
return {};
|
||||
}
|
||||
constexpr auto min1 =
|
||||
std::numeric_limits<IntermediateRep>::min() / Factor::num;
|
||||
if (count < min1) {
|
||||
ec = 1;
|
||||
return {};
|
||||
}
|
||||
count *= Factor::num;
|
||||
}
|
||||
|
||||
// this can't go wrong, right? den>0 is checked earlier.
|
||||
if (Factor::den != 1) {
|
||||
count /= Factor::den;
|
||||
}
|
||||
// convert to the to type, safely
|
||||
using ToRep = typename To::rep;
|
||||
const ToRep tocount = lossless_integral_conversion<ToRep>(count, ec);
|
||||
if (ec) {
|
||||
return {};
|
||||
}
|
||||
return To{tocount};
|
||||
}
|
||||
|
||||
/**
|
||||
* safe duration_cast between floating point durations
|
||||
*/
|
||||
template <typename To, typename FromRep, typename FromPeriod,
|
||||
FMT_ENABLE_IF(std::is_floating_point<FromRep>::value),
|
||||
FMT_ENABLE_IF(std::is_floating_point<typename To::rep>::value)>
|
||||
To safe_duration_cast(std::chrono::duration<FromRep, FromPeriod> from,
|
||||
int& ec) {
|
||||
using From = std::chrono::duration<FromRep, FromPeriod>;
|
||||
ec = 0;
|
||||
if (std::isnan(from.count())) {
|
||||
// nan in, gives nan out. easy.
|
||||
return To{std::numeric_limits<typename To::rep>::quiet_NaN()};
|
||||
}
|
||||
// maybe we should also check if from is denormal, and decide what to do about
|
||||
// it.
|
||||
|
||||
// +-inf should be preserved.
|
||||
if (std::isinf(from.count())) {
|
||||
return To{from.count()};
|
||||
}
|
||||
|
||||
// the basic idea is that we need to convert from count() in the from type
|
||||
// to count() in the To type, by multiplying it with this:
|
||||
using Factor = std::ratio_divide<typename From::period, typename To::period>;
|
||||
|
||||
static_assert(Factor::num > 0, "num must be positive");
|
||||
static_assert(Factor::den > 0, "den must be positive");
|
||||
|
||||
// the conversion is like this: multiply from.count() with Factor::num
|
||||
// /Factor::den and convert it to To::rep, all this without
|
||||
// overflow/underflow. let's start by finding a suitable type that can hold
|
||||
// both To, From and Factor::num
|
||||
using IntermediateRep =
|
||||
typename std::common_type<typename From::rep, typename To::rep,
|
||||
decltype(Factor::num)>::type;
|
||||
|
||||
// force conversion of From::rep -> IntermediateRep to be safe,
|
||||
// even if it will never happen be narrowing in this context.
|
||||
IntermediateRep count =
|
||||
safe_float_conversion<IntermediateRep>(from.count(), ec);
|
||||
if (ec) {
|
||||
return {};
|
||||
}
|
||||
|
||||
// multiply with Factor::num without overflow or underflow
|
||||
if (Factor::num != 1) {
|
||||
constexpr auto max1 = std::numeric_limits<IntermediateRep>::max() /
|
||||
static_cast<IntermediateRep>(Factor::num);
|
||||
if (count > max1) {
|
||||
ec = 1;
|
||||
return {};
|
||||
}
|
||||
constexpr auto min1 = std::numeric_limits<IntermediateRep>::lowest() /
|
||||
static_cast<IntermediateRep>(Factor::num);
|
||||
if (count < min1) {
|
||||
ec = 1;
|
||||
return {};
|
||||
}
|
||||
count *= static_cast<IntermediateRep>(Factor::num);
|
||||
}
|
||||
|
||||
// this can't go wrong, right? den>0 is checked earlier.
|
||||
if (Factor::den != 1) {
|
||||
using common_t = typename std::common_type<IntermediateRep, intmax_t>::type;
|
||||
count /= static_cast<common_t>(Factor::den);
|
||||
}
|
||||
|
||||
// convert to the to type, safely
|
||||
using ToRep = typename To::rep;
|
||||
|
||||
const ToRep tocount = safe_float_conversion<ToRep>(count, ec);
|
||||
if (ec) {
|
||||
return {};
|
||||
}
|
||||
return To{tocount};
|
||||
}
|
||||
|
||||
} // namespace safe_duration_cast
|
||||
|
||||
FMT_END_NAMESPACE
|
@ -1,11 +1,15 @@
|
||||
#ifndef VTKMDIY_THREAD_H
|
||||
#define VTKMDIY_THREAD_H
|
||||
|
||||
#ifdef VTKM_DIY_NO_THREADS
|
||||
#include <map>
|
||||
|
||||
#ifdef VTKMDIY_NO_THREADS
|
||||
#include "no-thread.hpp"
|
||||
#else
|
||||
|
||||
#include "thread/fast_mutex.h"
|
||||
#if !defined(_MSC_VER)
|
||||
#include "thirdparty/thread/fast_mutex.h"
|
||||
#endif
|
||||
|
||||
#include <thread>
|
||||
#include <mutex>
|
||||
@ -17,15 +21,71 @@ namespace diy
|
||||
using std::recursive_mutex;
|
||||
namespace this_thread = std::this_thread;
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
// fast_mutex implementation has issues on MSVC. Just use std::mutex
|
||||
using fast_mutex = std::mutex;
|
||||
#else
|
||||
// TODO: replace with our own implementation using std::atomic_flag
|
||||
using fast_mutex = tthread::fast_mutex;
|
||||
#endif
|
||||
|
||||
template<class Mutex>
|
||||
using lock_guard = std::unique_lock<Mutex>;
|
||||
|
||||
template<class T, class U>
|
||||
struct concurrent_map;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif // VTKMDIY_NO_THREADS
|
||||
|
||||
#include "critical-resource.hpp"
|
||||
|
||||
#if !defined(VTKMDIY_NO_THREADS)
|
||||
template<class T, class U>
|
||||
struct diy::concurrent_map
|
||||
{
|
||||
using Map = std::map<T,U>;
|
||||
using SharedPtr = std::shared_ptr<lock_guard<fast_mutex>>;
|
||||
|
||||
template<class MapIterator>
|
||||
struct iterator_
|
||||
{
|
||||
MapIterator it;
|
||||
SharedPtr lock_ptr;
|
||||
|
||||
iterator_(const MapIterator& it_, const SharedPtr& lock_ptr_ = SharedPtr()):
|
||||
it(it_), lock_ptr(lock_ptr_) {}
|
||||
|
||||
iterator_& operator++() { ++it; return *this; }
|
||||
iterator_ operator++(int) { iterator_ retval = *this; ++(*this); return retval; }
|
||||
|
||||
bool operator==(const iterator_& other) const { return it == other.it;}
|
||||
bool operator!=(const iterator_& other) const { return !(*this == other); }
|
||||
|
||||
decltype(*it) operator*() const { return *it; }
|
||||
decltype(it.operator->()) operator->() const { return it.operator->(); }
|
||||
};
|
||||
|
||||
using iterator = iterator_<typename Map::iterator>;
|
||||
using const_iterator = iterator_<typename Map::const_iterator>;
|
||||
|
||||
U& operator[](const T& x) { lock_guard<fast_mutex> l(mutex_); return map_[x]; }
|
||||
|
||||
iterator begin() { auto p = std::make_shared<lock_guard<fast_mutex>>(mutex_); return iterator(map_.begin(), p); }
|
||||
iterator end() { return iterator(map_.end()); }
|
||||
|
||||
const_iterator begin() const { auto p = std::make_shared<lock_guard<fast_mutex>>(mutex_); return const_iterator(map_.begin(), p); }
|
||||
const_iterator end() const { return const_iterator(map_.end()); }
|
||||
|
||||
iterator find(const T& x) { auto p = std::make_shared<lock_guard<fast_mutex>>(mutex_); return iterator(map_.find(x), p); }
|
||||
const_iterator find(const T& x) const { auto p = std::make_shared<lock_guard<fast_mutex>>(mutex_); return const_iterator(map_.find(x), p); }
|
||||
|
||||
void clear() { lock_guard<fast_mutex> l(mutex_); map_.clear(); }
|
||||
bool empty() { lock_guard<fast_mutex> l(mutex_); return map_.empty(); }
|
||||
|
||||
Map map_;
|
||||
mutable fast_mutex mutex_;
|
||||
};
|
||||
#endif // !defined(VTKMDIY_NO_THREADS)
|
||||
|
||||
#endif
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
#include <iostream>
|
||||
#include "constants.h"
|
||||
#include "point.hpp"
|
||||
#include "dynamic-point.hpp"
|
||||
|
||||
namespace diy
|
||||
{
|
||||
@ -19,12 +19,21 @@ namespace diy
|
||||
struct Bounds
|
||||
{
|
||||
using Coordinate = Coordinate_;
|
||||
using Point = diy::Point<Coordinate, DIY_MAX_DIM>;
|
||||
using Point = diy::DynamicPoint<Coordinate>;
|
||||
|
||||
Point min, max;
|
||||
|
||||
Bounds() = default;
|
||||
Bounds(int dim): min(dim), max(dim) {}
|
||||
Bounds(const Point& _min, const Point& _max) : min(_min), max(_max) {}
|
||||
|
||||
private:
|
||||
// make default constructor private to explicitly break old deprecated behavior;
|
||||
// any call to the default constructor should be replaced by a call to Bounds(0)
|
||||
Bounds():
|
||||
Bounds(0) {}
|
||||
|
||||
template<class T> friend struct diy::Serialization;
|
||||
|
||||
};
|
||||
using DiscreteBounds = Bounds<int>;
|
||||
using ContinuousBounds = Bounds<float>;
|
||||
@ -32,30 +41,43 @@ namespace diy
|
||||
//! Helper to create a 1-dimensional discrete domain with the specified extents
|
||||
inline
|
||||
diy::DiscreteBounds
|
||||
interval(int from, int to) { DiscreteBounds domain; domain.min[0] = from; domain.max[0] = to; return domain; }
|
||||
interval(int from, int to) { DiscreteBounds domain(1); domain.min[0] = from; domain.max[0] = to; return domain; }
|
||||
|
||||
struct Direction: public Point<int,DIY_MAX_DIM>
|
||||
struct Direction: public DynamicPoint<int>
|
||||
{
|
||||
Direction() { for (size_t i = 0; i < DIY_MAX_DIM; ++i) (*this)[i] = 0; }
|
||||
Direction(std::initializer_list<int> lst):
|
||||
Direction() { size_t i = 0; for(int x : lst) (*this)[i++] = x; }
|
||||
Direction(int dir)
|
||||
using Parent = DynamicPoint<int>;
|
||||
|
||||
using Parent::dimension;
|
||||
using Parent::operator[];
|
||||
|
||||
// enable inherited ctor
|
||||
using Parent::Parent;
|
||||
|
||||
// DM: This breaks the old behavior. Ideally, we'd explicitly deprecate
|
||||
// this, but we need the default constructor in Serialization. I
|
||||
// believe I've fixed all uses of this In DIY proper. Hopefully, no
|
||||
// existing codes break.
|
||||
Direction(): Parent(0) {}
|
||||
|
||||
Direction(int dim, int dir):
|
||||
Parent(dim)
|
||||
{
|
||||
for (size_t i = 0; i < DIY_MAX_DIM; ++i) (*this)[i] = 0;
|
||||
if (dir & DIY_X0) (*this)[0] -= 1;
|
||||
if (dir & DIY_X1) (*this)[0] += 1;
|
||||
if (dir & DIY_Y0) (*this)[1] -= 1;
|
||||
if (dir & DIY_Y1) (*this)[1] += 1;
|
||||
if (dir & DIY_Z0) (*this)[2] -= 1;
|
||||
if (dir & DIY_Z1) (*this)[2] += 1;
|
||||
if (dir & DIY_T0) (*this)[3] -= 1;
|
||||
if (dir & DIY_T1) (*this)[3] += 1;
|
||||
if (dim > 0 && dir & VTKMDIY_X0) (*this)[0] -= 1;
|
||||
if (dim > 0 && dir & VTKMDIY_X1) (*this)[0] += 1;
|
||||
if (dim > 1 && dir & VTKMDIY_Y0) (*this)[1] -= 1;
|
||||
if (dim > 1 && dir & VTKMDIY_Y1) (*this)[1] += 1;
|
||||
if (dim > 2 && dir & VTKMDIY_Z0) (*this)[2] -= 1;
|
||||
if (dim > 2 && dir & VTKMDIY_Z1) (*this)[2] += 1;
|
||||
if (dim > 3 && dir & VTKMDIY_T0) (*this)[3] -= 1;
|
||||
if (dim > 3 && dir & VTKMDIY_T1) (*this)[3] += 1;
|
||||
}
|
||||
|
||||
static Direction from_bits(int dir, int dim = VTKMDIY_MAX_DIM) { return Direction(dim, dir); }
|
||||
|
||||
bool
|
||||
operator==(const diy::Direction& y) const
|
||||
{
|
||||
for (size_t i = 0; i < DIY_MAX_DIM; ++i)
|
||||
for (size_t i = 0; i < dimension(); ++i)
|
||||
if ((*this)[i] != y[i]) return false;
|
||||
return true;
|
||||
}
|
||||
@ -64,7 +86,7 @@ namespace diy
|
||||
bool
|
||||
operator<(const diy::Direction& y) const
|
||||
{
|
||||
for (size_t i = 0; i < DIY_MAX_DIM; ++i)
|
||||
for (size_t i = 0; i < dimension(); ++i)
|
||||
{
|
||||
if ((*this)[i] < y[i]) return true;
|
||||
if ((*this)[i] > y[i]) return false;
|
||||
@ -89,6 +111,36 @@ namespace diy
|
||||
bool
|
||||
operator==(const diy::BlockID& x, const diy::BlockID& y)
|
||||
{ return x.gid == y.gid; }
|
||||
|
||||
// Serialization
|
||||
template<class C>
|
||||
struct Serialization<Bounds<C>>
|
||||
{
|
||||
static void save(BinaryBuffer& bb, const Bounds<C>& b)
|
||||
{
|
||||
diy::save(bb, b.min);
|
||||
diy::save(bb, b.max);
|
||||
}
|
||||
|
||||
static void load(BinaryBuffer& bb, Bounds<C>& b)
|
||||
{
|
||||
diy::load(bb, b.min);
|
||||
diy::load(bb, b.max);
|
||||
}
|
||||
};
|
||||
template<>
|
||||
struct Serialization<Direction>
|
||||
{
|
||||
static void save(BinaryBuffer& bb, const Direction& d)
|
||||
{
|
||||
diy::save(bb, static_cast<const Direction::Parent&>(d));
|
||||
}
|
||||
|
||||
static void load(BinaryBuffer& bb, Direction& d)
|
||||
{
|
||||
diy::load(bb, static_cast<Direction::Parent&>(d));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -3,6 +3,6 @@
|
||||
|
||||
#define VTKMDIY_VERSION_MAJOR 3
|
||||
#define VTKMDIY_VERSION_MINOR 5
|
||||
#define VTKMDIY_VERSION_PATCH dev1
|
||||
#define DIY_VERSION_PATCH dev1
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user