Import Upstream version 0.7.2

This commit is contained in:
rtlhq 2023-01-30 20:50:25 +08:00
commit 06f61af8c9
96 changed files with 29094 additions and 0 deletions

37
.appveyor.yml Normal file
View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

8
.github/PULL_REQUEST_TEMPLATE.md vendored Normal file
View File

@ -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

52
.gitignore vendored Normal file
View File

@ -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

17
.releash.py Normal file
View File

@ -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))

160
CMakeLists.txt Normal file
View File

@ -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/")

30
LICENSE Normal file
View File

@ -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.

71
README.md Normal file
View File

@ -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.

8
azure-pipelines.yml Normal file
View File

@ -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

13
docs/Doxyfile Normal file
View File

@ -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

192
docs/Makefile Normal file
View File

@ -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."

7
docs/environment.yml Normal file
View File

@ -0,0 +1,7 @@
name: xtl-docs
channels:
- conda-forge
dependencies:
- breathe==4.16.0

264
docs/make.bat Normal file
View File

@ -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

View File

@ -0,0 +1,4 @@
.wy-nav-content{
max-width: 1000px;
margin: auto;
}

115
docs/source/basic_types.rst Normal file
View File

@ -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

View File

@ -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

437
docs/source/changelog.rst Normal file
View File

@ -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)

493
docs/source/cmake.svg Normal file
View File

@ -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

1
docs/source/conda.svg Normal file
View File

@ -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

38
docs/source/conf.py Normal file
View File

@ -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'

View File

@ -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

86
docs/source/debian.svg Normal file
View File

@ -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

View File

@ -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

50
docs/source/index.rst Normal file
View File

@ -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

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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

30
docs/source/releasing.rst Normal file
View File

@ -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.

61
docs/source/spack.svg Normal file
View File

@ -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

70
docs/source/xtl.svg Normal file
View File

@ -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

6
environment-dev.yml Normal file
View File

@ -0,0 +1,6 @@
name: xtl
channels:
- conda-forge
dependencies:
- cmake
- nlohmann_json

476
include/xtl/xany.hpp Normal file
View File

@ -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

77
include/xtl/xbase64.hpp Normal file
View File

@ -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

435
include/xtl/xclosure.hpp Normal file
View File

@ -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

1361
include/xtl/xcomplex.hpp Normal file

File diff suppressed because it is too large Load Diff

View File

@ -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

View File

@ -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

View File

@ -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

208
include/xtl/xhash.hpp Normal file
View File

@ -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

View File

@ -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

View File

@ -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

98
include/xtl/xjson.hpp Normal file
View File

@ -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

View File

@ -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

View File

@ -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

640
include/xtl/xmeta_utils.hpp Normal file
View File

@ -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

View File

@ -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

1331
include/xtl/xoptional.hpp Normal file

File diff suppressed because it is too large Load Diff

View File

@ -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

View File

@ -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

42
include/xtl/xplatform.hpp Normal file
View File

@ -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

View File

@ -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

215
include/xtl/xsequence.hpp Normal file
View File

@ -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

21
include/xtl/xspan.hpp Normal file
View File

@ -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

778
include/xtl/xspan_impl.hpp Normal file
View File

@ -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

114
include/xtl/xsystem.hpp Normal file
View File

@ -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

View File

@ -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

View File

@ -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

206
include/xtl/xvariant.hpp Normal file
View File

@ -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

195
include/xtl/xvisitor.hpp Normal file
View File

@ -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

2
readthedocs.yml Normal file
View File

@ -0,0 +1,2 @@
conda:
file: docs/environment.yml

175
test/CMakeLists.txt Normal file
View File

@ -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)

24
test/copyGTest.cmake.in Normal file
View File

@ -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 ""
)

View File

@ -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 ""
)

40
test/test_xbase64.cpp Normal file
View File

@ -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

159
test/test_xclosure.cpp Normal file
View File

@ -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);
}
}

329
test/test_xcomplex.cpp Normal file
View File

@ -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);
}
}

View File

@ -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.);
}
}

View File

@ -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);
}
}

22
test/test_xfunctional.cpp Normal file
View File

@ -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.);
}
}

46
test/test_xhalf_float.cpp Normal file
View File

@ -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

177
test/test_xhash.cpp Normal file
View File

@ -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)));
}
}

View File

@ -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());
}
}

View File

@ -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);
}
}

623
test/test_xmasked_value.cpp Normal file
View File

@ -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.);
}
}

320
test/test_xmeta_utils.cpp Normal file
View File

@ -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);
}
}

319
test/test_xmultimethods.cpp Normal file
View File

@ -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>();
}
}

310
test/test_xoptional.cpp Normal file
View File

@ -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.);
}
}

28
test/test_xplatform.cpp Normal file
View File

@ -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
}
}

View File

@ -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);
}
}

130
test/test_xsequence.cpp Normal file
View File

@ -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);
}
}

31
test/test_xsystem.cpp Normal file
View File

@ -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));
}
}

143
test/test_xtype_traits.cpp Normal file
View File

@ -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));
}
}

228
test/test_xvariant.cpp Normal file
View File

@ -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
}

236
test/test_xvisitor.cpp Normal file
View File

@ -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);
}
}

7
xtl.pc.in Normal file
View File

@ -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}

21
xtlConfig.cmake.in Normal file
View File

@ -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()