forked from openkylin/xtl
Import Upstream version 0.7.2
This commit is contained in:
commit
06f61af8c9
|
@ -0,0 +1,37 @@
|
|||
build: false
|
||||
|
||||
platform:
|
||||
- x64
|
||||
|
||||
image:
|
||||
- Visual Studio 2017
|
||||
- Visual Studio 2015
|
||||
|
||||
environment:
|
||||
matrix:
|
||||
- MINICONDA: C:\xtl-conda
|
||||
|
||||
init:
|
||||
- "ECHO %MINICONDA%"
|
||||
- if "%APPVEYOR_BUILD_WORKER_IMAGE%" == "Visual Studio 2015" set VCVARPATH="C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat"
|
||||
- if "%APPVEYOR_BUILD_WORKER_IMAGE%" == "Visual Studio 2015" set VCARGUMENT=%PLATFORM%
|
||||
- if "%APPVEYOR_BUILD_WORKER_IMAGE%" == "Visual Studio 2017" set VCVARPATH="C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvars64.bat"
|
||||
- echo "%VCVARPATH% %VCARGUMENT%"
|
||||
- "%VCVARPATH% %VCARGUMENT%"
|
||||
- ps: if($env:Platform -eq "x64"){Start-FileDownload 'http://repo.continuum.io/miniconda/Miniconda3-latest-Windows-x86_64.exe' C:\Miniconda.exe; echo "Done"}
|
||||
- ps: if($env:Platform -eq "x86"){Start-FileDownload 'http://repo.continuum.io/miniconda/Miniconda3-latest-Windows-x86.exe' C:\Miniconda.exe; echo "Done"}
|
||||
- cmd: C:\Miniconda.exe /S /D=C:\xtl-conda
|
||||
- "set PATH=%MINICONDA%;%MINICONDA%\\Scripts;%MINICONDA%\\Library\\bin;%PATH%"
|
||||
|
||||
install:
|
||||
- conda config --set always_yes yes --set changeps1 no
|
||||
- conda update -q conda
|
||||
- conda info -a
|
||||
- conda env create --file environment-dev.yml
|
||||
- CALL conda.bat activate xtl
|
||||
- cmake -G "NMake Makefiles" -D CMAKE_INSTALL_PREFIX=%MINICONDA%\\LIBRARY -DDOWNLOAD_GTEST=ON .
|
||||
- nmake test_xtl
|
||||
- cd test
|
||||
|
||||
build_script:
|
||||
- .\test_xtl
|
|
@ -0,0 +1,42 @@
|
|||
jobs:
|
||||
- job: 'Linux_0'
|
||||
strategy:
|
||||
matrix:
|
||||
clang_4:
|
||||
llvm_version: '4.0'
|
||||
clang_5:
|
||||
llvm_version: '5.0'
|
||||
clang_6:
|
||||
llvm_version: '6.0'
|
||||
clang_7:
|
||||
llvm_version: '7'
|
||||
clang_8:
|
||||
llvm_version: '8'
|
||||
clang_9:
|
||||
llvm_version: '9'
|
||||
pool:
|
||||
vmImage: ubuntu-16.04
|
||||
variables:
|
||||
CC: clang-$(llvm_version)
|
||||
CXX: clang++-$(llvm_version)
|
||||
timeoutInMinutes: 360
|
||||
steps:
|
||||
|
||||
- script: |
|
||||
sudo add-apt-repository ppa:ubuntu-toolchain-r/test
|
||||
if [[ $(llvm_version) == '4.0' || $(llvm_version) == '5.0' ]]; then
|
||||
sudo apt-get update
|
||||
sudo apt-get --no-install-suggests --no-install-recommends install gcc-4.9 clang-$(llvm_version)
|
||||
else
|
||||
LLVM_VERSION=$(llvm_version)
|
||||
get -O - http://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -
|
||||
sudo add-apt-repository "deb http://apt.llvm.org/xenial/ llvm-toolchain-xenial-$LLVM_VERSION main"
|
||||
sudo apt-get update
|
||||
sudo apt-get --no-install-suggests --no-install-recommends install clang-$(llvm_version)
|
||||
fi
|
||||
displayName: Install build toolchain
|
||||
|
||||
- bash: echo "##vso[task.prependpath]$CONDA/bin"
|
||||
displayName: Add conda to PATH
|
||||
|
||||
- template: unix-build.yml
|
|
@ -0,0 +1,37 @@
|
|||
jobs:
|
||||
- job: 'Linux_1'
|
||||
strategy:
|
||||
matrix:
|
||||
gcc_4:
|
||||
gcc_version: '4.9'
|
||||
gcc_5:
|
||||
gcc_version: '5'
|
||||
gcc_6:
|
||||
gcc_version: '6'
|
||||
gcc_7:
|
||||
gcc_version: '7'
|
||||
gcc_8:
|
||||
gcc_version: '8'
|
||||
gcc_9:
|
||||
gcc_version: '9'
|
||||
pool:
|
||||
vmImage: ubuntu-16.04
|
||||
variables:
|
||||
CC: gcc-$(gcc_version)
|
||||
CXX: g++-$(gcc_version)
|
||||
timeoutInMinutes: 360
|
||||
steps:
|
||||
|
||||
- script: |
|
||||
if [[ $(gcc_version) == '4.9' || $(gcc_version) == '6' ]]; then
|
||||
sudo add-apt-repository ppa:ubuntu-toolchain-r/test
|
||||
sudo apt-get update
|
||||
sudo apt-get --no-install-suggests --no-install-recommends install g++-$(gcc_version)
|
||||
fi
|
||||
displayName: Install build toolchain
|
||||
|
||||
- bash: echo "##vso[task.prependpath]$CONDA/bin"
|
||||
displayName: Add conda to PATH
|
||||
|
||||
- template: unix-build.yml
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
jobs:
|
||||
- job: 'OSX'
|
||||
strategy:
|
||||
matrix:
|
||||
macOS_10_14:
|
||||
image_name: 'macOS-10.14'
|
||||
macOS_10_15:
|
||||
image_name: 'macOS-10.15'
|
||||
pool:
|
||||
vmImage: $(image_name)
|
||||
variables:
|
||||
CC: clang
|
||||
CXX: clang++
|
||||
timeoutInMinutes: 360
|
||||
steps:
|
||||
- script: |
|
||||
echo "Removing homebrew for Azure to avoid conflicts with conda"
|
||||
curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/uninstall > ~/uninstall_homebrew
|
||||
chmod +x ~/uninstall_homebrew
|
||||
~/uninstall_homebrew -f -q
|
||||
displayName: Remove homebrew
|
||||
|
||||
- bash: |
|
||||
echo "##vso[task.prependpath]$CONDA/bin"
|
||||
sudo chown -R $USER $CONDA
|
||||
displayName: Add conda to PATH
|
||||
|
||||
- template: unix-build.yml
|
|
@ -0,0 +1,83 @@
|
|||
|
||||
jobs:
|
||||
- job: 'Windows_clangcl'
|
||||
pool:
|
||||
vmImage: 'vs2017-win2016'
|
||||
timeoutInMinutes: 360
|
||||
steps:
|
||||
|
||||
# Install Chocolatey (https://chocolatey.org/install#install-with-powershellexe)
|
||||
- powershell: |
|
||||
Set-ExecutionPolicy Bypass -Scope Process -Force
|
||||
iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))
|
||||
Write-Host "##vso[task.setvariable variable=PATH]$env:PATH"
|
||||
choco --version
|
||||
displayName: "Install Chocolatey"
|
||||
|
||||
# Install Miniconda
|
||||
- script: |
|
||||
choco install miniconda3 --yes
|
||||
set PATH=C:\tools\miniconda3\Scripts;C:\tools\miniconda3;C:\tools\miniconda3\Library\bin;%PATH%
|
||||
echo '##vso[task.setvariable variable=PATH]%PATH%'
|
||||
set LIB=C:\tools\miniconda3\Library\lib;%LIB%
|
||||
echo '##vso[task.setvariable variable=LIB]%LIB%'
|
||||
conda --version
|
||||
displayName: "Install Miniconda"
|
||||
|
||||
# Configure Miniconda
|
||||
- script: |
|
||||
conda config --set always_yes yes
|
||||
conda config --append channels conda-forge
|
||||
conda info
|
||||
displayName: "Configure Miniconda"
|
||||
|
||||
# Create conda enviroment
|
||||
# Note: conda activate doesn't work here, because it creates a new shell!
|
||||
- script: |
|
||||
conda install cmake==3.14.0 ^
|
||||
ninja ^
|
||||
nlohmann_json ^
|
||||
python=3.6
|
||||
conda list
|
||||
displayName: "Install conda packages"
|
||||
|
||||
# Install LLVM
|
||||
# Note: LLVM distributed by conda is too old
|
||||
- script: |
|
||||
choco install llvm --yes
|
||||
set PATH=C:\Program Files\LLVM\bin;%PATH%
|
||||
echo '##vso[task.setvariable variable=PATH]%PATH%'
|
||||
clang-cl --version
|
||||
displayName: "Install LLVM"
|
||||
|
||||
# Configure
|
||||
- script: |
|
||||
setlocal EnableDelayedExpansion
|
||||
call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" x86_amd64
|
||||
mkdir build & cd build
|
||||
cmake -G Ninja ^
|
||||
-DCMAKE_BUILD_TYPE=Release ^
|
||||
-DCMAKE_C_COMPILER=clang-cl ^
|
||||
-DCMAKE_CXX_COMPILER=clang-cl ^
|
||||
-DDOWNLOAD_GTEST=ON ^
|
||||
$(Build.SourcesDirectory)
|
||||
displayName: "Configure xtl"
|
||||
workingDirectory: $(Build.BinariesDirectory)
|
||||
|
||||
# Build
|
||||
- script: |
|
||||
call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" x86_amd64
|
||||
cmake --build . ^
|
||||
--config Release ^
|
||||
--target test_xtl ^
|
||||
-- -v
|
||||
displayName: "Build xtl"
|
||||
workingDirectory: $(Build.BinariesDirectory)/build
|
||||
|
||||
# Test
|
||||
- script: |
|
||||
setlocal EnableDelayedExpansion
|
||||
cd test
|
||||
.\test_xtl
|
||||
displayName: "Test xtl"
|
||||
workingDirectory: $(Build.BinariesDirectory)/build/test
|
|
@ -0,0 +1,27 @@
|
|||
steps:
|
||||
- script: |
|
||||
conda config --set always_yes yes --set changeps1 no
|
||||
conda update -q conda
|
||||
conda env create --file environment-dev.yml
|
||||
displayName: Install dependencies
|
||||
|
||||
- script: |
|
||||
source activate xtl
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -DDOWNLOAD_GTEST=ON $(Build.SourcesDirectory)
|
||||
displayName: Configure xtl
|
||||
workingDirectory: $(Build.BinariesDirectory)
|
||||
|
||||
- script: |
|
||||
source activate xtl
|
||||
make -j2 test_xtl
|
||||
displayName: Build xtl
|
||||
workingDirectory: $(Build.BinariesDirectory)/build
|
||||
|
||||
- script: |
|
||||
source activate xtl
|
||||
cd test
|
||||
./test_xtl
|
||||
displayName: Test xtl
|
||||
workingDirectory: $(Build.BinariesDirectory)/build/test
|
|
@ -0,0 +1,8 @@
|
|||
# Checklist
|
||||
|
||||
- The title and the commit message(s) are descriptive
|
||||
- Small commits made to fix your PR have been squashed to avoid history pollution
|
||||
- Tests have been added for new features or bug fixes
|
||||
- API of new functions and classes are documented
|
||||
|
||||
# Description
|
|
@ -0,0 +1,52 @@
|
|||
# Prerequisites
|
||||
*.d
|
||||
|
||||
# Compiled Object files
|
||||
*.slo
|
||||
*.lo
|
||||
*.o
|
||||
*.obj
|
||||
|
||||
# Precompiled Headers
|
||||
*.gch
|
||||
*.pch
|
||||
|
||||
# Compiled Dynamic libraries
|
||||
*.so
|
||||
*.dylib
|
||||
*.dll
|
||||
|
||||
# Compiled Static libraries
|
||||
*.lai
|
||||
*.la
|
||||
*.a
|
||||
*.lib
|
||||
|
||||
# Executables
|
||||
*.exe
|
||||
*.out
|
||||
*.app
|
||||
|
||||
# Vim tmp files
|
||||
*.swp
|
||||
|
||||
# Build directory
|
||||
build/
|
||||
|
||||
# Test build artefacts
|
||||
test/test_xtl
|
||||
test/CMakeCache.txt
|
||||
test/Makefile
|
||||
test/CMakeFiles/
|
||||
test/cmake_install.cmake
|
||||
|
||||
# Documentation build artefacts
|
||||
docs/CMakeCache.txt
|
||||
docs/xml/
|
||||
docs/build/
|
||||
|
||||
# Jupyter artefacts
|
||||
.ipynb_checkpoints/
|
||||
|
||||
# Generated files
|
||||
*.pc
|
|
@ -0,0 +1,17 @@
|
|||
from releash import *
|
||||
|
||||
gitpush = ReleaseTargetGitPush('upstream', 'master')
|
||||
|
||||
xtl = add_package(path=".", name="xtl")
|
||||
version_xtl = VersionSourceAndTargetHpp(xtl, '{path}/include/xtl/xtl_config.hpp', prefix='XTL_VERSION_')
|
||||
gittag_xtl = ReleaseTargetGitTagVersion(version_source=version_xtl, prefix='', annotate=True)
|
||||
|
||||
xtl.version_source = version_xtl
|
||||
xtl.version_targets.append(version_xtl)
|
||||
|
||||
xtl.release_targets.append(gittag_xtl)
|
||||
xtl.release_targets.append(gitpush)
|
||||
|
||||
source_tarball_filename = 'https://github.com/xtensor-stack/xtl/archive/{version}.tar.gz'.format(version=version_xtl)
|
||||
xtl.release_targets.append(ReleaseTargetCondaForge(xtl, '../xtl-feedstock', source_tarball_filename=source_tarball_filename))
|
||||
|
|
@ -0,0 +1,160 @@
|
|||
############################################################################
|
||||
# Copyright (c) Johan Mabille, Sylvain Corlay and Wolf Vollprecht #
|
||||
# Copyright (c) QuantStack #
|
||||
# #
|
||||
# Distributed under the terms of the BSD 3-Clause License. #
|
||||
# #
|
||||
# The full license is in the file LICENSE, distributed with this software. #
|
||||
############################################################################
|
||||
|
||||
cmake_minimum_required(VERSION 3.1)
|
||||
project(xtl)
|
||||
|
||||
set(XTL_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||
|
||||
# Versioning
|
||||
# ===========
|
||||
|
||||
file(STRINGS "${XTL_INCLUDE_DIR}/xtl/xtl_config.hpp" xtl_version_defines
|
||||
REGEX "#define XTL_VERSION_(MAJOR|MINOR|PATCH)")
|
||||
foreach(ver ${xtl_version_defines})
|
||||
if(ver MATCHES "#define XTL_VERSION_(MAJOR|MINOR|PATCH) +([^ ]+)$")
|
||||
set(XTL_VERSION_${CMAKE_MATCH_1} "${CMAKE_MATCH_2}" CACHE INTERNAL "")
|
||||
endif()
|
||||
endforeach()
|
||||
set(${PROJECT_NAME}_VERSION
|
||||
${XTL_VERSION_MAJOR}.${XTL_VERSION_MINOR}.${XTL_VERSION_PATCH})
|
||||
message(STATUS "xtl v${${PROJECT_NAME}_VERSION}")
|
||||
|
||||
# Dependencies
|
||||
# ============
|
||||
|
||||
if(NOT TARGET nlohmann_json)
|
||||
find_package(nlohmann_json QUIET)
|
||||
endif()
|
||||
|
||||
# Build
|
||||
# =====
|
||||
|
||||
set(XTL_HEADERS
|
||||
${XTL_INCLUDE_DIR}/xtl/xany.hpp
|
||||
${XTL_INCLUDE_DIR}/xtl/xbasic_fixed_string.hpp
|
||||
${XTL_INCLUDE_DIR}/xtl/xbase64.hpp
|
||||
${XTL_INCLUDE_DIR}/xtl/xclosure.hpp
|
||||
${XTL_INCLUDE_DIR}/xtl/xcomplex.hpp
|
||||
${XTL_INCLUDE_DIR}/xtl/xcomplex_sequence.hpp
|
||||
${XTL_INCLUDE_DIR}/xtl/xspan.hpp
|
||||
${XTL_INCLUDE_DIR}/xtl/xspan_impl.hpp
|
||||
${XTL_INCLUDE_DIR}/xtl/xdynamic_bitset.hpp
|
||||
${XTL_INCLUDE_DIR}/xtl/xfunctional.hpp
|
||||
${XTL_INCLUDE_DIR}/xtl/xhalf_float.hpp
|
||||
${XTL_INCLUDE_DIR}/xtl/xhalf_float_impl.hpp
|
||||
${XTL_INCLUDE_DIR}/xtl/xhash.hpp
|
||||
${XTL_INCLUDE_DIR}/xtl/xhierarchy_generator.hpp
|
||||
${XTL_INCLUDE_DIR}/xtl/xiterator_base.hpp
|
||||
${XTL_INCLUDE_DIR}/xtl/xjson.hpp
|
||||
${XTL_INCLUDE_DIR}/xtl/xmasked_value_meta.hpp
|
||||
${XTL_INCLUDE_DIR}/xtl/xmasked_value.hpp
|
||||
${XTL_INCLUDE_DIR}/xtl/xmeta_utils.hpp
|
||||
${XTL_INCLUDE_DIR}/xtl/xmultimethods.hpp
|
||||
${XTL_INCLUDE_DIR}/xtl/xoptional_meta.hpp
|
||||
${XTL_INCLUDE_DIR}/xtl/xoptional.hpp
|
||||
${XTL_INCLUDE_DIR}/xtl/xoptional_sequence.hpp
|
||||
${XTL_INCLUDE_DIR}/xtl/xplatform.hpp
|
||||
${XTL_INCLUDE_DIR}/xtl/xproxy_wrapper.hpp
|
||||
${XTL_INCLUDE_DIR}/xtl/xsequence.hpp
|
||||
${XTL_INCLUDE_DIR}/xtl/xsystem.hpp
|
||||
${XTL_INCLUDE_DIR}/xtl/xtl_config.hpp
|
||||
${XTL_INCLUDE_DIR}/xtl/xtype_traits.hpp
|
||||
${XTL_INCLUDE_DIR}/xtl/xvariant.hpp
|
||||
${XTL_INCLUDE_DIR}/xtl/xvariant_impl.hpp
|
||||
${XTL_INCLUDE_DIR}/xtl/xvisitor.hpp
|
||||
)
|
||||
|
||||
add_library(xtl INTERFACE)
|
||||
|
||||
target_include_directories(xtl INTERFACE
|
||||
$<BUILD_INTERFACE:${XTL_INCLUDE_DIR}>
|
||||
$<INSTALL_INTERFACE:include>)
|
||||
|
||||
if(NOT (CMAKE_VERSION VERSION_LESS 3.15)) # CMake >= 3.15
|
||||
set_target_properties(xtl
|
||||
PROPERTIES
|
||||
PUBLIC_HEADER "${XTL_HEADERS}")
|
||||
endif()
|
||||
|
||||
target_compile_features(xtl INTERFACE cxx_std_14)
|
||||
|
||||
option(BUILD_TESTS "xtl test suite" OFF)
|
||||
option(DOWNLOAD_GTEST "build gtest from downloaded sources" OFF)
|
||||
option(XTL_DISABLE_EXCEPTIONS "Disable C++ exceptions" OFF)
|
||||
|
||||
if(DOWNLOAD_GTEST OR GTEST_SRC_DIR)
|
||||
set(BUILD_TESTS ON)
|
||||
endif()
|
||||
|
||||
if(BUILD_TESTS)
|
||||
enable_testing()
|
||||
add_subdirectory(test)
|
||||
endif()
|
||||
|
||||
# Installation
|
||||
# ============
|
||||
|
||||
include(GNUInstallDirs)
|
||||
include(CMakePackageConfigHelpers)
|
||||
|
||||
if(CMAKE_VERSION VERSION_LESS 3.15) # CMake < 3.15
|
||||
install(TARGETS xtl
|
||||
EXPORT ${PROJECT_NAME}-targets)
|
||||
else()
|
||||
install(TARGETS xtl
|
||||
EXPORT ${PROJECT_NAME}-targets
|
||||
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME})
|
||||
endif()
|
||||
|
||||
# Makes the project importable from the build directory
|
||||
export(EXPORT ${PROJECT_NAME}-targets
|
||||
FILE "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Targets.cmake")
|
||||
|
||||
if(CMAKE_VERSION VERSION_LESS 3.15) # CMake < 3.15
|
||||
install(FILES ${XTL_HEADERS}
|
||||
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/xtl)
|
||||
endif()
|
||||
|
||||
set(XTL_CMAKECONFIG_INSTALL_DIR "${CMAKE_INSTALL_DATAROOTDIR}/cmake/${PROJECT_NAME}" CACHE
|
||||
STRING "install path for xtlConfig.cmake")
|
||||
|
||||
configure_package_config_file(${PROJECT_NAME}Config.cmake.in
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake"
|
||||
INSTALL_DESTINATION ${XTL_CMAKECONFIG_INSTALL_DIR})
|
||||
|
||||
# xtl is header-only and does not depend on the architecture.
|
||||
# Remove CMAKE_SIZEOF_VOID_P from xtlConfigVersion.cmake so that an xtlConfig.cmake
|
||||
# generated for a 64 bit target can be used for 32 bit targets and vice versa.
|
||||
set(_XTL_CMAKE_SIZEOF_VOID_P ${CMAKE_SIZEOF_VOID_P})
|
||||
unset(CMAKE_SIZEOF_VOID_P)
|
||||
# ARCH_INDEPENDENT feature was introduced in cmake 3.14
|
||||
if (${CMAKE_VERSION} VERSION_LESS "3.14.0")
|
||||
write_basic_package_version_file(${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake
|
||||
VERSION ${${PROJECT_NAME}_VERSION}
|
||||
COMPATIBILITY AnyNewerVersion)
|
||||
else ()
|
||||
write_basic_package_version_file(${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake
|
||||
VERSION ${${PROJECT_NAME}_VERSION}
|
||||
COMPATIBILITY AnyNewerVersion
|
||||
ARCH_INDEPENDENT)
|
||||
endif ()
|
||||
set(CMAKE_SIZEOF_VOID_P ${_XTL_CMAKE_SIZEOF_VOID_P})
|
||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake
|
||||
${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake
|
||||
DESTINATION ${XTL_CMAKECONFIG_INSTALL_DIR})
|
||||
install(EXPORT ${PROJECT_NAME}-targets
|
||||
FILE ${PROJECT_NAME}Targets.cmake
|
||||
DESTINATION ${XTL_CMAKECONFIG_INSTALL_DIR})
|
||||
|
||||
configure_file(${PROJECT_NAME}.pc.in
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc"
|
||||
@ONLY)
|
||||
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc"
|
||||
DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/pkgconfig/")
|
|
@ -0,0 +1,30 @@
|
|||
BSD 3-Clause License
|
||||
|
||||
Copyright (c) 2017, Sylvain Corlay, Johan Mabille and Wolf Vollprecht
|
||||
Copyright (c) 2017, QuantStack
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
* Neither the name of the copyright holder nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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.
|
|
@ -0,0 +1,71 @@
|
|||
# ![xtl](docs/source/xtl.svg)
|
||||
|
||||
[![Appveyor](https://ci.appveyor.com/api/projects/status/wikc50xlb5rbrjy7?svg=true)](https://ci.appveyor.com/project/xtensor-stack/xtl)
|
||||
[![Azure](https://dev.azure.com/xtensor-stack/xtensor-stack/_apis/build/status/xtensor-stack.xtl?branchName=master)](https://dev.azure.com/xtensor-stack/xtensor-stack/_build/latest?definitionId=2&branchName=master)
|
||||
[![Documentation Status](http://readthedocs.org/projects/xtl/badge/?version=latest)](https://xtl.readthedocs.io/en/latest/?badge=latest)
|
||||
[![Join the Gitter Chat](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/QuantStack/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
|
||||
Basic tools (containers, algorithms) used by other quantstack packages
|
||||
|
||||
## Installation
|
||||
|
||||
### Install from conda
|
||||
|
||||
We provide a package for the conda package manager:
|
||||
|
||||
```bash
|
||||
conda install -c conda-forge xtl
|
||||
```
|
||||
|
||||
### Install from sources
|
||||
|
||||
`xtl` is a header-only library.
|
||||
|
||||
You can directly install it from the sources:
|
||||
|
||||
```bash
|
||||
cmake -D CMAKE_INSTALL_PREFIX=your_install_prefix
|
||||
make install
|
||||
```
|
||||
|
||||
## Documentation
|
||||
|
||||
To get started with using `xtl`, check out the full documentation
|
||||
|
||||
http://xtl.readthedocs.io/
|
||||
|
||||
|
||||
## Building the HTML documentation
|
||||
|
||||
xtl's documentation is built with three tools
|
||||
|
||||
- [doxygen](http://www.doxygen.org)
|
||||
- [sphinx](http://www.sphinx-doc.org)
|
||||
- [breathe](https://breathe.readthedocs.io)
|
||||
|
||||
While doxygen must be installed separately, you can install breathe by typing
|
||||
|
||||
```bash
|
||||
pip install breathe
|
||||
```
|
||||
|
||||
Breathe can also be installed with `conda`
|
||||
|
||||
```bash
|
||||
conda install -c conda-forge breathe
|
||||
```
|
||||
|
||||
Finally, build the documentation with
|
||||
|
||||
```bash
|
||||
make html
|
||||
```
|
||||
|
||||
from the `docs` subdirectory.
|
||||
|
||||
## License
|
||||
|
||||
We use a shared copyright model that enables all contributors to maintain the
|
||||
copyright on their contributions.
|
||||
|
||||
This software is licensed under the BSD-3-Clause license. See the [LICENSE](LICENSE) file for details.
|
|
@ -0,0 +1,8 @@
|
|||
trigger:
|
||||
- master
|
||||
|
||||
jobs:
|
||||
- template: ./.azure-pipelines/azure-pipelines-win.yml
|
||||
- template: ./.azure-pipelines/azure-pipelines-linux-clang.yml
|
||||
- template: ./.azure-pipelines/azure-pipelines-linux-gcc.yml
|
||||
- template: ./.azure-pipelines/azure-pipelines-osx.yml
|
|
@ -0,0 +1,13 @@
|
|||
PROJECT_NAME = "xtl"
|
||||
XML_OUTPUT = xml
|
||||
INPUT = ../include
|
||||
GENERATE_LATEX = NO
|
||||
GENERATE_MAN = NO
|
||||
GENERATE_RTF = NO
|
||||
CASE_SENSE_NAMES = NO
|
||||
GENERATE_HTML = NO
|
||||
GENERATE_XML = YES
|
||||
RECURSIVE = YES
|
||||
QUIET = YES
|
||||
JAVADOC_AUTOBRIEF = YES
|
||||
WARN_IF_UNDOCUMENTED = NO
|
|
@ -0,0 +1,192 @@
|
|||
# You can set these variables from the command line.
|
||||
SPHINXOPTS =
|
||||
SPHINXBUILD = sphinx-build
|
||||
INKSCAPE = inkscape
|
||||
SED = sed
|
||||
PAPER =
|
||||
BUILDDIR = build
|
||||
|
||||
# User-friendly check for sphinx-build
|
||||
ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1)
|
||||
$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/)
|
||||
endif
|
||||
|
||||
# Internal variables.
|
||||
PAPEROPT_a4 = -D latex_paper_size=a4
|
||||
PAPEROPT_letter = -D latex_paper_size=letter
|
||||
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source
|
||||
# the i18n builder cannot share the environment and doctrees with the others
|
||||
I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source
|
||||
|
||||
.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest coverage gettext api
|
||||
|
||||
default: html
|
||||
|
||||
help:
|
||||
@echo "Please use \`make <target>' where <target> is one of"
|
||||
@echo " html to make standalone HTML files"
|
||||
@echo " dirhtml to make HTML files named index.html in directories"
|
||||
@echo " singlehtml to make a single large HTML file"
|
||||
@echo " pickle to make pickle files"
|
||||
@echo " json to make JSON files"
|
||||
@echo " htmlhelp to make HTML files and a HTML help project"
|
||||
@echo " qthelp to make HTML files and a qthelp project"
|
||||
@echo " applehelp to make an Apple Help Book"
|
||||
@echo " devhelp to make HTML files and a Devhelp project"
|
||||
@echo " epub to make an epub"
|
||||
@echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
|
||||
@echo " latexpdf to make LaTeX files and run them through pdflatex"
|
||||
@echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx"
|
||||
@echo " text to make text files"
|
||||
@echo " man to make manual pages"
|
||||
@echo " texinfo to make Texinfo files"
|
||||
@echo " info to make Texinfo files and run them through makeinfo"
|
||||
@echo " gettext to make PO message catalogs"
|
||||
@echo " changes to make an overview of all changed/added/deprecated items"
|
||||
@echo " xml to make Docutils-native XML files"
|
||||
@echo " pseudoxml to make pseudoxml-XML files for display purposes"
|
||||
@echo " linkcheck to check all external links for integrity"
|
||||
@echo " doctest to run all doctests embedded in the documentation (if enabled)"
|
||||
@echo " coverage to run coverage check of the documentation (if enabled)"
|
||||
|
||||
clean:
|
||||
rm -rf $(BUILDDIR)/*
|
||||
rm -rf xml
|
||||
|
||||
html:
|
||||
doxygen
|
||||
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
|
||||
@echo
|
||||
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
|
||||
|
||||
dirhtml:
|
||||
doxygen
|
||||
$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
|
||||
@echo
|
||||
@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
|
||||
|
||||
singlehtml:
|
||||
doxygen
|
||||
$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
|
||||
@echo
|
||||
@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
|
||||
|
||||
pickle:
|
||||
doxygen
|
||||
$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
|
||||
@echo
|
||||
@echo "Build finished; now you can process the pickle files."
|
||||
|
||||
json:
|
||||
doxygen
|
||||
$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
|
||||
@echo
|
||||
@echo "Build finished; now you can process the JSON files."
|
||||
|
||||
htmlhelp:
|
||||
doxygen
|
||||
$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
|
||||
@echo
|
||||
@echo "Build finished; now you can run HTML Help Workshop with the" \
|
||||
".hhp project file in $(BUILDDIR)/htmlhelp."
|
||||
|
||||
epub:
|
||||
doxygen
|
||||
$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
|
||||
@echo
|
||||
@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
|
||||
|
||||
tex-generation:
|
||||
doxygen
|
||||
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
|
||||
${SED} -i.old -e 's/{\([^}]*\)}.svg/\1-svg.pdf/' $(BUILDDIR)/latex/xtl.tex
|
||||
(cd $(BUILDDIR)/latex/;\
|
||||
for i in *.svg; do\
|
||||
name=`basename $$i .svg`;\
|
||||
${INKSCAPE} -D -z --file=$$i --export-pdf=$$name-svg.pdf --export-latex; \
|
||||
done)
|
||||
|
||||
latex: tex-generation
|
||||
@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
|
||||
@echo "Run \`make' in that directory to run these through (pdf)latex" \
|
||||
"(use \`make latexpdf' here to do that automatically)."
|
||||
|
||||
latexpdf: tex-generation
|
||||
@echo "Running LaTeX files through pdflatex..."
|
||||
$(MAKE) -C $(BUILDDIR)/latex all-pdf
|
||||
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
|
||||
|
||||
latexpdfja: tex-generation
|
||||
@echo "Running LaTeX files through platex and dvipdfmx..."
|
||||
$(MAKE) -C $(BUILDDIR)/latex all-pdf-ja
|
||||
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
|
||||
|
||||
text:
|
||||
doxygen
|
||||
$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
|
||||
@echo
|
||||
@echo "Build finished. The text files are in $(BUILDDIR)/text."
|
||||
|
||||
man:
|
||||
doxygen
|
||||
$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
|
||||
@echo
|
||||
@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
|
||||
|
||||
texinfo:
|
||||
doxygen
|
||||
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
|
||||
@echo
|
||||
@echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
|
||||
@echo "Run \`make' in that directory to run these through makeinfo" \
|
||||
"(use \`make info' here to do that automatically)."
|
||||
|
||||
info:
|
||||
doxygen
|
||||
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
|
||||
@echo "Running Texinfo files through makeinfo..."
|
||||
make -C $(BUILDDIR)/texinfo info
|
||||
@echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
|
||||
|
||||
gettext:
|
||||
doxygen
|
||||
$(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
|
||||
@echo
|
||||
@echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
|
||||
|
||||
changes:
|
||||
doxygen
|
||||
$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
|
||||
@echo
|
||||
@echo "The overview file is in $(BUILDDIR)/changes."
|
||||
|
||||
linkcheck:
|
||||
doxygen
|
||||
$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
|
||||
@echo
|
||||
@echo "Link check complete; look for any errors in the above output " \
|
||||
"or in $(BUILDDIR)/linkcheck/output.txt."
|
||||
|
||||
doctest:
|
||||
doxygen
|
||||
$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
|
||||
@echo "Testing of doctests in the sources finished, look at the " \
|
||||
"results in $(BUILDDIR)/doctest/output.txt."
|
||||
|
||||
coverage:
|
||||
doxygen
|
||||
$(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) $(BUILDDIR)/coverage
|
||||
@echo "Testing of coverage in the sources finished, look at the " \
|
||||
"results in $(BUILDDIR)/coverage/python.txt."
|
||||
|
||||
xml:
|
||||
doxygen
|
||||
$(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml
|
||||
@echo
|
||||
@echo "Build finished. The XML files are in $(BUILDDIR)/xml."
|
||||
|
||||
pseudoxml:
|
||||
doxygen
|
||||
$(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml
|
||||
@echo
|
||||
@echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml."
|
|
@ -0,0 +1,7 @@
|
|||
name: xtl-docs
|
||||
|
||||
channels:
|
||||
- conda-forge
|
||||
|
||||
dependencies:
|
||||
- breathe==4.16.0
|
|
@ -0,0 +1,264 @@
|
|||
@ECHO OFF
|
||||
|
||||
REM Command file for Sphinx documentation
|
||||
|
||||
if "%SPHINXBUILD%" == "" (
|
||||
set SPHINXBUILD=sphinx-build
|
||||
)
|
||||
set BUILDDIR=build
|
||||
set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% source
|
||||
set I18NSPHINXOPTS=%SPHINXOPTS% source
|
||||
if NOT "%PAPER%" == "" (
|
||||
set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS%
|
||||
set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS%
|
||||
)
|
||||
|
||||
if "%1" == "" goto help
|
||||
|
||||
if "%1" == "help" (
|
||||
:help
|
||||
echo.Please use `make ^<target^>` where ^<target^> is one of
|
||||
echo. html to make standalone HTML files
|
||||
echo. dirhtml to make HTML files named index.html in directories
|
||||
echo. singlehtml to make a single large HTML file
|
||||
echo. pickle to make pickle files
|
||||
echo. json to make JSON files
|
||||
echo. htmlhelp to make HTML files and a HTML help project
|
||||
echo. qthelp to make HTML files and a qthelp project
|
||||
echo. devhelp to make HTML files and a Devhelp project
|
||||
echo. epub to make an epub
|
||||
echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter
|
||||
echo. text to make text files
|
||||
echo. man to make manual pages
|
||||
echo. texinfo to make Texinfo files
|
||||
echo. gettext to make PO message catalogs
|
||||
echo. changes to make an overview over all changed/added/deprecated items
|
||||
echo. xml to make Docutils-native XML files
|
||||
echo. pseudoxml to make pseudoxml-XML files for display purposes
|
||||
echo. linkcheck to check all external links for integrity
|
||||
echo. doctest to run all doctests embedded in the documentation if enabled
|
||||
echo. coverage to run coverage check of the documentation if enabled
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "clean" (
|
||||
for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i
|
||||
del /q /s %BUILDDIR%\*
|
||||
goto end
|
||||
)
|
||||
|
||||
|
||||
REM Check if sphinx-build is available and fallback to Python version if any
|
||||
%SPHINXBUILD% 1>NUL 2>NUL
|
||||
if errorlevel 9009 goto sphinx_python
|
||||
goto sphinx_ok
|
||||
|
||||
:sphinx_python
|
||||
|
||||
set SPHINXBUILD=python -m sphinx.__init__
|
||||
%SPHINXBUILD% 2> nul
|
||||
if errorlevel 9009 (
|
||||
echo.
|
||||
echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
|
||||
echo.installed, then set the SPHINXBUILD environment variable to point
|
||||
echo.to the full path of the 'sphinx-build' executable. Alternatively you
|
||||
echo.may add the Sphinx directory to PATH.
|
||||
echo.
|
||||
echo.If you don't have Sphinx installed, grab it from
|
||||
echo.http://sphinx-doc.org/
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
:sphinx_ok
|
||||
|
||||
|
||||
if "%1" == "html" (
|
||||
doxygen
|
||||
%SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished. The HTML pages are in %BUILDDIR%/html.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "dirhtml" (
|
||||
%SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "singlehtml" (
|
||||
%SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "pickle" (
|
||||
%SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished; now you can process the pickle files.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "json" (
|
||||
%SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished; now you can process the JSON files.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "htmlhelp" (
|
||||
%SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished; now you can run HTML Help Workshop with the ^
|
||||
.hhp project file in %BUILDDIR%/htmlhelp.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "qthelp" (
|
||||
%SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished; now you can run "qcollectiongenerator" with the ^
|
||||
.qhcp project file in %BUILDDIR%/qthelp, like this:
|
||||
echo.^> qcollectiongenerator %BUILDDIR%\qthelp\packagename.qhcp
|
||||
echo.To view the help file:
|
||||
echo.^> assistant -collectionFile %BUILDDIR%\qthelp\packagename.ghc
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "devhelp" (
|
||||
%SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "epub" (
|
||||
%SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished. The epub file is in %BUILDDIR%/epub.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "latex" (
|
||||
%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished; the LaTeX files are in %BUILDDIR%/latex.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "latexpdf" (
|
||||
%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
|
||||
cd %BUILDDIR%/latex
|
||||
make all-pdf
|
||||
cd %~dp0
|
||||
echo.
|
||||
echo.Build finished; the PDF files are in %BUILDDIR%/latex.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "latexpdfja" (
|
||||
%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
|
||||
cd %BUILDDIR%/latex
|
||||
make all-pdf-ja
|
||||
cd %~dp0
|
||||
echo.
|
||||
echo.Build finished; the PDF files are in %BUILDDIR%/latex.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "text" (
|
||||
%SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished. The text files are in %BUILDDIR%/text.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "man" (
|
||||
%SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished. The manual pages are in %BUILDDIR%/man.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "texinfo" (
|
||||
%SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "gettext" (
|
||||
%SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished. The message catalogs are in %BUILDDIR%/locale.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "changes" (
|
||||
%SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.The overview file is in %BUILDDIR%/changes.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "linkcheck" (
|
||||
%SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Link check complete; look for any errors in the above output ^
|
||||
or in %BUILDDIR%/linkcheck/output.txt.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "doctest" (
|
||||
%SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Testing of doctests in the sources finished, look at the ^
|
||||
results in %BUILDDIR%/doctest/output.txt.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "coverage" (
|
||||
%SPHINXBUILD% -b coverage %ALLSPHINXOPTS% %BUILDDIR%/coverage
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Testing of coverage in the sources finished, look at the ^
|
||||
results in %BUILDDIR%/coverage/python.txt.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "xml" (
|
||||
%SPHINXBUILD% -b xml %ALLSPHINXOPTS% %BUILDDIR%/xml
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished. The XML files are in %BUILDDIR%/xml.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "pseudoxml" (
|
||||
%SPHINXBUILD% -b pseudoxml %ALLSPHINXOPTS% %BUILDDIR%/pseudoxml
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished. The pseudo-XML files are in %BUILDDIR%/pseudoxml.
|
||||
goto end
|
||||
)
|
||||
|
||||
:end
|
|
@ -0,0 +1,4 @@
|
|||
.wy-nav-content{
|
||||
max-width: 1000px;
|
||||
margin: auto;
|
||||
}
|
|
@ -0,0 +1,115 @@
|
|||
.. Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht
|
||||
|
||||
Distributed under the terms of the BSD 3-Clause License.
|
||||
|
||||
The full license is in the file LICENSE, distributed with this software.
|
||||
|
||||
Basic types
|
||||
===========
|
||||
|
||||
any
|
||||
---
|
||||
|
||||
`xtl::any` is a backport of the C++17 class `std::any`. The class describes a
|
||||
type-safe container for single values of any type:
|
||||
|
||||
.. code::
|
||||
|
||||
#include <iostream>
|
||||
#include "xtl/xany.hpp"
|
||||
|
||||
xtl::any a = 1;
|
||||
std::cout << a.type().name() << ": " << xtl::any_cast<int>(a) << std::endl;
|
||||
// => i: 1
|
||||
|
||||
try
|
||||
{
|
||||
std::cout << xtl::any_cast<float>(a) << std::endl;
|
||||
}
|
||||
catch(const xtl::bad_any_cast& e)
|
||||
{
|
||||
std::cout << e.what() << std::endl;
|
||||
}
|
||||
// => bad any_cast
|
||||
|
||||
a.reset();
|
||||
std::cout << std::boolalpha << a.empty() << std::endl;
|
||||
// => true
|
||||
|
||||
The API of `xtl::any` is the same as that of `std::any`. Full documentation
|
||||
can be found on `cppreference <https://en.cppreference.com/w/cpp/utility/any>`_.
|
||||
|
||||
xbasic_fixed_string
|
||||
-------------------
|
||||
|
||||
TODO
|
||||
|
||||
xcomplex
|
||||
--------
|
||||
|
||||
`xcomplex` is the equivalent to `std::complex`, where the real ang imaginary
|
||||
part can be stored either as values, or as references. Therefore, it can be
|
||||
used as a proxy on real values already initialized. This is particularly
|
||||
interesting for storing real and imaginary parts in different containers,
|
||||
and gather them as complex values for computation. This allows optimzations
|
||||
(such as vectorization) on the real and imgaginary values.
|
||||
|
||||
.. code::
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include "xtl/xcomplex.hpp"
|
||||
|
||||
std::vector<double> arg1_real = { 1., 2.};
|
||||
std::vector<double> arg1_imag = { 3., 4.};
|
||||
std::vector<double> arg2_real = { 2., 4.};
|
||||
std::vector<double> arg2_real = { 1., 3.};
|
||||
std::vector<double> res_real(2);
|
||||
std::vector<double> res_imag(2);
|
||||
|
||||
using complex = xtl::xcomplex<double&, double&>;
|
||||
using const_complex = xtl::xcomplex<const double&, const double&>;
|
||||
for (size_t i = 0; i < 2; ++i)
|
||||
{
|
||||
complex res(res_real[i], res_img[i]);
|
||||
res = const_complex(arg1_real, arg1_imag) * const_complex(arg2_real, arg2_imag);
|
||||
std::cout << "res = (" << res.real(), << ", " << res.imag() << std::endl;
|
||||
}
|
||||
|
||||
The API of `xtl::xcomplex` is the same as that of `std::complex`, with the ability
|
||||
to store values as references. Full documentation can be found on
|
||||
`cppreference <https://en.cppreference.com/w/cpp/numeric/complex>`_.
|
||||
|
||||
half_float
|
||||
----------
|
||||
|
||||
The `half_cloat` class implements an IEEE-conformant half-precision floating-point type
|
||||
with the usual arithmetic operators and conversions. It is implicitly convertible from
|
||||
single-precision floating-point, which makes expressions and fnuctions with mixed-type
|
||||
operands to be of the most precise operand type.
|
||||
|
||||
.. code::
|
||||
|
||||
#include <iostream<
|
||||
#include "xtl/xhalf.hpp"
|
||||
|
||||
xtl::half_float f0 = 1.0f;
|
||||
xtl::half_float f1 = 2.0f;
|
||||
auto res = f0 + f1;
|
||||
std::cout << res << std::endl;
|
||||
|
||||
xmasked_value
|
||||
-------------
|
||||
|
||||
TODO
|
||||
|
||||
xoptional
|
||||
---------
|
||||
|
||||
TODO
|
||||
|
||||
xvariant
|
||||
--------
|
||||
|
||||
TODO
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
.. Copyright (c) 2017, Johan Mabille and Sylvain Corlay
|
||||
|
||||
Distributed under the terms of the BSD 3-Clause License.
|
||||
|
||||
The full license is in the file LICENSE, distributed with this software.
|
||||
|
||||
Build and configuration
|
||||
=======================
|
||||
|
||||
Build
|
||||
-----
|
||||
|
||||
``xtl`` build supports the following options:
|
||||
|
||||
- ``BUILD_TESTS``: enables the ``xtest`` target (see below).
|
||||
- ``DOWNLOAD_GTEST``: downloads ``gtest`` and builds it locally instead of using a binary installation.
|
||||
- ``GTEST_SRC_DIR``: indicates where to find the ``gtest`` sources instead of downloading them.
|
||||
- ``XTL_DISABLE_EXCEPTIONS``: indicates that tests should be run with exceptions disabled.
|
||||
|
||||
All these options are disabled by default. Enabling ``DOWNLOAD_GTEST`` or setting ``GTEST_SRC_DIR``
|
||||
enables ``BUILD_TESTS``.
|
||||
|
||||
If the ``BUILD_TESTS`` option is enabled, the following target is available:
|
||||
|
||||
- xtest: builds an run the test suite.
|
||||
|
||||
For instance, building the test suite of ``xtl`` where the sources of ``gtest`` are located in e.g. ``/usr/share/gtest``:
|
||||
|
||||
.. code::
|
||||
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -DGTEST_SRC_DIR=/usr/share/gtest ../
|
||||
make xtest
|
|
@ -0,0 +1,437 @@
|
|||
.. Copyright (c) 2017, Johan Mabille and Sylvain Corlay
|
||||
|
||||
Distributed under the terms of the BSD 3-Clause License.
|
||||
|
||||
The full license is in the file LICENSE, distributed with this software.
|
||||
|
||||
Changelog
|
||||
=========
|
||||
|
||||
0.7.2
|
||||
-----
|
||||
|
||||
- Removed C++14 code from xbase_fixed_string
|
||||
|
||||
0.7.1
|
||||
-----
|
||||
|
||||
- test/test_xsystem.cpp: Allow for ctest executable names
|
||||
- Fixed return type in xbasic_fixed_string to be compatible with C++11
|
||||
|
||||
0.7.0
|
||||
-----
|
||||
|
||||
- Added missing FreeBSD headers
|
||||
- Fixed call to sysctl
|
||||
- Added meta switch
|
||||
- Implement partial dispatch
|
||||
- Improve xbasic fixed string
|
||||
|
||||
0.6.23
|
||||
------
|
||||
|
||||
- Added ``xtl::executable_path`` and ``xtl::prefix_path``
|
||||
|
||||
0.6.22
|
||||
------
|
||||
|
||||
- Handle complex promote type w/ different T1 and T2
|
||||
- Install as arch dependent for cmake > 3.14
|
||||
|
||||
0.6.21
|
||||
------
|
||||
|
||||
- CMake: Modernized GTest integration
|
||||
- Add support for ``xtl::endianness``
|
||||
|
||||
0.6.20
|
||||
------
|
||||
|
||||
- Added xtraits for future simple specialization
|
||||
- Added half_float implementation
|
||||
|
||||
0.6.19
|
||||
------
|
||||
|
||||
- Improved ``mpl::contains`` implementation
|
||||
- Added ``are_equivalent_sequences``
|
||||
- Various minor improvements
|
||||
|
||||
0.6.18
|
||||
------
|
||||
|
||||
- Relaxed dimension constraint on multidispatcher
|
||||
- Replaced throw with XTL_THROW to support disabling exceptions
|
||||
|
||||
0.6.17
|
||||
------
|
||||
|
||||
- Implemented ``index_of`` for ``mpl::vector``
|
||||
- Implemented multimethods pattern
|
||||
- Implemented visitor pattern
|
||||
|
||||
0.6.16
|
||||
------
|
||||
|
||||
- Fixed mpark variant inclusion guards
|
||||
- Add a serialiser for xvariant to json
|
||||
- Removed capture all by reference
|
||||
|
||||
0.6.15
|
||||
------
|
||||
|
||||
- Renamed mpark variant header inclusion guard
|
||||
|
||||
0.6.14
|
||||
------
|
||||
|
||||
- Implemented value iterator for map containers
|
||||
|
||||
0.6.13
|
||||
------
|
||||
|
||||
- mpark/variant small change for CUDA 10.2 workaround
|
||||
- Switched the documentation build to QuantStack channel
|
||||
- Refactored CI
|
||||
|
||||
0.6.12
|
||||
------
|
||||
|
||||
- NVCC CUDA compiler compatibility
|
||||
- Wrapped call to ``find_package``
|
||||
|
||||
0.6.11
|
||||
------
|
||||
|
||||
- Avoids C++20 "requires" keyword
|
||||
|
||||
0.6.10
|
||||
------
|
||||
|
||||
- Set up xtl target's public headers
|
||||
- CMake: adding C++14 standard to target
|
||||
|
||||
0.6.9
|
||||
-----
|
||||
|
||||
- Implemented stepping iterators
|
||||
|
||||
0.6.8
|
||||
-----
|
||||
|
||||
- Fixed murmur implementation for x86 platform
|
||||
|
||||
0.6.7
|
||||
-----
|
||||
|
||||
- Specialized ``promote_type`` for ``std::complex``
|
||||
|
||||
0.6.6
|
||||
-----
|
||||
|
||||
- Fixed ``promote_type`` for ``std::chrono::time_point``
|
||||
- Update README for Conan installation instructions
|
||||
|
||||
0.6.5
|
||||
-----
|
||||
|
||||
- Add supports for clang-cl compiler
|
||||
- Fix cmake command
|
||||
- Fix compiler error with clang-cl compiler
|
||||
|
||||
0.6.4
|
||||
-----
|
||||
|
||||
- Fixed forward type
|
||||
|
||||
0.6.3
|
||||
-----
|
||||
|
||||
- Fix constness issue in xtl's implementation of std::any.
|
||||
|
||||
0.6.2
|
||||
-----
|
||||
|
||||
- Allows xtl to build with -fno-exceptions
|
||||
- Added ``constify`` and ``constify_t``
|
||||
- Added ``size_t`` overloads for random access iterators
|
||||
|
||||
0.6.1
|
||||
-----
|
||||
|
||||
- Latex does not know how to include svg
|
||||
- Added ``XTL_REQUIRES_IMPL`` macro
|
||||
- Removed warnings
|
||||
|
||||
0.6.0
|
||||
-----
|
||||
|
||||
- Standalone build of xtl tests
|
||||
- Moved ``xmasked_value`` from `xtensor`
|
||||
- Moved ``promote_type`` from `xtensor`
|
||||
- Disabled ``xoptional`` methods for ``xmasked_value``
|
||||
- Implemented ``select``
|
||||
- ``make_sequence`` from ``initializer_list``
|
||||
|
||||
0.5.4
|
||||
-----
|
||||
|
||||
- Implementation of mpl::unique
|
||||
- Prevent installation of gtest artifact
|
||||
|
||||
0.5.3
|
||||
-----
|
||||
|
||||
- upgraded to mpark/variant 1.4.0
|
||||
- implemented concepts
|
||||
- implemented split of type lists
|
||||
|
||||
0.5.2
|
||||
-----
|
||||
|
||||
- fixed C++11 compatibility in xjson.hpp
|
||||
|
||||
0.5.1
|
||||
-----
|
||||
|
||||
- reverse order of initialization of optional
|
||||
- fixup mime type rendering of fixed string
|
||||
- closure wrapper assignment fixed
|
||||
|
||||
0.5.0
|
||||
-----
|
||||
|
||||
- Serialization and deserialization of fixed strings
|
||||
- Inequality comparisons removed from bidirectional iterator base
|
||||
- Simplified forward sequence
|
||||
- Fixed forward sequence
|
||||
- Removed warnings
|
||||
- const reference getter for variant holding non const references
|
||||
- xget on rvalue fixed
|
||||
- Added storage option to fixed string
|
||||
- Added missing entries of header files in CMakeLists.txt
|
||||
- Refactored xdynamic_bitset
|
||||
- Fixed forwrad sequence for non resizable types
|
||||
- Removed meta pop-back
|
||||
|
||||
0.4.16
|
||||
------
|
||||
|
||||
- meta find_if implementation
|
||||
- Enable CTest and CMake cleanup
|
||||
- Make nlohmann_json optional in the tests, exported C++14 requirements
|
||||
|
||||
0.4.15
|
||||
------
|
||||
|
||||
- Value types in const closures are not const qualified anymore, to allow move
|
||||
- Added third template parameter to forward_sequence that allows for true
|
||||
forwarding of sequences
|
||||
|
||||
0.4.14
|
||||
------
|
||||
|
||||
- Fixed typo in 'xtl.pc.in'
|
||||
- Removed -march=native from systems that do not support in CMakeLists
|
||||
- Added hash.verification result for big-endian systemss
|
||||
- Fixed common_optional_impl
|
||||
- Implemented xeus-cling mime_bundle_repr for xoptional, xcomplex and xfixed_string
|
||||
|
||||
0.4.13
|
||||
------
|
||||
|
||||
- CMake call to find_package with nlohmann_json is QUIET
|
||||
- Fix typo in xoptional swap
|
||||
- Added pkgconfig support
|
||||
|
||||
0.4.12
|
||||
------
|
||||
|
||||
- operator overload fixes for xcomplex
|
||||
|
||||
0.4.11
|
||||
------
|
||||
|
||||
- add missing `<limits>` header in xcomplex
|
||||
- fix xcomplex isnan test
|
||||
|
||||
0.4.10
|
||||
------
|
||||
|
||||
- `xcomplex` implementation
|
||||
- `xcomplex_sequence` implementation
|
||||
|
||||
0.4.9
|
||||
-----
|
||||
|
||||
- return type of `static_if` fixed
|
||||
|
||||
0.4.8
|
||||
-----
|
||||
|
||||
- support for JSON serialization of xoptionals
|
||||
|
||||
0.4.7
|
||||
-----
|
||||
|
||||
- support for uninitialized `make_sequence`
|
||||
|
||||
0.4.6
|
||||
-----
|
||||
|
||||
- remove an unused file.
|
||||
- support for overloaded lambdas
|
||||
|
||||
0.4.5
|
||||
-----
|
||||
|
||||
- xget for variant on xclosure_wrapper
|
||||
|
||||
0.4.4
|
||||
-----
|
||||
|
||||
- bug fix in any
|
||||
- hierarchy generators
|
||||
|
||||
0.4.3
|
||||
-----
|
||||
|
||||
- missing near integers functions for `xoptional`
|
||||
- `xoptional` compilation issue fixed
|
||||
|
||||
0.4.2
|
||||
-----
|
||||
|
||||
- added missing operators for xoptional
|
||||
- removed compiler warning if cpp_exceptions already defined
|
||||
|
||||
0.4.1
|
||||
-----
|
||||
|
||||
- Bug fix in move semantics for xoptional free functions (`value` and `has_value`)
|
||||
- Use `static_if` instead of regular `if` to remove gcc-6 warning.
|
||||
- Document installation with the Spack package manager.
|
||||
- Fix complex operators with closure wrappers.
|
||||
- Integrate upstream fix for the variant implementation.
|
||||
|
||||
0.4.0
|
||||
-----
|
||||
|
||||
- Migration to modern target-based cmake
|
||||
|
||||
0.3.9
|
||||
-----
|
||||
|
||||
- Bug fix in the computing of hashes for 32 bit platforms
|
||||
- Fixing warnings
|
||||
|
||||
0.3.8
|
||||
-----
|
||||
|
||||
- Improvements and fixes in base iterators (common iterator tag)
|
||||
|
||||
0.3.7
|
||||
-----
|
||||
|
||||
- Fixes in `xoptional`.
|
||||
|
||||
0.3.6
|
||||
-----
|
||||
|
||||
- Addition of base iterators for linear containers, and associative containers.
|
||||
|
||||
0.3.5
|
||||
-----
|
||||
|
||||
- Addition of `value` and `has_value` free functions.
|
||||
- Bug fix in comparison operator for `xclosure_wrapper`.
|
||||
|
||||
0.3.4
|
||||
-----
|
||||
|
||||
- Better semantics for assignment operators in `xoptional`.
|
||||
- Addition of `static_if` in `xtl::mpl`.
|
||||
- Addition of `xtl::identity` functor in xfunctional.
|
||||
|
||||
0.3.3
|
||||
-----
|
||||
|
||||
- Work around Visual Studio compiler bug in `xoptional_proxy`.
|
||||
|
||||
0.3.2
|
||||
-----
|
||||
|
||||
- Improvement of xoptional value semantics (explicit constructors when underlying value type not implicitely constructable)
|
||||
|
||||
0.3.1
|
||||
-----
|
||||
|
||||
- Fixes in closure wrapper semantics
|
||||
|
||||
0.3.0
|
||||
-----
|
||||
|
||||
- Improve optional sequence
|
||||
- Use dynamic bitset in optional vector
|
||||
- Added base64encode and base64decode
|
||||
|
||||
0.2.11
|
||||
------
|
||||
|
||||
- Added dynamic bitset
|
||||
|
||||
0.2.10
|
||||
------
|
||||
|
||||
- Added meta programming tools
|
||||
|
||||
0.2.9
|
||||
-----
|
||||
|
||||
- Added variant implementation
|
||||
|
||||
0.2.8
|
||||
-----
|
||||
|
||||
- Added proxy wrapper for pointer semantics.
|
||||
|
||||
0.2.7
|
||||
-----
|
||||
|
||||
- Added implementation for closure pointer
|
||||
|
||||
0.2.6
|
||||
-----
|
||||
|
||||
- Added base class for random access iterators
|
||||
|
||||
0.2.5
|
||||
-----
|
||||
|
||||
- Added closure wrappers
|
||||
|
||||
0.2.4
|
||||
-----
|
||||
|
||||
- Added implementation of std::any
|
||||
|
||||
0.2.3
|
||||
-----
|
||||
|
||||
- Fixed bug in fixed-size string hashing
|
||||
|
||||
0.2.2
|
||||
-----
|
||||
|
||||
- Added the hashing of fixed-size strings
|
||||
|
||||
0.2.1
|
||||
-----
|
||||
|
||||
- Fixed-size strings
|
||||
- Fixup issue with ambiguous overload of operator<<
|
||||
|
||||
0.2.0
|
||||
-----
|
||||
|
||||
- Moving features from xtensor (xcomplex, xoptional, xsequence, xtypetraits)
|
|
@ -0,0 +1,493 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
id="svg2816"
|
||||
version="1.1"
|
||||
inkscape:version="0.47 r22583"
|
||||
width="2072"
|
||||
height="2072"
|
||||
sodipodi:docname="Cmake.svg">
|
||||
<metadata
|
||||
id="metadata2822">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<defs
|
||||
id="defs2820">
|
||||
<linearGradient
|
||||
id="linearGradient4276">
|
||||
<stop
|
||||
style="stop-color:#32691d;stop-opacity:1"
|
||||
offset="0"
|
||||
id="stop4278" />
|
||||
<stop
|
||||
id="stop4280"
|
||||
offset="0.02012207"
|
||||
style="stop-color:#01d200;stop-opacity:0" />
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop4282" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient4227">
|
||||
<stop
|
||||
style="stop-color:#ebebec;stop-opacity:1"
|
||||
offset="0"
|
||||
id="stop4229" />
|
||||
<stop
|
||||
id="stop4231"
|
||||
offset="0.00518292"
|
||||
style="stop-color:#d3d3d3;stop-opacity:0" />
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop4233" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient4129">
|
||||
<stop
|
||||
id="stop4131"
|
||||
offset="0"
|
||||
style="stop-color:#cbf595;stop-opacity:1" />
|
||||
<stop
|
||||
style="stop-color:#01da00;stop-opacity:0"
|
||||
offset="0.01826929"
|
||||
id="stop4133" />
|
||||
<stop
|
||||
id="stop4135"
|
||||
offset="1"
|
||||
style="stop-color:#ffffff;stop-opacity:0;" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient4039">
|
||||
<stop
|
||||
style="stop-color:#321e1d;stop-opacity:1"
|
||||
offset="0"
|
||||
id="stop4041" />
|
||||
<stop
|
||||
id="stop4043"
|
||||
offset="0.01546729"
|
||||
style="stop-color:#555548;stop-opacity:0" />
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop4045" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient3990">
|
||||
<stop
|
||||
style="stop-color:#321e1d;stop-opacity:1"
|
||||
offset="0"
|
||||
id="stop3992" />
|
||||
<stop
|
||||
id="stop3994"
|
||||
offset="0.02012207"
|
||||
style="stop-color:#5a5bd7;stop-opacity:0" />
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop3996" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient3941">
|
||||
<stop
|
||||
id="stop3943"
|
||||
offset="0"
|
||||
style="stop-color:#f6b1b2;stop-opacity:1" />
|
||||
<stop
|
||||
style="stop-color:#c51f1f;stop-opacity:0"
|
||||
offset="0.02821624"
|
||||
id="stop3945" />
|
||||
<stop
|
||||
id="stop3947"
|
||||
offset="1"
|
||||
style="stop-color:#ffffff;stop-opacity:0;" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient3851">
|
||||
<stop
|
||||
id="stop3853"
|
||||
offset="0"
|
||||
style="stop-color:#321e1d;stop-opacity:1" />
|
||||
<stop
|
||||
style="stop-color:#555548;stop-opacity:0"
|
||||
offset="0.02012207"
|
||||
id="stop3855" />
|
||||
<stop
|
||||
id="stop3857"
|
||||
offset="1"
|
||||
style="stop-color:#ffffff;stop-opacity:0;" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient3800">
|
||||
<stop
|
||||
style="stop-color:#cbcaf2;stop-opacity:1"
|
||||
offset="0"
|
||||
id="stop3802" />
|
||||
<stop
|
||||
id="stop3808"
|
||||
offset="0.02636753"
|
||||
style="stop-color:#5555d2;stop-opacity:0" />
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop3804" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient3715">
|
||||
<stop
|
||||
style="stop-color:#848484;stop-opacity:1"
|
||||
offset="0"
|
||||
id="stop3717" />
|
||||
<stop
|
||||
style="stop-color:#d2d2d2;stop-opacity:1"
|
||||
offset="1"
|
||||
id="stop3719" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient3669">
|
||||
<stop
|
||||
style="stop-color:#01a300;stop-opacity:1"
|
||||
offset="0"
|
||||
id="stop3671" />
|
||||
<stop
|
||||
style="stop-color:#01df00;stop-opacity:1"
|
||||
offset="1"
|
||||
id="stop3673" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient3653">
|
||||
<stop
|
||||
style="stop-color:#b40e0e;stop-opacity:1"
|
||||
offset="0"
|
||||
id="stop3655" />
|
||||
<stop
|
||||
style="stop-color:#ff5959;stop-opacity:1"
|
||||
offset="1"
|
||||
id="stop3657" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient3645">
|
||||
<stop
|
||||
style="stop-color:#1011a1;stop-opacity:1"
|
||||
offset="0"
|
||||
id="stop3647" />
|
||||
<stop
|
||||
style="stop-color:#6969e1;stop-opacity:1"
|
||||
offset="1"
|
||||
id="stop3649" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient3645"
|
||||
id="linearGradient3651"
|
||||
x1="-1527.3507"
|
||||
y1="1387.5206"
|
||||
x2="-1086.1161"
|
||||
y2="454.13968"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="translate(2104,48)" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient3653"
|
||||
id="linearGradient3659"
|
||||
x1="-933.38092"
|
||||
y1="680.41388"
|
||||
x2="-316.78384"
|
||||
y2="1721.275"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="translate(2104,48)" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient3669"
|
||||
id="linearGradient3675"
|
||||
x1="-678.82251"
|
||||
y1="1794.8141"
|
||||
x2="-1549.978"
|
||||
y2="1721.275"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="translate(2104,48)" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient3715"
|
||||
id="linearGradient3721"
|
||||
x1="-984.2926"
|
||||
y1="1472.3735"
|
||||
x2="-995.60632"
|
||||
y2="1093.3643"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="translate(2104,48)" />
|
||||
<filter
|
||||
inkscape:collect="always"
|
||||
id="filter3777">
|
||||
<feGaussianBlur
|
||||
inkscape:collect="always"
|
||||
stdDeviation="9.0766588"
|
||||
id="feGaussianBlur3779" />
|
||||
</filter>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient3800"
|
||||
id="linearGradient3806"
|
||||
x1="-1238.0465"
|
||||
y1="919.71448"
|
||||
x2="-555.82379"
|
||||
y2="917.51282"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(1.9188939,0.98349385,-0.45611308,0.88992183,3476.0418,1285.266)" />
|
||||
<linearGradient
|
||||
y2="913.40582"
|
||||
x2="-552.84039"
|
||||
y1="919.71448"
|
||||
x1="-1238.0465"
|
||||
gradientTransform="matrix(-1.9407023,0.93972781,-0.43581582,-0.90003588,-412.21511,3168.6506)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="linearGradient3828"
|
||||
xlink:href="#linearGradient3851"
|
||||
inkscape:collect="always" />
|
||||
<linearGradient
|
||||
id="linearGradient3851-6">
|
||||
<stop
|
||||
id="stop3853-2"
|
||||
offset="0"
|
||||
style="stop-color:#321e1d;stop-opacity:1" />
|
||||
<stop
|
||||
style="stop-color:#555548;stop-opacity:0"
|
||||
offset="0.02012207"
|
||||
id="stop3855-4" />
|
||||
<stop
|
||||
id="stop3857-5"
|
||||
offset="1"
|
||||
style="stop-color:#ffffff;stop-opacity:0;" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
y2="915.30005"
|
||||
x2="-555.83728"
|
||||
y1="919.71448"
|
||||
x1="-1238.0465"
|
||||
gradientTransform="matrix(0.02700295,-2.1560608,0.90368745,0.01314507,114.37039,-755.42907)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="linearGradient3877"
|
||||
xlink:href="#linearGradient3851-6"
|
||||
inkscape:collect="always" />
|
||||
<linearGradient
|
||||
y2="917.6181"
|
||||
x2="-554.89746"
|
||||
y1="919.71448"
|
||||
x1="-1238.0465"
|
||||
gradientTransform="matrix(3.1362513,0.00261809,0.06431073,0.7601511,4936.1356,68.133286)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="linearGradient3918"
|
||||
xlink:href="#linearGradient3941"
|
||||
inkscape:collect="always" />
|
||||
<linearGradient
|
||||
y2="917.51282"
|
||||
x2="-555.82379"
|
||||
y1="918.44379"
|
||||
x1="-1229.327"
|
||||
gradientTransform="matrix(-2.1510215,-0.07025797,-0.03821188,-0.48210687,-1498.469,1058.0104)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="linearGradient3967"
|
||||
xlink:href="#linearGradient3990"
|
||||
inkscape:collect="always" />
|
||||
<linearGradient
|
||||
y2="917.51282"
|
||||
x2="-555.82379"
|
||||
y1="920.41797"
|
||||
x1="-1237.1112"
|
||||
gradientTransform="matrix(-1.3798164,-1.6569612,0.7684458,-0.63991489,-2195.6367,413.8935)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="linearGradient4016"
|
||||
xlink:href="#linearGradient4039"
|
||||
inkscape:collect="always" />
|
||||
<linearGradient
|
||||
id="linearGradient3851-62">
|
||||
<stop
|
||||
id="stop3853-38"
|
||||
offset="0"
|
||||
style="stop-color:#321e1d;stop-opacity:1" />
|
||||
<stop
|
||||
style="stop-color:#555548;stop-opacity:0"
|
||||
offset="0.01739271"
|
||||
id="stop3855-2" />
|
||||
<stop
|
||||
id="stop3857-62"
|
||||
offset="1"
|
||||
style="stop-color:#ffffff;stop-opacity:0;" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
y2="910.64618"
|
||||
x2="-551.12549"
|
||||
y1="915.73645"
|
||||
x1="-1242.2334"
|
||||
gradientTransform="matrix(0.85312044,-1.9803029,0.91840135,0.39565006,2182.2918,-885.93458)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="linearGradient4065"
|
||||
xlink:href="#linearGradient3851-62"
|
||||
inkscape:collect="always" />
|
||||
<linearGradient
|
||||
y2="915.4801"
|
||||
x2="-555.86682"
|
||||
y1="919.71448"
|
||||
x1="-1238.0465"
|
||||
gradientTransform="matrix(1.3829904,1.654313,-0.7672176,0.6413869,2529.8389,3432.8719)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="linearGradient4106"
|
||||
xlink:href="#linearGradient4129"
|
||||
inkscape:collect="always" />
|
||||
<linearGradient
|
||||
y2="917.18665"
|
||||
x2="-866.86804"
|
||||
y1="918.09875"
|
||||
x1="-1242.5582"
|
||||
gradientTransform="matrix(1.3829904,1.654313,-0.7672176,0.6413869,2930.535,3096.9376)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="linearGradient4196"
|
||||
xlink:href="#linearGradient4227"
|
||||
inkscape:collect="always" />
|
||||
<linearGradient
|
||||
y2="917.51282"
|
||||
x2="-555.82379"
|
||||
y1="919.71448"
|
||||
x1="-1238.0465"
|
||||
gradientTransform="matrix(-0.83179183,1.989334,-0.83312221,-0.35033011,1447.5752,4603.6836)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
id="linearGradient4253"
|
||||
xlink:href="#linearGradient4276"
|
||||
inkscape:collect="always" />
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1280"
|
||||
inkscape:window-height="750"
|
||||
id="namedview2818"
|
||||
showgrid="false"
|
||||
inkscape:zoom="0.25"
|
||||
inkscape:cx="668.45545"
|
||||
inkscape:cy="769.26341"
|
||||
inkscape:window-x="-8"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg2816"
|
||||
showguides="true"
|
||||
inkscape:guide-bbox="true" />
|
||||
<g
|
||||
id="g3668">
|
||||
<path
|
||||
sodipodi:nodetypes="ccccccc"
|
||||
id="path2831-1"
|
||||
d="m 1971.5575,1939.9137 -1797.08691,-0.1258 c -11.0291,-1.2221 -8.5403,-6.713 -5.9958,-12.2215 L 1069.3546,128.0808 c 3.3139,-5.2772 6.2883,-4.4372 9.0861,-0.4108 l 900.8561,1799.4363 c 4.5781,9.1667 1.5811,13.1503 -7.7393,12.8074 z"
|
||||
style="fill:none;stroke:#3a393b;stroke-width:22.50000000000000000;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;filter:url(#filter3777);opacity:0.53974895" />
|
||||
<path
|
||||
sodipodi:nodetypes="cccc"
|
||||
id="path2828"
|
||||
d="M 1143.3083,1084.3217 158.69119,1926.0618 1060.5107,124.10214 1143.3083,1084.3217 z"
|
||||
style="fill:url(#linearGradient3651);fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-opacity:1" />
|
||||
<path
|
||||
sodipodi:nodetypes="ccccc"
|
||||
id="rect3781"
|
||||
d="m 1060.5637,125.61959 c 13.4152,80.71591 11.94,94.79031 -18.0349,140.07316 L 245.92029,1844.832 161.31739,1921.7588 1060.5637,125.61959 z"
|
||||
style="fill:url(#linearGradient3806);fill-opacity:1;fill-rule:nonzero;stroke:none" />
|
||||
<path
|
||||
sodipodi:nodetypes="cccccc"
|
||||
id="rect3781-0-9"
|
||||
d="m 1147.188,1083.1536 -50.1671,40.0537 -52.7887,-888.7261 c -4.0533,-47.4341 -6.2416,-43.17076 -6.5492,-68.17004 l 25.1004,-48.95208 84.4046,965.79452 z"
|
||||
style="fill:url(#linearGradient3967);fill-opacity:1;fill-rule:nonzero;stroke:none" />
|
||||
<path
|
||||
sodipodi:nodetypes="cccc"
|
||||
id="path2828-4"
|
||||
d="M 1188.9362,1609.9939 1060.9788,123.94021 1963.9529,1926.2261 1188.9362,1609.9939 z"
|
||||
style="fill:url(#linearGradient3659);fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-opacity:1" />
|
||||
<path
|
||||
sodipodi:nodetypes="ccccc"
|
||||
id="rect3781-9"
|
||||
d="m 1060.9071,120.07731 c 24.1749,30.04558 39.608,75.93991 48.9654,112.17843 l 179.3742,1415.10436 -98.4276,-38.4391 -129.912,-1488.84369 z"
|
||||
style="fill:url(#linearGradient3918);fill-opacity:1;fill-rule:nonzero;stroke:none" />
|
||||
<path
|
||||
sodipodi:nodetypes="cccc"
|
||||
id="path2828-1"
|
||||
d="M 743.40929,1423.8349 1964.8794,1926.0085 158.92799,1925.81 743.40929,1423.8349 z"
|
||||
style="fill:url(#linearGradient3675);fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-opacity:1" />
|
||||
<path
|
||||
sodipodi:nodetypes="cccccc"
|
||||
id="rect3781-0"
|
||||
d="m 1963.6891,1926.5277 -56.7139,-24.6169 -795.9854,-1603.05217 c -21.9472,-24.37845 -34.3449,-39.62306 -41.2192,-51.95192 -1.1264,-32.3188 -2.943,-61.0813 -9.9138,-126.2626 l 903.8323,1805.88359 z"
|
||||
style="fill:url(#linearGradient3828);fill-opacity:1;fill-rule:nonzero;stroke:none" />
|
||||
<path
|
||||
sodipodi:nodetypes="cccc"
|
||||
id="path2828-4-7"
|
||||
d="m 745.26609,1425.0475 397.42281,-339.0381 55.3298,523.5716 -452.75261,-184.5335 z"
|
||||
style="fill:url(#linearGradient3721);fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:4;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
|
||||
<path
|
||||
inkscape:transform-center-y="624.859"
|
||||
inkscape:transform-center-x="758.12355"
|
||||
sodipodi:nodetypes="cccccc"
|
||||
id="rect3781-8"
|
||||
d="m 742.72829,1426.2554 c 17.4821,6.7504 20.8419,8.2827 35.806,14.4205 -16.1593,13.8305 -69.88,86.4885 -91.4281,103.8499 l -428.4072,362.6992 -98.8195,18.3883 582.8488,-499.3579 z"
|
||||
style="fill:url(#linearGradient4106);fill-opacity:1;fill-rule:nonzero;stroke:none" />
|
||||
<path
|
||||
inkscape:transform-center-y="347.22075"
|
||||
inkscape:transform-center-x="-821.22079"
|
||||
sodipodi:nodetypes="cccccc"
|
||||
id="rect3781-0-8-6"
|
||||
d="m 1962.8676,1925.4594 -68.0643,-1.0486 -1174.86681,-479.6332 23.5048,-18.7167 470.76241,191.9416 748.6639,307.4569 z"
|
||||
style="fill:url(#linearGradient4253);fill-opacity:1;fill-rule:nonzero;stroke:none" />
|
||||
<path
|
||||
sodipodi:nodetypes="ccccc"
|
||||
id="rect3781-0-8"
|
||||
d="m 159.98259,1925.4405 50.2958,-42.8864 1643.00831,0.1531 110.3276,42.727 -1803.63171,0.01 z"
|
||||
style="fill:url(#linearGradient3877);fill-opacity:1;fill-rule:nonzero;stroke:none" />
|
||||
<path
|
||||
inkscape:transform-center-y="369.96725"
|
||||
inkscape:transform-center-x="-887.51544"
|
||||
sodipodi:nodetypes="ccccccc"
|
||||
id="rect3781-0-7"
|
||||
d="m 1199.8469,1610.9874 -2.1608,-22.3386 610.5884,235.1678 c 39.4555,18.7661 69.1058,27.2993 88.8249,43.327 12.6947,5.2081 34.7241,12.6345 46.1135,16.4736 13.9264,9.2219 11.5065,23.9583 20.3177,41.5431 l -763.6837,-314.1729 z"
|
||||
style="fill:url(#linearGradient4065);fill-opacity:1;fill-rule:nonzero;stroke:none" />
|
||||
<path
|
||||
sodipodi:nodetypes="ccccccc"
|
||||
id="path2831"
|
||||
d="m 1958.5868,1931.807 -1797.08691,-0.1258 c -11.0291,-1.2221 -8.5403,-6.713 -5.9958,-12.2215 L 1056.3839,119.97408 c 3.3139,-5.27718 6.2883,-4.43721 9.0861,-0.4108 l 900.8561,1799.43632 c 4.5781,9.1667 1.5811,13.1503 -7.7393,12.8074 z"
|
||||
style="fill:none;stroke:#000000;stroke-width:12.19999981;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
|
||||
<path
|
||||
sodipodi:nodetypes="cccccc"
|
||||
id="rect3781-0-98"
|
||||
d="m 160.09059,1924.1505 25.5248,-54.5322 52.0681,-38.5691 899.32641,-780.8749 c 4.7998,18.518 1.8803,6.9336 6.1315,33.989 l -983.05081,839.9872 z"
|
||||
style="fill:url(#linearGradient4016);fill-opacity:1;fill-rule:nonzero;stroke:none" />
|
||||
<path
|
||||
inkscape:transform-center-y="624.859"
|
||||
inkscape:transform-center-x="758.12355"
|
||||
sodipodi:nodetypes="ccccc"
|
||||
id="rect3781-8-2"
|
||||
d="m 1141.0494,1090.571 c -7.8922,86.6075 -17.7158,81.5443 -53.2471,118.0205 l -263.40721,244.6992 -74.9445,-29.2367 391.59881,-333.483 z"
|
||||
style="fill:url(#linearGradient4196);fill-opacity:1;fill-rule:nonzero;stroke:none" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 17 KiB |
|
@ -0,0 +1 @@
|
|||
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 127 127"><style>.st0{fill:#43b02a}</style><path class="st0" d="M13.8 81.2c-2.1 4.2-3.8 8.6-5.2 13.1 4.7 1.3 9.4 2.2 14.2 2.6.1-3.8.4-7.4.9-11-3.4-1.3-6.7-2.9-9.9-4.7zM33 32.8c-2.8 0-5.5.2-8.3.6.4 2.8.8 5.5 1.5 8.3 1.9-3.2 4.2-6.1 6.8-8.7v-.2zM10.5 98.7c3.6 5.5 8.1 10.4 13.2 14.5-.5-4.3-.9-8.4-.9-12.5-4.2-.4-8.3-1.1-12.3-2zM43 3.4c-5 1.7-9.6 4-14 6.8 3.3.6 6.5 1.3 9.7 2.3 1.2-3.1 2.7-6.1 4.3-9.1zM63.6 0c-2.5 0-4.9.2-7.3.4 3.4 2.4 6.6 4.9 9.7 7.7l2.5 2.3-2.5 2.5c-2.1 2-4.1 4.1-6 6.4v.1s-.4.4-1 1.1c1.5-.2 3-.2 4.6-.2 23.9 0 43.3 19.4 43.3 43.3s-19.4 43.3-43.3 43.3c-8.3 0-16.1-2.3-22.7-6.4-3.3.4-6.5.6-9.8.6-1.5 0-3 0-4.6-.1.1 4.9.6 10 1.4 15.3 10.2 6.9 22.4 10.9 35.6 10.9 35.1 0 63.6-28.5 63.6-63.6C127.2 28.5 98.7 0 63.6 0z"/><path class="st0" d="M55.1 15c1.3-1.5 2.6-3 3.9-4.4-3-2.5-6.1-4.9-9.4-6.9-2 3.4-3.8 7-5.3 10.6 2.9 1.1 5.7 2.3 8.4 3.6 1.3-1.6 2.2-2.6 2.4-2.9zM19.4 34.1c-4.7.8-9.3 2.1-13.8 3.7 1.8 4.6 4.1 9.1 6.7 13.3 3-2.1 6.1-4.1 9.3-5.8-1-3.7-1.7-7.4-2.2-11.2zM11.1 58.1c-3.4 2.8-6.6 5.8-9.6 9.2 3.3 2.9 6.8 5.5 10.5 7.9 1.7-3 3.6-6 5.6-8.8-2.2-2.6-4.4-5.4-6.5-8.3zM27.3 87.3c-.4 3.2-.7 6.5-.8 9.9 3.2.2 6.4.2 9.6 0-3.4-2.8-6.4-6.1-8.8-9.9zM36.6 18.1c-4-1.1-8.1-2-12.2-2.5-.4 4.2-.4 8.3-.1 12.4 3.3-.4 6.5-.6 9.8-.6.6-3.2 1.5-6.3 2.5-9.3zM42.3 19.9c-.8 2.4-1.5 4.8-2.1 7.2 2.8-1.8 5.8-3.3 8.9-4.4-2.2-1-4.5-1.9-6.8-2.8zM.5 72.1c.8 6.2 2.5 12.1 5 17.5C6.8 86 8.3 82.4 10 79c-3.3-2.1-6.4-4.4-9.5-6.9zM18.8 18.5c-3.8 3.8-7.1 8-9.9 12.6 3.3-1 6.6-1.8 10-2.4-.2-3.4-.3-6.8-.1-10.2zM15 55.2c1.6 2.3 3.4 4.6 5.3 6.8.2-4 .8-7.8 2-11.5-2.5 1.4-5 3-7.3 4.7zM15.8 77.3c2.7 1.5 5.4 2.9 8.3 4.1-1.7-3.7-2.8-7.6-3.4-11.8-1.8 2.5-3.4 5.1-4.9 7.7zM8.4 54.1c-2-3.2-3.8-6.5-5.4-10C1.2 49.7.1 55.7 0 61.8c2.7-2.8 5.5-5.4 8.4-7.7z"/></svg>
|
After Width: | Height: | Size: 1.8 KiB |
|
@ -0,0 +1,38 @@
|
|||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
on_rtd = os.environ.get('READTHEDOCS', None) == 'True'
|
||||
|
||||
if on_rtd:
|
||||
subprocess.call('cd ..; doxygen', shell=True)
|
||||
|
||||
import sphinx_rtd_theme
|
||||
|
||||
html_theme = "sphinx_rtd_theme"
|
||||
|
||||
html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]
|
||||
|
||||
def setup(app):
|
||||
app.add_stylesheet("main_stylesheet.css")
|
||||
|
||||
extensions = ['breathe']
|
||||
breathe_projects = { 'xtl': '../xml' }
|
||||
templates_path = ['_templates']
|
||||
html_static_path = ['_static']
|
||||
source_suffix = '.rst'
|
||||
master_doc = 'index'
|
||||
project = 'xtl'
|
||||
copyright = '2017, Johan Mabille and Sylvain Corlay'
|
||||
author = 'Johan Mabille and Sylvain Corlay'
|
||||
|
||||
html_logo = 'quantstack-white.svg'
|
||||
|
||||
exclude_patterns = []
|
||||
highlight_language = 'c++'
|
||||
pygments_style = 'sphinx'
|
||||
todo_include_todos = False
|
||||
htmlhelp_basename = 'xtldoc'
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
.. Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht
|
||||
|
||||
Distributed under the terms of the BSD 3-Clause License.
|
||||
|
||||
The full license is in the file LICENSE, distributed with this software.
|
||||
|
||||
Containers
|
||||
==========
|
||||
|
||||
xcomplex_sequence
|
||||
-----------------
|
||||
|
||||
TODO
|
||||
|
||||
xdynamic_bitset
|
||||
---------------
|
||||
|
||||
TODO
|
||||
|
||||
xiterator_base
|
||||
--------------
|
||||
|
||||
TODO
|
||||
|
||||
xoptional_sequence
|
||||
------------------
|
||||
|
||||
TODO
|
||||
|
||||
xsequence
|
||||
---------
|
||||
|
||||
TODO
|
||||
|
||||
xspan
|
||||
-----
|
||||
|
||||
TODO
|
||||
|
|
@ -0,0 +1,86 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 10.0, SVG Export Plug-In . SVG Version: 3.0.0 Build 77) -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd" [
|
||||
<!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/">
|
||||
<!ENTITY ns_extend "http://ns.adobe.com/Extensibility/1.0/">
|
||||
<!ENTITY ns_ai "http://ns.adobe.com/AdobeIllustrator/10.0/">
|
||||
<!ENTITY ns_graphs "http://ns.adobe.com/Graphs/1.0/">
|
||||
<!ENTITY ns_vars "http://ns.adobe.com/Variables/1.0/">
|
||||
<!ENTITY ns_imrep "http://ns.adobe.com/ImageReplacement/1.0/">
|
||||
<!ENTITY ns_sfw "http://ns.adobe.com/SaveForWeb/1.0/">
|
||||
<!ENTITY ns_custom "http://ns.adobe.com/GenericCustomNamespace/1.0/">
|
||||
<!ENTITY ns_adobe_xpath "http://ns.adobe.com/XPath/1.0/">
|
||||
<!ENTITY ns_svg "http://www.w3.org/2000/svg">
|
||||
<!ENTITY ns_xlink "http://www.w3.org/1999/xlink">
|
||||
]>
|
||||
<svg
|
||||
xmlns:x="&ns_extend;" xmlns:i="&ns_ai;" xmlns:graph="&ns_graphs;" i:viewOrigin="262 450" i:rulerOrigin="0 0" i:pageBounds="0 792 612 0"
|
||||
xmlns="&ns_svg;" xmlns:xlink="&ns_xlink;" xmlns:a="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/"
|
||||
width="87.041" height="108.445" viewBox="0 0 87.041 108.445" overflow="visible" enable-background="new 0 0 87.041 108.445"
|
||||
xml:space="preserve">
|
||||
<metadata>
|
||||
<variableSets xmlns="&ns_vars;">
|
||||
<variableSet varSetName="binding1" locked="none">
|
||||
<variables></variables>
|
||||
<v:sampleDataSets xmlns="&ns_custom;" xmlns:v="&ns_vars;"></v:sampleDataSets>
|
||||
</variableSet>
|
||||
</variableSets>
|
||||
<sfw xmlns="&ns_sfw;">
|
||||
<slices></slices>
|
||||
<sliceSourceBounds y="341.555" x="262" width="87.041" height="108.445" bottomLeftOrigin="true"></sliceSourceBounds>
|
||||
</sfw>
|
||||
</metadata>
|
||||
<g id="Layer_1" i:layer="yes" i:dimmedPercent="50" i:rgbTrio="#4F008000FFFF">
|
||||
<g>
|
||||
<path i:knockout="Off" fill="#A80030" d="M51.986,57.297c-1.797,0.025,0.34,0.926,2.686,1.287
|
||||
c0.648-0.506,1.236-1.018,1.76-1.516C54.971,57.426,53.484,57.434,51.986,57.297"/>
|
||||
<path i:knockout="Off" fill="#A80030" d="M61.631,54.893c1.07-1.477,1.85-3.094,2.125-4.766c-0.24,1.192-0.887,2.221-1.496,3.307
|
||||
c-3.359,2.115-0.316-1.256-0.002-2.537C58.646,55.443,61.762,53.623,61.631,54.893"/>
|
||||
<path i:knockout="Off" fill="#A80030" d="M65.191,45.629c0.217-3.236-0.637-2.213-0.924-0.978
|
||||
C64.602,44.825,64.867,46.932,65.191,45.629"/>
|
||||
<path i:knockout="Off" fill="#A80030" d="M45.172,1.399c0.959,0.172,2.072,0.304,1.916,0.533
|
||||
C48.137,1.702,48.375,1.49,45.172,1.399"/>
|
||||
<path i:knockout="Off" fill="#A80030" d="M47.088,1.932l-0.678,0.14l0.631-0.056L47.088,1.932"/>
|
||||
<path i:knockout="Off" fill="#A80030" d="M76.992,46.856c0.107,2.906-0.85,4.316-1.713,6.812l-1.553,0.776
|
||||
c-1.271,2.468,0.123,1.567-0.787,3.53c-1.984,1.764-6.021,5.52-7.313,5.863c-0.943-0.021,0.639-1.113,0.846-1.541
|
||||
c-2.656,1.824-2.131,2.738-6.193,3.846l-0.119-0.264c-10.018,4.713-23.934-4.627-23.751-17.371
|
||||
c-0.107,0.809-0.304,0.607-0.526,0.934c-0.517-6.557,3.028-13.143,9.007-15.832c5.848-2.895,12.704-1.707,16.893,2.197
|
||||
c-2.301-3.014-6.881-6.209-12.309-5.91c-5.317,0.084-10.291,3.463-11.951,7.131c-2.724,1.715-3.04,6.611-4.227,7.507
|
||||
C31.699,56.271,36.3,61.342,44.083,67.307c1.225,0.826,0.345,0.951,0.511,1.58c-2.586-1.211-4.954-3.039-6.901-5.277
|
||||
c1.033,1.512,2.148,2.982,3.589,4.137c-2.438-0.826-5.695-5.908-6.646-6.115c4.203,7.525,17.052,13.197,23.78,10.383
|
||||
c-3.113,0.115-7.068,0.064-10.566-1.229c-1.469-0.756-3.467-2.322-3.11-2.615c9.182,3.43,18.667,2.598,26.612-3.771
|
||||
c2.021-1.574,4.229-4.252,4.867-4.289c-0.961,1.445,0.164,0.695-0.574,1.971c2.014-3.248-0.875-1.322,2.082-5.609l1.092,1.504
|
||||
c-0.406-2.696,3.348-5.97,2.967-10.234c0.861-1.304,0.961,1.403,0.047,4.403c1.268-3.328,0.334-3.863,0.66-6.609
|
||||
c0.352,0.923,0.814,1.904,1.051,2.878c-0.826-3.216,0.848-5.416,1.262-7.285c-0.408-0.181-1.275,1.422-1.473-2.377
|
||||
c0.029-1.65,0.459-0.865,0.625-1.271c-0.324-0.186-1.174-1.451-1.691-3.877c0.375-0.57,1.002,1.478,1.512,1.562
|
||||
c-0.328-1.929-0.893-3.4-0.916-4.88c-1.49-3.114-0.527,0.415-1.736-1.337c-1.586-4.947,1.316-1.148,1.512-3.396
|
||||
c2.404,3.483,3.775,8.881,4.404,11.117c-0.48-2.726-1.256-5.367-2.203-7.922c0.73,0.307-1.176-5.609,0.949-1.691
|
||||
c-2.27-8.352-9.715-16.156-16.564-19.818c0.838,0.767,1.896,1.73,1.516,1.881c-3.406-2.028-2.807-2.186-3.295-3.043
|
||||
c-2.775-1.129-2.957,0.091-4.795,0.002c-5.23-2.774-6.238-2.479-11.051-4.217l0.219,1.023c-3.465-1.154-4.037,0.438-7.782,0.004
|
||||
c-0.228-0.178,1.2-0.644,2.375-0.815c-3.35,0.442-3.193-0.66-6.471,0.122c0.808-0.567,1.662-0.942,2.524-1.424
|
||||
c-2.732,0.166-6.522,1.59-5.352,0.295c-4.456,1.988-12.37,4.779-16.811,8.943l-0.14-0.933c-2.035,2.443-8.874,7.296-9.419,10.46
|
||||
l-0.544,0.127c-1.059,1.793-1.744,3.825-2.584,5.67c-1.385,2.36-2.03,0.908-1.833,1.278c-2.724,5.523-4.077,10.164-5.246,13.97
|
||||
c0.833,1.245,0.02,7.495,0.335,12.497c-1.368,24.704,17.338,48.69,37.785,54.228c2.997,1.072,7.454,1.031,11.245,1.141
|
||||
c-4.473-1.279-5.051-0.678-9.408-2.197c-3.143-1.48-3.832-3.17-6.058-5.102l0.881,1.557c-4.366-1.545-2.539-1.912-6.091-3.037
|
||||
l0.941-1.229c-1.415-0.107-3.748-2.385-4.386-3.646l-1.548,0.061c-1.86-2.295-2.851-3.949-2.779-5.23l-0.5,0.891
|
||||
c-0.567-0.973-6.843-8.607-3.587-6.83c-0.605-0.553-1.409-0.9-2.281-2.484l0.663-0.758c-1.567-2.016-2.884-4.6-2.784-5.461
|
||||
c0.836,1.129,1.416,1.34,1.99,1.533c-3.957-9.818-4.179-0.541-7.176-9.994l0.634-0.051c-0.486-0.732-0.781-1.527-1.172-2.307
|
||||
l0.276-2.75C4.667,58.121,6.719,47.409,7.13,41.534c0.285-2.389,2.378-4.932,3.97-8.92l-0.97-0.167
|
||||
c1.854-3.234,10.586-12.988,14.63-12.486c1.959-2.461-0.389-0.009-0.772-0.629c4.303-4.453,5.656-3.146,8.56-3.947
|
||||
c3.132-1.859-2.688,0.725-1.203-0.709c5.414-1.383,3.837-3.144,10.9-3.846c0.745,0.424-1.729,0.655-2.35,1.205
|
||||
c4.511-2.207,14.275-1.705,20.617,1.225c7.359,3.439,15.627,13.605,15.953,23.17l0.371,0.1
|
||||
c-0.188,3.802,0.582,8.199-0.752,12.238L76.992,46.856"/>
|
||||
<path i:knockout="Off" fill="#A80030" d="M32.372,59.764l-0.252,1.26c1.181,1.604,2.118,3.342,3.626,4.596
|
||||
C34.661,63.502,33.855,62.627,32.372,59.764"/>
|
||||
<path i:knockout="Off" fill="#A80030" d="M35.164,59.654c-0.625-0.691-0.995-1.523-1.409-2.352
|
||||
c0.396,1.457,1.207,2.709,1.962,3.982L35.164,59.654"/>
|
||||
<path i:knockout="Off" fill="#A80030" d="M84.568,48.916l-0.264,0.662c-0.484,3.438-1.529,6.84-3.131,9.994
|
||||
C82.943,56.244,84.088,52.604,84.568,48.916"/>
|
||||
<path i:knockout="Off" fill="#A80030" d="M45.527,0.537C46.742,0.092,48.514,0.293,49.803,0c-1.68,0.141-3.352,0.225-5.003,0.438
|
||||
L45.527,0.537"/>
|
||||
<path i:knockout="Off" fill="#A80030" d="M2.872,23.219c0.28,2.592-1.95,3.598,0.494,1.889
|
||||
C4.676,22.157,2.854,24.293,2.872,23.219"/>
|
||||
<path i:knockout="Off" fill="#A80030" d="M0,35.215c0.563-1.728,0.665-2.766,0.88-3.766C-0.676,33.438,0.164,33.862,0,35.215"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 6.7 KiB |
|
@ -0,0 +1,25 @@
|
|||
.. Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht
|
||||
|
||||
Distributed under the terms of the BSD 3-Clause License.
|
||||
|
||||
The full license is in the file LICENSE, distributed with this software.
|
||||
|
||||
|
||||
Design Patterns
|
||||
===============
|
||||
|
||||
Hierarchy Generator
|
||||
-------------------
|
||||
|
||||
TODO
|
||||
|
||||
Multimethods
|
||||
------------
|
||||
|
||||
TODO
|
||||
|
||||
Visitor
|
||||
-------
|
||||
|
||||
TODO
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
.. Copyright (c) 2017, Johan Mabille and Sylvain Corlay
|
||||
|
||||
Distributed under the terms of the BSD 3-Clause License.
|
||||
|
||||
The full license is in the file LICENSE, distributed with this software.
|
||||
|
||||
.. image:: xtl.svg
|
||||
:alt: xtl
|
||||
|
||||
Basic tools (containers, algorithms) used by other quantstack packages
|
||||
|
||||
Introduction
|
||||
------------
|
||||
|
||||
`xtl` gathers generic purpose algorithms and containers that are used by
|
||||
the `xtensor` stack and the `xeus` stack.
|
||||
|
||||
Some of the features are C++14 backport of C++17 classes and algorithms,
|
||||
such as `variant` or `any`.
|
||||
|
||||
Licensing
|
||||
---------
|
||||
|
||||
We use a shared copyright model that enables all contributors to maintain the
|
||||
copyright on their contributions.
|
||||
|
||||
This software is licensed under the BSD-3-Clause license. See the LICENSE file for details.
|
||||
|
||||
.. toctree::
|
||||
:caption: INSTALLATION
|
||||
:maxdepth: 2
|
||||
|
||||
installation
|
||||
changelog
|
||||
|
||||
.. toctree::
|
||||
:caption: USAGE
|
||||
:maxdepth: 2
|
||||
|
||||
basic_types
|
||||
containers
|
||||
meta_programming
|
||||
design_patterns
|
||||
miscellaneous
|
||||
|
||||
.. toctree::
|
||||
:caption: DEVELOPER ZONE
|
||||
|
||||
build-options
|
||||
releasing
|
|
@ -0,0 +1,75 @@
|
|||
.. Copyright (c) 2017, Johan Mabille and Sylvain Corlay
|
||||
|
||||
Distributed under the terms of the BSD 3-Clause License.
|
||||
|
||||
The full license is in the file LICENSE, distributed with this software.
|
||||
|
||||
|
||||
.. raw:: html
|
||||
|
||||
<style>
|
||||
.rst-content .section>img {
|
||||
width: 30px;
|
||||
margin-bottom: 0;
|
||||
margin-top: 0;
|
||||
margin-right: 15px;
|
||||
margin-left: 15px;
|
||||
float: left;
|
||||
}
|
||||
</style>
|
||||
|
||||
Installation
|
||||
============
|
||||
|
||||
Although ``xtl`` is a header-only library, we provide standardized means to install it, with package managers or with cmake.
|
||||
|
||||
Besides the xtl headers, all these methods place the ``cmake`` project configuration file in the right location so that third-party projects can use cmake's ``find_package`` to locate xtl headers.
|
||||
|
||||
.. image:: conda.svg
|
||||
|
||||
Using the conda package
|
||||
-----------------------
|
||||
|
||||
A package for xtl is available on the conda package manager.
|
||||
|
||||
.. code::
|
||||
|
||||
conda install -c conda-forge xtl
|
||||
|
||||
.. image:: spack.svg
|
||||
|
||||
Using the Spack package
|
||||
-----------------------
|
||||
|
||||
A package for xtl is available on the Spack package manager.
|
||||
|
||||
.. code::
|
||||
|
||||
spack install xtl
|
||||
spack load xtl
|
||||
|
||||
.. image:: cmake.svg
|
||||
|
||||
From source with cmake
|
||||
----------------------
|
||||
|
||||
You can also install ``xtl`` from source with cmake. On Unix platforms, from the source directory:
|
||||
|
||||
.. code::
|
||||
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -DCMAKE_INSTALL_PREFIX=/path/to/prefix ..
|
||||
make install
|
||||
|
||||
On Windows platforms, from the source directory:
|
||||
|
||||
.. code::
|
||||
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -G "NMake Makefiles" -DCMAKE_INSTALL_PREFIX=/path/to/prefix ..
|
||||
nmake
|
||||
nmake install
|
||||
|
||||
See the section of the documentation on :doc:`build-options`, for more details on how to cmake options.
|
|
@ -0,0 +1,24 @@
|
|||
.. Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht
|
||||
|
||||
Distributed under the terms of the BSD 3-Clause License.
|
||||
|
||||
The full license is in the file LICENSE, distributed with this software.
|
||||
|
||||
Meta Programming
|
||||
================
|
||||
|
||||
xclosure
|
||||
--------
|
||||
|
||||
TODO
|
||||
|
||||
xtype_traits
|
||||
------------
|
||||
|
||||
TODO
|
||||
|
||||
type vector
|
||||
-----------
|
||||
|
||||
TODO
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
.. Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht
|
||||
|
||||
Distributed under the terms of the BSD 3-Clause License.
|
||||
|
||||
The full license is in the file LICENSE, distributed with this software.
|
||||
|
||||
Miscellaneous
|
||||
=============
|
||||
|
||||
Base 64 encoding
|
||||
----------------
|
||||
|
||||
TODO
|
||||
|
||||
xhash
|
||||
-----
|
||||
|
||||
TODO
|
||||
|
||||
endianness
|
||||
----------
|
||||
|
||||
TODO
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Generator: Adobe Illustrator 19.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
version="1.1"
|
||||
id="Calque_1"
|
||||
x="0px"
|
||||
y="0px"
|
||||
viewBox="0 0 408.70001 84.5"
|
||||
xml:space="preserve"
|
||||
inkscape:version="0.91 r13725"
|
||||
sodipodi:docname="quantstack-white.svg"
|
||||
width="408.70001"
|
||||
height="84.5"><metadata
|
||||
id="metadata9"><rdf:RDF><cc:Work
|
||||
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
|
||||
id="defs7" /><sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1847"
|
||||
inkscape:window-height="1056"
|
||||
id="namedview5"
|
||||
showgrid="false"
|
||||
fit-margin-top="0"
|
||||
fit-margin-left="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-bottom="0"
|
||||
inkscape:zoom="0.69383003"
|
||||
inkscape:cx="204.25"
|
||||
inkscape:cy="41.75"
|
||||
inkscape:window-x="73"
|
||||
inkscape:window-y="24"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="Calque_1" /><path
|
||||
d="m 85.3,16 c 1.2,0.6 2.4,1.3 3.4,2.2 l 0,22.2 c 0,9.2 -1.8,19.7 -14.2,19.7 l -1.9,0 C 60.1,60.1 58.4,49.6 58.4,40.4 l 0,-22.2 c 1,-0.9 2.2,-1.6 3.4,-2.2 l 0,23.4 c 0,10.4 1.5,17.7 11.4,17.7 l 0.9,0 c 9.8,0 11.4,-7.3 11.4,-17.7 L 85.5,16 Z M 133,38.1 c 0,15 -5.1,22.1 -18.1,22.1 -0.1,0 -0.6,0 -0.7,0 -11,0 -14.2,-5.1 -14.2,-12.4 0,-10.2 9.7,-12.6 29.5,-13.4 -0.6,-9.3 -3.7,-15.2 -14.6,-15.2 -3,0 -5.8,0.5 -8.6,1.8 l -1.5,-2.9 c 3.3,-1.7 6.7,-2.1 10.1,-2.1 13,0 18.1,7 18.1,22.1 z m -3.4,-0.7 c -16.6,0.8 -26.1,2.2 -26.1,10.5 0,2.8 0.5,4.9 1.9,6.4 0.4,0.5 1,0.9 1.7,1.2 2.6,1.1 5.2,1.5 7.9,1.5 12.2,0 14.7,-7.4 14.7,-18.9 -0.1,-0.3 -0.1,-0.5 -0.1,-0.7 z m 201.7,0.7 c 0,15 -5.1,22.1 -18.1,22.1 -0.1,0 -0.6,0 -0.7,0 -11,0 -14.2,-5.1 -14.2,-12.4 0,-10.2 9.7,-12.6 29.5,-13.4 -0.6,-9.3 -3.7,-15.2 -14.6,-15.2 -3,0 -5.8,0.5 -8.6,1.8 l -1.5,-2.9 c 3.3,-1.7 6.7,-2.1 10.1,-2.1 13,0 18.1,7 18.1,22.1 z m -3.4,-0.7 c -16.6,0.8 -26.1,2.2 -26.1,10.5 0,2.8 0.5,4.9 1.9,6.4 0.4,0.5 1,0.9 1.7,1.2 2.6,1.1 5.2,1.5 7.9,1.5 12.2,0 14.7,-7.4 14.7,-18.9 -0.1,-0.3 -0.1,-0.5 -0.1,-0.7 z M 57.2,82.2 c -0.9,0.9 -1.8,1.7 -2.9,2.3 C 45,79.7 38.3,71.4 34.9,60.6 31.7,62.2 27.8,63 23.1,63 6.5,63 0,53.3 0,32.3 0,11.4 6.5,1.6 23.1,1.6 c 16.6,0 23.1,9.7 23.1,30.7 0,13 -2.5,21.6 -8.4,26.4 3.2,10.9 10,19 19.4,23.5 z M 42.7,32.3 C 42.7,15.9 39.4,4.8 23,4.8 6.6,4.8 3.3,15.8 3.3,32.3 c 0,16.4 3.3,27.5 19.7,27.5 16.4,0 19.7,-11 19.7,-27.5 z m 366,-10.4 C 408,21 407.2,20.2 406.3,19.5 l -18.3,18.2 0,-22 -0.4,0 c -1.1,0.2 -2,0.5 -3,0.8 l 0,42.6 c 1.1,0.4 2.2,0.6 3.4,0.9 l 0,-21.3 17.8,17.8 c 0.9,-0.7 1.7,-1.4 2.5,-2.3 l -16,-16 16.4,-16.3 z M 360.6,57 c -12.2,0 -14.7,-7.4 -14.7,-18.9 0,-11.5 2.5,-18.9 14.7,-18.9 3.1,0 6,0.5 8.8,1.9 l 1.5,-2.9 c -3.4,-1.7 -6.9,-2.1 -10.2,-2.1 -13,0 -18.1,7 -18.1,22.1 0,15 5.1,22.1 18.1,22.1 3.4,0 6.9,-0.4 10.3,-2.1 l -1.5,-2.9 c -3,1.2 -5.9,1.7 -8.9,1.7 z m -198,-41.1 -1.9,0 c -12.5,0 -14.2,10.5 -14.2,19.7 l 0,22.2 c 1,0.9 2.2,1.6 3.4,2.2 l 0,-23.3 c 0,-10.4 1.5,-17.7 11.4,-17.7 l 0.9,0 c 9.8,0 11.4,7.3 11.4,17.7 l 0,23.4 c 1.2,-0.6 2.4,-1.3 3.4,-2.2 l 0,-22.2 c -0.2,-9.3 -2,-19.8 -14.4,-19.8 z m 127.7,4.3 -1.6,-3.1 -10.4,0 0,-10.9 -3.3,0 0,10.8 -10.5,0 -1.6,3.1 12.1,0 c 0,0 0,22.4 0,23.7 l 0,0 c -0.1,2.6 0.3,5.1 1.2,7.3 0,0.1 1,2.2 2.6,4.1 0.8,0.9 2.4,2.3 4.6,3.8 l 1.5,-3.1 c -1.7,-1.2 -2.9,-2.2 -3.5,-2.9 -1.3,-1.5 -2,-3.2 -2,-3.2 -0.7,-1.6 -1,-3.3 -1,-5 0,-1.2 0,-24.7 0,-24.7 l 11.9,0 z M 197.8,6 l -3.3,0 0,10.8 -12,0 1.6,3.1 10.4,0 c 0,0 0,12.2 0,13.5 l 0,0 c -0.1,2.6 0.3,5.1 1.2,7.3 0,0.1 1,2.2 2.6,4.1 0.8,0.9 2.3,2.2 4.4,3.7 l 1.6,-3.1 c -1.7,-1.2 -2.9,-2.2 -3.4,-2.9 -1.3,-1.5 -2,-3.2 -2,-3.2 -0.7,-1.6 -1,-3.3 -1,-5 0,-1.2 0,-14.5 0,-14.5 l 10.4,0 1.6,-3.1 -12.1,0 0,-10.7 z m 40.3,22.2 c -1.9,-0.7 -3.6,-1.3 -5.3,-2.1 l 0,0 c -5.1,-2.1 -8.7,-4.8 -8.7,-10.8 0,-9.2 6.4,-12.1 14.5,-12.1 3.8,0 7.5,0.4 11.2,1.7 L 251.3,2 c -4,-1.5 -8.3,-2 -12.8,-2 -9.4,0 -17.7,4.1 -17.7,15.4 0,6.7 3.4,10.4 8.6,12.9 l 0,0 c 0.8,0.3 1.4,0.6 2.1,0.9 0,0 0,0 0,0 l 0,0 c 1.9,0.8 3.3,1.4 5.1,2 8.4,3 12.3,3.5 15.1,6.6 0.2,0.2 4.1,4.8 3.1,10.4 -0.5,2.9 -2.2,5.5 -4.9,7.8 -6.2,5.1 -15.9,4 -25.2,0.9 l -1.6,3.1 c 5.1,1.8 10.4,3 15.4,3 5.1,0 9.7,-1.2 13.5,-4.3 4.2,-3.5 5.7,-7.2 6.1,-9.8 1.3,-7.1 -3.3,-12.6 -3.8,-13.2 -2.7,-2.9 -7.6,-4.4 -16.2,-7.5 z"
|
||||
id="path3"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#ffffff" /></svg>
|
After Width: | Height: | Size: 4.9 KiB |
|
@ -0,0 +1,30 @@
|
|||
.. Copyright (c) 2017, Johan Mabille and Sylvain Corlay
|
||||
|
||||
Distributed under the terms of the BSD 3-Clause License.
|
||||
|
||||
The full license is in the file LICENSE, distributed with this software.
|
||||
|
||||
Releasing xtl
|
||||
=============
|
||||
|
||||
Releasing a new version
|
||||
-----------------------
|
||||
|
||||
From the relevant branch of xtl
|
||||
|
||||
- Make sure that you are in sync with the master branch of the upstream remote.
|
||||
- In file ``xtl_config.hpp``, set the macros for ``XTL_VERSION_MAJOR``, ``XTL_VERSION_MINOR`` and ``XTL_VERSION_PATCH`` to the desired values.
|
||||
- In file ``README.md``, modify the binder link to point to the new release.
|
||||
- Stage the changes (``git add``), commit the changes (``git commit``) and add a tag of the form ``Major.minor.patch``. It is important to not add any other content to the tag name.
|
||||
- Push the new commit and tag to the main repository. (``git push``, and ``git push --tags``)
|
||||
|
||||
Updating the conda-forge recipe
|
||||
-------------------------------
|
||||
|
||||
xtl has been packaged for the conda package manager. Once the new tag has been pushed on GitHub, edit the conda-forge recipe for xtl in the following fashion:
|
||||
|
||||
- Update the version number to the new ``Major.minor.patch``.
|
||||
- Set the build number to ``0``.
|
||||
- Update the hash of the source tarball.
|
||||
- Check for the versions of the dependencies.
|
||||
- Optionally, rerender the conda-forge feedstock.
|
|
@ -0,0 +1,61 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<svg width="256" height="256"
|
||||
viewBox="-128 -128 256 256"
|
||||
version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:ev="http://www.w3.org/2001/xml-events">
|
||||
|
||||
<style>
|
||||
.diamond { fill:#0f3a80; }
|
||||
circle.back { fill:#ffa600; stroke:#0f3a80; stroke-width:6; }
|
||||
circle.front { fill:#ffffff; stroke:#0f3a80; stroke-width:6; }
|
||||
line.back { stroke:#ffa600; stroke-width:7; }
|
||||
line.front { stroke:#ffffff; stroke-width:7; }
|
||||
line.shadow { stroke:#0f3a80; stroke-width:7; }
|
||||
</style>
|
||||
|
||||
<defs>
|
||||
<!-- need two arrows b/c we can't sync color with the marked element -->
|
||||
<marker id="barrow" markerWidth="4" markerHeight="3" refX=".05" refY="1.5"
|
||||
orient="auto" markerUnits="strokeWidth">
|
||||
<path d="M0,0 L0,3 L4,1.5 z" fill="#ffa600"/>
|
||||
</marker>
|
||||
<marker id="farrow" markerWidth="4" markerHeight="3" refX=".05" refY="1.5"
|
||||
orient="auto" markerUnits="strokeWidth">
|
||||
<path d="M0,0 L0,3 L4,1.5 z" fill="#ffffff"/>
|
||||
</marker>
|
||||
</defs>
|
||||
|
||||
<!-- rounded diamond shape -->
|
||||
<rect x="-97" y="-97" width="194" height="194" rx="26" ry="26"
|
||||
transform="rotate(45)" class="diamond"/>
|
||||
|
||||
<!-- background dependency structure -->
|
||||
<line x1="-11" y1="-80" x2="-11" y2="-29" transform="rotate(42 -11 -80)"
|
||||
class="back" marker-end="url(#barrow)"/>
|
||||
<line x1="-80" y1="0" x2="-80" y2="57" transform="rotate(-45 -80 0)"
|
||||
class="back" marker-end="url(#barrow)"/>
|
||||
<line x1="-11" y1="-80" x2="-11" y2="28" class="back"
|
||||
marker-end="url(#barrow)"/>
|
||||
|
||||
<circle cx="-11" cy="-80" r="23" class="back"/>
|
||||
<circle cx="0" cy="80" r="23" class="back"/>
|
||||
<circle cx="-80" cy="0" r="23" class="back"/>
|
||||
|
||||
<!-- foreground dependency structure -->
|
||||
<line x1="18" y1="-80" x2="18" y2="0" transform="rotate(42 17 -80)"
|
||||
class="shadow"/>
|
||||
<line x1="13" y1="-80" x2="13" y2="-5" transform="rotate(42 11 -80)"
|
||||
class="front" marker-end="url(#farrow)"/>
|
||||
|
||||
<line x1="11" y1="-80" x2="11" y2="-29" transform="rotate(-42 11 -80)"
|
||||
class="front" marker-end="url(#farrow)"/>
|
||||
<line x1="80" y1="0" x2="80" y2="57" transform="rotate(45 80 0)"
|
||||
class="front" marker-end="url(#farrow)"/>
|
||||
<line x1="11" y1="-80" x2="11" y2="28" class="front"
|
||||
marker-end="url(#farrow)"/>
|
||||
|
||||
<circle cx="11" cy="-80" r="23" class="front"/>
|
||||
<circle cx="80" cy="0" r="23" class="front"/>
|
||||
</svg>
|
After Width: | Height: | Size: 2.4 KiB |
|
@ -0,0 +1,70 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Generator: Adobe Illustrator 21.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
version="1.1"
|
||||
id="Calque_1"
|
||||
x="0px"
|
||||
y="0px"
|
||||
viewBox="0 0 86.783217 46.600001"
|
||||
width="278.74695"
|
||||
height="149.678801"
|
||||
xml:space="preserve"
|
||||
inkscape:version="0.91 r13725"
|
||||
sodipodi:docname="xtl.svg"><metadata
|
||||
id="metadata30"><rdf:RDF><cc:Work
|
||||
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
|
||||
id="defs28" /><sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1617"
|
||||
inkscape:window-height="783"
|
||||
id="namedview26"
|
||||
showgrid="false"
|
||||
fit-margin-top="0"
|
||||
fit-margin-left="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-bottom="0"
|
||||
inkscape:zoom="7.6277944"
|
||||
inkscape:cx="52.210005"
|
||||
inkscape:cy="19.495744"
|
||||
inkscape:window-x="299"
|
||||
inkscape:window-y="135"
|
||||
inkscape:window-maximized="0"
|
||||
inkscape:current-layer="Calque_1" /><style
|
||||
type="text/css"
|
||||
id="style20">
|
||||
.st0{fill:#7FD787;}
|
||||
.st1{opacity:0.28;fill:#7FD787;enable-background:new ;}
|
||||
</style><path
|
||||
class="st0"
|
||||
d="m 73.8,14.700001 0,0 0,0 z M 66.1,35.5 C 65.6,34.400001 65.4,33.200001 65.4,32 l 0,-17.399999 8.4,0 -1.1,-2.1 -7.3,0 0,-7.700001 -2.4,0 0,7.600001 -7.4,0 -1.1,2.2 8.5,0 L 63,31.3 c -0.1,1.8 0.2,3.6 0.8,5.1 0,0.1 0.7,1.5 1.8,2.9 0.6,0.6 1.7,1.6 3.2,2.7 l 1.1,-2.2 c -1.2,-0.8 -2,-1.5 -2.5,-2 -0.8,-1.2 -1.3,-2.3 -1.3,-2.3 z M 39.2,4.5 c -1.5,0.9 -2.6,2.1 -3.5,3.4 -0.4,0.7000004 -6.6,9.900001 -10.1,15.2 -2.9,4.400001 -10.3,15.5 -10.8,16.200001 -1.2,2 -2.9,3.799999 -4.8,5.1 0,0.1 -2.1,1.3 -4.6,2.1 -0.2,0 -0.4,0.1 -0.5,0.1 l 36.8,0 c -0.1,0 -0.2,-0.1 -0.4,-0.1 -2.5,-0.8 -4.5,-2 -4.6,-2.1 -1.9,-1.3 -3.6,-3.1 -4.8,-5.1 L 23.3,26.4 c 0.8,-1.199999 1.5,-2.3 2.1,-3.1 0,0.1 0.1,0.1 0.1,0.2 3.5,5.3 9.7,14.5 10.1,15.200001 0.9,1.299999 2,2.5 3.5,3.399999 0,0 1.5,1 3.5,1.600001 0.8,0.299999 2.2,0.5 4,0.7 l 0,2.1 0.1,0 L 46.7,2.2 c -1.8,0.2 -3.2,0.4 -4,0.7 -2,0.6 -3.5,1.6 -3.5,1.6 z M 11,38.800001 C 11.4,38.1 17.6,28.9 21.1,23.6 24,19.1 31.4,8.1 31.9,7.3 c 1.2,-2 2.9,-3.8 4.8,-5.1 0,-0.1 2.1,-1.3 4.6,-2.1 0.2,0 0.4,-0.1 0.5,-0.1 L 5,0 c 0.1,0 0.3,0.1 0.4,0.1 2.5,0.8 4.5,2 4.6,2.1 1.9,1.3 3.6,3.1 4.8,5.1 l 8.6,12.900001 c -0.8,1.199999 -1.5,2.3 -2.1,3.1 0,-0.1 -0.1,-0.1 -0.1,-0.200001 C 17.6,17.9 11.4,8.6000004 11,7.9 10.1,6.6 9,5.4 7.5,4.5 7.5,4.5 6,3.5 4,2.9 3.2,2.6 1.8,2.4 0,2.2 l 0,42.4 c 1.8,-0.199999 3.2,-0.399999 4,-0.699999 2,-0.6 3.5,-1.6 3.5,-1.6 1.5,-1.1 2.7,-2.200001 3.5,-3.5 z"
|
||||
id="path22"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#d77f7f;fill-opacity:1"
|
||||
sodipodi:nodetypes="cccccsccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc" /><path
|
||||
class="st1"
|
||||
d="m 25.4,23.300001 c -0.6,0.8 -1.3,1.9 -2.1,3.1 3.4,5.1 8.1,12.3 8.6,12.9 1.2,2 2.9,3.799999 4.8,5.1 0,0.1 2.1,1.3 4.6,2.1 0.2,0 0.4,0.1 0.5,0.1 l 4.8,0 0,-2.2 c -1.8,-0.2 -3.2,-0.400001 -4,-0.7 C 40.6,43.1 39.1,42.1 39.1,42.1 37.6,41.200001 36.5,40 35.6,38.700001 35.2,38 29,28.800001 25.5,23.500001 l 0,0 c 0,0 0,-0.100001 -0.1,-0.2 M 4.8,0 0,0 0,2.2 c 1.8,0.2 3.2,0.4 4,0.7 2,0.6 3.5,1.6 3.5,1.6 1.5,0.9 2.6,2.1 3.5,3.4 0.4,0.7000004 6.6,9.900001 10.1,15.2 l 0,0 c 0,0.100001 0.1,0.100001 0.1,0.2 0.6,-0.8 1.3,-1.9 2.1,-3.1 C 19.9,15.100001 15.2,7.9 14.7,7.3 13.5,5.3 11.8,3.5 9.9,2.2 9.9,2.1 7.8,0.9 5.3,0.1 5.2,0.1 5,0 4.8,0"
|
||||
id="path24"
|
||||
inkscape:connector-curvature="0"
|
||||
style="opacity:0.28000004;fill:#d77f7f;fill-opacity:1;enable-background:new" /><path
|
||||
inkscape:connector-curvature="0"
|
||||
class="st0"
|
||||
d="m 85.783221,1.2999959 -2.3,0.4 0,31.4000021 c 0,3.9 0.2,7.5 1,10.4 l 2.3,0 c -0.8,-2.9 -1,-6.6 -1,-10.3 z"
|
||||
id="path11"
|
||||
style="fill:#d77f7f;fill-opacity:1"
|
||||
sodipodi:nodetypes="ccsccsc" /></svg>
|
After Width: | Height: | Size: 4.4 KiB |
|
@ -0,0 +1,6 @@
|
|||
name: xtl
|
||||
channels:
|
||||
- conda-forge
|
||||
dependencies:
|
||||
- cmake
|
||||
- nlohmann_json
|
|
@ -0,0 +1,476 @@
|
|||
/***************************************************************************
|
||||
* Copyright (c) Sylvain Corlay and Johan Mabille and Wolf Vollprecht *
|
||||
* Copyright (c) QuantStack *
|
||||
* *
|
||||
* Distributed under the terms of the BSD 3-Clause License. *
|
||||
* *
|
||||
* The full license is in the file LICENSE, distributed with this software. *
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef XTL_ANY_HPP
|
||||
#define XTL_ANY_HPP
|
||||
|
||||
#include <stdexcept>
|
||||
#include <type_traits>
|
||||
#include <typeinfo>
|
||||
|
||||
#include "xtl/xmeta_utils.hpp"
|
||||
|
||||
namespace xtl
|
||||
{
|
||||
/**************************************
|
||||
* Implementation of C++17's std::any *
|
||||
**************************************/
|
||||
|
||||
// Copyright (c) 2016 Denilson das Mercês Amorim
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
class bad_any_cast : public std::bad_cast
|
||||
{
|
||||
public:
|
||||
|
||||
const char* what() const noexcept override
|
||||
{
|
||||
return "bad any cast";
|
||||
}
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
inline static void check_any_cast(const void* p) {
|
||||
if (p == nullptr) {
|
||||
#if defined(XTL_NO_EXCEPTIONS)
|
||||
std::fprintf(stderr, "bad_any_cast\n");
|
||||
std::terminate();
|
||||
#else
|
||||
throw bad_any_cast();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
class any final
|
||||
{
|
||||
public:
|
||||
|
||||
/// Constructs an object of type any with an empty state.
|
||||
any()
|
||||
: vtable(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
/// Constructs an object of type any with an equivalent state as other.
|
||||
any(const any& rhs)
|
||||
: vtable(rhs.vtable)
|
||||
{
|
||||
if (!rhs.empty())
|
||||
{
|
||||
rhs.vtable->copy(rhs.storage, this->storage);
|
||||
}
|
||||
}
|
||||
|
||||
/// Constructs an object of type any with a state equivalent to the original state of other.
|
||||
/// rhs is left in a valid but otherwise unspecified state.
|
||||
any(any&& rhs) noexcept
|
||||
: vtable(rhs.vtable)
|
||||
{
|
||||
if (!rhs.empty())
|
||||
{
|
||||
rhs.vtable->move(rhs.storage, this->storage);
|
||||
rhs.vtable = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
/// Same effect as this->clear().
|
||||
~any()
|
||||
{
|
||||
this->clear();
|
||||
}
|
||||
|
||||
/// Constructs an object of type any that contains an object of type T direct-initialized with std::forward<ValueType>(value).
|
||||
///
|
||||
/// T shall satisfy the CopyConstructible requirements, otherwise the program is ill-formed.
|
||||
/// This is because an `any` may be copy constructed into another `any` at any time, so a copy should always be allowed.
|
||||
template <typename ValueType, typename = typename std::enable_if<!std::is_same<typename std::decay<ValueType>::type, any>::value>::type>
|
||||
any(ValueType&& value)
|
||||
{
|
||||
static_assert(std::is_copy_constructible<typename std::decay<ValueType>::type>::value,
|
||||
"T shall satisfy the CopyConstructible requirements.");
|
||||
this->construct(std::forward<ValueType>(value));
|
||||
}
|
||||
|
||||
/// Has the same effect as any(rhs).swap(*this). No effects if an exception is thrown.
|
||||
any& operator=(const any& rhs)
|
||||
{
|
||||
any(rhs).swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Has the same effect as any(std::move(rhs)).swap(*this).
|
||||
///
|
||||
/// The state of *this is equivalent to the original state of rhs and rhs is left in a valid
|
||||
/// but otherwise unspecified state.
|
||||
any& operator=(any&& rhs) noexcept
|
||||
{
|
||||
any(std::move(rhs)).swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Has the same effect as any(std::forward<ValueType>(value)).swap(*this). No effect if a exception is thrown.
|
||||
///
|
||||
/// T shall satisfy the CopyConstructible requirements, otherwise the program is ill-formed.
|
||||
/// This is because an `any` may be copy constructed into another `any` at any time, so a copy should always be allowed.
|
||||
template <typename ValueType, typename = typename std::enable_if<!std::is_same<typename std::decay<ValueType>::type, any>::value>::type>
|
||||
any& operator=(ValueType&& value)
|
||||
{
|
||||
static_assert(std::is_copy_constructible<typename std::decay<ValueType>::type>::value,
|
||||
"T shall satisfy the CopyConstructible requirements.");
|
||||
any(std::forward<ValueType>(value)).swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// If not empty, destroys the contained object.
|
||||
void clear() noexcept
|
||||
{
|
||||
if (!empty())
|
||||
{
|
||||
this->vtable->destroy(storage);
|
||||
this->vtable = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
/// C++17 equivalent of clear
|
||||
void reset() noexcept
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
/// Returns true if *this has no contained object, otherwise false.
|
||||
bool empty() const noexcept
|
||||
{
|
||||
return this->vtable == nullptr;
|
||||
}
|
||||
|
||||
/// C++17 equivalent of !empty()
|
||||
bool has_value() const noexcept
|
||||
{
|
||||
return !empty();
|
||||
}
|
||||
|
||||
/// If *this has a contained object of type T, typeid(T); otherwise typeid(void).
|
||||
const std::type_info& type() const noexcept
|
||||
{
|
||||
return empty() ? typeid(void) : this->vtable->type();
|
||||
}
|
||||
|
||||
/// Exchange the states of *this and rhs.
|
||||
void swap(any& rhs) noexcept
|
||||
{
|
||||
if (this->vtable != rhs.vtable)
|
||||
{
|
||||
any tmp(std::move(rhs));
|
||||
|
||||
// move from *this to rhs.
|
||||
rhs.vtable = this->vtable;
|
||||
if (this->vtable != nullptr)
|
||||
{
|
||||
this->vtable->move(this->storage, rhs.storage);
|
||||
//this->vtable = nullptr; -- uneeded, see below
|
||||
}
|
||||
|
||||
// move from tmp (previously rhs) to *this.
|
||||
this->vtable = tmp.vtable;
|
||||
if (tmp.vtable != nullptr)
|
||||
{
|
||||
tmp.vtable->move(tmp.storage, this->storage);
|
||||
tmp.vtable = nullptr;
|
||||
}
|
||||
}
|
||||
else // same types
|
||||
{
|
||||
if (this->vtable != nullptr)
|
||||
this->vtable->swap(this->storage, rhs.storage);
|
||||
}
|
||||
}
|
||||
|
||||
private: // Storage and Virtual Method Table
|
||||
|
||||
union storage_union {
|
||||
using stack_storage_t = typename std::aligned_storage<2 * sizeof(void*), std::alignment_of<void*>::value>::type;
|
||||
|
||||
void* dynamic;
|
||||
stack_storage_t stack; // 2 words for e.g. shared_ptr
|
||||
};
|
||||
|
||||
/// Base VTable specification.
|
||||
struct vtable_type
|
||||
{
|
||||
// Note: The caller is responssible for doing .vtable = nullptr after destructful operations
|
||||
// such as destroy() and/or move().
|
||||
|
||||
/// The type of the object this vtable is for.
|
||||
const std::type_info& (*type)() noexcept;
|
||||
|
||||
/// Destroys the object in the union.
|
||||
/// The state of the union after this call is unspecified, caller must ensure not to use src anymore.
|
||||
void (*destroy)(storage_union&) noexcept;
|
||||
|
||||
/// Copies the **inner** content of the src union into the yet unitialized dest union.
|
||||
/// As such, both inner objects will have the same state, but on separate memory locations.
|
||||
void (*copy)(const storage_union& src, storage_union& dest);
|
||||
|
||||
/// Moves the storage from src to the yet unitialized dest union.
|
||||
/// The state of src after this call is unspecified, caller must ensure not to use src anymore.
|
||||
void (*move)(storage_union& src, storage_union& dest) noexcept;
|
||||
|
||||
/// Exchanges the storage between lhs and rhs.
|
||||
void (*swap)(storage_union& lhs, storage_union& rhs) noexcept;
|
||||
};
|
||||
|
||||
/// VTable for dynamically allocated storage.
|
||||
template <typename T>
|
||||
struct vtable_dynamic
|
||||
{
|
||||
static const std::type_info& type() noexcept
|
||||
{
|
||||
return typeid(T);
|
||||
}
|
||||
|
||||
static void destroy(storage_union& storage) noexcept
|
||||
{
|
||||
//assert(reinterpret_cast<T*>(storage.dynamic));
|
||||
delete reinterpret_cast<T*>(storage.dynamic);
|
||||
}
|
||||
|
||||
static void copy(const storage_union& src, storage_union& dest)
|
||||
{
|
||||
dest.dynamic = new T(*reinterpret_cast<const T*>(src.dynamic));
|
||||
}
|
||||
|
||||
static void move(storage_union& src, storage_union& dest) noexcept
|
||||
{
|
||||
dest.dynamic = src.dynamic;
|
||||
src.dynamic = nullptr;
|
||||
}
|
||||
|
||||
static void swap(storage_union& lhs, storage_union& rhs) noexcept
|
||||
{
|
||||
// just exchage the storage pointers.
|
||||
std::swap(lhs.dynamic, rhs.dynamic);
|
||||
}
|
||||
};
|
||||
|
||||
/// VTable for stack allocated storage.
|
||||
template <typename T>
|
||||
struct vtable_stack
|
||||
{
|
||||
static const std::type_info& type() noexcept
|
||||
{
|
||||
return typeid(T);
|
||||
}
|
||||
|
||||
static void destroy(storage_union& storage) noexcept
|
||||
{
|
||||
reinterpret_cast<T*>(&storage.stack)->~T();
|
||||
}
|
||||
|
||||
static void copy(const storage_union& src, storage_union& dest)
|
||||
{
|
||||
new (&dest.stack) T(reinterpret_cast<const T&>(src.stack));
|
||||
}
|
||||
|
||||
static void move(storage_union& src, storage_union& dest) noexcept
|
||||
{
|
||||
// one of the conditions for using vtable_stack is a nothrow move constructor,
|
||||
// so this move constructor will never throw a exception.
|
||||
new (&dest.stack) T(std::move(reinterpret_cast<T&>(src.stack)));
|
||||
destroy(src);
|
||||
}
|
||||
|
||||
static void swap(storage_union& lhs, storage_union& rhs) noexcept
|
||||
{
|
||||
storage_union tmp_storage;
|
||||
move(rhs, tmp_storage);
|
||||
move(lhs, rhs);
|
||||
move(tmp_storage, lhs);
|
||||
}
|
||||
};
|
||||
|
||||
/// Whether the type T must be dynamically allocated or can be stored on the stack.
|
||||
template <typename T>
|
||||
struct requires_allocation : std::integral_constant<bool,
|
||||
!(std::is_nothrow_move_constructible<T>::value // N4562 <20>6.3/3 [any.class]
|
||||
&& sizeof(T) <= sizeof(storage_union::stack) && std::alignment_of<T>::value <= std::alignment_of<storage_union::stack_storage_t>::value)>
|
||||
{
|
||||
};
|
||||
|
||||
/// Returns the pointer to the vtable of the type T.
|
||||
template <typename T>
|
||||
static vtable_type* vtable_for_type()
|
||||
{
|
||||
using VTableType = typename std::conditional<requires_allocation<T>::value, vtable_dynamic<T>, vtable_stack<T>>::type;
|
||||
static vtable_type table = {
|
||||
VTableType::type, VTableType::destroy,
|
||||
VTableType::copy, VTableType::move,
|
||||
VTableType::swap,
|
||||
};
|
||||
return &table;
|
||||
}
|
||||
|
||||
protected:
|
||||
template <typename T>
|
||||
friend const T* any_cast(const any* operand) noexcept;
|
||||
template <typename T>
|
||||
friend T* any_cast(any* operand) noexcept;
|
||||
|
||||
/// Same effect as is_same(this->type(), t);
|
||||
bool is_typed(const std::type_info& t) const
|
||||
{
|
||||
return is_same(this->type(), t);
|
||||
}
|
||||
|
||||
/// Checks if two type infos are the same.
|
||||
///
|
||||
/// If ANY_IMPL_FAST_TYPE_INFO_COMPARE is defined, checks only the address of the
|
||||
/// type infos, otherwise does an actual comparision. Checking addresses is
|
||||
/// only a valid approach when there's no interaction with outside sources
|
||||
/// (other shared libraries and such).
|
||||
static bool is_same(const std::type_info& a, const std::type_info& b)
|
||||
{
|
||||
#ifdef ANY_IMPL_FAST_TYPE_INFO_COMPARE
|
||||
return &a == &b;
|
||||
#else
|
||||
return a == b;
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Casts (with no type_info checks) the storage pointer as const T*.
|
||||
template <typename T>
|
||||
const T* cast() const noexcept
|
||||
{
|
||||
return requires_allocation<typename std::decay<T>::type>::value ? reinterpret_cast<const T*>(storage.dynamic) : reinterpret_cast<const T*>(&storage.stack);
|
||||
}
|
||||
|
||||
/// Casts (with no type_info checks) the storage pointer as T*.
|
||||
template <typename T>
|
||||
T* cast() noexcept
|
||||
{
|
||||
return requires_allocation<typename std::decay<T>::type>::value ? reinterpret_cast<T*>(storage.dynamic) : reinterpret_cast<T*>(&storage.stack);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
storage_union storage; // on offset(0) so no padding for align
|
||||
vtable_type* vtable;
|
||||
|
||||
/// Chooses between stack and dynamic allocation for the type decay_t<ValueType>,
|
||||
/// assigns the correct vtable, and constructs the object on our storage.
|
||||
template <typename ValueType>
|
||||
void construct(ValueType&& value)
|
||||
{
|
||||
using T = typename std::decay<ValueType>::type;
|
||||
|
||||
this->vtable = vtable_for_type<T>();
|
||||
|
||||
return xtl::mpl::static_if<requires_allocation<T>::value>([&](auto self)
|
||||
{
|
||||
self(*this).storage.dynamic = new T(std::forward<ValueType>(value));
|
||||
}, /*else*/ [&](auto self)
|
||||
{
|
||||
new (&self(*this).storage.stack) T(std::forward<ValueType>(value));
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <typename ValueType>
|
||||
inline ValueType any_cast_move_if_true(typename std::remove_reference<ValueType>::type* p, std::true_type)
|
||||
{
|
||||
return std::move(*p);
|
||||
}
|
||||
|
||||
template <typename ValueType>
|
||||
inline ValueType any_cast_move_if_true(typename std::remove_reference<ValueType>::type* p, std::false_type)
|
||||
{
|
||||
return *p;
|
||||
}
|
||||
}
|
||||
|
||||
/// Performs *any_cast<add_const_t<remove_reference_t<ValueType>>>(&operand), or throws bad_any_cast on failure.
|
||||
template <typename ValueType>
|
||||
inline ValueType any_cast(const any& operand)
|
||||
{
|
||||
auto p = any_cast<typename std::add_const<typename std::remove_reference<ValueType>::type>::type>(&operand);
|
||||
detail::check_any_cast(p);
|
||||
return *p;
|
||||
}
|
||||
|
||||
/// Performs *any_cast<remove_reference_t<ValueType>>(&operand), or throws bad_any_cast on failure.
|
||||
template <typename ValueType>
|
||||
inline ValueType any_cast(any& operand)
|
||||
{
|
||||
auto p = any_cast<typename std::remove_reference<ValueType>::type>(&operand);
|
||||
detail::check_any_cast(p);
|
||||
return *p;
|
||||
}
|
||||
|
||||
///
|
||||
/// If ANY_IMPL_ANYCAST_MOVEABLE is not defined, does as N4562 specifies:
|
||||
/// Performs *any_cast<remove_reference_t<ValueType>>(&operand), or throws bad_any_cast on failure.
|
||||
///
|
||||
/// If ANY_IMPL_ANYCAST_MOVEABLE is defined, does as LWG Defect 2509 specifies:
|
||||
/// If ValueType is MoveConstructible and isn't a lvalue reference, performs
|
||||
/// std::move(*any_cast<remove_reference_t<ValueType>>(&operand)), otherwise
|
||||
/// *any_cast<remove_reference_t<ValueType>>(&operand). Throws bad_any_cast on failure.
|
||||
///
|
||||
template <typename ValueType>
|
||||
inline ValueType any_cast(any&& operand)
|
||||
{
|
||||
#ifdef ANY_IMPL_ANY_CAST_MOVEABLE
|
||||
// https://cplusplus.github.io/LWG/lwg-active.html#2509
|
||||
using can_move = std::integral_constant<bool,
|
||||
std::is_move_constructible<ValueType>::value && !std::is_lvalue_reference<ValueType>::value>;
|
||||
#else
|
||||
using can_move = std::false_type;
|
||||
#endif
|
||||
|
||||
auto p = any_cast<typename std::remove_reference<ValueType>::type>(&operand);
|
||||
detail::check_any_cast(p);
|
||||
return detail::any_cast_move_if_true<ValueType>(p, can_move());
|
||||
}
|
||||
|
||||
/// If operand != nullptr && operand->type() == typeid(ValueType), a pointer to the object
|
||||
/// contained by operand, otherwise nullptr.
|
||||
template <typename T>
|
||||
inline const T* any_cast(const any* operand) noexcept
|
||||
{
|
||||
if (operand == nullptr || !operand->is_typed(typeid(T)))
|
||||
return nullptr;
|
||||
else
|
||||
return operand->cast<T>();
|
||||
}
|
||||
|
||||
/// If operand != nullptr && operand->type() == typeid(ValueType), a pointer to the object
|
||||
/// contained by operand, otherwise nullptr.
|
||||
template <typename T>
|
||||
inline T* any_cast(any* operand) noexcept
|
||||
{
|
||||
if (operand == nullptr || !operand->is_typed(typeid(T)))
|
||||
return nullptr;
|
||||
else
|
||||
return operand->cast<T>();
|
||||
}
|
||||
}
|
||||
|
||||
namespace std
|
||||
{
|
||||
inline void swap(xtl::any& lhs, xtl::any& rhs) noexcept
|
||||
{
|
||||
lhs.swap(rhs);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,77 @@
|
|||
/***************************************************************************
|
||||
* Copyright (c) Sylvain Corlay and Johan Mabille and Wolf Vollprecht *
|
||||
* Copyright (c) QuantStack *
|
||||
* *
|
||||
* Distributed under the terms of the BSD 3-Clause License. *
|
||||
* *
|
||||
* The full license is in the file LICENSE, distributed with this software. *
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef XTL_BASE64_HPP
|
||||
#define XTL_BASE64_HPP
|
||||
|
||||
#include <array>
|
||||
#include <cstddef>
|
||||
#include <string>
|
||||
|
||||
#include "xsequence.hpp"
|
||||
|
||||
namespace xtl
|
||||
{
|
||||
inline std::string base64decode(const std::string& input)
|
||||
{
|
||||
std::array<int, 256> T;
|
||||
T.fill(-1);
|
||||
for (std::size_t i = 0; i < 64; ++i)
|
||||
{
|
||||
T[std::size_t("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[i])] = int(i);
|
||||
}
|
||||
|
||||
std::string output;
|
||||
int val = 0;
|
||||
int valb = -8;
|
||||
for (char c : input)
|
||||
{
|
||||
if (T[std::size_t(c)] == -1)
|
||||
{
|
||||
break;
|
||||
}
|
||||
val = (val << 6) + T[std::size_t(c)];
|
||||
valb += 6;
|
||||
if (valb >= 0)
|
||||
{
|
||||
output.push_back(char((val >> valb) & 0xFF));
|
||||
valb -= 8;
|
||||
}
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
inline std::string base64encode(const std::string& input)
|
||||
{
|
||||
std::string output;
|
||||
int val = 0;
|
||||
int valb = -6;
|
||||
for (char sc : input)
|
||||
{
|
||||
unsigned char c = static_cast<unsigned char>(sc);
|
||||
val = (val << 8) + c;
|
||||
valb += 8;
|
||||
while (valb >= 0)
|
||||
{
|
||||
output.push_back("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[(val >> valb) & 0x3F]);
|
||||
valb -= 6;
|
||||
}
|
||||
}
|
||||
if (valb > -6)
|
||||
{
|
||||
output.push_back("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[((val << 8) >> (valb + 8)) & 0x3F]);
|
||||
}
|
||||
while (output.size() % 4)
|
||||
{
|
||||
output.push_back('=');
|
||||
}
|
||||
return output;
|
||||
}
|
||||
}
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,435 @@
|
|||
/***************************************************************************
|
||||
* Copyright (c) Sylvain Corlay and Johan Mabille and Wolf Vollprecht *
|
||||
* Copyright (c) QuantStack *
|
||||
* *
|
||||
* Distributed under the terms of the BSD 3-Clause License. *
|
||||
* *
|
||||
* The full license is in the file LICENSE, distributed with this software. *
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef XTL_CLOSURE_HPP
|
||||
#define XTL_CLOSURE_HPP
|
||||
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#include "xtl_config.hpp"
|
||||
|
||||
namespace xtl
|
||||
{
|
||||
|
||||
#ifdef __cpp_lib_as_const
|
||||
using std::as_const;
|
||||
#else
|
||||
template <class T>
|
||||
constexpr std::add_const_t<T>& as_const(T& t) noexcept
|
||||
{
|
||||
return t;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
constexpr std::add_const_t<T&&>& as_const(T&& t) noexcept = delete;
|
||||
#endif
|
||||
|
||||
/****************
|
||||
* closure_type *
|
||||
****************/
|
||||
|
||||
template <class S>
|
||||
struct closure_type
|
||||
{
|
||||
using underlying_type = std::conditional_t<std::is_const<std::remove_reference_t<S>>::value,
|
||||
const std::decay_t<S>,
|
||||
std::decay_t<S>>;
|
||||
using type = typename std::conditional<std::is_lvalue_reference<S>::value,
|
||||
underlying_type&,
|
||||
underlying_type>::type;
|
||||
};
|
||||
|
||||
template <class S>
|
||||
using closure_type_t = typename closure_type<S>::type;
|
||||
|
||||
template <class S>
|
||||
struct const_closure_type
|
||||
{
|
||||
using underlying_type = std::decay_t<S>;
|
||||
using type = typename std::conditional<std::is_lvalue_reference<S>::value,
|
||||
std::add_const_t<underlying_type>&,
|
||||
underlying_type>::type;
|
||||
};
|
||||
|
||||
template <class S>
|
||||
using const_closure_type_t = typename const_closure_type<S>::type;
|
||||
|
||||
/****************************
|
||||
* ptr_closure_closure_type *
|
||||
****************************/
|
||||
|
||||
template <class S>
|
||||
struct ptr_closure_type
|
||||
{
|
||||
using underlying_type = std::conditional_t<std::is_const<std::remove_reference_t<S>>::value,
|
||||
const std::decay_t<S>,
|
||||
std::decay_t<S>>;
|
||||
using type = std::conditional_t<std::is_lvalue_reference<S>::value,
|
||||
underlying_type*,
|
||||
underlying_type>;
|
||||
};
|
||||
|
||||
template <class S>
|
||||
using ptr_closure_type_t = typename ptr_closure_type<S>::type;
|
||||
|
||||
template <class S>
|
||||
struct const_ptr_closure_type
|
||||
{
|
||||
using underlying_type = const std::decay_t<S>;
|
||||
using type = std::conditional_t<std::is_lvalue_reference<S>::value,
|
||||
underlying_type*,
|
||||
underlying_type>;
|
||||
};
|
||||
|
||||
template <class S>
|
||||
using const_ptr_closure_type_t = typename const_ptr_closure_type<S>::type;
|
||||
|
||||
/********************
|
||||
* xclosure_wrapper *
|
||||
********************/
|
||||
|
||||
template <class CT>
|
||||
class xclosure_wrapper
|
||||
{
|
||||
public:
|
||||
|
||||
using self_type = xclosure_wrapper<CT>;
|
||||
using closure_type = CT;
|
||||
using const_closure_type = std::add_const_t<CT>;
|
||||
using value_type = std::decay_t<CT>;
|
||||
|
||||
using reference = std::conditional_t<
|
||||
std::is_const<std::remove_reference_t<CT>>::value,
|
||||
const value_type&, value_type&
|
||||
>;
|
||||
|
||||
using pointer = std::conditional_t<
|
||||
std::is_const<std::remove_reference_t<CT>>::value,
|
||||
const value_type*, value_type*
|
||||
>;
|
||||
|
||||
xclosure_wrapper(value_type&& e);
|
||||
xclosure_wrapper(reference e);
|
||||
|
||||
xclosure_wrapper(const self_type& rhs) = default;
|
||||
xclosure_wrapper(self_type&& rhs) = default;
|
||||
|
||||
self_type& operator=(const self_type& rhs);
|
||||
self_type& operator=(self_type&& rhs);
|
||||
|
||||
template <class T>
|
||||
self_type& operator=(T&&);
|
||||
|
||||
operator closure_type() noexcept;
|
||||
operator const_closure_type() const noexcept;
|
||||
|
||||
std::add_lvalue_reference_t<closure_type> get() & noexcept;
|
||||
std::add_lvalue_reference_t<std::add_const_t<closure_type>> get() const & noexcept;
|
||||
closure_type get() && noexcept;
|
||||
|
||||
pointer operator&() noexcept;
|
||||
|
||||
bool equal(const self_type& rhs) const;
|
||||
void swap(self_type& rhs);
|
||||
|
||||
private:
|
||||
|
||||
using storing_type = ptr_closure_type_t<CT>;
|
||||
storing_type m_wrappee;
|
||||
|
||||
template <class T>
|
||||
std::enable_if_t<std::is_lvalue_reference<CT>::value, std::add_lvalue_reference_t<std::remove_pointer_t<T>>>
|
||||
deref(T val) const;
|
||||
|
||||
template <class T>
|
||||
std::enable_if_t<!std::is_lvalue_reference<CT>::value, std::add_lvalue_reference_t<T>>
|
||||
deref(T& val) const;
|
||||
|
||||
template <class T>
|
||||
std::enable_if_t<std::is_lvalue_reference<CT>::value, T>
|
||||
get_pointer(T val) const;
|
||||
|
||||
template <class T>
|
||||
std::enable_if_t<!std::is_lvalue_reference<CT>::value, std::add_pointer_t<T>>
|
||||
get_pointer(T& val) const;
|
||||
|
||||
template <class T, class CTA>
|
||||
std::enable_if_t<std::is_lvalue_reference<CT>::value, T>
|
||||
get_storage_init(CTA&& e) const;
|
||||
|
||||
template <class T, class CTA>
|
||||
std::enable_if_t<!std::is_lvalue_reference<CT>::value, T>
|
||||
get_storage_init(CTA&& e) const;
|
||||
};
|
||||
|
||||
// TODO: remove this (backward compatibility)
|
||||
template <class CT>
|
||||
using closure_wrapper = xclosure_wrapper<CT>;
|
||||
|
||||
/********************
|
||||
* xclosure_pointer *
|
||||
********************/
|
||||
|
||||
template <class CT>
|
||||
class xclosure_pointer
|
||||
{
|
||||
public:
|
||||
|
||||
using self_type = xclosure_pointer<CT>;
|
||||
using closure_type = CT;
|
||||
using value_type = std::decay_t<CT>;
|
||||
|
||||
using reference = std::conditional_t<
|
||||
std::is_const<std::remove_reference_t<CT>>::value,
|
||||
const value_type&, value_type&
|
||||
>;
|
||||
|
||||
using const_reference = const value_type&;
|
||||
|
||||
using pointer = std::conditional_t<
|
||||
std::is_const<std::remove_reference_t<CT>>::value,
|
||||
const value_type*, value_type*
|
||||
>;
|
||||
|
||||
xclosure_pointer(value_type&& e);
|
||||
xclosure_pointer(reference e);
|
||||
|
||||
reference operator*() noexcept;
|
||||
const_reference operator*() const noexcept;
|
||||
pointer operator->() const noexcept;
|
||||
|
||||
private:
|
||||
|
||||
using storing_type = closure_type_t<CT>;
|
||||
storing_type m_wrappee;
|
||||
};
|
||||
|
||||
/***********************************
|
||||
* xclosure_wrapper implementation *
|
||||
***********************************/
|
||||
|
||||
template <class CT>
|
||||
inline xclosure_wrapper<CT>::xclosure_wrapper(value_type&& e)
|
||||
: m_wrappee(get_storage_init<storing_type>(std::move(e)))
|
||||
{
|
||||
}
|
||||
|
||||
template <class CT>
|
||||
inline xclosure_wrapper<CT>::xclosure_wrapper(reference e)
|
||||
: m_wrappee(get_storage_init<storing_type>(e))
|
||||
{
|
||||
}
|
||||
|
||||
template <class CT>
|
||||
inline auto xclosure_wrapper<CT>::operator=(const self_type& rhs) -> self_type&
|
||||
{
|
||||
deref(m_wrappee) = deref(rhs.m_wrappee);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class CT>
|
||||
inline auto xclosure_wrapper<CT>::operator=(self_type&& rhs) -> self_type&
|
||||
{
|
||||
swap(rhs);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class CT>
|
||||
template <class T>
|
||||
inline auto xclosure_wrapper<CT>::operator=(T&& t) -> self_type&
|
||||
{
|
||||
deref(m_wrappee) = std::forward<T>(t);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class CT>
|
||||
inline xclosure_wrapper<CT>::operator typename xclosure_wrapper<CT>::closure_type() noexcept
|
||||
{
|
||||
return deref(m_wrappee);
|
||||
}
|
||||
|
||||
template <class CT>
|
||||
inline xclosure_wrapper<CT>::operator typename xclosure_wrapper<CT>::const_closure_type() const noexcept
|
||||
{
|
||||
return deref(m_wrappee);
|
||||
}
|
||||
|
||||
template <class CT>
|
||||
inline auto xclosure_wrapper<CT>::get() & noexcept -> std::add_lvalue_reference_t<closure_type>
|
||||
{
|
||||
return deref(m_wrappee);
|
||||
}
|
||||
|
||||
template <class CT>
|
||||
inline auto xclosure_wrapper<CT>::get() const & noexcept -> std::add_lvalue_reference_t<std::add_const_t<closure_type>>
|
||||
{
|
||||
return deref(m_wrappee);
|
||||
}
|
||||
|
||||
template <class CT>
|
||||
inline auto xclosure_wrapper<CT>::get() && noexcept -> closure_type
|
||||
{
|
||||
return deref(m_wrappee);
|
||||
}
|
||||
|
||||
template <class CT>
|
||||
inline auto xclosure_wrapper<CT>::operator&() noexcept -> pointer
|
||||
{
|
||||
return get_pointer(m_wrappee);
|
||||
}
|
||||
|
||||
template <class CT>
|
||||
template <class T>
|
||||
inline std::enable_if_t<std::is_lvalue_reference<CT>::value, std::add_lvalue_reference_t<std::remove_pointer_t<T>>>
|
||||
xclosure_wrapper<CT>::deref(T val) const
|
||||
{
|
||||
return *val;
|
||||
}
|
||||
|
||||
template <class CT>
|
||||
template <class T>
|
||||
inline std::enable_if_t<!std::is_lvalue_reference<CT>::value, std::add_lvalue_reference_t<T>>
|
||||
xclosure_wrapper<CT>::deref(T& val) const
|
||||
{
|
||||
return val;
|
||||
}
|
||||
|
||||
template <class CT>
|
||||
template <class T>
|
||||
inline std::enable_if_t<std::is_lvalue_reference<CT>::value, T>
|
||||
xclosure_wrapper<CT>::get_pointer(T val) const
|
||||
{
|
||||
return val;
|
||||
}
|
||||
|
||||
template <class CT>
|
||||
template <class T>
|
||||
inline std::enable_if_t<!std::is_lvalue_reference<CT>::value, std::add_pointer_t<T>>
|
||||
xclosure_wrapper<CT>::get_pointer(T& val) const
|
||||
{
|
||||
return &val;
|
||||
}
|
||||
|
||||
template <class CT>
|
||||
template <class T, class CTA>
|
||||
inline std::enable_if_t<std::is_lvalue_reference<CT>::value, T>
|
||||
xclosure_wrapper<CT>::get_storage_init(CTA&& e) const
|
||||
{
|
||||
return &e;
|
||||
}
|
||||
|
||||
template <class CT>
|
||||
template <class T, class CTA>
|
||||
inline std::enable_if_t<!std::is_lvalue_reference<CT>::value, T>
|
||||
xclosure_wrapper<CT>::get_storage_init(CTA&& e) const
|
||||
{
|
||||
return e;
|
||||
}
|
||||
|
||||
template <class CT>
|
||||
inline bool xclosure_wrapper<CT>::equal(const self_type& rhs) const
|
||||
{
|
||||
return deref(m_wrappee) == rhs.deref(rhs.m_wrappee);
|
||||
}
|
||||
|
||||
template <class CT>
|
||||
inline void xclosure_wrapper<CT>::swap(self_type& rhs)
|
||||
{
|
||||
using std::swap;
|
||||
swap(deref(m_wrappee), deref(rhs.m_wrappee));
|
||||
}
|
||||
|
||||
template <class CT>
|
||||
inline bool operator==(const xclosure_wrapper<CT>& lhs, const xclosure_wrapper<CT>& rhs)
|
||||
{
|
||||
return lhs.equal(rhs);
|
||||
}
|
||||
|
||||
template <class CT>
|
||||
inline bool operator!=(const xclosure_wrapper<CT>& lhs, const xclosure_wrapper<CT>& rhs)
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
template <class CT>
|
||||
inline void swap(xclosure_wrapper<CT>& lhs, xclosure_wrapper<CT>& rhs)
|
||||
{
|
||||
lhs.swap(rhs);
|
||||
}
|
||||
|
||||
/***********************************
|
||||
* xclosure_pointer implementation *
|
||||
***********************************/
|
||||
|
||||
template <class CT>
|
||||
inline xclosure_pointer<CT>::xclosure_pointer(value_type&& e)
|
||||
: m_wrappee(std::move(e))
|
||||
{
|
||||
}
|
||||
|
||||
template <class CT>
|
||||
inline xclosure_pointer<CT>::xclosure_pointer(reference e)
|
||||
: m_wrappee(e)
|
||||
{
|
||||
}
|
||||
|
||||
template <class CT>
|
||||
inline auto xclosure_pointer<CT>::operator*() noexcept -> reference
|
||||
{
|
||||
return m_wrappee;
|
||||
}
|
||||
|
||||
template <class CT>
|
||||
inline auto xclosure_pointer<CT>::operator*() const noexcept -> const_reference
|
||||
{
|
||||
return m_wrappee;
|
||||
}
|
||||
|
||||
template <class CT>
|
||||
inline auto xclosure_pointer<CT>::operator->() const noexcept -> pointer
|
||||
{
|
||||
return const_cast<pointer>(std::addressof(m_wrappee));
|
||||
}
|
||||
|
||||
/*****************************
|
||||
* closure and const_closure *
|
||||
*****************************/
|
||||
|
||||
template <class T>
|
||||
inline decltype(auto) closure(T&& t)
|
||||
{
|
||||
return xclosure_wrapper<closure_type_t<T>>(std::forward<T>(t));
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline decltype(auto) const_closure(T&& t)
|
||||
{
|
||||
return xclosure_wrapper<const_closure_type_t<T>>(std::forward<T>(t));
|
||||
}
|
||||
|
||||
/********************************************
|
||||
* closure_pointer et const_closure_pointer *
|
||||
********************************************/
|
||||
|
||||
template <class T>
|
||||
inline auto closure_pointer(T&& t)
|
||||
{
|
||||
return xclosure_pointer<closure_type_t<T>>(std::forward<T>(t));
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline auto const_closure_pointer(T&& t)
|
||||
{
|
||||
return xclosure_pointer<const_closure_type_t<T>>(std::forward<T>(t));
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,578 @@
|
|||
/***************************************************************************
|
||||
* Copyright (c) Johan Mabille, Sylvain Corlay and Wolf Vollprecht *
|
||||
* Copyright (c) QuantStack *
|
||||
* *
|
||||
* Distributed under the terms of the BSD 3-Clause License. *
|
||||
* *
|
||||
* The full license is in the file LICENSE, distributed with this software. *
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef XTL_XCOMPLEX_SEQUENCE_HPP
|
||||
#define XTL_XCOMPLEX_SEQUENCE_HPP
|
||||
|
||||
#include <array>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
#include "xclosure.hpp"
|
||||
#include "xcomplex.hpp"
|
||||
#include "xiterator_base.hpp"
|
||||
#include "xsequence.hpp"
|
||||
|
||||
namespace xtl
|
||||
{
|
||||
/************************************
|
||||
* Optimized 1-D xcomplex container *
|
||||
************************************/
|
||||
|
||||
template <class IT, bool ieee_compliant>
|
||||
class xcomplex_iterator;
|
||||
|
||||
template <class C, bool ieee_compliant>
|
||||
class xcomplex_sequence
|
||||
{
|
||||
public:
|
||||
|
||||
using container_type = C;
|
||||
using cvt = typename C::value_type;
|
||||
|
||||
using value_type = xcomplex<cvt, cvt, ieee_compliant>;
|
||||
using reference = xcomplex<cvt&, cvt&, ieee_compliant>;
|
||||
using const_reference = xcomplex<const cvt&, const cvt&, ieee_compliant>;
|
||||
using pointer = xclosure_pointer<reference>;
|
||||
using const_pointer = xclosure_pointer<const_reference>;
|
||||
using size_type = typename container_type::size_type;
|
||||
using difference_type = typename container_type::difference_type;
|
||||
|
||||
using iterator = xcomplex_iterator<typename C::iterator, ieee_compliant>;
|
||||
using const_iterator = xcomplex_iterator<typename C::const_iterator, ieee_compliant>;
|
||||
using reverse_iterator = xcomplex_iterator<typename C::reverse_iterator, ieee_compliant>;
|
||||
using const_reverse_iterator = xcomplex_iterator<typename C::const_reverse_iterator, ieee_compliant>;
|
||||
|
||||
bool empty() const noexcept;
|
||||
size_type size() const noexcept;
|
||||
size_type max_size() const noexcept;
|
||||
|
||||
reference at(size_type i);
|
||||
const_reference at(size_type i) const;
|
||||
|
||||
reference operator[](size_type i);
|
||||
const_reference operator[](size_type i) const;
|
||||
|
||||
reference front();
|
||||
const_reference front() const;
|
||||
|
||||
reference back();
|
||||
const_reference back() const;
|
||||
|
||||
iterator begin() noexcept;
|
||||
iterator end() noexcept;
|
||||
|
||||
const_iterator begin() const noexcept;
|
||||
const_iterator end() const noexcept;
|
||||
const_iterator cbegin() const noexcept;
|
||||
const_iterator cend() const noexcept;
|
||||
|
||||
reverse_iterator rbegin() noexcept;
|
||||
reverse_iterator rend() noexcept;
|
||||
|
||||
const_reverse_iterator rbegin() const noexcept;
|
||||
const_reverse_iterator rend() const noexcept;
|
||||
const_reverse_iterator crbegin() const noexcept;
|
||||
const_reverse_iterator crend() const noexcept;
|
||||
|
||||
container_type real() && noexcept;
|
||||
container_type& real() & noexcept;
|
||||
const container_type& real() const & noexcept;
|
||||
|
||||
container_type imag() && noexcept;
|
||||
container_type& imag() & noexcept;
|
||||
const container_type& imag() const & noexcept;
|
||||
|
||||
protected:
|
||||
|
||||
xcomplex_sequence() = default;
|
||||
xcomplex_sequence(size_type s);
|
||||
xcomplex_sequence(size_type s, const value_type& v);
|
||||
template <class TR, class TC, bool B>
|
||||
xcomplex_sequence(size_type s, const xcomplex<TR, TC, B>& v);
|
||||
xcomplex_sequence(std::initializer_list<value_type> init);
|
||||
|
||||
~xcomplex_sequence() = default;
|
||||
|
||||
xcomplex_sequence(const xcomplex_sequence&) = default;
|
||||
xcomplex_sequence& operator=(const xcomplex_sequence&) = default;
|
||||
|
||||
xcomplex_sequence(xcomplex_sequence&&) = default;
|
||||
xcomplex_sequence& operator=(xcomplex_sequence&&) = default;
|
||||
|
||||
container_type m_real;
|
||||
container_type m_imag;
|
||||
};
|
||||
|
||||
template <class C, bool B>
|
||||
bool operator==(const xcomplex_sequence<C, B>& lhs, const xcomplex_sequence<C, B>& rhs);
|
||||
|
||||
template <class C, bool B>
|
||||
bool operator!=(const xcomplex_sequence<C, B>& lhs, const xcomplex_sequence<C, B>& rhs);
|
||||
|
||||
/******************
|
||||
* xcomplex_array *
|
||||
******************/
|
||||
|
||||
template <class T, std::size_t N, bool ieee_compliant = false>
|
||||
class xcomplex_array : public xcomplex_sequence<std::array<T, N>, ieee_compliant>
|
||||
{
|
||||
public:
|
||||
|
||||
using base_type = xcomplex_sequence<std::array<T, N>, ieee_compliant>;
|
||||
using value_type = typename base_type::value_type;
|
||||
using size_type = typename base_type::size_type;
|
||||
|
||||
xcomplex_array() = default;
|
||||
xcomplex_array(size_type s);
|
||||
xcomplex_array(size_type s, const value_type& v);
|
||||
|
||||
template <class TR, class TI, bool B>
|
||||
xcomplex_array(size_type s, const xcomplex<TR, TI, B>& v);
|
||||
};
|
||||
|
||||
/*******************
|
||||
* xcomplex_vector *
|
||||
*******************/
|
||||
|
||||
template <class T, bool ieee_compliant = false, class A = std::allocator<T>>
|
||||
class xcomplex_vector : public xcomplex_sequence<std::vector<T, A>, ieee_compliant>
|
||||
{
|
||||
public:
|
||||
|
||||
using base_type = xcomplex_sequence<std::vector<T, A>, ieee_compliant>;
|
||||
using value_type = typename base_type::value_type;
|
||||
using size_type = typename base_type::size_type;
|
||||
|
||||
xcomplex_vector() = default;
|
||||
xcomplex_vector(size_type s);
|
||||
xcomplex_vector(size_type s, const value_type& v);
|
||||
xcomplex_vector(std::initializer_list<value_type> init);
|
||||
|
||||
template <class TR, class TI, bool B>
|
||||
xcomplex_vector(size_type s, const xcomplex<TR, TI, B>& v);
|
||||
|
||||
void resize(size_type);
|
||||
void resize(size_type, const value_type&);
|
||||
template <class TR, class TI, bool B>
|
||||
void resize(size_type s, const xcomplex<TR, TI, B>& v);
|
||||
};
|
||||
|
||||
/*********************
|
||||
* xcomplex_iterator *
|
||||
*********************/
|
||||
|
||||
template <class IT, bool ieee_compliant>
|
||||
struct xcomplex_iterator_traits
|
||||
{
|
||||
using iterator_type = xcomplex_iterator<IT, ieee_compliant>;
|
||||
using value_type = xcomplex<typename IT::value_type, typename IT::value_type, ieee_compliant>;
|
||||
using reference = xcomplex<typename IT::reference, typename IT::reference, ieee_compliant>;
|
||||
using pointer = xclosure_pointer<reference>;
|
||||
using difference_type = typename IT::difference_type;
|
||||
};
|
||||
|
||||
template <class IT, bool B>
|
||||
class xcomplex_iterator : public xrandom_access_iterator_base2<xcomplex_iterator_traits<IT, B>>
|
||||
{
|
||||
public:
|
||||
|
||||
using self_type = xcomplex_iterator<IT, B>;
|
||||
using base_type = xrandom_access_iterator_base2<xcomplex_iterator_traits<IT, B>>;
|
||||
|
||||
using value_type = typename base_type::value_type;
|
||||
using reference = typename base_type::reference;
|
||||
using pointer = typename base_type::pointer;
|
||||
using difference_type = typename base_type::difference_type;
|
||||
|
||||
xcomplex_iterator() = default;
|
||||
xcomplex_iterator(IT it_real, IT it_imag);
|
||||
|
||||
self_type& operator++();
|
||||
self_type& operator--();
|
||||
|
||||
self_type& operator+=(difference_type n);
|
||||
self_type& operator-=(difference_type n);
|
||||
|
||||
difference_type operator-(const self_type& rhs) const;
|
||||
|
||||
reference operator*() const;
|
||||
pointer operator->() const;
|
||||
|
||||
bool operator==(const self_type& rhs) const;
|
||||
|
||||
private:
|
||||
|
||||
IT m_it_real;
|
||||
IT m_it_imag;
|
||||
};
|
||||
|
||||
/************************************
|
||||
* xcomplex_sequence implementation *
|
||||
************************************/
|
||||
|
||||
template <class C, bool B>
|
||||
inline xcomplex_sequence<C, B>::xcomplex_sequence(size_type s)
|
||||
: m_real(make_sequence<container_type>(s)),
|
||||
m_imag(make_sequence<container_type>(s))
|
||||
{
|
||||
}
|
||||
|
||||
template <class C, bool B>
|
||||
inline xcomplex_sequence<C, B>::xcomplex_sequence(size_type s, const value_type& v)
|
||||
: m_real(make_sequence<container_type>(s, v.real())),
|
||||
m_imag(make_sequence<container_type>(s, v.imag()))
|
||||
{
|
||||
}
|
||||
|
||||
template <class C, bool B>
|
||||
template <class TR, class TC, bool B2>
|
||||
inline xcomplex_sequence<C, B>::xcomplex_sequence(size_type s, const xcomplex<TR, TC, B2>& v)
|
||||
: m_real(make_sequence<container_type>(s, v.real())),
|
||||
m_imag(make_sequence<container_type>(s, v.imag()))
|
||||
{
|
||||
}
|
||||
|
||||
template <class C, bool B>
|
||||
inline xcomplex_sequence<C, B>::xcomplex_sequence(std::initializer_list<value_type> init)
|
||||
: m_real(make_sequence<container_type>(init.size())),
|
||||
m_imag(make_sequence<container_type>(init.size()))
|
||||
{
|
||||
std::transform(init.begin(), init.end(), m_real.begin(), [](const auto& v) { return v.real(); });
|
||||
std::transform(init.begin(), init.end(), m_imag.begin(), [](const auto& v) { return v.imag(); });
|
||||
}
|
||||
|
||||
template <class C, bool B>
|
||||
inline bool xcomplex_sequence<C, B>::empty() const noexcept
|
||||
{
|
||||
return m_real.empty();
|
||||
}
|
||||
|
||||
template <class C, bool B>
|
||||
inline auto xcomplex_sequence<C, B>::size() const noexcept -> size_type
|
||||
{
|
||||
return m_real.size();
|
||||
}
|
||||
|
||||
template <class C, bool B>
|
||||
inline auto xcomplex_sequence<C, B>::max_size() const noexcept -> size_type
|
||||
{
|
||||
return m_real.max_size();
|
||||
}
|
||||
|
||||
template <class C, bool B>
|
||||
inline auto xcomplex_sequence<C, B>::at(size_type i) -> reference
|
||||
{
|
||||
return reference(m_real.at(i), m_imag.at(i));
|
||||
}
|
||||
|
||||
template <class C, bool B>
|
||||
inline auto xcomplex_sequence<C, B>::at(size_type i) const -> const_reference
|
||||
{
|
||||
return const_reference(m_real.at(i), m_imag.at(i));
|
||||
}
|
||||
|
||||
template <class C, bool B>
|
||||
inline auto xcomplex_sequence<C, B>::operator[](size_type i) -> reference
|
||||
{
|
||||
return reference(m_real[i], m_imag[i]);
|
||||
}
|
||||
|
||||
template <class C, bool B>
|
||||
inline auto xcomplex_sequence<C, B>::operator[](size_type i) const -> const_reference
|
||||
{
|
||||
return const_reference(m_real[i], m_imag[i]);
|
||||
}
|
||||
|
||||
template <class C, bool B>
|
||||
inline auto xcomplex_sequence<C, B>::front() -> reference
|
||||
{
|
||||
return reference(m_real.front(), m_imag.front());
|
||||
}
|
||||
|
||||
template <class C, bool B>
|
||||
inline auto xcomplex_sequence<C, B>::front() const -> const_reference
|
||||
{
|
||||
return const_reference(m_real.front(), m_imag.front());
|
||||
}
|
||||
|
||||
template <class C, bool B>
|
||||
inline auto xcomplex_sequence<C, B>::back() -> reference
|
||||
{
|
||||
return reference(m_real.back(), m_imag.back());
|
||||
}
|
||||
|
||||
template <class C, bool B>
|
||||
inline auto xcomplex_sequence<C, B>::back() const -> const_reference
|
||||
{
|
||||
return const_reference(m_real.back(), m_imag.back());
|
||||
}
|
||||
|
||||
template <class C, bool B>
|
||||
inline auto xcomplex_sequence<C, B>::begin() noexcept -> iterator
|
||||
{
|
||||
return iterator(m_real.begin(), m_imag.begin());
|
||||
}
|
||||
|
||||
template <class C, bool B>
|
||||
inline auto xcomplex_sequence<C, B>::end() noexcept -> iterator
|
||||
{
|
||||
return iterator(m_real.end(), m_imag.end());
|
||||
}
|
||||
|
||||
template <class C, bool B>
|
||||
inline auto xcomplex_sequence<C, B>::begin() const noexcept -> const_iterator
|
||||
{
|
||||
return cbegin();
|
||||
}
|
||||
|
||||
template <class C, bool B>
|
||||
inline auto xcomplex_sequence<C, B>::end() const noexcept -> const_iterator
|
||||
{
|
||||
return cend();
|
||||
}
|
||||
|
||||
template <class C, bool B>
|
||||
inline auto xcomplex_sequence<C, B>::cbegin() const noexcept -> const_iterator
|
||||
{
|
||||
return const_iterator(m_real.cbegin(), m_imag.cbegin());
|
||||
}
|
||||
|
||||
template <class C, bool B>
|
||||
inline auto xcomplex_sequence<C, B>::cend() const noexcept -> const_iterator
|
||||
{
|
||||
return const_iterator(m_real.cend(), m_imag.cend());
|
||||
}
|
||||
|
||||
template <class C, bool B>
|
||||
inline auto xcomplex_sequence<C, B>::rbegin() noexcept -> reverse_iterator
|
||||
{
|
||||
return reverse_iterator(m_real.rbegin(), m_imag.rbegin());
|
||||
}
|
||||
|
||||
template <class C, bool B>
|
||||
inline auto xcomplex_sequence<C, B>::rend() noexcept -> reverse_iterator
|
||||
{
|
||||
return reverse_iterator(m_real.rend(), m_imag.rend());
|
||||
}
|
||||
|
||||
template <class C, bool B>
|
||||
inline auto xcomplex_sequence<C, B>::rbegin() const noexcept -> const_reverse_iterator
|
||||
{
|
||||
return crbegin();
|
||||
}
|
||||
|
||||
template <class C, bool B>
|
||||
inline auto xcomplex_sequence<C, B>::rend() const noexcept -> const_reverse_iterator
|
||||
{
|
||||
return crend();
|
||||
}
|
||||
|
||||
template <class C, bool B>
|
||||
inline auto xcomplex_sequence<C, B>::crbegin() const noexcept -> const_reverse_iterator
|
||||
{
|
||||
return const_reverse_iterator(m_real.crbegin(), m_imag.crbegin());
|
||||
}
|
||||
|
||||
template <class C, bool B>
|
||||
inline auto xcomplex_sequence<C, B>::crend() const noexcept -> const_reverse_iterator
|
||||
{
|
||||
return const_reverse_iterator(m_real.crend(), m_imag.crend());
|
||||
}
|
||||
|
||||
template <class C, bool B>
|
||||
inline auto xcomplex_sequence<C, B>::real() && noexcept -> container_type
|
||||
{
|
||||
return m_real;
|
||||
}
|
||||
|
||||
template <class C, bool B>
|
||||
inline auto xcomplex_sequence<C, B>::real() & noexcept -> container_type&
|
||||
{
|
||||
return m_real;
|
||||
}
|
||||
|
||||
template <class C, bool B>
|
||||
inline auto xcomplex_sequence<C, B>::real() const & noexcept -> const container_type&
|
||||
{
|
||||
return m_real;
|
||||
}
|
||||
|
||||
template <class C, bool B>
|
||||
inline auto xcomplex_sequence<C, B>::imag() && noexcept -> container_type
|
||||
{
|
||||
return m_imag;
|
||||
}
|
||||
|
||||
template <class C, bool B>
|
||||
inline auto xcomplex_sequence<C, B>::imag() & noexcept -> container_type&
|
||||
{
|
||||
return m_imag;
|
||||
}
|
||||
|
||||
template <class C, bool B>
|
||||
inline auto xcomplex_sequence<C, B>::imag() const & noexcept -> const container_type&
|
||||
{
|
||||
return m_imag;
|
||||
}
|
||||
|
||||
template <class C, bool B>
|
||||
inline bool operator==(const xcomplex_sequence<C, B>& lhs, const xcomplex_sequence<C, B>& rhs)
|
||||
{
|
||||
return lhs.real() == rhs.real() && lhs.imag() == rhs.imag();
|
||||
}
|
||||
|
||||
template <class C, bool B>
|
||||
inline bool operator!=(const xcomplex_sequence<C, B>& lhs, const xcomplex_sequence<C, B>& rhs)
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
/*********************************
|
||||
* xcomplex_array implementation *
|
||||
*********************************/
|
||||
|
||||
template <class T, std::size_t N, bool B>
|
||||
inline xcomplex_array<T, N, B>::xcomplex_array(size_type s)
|
||||
: base_type(s)
|
||||
{
|
||||
}
|
||||
|
||||
template <class T, std::size_t N, bool B>
|
||||
inline xcomplex_array<T, N, B>::xcomplex_array(size_type s, const value_type& v)
|
||||
: base_type(s, v)
|
||||
{
|
||||
}
|
||||
|
||||
template <class T, std::size_t N, bool B>
|
||||
template <class TR, class TI, bool B2>
|
||||
inline xcomplex_array<T, N, B>::xcomplex_array(size_type s, const xcomplex<TR, TI, B2>& v)
|
||||
: base_type(s, v)
|
||||
{
|
||||
}
|
||||
|
||||
/**********************************
|
||||
* xcomplex_vector implementation *
|
||||
**********************************/
|
||||
|
||||
template <class T, bool B, class A>
|
||||
inline xcomplex_vector<T, B, A>::xcomplex_vector(size_type s)
|
||||
: base_type(s)
|
||||
{
|
||||
}
|
||||
|
||||
template <class T, bool B, class A>
|
||||
inline xcomplex_vector<T, B, A>::xcomplex_vector(size_type s, const value_type& v)
|
||||
: base_type(s, v)
|
||||
{
|
||||
}
|
||||
|
||||
template <class T, bool B, class A>
|
||||
template <class TR, class TI, bool B2>
|
||||
inline xcomplex_vector<T, B, A>::xcomplex_vector(size_type s, const xcomplex<TR, TI, B2>& v)
|
||||
: base_type(s, v)
|
||||
{
|
||||
}
|
||||
|
||||
template <class T, bool B, class A>
|
||||
inline xcomplex_vector<T, B, A>::xcomplex_vector(std::initializer_list<value_type> init)
|
||||
: base_type(init)
|
||||
{
|
||||
}
|
||||
|
||||
template <class T, bool B, class A>
|
||||
void xcomplex_vector<T, B, A>::resize(size_type s)
|
||||
{
|
||||
this->m_real.resize(s);
|
||||
this->m_imag.resize(s);
|
||||
}
|
||||
|
||||
template <class T, bool B, class A>
|
||||
void xcomplex_vector<T, B, A>::resize(size_type s, const value_type& v)
|
||||
{
|
||||
this->m_real.resize(s, v.real());
|
||||
this->m_imag.resize(s, v.imag());
|
||||
}
|
||||
|
||||
template <class T, bool B, class A>
|
||||
template <class TR, class TI, bool B2>
|
||||
inline void xcomplex_vector<T, B, A>::resize(size_type s, const xcomplex<TR, TI, B2>& v)
|
||||
{
|
||||
this->m_real.resize(s, v.real());
|
||||
this->m_imag.resize(s, v.imag());
|
||||
}
|
||||
|
||||
/************************************
|
||||
* xcomplex_iterator implementation *
|
||||
************************************/
|
||||
|
||||
template <class IT, bool B>
|
||||
inline xcomplex_iterator<IT, B>::xcomplex_iterator(IT it_real, IT it_imag)
|
||||
: m_it_real(it_real), m_it_imag(it_imag)
|
||||
{
|
||||
}
|
||||
|
||||
template <class IT, bool B>
|
||||
inline auto xcomplex_iterator<IT, B>::operator++() -> self_type&
|
||||
{
|
||||
++m_it_real;
|
||||
++m_it_imag;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class IT, bool B>
|
||||
inline auto xcomplex_iterator<IT, B>::operator--() -> self_type&
|
||||
{
|
||||
--m_it_real;
|
||||
--m_it_imag;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class IT, bool B>
|
||||
inline auto xcomplex_iterator<IT, B>::operator+=(difference_type n) -> self_type&
|
||||
{
|
||||
m_it_real += n;
|
||||
m_it_imag += n;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class IT, bool B>
|
||||
inline auto xcomplex_iterator<IT, B>::operator-=(difference_type n) -> self_type&
|
||||
{
|
||||
m_it_real -= n;
|
||||
m_it_imag -= n;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class IT, bool B>
|
||||
inline auto xcomplex_iterator<IT, B>::operator-(const self_type& rhs) const -> difference_type
|
||||
{
|
||||
return m_it_real - rhs.m_it_real;
|
||||
}
|
||||
|
||||
template <class IT, bool B>
|
||||
inline auto xcomplex_iterator<IT, B>::operator*() const -> reference
|
||||
{
|
||||
return reference(*m_it_real, *m_it_imag);
|
||||
}
|
||||
|
||||
template <class IT, bool B>
|
||||
inline auto xcomplex_iterator<IT, B>::operator->() const -> pointer
|
||||
{
|
||||
return pointer(operator*());
|
||||
}
|
||||
|
||||
template <class IT, bool B>
|
||||
inline bool xcomplex_iterator<IT, B>::operator==(const self_type& rhs) const
|
||||
{
|
||||
return m_it_real == rhs.m_it_real && m_it_imag == rhs.m_it_imag;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,44 @@
|
|||
/***************************************************************************
|
||||
* Copyright (c) Johan Mabille, Sylvain Corlay and Wolf Vollprecht *
|
||||
* Copyright (c) QuantStack *
|
||||
* *
|
||||
* Distributed under the terms of the BSD 3-Clause License. *
|
||||
* *
|
||||
* The full license is in the file LICENSE, distributed with this software. *
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef XTL_FUNCTIONAL_HPP
|
||||
#define XTL_FUNCTIONAL_HPP
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include "xtl_config.hpp"
|
||||
#include "xtype_traits.hpp"
|
||||
|
||||
namespace xtl
|
||||
{
|
||||
/***************************
|
||||
* identity implementation *
|
||||
***************************/
|
||||
|
||||
struct identity
|
||||
{
|
||||
template <class T>
|
||||
T&& operator()(T&& x) const
|
||||
{
|
||||
return std::forward<T>(x);
|
||||
}
|
||||
};
|
||||
|
||||
/*************************
|
||||
* select implementation *
|
||||
*************************/
|
||||
|
||||
template <class B, class T1, class T2, XTL_REQUIRES(all_scalar<B, T1, T2>)>
|
||||
inline std::common_type_t<T1, T2> select(const B& cond, const T1& v1, const T2& v2) noexcept
|
||||
{
|
||||
return cond ? v1 : v2;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,41 @@
|
|||
/***************************************************************************
|
||||
* Copyright (c) Johan Mabille, Sylvain Corlay and Wolf Vollprecht *
|
||||
* Copyright (c) QuantStack *
|
||||
* *
|
||||
* Distributed under the terms of the BSD 3-Clause License. *
|
||||
* *
|
||||
* The full license is in the file LICENSE, distributed with this software. *
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef XTL_XHALF_FLOAT_HPP
|
||||
#define XTL_XHALF_FLOAT_HPP
|
||||
|
||||
#include "xtype_traits.hpp"
|
||||
#include "xhalf_float_impl.hpp"
|
||||
|
||||
namespace xtl
|
||||
{
|
||||
using half_float = half_float::half;
|
||||
|
||||
template <>
|
||||
struct is_scalar<half_float> : std::true_type
|
||||
{
|
||||
};
|
||||
|
||||
template <>
|
||||
struct is_arithmetic<half_float> : std::true_type
|
||||
{
|
||||
};
|
||||
|
||||
template <>
|
||||
struct is_signed<half_float> : std::true_type
|
||||
{
|
||||
};
|
||||
|
||||
template <>
|
||||
struct is_floating_point<half_float> : std::true_type
|
||||
{
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,208 @@
|
|||
/***************************************************************************
|
||||
* Copyright (c) Johan Mabille, Sylvain Corlay and Wolf Vollprecht *
|
||||
* Copyright (c) QuantStack *
|
||||
* *
|
||||
* Distributed under the terms of the BSD 3-Clause License. *
|
||||
* *
|
||||
* The full license is in the file LICENSE, distributed with this software. *
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef XTL_HASH_HPP
|
||||
#define XTL_HASH_HPP
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
namespace xtl
|
||||
{
|
||||
|
||||
std::size_t hash_bytes(const void* buffer, std::size_t length, std::size_t seed);
|
||||
|
||||
uint32_t murmur2_x86(const void* buffer, std::size_t length, uint32_t seed);
|
||||
uint64_t murmur2_x64(const void* buffer, std::size_t length, uint64_t seed);
|
||||
|
||||
/******************************
|
||||
* hash_bytes implementation *
|
||||
******************************/
|
||||
|
||||
namespace detail
|
||||
{
|
||||
// Dummy hash implementation for unusual sizeof(std::size_t)
|
||||
template <std::size_t N>
|
||||
std::size_t murmur_hash(const void* buffer, std::size_t length, std::size_t seed)
|
||||
{
|
||||
std::size_t hash = seed;
|
||||
const char* data = static_cast<const char*>(buffer);
|
||||
for (; length != 0; --length)
|
||||
{
|
||||
hash = (hash * 131) + static_cast<std::size_t>(*data++);
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
// Murmur hash is an algorithm written by Austin Appleby. See https://github.com/aappleby/smhasher/blob/master/src/MurmurHash2.cpp
|
||||
inline uint32_t murmur2_x86_impl(const void* buffer, std::size_t length, uint32_t seed)
|
||||
{
|
||||
const uint32_t m = 0x5bd1e995;
|
||||
uint32_t len = static_cast<uint32_t>(length);
|
||||
|
||||
// Initialize the hash to a 'random' value
|
||||
uint32_t h = seed ^ len;
|
||||
|
||||
// Mix 4 bytes at a time into the hash
|
||||
const unsigned char * data = (const unsigned char *)buffer;
|
||||
|
||||
while(len >= 4)
|
||||
{
|
||||
uint32_t k = *(uint32_t*)data;
|
||||
k *= m;
|
||||
k ^= k >> 24;
|
||||
k *= m;
|
||||
|
||||
h *= m;
|
||||
h ^= k;
|
||||
|
||||
data += 4;
|
||||
len -= 4;
|
||||
}
|
||||
|
||||
// Handle the last few bytes of the input array
|
||||
switch(len)
|
||||
{
|
||||
case 3: h ^= static_cast<uint32_t>(data[2] << 16);
|
||||
case 2: h ^= static_cast<uint32_t>(data[1] << 8);
|
||||
case 1: h ^= static_cast<uint32_t>(data[0]);
|
||||
h *= m;
|
||||
};
|
||||
|
||||
// Do a few final mixes of the hash to ensure the last few
|
||||
// // bytes are well-incorporated.
|
||||
h ^= h >> 13;
|
||||
h *= m;
|
||||
h ^= h >> 15;
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline std::size_t murmur_hash<4>(const void* buffer, std::size_t length, std::size_t seed)
|
||||
{
|
||||
return std::size_t(murmur2_x86_impl(buffer, length, static_cast<uint32_t>(seed)));
|
||||
}
|
||||
|
||||
inline std::size_t load_bytes(const char* p, int n)
|
||||
{
|
||||
std::size_t result = 0;
|
||||
--n;
|
||||
do
|
||||
{
|
||||
result = (result << 8) + static_cast<unsigned char>(p[n]);
|
||||
} while (--n >= 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
#if INTPTR_MAX == INT64_MAX
|
||||
// 64-bits hash for 64-bits platform
|
||||
template <>
|
||||
inline std::size_t murmur_hash<8>(const void* buffer, std::size_t length, std::size_t seed)
|
||||
{
|
||||
constexpr std::size_t m = (static_cast<std::size_t>(0xc6a4a793UL) << 32UL) +
|
||||
static_cast<std::size_t>(0x5bd1e995UL);
|
||||
constexpr int r = 47;
|
||||
const char* data = static_cast<const char*>(buffer);
|
||||
const char* end = data + (length & std::size_t(~0x7));
|
||||
std::size_t hash = seed ^ (length * m);
|
||||
while (data != end)
|
||||
{
|
||||
std::size_t k;
|
||||
std::memcpy(&k, data, sizeof(k));
|
||||
k *= m;
|
||||
k ^= k >> r;
|
||||
k *= m;
|
||||
hash ^= k;
|
||||
hash *= m;
|
||||
data += 8;
|
||||
}
|
||||
if ((length & 0x7) != 0)
|
||||
{
|
||||
std::size_t k = load_bytes(end, length & 0x7);
|
||||
hash ^= k;
|
||||
hash *= m;
|
||||
}
|
||||
hash ^= hash >> r;
|
||||
hash *= m;
|
||||
hash ^= hash >> r;
|
||||
|
||||
return hash;
|
||||
}
|
||||
#elif INTPTR_MAX == INT32_MAX
|
||||
//64-bits hash for 32-bits platform
|
||||
inline void mmix(uint32_t& h, uint32_t& k, uint32_t m, int r)
|
||||
{
|
||||
k *= m; k ^= k >> r; k *= m; h *= m; h ^= k;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline std::size_t murmur_hash<8>(const void* buffer, std::size_t length, std::size_t seed)
|
||||
{
|
||||
const uint32_t m = 0x5bd1e995;
|
||||
const int r = 24;
|
||||
uint32_t l = length;
|
||||
|
||||
const auto* data = reinterpret_cast<const unsigned char*>(buffer);
|
||||
|
||||
uint32_t h = seed;
|
||||
|
||||
while (length >= 4)
|
||||
{
|
||||
uint32_t k = *(uint32_t*)data;
|
||||
|
||||
mmix(h, k, m, r);
|
||||
|
||||
data += 4;
|
||||
length -= 4;
|
||||
}
|
||||
|
||||
uint32_t t = 0;
|
||||
|
||||
switch (length)
|
||||
{
|
||||
case 3: t ^= data[2] << 16;
|
||||
case 2: t ^= data[1] << 8;
|
||||
case 1: t ^= data[0];
|
||||
};
|
||||
|
||||
mmix(h, t, m, r);
|
||||
mmix(h, l, m, r);
|
||||
|
||||
h ^= h >> 13;
|
||||
h *= m;
|
||||
h ^= h >> 15;
|
||||
|
||||
return h;
|
||||
}
|
||||
#else
|
||||
#error Unknown pointer size or missing size macros!
|
||||
#endif
|
||||
}
|
||||
|
||||
inline std::size_t hash_bytes(const void* buffer, std::size_t length, std::size_t seed)
|
||||
{
|
||||
return detail::murmur_hash<sizeof(std::size_t)>(buffer, length, seed);
|
||||
}
|
||||
|
||||
inline uint32_t murmur2_x86(const void* buffer, std::size_t length, uint32_t seed)
|
||||
{
|
||||
return detail::murmur2_x86_impl(buffer, length, seed);
|
||||
}
|
||||
|
||||
inline uint64_t murmur2_x64(const void* buffer, std::size_t length, uint64_t seed)
|
||||
{
|
||||
return detail::murmur_hash<8>(buffer, length, seed);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,73 @@
|
|||
/***************************************************************************
|
||||
* Copyright (c) Johan Mabille, Sylvain Corlay and Wolf Vollprecht *
|
||||
* Copyright (c) QuantStack *
|
||||
* *
|
||||
* Distributed under the terms of the BSD 3-Clause License. *
|
||||
* *
|
||||
* The full license is in the file LICENSE, distributed with this software. *
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef XTL_HIERARCHY_GENERATOR_HPP
|
||||
#define XTL_HIERARCHY_GENERATOR_HPP
|
||||
|
||||
#include "xmeta_utils.hpp"
|
||||
|
||||
namespace xtl
|
||||
{
|
||||
|
||||
/*********************************
|
||||
* scattered hierarchy generator *
|
||||
*********************************/
|
||||
|
||||
template <class TL, template <class> class U>
|
||||
class xscatter_hierarchy_generator;
|
||||
|
||||
template <template <class> class U, class T, class... Args>
|
||||
class xscatter_hierarchy_generator<mpl::vector<T, Args...>, U>
|
||||
: public U<T>, public xscatter_hierarchy_generator<mpl::vector<Args...>, U>
|
||||
{
|
||||
};
|
||||
|
||||
template <template <class> class U>
|
||||
class xscatter_hierarchy_generator<mpl::vector<>, U>
|
||||
{
|
||||
};
|
||||
|
||||
/******************************
|
||||
* linear hierarchy generator *
|
||||
******************************/
|
||||
|
||||
class default_root {};
|
||||
|
||||
template <class TL, template <class, class> class U, class Root = default_root>
|
||||
class xlinear_hierarchy_generator;
|
||||
|
||||
template <template <class, class> class U, class Root, class T0, class... Args>
|
||||
class xlinear_hierarchy_generator<mpl::vector<T0, Args...>, U, Root>
|
||||
: public U<T0, xlinear_hierarchy_generator<mpl::vector<Args...>, U, Root>>
|
||||
{
|
||||
public:
|
||||
|
||||
using base_type = U<T0, xlinear_hierarchy_generator<mpl::vector<Args...>, U, Root>>;
|
||||
template <class... T>
|
||||
inline xlinear_hierarchy_generator(T&&... args)
|
||||
: base_type(std::forward<T>(args)...)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
template <template <class, class> class U, class Root>
|
||||
class xlinear_hierarchy_generator<mpl::vector<>, U, Root>
|
||||
: public Root
|
||||
{
|
||||
public:
|
||||
|
||||
template <class... T>
|
||||
inline xlinear_hierarchy_generator(T&&... args)
|
||||
: Root(std::forward<T>(args)...)
|
||||
{
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,422 @@
|
|||
/***************************************************************************
|
||||
* Copyright (c) Johan Mabille, Sylvain Corlay and Wolf Vollprecht *
|
||||
* Copyright (c) QuantStack *
|
||||
* *
|
||||
* Distributed under the terms of the BSD 3-Clause License. *
|
||||
* *
|
||||
* The full license is in the file LICENSE, distributed with this software. *
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef XTL_XITERATOR_BASE_HPP
|
||||
#define XTL_XITERATOR_BASE_HPP
|
||||
|
||||
#include <cstddef>
|
||||
#include <iterator>
|
||||
|
||||
namespace xtl
|
||||
{
|
||||
/**************************************
|
||||
* class xbidirectional_iterator_base *
|
||||
**************************************/
|
||||
|
||||
template <class I, class T, class D = std::ptrdiff_t, class P = T*, class R = T&>
|
||||
class xbidirectional_iterator_base
|
||||
{
|
||||
public:
|
||||
|
||||
using derived_type = I;
|
||||
using value_type = T;
|
||||
using reference = R;
|
||||
using pointer = P;
|
||||
using difference_type = D;
|
||||
using iterator_category = std::bidirectional_iterator_tag;
|
||||
|
||||
inline friend derived_type operator++(derived_type& d, int)
|
||||
{
|
||||
derived_type tmp(d);
|
||||
++d;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
inline friend derived_type operator--(derived_type& d, int)
|
||||
{
|
||||
derived_type tmp(d);
|
||||
--d;
|
||||
return tmp;
|
||||
|
||||
}
|
||||
|
||||
inline friend bool operator!=(const derived_type& lhs, const derived_type& rhs)
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
using xbidirectional_iterator_base2 = xbidirectional_iterator_base<typename T::iterator_type,
|
||||
typename T::value_type,
|
||||
typename T::difference_type,
|
||||
typename T::pointer,
|
||||
typename T::reference>;
|
||||
|
||||
template <class I, class T>
|
||||
using xbidirectional_iterator_base3 = xbidirectional_iterator_base<I,
|
||||
typename T::value_type,
|
||||
typename T::difference_type,
|
||||
typename T::pointer,
|
||||
typename T::reference>;
|
||||
|
||||
/********************************
|
||||
* xrandom_access_iterator_base *
|
||||
********************************/
|
||||
|
||||
template <class I, class T, class D = std::ptrdiff_t, class P = T*, class R = T&>
|
||||
class xrandom_access_iterator_base : public xbidirectional_iterator_base<I, T, D, P, R>
|
||||
{
|
||||
public:
|
||||
|
||||
using derived_type = I;
|
||||
using value_type = T;
|
||||
using reference = R;
|
||||
using pointer = P;
|
||||
using difference_type = D;
|
||||
using iterator_category = std::random_access_iterator_tag;
|
||||
|
||||
inline reference operator[](difference_type n) const
|
||||
{
|
||||
return *(*static_cast<const derived_type*>(this) + n);
|
||||
}
|
||||
|
||||
inline friend derived_type operator+(const derived_type& it, difference_type n)
|
||||
{
|
||||
derived_type tmp(it);
|
||||
return tmp += n;
|
||||
}
|
||||
|
||||
inline friend derived_type operator+(difference_type n, const derived_type& it)
|
||||
{
|
||||
derived_type tmp(it);
|
||||
return tmp += n;
|
||||
}
|
||||
|
||||
inline friend derived_type operator-(const derived_type& it, difference_type n)
|
||||
{
|
||||
derived_type tmp(it);
|
||||
return tmp -= n;
|
||||
}
|
||||
|
||||
inline friend bool operator<=(const derived_type& lhs, const derived_type& rhs)
|
||||
{
|
||||
return !(rhs < lhs);
|
||||
}
|
||||
|
||||
inline friend bool operator>=(const derived_type& lhs, const derived_type& rhs)
|
||||
{
|
||||
return !(lhs < rhs);
|
||||
}
|
||||
|
||||
inline friend bool operator>(const derived_type& lhs, const derived_type& rhs)
|
||||
{
|
||||
return rhs < lhs;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
template <class T>
|
||||
using xrandom_access_iterator_base2 = xrandom_access_iterator_base<typename T::iterator_type,
|
||||
typename T::value_type,
|
||||
typename T::difference_type,
|
||||
typename T::pointer,
|
||||
typename T::reference>;
|
||||
|
||||
template <class I, class T>
|
||||
using xrandom_access_iterator_base3 = xrandom_access_iterator_base<I,
|
||||
typename T::value_type,
|
||||
typename T::difference_type,
|
||||
typename T::pointer,
|
||||
typename T::reference>;
|
||||
|
||||
/*******************************
|
||||
* xrandom_access_iterator_ext *
|
||||
*******************************/
|
||||
|
||||
// Extension for random access iterators defining operator[] and operator+ overloads
|
||||
// accepting size_t arguments.
|
||||
template <class I, class R>
|
||||
class xrandom_access_iterator_ext
|
||||
{
|
||||
public:
|
||||
|
||||
using derived_type = I;
|
||||
using reference = R;
|
||||
using size_type = std::size_t;
|
||||
|
||||
inline reference operator[](size_type n) const
|
||||
{
|
||||
return *(*static_cast<const derived_type*>(this) + n);
|
||||
}
|
||||
|
||||
inline friend derived_type operator+(const derived_type& it, size_type n)
|
||||
{
|
||||
derived_type tmp(it);
|
||||
return tmp += n;
|
||||
}
|
||||
|
||||
inline friend derived_type operator+(size_type n, const derived_type& it)
|
||||
{
|
||||
derived_type tmp(it);
|
||||
return tmp += n;
|
||||
}
|
||||
|
||||
inline friend derived_type operator-(const derived_type& it, size_type n)
|
||||
{
|
||||
derived_type tmp(it);
|
||||
return tmp -= n;
|
||||
}
|
||||
};
|
||||
|
||||
/*****************
|
||||
* xkey_iterator *
|
||||
*****************/
|
||||
|
||||
template <class M>
|
||||
class xkey_iterator : public xbidirectional_iterator_base<xkey_iterator<M>, const typename M::key_type>
|
||||
{
|
||||
public:
|
||||
|
||||
using self_type = xkey_iterator;
|
||||
using base_type = xbidirectional_iterator_base<self_type, const typename M::key_type>;
|
||||
using value_type = typename base_type::value_type;
|
||||
using reference = typename base_type::reference;
|
||||
using pointer = typename base_type::pointer;
|
||||
using difference_type = typename base_type::difference_type;
|
||||
using iterator_category = typename base_type::iterator_category;
|
||||
using subiterator = typename M::const_iterator;
|
||||
|
||||
inline xkey_iterator(subiterator it) noexcept
|
||||
: m_it(it)
|
||||
{
|
||||
}
|
||||
|
||||
inline self_type& operator++()
|
||||
{
|
||||
++m_it;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline self_type& operator--()
|
||||
{
|
||||
--m_it;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline reference operator*() const
|
||||
{
|
||||
return m_it->first;
|
||||
}
|
||||
|
||||
inline pointer operator->() const
|
||||
{
|
||||
return&(m_it->first);
|
||||
}
|
||||
|
||||
inline bool operator==(const self_type& rhs) const
|
||||
{
|
||||
return m_it == rhs.m_it;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
subiterator m_it;
|
||||
};
|
||||
|
||||
/*******************
|
||||
* xvalue_iterator *
|
||||
*******************/
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <class M>
|
||||
struct xvalue_iterator_types
|
||||
{
|
||||
using subiterator = typename M::iterator;
|
||||
using value_type = typename M::mapped_type;
|
||||
using reference = value_type&;
|
||||
using pointer = value_type*;
|
||||
using difference_type = typename subiterator::difference_type;
|
||||
};
|
||||
|
||||
template <class M>
|
||||
struct xvalue_iterator_types<const M>
|
||||
{
|
||||
using subiterator = typename M::const_iterator;
|
||||
using value_type = typename M::mapped_type;
|
||||
using reference = const value_type&;
|
||||
using pointer = const value_type*;
|
||||
using difference_type = typename subiterator::difference_type;
|
||||
};
|
||||
}
|
||||
|
||||
template <class M>
|
||||
class xvalue_iterator : xbidirectional_iterator_base3<xvalue_iterator<M>,
|
||||
detail::xvalue_iterator_types<M>>
|
||||
{
|
||||
public:
|
||||
|
||||
using self_type = xvalue_iterator<M>;
|
||||
using base_type = xbidirectional_iterator_base3<self_type, detail::xvalue_iterator_types<M>>;
|
||||
using value_type = typename base_type::value_type;
|
||||
using reference = typename base_type::reference;
|
||||
using pointer = typename base_type::pointer;
|
||||
using difference_type = typename base_type::difference_type;
|
||||
using subiterator = typename detail::xvalue_iterator_types<M>::subiterator;
|
||||
|
||||
inline xvalue_iterator(subiterator it) noexcept
|
||||
: m_it(it)
|
||||
{
|
||||
}
|
||||
|
||||
inline self_type& operator++()
|
||||
{
|
||||
++m_it;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline self_type& operator--()
|
||||
{
|
||||
--m_it;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline reference operator*() const
|
||||
{
|
||||
return m_it->second;
|
||||
}
|
||||
|
||||
inline pointer operator->() const
|
||||
{
|
||||
return&(m_it->second);
|
||||
}
|
||||
|
||||
inline bool operator==(const self_type& rhs) const
|
||||
{
|
||||
return m_it == rhs.m_it;
|
||||
}
|
||||
private:
|
||||
|
||||
subiterator m_it;
|
||||
};
|
||||
|
||||
/**********************
|
||||
* xstepping_iterator *
|
||||
**********************/
|
||||
|
||||
template <class It>
|
||||
class xstepping_iterator : public xrandom_access_iterator_base3<xstepping_iterator<It>,
|
||||
std::iterator_traits<It>>
|
||||
{
|
||||
public:
|
||||
|
||||
using self_type = xstepping_iterator;
|
||||
using base_type = xrandom_access_iterator_base3<self_type, std::iterator_traits<It>>;
|
||||
using value_type = typename base_type::value_type;
|
||||
using reference = typename base_type::reference;
|
||||
using pointer = typename base_type::pointer;
|
||||
using difference_type = typename base_type::difference_type;
|
||||
using iterator_category = typename base_type::iterator_category;
|
||||
using subiterator = It;
|
||||
|
||||
xstepping_iterator() = default;
|
||||
|
||||
inline xstepping_iterator(subiterator it, difference_type step) noexcept
|
||||
: m_it(it), m_step(step)
|
||||
{
|
||||
}
|
||||
|
||||
inline self_type& operator++()
|
||||
{
|
||||
std::advance(m_it, m_step);
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline self_type& operator--()
|
||||
{
|
||||
std::advance(m_it, -m_step);
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline self_type& operator+=(difference_type n)
|
||||
{
|
||||
std::advance(m_it, n*m_step);
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline self_type& operator-=(difference_type n)
|
||||
{
|
||||
std::advance(m_it, -n*m_step);
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline difference_type operator-(const self_type& rhs) const
|
||||
{
|
||||
return std::distance(rhs.m_it, m_it) / m_step;
|
||||
}
|
||||
|
||||
inline reference operator*() const
|
||||
{
|
||||
return *m_it;
|
||||
}
|
||||
|
||||
inline pointer operator->() const
|
||||
{
|
||||
return m_it;
|
||||
}
|
||||
|
||||
inline bool equal(const self_type& rhs) const
|
||||
{
|
||||
return m_it == rhs.m_it && m_step == rhs.m_step;
|
||||
}
|
||||
|
||||
inline bool less_than(const self_type& rhs) const
|
||||
{
|
||||
return m_it < rhs.m_it && m_step == rhs.m_step;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
subiterator m_it;
|
||||
difference_type m_step;
|
||||
};
|
||||
|
||||
template <class It>
|
||||
inline bool operator==(const xstepping_iterator<It>& lhs, const xstepping_iterator<It>& rhs)
|
||||
{
|
||||
return lhs.equal(rhs);
|
||||
}
|
||||
|
||||
template <class It>
|
||||
inline bool operator<(const xstepping_iterator<It>& lhs, const xstepping_iterator<It>& rhs)
|
||||
{
|
||||
return lhs.less_than(rhs);
|
||||
}
|
||||
|
||||
template <class It>
|
||||
inline xstepping_iterator<It> make_stepping_iterator(It it, typename std::iterator_traits<It>::difference_type step)
|
||||
{
|
||||
return xstepping_iterator<It>(it, step);
|
||||
}
|
||||
|
||||
/***********************
|
||||
* common_iterator_tag *
|
||||
***********************/
|
||||
|
||||
template <class... Its>
|
||||
struct common_iterator_tag : std::common_type<typename std::iterator_traits<Its>::iterator_category...>
|
||||
{
|
||||
};
|
||||
|
||||
template <class... Its>
|
||||
using common_iterator_tag_t = typename common_iterator_tag<Its...>::type;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,98 @@
|
|||
/***************************************************************************
|
||||
* Copyright (c) Johan Mabille, Sylvain Corlay and Wolf Vollprecht *
|
||||
* Copyright (c) QuantStack *
|
||||
* *
|
||||
* Distributed under the terms of the BSD 3-Clause License. *
|
||||
* *
|
||||
* The full license is in the file LICENSE, distributed with this software. *
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef XTL_JSON_HPP
|
||||
#define XTL_JSON_HPP
|
||||
|
||||
// WARNING:
|
||||
// All the code in this file and in the
|
||||
// files it includes must be C++11 compliant,
|
||||
// otherwise it breaks xeus-cling C++11 kernel
|
||||
|
||||
#include <cstddef>
|
||||
#include <string>
|
||||
#include "xtl/xvariant.hpp"
|
||||
#include "nlohmann/json.hpp"
|
||||
|
||||
namespace xtl
|
||||
{
|
||||
/***********************************************************
|
||||
* to_json and from_json specialization for xtl::xoptional *
|
||||
***********************************************************/
|
||||
|
||||
// xoptional forward declaration.
|
||||
template <class D, class B>
|
||||
class xoptional;
|
||||
|
||||
template <class T>
|
||||
xoptional<T, bool> missing() noexcept;
|
||||
|
||||
// to_json and from_json ADL overload
|
||||
template <class D, class B>
|
||||
void to_json(nlohmann::json& j, const xoptional<D, B>& o)
|
||||
{
|
||||
if (!o.has_value())
|
||||
{
|
||||
j = nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
j = o.value();
|
||||
}
|
||||
}
|
||||
|
||||
template <class D, class B>
|
||||
void from_json(const nlohmann::json& j, xoptional<D, B>& o)
|
||||
{
|
||||
if (j.is_null())
|
||||
{
|
||||
o = missing<D>();
|
||||
}
|
||||
else
|
||||
{
|
||||
o = j.get<D>();
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
* to_json and from_json specialization for xtl::basic_fixed_string *
|
||||
********************************************************************/
|
||||
|
||||
// xbasic_fixed_string forward declaration.
|
||||
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
|
||||
class xbasic_fixed_string;
|
||||
|
||||
// to_json and from_json ADL overload
|
||||
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
|
||||
void to_json(::nlohmann::json& j, const xbasic_fixed_string<CT, N, ST, EP, TR>& str)
|
||||
{
|
||||
j = str.c_str();
|
||||
}
|
||||
|
||||
template <class CT, std::size_t N, int ST, template <std::size_t> class EP, class TR>
|
||||
void from_json(const ::nlohmann::json& j, xbasic_fixed_string<CT, N, ST, EP, TR>& str)
|
||||
{
|
||||
str = j.get<std::string>();
|
||||
}
|
||||
}
|
||||
|
||||
// overloading in the mpark namespace because `xtl::variant` is just a typedef on `mpark::variant`
|
||||
namespace mpark
|
||||
{
|
||||
template <class... Ts>
|
||||
void to_json(nlohmann::json& j, const xtl::variant<Ts...>& data) {
|
||||
xtl::visit
|
||||
(
|
||||
[&j] (const auto & arg) { j = arg; },
|
||||
data
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,546 @@
|
|||
/***************************************************************************
|
||||
* Copyright (c) Johan Mabille, Sylvain Corlay, Wolf Vollprecht and *
|
||||
* Martin Renou *
|
||||
* Copyright (c) QuantStack *
|
||||
* *
|
||||
* Distributed under the terms of the BSD 3-Clause License. *
|
||||
* *
|
||||
* The full license is in the file LICENSE, distributed with this software. *
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef XTL_XMASKED_VALUE_HPP
|
||||
#define XTL_XMASKED_VALUE_HPP
|
||||
|
||||
#include "xmasked_value_meta.hpp"
|
||||
#include "xtype_traits.hpp"
|
||||
|
||||
namespace xtl
|
||||
{
|
||||
template <class T>
|
||||
inline xmasked_value<T, bool> masked() noexcept
|
||||
{
|
||||
return xmasked_value<T, bool>(T(0), false);
|
||||
}
|
||||
|
||||
/****************************
|
||||
* xmasked_value declaration *
|
||||
*****************************/
|
||||
|
||||
template <class T, class B>
|
||||
class xmasked_value
|
||||
{
|
||||
public:
|
||||
|
||||
using self_type = xmasked_value<T, B>;
|
||||
|
||||
using value_type = T;
|
||||
using flag_type = B;
|
||||
|
||||
template <class T1, class B1>
|
||||
constexpr xmasked_value(T1&& value, B1&& flag);
|
||||
|
||||
template <class T1>
|
||||
constexpr xmasked_value(T1&& value);
|
||||
|
||||
explicit constexpr xmasked_value();
|
||||
|
||||
inline operator value_type() {
|
||||
return m_value;
|
||||
}
|
||||
|
||||
std::add_lvalue_reference_t<T> value() & noexcept;
|
||||
std::add_lvalue_reference_t<std::add_const_t<T>> value() const & noexcept;
|
||||
std::conditional_t<std::is_reference<T>::value, apply_cv_t<T, std::decay_t<T>>&, std::decay_t<T>> value() && noexcept;
|
||||
std::conditional_t<std::is_reference<T>::value, const std::decay_t<T>&, std::decay_t<T>> value() const && noexcept;
|
||||
|
||||
std::add_lvalue_reference_t<B> visible() & noexcept;
|
||||
std::add_lvalue_reference_t<std::add_const_t<B>> visible() const & noexcept;
|
||||
std::conditional_t<std::is_reference<B>::value, apply_cv_t<B, std::decay_t<B>>&, std::decay_t<B>> visible() && noexcept;
|
||||
std::conditional_t<std::is_reference<B>::value, const std::decay_t<B>&, std::decay_t<B>> visible() const && noexcept;
|
||||
|
||||
template <class T1, class B1>
|
||||
bool equal(const xmasked_value<T1, B1>& rhs) const noexcept;
|
||||
|
||||
template <class T1, XTL_DISALLOW(is_xmasked_value<T1>)>
|
||||
bool equal(const T1& rhs) const noexcept;
|
||||
|
||||
template <class T1, class B1>
|
||||
void swap(xmasked_value<T1, B1>& other);
|
||||
|
||||
#define DEFINE_ASSIGN_OPERATOR(OP) \
|
||||
template <class T1> \
|
||||
inline xmasked_value& operator OP(const T1& rhs) \
|
||||
{ \
|
||||
if (m_visible) \
|
||||
{ \
|
||||
m_value OP rhs; \
|
||||
} \
|
||||
return *this; \
|
||||
} \
|
||||
\
|
||||
template <class T1, class B1> \
|
||||
inline xmasked_value& operator OP(const xmasked_value<T1, B1>& rhs) \
|
||||
{ \
|
||||
m_visible = m_visible && rhs.visible(); \
|
||||
if (m_visible) \
|
||||
{ \
|
||||
m_value OP rhs.value(); \
|
||||
} \
|
||||
return *this; \
|
||||
}
|
||||
|
||||
DEFINE_ASSIGN_OPERATOR(=);
|
||||
DEFINE_ASSIGN_OPERATOR(+=);
|
||||
DEFINE_ASSIGN_OPERATOR(-=);
|
||||
DEFINE_ASSIGN_OPERATOR(*=);
|
||||
DEFINE_ASSIGN_OPERATOR(/=);
|
||||
DEFINE_ASSIGN_OPERATOR(%=);
|
||||
DEFINE_ASSIGN_OPERATOR(&=);
|
||||
DEFINE_ASSIGN_OPERATOR(|=);
|
||||
DEFINE_ASSIGN_OPERATOR(^=);
|
||||
#undef DEFINE_ASSIGN_OPERATOR
|
||||
|
||||
private:
|
||||
|
||||
value_type m_value;
|
||||
flag_type m_visible;
|
||||
};
|
||||
|
||||
/********************************
|
||||
* xmasked_value implementation *
|
||||
********************************/
|
||||
|
||||
template <class T, class B>
|
||||
template <class T1, class B1>
|
||||
inline constexpr xmasked_value<T, B>::xmasked_value(T1&& value, B1&& flag)
|
||||
: m_value(std::forward<T1>(value)), m_visible(std::forward<B1>(flag))
|
||||
{
|
||||
}
|
||||
|
||||
template <class T, class B>
|
||||
template <class T1>
|
||||
inline constexpr xmasked_value<T, B>::xmasked_value(T1&& value)
|
||||
: m_value(std::forward<T1>(value)), m_visible(true)
|
||||
{
|
||||
}
|
||||
|
||||
template <class T, class B>
|
||||
inline constexpr xmasked_value<T, B>::xmasked_value()
|
||||
: m_value(0), m_visible(true)
|
||||
{
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline auto masked_value(T&& val)
|
||||
{
|
||||
return xmasked_value<T>(std::forward<T>(val));
|
||||
}
|
||||
|
||||
template <class T, class B>
|
||||
inline auto masked_value(T&& val, B&& mask)
|
||||
{
|
||||
return xmasked_value<T, B>(std::forward<T>(val), std::forward<B>(mask));
|
||||
}
|
||||
|
||||
template <class T, class B>
|
||||
inline auto xmasked_value<T, B>::value() & noexcept -> std::add_lvalue_reference_t<T>
|
||||
{
|
||||
return m_value;
|
||||
}
|
||||
|
||||
template <class T, class B>
|
||||
inline auto xmasked_value<T, B>::value() const & noexcept -> std::add_lvalue_reference_t<std::add_const_t<T>>
|
||||
{
|
||||
return m_value;
|
||||
}
|
||||
|
||||
template <class T, class B>
|
||||
inline auto xmasked_value<T, B>::value() && noexcept -> std::conditional_t<std::is_reference<T>::value, apply_cv_t<T, std::decay_t<T>>&, std::decay_t<T>>
|
||||
{
|
||||
return m_value;
|
||||
}
|
||||
|
||||
template <class T, class B>
|
||||
inline auto xmasked_value<T, B>::value() const && noexcept -> std::conditional_t<std::is_reference<T>::value, const std::decay_t<T>&, std::decay_t<T>>
|
||||
{
|
||||
return m_value;
|
||||
}
|
||||
|
||||
template <class T, class B>
|
||||
inline auto xmasked_value<T, B>::visible() & noexcept -> std::add_lvalue_reference_t<B>
|
||||
{
|
||||
return m_visible;
|
||||
}
|
||||
|
||||
template <class T, class B>
|
||||
inline auto xmasked_value<T, B>::visible() const & noexcept -> std::add_lvalue_reference_t<std::add_const_t<B>>
|
||||
{
|
||||
return m_visible;
|
||||
}
|
||||
|
||||
template <class T, class B>
|
||||
inline auto xmasked_value<T, B>::visible() && noexcept -> std::conditional_t<std::is_reference<B>::value, apply_cv_t<B, std::decay_t<B>>&, std::decay_t<B>>
|
||||
{
|
||||
return m_visible;
|
||||
}
|
||||
|
||||
template <class T, class B>
|
||||
inline auto xmasked_value<T, B>::visible() const && noexcept -> std::conditional_t<std::is_reference<B>::value, const std::decay_t<B>&, std::decay_t<B>>
|
||||
{
|
||||
return m_visible;
|
||||
}
|
||||
|
||||
template <class T, class B>
|
||||
template <class T1, class B1>
|
||||
inline bool xmasked_value<T, B>::equal(const xmasked_value<T1, B1>& rhs) const noexcept
|
||||
{
|
||||
return (!m_visible && !rhs.visible()) || (m_value == rhs.value() && (m_visible && rhs.visible()));
|
||||
}
|
||||
|
||||
template <class T, class B>
|
||||
template <class T1, check_disallow<is_xmasked_value<T1>>>
|
||||
inline bool xmasked_value<T, B>::equal(const T1& rhs) const noexcept
|
||||
{
|
||||
return m_visible && m_value == rhs;
|
||||
}
|
||||
|
||||
template <class T, class B>
|
||||
template <class T1, class B1>
|
||||
inline void xmasked_value<T, B>::swap(xmasked_value<T1, B1>& other)
|
||||
{
|
||||
using std::swap;
|
||||
swap(m_value, other.m_value);
|
||||
swap(m_visible, other.m_visible);
|
||||
}
|
||||
|
||||
template <class T1, class B1, class T2, class B2>
|
||||
inline bool operator==(const xmasked_value<T1, B1>& lhs, const xmasked_value<T2, B2>& rhs) noexcept
|
||||
{
|
||||
return lhs.equal(rhs);
|
||||
}
|
||||
|
||||
template <class T1, class T2, class B2, XTL_REQUIRES(negation<is_xmasked_value<T1>>)>
|
||||
inline bool operator==(const T1& lhs, const xmasked_value<T2, B2>& rhs) noexcept
|
||||
{
|
||||
return rhs.equal(lhs);
|
||||
}
|
||||
|
||||
template <class T1, class B1, class T2, XTL_REQUIRES(negation<is_xmasked_value<T2>>)>
|
||||
inline bool operator==(const xmasked_value<T1, B1>& lhs, const T2& rhs) noexcept
|
||||
{
|
||||
return lhs.equal(rhs);
|
||||
}
|
||||
|
||||
template <class T1, class B1, class T2, class B2>
|
||||
inline bool operator!=(const xmasked_value<T1, B1>& lhs, const xmasked_value<T2, B2>& rhs) noexcept
|
||||
{
|
||||
return !lhs.equal(rhs);
|
||||
}
|
||||
|
||||
template <class T1, class T2, class B2, XTL_REQUIRES(negation<is_xmasked_value<T1>>)>
|
||||
inline bool operator!=(const T1& lhs, const xmasked_value<T2, B2>& rhs) noexcept
|
||||
{
|
||||
return !rhs.equal(lhs);
|
||||
}
|
||||
|
||||
template <class T1, class B1, class T2, XTL_REQUIRES(negation<is_xmasked_value<T2>>)>
|
||||
inline bool operator!=(const xmasked_value<T1, B1>& lhs, const T2& rhs) noexcept
|
||||
{
|
||||
return !lhs.equal(rhs);
|
||||
}
|
||||
|
||||
template <class T, class B>
|
||||
inline auto operator+(const xmasked_value<T, B>& e) noexcept
|
||||
-> xmasked_value<std::decay_t<T>, std::decay_t<B>>
|
||||
{
|
||||
return xmasked_value<std::decay_t<T>, std::decay_t<B>>(e.value(), e.visible());
|
||||
}
|
||||
|
||||
template <class T, class B>
|
||||
inline auto operator-(const xmasked_value<T, B>& e) noexcept
|
||||
-> xmasked_value<std::decay_t<T>, std::decay_t<B>>
|
||||
{
|
||||
return xmasked_value<std::decay_t<T>, std::decay_t<B>>(-e.value(), e.visible());
|
||||
}
|
||||
|
||||
template <class T, class B>
|
||||
inline auto operator~(const xmasked_value<T, B>& e) noexcept
|
||||
-> xmasked_value<std::decay_t<T>>
|
||||
{
|
||||
using value_type = std::decay_t<T>;
|
||||
return e.visible() ? masked_value(~e.value()) : masked<value_type>();
|
||||
}
|
||||
|
||||
template <class T, class B>
|
||||
inline auto operator!(const xmasked_value<T, B>& e) noexcept -> xmasked_value<decltype(!e.value())>
|
||||
{
|
||||
using return_type = xmasked_value<decltype(!e.value())>;
|
||||
using value_type = typename return_type::value_type;
|
||||
return e.visible() ? return_type(!e.value()) : masked<value_type>();
|
||||
}
|
||||
|
||||
template <class T, class B, class OC, class OT>
|
||||
inline std::basic_ostream<OC, OT>& operator<<(std::basic_ostream<OC, OT>& out, xmasked_value<T, B> v)
|
||||
{
|
||||
if (v.visible())
|
||||
{
|
||||
out << v.value();
|
||||
}
|
||||
else
|
||||
{
|
||||
out << "masked";
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
template <class T1, class B1, class T2, class B2>
|
||||
inline void swap(xmasked_value<T1, B1>& lhs, xmasked_value<T2, B2>& rhs)
|
||||
{
|
||||
lhs.swap(rhs);
|
||||
}
|
||||
|
||||
#define DEFINE_OPERATOR(OP) \
|
||||
template <class T1, class B1, class T2, class B2> \
|
||||
inline auto operator OP(const xmasked_value<T1, B1>& e1, const xmasked_value<T2, B2>& e2) noexcept \
|
||||
-> xmasked_value<promote_type_t<std::decay_t<T1>, std::decay_t<T2>>> \
|
||||
{ \
|
||||
using value_type = promote_type_t<std::decay_t<T1>, std::decay_t<T2>>; \
|
||||
return e1.visible() && e2.visible() ? masked_value(e1.value() OP e2.value()) : masked<value_type>(); \
|
||||
} \
|
||||
\
|
||||
template <class T1, class B1, class T2, XTL_REQUIRES(negation<is_xmasked_value<T2>>)> \
|
||||
inline auto operator OP(const xmasked_value<T1, B1>& e1, const T2& e2) noexcept \
|
||||
-> xmasked_value<promote_type_t<std::decay_t<T1>, std::decay_t<T2>>> \
|
||||
{ \
|
||||
using value_type = promote_type_t<std::decay_t<T1>, std::decay_t<T2>>; \
|
||||
return e1.visible() ? masked_value(e1.value() OP e2) : masked<value_type>(); \
|
||||
} \
|
||||
\
|
||||
template <class T1, class T2, class B2, XTL_REQUIRES(negation<is_xmasked_value<T1>>)> \
|
||||
inline auto operator OP(const T1& e1, const xmasked_value<T2, B2>& e2) noexcept \
|
||||
-> xmasked_value<promote_type_t<std::decay_t<T1>, std::decay_t<T2>>> \
|
||||
{ \
|
||||
using value_type = promote_type_t<std::decay_t<T1>, std::decay_t<T2>>; \
|
||||
return e2.visible() ? masked_value(e1 OP e2.value()) : masked<value_type>(); \
|
||||
}
|
||||
|
||||
#define DEFINE_BOOL_OPERATOR(OP) \
|
||||
template <class T1, class B1, class T2, class B2> \
|
||||
inline auto operator OP(const xmasked_value<T1, B1>& e1, const xmasked_value<T2, B2>& e2) noexcept \
|
||||
-> xmasked_value<decltype(e1.value() OP e2.value())> \
|
||||
{ \
|
||||
return e1.visible() && e2.visible() ? \
|
||||
masked_value(e1.value() OP e2.value()) : \
|
||||
masked<decltype(e1.value() OP e2.value())>(); \
|
||||
} \
|
||||
\
|
||||
template <class T1, class B1, class T2, XTL_REQUIRES(negation<is_xmasked_value<T2>>)> \
|
||||
inline auto operator OP(const xmasked_value<T1, B1>& e1, const T2& e2) noexcept \
|
||||
-> xmasked_value<decltype(e1.value() OP e2)> \
|
||||
{ \
|
||||
return e1.visible() ? masked_value(e1.value() OP e2) : masked<decltype(e1.value() OP e2)>(); \
|
||||
} \
|
||||
\
|
||||
template <class T1, class T2, class B2, XTL_REQUIRES(negation<is_xmasked_value<T1>>)> \
|
||||
inline auto operator OP(const T1& e1, const xmasked_value<T2, B2>& e2) noexcept \
|
||||
-> xmasked_value<decltype(e1 OP e2.value())> \
|
||||
{ \
|
||||
return e2.visible() ? masked_value(e1 OP e2.value()) : masked<decltype(e1 OP e2.value())>(); \
|
||||
}
|
||||
|
||||
#define DEFINE_UNARY_OPERATOR(OP) \
|
||||
template <class T, class B> \
|
||||
inline xmasked_value<std::decay_t<T>> OP(const xmasked_value<T, B>& e) \
|
||||
{ \
|
||||
using std::OP; \
|
||||
return e.visible() ? masked_value(OP(e.value())) : masked<std::decay_t<T>>(); \
|
||||
}
|
||||
|
||||
#define DEFINE_UNARY_BOOL_OPERATOR(OP) \
|
||||
template <class T, class B> \
|
||||
inline auto OP(const xmasked_value<T, B>& e) \
|
||||
{ \
|
||||
using std::OP; \
|
||||
return e.visible() ? masked_value(OP(e.value())) : masked<decltype(OP(e.value()))>(); \
|
||||
}
|
||||
|
||||
#define DEFINE_BINARY_OPERATOR(OP) \
|
||||
template <class T1, class B1, class T2, class B2> \
|
||||
inline auto OP(const xmasked_value<T1, B1>& e1, const xmasked_value<T2, B2>& e2) \
|
||||
{ \
|
||||
using std::OP; \
|
||||
return e1.visible() && e2.visible() ? \
|
||||
masked_value(OP(e1.value(), e2.value())) : \
|
||||
masked<decltype(OP(e1.value(), e2.value()))>(); \
|
||||
} \
|
||||
\
|
||||
template <class T1, class B1, class T2> \
|
||||
inline auto OP(const xmasked_value<T1, B1>& e1, const T2& e2) \
|
||||
{ \
|
||||
using std::OP; \
|
||||
return e1.visible() ? masked_value(OP(e1.value(), e2)) : masked<decltype(OP(e1.value(), e2))>(); \
|
||||
} \
|
||||
\
|
||||
template <class T1, class T2, class B2> \
|
||||
inline auto OP(const T1& e1, const xmasked_value<T2, B2>& e2) \
|
||||
{ \
|
||||
using std::OP; \
|
||||
return e2.visible() ? masked_value(OP(e1, e2.value())) : masked<decltype(OP(e1, e2.value()))>(); \
|
||||
}
|
||||
|
||||
#define DEFINE_TERNARY_OPERATOR_MMM(OP) \
|
||||
template <class T1, class B1, class T2, class B2, class T3, class B3> \
|
||||
inline auto OP(const xmasked_value<T1, B1>& e1, const xmasked_value<T2, B2>& e2, const xmasked_value<T3, B3>& e3) \
|
||||
{ \
|
||||
using std::OP; \
|
||||
return (e1.visible() && e2.visible() && e3.visible()) ? \
|
||||
masked_value(OP(e1.value(), e2.value(), e3.value())) : \
|
||||
masked<decltype(OP(e1.value(), e2.value(), e3.value()))>(); \
|
||||
}
|
||||
|
||||
#define DEFINE_TERNARY_OPERATOR_MMT(OP) \
|
||||
template <class T1, class B1, class T2, class B2, class T3> \
|
||||
inline auto OP(const xmasked_value<T1, B1>& e1, const xmasked_value<T2, B2>& e2, const T3& e3) \
|
||||
{ \
|
||||
using std::OP; \
|
||||
return (e1.visible() && e2.visible()) ? \
|
||||
masked_value(OP(e1.value(), e2.value(), e3)) : \
|
||||
masked<decltype(OP(e1.value(), e2.value(), e3))>(); \
|
||||
}
|
||||
|
||||
#define DEFINE_TERNARY_OPERATOR_MTM(OP) \
|
||||
template <class T1, class B1, class T2, class T3, class B3> \
|
||||
inline auto OP(const xmasked_value<T1, B1>& e1, const T2& e2, const xmasked_value<T3, B3>& e3) \
|
||||
{ \
|
||||
using std::OP; \
|
||||
return (e1.visible() && e3.visible()) ? \
|
||||
masked_value(OP(e1.value(), e2, e3.value())) : \
|
||||
masked<decltype(OP(e1.value(), e2, e3.value()))>(); \
|
||||
}
|
||||
|
||||
#define DEFINE_TERNARY_OPERATOR_TMM(OP) \
|
||||
template <class T1, class T2, class B2, class T3, class B3> \
|
||||
inline auto OP(const T1& e1, const xmasked_value<T2, B2>& e2, const xmasked_value<T3, B3>& e3) \
|
||||
{ \
|
||||
using std::OP; \
|
||||
return (e2.visible() && e3.visible()) ? \
|
||||
masked_value(OP(e1, e2.value(), e3.value())) : \
|
||||
masked<decltype(OP(e1, e2.value(), e3.value()))>(); \
|
||||
}
|
||||
|
||||
#define DEFINE_TERNARY_OPERATOR_TTM(OP) \
|
||||
template <class T1, class T2, class T3, class B3> \
|
||||
inline auto OP(const T1& e1, const T2& e2, const xmasked_value<T3, B3>& e3) \
|
||||
{ \
|
||||
using std::OP; \
|
||||
return e3.visible() ? \
|
||||
masked_value(OP(e1, e2, e3.value())) : \
|
||||
masked<decltype(OP(e1, e2, e3.value()))>(); \
|
||||
}
|
||||
|
||||
#define DEFINE_TERNARY_OPERATOR_TMT(OP) \
|
||||
template <class T1, class T2, class B2, class T3> \
|
||||
inline auto OP(const T1& e1, const xmasked_value<T2, B2>& e2, const T3& e3) \
|
||||
{ \
|
||||
using std::OP; \
|
||||
return e2.visible() ? \
|
||||
masked_value(OP(e1, e2.value(), e3)) : \
|
||||
masked<decltype(OP(e1, e2.value(), e3))>(); \
|
||||
}
|
||||
|
||||
#define DEFINE_TERNARY_OPERATOR_MTT(OP) \
|
||||
template <class T1, class B1, class T2, class T3> \
|
||||
inline auto OP(const xmasked_value<T1, B1>& e1, const T2& e2, const T3& e3) \
|
||||
{ \
|
||||
using std::OP; \
|
||||
return e1.visible() ? \
|
||||
masked_value(OP(e1.value(), e2, e3)) : \
|
||||
masked<decltype(OP(e1.value(), e2, e3))>(); \
|
||||
}
|
||||
|
||||
#define DEFINE_TERNARY_OPERATOR(OP) \
|
||||
DEFINE_TERNARY_OPERATOR_MMM(OP) \
|
||||
\
|
||||
DEFINE_TERNARY_OPERATOR_MMT(OP) \
|
||||
DEFINE_TERNARY_OPERATOR_MTM(OP) \
|
||||
DEFINE_TERNARY_OPERATOR_TMM(OP) \
|
||||
DEFINE_TERNARY_OPERATOR_TTM(OP) \
|
||||
DEFINE_TERNARY_OPERATOR_TMT(OP) \
|
||||
DEFINE_TERNARY_OPERATOR_MTT(OP)
|
||||
|
||||
DEFINE_OPERATOR(+);
|
||||
DEFINE_OPERATOR(-);
|
||||
DEFINE_OPERATOR(*);
|
||||
DEFINE_OPERATOR(/);
|
||||
DEFINE_OPERATOR(%);
|
||||
DEFINE_BOOL_OPERATOR(||);
|
||||
DEFINE_BOOL_OPERATOR(&&);
|
||||
DEFINE_OPERATOR(&);
|
||||
DEFINE_OPERATOR(|);
|
||||
DEFINE_OPERATOR(^);
|
||||
DEFINE_BOOL_OPERATOR(<);
|
||||
DEFINE_BOOL_OPERATOR(<=);
|
||||
DEFINE_BOOL_OPERATOR(>);
|
||||
DEFINE_BOOL_OPERATOR(>=);
|
||||
DEFINE_UNARY_OPERATOR(abs)
|
||||
DEFINE_UNARY_OPERATOR(fabs)
|
||||
DEFINE_UNARY_OPERATOR(exp)
|
||||
DEFINE_UNARY_OPERATOR(exp2)
|
||||
DEFINE_UNARY_OPERATOR(expm1)
|
||||
DEFINE_UNARY_OPERATOR(log)
|
||||
DEFINE_UNARY_OPERATOR(log10)
|
||||
DEFINE_UNARY_OPERATOR(log2)
|
||||
DEFINE_UNARY_OPERATOR(log1p)
|
||||
DEFINE_UNARY_OPERATOR(sqrt)
|
||||
DEFINE_UNARY_OPERATOR(cbrt)
|
||||
DEFINE_UNARY_OPERATOR(sin)
|
||||
DEFINE_UNARY_OPERATOR(cos)
|
||||
DEFINE_UNARY_OPERATOR(tan)
|
||||
DEFINE_UNARY_OPERATOR(acos)
|
||||
DEFINE_UNARY_OPERATOR(asin)
|
||||
DEFINE_UNARY_OPERATOR(atan)
|
||||
DEFINE_UNARY_OPERATOR(sinh)
|
||||
DEFINE_UNARY_OPERATOR(cosh)
|
||||
DEFINE_UNARY_OPERATOR(tanh)
|
||||
DEFINE_UNARY_OPERATOR(acosh)
|
||||
DEFINE_UNARY_OPERATOR(asinh)
|
||||
DEFINE_UNARY_OPERATOR(atanh)
|
||||
DEFINE_UNARY_OPERATOR(erf)
|
||||
DEFINE_UNARY_OPERATOR(erfc)
|
||||
DEFINE_UNARY_OPERATOR(tgamma)
|
||||
DEFINE_UNARY_OPERATOR(lgamma)
|
||||
DEFINE_UNARY_OPERATOR(ceil)
|
||||
DEFINE_UNARY_OPERATOR(floor)
|
||||
DEFINE_UNARY_OPERATOR(trunc)
|
||||
DEFINE_UNARY_OPERATOR(round)
|
||||
DEFINE_UNARY_OPERATOR(nearbyint)
|
||||
DEFINE_UNARY_OPERATOR(rint)
|
||||
DEFINE_UNARY_BOOL_OPERATOR(isfinite)
|
||||
DEFINE_UNARY_BOOL_OPERATOR(isinf)
|
||||
DEFINE_UNARY_BOOL_OPERATOR(isnan)
|
||||
DEFINE_BINARY_OPERATOR(fmod)
|
||||
DEFINE_BINARY_OPERATOR(remainder)
|
||||
DEFINE_BINARY_OPERATOR(fmax)
|
||||
DEFINE_BINARY_OPERATOR(fmin)
|
||||
DEFINE_BINARY_OPERATOR(fdim)
|
||||
DEFINE_BINARY_OPERATOR(pow)
|
||||
DEFINE_BINARY_OPERATOR(hypot)
|
||||
DEFINE_BINARY_OPERATOR(atan2)
|
||||
DEFINE_TERNARY_OPERATOR(fma)
|
||||
|
||||
#undef DEFINE_TERNARY_OPERATOR
|
||||
#undef DEFINE_TERNARY_OPERATOR_MMM
|
||||
#undef DEFINE_TERNARY_OPERATOR_MMT
|
||||
#undef DEFINE_TERNARY_OPERATOR_MTM
|
||||
#undef DEFINE_TERNARY_OPERATOR_TMM
|
||||
#undef DEFINE_TERNARY_OPERATOR_TTM
|
||||
#undef DEFINE_TERNARY_OPERATOR_TMT
|
||||
#undef DEFINE_TERNARY_OPERATOR_MTT
|
||||
#undef DEFINE_BINARY_OPERATOR
|
||||
#undef DEFINE_UNARY_OPERATOR
|
||||
#undef DEFINE_UNARY_BOOL_OPERATOR
|
||||
#undef DEFINE_OPERATOR
|
||||
#undef DEFINE_BOOL_OPERATOR
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,41 @@
|
|||
/***************************************************************************
|
||||
* Copyright (c) Johan Mabille, Sylvain Corlay, Wolf Vollprecht and *
|
||||
* Martin Renou *
|
||||
* Copyright (c) QuantStack *
|
||||
* *
|
||||
* Distributed under the terms of the BSD 3-Clause License. *
|
||||
* *
|
||||
* The full license is in the file LICENSE, distributed with this software. *
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef XTL_XMASKED_VALUE_META_HPP
|
||||
#define XTL_XMASKED_VALUE_META_HPP
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
namespace xtl
|
||||
{
|
||||
template <class T, class B = bool>
|
||||
class xmasked_value;
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <class E>
|
||||
struct is_xmasked_value_impl : std::false_type
|
||||
{
|
||||
};
|
||||
|
||||
template <class T, class B>
|
||||
struct is_xmasked_value_impl<xmasked_value<T, B>> : std::true_type
|
||||
{
|
||||
};
|
||||
}
|
||||
|
||||
template <class E>
|
||||
using is_xmasked_value = detail::is_xmasked_value_impl<E>;
|
||||
|
||||
template <class E, class R>
|
||||
using disable_xmasked_value = std::enable_if_t<!is_xmasked_value<E>::value, R>;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,640 @@
|
|||
/***************************************************************************
|
||||
* Copyright (c) Johan Mabille, Sylvain Corlay and Wolf Vollprecht *
|
||||
* Copyright (c) QuantStack *
|
||||
* *
|
||||
* Distributed under the terms of the BSD 3-Clause License. *
|
||||
* *
|
||||
* The full license is in the file LICENSE, distributed with this software. *
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef XTL_XMETA_UTILS_HPP
|
||||
#define XTL_XMETA_UTILS_HPP
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <type_traits>
|
||||
|
||||
#include "xfunctional.hpp"
|
||||
#include "xtl_config.hpp"
|
||||
|
||||
namespace xtl
|
||||
{
|
||||
// TODO move to a xutils if we have one
|
||||
|
||||
// gcc 4.9 is affected by C++14 defect CGW 1558
|
||||
// see http://open-std.org/JTC1/SC22/WG21/docs/cwg_defects.html#1558
|
||||
template <class... T>
|
||||
struct make_void
|
||||
{
|
||||
using type = void;
|
||||
};
|
||||
|
||||
template <class... T>
|
||||
using void_t = typename make_void<T...>::type;
|
||||
|
||||
namespace mpl
|
||||
{
|
||||
/*************
|
||||
* mpl types *
|
||||
*************/
|
||||
|
||||
template <class... T>
|
||||
struct vector
|
||||
{
|
||||
};
|
||||
|
||||
template <bool B>
|
||||
using bool_ = std::integral_constant<bool, B>;
|
||||
|
||||
template <std::size_t S>
|
||||
using size_t_ = std::integral_constant<std::size_t, S>;
|
||||
|
||||
/*******
|
||||
* if_ *
|
||||
*******/
|
||||
|
||||
template <bool B, class T, class F>
|
||||
struct if_c : std::conditional<B, T, F>
|
||||
{
|
||||
};
|
||||
|
||||
template <bool B, class T, class F>
|
||||
using if_c_t = typename if_c<B, T, F>::type;
|
||||
|
||||
template <class B, class T, class F>
|
||||
struct if_ : if_c<B::value, T, F>
|
||||
{
|
||||
};
|
||||
|
||||
template <class B, class T, class F>
|
||||
using if_t = typename if_<B, T, F>::type;
|
||||
|
||||
/***********
|
||||
* eval_if *
|
||||
***********/
|
||||
|
||||
template <bool B, class T, class F>
|
||||
struct eval_if_c
|
||||
{
|
||||
using type = typename T::type;
|
||||
};
|
||||
|
||||
template <class T, class F>
|
||||
struct eval_if_c<false, T, F>
|
||||
{
|
||||
using type = typename F::type;
|
||||
};
|
||||
|
||||
template <class B, class T, class F>
|
||||
struct eval_if : eval_if_c<B::value, T, F>
|
||||
{
|
||||
};
|
||||
|
||||
template <class B, class T, class F>
|
||||
using eval_if_t = typename eval_if<B, T, F>::type;
|
||||
|
||||
/********
|
||||
* cast *
|
||||
********/
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <class A, template <class...> class B>
|
||||
struct cast_impl;
|
||||
|
||||
template <template <class...> class A, class... T, template <class...> class B>
|
||||
struct cast_impl<A<T...>, B>
|
||||
{
|
||||
using type = B<T...>;
|
||||
};
|
||||
}
|
||||
|
||||
template <class A, template <class...> class B>
|
||||
struct cast : detail::cast_impl<A, B>
|
||||
{
|
||||
};
|
||||
|
||||
template <class A, template <class...> class B>
|
||||
using cast_t = typename cast<A, B>::type;
|
||||
|
||||
/********
|
||||
* size *
|
||||
********/
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <class L>
|
||||
struct size_impl;
|
||||
|
||||
template <template <class...> class F, class... T>
|
||||
struct size_impl<F<T...>> : size_t_<sizeof...(T)>
|
||||
{
|
||||
};
|
||||
}
|
||||
|
||||
template <class L>
|
||||
struct size : detail::size_impl<L>
|
||||
{
|
||||
};
|
||||
|
||||
/*********
|
||||
* empty *
|
||||
*********/
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <class L>
|
||||
struct empty_impl;
|
||||
|
||||
template <template <class...> class F, class... T>
|
||||
struct empty_impl<F<T...>> : bool_<sizeof...(T) == std::size_t(0)>
|
||||
{
|
||||
};
|
||||
}
|
||||
|
||||
template <class L>
|
||||
struct empty : detail::empty_impl<L>
|
||||
{
|
||||
};
|
||||
|
||||
template <class L>
|
||||
using empty_t = typename empty<L>::type;
|
||||
|
||||
/********
|
||||
* plus *
|
||||
********/
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <class... T>
|
||||
struct plus_impl;
|
||||
|
||||
template <>
|
||||
struct plus_impl<> : size_t_<0>
|
||||
{
|
||||
};
|
||||
|
||||
template <class T1, class... T>
|
||||
struct plus_impl<T1, T...> : size_t_<T1::value + plus_impl<T...>::value>
|
||||
{
|
||||
};
|
||||
}
|
||||
|
||||
template <class... T>
|
||||
struct plus : detail::plus_impl<T...>
|
||||
{
|
||||
};
|
||||
|
||||
/*********
|
||||
* count *
|
||||
*********/
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <class L, class V>
|
||||
struct count_impl;
|
||||
|
||||
template <template <class...> class L, class... T, class V>
|
||||
struct count_impl<L<T...>, V> : plus<std::is_same<T, V>...>
|
||||
{
|
||||
};
|
||||
}
|
||||
|
||||
template <class L, class V>
|
||||
struct count : detail::count_impl<L, V>
|
||||
{
|
||||
};
|
||||
|
||||
/************
|
||||
* count_if *
|
||||
************/
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <class L, template <class> class P>
|
||||
struct count_if_impl;
|
||||
|
||||
template <template <class...> class L, class... T, template <class> class P>
|
||||
struct count_if_impl<L<T...>, P> : plus<P<T>...>
|
||||
{
|
||||
};
|
||||
}
|
||||
|
||||
template <class L, template <class> class P>
|
||||
struct count_if : detail::count_if_impl<L, P>
|
||||
{
|
||||
};
|
||||
|
||||
/************
|
||||
* index_of *
|
||||
************/
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <class L, class V>
|
||||
struct index_of_impl;
|
||||
|
||||
template <template <class...> class L, class V>
|
||||
struct index_of_impl<L<>, V>
|
||||
{
|
||||
static constexpr size_t value = SIZE_MAX;
|
||||
};
|
||||
|
||||
template <template <class...> class L, class... T, class V>
|
||||
struct index_of_impl<L<V, T...>, V>
|
||||
{
|
||||
static constexpr size_t value = 0u;
|
||||
};
|
||||
|
||||
template <template <class...> class L, class U, class... T, class V>
|
||||
struct index_of_impl<L<U, T...>, V>
|
||||
{
|
||||
static constexpr size_t tmp = index_of_impl<L<T...>, V>::value;
|
||||
static constexpr size_t value = tmp == SIZE_MAX ? SIZE_MAX : 1u + tmp;
|
||||
};
|
||||
}
|
||||
|
||||
template <class L, class T>
|
||||
struct index_of : detail::index_of_impl<L, T>
|
||||
{
|
||||
};
|
||||
|
||||
/************
|
||||
* contains *
|
||||
************/
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <class L, class V>
|
||||
struct contains_impl;
|
||||
|
||||
template <template <class...> class L, class V>
|
||||
struct contains_impl<L<>, V> : std::false_type
|
||||
{
|
||||
};
|
||||
|
||||
template <template <class...> class L, class... T, class V>
|
||||
struct contains_impl<L<V, T...>, V> : std::true_type
|
||||
{
|
||||
};
|
||||
|
||||
template <template <class...> class L, class U, class... T, class V>
|
||||
struct contains_impl<L<U, T...>, V> : contains_impl<L<T...>, V>
|
||||
{
|
||||
};
|
||||
}
|
||||
|
||||
template <class L, class V>
|
||||
struct contains : detail::contains_impl<L, V>
|
||||
{
|
||||
};
|
||||
|
||||
/*********
|
||||
* front *
|
||||
*********/
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <class L>
|
||||
struct front_impl;
|
||||
|
||||
template <template <class...> class L, class T, class... U>
|
||||
struct front_impl<L<T, U...>>
|
||||
{
|
||||
using type = T;
|
||||
};
|
||||
}
|
||||
|
||||
template <class L>
|
||||
struct front : detail::front_impl<L>
|
||||
{
|
||||
};
|
||||
|
||||
template <class L>
|
||||
using front_t = typename front<L>::type;
|
||||
|
||||
/********
|
||||
* back *
|
||||
********/
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <class L>
|
||||
struct back_impl;
|
||||
|
||||
template <template <class...> class L, class T>
|
||||
struct back_impl<L<T>>
|
||||
{
|
||||
using type = T;
|
||||
};
|
||||
|
||||
// Compilation time improvement
|
||||
template <template <class...> class L, class T1, class T2>
|
||||
struct back_impl<L<T1, T2>>
|
||||
{
|
||||
using type = T2;
|
||||
};
|
||||
|
||||
template <template <class...> class L, class T1, class T2, class T3>
|
||||
struct back_impl<L<T1, T2, T3>>
|
||||
{
|
||||
using type = T3;
|
||||
};
|
||||
|
||||
template <template <class...> class L, class T1, class T2, class T3, class T4>
|
||||
struct back_impl<L<T1, T2, T3, T4>>
|
||||
{
|
||||
using type = T4;
|
||||
};
|
||||
|
||||
template <template <class...> class L, class T, class... U>
|
||||
struct back_impl<L<T, U...>> : back_impl<L<U...>>
|
||||
{
|
||||
};
|
||||
}
|
||||
|
||||
template <class L>
|
||||
struct back : detail::back_impl<L>
|
||||
{
|
||||
};
|
||||
|
||||
template <class L>
|
||||
using back_t = typename back<L>::type;
|
||||
|
||||
/**************
|
||||
* push_front *
|
||||
**************/
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <class L, class... T>
|
||||
struct push_front_impl;
|
||||
|
||||
template <template <class...> class L, class... U, class... T>
|
||||
struct push_front_impl<L<U...>, T...>
|
||||
{
|
||||
using type = L<T..., U...>;
|
||||
};
|
||||
}
|
||||
|
||||
template <class L, class... T>
|
||||
struct push_front : detail::push_front_impl<L, T...>
|
||||
{
|
||||
};
|
||||
|
||||
template <class L, class... T>
|
||||
using push_front_t = typename push_front<L, T...>::type;
|
||||
|
||||
/*************
|
||||
* push_back *
|
||||
*************/
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <class L, class... T>
|
||||
struct push_back_impl;
|
||||
|
||||
template <template <class...> class L, class... U, class... T>
|
||||
struct push_back_impl<L<U...>, T...>
|
||||
{
|
||||
using type = L<U..., T...>;
|
||||
};
|
||||
}
|
||||
|
||||
template <class L, class... T>
|
||||
struct push_back : detail::push_back_impl<L, T...>
|
||||
{
|
||||
};
|
||||
|
||||
template <class L, class... T>
|
||||
using push_back_t = typename push_back<L, T...>::type;
|
||||
|
||||
/*************
|
||||
* pop_front *
|
||||
*************/
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <class L>
|
||||
struct pop_front_impl;
|
||||
|
||||
template <template <class...> class L, class T, class... U>
|
||||
struct pop_front_impl<L<T, U...>>
|
||||
{
|
||||
using type = L<U...>;
|
||||
};
|
||||
}
|
||||
|
||||
template <class L>
|
||||
struct pop_front : detail::pop_front_impl<L>
|
||||
{
|
||||
};
|
||||
|
||||
template <class L>
|
||||
using pop_front_t = typename pop_front<L>::type;
|
||||
|
||||
/*************
|
||||
* transform *
|
||||
*************/
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <template <class...> class F, class L>
|
||||
struct transform_impl;
|
||||
|
||||
template <template <class...> class F, template <class...> class L, class... T>
|
||||
struct transform_impl<F, L<T...>>
|
||||
{
|
||||
using type = L<F<T>...>;
|
||||
};
|
||||
}
|
||||
|
||||
template <template <class...> class F, class L>
|
||||
struct transform : detail::transform_impl<F, L>
|
||||
{
|
||||
};
|
||||
|
||||
template <template <class...> class F, class L>
|
||||
using transform_t = typename transform<F, L>::type;
|
||||
|
||||
/*************
|
||||
* merge_set *
|
||||
*************/
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <class S1, class S2>
|
||||
struct merge_set_impl;
|
||||
|
||||
template <template <class...> class L, class... T>
|
||||
struct merge_set_impl<L<T...>, L<>>
|
||||
{
|
||||
using type = L<T...>;
|
||||
};
|
||||
|
||||
template <template <class...> class L, class... T, class U1, class... U>
|
||||
struct merge_set_impl<L<T...>, L<U1, U...>>
|
||||
{
|
||||
using type = typename merge_set_impl<if_t<contains<L<T...>, U1>,
|
||||
L<T...>,
|
||||
L<T..., U1>>,
|
||||
L<U...>>::type;
|
||||
};
|
||||
}
|
||||
|
||||
template <class S1, class S2>
|
||||
struct merge_set : detail::merge_set_impl<S1, S2>
|
||||
{
|
||||
};
|
||||
|
||||
template <class S1, class S2>
|
||||
using merge_set_t = typename merge_set<S1, S2>::type;
|
||||
|
||||
/***********
|
||||
* find_if *
|
||||
***********/
|
||||
|
||||
template <template <class> class Test, class L>
|
||||
struct find_if;
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <template <class> class Test, std::size_t I, class... T>
|
||||
struct find_if_impl;
|
||||
|
||||
template <template <class> class Test, std::size_t I>
|
||||
struct find_if_impl<Test, I> : size_t_<I>
|
||||
{
|
||||
};
|
||||
|
||||
template <template <class> class Test, std::size_t I, class T0, class... T>
|
||||
struct find_if_impl<Test, I, T0, T...> : std::conditional_t<Test<T0>::value,
|
||||
size_t_<I>,
|
||||
find_if_impl<Test, I + 1, T...>>
|
||||
{
|
||||
};
|
||||
}
|
||||
|
||||
template <template <class> class Test, template <class...> class L, class... T>
|
||||
struct find_if<Test, L<T...>> : detail::find_if_impl<Test, 0, T...>
|
||||
{
|
||||
};
|
||||
|
||||
/*********
|
||||
* split *
|
||||
*********/
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <std::size_t N, class L1, class L2>
|
||||
struct transfer
|
||||
{
|
||||
using new_l1 = push_back_t<L1, front_t<L2>>;
|
||||
using new_l2 = pop_front_t<L2>;
|
||||
using new_transfer = transfer<N - 1, new_l1, new_l2>;
|
||||
using first_type = typename new_transfer::first_type;
|
||||
using second_type = typename new_transfer::second_type;
|
||||
};
|
||||
|
||||
template <class L1, class L2>
|
||||
struct transfer<0, L1, L2>
|
||||
{
|
||||
using first_type = L1;
|
||||
using second_type = L2;
|
||||
};
|
||||
|
||||
template <std::size_t N, class L>
|
||||
struct split_impl
|
||||
{
|
||||
using tr_type = transfer<N, vector<>, L>;
|
||||
using first_type = typename tr_type::first_type;
|
||||
using second_type = typename tr_type::second_type;
|
||||
};
|
||||
}
|
||||
|
||||
template <std::size_t N, class L>
|
||||
struct split : detail::split_impl<N, L>
|
||||
{
|
||||
};
|
||||
|
||||
/**********
|
||||
* unique *
|
||||
**********/
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <class L>
|
||||
struct unique_impl;
|
||||
|
||||
template <template <class...> class L, class... T>
|
||||
struct unique_impl<L<T...>>
|
||||
{
|
||||
using type = merge_set_t<L<>, L<T...>>;
|
||||
};
|
||||
}
|
||||
|
||||
template <class L>
|
||||
struct unique : detail::unique_impl<L>
|
||||
{
|
||||
};
|
||||
|
||||
template <class L>
|
||||
using unique_t = typename unique<L>::type;
|
||||
|
||||
/*************
|
||||
* static_if *
|
||||
*************/
|
||||
|
||||
template <class TF, class FF>
|
||||
decltype(auto) static_if(std::true_type, const TF& tf, const FF&)
|
||||
{
|
||||
return tf(identity());
|
||||
}
|
||||
|
||||
template <class TF, class FF>
|
||||
decltype(auto) static_if(std::false_type, const TF&, const FF& ff)
|
||||
{
|
||||
return ff(identity());
|
||||
}
|
||||
|
||||
template <bool cond, class TF, class FF>
|
||||
decltype(auto) static_if(const TF& tf, const FF& ff)
|
||||
{
|
||||
return static_if(std::integral_constant<bool, cond>(), tf, ff);
|
||||
}
|
||||
|
||||
/***********
|
||||
* switch_ *
|
||||
***********/
|
||||
|
||||
using default_t = std::true_type;
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <class... T>
|
||||
struct switch_impl;
|
||||
|
||||
template <class C, class T, class... U>
|
||||
struct switch_impl<C, T, U...>
|
||||
: std::conditional<C::value, T, typename switch_impl<U...>::type>
|
||||
{
|
||||
};
|
||||
|
||||
template <class C, class T, class U>
|
||||
struct switch_impl<C, T, default_t, U>
|
||||
: std::conditional<C::value, T, U>
|
||||
{
|
||||
};
|
||||
}
|
||||
|
||||
template <class... T>
|
||||
struct switch_ : detail::switch_impl<T...>
|
||||
{
|
||||
};
|
||||
|
||||
template <class... T>
|
||||
using switch_t = typename switch_<T...>::type;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,422 @@
|
|||
/***************************************************************************
|
||||
* Copyright (c) Johan Mabille, Sylvain Corlay and Wolf Vollprecht *
|
||||
* Copyright (c) QuantStack *
|
||||
* *
|
||||
* Distributed under the terms of the BSD 3-Clause License. *
|
||||
* *
|
||||
* The full license is in the file LICENSE, distributed with this software. *
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef XTL_MULTIMETHODS_HPP
|
||||
#define XTL_MULTIMETHODS_HPP
|
||||
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include <typeindex>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
|
||||
#include "xmeta_utils.hpp"
|
||||
|
||||
namespace xtl
|
||||
{
|
||||
// Loki's multimethods ported to modern C++ and generalized to N arguments
|
||||
// Original implementation can be found at
|
||||
// https://github.com/snaewe/loki-lib/blob/master/include/loki/MultiMethods.h
|
||||
|
||||
struct symmetric_dispatch {};
|
||||
struct antisymmetric_dispatch {};
|
||||
|
||||
/*********************
|
||||
* static_dispatcher *
|
||||
*********************/
|
||||
|
||||
template
|
||||
<
|
||||
class executor,
|
||||
class base_lhs,
|
||||
class lhs_type_list,
|
||||
class return_type = void,
|
||||
class symmetric = antisymmetric_dispatch,
|
||||
class base_rhs = base_lhs,
|
||||
class rhs_type_list = lhs_type_list
|
||||
>
|
||||
class static_dispatcher
|
||||
{
|
||||
private:
|
||||
|
||||
template <class lhs_type, class rhs_type>
|
||||
static return_type invoke_executor(lhs_type& lhs,
|
||||
rhs_type& rhs,
|
||||
executor& exec,
|
||||
std::false_type)
|
||||
{
|
||||
return exec.run(lhs, rhs);
|
||||
}
|
||||
|
||||
template <class lhs_type, class rhs_type>
|
||||
static return_type invoke_executor(lhs_type& lhs,
|
||||
rhs_type& rhs,
|
||||
executor& exec,
|
||||
std::true_type)
|
||||
{
|
||||
return exec.run(rhs, lhs);
|
||||
}
|
||||
|
||||
template <class lhs_type>
|
||||
static return_type dispatch_rhs(lhs_type& lhs,
|
||||
base_rhs& rhs,
|
||||
executor& exec,
|
||||
mpl::vector<>)
|
||||
{
|
||||
return exec.on_error(lhs, rhs);
|
||||
}
|
||||
|
||||
template <class lhs_type, class T, class... U>
|
||||
static return_type dispatch_rhs(lhs_type& lhs,
|
||||
base_rhs& rhs,
|
||||
executor& exec,
|
||||
mpl::vector<T, U...>)
|
||||
{
|
||||
if (T* p = dynamic_cast<T*>(&rhs))
|
||||
{
|
||||
constexpr std::size_t lhs_index = mpl::index_of<lhs_type_list, lhs_type>::value;
|
||||
constexpr std::size_t rhs_index = mpl::index_of<rhs_type_list, T>::value;
|
||||
|
||||
using invoke_flag = std::integral_constant<bool,
|
||||
std::is_same<symmetric, symmetric_dispatch>::value && (rhs_index < lhs_index)>;
|
||||
return invoke_executor(lhs, *p, exec, invoke_flag());
|
||||
}
|
||||
return dispatch_rhs(lhs, rhs, exec, mpl::vector<U...>());
|
||||
}
|
||||
|
||||
static return_type dispatch_lhs(base_lhs& lhs,
|
||||
base_rhs& rhs,
|
||||
executor& exec,
|
||||
mpl::vector<>)
|
||||
{
|
||||
return exec.on_error(lhs, rhs);
|
||||
}
|
||||
|
||||
template <class T, class... U>
|
||||
static return_type dispatch_lhs(base_lhs& lhs,
|
||||
base_rhs& rhs,
|
||||
executor& exec,
|
||||
mpl::vector<T, U...>)
|
||||
{
|
||||
if (T* p = dynamic_cast<T*>(&lhs))
|
||||
{
|
||||
return dispatch_rhs(*p, rhs, exec, rhs_type_list());
|
||||
}
|
||||
return dispatch_lhs(lhs, rhs, exec, mpl::vector<U...>());
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
static return_type dispatch(base_lhs& lhs, base_rhs& rhs, executor& exec)
|
||||
{
|
||||
return dispatch_lhs(lhs, rhs, exec, lhs_type_list());
|
||||
}
|
||||
};
|
||||
|
||||
// TODO: generalize to N-D with mpl::vector of mpl:vector
|
||||
// Warning: this is hardcore ;)
|
||||
|
||||
/********************
|
||||
* basic_dispatcher *
|
||||
********************/
|
||||
|
||||
template
|
||||
<
|
||||
class type_list,
|
||||
class return_type,
|
||||
class undispatched_type_list,
|
||||
class callback_type
|
||||
>
|
||||
class basic_dispatcher;
|
||||
|
||||
template
|
||||
<
|
||||
class return_type,
|
||||
class callback_type,
|
||||
class... B,
|
||||
class... T
|
||||
>
|
||||
class basic_dispatcher<mpl::vector<B...>, return_type, mpl::vector<T...>, callback_type>
|
||||
{
|
||||
private:
|
||||
|
||||
using key_type = std::array<std::type_index, sizeof...(B)>;
|
||||
using map_type = std::map<key_type, callback_type>;
|
||||
map_type m_callback_map;
|
||||
|
||||
template <class... U>
|
||||
key_type make_key() const
|
||||
{
|
||||
return {{std::type_index(typeid(U))...}};
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
template <class... D>
|
||||
void insert(callback_type&& cb)
|
||||
{
|
||||
static_assert(sizeof...(D) == sizeof...(B),
|
||||
"Number of callback arguments must match dispatcher dimension");
|
||||
m_callback_map[make_key<D...>()] = std::move(cb);
|
||||
}
|
||||
|
||||
template <class... D>
|
||||
void erase()
|
||||
{
|
||||
static_assert(sizeof...(D) == sizeof...(B),
|
||||
"Number of callback arguments must match dispatcher dimension");
|
||||
m_callback_map.erase(make_key<D...>());
|
||||
}
|
||||
|
||||
inline return_type dispatch(B&... args, T&... udargs) const
|
||||
{
|
||||
key_type k = {{std::type_index(typeid(args))...}};
|
||||
auto it = m_callback_map.find(k);
|
||||
if (it == m_callback_map.end())
|
||||
{
|
||||
XTL_THROW(std::runtime_error, "callback not found");
|
||||
}
|
||||
return (it->second)(args..., udargs...);
|
||||
}
|
||||
};
|
||||
|
||||
/*************************
|
||||
* basic_fast_dispatcher *
|
||||
*************************/
|
||||
|
||||
#define XTL_IMPLEMENT_INDEXABLE_CLASS() \
|
||||
static std::size_t& get_class_static_index()\
|
||||
{ \
|
||||
static std::size_t index = SIZE_MAX; \
|
||||
return index; \
|
||||
} \
|
||||
virtual std::size_t get_class_index() const \
|
||||
{ \
|
||||
return get_class_static_index(); \
|
||||
}
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <class T>
|
||||
class recursive_container_impl : private std::vector<T>
|
||||
{
|
||||
public:
|
||||
|
||||
using base_type = std::vector<T>;
|
||||
|
||||
using base_type::base_type;
|
||||
using base_type::operator[];
|
||||
using base_type::size;
|
||||
using base_type::resize;
|
||||
};
|
||||
|
||||
template <class callback_type, std::size_t level>
|
||||
class recursive_container
|
||||
: public recursive_container_impl<recursive_container<callback_type, level-1>>
|
||||
{
|
||||
};
|
||||
|
||||
template <class callback>
|
||||
class recursive_container<callback, 0>
|
||||
: public recursive_container_impl<callback>
|
||||
{
|
||||
};
|
||||
}
|
||||
|
||||
template
|
||||
<
|
||||
class type_list,
|
||||
class return_type,
|
||||
class undispatched_type_list,
|
||||
class callback_type
|
||||
>
|
||||
class basic_fast_dispatcher;
|
||||
|
||||
template
|
||||
<
|
||||
class return_type,
|
||||
class callback_type,
|
||||
class... B,
|
||||
class... T
|
||||
>
|
||||
class basic_fast_dispatcher<mpl::vector<B...>, return_type, mpl::vector<T...>, callback_type>
|
||||
{
|
||||
private:
|
||||
|
||||
static constexpr std::size_t nb_args = sizeof...(B);
|
||||
|
||||
using storage_type = detail::recursive_container<callback_type, sizeof...(B) - 1>;
|
||||
using index_type = std::array<std::size_t, nb_args>;
|
||||
using index_ref_type = std::array<std::reference_wrapper<std::size_t>, nb_args>;
|
||||
|
||||
storage_type m_callbacks;
|
||||
std::size_t m_next_index;
|
||||
|
||||
template <std::size_t I, class C>
|
||||
void resize_container(C& c, const index_ref_type& index)
|
||||
{
|
||||
std::size_t& idx = index[I];
|
||||
if (idx == SIZE_MAX)
|
||||
{
|
||||
c.resize(++m_next_index);
|
||||
idx = c.size() - 1u;
|
||||
}
|
||||
else if(c.size() <= idx)
|
||||
{
|
||||
c.resize(idx + 1u);
|
||||
}
|
||||
}
|
||||
|
||||
template <std::size_t I, class C>
|
||||
std::enable_if_t<I + 1 == nb_args>
|
||||
insert_impl(callback_type&& cb, C& c, const index_ref_type& index)
|
||||
{
|
||||
resize_container<I>(c, index);
|
||||
c[index[I]] = std::move(cb);
|
||||
}
|
||||
|
||||
template <std::size_t I, class C>
|
||||
std::enable_if_t<I + 1 != nb_args>
|
||||
insert_impl(callback_type&& cb, C& c, const index_ref_type& index)
|
||||
{
|
||||
resize_container<I>(c, index);
|
||||
insert_impl<I+1>(std::move(cb), c[index[I]], index);
|
||||
}
|
||||
|
||||
template <std::size_t I, class C>
|
||||
void check_size(C& c, const index_type& index) const
|
||||
{
|
||||
if (index[I] >= c.size())
|
||||
{
|
||||
XTL_THROW(std::runtime_error, "callback not found");
|
||||
}
|
||||
}
|
||||
|
||||
template <std::size_t I, class C>
|
||||
std::enable_if_t<I + 1 == nb_args, return_type>
|
||||
dispatch_impl(C& c, const index_type& index, B&... args, T&... udargs) const
|
||||
{
|
||||
check_size<I>(c, index);
|
||||
return c[index[I]](args..., udargs...);
|
||||
}
|
||||
|
||||
template <std::size_t I, class C>
|
||||
std::enable_if_t<I + 1 != nb_args, return_type>
|
||||
dispatch_impl(C& c, const index_type& index, B&... args, T&... udargs) const
|
||||
{
|
||||
check_size<I>(c, index);
|
||||
return dispatch_impl<I+1>(c[index[I]], index, args..., udargs...);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
inline basic_fast_dispatcher()
|
||||
: m_next_index(0)
|
||||
{
|
||||
}
|
||||
|
||||
template <class... D>
|
||||
void insert(callback_type&& cb)
|
||||
{
|
||||
static_assert(sizeof...(D) == sizeof...(B),
|
||||
"Number of callback arguments must match dispatcher dimension");
|
||||
index_ref_type index = {{std::ref(D::get_class_static_index())...}};
|
||||
insert_impl<0>(std::move(cb), m_callbacks, index);
|
||||
}
|
||||
|
||||
inline return_type dispatch(B&... args, T&... udargs) const
|
||||
{
|
||||
index_type index = {{args.get_class_index()...}};
|
||||
return dispatch_impl<0>(m_callbacks, index, args..., udargs...);
|
||||
}
|
||||
};
|
||||
|
||||
/******************************
|
||||
* dynamic and static casters *
|
||||
******************************/
|
||||
|
||||
template <class T, class F>
|
||||
struct static_caster
|
||||
{
|
||||
static T& cast(F& f)
|
||||
{
|
||||
return static_cast<T&>(f);
|
||||
}
|
||||
};
|
||||
|
||||
template <class T, class F>
|
||||
struct dynamic_caster
|
||||
{
|
||||
static T& cast(F& f)
|
||||
{
|
||||
return dynamic_cast<T&>(f);
|
||||
}
|
||||
};
|
||||
|
||||
/**********************
|
||||
* functor_dispatcher *
|
||||
**********************/
|
||||
|
||||
template
|
||||
<
|
||||
class type_list,
|
||||
class return_type,
|
||||
class undispatched_type = mpl::vector<>,
|
||||
template <class, class> class casting_policy = dynamic_caster,
|
||||
template <class, class, class, class> class dispatcher = basic_dispatcher
|
||||
>
|
||||
class functor_dispatcher;
|
||||
|
||||
template
|
||||
<
|
||||
class return_type,
|
||||
template <class, class> class casting_policy,
|
||||
template <class, class, class, class> class dispatcher,
|
||||
class... B,
|
||||
class... T
|
||||
>
|
||||
class functor_dispatcher<mpl::vector<B...>, return_type, mpl::vector<T...>, casting_policy, dispatcher>
|
||||
{
|
||||
private:
|
||||
|
||||
using functor_type = std::function<return_type (B&..., T&...)>;
|
||||
using backend = dispatcher<mpl::vector<B...>,
|
||||
return_type,
|
||||
mpl::vector<T...>,
|
||||
functor_type>;
|
||||
backend m_backend;
|
||||
|
||||
public:
|
||||
|
||||
template <class... D, class Fun>
|
||||
void insert(const Fun& fun)
|
||||
{
|
||||
functor_type f([fun](B&... args, T&... udargs) -> return_type
|
||||
{
|
||||
return fun(casting_policy<D&, B&>::cast(args)..., udargs...);
|
||||
});
|
||||
m_backend.template insert<D...>(std::move(f));
|
||||
}
|
||||
|
||||
template <class... D>
|
||||
void erase()
|
||||
{
|
||||
m_backend.template erase<D...>();
|
||||
}
|
||||
|
||||
inline return_type dispatch(B&... args, T&... udargs) const
|
||||
{
|
||||
return m_backend.dispatch(args..., udargs...);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,141 @@
|
|||
/***************************************************************************
|
||||
* Copyright (c) Johan Mabille, Sylvain Corlay, Wolf Vollprecht and *
|
||||
* Martin Renou *
|
||||
* Copyright (c) QuantStack *
|
||||
* *
|
||||
* Distributed under the terms of the BSD 3-Clause License. *
|
||||
* *
|
||||
* The full license is in the file LICENSE, distributed with this software. *
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef XTL_OPTIONAL_META_HPP
|
||||
#define XTL_OPTIONAL_META_HPP
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
#include "xmasked_value_meta.hpp"
|
||||
#include "xmeta_utils.hpp"
|
||||
#include "xtype_traits.hpp"
|
||||
|
||||
namespace xtl
|
||||
{
|
||||
template <class CT, class CB = bool>
|
||||
class xoptional;
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <class E>
|
||||
struct is_xoptional_impl : std::false_type
|
||||
{
|
||||
};
|
||||
|
||||
template <class CT, class CB>
|
||||
struct is_xoptional_impl<xoptional<CT, CB>> : std::true_type
|
||||
{
|
||||
};
|
||||
|
||||
template <class CT, class CTO, class CBO>
|
||||
using converts_from_xoptional = disjunction<
|
||||
std::is_constructible<CT, const xoptional<CTO, CBO>&>,
|
||||
std::is_constructible<CT, xoptional<CTO, CBO>&>,
|
||||
std::is_constructible<CT, const xoptional<CTO, CBO>&&>,
|
||||
std::is_constructible<CT, xoptional<CTO, CBO>&&>,
|
||||
std::is_convertible<const xoptional<CTO, CBO>&, CT>,
|
||||
std::is_convertible<xoptional<CTO, CBO>&, CT>,
|
||||
std::is_convertible<const xoptional<CTO, CBO>&&, CT>,
|
||||
std::is_convertible<xoptional<CTO, CBO>&&, CT>
|
||||
>;
|
||||
|
||||
template <class CT, class CTO, class CBO>
|
||||
using assigns_from_xoptional = disjunction<
|
||||
std::is_assignable<std::add_lvalue_reference_t<CT>, const xoptional<CTO, CBO>&>,
|
||||
std::is_assignable<std::add_lvalue_reference_t<CT>, xoptional<CTO, CBO>&>,
|
||||
std::is_assignable<std::add_lvalue_reference_t<CT>, const xoptional<CTO, CBO>&&>,
|
||||
std::is_assignable<std::add_lvalue_reference_t<CT>, xoptional<CTO, CBO>&&>
|
||||
>;
|
||||
|
||||
template <class... Args>
|
||||
struct common_optional_impl;
|
||||
|
||||
template <class T>
|
||||
struct common_optional_impl<T>
|
||||
{
|
||||
using type = std::conditional_t<is_xoptional_impl<T>::value, T, xoptional<T>>;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct identity
|
||||
{
|
||||
using type = T;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct get_value_type
|
||||
{
|
||||
using type = typename T::value_type;
|
||||
};
|
||||
|
||||
template<class T1, class T2>
|
||||
struct common_optional_impl<T1, T2>
|
||||
{
|
||||
using decay_t1 = std::decay_t<T1>;
|
||||
using decay_t2 = std::decay_t<T2>;
|
||||
using type1 = xtl::mpl::eval_if_t<xtl::is_fundamental<decay_t1>, identity<decay_t1>, get_value_type<decay_t1>>;
|
||||
using type2 = xtl::mpl::eval_if_t<xtl::is_fundamental<decay_t2>, identity<decay_t2>, get_value_type<decay_t2>>;
|
||||
using type = xoptional<std::common_type_t<type1, type2>>;
|
||||
};
|
||||
|
||||
template <class T1, class T2, class B2>
|
||||
struct common_optional_impl<T1, xoptional<T2, B2>>
|
||||
: common_optional_impl<T1, T2>
|
||||
{
|
||||
};
|
||||
|
||||
template <class T1, class B1, class T2>
|
||||
struct common_optional_impl<xoptional<T1, B1>, T2>
|
||||
: common_optional_impl<T1, T2>
|
||||
{
|
||||
};
|
||||
|
||||
template <class T1, class B1, class T2, class B2>
|
||||
struct common_optional_impl<xoptional<T1, B1>, xoptional<T2, B2>>
|
||||
: common_optional_impl<T1, T2>
|
||||
{
|
||||
};
|
||||
|
||||
template <class T1, class T2, class... Args>
|
||||
struct common_optional_impl<T1, T2, Args...>
|
||||
{
|
||||
using type = typename common_optional_impl<
|
||||
typename common_optional_impl<T1, T2>::type,
|
||||
Args...
|
||||
>::type;
|
||||
};
|
||||
}
|
||||
|
||||
template <class E>
|
||||
using is_xoptional = detail::is_xoptional_impl<E>;
|
||||
|
||||
template <class E, class R = void>
|
||||
using disable_xoptional = std::enable_if_t<!is_xoptional<E>::value, R>;
|
||||
|
||||
template <class... Args>
|
||||
struct at_least_one_xoptional : disjunction<is_xoptional<Args>...>
|
||||
{
|
||||
};
|
||||
|
||||
template <class... Args>
|
||||
struct common_optional : detail::common_optional_impl<Args...>
|
||||
{
|
||||
};
|
||||
|
||||
template <class... Args>
|
||||
using common_optional_t = typename common_optional<Args...>::type;
|
||||
|
||||
template <class E>
|
||||
struct is_not_xoptional_nor_xmasked_value : negation<disjunction<is_xoptional<E>, is_xmasked_value<E>>>
|
||||
{
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,622 @@
|
|||
/***************************************************************************
|
||||
* Copyright (c) Johan Mabille, Sylvain Corlay and Wolf Vollprecht *
|
||||
* Copyright (c) QuantStack *
|
||||
* *
|
||||
* Distributed under the terms of the BSD 3-Clause License. *
|
||||
* *
|
||||
* The full license is in the file LICENSE, distributed with this software. *
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef XTL_OPTIONAL_SEQUENCE_HPP
|
||||
#define XTL_OPTIONAL_SEQUENCE_HPP
|
||||
|
||||
#include <array>
|
||||
#include <bitset>
|
||||
#include <cstddef>
|
||||
#include <iterator>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "xdynamic_bitset.hpp"
|
||||
#include "xiterator_base.hpp"
|
||||
#include "xoptional.hpp"
|
||||
#include "xsequence.hpp"
|
||||
|
||||
namespace xtl
|
||||
{
|
||||
/**************************************
|
||||
* Optimized 1-D xoptional containers *
|
||||
**************************************/
|
||||
|
||||
template <class ITV, class ITB>
|
||||
class xoptional_iterator;
|
||||
|
||||
template <class BC, class FC>
|
||||
class xoptional_sequence
|
||||
{
|
||||
public:
|
||||
|
||||
// Internal typedefs
|
||||
|
||||
using base_container_type = BC;
|
||||
using base_value_type = typename base_container_type::value_type;
|
||||
using base_reference = typename base_container_type::reference;
|
||||
using base_const_reference = typename base_container_type::const_reference;
|
||||
|
||||
using flag_container_type = FC;
|
||||
using flag_type = typename flag_container_type::value_type;
|
||||
using flag_reference = typename flag_container_type::reference;
|
||||
using flag_const_reference = typename flag_container_type::const_reference;
|
||||
|
||||
// Container typedefs
|
||||
using value_type = xoptional<base_value_type, flag_type>;
|
||||
using reference = xoptional<base_reference, flag_reference>;
|
||||
using const_reference = xoptional<base_const_reference, flag_const_reference>;
|
||||
using pointer = xclosure_pointer<reference>;
|
||||
using const_pointer = xclosure_pointer<const_reference>;
|
||||
|
||||
// Other typedefs
|
||||
using size_type = typename base_container_type::size_type;
|
||||
using difference_type = typename base_container_type::difference_type;
|
||||
using iterator = xoptional_iterator<typename base_container_type::iterator,
|
||||
typename flag_container_type::iterator>;
|
||||
using const_iterator = xoptional_iterator<typename base_container_type::const_iterator,
|
||||
typename flag_container_type::const_iterator>;
|
||||
|
||||
using reverse_iterator = xoptional_iterator<typename base_container_type::reverse_iterator,
|
||||
typename flag_container_type::reverse_iterator>;
|
||||
using const_reverse_iterator = xoptional_iterator<typename base_container_type::const_reverse_iterator,
|
||||
typename flag_container_type::const_reverse_iterator>;
|
||||
|
||||
bool empty() const noexcept;
|
||||
size_type size() const noexcept;
|
||||
size_type max_size() const noexcept;
|
||||
|
||||
reference at(size_type i);
|
||||
const_reference at(size_type i) const;
|
||||
|
||||
reference operator[](size_type i);
|
||||
const_reference operator[](size_type i) const;
|
||||
|
||||
reference front();
|
||||
const_reference front() const;
|
||||
|
||||
reference back();
|
||||
const_reference back() const;
|
||||
|
||||
iterator begin() noexcept;
|
||||
iterator end() noexcept;
|
||||
|
||||
const_iterator begin() const noexcept;
|
||||
const_iterator end() const noexcept;
|
||||
const_iterator cbegin() const noexcept;
|
||||
const_iterator cend() const noexcept;
|
||||
|
||||
reverse_iterator rbegin() noexcept;
|
||||
reverse_iterator rend() noexcept;
|
||||
|
||||
const_reverse_iterator rbegin() const noexcept;
|
||||
const_reverse_iterator rend() const noexcept;
|
||||
const_reverse_iterator crbegin() const noexcept;
|
||||
const_reverse_iterator crend() const noexcept;
|
||||
|
||||
base_container_type value() && noexcept;
|
||||
base_container_type& value() & noexcept;
|
||||
const base_container_type& value() const & noexcept;
|
||||
|
||||
flag_container_type has_value() && noexcept;
|
||||
flag_container_type& has_value() & noexcept;
|
||||
const flag_container_type& has_value() const & noexcept;
|
||||
|
||||
protected:
|
||||
|
||||
xoptional_sequence() = default;
|
||||
xoptional_sequence(size_type s, const base_value_type& v);
|
||||
template <class CTO, class CBO>
|
||||
xoptional_sequence(size_type s, const xoptional<CTO, CBO>& v);
|
||||
|
||||
~xoptional_sequence() = default;
|
||||
|
||||
xoptional_sequence(const xoptional_sequence&) = default;
|
||||
xoptional_sequence& operator=(const xoptional_sequence&) = default;
|
||||
|
||||
xoptional_sequence(xoptional_sequence&&) = default;
|
||||
xoptional_sequence& operator=(xoptional_sequence&&) = default;
|
||||
|
||||
base_container_type m_values;
|
||||
flag_container_type m_flags;
|
||||
};
|
||||
|
||||
template <class BC, class FC>
|
||||
bool operator==(const xoptional_sequence<BC, FC>& lhs, const xoptional_sequence<BC, FC>& rhs);
|
||||
|
||||
template <class BC, class FC>
|
||||
bool operator!=(const xoptional_sequence<BC, FC>& lhs, const xoptional_sequence<BC, FC>& rhs);
|
||||
|
||||
template <class BC, class FC>
|
||||
bool operator<(const xoptional_sequence<BC, FC>& lhs, const xoptional_sequence<BC, FC>& rhs);
|
||||
|
||||
template <class BC, class FC>
|
||||
bool operator<=(const xoptional_sequence<BC, FC>& lhs, const xoptional_sequence<BC, FC>& rhs);
|
||||
|
||||
template <class BC, class FC>
|
||||
bool operator>(const xoptional_sequence<BC, FC>& lhs, const xoptional_sequence<BC, FC>& rhs);
|
||||
|
||||
template <class BC, class FC>
|
||||
bool operator>=(const xoptional_sequence<BC, FC>& lhs, const xoptional_sequence<BC, FC>& rhs);
|
||||
|
||||
/********************************
|
||||
* xoptional_array declarations *
|
||||
********************************/
|
||||
|
||||
// There is no value_type in std::bitset ...
|
||||
template <class T, std::size_t I, class BC = xdynamic_bitset<std::size_t>>
|
||||
class xoptional_array : public xoptional_sequence<std::array<T, I>, BC>
|
||||
{
|
||||
public:
|
||||
|
||||
using self_type = xoptional_array;
|
||||
using base_container_type = std::array<T, I>;
|
||||
using flag_container_type = BC;
|
||||
using base_type = xoptional_sequence<base_container_type, flag_container_type>;
|
||||
using base_value_type = typename base_type::base_value_type;
|
||||
using size_type = typename base_type::size_type;
|
||||
|
||||
xoptional_array() = default;
|
||||
xoptional_array(size_type s, const base_value_type& v);
|
||||
|
||||
template <class CTO, class CBO>
|
||||
xoptional_array(size_type s, const xoptional<CTO, CBO>& v);
|
||||
};
|
||||
|
||||
/********************
|
||||
* xoptional_vector *
|
||||
********************/
|
||||
|
||||
template <class T, class A = std::allocator<T>, class BC = xdynamic_bitset<std::size_t>>
|
||||
class xoptional_vector : public xoptional_sequence<std::vector<T, A>, BC>
|
||||
{
|
||||
public:
|
||||
|
||||
using self_type = xoptional_vector;
|
||||
using base_container_type = std::vector<T, A>;
|
||||
using flag_container_type = BC;
|
||||
using base_type = xoptional_sequence<base_container_type, flag_container_type>;
|
||||
using base_value_type = typename base_type::base_value_type;
|
||||
using allocator_type = A;
|
||||
|
||||
using value_type = typename base_type::value_type;
|
||||
using size_type = typename base_type::size_type;
|
||||
using difference_type = typename base_type::difference_type;
|
||||
using reference = typename base_type::reference;
|
||||
using const_reference = typename base_type::const_reference;
|
||||
using pointer = typename base_type::pointer;
|
||||
using const_pointer = typename base_type::const_pointer;
|
||||
|
||||
using iterator = typename base_type::iterator;
|
||||
using const_iterator = typename base_type::const_iterator;
|
||||
using reverse_iterator = typename base_type::reverse_iterator;
|
||||
using const_reverse_iterator = typename base_type::const_reverse_iterator;
|
||||
|
||||
xoptional_vector() = default;
|
||||
xoptional_vector(size_type, const base_value_type&);
|
||||
|
||||
template <class CTO, class CBO>
|
||||
xoptional_vector(size_type, const xoptional<CTO, CBO>&);
|
||||
|
||||
void resize(size_type);
|
||||
void resize(size_type, const base_value_type&);
|
||||
template <class CTO, class CBO>
|
||||
void resize(size_type, const xoptional<CTO, CBO>&);
|
||||
};
|
||||
|
||||
/**********************************
|
||||
* xoptional_iterator declaration *
|
||||
**********************************/
|
||||
|
||||
template <class ITV, class ITB>
|
||||
struct xoptional_iterator_traits
|
||||
{
|
||||
using iterator_type = xoptional_iterator<ITV, ITB>;
|
||||
using value_type = xoptional<typename ITV::value_type, typename ITB::value_type>;
|
||||
using reference = xoptional<typename ITV::reference, typename ITB::reference>;
|
||||
using pointer = xclosure_pointer<reference>;
|
||||
using difference_type = typename ITV::difference_type;
|
||||
};
|
||||
|
||||
template <class ITV, class ITB>
|
||||
class xoptional_iterator : public xrandom_access_iterator_base2<xoptional_iterator_traits<ITV, ITB>>
|
||||
{
|
||||
public:
|
||||
|
||||
using self_type = xoptional_iterator<ITV, ITB>;
|
||||
using base_type = xrandom_access_iterator_base2<xoptional_iterator_traits<ITV, ITB>>;
|
||||
|
||||
using value_type = typename base_type::value_type;
|
||||
using reference = typename base_type::reference;
|
||||
using pointer = typename base_type::pointer;
|
||||
using difference_type = typename base_type::difference_type;
|
||||
|
||||
xoptional_iterator() = default;
|
||||
xoptional_iterator(ITV itv, ITB itb);
|
||||
|
||||
self_type& operator++();
|
||||
self_type& operator--();
|
||||
|
||||
self_type& operator+=(difference_type n);
|
||||
self_type& operator-=(difference_type n);
|
||||
|
||||
difference_type operator-(const self_type& rhs) const;
|
||||
|
||||
reference operator*() const;
|
||||
pointer operator->() const;
|
||||
|
||||
bool operator==(const self_type& rhs) const;
|
||||
bool operator<(const self_type& rhs) const;
|
||||
|
||||
private:
|
||||
|
||||
ITV m_itv;
|
||||
ITB m_itb;
|
||||
};
|
||||
|
||||
/*************************************
|
||||
* xoptional_sequence implementation *
|
||||
*************************************/
|
||||
|
||||
template <class BC, class FC>
|
||||
inline xoptional_sequence<BC, FC>::xoptional_sequence(size_type s, const base_value_type& v)
|
||||
: m_values(make_sequence<base_container_type>(s, v)),
|
||||
m_flags(make_sequence<flag_container_type>(s, true))
|
||||
{
|
||||
}
|
||||
|
||||
template <class BC, class FC>
|
||||
template <class CTO, class CBO>
|
||||
inline xoptional_sequence<BC, FC>::xoptional_sequence(size_type s, const xoptional<CTO, CBO>& v)
|
||||
: m_values(make_sequence<base_container_type>(s, v.value())), m_flags(make_sequence<flag_container_type>(s, v.has_value()))
|
||||
{
|
||||
}
|
||||
|
||||
template <class BC, class FC>
|
||||
inline auto xoptional_sequence<BC, FC>::empty() const noexcept -> bool
|
||||
{
|
||||
return m_values.empty();
|
||||
}
|
||||
|
||||
template <class BC, class FC>
|
||||
inline auto xoptional_sequence<BC, FC>::size() const noexcept -> size_type
|
||||
{
|
||||
return m_values.size();
|
||||
}
|
||||
|
||||
template <class BC, class FC>
|
||||
inline auto xoptional_sequence<BC, FC>::max_size() const noexcept -> size_type
|
||||
{
|
||||
return m_values.max_size();
|
||||
}
|
||||
|
||||
template <class BC, class FC>
|
||||
inline auto xoptional_sequence<BC, FC>::at(size_type i) -> reference
|
||||
{
|
||||
return reference(m_values.at(i), m_flags.at(i));
|
||||
}
|
||||
|
||||
template <class BC, class FC>
|
||||
inline auto xoptional_sequence<BC, FC>::at(size_type i) const -> const_reference
|
||||
{
|
||||
return const_reference(m_values.at(i), m_flags.at(i));
|
||||
}
|
||||
|
||||
template <class BC, class FC>
|
||||
inline auto xoptional_sequence<BC, FC>::operator[](size_type i) -> reference
|
||||
{
|
||||
return reference(m_values[i], m_flags[i]);
|
||||
}
|
||||
|
||||
template <class BC, class FC>
|
||||
inline auto xoptional_sequence<BC, FC>::operator[](size_type i) const -> const_reference
|
||||
{
|
||||
return const_reference(m_values[i], m_flags[i]);
|
||||
}
|
||||
|
||||
template <class BC, class FC>
|
||||
inline auto xoptional_sequence<BC, FC>::front() -> reference
|
||||
{
|
||||
return reference(m_values.front(), m_flags.front());
|
||||
}
|
||||
|
||||
template <class BC, class FC>
|
||||
inline auto xoptional_sequence<BC, FC>::front() const -> const_reference
|
||||
{
|
||||
return const_reference(m_values.front(), m_flags.front());
|
||||
}
|
||||
|
||||
template <class BC, class FC>
|
||||
inline auto xoptional_sequence<BC, FC>::back() -> reference
|
||||
{
|
||||
return reference(m_values.back(), m_flags.back());
|
||||
}
|
||||
|
||||
template <class BC, class FC>
|
||||
inline auto xoptional_sequence<BC, FC>::back() const -> const_reference
|
||||
{
|
||||
return const_reference(m_values.back(), m_flags.back());
|
||||
}
|
||||
|
||||
template <class BC, class FC>
|
||||
inline auto xoptional_sequence<BC, FC>::begin() noexcept -> iterator
|
||||
{
|
||||
return iterator(m_values.begin(), m_flags.begin());
|
||||
}
|
||||
|
||||
template <class BC, class FC>
|
||||
inline auto xoptional_sequence<BC, FC>::end() noexcept -> iterator
|
||||
{
|
||||
return iterator(m_values.end(), m_flags.end());
|
||||
}
|
||||
|
||||
template <class BC, class FC>
|
||||
inline auto xoptional_sequence<BC, FC>::begin() const noexcept -> const_iterator
|
||||
{
|
||||
return cbegin();
|
||||
}
|
||||
|
||||
template <class BC, class FC>
|
||||
inline auto xoptional_sequence<BC, FC>::end() const noexcept -> const_iterator
|
||||
{
|
||||
return cend();
|
||||
}
|
||||
|
||||
template <class BC, class FC>
|
||||
inline auto xoptional_sequence<BC, FC>::cbegin() const noexcept -> const_iterator
|
||||
{
|
||||
return const_iterator(m_values.cbegin(), m_flags.cbegin());
|
||||
}
|
||||
|
||||
template <class BC, class FC>
|
||||
inline auto xoptional_sequence<BC, FC>::cend() const noexcept -> const_iterator
|
||||
{
|
||||
return const_iterator(m_values.cend(), m_flags.cend());
|
||||
}
|
||||
|
||||
template <class BC, class FC>
|
||||
inline auto xoptional_sequence<BC, FC>::rbegin() noexcept -> reverse_iterator
|
||||
{
|
||||
return reverse_iterator(m_values.rbegin(), m_flags.rbegin());
|
||||
}
|
||||
|
||||
template <class BC, class FC>
|
||||
inline auto xoptional_sequence<BC, FC>::rend() noexcept -> reverse_iterator
|
||||
{
|
||||
return reverse_iterator(m_values.rend(), m_flags.rend());
|
||||
}
|
||||
|
||||
template <class BC, class FC>
|
||||
inline auto xoptional_sequence<BC, FC>::rbegin() const noexcept -> const_reverse_iterator
|
||||
{
|
||||
return crbegin();
|
||||
}
|
||||
|
||||
template <class BC, class FC>
|
||||
inline auto xoptional_sequence<BC, FC>::rend() const noexcept -> const_reverse_iterator
|
||||
{
|
||||
return crend();
|
||||
}
|
||||
|
||||
template <class BC, class FC>
|
||||
inline auto xoptional_sequence<BC, FC>::crbegin() const noexcept -> const_reverse_iterator
|
||||
{
|
||||
return const_reverse_iterator(m_values.crbegin(), m_flags.crbegin());
|
||||
}
|
||||
|
||||
template <class BC, class FC>
|
||||
inline auto xoptional_sequence<BC, FC>::crend() const noexcept -> const_reverse_iterator
|
||||
{
|
||||
return const_reverse_iterator(m_values.crend(), m_flags.crend());
|
||||
}
|
||||
|
||||
template <class BC, class FC>
|
||||
inline auto xoptional_sequence<BC, FC>::value() && noexcept -> base_container_type
|
||||
{
|
||||
return m_values;
|
||||
}
|
||||
|
||||
template <class BC, class FC>
|
||||
inline auto xoptional_sequence<BC, FC>::value() & noexcept -> base_container_type&
|
||||
{
|
||||
return m_values;
|
||||
}
|
||||
|
||||
template <class BC, class FC>
|
||||
inline auto xoptional_sequence<BC, FC>::value() const & noexcept -> const base_container_type&
|
||||
{
|
||||
return m_values;
|
||||
}
|
||||
|
||||
template <class BC, class FC>
|
||||
inline auto xoptional_sequence<BC, FC>::has_value() && noexcept-> flag_container_type
|
||||
{
|
||||
return m_flags;
|
||||
}
|
||||
|
||||
template <class BC, class FC>
|
||||
inline auto xoptional_sequence<BC, FC>::has_value() & noexcept -> flag_container_type&
|
||||
{
|
||||
return m_flags;
|
||||
}
|
||||
|
||||
template <class BC, class FC>
|
||||
inline auto xoptional_sequence<BC, FC>::has_value() const & noexcept -> const flag_container_type&
|
||||
{
|
||||
return m_flags;
|
||||
}
|
||||
|
||||
template <class BC, class FC>
|
||||
inline bool operator==(const xoptional_sequence<BC, FC>& lhs, const xoptional_sequence<BC, FC>& rhs)
|
||||
{
|
||||
return lhs.value() == rhs.value() && lhs.has_value() == rhs.has_value();
|
||||
}
|
||||
|
||||
template <class BC, class FC>
|
||||
inline bool operator!=(const xoptional_sequence<BC, FC>& lhs, const xoptional_sequence<BC, FC>& rhs)
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
template <class BC, class FC>
|
||||
inline bool operator<(const xoptional_sequence<BC, FC>& lhs, const xoptional_sequence<BC, FC>& rhs)
|
||||
{
|
||||
return lhs.value() < rhs.value() && lhs.has_value() == rhs.has_value();
|
||||
}
|
||||
|
||||
template <class BC, class FC>
|
||||
inline bool operator<=(const xoptional_sequence<BC, FC>& lhs, const xoptional_sequence<BC, FC>& rhs)
|
||||
{
|
||||
return lhs.value() <= rhs.value() && lhs.has_value() == rhs.has_value();
|
||||
}
|
||||
|
||||
template <class BC, class FC>
|
||||
inline bool operator>(const xoptional_sequence<BC, FC>& lhs, const xoptional_sequence<BC, FC>& rhs)
|
||||
{
|
||||
return lhs.value() > rhs.value() && lhs.has_value() == rhs.has_value();
|
||||
}
|
||||
|
||||
template <class BC, class FC>
|
||||
inline bool operator>=(const xoptional_sequence<BC, FC>& lhs, const xoptional_sequence<BC, FC>& rhs)
|
||||
{
|
||||
return lhs.value() >= rhs.value() && lhs.has_value() == rhs.has_value();
|
||||
}
|
||||
|
||||
/**********************************
|
||||
* xoptional_array implementation *
|
||||
**********************************/
|
||||
|
||||
template <class T, std::size_t I, class BC>
|
||||
xoptional_array<T, I, BC>::xoptional_array(size_type s, const base_value_type& v)
|
||||
: base_type(s, v)
|
||||
{
|
||||
}
|
||||
|
||||
template <class T, std::size_t I, class BC>
|
||||
template <class CTO, class CBO>
|
||||
xoptional_array<T, I, BC>::xoptional_array(size_type s, const xoptional<CTO, CBO>& v)
|
||||
: base_type(s, v)
|
||||
{
|
||||
}
|
||||
|
||||
/*******************************************************
|
||||
* xoptional_array and xoptional_vector implementation *
|
||||
*******************************************************/
|
||||
|
||||
template <class T, class A, class BC>
|
||||
xoptional_vector<T, A, BC>::xoptional_vector(size_type s, const base_value_type& v)
|
||||
: base_type(s, v)
|
||||
{
|
||||
}
|
||||
|
||||
template <class T, class A, class BC>
|
||||
template <class CTO, class CBO>
|
||||
xoptional_vector<T, A, BC>::xoptional_vector(size_type s, const xoptional<CTO, CBO>& v)
|
||||
: base_type(s, v)
|
||||
{
|
||||
}
|
||||
|
||||
template <class T, class A, class BC>
|
||||
void xoptional_vector<T, A, BC>::resize(size_type s)
|
||||
{
|
||||
// Default to missing
|
||||
this->m_values.resize(s);
|
||||
this->m_flags.resize(s, false);
|
||||
}
|
||||
|
||||
template <class T, class A, class BC>
|
||||
void xoptional_vector<T, A, BC>::resize(size_type s, const base_value_type& v)
|
||||
{
|
||||
this->m_values.resize(s, v);
|
||||
this->m_flags.resize(s, true);
|
||||
}
|
||||
|
||||
template <class T, class A, class BC>
|
||||
template <class CTO, class CBO>
|
||||
void xoptional_vector<T, A, BC>::resize(size_type s, const xoptional<CTO, CBO>& v)
|
||||
{
|
||||
this->m_values.resize(s, v.value());
|
||||
this->m_flags.resize(s, v.has_value());
|
||||
}
|
||||
|
||||
/*************************************
|
||||
* xoptional_iterator implementation *
|
||||
*************************************/
|
||||
|
||||
template <class ITV, class ITB>
|
||||
xoptional_iterator<ITV, ITB>::xoptional_iterator(ITV itv, ITB itb)
|
||||
: m_itv(itv), m_itb(itb)
|
||||
{
|
||||
}
|
||||
|
||||
template <class ITV, class ITB>
|
||||
auto xoptional_iterator<ITV, ITB>::operator++() -> self_type&
|
||||
{
|
||||
++m_itv;
|
||||
++m_itb;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class ITV, class ITB>
|
||||
auto xoptional_iterator<ITV, ITB>::operator--() -> self_type&
|
||||
{
|
||||
--m_itv;
|
||||
--m_itb;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class ITV, class ITB>
|
||||
auto xoptional_iterator<ITV, ITB>::operator+=(difference_type n) -> self_type&
|
||||
{
|
||||
m_itv += n;
|
||||
m_itb += n;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class ITV, class ITB>
|
||||
auto xoptional_iterator<ITV, ITB>::operator-=(difference_type n) -> self_type&
|
||||
{
|
||||
m_itv -= n;
|
||||
m_itb -= n;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class ITV, class ITB>
|
||||
auto xoptional_iterator<ITV, ITB>::operator-(const self_type& rhs) const -> difference_type
|
||||
{
|
||||
return m_itv - rhs.m_itv;
|
||||
}
|
||||
|
||||
template <class ITV, class ITB>
|
||||
auto xoptional_iterator<ITV, ITB>::operator*() const -> reference
|
||||
{
|
||||
return reference(*m_itv, *m_itb);
|
||||
}
|
||||
|
||||
template <class ITV, class ITB>
|
||||
auto xoptional_iterator<ITV, ITB>::operator-> () const -> pointer
|
||||
{
|
||||
return pointer(operator*());
|
||||
}
|
||||
|
||||
template <class ITV, class ITB>
|
||||
bool xoptional_iterator<ITV, ITB>::operator==(const self_type& rhs) const
|
||||
{
|
||||
return m_itv == rhs.m_itv && m_itb == rhs.m_itb;
|
||||
}
|
||||
|
||||
template <class ITV, class ITB>
|
||||
bool xoptional_iterator<ITV, ITB>::operator<(const self_type& rhs) const
|
||||
{
|
||||
return m_itv < rhs.m_itv && m_itb < rhs.m_itb;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,42 @@
|
|||
/***************************************************************************
|
||||
* Copyright (c) Johan Mabille, Sylvain Corlay and Wolf Vollprecht *
|
||||
* Copyright (c) QuantStack *
|
||||
* *
|
||||
* Distributed under the terms of the BSD 3-Clause License. *
|
||||
* *
|
||||
* The full license is in the file LICENSE, distributed with this software. *
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef XTL_XPLATFORM_HPP
|
||||
#define XTL_XPLATFORM_HPP
|
||||
|
||||
#include <cstring>
|
||||
#include <cstdint>
|
||||
|
||||
namespace xtl
|
||||
{
|
||||
enum class endian
|
||||
{
|
||||
big_endian,
|
||||
little_endian,
|
||||
mixed
|
||||
};
|
||||
|
||||
inline endian endianness()
|
||||
{
|
||||
uint32_t utmp = 0x01020304;
|
||||
char btmp[sizeof(utmp)];
|
||||
std::memcpy(&btmp[0], &utmp, sizeof(utmp));
|
||||
switch(btmp[0])
|
||||
{
|
||||
case 0x01:
|
||||
return endian::big_endian;
|
||||
case 0x04:
|
||||
return endian::little_endian;
|
||||
default:
|
||||
return endian::mixed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,48 @@
|
|||
/***************************************************************************
|
||||
* Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht *
|
||||
* *
|
||||
* Distributed under the terms of the BSD 3-Clause License. *
|
||||
* *
|
||||
* The full license is in the file LICENSE, distributed with this software. *
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef XTL_XPROXY_WRAPPER_HPP
|
||||
#define XTL_XPROXY_WRAPPER_HPP
|
||||
|
||||
#include "xclosure.hpp"
|
||||
|
||||
namespace xtl
|
||||
{
|
||||
|
||||
template <class P>
|
||||
class xproxy_wrapper_impl : public P
|
||||
{
|
||||
public:
|
||||
|
||||
using self_type = xproxy_wrapper_impl<P>;
|
||||
using lv_pointer = xclosure_pointer<P&>;
|
||||
using rv_pointer = xclosure_pointer<P>;
|
||||
|
||||
explicit xproxy_wrapper_impl(P&& rhs)
|
||||
: P(std::move(rhs))
|
||||
{
|
||||
}
|
||||
|
||||
inline lv_pointer operator&() & { return lv_pointer(*this); }
|
||||
inline rv_pointer operator&() && { return rv_pointer(std::move(*this)); }
|
||||
};
|
||||
|
||||
template <class P>
|
||||
using xproxy_wrapper = std::conditional_t<std::is_class<P>::value,
|
||||
xproxy_wrapper_impl<P>,
|
||||
xclosure_wrapper<P>>;
|
||||
|
||||
template <class P>
|
||||
inline xproxy_wrapper<P> proxy_wrapper(P&& proxy)
|
||||
{
|
||||
return xproxy_wrapper<P>(std::forward<P>(proxy));
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,215 @@
|
|||
/***************************************************************************
|
||||
* Copyright (c) Johan Mabille, Sylvain Corlay and Wolf Vollprecht *
|
||||
* Copyright (c) QuantStack *
|
||||
* *
|
||||
* Distributed under the terms of the BSD 3-Clause License. *
|
||||
* *
|
||||
* The full license is in the file LICENSE, distributed with this software. *
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef XTL_SEQUENCE_HPP
|
||||
#define XTL_SEQUENCE_HPP
|
||||
|
||||
#include <array>
|
||||
#include <cstddef>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "xtl_config.hpp"
|
||||
#include "xmeta_utils.hpp"
|
||||
|
||||
namespace xtl
|
||||
{
|
||||
template <class S>
|
||||
S make_sequence(typename S::size_type size);
|
||||
|
||||
template <class S>
|
||||
S make_sequence(typename S::size_type size, typename S::value_type v);
|
||||
|
||||
template <class S>
|
||||
S make_sequence(std::initializer_list<typename S::value_type> init);
|
||||
|
||||
template <class R, class A>
|
||||
decltype(auto) forward_sequence(A&& s);
|
||||
|
||||
// equivalent to std::size(c) in c++17
|
||||
template <class C>
|
||||
constexpr auto sequence_size(const C& c) -> decltype(c.size());
|
||||
|
||||
// equivalent to std::size(a) in c++17
|
||||
template <class T, std::size_t N>
|
||||
constexpr std::size_t sequence_size(const T (&a)[N]);
|
||||
|
||||
/********************************
|
||||
* make_sequence implementation *
|
||||
********************************/
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <class S>
|
||||
struct sequence_builder
|
||||
{
|
||||
using value_type = typename S::value_type;
|
||||
using size_type = typename S::size_type;
|
||||
|
||||
inline static S make(size_type size)
|
||||
{
|
||||
return S(size);
|
||||
}
|
||||
|
||||
inline static S make(size_type size, value_type v)
|
||||
{
|
||||
return S(size, v);
|
||||
}
|
||||
|
||||
inline static S make(std::initializer_list<value_type> init)
|
||||
{
|
||||
return S(init);
|
||||
}
|
||||
};
|
||||
|
||||
template <class T, std::size_t N>
|
||||
struct sequence_builder<std::array<T, N>>
|
||||
{
|
||||
using sequence_type = std::array<T, N>;
|
||||
using value_type = typename sequence_type::value_type;
|
||||
using size_type = typename sequence_type::size_type;
|
||||
|
||||
inline static sequence_type make(size_type /*size*/)
|
||||
{
|
||||
return sequence_type();
|
||||
}
|
||||
|
||||
inline static sequence_type make(size_type /*size*/, value_type v)
|
||||
{
|
||||
sequence_type s;
|
||||
s.fill(v);
|
||||
return s;
|
||||
}
|
||||
|
||||
inline static sequence_type make(std::initializer_list<value_type> init)
|
||||
{
|
||||
sequence_type s;
|
||||
std::copy(init.begin(), init.end(), s.begin());
|
||||
return s;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
template <class S>
|
||||
inline S make_sequence(typename S::size_type size)
|
||||
{
|
||||
return detail::sequence_builder<S>::make(size);
|
||||
}
|
||||
|
||||
template <class S>
|
||||
inline S make_sequence(typename S::size_type size, typename S::value_type v)
|
||||
{
|
||||
return detail::sequence_builder<S>::make(size, v);
|
||||
}
|
||||
|
||||
template <class S>
|
||||
inline S make_sequence(std::initializer_list<typename S::value_type> init)
|
||||
{
|
||||
return detail::sequence_builder<S>::make(init);
|
||||
}
|
||||
|
||||
/***********************************
|
||||
* forward_sequence implementation *
|
||||
***********************************/
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <class R, class A, class E = void>
|
||||
struct sequence_forwarder_impl
|
||||
{
|
||||
template <class T>
|
||||
static inline R forward(const T& r)
|
||||
{
|
||||
R ret;
|
||||
std::copy(std::begin(r), std::end(r), std::begin(ret));
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
template <class R, class A>
|
||||
struct sequence_forwarder_impl<R, A, void_t<decltype(std::declval<R>().resize(
|
||||
std::declval<std::size_t>()))>>
|
||||
{
|
||||
template <class T>
|
||||
static inline auto forward(const T& r)
|
||||
{
|
||||
return R(std::begin(r), std::end(r));
|
||||
}
|
||||
};
|
||||
|
||||
template <class R, class A>
|
||||
struct sequence_forwarder
|
||||
: sequence_forwarder_impl<R, A>
|
||||
{
|
||||
};
|
||||
|
||||
template <class R>
|
||||
struct sequence_forwarder<R, R>
|
||||
{
|
||||
template <class T>
|
||||
static inline T&& forward(T&& t) noexcept
|
||||
{
|
||||
return std::forward<T>(t);
|
||||
}
|
||||
};
|
||||
|
||||
template <class R, class A>
|
||||
using forwarder_type = detail::sequence_forwarder<
|
||||
std::decay_t<R>,
|
||||
std::remove_cv_t<std::remove_reference_t<A>>
|
||||
>;
|
||||
}
|
||||
|
||||
template <class R, class A>
|
||||
inline decltype(auto) forward_sequence(typename std::remove_reference<A>::type& s)
|
||||
{
|
||||
using forwarder = detail::forwarder_type<R, A>;
|
||||
return forwarder::forward(std::forward<A>(s));
|
||||
}
|
||||
|
||||
template <class R, class A>
|
||||
inline decltype(auto) forward_sequence(typename std::remove_reference<A>::type&& s)
|
||||
{
|
||||
using forwarder = detail::forwarder_type<R, A>;
|
||||
static_assert(!std::is_lvalue_reference<A>::value,
|
||||
"Can not forward an rvalue as an lvalue.");
|
||||
return forwarder::forward(std::move(s));
|
||||
}
|
||||
|
||||
/********************************
|
||||
* sequence_size implementation *
|
||||
********************************/
|
||||
|
||||
// equivalent to std::size(c) in c++17
|
||||
template <class C>
|
||||
constexpr auto sequence_size(const C& c) -> decltype(c.size())
|
||||
{
|
||||
return c.size();
|
||||
}
|
||||
|
||||
// equivalent to std::size(a) in c++17
|
||||
template <class T, std::size_t N>
|
||||
constexpr std::size_t sequence_size(const T (&)[N])
|
||||
{
|
||||
return N;
|
||||
}
|
||||
|
||||
/****************************
|
||||
* are_equivalent_sequences *
|
||||
****************************/
|
||||
|
||||
template <class E1, class E2>
|
||||
inline bool are_equivalent_sequences(const E1& e1, const E2& e2)
|
||||
{
|
||||
return std::equal(e1.cbegin(), e1.cend(), e2.cbegin(), e2.cend());
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,21 @@
|
|||
/***************************************************************************
|
||||
* Copyright (c) Johan Mabille, Sylvain Corlay and Wolf Vollprecht *
|
||||
* Copyright (c) QuantStack *
|
||||
* *
|
||||
* Distributed under the terms of the BSD 3-Clause License. *
|
||||
* *
|
||||
* The full license is in the file LICENSE, distributed with this software. *
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef XTL_XSPAN_HPP
|
||||
#define XTL_XSPAN_HPP
|
||||
|
||||
#include "xspan_impl.hpp"
|
||||
|
||||
namespace xtl
|
||||
{
|
||||
using tcb::span;
|
||||
constexpr std::ptrdiff_t dynamic_extent = tcb::dynamic_extent;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,778 @@
|
|||
// https://github.com/tcbrindle/span/blob/master/include/tcb/span.hpp
|
||||
// TCP SPAN @commit cd0c6d0
|
||||
|
||||
/*
|
||||
This is an implementation of std::span from P0122R7
|
||||
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0122r7.pdf
|
||||
*/
|
||||
|
||||
// Copyright Tristan Brindle 2018.
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file ../../LICENSE_1_0.txt or copy at
|
||||
// https://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef TCB_SPAN_HPP_INCLUDED
|
||||
#define TCB_SPAN_HPP_INCLUDED
|
||||
|
||||
#include <array>
|
||||
#include <cstddef>
|
||||
#include <type_traits>
|
||||
|
||||
#ifndef TCB_SPAN_NO_EXCEPTIONS
|
||||
// Attempt to discover whether we're being compiled with exception support
|
||||
#if !(defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND))
|
||||
#define TCB_SPAN_NO_EXCEPTIONS
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef TCB_SPAN_NO_EXCEPTIONS
|
||||
#include <cstdio>
|
||||
#include <stdexcept>
|
||||
#endif
|
||||
|
||||
// Various feature test macros
|
||||
|
||||
#ifndef TCB_SPAN_NAMESPACE_NAME
|
||||
#define TCB_SPAN_NAMESPACE_NAME tcb
|
||||
#endif
|
||||
|
||||
#ifdef TCB_SPAN_STD_COMPLIANT_MODE
|
||||
#define TCB_SPAN_NO_DEPRECATION_WARNINGS
|
||||
#endif
|
||||
|
||||
#ifndef TCB_SPAN_NO_DEPRECATION_WARNINGS
|
||||
#define TCB_SPAN_DEPRECATED_FOR(msg) [[deprecated(msg)]]
|
||||
#else
|
||||
#define TCB_SPAN_DEPRECATED_FOR(msg)
|
||||
#endif
|
||||
|
||||
#if __cplusplus >= 201703L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L)
|
||||
#define TCB_SPAN_HAVE_CPP17
|
||||
#endif
|
||||
|
||||
#if __cplusplus >= 201402L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201402L)
|
||||
#define TCB_SPAN_HAVE_CPP14
|
||||
#endif
|
||||
|
||||
namespace TCB_SPAN_NAMESPACE_NAME {
|
||||
|
||||
// Establish default contract checking behavior
|
||||
#if !defined(TCB_SPAN_THROW_ON_CONTRACT_VIOLATION) && \
|
||||
!defined(TCB_SPAN_TERMINATE_ON_CONTRACT_VIOLATION) && \
|
||||
!defined(TCB_SPAN_NO_CONTRACT_CHECKING)
|
||||
#if defined(NDEBUG) || !defined(TCB_SPAN_HAVE_CPP14)
|
||||
#define TCB_SPAN_NO_CONTRACT_CHECKING
|
||||
#else
|
||||
#define TCB_SPAN_TERMINATE_ON_CONTRACT_VIOLATION
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(TCB_SPAN_THROW_ON_CONTRACT_VIOLATION)
|
||||
struct contract_violation_error : std::logic_error {
|
||||
explicit contract_violation_error(const char* msg) : std::logic_error(msg)
|
||||
{}
|
||||
};
|
||||
|
||||
inline void contract_violation(const char* msg)
|
||||
{
|
||||
throw contract_violation_error(msg);
|
||||
}
|
||||
|
||||
#elif defined(TCB_SPAN_TERMINATE_ON_CONTRACT_VIOLATION)
|
||||
[[noreturn]] inline void contract_violation(const char* /*unused*/)
|
||||
{
|
||||
std::terminate();
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(TCB_SPAN_NO_CONTRACT_CHECKING)
|
||||
#define TCB_SPAN_STRINGIFY(cond) #cond
|
||||
#define TCB_SPAN_EXPECT(cond) \
|
||||
cond ? (void) 0 : contract_violation("Expected " TCB_SPAN_STRINGIFY(cond))
|
||||
#else
|
||||
#define TCB_SPAN_EXPECT(cond)
|
||||
#endif
|
||||
|
||||
#if defined(TCB_SPAN_HAVE_CPP17) || defined(__cpp_inline_variables)
|
||||
#define TCB_SPAN_INLINE_VAR inline
|
||||
#else
|
||||
#define TCB_SPAN_INLINE_VAR
|
||||
#endif
|
||||
|
||||
#if defined(TCB_SPAN_HAVE_CPP14) || \
|
||||
(defined(__cpp_constexpr) && __cpp_constexpr >= 201304)
|
||||
#define TCB_SPAN_CONSTEXPR14 constexpr
|
||||
#else
|
||||
#define TCB_SPAN_CONSTEXPR14
|
||||
#endif
|
||||
|
||||
#if defined(TCB_SPAN_NO_CONTRACT_CHECKING)
|
||||
#define TCB_SPAN_CONSTEXPR11 constexpr
|
||||
#else
|
||||
#define TCB_SPAN_CONSTEXPR11 TCB_SPAN_CONSTEXPR14
|
||||
#endif
|
||||
|
||||
#if defined(TCB_SPAN_HAVE_CPP17) || defined(__cpp_deduction_guides)
|
||||
#define TCB_SPAN_HAVE_DEDUCTION_GUIDES
|
||||
#endif
|
||||
|
||||
#if defined(TCB_SPAN_HAVE_CPP17) || defined(__cpp_lib_byte)
|
||||
#define TCB_SPAN_HAVE_STD_BYTE
|
||||
#endif
|
||||
|
||||
#if defined(TCB_SPAN_HAVE_CPP17) || defined(__cpp_lib_array_constexpr)
|
||||
#define TCB_SPAN_HAVE_CONSTEXPR_STD_ARRAY_ETC
|
||||
#endif
|
||||
|
||||
#if defined(TCB_SPAN_HAVE_CONSTEXPR_STD_ARRAY_ETC)
|
||||
#define TCB_SPAN_ARRAY_CONSTEXPR constexpr
|
||||
#else
|
||||
#define TCB_SPAN_ARRAY_CONSTEXPR
|
||||
#endif
|
||||
|
||||
#ifdef TCB_SPAN_HAVE_STD_BYTE
|
||||
using byte = std::byte;
|
||||
#else
|
||||
using byte = unsigned char;
|
||||
#endif
|
||||
|
||||
TCB_SPAN_INLINE_VAR constexpr std::ptrdiff_t dynamic_extent = -1;
|
||||
|
||||
template <typename ElementType, std::ptrdiff_t Extent = dynamic_extent>
|
||||
class span;
|
||||
|
||||
namespace detail {
|
||||
|
||||
template <typename E, std::ptrdiff_t S>
|
||||
struct span_storage {
|
||||
constexpr span_storage() noexcept = default;
|
||||
|
||||
constexpr span_storage(E* aptr, std::ptrdiff_t /*unused*/) noexcept
|
||||
: ptr(aptr)
|
||||
{}
|
||||
|
||||
E* ptr = nullptr;
|
||||
static constexpr std::ptrdiff_t size = S;
|
||||
};
|
||||
|
||||
template <typename E>
|
||||
struct span_storage<E, dynamic_extent> {
|
||||
constexpr span_storage() noexcept = default;
|
||||
|
||||
constexpr span_storage(E* aptr, std::size_t asize) noexcept
|
||||
: ptr(aptr), size(asize)
|
||||
{}
|
||||
|
||||
E* ptr = nullptr;
|
||||
std::size_t size = 0;
|
||||
};
|
||||
|
||||
// Reimplementation of C++17 std::size() and std::data()
|
||||
#if defined(TCB_SPAN_HAVE_CPP17) || \
|
||||
defined(__cpp_lib_nonmember_container_access)
|
||||
using std::data;
|
||||
using std::size;
|
||||
#else
|
||||
template <class C>
|
||||
constexpr auto size(const C& c) -> decltype(c.size())
|
||||
{
|
||||
return c.size();
|
||||
}
|
||||
|
||||
template <class T, std::size_t N>
|
||||
constexpr std::size_t size(const T (&)[N]) noexcept
|
||||
{
|
||||
return N;
|
||||
}
|
||||
|
||||
template <class C>
|
||||
constexpr auto data(C& c) -> decltype(c.data())
|
||||
{
|
||||
return c.data();
|
||||
}
|
||||
|
||||
template <class C>
|
||||
constexpr auto data(const C& c) -> decltype(c.data())
|
||||
{
|
||||
return c.data();
|
||||
}
|
||||
|
||||
template <class T, std::size_t N>
|
||||
constexpr T* data(T (&array)[N]) noexcept
|
||||
{
|
||||
return array;
|
||||
}
|
||||
|
||||
template <class E>
|
||||
constexpr const E* data(std::initializer_list<E> il) noexcept
|
||||
{
|
||||
return il.begin();
|
||||
}
|
||||
#endif // TCB_SPAN_HAVE_CPP17
|
||||
|
||||
#if defined(TCB_SPAN_HAVE_CPP17) || defined(__cpp_lib_void_t)
|
||||
using std::void_t;
|
||||
#else
|
||||
template <typename...>
|
||||
using void_t = void;
|
||||
#endif
|
||||
|
||||
template <typename T>
|
||||
using uncvref_t =
|
||||
typename std::remove_cv<typename std::remove_reference<T>::type>::type;
|
||||
|
||||
template <typename>
|
||||
struct is_span : std::false_type {};
|
||||
|
||||
template <typename T, std::ptrdiff_t S>
|
||||
struct is_span<span<T, S>> : std::true_type {};
|
||||
|
||||
template <typename>
|
||||
struct is_std_array : std::false_type {};
|
||||
|
||||
template <typename T, std::size_t N>
|
||||
struct is_std_array<std::array<T, N>> : std::true_type {};
|
||||
|
||||
template <typename, typename = void>
|
||||
struct has_size_and_data : std::false_type {};
|
||||
|
||||
template <typename T>
|
||||
struct has_size_and_data<T, void_t<decltype(detail::size(std::declval<T>())),
|
||||
decltype(detail::data(std::declval<T>()))>>
|
||||
: std::true_type {};
|
||||
|
||||
template <typename C, typename U = uncvref_t<C>>
|
||||
struct is_container {
|
||||
static constexpr bool value =
|
||||
!is_span<U>::value && !is_std_array<U>::value &&
|
||||
!std::is_array<U>::value && has_size_and_data<C>::value;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
using remove_pointer_t = typename std::remove_pointer<T>::type;
|
||||
|
||||
template <typename, typename, typename = void>
|
||||
struct is_container_element_type_compatible : std::false_type {};
|
||||
|
||||
template <typename T, typename E>
|
||||
struct is_container_element_type_compatible<
|
||||
T, E, void_t<decltype(detail::data(std::declval<T>()))>>
|
||||
: std::is_convertible<
|
||||
remove_pointer_t<decltype(detail::data(std::declval<T>()))> (*)[],
|
||||
E (*)[]> {};
|
||||
|
||||
template <typename, typename = size_t>
|
||||
struct is_complete : std::false_type {};
|
||||
|
||||
template <typename T>
|
||||
struct is_complete<T, decltype(sizeof(T))> : std::true_type {};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <typename ElementType, std::ptrdiff_t Extent>
|
||||
class span {
|
||||
static_assert(Extent == dynamic_extent || Extent >= 0,
|
||||
"A span must have an extent greater than or equal to zero, "
|
||||
"or a dynamic extent");
|
||||
static_assert(std::is_object<ElementType>::value,
|
||||
"A span's ElementType must be an object type (not a "
|
||||
"reference type or void)");
|
||||
static_assert(detail::is_complete<ElementType>::value,
|
||||
"A span's ElementType must be a complete type (not a forward "
|
||||
"declaration)");
|
||||
static_assert(!std::is_abstract<ElementType>::value,
|
||||
"A span's ElementType cannot be an abstract class type");
|
||||
|
||||
using storage_type = detail::span_storage<ElementType, Extent>;
|
||||
|
||||
public:
|
||||
// constants and types
|
||||
using element_type = ElementType;
|
||||
using value_type = typename std::remove_cv<ElementType>::type;
|
||||
using index_type = std::size_t;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using pointer = ElementType*;
|
||||
using reference = ElementType&;
|
||||
using iterator = pointer;
|
||||
using const_iterator = const ElementType*;
|
||||
using reverse_iterator = std::reverse_iterator<iterator>;
|
||||
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
|
||||
|
||||
static constexpr index_type extent = static_cast<index_type>(Extent);
|
||||
|
||||
// [span.cons], span constructors, copy, assignment, and destructor
|
||||
template <std::ptrdiff_t E = Extent,
|
||||
typename std::enable_if<E <= 0, int>::type = 0>
|
||||
constexpr span() noexcept
|
||||
{}
|
||||
|
||||
TCB_SPAN_CONSTEXPR11 span(pointer ptr, index_type count)
|
||||
: storage_(ptr, count)
|
||||
{
|
||||
TCB_SPAN_EXPECT(extent == dynamic_extent || count == extent);
|
||||
}
|
||||
|
||||
TCB_SPAN_CONSTEXPR11 span(pointer first_elem, pointer last_elem)
|
||||
: storage_(first_elem, last_elem - first_elem)
|
||||
{
|
||||
TCB_SPAN_EXPECT(extent == dynamic_extent ||
|
||||
last_elem - first_elem == extent);
|
||||
}
|
||||
|
||||
template <
|
||||
std::size_t N, std::ptrdiff_t E = Extent,
|
||||
typename std::enable_if<
|
||||
(E == dynamic_extent || static_cast<std::ptrdiff_t>(N) == E) &&
|
||||
detail::is_container_element_type_compatible<
|
||||
element_type (&)[N], ElementType>::value,
|
||||
int>::type = 0>
|
||||
constexpr span(element_type (&arr)[N]) noexcept : storage_(arr, N)
|
||||
{}
|
||||
|
||||
template <
|
||||
std::size_t N, std::ptrdiff_t E = Extent,
|
||||
typename std::enable_if<
|
||||
(E == dynamic_extent || static_cast<std::ptrdiff_t>(N) == E) &&
|
||||
detail::is_container_element_type_compatible<
|
||||
std::array<value_type, N>&, ElementType>::value,
|
||||
int>::type = 0>
|
||||
TCB_SPAN_ARRAY_CONSTEXPR span(std::array<value_type, N>& arr) noexcept
|
||||
: storage_(arr.data(), N)
|
||||
{}
|
||||
|
||||
template <
|
||||
std::size_t N, std::ptrdiff_t E = Extent,
|
||||
typename std::enable_if<
|
||||
(E == dynamic_extent || static_cast<std::ptrdiff_t>(N) == E) &&
|
||||
detail::is_container_element_type_compatible<
|
||||
const std::array<value_type, N>&, ElementType>::value,
|
||||
int>::type = 0>
|
||||
TCB_SPAN_ARRAY_CONSTEXPR span(const std::array<value_type, N>& arr) noexcept
|
||||
: storage_(arr.data(), N)
|
||||
{}
|
||||
|
||||
template <typename Container,
|
||||
typename std::enable_if<
|
||||
detail::is_container<Container>::value &&
|
||||
detail::is_container_element_type_compatible<
|
||||
Container&, ElementType>::value,
|
||||
int>::type = 0>
|
||||
TCB_SPAN_CONSTEXPR11 span(Container& cont)
|
||||
: storage_(detail::data(cont), detail::size(cont))
|
||||
{
|
||||
TCB_SPAN_EXPECT(extent == dynamic_extent ||
|
||||
static_cast<std::ptrdiff_t>(detail::size(cont)) ==
|
||||
extent);
|
||||
}
|
||||
|
||||
template <typename Container,
|
||||
typename std::enable_if<
|
||||
detail::is_container<Container>::value &&
|
||||
detail::is_container_element_type_compatible<
|
||||
const Container&, ElementType>::value,
|
||||
int>::type = 0>
|
||||
TCB_SPAN_CONSTEXPR11 span(const Container& cont)
|
||||
: storage_(detail::data(cont), detail::size(cont))
|
||||
{
|
||||
TCB_SPAN_EXPECT(extent == dynamic_extent ||
|
||||
static_cast<std::ptrdiff_t>(detail::size(cont)) ==
|
||||
extent);
|
||||
}
|
||||
|
||||
constexpr span(const span& other) noexcept = default;
|
||||
|
||||
template <typename OtherElementType, std::ptrdiff_t OtherExtent,
|
||||
typename std::enable_if<
|
||||
(Extent == OtherExtent || Extent == dynamic_extent) &&
|
||||
std::is_convertible<OtherElementType (*)[],
|
||||
ElementType (*)[]>::value,
|
||||
int>::type = 0>
|
||||
constexpr span(const span<OtherElementType, OtherExtent>& other) noexcept
|
||||
: storage_(other.data(), other.size())
|
||||
{}
|
||||
|
||||
~span() noexcept = default;
|
||||
|
||||
span& operator=(const span& other) noexcept = default;
|
||||
|
||||
// [span.sub], span subviews
|
||||
template <std::ptrdiff_t Count>
|
||||
TCB_SPAN_CONSTEXPR11 span<element_type, Count> first() const
|
||||
{
|
||||
TCB_SPAN_EXPECT(Count >= 0 && Count <= size());
|
||||
return {data(), Count};
|
||||
}
|
||||
|
||||
template <std::ptrdiff_t Count>
|
||||
TCB_SPAN_CONSTEXPR11 span<element_type, Count> last() const
|
||||
{
|
||||
TCB_SPAN_EXPECT(Count >= 0 && Count <= size());
|
||||
return {data() + (size() - Count), Count};
|
||||
}
|
||||
|
||||
template <std::ptrdiff_t Offset, std::ptrdiff_t Count = dynamic_extent>
|
||||
using subspan_return_t =
|
||||
span<ElementType, Count != dynamic_extent
|
||||
? Count
|
||||
: (Extent != dynamic_extent ? Extent - Offset
|
||||
: dynamic_extent)>;
|
||||
|
||||
template <std::ptrdiff_t Offset, std::ptrdiff_t Count = dynamic_extent>
|
||||
TCB_SPAN_CONSTEXPR11 subspan_return_t<Offset, Count> subspan() const
|
||||
{
|
||||
TCB_SPAN_EXPECT((Offset >= 0 && Offset <= size()) &&
|
||||
(Count == dynamic_extent ||
|
||||
(Count >= 0 && Offset + Count <= size())));
|
||||
return {data() + Offset,
|
||||
Count != dynamic_extent
|
||||
? Count
|
||||
: (Extent != dynamic_extent ? Extent - Offset
|
||||
: size() - Offset)};
|
||||
}
|
||||
|
||||
TCB_SPAN_CONSTEXPR11 span<element_type, dynamic_extent>
|
||||
first(index_type count) const
|
||||
{
|
||||
TCB_SPAN_EXPECT(count >= 0 && count <= size());
|
||||
return {data(), count};
|
||||
}
|
||||
|
||||
TCB_SPAN_CONSTEXPR11 span<element_type, dynamic_extent>
|
||||
last(index_type count) const
|
||||
{
|
||||
TCB_SPAN_EXPECT(count >= 0 && count <= size());
|
||||
return {data() + (size() - count), count};
|
||||
}
|
||||
|
||||
TCB_SPAN_CONSTEXPR11 span<element_type, dynamic_extent>
|
||||
subspan(index_type offset, index_type count = static_cast<index_type>(dynamic_extent)) const
|
||||
{
|
||||
TCB_SPAN_EXPECT((offset >= 0 && offset <= size()) &&
|
||||
(count == dynamic_extent ||
|
||||
(count >= 0 && offset + count <= size())));
|
||||
return {data() + offset,
|
||||
count == dynamic_extent ? size() - offset : count};
|
||||
}
|
||||
|
||||
// [span.obs], span observers
|
||||
constexpr index_type size() const noexcept { return storage_.size; }
|
||||
|
||||
constexpr index_type size_bytes() const noexcept
|
||||
{
|
||||
return size() * sizeof(element_type);
|
||||
}
|
||||
|
||||
constexpr bool empty() const noexcept { return size() == 0; }
|
||||
|
||||
// [span.elem], span element access
|
||||
TCB_SPAN_CONSTEXPR11 reference operator[](index_type idx) const
|
||||
{
|
||||
TCB_SPAN_EXPECT(idx >= 0 && idx < size());
|
||||
return *(data() + idx);
|
||||
}
|
||||
|
||||
/* Extension: not in P0122 */
|
||||
#ifndef TCB_SPAN_STD_COMPLIANT_MODE
|
||||
TCB_SPAN_CONSTEXPR14 reference at(index_type idx) const
|
||||
{
|
||||
#ifndef TCB_SPAN_NO_EXCEPTIONS
|
||||
if (idx < 0 || idx >= size()) {
|
||||
char msgbuf[64] = {
|
||||
0,
|
||||
};
|
||||
std::snprintf(msgbuf, sizeof(msgbuf),
|
||||
"Index %td is out of range for span of size %td", idx,
|
||||
size());
|
||||
throw std::out_of_range{msgbuf};
|
||||
}
|
||||
#endif // TCB_SPAN_NO_EXCEPTIONS
|
||||
return this->operator[](idx);
|
||||
}
|
||||
|
||||
TCB_SPAN_CONSTEXPR11 reference front() const
|
||||
{
|
||||
TCB_SPAN_EXPECT(!empty());
|
||||
return *data();
|
||||
}
|
||||
|
||||
TCB_SPAN_CONSTEXPR11 reference back() const
|
||||
{
|
||||
TCB_SPAN_EXPECT(!empty());
|
||||
return *(data() + (size() - 1));
|
||||
}
|
||||
|
||||
#endif // TCB_SPAN_STD_COMPLIANT_MODE
|
||||
|
||||
#ifndef TCB_SPAN_NO_FUNCTION_CALL_OPERATOR
|
||||
TCB_SPAN_DEPRECATED_FOR("Use operator[] instead")
|
||||
constexpr reference operator()(index_type idx) const
|
||||
{
|
||||
return this->operator[](idx);
|
||||
}
|
||||
#endif // TCB_SPAN_NO_FUNCTION_CALL_OPERATOR
|
||||
|
||||
constexpr pointer data() const noexcept { return storage_.ptr; }
|
||||
|
||||
// [span.iterators], span iterator support
|
||||
constexpr iterator begin() const noexcept { return data(); }
|
||||
|
||||
constexpr iterator end() const noexcept { return data() + size(); }
|
||||
|
||||
constexpr const_iterator cbegin() const noexcept { return begin(); }
|
||||
|
||||
constexpr const_iterator cend() const noexcept { return end(); }
|
||||
|
||||
TCB_SPAN_ARRAY_CONSTEXPR reverse_iterator rbegin() const noexcept
|
||||
{
|
||||
return reverse_iterator(end());
|
||||
}
|
||||
|
||||
TCB_SPAN_ARRAY_CONSTEXPR reverse_iterator rend() const noexcept
|
||||
{
|
||||
return reverse_iterator(begin());
|
||||
}
|
||||
|
||||
TCB_SPAN_ARRAY_CONSTEXPR const_reverse_iterator crbegin() const noexcept
|
||||
{
|
||||
return const_reverse_iterator(cend());
|
||||
}
|
||||
|
||||
TCB_SPAN_ARRAY_CONSTEXPR const_reverse_iterator crend() const noexcept
|
||||
{
|
||||
return const_reverse_iterator(cbegin());
|
||||
}
|
||||
|
||||
private:
|
||||
storage_type storage_{};
|
||||
};
|
||||
|
||||
#ifdef TCB_SPAN_HAVE_DEDUCTION_GUIDES
|
||||
|
||||
/* Deduction Guides */
|
||||
template <class T, size_t N>
|
||||
span(T (&)[N])->span<T, N>;
|
||||
|
||||
template <class T, size_t N>
|
||||
span(std::array<T, N>&)->span<T, N>;
|
||||
|
||||
template <class T, size_t N>
|
||||
span(const std::array<T, N>&)->span<const T, N>;
|
||||
|
||||
template <class Container>
|
||||
span(Container&)->span<typename Container::value_type>;
|
||||
|
||||
template <class Container>
|
||||
span(const Container&)->span<const typename Container::value_type>;
|
||||
|
||||
#endif // TCB_HAVE_DEDUCTION_GUIDES
|
||||
|
||||
template <typename ElementType, std::ptrdiff_t Extent>
|
||||
constexpr span<ElementType, Extent>
|
||||
make_span(span<ElementType, Extent> s) noexcept
|
||||
{
|
||||
return s;
|
||||
}
|
||||
|
||||
#define AS_SIGNED(N) static_cast<std::ptrdiff_t>(N)
|
||||
|
||||
template <typename T, std::size_t N>
|
||||
constexpr span<T, AS_SIGNED(N)> make_span(T (&arr)[N]) noexcept
|
||||
{
|
||||
return {arr};
|
||||
}
|
||||
|
||||
template <typename T, std::size_t N>
|
||||
TCB_SPAN_ARRAY_CONSTEXPR span<T, AS_SIGNED(N)> make_span(std::array<T, N>& arr) noexcept
|
||||
{
|
||||
return {arr};
|
||||
}
|
||||
|
||||
template <typename T, std::size_t N>
|
||||
TCB_SPAN_ARRAY_CONSTEXPR span<const T, AS_SIGNED(N)>
|
||||
make_span(const std::array<T, N>& arr) noexcept
|
||||
{
|
||||
return {arr};
|
||||
}
|
||||
|
||||
#undef AS_SIGNED
|
||||
|
||||
template <typename Container>
|
||||
constexpr span<typename Container::value_type> make_span(Container& cont)
|
||||
{
|
||||
return {cont};
|
||||
}
|
||||
|
||||
template <typename Container>
|
||||
constexpr span<const typename Container::value_type>
|
||||
make_span(const Container& cont)
|
||||
{
|
||||
return {cont};
|
||||
}
|
||||
|
||||
/* Comparison operators */
|
||||
// Implementation note: the implementations of == and < are equivalent to
|
||||
// 4-legged std::equal and std::lexicographical_compare respectively
|
||||
|
||||
template <typename T, std::ptrdiff_t X, typename U, std::ptrdiff_t Y>
|
||||
TCB_SPAN_CONSTEXPR14 bool operator==(span<T, X> lhs, span<U, Y> rhs)
|
||||
{
|
||||
if (lhs.size() != rhs.size()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (std::ptrdiff_t i = 0; i < lhs.size(); i++) {
|
||||
if (lhs[i] != rhs[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename T, std::ptrdiff_t X, typename U, std::ptrdiff_t Y>
|
||||
TCB_SPAN_CONSTEXPR14 bool operator!=(span<T, X> lhs, span<U, Y> rhs)
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
template <typename T, std::ptrdiff_t X, typename U, std::ptrdiff_t Y>
|
||||
TCB_SPAN_CONSTEXPR14 bool operator<(span<T, X> lhs, span<U, Y> rhs)
|
||||
{
|
||||
// No std::min to avoid dragging in <algorithm>
|
||||
const std::ptrdiff_t size =
|
||||
lhs.size() < rhs.size() ? lhs.size() : rhs.size();
|
||||
|
||||
for (std::ptrdiff_t i = 0; i < size; i++) {
|
||||
if (lhs[i] < rhs[i]) {
|
||||
return true;
|
||||
}
|
||||
if (lhs[i] > rhs[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return lhs.size() < rhs.size();
|
||||
}
|
||||
|
||||
template <typename T, std::ptrdiff_t X, typename U, std::ptrdiff_t Y>
|
||||
TCB_SPAN_CONSTEXPR14 bool operator<=(span<T, X> lhs, span<U, Y> rhs)
|
||||
{
|
||||
return !(rhs < lhs);
|
||||
}
|
||||
|
||||
template <typename T, std::ptrdiff_t X, typename U, std::ptrdiff_t Y>
|
||||
TCB_SPAN_CONSTEXPR14 bool operator>(span<T, X> lhs, span<U, Y> rhs)
|
||||
{
|
||||
return rhs < lhs;
|
||||
}
|
||||
|
||||
template <typename T, std::ptrdiff_t X, typename U, std::ptrdiff_t Y>
|
||||
TCB_SPAN_CONSTEXPR14 bool operator>=(span<T, X> lhs, span<U, Y> rhs)
|
||||
{
|
||||
return !(lhs < rhs);
|
||||
}
|
||||
|
||||
template <typename ElementType, std::ptrdiff_t Extent>
|
||||
span<const byte, ((Extent == dynamic_extent)
|
||||
? dynamic_extent
|
||||
: (static_cast<ptrdiff_t>(sizeof(ElementType)) * Extent))>
|
||||
as_bytes(span<ElementType, Extent> s) noexcept
|
||||
{
|
||||
return {reinterpret_cast<const byte*>(s.data()), s.size_bytes()};
|
||||
}
|
||||
|
||||
template <
|
||||
class ElementType, ptrdiff_t Extent,
|
||||
typename std::enable_if<!std::is_const<ElementType>::value, int>::type = 0>
|
||||
span<byte, ((Extent == dynamic_extent)
|
||||
? dynamic_extent
|
||||
: (static_cast<ptrdiff_t>(sizeof(ElementType)) * Extent))>
|
||||
as_writable_bytes(span<ElementType, Extent> s) noexcept
|
||||
{
|
||||
return {reinterpret_cast<byte*>(s.data()), s.size_bytes()};
|
||||
}
|
||||
|
||||
/* Extension: nonmember subview operations */
|
||||
|
||||
#ifndef TCB_SPAN_STD_COMPLIANT_MODE
|
||||
|
||||
template <std::ptrdiff_t Count, typename T>
|
||||
TCB_SPAN_CONSTEXPR11 auto first(T& t)
|
||||
-> decltype(make_span(t).template first<Count>())
|
||||
{
|
||||
return make_span(t).template first<Count>();
|
||||
}
|
||||
|
||||
template <std::ptrdiff_t Count, typename T>
|
||||
TCB_SPAN_CONSTEXPR11 auto last(T& t)
|
||||
-> decltype(make_span(t).template last<Count>())
|
||||
{
|
||||
return make_span(t).template last<Count>();
|
||||
}
|
||||
|
||||
template <std::ptrdiff_t Offset, std::ptrdiff_t Count = dynamic_extent,
|
||||
typename T>
|
||||
TCB_SPAN_CONSTEXPR11 auto subspan(T& t)
|
||||
-> decltype(make_span(t).template subspan<Offset, Count>())
|
||||
{
|
||||
return make_span(t).template subspan<Offset, Count>();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
TCB_SPAN_CONSTEXPR11 auto first(T& t, std::ptrdiff_t count)
|
||||
-> decltype(make_span(t).first(count))
|
||||
{
|
||||
return make_span(t).first(count);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
TCB_SPAN_CONSTEXPR11 auto last(T& t, std::ptrdiff_t count)
|
||||
-> decltype(make_span(t).last(count))
|
||||
{
|
||||
return make_span(t).last(count);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
TCB_SPAN_CONSTEXPR11 auto subspan(T& t, std::ptrdiff_t offset,
|
||||
std::ptrdiff_t count = dynamic_extent)
|
||||
-> decltype(make_span(t).subspan(offset, count))
|
||||
{
|
||||
return make_span(t).subspan(offset, count);
|
||||
}
|
||||
|
||||
#endif // TCB_SPAN_STD_COMPLIANT_MODE
|
||||
|
||||
} // namespace TCB_SPAN_NAMESPACE_NAME
|
||||
|
||||
/* Extension: support for C++17 structured bindings */
|
||||
|
||||
#ifndef TCB_SPAN_STD_COMPLIANT_MODE
|
||||
|
||||
namespace TCB_SPAN_NAMESPACE_NAME {
|
||||
|
||||
template <std::ptrdiff_t N, typename E, std::ptrdiff_t S>
|
||||
constexpr auto get(span<E, S> s) -> decltype(s[N])
|
||||
{
|
||||
return s[N];
|
||||
}
|
||||
|
||||
} // namespace TCB_SPAN_NAMESPACE_NAME
|
||||
|
||||
namespace std {
|
||||
|
||||
template <typename E, ptrdiff_t S>
|
||||
class tuple_size<tcb::span<E, S>> : public integral_constant<size_t, static_cast<size_t>(S)> {};
|
||||
|
||||
template <typename E>
|
||||
class tuple_size<tcb::span<E, tcb::dynamic_extent>>; // not defined
|
||||
|
||||
template <size_t N, typename E, ptrdiff_t S>
|
||||
class tuple_element<N, tcb::span<E, S>> {
|
||||
public:
|
||||
using type = E;
|
||||
};
|
||||
|
||||
} // end namespace std
|
||||
|
||||
#endif // TCB_SPAN_STD_COMPLIANT_MODE
|
||||
|
||||
#endif // TCB_SPAN_HPP_INCLUDED
|
|
@ -0,0 +1,114 @@
|
|||
/***************************************************************************
|
||||
* Copyright (c) Johan Mabille, Sylvain Corlay and Wolf Vollprecht *
|
||||
* Copyright (c) QuantStack *
|
||||
* *
|
||||
* Distributed under the terms of the BSD 3-Clause License. *
|
||||
* *
|
||||
* The full license is in the file LICENSE, distributed with this software. *
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef XTL_XSYSTEM_HPP
|
||||
#define XTL_XSYSTEM_HPP
|
||||
|
||||
#if defined(__linux__)
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
#if defined(_WIN32)
|
||||
# if defined(NOMINMAX)
|
||||
# include <windows.h>
|
||||
# else
|
||||
# define NOMINMAX
|
||||
# include <windows.h>
|
||||
# undef NOMINMAX
|
||||
# endif
|
||||
#endif
|
||||
#ifdef __APPLE__
|
||||
# include <cstdint>
|
||||
# include <mach-o/dyld.h>
|
||||
#endif
|
||||
#if defined(__sun)
|
||||
# include <stdlib.h>
|
||||
#endif
|
||||
#ifdef __FreeBSD__
|
||||
# include <sys/types.h>
|
||||
# include <sys/sysctl.h>
|
||||
#endif
|
||||
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
|
||||
namespace xtl
|
||||
{
|
||||
std::string executable_path();
|
||||
std::string prefix_path();
|
||||
|
||||
/******************
|
||||
* implementation *
|
||||
******************/
|
||||
|
||||
inline std::string executable_path()
|
||||
{
|
||||
std::string path;
|
||||
char buffer[1024];
|
||||
std::memset(buffer, '\0', sizeof(buffer));
|
||||
#if defined(__linux__)
|
||||
if (readlink("/proc/self/exe", buffer, sizeof(buffer)) != -1)
|
||||
{
|
||||
path = buffer;
|
||||
}
|
||||
else
|
||||
{
|
||||
// failed to determine run path
|
||||
}
|
||||
#elif defined (_WIN32)
|
||||
if (GetModuleFileName(nullptr, buffer, sizeof(buffer)) != 0)
|
||||
{
|
||||
path = buffer;
|
||||
}
|
||||
else
|
||||
{
|
||||
// failed to determine run path
|
||||
}
|
||||
#elif defined (__APPLE__)
|
||||
std::uint32_t size = sizeof(buffer);
|
||||
if(_NSGetExecutablePath(buffer, &size) == 0)
|
||||
{
|
||||
path = buffer;
|
||||
}
|
||||
else
|
||||
{
|
||||
// failed to determine run path
|
||||
}
|
||||
#elif defined (__FreeBSD__)
|
||||
int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1};
|
||||
size_t buffer_size = sizeof(buffer);
|
||||
if (sysctl(mib, 4, buffer, &buffer_size, NULL, 0) != -1)
|
||||
{
|
||||
path = buffer;
|
||||
}
|
||||
else
|
||||
{
|
||||
// failed to determine run path
|
||||
}
|
||||
#elif defined(__sun)
|
||||
path = getexecname();
|
||||
#endif
|
||||
return path;
|
||||
}
|
||||
|
||||
inline std::string prefix_path()
|
||||
{
|
||||
std::string path = executable_path();
|
||||
#if defined (_WIN32)
|
||||
char separator = '\\';
|
||||
#else
|
||||
char separator = '/';
|
||||
#endif
|
||||
std::string bin_folder = path.substr(0, path.find_last_of(separator));
|
||||
std::string prefix = bin_folder.substr(0, bin_folder.find_last_of(separator)) + separator;
|
||||
return prefix;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
/***************************************************************************
|
||||
* Copyright (c) Johan Mabille, Sylvain Corlay and Wolf Vollprecht *
|
||||
* Copyright (c) QuantStack *
|
||||
* *
|
||||
* Distributed under the terms of the BSD 3-Clause License. *
|
||||
* *
|
||||
* The full license is in the file LICENSE, distributed with this software. *
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef XTL_CONFIG_HPP
|
||||
#define XTL_CONFIG_HPP
|
||||
|
||||
#define XTL_VERSION_MAJOR 0
|
||||
#define XTL_VERSION_MINOR 7
|
||||
#define XTL_VERSION_PATCH 2
|
||||
|
||||
#ifndef __has_feature
|
||||
#define __has_feature(x) 0
|
||||
#endif
|
||||
|
||||
// Attempt to discover whether we're being compiled with exception support
|
||||
#if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(XTL_NO_EXCEPTIONS)
|
||||
// Exceptions are enabled.
|
||||
#else
|
||||
// Exceptions are disabled.
|
||||
#define XTL_NO_EXCEPTIONS
|
||||
#endif
|
||||
|
||||
#if defined(XTL_NO_EXCEPTIONS)
|
||||
#define XTL_THROW(_, msg) \
|
||||
{ \
|
||||
std::cerr << msg << std::endl; \
|
||||
std::abort(); \
|
||||
}
|
||||
#else
|
||||
#define XTL_THROW(exception, msg) throw exception(msg)
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,458 @@
|
|||
/***************************************************************************
|
||||
* Copyright (c) Johan Mabille, Sylvain Corlay and Wolf Vollprecht *
|
||||
* Copyright (c) QuantStack *
|
||||
* *
|
||||
* Distributed under the terms of the BSD 3-Clause License. *
|
||||
* *
|
||||
* The full license is in the file LICENSE, distributed with this software. *
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef XTL_TYPE_TRAITS_HPP
|
||||
#define XTL_TYPE_TRAITS_HPP
|
||||
|
||||
#include <complex>
|
||||
#include <chrono>
|
||||
#include <type_traits>
|
||||
|
||||
#include "xtl_config.hpp"
|
||||
|
||||
namespace xtl
|
||||
{
|
||||
/************************************
|
||||
* std proxy traits *
|
||||
************************************/
|
||||
|
||||
template <class T>
|
||||
struct is_scalar : std::is_scalar<T>
|
||||
{
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct is_arithmetic : std::is_arithmetic<T>
|
||||
{
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct is_fundamental : std::is_fundamental<T>
|
||||
{
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct is_signed : std::is_signed<T>
|
||||
{
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct is_floating_point : std::is_floating_point<T>
|
||||
{
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct is_integral : std::is_integral<T>
|
||||
{
|
||||
};
|
||||
|
||||
/************************************
|
||||
* arithmetic type promotion traits *
|
||||
************************************/
|
||||
|
||||
/**
|
||||
* Traits class for the result type of mixed arithmetic expressions.
|
||||
* For example, <tt>promote_type<unsigned char, unsigned char>::type</tt> tells
|
||||
* the user that <tt>unsigned char + unsigned char => int</tt>.
|
||||
*/
|
||||
template <class... T>
|
||||
struct promote_type;
|
||||
|
||||
template <>
|
||||
struct promote_type<>
|
||||
{
|
||||
using type = void;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct promote_type<T>
|
||||
{
|
||||
using type = typename promote_type<T, T>::type;
|
||||
};
|
||||
|
||||
template <class C, class D1, class D2>
|
||||
struct promote_type<std::chrono::time_point<C, D1>, std::chrono::time_point<C, D2>>
|
||||
{
|
||||
using type = std::chrono::time_point<C, typename promote_type<D1, D2>::type>;
|
||||
};
|
||||
|
||||
template <class T0, class T1>
|
||||
struct promote_type<T0, T1>
|
||||
{
|
||||
using type = decltype(std::declval<std::decay_t<T0>>() + std::declval<std::decay_t<T1>>());
|
||||
};
|
||||
|
||||
template <class T0, class... REST>
|
||||
struct promote_type<T0, REST...>
|
||||
{
|
||||
using type = decltype(std::declval<std::decay_t<T0>>() + std::declval<typename promote_type<REST...>::type>());
|
||||
};
|
||||
|
||||
template <>
|
||||
struct promote_type<bool>
|
||||
{
|
||||
using type = bool;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct promote_type<bool, T>
|
||||
{
|
||||
using type = T;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct promote_type<bool, std::complex<T>>
|
||||
{
|
||||
using type = std::complex<T>;
|
||||
};
|
||||
|
||||
template <class T1, class T2>
|
||||
struct promote_type<T1, std::complex<T2>>
|
||||
{
|
||||
using type = std::complex<typename promote_type<T1, T2>::type>;
|
||||
};
|
||||
|
||||
template <class T1, class T2>
|
||||
struct promote_type<std::complex<T1>, T2>
|
||||
: promote_type<T2, std::complex<T1>>
|
||||
{
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct promote_type<std::complex<T>, std::complex<T>>
|
||||
{
|
||||
using type = std::complex<T>;
|
||||
};
|
||||
|
||||
template <class T1, class T2>
|
||||
struct promote_type<std::complex<T1>, std::complex<T2>>
|
||||
{
|
||||
using type = std::complex<typename promote_type<T1, T2>::type>;
|
||||
};
|
||||
|
||||
template <class... REST>
|
||||
struct promote_type<bool, REST...>
|
||||
{
|
||||
using type = typename promote_type<bool, typename promote_type<REST...>::type>::type;
|
||||
};
|
||||
|
||||
/**
|
||||
* Abbreviation of 'typename promote_type<T>::type'.
|
||||
*/
|
||||
template <class... T>
|
||||
using promote_type_t = typename promote_type<T...>::type;
|
||||
|
||||
/**
|
||||
* Traits class to find the biggest type of the same kind.
|
||||
*
|
||||
* For example, <tt>big_promote_type<unsigned char>::type</tt> is <tt>unsigned long long</tt>.
|
||||
* The default implementation only supports built-in types and <tt>std::complex</tt>. All
|
||||
* other types remain unchanged unless <tt>big_promote_type</tt> gets specialized for them.
|
||||
*/
|
||||
template <class T>
|
||||
struct big_promote_type
|
||||
{
|
||||
private:
|
||||
|
||||
using V = std::decay_t<T>;
|
||||
static constexpr bool is_arithmetic = xtl::is_arithmetic<V>::value;
|
||||
static constexpr bool is_signed = xtl::is_signed<V>::value;
|
||||
static constexpr bool is_integral = xtl::is_integral<V>::value;
|
||||
static constexpr bool is_long_double = std::is_same<V, long double>::value;
|
||||
|
||||
public:
|
||||
|
||||
using type = std::conditional_t<is_arithmetic,
|
||||
std::conditional_t<is_integral,
|
||||
std::conditional_t<is_signed, long long, unsigned long long>,
|
||||
std::conditional_t<is_long_double, long double, double>
|
||||
>,
|
||||
V
|
||||
>;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct big_promote_type<std::complex<T>>
|
||||
{
|
||||
using type = std::complex<typename big_promote_type<T>::type>;
|
||||
};
|
||||
|
||||
/**
|
||||
* Abbreviation of 'typename big_promote_type<T>::type'.
|
||||
*/
|
||||
template <class T>
|
||||
using big_promote_type_t = typename big_promote_type<T>::type;
|
||||
|
||||
namespace traits_detail
|
||||
{
|
||||
using std::sqrt;
|
||||
|
||||
template <class T>
|
||||
using real_promote_type_t = decltype(sqrt(std::declval<std::decay_t<T>>()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Result type of algebraic expressions.
|
||||
*
|
||||
* For example, <tt>real_promote_type<int>::type</tt> tells the
|
||||
* user that <tt>sqrt(int) => double</tt>.
|
||||
*/
|
||||
template <class T>
|
||||
struct real_promote_type
|
||||
{
|
||||
using type = traits_detail::real_promote_type_t<T>;
|
||||
};
|
||||
|
||||
/**
|
||||
* Abbreviation of 'typename real_promote_type<T>::type'.
|
||||
*/
|
||||
template <class T>
|
||||
using real_promote_type_t = typename real_promote_type<T>::type;
|
||||
|
||||
/**
|
||||
* Traits class to replace 'bool' with 'uint8_t' and keep everything else.
|
||||
*
|
||||
* This is useful for scientific computing, where a boolean mask array is
|
||||
* usually implemented as an array of bytes.
|
||||
*/
|
||||
template <class T>
|
||||
struct bool_promote_type
|
||||
{
|
||||
using type = typename std::conditional<std::is_same<T, bool>::value, uint8_t, T>::type;
|
||||
};
|
||||
|
||||
/**
|
||||
* Abbreviation for typename bool_promote_type<T>::type
|
||||
*/
|
||||
template <class T>
|
||||
using bool_promote_type_t = typename bool_promote_type<T>::type;
|
||||
|
||||
/************
|
||||
* apply_cv *
|
||||
************/
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <class T, class U, bool = std::is_const<std::remove_reference_t<T>>::value,
|
||||
bool = std::is_volatile<std::remove_reference_t<T>>::value>
|
||||
struct apply_cv_impl
|
||||
{
|
||||
using type = U;
|
||||
};
|
||||
|
||||
template <class T, class U>
|
||||
struct apply_cv_impl<T, U, true, false>
|
||||
{
|
||||
using type = const U;
|
||||
};
|
||||
|
||||
template <class T, class U>
|
||||
struct apply_cv_impl<T, U, false, true>
|
||||
{
|
||||
using type = volatile U;
|
||||
};
|
||||
|
||||
template <class T, class U>
|
||||
struct apply_cv_impl<T, U, true, true>
|
||||
{
|
||||
using type = const volatile U;
|
||||
};
|
||||
|
||||
template <class T, class U>
|
||||
struct apply_cv_impl<T&, U, false, false>
|
||||
{
|
||||
using type = U&;
|
||||
};
|
||||
|
||||
template <class T, class U>
|
||||
struct apply_cv_impl<T&, U, true, false>
|
||||
{
|
||||
using type = const U&;
|
||||
};
|
||||
|
||||
template <class T, class U>
|
||||
struct apply_cv_impl<T&, U, false, true>
|
||||
{
|
||||
using type = volatile U&;
|
||||
};
|
||||
|
||||
template <class T, class U>
|
||||
struct apply_cv_impl<T&, U, true, true>
|
||||
{
|
||||
using type = const volatile U&;
|
||||
};
|
||||
}
|
||||
|
||||
template <class T, class U>
|
||||
struct apply_cv
|
||||
{
|
||||
using type = typename detail::apply_cv_impl<T, U>::type;
|
||||
};
|
||||
|
||||
template <class T, class U>
|
||||
using apply_cv_t = typename apply_cv<T, U>::type;
|
||||
|
||||
/****************************************************************
|
||||
* C++17 logical operators (disjunction, conjunction, negation) *
|
||||
****************************************************************/
|
||||
|
||||
/********************
|
||||
* disjunction - or *
|
||||
********************/
|
||||
|
||||
template <class...>
|
||||
struct disjunction;
|
||||
|
||||
template <>
|
||||
struct disjunction<> : std::false_type
|
||||
{
|
||||
};
|
||||
|
||||
template <class Arg>
|
||||
struct disjunction<Arg> : Arg
|
||||
{
|
||||
};
|
||||
|
||||
template <class Arg1, class Arg2, class... Args>
|
||||
struct disjunction<Arg1, Arg2, Args...> : std::conditional_t<Arg1::value, Arg1, disjunction<Arg2, Args...>>
|
||||
{
|
||||
};
|
||||
|
||||
/*********************
|
||||
* conjunction - and *
|
||||
*********************/
|
||||
|
||||
template <class...>
|
||||
struct conjunction;
|
||||
|
||||
template <>
|
||||
struct conjunction<> : std::true_type
|
||||
{
|
||||
};
|
||||
|
||||
template <class Arg1>
|
||||
struct conjunction<Arg1> : Arg1
|
||||
{
|
||||
};
|
||||
|
||||
template <class Arg1, class Arg2, class... Args>
|
||||
struct conjunction<Arg1, Arg2, Args...> : std::conditional_t<Arg1::value, conjunction<Arg2, Args...>, Arg1>
|
||||
{
|
||||
};
|
||||
|
||||
/******************
|
||||
* negation - not *
|
||||
******************/
|
||||
|
||||
template <class Arg>
|
||||
struct negation : std::integral_constant<bool, !Arg::value>
|
||||
{
|
||||
};
|
||||
|
||||
/************
|
||||
* concepts *
|
||||
************/
|
||||
|
||||
#if !defined(__GNUC__) || (defined(__GNUC__) && (__GNUC__ >= 5))
|
||||
|
||||
template <class... C>
|
||||
constexpr bool xtl_requires = conjunction<C...>::value;
|
||||
|
||||
template <class... C>
|
||||
constexpr bool either = disjunction<C...>::value;
|
||||
|
||||
template <class... C>
|
||||
constexpr bool disallow = xtl::negation<xtl::conjunction<C...>>::value;
|
||||
|
||||
template <class... C>
|
||||
constexpr bool disallow_one = xtl::negation<xtl::disjunction<C...>>::value;
|
||||
|
||||
template <class... C>
|
||||
using check_requires = std::enable_if_t<xtl_requires<C...>, int>;
|
||||
|
||||
template <class... C>
|
||||
using check_either = std::enable_if_t<either<C...>, int>;
|
||||
|
||||
template <class... C>
|
||||
using check_disallow = std::enable_if_t<disallow<C...>, int>;
|
||||
|
||||
template <class... C>
|
||||
using check_disallow_one = std::enable_if_t<disallow_one<C...>, int>;
|
||||
|
||||
#else
|
||||
|
||||
template <class... C>
|
||||
using check_requires = std::enable_if_t<conjunction<C...>::value, int>;
|
||||
|
||||
template <class... C>
|
||||
using check_either = std::enable_if_t<disjunction<C...>::value, int>;
|
||||
|
||||
template <class... C>
|
||||
using check_disallow = std::enable_if_t<xtl::negation<xtl::conjunction<C...>>::value, int>;
|
||||
|
||||
template <class... C>
|
||||
using check_disallow_one = std::enable_if_t<xtl::negation<xtl::disjunction<C...>>::value, int>;
|
||||
|
||||
#endif
|
||||
|
||||
#define XTL_REQUIRES_IMPL(...) xtl::check_requires<__VA_ARGS__>
|
||||
#define XTL_REQUIRES(...) XTL_REQUIRES_IMPL(__VA_ARGS__) = 0
|
||||
|
||||
#define XTL_EITHER_IMPL(...) xtl::check_either<__VA_ARGS__>
|
||||
#define XTL_EITHER(...) XTL_EITHER_IMPL(__VA_ARGS__) = 0
|
||||
|
||||
#define XTL_DISALLOW_IMPL(...) xtl::check_disallow<__VA_ARGS__>
|
||||
#define XTL_DISALLOW(...) XTL_DISALLOW_IMPL(__VA_ARGS__) = 0
|
||||
|
||||
#define XTL_DISALLOW_ONE_IMPL(...) xtl::check_disallow_one<__VA_ARGS__>
|
||||
#define XTL_DISALLOW_ONE(...) XTL_DISALLOW_ONE_IMPL(__VA_ARGS__) = 0
|
||||
|
||||
// For backward compatibility
|
||||
template <class... C>
|
||||
using check_concept = check_requires<C...>;
|
||||
|
||||
/**************
|
||||
* all_scalar *
|
||||
**************/
|
||||
|
||||
template <class... Args>
|
||||
struct all_scalar : conjunction<xtl::is_scalar<Args>...>
|
||||
{
|
||||
};
|
||||
|
||||
/************
|
||||
* constify *
|
||||
************/
|
||||
|
||||
// Adds const to the underlying type of a reference or pointer, or to the type itself
|
||||
// if it's not a reference nor a pointer
|
||||
|
||||
template <class T>
|
||||
struct constify
|
||||
{
|
||||
using type = std::add_const_t<T>;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct constify<T*>
|
||||
{
|
||||
using type = std::add_const_t<T>*;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct constify<T&>
|
||||
{
|
||||
using type = std::add_const_t<T>&;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
using constify_t = typename constify<T>::type;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,206 @@
|
|||
/***************************************************************************
|
||||
* Copyright (c) Johan Mabille, Sylvain Corlay and Wolf Vollprecht *
|
||||
* Copyright (c) QuantStack *
|
||||
* *
|
||||
* Distributed under the terms of the BSD 3-Clause License. *
|
||||
* *
|
||||
* The full license is in the file LICENSE, distributed with this software. *
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef XTL_XVARIANT_HPP
|
||||
#define XTL_XVARIANT_HPP
|
||||
|
||||
#include "xvariant_impl.hpp"
|
||||
#include "xclosure.hpp"
|
||||
#include "xmeta_utils.hpp"
|
||||
|
||||
namespace xtl
|
||||
{
|
||||
using mpark::variant;
|
||||
using mpark::monostate;
|
||||
using mpark::bad_variant_access;
|
||||
using mpark::variant_size;
|
||||
#ifdef MPARK_VARIABLE_TEMPLATES
|
||||
using mpark::variant_size_v;
|
||||
#endif
|
||||
using mpark::variant_alternative;
|
||||
using mpark::variant_alternative_t;
|
||||
using mpark::variant_npos;
|
||||
|
||||
using mpark::visit;
|
||||
using mpark::holds_alternative;
|
||||
using mpark::get;
|
||||
using mpark::get_if;
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <class T>
|
||||
struct xgetter
|
||||
{
|
||||
template <class... Ts>
|
||||
static constexpr T& get(xtl::variant<Ts...>& v)
|
||||
{
|
||||
return xtl::get<T>(v);
|
||||
}
|
||||
|
||||
template <class... Ts>
|
||||
static constexpr T&& get(xtl::variant<Ts...>&& v)
|
||||
{
|
||||
return xtl::get<T>(std::move(v));
|
||||
}
|
||||
|
||||
template <class... Ts>
|
||||
static constexpr const T& get(const xtl::variant<Ts...>& v)
|
||||
{
|
||||
return xtl::get<T>(v);
|
||||
}
|
||||
|
||||
template <class... Ts>
|
||||
static constexpr const T&& get(const xtl::variant<Ts...>&& v)
|
||||
{
|
||||
return xtl::get<T>(std::move(v));
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct xgetter<T&>
|
||||
{
|
||||
template <class... Ts>
|
||||
static constexpr T& get(xtl::variant<Ts...>& v)
|
||||
{
|
||||
return xtl::get<xtl::xclosure_wrapper<T&>>(v).get();
|
||||
}
|
||||
|
||||
template <class... Ts>
|
||||
static constexpr T& get(xtl::variant<Ts...>&& v)
|
||||
{
|
||||
return xtl::get<xtl::xclosure_wrapper<T&>>(std::move(v)).get();
|
||||
}
|
||||
|
||||
template <class... Ts>
|
||||
static constexpr const T& get(const xtl::variant<Ts...>& v)
|
||||
{
|
||||
return xtl::get<xtl::xclosure_wrapper<T&>>(v).get();
|
||||
}
|
||||
|
||||
template <class... Ts>
|
||||
static constexpr const T& get(const xtl::variant<Ts...>&& v)
|
||||
{
|
||||
return xtl::get<xtl::xclosure_wrapper<T&>>(std::move(v)).get();
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct xgetter<const T&>
|
||||
{
|
||||
template <class... Ts>
|
||||
static constexpr const T& get(const xtl::variant<Ts...>& v)
|
||||
{
|
||||
using cl_type = xtl::xclosure_wrapper<const T&>;
|
||||
return get_impl(v, xtl::mpl::contains<xtl::mpl::vector<Ts...>, cl_type>());
|
||||
}
|
||||
|
||||
template <class... Ts>
|
||||
static constexpr const T& get(const xtl::variant<Ts...>&& v)
|
||||
{
|
||||
using cl_type = xtl::xclosure_wrapper<const T&>;
|
||||
return get_impl(std::move(v), xtl::mpl::contains<xtl::mpl::vector<Ts...>, cl_type>());
|
||||
}
|
||||
|
||||
template <class... Ts>
|
||||
static constexpr const T& get(xtl::variant<Ts...>& v)
|
||||
{
|
||||
return get(static_cast<const xtl::variant<Ts...>&>(v));
|
||||
}
|
||||
|
||||
template <class... Ts>
|
||||
static constexpr const T& get(xtl::variant<Ts...>&& v)
|
||||
{
|
||||
return get(static_cast<const xtl::variant<Ts...>&&>(v));
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
template <class... Ts>
|
||||
static constexpr const T& get_impl(const xtl::variant<Ts...>& v, xtl::mpl::bool_<true>)
|
||||
{
|
||||
return xtl::get<xtl::xclosure_wrapper<const T&>>(v).get();
|
||||
}
|
||||
|
||||
template <class... Ts>
|
||||
static constexpr const T& get_impl(const xtl::variant<Ts...>& v, xtl::mpl::bool_<false>)
|
||||
{
|
||||
return static_cast<const xtl::xclosure_wrapper<T&>&>(xtl::get<xtl::xclosure_wrapper<T&>>(v)).get();
|
||||
}
|
||||
|
||||
template <class... Ts>
|
||||
static constexpr const T& get_impl(const xtl::variant<Ts...>&& v, xtl::mpl::bool_<true>)
|
||||
{
|
||||
return xtl::get<xtl::closure_wrapper<const T&>>(std::move(v)).get();
|
||||
}
|
||||
|
||||
template <class... Ts>
|
||||
static constexpr const T& get_impl(const xtl::variant<Ts...>&& v, xtl::mpl::bool_<false>)
|
||||
{
|
||||
return static_cast<const xtl::xclosure_wrapper<T&>&&>(xtl::get<xtl::xclosure_wrapper<T&>>(std::move(v))).get();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
template <class T, class... Ts>
|
||||
constexpr decltype(auto) xget(xtl::variant<Ts...>& v)
|
||||
{
|
||||
return detail::xgetter<T>::get(v);
|
||||
}
|
||||
|
||||
template <class T, class... Ts>
|
||||
constexpr decltype(auto) xget(xtl::variant<Ts...>&& v)
|
||||
{
|
||||
return detail::xgetter<T>::get(std::move(v));
|
||||
}
|
||||
|
||||
template <class T, class... Ts>
|
||||
constexpr decltype(auto) xget(const xtl::variant<Ts...>& v)
|
||||
{
|
||||
return detail::xgetter<T>::get(v);
|
||||
}
|
||||
|
||||
template <class T, class... Ts>
|
||||
constexpr decltype(auto) xget(const xtl::variant<Ts...>&& v)
|
||||
{
|
||||
return detail::xgetter<T>::get(std::move(v));
|
||||
}
|
||||
|
||||
/************************
|
||||
* overload for lambdas *
|
||||
************************/
|
||||
|
||||
// This hierarchy is required since ellipsis in using declarations are not supported until C++17
|
||||
template <class... Ts>
|
||||
struct overloaded;
|
||||
|
||||
template <class T>
|
||||
struct overloaded<T> : T
|
||||
{
|
||||
overloaded(T arg) : T(arg) {}
|
||||
using T::operator();
|
||||
};
|
||||
|
||||
template <class T1, class T2, class... Ts>
|
||||
struct overloaded<T1, T2, Ts...> : T1, overloaded<T2, Ts...>
|
||||
{
|
||||
template <class... Us>
|
||||
overloaded(T1 t1, T2 t2, Us... args) : T1(t1), overloaded<T2, Ts...>(t2, args...) {}
|
||||
|
||||
using T1::operator();
|
||||
using overloaded<T2, Ts...>::operator();
|
||||
};
|
||||
|
||||
template <class... Ts>
|
||||
inline overloaded<Ts...> make_overload(Ts... arg)
|
||||
{
|
||||
return overloaded<Ts...>{arg...};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,195 @@
|
|||
/***************************************************************************
|
||||
* Copyright (c) Johan Mabille, Sylvain Corlay and Wolf Vollprecht *
|
||||
* Copyright (c) QuantStack *
|
||||
* *
|
||||
* Distributed under the terms of the BSD 3-Clause License. *
|
||||
* *
|
||||
* The full license is in the file LICENSE, distributed with this software. *
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef XTL_VISITOR_HPP
|
||||
#define XTL_VISITOR_HPP
|
||||
|
||||
#include <stdexcept>
|
||||
#include "xmeta_utils.hpp"
|
||||
|
||||
namespace xtl
|
||||
{
|
||||
// Loki's visitor ported to C++14
|
||||
// Original implementation can be found at:
|
||||
// https://github.com/snaewe/loki-lib/blob/master/include/loki/Visitor.h
|
||||
|
||||
/****************
|
||||
* base_visitor *
|
||||
****************/
|
||||
|
||||
class base_visitor
|
||||
{
|
||||
public:
|
||||
|
||||
virtual ~base_visitor() = default;
|
||||
};
|
||||
|
||||
/***********
|
||||
* visitor *
|
||||
***********/
|
||||
|
||||
template <class T, class R = void, bool is_const = true>
|
||||
class visitor
|
||||
{
|
||||
public:
|
||||
|
||||
using return_type = R;
|
||||
using param_type = std::conditional_t<is_const, const T, T>;
|
||||
|
||||
virtual ~visitor() = default;
|
||||
|
||||
virtual return_type visit(param_type&) = 0;
|
||||
};
|
||||
|
||||
template <class R, bool is_const>
|
||||
class visitor<mpl::vector<>, R, is_const>
|
||||
{
|
||||
};
|
||||
|
||||
template <class R, bool is_const, class T, class... U>
|
||||
class visitor<mpl::vector<T, U...>, R, is_const>
|
||||
: public visitor<T, R, is_const>
|
||||
, public visitor<mpl::vector<U...>, R, is_const>
|
||||
{
|
||||
};
|
||||
|
||||
/**********************
|
||||
* catch_all policies *
|
||||
**********************/
|
||||
|
||||
template <class R, class T>
|
||||
struct default_catch_all
|
||||
{
|
||||
static R on_unknown_visitor(T&, base_visitor&)
|
||||
{
|
||||
return R();
|
||||
}
|
||||
};
|
||||
|
||||
template <class R, class T>
|
||||
struct throwing_catch_all
|
||||
{
|
||||
static R on_unknown_visitor(T&, base_visitor&)
|
||||
{
|
||||
XTL_THROW(std::runtime_error, "Unknown visited type");
|
||||
}
|
||||
};
|
||||
|
||||
/******************
|
||||
* base_visitable *
|
||||
******************/
|
||||
|
||||
template
|
||||
<
|
||||
class R = void,
|
||||
bool const_visitable = false,
|
||||
template <class, class> class catch_all = default_catch_all
|
||||
>
|
||||
class base_visitable;
|
||||
|
||||
template <class R, template <class, class> class catch_all>
|
||||
class base_visitable<R, false, catch_all>
|
||||
{
|
||||
public:
|
||||
|
||||
using return_type = R;
|
||||
|
||||
virtual ~base_visitable() = default;
|
||||
virtual return_type accept(base_visitor&) = 0;
|
||||
|
||||
protected:
|
||||
|
||||
template <class T>
|
||||
static return_type accept_impl(T& visited, base_visitor& vis)
|
||||
{
|
||||
if (auto* p = dynamic_cast<visitor<T, R, false>*>(&vis))
|
||||
{
|
||||
return p->visit(visited);
|
||||
}
|
||||
return catch_all<R, T>::on_unknown_visitor(visited, vis);
|
||||
}
|
||||
};
|
||||
|
||||
template <class R, template <class, class> class catch_all>
|
||||
class base_visitable<R, true, catch_all>
|
||||
{
|
||||
public:
|
||||
|
||||
using return_type = R;
|
||||
|
||||
virtual ~base_visitable() = default;
|
||||
virtual return_type accept(base_visitor&) const = 0;
|
||||
|
||||
protected:
|
||||
|
||||
template <class T>
|
||||
static return_type accept_impl(const T& visited, base_visitor& vis)
|
||||
{
|
||||
if (auto* p = dynamic_cast<visitor<T, R, true>*>(&vis))
|
||||
{
|
||||
return p->visit(visited);
|
||||
}
|
||||
return catch_all<R, const T>::on_unknown_visitor(visited, vis);
|
||||
}
|
||||
};
|
||||
|
||||
/************************
|
||||
* XTL_DEFINE_VISITABLE *
|
||||
************************/
|
||||
|
||||
#define XTL_DEFINE_VISITABLE() \
|
||||
return_type accept(::xtl::base_visitor& vis) override \
|
||||
{ return accept_impl(*this, vis); }
|
||||
|
||||
#define XTL_DEFINE_CONST_VISITABLE() \
|
||||
return_type accept(::xtl::base_visitor& vis) const override \
|
||||
{ return accept_impl(*this, vis); }
|
||||
|
||||
/******************
|
||||
* cyclic_visitor *
|
||||
******************/
|
||||
|
||||
template <class T, class R, bool is_const = true>
|
||||
class cyclic_visitor;
|
||||
|
||||
template <class R, bool is_const, class... T>
|
||||
class cyclic_visitor<mpl::vector<T...>, R, is_const>
|
||||
: public visitor<mpl::vector<T...>, R, is_const>
|
||||
{
|
||||
public:
|
||||
|
||||
using return_type = R;
|
||||
|
||||
template <class V>
|
||||
return_type generic_visit(V& visited)
|
||||
{
|
||||
visitor<std::remove_const_t<V>, return_type, is_const>& sub_obj = *this;
|
||||
return sub_obj.visit(visited);
|
||||
}
|
||||
};
|
||||
|
||||
/*******************************
|
||||
* XTL_DEFINE_CYCLIC_VISITABLE *
|
||||
*******************************/
|
||||
|
||||
#define XTL_DEFINE_CYCLIC_VISITABLE(some_visitor) \
|
||||
virtual some_visitor::return_type accept(some_visitor& vis) \
|
||||
{ \
|
||||
return vis.generic_visit(*this); \
|
||||
}
|
||||
|
||||
#define XTL_DEFINE_CONST_CYCLIC_VISITABLE(some_visitor) \
|
||||
virtual some_visitor::return_type accept(some_visitor& vis) const \
|
||||
{ \
|
||||
return vis.generic_visit(*this); \
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
conda:
|
||||
file: docs/environment.yml
|
|
@ -0,0 +1,175 @@
|
|||
############################################################################
|
||||
# Copyright (c) Johan Mabille, Sylvain Corlay and Wolf Vollprecht #
|
||||
# Copyright (c) QuantStack #
|
||||
# #
|
||||
# Distributed under the terms of the BSD 3-Clause License. #
|
||||
# #
|
||||
# The full license is in the file LICENSE, distributed with this software. #
|
||||
############################################################################
|
||||
|
||||
cmake_minimum_required(VERSION 3.1)
|
||||
|
||||
if (CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR)
|
||||
project(xtl-test)
|
||||
|
||||
enable_testing()
|
||||
|
||||
find_package(xtl REQUIRED CONFIG)
|
||||
find_package(nlohmann_json QUIET CONFIG)
|
||||
set(XTL_INCLUDE_DIR ${xtl_INCLUDE_DIRS})
|
||||
endif ()
|
||||
|
||||
if(NOT CMAKE_BUILD_TYPE)
|
||||
message(STATUS "Setting tests build type to Release")
|
||||
set(CMAKE_BUILD_TYPE Release CACHE STRING "Choose the type of build." FORCE)
|
||||
else()
|
||||
message(STATUS "Tests build type is ${CMAKE_BUILD_TYPE}")
|
||||
endif()
|
||||
|
||||
include(CheckCXXCompilerFlag)
|
||||
|
||||
string(TOUPPER "${CMAKE_BUILD_TYPE}" U_CMAKE_BUILD_TYPE)
|
||||
|
||||
if(nlohmann_json_FOUND)
|
||||
add_definitions(-DHAVE_NLOHMANN_JSON)
|
||||
endif()
|
||||
|
||||
if(CMAKE_CXX_COMPILER_ID MATCHES GNU OR CMAKE_CXX_COMPILER_ID MATCHES Intel)
|
||||
add_compile_options(-Wunused-parameter -Wextra -Wreorder -Wconversion -Wsign-conversion)
|
||||
|
||||
if(NOT CMAKE_CXX_FLAGS MATCHES "-march")
|
||||
CHECK_CXX_COMPILER_FLAG(-march=native HAS_MARCH_NATIVE)
|
||||
if (HAS_MARCH_NATIVE)
|
||||
add_compile_options(-march=native)
|
||||
endif()
|
||||
endif()
|
||||
if (XTL_DISABLE_EXCEPTIONS)
|
||||
add_compile_options(-fno-exceptions)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(CMAKE_CXX_COMPILER_ID MATCHES MSVC)
|
||||
add_compile_options(/EHsc /MP /bigobj)
|
||||
set(CMAKE_EXE_LINKER_FLAGS /MANIFEST:NO)
|
||||
if (XTL_DISABLE_EXCEPTIONS)
|
||||
add_compile_options(/EHs-c-)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(CMAKE_CXX_COMPILER_ID MATCHES Clang)
|
||||
if(NOT WIN32)
|
||||
add_compile_options(-Wunused-parameter -Wextra -Wreorder -Wconversion -Wsign-conversion)
|
||||
|
||||
if(NOT CMAKE_CXX_FLAGS MATCHES "-march")
|
||||
CHECK_CXX_COMPILER_FLAG(-march=native HAS_MARCH_NATIVE)
|
||||
if (HAS_MARCH_NATIVE)
|
||||
add_compile_options(-march=native)
|
||||
endif()
|
||||
endif()
|
||||
if (XTL_DISABLE_EXCEPTIONS)
|
||||
add_compile_options(-fno-exceptions)
|
||||
endif()
|
||||
else() # we are using clang-cl
|
||||
add_compile_options(/EHsc /bigobj -fms-compatibility)
|
||||
set(CMAKE_EXE_LINKER_FLAGS /MANIFEST:NO)
|
||||
if (XTL_DISABLE_EXCEPTIONS)
|
||||
add_compile_options(/EHs-c-)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(DOWNLOAD_GTEST OR GTEST_SRC_DIR)
|
||||
if(DOWNLOAD_GTEST)
|
||||
# Download and unpack googletest at configure time
|
||||
configure_file(downloadGTest.cmake.in googletest-download/CMakeLists.txt)
|
||||
else()
|
||||
# Copy local source of googletest at configure time
|
||||
configure_file(copyGTest.cmake.in googletest-download/CMakeLists.txt)
|
||||
endif()
|
||||
execute_process(COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" .
|
||||
RESULT_VARIABLE result
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/googletest-download )
|
||||
if(result)
|
||||
message(FATAL_ERROR "CMake step for googletest failed: ${result}")
|
||||
endif()
|
||||
execute_process(COMMAND ${CMAKE_COMMAND} --build .
|
||||
RESULT_VARIABLE result
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/googletest-download )
|
||||
if(result)
|
||||
message(FATAL_ERROR "Build step for googletest failed: ${result}")
|
||||
endif()
|
||||
|
||||
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
|
||||
|
||||
# Add googletest directly to our build. This defines
|
||||
# the gtest and gtest_main targets.
|
||||
add_subdirectory(${CMAKE_CURRENT_BINARY_DIR}/googletest-src
|
||||
${CMAKE_CURRENT_BINARY_DIR}/googletest-build EXCLUDE_FROM_ALL)
|
||||
|
||||
set(GTEST_INCLUDE_DIRS "${gtest_SOURCE_DIR}/include")
|
||||
add_library(GTest::GTest INTERFACE IMPORTED)
|
||||
target_link_libraries(GTest::GTest INTERFACE gtest)
|
||||
add_library(GTest::Main INTERFACE IMPORTED)
|
||||
target_link_libraries(GTest::Main INTERFACE gtest_main)
|
||||
else()
|
||||
find_package(GTest REQUIRED)
|
||||
endif()
|
||||
|
||||
find_package(Threads)
|
||||
|
||||
include_directories(${GTEST_INCLUDE_DIRS})
|
||||
|
||||
set(XTL_TESTS
|
||||
test_xbase64.cpp
|
||||
test_xbasic_fixed_string.cpp
|
||||
test_xcomplex.cpp
|
||||
test_xcomplex_sequence.cpp
|
||||
test_xclosure.cpp
|
||||
test_xdynamic_bitset.cpp
|
||||
test_xfunctional.cpp
|
||||
test_xhalf_float.cpp
|
||||
test_xhash.cpp
|
||||
test_xhierarchy_generator.cpp
|
||||
test_xiterator_base.cpp
|
||||
test_xmasked_value.cpp
|
||||
test_xmeta_utils.cpp
|
||||
test_xmultimethods.cpp
|
||||
test_xoptional.cpp
|
||||
test_xsequence.cpp
|
||||
test_xtype_traits.cpp
|
||||
test_xplatform.cpp
|
||||
test_xproxy_wrapper.cpp
|
||||
test_xsystem.cpp
|
||||
test_xvariant.cpp
|
||||
test_xvisitor.cpp
|
||||
)
|
||||
|
||||
if(nlohmann_json_FOUND)
|
||||
# Version up to 3.1.2 export the target `nlohmann_json`
|
||||
if(TARGET nlohmann_json)
|
||||
set(nlohmann_json_TARGET nlohmann_json)
|
||||
# Newer versions export the namespaced target `nlohmann_json::nlohmann_json`
|
||||
elseif(TARGET nlohmann_json::nlohmann_json)
|
||||
set(nlohmann_json_TARGET nlohmann_json::nlohmann_json)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
foreach(filename IN LISTS XTL_TESTS)
|
||||
get_filename_component(targetname ${filename} NAME_WE)
|
||||
|
||||
add_executable(${targetname} ${filename} ${XTL_HEADERS})
|
||||
target_include_directories(${targetname} PRIVATE ${XTL_INCLUDE_DIR})
|
||||
target_link_libraries(${targetname} xtl GTest::GTest GTest::Main Threads::Threads ${nlohmann_json_TARGET})
|
||||
|
||||
add_test(NAME ${targetname} COMMAND ${targetname})
|
||||
endforeach()
|
||||
|
||||
add_executable(test_xtl ${XTL_TESTS} ${XTL_HEADERS})
|
||||
target_include_directories(test_xtl PRIVATE ${XTL_INCLUDE_DIR})
|
||||
if(DOWNLOAD_GTEST OR GTEST_SRC_DIR)
|
||||
add_dependencies(test_xtl gtest_main)
|
||||
endif()
|
||||
target_link_libraries(test_xtl xtl GTest::GTest GTest::Main Threads::Threads ${nlohmann_json_TARGET})
|
||||
|
||||
add_custom_target(xtest COMMAND test_xtl DEPENDS test_xtl)
|
||||
add_test(NAME xtest COMMAND test_xtl)
|
|
@ -0,0 +1,24 @@
|
|||
############################################################################
|
||||
# Copyright (c) Johan Mabille, Sylvain Corlay and Wolf Vollprecht #
|
||||
# Copyright (c) QuantStack #
|
||||
# #
|
||||
# Distributed under the terms of the BSD 3-Clause License. #
|
||||
# #
|
||||
# The full license is in the file LICENSE, distributed with this software. #
|
||||
############################################################################
|
||||
|
||||
cmake_minimum_required(VERSION 2.8.2)
|
||||
|
||||
project(googletest-download NONE)
|
||||
|
||||
include(ExternalProject)
|
||||
ExternalProject_Add(googletest
|
||||
URL "${GTEST_SRC_DIR}"
|
||||
SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/googletest-src"
|
||||
BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/googletest-build"
|
||||
CONFIGURE_COMMAND ""
|
||||
BUILD_COMMAND ""
|
||||
INSTALL_COMMAND ""
|
||||
TEST_COMMAND ""
|
||||
)
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
############################################################################
|
||||
# Copyright (c) Johan Mabille, Sylvain Corlay and Wolf Vollprecht #
|
||||
# Copyright (c) QuantStack #
|
||||
# #
|
||||
# Distributed under the terms of the BSD 3-Clause License. #
|
||||
# #
|
||||
# The full license is in the file LICENSE, distributed with this software. #
|
||||
############################################################################
|
||||
|
||||
cmake_minimum_required(VERSION 2.8.2)
|
||||
|
||||
project(googletest-download NONE)
|
||||
|
||||
include(ExternalProject)
|
||||
ExternalProject_Add(googletest
|
||||
GIT_REPOSITORY https://github.com/JohanMabille/googletest.git
|
||||
GIT_TAG warnings
|
||||
SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/googletest-src"
|
||||
BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/googletest-build"
|
||||
CONFIGURE_COMMAND ""
|
||||
BUILD_COMMAND ""
|
||||
INSTALL_COMMAND ""
|
||||
TEST_COMMAND ""
|
||||
)
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
/***************************************************************************
|
||||
* Copyright (c) Johan Mabille, Sylvain Corlay and Wolf Vollprecht *
|
||||
* Copyright (c) QuantStack *
|
||||
* *
|
||||
* Distributed under the terms of the BSD 3-Clause License. *
|
||||
* *
|
||||
* The full license is in the file LICENSE, distributed with this software. *
|
||||
****************************************************************************/
|
||||
|
||||
#include "xtl/xbase64.hpp"
|
||||
|
||||
#include <complex>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
namespace xtl
|
||||
{
|
||||
TEST(xbase64, encode)
|
||||
{
|
||||
EXPECT_EQ(base64encode(""), "");
|
||||
EXPECT_EQ(base64encode("f"), "Zg==");
|
||||
EXPECT_EQ(base64encode("fo"), "Zm8=");
|
||||
EXPECT_EQ(base64encode("foo"), "Zm9v");
|
||||
EXPECT_EQ(base64encode("foob"), "Zm9vYg==");
|
||||
EXPECT_EQ(base64encode("fooba"), "Zm9vYmE=");
|
||||
EXPECT_EQ(base64encode("foobar"), "Zm9vYmFy");
|
||||
}
|
||||
|
||||
TEST(xbase64, decode)
|
||||
{
|
||||
EXPECT_EQ(base64decode(""), "");
|
||||
EXPECT_EQ(base64decode("Zg=="), "f");
|
||||
EXPECT_EQ(base64decode("Zm8="), "fo");
|
||||
EXPECT_EQ(base64decode("Zm9v"), "foo");
|
||||
EXPECT_EQ(base64decode("Zm9vYg=="), "foob");
|
||||
EXPECT_EQ(base64decode("Zm9vYmE="), "fooba");
|
||||
EXPECT_EQ(base64decode("Zm9vYmFy"), "foobar");
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,159 @@
|
|||
/***************************************************************************
|
||||
* Copyright (c) Johan Mabille, Sylvain Corlay and Wolf Vollprecht *
|
||||
* Copyright (c) QuantStack *
|
||||
* *
|
||||
* Distributed under the terms of the BSD 3-Clause License. *
|
||||
* *
|
||||
* The full license is in the file LICENSE, distributed with this software. *
|
||||
****************************************************************************/
|
||||
|
||||
#include "xtl/xclosure.hpp"
|
||||
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
namespace xtl
|
||||
{
|
||||
TEST(xclosure, closure_types)
|
||||
{
|
||||
bool rvalue_test = std::is_same<closure_type_t<double&&>, double>::value;
|
||||
bool lvalue_reference_test = std::is_same<closure_type_t<double&>, double&>::value;
|
||||
bool const_lvalue_reference_test = std::is_same<closure_type_t<const double&>, const double&>::value;
|
||||
|
||||
EXPECT_TRUE(rvalue_test);
|
||||
EXPECT_TRUE(lvalue_reference_test);
|
||||
EXPECT_TRUE(const_lvalue_reference_test);
|
||||
}
|
||||
|
||||
TEST(xclosure, lvalue_closure_wrappers)
|
||||
{
|
||||
double x = 0.0;
|
||||
auto x_closure = closure(x);
|
||||
x_closure = 1.0;
|
||||
EXPECT_EQ(x, 1.0);
|
||||
EXPECT_EQ(&x, &x_closure);
|
||||
}
|
||||
|
||||
TEST(xclosure, rvalue_closure_wrappers)
|
||||
{
|
||||
double x = 0.0;
|
||||
auto x_closure = closure(std::move(x));
|
||||
x_closure = 1.0;
|
||||
EXPECT_EQ(x, 0.0);
|
||||
EXPECT_NE(&x, &x_closure);
|
||||
}
|
||||
|
||||
TEST(xclosure, copy)
|
||||
{
|
||||
std::vector<int> v = { 1, 2, 3 };
|
||||
auto cl1 = closure(v);
|
||||
auto cl2(cl1);
|
||||
|
||||
cl2.get()[0] = 4;
|
||||
EXPECT_EQ(v[0], 4);
|
||||
|
||||
auto cl3(const_cast<const std::decay_t<decltype(cl1)>&>(cl1));
|
||||
cl3.get()[0] = 5;
|
||||
EXPECT_EQ(v[0], 5);
|
||||
}
|
||||
|
||||
TEST(xclosure, assign)
|
||||
{
|
||||
std::vector<int> v1 = { 1, 2, 3 };
|
||||
std::vector<int> v2 = { 3, 2, 1 };
|
||||
std::vector<int> v3 = v1;
|
||||
|
||||
auto cl1 = closure(v1);
|
||||
auto cl2 = closure(v2);
|
||||
auto cl3 = closure(v3);
|
||||
|
||||
cl1 = cl2;
|
||||
EXPECT_EQ(v1, v2);
|
||||
|
||||
cl3 = const_cast<const std::decay_t<decltype(cl2)>&>(cl2);
|
||||
EXPECT_EQ(v3, v2);
|
||||
}
|
||||
|
||||
TEST(xclosure, move)
|
||||
{
|
||||
std::vector<int> v = { 1, 2, 3 };
|
||||
|
||||
auto cl1 = closure(v);
|
||||
auto cl2(std::move(cl1));
|
||||
|
||||
cl2.get()[0] = 4;
|
||||
EXPECT_EQ(v[0], 4);
|
||||
}
|
||||
|
||||
TEST(xclosure, move_assign)
|
||||
{
|
||||
std::vector<int> v1 = { 1, 2, 3 };
|
||||
std::vector<int> v2 = { 3, 2, 1 };
|
||||
std::vector<int> v3 = v2;
|
||||
|
||||
auto cl1 = closure(v1);
|
||||
auto cl2 = closure(v2);
|
||||
|
||||
cl1 = std::move(cl2);
|
||||
EXPECT_EQ(v1, v3);
|
||||
|
||||
}
|
||||
|
||||
TEST(xclosure, swap)
|
||||
{
|
||||
std::vector<int> v1 = { 1, 2, 3 };
|
||||
std::vector<int> v2 = { 3, 2, 1 };
|
||||
std::vector<int> v3 = v1;
|
||||
std::vector<int> v4 = v2;
|
||||
|
||||
auto cl1 = closure(v1);
|
||||
auto cl2 = closure(v2);
|
||||
|
||||
using std::swap;
|
||||
swap(cl1, cl2);
|
||||
EXPECT_EQ(v1, v4);
|
||||
EXPECT_EQ(v2, v3);
|
||||
}
|
||||
|
||||
TEST(xclosure, swap_pointers)
|
||||
{
|
||||
int* d1 = new int[3];
|
||||
int* d2 = new int[3];
|
||||
|
||||
int* d3 = d1;
|
||||
int* d4 = d2;
|
||||
|
||||
auto cl1 = closure(d1);
|
||||
auto cl2 = closure(d2);
|
||||
|
||||
using std::swap;
|
||||
swap(cl1, cl2);
|
||||
|
||||
EXPECT_EQ(d1, d4);
|
||||
EXPECT_EQ(d2, d3);
|
||||
|
||||
delete[] d2;
|
||||
delete[] d1;
|
||||
}
|
||||
|
||||
TEST(xclosure_pointer, lvalue_closure_wrappers)
|
||||
{
|
||||
double x = 0.0;
|
||||
auto x_closure = closure_pointer(x);
|
||||
*x_closure = 1.0;
|
||||
EXPECT_EQ(x, 1.0);
|
||||
EXPECT_EQ(x_closure.operator->(), &x);
|
||||
}
|
||||
|
||||
TEST(xclosure_pointer, rvalue_closure_wrappers)
|
||||
{
|
||||
double x = 0.0;
|
||||
auto x_closure = closure_pointer(std::move(x));
|
||||
*x_closure = 1.0;
|
||||
EXPECT_EQ(x, 0.0);
|
||||
EXPECT_NE(x_closure.operator->(), &x);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,329 @@
|
|||
/***************************************************************************
|
||||
* Copyright (c) Johan Mabille, Sylvain Corlay and Wolf Vollprecht *
|
||||
* Copyright (c) QuantStack *
|
||||
* *
|
||||
* Distributed under the terms of the BSD 3-Clause License. *
|
||||
* *
|
||||
* The full license is in the file LICENSE, distributed with this software. *
|
||||
****************************************************************************/
|
||||
|
||||
#include "xtl/xcomplex.hpp"
|
||||
|
||||
#include <complex>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "xtl/xclosure.hpp"
|
||||
|
||||
namespace xtl
|
||||
{
|
||||
using namespace std::complex_literals;
|
||||
|
||||
using complex_type = xcomplex<double>;
|
||||
using complex_ref_type = xcomplex<double&, double&>;
|
||||
|
||||
TEST(xcomplex, constructor)
|
||||
{
|
||||
complex_type c0;
|
||||
EXPECT_EQ(c0.real(), 0.);
|
||||
EXPECT_EQ(c0.imag(), 0.);
|
||||
|
||||
complex_type c1(2.);
|
||||
EXPECT_EQ(c1.real(), 2.);
|
||||
EXPECT_EQ(c1.imag(), 0.);
|
||||
|
||||
complex_type c2(2., 3.);
|
||||
EXPECT_EQ(c2.real(), 2.);
|
||||
EXPECT_EQ(c2.imag(), 3.);
|
||||
|
||||
complex_type c3(c2);
|
||||
EXPECT_EQ(c3.real(), c2.real());
|
||||
EXPECT_EQ(c3.imag(), c2.imag());
|
||||
|
||||
complex_type c4(std::move(c3));
|
||||
EXPECT_EQ(c4.real(), c2.real());
|
||||
EXPECT_EQ(c4.imag(), c2.imag());
|
||||
|
||||
std::complex<double> sc(1., 2.);
|
||||
complex_type c5(sc);
|
||||
EXPECT_EQ(c5.real(), sc.real());
|
||||
EXPECT_EQ(c5.imag(), sc.imag());
|
||||
|
||||
complex_type c6(std::move(sc));
|
||||
EXPECT_EQ(c6.real(), c5.real());
|
||||
EXPECT_EQ(c6.imag(), c5.imag());
|
||||
|
||||
double re = 1.2, im = 4.5;
|
||||
complex_ref_type c7(re, im);
|
||||
EXPECT_EQ(c7.real(), re);
|
||||
EXPECT_EQ(c7.imag(), im);
|
||||
|
||||
xcomplex<float> f(1.f, 2.f);
|
||||
complex_type c8(f);
|
||||
EXPECT_EQ(c8.real(), 1.);
|
||||
EXPECT_EQ(c8.imag(), 2.);
|
||||
}
|
||||
|
||||
TEST(xcomplex, assign)
|
||||
{
|
||||
complex_type c0(1., 2.);
|
||||
complex_type c1(4., 5.);
|
||||
|
||||
c0 = 3.;
|
||||
EXPECT_EQ(c0.real(), 3.);
|
||||
EXPECT_EQ(c0.imag(), 0.);
|
||||
|
||||
c0 = std::move(4.);
|
||||
EXPECT_EQ(c0.real(), 4.);
|
||||
EXPECT_EQ(c0.imag(), 0.);
|
||||
|
||||
c0 = c1;
|
||||
EXPECT_EQ(c0.real(), c1.real());
|
||||
EXPECT_EQ(c0.imag(), c1.imag());
|
||||
|
||||
c0 = complex_type(2., 3.);
|
||||
EXPECT_EQ(c0.real(), 2.);
|
||||
EXPECT_EQ(c0.imag(), 3.);
|
||||
|
||||
std::complex<double> c2(1.4, 5.2);
|
||||
c0 = c2;
|
||||
EXPECT_EQ(c0.real(), c2.real());
|
||||
EXPECT_EQ(c0.imag(), c2.imag());
|
||||
|
||||
c0 = std::complex<double>(1.2, 2.5);
|
||||
EXPECT_EQ(c0.real(), 1.2);
|
||||
EXPECT_EQ(c0.imag(), 2.5);
|
||||
}
|
||||
|
||||
TEST(xcomplex, conversion)
|
||||
{
|
||||
complex_type c(1., 2.);
|
||||
std::complex<double> sc = c;
|
||||
EXPECT_EQ(c.real(), sc.real());
|
||||
EXPECT_EQ(c.imag(), sc.imag());
|
||||
}
|
||||
|
||||
TEST(xcomplex, comparison)
|
||||
{
|
||||
complex_type vc0(1., 2.);
|
||||
complex_type vc1(2., 4.);
|
||||
|
||||
EXPECT_TRUE(vc0 == vc0);
|
||||
EXPECT_FALSE(vc0 == vc1);
|
||||
|
||||
EXPECT_FALSE(vc0 != vc0);
|
||||
EXPECT_TRUE(vc0 != vc1);
|
||||
}
|
||||
|
||||
TEST(xcomplex, computed_assign)
|
||||
{
|
||||
complex_type vc0(1., 2.);
|
||||
complex_type vc1(2., 4.);
|
||||
|
||||
complex_type c0(vc0);
|
||||
c0 += vc1;
|
||||
EXPECT_EQ(c0.real(), 3.);
|
||||
EXPECT_EQ(c0.imag(), 6.);
|
||||
|
||||
complex_type c1(vc0);
|
||||
c1 -= vc1;
|
||||
EXPECT_EQ(c1.real(), -1.);
|
||||
EXPECT_EQ(c1.imag(), -2.);
|
||||
|
||||
complex_type c2(vc0);
|
||||
c2 *= vc1;
|
||||
EXPECT_EQ(c2.real(), -6.);
|
||||
EXPECT_EQ(c2.imag(), 8.);
|
||||
|
||||
complex_type c3(vc0);
|
||||
c3 /= vc1;
|
||||
EXPECT_EQ(c3.real(), 0.5);
|
||||
EXPECT_EQ(c3.imag(), 0.);
|
||||
|
||||
double v = 0.5;
|
||||
|
||||
complex_type c4(vc0);
|
||||
c4 += v;
|
||||
EXPECT_EQ(c4.real(), 1.5);
|
||||
EXPECT_EQ(c4.imag(), 2.);
|
||||
|
||||
complex_type c5(vc0);
|
||||
c5 -= v;
|
||||
EXPECT_EQ(c5.real(), 0.5);
|
||||
EXPECT_EQ(c5.imag(), 2.);
|
||||
|
||||
complex_type c6(vc0);
|
||||
c6 *= v;
|
||||
EXPECT_EQ(c6.real(), 0.5);
|
||||
EXPECT_EQ(c6.imag(), 1.);
|
||||
|
||||
complex_type c7(vc0);
|
||||
c7 /= v;
|
||||
EXPECT_EQ(c7.real(), 2.);
|
||||
EXPECT_EQ(c7.imag(), 4.);
|
||||
|
||||
xcomplex<double, double, true> sc(vc1);
|
||||
xcomplex<double, double, true> c8(vc0);
|
||||
c8 *= sc;
|
||||
EXPECT_EQ(c8.real(), -6.);
|
||||
EXPECT_EQ(c8.imag(), 8.);
|
||||
|
||||
xcomplex<double, double, true> c9(vc0);
|
||||
c9 /= sc;
|
||||
EXPECT_EQ(c9.real(), 0.5);
|
||||
EXPECT_EQ(c9.imag(), 0.);
|
||||
}
|
||||
|
||||
TEST(xcomplex, arithmetic)
|
||||
{
|
||||
complex_type vc0(1., 2.);
|
||||
complex_type vc1(2., 4.);
|
||||
|
||||
complex_type c0 = vc0 + vc1;
|
||||
EXPECT_EQ(c0.real(), 3.);
|
||||
EXPECT_EQ(c0.imag(), 6.);
|
||||
|
||||
complex_type c1 = vc0 - vc1;
|
||||
EXPECT_EQ(c1.real(), -1.);
|
||||
EXPECT_EQ(c1.imag(), -2.);
|
||||
|
||||
complex_type c2 = vc0 * vc1;
|
||||
EXPECT_EQ(c2.real(), -6.);
|
||||
EXPECT_EQ(c2.imag(), 8.);
|
||||
|
||||
complex_type c3 = vc0 / vc1;
|
||||
EXPECT_EQ(c3.real(), 0.5);
|
||||
EXPECT_EQ(c3.imag(), 0.);
|
||||
|
||||
double v = 0.5;
|
||||
|
||||
complex_type c4 = vc0 + v;
|
||||
EXPECT_EQ(c4.real(), 1.5);
|
||||
EXPECT_EQ(c4.imag(), 2.);
|
||||
|
||||
complex_type c5 = vc0 - v;
|
||||
EXPECT_EQ(c5.real(), 0.5);
|
||||
EXPECT_EQ(c5.imag(), 2.);
|
||||
|
||||
complex_type c6 = vc0 * v;
|
||||
EXPECT_EQ(c6.real(), 0.5);
|
||||
EXPECT_EQ(c6.imag(), 1.);
|
||||
|
||||
complex_type c7 = vc0 / v;
|
||||
EXPECT_EQ(c7.real(), 2.);
|
||||
EXPECT_EQ(c7.imag(), 4.);
|
||||
}
|
||||
|
||||
TEST(xcomplex, real_imag)
|
||||
{
|
||||
complex_type c(1., 2.);
|
||||
|
||||
auto d1 = real(c);
|
||||
EXPECT_EQ(d1, c.real());
|
||||
|
||||
auto d2 = real(std::move(c));
|
||||
EXPECT_EQ(d2, c.real());
|
||||
|
||||
auto d3 = imag(c);
|
||||
EXPECT_EQ(d3, c.imag());
|
||||
|
||||
auto d4 = imag(std::move(c));
|
||||
EXPECT_EQ(d4, c.imag());
|
||||
}
|
||||
|
||||
TEST(xcomplex, free_functions)
|
||||
{
|
||||
complex_type c(1., 2.);
|
||||
std::complex<double> sc(c);
|
||||
|
||||
EXPECT_EQ(abs(c), std::abs(sc));
|
||||
EXPECT_EQ(arg(c), std::arg(sc));
|
||||
EXPECT_EQ(norm(c), std::norm(sc));
|
||||
EXPECT_EQ(conj(c), complex_type(std::conj(sc)));
|
||||
EXPECT_EQ(proj(c), complex_type(std::proj(sc)));
|
||||
}
|
||||
|
||||
TEST(xcomplex, exponential)
|
||||
{
|
||||
complex_type c(1., 2.);
|
||||
std::complex<double> sc(c);
|
||||
EXPECT_EQ(exp(c), complex_type(std::exp(sc)));
|
||||
EXPECT_EQ(log(c), complex_type(std::log(sc)));
|
||||
EXPECT_EQ(log10(c), complex_type(std::log10(sc)));
|
||||
}
|
||||
|
||||
TEST(xcomplex, power)
|
||||
{
|
||||
complex_type c(1., 2.);
|
||||
std::complex<double> sc(c);
|
||||
double d = 1.5;
|
||||
EXPECT_EQ(pow(c, c), complex_type(std::pow(sc, sc)));
|
||||
EXPECT_EQ(pow(c, d), complex_type(std::pow(sc, d)));
|
||||
EXPECT_EQ(pow(d, c), complex_type(std::pow(d, sc)));
|
||||
EXPECT_EQ(sqrt(c), complex_type(std::sqrt(sc)));
|
||||
}
|
||||
|
||||
TEST(xcomplex, trigonometric)
|
||||
{
|
||||
complex_type c(1., 2.);
|
||||
std::complex<double> sc(c);
|
||||
EXPECT_EQ(sin(c), complex_type(std::sin(sc)));
|
||||
EXPECT_EQ(cos(c), complex_type(std::cos(sc)));
|
||||
EXPECT_EQ(tan(c), complex_type(std::tan(sc)));
|
||||
EXPECT_EQ(asin(c), complex_type(std::asin(sc)));
|
||||
EXPECT_EQ(acos(c), complex_type(std::acos(sc)));
|
||||
EXPECT_EQ(atan(c), complex_type(std::atan(sc)));
|
||||
}
|
||||
|
||||
TEST(xcomplex, hyperbolic)
|
||||
{
|
||||
complex_type c(1., 2.);
|
||||
std::complex<double> sc(c);
|
||||
EXPECT_EQ(sinh(c), complex_type(std::sinh(sc)));
|
||||
EXPECT_EQ(cosh(c), complex_type(std::cosh(sc)));
|
||||
EXPECT_EQ(tanh(c), complex_type(std::tanh(sc)));
|
||||
EXPECT_EQ(asinh(c), complex_type(std::asinh(sc)));
|
||||
EXPECT_EQ(acosh(c), complex_type(std::acosh(sc)));
|
||||
EXPECT_EQ(atanh(c), complex_type(std::atanh(sc)));
|
||||
}
|
||||
|
||||
TEST(xcomplex, forward_offset)
|
||||
{
|
||||
// Test that lvalues can be modified
|
||||
std::complex<double> clv;
|
||||
forward_real(clv) = 3.0;
|
||||
EXPECT_EQ(std::real(clv), 3.0);
|
||||
|
||||
forward_imag(clv) = 1.0;
|
||||
EXPECT_EQ(std::imag(clv), 1.0);
|
||||
|
||||
double rlv = 2.0;
|
||||
forward_real(rlv) = 1.0;
|
||||
EXPECT_EQ(forward_imag(rlv), 0.0);
|
||||
EXPECT_EQ(forward_real(rlv), 1.0);
|
||||
}
|
||||
|
||||
TEST(xcomplex, scalar)
|
||||
{
|
||||
double d = 1.0;
|
||||
ASSERT_EQ(1.0, real(d));
|
||||
ASSERT_EQ(0.0, imag(d));
|
||||
real(d) = 2.0;
|
||||
ASSERT_EQ(2.0, d);
|
||||
}
|
||||
|
||||
TEST(xcomplex, closure)
|
||||
{
|
||||
double x = 5.0;
|
||||
auto x_closure = closure(x);
|
||||
std::complex<double> b(0, 5), c;
|
||||
EXPECT_EQ(b + x_closure, b + 5.0);
|
||||
EXPECT_EQ(x_closure + b, 5.0 + b);
|
||||
EXPECT_EQ(b - x_closure, b - 5.0);
|
||||
EXPECT_EQ(x_closure - b, 5.0 - b);
|
||||
EXPECT_EQ(b * x_closure, b * 5.0);
|
||||
EXPECT_EQ(x_closure * b, 5.0 * b);
|
||||
EXPECT_EQ(b / x_closure, b / 5.0);
|
||||
EXPECT_EQ(x_closure / b, 5.0 / b);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,174 @@
|
|||
/***************************************************************************
|
||||
* Copyright (c) Johan Mabille, Sylvain Corlay and Wolf Vollprecht *
|
||||
* Copyright (c) QuantStack *
|
||||
* *
|
||||
* Distributed under the terms of the BSD 3-Clause License. *
|
||||
* *
|
||||
* The full license is in the file LICENSE, distributed with this software. *
|
||||
****************************************************************************/
|
||||
|
||||
#include "xtl/xcomplex_sequence.hpp"
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
namespace xtl
|
||||
{
|
||||
using complex_vector = xcomplex_vector<double, false>;
|
||||
|
||||
TEST(xcomplex_sequence, constructor)
|
||||
{
|
||||
complex_vector v1;
|
||||
EXPECT_TRUE(v1.empty());
|
||||
EXPECT_EQ(v1.size(), std::size_t(0));
|
||||
|
||||
complex_vector v2(10);
|
||||
EXPECT_FALSE(v2.empty());
|
||||
EXPECT_EQ(v2.size(), std::size_t(10));
|
||||
|
||||
complex_vector v3(10, xcomplex<double>(1., 1.));
|
||||
EXPECT_FALSE(v3.empty());
|
||||
EXPECT_EQ(v3.size(), std::size_t(10));
|
||||
}
|
||||
|
||||
TEST(xcomplex_sequence, resize)
|
||||
{
|
||||
complex_vector v1(2);
|
||||
v1.resize(4);
|
||||
EXPECT_EQ(v1.size(), 4u);
|
||||
|
||||
v1.resize(8, xcomplex<double>(1., 1.));
|
||||
EXPECT_EQ(v1.size(), 8u);
|
||||
}
|
||||
|
||||
TEST(xcomplex_sequence, access)
|
||||
{
|
||||
xcomplex<double> c0(1., 2.);
|
||||
xcomplex<double> c1(2., 3.);
|
||||
|
||||
complex_vector v = { c0, c1 };
|
||||
EXPECT_EQ(v[0], c0);
|
||||
EXPECT_EQ(v[1], c1);
|
||||
}
|
||||
|
||||
TEST(xcomplex_sequence, at)
|
||||
{
|
||||
xcomplex<double> c0(1., 2.);
|
||||
xcomplex<double> c1(2., 3.);
|
||||
|
||||
complex_vector v = { c0, c1 };
|
||||
EXPECT_EQ(v.at(0), c0);
|
||||
EXPECT_EQ(v.at(1), c1);
|
||||
}
|
||||
|
||||
TEST(xcomplex_sequence, front)
|
||||
{
|
||||
xcomplex<double> c0(1., 2.);
|
||||
xcomplex<double> c1(2., 3.);
|
||||
|
||||
complex_vector v = { c0, c1 };
|
||||
EXPECT_EQ(v.front(), c0);
|
||||
}
|
||||
|
||||
TEST(xcomplex_sequence, back)
|
||||
{
|
||||
xcomplex<double> c0(1., 2.);
|
||||
xcomplex<double> c1(2., 3.);
|
||||
|
||||
complex_vector v = { c0, c1 };
|
||||
EXPECT_EQ(v.back(), c1);
|
||||
}
|
||||
|
||||
TEST(xcomplex_sequence, iterator)
|
||||
{
|
||||
xcomplex<double> c0(1., 2.);
|
||||
xcomplex<double> c1(2., 3.);
|
||||
xcomplex<double> c2(4., 6.);
|
||||
xcomplex<double> c3(8., 12.);
|
||||
|
||||
complex_vector v = { c0, c1, c2, c3 };
|
||||
auto iter = v.begin();
|
||||
auto citer = v.cbegin();
|
||||
|
||||
EXPECT_EQ(*iter, c0);
|
||||
EXPECT_EQ(*citer, c0);
|
||||
|
||||
++iter, ++citer;
|
||||
EXPECT_EQ(*iter, c1);
|
||||
EXPECT_EQ(*citer, c1);
|
||||
|
||||
++iter, ++citer;
|
||||
EXPECT_EQ(*iter, c2);
|
||||
EXPECT_EQ(*citer, c2);
|
||||
|
||||
++iter, ++citer;
|
||||
EXPECT_EQ(*iter, c3);
|
||||
EXPECT_EQ(*citer, c3);
|
||||
|
||||
++iter, ++citer;
|
||||
EXPECT_EQ(iter, v.end());
|
||||
EXPECT_EQ(citer, v.cend());
|
||||
}
|
||||
|
||||
TEST(xcomplex_sequence, reverse_iterator)
|
||||
{
|
||||
xcomplex<double> c0(1., 2.);
|
||||
xcomplex<double> c1(2., 3.);
|
||||
xcomplex<double> c2(4., 6.);
|
||||
xcomplex<double> c3(8., 12.);
|
||||
|
||||
complex_vector v = { c0, c1, c2, c3 };
|
||||
auto iter = v.rbegin();
|
||||
auto citer = v.crbegin();
|
||||
|
||||
EXPECT_EQ(*iter, c3);
|
||||
EXPECT_EQ(*citer, c3);
|
||||
|
||||
++iter, ++citer;
|
||||
EXPECT_EQ(*iter, c2);
|
||||
EXPECT_EQ(*citer, c2);
|
||||
|
||||
++iter, ++citer;
|
||||
EXPECT_EQ(*iter, c1);
|
||||
EXPECT_EQ(*citer, c1);
|
||||
|
||||
++iter, ++citer;
|
||||
EXPECT_EQ(*iter, c0);
|
||||
EXPECT_EQ(*citer, c0);
|
||||
|
||||
++iter, ++citer;
|
||||
EXPECT_EQ(iter, v.rend());
|
||||
EXPECT_EQ(citer, v.crend());
|
||||
}
|
||||
|
||||
TEST(xcomplex_sequence, comparison)
|
||||
{
|
||||
xcomplex<double> c0(1., 2.);
|
||||
xcomplex<double> c1(2., 3.);
|
||||
xcomplex<double> c2(4., 6.);
|
||||
xcomplex<double> c3(8., 12.);
|
||||
complex_vector v1 = { c0, c1, c2, c3 };
|
||||
|
||||
EXPECT_TRUE(v1 == v1);
|
||||
EXPECT_FALSE(v1 != v1);
|
||||
}
|
||||
|
||||
TEST(xcomplex_sequence, real)
|
||||
{
|
||||
xcomplex<double> c0(1., 2.);
|
||||
xcomplex<double> c1(2., 3.);
|
||||
|
||||
complex_vector v = { c0, c1 };
|
||||
EXPECT_EQ(v.real()[0], 1.);
|
||||
EXPECT_EQ(v.real()[1], 2.);
|
||||
}
|
||||
|
||||
TEST(xcomplex_sequence, imag)
|
||||
{
|
||||
xcomplex<double> c0(1., 2.);
|
||||
xcomplex<double> c1(2., 3.);
|
||||
|
||||
complex_vector v = { c0, c1 };
|
||||
EXPECT_EQ(v.imag()[0], 2.);
|
||||
EXPECT_EQ(v.imag()[1], 3.);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,728 @@
|
|||
/***************************************************************************
|
||||
* Copyright (c) Johan Mabille, Sylvain Corlay and Wolf Vollprecht *
|
||||
* Copyright (c) QuantStack *
|
||||
* *
|
||||
* Distributed under the terms of the BSD 3-Clause License. *
|
||||
* *
|
||||
* The full license is in the file LICENSE, distributed with this software. *
|
||||
****************************************************************************/
|
||||
|
||||
#include "xtl/xdynamic_bitset.hpp"
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
namespace xtl
|
||||
{
|
||||
using bitset = xdynamic_bitset<uint64_t>;
|
||||
using bitset_view = xdynamic_bitset_view<uint64_t>;
|
||||
|
||||
TEST(xdynamic_bitset, constructors)
|
||||
{
|
||||
// empty constructor
|
||||
{
|
||||
bitset b;
|
||||
EXPECT_TRUE(b.empty());
|
||||
EXPECT_EQ(0u, b.size());
|
||||
EXPECT_EQ(0u, b.block_count());
|
||||
}
|
||||
|
||||
// Size constructor
|
||||
{
|
||||
bitset b(80u);
|
||||
EXPECT_FALSE(b.empty());
|
||||
EXPECT_EQ(80u, b.size());
|
||||
EXPECT_EQ(2u, b.block_count());
|
||||
bool res = false;
|
||||
for (std::size_t i = 0; i < b.size(); ++i)
|
||||
{
|
||||
res = res || b[i];
|
||||
}
|
||||
EXPECT_FALSE(res);
|
||||
}
|
||||
|
||||
// Value constructor
|
||||
{
|
||||
bitset b(80u, true);
|
||||
EXPECT_FALSE(b.empty());
|
||||
EXPECT_EQ(80u, b.size());
|
||||
EXPECT_EQ(2u, b.block_count());
|
||||
bool res = true;
|
||||
for (std::size_t i = 0; i < b.size(); ++i)
|
||||
{
|
||||
res = res && b[i];
|
||||
}
|
||||
EXPECT_TRUE(res);
|
||||
}
|
||||
|
||||
// Iterator pair constructor
|
||||
{
|
||||
std::vector<uint64_t> src(2u, 0xAAAAAAAAAAAAAAAA);
|
||||
bitset b(src.begin(), src.end());
|
||||
bool res = true;
|
||||
std::size_t size(128u);
|
||||
for (std::size_t i = 0; i < size; i += 2)
|
||||
{
|
||||
res = res && !b[i];
|
||||
res = res && b[i + 1];
|
||||
}
|
||||
EXPECT_EQ(size, b.size());
|
||||
EXPECT_TRUE(res);
|
||||
}
|
||||
|
||||
// Initializer_list
|
||||
{
|
||||
bitset b = { true, true, false, true };
|
||||
EXPECT_EQ(4u, b.size());
|
||||
EXPECT_TRUE(b[0]);
|
||||
EXPECT_TRUE(b[1]);
|
||||
EXPECT_FALSE(b[2]);
|
||||
EXPECT_TRUE(b[3]);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(xdynamic_bitset, assign)
|
||||
{
|
||||
// same value repeated
|
||||
{
|
||||
bitset b(40u, false);
|
||||
b.assign(80u, true);
|
||||
EXPECT_EQ(80u, b.size());
|
||||
EXPECT_TRUE(b.all());
|
||||
}
|
||||
|
||||
// Block iterator
|
||||
{
|
||||
bitset b(40u, false);
|
||||
std::vector<uint64_t> src(2u, 0xAAAAAAAAAAAAAAAA);
|
||||
b.assign(src.begin(), src.end());
|
||||
bool res = true;
|
||||
std::size_t size(128u);
|
||||
for (std::size_t i = 0; i < size; i += 2)
|
||||
{
|
||||
res = res && !b[i];
|
||||
res = res && b[i + 1];
|
||||
}
|
||||
EXPECT_EQ(size, b.size());
|
||||
EXPECT_TRUE(res);
|
||||
}
|
||||
|
||||
// Initializer list
|
||||
{
|
||||
bitset b(40u, true);
|
||||
b.assign({ true, true, false, true });
|
||||
EXPECT_EQ(4u, b.size());
|
||||
EXPECT_TRUE(b[0]);
|
||||
EXPECT_TRUE(b[1]);
|
||||
EXPECT_FALSE(b[2]);
|
||||
EXPECT_TRUE(b[3]);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(xdynamic_bitset, resize)
|
||||
{
|
||||
std::size_t size1 = 80u;
|
||||
bitset b(size1, false);
|
||||
std::size_t size2 = 100u;
|
||||
b.resize(size2, true);
|
||||
bool res = true;
|
||||
for (std::size_t i = 0; i < size1; ++i)
|
||||
{
|
||||
res = res && !b[i];
|
||||
}
|
||||
for (std::size_t i = size1; i < size2; ++i)
|
||||
{
|
||||
res = res && b[i];
|
||||
}
|
||||
EXPECT_EQ(size2, b.size());
|
||||
EXPECT_TRUE(res);
|
||||
|
||||
std::size_t size3 = 40u;
|
||||
b.resize(size3);
|
||||
res = false;
|
||||
for (std::size_t i = 0; i < size3; ++i)
|
||||
{
|
||||
res = res && b[i];
|
||||
}
|
||||
EXPECT_EQ(size3, b.size());
|
||||
EXPECT_FALSE(res);
|
||||
}
|
||||
|
||||
TEST(xdynamic_bitset, clear)
|
||||
{
|
||||
std::size_t size1 = 80u;
|
||||
bitset b(size1, false);
|
||||
b.clear();
|
||||
EXPECT_EQ(0u, b.size());
|
||||
}
|
||||
|
||||
TEST(xdynamic_bitset, reserve)
|
||||
{
|
||||
std::size_t size = 80u;
|
||||
std::size_t cap = 128u;
|
||||
bitset b;
|
||||
b.reserve(size);
|
||||
EXPECT_EQ(0u, b.size());
|
||||
EXPECT_EQ(cap, b.capacity());
|
||||
}
|
||||
|
||||
TEST(xdynamic_bitset, push_back)
|
||||
{
|
||||
bitset b(80u, false);
|
||||
b.push_back(true);
|
||||
EXPECT_EQ(81u, b.size());
|
||||
EXPECT_TRUE(b.back());
|
||||
b.push_back(false);
|
||||
EXPECT_EQ(82u, b.size());
|
||||
EXPECT_FALSE(b.back());
|
||||
}
|
||||
|
||||
TEST(xdynamic_bitset, pop_back)
|
||||
{
|
||||
bitset b(80u, false);
|
||||
b.push_back(true);
|
||||
b.push_back(false);
|
||||
b.pop_back();
|
||||
EXPECT_EQ(81u, b.size());
|
||||
EXPECT_TRUE(b.back());
|
||||
b.pop_back();
|
||||
EXPECT_EQ(80u, b.size());
|
||||
EXPECT_FALSE(b.back());
|
||||
}
|
||||
|
||||
TEST(xdynamic_bitset, at)
|
||||
{
|
||||
bitset b(80u, false);
|
||||
b.at(4u) = true;
|
||||
EXPECT_TRUE(b[4u]);
|
||||
}
|
||||
|
||||
TEST(xdynamic_bitset, front)
|
||||
{
|
||||
bitset b(80u, false);
|
||||
b.front() = true;
|
||||
EXPECT_TRUE(b[0]);
|
||||
}
|
||||
|
||||
TEST(xdynamic_bitset, back)
|
||||
{
|
||||
bitset b(80u, false);
|
||||
b.back() = true;
|
||||
EXPECT_TRUE(b[79u]);
|
||||
}
|
||||
|
||||
template <class B>
|
||||
void test_bitset_iterator(B& b)
|
||||
{
|
||||
b[17] = true;
|
||||
auto it = b.begin();
|
||||
auto cit = b.cbegin();
|
||||
EXPECT_FALSE(*it);
|
||||
EXPECT_FALSE(*cit);
|
||||
it += 16, cit += 16;
|
||||
++it, ++cit;
|
||||
EXPECT_TRUE(*it);
|
||||
EXPECT_TRUE(*cit);
|
||||
it += 17, cit += 17;
|
||||
it -= 16, cit -= 16;
|
||||
--it, --cit;
|
||||
EXPECT_TRUE(*it);
|
||||
EXPECT_TRUE(*cit);
|
||||
it += 63, cit += 63;
|
||||
EXPECT_EQ(it, b.end());
|
||||
EXPECT_EQ(cit, b.cend());
|
||||
}
|
||||
|
||||
TEST(xdynamic_bitset, iterator)
|
||||
{
|
||||
bitset b(80u, false);
|
||||
test_bitset_iterator(b);
|
||||
}
|
||||
|
||||
TEST(xdynamic_bitset_view, iterator)
|
||||
{
|
||||
std::array<uint64_t, 2> bs = {0, 0};
|
||||
bitset_view b(bs.data(), 80);
|
||||
test_bitset_iterator(b);
|
||||
}
|
||||
|
||||
template <class B>
|
||||
void test_bitset_reverse_iterator(B& b)
|
||||
{
|
||||
b[62] = true;
|
||||
auto it = b.rbegin();
|
||||
auto cit = b.crbegin();
|
||||
EXPECT_FALSE(*it);
|
||||
EXPECT_FALSE(*cit);
|
||||
it += 16, cit += 16;
|
||||
++it, ++cit;
|
||||
EXPECT_TRUE(*it);
|
||||
EXPECT_TRUE(*cit);
|
||||
it += 17, cit += 17;
|
||||
it -= 16, cit -= 16;
|
||||
--it, --cit;
|
||||
EXPECT_TRUE(*it);
|
||||
EXPECT_TRUE(*cit);
|
||||
it += 63, cit += 63;
|
||||
EXPECT_EQ(it, b.rend());
|
||||
EXPECT_EQ(cit, b.crend());
|
||||
}
|
||||
|
||||
TEST(xdynamic_bitset, reverse_iterator)
|
||||
{
|
||||
bitset b(80u, false);
|
||||
test_bitset_reverse_iterator(b);
|
||||
}
|
||||
|
||||
TEST(xdynamic_bitset_view, reverse_iterator)
|
||||
{
|
||||
std::array<uint64_t, 2> bs = {0, 0};
|
||||
bitset_view b(bs.data(), 80);
|
||||
test_bitset_reverse_iterator(b);
|
||||
}
|
||||
|
||||
template <class C>
|
||||
void print(C& c)
|
||||
{
|
||||
for (auto el : c) std::cout << el << ", ";
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
template <class B>
|
||||
void test_set(B& b)
|
||||
{
|
||||
b.set(47u, true);
|
||||
bool res = true;
|
||||
for (size_t i = 0; i < 80u; ++i)
|
||||
{
|
||||
res = res && (i != 47u ? !b[i] : b[i]);
|
||||
}
|
||||
EXPECT_TRUE(res);
|
||||
b.set();
|
||||
res = true;
|
||||
for (size_t i = 0; i < 80u; ++i)
|
||||
{
|
||||
res = res && b[i];
|
||||
}
|
||||
EXPECT_TRUE(res);
|
||||
}
|
||||
|
||||
TEST(xdynamic_bitset, set)
|
||||
{
|
||||
bitset b(80u, false);
|
||||
test_set(b);
|
||||
}
|
||||
|
||||
TEST(xdynamic_bitset_view, set)
|
||||
{
|
||||
std::array<uint64_t, 2> bs = {0, 0};
|
||||
bitset_view b(bs.data(), 80);
|
||||
test_set(b);
|
||||
}
|
||||
|
||||
template <class B>
|
||||
void test_reset(B& b)
|
||||
{
|
||||
b.reset(47u);
|
||||
bool res = true;
|
||||
for (size_t i = 0; i < 80u; ++i)
|
||||
{
|
||||
res = res && (i != 47u ? b[i] : !b[i]);
|
||||
}
|
||||
EXPECT_TRUE(res);
|
||||
b.reset();
|
||||
res = true;
|
||||
for (size_t i = 0; i < 80u; ++i)
|
||||
{
|
||||
res = res && !b[i];
|
||||
}
|
||||
EXPECT_TRUE(res);
|
||||
}
|
||||
|
||||
TEST(xdynamic_bitset, reset)
|
||||
{
|
||||
bitset b(80u, true);
|
||||
test_reset(b);
|
||||
}
|
||||
|
||||
TEST(xdynamic_bitset_view, reset)
|
||||
{
|
||||
bitset bs(80u, true);
|
||||
bitset_view b(bs.data(), 80);
|
||||
test_reset(b);
|
||||
}
|
||||
|
||||
template <class B>
|
||||
void test_flip(B& b)
|
||||
{
|
||||
b.flip(47u);
|
||||
bool res = true;
|
||||
for (size_t i = 0; i < 80u; ++i)
|
||||
{
|
||||
res = res && (i != 47u ? !b[i] : b[i]);
|
||||
}
|
||||
EXPECT_TRUE(res);
|
||||
|
||||
b.reset();
|
||||
for (std::size_t i = 0; i < 80u; i += 2)
|
||||
{
|
||||
b[i] = true;
|
||||
}
|
||||
b.flip();
|
||||
res = true;
|
||||
for (std::size_t i = 0; i < 80u; i += 2)
|
||||
{
|
||||
res = res && !b[i] && b[i + 1];
|
||||
}
|
||||
EXPECT_TRUE(res);
|
||||
}
|
||||
|
||||
TEST(xdynamic_bitset, flip)
|
||||
{
|
||||
bitset b(80u, false);
|
||||
test_flip(b);
|
||||
}
|
||||
|
||||
TEST(xdynamic_bitset_view, flip)
|
||||
{
|
||||
std::array<uint64_t, 2> bs = {0, 0};
|
||||
bitset_view b(bs.data(), 80);
|
||||
test_flip(b);
|
||||
}
|
||||
|
||||
template <class B>
|
||||
void test_all(B& b)
|
||||
{
|
||||
EXPECT_FALSE(b.all());
|
||||
b.flip(47u);
|
||||
EXPECT_FALSE(b.all());
|
||||
b.flip();
|
||||
EXPECT_FALSE(b.all());
|
||||
b.flip(47u);
|
||||
EXPECT_TRUE(b.all());
|
||||
}
|
||||
|
||||
TEST(xdynamic_bitset, all)
|
||||
{
|
||||
bitset b(80u, false);
|
||||
test_all(b);
|
||||
}
|
||||
|
||||
TEST(xdynamic_bitset_view, all)
|
||||
{
|
||||
bitset bs(80u, false);
|
||||
bitset_view b(bs.data(), 80);
|
||||
test_all(b);
|
||||
}
|
||||
|
||||
template <class B>
|
||||
void test_any(B& b)
|
||||
{
|
||||
EXPECT_FALSE(b.any());
|
||||
b.flip(47u);
|
||||
EXPECT_TRUE(b.any());
|
||||
}
|
||||
|
||||
TEST(xdynamic_bitset, any)
|
||||
{
|
||||
bitset b(80u, false);
|
||||
test_any(b);
|
||||
}
|
||||
|
||||
TEST(xdynamic_bitset_view, any)
|
||||
{
|
||||
bitset bs(80u, false);
|
||||
bitset_view b(bs.data(), 80);
|
||||
test_any(b);
|
||||
}
|
||||
|
||||
template <class B>
|
||||
void test_none(B& b)
|
||||
{
|
||||
EXPECT_TRUE(b.none());
|
||||
b.flip(47u);
|
||||
EXPECT_FALSE(b.none());
|
||||
}
|
||||
|
||||
TEST(xdynamic_bitset, none)
|
||||
{
|
||||
bitset b(80u, false);
|
||||
test_none(b);
|
||||
}
|
||||
|
||||
TEST(xdynamic_bitset_view, none)
|
||||
{
|
||||
bitset bs(80u, false);
|
||||
bitset_view b(bs.data(), 80);
|
||||
test_none(b);
|
||||
}
|
||||
|
||||
template <class B>
|
||||
void test_count(B& b)
|
||||
{
|
||||
b[0] = true;
|
||||
b[17] = true;
|
||||
b[45] = true;
|
||||
b[65] = true;
|
||||
b[78] = true;
|
||||
EXPECT_EQ(5u, b.count());
|
||||
}
|
||||
|
||||
TEST(xdynamic_bitset, count)
|
||||
{
|
||||
bitset b(80u, false);
|
||||
test_count(b);
|
||||
}
|
||||
|
||||
TEST(xdynamic_bitset_view, count)
|
||||
{
|
||||
std::array<uint64_t, 2> bs = {0, 0};
|
||||
bitset_view b(bs.data(), 80);
|
||||
test_count(b);
|
||||
}
|
||||
|
||||
template <class B>
|
||||
void test_bitwise_not(B& b1)
|
||||
{
|
||||
bitset b2 = ~b1;
|
||||
bitset res(80u, true);
|
||||
EXPECT_TRUE(res == b2);
|
||||
}
|
||||
|
||||
TEST(xdynamic_bitset, bitwise_not)
|
||||
{
|
||||
bitset b1(80u, false);
|
||||
test_bitwise_not(b1);
|
||||
}
|
||||
|
||||
TEST(xdynamic_bitset_view, bitwise_not)
|
||||
{
|
||||
std::array<uint64_t, 2> bs = {0, 0};
|
||||
bitset_view b(bs.data(), 80);
|
||||
test_bitwise_not(b);
|
||||
}
|
||||
|
||||
template <class B>
|
||||
void test_bitwise_and(B& b1)
|
||||
{
|
||||
bitset b2(80u, false);
|
||||
bitset bres(80u, false);
|
||||
bres.flip(2);
|
||||
|
||||
b1[2] = true;
|
||||
b2[2] = true;
|
||||
b1[5] = true;
|
||||
b2[7] = true;
|
||||
|
||||
bitset b11(b1);
|
||||
bitset b22(b2);
|
||||
|
||||
b1 &= b2;
|
||||
EXPECT_TRUE(bres == b1);
|
||||
|
||||
bitset b3 = b11 & b22;
|
||||
EXPECT_TRUE(bres == b3);
|
||||
}
|
||||
|
||||
TEST(xdynamic_bitset, bitwise_and)
|
||||
{
|
||||
bitset b1(80u, false);
|
||||
test_bitwise_and(b1);
|
||||
}
|
||||
|
||||
TEST(xdynamic_bitset_view, bitwise_and)
|
||||
{
|
||||
std::array<uint64_t, 2> bs = {0, 0};
|
||||
bitset_view b(bs.data(), 80);
|
||||
test_bitwise_and(b);
|
||||
}
|
||||
|
||||
template <class B>
|
||||
void test_bitwise_or(B& b1)
|
||||
{
|
||||
bitset b2(80u, false);
|
||||
bitset bres(80u, false);
|
||||
bres.flip(2);
|
||||
bres.flip(5);
|
||||
bres.flip(7);
|
||||
|
||||
b1[2] = true;
|
||||
b2[2] = true;
|
||||
b1[5] = true;
|
||||
b2[7] = true;
|
||||
|
||||
bitset b11(b1);
|
||||
bitset b22(b2);
|
||||
|
||||
b1 |= b2;
|
||||
EXPECT_TRUE(bres == b1);
|
||||
|
||||
bitset b3 = b11 | b22;
|
||||
EXPECT_TRUE(bres == b3);
|
||||
}
|
||||
|
||||
TEST(xdynamic_bitset, bitwise_or)
|
||||
{
|
||||
bitset b1(80u, false);
|
||||
test_bitwise_or(b1);
|
||||
}
|
||||
|
||||
TEST(xdynamic_bitset_view, bitwise_or)
|
||||
{
|
||||
std::array<uint64_t, 2> bs = {0, 0};
|
||||
bitset_view b(bs.data(), 80);
|
||||
test_bitwise_or(b);
|
||||
}
|
||||
|
||||
template <class B>
|
||||
void test_bitwise_xor(B& b1, B& b2)
|
||||
{
|
||||
bitset bres(80u, false);
|
||||
bres.flip(5);
|
||||
bres.flip(7);
|
||||
|
||||
b1[2] = true;
|
||||
b2[2] = true;
|
||||
b1[5] = true;
|
||||
b2[7] = true;
|
||||
|
||||
bitset b11(b1);
|
||||
bitset b22(b2);
|
||||
|
||||
b1 ^= b2;
|
||||
EXPECT_TRUE(bres == b1);
|
||||
|
||||
bitset b3 = b11 ^ b22;
|
||||
EXPECT_TRUE(bres == b3);
|
||||
}
|
||||
|
||||
TEST(xdynamic_bitset, bitwise_xor)
|
||||
{
|
||||
bitset b1(80u, false);
|
||||
bitset b2(80u, false);
|
||||
test_bitwise_xor(b1, b2);
|
||||
}
|
||||
|
||||
TEST(xdynamic_bitset_view, bitwise_xor)
|
||||
{
|
||||
std::array<uint64_t, 2> bs1 = {0, 0};
|
||||
std::array<uint64_t, 2> bs2 = {0, 0};
|
||||
bitset_view b1(bs1.data(), 80);
|
||||
bitset_view b2(bs2.data(), 80);
|
||||
test_bitwise_xor(b1, b2);
|
||||
}
|
||||
|
||||
template <class B>
|
||||
void test_shift_left(B& b1)
|
||||
{
|
||||
b1[2] = true;
|
||||
b1[7] = true;
|
||||
b1[15] = true;
|
||||
b1[45] = true;
|
||||
b1[78] = true;
|
||||
|
||||
bitset b2 = b1 << 4;
|
||||
|
||||
bitset bres(80u, false);
|
||||
bres[6] = true;
|
||||
bres[11] = true;
|
||||
bres[19] = true;
|
||||
bres[49] = true;
|
||||
|
||||
EXPECT_TRUE(b2 == bres);
|
||||
}
|
||||
|
||||
TEST(xdynamic_bitset, shift_left)
|
||||
{
|
||||
bitset b1(80u, false);
|
||||
test_shift_left(b1);
|
||||
}
|
||||
|
||||
TEST(xdynamic_bitset_view, shift_left)
|
||||
{
|
||||
bitset bs(80u, false);
|
||||
bitset_view b1(bs.data(), 80u);
|
||||
test_shift_left(b1);
|
||||
}
|
||||
|
||||
template <class B>
|
||||
void test_shift_right(B& b1)
|
||||
{
|
||||
b1[2] = true;
|
||||
b1[7] = true;
|
||||
b1[15] = true;
|
||||
b1[45] = true;
|
||||
b1[78] = true;
|
||||
|
||||
bitset b2 = b1 >> 4;
|
||||
|
||||
bitset bres(80u, false);
|
||||
bres[3] = true;
|
||||
bres[11] = true;
|
||||
bres[41] = true;
|
||||
bres[74] = true;
|
||||
|
||||
EXPECT_TRUE(b2 == bres);
|
||||
}
|
||||
|
||||
TEST(xdynamic_bitset, shift_right)
|
||||
{
|
||||
bitset b1(80u, false);
|
||||
test_shift_right(b1);
|
||||
}
|
||||
|
||||
TEST(xdynamic_bitset_view, shift_right)
|
||||
{
|
||||
bitset bs(80u, false);
|
||||
bitset_view b1(bs.data(), 80u);
|
||||
test_shift_right(b1);
|
||||
}
|
||||
|
||||
template <class B>
|
||||
void test_comparison(B& b1)
|
||||
{
|
||||
bitset b2(80u, false);
|
||||
|
||||
EXPECT_TRUE(b1 == b1);
|
||||
EXPECT_FALSE(b1 == b2);
|
||||
EXPECT_TRUE(b1 != b2);
|
||||
EXPECT_FALSE(b1 != b1);
|
||||
|
||||
bitset b11 = b1;
|
||||
b11[79] = false;
|
||||
EXPECT_FALSE(b11 == b2);
|
||||
EXPECT_FALSE(b11 == b1);
|
||||
}
|
||||
|
||||
TEST(xdynamic_bitset, comparison)
|
||||
{
|
||||
bitset b1(80u, true);
|
||||
test_comparison(b1);
|
||||
}
|
||||
|
||||
TEST(xdynamic_bitset_view, comparison)
|
||||
{
|
||||
bitset bs(80u, true);
|
||||
bitset_view b1(bs.data(), 80u);
|
||||
test_comparison(b1);
|
||||
}
|
||||
|
||||
TEST(xdynamic_bitset, view)
|
||||
{
|
||||
uint64_t i = 0b00001100;
|
||||
auto bv = bitset_view(&i, 8);
|
||||
|
||||
EXPECT_EQ(bv[0], false);
|
||||
EXPECT_EQ(bv[1], false);
|
||||
EXPECT_EQ(bv[2], true);
|
||||
EXPECT_EQ(bv[3], true);
|
||||
|
||||
auto be = bitset({false, false, true, true, false, false, false, false});
|
||||
|
||||
uint64_t j = 0b11110011;
|
||||
auto jbv = bitset_view(&j, 8);
|
||||
EXPECT_EQ(jbv, ~bv);
|
||||
bv.flip();
|
||||
EXPECT_EQ(jbv, bv);
|
||||
EXPECT_EQ(i, j);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
/***************************************************************************
|
||||
* Copyright (c) Johan Mabille, Sylvain Corlay and Wolf Vollprecht *
|
||||
* Copyright (c) QuantStack *
|
||||
* *
|
||||
* Distributed under the terms of the BSD 3-Clause License. *
|
||||
* *
|
||||
* The full license is in the file LICENSE, distributed with this software. *
|
||||
****************************************************************************/
|
||||
|
||||
#include "xtl/xfunctional.hpp"
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "xtl/xoptional.hpp"
|
||||
|
||||
namespace xtl
|
||||
{
|
||||
TEST(xfunctional, select_scalar)
|
||||
{
|
||||
EXPECT_EQ(select(true, 2., 3.), 2.);
|
||||
EXPECT_EQ(select(false, 2., 3.), 3.);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/***************************************************************************
|
||||
* Copyright (c) Johan Mabille, Sylvain Corlay and Wolf Vollprecht *
|
||||
* Copyright (c) QuantStack *
|
||||
* *
|
||||
* Distributed under the terms of the BSD 3-Clause License. *
|
||||
* *
|
||||
* The full license is in the file LICENSE, distributed with this software. *
|
||||
****************************************************************************/
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wconversion"
|
||||
#pragma GCC diagnostic ignored "-Wsign-conversion"
|
||||
#endif
|
||||
#include "xtl/xhalf_float.hpp"
|
||||
|
||||
namespace xtl
|
||||
{
|
||||
TEST(half_float, traits)
|
||||
{
|
||||
EXPECT_TRUE(xtl::is_scalar<half_float>::value);
|
||||
EXPECT_TRUE(xtl::is_arithmetic<half_float>::value);
|
||||
EXPECT_TRUE(xtl::is_signed<half_float>::value);
|
||||
EXPECT_TRUE(xtl::is_floating_point<half_float>::value);
|
||||
}
|
||||
|
||||
TEST(half_float, arithmetic)
|
||||
{
|
||||
auto f0 = 2.f;
|
||||
auto f1 = 3.f;
|
||||
half_float h0 = f0;
|
||||
half_float h1 = f1;
|
||||
|
||||
EXPECT_EQ((half_float)f0+(half_float)f1, (float)(h0+h1));
|
||||
EXPECT_EQ((half_float)f0-(half_float)f1, (float)(h0-h1));
|
||||
EXPECT_EQ((half_float)f0*(half_float)f1, (float)(h0*h1));
|
||||
EXPECT_EQ((half_float)f0/(half_float)f1, (float)(h0/h1));
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef GCC
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
|
@ -0,0 +1,177 @@
|
|||
/***************************************************************************
|
||||
* Copyright (c) Johan Mabille, Sylvain Corlay and Wolf Vollprecht *
|
||||
* Copyright (c) QuantStack *
|
||||
* *
|
||||
* Distributed under the terms of the BSD 3-Clause License. *
|
||||
* *
|
||||
* The full license is in the file LICENSE, distributed with this software. *
|
||||
****************************************************************************/
|
||||
|
||||
#include "xtl/xhash.hpp"
|
||||
#include "xtl/xplatform.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
namespace xtl
|
||||
{
|
||||
|
||||
// Adaptation of tests provided by Austin Appleby in https://github.com/aappleby/smhasher
|
||||
template <class F>
|
||||
uint32_t verification_test(F f, std::size_t hashbytes)
|
||||
{
|
||||
uint8_t* key = new uint8_t[256];
|
||||
uint8_t* hashes = new uint8_t[hashbytes * 256];
|
||||
uint8_t* res = new uint8_t[hashbytes];
|
||||
|
||||
std::memset(key, 0, 256);
|
||||
std::memset(hashes, 0, hashbytes * 256);
|
||||
std::memset(res, 0, hashbytes);
|
||||
|
||||
// Hash keys of the form {0}, {0,1}, {0,1,2}... up to N=255,using 256-N as
|
||||
// the seed
|
||||
for(std::size_t i = 0; i < 256; i++)
|
||||
{
|
||||
key[i] = (uint8_t)i;
|
||||
*reinterpret_cast<std::size_t*>(hashes + i * hashbytes) = f(key,i,256-i);
|
||||
}
|
||||
|
||||
// Then hash the result array
|
||||
*reinterpret_cast<std::size_t*>(res) = f(hashes,hashbytes*256,0);
|
||||
|
||||
// The first four bytes of that hash, interpreted as a little-endian integer, is our
|
||||
// verification value
|
||||
uint32_t verification = uint32_t((res[0] << 0) | (res[1] << 8) | (res[2] << 16) | (res[3] << 24));
|
||||
|
||||
delete [] key;
|
||||
delete [] hashes;
|
||||
delete [] res;
|
||||
|
||||
return verification;
|
||||
}
|
||||
|
||||
void rand_p(void* buffer, int bytes)
|
||||
{
|
||||
uint32_t * blocks = reinterpret_cast<uint32_t*>(buffer);
|
||||
|
||||
while(bytes >= 4)
|
||||
{
|
||||
blocks[0] = static_cast<uint32_t>(std::rand());
|
||||
blocks++;
|
||||
bytes -= 4;
|
||||
}
|
||||
|
||||
uint8_t* tail = reinterpret_cast<uint8_t*>(blocks);
|
||||
for(int i = 0; i < bytes; i++)
|
||||
{
|
||||
tail[i] = static_cast<uint8_t>(std::rand());
|
||||
}
|
||||
}
|
||||
|
||||
void flipbit(void * block, int len, uint32_t bit)
|
||||
{
|
||||
uint8_t * b = (uint8_t*)block;
|
||||
int byte = int(bit >> 3);
|
||||
bit = bit & 0x7;
|
||||
if(byte < len)
|
||||
{
|
||||
b[byte] ^= static_cast<uint8_t>(1 << bit);
|
||||
}
|
||||
}
|
||||
|
||||
template <class F>
|
||||
bool sanity_test(F f, std::size_t hashbytes)
|
||||
{
|
||||
std::srand(883741);
|
||||
bool result = true;
|
||||
|
||||
int reps = 10;
|
||||
int keymax = 256;
|
||||
int pad = 16;
|
||||
int buflen = keymax + pad*3;
|
||||
|
||||
uint8_t * buffer1 = new uint8_t[std::size_t(buflen)];
|
||||
uint8_t * buffer2 = new uint8_t[std::size_t(buflen)];
|
||||
|
||||
uint8_t * hash1 = new uint8_t[hashbytes];
|
||||
uint8_t * hash2 = new uint8_t[hashbytes];
|
||||
|
||||
for(int irep = 0; irep < reps; irep++)
|
||||
{
|
||||
for(int len = 4; len <= keymax; len++)
|
||||
{
|
||||
for(int offset = pad; offset < pad*2; offset++)
|
||||
{
|
||||
uint8_t * key1 = &buffer1[pad];
|
||||
uint8_t * key2 = &buffer2[pad+offset];
|
||||
|
||||
rand_p(buffer1,buflen);
|
||||
rand_p(buffer2,buflen);
|
||||
|
||||
std::memcpy(key2,key1,std::size_t(len));
|
||||
|
||||
*reinterpret_cast<std::size_t*>(hash1) = f(key1,std::size_t(len),0);
|
||||
|
||||
for(int bit = 0; bit < (len * 8); bit++)
|
||||
{
|
||||
// Flip a bit, hash the key -> we should get a different result.
|
||||
flipbit(key2,len,uint32_t(bit));
|
||||
*reinterpret_cast<std::size_t*>(hash2) = f(key2,std::size_t(len),0);
|
||||
|
||||
if(std::memcmp(hash1,hash2,hashbytes) == 0)
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
|
||||
flipbit(key2,len,uint32_t(bit));
|
||||
*reinterpret_cast<std::size_t*>(hash2) = f(key2,std::size_t(len),0);
|
||||
|
||||
if(std::memcmp(hash1,hash2,hashbytes) != 0)
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
delete [] buffer1;
|
||||
delete [] buffer2;
|
||||
delete [] hash1;
|
||||
delete [] hash2;
|
||||
return result;
|
||||
}
|
||||
|
||||
TEST(hash, verification)
|
||||
{
|
||||
#if INTPTR_MAX == INT64_MAX
|
||||
uint32_t res;
|
||||
switch(endianness()) {
|
||||
case endian::big_endian:
|
||||
res = 0x8fda498d;
|
||||
break;
|
||||
case endian::little_endian:
|
||||
res = sizeof(std::size_t) == 4 ? 0x27864c1e : 0x1f0d3804;
|
||||
break;
|
||||
default:
|
||||
assert(false && "unsupported exotic architecture");
|
||||
}
|
||||
#elif INTPTR_MAX == INT32_MAX
|
||||
uint32_t res = sizeof(std::size_t) == 4 ? 0x27864c1e : 0xdd537c05;
|
||||
#else
|
||||
#error Unknown pointer size or missing size macros!
|
||||
#endif
|
||||
uint32_t actual = verification_test(&hash_bytes, sizeof(std::size_t));
|
||||
|
||||
EXPECT_EQ(actual, res);
|
||||
}
|
||||
|
||||
TEST(hash, sanity)
|
||||
{
|
||||
EXPECT_TRUE(sanity_test(&hash_bytes, sizeof(std::size_t)));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,111 @@
|
|||
/***************************************************************************
|
||||
* Copyright (c) Johan Mabille, Sylvain Corlay and Wolf Vollprecht *
|
||||
* Copyright (c) QuantStack *
|
||||
* *
|
||||
* Distributed under the terms of the BSD 3-Clause License. *
|
||||
* *
|
||||
* The full license is in the file LICENSE, distributed with this software. *
|
||||
****************************************************************************/
|
||||
|
||||
#include "xtl/xhierarchy_generator.hpp"
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
|
||||
namespace xtl
|
||||
{
|
||||
template <class T>
|
||||
class node
|
||||
{
|
||||
public:
|
||||
|
||||
virtual ~node() {}
|
||||
virtual int get_value(T) const = 0;
|
||||
};
|
||||
|
||||
using node_list = mpl::vector<int, double, std::string>;
|
||||
using interface_type = xscatter_hierarchy_generator<node_list, node>;
|
||||
|
||||
class scatter_test : public interface_type
|
||||
{
|
||||
public:
|
||||
|
||||
virtual ~scatter_test() {}
|
||||
|
||||
int get_value(int) const override { return 0; }
|
||||
int get_value(double) const override { return 1; }
|
||||
int get_value(std::string) const override { return 2; }
|
||||
};
|
||||
|
||||
TEST(xhierarchy, scattered)
|
||||
{
|
||||
scatter_test t;
|
||||
EXPECT_EQ(0, t.get_value(int(0)));
|
||||
EXPECT_EQ(1, t.get_value(double(0)));
|
||||
EXPECT_EQ(2, t.get_value(std::string()));
|
||||
}
|
||||
|
||||
template <class T, class B>
|
||||
class node_implem : public B
|
||||
{
|
||||
public:
|
||||
|
||||
node_implem(int i, double d)
|
||||
: B(i, d)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~node_implem() {}
|
||||
|
||||
int get_value(T) const override
|
||||
{
|
||||
if (std::is_same<T, int>::value)
|
||||
return 0;
|
||||
else if (std::is_same<T, double>::value)
|
||||
return 1;
|
||||
else
|
||||
return 2;
|
||||
}
|
||||
};
|
||||
|
||||
class scatter_node : public interface_type
|
||||
{
|
||||
public:
|
||||
|
||||
scatter_node(int i, double d)
|
||||
: m_i(i), m_d(d)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~scatter_node() {}
|
||||
|
||||
template <class T>
|
||||
int do_get_value(T arg) const
|
||||
{
|
||||
const node<T>& n = *this;
|
||||
return n.get_value(arg);
|
||||
}
|
||||
|
||||
int get_int() const { return m_i; }
|
||||
double get_double() const { return m_d; }
|
||||
|
||||
private:
|
||||
|
||||
int m_i;
|
||||
double m_d;
|
||||
};
|
||||
|
||||
using implementation_test = xlinear_hierarchy_generator<node_list, node_implem, scatter_node>;
|
||||
|
||||
TEST(xhierarchy, linear)
|
||||
{
|
||||
implementation_test t(1, 2.5);
|
||||
EXPECT_EQ(0, t.do_get_value(int(0)));
|
||||
EXPECT_EQ(1, t.do_get_value(double(0)));
|
||||
EXPECT_EQ(2, t.do_get_value(std::string()));
|
||||
EXPECT_EQ(1, t.get_int());
|
||||
EXPECT_EQ(2.5, t.get_double());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,298 @@
|
|||
/***************************************************************************
|
||||
* Copyright (c) 2016, Sylvain Corlay and Johan Mabille *
|
||||
* *
|
||||
* Distributed under the terms of the BSD 3-Clause License. *
|
||||
* *
|
||||
* The full license is in the file LICENSE, distributed with this software. *
|
||||
****************************************************************************/
|
||||
|
||||
#include "xtl/xiterator_base.hpp"
|
||||
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
|
||||
namespace adl
|
||||
{
|
||||
class iterator_test : public xtl::xrandom_access_iterator_base<iterator_test, int, int, int*, int>,
|
||||
public xtl::xrandom_access_iterator_ext<iterator_test, int>
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
using self_type = iterator_test;
|
||||
using base_type = xtl::xrandom_access_iterator_base<self_type, int, int, int*, int>;
|
||||
using ext_type = xtl::xrandom_access_iterator_ext<iterator_test, int>;
|
||||
using value_type = typename base_type::value_type;
|
||||
using reference = typename base_type::reference;
|
||||
using pointer = typename base_type::pointer;
|
||||
using difference_type = typename base_type::difference_type;
|
||||
using size_type = typename ext_type::size_type;
|
||||
|
||||
inline iterator_test() : m_value(0) {}
|
||||
|
||||
inline self_type& operator++()
|
||||
{
|
||||
++m_value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline self_type& operator--()
|
||||
{
|
||||
--m_value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline self_type& operator+=(difference_type n)
|
||||
{
|
||||
m_value += n;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline self_type& operator-=(difference_type n)
|
||||
{
|
||||
m_value -= n;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline self_type& operator+=(size_type n)
|
||||
{
|
||||
m_value += static_cast<value_type>(n);
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline self_type& operator-=(size_type n)
|
||||
{
|
||||
m_value -= static_cast<value_type>(n);
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline reference operator*() const
|
||||
{
|
||||
return m_value;
|
||||
}
|
||||
|
||||
inline pointer operator->() const
|
||||
{
|
||||
return &m_value;
|
||||
}
|
||||
|
||||
using base_type::operator[];
|
||||
using ext_type::operator[];
|
||||
|
||||
mutable value_type m_value;
|
||||
};
|
||||
|
||||
inline int operator-(const iterator_test& lhs, const iterator_test& rhs)
|
||||
{
|
||||
return *lhs - *rhs;
|
||||
}
|
||||
|
||||
inline bool operator==(const iterator_test& lhs, const iterator_test& rhs)
|
||||
{
|
||||
return lhs.m_value == rhs.m_value;
|
||||
}
|
||||
|
||||
inline bool operator<(const iterator_test& lhs, const iterator_test& rhs)
|
||||
{
|
||||
return lhs.m_value < rhs.m_value;
|
||||
}
|
||||
}
|
||||
|
||||
namespace xtl
|
||||
{
|
||||
using iterator = adl::iterator_test;
|
||||
|
||||
TEST(xiterator_base, increment)
|
||||
{
|
||||
iterator it;
|
||||
++it;
|
||||
EXPECT_EQ(1, *it);
|
||||
it++;
|
||||
EXPECT_EQ(2, *it);
|
||||
}
|
||||
|
||||
TEST(xiterator_base, decrement)
|
||||
{
|
||||
iterator it;
|
||||
--it;
|
||||
EXPECT_EQ(-1, *it);
|
||||
it--;
|
||||
EXPECT_EQ(-2, *it);
|
||||
}
|
||||
|
||||
TEST(xiterator_base, plus_assign)
|
||||
{
|
||||
iterator it;
|
||||
++it;
|
||||
it += 5;
|
||||
EXPECT_EQ(6, *it);
|
||||
|
||||
it += std::size_t(5);
|
||||
EXPECT_EQ(11, *it);
|
||||
}
|
||||
|
||||
TEST(xiterator_base, minus_assign)
|
||||
{
|
||||
iterator it;
|
||||
++it;
|
||||
it -= 5;
|
||||
EXPECT_EQ(-4, *it);
|
||||
|
||||
it -= std::size_t(5);
|
||||
EXPECT_EQ(-9, *it);
|
||||
}
|
||||
|
||||
TEST(xiterator_base, plus)
|
||||
{
|
||||
iterator it;
|
||||
++it;
|
||||
iterator it2 = it + 4;
|
||||
EXPECT_EQ(5, *it2);
|
||||
|
||||
iterator it3 = 5 + it;
|
||||
EXPECT_EQ(6, *it3);
|
||||
|
||||
iterator it4 = it + std::size_t(4);
|
||||
EXPECT_EQ(*it2, *it4);
|
||||
|
||||
iterator it5 = std::size_t(5) + it;
|
||||
EXPECT_EQ(*it3, *it5);
|
||||
}
|
||||
|
||||
TEST(xiterator_base, minus)
|
||||
{
|
||||
iterator it;
|
||||
++it;
|
||||
iterator it2 = it - 5;
|
||||
EXPECT_EQ(-4, *it2);
|
||||
|
||||
int diff = it - it2;
|
||||
EXPECT_EQ(5, diff);
|
||||
|
||||
iterator it3 = it - std::size_t(5);
|
||||
EXPECT_EQ(*it2, *it3);
|
||||
}
|
||||
|
||||
TEST(xiterator_base, random_access)
|
||||
{
|
||||
iterator it;
|
||||
EXPECT_EQ(it[5], *(it + 5));
|
||||
EXPECT_EQ(it[5], it[std::size_t(5)]);
|
||||
}
|
||||
|
||||
TEST(xiterator_base, comparison)
|
||||
{
|
||||
iterator it;
|
||||
iterator it2(it);
|
||||
++it;
|
||||
|
||||
EXPECT_TRUE(it == it);
|
||||
EXPECT_TRUE(it != it2);
|
||||
EXPECT_TRUE(it2 <= it);
|
||||
EXPECT_TRUE(it2 < it);
|
||||
EXPECT_TRUE(it >= it2);
|
||||
EXPECT_TRUE(it > it2);
|
||||
}
|
||||
|
||||
TEST(xiterator_base, xkey_iterator)
|
||||
{
|
||||
using map_type = std::map<std::string, int>;
|
||||
map_type m = { {"a", 0}, {"b", 1}, {"c", 2} };
|
||||
using xkeyiterator = xkey_iterator<map_type>;
|
||||
|
||||
xkeyiterator it(m.begin());
|
||||
EXPECT_EQ(*it, "a");
|
||||
xkeyiterator it2 = it;
|
||||
EXPECT_EQ(it, it2);
|
||||
++it2;
|
||||
EXPECT_EQ(*it2, "b");
|
||||
EXPECT_NE(it, it2);
|
||||
++it2;
|
||||
EXPECT_EQ(*it2, "c");
|
||||
++it2;
|
||||
EXPECT_EQ(it2, xkeyiterator(m.end()));
|
||||
}
|
||||
|
||||
TEST(xiterator_base, xvalue_iterator)
|
||||
{
|
||||
using map_type = std::map<std::string, int>;
|
||||
map_type m = { {"a", 0}, {"b", 1}, {"c", 2} };
|
||||
using xvalueiterator = xvalue_iterator<map_type>;
|
||||
|
||||
xvalueiterator it(m.begin());
|
||||
EXPECT_EQ(*it, 0);
|
||||
xvalueiterator it2 = it;
|
||||
EXPECT_EQ(it, it2);
|
||||
++it2;
|
||||
EXPECT_EQ(*it2, 1);
|
||||
EXPECT_NE(it, it2);
|
||||
++it2;
|
||||
EXPECT_EQ(*it2, 2);
|
||||
++it2;
|
||||
EXPECT_EQ(it2, xvalueiterator(m.end()));
|
||||
}
|
||||
|
||||
TEST(xiterator_base, tag_promotion)
|
||||
{
|
||||
using random_iterator = std::vector<int>::iterator;
|
||||
using bidirectional_iterator = std::list<int>::iterator;
|
||||
|
||||
using type1 = common_iterator_tag_t<random_iterator, bidirectional_iterator>;
|
||||
using type2 = common_iterator_tag_t<random_iterator, random_iterator>;
|
||||
|
||||
bool b1 = std::is_same<type1, std::bidirectional_iterator_tag>::value;
|
||||
bool b2 = std::is_same<type2, std::random_access_iterator_tag>::value;
|
||||
|
||||
EXPECT_TRUE(b1);
|
||||
EXPECT_TRUE(b2);
|
||||
}
|
||||
|
||||
TEST(xstepping_iterator, increment)
|
||||
{
|
||||
std::vector<int> v = { 1, 2, 3, 4 };
|
||||
auto it = make_stepping_iterator(v.begin(), 2);
|
||||
auto it_end = make_stepping_iterator(v.end(), 2);
|
||||
++it;
|
||||
EXPECT_EQ(*it, 3);
|
||||
++it;
|
||||
EXPECT_EQ(it, it_end);
|
||||
}
|
||||
|
||||
TEST(xstepping_iterator, decrement)
|
||||
{
|
||||
std::vector<int> v = { 1, 2, 3, 4 };
|
||||
auto it = make_stepping_iterator(v.begin(), 2);
|
||||
auto it_end = make_stepping_iterator(v.end(), 2);
|
||||
--it_end;
|
||||
EXPECT_EQ(*it_end, 3);
|
||||
--it_end;
|
||||
EXPECT_EQ(it, it_end);
|
||||
}
|
||||
|
||||
TEST(xstepping_iterator, plus_assign)
|
||||
{
|
||||
std::vector<int> v = { 1, 2, 3, 4, 5, 6, 7, 8 };
|
||||
auto it = make_stepping_iterator(v.begin(), 2);
|
||||
auto it_end = make_stepping_iterator(v.end(), 2);
|
||||
it += 2;
|
||||
EXPECT_EQ(*it, 5);
|
||||
it += 2;
|
||||
EXPECT_EQ(it, it_end);
|
||||
}
|
||||
|
||||
TEST(xstepping_iterator, minus_assign)
|
||||
{
|
||||
std::vector<int> v = { 1, 2, 3, 4, 5, 6, 7, 8 };
|
||||
auto it = make_stepping_iterator(v.begin(), 2);
|
||||
auto it_end = make_stepping_iterator(v.end(), 2);
|
||||
it_end -= 2;
|
||||
EXPECT_EQ(*it_end, 5);
|
||||
it_end -= 2;
|
||||
EXPECT_EQ(it_end, it);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,623 @@
|
|||
/***************************************************************************
|
||||
* Copyright (c) Johan Mabille, Sylvain Corlay Wolf Vollprecht and *
|
||||
* Martin Renou *
|
||||
* Copyright (c) QuantStack *
|
||||
* *
|
||||
* Distributed under the terms of the BSD 3-Clause License. *
|
||||
* *
|
||||
* The full license is in the file LICENSE, distributed with this software. *
|
||||
****************************************************************************/
|
||||
|
||||
#include "xtl/xmasked_value.hpp"
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "xtl/xoptional.hpp"
|
||||
|
||||
namespace xtl
|
||||
{
|
||||
using optional_type = xoptional<double&, bool&>;
|
||||
|
||||
TEST(xmasked_value, ctor)
|
||||
{
|
||||
double a = 5.2;
|
||||
|
||||
auto m = xmasked_value<double&>(a);
|
||||
EXPECT_EQ(m.value(), 5.2);
|
||||
EXPECT_EQ(m.visible(), true);
|
||||
}
|
||||
|
||||
TEST(xmasked_value, value)
|
||||
{
|
||||
double a = 5.2;
|
||||
bool bool_val = true;
|
||||
|
||||
auto b = optional_type(a, bool_val);
|
||||
auto c = xmasked_value<optional_type>(b);
|
||||
|
||||
EXPECT_EQ(c.value(), 5.2);
|
||||
a = 3.35;
|
||||
EXPECT_EQ(c.value(), 3.35);
|
||||
c.value() = 126.;
|
||||
EXPECT_EQ(c.value(), 126.);
|
||||
EXPECT_EQ(a, 126.);
|
||||
|
||||
auto c2 = xmasked_value<double>(3.);
|
||||
EXPECT_EQ(c2.value(), 3.);
|
||||
c2.value() = 36.;
|
||||
EXPECT_EQ(c2.value(), 36.);
|
||||
}
|
||||
|
||||
TEST(xmasked_value, visible)
|
||||
{
|
||||
double a = 5.2;
|
||||
bool bool_val = true;
|
||||
|
||||
auto b = optional_type(a, bool_val);
|
||||
auto c = xmasked_value<optional_type, bool&>(b, bool_val);
|
||||
|
||||
EXPECT_TRUE(c.visible());
|
||||
bool_val = false;
|
||||
EXPECT_FALSE(c.visible());
|
||||
}
|
||||
|
||||
TEST(xmasked_value, conversion)
|
||||
{
|
||||
double a = 5.2;
|
||||
bool bool_val = true;
|
||||
|
||||
auto b = xmasked_value<double&, bool&>(a, bool_val);
|
||||
|
||||
xoptional<double&, bool> c = b;
|
||||
EXPECT_EQ(c.value(), 5.2);
|
||||
EXPECT_TRUE(c.has_value());
|
||||
|
||||
double& val = b;
|
||||
EXPECT_EQ(val, 5.2);
|
||||
val = 36.;
|
||||
EXPECT_EQ(c.value(), 36.);
|
||||
EXPECT_EQ(b.value(), 36.);
|
||||
}
|
||||
|
||||
TEST(xmasked_value, comparison)
|
||||
{
|
||||
double a = 5.2;
|
||||
bool bool_val = true;
|
||||
|
||||
auto m1 = xmasked_value<double&, bool&>(a, bool_val);
|
||||
auto m2 = xmasked_value<double&, bool&>(a, bool_val);
|
||||
|
||||
EXPECT_EQ(m1, m2);
|
||||
EXPECT_EQ(m2, m1);
|
||||
|
||||
EXPECT_EQ(m1, 5.2);
|
||||
EXPECT_EQ(5.2, m1);
|
||||
|
||||
EXPECT_NE(m1, 6.2);
|
||||
EXPECT_NE(6.2, m1);
|
||||
|
||||
bool_val = false;
|
||||
|
||||
EXPECT_NE(m1, 5.2);
|
||||
EXPECT_NE(5.2, m1);
|
||||
|
||||
using opt_type = xoptional<double, bool>;
|
||||
using masked_opt_type = xmasked_value<opt_type>;
|
||||
|
||||
auto masked1 = masked_opt_type(opt_type(5.2));
|
||||
auto o1 = opt_type(5.2);
|
||||
|
||||
EXPECT_EQ(masked1, o1);
|
||||
EXPECT_EQ(masked1, 5.2);
|
||||
|
||||
masked1.visible() = false;
|
||||
EXPECT_NE(masked1, o1);
|
||||
}
|
||||
|
||||
TEST(xmasked_value, swap)
|
||||
{
|
||||
double a1 = 5.2;
|
||||
bool b1 = true;
|
||||
double a2 = 36.5;
|
||||
bool b2 = false;
|
||||
|
||||
auto m1 = xmasked_value<double&, bool&>(a1, b1);
|
||||
auto m2 = xmasked_value<double&, bool&>(a2, b2);
|
||||
|
||||
EXPECT_EQ(a1, 5.2);
|
||||
EXPECT_EQ(b1, true);
|
||||
EXPECT_EQ(a2, 36.5);
|
||||
EXPECT_EQ(b2, false);
|
||||
|
||||
m1.swap(m2);
|
||||
|
||||
EXPECT_EQ(a1, 36.5);
|
||||
EXPECT_EQ(b1, false);
|
||||
EXPECT_EQ(a2, 5.2);
|
||||
EXPECT_EQ(b2, true);
|
||||
|
||||
using opt_type = xoptional<double>;
|
||||
|
||||
auto o1 = opt_type(3.5, true);
|
||||
auto o2 = opt_type(6.5, false);
|
||||
auto m3 = xmasked_value<opt_type>(o1, true);
|
||||
auto m4 = xmasked_value<opt_type>(o2, false);
|
||||
|
||||
swap(m3, m4);
|
||||
|
||||
EXPECT_EQ(m3.value().value(), 6.5);
|
||||
EXPECT_FALSE(m3.value().has_value());
|
||||
EXPECT_FALSE(m3.visible());
|
||||
EXPECT_EQ(m4.value().value(), 3.5);
|
||||
EXPECT_TRUE(m4.value().has_value());
|
||||
EXPECT_TRUE(m4.visible());
|
||||
}
|
||||
|
||||
TEST(xmasked_value, arithm_neg)
|
||||
{
|
||||
double a = 5.2;
|
||||
bool b = true;
|
||||
|
||||
auto m = xmasked_value<double&, bool&>(a, b);
|
||||
|
||||
xmasked_value<double, bool> r = -m;
|
||||
EXPECT_EQ(r.value(), -5.2);
|
||||
EXPECT_EQ(r.visible(), true);
|
||||
}
|
||||
|
||||
TEST(xmasked_value, arithm_plus)
|
||||
{
|
||||
double a = 5.2;
|
||||
bool b = true;
|
||||
|
||||
auto o = optional_type(a, b);
|
||||
|
||||
auto m = xmasked_value<optional_type>(o);
|
||||
|
||||
auto r1 = m + o;
|
||||
EXPECT_EQ(r1.value(), 10.4);
|
||||
EXPECT_EQ(r1.visible(), true);
|
||||
|
||||
auto r2 = o + m;
|
||||
EXPECT_EQ(r2.value(), 10.4);
|
||||
EXPECT_EQ(r2.visible(), true);
|
||||
|
||||
auto r3 = m + m;
|
||||
EXPECT_EQ(r3.value(), 10.4);
|
||||
EXPECT_EQ(r3.visible(), true);
|
||||
|
||||
auto r4 = 4.2 + m;
|
||||
EXPECT_EQ(r4.value(), 9.4);
|
||||
EXPECT_EQ(r4.visible(), true);
|
||||
|
||||
auto r5 = m + 4.2;
|
||||
EXPECT_EQ(r5.value(), 9.4);
|
||||
EXPECT_EQ(r5.visible(), true);
|
||||
}
|
||||
|
||||
TEST(xmasked_value, arithm_minus)
|
||||
{
|
||||
double a = 5.2;
|
||||
bool b = true;
|
||||
|
||||
auto o = optional_type(a, b);
|
||||
|
||||
auto m = xmasked_value<optional_type>(o);
|
||||
|
||||
auto r1 = m - o;
|
||||
EXPECT_EQ(r1.value(), 0.0);
|
||||
EXPECT_EQ(r1.visible(), true);
|
||||
|
||||
auto r2 = o - m;
|
||||
EXPECT_EQ(r2.value(), 0.0);
|
||||
EXPECT_EQ(r2.visible(), true);
|
||||
|
||||
auto r3 = m - m;
|
||||
EXPECT_EQ(r3.value(), 0.0);
|
||||
EXPECT_EQ(r3.visible(), true);
|
||||
|
||||
auto r4 = 4.2 - m;
|
||||
EXPECT_EQ(r4.value(), -1.0);
|
||||
EXPECT_EQ(r4.visible(), true);
|
||||
|
||||
auto r5 = m - 4.2;
|
||||
EXPECT_EQ(r5.value(), 1.0);
|
||||
EXPECT_EQ(r5.visible(), true);
|
||||
}
|
||||
|
||||
TEST(xmasked_value, arithm_mult)
|
||||
{
|
||||
double a = 5.0;
|
||||
bool b = true;
|
||||
|
||||
auto o = optional_type(a, b);
|
||||
|
||||
auto m = xmasked_value<optional_type>(o);
|
||||
|
||||
auto r1 = m * o;
|
||||
EXPECT_EQ(r1.value(), 25.);
|
||||
EXPECT_EQ(r1.visible(), true);
|
||||
|
||||
auto r2 = o * m;
|
||||
EXPECT_EQ(r2.value(), 25.);
|
||||
EXPECT_EQ(r2.visible(), true);
|
||||
|
||||
auto r3 = m * m;
|
||||
EXPECT_EQ(r3.value(), 25.);
|
||||
EXPECT_EQ(r3.visible(), true);
|
||||
|
||||
auto r4 = 4. * m;
|
||||
EXPECT_EQ(r4.value(), 20.);
|
||||
EXPECT_EQ(r4.visible(), true);
|
||||
|
||||
auto r5 = m * 4.;
|
||||
EXPECT_EQ(r5.value(), 20.);
|
||||
EXPECT_EQ(r5.visible(), true);
|
||||
}
|
||||
|
||||
TEST(xmasked_value, arithm_div)
|
||||
{
|
||||
double a = 5.0;
|
||||
bool b = true;
|
||||
|
||||
auto o = optional_type(a, b);
|
||||
|
||||
auto m = xmasked_value<optional_type>(o);
|
||||
|
||||
auto r1 = m / o;
|
||||
EXPECT_EQ(r1.value(), 1.);
|
||||
EXPECT_EQ(r1.visible(), true);
|
||||
|
||||
auto r2 = o / m;
|
||||
EXPECT_EQ(r2.value(), 1.);
|
||||
EXPECT_EQ(r2.visible(), true);
|
||||
|
||||
auto r3 = m / m;
|
||||
EXPECT_EQ(r3.value(), 1.);
|
||||
EXPECT_EQ(r3.visible(), true);
|
||||
|
||||
auto r4 = 25. / m;
|
||||
EXPECT_EQ(r4.value(), 5.);
|
||||
EXPECT_EQ(r4.visible(), true);
|
||||
|
||||
auto r5 = m / 1.;
|
||||
EXPECT_EQ(r5.value(), 5.);
|
||||
EXPECT_EQ(r5.visible(), true);
|
||||
}
|
||||
|
||||
TEST(xmasked_value, operator_or)
|
||||
{
|
||||
bool b = true;
|
||||
|
||||
auto o = xoptional<bool, bool&>(true, b);
|
||||
auto m = xmasked_value<xoptional<bool, bool&>, bool>(o, true);
|
||||
|
||||
auto r1 = m || o;
|
||||
EXPECT_EQ(r1.value(), true);
|
||||
EXPECT_EQ(r1.visible(), true);
|
||||
|
||||
auto r2 = o || m;
|
||||
EXPECT_EQ(r2.value(), true);
|
||||
EXPECT_EQ(r2.visible(), true);
|
||||
|
||||
auto r3 = m || m;
|
||||
EXPECT_EQ(r3.value(), true);
|
||||
EXPECT_EQ(r3.visible(), true);
|
||||
|
||||
auto r4 = true || m;
|
||||
EXPECT_EQ(r4.value(), true);
|
||||
EXPECT_EQ(r4.visible(), true);
|
||||
|
||||
auto r5 = false || m;
|
||||
EXPECT_EQ(r5.value(), true);
|
||||
EXPECT_EQ(r5.visible(), true);
|
||||
|
||||
auto r6 = m || true;
|
||||
EXPECT_EQ(r6.value(), true);
|
||||
EXPECT_EQ(r6.visible(), true);
|
||||
|
||||
auto r7 = m || false;
|
||||
EXPECT_EQ(r7.value(), true);
|
||||
EXPECT_EQ(r7.visible(), true);
|
||||
}
|
||||
|
||||
TEST(xmasked_value, operator_and)
|
||||
{
|
||||
bool b = true;
|
||||
|
||||
auto o = xoptional<bool, bool&>(true, b);
|
||||
auto m = xmasked_value<xoptional<bool, bool&>, bool>(o, true);
|
||||
|
||||
auto r1 = m && o;
|
||||
EXPECT_EQ(r1.value(), true);
|
||||
EXPECT_EQ(r1.visible(), true);
|
||||
|
||||
auto r2 = o && m;
|
||||
EXPECT_EQ(r2.value(), true);
|
||||
EXPECT_EQ(r2.visible(), true);
|
||||
|
||||
auto r3 = m && m;
|
||||
EXPECT_EQ(r3.value(), true);
|
||||
EXPECT_EQ(r3.visible(), true);
|
||||
|
||||
auto r4 = true && m;
|
||||
EXPECT_EQ(r4.value(), true);
|
||||
EXPECT_EQ(r4.visible(), true);
|
||||
|
||||
auto r5 = false && m;
|
||||
EXPECT_EQ(r5.value(), false);
|
||||
EXPECT_EQ(r5.visible(), true);
|
||||
|
||||
auto r6 = m && true;
|
||||
EXPECT_EQ(r6.value(), true);
|
||||
EXPECT_EQ(r6.visible(), true);
|
||||
|
||||
auto r7 = m && false;
|
||||
EXPECT_EQ(r7.value(), false);
|
||||
EXPECT_EQ(r7.visible(), true);
|
||||
|
||||
m.visible() = false;
|
||||
auto r8 = m && true;
|
||||
EXPECT_EQ(r8.visible(), false);
|
||||
}
|
||||
|
||||
TEST(xmasked_value, operator_not)
|
||||
{
|
||||
using opt_type = xoptional<bool>;
|
||||
|
||||
bool b = true;
|
||||
|
||||
auto m1 = xmasked_value<bool, bool&>(true, b);
|
||||
auto m2 = xmasked_value<bool, bool&>(false, b);
|
||||
auto m3 = xmasked_value<opt_type>(opt_type(true));
|
||||
|
||||
EXPECT_EQ(!m1, false);
|
||||
EXPECT_EQ(!m2, true);
|
||||
EXPECT_EQ(!m3, false);
|
||||
}
|
||||
|
||||
TEST(xmasked_value, operator_less)
|
||||
{
|
||||
double a1 = 5.0;
|
||||
double a2 = 10.0;
|
||||
bool b = true;
|
||||
|
||||
auto o = optional_type(a1, b);
|
||||
auto o2 = optional_type(a2, b);
|
||||
|
||||
auto m = xmasked_value<optional_type, bool>(o2, true);
|
||||
|
||||
auto r1 = m < o;
|
||||
EXPECT_EQ(r1.value(), false);
|
||||
EXPECT_EQ(r1.visible(), true);
|
||||
|
||||
auto r2 = o < m;
|
||||
EXPECT_EQ(r2.value(), true);
|
||||
EXPECT_EQ(r2.visible(), true);
|
||||
|
||||
auto r3 = m < m;
|
||||
EXPECT_EQ(r3.value(), false);
|
||||
EXPECT_EQ(r3.visible(), true);
|
||||
|
||||
auto r4 = 25. < m;
|
||||
EXPECT_EQ(r4.value(), false);
|
||||
EXPECT_EQ(r4.visible(), true);
|
||||
|
||||
auto r5 = m < 25.;
|
||||
EXPECT_EQ(r5.value(), true);
|
||||
EXPECT_EQ(r5.visible(), true);
|
||||
}
|
||||
|
||||
TEST(xmasked_value, operator_less_equal)
|
||||
{
|
||||
double a1 = 5.0;
|
||||
double a2 = 10.0;
|
||||
bool b = true;
|
||||
|
||||
auto o = optional_type(a1, b);
|
||||
auto o2 = optional_type(a2, b);
|
||||
|
||||
auto m = xmasked_value<optional_type, bool>(o2, true);
|
||||
|
||||
auto r1 = m <= o;
|
||||
EXPECT_EQ(r1.value(), false);
|
||||
EXPECT_EQ(r1.visible(), true);
|
||||
|
||||
auto r2 = o <= m;
|
||||
EXPECT_EQ(r2.value(), true);
|
||||
EXPECT_EQ(r2.visible(), true);
|
||||
|
||||
auto r3 = m <= m;
|
||||
EXPECT_EQ(r3.value(), true);
|
||||
EXPECT_EQ(r3.visible(), true);
|
||||
|
||||
auto r4 = 25. <= m;
|
||||
EXPECT_EQ(r4.value(), false);
|
||||
EXPECT_EQ(r4.visible(), true);
|
||||
|
||||
auto r5 = m <= 25.;
|
||||
EXPECT_EQ(r5.value(), true);
|
||||
EXPECT_EQ(r5.visible(), true);
|
||||
}
|
||||
|
||||
TEST(xmasked_value, operator_more)
|
||||
{
|
||||
double a1 = 5.0;
|
||||
double a2 = 10.0;
|
||||
bool b = true;
|
||||
|
||||
auto o = optional_type(a1, b);
|
||||
auto o2 = optional_type(a2, b);
|
||||
|
||||
auto m = xmasked_value<optional_type, bool&>(o2, b);
|
||||
|
||||
auto r1 = m > o;
|
||||
EXPECT_EQ(r1.value(), true);
|
||||
EXPECT_EQ(r1.visible(), true);
|
||||
|
||||
auto r2 = o > m;
|
||||
EXPECT_EQ(r2.value(), false);
|
||||
EXPECT_EQ(r2.visible(), true);
|
||||
|
||||
auto r3 = m > m;
|
||||
EXPECT_EQ(r3.value(), false);
|
||||
EXPECT_EQ(r3.visible(), true);
|
||||
|
||||
auto r4 = 25. > m;
|
||||
EXPECT_EQ(r4.value(), true);
|
||||
EXPECT_EQ(r4.visible(), true);
|
||||
|
||||
auto r5 = m > 25.;
|
||||
EXPECT_EQ(r5.value(), false);
|
||||
EXPECT_EQ(r5.visible(), true);
|
||||
}
|
||||
|
||||
TEST(xmasked_value, operator_more_equal)
|
||||
{
|
||||
double a1 = 5.0;
|
||||
double a2 = 10.0;
|
||||
bool b = true;
|
||||
|
||||
auto o = optional_type(a1, b);
|
||||
auto o2 = optional_type(a2, b);
|
||||
|
||||
auto m = xmasked_value<optional_type, bool&>(o2, b);
|
||||
|
||||
auto r1 = m >= o;
|
||||
EXPECT_EQ(r1.value(), true);
|
||||
EXPECT_EQ(r1.visible(), true);
|
||||
|
||||
auto r2 = o >= m;
|
||||
EXPECT_EQ(r2.value(), false);
|
||||
EXPECT_EQ(r2.visible(), true);
|
||||
|
||||
auto r3 = m >= m;
|
||||
EXPECT_EQ(r3.value(), true);
|
||||
EXPECT_EQ(r3.visible(), true);
|
||||
|
||||
auto r4 = 25. >= m;
|
||||
EXPECT_EQ(r4.value(), true);
|
||||
EXPECT_EQ(r4.visible(), true);
|
||||
|
||||
auto r5 = m >= 25.;
|
||||
EXPECT_EQ(r5.value(), false);
|
||||
EXPECT_EQ(r5.visible(), true);
|
||||
}
|
||||
|
||||
TEST(xmasked_value, assign)
|
||||
{
|
||||
double a = 5.2;
|
||||
double a2 = 3.35;
|
||||
bool bool_val = true;
|
||||
|
||||
auto b = optional_type(a, bool_val);
|
||||
auto c = xmasked_value<optional_type>(b);
|
||||
|
||||
// Value not masked, assigning a value works
|
||||
EXPECT_EQ(c.value(), 5.2);
|
||||
c = a2;
|
||||
EXPECT_EQ(c.value(), 3.35);
|
||||
EXPECT_EQ(a, 3.35);
|
||||
c += 1.;
|
||||
EXPECT_EQ(c.value(), 4.35);
|
||||
EXPECT_EQ(a, 4.35);
|
||||
c -= 1.;
|
||||
c *= 2.;
|
||||
EXPECT_NEAR(a, 6.7, 0.0001);
|
||||
c -= b;
|
||||
EXPECT_NEAR(a, 0., 0.0001);
|
||||
c = 3.35;
|
||||
|
||||
// When masked, the assign doesn't do anything
|
||||
c.visible() = false;
|
||||
c = 126.;
|
||||
EXPECT_EQ(c.value(), 3.35);
|
||||
EXPECT_EQ(a, 3.35);
|
||||
c *= 126;
|
||||
EXPECT_EQ(c.value(), 3.35);
|
||||
EXPECT_EQ(a, 3.35);
|
||||
}
|
||||
|
||||
TEST(xmasked_value, unary_op)
|
||||
{
|
||||
double a1 = -5.2;
|
||||
double a2 = 5.2;
|
||||
bool bool_val = true;
|
||||
|
||||
auto m1 = xmasked_value<double&, bool&>(a1, bool_val);
|
||||
auto m2 = xmasked_value<double&, bool&>(a2, bool_val);
|
||||
|
||||
EXPECT_EQ(abs(m1).value(), 5.2);
|
||||
EXPECT_EQ(abs(m2).value(), 5.2);
|
||||
}
|
||||
|
||||
TEST(xmasked_value, unary_bool_op)
|
||||
{
|
||||
double a = -5.2;
|
||||
bool bool_val = true;
|
||||
|
||||
auto m = xmasked_value<double&, bool&>(a, bool_val);
|
||||
|
||||
EXPECT_EQ(isfinite(m).value(), true);
|
||||
}
|
||||
|
||||
TEST(xmasked_value, binary_op)
|
||||
{
|
||||
double a1 = 5.0;
|
||||
double a2 = 5.0;
|
||||
bool bool_val = true;
|
||||
|
||||
auto o = xoptional<double&>(a1);
|
||||
auto m1 = xmasked_value<xoptional<double&>, bool&>(o, bool_val);
|
||||
auto m2 = xmasked_value<double&, bool&>(a2, bool_val);
|
||||
|
||||
EXPECT_EQ(pow(m1, m1).value(), std::pow(5., 5.));
|
||||
EXPECT_EQ(pow(m1, o).value(), std::pow(5., 5.));
|
||||
EXPECT_EQ(pow(o, m1).value(), std::pow(5., 5.));
|
||||
EXPECT_EQ(pow(m1, 2).value(), 25.0);
|
||||
EXPECT_EQ(pow(2, m1).value(), 32);
|
||||
}
|
||||
|
||||
TEST(xmasked_value, ternary_op)
|
||||
{
|
||||
double a1 = 5.0;
|
||||
double a2 = 11.0;
|
||||
bool bool_val = true;
|
||||
|
||||
auto m1 = xmasked_value<double&, bool&>(a1, bool_val);
|
||||
auto m2 = xmasked_value<double&, bool&>(a2, bool_val);
|
||||
auto masked1 = masked<double>();
|
||||
|
||||
EXPECT_EQ(fma(m1, m2, m2).value(), 66.);
|
||||
EXPECT_EQ(fma(m1, masked1, m2), masked1);
|
||||
|
||||
EXPECT_EQ(fma(m1, m2, 2.).value(), 57.);
|
||||
EXPECT_EQ(fma(m1, 2., m2).value(), 21.);
|
||||
EXPECT_EQ(fma(2., m1, m2).value(), 21.);
|
||||
EXPECT_EQ(fma(2., 10., m2).value(), 31.);
|
||||
EXPECT_EQ(fma(2., m2, 3.).value(), 25.);
|
||||
EXPECT_EQ(fma(m2, 5., 3.).value(), 58.);
|
||||
EXPECT_EQ(fma(m2, 5., masked1), masked1);
|
||||
|
||||
auto o = xoptional<double>(2.);
|
||||
auto o1 = xoptional<double>(5.);
|
||||
auto o2 = xoptional<double>(11.);
|
||||
auto m3 = xmasked_value<xoptional<double>, bool&>(o1, bool_val);
|
||||
auto m4 = xmasked_value<xoptional<double>, bool&>(o2, bool_val);
|
||||
auto masked2 = masked<xoptional<double>>();
|
||||
|
||||
EXPECT_EQ(fma(m3, m4, o).value(), 57.);
|
||||
EXPECT_EQ(fma(m3, o, m4).value(), 21.);
|
||||
EXPECT_EQ(fma(o, m3, m4).value(), 21.);
|
||||
EXPECT_EQ(fma(o, m3, masked2), masked2);
|
||||
EXPECT_EQ(fma(o, o, m4).value(), 15.);
|
||||
EXPECT_EQ(fma(o, m4, o).value(), 24.);
|
||||
EXPECT_EQ(fma(m4, o, o).value(), 24.);
|
||||
|
||||
EXPECT_EQ(fma(3., m4, o).value(), 35.);
|
||||
EXPECT_EQ(fma(m4, 3., o).value(), 35.);
|
||||
EXPECT_EQ(fma(m4, o, 3.).value(), 25.);
|
||||
EXPECT_EQ(fma(o, m4, 3.).value(), 25.);
|
||||
EXPECT_EQ(fma(o, 3., m3).value(), 11.);
|
||||
EXPECT_EQ(fma(3., o, m3).value(), 11.);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,320 @@
|
|||
/***************************************************************************
|
||||
* Copyright (c) Johan Mabille, Sylvain Corlay and Wolf Vollprecht *
|
||||
* Copyright (c) QuantStack *
|
||||
* *
|
||||
* Distributed under the terms of the BSD 3-Clause License. *
|
||||
* *
|
||||
* The full license is in the file LICENSE, distributed with this software. *
|
||||
****************************************************************************/
|
||||
#include "xtl/xmeta_utils.hpp"
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "xtl/xvariant.hpp"
|
||||
|
||||
namespace xtl
|
||||
{
|
||||
using vector_t = mpl::vector<int, double, char*>;
|
||||
using variant_t = variant<int, double, char*>;
|
||||
|
||||
TEST(mpl, if_)
|
||||
{
|
||||
using true_cond = mpl::bool_<true>;
|
||||
using false_cond = mpl::bool_<false>;
|
||||
|
||||
bool res1 = std::is_same<mpl::if_t<true_cond, vector_t, variant_t>, vector_t>::value;
|
||||
bool res2 = std::is_same<mpl::if_t<false_cond, vector_t, variant_t>, variant_t>::value;
|
||||
|
||||
EXPECT_TRUE(res1);
|
||||
EXPECT_TRUE(res2);
|
||||
}
|
||||
|
||||
TEST(mpl, cast)
|
||||
{
|
||||
using type = mpl::cast_t<vector_t, variant>;
|
||||
bool res = std::is_same<type, variant_t>::value;
|
||||
EXPECT_TRUE(res);
|
||||
}
|
||||
|
||||
TEST(mpl, size)
|
||||
{
|
||||
std::size_t size = mpl::size<vector_t>::value;
|
||||
EXPECT_EQ(size, 3u);
|
||||
}
|
||||
|
||||
TEST(mpl, empty)
|
||||
{
|
||||
bool res1 = mpl::empty<vector_t>::value;
|
||||
bool res2 = mpl::empty<mpl::vector<>>::value;
|
||||
|
||||
EXPECT_FALSE(res1);
|
||||
EXPECT_TRUE(res2);
|
||||
}
|
||||
|
||||
TEST(mpl, count)
|
||||
{
|
||||
using type = mpl::vector<int, double, int, float, double, double>;
|
||||
std::size_t c1 = mpl::count<type, int>::value;
|
||||
std::size_t c2 = mpl::count<type, double>::value;
|
||||
std::size_t c3 = mpl::count<type, float>::value;
|
||||
std::size_t c4 = mpl::count<type, char>::value;
|
||||
|
||||
EXPECT_EQ(c1, 2u);
|
||||
EXPECT_EQ(c2, 3u);
|
||||
EXPECT_EQ(c3, 1u);
|
||||
EXPECT_EQ(c4, 0u);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
struct is_double : std::is_same<T, double>
|
||||
{
|
||||
};
|
||||
|
||||
TEST(mpl, count_if)
|
||||
{
|
||||
using type = mpl::vector<int, double, float, double>;
|
||||
std::size_t c1 = mpl::count_if<type, is_double>::value;
|
||||
EXPECT_EQ(c1, 2u);
|
||||
}
|
||||
|
||||
TEST(mpl, contains)
|
||||
{
|
||||
using type = mpl::vector<int, double, double>;
|
||||
bool res1 = mpl::contains<type, int>::value;
|
||||
bool res2 = mpl::contains<type, double>::value;
|
||||
bool res3 = mpl::contains<type, float>::value;
|
||||
|
||||
EXPECT_TRUE(res1);
|
||||
EXPECT_TRUE(res2);
|
||||
EXPECT_FALSE(res3);
|
||||
}
|
||||
|
||||
TEST(mpl, index_of)
|
||||
{
|
||||
using type1 = mpl::vector<int, double, float>;
|
||||
std::size_t res1 = mpl::index_of<type1, int>::value;
|
||||
std::size_t res2 = mpl::index_of<type1, double>::value;
|
||||
std::size_t res3 = mpl::index_of<type1, float>::value;
|
||||
std::size_t res4 = mpl::index_of<type1, short>::value;
|
||||
|
||||
EXPECT_EQ(res1, 0u);
|
||||
EXPECT_EQ(res2, 1u);
|
||||
EXPECT_EQ(res3, 2u);
|
||||
EXPECT_EQ(res4, SIZE_MAX);
|
||||
}
|
||||
|
||||
TEST(mpl, front)
|
||||
{
|
||||
using type = mpl::front_t<variant_t>;
|
||||
bool res = std::is_same<type, int>::value;
|
||||
EXPECT_TRUE(res);
|
||||
}
|
||||
|
||||
TEST(mpl, back)
|
||||
{
|
||||
using type = mpl::back_t<variant_t>;
|
||||
bool res = std::is_same<type, char*>::value;
|
||||
EXPECT_TRUE(res);
|
||||
}
|
||||
|
||||
TEST(mpl, push_front)
|
||||
{
|
||||
using type = mpl::push_front_t<vector_t, double>;
|
||||
using res_type = mpl::vector<double, int, double, char*>;
|
||||
bool res = std::is_same<type, res_type>::value;
|
||||
EXPECT_TRUE(res);
|
||||
}
|
||||
|
||||
TEST(mpl, push_back)
|
||||
{
|
||||
using type = mpl::push_back_t<vector_t, double>;
|
||||
using res_type = mpl::vector<int, double, char*, double>;
|
||||
bool res = std::is_same<type, res_type>::value;
|
||||
EXPECT_TRUE(res);
|
||||
}
|
||||
|
||||
TEST(mpl, pop_front)
|
||||
{
|
||||
using type = mpl::pop_front_t<vector_t>;
|
||||
using res_type = mpl::vector<double, char*>;
|
||||
bool res = std::is_same<type, res_type>::value;
|
||||
EXPECT_TRUE(res);
|
||||
}
|
||||
|
||||
TEST(mpl, transform)
|
||||
{
|
||||
using type = mpl::transform_t<std::add_pointer_t, vector_t>;
|
||||
using res_type = mpl::vector<int*, double*, char**>;
|
||||
bool res = std::is_same<type, res_type>::value;
|
||||
EXPECT_TRUE(res);
|
||||
}
|
||||
|
||||
TEST(mpl, merge_set)
|
||||
{
|
||||
using arg2 = mpl::vector<double, float, int, short>;
|
||||
using type = mpl::merge_set_t<vector_t, arg2>;
|
||||
using res_type = mpl::vector<int, double, char*, float, short>;
|
||||
bool res = std::is_same<type, res_type>::value;
|
||||
EXPECT_TRUE(res);
|
||||
|
||||
using res_type2 = mpl::merge_set_t<vector_t, vector_t>;
|
||||
bool res2 = std::is_same<res_type2, vector_t>::value;
|
||||
EXPECT_TRUE(res2);
|
||||
}
|
||||
|
||||
TEST(mpl, find_if_)
|
||||
{
|
||||
using arg1 = mpl::vector<double, int, float, int>;
|
||||
constexpr size_t res1 = mpl::find_if<xtl::is_integral, arg1>::value;
|
||||
EXPECT_EQ(res1, 1ul);
|
||||
|
||||
using arg2 = mpl::vector<double, float, double>;
|
||||
constexpr size_t res2 = mpl::find_if<xtl::is_integral, arg2>::value;
|
||||
EXPECT_EQ(res2, 3ul);
|
||||
|
||||
using arg3 = mpl::vector<>;
|
||||
constexpr size_t res3 = mpl::find_if<xtl::is_integral, arg3>::value;
|
||||
EXPECT_EQ(res3, 0ul);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void debug(T&&)
|
||||
{
|
||||
std::cout << __PRETTY_FUNCTION__ << std::endl;
|
||||
}
|
||||
|
||||
TEST(mpl, split)
|
||||
{
|
||||
using arg = mpl::vector<double, int, float, short>;
|
||||
{
|
||||
using sp = mpl::split<0u, arg>;
|
||||
using first_res_type = typename sp::first_type;
|
||||
using second_res_type = typename sp::second_type;
|
||||
bool first_res = std::is_same<first_res_type, mpl::vector<>>::value;
|
||||
bool second_res = std::is_same<second_res_type, arg>::value;
|
||||
EXPECT_TRUE(first_res);
|
||||
EXPECT_TRUE(second_res);
|
||||
}
|
||||
{
|
||||
using sp = mpl::split<1u, arg>;
|
||||
using first_res_type = typename sp::first_type;
|
||||
using second_res_type = typename sp::second_type;
|
||||
bool first_res = std::is_same<first_res_type, mpl::vector<double>>::value;
|
||||
bool second_res = std::is_same<second_res_type, mpl::vector<int, float, short>>::value;
|
||||
EXPECT_TRUE(first_res);
|
||||
EXPECT_TRUE(second_res);
|
||||
}
|
||||
{
|
||||
using sp = mpl::split<2u, arg>;
|
||||
using first_res_type = typename sp::first_type;
|
||||
using second_res_type = typename sp::second_type;
|
||||
bool first_res = std::is_same<first_res_type, mpl::vector<double, int>>::value;
|
||||
bool second_res = std::is_same<second_res_type, mpl::vector<float, short>>::value;
|
||||
EXPECT_TRUE(first_res);
|
||||
EXPECT_TRUE(second_res);
|
||||
}
|
||||
{
|
||||
using sp = mpl::split<3u, arg>;
|
||||
using first_res_type = typename sp::first_type;
|
||||
using second_res_type = typename sp::second_type;
|
||||
bool first_res = std::is_same<first_res_type, mpl::vector<double, int, float>>::value;
|
||||
bool second_res = std::is_same<second_res_type, mpl::vector<short>>::value;
|
||||
EXPECT_TRUE(first_res);
|
||||
EXPECT_TRUE(second_res);
|
||||
}
|
||||
{
|
||||
using sp = mpl::split<4u, arg>;
|
||||
using first_res_type = typename sp::first_type;
|
||||
using second_res_type = typename sp::second_type;
|
||||
bool first_res = std::is_same<first_res_type, arg>::value;
|
||||
bool second_res = std::is_same<second_res_type, mpl::vector<>>::value;
|
||||
EXPECT_TRUE(first_res);
|
||||
EXPECT_TRUE(second_res);
|
||||
}
|
||||
}
|
||||
|
||||
template <bool B>
|
||||
int static_if_tester()
|
||||
{
|
||||
int input = 0;
|
||||
return mpl::static_if<B == false>([&](auto /*self*/)
|
||||
{
|
||||
return input;
|
||||
}, /*else*/ [&](auto /*self*/)
|
||||
{
|
||||
return input + 1;
|
||||
});
|
||||
}
|
||||
|
||||
TEST(mpl, static_if)
|
||||
{
|
||||
int output_0 = static_if_tester<false>();
|
||||
int output_1 = static_if_tester<true>();
|
||||
EXPECT_EQ(output_0, 0);
|
||||
EXPECT_EQ(output_1, 1);
|
||||
}
|
||||
|
||||
template <bool B>
|
||||
struct static_if_tester2
|
||||
{
|
||||
int input = 0;
|
||||
|
||||
inline int& operator()()
|
||||
{
|
||||
return mpl::static_if<B == false>([&](auto /*self*/) -> int&
|
||||
{
|
||||
return input;
|
||||
}, /*else*/ [&](auto /*self*/) -> int&
|
||||
{
|
||||
input++;
|
||||
return input;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
TEST(mpl, static_if2)
|
||||
{
|
||||
static_if_tester2<false> tester;
|
||||
int& output_0 = tester();
|
||||
EXPECT_EQ(output_0, 0);
|
||||
|
||||
output_0++;
|
||||
int& output_1 = tester();
|
||||
EXPECT_EQ(output_1, 1);
|
||||
|
||||
static_if_tester2<true> tester2;
|
||||
int& output_3 = tester2();
|
||||
EXPECT_EQ(output_3, 1);
|
||||
tester2();
|
||||
EXPECT_EQ(output_3, 2);
|
||||
}
|
||||
|
||||
TEST(mpl, unique)
|
||||
{
|
||||
using input1 = mpl::vector<double, int, double, int, int>;
|
||||
using input2 = mpl::vector<double, int>;
|
||||
using res_type1 = mpl::unique_t<input1>;
|
||||
using res_type2 = mpl::unique_t<input2>;
|
||||
|
||||
constexpr bool res1 = std::is_same<res_type1, input2>::value;
|
||||
constexpr bool res2 = std::is_same<res_type2, input2>::value;
|
||||
|
||||
EXPECT_TRUE(res1);
|
||||
EXPECT_TRUE(res2);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
using switch_type = mpl::switch_t<std::is_integral<T>, int,
|
||||
std::is_floating_point<T>, double,
|
||||
mpl::default_t, char>;
|
||||
|
||||
TEST(mpl, switch_t)
|
||||
{
|
||||
constexpr bool res1 = std::is_same<switch_type<short>, int>::value;
|
||||
constexpr bool res2 = std::is_same<switch_type<float>, double>::value;
|
||||
constexpr bool res3 = std::is_same<switch_type<mpl::vector<>>, char>::value;
|
||||
|
||||
EXPECT_TRUE(res1);
|
||||
EXPECT_TRUE(res2);
|
||||
EXPECT_TRUE(res3);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,319 @@
|
|||
/***************************************************************************
|
||||
* Copyright (c) Johan Mabille, Sylvain Corlay and Wolf Vollprecht *
|
||||
* Copyright (c) QuantStack *
|
||||
* *
|
||||
* Distributed under the terms of the BSD 3-Clause License. *
|
||||
* *
|
||||
* The full license is in the file LICENSE, distributed with this software. *
|
||||
****************************************************************************/
|
||||
|
||||
#include <iostream>
|
||||
#include "xtl/xmultimethods.hpp"
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
namespace xtl
|
||||
{
|
||||
struct undispatched_type
|
||||
{
|
||||
};
|
||||
|
||||
enum class shape_id
|
||||
{
|
||||
unknown_id,
|
||||
rectangle_id,
|
||||
circle_id,
|
||||
triangle_id
|
||||
};
|
||||
|
||||
class shape
|
||||
{
|
||||
public:
|
||||
|
||||
XTL_IMPLEMENT_INDEXABLE_CLASS()
|
||||
|
||||
virtual ~shape() = default;
|
||||
|
||||
shape(const shape&) = delete;
|
||||
shape(shape&&) = delete;
|
||||
|
||||
shape& operator=(const shape&) = delete;
|
||||
shape& operator=(shape&&) = delete;
|
||||
|
||||
protected:
|
||||
|
||||
shape() = default;
|
||||
};
|
||||
|
||||
template <shape_id id>
|
||||
class shape_impl : public shape
|
||||
{
|
||||
public:
|
||||
|
||||
XTL_IMPLEMENT_INDEXABLE_CLASS()
|
||||
|
||||
shape_impl() = default;
|
||||
virtual ~shape_impl() = default;
|
||||
|
||||
shape_id get_id() const
|
||||
{
|
||||
return id;
|
||||
}
|
||||
};
|
||||
|
||||
using rectangle = shape_impl<shape_id::rectangle_id>;
|
||||
using circle = shape_impl<shape_id::circle_id>;
|
||||
using triangle = shape_impl<shape_id::triangle_id>;
|
||||
|
||||
using dispatch_return_type = std::pair<shape_id, shape_id>;
|
||||
|
||||
namespace
|
||||
{
|
||||
template <class T1, class T2>
|
||||
dispatch_return_type dispatch_shape_impl(const T1& t1, const T2& t2)
|
||||
{
|
||||
return std::make_pair(t1.get_id(), t2.get_id());
|
||||
}
|
||||
|
||||
#define DEFINE_DISPATCH_SHAPE(T1, T2) \
|
||||
dispatch_return_type dispatch_##T1##_##T2(const T1& t1, const T2& t2) \
|
||||
{ return dispatch_shape_impl(t1, t2); }
|
||||
|
||||
DEFINE_DISPATCH_SHAPE(rectangle, circle)
|
||||
DEFINE_DISPATCH_SHAPE(rectangle, triangle)
|
||||
DEFINE_DISPATCH_SHAPE(circle, rectangle)
|
||||
DEFINE_DISPATCH_SHAPE(circle, triangle)
|
||||
DEFINE_DISPATCH_SHAPE(triangle, rectangle)
|
||||
DEFINE_DISPATCH_SHAPE(triangle, circle)
|
||||
|
||||
template <class T1, class T2>
|
||||
dispatch_return_type partial_dispatch_shape_impl(const T1& t1, const T2& t2, const undispatched_type&)
|
||||
{
|
||||
return std::make_pair(t1.get_id(), t2.get_id());
|
||||
}
|
||||
|
||||
#define DEFINE_PARTIAL_DISPATCH_SHAPE(T1, T2) \
|
||||
dispatch_return_type partial_dispatch_##T1##_##T2(const T1& t1, const T2& t2, const undispatched_type& i) \
|
||||
{ return partial_dispatch_shape_impl(t1, t2, i); }
|
||||
|
||||
DEFINE_PARTIAL_DISPATCH_SHAPE(rectangle, circle)
|
||||
DEFINE_PARTIAL_DISPATCH_SHAPE(rectangle, triangle)
|
||||
DEFINE_PARTIAL_DISPATCH_SHAPE(circle, rectangle)
|
||||
DEFINE_PARTIAL_DISPATCH_SHAPE(circle, triangle)
|
||||
DEFINE_PARTIAL_DISPATCH_SHAPE(triangle, rectangle)
|
||||
DEFINE_PARTIAL_DISPATCH_SHAPE(triangle, circle)
|
||||
}
|
||||
|
||||
class dispatch_tester
|
||||
{
|
||||
public:
|
||||
|
||||
using return_type = dispatch_return_type;
|
||||
|
||||
template <class T1, class T2>
|
||||
return_type run(const T1& t1, const T2& t2) const
|
||||
{
|
||||
return dispatch_shape_impl(t1, t2);
|
||||
}
|
||||
|
||||
return_type on_error(const shape&, const shape&) const
|
||||
{
|
||||
return std::make_pair(shape_id::unknown_id, shape_id::unknown_id);
|
||||
}
|
||||
};
|
||||
|
||||
TEST(multimethods, static_dispatch)
|
||||
{
|
||||
using return_type = dispatch_tester::return_type;
|
||||
using dispatcher_type = static_dispatcher
|
||||
<
|
||||
dispatch_tester,
|
||||
const shape,
|
||||
mpl::vector<const rectangle, const circle, const triangle>,
|
||||
return_type
|
||||
>;
|
||||
rectangle r;
|
||||
circle c;
|
||||
triangle t;
|
||||
shape* p1 = &r;
|
||||
shape* p2 = &c;
|
||||
shape* p3 = &t;
|
||||
dispatch_tester tester;
|
||||
|
||||
return_type r1 = dispatcher_type::dispatch(*p1, *p2, tester);
|
||||
return_type r2 = dispatcher_type::dispatch(*p1, *p3, tester);
|
||||
return_type r3 = dispatcher_type::dispatch(*p2, *p1, tester);
|
||||
return_type r4 = dispatcher_type::dispatch(*p2, *p3, tester);
|
||||
return_type r5 = dispatcher_type::dispatch(*p3, *p1, tester);
|
||||
return_type r6 = dispatcher_type::dispatch(*p3, *p2, tester);
|
||||
|
||||
EXPECT_EQ(r1, return_type(shape_id::rectangle_id, shape_id::circle_id));
|
||||
EXPECT_EQ(r2, return_type(shape_id::rectangle_id, shape_id::triangle_id));
|
||||
EXPECT_EQ(r3, return_type(shape_id::circle_id, shape_id::rectangle_id));
|
||||
EXPECT_EQ(r4, return_type(shape_id::circle_id, shape_id::triangle_id));
|
||||
EXPECT_EQ(r5, return_type(shape_id::triangle_id, shape_id::rectangle_id));
|
||||
EXPECT_EQ(r6, return_type(shape_id::triangle_id, shape_id::circle_id));
|
||||
}
|
||||
|
||||
TEST(multimethods, static_dispatch_symmetry)
|
||||
{
|
||||
using return_type = dispatch_tester::return_type;
|
||||
using dispatcher_type = static_dispatcher
|
||||
<
|
||||
dispatch_tester,
|
||||
const shape,
|
||||
mpl::vector<const rectangle, const circle, const triangle>,
|
||||
return_type,
|
||||
symmetric_dispatch
|
||||
>;
|
||||
rectangle r;
|
||||
circle c;
|
||||
triangle t;
|
||||
shape* p1 = &r;
|
||||
shape* p2 = &c;
|
||||
shape* p3 = &t;
|
||||
dispatch_tester tester;
|
||||
|
||||
return_type r1 = dispatcher_type::dispatch(*p1, *p2, tester);
|
||||
return_type r2 = dispatcher_type::dispatch(*p1, *p3, tester);
|
||||
return_type r3 = dispatcher_type::dispatch(*p2, *p1, tester);
|
||||
return_type r4 = dispatcher_type::dispatch(*p2, *p3, tester);
|
||||
return_type r5 = dispatcher_type::dispatch(*p3, *p1, tester);
|
||||
return_type r6 = dispatcher_type::dispatch(*p3, *p2, tester);
|
||||
|
||||
EXPECT_EQ(r1, return_type(shape_id::rectangle_id, shape_id::circle_id));
|
||||
EXPECT_EQ(r2, return_type(shape_id::rectangle_id, shape_id::triangle_id));
|
||||
EXPECT_EQ(r3, return_type(shape_id::rectangle_id, shape_id::circle_id));
|
||||
EXPECT_EQ(r4, return_type(shape_id::circle_id, shape_id::triangle_id));
|
||||
EXPECT_EQ(r5, return_type(shape_id::rectangle_id, shape_id::triangle_id));
|
||||
EXPECT_EQ(r6, return_type(shape_id::circle_id, shape_id::triangle_id));
|
||||
}
|
||||
|
||||
template <class D>
|
||||
void test_function_dispatcher()
|
||||
{
|
||||
using dispatcher_type = D;
|
||||
using return_type = dispatch_return_type;
|
||||
dispatcher_type d;
|
||||
d.template insert<const rectangle, const circle>(&dispatch_rectangle_circle);
|
||||
d.template insert<const rectangle, const triangle>(&dispatch_rectangle_triangle);
|
||||
d.template insert<const circle, const rectangle>(&dispatch_circle_rectangle);
|
||||
d.template insert<const circle, const triangle>(&dispatch_circle_triangle);
|
||||
d.template insert<const triangle, const rectangle>(&dispatch_triangle_rectangle);
|
||||
d.template insert<const triangle, const circle>(&dispatch_triangle_circle);
|
||||
|
||||
rectangle r;
|
||||
circle c;
|
||||
triangle t;
|
||||
shape* p1 = &r;
|
||||
shape* p2 = &c;
|
||||
shape* p3 = &t;
|
||||
|
||||
return_type r1 = d.dispatch(*p1, *p2);
|
||||
return_type r2 = d.dispatch(*p1, *p3);
|
||||
return_type r3 = d.dispatch(*p2, *p1);
|
||||
return_type r4 = d.dispatch(*p2, *p3);
|
||||
return_type r5 = d.dispatch(*p3, *p1);
|
||||
return_type r6 = d.dispatch(*p3, *p2);
|
||||
|
||||
EXPECT_EQ(r1, return_type(shape_id::rectangle_id, shape_id::circle_id));
|
||||
EXPECT_EQ(r2, return_type(shape_id::rectangle_id, shape_id::triangle_id));
|
||||
EXPECT_EQ(r3, return_type(shape_id::circle_id, shape_id::rectangle_id));
|
||||
EXPECT_EQ(r4, return_type(shape_id::circle_id, shape_id::triangle_id));
|
||||
EXPECT_EQ(r5, return_type(shape_id::triangle_id, shape_id::rectangle_id));
|
||||
EXPECT_EQ(r6, return_type(shape_id::triangle_id, shape_id::circle_id));
|
||||
}
|
||||
|
||||
TEST(multimethods, function_dispatcher)
|
||||
{
|
||||
using return_type = dispatch_return_type;
|
||||
using dispatcher_type = functor_dispatcher
|
||||
<
|
||||
mpl::vector<const shape, const shape>,
|
||||
return_type
|
||||
>;
|
||||
|
||||
test_function_dispatcher<dispatcher_type>();
|
||||
}
|
||||
|
||||
TEST(multimethods, function_dispatcher_static_cast)
|
||||
{
|
||||
using return_type = dispatch_return_type;
|
||||
using dispatcher_type = functor_dispatcher
|
||||
<
|
||||
mpl::vector<const shape, const shape>,
|
||||
return_type,
|
||||
mpl::vector<>,
|
||||
static_caster
|
||||
>;
|
||||
|
||||
test_function_dispatcher<dispatcher_type>();
|
||||
}
|
||||
|
||||
TEST(multimethods, fast_function_dispatcher)
|
||||
{
|
||||
using return_type = dispatch_return_type;
|
||||
using dispatcher_type = functor_dispatcher
|
||||
<
|
||||
mpl::vector<const shape, const shape>,
|
||||
return_type,
|
||||
mpl::vector<>,
|
||||
static_caster,
|
||||
basic_fast_dispatcher
|
||||
>;
|
||||
|
||||
test_function_dispatcher<dispatcher_type>();
|
||||
}
|
||||
|
||||
template <class D>
|
||||
void test_function_partial_dispatcher()
|
||||
{
|
||||
using dispatcher_type = D;
|
||||
using return_type = dispatch_return_type;
|
||||
dispatcher_type d;
|
||||
d.template insert<const rectangle, const circle>(&partial_dispatch_rectangle_circle);
|
||||
d.template insert<const rectangle, const triangle>(&partial_dispatch_rectangle_triangle);
|
||||
d.template insert<const circle, const rectangle>(&partial_dispatch_circle_rectangle);
|
||||
d.template insert<const circle, const triangle>(&partial_dispatch_circle_triangle);
|
||||
d.template insert<const triangle, const rectangle>(&partial_dispatch_triangle_rectangle);
|
||||
d.template insert<const triangle, const circle>(&partial_dispatch_triangle_circle);
|
||||
|
||||
undispatched_type i;
|
||||
|
||||
rectangle r;
|
||||
circle c;
|
||||
triangle t;
|
||||
shape* p1 = &r;
|
||||
shape* p2 = &c;
|
||||
shape* p3 = &t;
|
||||
|
||||
return_type r1 = d.dispatch(*p1, *p2, i);
|
||||
return_type r2 = d.dispatch(*p1, *p3, i);
|
||||
return_type r3 = d.dispatch(*p2, *p1, i);
|
||||
return_type r4 = d.dispatch(*p2, *p3, i);
|
||||
return_type r5 = d.dispatch(*p3, *p1, i);
|
||||
return_type r6 = d.dispatch(*p3, *p2, i);
|
||||
|
||||
EXPECT_EQ(r1, return_type(shape_id::rectangle_id, shape_id::circle_id));
|
||||
EXPECT_EQ(r2, return_type(shape_id::rectangle_id, shape_id::triangle_id));
|
||||
EXPECT_EQ(r3, return_type(shape_id::circle_id, shape_id::rectangle_id));
|
||||
EXPECT_EQ(r4, return_type(shape_id::circle_id, shape_id::triangle_id));
|
||||
EXPECT_EQ(r5, return_type(shape_id::triangle_id, shape_id::rectangle_id));
|
||||
EXPECT_EQ(r6, return_type(shape_id::triangle_id, shape_id::circle_id));
|
||||
}
|
||||
|
||||
TEST(multimethods, fast_function_partial_dispatcher)
|
||||
{
|
||||
using return_type = dispatch_return_type;
|
||||
using dispatcher_type = functor_dispatcher
|
||||
<
|
||||
mpl::vector<const shape, const shape>,
|
||||
return_type,
|
||||
mpl::vector<const undispatched_type>,
|
||||
static_caster,
|
||||
basic_fast_dispatcher
|
||||
>;
|
||||
|
||||
test_function_partial_dispatcher<dispatcher_type>();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,310 @@
|
|||
/***************************************************************************
|
||||
* Copyright (c) Johan Mabille, Sylvain Corlay and Wolf Vollprecht *
|
||||
* Copyright (c) QuantStack *
|
||||
* *
|
||||
* Distributed under the terms of the BSD 3-Clause License. *
|
||||
* *
|
||||
* The full license is in the file LICENSE, distributed with this software. *
|
||||
****************************************************************************/
|
||||
|
||||
#include "xtl/xoptional.hpp"
|
||||
#include "xtl/xoptional_sequence.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "xtl/xany.hpp"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#ifdef HAVE_NLOHMANN_JSON
|
||||
#include "xtl/xjson.hpp"
|
||||
#endif
|
||||
|
||||
|
||||
namespace xtl
|
||||
{
|
||||
TEST(xoptional, scalar_tests)
|
||||
{
|
||||
// Test uninitialized == missing
|
||||
xoptional<double, bool> v0;
|
||||
ASSERT_FALSE(v0.has_value());
|
||||
|
||||
// Test initialization from value
|
||||
xoptional<double, bool> v1(1.0);
|
||||
ASSERT_TRUE(v1.has_value());
|
||||
ASSERT_EQ(v1.value(), 1.0);
|
||||
|
||||
// Test lvalue closure types
|
||||
double value1 = 3.0;
|
||||
int there = 0;
|
||||
auto opt1 = optional(value1, there);
|
||||
ASSERT_FALSE(opt1.has_value());
|
||||
opt1 = 1.0;
|
||||
ASSERT_TRUE(opt1.has_value());
|
||||
ASSERT_EQ(value1, 1.0);
|
||||
|
||||
// Test rvalue closure type for boolean
|
||||
double value2 = 3.0;
|
||||
auto opt2 = optional(value2, true);
|
||||
opt2 = 2.0;
|
||||
ASSERT_TRUE(opt2.has_value());
|
||||
ASSERT_EQ(value2, 2.0);
|
||||
|
||||
auto ptr_opt2 = &opt2;
|
||||
EXPECT_TRUE(ptr_opt2->has_value());
|
||||
EXPECT_EQ(ptr_opt2->value(), 2.0);
|
||||
}
|
||||
|
||||
TEST(xoptional, string)
|
||||
{
|
||||
xoptional<std::string, bool> opt1;
|
||||
opt1 = "foo";
|
||||
ASSERT_TRUE(opt1.has_value());
|
||||
|
||||
xoptional<std::string, bool> opt2 = "bar";
|
||||
ASSERT_TRUE(opt2.has_value());
|
||||
}
|
||||
|
||||
TEST(xoptional, vector)
|
||||
{
|
||||
xoptional_vector<double> v(3, 2.0);
|
||||
ASSERT_TRUE(v.front().has_value());
|
||||
ASSERT_TRUE(v[0].has_value());
|
||||
ASSERT_EQ(v[0].value(), 2.0);
|
||||
v[1] = missing<double>();
|
||||
ASSERT_FALSE(v[1].has_value());
|
||||
ASSERT_TRUE(v.has_value().front());
|
||||
ASSERT_FALSE(v.has_value()[1]);
|
||||
}
|
||||
|
||||
TEST(xoptional, vector_iteration)
|
||||
{
|
||||
xoptional_vector<double> v(4, 2.0);
|
||||
v[0] = missing<double>();
|
||||
std::vector<double> res;
|
||||
for (auto it = v.cbegin(); it != v.cend(); ++it)
|
||||
{
|
||||
res.push_back(it->value_or(0.0));
|
||||
}
|
||||
std::vector<double> expect = {0.0, 2.0, 2.0, 2.0};
|
||||
ASSERT_TRUE(std::equal(res.begin(), res.end(), expect.begin()));
|
||||
}
|
||||
|
||||
TEST(xoptional, comparison)
|
||||
{
|
||||
ASSERT_TRUE(optional(1.0, true) == 1.0);
|
||||
ASSERT_TRUE(optional(1.0, false) == missing<double>());
|
||||
ASSERT_FALSE(missing<double>() == 1.0);
|
||||
ASSERT_TRUE(missing<double>() != 1.0);
|
||||
}
|
||||
|
||||
TEST(xoptional, vector_comparison)
|
||||
{
|
||||
xoptional_vector<double> v1(4, 2.0);
|
||||
v1[0] = missing<double>();
|
||||
|
||||
xoptional_vector<double> v2(4, 1.0);
|
||||
v2[0] = missing<double>();
|
||||
|
||||
EXPECT_TRUE(v1 == v1);
|
||||
EXPECT_FALSE(v1 == v2);
|
||||
EXPECT_TRUE(v1 != v2);
|
||||
EXPECT_FALSE(v1 != v1);
|
||||
EXPECT_TRUE(v2 < v1);
|
||||
EXPECT_FALSE(v1 < v1);
|
||||
EXPECT_TRUE(v1 <= v1);
|
||||
EXPECT_FALSE(v1 <= v2);
|
||||
EXPECT_TRUE(v1 > v2);
|
||||
EXPECT_FALSE(v2 > v1);
|
||||
EXPECT_TRUE(v1 >= v1);
|
||||
EXPECT_FALSE(v2 >= v1);
|
||||
}
|
||||
|
||||
TEST(xoptional, io)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << missing<int>();
|
||||
ASSERT_EQ(oss.str(), std::string("N/A"));
|
||||
}
|
||||
|
||||
struct implicit_double
|
||||
{
|
||||
implicit_double(double v) : m_value(v) {}
|
||||
double m_value;
|
||||
};
|
||||
|
||||
struct explicit_double
|
||||
{
|
||||
explicit explicit_double(double v) : m_value(v) {}
|
||||
double m_value;
|
||||
};
|
||||
|
||||
struct implicit_bool
|
||||
{
|
||||
implicit_bool(bool b) : m_value(b) {}
|
||||
bool m_value;
|
||||
};
|
||||
|
||||
struct explicit_bool
|
||||
{
|
||||
explicit explicit_bool(bool b) : m_value(b) {}
|
||||
bool m_value;
|
||||
};
|
||||
|
||||
TEST(xoptional, implicit_constructor)
|
||||
{
|
||||
bool res1 = std::is_convertible<double, implicit_double>::value;
|
||||
bool res2 = std::is_convertible<double, explicit_double>::value;
|
||||
EXPECT_TRUE(res1);
|
||||
EXPECT_FALSE(res2);
|
||||
|
||||
bool res3 = std::is_convertible<double, xoptional<implicit_double>>::value;
|
||||
bool res4 = std::is_convertible<double, xoptional<explicit_double>>::value;
|
||||
EXPECT_TRUE(res3);
|
||||
EXPECT_FALSE(res4);
|
||||
|
||||
bool res5 = std::is_convertible<xoptional<double>, xoptional<implicit_double >>::value;
|
||||
bool res6 = std::is_convertible<xoptional<double>, xoptional<explicit_double >>::value;
|
||||
EXPECT_TRUE(res5);
|
||||
EXPECT_FALSE(res6);
|
||||
|
||||
bool res7 = std::is_convertible<xoptional<double, bool>, xoptional<double, implicit_bool>>::value;
|
||||
bool res8 = std::is_convertible<xoptional<double, bool>, xoptional<double, explicit_bool>>::value;
|
||||
EXPECT_TRUE(res7);
|
||||
EXPECT_FALSE(res8);
|
||||
}
|
||||
|
||||
TEST(xoptional, xoptional_proxy)
|
||||
{
|
||||
using optional = xoptional<double, bool>;
|
||||
using optional_ref = xoptional<double&, bool&>;
|
||||
double d1 = 1.2;
|
||||
bool b1 = true;
|
||||
double d2 = 2.3;
|
||||
bool b2 = true;
|
||||
|
||||
optional_ref o1(d1, b1);
|
||||
optional_ref o2(d2, b2);
|
||||
|
||||
auto res1 = o1 + o2;
|
||||
EXPECT_EQ(res1, optional(d1 + d2, true));
|
||||
|
||||
auto res2 = o1 - o2;
|
||||
EXPECT_EQ(res2, optional(d1 - d2, true));
|
||||
|
||||
auto res3 = o1 * o2;
|
||||
EXPECT_EQ(res3, optional(d1 * d2, true));
|
||||
|
||||
auto res4 = o1 / o2;
|
||||
EXPECT_EQ(res4, optional(d1 / d2, true));
|
||||
|
||||
xoptional<bool> res7 = o1 < o2;
|
||||
EXPECT_TRUE(res7.value());
|
||||
|
||||
double d3 = 4.5;
|
||||
bool b3 = true;
|
||||
optional_ref o3(d3, b3);
|
||||
|
||||
auto res8 = fma(o1, o2, o3);
|
||||
EXPECT_EQ(res8, std::fma(d1, d2, d3));
|
||||
|
||||
using optional_int = xoptional<int, bool>;
|
||||
using optional_int_ref = xoptional<int&, bool&>;
|
||||
int i1 = 9;
|
||||
int i2 = 4;
|
||||
|
||||
optional_int_ref oi1(i1, b1);
|
||||
optional_int_ref oi2(i2, b2);
|
||||
|
||||
auto res9 = oi1 % oi2;
|
||||
EXPECT_EQ(res9, optional(i1 % i2, true));
|
||||
|
||||
auto res10 = oi1 & oi2;
|
||||
EXPECT_EQ(res10, optional(i1 & i2, true));
|
||||
|
||||
auto res11 = oi1 | oi2;
|
||||
EXPECT_EQ(res11, optional(i1 | i2, true));
|
||||
|
||||
auto res12 = oi1 ^ oi2;
|
||||
EXPECT_EQ(res12, optional(i1 ^ i2, true));
|
||||
|
||||
auto res13 = ~oi1;
|
||||
EXPECT_EQ(res13, optional(~i1, true));
|
||||
|
||||
auto res5 = oi1 || oi2;
|
||||
EXPECT_EQ(res5, optional(i1 || i2, true));
|
||||
|
||||
auto res6 = oi1 && oi2;
|
||||
EXPECT_EQ(res6, optional(i1 && i2, true));
|
||||
}
|
||||
|
||||
TEST(xoptional, free_functions)
|
||||
{
|
||||
// Test uninitialized == missing
|
||||
xoptional<double, bool> v0;
|
||||
ASSERT_FALSE(has_value(v0));
|
||||
|
||||
// Test initialization from value
|
||||
xoptional<double, bool> v1(1.0);
|
||||
ASSERT_TRUE(has_value(v1));
|
||||
ASSERT_EQ(value(v1), 1.0);
|
||||
|
||||
// Test lvalue closure types
|
||||
double value1 = 3.0;
|
||||
int there = 0;
|
||||
auto opt1 = optional(value1, there);
|
||||
ASSERT_FALSE(has_value(opt1));
|
||||
opt1 = 1.0;
|
||||
ASSERT_TRUE(has_value(opt1));
|
||||
ASSERT_EQ(value1, 1.0);
|
||||
|
||||
// Test rvalue closure type for boolean
|
||||
double value2 = 3.0;
|
||||
auto opt2 = optional(value2, true);
|
||||
value(opt2) = 2.0;
|
||||
ASSERT_TRUE(has_value(opt2));
|
||||
ASSERT_EQ(value2, 2.0);
|
||||
}
|
||||
|
||||
TEST(xoptional, any)
|
||||
{
|
||||
using opt_type = xoptional<const double&, const bool&>;
|
||||
double d = 1.;
|
||||
bool f = true;
|
||||
opt_type o(d, f);
|
||||
xtl::any a(o);
|
||||
|
||||
opt_type res = any_cast<opt_type>(a);
|
||||
EXPECT_EQ(res.value(), o.value());
|
||||
EXPECT_EQ(res.has_value(), o.has_value());
|
||||
}
|
||||
|
||||
#ifdef HAVE_NLOHMANN_JSON
|
||||
TEST(xoptional, json)
|
||||
{
|
||||
xoptional<double> m1 = missing<double>();
|
||||
nlohmann::json j1 = m1;
|
||||
EXPECT_TRUE(j1.is_null());
|
||||
EXPECT_EQ(j1.get<xoptional<double>>(), missing<double>());
|
||||
|
||||
xoptional<double> m2 = 3.0;
|
||||
nlohmann::json j2 = m2;
|
||||
EXPECT_EQ(j2.get<xoptional<double>>(), 3.0);
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST(xoptional, select)
|
||||
{
|
||||
using opt_type = xoptional<double, bool>;
|
||||
using bool_opt_type = xoptional<bool, bool>;
|
||||
auto missing_val = missing<double>();
|
||||
|
||||
EXPECT_EQ(select(true, missing_val, 3.), missing_val);
|
||||
EXPECT_EQ(select(false, missing_val, 3.).value(), 3.);
|
||||
EXPECT_TRUE(select(false, missing_val, 3.).has_value());
|
||||
EXPECT_EQ(select(bool_opt_type(true), 2., 3.).value(), 2.);
|
||||
EXPECT_EQ(select(bool_opt_type(false), 2., 3.).value(), 3.);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
/***************************************************************************
|
||||
* Copyright (c) Johan Mabille, Sylvain Corlay and Wolf Vollprecht *
|
||||
* Copyright (c) QuantStack *
|
||||
* *
|
||||
* Distributed under the terms of the BSD 3-Clause License. *
|
||||
* *
|
||||
* The full license is in the file LICENSE, distributed with this software. *
|
||||
****************************************************************************/
|
||||
|
||||
#include "xtl/xplatform.hpp"
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
namespace xtl
|
||||
{
|
||||
|
||||
TEST(platform, endian)
|
||||
{
|
||||
#if defined(__BYTE_ORDER) && __BYTE_ORDER == __BIG_ENDIAN
|
||||
EXPECT_TRUE(endianness() == endian::big_endian);
|
||||
#endif
|
||||
|
||||
#if defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
EXPECT_TRUE(endianness() == endian::little_endian);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
/***************************************************************************
|
||||
* Copyright (c) Johan Mabille, Sylvain Corlay and Wolf Vollprecht *
|
||||
* Copyright (c) QuantStack *
|
||||
* *
|
||||
* Distributed under the terms of the BSD 3-Clause License. *
|
||||
* *
|
||||
* The full license is in the file LICENSE, distributed with this software. *
|
||||
****************************************************************************/
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include "xtl/xproxy_wrapper.hpp"
|
||||
|
||||
namespace xtl
|
||||
{
|
||||
using double_wrapper = xproxy_wrapper<double>;
|
||||
|
||||
double_wrapper func_double()
|
||||
{
|
||||
return proxy_wrapper(2.5);
|
||||
}
|
||||
|
||||
struct Tester
|
||||
{
|
||||
using value_type = double;
|
||||
|
||||
value_type func() { return 1.; }
|
||||
value_type func() const { return 2.; }
|
||||
};
|
||||
|
||||
using tester_wrapper = xproxy_wrapper<Tester>;
|
||||
|
||||
tester_wrapper func_tester()
|
||||
{
|
||||
return proxy_wrapper(Tester());
|
||||
}
|
||||
|
||||
|
||||
TEST(xproxy_wrapper, fundamental_type)
|
||||
{
|
||||
auto wd = func_double();
|
||||
auto pd = &wd;
|
||||
|
||||
double d1 = wd;
|
||||
double d2 = *pd;
|
||||
EXPECT_EQ(2.5, d1);
|
||||
EXPECT_EQ(2.5, d2);
|
||||
|
||||
wd = 3.5;
|
||||
EXPECT_EQ(3.5, *pd);
|
||||
}
|
||||
|
||||
TEST(xproxy_wrapper, user_type)
|
||||
{
|
||||
auto wu = func_tester();
|
||||
auto pu = &wu;
|
||||
|
||||
using wrapper_type = decltype(wu);
|
||||
using value_type = wrapper_type::value_type;
|
||||
static_assert(std::is_same<value_type, double>::value, "value_type should be double");
|
||||
|
||||
double res = wu.func();
|
||||
double res2 = pu->func();
|
||||
|
||||
EXPECT_EQ(1., res);
|
||||
EXPECT_EQ(1., res2);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,130 @@
|
|||
/***************************************************************************
|
||||
* Copyright (c) Johan Mabille, Sylvain Corlay and Wolf Vollprecht *
|
||||
* Copyright (c) QuantStack *
|
||||
* *
|
||||
* Distributed under the terms of the BSD 3-Clause License. *
|
||||
* *
|
||||
* The full license is in the file LICENSE, distributed with this software. *
|
||||
****************************************************************************/
|
||||
|
||||
#include "xtl/xsequence.hpp"
|
||||
|
||||
#include <array>
|
||||
#include <vector>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
namespace xtl
|
||||
{
|
||||
template <class T, std::size_t N>
|
||||
struct aligned_array
|
||||
: std::array<T, N>
|
||||
{
|
||||
};
|
||||
|
||||
bool result(const std::array<int, 2>& /*lval*/)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool result(std::array<int, 2>&& /*lval*/)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool test(T&& arg)
|
||||
{
|
||||
using shape_type = std::array<int, 2>;
|
||||
return result(xtl::forward_sequence<shape_type, T>(arg));
|
||||
}
|
||||
|
||||
TEST(xsequence, forward_type)
|
||||
{
|
||||
std::array<int, 2> a, b;
|
||||
std::vector<int> c;
|
||||
EXPECT_TRUE(test(std::move(a)));
|
||||
EXPECT_FALSE(test(a));
|
||||
EXPECT_TRUE(test(c));
|
||||
EXPECT_TRUE(test(std::move(c)));
|
||||
}
|
||||
|
||||
template <class R, class T>
|
||||
R test_different_array(T& array)
|
||||
{
|
||||
return xtl::forward_sequence<R, T>(array);
|
||||
}
|
||||
|
||||
TEST(xsequence, different_arrays)
|
||||
{
|
||||
std::array<int, 3> x, y;
|
||||
aligned_array<int, 3> aa, ab;
|
||||
|
||||
auto res1 = test_different_array<aligned_array<int, 3>>(x);
|
||||
auto res2 = test_different_array<aligned_array<int, 3>>(aa);
|
||||
}
|
||||
|
||||
TEST(xsequence, forward)
|
||||
{
|
||||
std::array<int, 2> a = { 1, 2 };
|
||||
std::vector<int> b = { 1, 2 };
|
||||
|
||||
std::vector<int> resa = xtl::forward_sequence<std::vector<int>, decltype(a)>(a);
|
||||
EXPECT_EQ(resa, b);
|
||||
|
||||
std::array<int, 2> resb = xtl::forward_sequence<std::array<int, 2>, decltype(b)>(b);
|
||||
EXPECT_EQ(resb, a);
|
||||
}
|
||||
|
||||
TEST(xsequence, make_sequence)
|
||||
{
|
||||
using vector_type = std::vector<int>;
|
||||
using array_type = std::array<int, 3>;
|
||||
|
||||
std::size_t size = 3u;
|
||||
int init_value = 2;
|
||||
std::initializer_list<int> init_list = { 3, 2, 4 };
|
||||
|
||||
vector_type v0 = xtl::make_sequence<vector_type>(size);
|
||||
EXPECT_EQ(v0.size(), size);
|
||||
|
||||
array_type a0 = xtl::make_sequence<array_type>(size);
|
||||
EXPECT_EQ(a0.size(), size);
|
||||
|
||||
vector_type v1 = xtl::make_sequence<vector_type>(size, init_value);
|
||||
EXPECT_EQ(v1.size(), size);
|
||||
EXPECT_EQ(v1[0], init_value);
|
||||
EXPECT_EQ(v1[1], init_value);
|
||||
EXPECT_EQ(v1[2], init_value);
|
||||
|
||||
array_type a1 = xtl::make_sequence<array_type>(size, init_value);
|
||||
EXPECT_EQ(a1.size(), size);
|
||||
EXPECT_EQ(a1[0], init_value);
|
||||
EXPECT_EQ(a1[1], init_value);
|
||||
EXPECT_EQ(a1[2], init_value);
|
||||
|
||||
vector_type v2 = xtl::make_sequence<vector_type>(init_list);
|
||||
EXPECT_EQ(v2.size(), size);
|
||||
EXPECT_EQ(v2[0], 3);
|
||||
EXPECT_EQ(v2[1], 2);
|
||||
EXPECT_EQ(v2[2], 4);
|
||||
|
||||
array_type a2 = xtl::make_sequence<array_type>(init_list);
|
||||
EXPECT_EQ(a2.size(), size);
|
||||
EXPECT_EQ(a2[0], 3);
|
||||
EXPECT_EQ(a2[1], 2);
|
||||
EXPECT_EQ(a2[2], 4);
|
||||
}
|
||||
|
||||
TEST(xsequence, are_equivalent_sequences)
|
||||
{
|
||||
std::array<size_t, 2> a = {2, 3};
|
||||
std::array<size_t, 2> b = {2, 4};
|
||||
std::array<size_t, 3> c = {2, 4, 4};
|
||||
|
||||
EXPECT_TRUE(xtl::are_equivalent_sequences(a, a) == true);
|
||||
EXPECT_TRUE(xtl::are_equivalent_sequences(a, b) == false);
|
||||
EXPECT_TRUE(xtl::are_equivalent_sequences(a, c) == false);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
/***************************************************************************
|
||||
* Copyright (c) Johan Mabille, Sylvain Corlay and Wolf Vollprecht *
|
||||
* Copyright (c) QuantStack *
|
||||
* *
|
||||
* Distributed under the terms of the BSD 3-Clause License. *
|
||||
* *
|
||||
* The full license is in the file LICENSE, distributed with this software. *
|
||||
****************************************************************************/
|
||||
|
||||
#include "xtl/xsystem.hpp"
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
namespace xtl
|
||||
{
|
||||
TEST(system, executable_path)
|
||||
{
|
||||
std::string exec_path = executable_path();
|
||||
EXPECT_TRUE(!exec_path.empty());
|
||||
}
|
||||
|
||||
TEST(system, prefix_path)
|
||||
{
|
||||
std::string prefix = prefix_path();
|
||||
std::string exec_path = executable_path();
|
||||
|
||||
EXPECT_NE(prefix.size(), exec_path.size());
|
||||
EXPECT_TRUE(std::equal(prefix.cbegin(), prefix.cend(), exec_path.cbegin()));
|
||||
EXPECT_TRUE((exec_path.find("test_xtl") != std::string::npos) || (exec_path.find("test_xsystem") != std::string::npos));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,143 @@
|
|||
/***************************************************************************
|
||||
* Copyright (c) Johan Mabille, Sylvain Corlay and Wolf Vollprecht *
|
||||
* Copyright (c) QuantStack *
|
||||
* *
|
||||
* Distributed under the terms of the BSD 3-Clause License. *
|
||||
* *
|
||||
* The full license is in the file LICENSE, distributed with this software. *
|
||||
****************************************************************************/
|
||||
|
||||
#include "xtl/xtype_traits.hpp"
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
|
||||
namespace xtl
|
||||
{
|
||||
using std::true_type;
|
||||
using std::false_type;
|
||||
|
||||
TEST(xtype_traits, conjunction)
|
||||
{
|
||||
bool res;
|
||||
res = conjunction<>::value;
|
||||
EXPECT_EQ(res, true);
|
||||
res = conjunction<false_type, false_type>::value;
|
||||
EXPECT_EQ(res, false);
|
||||
res = conjunction<false_type, true_type>::value;
|
||||
EXPECT_EQ(res, false);
|
||||
res = conjunction<true_type, false_type>::value;
|
||||
EXPECT_EQ(res, false);
|
||||
res = conjunction<true_type, true_type>::value;
|
||||
EXPECT_EQ(res, true);
|
||||
res = conjunction<true_type, true_type, true_type>::value;
|
||||
EXPECT_EQ(res, true);
|
||||
res = conjunction<true_type, true_type, false_type>::value;
|
||||
EXPECT_EQ(res, false);
|
||||
}
|
||||
|
||||
TEST(xtype_traits, disjunction)
|
||||
{
|
||||
bool res;
|
||||
res = disjunction<>::value;
|
||||
EXPECT_EQ(res, false);
|
||||
res = disjunction<false_type, false_type>::value;
|
||||
EXPECT_EQ(res, false);
|
||||
res = disjunction<false_type, true_type>::value;
|
||||
EXPECT_EQ(res, true);
|
||||
res = disjunction<true_type, false_type>::value;
|
||||
EXPECT_EQ(res, true);
|
||||
res = disjunction<true_type, true_type>::value;
|
||||
EXPECT_EQ(res, true);
|
||||
res = disjunction<true_type, true_type, true_type>::value;
|
||||
EXPECT_EQ(res, true);
|
||||
res = disjunction<true_type, true_type, false_type>::value;
|
||||
EXPECT_EQ(res, true);
|
||||
res = disjunction<false_type, false_type, false_type>::value;
|
||||
EXPECT_EQ(res, false);
|
||||
}
|
||||
|
||||
template <class T, XTL_REQUIRES(xtl::is_integral<T>, xtl::is_signed<T>)>
|
||||
int test_requires(T);
|
||||
|
||||
template <class T, XTL_REQUIRES_IMPL(xtl::is_integral<T>, xtl::is_signed<T>)>
|
||||
int test_requires(T)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <class T, XTL_REQUIRES(xtl::is_integral<T>, xtl::negation<xtl::is_signed<T>>)>
|
||||
int test_requires(T)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
template <class T, XTL_DISALLOW(xtl::is_integral<T>)>
|
||||
int test_requires(T)
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
|
||||
TEST(xtype_traits, requires)
|
||||
{
|
||||
int i = 0;
|
||||
unsigned int ui = 1u;
|
||||
double d = 1.;
|
||||
EXPECT_EQ(test_requires(i), 0);
|
||||
EXPECT_EQ(test_requires(ui), 1);
|
||||
EXPECT_EQ(test_requires(d), 2);
|
||||
}
|
||||
|
||||
template <class T, XTL_EITHER(xtl::is_integral<T>, xtl::is_floating_point<T>)>
|
||||
int test_either_disallow(T)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <class T, XTL_DISALLOW_ONE(xtl::is_integral<T>, xtl::is_floating_point<T>)>
|
||||
int test_either_disallow(T)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
TEST(xtype_traits, either_disallow)
|
||||
{
|
||||
int i = 0;
|
||||
float d = 1.;
|
||||
int* p = &i;
|
||||
EXPECT_EQ(test_either_disallow(i), 0);
|
||||
EXPECT_EQ(test_either_disallow(d), 0);
|
||||
EXPECT_EQ(test_either_disallow(p), 1);
|
||||
}
|
||||
|
||||
TEST(xtype_traits, constify)
|
||||
{
|
||||
bool res = std::is_same<constify_t<int&>, const int&>::value;
|
||||
EXPECT_TRUE(res);
|
||||
|
||||
res = std::is_same<constify_t<const int&>, const int&>::value;
|
||||
EXPECT_TRUE(res);
|
||||
|
||||
res = std::is_same<constify_t<int*>, const int*>::value;
|
||||
EXPECT_TRUE(res);
|
||||
|
||||
res = std::is_same<constify_t<const int*>, const int*>::value;
|
||||
EXPECT_TRUE(res);
|
||||
|
||||
res = std::is_same<constify_t<int>, const int>::value;
|
||||
EXPECT_TRUE(res);
|
||||
|
||||
res = std::is_same<constify_t<const int>, const int>::value;
|
||||
EXPECT_TRUE(res);
|
||||
}
|
||||
|
||||
TEST(xtype_traits, promote_type)
|
||||
{
|
||||
using time_type = std::chrono::system_clock::time_point;
|
||||
EXPECT_TRUE((std::is_same<time_type, promote_type_t<time_type, time_type>>::value));
|
||||
EXPECT_TRUE((std::is_same<int, promote_type_t<unsigned char, unsigned char>>::value));
|
||||
EXPECT_TRUE((std::is_same<std::complex<double>, promote_type_t<unsigned char, std::complex<double>>>::value));
|
||||
EXPECT_TRUE((std::is_same<std::complex<double>, promote_type_t<std::complex<float>, std::complex<double>>>::value));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,228 @@
|
|||
/***************************************************************************
|
||||
* Copyright (c) Johan Mabille, Sylvain Corlay and Wolf Vollprecht *
|
||||
* Copyright (c) QuantStack *
|
||||
* *
|
||||
* Distributed under the terms of the BSD 3-Clause License. *
|
||||
* *
|
||||
* The full license is in the file LICENSE, distributed with this software. *
|
||||
****************************************************************************/
|
||||
|
||||
#include "xtl/xvariant.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "xtl/xtl_config.hpp"
|
||||
|
||||
#ifdef HAVE_NLOHMANN_JSON
|
||||
#include "xtl/xjson.hpp"
|
||||
#endif
|
||||
|
||||
using namespace std::literals;
|
||||
|
||||
namespace xtl
|
||||
{
|
||||
TEST(xvariant, basic)
|
||||
{
|
||||
xtl::variant<int, float> v, w;
|
||||
v = 12;
|
||||
int i = xtl::get<int>(v);
|
||||
EXPECT_EQ(12, i);
|
||||
|
||||
w = xtl::get<int>(v);
|
||||
EXPECT_EQ(12, xtl::get<int>(w));
|
||||
w = xtl::get<0>(v);
|
||||
EXPECT_EQ(12, xtl::get<int>(w));
|
||||
w = v;
|
||||
EXPECT_EQ(12, xtl::get<int>(w));
|
||||
}
|
||||
|
||||
TEST(xvariant, bad_variant_access)
|
||||
{
|
||||
xtl::variant<int, float> v;
|
||||
v = 12;
|
||||
#if defined(XTL_NO_EXCEPTIONS)
|
||||
EXPECT_DEATH_IF_SUPPORTED(xtl::get<float>(v), "");
|
||||
#else
|
||||
EXPECT_THROW(xtl::get<float>(v), xtl::bad_variant_access);
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST(xvariant, converting_constructor)
|
||||
{
|
||||
xtl::variant<std::string> x("abc");
|
||||
x = "def";
|
||||
EXPECT_EQ(std::string("def"), xtl::get<std::string>(x));
|
||||
}
|
||||
|
||||
TEST(xvariant, holds_alternative)
|
||||
{
|
||||
xtl::variant<std::string, bool> y("abc");
|
||||
EXPECT_TRUE(xtl::holds_alternative<bool>(y));
|
||||
y = "xyz"s;
|
||||
EXPECT_TRUE(xtl::holds_alternative<std::string>(y));
|
||||
}
|
||||
|
||||
TEST(xvariant, visit)
|
||||
{
|
||||
using var_t = xtl::variant<int, long, double, std::string>;
|
||||
std::vector<var_t> vec = { 10, 15l, 1.5, "hello" };
|
||||
std::vector<var_t> vec_res(4);
|
||||
for (std::size_t i = 0; i < vec.size(); ++i)
|
||||
{
|
||||
var_t v = vec[i];
|
||||
var_t w = xtl::visit([](auto&& arg) -> var_t {return arg + arg; }, v);
|
||||
vec_res[i] = w;
|
||||
}
|
||||
EXPECT_EQ(20, xtl::get<0>(vec_res[0]));
|
||||
EXPECT_EQ(30l, xtl::get<1>(vec_res[1]));
|
||||
EXPECT_EQ(3., xtl::get<2>(vec_res[2]));
|
||||
EXPECT_EQ("hellohello", xtl::get<3>(vec_res[3]));
|
||||
}
|
||||
|
||||
using variant_ref = xtl::variant<xclosure_wrapper<int&>, xclosure_wrapper<double&>>;
|
||||
|
||||
variant_ref build_test_variant(int& ref)
|
||||
{
|
||||
variant_ref res(closure(ref));
|
||||
return res;
|
||||
}
|
||||
|
||||
const variant_ref build_test_cvariant(int& ref)
|
||||
{
|
||||
variant_ref res(closure(ref));
|
||||
return res;
|
||||
}
|
||||
|
||||
TEST(xvariant, closure_wrapper)
|
||||
{
|
||||
{
|
||||
int i = 2;
|
||||
variant_ref v = closure(i);
|
||||
int& ir = xtl::xget<int&>(v);
|
||||
EXPECT_EQ(&ir, &i);
|
||||
ir = 4;
|
||||
EXPECT_EQ(i, 4);
|
||||
int ir2 = xtl::xget<int&>(v);
|
||||
EXPECT_EQ(ir2, i);
|
||||
|
||||
const int& cir = xtl::xget<const int&>(v);
|
||||
EXPECT_EQ(&cir, &i);
|
||||
}
|
||||
|
||||
{
|
||||
int i = 2;
|
||||
const variant_ref v = closure(i);
|
||||
const int& ir = xtl::xget<int&>(v);
|
||||
EXPECT_EQ(&ir, &i);
|
||||
int ir2 = xtl::xget<int&>(v);
|
||||
EXPECT_EQ(ir2, i);
|
||||
|
||||
const int& cir = xtl::xget<const int&>(v);
|
||||
EXPECT_EQ(&cir, &i);
|
||||
}
|
||||
|
||||
{
|
||||
int i = 2;
|
||||
int& ir = xtl::xget<int&>(build_test_variant(i));
|
||||
EXPECT_EQ(&ir, &i);
|
||||
ir = 4;
|
||||
EXPECT_EQ(i, 4);
|
||||
|
||||
const int& cir = xtl::xget<const int&>(build_test_variant(i));
|
||||
EXPECT_EQ(&cir,&i);
|
||||
}
|
||||
|
||||
{
|
||||
int i = 2;
|
||||
const int& ir = xtl::xget<int&>(build_test_cvariant(i));
|
||||
EXPECT_EQ(&ir, &i);
|
||||
i = 4;
|
||||
EXPECT_EQ(ir, i);
|
||||
|
||||
const int& cir = xtl::xget<const int&>(build_test_cvariant(i));
|
||||
EXPECT_EQ(&cir,&i);
|
||||
}
|
||||
}
|
||||
|
||||
using variant_cref = xtl::variant<xclosure_wrapper<const int&>, xclosure_wrapper<const double&>>;
|
||||
|
||||
variant_cref build_test_variant(const int& ref)
|
||||
{
|
||||
variant_cref res(closure(ref));
|
||||
return res;
|
||||
}
|
||||
|
||||
const variant_cref build_test_cvariant(const int& ref)
|
||||
{
|
||||
variant_cref res(closure(ref));
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
TEST(xvariant, const_closure_wrapper)
|
||||
{
|
||||
{
|
||||
const int i = 2;
|
||||
variant_cref v = closure(i);
|
||||
const int& cir = xtl::xget<const int&>(v);
|
||||
EXPECT_EQ(&cir, &i);
|
||||
}
|
||||
|
||||
{
|
||||
const int i = 2;
|
||||
const variant_cref v = closure(i);
|
||||
const int& cir = xtl::xget<const int&>(v);
|
||||
EXPECT_EQ(&cir, &i);
|
||||
}
|
||||
|
||||
{
|
||||
const int i = 2;
|
||||
const int& cir = xtl::xget<const int&>(build_test_variant(i));
|
||||
EXPECT_EQ(&cir, &i);
|
||||
}
|
||||
|
||||
{
|
||||
const int i = 2;
|
||||
const int& cir = xtl::xget<const int&>(build_test_cvariant(i));
|
||||
EXPECT_EQ(&cir, &i);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(xvariant, overloaded_lambdas)
|
||||
{
|
||||
using var_t = xtl::variant<int, double, std::string>;
|
||||
std::vector<var_t> vec = { 1, 2.5, "hello" };
|
||||
|
||||
bool res = true;
|
||||
|
||||
for (auto& v : vec)
|
||||
{
|
||||
res &= xtl::visit(xtl::make_overload([](int arg) { return arg == 1; },
|
||||
[](double arg) { return arg == 2.5; },
|
||||
[](const std::string& arg) { return arg == "hello"; }),
|
||||
v);
|
||||
}
|
||||
|
||||
EXPECT_TRUE(res);
|
||||
}
|
||||
|
||||
#ifdef HAVE_NLOHMANN_JSON
|
||||
TEST(xvariant, json)
|
||||
{
|
||||
typedef xtl::variant<double, std::string> stringNumType;
|
||||
|
||||
nlohmann::json j1;
|
||||
stringNumType m1 = "Hello";
|
||||
j1["salutation"] = m1;
|
||||
EXPECT_EQ(j1.at("salutation"), "Hello");
|
||||
|
||||
nlohmann::json j2;
|
||||
stringNumType m2 = 3.0;
|
||||
j2["num"] = m2;
|
||||
EXPECT_EQ(j2.at("num"), 3.0);
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
|
@ -0,0 +1,236 @@
|
|||
/***************************************************************************
|
||||
* Copyright (c) Johan Mabille, Sylvain Corlay and Wolf Vollprecht *
|
||||
* Copyright (c) QuantStack *
|
||||
* *
|
||||
* Distributed under the terms of the BSD 3-Clause License. *
|
||||
* *
|
||||
* The full license is in the file LICENSE, distributed with this software. *
|
||||
****************************************************************************/
|
||||
|
||||
#include "xtl/xvisitor.hpp"
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
namespace xtl
|
||||
{
|
||||
class root : public base_visitable<int, false>
|
||||
{
|
||||
public:
|
||||
|
||||
XTL_DEFINE_VISITABLE()
|
||||
};
|
||||
|
||||
class leaf_one : public root
|
||||
{
|
||||
public:
|
||||
|
||||
XTL_DEFINE_VISITABLE()
|
||||
};
|
||||
|
||||
class leaf_two : public root
|
||||
{
|
||||
public:
|
||||
|
||||
XTL_DEFINE_VISITABLE()
|
||||
};
|
||||
|
||||
class acyclic_visitor_tester
|
||||
: public base_visitor
|
||||
, public visitor<mpl::vector<leaf_one, leaf_two>, int, false>
|
||||
{
|
||||
public:
|
||||
|
||||
int visit(leaf_one&) override
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
int visit(leaf_two&) override
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
};
|
||||
|
||||
TEST(visitor, acyclic_visitor)
|
||||
{
|
||||
leaf_one l1;
|
||||
leaf_two l2;
|
||||
root* r1 = &l1;
|
||||
root* r2 = &l2;
|
||||
|
||||
acyclic_visitor_tester t;
|
||||
|
||||
int res1 = r1->accept(t);
|
||||
EXPECT_EQ(res1, 1);
|
||||
|
||||
int res2 = r2->accept(t);
|
||||
EXPECT_EQ(res2, 2);
|
||||
}
|
||||
|
||||
class const_root : public base_visitable<int, true>
|
||||
{
|
||||
public:
|
||||
|
||||
XTL_DEFINE_CONST_VISITABLE()
|
||||
};
|
||||
|
||||
class const_leaf_one : public const_root
|
||||
{
|
||||
public:
|
||||
|
||||
XTL_DEFINE_CONST_VISITABLE()
|
||||
};
|
||||
|
||||
class const_leaf_two : public const_root
|
||||
{
|
||||
public:
|
||||
|
||||
XTL_DEFINE_CONST_VISITABLE()
|
||||
};
|
||||
|
||||
class const_acyclic_visitor_tester
|
||||
: public base_visitor
|
||||
, public visitor<mpl::vector<const_leaf_one, const_leaf_two>, int, true>
|
||||
{
|
||||
public:
|
||||
|
||||
int visit(const const_leaf_one&) override
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
int visit(const const_leaf_two&) override
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
};
|
||||
|
||||
TEST(visitor, const_acyclic_visitor)
|
||||
{
|
||||
const_leaf_one l1;
|
||||
const_leaf_two l2;
|
||||
const_root* r1 = &l1;
|
||||
const_root* r2 = &l2;
|
||||
|
||||
const_acyclic_visitor_tester t;
|
||||
|
||||
int res1 = r1->accept(t);
|
||||
EXPECT_EQ(res1, 1);
|
||||
|
||||
int res2 = r2->accept(t);
|
||||
EXPECT_EQ(res2, 2);
|
||||
}
|
||||
|
||||
class cleaf_one;
|
||||
class cleaf_two;
|
||||
|
||||
class cyclic_visitor_tester
|
||||
: public cyclic_visitor<mpl::vector<cleaf_one, cleaf_two>, int, false>
|
||||
{
|
||||
public:
|
||||
|
||||
int visit(cleaf_one&) override
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
int visit(cleaf_two&) override
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
};
|
||||
|
||||
class croot
|
||||
{
|
||||
public:
|
||||
|
||||
virtual int accept(cyclic_visitor_tester&) = 0;
|
||||
};
|
||||
|
||||
class cleaf_one : public croot
|
||||
{
|
||||
public:
|
||||
|
||||
XTL_DEFINE_CYCLIC_VISITABLE(cyclic_visitor_tester)
|
||||
};
|
||||
|
||||
class cleaf_two : public croot
|
||||
{
|
||||
public:
|
||||
|
||||
XTL_DEFINE_CYCLIC_VISITABLE(cyclic_visitor_tester)
|
||||
};
|
||||
|
||||
TEST(visitor, cyclic_visitor)
|
||||
{
|
||||
cleaf_one l1;
|
||||
cleaf_two l2;
|
||||
croot* r1 = &l1;
|
||||
croot* r2 = &l2;
|
||||
|
||||
cyclic_visitor_tester t;
|
||||
|
||||
int res1 = r1->accept(t);
|
||||
EXPECT_EQ(res1, 1);
|
||||
|
||||
int res2 = r2->accept(t);
|
||||
EXPECT_EQ(res2, 2);
|
||||
}
|
||||
|
||||
class ccleaf_one;
|
||||
class ccleaf_two;
|
||||
|
||||
class ccyclic_visitor_tester
|
||||
: public cyclic_visitor<mpl::vector<ccleaf_one, ccleaf_two>, int, true>
|
||||
{
|
||||
public:
|
||||
|
||||
int visit(const ccleaf_one&) override
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
int visit(const ccleaf_two&) override
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
};
|
||||
|
||||
class ccroot
|
||||
{
|
||||
public:
|
||||
|
||||
virtual int accept(ccyclic_visitor_tester&) const = 0;
|
||||
};
|
||||
|
||||
class ccleaf_one : public ccroot
|
||||
{
|
||||
public:
|
||||
|
||||
XTL_DEFINE_CONST_CYCLIC_VISITABLE(ccyclic_visitor_tester)
|
||||
};
|
||||
|
||||
class ccleaf_two : public ccroot
|
||||
{
|
||||
public:
|
||||
|
||||
XTL_DEFINE_CONST_CYCLIC_VISITABLE(ccyclic_visitor_tester)
|
||||
};
|
||||
|
||||
TEST(visitor, const_cyclic_visitor)
|
||||
{
|
||||
ccleaf_one l1;
|
||||
ccleaf_two l2;
|
||||
ccroot* r1 = &l1;
|
||||
ccroot* r2 = &l2;
|
||||
|
||||
ccyclic_visitor_tester t;
|
||||
|
||||
int res1 = r1->accept(t);
|
||||
EXPECT_EQ(res1, 1);
|
||||
|
||||
int res2 = r2->accept(t);
|
||||
EXPECT_EQ(res2, 2);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
prefix=@CMAKE_INSTALL_PREFIX@
|
||||
includedir=${prefix}/include
|
||||
|
||||
Name: xtl
|
||||
Description: Basic tools (containers, algorithms) used by other quantstack packages.
|
||||
Version: @xtl_VERSION@
|
||||
Cflags: -I${includedir}
|
|
@ -0,0 +1,21 @@
|
|||
############################################################################
|
||||
# Copyright (c) 2017, Sylvain Corlay and Johan Mabille #
|
||||
# #
|
||||
# Distributed under the terms of the BSD 3-Clause License. #
|
||||
# #
|
||||
# The full license is in the file LICENSE, distributed with this software. #
|
||||
############################################################################
|
||||
|
||||
# xtl cmake module
|
||||
# This module sets the following variables in your project::
|
||||
#
|
||||
# xtl_FOUND - true if xtl found on the system
|
||||
# xtl_INCLUDE_DIRS - the directory containing xtl headers
|
||||
# xtl_LIBRARY - empty
|
||||
|
||||
@PACKAGE_INIT@
|
||||
|
||||
if(NOT TARGET @PROJECT_NAME@)
|
||||
include("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake")
|
||||
get_target_property(@PROJECT_NAME@_INCLUDE_DIRS @PROJECT_NAME@ INTERFACE_INCLUDE_DIRECTORIES)
|
||||
endif()
|
Loading…
Reference in New Issue