[
  {
    "path": ".appveyor.yml",
    "content": "build: false\n\nos: Visual Studio 2015\n\nplatform:\n  - x64\n\nenvironment:\n  matrix:\n    - MINICONDA: C:\\xframe-conda\n\ninit:\n  - \"ECHO %MINICONDA%\"\n  - C:\\\"Program Files (x86)\"\\\"Microsoft Visual Studio 14.0\"\\VC\\vcvarsall.bat %PLATFORM%\n  - ps: if($env:Platform -eq \"x64\"){Start-FileDownload 'http://repo.continuum.io/miniconda/Miniconda3-latest-Windows-x86_64.exe' C:\\Miniconda.exe; echo \"Done\"}\n  - ps: if($env:Platform -eq \"x86\"){Start-FileDownload 'http://repo.continuum.io/miniconda/Miniconda3-latest-Windows-x86.exe' C:\\Miniconda.exe; echo \"Done\"}\n  - cmd: C:\\Miniconda.exe /S /D=C:\\xframe-conda\n  - \"set PATH=%MINICONDA%;%MINICONDA%\\\\Scripts;%MINICONDA%\\\\Library\\\\bin;%PATH%\"\n\ninstall:\n  - conda config --set always_yes yes --set changeps1 no\n  - conda update -q conda\n  - conda info -a\n  - conda env create --file environment-dev.yml\n  - CALL conda.bat activate xframe\n  - cmake -G \"NMake Makefiles\" -D CMAKE_INSTALL_PREFIX=%MINICONDA%\\\\LIBRARY -DDOWNLOAD_GTEST=ON .\n  - nmake test_xframe\n  - cd test\n\nbuild_script:\n  - .\\test_xframe\n"
  },
  {
    "path": ".azure-pipelines/azure-pipelines-linux-clang.yml",
    "content": "jobs:\n  - job: 'Linux_0'\n    strategy:\n      matrix:\n        clang_4:\n          llvm_version: '4.0'\n        clang_5:\n          llvm_version: '5.0'\n        clang_6:\n          llvm_version: '6.0'\n        clang_7:\n          llvm_version: '7'\n        clang_8:\n          llvm_version: '8'\n        clang_9:\n          llvm_version: '9'\n        clang_10:\n          llvm_version: '10'\n    pool:\n      vmImage: ubuntu-16.04\n    variables:\n      CC: clang-$(llvm_version)\n      CXX: clang++-$(llvm_version)\n    timeoutInMinutes: 360\n    steps:\n\n      - script: |\n          sudo add-apt-repository ppa:ubuntu-toolchain-r/test\n          if [[ $(llvm_version) == '4.0' || $(llvm_version) == '5.0' ]]; then\n            sudo apt-get update\n            sudo apt-get --no-install-suggests --no-install-recommends install gcc-4.9 clang-$(llvm_version)\n          else\n            LLVM_VERSION=$(llvm_version)\n            get -O - http://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -\n            sudo add-apt-repository \"deb http://apt.llvm.org/xenial/ llvm-toolchain-xenial-$LLVM_VERSION main\"\n            sudo apt-get update\n            sudo apt-get --no-install-suggests --no-install-recommends install clang-$(llvm_version)\n          fi\n        displayName: Install build toolchain\n\n      - bash: echo \"##vso[task.prependpath]$CONDA/bin\"\n        displayName: Add conda to PATH\n\n      - template: unix-build.yml\n"
  },
  {
    "path": ".azure-pipelines/azure-pipelines-linux-gcc.yml",
    "content": "jobs:\n  - job: 'Linux_1'\n    strategy:\n      matrix:\n        gcc_4:\n          gcc_version: '4.9'\n        gcc_5:\n          gcc_version: '5'\n        gcc_6:\n          gcc_version: '6'\n        gcc_7:\n          gcc_version: '7'\n        gcc_8:\n          gcc_version: '8'\n        gcc_9:\n          gcc_version: '9'\n    pool:\n      vmImage: ubuntu-16.04\n    variables:\n      CC: gcc-$(gcc_version)\n      CXX: g++-$(gcc_version)\n    timeoutInMinutes: 360\n    steps:\n\n      - script: |\n          if [[ $(gcc_version) == '4.9' || $(gcc_version) == '6' ]]; then\n            sudo add-apt-repository ppa:ubuntu-toolchain-r/test\n            sudo apt-get update\n            sudo apt-get --no-install-suggests --no-install-recommends install g++-$(gcc_version)\n          fi\n        displayName: Install build toolchain\n          \n      - bash: echo \"##vso[task.prependpath]$CONDA/bin\"\n        displayName: Add conda to PATH\n\n      - template: unix-build.yml\n\n"
  },
  {
    "path": ".azure-pipelines/azure-pipelines-osx.yml",
    "content": "jobs:\n  - job: 'OSX'\n    strategy:\n      matrix:\n        macOS_10_14:\n          image_name: 'macOS-10.14'\n        macOS_10_15:\n          image_name: 'macOS-10.15'\n    pool:\n      vmImage: $(image_name)\n    variables:\n        CC: clang\n        CXX: clang++\n    timeoutInMinutes: 360\n    steps:\n      - script: |\n          echo \"Removing homebrew for Azure to avoid conflicts with conda\"\n          curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/uninstall > ~/uninstall_homebrew\n          chmod +x ~/uninstall_homebrew\n          ~/uninstall_homebrew -f -q\n        displayName: Remove homebrew\n\n      - bash: |\n          echo \"##vso[task.prependpath]$CONDA/bin\"\n          sudo chown -R $USER $CONDA\n        displayName: Add conda to PATH\n\n      - template: unix-build.yml\n"
  },
  {
    "path": ".azure-pipelines/unix-build.yml",
    "content": "steps:\n  - script: |\n      conda config --set always_yes yes --set changeps1 no\n      conda update -q conda\n      conda env create --file environment-dev.yml\n      source activate xframe\n\n  - script: |\n      source activate xframe\n      mkdir build\n      cd build\n      cmake -DCMAKE_INSTALL_PREFIX=$CONDA_PREFIX -DDOWNLOAD_GTEST=ON $(Build.SourcesDirectory)\n    displayName: Configure xframe\n    workingDirectory: $(Build.BinariesDirectory)\n\n  - script: |\n      source activate xxframe\n      make -j2 test_xframe\n    displayName: Build xframe\n    workingDirectory: $(Build.BinariesDirectory)/build\n\n  - script: |\n      source activate xframe\n      cd test\n      ./test_xframe\n    displayName: Test xframe\n    workingDirectory: $(Build.BinariesDirectory)/build/test\n          \n"
  },
  {
    "path": ".gitignore",
    "content": "# Prerequisites\n*.d\n\n# Compiled Object files\n*.slo\n*.lo\n*.o\n*.obj\n\n# Precompiled Headers\n*.gch\n*.pch\n\n# Compiled Dynamic libraries\n*.so\n*.dylib\n*.dll\n\n# Compiled Static libraries\n*.lai\n*.la\n*.a\n*.lib\n\n# Executables\n*.exe\n*.out\n*.app\n\n# Vim tmp files\n*.swp\n\n# Build directory\nbuild/\n\n# Test build artefacts\ntest/test_xtensor\ntest/CMakeCache.txt\ntest/Makefile\ntest/CMakeFiles/\ntest/cmake_install.cmake\n\n# Documentation build artefacts\ndocs/CMakeCache.txt\ndocs/xml/\ndocs/build/\n\n# Jupyter artefacts\n.ipynb_checkpoints/\n\n# Generated files\n*.pc\n"
  },
  {
    "path": ".travis.yml",
    "content": "language: cpp\ndist: xenial\nmatrix:\n  include:\n    - os: linux\n      addons:\n        apt:\n          sources:\n            - ubuntu-toolchain-r-test\n          packages:\n            - g++-4.9\n      env: COMPILER=gcc GCC=4.9\n    - os: linux\n      addons:\n        apt:\n          sources:\n            - ubuntu-toolchain-r-test\n          packages:\n            - g++-5\n      env: COMPILER=gcc GCC=5\n    - os: linux\n      addons:\n        apt:\n          sources:\n            - ubuntu-toolchain-r-test\n          packages:\n            - g++-6\n      env: COMPILER=gcc GCC=6\n    - os: linux\n      addons:\n        apt:\n          sources:\n            - ubuntu-toolchain-r-test\n          packages:\n            - g++-7\n      env: COMPILER=gcc GCC=7\n    - os: linux\n      addons:\n        apt:\n          sources:\n            - ubuntu-toolchain-r-test\n            - llvm-toolchain-xenial-4.0\n          packages:\n            - g++-4.9\n            - clang-4.0\n      env: COMPILER=clang CLANG=4.0\n    - os: linux\n      addons:\n        apt:\n          sources:\n            - ubuntu-toolchain-r-test\n            - llvm-toolchain-xenial-5.0\n          packages:\n            - g++-4.9\n            - clang-5.0\n      env: COMPILER=clang CLANG=5.0\n    - os: linux\n      addons:\n        apt:\n          sources:\n            - ubuntu-toolchain-r-test\n            - llvm-toolchain-xenial-6.0\n          packages:\n            - clang-6.0\n      env: COMPILER=clang CLANG=6.0\n    - os: osx\n      osx_image: xcode8\n      compiler: clang\nenv:\n  global:\n    - MINCONDA_VERSION=\"latest\"\n    - MINCONDA_LINUX=\"Linux-x86_64\"\n    - MINCONDA_OSX=\"MacOSX-x86_64\"\nbefore_install:\n    - |\n      # Configure build variables\n      if [[ \"$TRAVIS_OS_NAME\" == \"linux\" ]]; then\n        if [[ \"$COMPILER\" == \"gcc\" ]]; then\n          export CXX=g++-$GCC CC=gcc-$GCC;\n        fi\n        if [[ \"$COMPILER\" == \"clang\" ]]; then\n          export CXX=clang++-$CLANG CC=clang-$CLANG;\n        fi\n      elif [[ \"$TRAVIS_OS_NAME\" == \"osx\" ]]; then\n        export CXX=clang++ CC=clang;\n      fi\ninstall:\n    # Define the version of miniconda to download\n    - if [[ \"$TRAVIS_OS_NAME\" == \"linux\" ]]; then\n        MINCONDA_OS=$MINCONDA_LINUX;\n      elif [[ \"$TRAVIS_OS_NAME\" == \"osx\" ]]; then\n        MINCONDA_OS=$MINCONDA_OSX;\n      fi\n    - wget \"http://repo.continuum.io/miniconda/Miniconda3-$MINCONDA_VERSION-$MINCONDA_OS.sh\" -O miniconda.sh;\n    - bash miniconda.sh -b -p $HOME/miniconda\n    - export PATH=\"$HOME/miniconda/bin:$PATH\"\n    - hash -r\n    - conda config --set always_yes yes --set changeps1 no\n    # The 2 following lines are a workaround to https://github.com/conda/conda/issues/9337\n    - pip uninstall -y setuptools\n    - conda install setuptools\n    - conda update -q conda\n    - conda install cmake -c conda-forge\n    - conda install xtensor=0.21.4 -c conda-forge\n    # Testing\n    - mkdir build\n    - cd build\n    - cmake -DDOWNLOAD_GTEST=ON ..;\n    - make -j2 test_xframe\n    - cd test\nscript:\n    - ./test_xframe\n"
  },
  {
    "path": "CMakeLists.txt",
    "content": "############################################################################\n# Copyright (c) Johan Mabille and Sylvain Corlay                           #\n# Copyright (c) QuantStack                                                 #\n#                                                                          #\n# Distributed under the terms of the BSD 3-Clause License.                 #\n#                                                                          #\n# The full license is in the file LICENSE, distributed with this software. #\n############################################################################\n\ncmake_minimum_required(VERSION 3.1)\nproject(xframe)\n\nset(XFRAME_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/include)\n\n# Versionning\n# ===========\n\nfile(STRINGS \"${XFRAME_INCLUDE_DIR}/xframe/xframe_config.hpp\" xframe_version_defines\n    REGEX \"#define XFRAME_VERSION_(MAJOR|MINOR|PATCH)\")\nforeach(ver ${xframe_version_defines})\n    if(ver MATCHES \"#define XFRAME_VERSION_(MAJOR|MINOR|PATCH) +([^ ]+)$\")\n        set(XFRAME_VERSION_${CMAKE_MATCH_1} \"${CMAKE_MATCH_2}\" CACHE INTERNAL \"\")\n    endif()\nendforeach()\nset(${PROJECT_NAME}_VERSION\n    ${XFRAME_VERSION_MAJOR}.${XFRAME_VERSION_MINOR}.${XFRAME_VERSION_PATCH})\nmessage(STATUS \"xframe v${${PROJECT_NAME}_VERSION}\")\n\n# Dependencies\n# ============\n\nfind_package(xtensor REQUIRED)\ninclude_directories(${xtensor_INCLUDE_DIRS})\n\nfind_package(xtl REQUIRED)\ninclude_directories(${xtl_INCLUDE_DIRS})\n\n# Build\n# =====\n\nset(XFRAME_HEADERS\n    ${XFRAME_INCLUDE_DIR}/xframe/xaxis.hpp\n    ${XFRAME_INCLUDE_DIR}/xframe/xaxis_base.hpp\n    ${XFRAME_INCLUDE_DIR}/xframe/xaxis_default.hpp\n    ${XFRAME_INCLUDE_DIR}/xframe/xaxis_expression_leaf.hpp\n    ${XFRAME_INCLUDE_DIR}/xframe/xaxis_function.hpp\n    ${XFRAME_INCLUDE_DIR}/xframe/xaxis_index_slice.hpp\n    ${XFRAME_INCLUDE_DIR}/xframe/xaxis_label_slice.hpp\n    ${XFRAME_INCLUDE_DIR}/xframe/xaxis_math.hpp\n    ${XFRAME_INCLUDE_DIR}/xframe/xaxis_meta.hpp\n    ${XFRAME_INCLUDE_DIR}/xframe/xaxis_scalar.hpp\n    ${XFRAME_INCLUDE_DIR}/xframe/xaxis_variant.hpp\n    ${XFRAME_INCLUDE_DIR}/xframe/xaxis_view.hpp\n    ${XFRAME_INCLUDE_DIR}/xframe/xcoordinate.hpp\n    ${XFRAME_INCLUDE_DIR}/xframe/xcoordinate_base.hpp\n    ${XFRAME_INCLUDE_DIR}/xframe/xcoordinate_chain.hpp\n    ${XFRAME_INCLUDE_DIR}/xframe/xcoordinate_expanded.hpp\n    ${XFRAME_INCLUDE_DIR}/xframe/xcoordinate_system.hpp\n    ${XFRAME_INCLUDE_DIR}/xframe/xcoordinate_view.hpp\n    ${XFRAME_INCLUDE_DIR}/xframe/xdimension.hpp\n    ${XFRAME_INCLUDE_DIR}/xframe/xdynamic_variable_impl.hpp\n    ${XFRAME_INCLUDE_DIR}/xframe/xdynamic_variable.hpp\n    ${XFRAME_INCLUDE_DIR}/xframe/xexpand_dims_view.hpp\n    ${XFRAME_INCLUDE_DIR}/xframe/xframe_config.hpp\n    ${XFRAME_INCLUDE_DIR}/xframe/xframe_expression.hpp\n    ${XFRAME_INCLUDE_DIR}/xframe/xframe_trace.hpp\n    ${XFRAME_INCLUDE_DIR}/xframe/xframe_utils.hpp\n    ${XFRAME_INCLUDE_DIR}/xframe/xio.hpp\n    ${XFRAME_INCLUDE_DIR}/xframe/xnamed_axis.hpp\n    ${XFRAME_INCLUDE_DIR}/xframe/xreindex_view.hpp\n    ${XFRAME_INCLUDE_DIR}/xframe/xreindex_data.hpp\n    ${XFRAME_INCLUDE_DIR}/xframe/xselecting.hpp\n    ${XFRAME_INCLUDE_DIR}/xframe/xsequence_view.hpp\n    ${XFRAME_INCLUDE_DIR}/xframe/xvariable.hpp\n    ${XFRAME_INCLUDE_DIR}/xframe/xvariable_assign.hpp\n    ${XFRAME_INCLUDE_DIR}/xframe/xvariable_base.hpp\n    ${XFRAME_INCLUDE_DIR}/xframe/xvariable_function.hpp\n    ${XFRAME_INCLUDE_DIR}/xframe/xvariable_masked_view.hpp\n    ${XFRAME_INCLUDE_DIR}/xframe/xvariable_math.hpp\n    ${XFRAME_INCLUDE_DIR}/xframe/xvariable_meta.hpp\n    ${XFRAME_INCLUDE_DIR}/xframe/xvariable_scalar.hpp\n    ${XFRAME_INCLUDE_DIR}/xframe/xvariable_view.hpp\n    ${XFRAME_INCLUDE_DIR}/xframe/xvector_variant.hpp\n)\n\nOPTION(BUILD_TESTS \"xframe test suite\" OFF)\nOPTION(DOWNLOAD_GTEST \"build gtest from downloaded sources\" OFF)\n\nif(DOWNLOAD_GTEST OR GTEST_SRC_DIR)\n    set(BUILD_TESTS ON)\nendif()\n\nif(BUILD_TESTS)\n    add_subdirectory(test)\nendif()\n\n# Installation\n# ============\n\ninclude(GNUInstallDirs)\ninclude(CMakePackageConfigHelpers)\n\ninstall(FILES ${XFRAME_HEADERS}\n        DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/xframe)\n\nset(XFRAME_CMAKECONFIG_INSTALL_DIR \"${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}\" CACHE\n    STRING \"install path for xframeConfig.cmake\")\n\nconfigure_package_config_file(${PROJECT_NAME}Config.cmake.in\n                              \"${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake\"\n                              INSTALL_DESTINATION ${XFRAME_CMAKECONFIG_INSTALL_DIR})\n\n# xframe is header-only and does not depend on the architecture.\n# Remove CMAKE_SIZEOF_VOID_P from xframeConfigVersion.cmake so that an xframeConfig.cmake\n# generated for a 64 bit target can be used for 32 bit targets and vice versa.\nset(_XFRAME_CMAKE_SIZEOF_VOID_P ${CMAKE_SIZEOF_VOID_P})\nunset(CMAKE_SIZEOF_VOID_P)\nwrite_basic_package_version_file(${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake\n                                 VERSION ${${PROJECT_NAME}_VERSION}\n                                 COMPATIBILITY AnyNewerVersion)\nset(CMAKE_SIZEOF_VOID_P ${_XFRAME_CMAKE_SIZEOF_VOID_P})\ninstall(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake\n              ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake\n        DESTINATION ${XFRAME_CMAKECONFIG_INSTALL_DIR})\n\n\nconfigure_file(${PROJECT_NAME}.pc.in\n        \"${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc\"\n        @ONLY)\ninstall(FILES \"${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc\"\n        DESTINATION \"${CMAKE_INSTALL_LIBDIR}/pkgconfig/\")\n"
  },
  {
    "path": "LICENSE",
    "content": "BSD 3-Clause License\n\nCopyright (c) 2017, Johan Mabille, Sylvain Corlay, Wolf Vollprecht and\n                    Martin Renou\nCopyright (c) 2017, QuantStack\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n* Redistributions of source code must retain the above copyright notice, this\n  list of conditions and the following disclaimer.\n\n* Redistributions in binary form must reproduce the above copyright notice,\n  this list of conditions and the following disclaimer in the documentation\n  and/or other materials provided with the distribution.\n\n* Neither the name of the copyright holder nor the names of its\n  contributors may be used to endorse or promote products derived from\n  this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\nAND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\nIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE\nFOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\nDAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\nSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\nCAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\nOR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\nOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
  },
  {
    "path": "README.md",
    "content": "# ![xframe](docs/source/xframe.svg)\n\n[![Travis](https://travis-ci.org/xtensor-stack/xframe.svg?branch=master)](https://travis-ci.org/xtensor-stack/xframe)\n[![Appveyor](https://ci.appveyor.com/api/projects/status/nhjtyvkefhyo26v5?svg=true)](https://ci.appveyor.com/project/xtensor-stack/xframe)\n[![Documentation](http://readthedocs.org/projects/xframe/badge/?version=latest)](https://xframe.readthedocs.io/en/latest/?badge=latest)\n[![Binder](https://img.shields.io/badge/launch-binder-brightgreen.svg)](https://mybinder.org/v2/gh/xtensor-stack/xframe/stable?filepath=notebooks%2Fxframe.ipynb)\n[![Zulip](https://img.shields.io/badge/social_chat-zulip-blue.svg)](https://xtensor.zulipchat.com/#narrow/channel/539553-Ask-anything)\n\n## Introduction\n\n**xframe is an early developer preview, and is not suitable for general usage yet. Features and implementation are subject to change.**\n\n`xframe` is a dataframe for C++, based on [xtensor](https://github.com/xtensor-stack/xtensor) and [xtl](https://github.com/xtensor-stack/xtl).\n\nFor more information on using `xframe`, check out the reference documentation\n\nhttps://xframe.readthedocs.io/\n\n# Installation\n\n## Package managers\n\nWe provide a package for the mamba (or conda) package manager:\n\n```\nmamba install -c conda-forge xtensor\n```\n\n## Dependencies\n\n`xframe` depends on the [xtensor](https://github.com/xtensor-stack/xtensor) library:\n\n|  xframe  |  xtensor  |\n|----------|-----------|\n|  master  |  ^0.21.4  |\n|   0.3.0  |  ^0.21.4  |\n|   0.2.0  |  ^0.20.0  |\n|   0.1.0  |  ^0.19.1  |\n|   0.0.2  |  ^0.19.1  |\n|   0.0.1  |  ^0.19.1  |\n\n## License\n\nWe use a shared copyright model that enables all contributors to maintain the\ncopyright on their contributions.\n\nThis software is licensed under the BSD-3-Clause license. See the [LICENSE](LICENSE) file for details.\n"
  },
  {
    "path": "azure-pipelines.yml",
    "content": "trigger:\n  - master\n\njobs:\n  - template: ./.azure-pipelines/azure-pipelines-linux-clang.yml\n  - template: ./.azure-pipelines/azure-pipelines-linux-gcc.yml\n  - template: ./.azure-pipelines/azure-pipelines-osx.yml\n\n"
  },
  {
    "path": "docs/Doxyfile",
    "content": "PROJECT_NAME      = \"xframe\"\nXML_OUTPUT        = xml\nINPUT             = ../include\nGENERATE_LATEX    = NO\nGENERATE_MAN      = NO\nGENERATE_RTF      = NO\nCASE_SENSE_NAMES  = NO\nGENERATE_HTML     = NO\nGENERATE_XML      = YES\nRECURSIVE         = YES\nQUIET             = YES\nJAVADOC_AUTOBRIEF = YES\nWARN_IF_UNDOCUMENTED = NO\nMACRO_EXPANSION = YES\n"
  },
  {
    "path": "docs/Makefile",
    "content": "# You can set these variables from the command line.\nSPHINXOPTS    =\nSPHINXBUILD   = sphinx-build\nPAPER         =\nBUILDDIR      = build\n\n# User-friendly check for sphinx-build\nifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1)\n$(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/)\nendif\n\n# Internal variables.\nPAPEROPT_a4     = -D latex_paper_size=a4\nPAPEROPT_letter = -D latex_paper_size=letter\nALLSPHINXOPTS   = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source\n# the i18n builder cannot share the environment and doctrees with the others\nI18NSPHINXOPTS  = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source\n\n.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest coverage gettext api\n\ndefault: html\n\nhelp:\n\t@echo \"Please use \\`make <target>' where <target> is one of\"\n\t@echo \"  html       to make standalone HTML files\"\n\t@echo \"  dirhtml    to make HTML files named index.html in directories\"\n\t@echo \"  singlehtml to make a single large HTML file\"\n\t@echo \"  pickle     to make pickle files\"\n\t@echo \"  json       to make JSON files\"\n\t@echo \"  htmlhelp   to make HTML files and a HTML help project\"\n\t@echo \"  qthelp     to make HTML files and a qthelp project\"\n\t@echo \"  applehelp  to make an Apple Help Book\"\n\t@echo \"  devhelp    to make HTML files and a Devhelp project\"\n\t@echo \"  epub       to make an epub\"\n\t@echo \"  latex      to make LaTeX files, you can set PAPER=a4 or PAPER=letter\"\n\t@echo \"  latexpdf   to make LaTeX files and run them through pdflatex\"\n\t@echo \"  latexpdfja to make LaTeX files and run them through platex/dvipdfmx\"\n\t@echo \"  text       to make text files\"\n\t@echo \"  man        to make manual pages\"\n\t@echo \"  texinfo    to make Texinfo files\"\n\t@echo \"  info       to make Texinfo files and run them through makeinfo\"\n\t@echo \"  gettext    to make PO message catalogs\"\n\t@echo \"  changes    to make an overview of all changed/added/deprecated items\"\n\t@echo \"  xml        to make Docutils-native XML files\"\n\t@echo \"  pseudoxml  to make pseudoxml-XML files for display purposes\"\n\t@echo \"  linkcheck  to check all external links for integrity\"\n\t@echo \"  doctest    to run all doctests embedded in the documentation (if enabled)\"\n\t@echo \"  coverage   to run coverage check of the documentation (if enabled)\"\n\nclean:\n\trm -rf $(BUILDDIR)/*\n\trm -rf xml\n\nhtml:\n\tdoxygen\n\t$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html\n\t@echo\n\t@echo \"Build finished. The HTML pages are in $(BUILDDIR)/html.\"\n\ndirhtml:\n\tdoxygen\n\t$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml\n\t@echo\n\t@echo \"Build finished. The HTML pages are in $(BUILDDIR)/dirhtml.\"\n\nsinglehtml:\n\tdoxygen\n\t$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml\n\t@echo\n\t@echo \"Build finished. The HTML page is in $(BUILDDIR)/singlehtml.\"\n\npickle:\n\tdoxygen\n\t$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle\n\t@echo\n\t@echo \"Build finished; now you can process the pickle files.\"\n\njson:\n\tdoxygen\n\t$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json\n\t@echo\n\t@echo \"Build finished; now you can process the JSON files.\"\n\nhtmlhelp:\n\tdoxygen\n\t$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp\n\t@echo\n\t@echo \"Build finished; now you can run HTML Help Workshop with the\" \\\n\t      \".hhp project file in $(BUILDDIR)/htmlhelp.\"\n\nepub:\n\tdoxygen\n\t$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub\n\t@echo\n\t@echo \"Build finished. The epub file is in $(BUILDDIR)/epub.\"\n\nlatex:\n\tdoxygen\n\t$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex\n\t@echo\n\t@echo \"Build finished; the LaTeX files are in $(BUILDDIR)/latex.\"\n\t@echo \"Run \\`make' in that directory to run these through (pdf)latex\" \\\n\t      \"(use \\`make latexpdf' here to do that automatically).\"\n\nlatexpdf:\n\tdoxygen\n\t$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex\n\t@echo \"Running LaTeX files through pdflatex...\"\n\t$(MAKE) -C $(BUILDDIR)/latex all-pdf\n\t@echo \"pdflatex finished; the PDF files are in $(BUILDDIR)/latex.\"\n\nlatexpdfja:\n\tdoxygen\n\t$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex\n\t@echo \"Running LaTeX files through platex and dvipdfmx...\"\n\t$(MAKE) -C $(BUILDDIR)/latex all-pdf-ja\n\t@echo \"pdflatex finished; the PDF files are in $(BUILDDIR)/latex.\"\n\ntext:\n\tdoxygen\n\t$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text\n\t@echo\n\t@echo \"Build finished. The text files are in $(BUILDDIR)/text.\"\n\nman:\n\tdoxygen\n\t$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man\n\t@echo\n\t@echo \"Build finished. The manual pages are in $(BUILDDIR)/man.\"\n\ntexinfo:\n\tdoxygen\n\t$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo\n\t@echo\n\t@echo \"Build finished. The Texinfo files are in $(BUILDDIR)/texinfo.\"\n\t@echo \"Run \\`make' in that directory to run these through makeinfo\" \\\n\t      \"(use \\`make info' here to do that automatically).\"\n\ninfo:\n\tdoxygen\n\t$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo\n\t@echo \"Running Texinfo files through makeinfo...\"\n\tmake -C $(BUILDDIR)/texinfo info\n\t@echo \"makeinfo finished; the Info files are in $(BUILDDIR)/texinfo.\"\n\ngettext:\n\tdoxygen\n\t$(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale\n\t@echo\n\t@echo \"Build finished. The message catalogs are in $(BUILDDIR)/locale.\"\n\nchanges:\n\tdoxygen\n\t$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes\n\t@echo\n\t@echo \"The overview file is in $(BUILDDIR)/changes.\"\n\nlinkcheck:\n\tdoxygen\n\t$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck\n\t@echo\n\t@echo \"Link check complete; look for any errors in the above output \" \\\n\t      \"or in $(BUILDDIR)/linkcheck/output.txt.\"\n\ndoctest:\n\tdoxygen\n\t$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest\n\t@echo \"Testing of doctests in the sources finished, look at the \" \\\n\t      \"results in $(BUILDDIR)/doctest/output.txt.\"\n\ncoverage:\n\tdoxygen\n\t$(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) $(BUILDDIR)/coverage\n\t@echo \"Testing of coverage in the sources finished, look at the \" \\\n\t      \"results in $(BUILDDIR)/coverage/python.txt.\"\n\nxml:\n\tdoxygen\n\t$(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml\n\t@echo\n\t@echo \"Build finished. The XML files are in $(BUILDDIR)/xml.\"\n\npseudoxml:\n\tdoxygen\n\t$(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml\n\t@echo\n\t@echo \"Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml.\"\n"
  },
  {
    "path": "docs/environment.yml",
    "content": "name: xframe-docs\n\nchannels:\n  - QuantStack\n\ndependencies:\n  - breathe\n"
  },
  {
    "path": "docs/make.bat",
    "content": "@ECHO OFF\r\n\r\nREM Command file for Sphinx documentation\r\n\r\nif \"%SPHINXBUILD%\" == \"\" (\r\n\tset SPHINXBUILD=sphinx-build\r\n)\r\nset BUILDDIR=build\r\nset ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% source\r\nset I18NSPHINXOPTS=%SPHINXOPTS% source\r\nif NOT \"%PAPER%\" == \"\" (\r\n\tset ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS%\r\n\tset I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS%\r\n)\r\n\r\nif \"%1\" == \"\" goto help\r\n\r\nif \"%1\" == \"help\" (\r\n\t:help\r\n\techo.Please use `make ^<target^>` where ^<target^> is one of\r\n\techo.  html       to make standalone HTML files\r\n\techo.  dirhtml    to make HTML files named index.html in directories\r\n\techo.  singlehtml to make a single large HTML file\r\n\techo.  pickle     to make pickle files\r\n\techo.  json       to make JSON files\r\n\techo.  htmlhelp   to make HTML files and a HTML help project\r\n\techo.  qthelp     to make HTML files and a qthelp project\r\n\techo.  devhelp    to make HTML files and a Devhelp project\r\n\techo.  epub       to make an epub\r\n\techo.  latex      to make LaTeX files, you can set PAPER=a4 or PAPER=letter\r\n\techo.  text       to make text files\r\n\techo.  man        to make manual pages\r\n\techo.  texinfo    to make Texinfo files\r\n\techo.  gettext    to make PO message catalogs\r\n\techo.  changes    to make an overview over all changed/added/deprecated items\r\n\techo.  xml        to make Docutils-native XML files\r\n\techo.  pseudoxml  to make pseudoxml-XML files for display purposes\r\n\techo.  linkcheck  to check all external links for integrity\r\n\techo.  doctest    to run all doctests embedded in the documentation if enabled\r\n\techo.  coverage   to run coverage check of the documentation if enabled\r\n\tgoto end\r\n)\r\n\r\nif \"%1\" == \"clean\" (\r\n\tfor /d %%i in (%BUILDDIR%\\*) do rmdir /q /s %%i\r\n\tdel /q /s %BUILDDIR%\\*\r\n\tgoto end\r\n)\r\n\r\n\r\nREM Check if sphinx-build is available and fallback to Python version if any\r\n%SPHINXBUILD% 1>NUL 2>NUL\r\nif errorlevel 9009 goto sphinx_python\r\ngoto sphinx_ok\r\n\r\n:sphinx_python\r\n\r\nset SPHINXBUILD=python -m sphinx.__init__\r\n%SPHINXBUILD% 2> nul\r\nif errorlevel 9009 (\r\n\techo.\r\n\techo.The 'sphinx-build' command was not found. Make sure you have Sphinx\r\n\techo.installed, then set the SPHINXBUILD environment variable to point\r\n\techo.to the full path of the 'sphinx-build' executable. Alternatively you\r\n\techo.may add the Sphinx directory to PATH.\r\n\techo.\r\n\techo.If you don't have Sphinx installed, grab it from\r\n\techo.http://sphinx-doc.org/\r\n\texit /b 1\r\n)\r\n\r\n:sphinx_ok\r\n\r\n\r\nif \"%1\" == \"html\" (\r\n        doxygen\r\n\t%SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html\r\n\tif errorlevel 1 exit /b 1\r\n\techo.\r\n\techo.Build finished. The HTML pages are in %BUILDDIR%/html.\r\n\tgoto end\r\n)\r\n\r\nif \"%1\" == \"dirhtml\" (\r\n\t%SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml\r\n\tif errorlevel 1 exit /b 1\r\n\techo.\r\n\techo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml.\r\n\tgoto end\r\n)\r\n\r\nif \"%1\" == \"singlehtml\" (\r\n\t%SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml\r\n\tif errorlevel 1 exit /b 1\r\n\techo.\r\n\techo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml.\r\n\tgoto end\r\n)\r\n\r\nif \"%1\" == \"pickle\" (\r\n\t%SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle\r\n\tif errorlevel 1 exit /b 1\r\n\techo.\r\n\techo.Build finished; now you can process the pickle files.\r\n\tgoto end\r\n)\r\n\r\nif \"%1\" == \"json\" (\r\n\t%SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json\r\n\tif errorlevel 1 exit /b 1\r\n\techo.\r\n\techo.Build finished; now you can process the JSON files.\r\n\tgoto end\r\n)\r\n\r\nif \"%1\" == \"htmlhelp\" (\r\n\t%SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp\r\n\tif errorlevel 1 exit /b 1\r\n\techo.\r\n\techo.Build finished; now you can run HTML Help Workshop with the ^\r\n.hhp project file in %BUILDDIR%/htmlhelp.\r\n\tgoto end\r\n)\r\n\r\nif \"%1\" == \"qthelp\" (\r\n\t%SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp\r\n\tif errorlevel 1 exit /b 1\r\n\techo.\r\n\techo.Build finished; now you can run \"qcollectiongenerator\" with the ^\r\n.qhcp project file in %BUILDDIR%/qthelp, like this:\r\n\techo.^> qcollectiongenerator %BUILDDIR%\\qthelp\\packagename.qhcp\r\n\techo.To view the help file:\r\n\techo.^> assistant -collectionFile %BUILDDIR%\\qthelp\\packagename.ghc\r\n\tgoto end\r\n)\r\n\r\nif \"%1\" == \"devhelp\" (\r\n\t%SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp\r\n\tif errorlevel 1 exit /b 1\r\n\techo.\r\n\techo.Build finished.\r\n\tgoto end\r\n)\r\n\r\nif \"%1\" == \"epub\" (\r\n\t%SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub\r\n\tif errorlevel 1 exit /b 1\r\n\techo.\r\n\techo.Build finished. The epub file is in %BUILDDIR%/epub.\r\n\tgoto end\r\n)\r\n\r\nif \"%1\" == \"latex\" (\r\n\t%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex\r\n\tif errorlevel 1 exit /b 1\r\n\techo.\r\n\techo.Build finished; the LaTeX files are in %BUILDDIR%/latex.\r\n\tgoto end\r\n)\r\n\r\nif \"%1\" == \"latexpdf\" (\r\n\t%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex\r\n\tcd %BUILDDIR%/latex\r\n\tmake all-pdf\r\n\tcd %~dp0\r\n\techo.\r\n\techo.Build finished; the PDF files are in %BUILDDIR%/latex.\r\n\tgoto end\r\n)\r\n\r\nif \"%1\" == \"latexpdfja\" (\r\n\t%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex\r\n\tcd %BUILDDIR%/latex\r\n\tmake all-pdf-ja\r\n\tcd %~dp0\r\n\techo.\r\n\techo.Build finished; the PDF files are in %BUILDDIR%/latex.\r\n\tgoto end\r\n)\r\n\r\nif \"%1\" == \"text\" (\r\n\t%SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text\r\n\tif errorlevel 1 exit /b 1\r\n\techo.\r\n\techo.Build finished. The text files are in %BUILDDIR%/text.\r\n\tgoto end\r\n)\r\n\r\nif \"%1\" == \"man\" (\r\n\t%SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man\r\n\tif errorlevel 1 exit /b 1\r\n\techo.\r\n\techo.Build finished. The manual pages are in %BUILDDIR%/man.\r\n\tgoto end\r\n)\r\n\r\nif \"%1\" == \"texinfo\" (\r\n\t%SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo\r\n\tif errorlevel 1 exit /b 1\r\n\techo.\r\n\techo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo.\r\n\tgoto end\r\n)\r\n\r\nif \"%1\" == \"gettext\" (\r\n\t%SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale\r\n\tif errorlevel 1 exit /b 1\r\n\techo.\r\n\techo.Build finished. The message catalogs are in %BUILDDIR%/locale.\r\n\tgoto end\r\n)\r\n\r\nif \"%1\" == \"changes\" (\r\n\t%SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes\r\n\tif errorlevel 1 exit /b 1\r\n\techo.\r\n\techo.The overview file is in %BUILDDIR%/changes.\r\n\tgoto end\r\n)\r\n\r\nif \"%1\" == \"linkcheck\" (\r\n\t%SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck\r\n\tif errorlevel 1 exit /b 1\r\n\techo.\r\n\techo.Link check complete; look for any errors in the above output ^\r\nor in %BUILDDIR%/linkcheck/output.txt.\r\n\tgoto end\r\n)\r\n\r\nif \"%1\" == \"doctest\" (\r\n\t%SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest\r\n\tif errorlevel 1 exit /b 1\r\n\techo.\r\n\techo.Testing of doctests in the sources finished, look at the ^\r\nresults in %BUILDDIR%/doctest/output.txt.\r\n\tgoto end\r\n)\r\n\r\nif \"%1\" == \"coverage\" (\r\n\t%SPHINXBUILD% -b coverage %ALLSPHINXOPTS% %BUILDDIR%/coverage\r\n\tif errorlevel 1 exit /b 1\r\n\techo.\r\n\techo.Testing of coverage in the sources finished, look at the ^\r\nresults in %BUILDDIR%/coverage/python.txt.\r\n\tgoto end\r\n)\r\n\r\nif \"%1\" == \"xml\" (\r\n\t%SPHINXBUILD% -b xml %ALLSPHINXOPTS% %BUILDDIR%/xml\r\n\tif errorlevel 1 exit /b 1\r\n\techo.\r\n\techo.Build finished. The XML files are in %BUILDDIR%/xml.\r\n\tgoto end\r\n)\r\n\r\nif \"%1\" == \"pseudoxml\" (\r\n\t%SPHINXBUILD% -b pseudoxml %ALLSPHINXOPTS% %BUILDDIR%/pseudoxml\r\n\tif errorlevel 1 exit /b 1\r\n\techo.\r\n\techo.Build finished. The pseudo-XML files are in %BUILDDIR%/pseudoxml.\r\n\tgoto end\r\n)\r\n\r\n:end\r\n"
  },
  {
    "path": "docs/source/_static/main_stylesheet.css",
    "content": ".wy-nav-content{\n    max-width: 1000px;\n    margin: auto;\n}\n"
  },
  {
    "path": "docs/source/api/axis_index.rst",
    "content": ".. Copyright (c) 2018, Johan Mabille, Sylvain Corlay, Wolf Vollprecht\n   and Martin Renou\n\n   Distributed under the terms of the BSD 3-Clause License.\n\n   The full license is in the file LICENSE, distributed with this software.\n\nAxes\n====\n\n.. toctree::\n\n   xaxis_base\n   xaxis\n   xaxis_default\n   xaxis_function\n   xaxis_expression_leaf\n   xaxis_view\n   xaxis_variant\n   xnamed_axis\n"
  },
  {
    "path": "docs/source/api/coordinate_index.rst",
    "content": ".. Copyright (c) 2018, Johan Mabille, Sylvain Corlay, Wolf Vollprecht\n   and Martin Renou\n\n   Distributed under the terms of the BSD 3-Clause License.\n\n   The full license is in the file LICENSE, distributed with this software.\n\nCoordinates and dimensions\n==========================\n\n.. toctree::\n\n   xcoordinate_base\n   xcoordinate\n   xcoordinate_view\n   xcoordinate_chain\n   xcoordinate_expanded\n   xdimension\n"
  },
  {
    "path": "docs/source/api/variable_index.rst",
    "content": ".. Copyright (c) 2018, Johan Mabille, Sylvain Corlay, Wolf Vollprecht\n   and Martin Renou\n\n   Distributed under the terms of the BSD 3-Clause License.\n\n   The full license is in the file LICENSE, distributed with this software.\n\nVariables\n=========\n\n.. toctree::\n\n   xexpand_dims_view\n   xvariable_masked_view\n"
  },
  {
    "path": "docs/source/api/xaxis.rst",
    "content": ".. Copyright (c) 2018, Johan Mabille, Sylvain Corlay, Wolf Vollprecht\n   and Martin Renou\n\n   Distributed under the terms of the BSD 3-Clause License.\n\n   The full license is in the file LICENSE, distributed with this software.\n\nxaxis\n=====\n\nDefined in ``xframe/xaxis.hpp``\n\n.. doxygenclass:: xf::xaxis\n   :project: xframe\n   :members:\n\n.. doxygenfunction:: xf::axis(L, L, L)\n   :project: xframe\n\n.. doxygenfunction:: xf::axis(std::initializer_list<L>)\n   :project: xframe\n\n"
  },
  {
    "path": "docs/source/api/xaxis_base.rst",
    "content": ".. Copyright (c) 2018, Johan Mabille, Sylvain Corlay, Wolf Vollprecht\n   and Martin Renou\n\n   Distributed under the terms of the BSD 3-Clause License.\n\n   The full license is in the file LICENSE, distributed with this software.\n\nxaxis_base\n==========\n\nDefined in ``xframe/xaxis_base.hpp``\n\n.. doxygenclass:: xf::xaxis_base\n   :project: xframe\n   :members:\n\n.. doxygenfunction:: operator==(const xaxis_base<D1>&, const xaxis_base<D2>&)\n   :project: xframe\n\n.. doxygenfunction:: operator!=(const xaxis_base<D1>&, const xaxis_base<D2>&)\n   :project: xframe\n"
  },
  {
    "path": "docs/source/api/xaxis_default.rst",
    "content": ".. Copyright (c) 2018, Johan Mabille, Sylvain Corlay, Wolf Vollprecht\n   and Martin Renou\n\n   Distributed under the terms of the BSD 3-Clause License.\n\n   The full license is in the file LICENSE, distributed with this software.\n\nxaxis_default\n=============\n\nDefined in ``xframe/xaxis_default.hpp``\n\n.. doxygenclass:: xf::xaxis_default\n   :project: xframe\n   :members:\n\n.. doxygenfunction:: xf::axis(L)\n   :project: xframe\n\n"
  },
  {
    "path": "docs/source/api/xaxis_expression_leaf.rst",
    "content": ".. Copyright (c) 2018, Johan Mabille, Sylvain Corlay, Wolf Vollprecht\n   and Martin Renou\n\n   Distributed under the terms of the BSD 3-Clause License.\n\n   The full license is in the file LICENSE, distributed with this software.\n\nxaxis_expression_leaf\n=====================\n\nDefined in ``xframe/xaxis_expression_leaf.hpp``\n\n.. doxygenclass:: xf::xaxis_expression_leaf\n   :project: xframe\n   :members:\n"
  },
  {
    "path": "docs/source/api/xaxis_function.rst",
    "content": ".. Copyright (c) 2018, Johan Mabille, Sylvain Corlay, Wolf Vollprecht\n   and Martin Renou\n\n   Distributed under the terms of the BSD 3-Clause License.\n\n   The full license is in the file LICENSE, distributed with this software.\n\nxaxis_function\n==============\n\nDefined in ``xframe/xaxis_function.hpp``\n\n.. doxygenclass:: xf::xaxis_function\n   :project: xframe\n   :members:\n"
  },
  {
    "path": "docs/source/api/xaxis_variant.rst",
    "content": ".. Copyright (c) 2018, Johan Mabille, Sylvain Corlay, Wolf Vollprecht\n   and Martin Renou\n\n   Distributed under the terms of the BSD 3-Clause License.\n\n   The full license is in the file LICENSE, distributed with this software.\n\nxaxis_variant\n=============\n\nDefined in ``xframe/xaxis_variant.hpp``\n\n.. doxygenclass:: xf::xaxis_variant\n   :project: xframe\n   :members:\n\n"
  },
  {
    "path": "docs/source/api/xaxis_view.rst",
    "content": ".. Copyright (c) 2018, Johan Mabille, Sylvain Corlay, Wolf Vollprecht\n   and Martin Renou\n\n   Distributed under the terms of the BSD 3-Clause License.\n\n   The full license is in the file LICENSE, distributed with this software.\n\nxaxis_view\n==========\n\nDefined in ``xframe/xaxis_view.hpp``\n\n.. doxygenclass:: xf::xaxis_view\n   :project: xframe\n   :members:\n\n.. doxygenfunction:: operator==(const xaxis_view<L, T, MT>&, const xaxis_view<L, T, MT>&)\n   :project: xframe\n\n.. doxygenfunction:: operator!=(const xaxis_view<L, T, MT>&, const xaxis_view<L, T, MT>&)\n   :project: xframe\n\n.. doxygenfunction:: operator==(const xaxis_view<L, T, MT>&, const xaxis_variant<L, T, MT>&)\n   :project: xframe\n\n.. doxygenfunction:: operator!=(const xaxis_view<L, T, MT>&, const xaxis_variant<L, T, MT>&)\n   :project: xframe\n\n.. doxygenfunction:: operator==(const xaxis_variant<L, T, MT>&, const xaxis_view<L, T, MT>&)\n   :project: xframe\n\n.. doxygenfunction:: operator!=(const xaxis_variant<L, T, MT>&, const xaxis_view<L, T, MT>&)\n   :project: xframe\n"
  },
  {
    "path": "docs/source/api/xcoordinate.rst",
    "content": ".. Copyright (c) 2018, Johan Mabille, Sylvain Corlay, Wolf Vollprecht\n   and Martin Renou\n\n   Distributed under the terms of the BSD 3-Clause License.\n\n   The full license is in the file LICENSE, distributed with this software.\n\nxcoordinate\n===========\n\nDefined in ``xframe/xcoordinate.hpp``\n\n.. doxygenclass:: xf::xcoordinate\n   :project: xframe\n   :members:\n\n.. doxygenfunction:: coordinate(const std::map<K, xaxis_variant<L, S, MT>>&)\n   :project: xframe\n\n.. doxygenfunction:: coordinate(std::map<K, xaxis_variant<L, S, MT>>&&)\n   :project: xframe\n\n.. doxygenfunction:: coordinate(xnamed_axis<K, S, MT, L, LT>, xnamed_axis<K1, S, MT, L, LT1>...)\n   :project: xframe\n\n.. doxygenfunction:: broadcast_coordinates(xcoordinate<K, L, S, MT>&, const Args&...)\n   :project: xframe\n"
  },
  {
    "path": "docs/source/api/xcoordinate_base.rst",
    "content": ".. Copyright (c) 2018, Johan Mabille, Sylvain Corlay, Wolf Vollprecht\n   and Martin Renou\n\n   Distributed under the terms of the BSD 3-Clause License.\n\n   The full license is in the file LICENSE, distributed with this software.\n\nxcoordinate_base\n================\n\nDefined in ``xframe/xcoordinate_base.hpp``\n\n.. doxygenclass:: xf::xcoordinate_base\n   :project: xframe\n   :members:\n\n.. doxygenfunction:: operator==(const xcoordinate_base<K, A1>&, const xcoordinate_base<K, A2>&)\n   :project: xframe\n\n.. doxygenfunction:: operator!=(const xcoordinate_base<K, A1>&, const xcoordinate_base<K, A2>&)\n   :project: xframe\n"
  },
  {
    "path": "docs/source/api/xcoordinate_chain.rst",
    "content": ".. Copyright (c) 2018, Johan Mabille, Sylvain Corlay, Wolf Vollprecht\n   and Martin Renou\n\n   Distributed under the terms of the BSD 3-Clause License.\n\n   The full license is in the file LICENSE, distributed with this software.\n\nxcoordinate_chain\n=================\n\nDefined in ``xframe/xcoordinate_chain.hpp``\n\n.. doxygenclass:: xf::xcoordinate_chain\n   :project: xframe\n   :members:\n\n.. doxygenfunction:: reindex(const C&, const typename C::map_type&)\n   :project: xframe\n\n.. doxygenfunction:: reindex(const C&, typename C::map_type&&)\n   :project: xframe\n"
  },
  {
    "path": "docs/source/api/xcoordinate_expanded.rst",
    "content": ".. Copyright (c) 2018, Johan Mabille, Sylvain Corlay, Wolf Vollprecht\n   and Martin Renou\n\n   Distributed under the terms of the BSD 3-Clause License.\n\n   The full license is in the file LICENSE, distributed with this software.\n\nxcoordinate_expanded\n====================\n\nDefined in ``xframe/xcoordinate_expanded.hpp``\n\n.. doxygenclass:: xf::xcoordinate_expanded\n   :project: xframe\n   :members:\n\n.. doxygenfunction:: expand_dims(const C&, const typename C::map_type&)\n   :project: xframe\n\n.. doxygenfunction:: expand_dims(const C&, typename C::map_type&&)\n   :project: xframe\n"
  },
  {
    "path": "docs/source/api/xcoordinate_view.rst",
    "content": ".. Copyright (c) 2018, Johan Mabille, Sylvain Corlay, Wolf Vollprecht\n   and Martin Renou\n\n   Distributed under the terms of the BSD 3-Clause License.\n\n   The full license is in the file LICENSE, distributed with this software.\n\nxcoordinate_view\n================\n\nDefined in ``xframe/xcoordinate_view.hpp``\n\n.. doxygenclass:: xf::xcoordinate_view\n   :project: xframe\n   :members:\n\n.. doxygenfunction:: coordinate_view(const std::map<K, xaxis_view<L, S, MT>>&)\n   :project: xframe\n\n.. doxygenfunction:: coordinate_view(std::map<K, xaxis_view<L, S, MT>>&&)\n   :project: xframe\n"
  },
  {
    "path": "docs/source/api/xdimension.rst",
    "content": ".. Copyright (c) 2018, Johan Mabille, Sylvain Corlay, Wolf Vollprecht\n   and Martin Renou\n\n   Distributed under the terms of the BSD 3-Clause License.\n\n   The full license is in the file LICENSE, distributed with this software.\n\nxdimension\n==========\n\nDefined in ``xframe/xdimension.hpp``\n\n.. doxygenclass:: xf::xdimension\n   :project: xframe\n   :members:\n\n.. doxygenfunction:: operator==(const xdimension<L, T>&, const xdimension<L, T>&)\n   :project: xframe\n\n.. doxygenfunction:: operator!=(const xdimension<L, T>&, const xdimension<L, T>&)\n   :project: xframe\n"
  },
  {
    "path": "docs/source/api/xexpand_dims_view.rst",
    "content": ".. Copyright (c) 2018, Johan Mabille, Sylvain Corlay, Wolf Vollprecht\n   and Martin Renou\n\n   Distributed under the terms of the BSD 3-Clause License.\n\n   The full license is in the file LICENSE, distributed with this software.\n\nxexpand_dims_view\n=================\n\nDefined in ``xframe/xexpand_dims_view.hpp``\n\n.. doxygenclass:: xf::xexpand_dims_view\n   :project: xframe\n   :members:\n\n.. doxygenfunction:: expand_dims(E&&, std::initializer_list<K>)\n   :project: xframe\n\n.. doxygenfunction:: expand_dims(E&&, std::initializer_list<std::pair<typename std::decay_t<E>::key_type, std::size_t>>)\n   :project: xframe\n"
  },
  {
    "path": "docs/source/api/xnamed_axis.rst",
    "content": ".. Copyright (c) 2018, Johan Mabille, Sylvain Corlay, Wolf Vollprecht\n   and Martin Renou\n\n   Distributed under the terms of the BSD 3-Clause License.\n\n   The full license is in the file LICENSE, distributed with this software.\n\nxnamed_axis\n===========\n\nDefined in ``xframe/xnamed_axis.hpp``\n\n.. doxygenclass:: xf::xnamed_axis\n   :project: xframe\n   :members:\n\n.. doxygenfunction:: xf::named_axis(const K&, A&&)\n  :project: xframe\n"
  },
  {
    "path": "docs/source/api/xvariable_masked_view.rst",
    "content": ".. Copyright (c) 2018, Johan Mabille, Sylvain Corlay, Wolf Vollprecht\n   and Martin Renou\n\n   Distributed under the terms of the BSD 3-Clause License.\n\n   The full license is in the file LICENSE, distributed with this software.\n\nxvariable_masked_view\n=====================\n\nDefined in ``xframe/xvariable_masked_view.hpp``\n\n.. doxygenclass:: xf::xvariable_masked_view\n   :project: xframe\n   :members:\n\n.. doxygenfunction:: where(EV&&, EAX&&)\n   :project: xframe\n"
  },
  {
    "path": "docs/source/computation.rst",
    "content": ".. Copyright (c) 2018, Johan Mabille, Sylvain Corlay, Wolf Vollprecht\n   and Martin Renou\n\n   Distributed under the terms of the BSD 3-Clause License.\n\n   The full license is in the file LICENSE, distributed with this software.\n\nComputation\n===========\n\n`xframe` is actually more than a multi-dimensional data frame library; like `xtensor`_,\nit is an expression engine that allows numerical computation on any object implementing\nthe variable or the frame interfaces.\n\nExpressions\n-----------\n\nAssume ``x``, ``y`` and ``z`` are variables with *compatible coordinates* (we'll come back\nto that later), the return type of an expression such as ``x + exp(y) * sin(z)`` is \n**not a variable**. The result is a variable expression which offers the same interface\nas ``xvariable`` but does not hold any value. Such expressions can be plugged into others\nto build more cmoplex expressions:\n\n.. code::\n\n    auto f = x + exp(y) * sin(z);\n    auto f2 = x + exp(w) * cos(f);\n\nThe expression engines avoids the evaluation of intermediate results and their storage in\ntemporary variables, so you can achieve the same performance as if you had written a loop.\nSuch a loop is quite more complicated than an array loop since labels and dimension names\nare involved in the assignment mechanism.\n\nSince a variable expression provides the same API as ``xvariable``, all the indexing and\nselection operations are available:\n\n.. code::\n\n    auto v = (x + exp(y) * sin(z)).select({{\"city\", \"Paris\"}, {\"group\", \"a\"}});\n    auto view = select(x + exp(y) * sin(z), {{\"city\", xf::keep(\"Paris\")}, {\"group\", xf::drop({\"b\", \"d\", \"h\"})}});\n\nLazy evaluation\n---------------\n\nAn expression such as ``x + exp(y) * sin(z)`` does not hold the result. **Values are only computed\nupon access or when the expression is assigned to a variable**. this allows to operate symbolically\non very large data sets and only compute the result for the indices of interest:\n\n.. code::\n\n    // Assuming x and y are variables each holding ~1M values\n    auto f = cos(x) + sin(y);\n    \n    double first_res = f.locate(\"a\", \"London\");\n    double second_res = f.locate(\"b\", \"Pekin\");\n    // Only two values have been computed\n\nThat means if you use the same expression in two assign statements, the computation of the expression\nwill be done twice. Depending on the complexity of the cmoputation and the size of the data, it might\nbe convenient to store the result of the expression in a temporary variable:\n\n.. code::\n\n    variable_type tmp = cos(x) + sin(y);\n    variable_type res1 = tmp + 2 * exp(z);\n    variable_type res2 = tmp - 3 * exp(w);\n\nBroadcasting by dimension names\n-------------------------------\n\nLike `xarray`_, broadcasting in *xframe* is done according to the dimension names rather than\ntheir positions. This way, you do not need to transpose variable or insert dimensions of length\n1 to to get array operations to work, as commonly done in `xtensor`_ with ``xt::reshape`` or\n``xt::newaxis``.\n\nThis can be illustrated with the following examples. First, consider two one-dimensional variable\naligned along different dimensions:\n\n.. code::\n\n    auto v1 = variable_type(data_type({1., 2.}), {{\"x\", xf::axis(1, 3)}});\n    auto v2 = variable_type(data_type({3., 7.}), {{\"y\", xf::axis(2, 5)}});\n\nWe can apply mathematical operations to these variables, their dimension are expanded automatically:\n\n.. code::\n\n    variable_type res = v1 + v2;\n    std::cout << res << std::endl;\n    // Output:\n    // {{ 4.  8.}\n    //  { 5.  9.}}\n    // Coordinates:\n    // x: (1, 3, )\n    // y: (2, 5, )\n    \nContrary to `xarray`_ , dimensions are not reordered to the order in which they first appeared:\n\n.. code::\n\n    auto v3 = variable_type(data_type({{1., 2.}, {3., 4.}}),\n                            {{\"y\", xf::axis({2, 5})}, {\"x\", xf::axis({1, 4})}});\n    variable_type res2 = v1 + v3;\n    std::cout << res2 << std::endl;\n    // Output:\n    // {{ 2.  4. }\n    //  { 4.  6. }}\n    // Coordinates:\n    // y: (2, 5, )\n    // x: (1, 3, )\n\nThis allows many optimizations in the assignment mechanism.\n\nAutomatic alignment\n-------------------\n\n`xframe` enforces alignment between coordinate labels on objects involved in operations.\nThe default result of an operation is by the *intersection* of the coordinate labels:\n\n.. code::\n\n    auto v4 = variable_type(data_type({1., 2., 3.}), {{\"x\", xf::axis({1, 3, 5})}});\n    auto v5 = variable_type(data_type({4., 7., 12.}), {{\"x\", xf::axis({1, 5, 7})}});\n\n    variable_type res3 = v4 + v5;\n    std::cout << res3 << std::endl;\n    // Output:\n    // { 5.  10. }\n    // Coordinates:\n    // x: (1, 5,)\n\nOperations are slower when variables are not aligned, so it might be useful to\nexplicitly align variables involved in loops of performance critical code.\n\nOperators and functions\n-----------------------\n\n`xframe` provides all the basic operators and mathematical functions:\n\n- arithmetic operators: ``+``, ``-``, ``*``, ``/``\n- logical operators: ``&&``, ``||``, ``!``\n- comparison operators: ``==``, ``!=``, ``<``, ``<=``, ``>``, ``>=``\n- basic functions: ``abs``, ``remainder``, ``fma``, ...\n- exponential functions: ``exp``, ``expm1``, ``log``, ``log1p``, ...\n- power functions: ``pow``, ``sqrt``, ``cbrt``, ...\n- trigonometric functions: ``sin``, ``cos``, ``tan``, ...\n- hyperbolic functions: ``sinh``, ``cosh``, ``tanh``, ...\n- error and gamma functions: ``erf``, ``erfc``, ``tgamma``, ``lgamma``, ...\n\nActually, any function operating on ``xtensor`` expressions can work with\n``xvariable`` expressions without any additional work; the only constraint\nis to accept and return expressions:\n\n.. code::\n\n    template <class E1, class E2>\n    inline auto distance(const xexpression<E1>& e1, const xexpression<E2>& e2)\n    {\n        const E1& de1 = e1.derived_cast();\n        const E2& de2 = e2.derived_cast();\n        // \n        return sqrt(de1 * de1 + de2 * de2);\n    }\n\nThis function can work with both tnesor and variable expressions, performing\nbroadcasting according to the rules of `xtensor` or `xframe` depending on\nits argument type:\n\n.. code::\n\n    xt::xarray<double> a1 = {1., 2. };\n    xt::xarray<double> a2 = {{1., 3.}, {4., 7.}};\n\n    // Broadcasting is applied according to xtensor rules,\n    // that is by dimension order\n    xt::xarray<double> ares = distance(a1, a2);\n\n    // Broadcasting is applied according to xframe rules,\n    // that is by dimension name\n    variable_type vres = distance(v1, v3);\n\nMissing values\n--------------\n\nContrary to `pandas`_ or `xarray`_, `xframe` does not use particular values\nfor representing missing values. Instead, it makes use of the dedicated type\n``xtl::xoptional`` which gathers the value and a flag to specify whether the\nvalue is missing or not:\n\n.. code::\n\n    data_type d = {1., 2., 3. };\n    d(1).has_value() = false;\n\n    auto v = variable_type(d, {{\"x\", xf::axis({1, 3, 4})}});\n    std::cout << v << std::endl;\n    // Output:\n    // { 1.  N/A  3. }\n    // Coordinates:\n    // x: (1, 3, 4,)\n\n.. _pandas: https://pandas.pydata.org\n.. _xarray: https://xarray.pydata.org\n.. _xtensor: https://github.com/xtensor-stack/xtensor\n\n"
  },
  {
    "path": "docs/source/conf.py",
    "content": "#!/usr/bin/env python3\n# -*- coding: utf-8 -*-\n\nimport os\nimport subprocess\n\non_rtd = os.environ.get('READTHEDOCS', None) == 'True'\n\nif on_rtd:\n    subprocess.call('cd ..; doxygen', shell=True)\n\nimport sphinx_rtd_theme\n\nhtml_theme = \"sphinx_rtd_theme\"\n\nhtml_theme_path = [sphinx_rtd_theme.get_html_theme_path()]\n\ndef setup(app):\n    app.add_stylesheet(\"main_stylesheet.css\")\n\nextensions = ['breathe']\nbreathe_projects = { 'xframe': '../xml' }\ntemplates_path = ['_templates']\nhtml_static_path = ['_static']\nsource_suffix = '.rst'\nmaster_doc = 'index'\nproject = 'xframe'\ncopyright = '2018, Johan Mabille, Sylvain Corlay, Wolf Vollprecht and Martin Renou'\nauthor = 'Johan Mabille, Sylvain Corlay, Wolf Vollprecht and Martin Renou'\n\nhtml_logo = 'quantstack-white.svg'\n\nexclude_patterns = []\nhighlight_language = 'c++'\npygments_style = 'sphinx'\ntodo_include_todos = False\nhtmlhelp_basename = 'xframedoc'\n\n"
  },
  {
    "path": "docs/source/data_structure.rst",
    "content": ".. Copyright (c) 2018, Johan Mabille, Sylvain Corlay, Wolf Vollprecht\n   and Martin Renou\n\n   Distributed under the terms of the BSD 3-Clause License.\n\n   The full license is in the file LICENSE, distributed with this software.\n\nData structures\n===============\n\nAxes\n----\n\nAn axis is a mapping of labels to positions in a given dimension. It is the equivalent of\nthe ``index`` object from `pandas`_. `xframe` supports many types of labels, the most common\nare strings, char, integers and dates. An axis is created from a list of labels, a builder\nfunction is provided so the type of the axis can be inferred. The following example illustrates\nthe two main ways of creating an axis:\n\n.. code::\n\n    using saxis_type = xf::xaxis<xf::fstring, std::size_t>;\n\n    saxis_type s1({ \"a\", \"b\", \"d\", \"e\" });\n    auto s2 = xf::axis({ \"a\", \"b\", \"d\", \"e\" });\n    // s1 and s2 are similar axes\n\nIt is also possible to create an axis given the size of the axis or the start, stop and step:\n\n.. code::\n\n    auto s3 = xf::axis(5);        // == xf::axis({ 0, 1, 2, 3, 4 });\n    auto s4 = xf::axis(2, 7);     // == xf::axis({ 2, 3, 4, 5, 6 });\n    auto s5 = xf::axis(0, 10, 2); // == xf::axis({ 0, 2, 4, 6, 8 });\n    auto s6 = xf::axis(\"a\", \"d\"); // == xf::axis({ \"a\", \"b\", \"c\" });\n\nThe axis API is similar to the one of a constant ``std::map`` that throws an exception when\nasked a missing key:\n\n.. code::\n\n    std::size_t i0 = s1[\"a\"];\n    try\n    {\n        std::size_t i1 = s1[\"c\"];\n    }\n    catch(std::exception& e)\n    {\n        // The exception will be catch since \"c\" is not a label of s1\n        std::cout << e.what() << std::endl;\n    }\n\n``xaxis`` also provides iterators and methods to compute the union and the intersection of\naxes. However a user rarely needs to manipulate the axes directly, the most common operation\nis to create them and then store them in a coordinate system.\n\nCoordinates\n-----------\n\nCoordinates are mappings of dimension names to axes. `xframe` provides different methods\nto easily create them:\n\n.. code::\n\n    using coordinate_type = xf::xcoordinate<xf::fstring>;\n\n    coordinate_type c1({{\"group\", xf::axis({\"a\", \"b\", \"d\", \"e\"})},\n                        {\"city\",  xf::axis({\"London\", \"Paris\", \"Brussels\"})}});\n    auto c2 = xf::coordinate({{\"group\", xf::axis({\"a\", \"b\", \"d\", \"e\"})},\n                              {\"city\",  xf::axis({\"London\", \"Paris\", \"Brussels\"})}});\n    // c1 and c2 are similar coordinates\n\n.. note::\n\n   The builder function ``xf::coordinate`` converts the ``const char*``\n   arguments to ``fstring`` and returns a ``xcoordinate<fstring>`` object. You can modify\n   this behavior by specifying the key type of the coordinate as the first template parameter\n   of the ``coordinate`` function:\n   ``auto c2 = xf::coordinate<std::string>({{\"group\", xf::axis({\"a\", \"b\", \"d\", \"e\"})}, ...});``\n\n``xnamed_axis`` allows to store a dimension name - axis pair that you can reuse in different\ncoordinates objects; if you want to create a coordinate object from a named axis, all the\narguments must be named axes; fortunately, a ``xnamed_axis`` can be created in place, as\nshown below:\n\n.. code::\n\n    // This object will be used in different coordinates objects\n    auto a1 = xf::named_axis(\"igroup\", xf::axis({1, 2, 4, 5})});\n\n    auto c1 = xf::coordinate<xf::fstring>(a1, xf::named_axis(\"city\", xf::axis({\"London\", \"Parid\", \"Brussels\"})));\n    auto c2 = xf::coordinate<xf::fstring>(a1, xf::named_axis(\"country\", xf::axis({\"USA\", \"Japan\"})));\n\nAs you can notice, coordinates objects can store axes with different label types. By default,\nthese types are ``int``, ``std::size_t``, ``char`` and ``xf::fstring``, you can\nspecify a different type list:\n\n.. code::\n\n    using coordinate_type = xf::xcoordinate<xf::fstring, xtl::mpl::vector<int, std::string>>;\n\n    coordinate_type c({{\"group\", xf::axis({\"a\", \"b\", \"d\", \"e\"})},\n                       {\"city\",  xf::axis({\"London\", \"Paris\", \"Brussels\"})}});\n\nDimension\n---------\n\nA dimension object is the mapping of the dimension names to the dimension positions in the\ndata tensor. Creating a ``xdimension`` is as simple as creating an ``xcoordinate`` or an\n``xaxis``:\n\n.. code::\n\n    using dimension_type = xf::xdimension<xf::fstring>;\n\n    dimension_type dim1({\"city\", \"group\"});\n    auto dim2 = xf::dimension({\"city\", \"group\"});\n    // dim1 and dim2 are similar dimensions\n\n``xdimension`` provides an API similar to ``xaxis`` and therefore can be considered as a\nspecial axis. Together a dimension object and a coordinate object form a coordinate system\nwhich maps labels and dimension names to indexes in the data tensor.\n\n.. note::\n\n   Like ``xf::coordinate``, the builder function ``xf::dimension`` converts the ``const char*``\n   arguments to ``fstring`` and returns a ``xdimension<fstring>`` object. You can modify\n   this behavior by specifying the label type of the dimension as the first template parameter\n   of the ``dimension`` function:\n   ``auto d = xf::dimension<std::string>({\"city\", \"group\"});``\n\nVariables\n---------\n\nA variable is a data tensor with a coordinate system, that is an ``xcoordinate`` object and\nan ``xdimension`` object. It is the C++ equivalent of the ``xarray.DataArray`` Python class.\n``xvariable`` provides many constructors:\n\n.. code::\n\n    using coordinate_type = xf::xcoordinate<xf::fstring>;\n    using dimension_type = xf::xdimension<xf::fstring>;\n    using variable_type = xvariable<double, coordinate_type>;\n\n    data_type d = xt::eval(xt::random::rand({3, 4}));\n    auto c = xf::coordinate({{\"group\", xf::axis({\"a\", \"b\", \"d\", \"e\"})},\n                             {\"city\",  xf::axis({\"London\", \"Paris\", \"Brussels\"})}});\n    auto dim = xf::dimension({\"city\", \"group\"});\n\n    variable_type v1(d, c, dim);\n\n    // Coordinates and dimension can be built in place\n    variable_type v2(d, xf::coordinate({{\"group\", xf::axis({\"a\", \"b\", \"d\", \"e\"})},\n                                        {\"city\",  xf::axis({\"London\", \"Paris\", \"Brussels\"})}}),\n                        xf::dimension({\"city\", \"group\"}));\n\nThe data parameter can be omitted, in that case the variable creates an uninitialized data tensor:\n\n.. code::\n\n    variable_type v3(c, dim);\n\n    variable_type v4(xf::coordinate({{\"group\", xf::axis({\"a\", \"b\", \"d\", \"e\"})},\n                                     {\"city\",  xf::axis({\"London\", \"Paris\", \"Brussels\"})}}),\n                     xf::dimension({\"city\", \"group\"}));\n\nA variable can also be created from a map of axes and a list of dimension names:\n\n.. code::\n\n    variable_type::coordinate_map coord_map;\n    coord_map[\"group\"] = xf::axis({\"a\", \"b\", \"d\", \"e\"});\n    coord_map[\"city\"]  = xf::axis({\"London\", \"Paris\", \"Brussels\"});\n    dimension_type::label_list dim_list = {\"group\", \"city\"};\n\n    variable_type v5(d, coord_map, dim_list);\n    variable_type v6(coord_map, dim_list);\n\nIf the dimension object is omitted, the dimension mapping is inferred from the coordinate\nobject. In the code below, the mapping is different from the previous defined variables,\n``group`` is the name of the first dimension and ``city`` is the name of the second one:\n\n.. code::\n\n    variable_type v7(d, {{\"group\", xf::axis({\"a\", \"b\", \"d\", \"e\"})},\n                         {\"city\",  xf::axis({\"london\", \"Paris\", \"Brussels\"})}});\n\n    // variable with same coordinate system but uninitialized data\n    variable_type v8({{\"group\", xf::axis({\"a\", \"b\", \"d\", \"e\"})},\n                      {\"city\",  xf::axis({\"london\", \"Paris\", \"Brussels\"})}});\n\n`xframe` also provides builder functions, so that the type of the variable can be inferred:\n\n.. code::\n\n    auto v10 = variable(d, c, dim);\n    auto v11 = variable(d, xf::coordinate({{\"group\", xf::axis({\"a\", \"b\", \"d\", \"e\"})},\n                                           {\"city\",  xf::axis({\"London\", \"Paris\", \"Brussels\"})}}),\n                           xf::dimension({\"city\", \"group\"}));\n\n    auto v12 = variable(c, dim);\n    auto v13 = variable(xf::coordinate({{\"group\", xf::axis({\"a\", \"b\", \"d\", \"e\"})},\n                                        {\"city\",  xf::axis({\"London\", \"Paris\", \"Brussels\"})}}),\n                        xf::dimension({\"city\", \"group\"}));\n\nSummary\n-------\n\n.. image:: xframe_summary.png\n   :alt: xframe summay\n\n.. _pandas: https://pandas.pydata.org\n"
  },
  {
    "path": "docs/source/getting_started.rst",
    "content": ".. Copyright (c) 2018, Johan Mabille, Sylvain Corlay, Wolf Vollprecht\n   and Martin Renou\n\n   Distributed under the terms of the BSD 3-Clause License.\n\n   The full license is in the file LICENSE, distributed with this software.\n\nGetting started\n===============\n\nThis short guide explains how to get started with `xframe` once you have installed it with one of\nthe methods described in the installation section.\n\nFirst example\n-------------\n\n.. code::\n\n    #include <iostream>\n    #include \"xtensor/xrandom.hpp\"\n    #include \"xframe/xio.hpp\"\n    #include \"xframe/xvariable.hpp\"\n\n    int main(int argc, char* argv[])\n    {\n        using coordinate_type = xf::xcoordinate<xf::fstring>;\n        using variable_type = xf::xvariable<double, coordinate_type>;\n        using data_type = variable_type::data_type;\n\n        // Creation of the data\n        data_type data = xt::eval(xt::random::rand({6, 3}, 15., 25.));\n        data(0, 0).has_value() = false;\n        data(2, 1).has_value() = false;\n\n        // Creation of coordinates and dimensions\n        auto time_axis = xf::axis({\"2018-01-01\", \"2018-01-02\", \"2018-01-03\", \"2018-01-04\", \"2018-01-05\", \"2018-01-06\"});\n        auto city_axis = xf::axis({\"London\", \"Paris\", \"Brussels\"});\n        auto coord = xf::coordinate({{\"date\", time_axis}, {\"city\", city_axis}});\n        auto dim = xf::dimension({\"date\", \"city\"});\n\n        // Creation of the variable\n        auto var = variable_type(data, coord, dim);\n        std::cout << var << std::endl;\n\n        return 0;\n    }\n\nThis example creates a variable, that is, a tensor data (here random) with labels and dimension names.\n\nCompiling the first example\n---------------------------\n\n`xframe` is a header-only library, so there is no library to link with. The only constraint\nis that the compiler must be able to find the headers of `xframe` and those of its dependencies,\nthat is, `xtensor` and `xtl`; this is usually done by having the directory containing the headers\nin the include path. With GCC, use the ``-I`` option to achieve this. Assuming the first example\ncode is located in ``example.cpp``, the compilation command is:\n\n.. code:: bash\n\n    gcc -I /path/to/headers/ example.cpp -o example\n\nWhen you run the program, it produces the following output (data should be different\nsince it is randomly generated):\n\n.. code::\n\n    {{    N/A, 23.3501, 24.6887},\n     {17.2103, 18.0817, 20.4722},\n     {16.8838,     N/A, 24.9646},\n     {24.6769, 22.2584, 24.8111},\n     {16.0986, 22.9811, 17.9703},\n     {15.0478, 16.1246, 21.3976}}\n    Coordinates:\n    date: (2018-01-01, 2018-01-02, 2018-01-03, 2018-01-04, 2018-01-05, 2018-01-06, )\n    city: (London, Paris, Brussels)\n\nBuilding with cmake\n-------------------\n\nA better alternative for building programs using `xframe` is to use `cmake`, especially if you are\ndeveloping for several platforms. Assuming the following folder structure:\n\n.. code:: bash\n\n    first_example\n       |- src\n       |   |- example.cpp\n       |- CMakeLists.txt\n\nThe following minimal ``CMakeLists.txt`` is enough to build the first example:\n\n.. code:: cmake\n\n    cmake_minimum_required(VERSION 3.1)\n    project(first_example)\n\n    find_package(xtl REQUIRED)\n    find_package(xframeREQUIRED)\n\n    add_executable(first_example src/example.cpp)\n    target_link_libraries(first_example xtensor)\n\n`cmake` has to know where to find the headers, this is done through the ``CMAKE_INSTALL_PREFIX``\nvariable. Note that ``CMAKE_INSTALL_PREFIX`` is usually the path to a folder containing the following\nsubfolders: ``include``, ``lib`` and ``bin``, so you don't have to pass any additional option for linking.\nExamples of valid values for ``CMAKE_INSTALL_PREFIX`` on Unix platforms are ``/usr/local``, ``/opt``.\n\nThe following commands create a directory for building (avoid building in the source folder), builds\nthe first example with cmake and then runs the program:\n\n.. code:: bash\n\n    mkdir build\n    cd build\n    cmake -DCMAKE_INSTALL_PREFIX=your_prefix ..\n    make\n    ./first_program\n\nSecond example: simplified variable creation\n--------------------------------------------\n\n`xframe` provides many shortcuts so coordinates and variables can be created with a concise syntax.\nThe following example creates the same variable as the previous one:\n\n.. code::\n\n    #include <iostream>\n    #include \"xtensor/xrandom.hpp\"\n    #include \"xframe/xio.hpp\"\n    #include \"xframe/xvariable.hpp\"\n\n    int main(int argc, char* argv[])\n    {\n        using coordinate_type = xf::xcoordinate<xf::fstring>;\n        using variable_type = xf::xvariable<double, coordinate_type>;\n        using data_type = variable_type::data_type;\n\n        // Creation of the data\n        data_type data = xt::eval(xt::random::rand({6, 3}, 15., 25.));\n        data(0, 0).has_value() = false;\n        data(2, 1).has_value() = false;\n\n        // Creation of the variable\n        auto var = variable_type(\n            data,\n            {\n                {\"date\", xf::axis({\"2018-01-01\", \"2018-01-02\", \"2018-01-03\", \"2018-01-04\", \"2018-01-05\", \"2018-01-06\"})},\n                {\"city\", xf::axis({\"London\", \"Paris\", \"Brussels\"})}\n            }\n        );\n        std::cout << var << std::endl;\n\n        return 0;\n    }\n\nWhen compiled and run, this produces output similar to the one of the previous example (same coordinate system\nbut different data due to random generation).\n\nThird example: data access\n--------------------------\n\n`xframe` provides different ways to access data in a variable.\n\n.. code::\n\n    #include <iostream>\n    #include \"xtensor/xrandom.hpp\"\n    #include \"xframe/xio.hpp\"\n    #include \"xframe/xvariable.hpp\"\n\n    int main(int argc, char* argv[])\n    {\n\n        using coordinate_type = xf::xcoordinate<xf::fstring>;\n        using variable_type = xf::xvariable<double, coordinate_type>;\n        using data_type = variable_type::data_type;\n\n        // Creation of the data\n        data_type data = xt::eval(xt::random::rand({6, 3}, 15., 25.));\n        data(0, 0).has_value() = false;\n        data(2, 1).has_value() = false;\n\n        // Creation of the variable\n        auto var = variable_type(\n            data,\n            {\n                {\"date\", xf::axis({\"2018-01-01\", \"2018-01-02\", \"2018-01-03\", \"2018-01-04\", \"2018-01-05\", \"2018-01-06\"})},\n                {\"city\", xf::axis({\"London\", \"Paris\", \"Brussels\"})}\n            }\n        );\n\n        // Data access\n        std::cout << \"operator() - \" << var(3, 0) << std::endl;\n        std::cout << \"locate     - \" << var.locate(\"2018-01-04\", \"London\") << std::endl;\n        std::cout << \"iselect    - \" << var.iselect({{\"date\", 3}, {\"city\", 0}}) << std::endl;\n        std::cout << \"select     - \" << var.select({{\"date\", \"2018-01-04\"}, {\"city\", \"London\"}}) << std::endl;\n\n        return 0;\n    }\n\nOutputs:\n\n.. code::\n\n    operator() - 24.6769\n    locate     - 24.6769\n    iselect    - 24.6769\n    select     - 24.6769\n\n"
  },
  {
    "path": "docs/source/index.rst",
    "content": ".. Copyright (c) 2018, Johan Mabille, Sylvain Corlay, Wolf Vollprecht\n   and Martin Renou\n\n   Distributed under the terms of the BSD 3-Clause License.\n\n   The full license is in the file LICENSE, distributed with this software.\n\n.. image:: xframe.svg\n   :alt: xframe\n\nMulti-dimensional labeled arrays and data frame based on `xtensor`_.\n\nIntroduction\n------------\n\n`xframe` is a C++ library meant for numerical analysis with multi-dimensional\nlabeled array expressions (also referred as variable expressions) and data frame\nexpressions. It is built upon `xtensor`_ and provides similar features:\n\n- an extensible expression system enabling **lazy broadcasting** based on dimension\n  names.\n- an API following the idioms of the C++ standard library.\n- tools to manipulate variable expressions and build upon *xframe*.\n\nThe API of `xframe` is inspired by the ones of `pandas`_ and `xarray`_.\n\n`xframe` requires a modern C++ compiler supporting C++14. The following C++\ncompilers are supported:\n\n- On Windows platforms, Visual C++ 2015 Update 2, or more recent\n- On Unix platforms, gcc 4.9 or a recent version of Clang\n\nLicensing\n---------\n\nWe use a shared copyright model that enables all contributors to maintain the\ncopyright on their contributions.\n\nThis software is licensed under the BSD-3-Clause license. See the LICENSE file\nfor details.\n\n\n.. toctree::\n   :caption: INSTALLATION\n   :maxdepth: 1\n\n   installation\n\n.. toctree::\n   :caption: USAGE\n   :maxdepth: 2\n\n   getting_started\n   data_structure\n   indexing\n   computation\n\n.. toctree::\n   :caption: API REFERENCE\n   :maxdepth: 2\n\n   api/axis_index\n   api/coordinate_index\n   api/variable_index\n\n.. toctree::\n   :caption: MISCELLANEOUS\n\n   xarray\n\n.. _xtensor: https://github.com/xtensor-stack/xtensor\n.. _pandas: https://pandas.pydata.org\n.. _xarray: https://xarray.pydata.org\n"
  },
  {
    "path": "docs/source/indexing.rst",
    "content": ".. Copyright (c) 2018, Johan Mabille, Sylvain Corlay, Wolf Vollprecht\n   and Martin Renou\n\n   Distributed under the terms of the BSD 3-Clause License.\n\n   The full license is in the file LICENSE, distributed with this software.\n\nIndexing and selecting data\n===========================\n\nIn this section, we consider the following variable:\n\n.. code::\n\n    using coordinate_type = xf::xcoordinate<xf::fstring>;\n    using dimension_type = xf::xdimension<xf::fstring>;\n    using variable_type = xf::xvariable<double, coordinate_type>;\n\n    data_type d = xt::eval(xt::random::rand({6, 3}, 15., 25.));\n    variable_type v(std::move(d),\n                    {\n                        {\"group\", xf::axis({\"a\", \"b\", \"d\", \"e\", \"g\", \"h\"})},\n                        {\"city\",  xf::axis({\"London\", \"Paris\", \"Brussels\"})}\n                    });\n\nPrinting this variable in a Jupyter Notebook gives:\n\n+-------+---------+---------+----------+\n|       | London  |  Paris  | Brussels |\n+=======+=========+=========+==========+\n| **a** | 16.3548 | 23.3501 | 24.6887  |\n+-------+---------+---------+----------+\n| **b** | 17.2103 | 18.0817 | 20.4722  |\n+-------+---------+---------+----------+\n| **d** | 16.8838 | 24.9288 | 24.9646  |\n+-------+---------+---------+----------+\n| **e** | 24.6769 | 22.2584 | 24.8111  |\n+-------+---------+---------+----------+\n| **g** | 16.0986 | 22.9811 | 17.9703  |\n+-------+---------+---------+----------+\n| **h** | 15.0478 | 16.1246 | 21.3976  |\n+-------+---------+---------+----------+\n\n`xframe` provides flexible indexing methods for data selection, similar to the\nones of `xarray`_. These methods are summarized in the following table:\n\n+------------------+--------------+---------------------------------------------------+\n| Dimension lookup | Index lookup | ``xvariable`` syntax                              |\n+==================+==============+===================================================+\n| Positional       | By integer   | ``v(2, 1)``                                       |\n+------------------+--------------+---------------------------------------------------+\n| Positional       | By label     | ``v.locate(\"d\", \"Paris\")``                        |\n+------------------+--------------+---------------------------------------------------+\n| By name          | By integer   | ``v.iselect({{\"group\", 2}, {\"city\", 1}})``        |\n+------------------+--------------+---------------------------------------------------+\n| By name          | By label     | ``v.select({{\"group\", \"d\"}, {\"city\", \"Paris\"}})`` |\n+------------------+--------------+---------------------------------------------------+\n\nPositional indexing\n-------------------\n\nThe most basic way to access elements of an ``xvariable`` is to use ``operator()``, like\nyou would do with an ``xtensor``:\n\n.. code::\n\n    std::cout << v(2, 1) << std::endl;\n\nContrary to Python, it is not possible to have different return types for a same method\nin C++. Multi selection is done with free functions that return views on the variable:,\n\n.. code::\n\n    #include \"xvariable_view.hpp\"\n\n    auto view1 = xf::ilocate(v, xf::irange(0, 5, 2), xf::irange(1, 3));\n    std::cout << view1 << std::endl;\n\n+-------+---------+----------+\n|       |  Paris  | Brussels |\n+=======+=========+==========+\n| **a** | 23.3501 | 24.6887  |\n+-------+---------+----------+\n| **d** | 24.9288 | 24.9646  |\n+-------+---------+----------+\n| **g** | 22.9811 | 17.9703  |\n+-------+---------+----------+\n\nTherefore a change in the view will reflect in the underlying variable:\n\n.. code::\n\n    view1(0, 1) = 0.;\n    std::cout << v(2, 2) << std::endl;\n    // Outputs 0.\n\nIn the code creating the view, ``irange`` returns a range slice from `xtensor`, so any multi\nselection in `xtensor` is also supported in `xframe`.\n\n``xvariable`` also supports label-based indexing, with the ``locate`` method for single\npoint selection, and ``locate`` free function for multi selection:\n\n.. code::\n\n    std::cout << v.locate(\"d\", \"Paris\") << std::endl;\n    auto view2 = xf::locate(v, xf::range(\"a\", \"h\", 2), xf::range(\"Paris\", \"Brussels\"));\n    std::cout << view2 << std::endl;\n    // Same output as previous code\n\nBe aware of the difference between ``range`` and ``irange`` parameters: for the former one,\naccepting labels, the last value is *included* while for the latter one, accepting integral\nindices, the las value is *excluded*.\n\n`xframe` provides label-based slices similar to those of `xtensor`, so label-based\nmulti selection is really similar to positional multi selection.\n\nIndxing with dimension names\n----------------------------\n\nWith the dimension names, we do not have to rely on the dimension order. We can use them\nexplicitely to select data; Like positional indexing, `xframe` provides methods and\nfree functions depending on the kind of selection you want to do:\n\n.. code::\n\n    // Dimension by name, index by position\n    std::cout << v.iselect({{\"city\", 1}, {\"group\", 2}}) << std::endl;\n    auto view3 = xf::iselect(v, {{\"city\", xf::irange(1, 3)}, {\"group\", xf::irange(0, 5, 2)}});\n    \n    // Dimension by name, index by label\n    std::cout << v.select({{\"city\", \"Paris\"}, {\"group\", \"d\"}}) << std::endl;\n    auto view4 = xf::select(v, {{\"city\", xf::range(\"Paris\", \"Brussels\")}, {\"group\", xf::range(\"a\", \"h\", 2)}});\n    // view3 and view4 gives the same output as view2 and view1\n\nContrary to `xarray`_, `xframe` does not provide a selection operator accepting a map\nargument.\n\nKeeping and dropping labels\n---------------------------\n\n``drop`` and ``keep`` functions return slices that can be used to create a view with\nthe listed labels along the specified dimensions dropped or kept:\n\n.. code::\n\n    auto view5 = xf::select(v, {{\"city\", xf::drop(\"London\")}, {\"group\", xf::keep(\"a\", \"d\", \"g\")}});\n    // view5 is equivalent to view4\n\nThis is different form `xarray`_  where the ``xarray.DataArray.drop`` method returns a new object.\nTo achieve the same with `xframe`, simply assign the view to a new ``xvariable`` object:\n\n.. code::\n\n    variable_type v2 = view5;\n\nMasking views\n-------------\n\nMasking views allow to select data points based on conditions expresses on labels. These conditions\ncan be arbitrary complicated boolean expressions. Contrary to other views which are generally a\nsubset of the original data, a masking view has the same shape as its underlying ``xvariable``.\n\nMasking views are created with the ``where`` function:\n\n.. code::\n\n    data_type d2 = {{ 1.,  2., 3. },\n                    { 4.,  5., 6. },\n                    { 7.,  8., 9. }};\n\n    auto v3 = variable_type(\n        d2,\n        {\n            {\"x\", xf::axis(3)},\n            {\"y\", xf::axis(3)},\n        }\n    );\n\n    auto view6 = xf::where(\n        v3,\n        not_equal(v3.axis<int>(\"x\"), 2) && v3.axis<int>(\"y\") < 2\n    );\n    std::cout << view6 << std::endl;\n\nIn a Jupyter Notebookn, this outputs the following:\n\n+-------+--------+--------+--------+\n|       |    0   |    1   |    2   |\n+=======+========+========+========+\n| **0** |    1   |    2   | masked |\n+-------+--------+--------+--------+\n| **1** |    4   |    5   | masked |\n+-------+--------+--------+--------+\n| **2** | masked | masked | masked |\n+-------+--------+--------+--------+\n\nWhen assigning to a masked view, masked values are not changed. Like other views,\na masking view is a proxy on its underlying variable, no copy is made, so changing\nan unmasked value actually changes the corresponding value in the undnerlying variable.\n\nAssigning values with indexing\n------------------------------\n\nData selection in variables return either references or views; therefore, contrary to\n`xarray`_, it is *possible* to assign values to a subset of a variable with any of the\nindexing method:\n\n.. code::\n\n    // The next four lines are equivalent, they change a single value of v:\n    v(2, 1) = 2.5;\n    v.locate(\"d\", \"Paris\") = 2.5;\n    v.iselect({{\"city\", 1}, {\"group\", 2}}) = 2.5;\n    v.select({{\"city\", \"Paris\"}, {\"group\", \"d\"}}) = 2.5;\n\n    data_type d3 = {{0.,  1.},\n                    {2.,  3.},\n                    {4.,  5.}};\n\n    auto v4 = variable_type(\n        d3,\n        {\n            {\"group\", xf::axis({\"a\", \"d\", \"g\"})},\n            {\"city\", xf::axis({\"Paris\", \"Brussels\"})}\n        }\n    );\n\n    // The next four lines are equivalent, they change a subset of v\n    xf::ilocate(v, xf::irange(0, 5, 2), xf::irange(1, 3)) = v4;\n    xf::locate(v, xf::range(\"a\", \"h\", 2), xf::range(\"Paris\", \"Brussels\")) = v4;\n    xf::iselect(v, {{\"city\", xf::irange(1, 3)}, {\"group\", xf::irange(0, 5, 2)}}) = v4;\n    xf::select(v, {{\"city\", xr::range(\"Paris\", \"Brussels\")}, {\"group\", xf::range(\"a\", \"h\", 2)}}) = v4;\n\nPrinting ``v`` after the assign gives\n\n+-------+---------+---------+----------+\n|       | London  |  Paris  | Brussels |\n+=======+=========+=========+==========+\n| **a** | 16.3548 |    0    |    1     |\n+-------+---------+---------+----------+\n| **b** | 17.2103 | 18.0817 | 20.4722  |\n+-------+---------+---------+----------+\n| **d** | 16.8838 |    2    |    3     |\n+-------+---------+---------+----------+\n| **e** | 24.6769 | 22.2584 | 24.8111  |\n+-------+---------+---------+----------+\n| **g** | 16.0986 |    4    |    5     |\n+-------+---------+---------+----------+\n| **h** | 15.0478 | 16.1246 | 21.3976  |\n+-------+---------+---------+----------+\n\nReindexing views\n----------------\n\nReindexing views give variables new set of coordinates to corresponding dimensions. Like other views,\nno copy is involved. Asking for values corresponding to new labels not found in the original set of\ncoordinates returns missing values. In the next example, we reindex the ``city`` dimension:\n\n.. code::\n\n    auto view7 = xf::reindex(v, {{\"city\", xf::axis({\"London\", \"New York\", \"Brussels\"})}});\n\n+-------+---------+----------+----------+\n|       | London  | New York | Brussels |\n+=======+=========+==========+==========+\n| **a** | 16.3548 |   N/A    | 24.6887  |\n+-------+---------+----------+----------+\n| **b** | 17.2103 |   N/A    | 20.4722  |\n+-------+---------+----------+----------+\n| **d** | 16.8838 |   N/A    | 24.9646  |\n+-------+---------+----------+----------+\n| **e** | 24.6769 |   N/A    | 24.8111  |\n+-------+---------+----------+----------+\n| **g** | 16.0986 |   N/A    | 17.9703  |\n+-------+---------+----------+----------+\n| **h** | 15.0478 |   N/A    | 21.3976  |\n+-------+---------+----------+----------+\n\nLike `xarray`_, `xframe` provides the useful ``reindex_like`` shortcut which allows to reindex a\nvariable given the set of coordinates of another variable:\n\n.. code::\n\n    auto v5 = variable_type(\n        d,\n        {\n            {\"group\", xf::axis({\"a\", \"b\", \"d\", \"e\", \"g\", \"h\"})},\n            {\"city\", xf::axis({\"London\", \"New York\", \"Brussels\"})}\n        }\n    );\n\n    auto view8 = xf::reindex_like(v, v5);\n    // view8 is equivalent to view7\n\nA reindexing view is a read-only view, it is not possible to change its value with indexing.\nThis allows memory optimizations, the view does not have to store the missing values, it can\nreturn a proxy to a static-allocated missing value.\n\nThe ``align`` function allows to reindex many variables with more flexible options:\n\n.. code::\n\n    auto t1 = xf::align<join::inner>(v, v5);\n    std::cout << std::get<0>(t1) << std::endl;\n    std::cout << std::get<1>(t1) << std::endl;\n\nThe last lines print the same output:\n\n+-------+---------+----------+\n|       | London  | Brussels |\n+=======+=========+==========+\n| **a** | 16.3548 | 24.6887  |\n+-------+---------+----------+\n| **b** | 17.2103 | 20.4722  |\n+-------+---------+----------+\n| **d** | 16.8838 | 24.9646  |\n+-------+---------+----------+\n| **e** | 24.6769 | 24.8111  |\n+-------+---------+----------+\n| **g** | 16.0986 | 17.9703  |\n+-------+---------+----------+\n| **h** | 15.0478 | 21.3976  |\n+-------+---------+----------+\n\nIn the following, the variables are aligned w.r.t the union of the coordinates instead\nof their intersection:\n\n.. code::\n\n    auto t2 = xf::align<join::outer>(v, v5);\n    std::cout << std::get<0>(t2) << std::endl;\n    std::cout << std::get<1>(t2) << std::endl;\n\nThe first outuput is\n\n+-------+---------+---------+----------+----------+\n|       | London  |  Paris  | Brussels | New York |\n+=======+=========+=========+==========+==========+\n| **a** | 16.3548 | 23.3501 | 24.6887  |   N/A    |\n+-------+---------+---------+----------+----------+\n| **b** | 17.2103 | 18.0817 | 20.4722  |   N/A    |\n+-------+---------+---------+----------+----------+\n| **d** | 16.8838 | 24.9288 | 24.9646  |   N/A    |\n+-------+---------+---------+----------+----------+\n| **e** | 24.6769 | 22.2584 | 24.8111  |   N/A    |\n+-------+---------+---------+----------+----------+\n| **g** | 16.0986 | 22.9811 | 17.9703  |   N/A    |\n+-------+---------+---------+----------+----------+\n| **h** | 15.0478 | 16.1246 | 21.3976  |   N/A    |\n+-------+---------+---------+----------+----------+\n\nWhile the second have ``N/A`` in the ``Paris`` column.\n\n.. _xarray: https://xarray.pydata.org\n"
  },
  {
    "path": "docs/source/installation.rst",
    "content": ".. Copyright (c) 2018, Johan Mabille, Sylvain Corlay and Wolf Vollprecht\n   and Martin Renou\n\n   Distributed under the terms of the BSD 3-Clause License.\n\n   The full license is in the file LICENSE, distributed with this software.\n\n\n.. raw:: html\n\n   <style>\n   .rst-content .section>img {\n       width: 30px;\n       margin-bottom: 0;\n       margin-top: 0;\n       margin-right: 15px;\n       margin-left: 15px;\n       float: left;\n   }\n   </style>\n\nInstallation\n============\n\nAlthough ``xframe`` is a header-only library, we provide standardized means to\ninstall it, with package managers or with cmake.\n\nBesides the xframe headers, all these methods place the ``cmake`` project\nconfiguration file in the right location so that third-party projects can use\ncmake's ``find_package`` to locate xframe headers.\n\n.. image:: conda.svg\n\nUsing the conda-forge package\n-----------------------------\n\nA package for xframe is available for the mamba (or conda) package manager.\n\n.. code::\n\n    mamba install -c conda-forge xframe\n\n.. image:: cmake.svg\n\nFrom source with cmake\n----------------------\n\nYou can also install ``xframe`` from source with cmake. This requires that you\nhave the xtensor_ library installed on your system. On Unix platforms,\nfrom the source directory:\n\n.. code::\n\n    mkdir build\n    cd build\n    cmake -DCMAKE_INSTALL_PREFIX=path_to_prefix ..\n    make install\n\nOn Windows platforms, from the source directory:\n\n.. code::\n\n    mkdir build\n    cd build\n    cmake -G \"NMake Makefiles\" -DCMAKE_INSTALL_PREFIX=path_to_prefix ..\n    nmake\n    nmake install\n\n``path_to_prefix`` is the absolute path to the folder where cmake searches for\ndependencies and installs libraries. ``xframe`` installation from cmake assumes\nthis folder contains ``include`` and ``lib`` subfolders.\n\nIncluding xframe in your project\n--------------------------------\n\nThe different packages of ``xframe`` are built with cmake, so whatever the\ninstallation mode you choose, you can add ``xframe`` to your project using cmake:\n\n.. code::\n\n    find_package(xframe REQUIRED)\n    target_include_directories(your_target PUBLIC ${xframe_INCLUDE_DIRS})\n    target_link_libraries(your_target PUBLIC xframe)\n\n.. _xtensor: https://github.com/xtensor-stack/xtensor\n"
  },
  {
    "path": "docs/source/xarray.rst",
    "content": ".. Copyright (c) 2018, Johan Mabille, Sylvain Corlay, Wolf Vollprecht\n   and Martin Renou\n\n   Distributed under the terms of the BSD 3-Clause License.\n\n   The full license is in the file LICENSE, distributed with this software.\n\nFrom xarray to xframe\n=====================\n\n.. raw:: html\n\n   <style>\n   .rst-content table.docutils {\n       width: 100%;\n       table-layout: fixed;\n       border: none;\n   }\n\n   table.docutils th {\n       text-align: center;\n   }\n\n   table.docutils .line-block {\n       margin-left: 0;\n       margin-bottom: 0;\n   }\n\n   table.docutils code.literal {\n       color: initial;\n   }\n\n   code.docutils {\n       background: initial;\n       border: none;\n   }\n\n   * {\n       border: none;\n   }\n\n   .rst-content table.docutils thead {\n       background-color: #d0e0e0;\n   }\n\n   .rst-content table.docutils td {\n       border-bottom: none;\n       border-left: none;\n   }\n\n   .rst-content table.docutils tr:hover {\n       background-color: #d0e0e0;\n   }\n\n   .rst-content table.docutils:not(.field-list) tr:nth-child(2n-1):hover td {\n       background-color: initial;\n   }\n\n   #linear-algebra table.docutils thead .row-odd {\n       background: #ffdddd;\n   }\n\n   #linear-algebra tr:nth-child(2n-1) td {\n       background: #f9f3f3;\n   }\n\n   #linear-algebra tr:hover {\n       background: #ffdddd;\n   }\n\n   #linear-algebra tr:nth-child(2n-1):hover td {\n       background-color: initial;\n   }\n   </style>\n\n.. |_| unicode:: 0xA0\n\nContainers\n----------\n\n+------------------------------------------------+--------------------------------------------------+\n|             Python 3 - xarray                  |               C++ 14 - xframe                    |\n+================================================+==================================================+\n| | ``xr.DataArray([[1, 2], [3, 4]],``           | | ``xf::variable<double>({{1, 2}, {3, 4}},``     |\n| | |_| |_| |_| ``[('x', ['a', 'b']),``          | | |_| |_| |_| ``{{\"x\", xf::axis({\"a\", \"b\"})},``  |\n| | |_| |_| |_| |_| ``('y', [1, 4])])``          | | |_| |_| |_| |_| ``{\"y\", xf::axis({1, 4})}})``  |\n+------------------------------------------------+--------------------------------------------------+\n\nIndexing\n--------\n\n`xframe` returns views for multi-selection, no copy is made.\n\n+-----------------------------------------------+-------------------------------------------------------------+\n|             Python 3 - xarray                 |                      C++ 14 - xframe                        |\n+===============================================+=============================================================+\n| ``da[0, 1]``                                  | ``v(0, 1)``                                                 |\n+-----------------------------------------------+-------------------------------------------------------------+\n| ``da.loc['a', 'Paris']``                      | ``v.locate(\"a\", \"Paris\")``                                  |\n+-----------------------------------------------+-------------------------------------------------------------+\n| ``da.isel(city=1, group=0)``                  | ``v.iselect({{\"city\", 1}, {\"group\", 0}})``                  |\n+-----------------------------------------------+-------------------------------------------------------------+\n| ``da.sel(city='Paris', group='a')``           | ``v.select({{\"city\", \"Paris\"}, {\"group\", \"a\"}})``           |\n+-----------------------------------------------+-------------------------------------------------------------+\n| ``da[:, 1]``                                  | ``xf::ilocate(v, xf::iall(), 1)``                           |\n+-----------------------------------------------+-------------------------------------------------------------+\n| ``da.loc[:, 'Paris']``                        | ``xf::locate(v, xf::all(), \"Paris\")``                       |\n+-----------------------------------------------+-------------------------------------------------------------+\n| ``da.isel(city=1)``                           | ``xf::iselect(v, {{\"city\", 1}})``                           |\n+-----------------------------------------------+-------------------------------------------------------------+\n| ``da.sel(city='Paris')``                      | ``xf::select(v, {{\"city\", \"Paris\"}})``                      |\n+-----------------------------------------------+-------------------------------------------------------------+\n| ``da.reindex(city=['NYC', 'Paris'])``         | ``xf::reindex(v, {{\"city\", xf::axis({\"NYC\", \"Paris\"})}})``  |\n+-----------------------------------------------+-------------------------------------------------------------+\n| ``da.reindex_like(df)``                       | ``xf::reindex_like(v, v2)``                                 |\n+-----------------------------------------------+-------------------------------------------------------------+\n\nLogical\n-------\n\nLogical universal functions are truly lazy. ``xf::where(condition, a, b)`` does not evaluate ``a``\nwhere ``condition`` is falsy, and it does not evaluate ``b`` where ``condition`` is truthy.\n`xarray` relies on `numpy` functions, that can also operate on ``xarray.DataArray``.\n\n+-----------------------------------------------+-----------------------------------------------+\n|            Python 3 - xarray                  |                C++ 14 - xframe                |\n+===============================================+===============================================+\n| ``xr.where(a > 5, a, b)``                     | ``xf::where(a > 5, a, b)``                    |\n| ``xr.where(a > 5, 100, a)``                   | ``xf::where(a > 5, 100, a)``                  |\n+-----------------------------------------------+-----------------------------------------------+\n| ``np.any(a)``                                 | ``xf::any(a)``                                |\n+-----------------------------------------------+-----------------------------------------------+\n| ``np.all(a)``                                 | ``xf::all(a)``                                |\n+-----------------------------------------------+-----------------------------------------------+\n| ``np.logical_and(a, b)``                      | ``a && b``                                    |\n+-----------------------------------------------+-----------------------------------------------+\n| ``np.logical_or(a, b)``                       | ``a || b``                                    |\n+-----------------------------------------------+-----------------------------------------------+\n| ``np.isclose(a, b)``                          | ``xf::isclose(a, b)``                         |\n+-----------------------------------------------+-----------------------------------------------+\n| ``np.allclose(a, b)``                         | ``xf::allclose(a, b)``                        |\n+-----------------------------------------------+-----------------------------------------------+\n\nComparisons\n-----------\n\n`xarray` relies on `numpy` functions, that can also operate on ``xarray.DataArray``.\n\n+-----------------------------------------------+-----------------------------------------------+\n|            Python 3 - xarray                  |                C++ 14 - xframe                |\n+===============================================+===============================================+\n| ``np.equal(a, b)``                            | ``xf::equal(a, b)``                           |\n+-----------------------------------------------+-----------------------------------------------+\n| ``np.not_equal(a, b)``                        | ``xf::not_equal(a, b)``                       |\n+-----------------------------------------------+-----------------------------------------------+\n| ``np.less(a, b)``                             || ``xf::less(a, b)``                           |\n|                                               || ``a < b``                                    |\n+-----------------------------------------------+-----------------------------------------------+\n| ``np.less_equal(a, b)``                       || ``xf::less_equal(a, b)``                     |\n|                                               || ``a <= b``                                   |\n+-----------------------------------------------+-----------------------------------------------+\n| ``np.greater(a, b)``                          || ``xf::greater(a, b)``                        |\n|                                               || ``a > b``                                    |\n+-----------------------------------------------+-----------------------------------------------+\n| ``np.greater_equal(a, b)``                    || ``xf::greater_equal(a, b)``                  |\n|                                               || ``a >= b``                                   |\n+-----------------------------------------------+-----------------------------------------------+\n\nMathematical functions\n----------------------\n\nxframe universal functions are provided for a large set number of mathematical functions.\n`xarray` relies on `numpy` functions, that can also operate on ``xarray.DataArray``.\n\n**Basic functions:**\n\n+-----------------------------------------------+-----------------------------------------------+\n|            Python 3 - xarray                  |                C++ 14 - xframe                |\n+===============================================+===============================================+\n| ``np.absolute(a)``                            | ``xf::abs(a)``                                |\n+-----------------------------------------------+-----------------------------------------------+\n| ``np.sign(a)``                                | ``xf::sign(a)``                               |\n+-----------------------------------------------+-----------------------------------------------+\n| ``np.remainder(a, b)``                        | ``xf::remainder(a, b)``                       |\n+-----------------------------------------------+-----------------------------------------------+\n| ``np.clip(a, min, max)``                      | ``xf::clip(a, min, max)``                     |\n+-----------------------------------------------+-----------------------------------------------+\n|                                               | ``xf::fma(a, b, c)``                          |\n+-----------------------------------------------+-----------------------------------------------+\n\n**Exponential functions:**\n\n+-----------------------------------------------+-----------------------------------------------+\n|            Python 3 - xarray                  |                C++ 14 - xframe                |\n+===============================================+===============================================+\n| ``np.exp(a)``                                 | ``xf::exp(a)``                                |\n+-----------------------------------------------+-----------------------------------------------+\n| ``np.expm1(a)``                               | ``xf::expm1(a)``                              |\n+-----------------------------------------------+-----------------------------------------------+\n| ``np.log(a)``                                 | ``xf::log(a)``                                |\n+-----------------------------------------------+-----------------------------------------------+\n| ``np.log1p(a)``                               | ``xf::log1p(a)``                              |\n+-----------------------------------------------+-----------------------------------------------+\n\n**Power functions:**\n\n+-----------------------------------------------+-----------------------------------------------+\n|            Python 3 - xarray                  |                C++ 14 - xframe                |\n+===============================================+===============================================+\n| ``np.power(a, p)``                            | ``xf::pow(a, b)``                             |\n+-----------------------------------------------+-----------------------------------------------+\n| ``np.sqrt(a)``                                | ``xf::sqrt(a)``                               |\n+-----------------------------------------------+-----------------------------------------------+\n| ``np.square(a)``                              | ``xf::square(a)``                             |\n|                                               | ``xf::cube(a)``                               |\n+-----------------------------------------------+-----------------------------------------------+\n| ``np.cbrt(a)``                                | ``xf::cbrt(a)``                               |\n+-----------------------------------------------+-----------------------------------------------+\n\n**Trigonometric functions:**\n\n+-----------------------------------------------+-----------------------------------------------+\n|            Python 3 - xarray                  |                C++ 14 - xframe                |\n+===============================================+===============================================+\n| ``np.sin(a)``                                 | ``xf::sin(a)``                                |\n+-----------------------------------------------+-----------------------------------------------+\n| ``np.cos(a)``                                 | ``xf::cos(a)``                                |\n+-----------------------------------------------+-----------------------------------------------+\n| ``np.tan(a)``                                 | ``xf::tan(a)``                                |\n+-----------------------------------------------+-----------------------------------------------+\n\n**Hyperbolic functions:**\n\n+-----------------------------------------------+-----------------------------------------------+\n|            Python 3 - xarray                  |                C++ 14 - xframe                |\n+===============================================+===============================================+\n| ``np.sinh(a)``                                | ``xf::sinh(a)``                               |\n+-----------------------------------------------+-----------------------------------------------+\n| ``np.cosh(a)``                                | ``xf::cosh(a)``                               |\n+-----------------------------------------------+-----------------------------------------------+\n| ``np.tanh(a)``                                | ``xf::tanh(a)``                               |\n+-----------------------------------------------+-----------------------------------------------+\n\n**Error and gamma functions:**\n\n+-----------------------------------------------+-----------------------------------------------+\n|            Python 3 - xarray                  |                C++ 14 - xframe                |\n+===============================================+===============================================+\n| ``scipy.special.erf(a)``                      | ``xf::erf(a)``                                |\n+-----------------------------------------------+-----------------------------------------------+\n| ``scipy.special.gamma(a)``                    | ``xf::tgamma(a)``                             |\n+-----------------------------------------------+-----------------------------------------------+\n| ``scipy.special.gammaln(a)``                  | ``xf::lgamma(a)``                             |\n+-----------------------------------------------+-----------------------------------------------+\n"
  },
  {
    "path": "docs/source/xframe_summary_drawio.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<mxfile modified=\"2019-01-22T08:40:54.529Z\" host=\"www.draw.io\" agent=\"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/71.0.3578.98 Chrome/71.0.3578.98 Safari/537.36\" etag=\"Ukd6bYewr-A5ItxCvbHP\" version=\"10.1.3-4\" type=\"google\"><diagram id=\"cwnSat86R0DeLljoPVqK\" name=\"Page-1\">7Z3dc6M2EMD/Gs+0D70BBNg8xo5z7fTaaece2t5LhxjFpoeRC3Ji96+vMOJz1x8Xg3ACfriDBcuwP620u6zIiMzWu4+Ru1n9wjwajAzN243I/cgwdMd0xH+JZC8lumamkmXke1JWCD77/1Ep1KR063s0rpzIGQu4v6kKFywM6YJXZG4UsZfqaU8sqP7qxl1SIPi8cAMo/cP3+CqVTiytkP9I/eWK5/cnj6zd7GQpiFeux15KIjIfkVnEGE+31rsZDRLtZXpJv/dw5Gh+YREN+SVfsOa7TyR4Cb/8tFxv519+5/TnyQ+WkTbz7AZbecfyavk+U0HEtqFHk1a0EZm+rHxOP2/cRXL0RVAXshVfB2JPF5tPLOSSop6c7gb+MhQ7Uaqj6ZMfBDMWsEjIQhaK86Yxj9hXmglHBiE2cYj4vannxqvDDyctw/uVKnimEae7kkje/0fK1pRHe3GKPDqRKGRnJBmrl4KsZUvZqkw1Y+jK3rTMmy4ULjakzr9B/4bTY/3rk+71P+mx/u3O1a8D7e/cnR83hsDQMP1qmuNomjwTk6ffyMZ7oxnlO1XlI31fdxDlT1rr+kD3+v1h3tps/HA5IneAgrhRXlV1VbWyPyNdvG4FidZ8McneSfna97zkV1C0VfgNkKjbAYICI0HaImEBTVNPOCFyl0V8xZYsdIN5Ia0ppYTkH8r5XnZ/d8uZEBUtfGJsk6NzI36XeEjJb2xomMke/OTqD83S0KudISSV4+L2/yzv/JXsfLCy3ftd+eD9/hzDmG2jBT2hKuk8iutcUn7iPDs9L9HjyR4R0cDl/nPV2cMAy6/+xnxxyXlPsvRqT3Ksagvpdcov1XpJfhWv7zgmMOHAfaTBteNnyX7FqPhw+GDjqK6NiTOH42gub2UcJeetd6LSem0AYcNin/ssvA5DK8qzjNtS3hgoj+7c9SZRWH/mn9y/6moCusAJLk0Fi8CNY39x2uk6qqazQ3LZG0WUkMmuHLnro4hu1pSbTkVg6AYN2dqZhlqeAy4IIEvspD28J3DWK8GBhupRTsvgMtehN+RMoyFyoKH6wNg2ORi2vnNydlPk6g2pJgeD3vdNzqrPTq8lBxpSTY70jZzZFLl6Q6rJwShVA+iud+0XgiONrvPt68nbo33kG6LV8RGMpV5kIL1I1453mOtSrhbAIe7ADhL1P0Zia8nzO+8DIFO/NUAwoWD0GpB1a4Bg0oL0GpBza4BgPsPsDw6L3BqOvqUorKZSFKAhxa6bgQW69r/bpGRl6habb8S4jj2maMDogJuHPFtXanSZjaHoHgd0JxzAztFhoW7Giw7oTriGnaODsW7BazmgO+E0do4OxsUFL39Ad8LB7BwdjJhhSc1tYmoCx61lmAwYHxfmsxss6QS6ri0ps+xyQeaCscjzQ5dTAKzZssyHB8chBGo8l6soyzSQmnC1dZkEBl2/in/6WJiJwVBaGEMI0PVQmnlMV5fWZhI5OasuzjR0tdWZBAYDnr+mYXwoDdRCd93AiFoaJ+/mpk4MbGStHWm5IBOzWqVFhQS68g0sK7iRZQT1Cs7utQ297x7WcBqI1612qsK87pry45W7STYX2yjYTyN38TUZqM91/EJ32AKnWucnxHEO1eJ1XE0MNHVfzbzMXa6n35vTOVY4m+fHH+OFH8dvPk2eTx4NEDSzwPwEQRMh2NoCNII9m8p4FXHPQPAowXHHBE0YsrYz7ygApR0+DYEanx8sdaWgkIeJAygEFGJRakEZAFTiPX83Gk+PPP0Vv6MdebpYPUSPHyo/HRnff99Cvwjo05V+49leIR3/JnrF5PxMqWcBrZpuAR9LZt1CS2GS9D/dGAAiADGzVgsQCYtLCYnmc7vlyBdEz7atabMZZJDLG2BQixcIss5ObW7XhLFyXxfdCxgfNDJxrPHEnhCNWDZgozR+NsdA9UOq95iuZNx7NtWbvf5JdaqXEMUL8WEioBepXmxEVZp8NGH8/oZW33euviwz1u/cLUFcM7UvgLlgQek7y92SC0sdWsvdWqeqLIfc7fnMX060q8yfdarYcsjdXkAQsUG1BJGayyElCFOCmKkpTQlaMG4dQGGgEItSCwo+BdZawKQgE9cgpMn5YU9tJs6C4aI+UDrvXiim1Od385pIaKr45bA2DE5Lxch/x/uY03VjRI7krS9+GaJ9+GBBVfJpJZ9tYs+ElOazbQPxC+5v3y8wzHYHM0Cq6yoJG0a77/zZT/2FRaixZEvT1RgLjFff++IKYl4AAUv7tAcBW+b3BnIDbY9Y9TezdT9iISFnb7wvC7ET1d4XUts6TO1G0eMzVF2nQW0Ypuy4mNjFzRsa3W0iGncyyedKbxFGfZK30NBe5SQ/RoKWZzfy3ceg7Sn+rMJVrJ9ECSid4cfYw7RhhgczfOcD1xgGjz2P743xBcbUUIAvdou/PZbWwRR/wo3M/wc=</diagram></mxfile>"
  },
  {
    "path": "environment-dev.yml",
    "content": "name: xframe\nchannels:\n  - conda-forge\ndependencies:\n  - cmake\n  - xtensor=0.21.4\n\n"
  },
  {
    "path": "environment.yml",
    "content": "name: xframe\nchannels:\n  - QuantStack\n  - conda-forge\ndependencies:\n  - xframe=0.3.0\n  - xeus-cling=0.8.1\n  - notebook\n"
  },
  {
    "path": "include/xframe/xaxis.hpp",
    "content": "/***************************************************************************\n* Copyright (c) Johan Mabille, Sylvain Corlay, Wolf Vollprecht and         *\n* Martin Renou                                                             *\n* Copyright (c) QuantStack                                                 *\n*                                                                          *\n* Distributed under the terms of the BSD 3-Clause License.                 *\n*                                                                          *\n* The full license is in the file LICENSE, distributed with this software. *\n****************************************************************************/\n\n#ifndef XFRAME_XAXIS_HPP\n#define XFRAME_XAXIS_HPP\n\n#include <initializer_list>\n#include <iterator>\n#include <algorithm>\n#include <map>\n#include <type_traits>\n#include <unordered_map>\n#include <vector>\n\n#include \"xtl/xiterator_base.hpp\"\n\n#include \"xtensor/xbuilder.hpp\"\n\n#include \"xaxis_base.hpp\"\n#include \"xframe_utils.hpp\"\n\nnamespace xf\n{\n    template <class L, class T, class MT>\n    class xaxis_iterator;\n\n    template <class L, class T>\n    class xaxis_default;\n\n    /*********************\n     * map container tag *\n     *********************/\n\n    struct map_tag {};\n    struct hash_map_tag {};\n\n    template <class K, class T, class MT>\n    struct map_container;\n\n    template <class K, class T>\n    struct map_container<K, T, map_tag>\n    {\n        using type = std::map<K, T>;\n    };\n\n    template <class K, class T>\n    struct map_container<K, T, hash_map_tag>\n    {\n        using type = std::unordered_map<K, T>;\n    };\n\n    template <class K, class T, class MT>\n    using map_container_t = typename map_container<K, T, MT>::type;\n\n    /*********\n     * xaxis *\n     *********/\n\n    /**\n     * @class xaxis\n     * @brief Class modeling an axis in a coordinate system.\n     *\n     * The xaxis class is used for modeling general axes; an axis is a mapping\n     * of labels to positions in a given dimension. It is the equivalent of\n     * the \\c Index object from <a href=\"pandas.pydata.org\">pandas</a>.\n     *\n     * @tparam L the type of labels.\n     * @tparam T the integer type used to represent positions. Default value is\n     *           \\c std::size_t.\n     * @tparam MT the tag used for choosing the map type which holds the label-\n     *            position pairs. Possible values are \\c map_tag and \\c hash_map_tag.\n     *            Default value is \\c hash_map_tag.\n     */\n    template <class L, class T = std::size_t, class MT = hash_map_tag>\n    class xaxis : public xaxis_base<xaxis<L, T, MT>>\n    {\n    public:\n\n        using base_type = xaxis_base<xaxis>;\n        using self_type = xaxis<L, T, MT>;\n        using key_type = typename base_type::key_type;\n        using label_list = typename base_type::label_list;\n        using mapped_type = typename base_type::mapped_type;\n        using map_type = map_container_t<key_type, mapped_type, MT>;\n        using value_type = typename map_type::value_type;\n        using reference = typename map_type::const_reference;\n        using const_reference = typename map_type::const_reference;\n        using pointer = typename map_type::const_pointer;\n        using const_pointer = typename map_type::const_pointer;\n        using size_type = typename base_type::size_type;\n        using difference_type = typename base_type::difference_type;\n        using iterator = typename base_type::iterator;\n        using const_iterator = typename base_type::const_iterator;\n        using reverse_iterator = typename base_type::reverse_iterator;\n        using const_reverse_iterator = typename base_type::const_reverse_iterator;\n\n        explicit xaxis();\n        explicit xaxis(const label_list& labels);\n        explicit xaxis(label_list&& labels);\n        xaxis(std::initializer_list<key_type> init);\n\n        template <class L1>\n        explicit xaxis(xaxis_default<L1, T> axis);\n\n        template <class InputIt>\n        xaxis(InputIt first, InputIt last);\n\n        bool is_sorted() const noexcept;\n\n        bool contains(const key_type& key) const;\n        mapped_type operator[](const key_type& key) const;\n\n        template <class F>\n        self_type filter(const F& f) const noexcept;\n\n        template <class F>\n        self_type filter(const F& f, size_type size) const noexcept;\n\n        const_iterator find(const key_type& key) const;\n\n        const_iterator cbegin() const noexcept;\n        const_iterator cend() const noexcept;\n\n        template <class... Args>\n        bool merge(const Args&... axes);\n\n        template <class... Args>\n        bool intersect(const Args&... axes);\n\n    protected:\n\n        void populate_index();\n        void set_labels(const label_list& labels);\n\n        template <class Arg, class... Args>\n        bool merge_unsorted(bool broadcasting, const Arg& a, const Args&... axes);\n        bool merge_unsorted(bool broadcasting);\n\n        template <class Arg, class... Args>\n        bool intersect_unsorted(const Arg& al, const Args&... axes_labels);\n        bool intersect_unsorted();\n\n    private:\n\n        xaxis(const label_list& labels, bool is_sorted);\n        xaxis(label_list&& labels, bool is_sorted);\n\n        typename map_type::const_iterator find_index(const key_type& key) const;\n\n        template <class... Args>\n        bool merge_impl(const Args&... axes);\n\n        template <class Arg1, class... Args>\n        bool merge_empty(const Arg1& a, const Args&... axes);\n        bool merge_empty();\n\n        bool init_is_sorted() const noexcept;\n\n        template <class Arg, class... Args>\n        bool all_sorted(const Arg& a, const Args&... axes) const noexcept;\n\n        template <class Arg>\n        bool all_sorted(const Arg& a) const noexcept;\n\n        map_type m_index;\n        bool m_is_sorted;\n\n        friend class xaxis_iterator<L, T, MT>;\n        friend class xaxis_default<L, T>;\n    };\n\n    template <class L, class T, class MT, class... Args>\n    bool merge_axes(xaxis<L, T, MT>& output, const Args&... axes);\n\n    template <class L, class T, class MT, class... Args>\n    bool intersect_axes(xaxis<L, T, MT>& output, const Args&... axes);\n\n    /******************\n     * xaxis builders *\n     ******************/\n\n    template <class T = std::size_t, class L>\n    xaxis<L, T> axis(L start, L stop, L step = 1) noexcept;\n\n    template <class T = std::size_t, class L>\n    xaxis<L, T> axis(std::initializer_list<L> init) noexcept;\n\n    template <class T = std::size_t>\n    xaxis<XFRAME_STRING_LABEL, T> axis(std::initializer_list<const char*> init) noexcept;\n\n    /********************\n    * xaxis_inner_types *\n    *********************/\n\n    template <class L, class T, class MT>\n    struct xaxis_inner_types<xaxis<L, T, MT>>\n    {\n        using key_type = L;\n        using mapped_type = T;\n        using iterator = xaxis_iterator<L, T, MT>;\n    };\n\n    /******************\n     * xaxis_iterator *\n     ******************/\n\n    template <class L, class T, class MT>\n    class xaxis_iterator : public xtl::xrandom_access_iterator_base<xaxis_iterator<L, T, MT>,\n                                                                    typename xaxis<L, T, MT>::value_type,\n                                                                    typename xaxis<L, T, MT>::difference_type,\n                                                                    typename xaxis<L, T, MT>::const_pointer,\n                                                                    typename xaxis<L, T, MT>::const_reference>\n    {\n\n    public:\n\n        using self_type = xaxis_iterator<L, T, MT>;\n        using container_type = xaxis<L, T, MT>;\n        using label_list = typename container_type::label_list;\n        using label_iterator = typename label_list::const_iterator;\n        using value_type = typename container_type::value_type;\n        using reference = typename container_type::const_reference;\n        using pointer = typename container_type::const_pointer;\n        using difference_type = typename container_type::difference_type;\n        using iterator_category = std::random_access_iterator_tag;\n\n        xaxis_iterator() = default;\n        xaxis_iterator(const container_type* c, label_iterator it);\n\n        self_type& operator++();\n        self_type& operator--();\n\n        self_type& operator+=(difference_type n);\n        self_type& operator-=(difference_type n);\n\n        difference_type operator-(const self_type& rhs) const;\n\n        reference operator*() const;\n        pointer operator->() const;\n\n        bool equal(const self_type& rhs) const noexcept;\n        bool less_than(const self_type& rhs) const noexcept;\n\n    private:\n\n        const container_type* p_c;\n        label_iterator m_it;\n    };\n\n    template <class L, class T, class MT>\n    typename xaxis_iterator<L, T, MT>::difference_type operator-(const xaxis_iterator<L, T, MT>& lhs, const xaxis_iterator<L, T, MT>& rhs);\n\n    template <class L, class T, class MT>\n    bool operator==(const xaxis_iterator<L, T, MT>& lhs, const xaxis_iterator<L, T, MT>& rhs) noexcept;\n\n    template <class L, class T, class MT>\n    bool operator<(const xaxis_iterator<L, T, MT>& lhs, const xaxis_iterator<L, T, MT>& rhs) noexcept;\n\n    /************************\n     * xaxis implementation *\n     ************************/\n\n    /**\n     * @name Constructors\n     */\n    //@{\n    /**\n     * Constructs an empty axis.\n     */\n    template <class L, class T, class MT>\n    inline xaxis<L, T, MT>::xaxis()\n        : base_type(), m_index(), m_is_sorted(true)\n    {\n    }\n\n    /**\n     * Constructs an axis with the given list of labels. This list\n     * is copied and the constructor internally checks whether it\n     * is sorted.\n     * @param labels the list of labels.\n     */\n    template <class L, class T, class MT>\n    inline xaxis<L, T, MT>::xaxis(const label_list& labels)\n        : base_type(labels), m_index(), m_is_sorted()\n    {\n        m_is_sorted = init_is_sorted();\n        populate_index();\n    }\n\n    /**\n     * Constructs an axis with the given list of labels. The list is\n     * moved and therefore it is invalid after the axis has been\n     * constructed. The constructor internally checks whether the list\n     * is sorted.\n     * @param labels the list of labels.\n     */\n    template <class L, class T, class MT>\n    inline xaxis<L, T, MT>::xaxis(label_list&& labels)\n        : base_type(std::move(labels)), m_index(), m_is_sorted()\n    {\n        m_is_sorted = init_is_sorted();\n        populate_index();\n    }\n\n    /**\n     * Constructs an axis with the given list of labels, and a boolean\n     * specifying if the labels list is sorted. This is an optimization\n     * that prevents the constructor to check if the labels list is sorted.\n     * The list is copied.\n     * @param labels th list of labels.\n     * @param is_sorted a boolean parameter indicating if the labels list\n     *                  is sorted.\n     */\n    template <class L, class T, class MT>\n    inline xaxis<L, T, MT>::xaxis(const label_list& labels, bool is_sorted)\n        : base_type(labels), m_index(), m_is_sorted(is_sorted)\n    {\n        populate_index();\n    }\n    /**\n     * Constructs an axis with the given list of labels, and a boolean\n     * specifying if the labels list is sorted. This is an optimization\n     * that prevents the constructor to check if the labels list is sorted.\n     * The list is moved and therefore invalid after the axis has been\n     * constructed.\n     * @param labels th list of labels.\n     * @param is_sorted a boolean parameter indicating if the labels list\n     *                  is sorted.\n     */\n\n    template <class L, class T, class MT>\n    inline xaxis<L, T, MT>::xaxis(label_list&& labels, bool is_sorted)\n        : base_type(labels), m_index(), m_is_sorted(is_sorted)\n    {\n        populate_index();\n    }\n\n    /**\n     * Constructs an axis from the given initializer list of labels. The\n     * constructor internally checks whether the list is sorted.\n     */\n    template <class L, class T, class MT>\n    inline xaxis<L, T, MT>::xaxis(std::initializer_list<key_type> init)\n        : base_type(init), m_index(), m_is_sorted()\n    {\n        m_is_sorted = init_is_sorted();\n        populate_index();\n    }\n\n    /**\n     * Constructs an axis from a \\c default_axis.\n     * @sa default_axis\n     */\n    template <class L, class T, class MT>\n    template <class L1>\n    inline xaxis<L, T, MT>::xaxis(xaxis_default<L1, T> axis)\n        : base_type(axis.labels()), m_index(), m_is_sorted(true)\n    {\n        static_assert(std::is_same<L, L1>::value, \"key_type L and key_type L1 must be the same\");\n\n        populate_index();\n    }\n\n    /**\n     * Constructs an axis from the content of the range [first, last)\n     * @param first An iterator to the first label.\n     * @param last An iterator the the element following the last label.\n     */\n    template <class L, class T, class MT>\n    template <class InputIt>\n    inline xaxis<L, T, MT>::xaxis(InputIt first, InputIt last)\n        : base_type(first, last), m_index(), m_is_sorted()\n    {\n        m_is_sorted = init_is_sorted();\n        populate_index();\n    }\n    //@}\n\n    /**\n     * Returns true if the labels list is sorted.\n     */\n    template <class L, class T, class MT>\n    inline bool xaxis<L, T, MT>::is_sorted() const noexcept\n    {\n        return m_is_sorted;\n    }\n\n    /**\n      * @name Data\n     */\n    //@{\n    /**\n     * Returns true if the axis contains the speficied label.\n     * @param key the label to search for.\n     */\n    template <class L, class T, class MT>\n    inline bool xaxis<L, T, MT>::contains(const key_type& key) const\n    {\n        return m_index.count(key) != typename map_type::size_type(0);\n    }\n\n    /**\n     * Returns the position of the specified label. If this last one is\n     * not found, an exception is thrown.\n     * @param key the label to search for.\n     */\n    template <class L, class T, class MT>\n    inline auto xaxis<L, T, MT>::operator[](const key_type& key) const -> mapped_type\n    {\n        return m_index.at(key);\n    }\n    //@}\n\n    /**\n     * @name Filters\n     */\n    //@{\n    /**\n     * Builds an return a new axis by applying the given filter to the axis.\n     * @param f the filter used to select the labels to keep in the new axis.\n     */\n    template <class L, class T, class MT>\n    template <class F>\n    inline auto xaxis<L, T, MT>::filter(const F& f) const noexcept -> self_type\n    {\n        return self_type(base_type::filter_labels(f), m_is_sorted);\n    }\n\n    /**\n     * Builds an return a new axis by applying the given filter to the axis. When\n     * the size of the new list of labels is known, this method allows some\n     * optimizations compared to the previous one.\n     * @param f the filter used to select the labels to keep in the new axis.\n     * @param size the size of the new label list.\n     */\n    template <class L, class T, class MT>\n    template <class F>\n    inline auto xaxis<L, T, MT>::filter(const F& f, size_type size) const noexcept -> self_type\n    {\n        return self_type(base_type::filter_labels(f, size), m_is_sorted);\n    }\n    //@}\n\n    /**\n     * @name Iterator\n     */\n    //@{\n    /**\n     * Returns a constant iterator to the element with label equivalent to \\c key. If\n     * no such element is found, past-the-end iterator is returned.\n     * @param key the label to search for.\n     */\n    template <class L, class T, class MT>\n    inline auto xaxis<L, T, MT>::find(const key_type& key) const -> const_iterator\n    {\n        auto map_iter = m_index.find(key);\n        return map_iter != m_index.end() ? cbegin() + map_iter->second : cend();\n    }\n\n    /**\n     * Returns a constant iterator to the first element of the axis.\n     * This element is a pair label - position.\n     */\n    template <class L, class T, class MT>\n    inline auto xaxis<L, T, MT>::cbegin() const noexcept -> const_iterator\n    {\n        return const_iterator(this, this->labels().begin());\n    }\n\n    /**\n     * Returns a constant iterator to the element following the last element\n     * of the axis.\n     */\n    template <class L, class T, class MT>\n    inline auto xaxis<L, T, MT>::cend() const noexcept -> const_iterator\n    {\n        return const_iterator(this, this->labels().end());\n    }\n    //@}\n\n    /**\n     * @name Set operations\n     */\n    //@{\n    /**\n     * Merges all the axes arguments into this ones. After this function call,\n     * the axis contains all the labels from all the arguments.\n     * @param axes the axes to merge.\n     * @return true is the axis already contained all the labels.\n     */\n    template <class L, class T, class MT>\n    template <class... Args>\n    inline bool xaxis<L, T, MT>::merge(const Args&... axes)\n    {\n        return this->empty() ? merge_empty(axes...) : merge_impl(axes...);\n    }\n\n    /**\n     * Replaces the labels with the intersection of the labels of\n     * the axes arguments and the labels of this axis.\n     * @param axes the axes to intersect.\n     * @return true if the intersection is equivalent to this axis.\n     */\n    template <class L, class T, class MT>\n    template <class... Args>\n    inline bool xaxis<L, T, MT>::intersect(const Args&... axes)\n    {\n        bool res = true;\n        if (all_sorted(*this, axes...))\n        {\n            res = intersect_to(this->mutable_labels(), axes.labels()...);\n            populate_index();\n        }\n        else\n        {\n            res = intersect_unsorted(axes.labels()...);\n        }\n        return res;\n    }\n    //@}\n\n    template <class L, class T, class MT>\n    inline void xaxis<L, T, MT>::populate_index()\n    {\n        for(size_type i = 0; i < this->labels().size(); ++i)\n        {\n            m_index[this->labels()[i]] = T(i);\n        }\n    }\n\n    template <class L, class T, class MT>\n    void xaxis<L, T, MT>::set_labels(const label_list& labels)\n    {\n        this->mutable_labels() = labels;\n        populate_index();\n    }\n\n    template <class L, class T, class MT>\n    inline auto xaxis<L, T, MT>::find_index(const key_type& key) const -> typename map_type::const_iterator\n    {\n        return m_index.find(key);\n    }\n\n    template <class L, class T, class MT>\n    template <class... Args>\n    inline bool xaxis<L, T, MT>::merge_impl(const Args&... axes)\n    {\n        bool res = true;\n        if(all_sorted(*this, axes...))\n        {\n            res = merge_to(this->mutable_labels(), axes.labels()...);\n            populate_index();\n        }\n        else\n        {\n            m_is_sorted = false;\n            if (m_index.empty())\n            {\n                populate_index();\n            }\n            res = merge_unsorted(false, axes.labels()...);\n        }\n        return res;\n    }\n\n    template <class L, class T, class MT>\n    template <class Arg1, class... Args>\n    inline bool xaxis<L, T, MT>::merge_empty(const Arg1& a, const Args&... axes)\n    {\n        this->mutable_labels() = a.labels();\n        return merge_impl(axes...);\n    }\n\n    template <class L, class T, class MT>\n    inline bool xaxis<L, T, MT>::merge_empty()\n    {\n        return true;\n    }\n\n    template <class L, class T, class MT>\n    inline bool xaxis<L, T, MT>::init_is_sorted() const noexcept\n    {\n        return std::is_sorted(this->labels().begin(), this->labels().end());\n    }\n\n    template <class L, class T, class MT>\n    template <class Arg, class... Args>\n    inline bool xaxis<L, T, MT>::all_sorted(const Arg& a, const Args&... axes) const noexcept\n    {\n        return a.is_sorted() && all_sorted(axes...);\n    }\n\n    template <class L, class T, class MT>\n    template <class Arg>\n    inline bool xaxis<L, T, MT>::all_sorted(const Arg& a) const noexcept\n    {\n        return a.is_sorted();\n    }\n\n    template <class L, class T, class MT>\n    template <class Arg, class... Args>\n    inline bool xaxis<L, T, MT>::merge_unsorted(bool broadcasting, const Arg& a, const Args&... axes_labels)\n    {\n        bool res = merge_unsorted(broadcasting, axes_labels...);\n        auto& labels = this->mutable_labels();\n        auto output_iter = labels.rbegin();\n        auto output_end = labels.rend();\n        auto input_iter = a.rbegin();\n        auto input_end = a.rend();\n        while ((output_iter != output_end) && (input_iter != input_end) && (*output_iter == *input_iter))\n        {\n            ++output_iter;\n            ++input_iter;\n        }\n        if(input_iter == input_end)\n        {\n            if(output_iter != output_end)\n            {\n                res &= broadcasting;\n            }\n        }\n        else if(output_iter == output_end)\n        {\n            std::copy(a.begin(), a.begin() + std::distance(input_iter, input_end),\n                      std::inserter(labels, labels.begin()));\n            populate_index();\n            res &= broadcasting;\n        }\n        else\n        {\n            while(input_iter != input_end)\n            {\n                if(!contains(*input_iter))\n                {\n                    if(output_iter != labels.rbegin())\n                    {\n                        labels.insert(labels.begin(), *input_iter);\n                    }\n                    else\n                    {\n                        labels.push_back(*input_iter);\n                    }\n                }\n                ++input_iter;\n            }\n            populate_index();\n            res = false;\n        }\n        return res;\n    }\n\n    template <class L, class T, class MT>\n    inline bool xaxis<L, T, MT>::merge_unsorted(bool /*broadcasting*/)\n    {\n        return true;\n    }\n\n    template <class L, class T, class MT>\n    template <class Arg, class... Args>\n    inline bool xaxis<L, T, MT>::intersect_unsorted(const Arg& al, const Args&... axes_labels)\n    {\n        bool res = intersect_unsorted(axes_labels...);\n        auto& labels = this->mutable_labels();\n        auto iter = labels.begin();\n        auto iter_end = labels.end();\n        bool must_populate = false;\n        while (iter != iter_end)\n        {\n            auto it = std::find(al.begin(), al.end(), *iter);\n            if (it == al.end())\n            {\n                iter = labels.erase(iter, iter + 1);\n                iter_end = labels.end();\n                res = false;\n                must_populate = true;\n            }\n            else\n            {\n                if (it - al.begin() != iter - labels.begin())\n                {\n                    res = false;\n                }\n                ++iter;\n            }\n        }\n        if (must_populate)\n        {\n            populate_index();\n        }\n        return res;\n    }\n\n    template <class L, class T, class MT>\n    inline bool xaxis<L, T, MT>::intersect_unsorted()\n    {\n        return true;\n    }\n\n    template <class L, class T, class MT, class... Args>\n    inline bool merge_axes(xaxis<L, T, MT>& output, const Args&... axes)\n    {\n        return output.merge(axes...);\n    }\n\n    template <class L, class T, class MT, class... Args>\n    inline bool intersect_axes(xaxis<L, T, MT>& output, const Args&... axes)\n    {\n        return output.intersect(axes...);\n    }\n\n    /*********************************\n     * xaxis_iterator implementation *\n     *********************************/\n\n    template <class L, class T, class MT>\n    inline xaxis_iterator<L, T, MT>::xaxis_iterator(const container_type* c, label_iterator it)\n        : p_c(c), m_it(it)\n    {\n    }\n\n    template <class L, class T, class MT>\n    inline auto xaxis_iterator<L, T, MT>::operator++() -> self_type&\n    {\n        ++m_it;\n        return *this;\n    }\n\n    template <class L, class T, class MT>\n    inline auto xaxis_iterator<L, T, MT>::operator--() -> self_type&\n    {\n        --m_it;\n        return *this;\n    }\n\n    template <class L, class T, class MT>\n    inline auto xaxis_iterator<L, T, MT>::operator+=(difference_type n) -> self_type&\n    {\n        m_it += n;\n        return *this;\n    }\n\n    template <class L, class T, class MT>\n    inline auto xaxis_iterator<L, T, MT>::operator-=(difference_type n) -> self_type&\n    {\n        m_it -= n;\n        return *this;\n    }\n\n    template <class L, class T, class MT>\n    inline auto xaxis_iterator<L, T, MT>::operator-(const self_type& rhs) const -> difference_type\n    {\n        return m_it - rhs.m_it;\n    }\n\n    template <class L, class T, class MT>\n    inline auto xaxis_iterator<L, T, MT>::operator*() const -> reference\n    {\n        return *(p_c->find_index(*m_it));\n    }\n\n    template <class L, class T, class MT>\n    inline auto xaxis_iterator<L, T, MT>::operator->() const -> pointer\n    {\n        return &(*(p_c->find_index(*m_it)));\n    }\n\n    template <class L, class T, class MT>\n    inline bool xaxis_iterator<L, T, MT>::equal(const self_type& rhs) const noexcept\n    {\n        return m_it == rhs.m_it;\n    }\n\n    template <class L, class T, class MT>\n    inline bool xaxis_iterator<L, T, MT>::less_than(const self_type& rhs) const noexcept\n    {\n        return m_it < rhs.m_it;\n    }\n\n    template <class L, class T, class MT>\n    inline typename xaxis_iterator<L, T, MT>::difference_type operator-(const xaxis_iterator<L, T, MT>& lhs, const xaxis_iterator<L, T, MT>& rhs)\n    {\n        return lhs.operator-(rhs);\n    }\n\n    template <class L, class T, class MT>\n    inline bool operator==(const xaxis_iterator<L, T, MT>& lhs, const xaxis_iterator<L, T, MT>& rhs) noexcept\n    {\n        return lhs.equal(rhs);\n    }\n\n    template <class L, class T, class MT>\n    inline bool operator<(const xaxis_iterator<L, T, MT>& lhs, const xaxis_iterator<L, T, MT>& rhs) noexcept\n    {\n        return lhs.less_than(rhs);\n    }\n\n    /********************************\n     * axis builders implementation *\n     ********************************/\n\n    /**\n     * Returns an axis containing a range of integral labels.\n     * @param start the first value of the range.\n     * @param stop the end of the range. The range doe snot contain\n     *             this value.\n     * @param step Spacing between values. Default step is \\c 1.\n     * @tparam T the integral type used for positions. Default value\n     * @tparam L the type of the labels.\n     */\n    template <class T, class L>\n    inline xaxis<L, T> axis(L start, L stop, L step) noexcept\n    {\n        auto range = xt::arange(start, stop, step);\n        return xaxis<L, T>(range.begin(), range.end());\n    }\n\n    /**\n     * Builds an returns an axis from the specified list of labels.\n     * @param init the list of labels.\n     * @tparam T the integral type used for positions. Default value\n     *           is \\c std::size_t.\n     * @tparam L the type of the labels.\n     */\n    template <class T, class L>\n    inline xaxis<L, T> axis(std::initializer_list<L> init) noexcept\n    {\n        return xaxis<L, T>(init);\n    }\n\n    template <class T>\n    inline xaxis<XFRAME_STRING_LABEL, T> axis(std::initializer_list<const char*> init) noexcept\n    {\n        return xaxis<XFRAME_STRING_LABEL, T>(init.begin(), init.end());\n    }\n}\n\n#endif\n"
  },
  {
    "path": "include/xframe/xaxis_base.hpp",
    "content": "/***************************************************************************\n* Copyright (c) Johan Mabille, Sylvain Corlay, Wolf Vollprecht and         *\n* Martin Renou                                                             *\n* Copyright (c) QuantStack                                                 *\n*                                                                          *\n* Distributed under the terms of the BSD 3-Clause License.                 *\n*                                                                          *\n* The full license is in the file LICENSE, distributed with this software. *\n****************************************************************************/\n\n#ifndef XFRAME_XAXIS_BASE_HPP\n#define XFRAME_XAXIS_BASE_HPP\n\n#include <algorithm>\n#include <iterator>\n#include <vector>\n\nnamespace xf\n{\n\n    template <class D>\n    struct xaxis_inner_types;\n\n    /**************\n     * xaxis_base *\n     **************/\n\n    /**\n     * @class xaxis_base\n     * @brief Base class for axes.\n     *\n     * The xaxis_base class defines the common interface for axes, which define the\n     * mapping of labels to positions in a given dimension. The axis_base class\n     * embeds the list of labels only, the mapping is hold by the inheriting classes.\n     *\n     * @tparam D The derived type, i.e. the inheriting class for which xaxis_base\n     *           provides the interface.\n     */\n    template <class D>\n    class xaxis_base\n    {\n    public:\n\n        using derived_type = D;\n        using inner_types = xaxis_inner_types<D>;\n\n        using key_type = typename inner_types::key_type;\n        using mapped_type = typename inner_types::mapped_type;\n        using label_list = std::vector<key_type>;\n        using size_type = typename label_list::size_type;\n        using difference_type = typename label_list::difference_type;\n        using iterator = typename inner_types::iterator;\n        using const_iterator = iterator;\n        using reverse_iterator = std::reverse_iterator<iterator>;\n        using const_reverse_iterator = reverse_iterator;\n\n        static_assert(std::is_integral<mapped_type>::value, \"mapped_type T must be an integral type\");\n\n        derived_type& derived_cast() & noexcept;\n        const derived_type& derived_cast() const & noexcept;\n        derived_type derived_cast() && noexcept;\n\n        const label_list& labels() const noexcept;\n        key_type label(size_type i) const;\n\n        bool empty() const noexcept;\n        size_type size() const noexcept;\n\n        const_iterator begin() const noexcept;\n        const_iterator end() const noexcept;\n\n        const_reverse_iterator rbegin() const noexcept;\n        const_reverse_iterator rend() const noexcept;\n\n        const_reverse_iterator crbegin() const noexcept;\n        const_reverse_iterator crend() const noexcept;\n\n    protected:\n\n        xaxis_base();\n        xaxis_base(const label_list& labels);\n        xaxis_base(label_list&& labels);\n        xaxis_base(std::initializer_list<key_type> init);\n\n        template <class InputIt>\n        xaxis_base(InputIt first, InputIt last);\n\n        ~xaxis_base() = default;\n\n        xaxis_base(const xaxis_base&) = default;\n        xaxis_base& operator=(const xaxis_base&) = default;\n\n        xaxis_base(xaxis_base&&) = default;\n        xaxis_base& operator=(xaxis_base&&) = default;\n\n        label_list& mutable_labels() noexcept;\n\n        template <class F>\n        label_list filter_labels(const F& f) const noexcept;\n\n        template <class F>\n        label_list filter_labels(const F& f, size_type size) const noexcept;\n\n        label_list m_labels;\n    };\n\n    template <class D1, class D2>\n    bool operator==(const xaxis_base<D1>& lhs, const xaxis_base<D2>& rhs) noexcept;\n\n    template <class D1, class D2>\n    bool operator!=(const xaxis_base<D1>& lhs, const xaxis_base<D2>& rhs) noexcept;\n\n    template <class OS, class D>\n    OS& operator<<(OS& out, const xaxis_base<D>& axis);\n\n    /************************\n     * is_axis metafunction *\n     ************************/\n\n    template <class T>\n    struct is_axis : std::is_base_of<xaxis_base<T>, T>\n    {\n    };\n\n    /*****************************\n     * xaxis_base implementation *\n     *****************************/\n\n    template <class D>\n    inline xaxis_base<D>::xaxis_base()\n        : m_labels()\n    {\n    }\n\n    template <class D>\n    inline xaxis_base<D>::xaxis_base(const label_list& labels)\n        : m_labels(labels)\n    {\n    }\n\n    template <class D>\n    inline xaxis_base<D>::xaxis_base(label_list&& labels)\n        : m_labels(std::move(labels))\n    {\n    }\n\n    template <class D>\n    inline xaxis_base<D>::xaxis_base(std::initializer_list<key_type> init)\n        : m_labels(init)\n    {\n    }\n\n    template <class D>\n    template <class InputIt>\n    inline xaxis_base<D>::xaxis_base(InputIt first, InputIt last)\n        : m_labels(first, last)\n    {\n    }\n\n    /**\n     * @name Downcast\n     */\n    //@{\n    /**\n     * Casts the object to its inheriting type (i.e. D); this method\n     * is called when the object is an lvalue.\n     */\n    template <class D>\n    inline auto xaxis_base<D>::derived_cast() & noexcept -> derived_type&\n    {\n        return *static_cast<derived_type*>(this);\n    }\n\n    /**\n     * Casts the object to its inheriting type (i.e. D); this method\n     * is called when the object is a constant lvalue.\n     */\n    template <class D>\n    inline auto xaxis_base<D>::derived_cast() const & noexcept -> const derived_type&\n    {\n        return *static_cast<const derived_type*>(this);\n    }\n\n    /**\n     * Casts the object to its inheriting type (i.e. D); this method\n     * is called when the object is an rvalue.\n     */\n    template <class D>\n    inline auto xaxis_base<D>::derived_cast() && noexcept -> derived_type\n    {\n        return *static_cast<derived_type*>(this);\n    }\n    //@}\n\n    /**\n     * @name Labels\n     */\n    //@{\n    /**\n     * Returns the list of labels contained in the axis.\n     */\n    template <class D>\n    inline auto xaxis_base<D>::labels() const noexcept -> const label_list&\n    {\n        return m_labels;\n    }\n\n    /**\n     * Return the i-th label of the axis.\n     * @param i the position of the label.\n     */\n    template <class D>\n    inline auto xaxis_base<D>::label(size_type i) const -> key_type\n    {\n        return m_labels[i];\n    }\n\n    /**\n     * Checks if the axis has no labels.\n     */\n    template <class D>\n    inline bool xaxis_base<D>::empty() const noexcept\n    {\n        return m_labels.empty();\n    }\n\n    /**\n     * Returns the number of labels in the axis.\n     */\n    template <class D>\n    inline auto xaxis_base<D>::size() const noexcept -> size_type\n    {\n        return m_labels.size();\n    }\n    //@}\n\n    /**\n     * @name Iterators\n     */\n    //@{\n    /**\n     * Returns a constant iterator to the first element of the axis.\n     * This element is a pair label - position.\n     */\n    template <class D>\n    inline auto xaxis_base<D>::begin() const noexcept -> const_iterator\n    {\n        return derived_cast().cbegin();\n    }\n\n    /**\n     * Returns a constant iterator to the element following the last element\n     * of the axis.\n     */\n    template <class D>\n    inline auto xaxis_base<D>::end() const noexcept -> const_iterator\n    {\n        return derived_cast().cend();\n    }\n\n    /**\n     * Returns a constant iterator to the first element of the reverse axis.\n     * This element is a pair labal - position.\n     */\n    template <class D>\n    inline auto xaxis_base<D>::rbegin() const noexcept -> const_reverse_iterator\n    {\n        return crbegin();\n    }\n\n    /**\n     * Returns a constant iterator to the element following the last element\n     * of the reversed axis.\n     */\n    template <class D>\n    inline auto xaxis_base<D>::rend() const noexcept -> const_reverse_iterator\n    {\n        return crend();\n    }\n\n    /**\n     * Returns a constant iterator to the first element of the reverse axis.\n     * This element is a pair labal - position.\n     */\n    template <class D>\n    inline auto xaxis_base<D>::crbegin() const noexcept -> const_reverse_iterator\n    {\n        return const_reverse_iterator(derived_cast().cend());\n    }\n\n    /**\n     * Returns a constant iterator to the element following the last element\n     * of the reversed axis.\n     */\n    template <class D>\n    inline auto xaxis_base<D>::crend() const noexcept -> const_reverse_iterator\n    {\n        return const_reverse_iterator(derived_cast().cbegin());\n    }\n    //@}\n\n    template <class D>\n    inline auto xaxis_base<D>::mutable_labels() noexcept -> label_list&\n    {\n        return m_labels;\n    }\n\n    template <class D>\n    template <class F>\n    inline auto xaxis_base<D>::filter_labels(const F& f) const noexcept -> label_list\n    {\n        label_list l;\n        std::copy_if(m_labels.cbegin(), m_labels.cend(), std::back_inserter(l), f);\n        return l;\n    }\n\n    template <class D>\n    template <class F>\n    inline auto xaxis_base<D>::filter_labels(const F& f, size_type size) const noexcept -> label_list\n    {\n        label_list l(size);\n        std::copy_if(m_labels.cbegin(), m_labels.cend(), l.begin(), f);\n        return l;\n    }\n\n    /**\n     * Returns true is \\c lhs and \\c rhs are equivalent axes, i.e. they contain the same\n     * label - position pairs.\n     * @param lhs an axis.\n     * @param rhs an axis.\n     */\n    template <class D1, class D2>\n    inline bool operator==(const xaxis_base<D1>& lhs, const xaxis_base<D2>& rhs) noexcept\n    {\n        return lhs.labels() == rhs.labels();\n    }\n\n    /**\n     * Returns true is \\c lhs and \\c rhs are not equivalent axes, i.e. they contain different\n     * label - position pairs.\n     * @param lhs an axis.\n     * @param rhs an axis.\n     */\n    template <class D1, class D2>\n    inline bool operator!=(const xaxis_base<D1>& lhs, const xaxis_base<D2>& rhs) noexcept\n    {\n        return !(lhs == rhs);\n    }\n\n    template <class OS, class D>\n    inline OS& operator<<(OS& out, const xaxis_base<D>& axis)\n    {\n        using iterator = std::ostream_iterator<typename xaxis_base<D>::key_type, typename OS::char_type, typename OS::traits_type>;\n        out << '(';\n        std::copy(axis.labels().begin(), axis.labels().end(), iterator(out, \", \"));\n        out << ')';\n        return out;\n    }\n}\n\n#endif\n"
  },
  {
    "path": "include/xframe/xaxis_default.hpp",
    "content": "/***************************************************************************\n* Copyright (c) Johan Mabille, Sylvain Corlay, Wolf Vollprecht and         *\n* Martin Renou                                                             *\n* Copyright (c) QuantStack                                                 *\n*                                                                          *\n* Distributed under the terms of the BSD 3-Clause License.                 *\n*                                                                          *\n* The full license is in the file LICENSE, distributed with this software. *\n****************************************************************************/\n\n#ifndef XFRAME_XAXIS_DEFAULT_HPP\n#define XFRAME_XAXIS_DEFAULT_HPP\n\n#include <utility>\n#include <vector>\n#include <ostream>\n#include <iterator>\n\n#include \"xtl/xiterator_base.hpp\"\n\n#include \"xaxis_base.hpp\"\n#include \"xaxis.hpp\"\n\nnamespace xf\n{\n    template <class L, class T>\n    class xaxis_default_iterator;\n\n    template <class L1, class T1, class MT1>\n    class xaxis_variant;\n\n    /*****************\n     * xaxis_default *\n     *****************/\n\n    /**\n     * @class xaxis_default\n     * @brief Default axis with integral labels.\n     *\n     * The xaxis_default class is used for modeling a default axis\n     * that holds a contiguous sequence of integral labels starting at 0.\n     *\n     * @tparam L the type of labels. This must be an integral type.\n     * @tparam T the integer type used to represent positions. Default value is\n     *           \\c std::size_t.\n     */\n    template <class L, class T = std::size_t>\n    class xaxis_default : public xaxis_base<xaxis_default<L, T>>\n    {\n    public:\n\n        using base_type = xaxis_base<xaxis_default>;\n        using self_type = xaxis_default<L, T>;\n        using axis_type = xaxis<L, T>;\n        using key_type = typename base_type::key_type;\n        using label_list = typename base_type::label_list;\n        using mapped_type = typename base_type::mapped_type;\n        using value_type = std::pair<key_type, mapped_type>;\n        using reference = value_type&;\n        using const_reference = const value_type&;\n        using pointer = value_type*;\n        using const_pointer = const value_type*;\n        using size_type = typename base_type::size_type;\n        using difference_type = typename base_type::difference_type;\n        using iterator = typename base_type::iterator;\n        using const_iterator = typename base_type::const_iterator;\n        using reverse_iterator = typename base_type::reverse_iterator;\n        using const_reverse_iterator = typename base_type::const_reverse_iterator;\n\n        static_assert(std::is_integral<key_type>::value, \"key_type L must be an integral type\");\n\n        explicit xaxis_default(size_type size = 0);\n\n        bool is_sorted() const noexcept;\n\n        bool contains(const key_type& key) const;\n        mapped_type operator[](const key_type& key) const;\n\n        template <class F>\n        axis_type filter(const F& f) const noexcept;\n\n        template <class F>\n        axis_type filter(const F& f, size_type size) const noexcept;\n\n        const_iterator find(const key_type& key) const;\n\n        const_iterator cbegin() const noexcept;\n        const_iterator cend() const noexcept;\n\n    protected:\n\n        void populate_labels(const size_type& size = 0);\n\n    private:\n\n        template <class... Args>\n        bool merge(const Args&... /*axes*/);\n\n        template <class... Args>\n        bool intersect(const Args&... /*axes*/);\n\n        template <class L1, class T1, class MT1>\n        friend class xaxis_variant;\n    };\n\n    /*************************\n     * xaxis_default builder *\n     *************************/\n\n    template <class T = std::size_t, class L>\n    xaxis_default<L, T> axis(L size) noexcept;\n\n    /********************\n    * xaxis_inner_types *\n    *********************/\n\n    template <class L, class T>\n    struct xaxis_inner_types<xaxis_default<L, T>>\n    {\n        using key_type = L;\n        using mapped_type = T;\n        using iterator = xaxis_default_iterator<L, T>;\n    };\n\n    /**************************\n     * xaxis_default_iterator *\n     **************************/\n\n    template <class L, class T>\n    class xaxis_default_iterator : public xtl::xrandom_access_iterator_base<xaxis_default_iterator<L, T>,\n                                                                   typename xaxis_default<L, T>::value_type,\n                                                                   typename xaxis_default<L, T>::difference_type,\n                                                                   typename xaxis_default<L, T>::const_pointer,\n                                                                   typename xaxis_default<L, T>::const_reference>\n    {\n\n    public:\n\n        using self_type = xaxis_default_iterator<L, T>;\n        using container_type = xaxis_default<L, T>;\n        using label_list = typename container_type::label_list;\n        using key_type = typename container_type::key_type;\n        using mapped_type = typename container_type::mapped_type;\n        using value_type = typename container_type::value_type;\n        using reference = typename container_type::const_reference;\n        using pointer = typename container_type::const_pointer;\n        using difference_type = typename label_list::difference_type;\n        using iterator_category = std::random_access_iterator_tag;\n\n        xaxis_default_iterator() = default;\n        xaxis_default_iterator(mapped_type value);\n\n        self_type& operator++();\n        self_type& operator--();\n\n        self_type& operator+=(difference_type n);\n        self_type& operator-=(difference_type n);\n\n        difference_type operator-(const self_type& rhs) const;\n\n        reference operator*() const;\n        pointer operator->() const;\n\n        bool equal(const self_type& rhs) const noexcept;\n        bool less_than(const self_type& rhs) const noexcept;\n\n    private:\n\n        value_type m_value;\n    };\n\n    template <class L, class T>\n    typename xaxis_default_iterator<L, T>::difference_type operator-(const xaxis_default_iterator<L, T>& lhs, const xaxis_default_iterator<L, T>& rhs);\n\n    template <class L, class T>\n    bool operator==(const xaxis_default_iterator<L, T>& lhs, const xaxis_default_iterator<L, T>& rhs) noexcept;\n\n    template <class L, class T>\n    bool operator<(const xaxis_default_iterator<L, T>& lhs, const xaxis_default_iterator<L, T>& rhs) noexcept;\n\n    /********************************\n     * xaxis_default implementation *\n     ********************************/\n\n    /**\n     * Constructs a default axis holding \\c size integral elements.\n     * The labels sequence is [0, 1, ..... size - 1)\n     */\n    template <class L, class T>\n    inline xaxis_default<L, T>::xaxis_default(size_type size)\n        : base_type()\n    {\n        populate_labels(size);\n    }\n\n    /**\n     * Returns true if the labels list is sorted.\n     */\n    template <class L, class T>\n    inline bool xaxis_default<L, T>::is_sorted() const noexcept\n    {\n        return true;\n    }\n\n    /**\n     * Returns true if the axis contains the speficied label.\n     * @param key the label to search for.\n     */\n    template <class L, class T>\n    inline bool xaxis_default<L, T>::contains(const key_type& key) const\n    {\n        return key_type(0) <= key && key < key_type(this->size());\n    }\n\n    /**\n     * Returns the position of the specified label. If this last one is\n     * not found, an exception is thrown.\n     * @param key the label to search for.\n     */\n    template <class L, class T>\n    inline auto xaxis_default<L, T>::operator[](const key_type& key) const -> mapped_type\n    {\n        return mapped_type(this->labels().at(key));\n    }\n\n    /**\n     * Builds an return a new axis by applying the given filter to the axis.\n     * @param f the filter used to select the labels to keep in the new axis.\n     */\n    template <class L, class T>\n    template <class F>\n    inline auto xaxis_default<L, T>::filter(const F& f) const noexcept -> axis_type\n    {\n        return axis_type(base_type::filter_labels(f), true);\n    }\n\n    /**\n     * Builds an return a new axis by applying the given filter to the axis. When\n     * the size of the new list of labels is known, this method allows some\n     * optimizations compared to the previous one.\n     * @param f the filter used to select the labels to keep in the new axis.\n     * @param size the size of the new label list.\n     */\n    template <class L, class T>\n    template <class F>\n    inline auto xaxis_default<L, T>::filter(const F& f, size_type size) const noexcept -> axis_type\n    {\n        return axis_type(base_type::filter_labels(f, size), true);\n    }\n\n    /**\n     * Returns a constant iterator to the element with label equivalent to \\c key. If\n     * no such element is found, past-the-end iterator is returned.\n     * @param key the label to search for.\n     */\n    template <class L, class T>\n    inline auto xaxis_default<L, T>::find(const key_type& key) const -> const_iterator\n    {\n        return contains(key) ? const_iterator(mapped_type(key)) : cend();\n    }\n\n    /**\n     * Returns a constant iterator to the first element of the axis.\n     * This element is a pair label - position.\n     */\n    template <class L, class T>\n    inline auto xaxis_default<L, T>::cbegin() const noexcept -> const_iterator\n    {\n        return const_iterator(mapped_type(0));\n    }\n\n    /**\n     * Returns a constant iterator to the element following the last element\n     * of the axis.\n     */\n    template <class L, class T>\n    inline auto xaxis_default<L, T>::cend() const noexcept -> const_iterator\n    {\n        return const_iterator(mapped_type(this->size()));\n    }\n\n    template <class L, class T>\n    inline void xaxis_default<L, T>::populate_labels(const size_type& size)\n    {\n        auto& labels = this->mutable_labels();\n        for(size_type i = 0; i < size; ++i)\n        {\n            labels.push_back(key_type(i));\n        }\n    }\n\n    template <class L, class T>\n    template <class... Args>\n    inline bool xaxis_default<L, T>::merge(const Args&... /*axes*/)\n    {\n        throw std::runtime_error(\"merge forbidden for xaxis_default\");\n    }\n\n    template <class L, class T>\n    template <class... Args>\n    inline bool xaxis_default<L, T>::intersect(const Args&... /*axes*/)\n    {\n        throw std::runtime_error(\"intersect forbidden for xaxis_default\");\n    }\n\n    /****************************************\n     * xaxis_default builder implementation *\n     ****************************************/\n\n    /**\n     * Returns a default axis that holds \\c size integral\n     * labels.\n     * @param size the number of labels.\n     * @tparam T the integral type used for positions. Default value\n     *           is \\c std::size_t.\n     * @tparam L the type of the labels. This must be an integral type.\n     */\n    template <class T, class L>\n    inline xaxis_default<L, T> axis(L size) noexcept\n    {\n        return xaxis_default<L, T>(size);\n    }\n\n    /*****************************************\n     * xaxis_default_iterator implementation *\n     *****************************************/\n\n    template <class L, class T>\n    inline xaxis_default_iterator<L, T>::xaxis_default_iterator(mapped_type value)\n        : m_value(std::make_pair(static_cast<key_type>(value), value))\n    {\n    }\n\n    template <class L, class T>\n    inline auto xaxis_default_iterator<L, T>::operator++() -> self_type&\n    {\n        ++m_value.first;\n        ++m_value.second;\n        return *this;\n    }\n\n    template <class L, class T>\n    inline auto xaxis_default_iterator<L, T>::operator--() -> self_type&\n    {\n        --m_value.first;\n        --m_value.second;\n        return *this;\n    }\n\n    template <class L, class T>\n    inline auto xaxis_default_iterator<L, T>::operator+=(difference_type n) -> self_type&\n    {\n        m_value.first = static_cast<key_type>(m_value.first + n);\n        m_value.second += static_cast<mapped_type>(n);\n        return *this;\n    }\n\n    template <class L, class T>\n    inline auto xaxis_default_iterator<L, T>::operator-=(difference_type n) -> self_type&\n    {\n        m_value.first = static_cast<key_type>(m_value.first - n);\n        m_value.second -= static_cast<mapped_type>(n);\n        return *this;\n    }\n\n    template <class L, class T>\n    inline auto xaxis_default_iterator<L, T>::operator-(const self_type& rhs) const -> difference_type\n    {\n        return m_value.first - rhs.m_value.first;\n        return m_value.second - rhs.m_value.second;\n    }\n\n    template <class L, class T>\n    inline auto xaxis_default_iterator<L, T>::operator*() const -> reference\n    {\n        return m_value;\n    }\n\n    template <class L, class T>\n    inline auto xaxis_default_iterator<L, T>::operator->() const -> pointer\n    {\n        return &m_value;\n    }\n\n    template <class L, class T>\n    inline bool xaxis_default_iterator<L, T>::equal(const self_type& rhs) const noexcept\n    {\n        return m_value.first == rhs.m_value.first;\n    }\n\n    template <class L, class T>\n    inline bool xaxis_default_iterator<L, T>::less_than(const self_type& rhs) const noexcept\n    {\n        return m_value.first < rhs.m_value.first;\n    }\n\n    template <class L, class T>\n    inline typename xaxis_default_iterator<L, T>::difference_type operator-(const xaxis_default_iterator<L, T>& lhs, const xaxis_default_iterator<L, T>& rhs)\n    {\n        return lhs.operator-(rhs);\n    }\n\n    template <class L, class T>\n    inline bool operator==(const xaxis_default_iterator<L, T>& lhs, const xaxis_default_iterator<L, T>& rhs) noexcept\n    {\n        return lhs.equal(rhs);\n    }\n\n    template <class L, class T>\n    inline bool operator<(const xaxis_default_iterator<L, T>& lhs, const xaxis_default_iterator<L, T>& rhs) noexcept\n    {\n        return lhs.less_than(rhs);\n    }\n}\n\n#endif\n"
  },
  {
    "path": "include/xframe/xaxis_expression_leaf.hpp",
    "content": "/***************************************************************************\n* Copyright (c) Johan Mabille, Sylvain Corlay, Wolf Vollprecht and         *\n* Martin Renou                                                             *\n* Copyright (c) QuantStack                                                 *\n*                                                                          *\n* Distributed under the terms of the BSD 3-Clause License.                 *\n*                                                                          *\n* The full license is in the file LICENSE, distributed with this software. *\n****************************************************************************/\n\n#ifndef XFRAME_XAXIS_EXPRESSION_LEAF_HPP\n#define XFRAME_XAXIS_EXPRESSION_LEAF_HPP\n\n#include \"xtl/xvariant.hpp\"\n#include \"xtl/xmeta_utils.hpp\"\n\n#include \"xtensor/xoptional.hpp\"\n\n#include \"xframe_config.hpp\"\n#include \"xframe_utils.hpp\"\n#include \"xframe_expression.hpp\"\n\nnamespace xf\n{\n    /*************************\n     * xaxis_expression_leaf *\n     *************************/\n\n    /**\n     * @class xaxis_expression_leaf\n     * @brief An subset of an expression on axis\n     *\n     * The xaxis_expression_leaf class is used with xaxis_function for creating\n     * an expression on xnamed_axis, e.g. `auto expr = not_equal(axis1, 2) && axis2 < 3`.\n     * In the example above, `axis1`, `axis2` are xnamed_axis which will be converted to\n     * xaxis expression leaves before stored in the xaxis_function object.\n     *\n     * @tparam CTA the named axis type.\n     * @sa xaxis_function\n     */\n    template <class CTA>\n    class xaxis_expression_leaf : public xt::xexpression<xaxis_expression_leaf<CTA>>\n    {\n    public:\n\n        using named_axis_type = std::decay_t<CTA>;\n        using name_type = typename named_axis_type::name_type;\n        using size_type = typename named_axis_type::size_type;\n\n        using value_type = typename named_axis_type::value_type;\n        using reference = typename named_axis_type::reference;\n        using const_reference = typename named_axis_type::const_reference;\n        using pointer = typename named_axis_type::pointer;\n        using const_pointer = typename named_axis_type::const_pointer;\n\n        template <std::size_t N = dynamic()>\n        using selector_sequence_type = detail::xselector_sequence_t<std::pair<name_type, size_type>, N>;\n\n        using expression_tag = xaxis_expression_tag;\n\n        template <class AX>\n        xaxis_expression_leaf(AX&& n_axis) noexcept;\n\n        template <std::size_t N = std::numeric_limits<size_type>::max()>\n        const_reference operator()(const selector_sequence_type<N>& selector) const;\n\n    private:\n\n        xaxis_closure_t<CTA> m_named_axis;\n    };\n\n    /****************************************\n     * xaxis_expression_leaf implementation *\n     ****************************************/\n\n    /**\n     * Builds an xaxis_expression_leaf.\n     * @param n_axis the xnamed_axis.\n     */\n    template <class CTA>\n    template <class AX>\n    inline xaxis_expression_leaf<CTA>::xaxis_expression_leaf(AX&& n_axis) noexcept\n        : m_named_axis(std::forward<AX>(n_axis))\n    {\n    }\n\n    /**\n     * Returns the label from the xnamed_axis, given a selector.\n     * @param selector a selector_sequence_type.\n     */\n    template <class CTA>\n    template <std::size_t N>\n    auto xaxis_expression_leaf<CTA>::operator()(const selector_sequence_type<N>& selector) const -> const_reference\n    {\n        for (const auto& sel: selector)\n        {\n            if (m_named_axis.name() == sel.first)\n            {\n                return m_named_axis.label(sel.second);\n            }\n        }\n        throw std::runtime_error(std::string(\"Missing label for axis \") + std::string(m_named_axis.name()));\n    }\n}\n\n#endif\n"
  },
  {
    "path": "include/xframe/xaxis_function.hpp",
    "content": "/***************************************************************************\n* Copyright (c) Johan Mabille, Sylvain Corlay, Wolf Vollprecht and         *\n* Martin Renou                                                             *\n* Copyright (c) QuantStack                                                 *\n*                                                                          *\n* Distributed under the terms of the BSD 3-Clause License.                 *\n*                                                                          *\n* The full license is in the file LICENSE, distributed with this software. *\n****************************************************************************/\n\n#ifndef XFRAME_XAXIS_FUNCTION_HPP\n#define XFRAME_XAXIS_FUNCTION_HPP\n\n#include \"xtensor/xoptional.hpp\"\n#include \"xtensor/xgenerator.hpp\"\n\n#include \"xframe_expression.hpp\"\n#include \"xframe_utils.hpp\"\n#include \"xaxis_meta.hpp\"\n#include \"xaxis_expression_leaf.hpp\"\n\nnamespace xf\n{\n    /******************\n     * xaxis_function *\n     ******************/\n\n    /**\n     * @class xaxis_function\n     * @brief An expression of xaxis\n     *\n     * The xaxis_function class is used for creating an expression on named axis, e.g.\n     * `auto expr = not_equal(axis1, 2) && axis2 < 2`.\n     *\n     * @tparam F the function type.\n     * @tparam R the result type.\n     * @tparam CT the function argument types.\n     * @sa xaxis_expression_leaf\n     * @sa xnamed_axis\n     */\n    template <class F, class R, class... CT>\n    class xaxis_function : public xt::xexpression<xaxis_function<F, R, CT...>>\n    {\n    public:\n\n        using self_type = xaxis_function<F, R, CT...>;\n        using functor_type = std::remove_reference_t<F>;\n\n        using value_type = R;\n        using reference = value_type;\n        using const_reference = value_type;\n        using pointer = value_type*;\n        using const_pointer = const value_type*;\n        using name_type = detail::common_name_type_t<std::decay_t<xaxis_expression_closure_t<CT>>...>;\n        using size_type = xt::common_size_type_t<std::decay_t<xaxis_expression_closure_t<CT>>...>;\n\n        template <std::size_t N = dynamic()>\n        using selector_sequence_type = detail::xselector_sequence_t<std::pair<name_type, size_type>, N>;\n\n        using expression_tag = xaxis_expression_tag;\n\n        template <class Func, class U = std::enable_if<!std::is_base_of<Func, self_type>::value>>\n        xaxis_function(Func&& f, CT... e) noexcept;\n\n        template <std::size_t N = dynamic()>\n        const_reference operator()(const selector_sequence_type<N>& selector) const;\n\n    private:\n\n        template <std::size_t N, std::size_t... I>\n        const_reference evaluate(std::index_sequence<I...>, const selector_sequence_type<N>& selector) const;\n\n        std::tuple<xaxis_expression_closure_t<CT>...> m_e;\n        functor_type m_f;\n    };\n\n    /*********************************\n     * xaxis_function implementation *\n     *********************************/\n\n    /**\n     * Builds an axis function.\n     * @param f the function to apply.\n     * @param e the function arguments.\n     */\n    template <class F, class R, class... CT>\n    template <class Func, class>\n    inline xaxis_function<F, R, CT...>::xaxis_function(Func&& f, CT... e) noexcept\n        : m_e(detail::get_axis_closure(std::forward<CT>(e))...),\n          m_f(std::forward<Func>(f))\n    {\n    }\n\n    /**\n     * Returns an evaluation of the xaxis_function.\n     * Example:\n     * \\code{.cpp}\n     * auto axis1 = named_axis(\"abs\", axis(16));\n     * auto axis2 = named_axis(\"ord\", axis({'a', 'c', 'i'}));\n     *\n     * auto func1 = axis1 < 5 && not_equal(axis2, 'i');\n     *\n     * // This will evaluate the xaxis_function for `axis1.label(10) == 9` and `axis2.label(1) == 'c'``\n     * func1({{\"abs\", 10}, {\"ord\", 1}});\n     * \\endcode\n     *\n     * @param selector a selector_sequence_type for selecting the position\n     *                 where you want to evaluate the function.\n     * @return the evaluation of the xaxis_function\n     */\n    template <class F, class R, class... CT>\n    template <std::size_t N>\n    inline auto xaxis_function<F, R, CT...>::operator()(const selector_sequence_type<N>& selector) const -> const_reference\n    {\n        return evaluate<N>(std::make_index_sequence<sizeof...(CT)>(), selector);\n    }\n\n    template <class F, class R, class... CT>\n    template <std::size_t N, std::size_t... I>\n    inline auto xaxis_function<F, R, CT...>::evaluate(std::index_sequence<I...>, const selector_sequence_type<N>& selector) const -> const_reference\n    {\n#ifdef _MSC_VER\n        return m_f(std::get<I>(m_e).operator()<N>(selector)...);\n#else\n        return m_f(std::get<I>(m_e).template operator()<N>(selector)...);\n#endif\n    }\n\n    /**********************\n     * axis_function_mask *\n     **********************/\n\n    namespace detail\n    {\n        template <class AF, class DM>\n        class axis_function_mask_impl\n        {\n        public:\n\n            using axis_function_type = std::remove_reference_t<AF>;\n\n            using value_type = typename axis_function_type::value_type;\n            using name_type = typename axis_function_type::name_type;\n            using size_type = typename axis_function_type::size_type;\n\n            template <std::size_t N = dynamic()>\n            using selector_sequence_type = detail::xselector_sequence_t<std::pair<name_type, size_type>, N>;\n\n            axis_function_mask_impl(AF&& axis_function, DM&& dim_mapping)\n                : m_axis_function(std::forward<AF>(axis_function)),\n                  m_dimension_mapping(std::forward<DM>(dim_mapping))\n            {\n            }\n\n            template <class... Args>\n            inline value_type operator()(Args... args) const\n            {\n                auto selector = make_selector(std::make_index_sequence<sizeof...(Args)>(), args...);\n#ifdef _MSC_VER\n                return m_axis_function.operator()<sizeof...(Args)>(selector);\n#else\n                return m_axis_function.template operator()<sizeof...(Args)>(selector);\n#endif\n            }\n\n            template <class It>\n            inline value_type element(It first, It last) const\n            {\n                // TODO avoid dynamic allocation\n                auto selector = selector_sequence_type<dynamic()>();\n                std::size_t i = 0;\n                for (It it = first; it != last; ++it)\n                {\n                    selector.push_back(std::make_pair(m_dimension_mapping.label(i++), static_cast<size_type>(*it)));\n                }\n#ifdef _MSC_VER\n                return m_axis_function.operator()<dynamic()>(selector);\n#else\n                return m_axis_function.template operator()<dynamic()>(selector);\n#endif\n            }\n\n        private:\n\n            AF m_axis_function;\n            DM m_dimension_mapping;\n\n            template <class... Args, std::size_t... I>\n            inline selector_sequence_type<sizeof...(Args)> make_selector(std::index_sequence<I...>, Args&&... args) const\n            {\n                return {std::make_pair(m_dimension_mapping.label(I), static_cast<size_type>(args))...};\n            }\n        };\n    }\n\n    template <class AF, class DM, class S>\n    inline auto axis_function_mask(AF&& axis_function, DM&& dim_mapping, const S& shape) noexcept\n    {\n        return xt::detail::make_xgenerator(\n            detail::axis_function_mask_impl<AF, DM>(std::forward<AF>(axis_function), std::forward<DM>(dim_mapping)),\n            shape\n        );\n    }\n}\n\n#endif\n"
  },
  {
    "path": "include/xframe/xaxis_index_slice.hpp",
    "content": "/***************************************************************************\n* Copyright (c) Johan Mabille, Sylvain Corlay, Wolf Vollprecht and         *\n* Martin Renou                                                             *\n* Copyright (c) QuantStack                                                 *\n*                                                                          *\n* Distributed under the terms of the BSD 3-Clause License.                 *\n*                                                                          *\n* The full license is in the file LICENSE, distributed with this software. *\n****************************************************************************/\n\n#ifndef XFRAME_XAXIS_INDEX_SLICE_HPP\n#define XFRAME_XAXIS_INDEX_SLICE_HPP\n\n#include <cstddef>\n#include <type_traits>\n#include \"xtl/xvariant.hpp\"\n#include \"xtensor/xstorage.hpp\"\n#include \"xtensor/xslice.hpp\"\n\nnamespace xf\n{\n\n    /*********************\n     * xaxis_index_slice *\n     *********************/\n\n    template <class T>\n    class xaxis_index_slice;\n\n    namespace detail\n    {\n        template <class T>\n        struct is_xaxis_index_slice : std::false_type\n        {\n        };\n\n        template <class T>\n        struct is_xaxis_index_slice<xaxis_index_slice<T>> : std::true_type\n        {\n        };\n\n        template <class S>\n        using disable_xaxis_index_slice_t = std::enable_if_t<!is_xaxis_index_slice<std::decay_t<S>>::value, void>;\n    }\n\n    template <class T>\n    class xaxis_index_slice\n    {\n    public:\n\n        using self_type = xaxis_index_slice<T>;\n        using size_type = T;\n        using storage_type = xtl::variant<xt::xrange<T>,\n                                          xt::xstepped_range<T>,\n                                          xt::xkeep_slice<T>,\n                                          xt::xdrop_slice<T>,\n                                          xt::xall<T>>;\n\n        xaxis_index_slice() = default;\n        template <class S, typename = detail::disable_xaxis_index_slice_t<S>>\n        xaxis_index_slice(S&& slice) noexcept;\n\n        size_type size() const noexcept;\n        bool contains(size_type i) const noexcept;\n\n        size_type operator()(size_type i) const noexcept;\n        size_type step_size(size_type i, size_type n = 1) const noexcept;\n\n        size_type revert_index(size_type i) const noexcept;\n\n        template <class V, class U>\n        V convert_storage() const;\n\n        bool operator==(const self_type& rhs) const noexcept;\n        bool operator!=(const self_type& rhs) const noexcept;\n\n    private:\n\n        storage_type m_slice;\n    };\n\n    /*********************\n     * Builder functions *\n     *********************/\n\n    template <class A>\n    auto irange(A start_val);\n\n    template <class A, class B>\n    auto irange(A start_val, B stop_val);\n\n    template <class A, class B, class C>\n    auto irange(A start_val, B stop_val, C step);\n\n    template <class... T>\n    auto ikeep(T&&... t);\n\n    template <class... T>\n    auto idrop(T&&... t);\n\n    auto iall() noexcept;\n\n    /************************************\n     * xaxis_index_slice implementation *\n     ************************************/\n\n    template <class T>\n    template <class S, typename>\n    inline xaxis_index_slice<T>::xaxis_index_slice(S&& slice) noexcept\n        : m_slice(std::forward<S>(slice))\n    {\n    }\n\n    template <class T>\n    inline auto xaxis_index_slice<T>::size() const noexcept -> size_type\n    {\n        return xtl::visit([](auto&& arg) { return arg.size(); }, m_slice);\n    }\n\n    template <class T>\n    inline bool xaxis_index_slice<T>::contains(size_type i) const noexcept\n    {\n        return xtl::visit([i](auto&& arg) { return arg.contains(i); }, m_slice);\n    }\n\n    template <class T>\n    inline auto xaxis_index_slice<T>::operator()(size_type i) const noexcept -> size_type\n    {\n        return xtl::visit([i](auto&& arg) { return arg(i); }, m_slice);\n    }\n\n    template <class T>\n    inline auto xaxis_index_slice<T>::step_size(size_type i, size_type n) const noexcept -> size_type\n    {\n        return xtl::visit([i, n](auto&& arg) { return arg.step_size(i, n); }, m_slice);\n    }\n\n    template <class T>\n    inline auto xaxis_index_slice<T>::revert_index(size_type i) const noexcept -> size_type\n    {\n        return xtl::visit([i](auto&& arg) { return arg.revert_index(i); }, m_slice);\n    }\n\n    // TODO: remove this when xrange and xstepped_range has been added\n    // to xdynamic_slice in xtensor\n    namespace detail\n    {\n        template <class U, class T>\n        inline xt::xrange_adaptor<U, U, U> convert_range(const xt::xrange<T>& r)\n        {\n            T start = r(T(0));\n            T stop = start + r.size();\n            return xt::xrange_adaptor<U, U, U>(start, stop, T(1));\n        }\n\n        template <class U, class T>\n        inline xt::xrange_adaptor<U, U, U> convert_range(const xt::xstepped_range<T>& r)\n        {\n            T start = r(T(0));\n            T stop = start + r.size();\n            T step = r.step_size(T(0));\n            return xt::xrange_adaptor<U, U, U>(start, stop, step);\n        }\n    }\n\n    template <class T>\n    template <class V, class U>\n    inline V xaxis_index_slice<T>::convert_storage() const\n    {\n        return xtl::visit(\n            xtl::make_overload(\n                /*[](const xt::xrange<T>& s) -> V { return detail::convert_range<U>(s); },\n                [](const xt::xstepped_range<T>& s) -> V { return detail::convert_range<U>(s); },*/\n                [](const xt::xrange<T>& s) -> V { return xt::xrange<U>(s); },\n                [](const xt::xstepped_range<T>& s) -> V { return xt::xstepped_range<U>(s); },\n                [](const xt::xkeep_slice<T>& s) -> V { return xt::xkeep_slice<U>(s); },\n                [](const xt::xdrop_slice<T>& s) -> V { return xt::xdrop_slice<U>(s); },\n                [](const xt::xall<T>&) -> V { return xt::xall_tag(); }),\n            m_slice);\n    }\n\n    template <class T>\n    inline bool xaxis_index_slice<T>::operator==(const self_type& rhs) const noexcept\n    {\n        return m_slice == rhs.m_slice;\n    }\n\n    template <class T>\n    inline bool xaxis_index_slice<T>::operator!=(const self_type& rhs) const noexcept\n    {\n        return !(*this == rhs);\n    }\n\n    /************************************\n     * Builder functions implementation *\n     ************************************/\n    template <class A>\n    inline auto irange(A start_val)\n    {\n        return xt::range(start_val);\n    }\n\n    template <class A, class B>\n    inline auto irange(A start_val, B stop_val)\n    {\n        return xt::range(start_val, stop_val);\n    }\n\n    template <class A, class B, class C>\n    inline auto irange(A start_val, B stop_val, C step)\n    {\n        return xt::range(start_val, stop_val, step);\n    }\n\n    template <class... T>\n    inline auto ikeep(T&&... t)\n    {\n        return xt::keep(std::forward<T>(t)...);\n    }\n\n    template <class... T>\n    inline auto idrop(T&&... t)\n    {\n        return xt::drop(std::forward<T>(t)...);\n    }\n\n    inline auto iall() noexcept\n    {\n        return xt::all();\n    }\n}\n\n#endif\n"
  },
  {
    "path": "include/xframe/xaxis_label_slice.hpp",
    "content": "/***************************************************************************\n* Copyright (c) Johan Mabille, Sylvain Corlay, Wolf Vollprecht and         *\n* Martin Renou                                                             *\n* Copyright (c) QuantStack                                                 *\n*                                                                          *\n* Distributed under the terms of the BSD 3-Clause License.                 *\n*                                                                          *\n* The full license is in the file LICENSE, distributed with this software. *\n****************************************************************************/\n\n#ifndef XFRAME_XAXIS_LABEL_SLICE_HPP\n#define XFRAME_XAXIS_LABEL_SLICE_HPP\n\n#include <cmath>\n#include <xtl/xvariant.hpp>\n#include \"xaxis_index_slice.hpp\"\n#include \"xframe_config.hpp\"\n\nnamespace xf\n{\n    /**************************\n     * xlabel_slice_variant_t *\n     **************************/\n\n    template <class L>\n    using xlabel_variant_t = xtl::mpl::cast_t<L, xtl::variant>;\n\n    /***************\n     * xaxis_range *\n     ***************/\n\n    template <class L>\n    class xaxis_range\n    {\n    public:\n\n        using value_type = xlabel_variant_t<L>;\n\n        xaxis_range(const value_type& first, const value_type& last) noexcept;\n        xaxis_range(value_type&& first, value_type&& last) noexcept;\n\n        template <class A>\n        using index_slice_type = xt::xrange<typename A::mapped_type>;\n\n        template <class A>\n        index_slice_type<A> build_index_slice(const A& axis) const;\n\n    private:\n\n        value_type m_first;\n        value_type m_last;\n    };\n\n    /***********************\n     * xaxis_stepped_range *\n     ***********************/\n\n    template <class L>\n    class xaxis_stepped_range\n    {\n    public:\n\n        using value_type = xlabel_variant_t<L>;\n        using size_type = std::size_t;\n\n        xaxis_stepped_range(const value_type& first, const value_type& last, size_type step) noexcept;\n        xaxis_stepped_range(value_type&& first, value_type&& last, size_type step) noexcept;\n\n        template <class A>\n        using index_slice_type = xt::xstepped_range<typename A::mapped_type>;\n\n        template <class A>\n        index_slice_type<A> build_index_slice(const A& axis) const;\n\n    private:\n\n        value_type m_first;\n        value_type m_last;\n        size_type m_step;\n    };\n\n    /*************\n     * xaxis_all *\n     *************/\n\n    class xaxis_all\n    {\n    public:\n\n        template <class A>\n        using index_slice_type = xt::xall<typename A::mapped_type>;\n\n        template <class A>\n        index_slice_type<A> build_index_slice(const A& axis) const;\n    };\n\n    /********************\n     * xaxis_keep_slice *\n     *******************/\n\n    template <class L>\n    class xaxis_keep_slice;\n\n    namespace detail\n    {\n        template <class T>\n        struct is_xaxis_keep_slice : std::false_type\n        {\n        };\n\n        template <class L>\n        struct is_xaxis_keep_slice<xaxis_keep_slice<L>>\n            : std::true_type\n        {\n        };\n\n        template <class T>\n        using disable_xaxis_keep_slice_t = std::enable_if_t<!is_xaxis_keep_slice<std::decay_t<T>>::value, void>;\n\n        template <class T>\n        using enable_xaxis_keep_slice_t = std::enable_if_t<is_xaxis_keep_slice<std::decay_t<T>>::value, void>;\n    }\n\n    template <class L>\n    class xaxis_keep_slice\n    {\n    public:\n\n        using value_type = xlabel_variant_t<L>;\n        using container_type = xt::svector<value_type>;\n\n        template <class C, typename = detail::disable_xaxis_keep_slice_t<C>>\n        explicit xaxis_keep_slice(C& cont);\n        explicit xaxis_keep_slice(container_type&& cont);\n\n        template <class A>\n        using index_slice_type = xt::xkeep_slice<typename A::mapped_type>;\n\n        template <class A>\n        index_slice_type<A> build_index_slice(const A& axis) const;\n\n    private:\n\n        container_type m_labels;\n    };\n\n    /********************\n     * xaxis_drop_slice *\n     ********************/\n\n    template <class L>\n    class xaxis_drop_slice;\n\n    namespace detail\n    {\n        template <class T>\n        struct is_axis_drop_slice : std::false_type\n        {\n        };\n\n        template <class L>\n        struct is_axis_drop_slice<xaxis_drop_slice<L>>\n            : std::true_type\n        {\n        };\n\n        template <class T>\n        using disable_xaxis_drop_slice_t = std::enable_if_t<!is_axis_drop_slice<std::decay_t<T>>::value, void>;\n\n        template <class T>\n        using enable_xaxis_drop_slice_t = std::enable_if_t<is_axis_drop_slice<std::decay_t<T>>::value, void>;\n    }\n\n    template <class L>\n    class xaxis_drop_slice\n    {\n    public:\n\n        using value_type = xlabel_variant_t<L>;\n        using container_type = xt::svector<value_type>;\n\n        template <class C, typename = detail::disable_xaxis_drop_slice_t<C>>\n        explicit xaxis_drop_slice(C& cont);\n        explicit xaxis_drop_slice(container_type&& cont);\n\n        template <class A>\n        using index_slice_type = xt::xdrop_slice<typename A::mapped_type>;\n\n        template <class A>\n        index_slice_type<A> build_index_slice(const A& axis) const;\n\n    private:\n\n        container_type m_labels;\n    };\n\n    /***************\n     * xaxis_slice *\n     ***************/\n\n    template <class L = XFRAME_DEFAULT_LABEL_LIST>\n    class xaxis_slice\n    {\n    public:\n\n        using squeeze_type = xlabel_variant_t<L>;\n        using storage_type = xtl::variant<xaxis_range<L>,\n                                          xaxis_stepped_range<L>,\n                                          xaxis_keep_slice<L>,\n                                          xaxis_drop_slice<L>,\n                                          xaxis_all,\n                                          squeeze_type>;\n\n        xaxis_slice() = default;\n        template <class V>\n        xaxis_slice(const V& slice);\n        template <class V>\n        xaxis_slice(V&& slice);\n\n        template <class A>\n        using index_slice_type = xaxis_index_slice<typename A::mapped_type>;\n\n        template <class A>\n        index_slice_type<A> build_index_slice(const A& axis) const;\n\n        const squeeze_type* get_squeeze() const noexcept;\n\n    private:\n\n        storage_type m_data;\n    };\n\n    template <class L = XFRAME_DEFAULT_LABEL_LIST>\n    xaxis_slice<L> range(const xlabel_variant_t<L>& first, const xlabel_variant_t<L>& last);\n\n    template <class L = XFRAME_DEFAULT_LABEL_LIST>\n    xaxis_slice<L> range(xlabel_variant_t<L>&& first, xlabel_variant_t<L>&& last);\n\n    template <class S, class L = XFRAME_DEFAULT_LABEL_LIST>\n    xaxis_slice<L> range(const xlabel_variant_t<L>& first, const xlabel_variant_t<L>& last, S step);\n\n    template <class S, class L = XFRAME_DEFAULT_LABEL_LIST>\n    xaxis_slice<L> range(xlabel_variant_t<L>&& first, xlabel_variant_t<L>&& last, S step);\n\n    xaxis_all all() noexcept;\n\n    namespace detail\n    {\n        template <class T, typename = xt::void_t<>>\n        struct has_size : std::false_type\n        {\n        };\n\n        template <class T>\n        struct has_size<T, xt::void_t<decltype(std::declval<T>().size())>>\n            : std::true_type\n        {\n        };\n\n        template <class T, class R>\n        using enable_container_t = std::enable_if_t<has_size<T>::value, R>;\n\n        template <class T, class R>\n        using disable_container_t = std::enable_if_t<!has_size<T>::value, R>;\n    }\n\n    template <class L = XFRAME_DEFAULT_LABEL_LIST, class T>\n    detail::enable_container_t<T, xaxis_slice<L>> keep(T&& indices);\n\n    template <class L = XFRAME_DEFAULT_LABEL_LIST, class T>\n    detail::disable_container_t<T, xaxis_slice<L>> keep(T index);\n\n    template <class L = XFRAME_DEFAULT_LABEL_LIST, class T0, class T1, class... Args>\n    xaxis_slice<L> keep(T0 t0, T1 t1, Args... args);\n\n    template <class L = XFRAME_DEFAULT_LABEL_LIST, class T>\n    detail::enable_container_t<T, xaxis_slice<L>> drop(T&& indices);\n\n    template <class L = XFRAME_DEFAULT_LABEL_LIST, class T>\n    detail::disable_container_t<T, xaxis_slice<L>> drop(T index);\n\n    template <class L = XFRAME_DEFAULT_LABEL_LIST, class T0, class T1, class... Args>\n    xaxis_slice<L> drop(T0 t0, T1 t1, Args... args);\n\n    /******************************\n     * xaxis_range implementation *\n     ******************************/\n\n    template <class V>\n    inline xaxis_range<V>::xaxis_range(const value_type& first, const value_type& last) noexcept\n        : m_first(first), m_last(last)\n    {\n    }\n\n    template <class V>\n    inline xaxis_range<V>::xaxis_range(value_type&& first, value_type&& last) noexcept\n        : m_first(std::move(first)), m_last(std::move(last))\n    {\n    }\n\n    template <class V>\n    template <class A>\n    inline auto xaxis_range<V>::build_index_slice(const A& axis) const -> index_slice_type<A>\n    {\n        return index_slice_type<A>(axis[m_first], axis[m_last] + 1);\n    }\n\n    /**************************************\n     * xaxis_stepped_range implementation *\n     **************************************/\n\n    template <class V>\n    inline xaxis_stepped_range<V>::xaxis_stepped_range(const value_type& first, const value_type& last, size_type step) noexcept\n        : m_first(first), m_last(last), m_step(step)\n    {\n    }\n\n    template <class V>\n    inline xaxis_stepped_range<V>::xaxis_stepped_range(value_type&& first, value_type&& last, size_type step) noexcept\n        : m_first(std::move(first)), m_last(std::move(last)), m_step(step)\n    {\n    }\n\n    template <class V>\n    template <class A>\n    inline auto xaxis_stepped_range<V>::build_index_slice(const A& axis) const -> index_slice_type<A>\n    {\n        return index_slice_type<A>(axis[m_first], axis[m_last] + 1, m_step);\n    }\n\n    /****************************\n     * xaxis_all implementation *\n     ****************************/\n\n    template <class A>\n    inline auto xaxis_all::build_index_slice(const A& axis) const -> index_slice_type<A>\n    {\n        return index_slice_type<A>(axis.size());\n    }\n\n    /*****************************\n     * xaxis_keep_implementation *\n     *****************************/\n\n    template <class L>\n    template <class C, typename>\n    inline xaxis_keep_slice<L>::xaxis_keep_slice(C& cont)\n        : m_labels(cont.begin(), cont.end())\n    {\n    }\n\n    template <class L>\n    inline xaxis_keep_slice<L>::xaxis_keep_slice(container_type&& cont)\n        : m_labels(std::move(cont))\n    {\n    }\n\n    template <class L>\n    template <class A>\n    inline auto xaxis_keep_slice<L>::build_index_slice(const A& axis) const -> index_slice_type<A>\n    {\n        using index_container_type = typename index_slice_type<A>::container_type;\n        index_container_type c(m_labels.size());\n        std::transform(m_labels.cbegin(), m_labels.cend(), c.begin(), [&axis](const auto& arg) { return axis[arg]; });\n        index_slice_type<A> res(std::move(c));\n        res.normalize(axis.size());\n        return res;\n    }\n\n    /****************************\n     * xaxis_drop_implemenation *\n     ****************************/\n\n    template <class L>\n    template <class C, typename>\n    inline xaxis_drop_slice<L>::xaxis_drop_slice(C& cont)\n        : m_labels(cont.begin(), cont.end())\n    {\n    }\n\n    template <class L>\n    inline xaxis_drop_slice<L>::xaxis_drop_slice(container_type&& cont)\n        : m_labels(std::move(cont))\n    {\n    }\n\n    template <class L>\n    template <class A>\n    inline auto xaxis_drop_slice<L>::build_index_slice(const A& axis) const -> index_slice_type<A>\n    {\n        using index_container_type = typename index_slice_type<A>::container_type;\n        index_container_type c(m_labels.size());\n        std::transform(m_labels.cbegin(), m_labels.cend(), c.begin(), [&axis](const auto& arg) { return axis[arg]; });\n        index_slice_type<A> res(std::move(c));\n        res.normalize(axis.size());\n        return res;\n    }\n\n    /******************************\n     * xaxis_slice implementation *\n     ******************************/\n\n    template <class L>\n    template <class V>\n    inline xaxis_slice<L>::xaxis_slice(const V& slice)\n        : m_data(slice)\n    {\n    }\n\n    template <class L>\n    template <class V>\n    inline xaxis_slice<L>::xaxis_slice(V&& slice)\n        : m_data(std::move(slice))\n    {\n    }\n\n    template <class L>\n    template <class A>\n    inline auto xaxis_slice<L>::build_index_slice(const A& axis) const -> index_slice_type<A>\n    {\n        return xtl::visit(\n            xtl::make_overload(\n                [&axis](const auto& arg) { return index_slice_type<A>(arg.build_index_slice(axis)); },\n                [&axis](const squeeze_type&) -> index_slice_type<A> { throw std::runtime_error(\"build_islice forbidden for squeeze\"); }\n            ),\n            m_data);\n    }\n\n    template <class L>\n    inline auto xaxis_slice<L>::get_squeeze() const noexcept -> const squeeze_type*\n    {\n        return xtl::get_if<squeeze_type>(&m_data);\n    }\n\n    /***********************************\n     * helper functions implementation *\n     ***********************************/\n\n    template <class L>\n    inline xaxis_slice<L> range(const xlabel_variant_t<L>& first, const xlabel_variant_t<L>& last)\n    {\n        return xaxis_slice<L>(xaxis_range<L>(first, last));\n    }\n\n    template <class L>\n    inline xaxis_slice<L> range(xlabel_variant_t<L>&& first, xlabel_variant_t<L>&& last)\n    {\n        return xaxis_slice<L>(xaxis_range<L>(std::move(first), std::move(last)));\n    }\n\n    template <class S, class L>\n    inline xaxis_slice<L> range(const xlabel_variant_t<L>& first, const xlabel_variant_t<L>& last, S step)\n    {\n        return xaxis_slice<L>(xaxis_stepped_range<L>(first, last, step));\n    }\n\n    template <class S, class L>\n    inline xaxis_slice<L> range(xlabel_variant_t<L>&& first, xlabel_variant_t<L>&& last, S step)\n    {\n        return xaxis_slice<L>(xaxis_stepped_range<L>(std::move(first), std::move(last), step));\n    }\n\n    namespace detail\n    {\n        template <template <class> class R, class L, class T>\n        inline detail::enable_container_t<T, xaxis_slice<L>>\n        common_drop_keep(T&& indices)\n        {\n            R<L> slice(std::forward<T>(indices));\n            return xaxis_slice<L>(std::move(slice));\n        }\n\n        template <template <class> class R, class L, class T>\n        inline detail::disable_container_t<T, xaxis_slice<L>>\n        common_drop_keep(T index)\n        {\n            using slice_type = R<L>;\n            using container_type = typename slice_type::container_type;\n            using value_type = typename slice_type::value_type;\n            container_type tmp = { value_type(index) };\n            return xaxis_slice<L>(slice_type(std::move(tmp)));\n        }\n\n        template <template <class> class R, class L, class T0, class T1, class... Args>\n        inline xaxis_slice<L>\n        common_drop_keep(T0 t0, T1 t1, Args... args)\n        {\n            using slice_type = R<L>;\n            using container_type = typename slice_type::container_type;\n            using value_type = typename slice_type::value_type;\n            container_type tmp = { value_type(t0), value_type(t1), value_type(args)... };\n            return xaxis_slice<L>(slice_type(std::move(tmp)));\n        }\n    }\n\n    template <class L, class T>\n    inline detail::enable_container_t<T, xaxis_slice<L>> keep(T&& indices)\n    {\n        return detail::common_drop_keep<xaxis_keep_slice, L>(std::forward<T>(indices));\n    }\n\n    template <class L, class T>\n    inline detail::disable_container_t<T, xaxis_slice<L>> keep(T index)\n    {\n        return detail::common_drop_keep<xaxis_keep_slice, L>(index);\n    }\n\n    template <class L, class T0, class T1, class... Args>\n    inline xaxis_slice<L> keep(T0 t0, T1 t1, Args... args)\n    {\n        return detail::common_drop_keep<xaxis_keep_slice, L>(t0, t1, args...);\n    }\n\n    template <class L, class T>\n    inline detail::enable_container_t<T, xaxis_slice<L>> drop(T&& indices)\n    {\n        return detail::common_drop_keep<xaxis_drop_slice, L>(std::forward<T>(indices));\n    }\n\n    template <class L, class T>\n    inline detail::disable_container_t<T, xaxis_slice<L>> drop(T index)\n    {\n        return detail::common_drop_keep<xaxis_drop_slice, L>(index);\n    }\n\n    template <class L, class T0, class T1, class... Args>\n    inline xaxis_slice<L> drop(T0 t0, T1 t1, Args... args)\n    {\n        return detail::common_drop_keep<xaxis_drop_slice, L>(t0, t1, args...);\n    }\n\n    inline xaxis_all all() noexcept\n    {\n        return xaxis_all();\n    }\n}\n\n#endif\n"
  },
  {
    "path": "include/xframe/xaxis_math.hpp",
    "content": "/***************************************************************************\n* Copyright (c) Johan Mabille, Sylvain Corlay, Wolf Vollprecht and         *\n* Martin Renou                                                             *\n* Copyright (c) QuantStack                                                 *\n*                                                                          *\n* Distributed under the terms of the BSD 3-Clause License.                 *\n*                                                                          *\n* The full license is in the file LICENSE, distributed with this software. *\n****************************************************************************/\n\n#ifndef XFRAME_XAXIS_MATH_HPP\n#define XFRAME_XAXIS_MATH_HPP\n\n#include \"xtensor/xmath.hpp\"\n\n#include \"xframe_expression.hpp\"\n#include \"xaxis_function.hpp\"\n\nnamespace xt\n{\n    namespace detail\n    {\n        template <class F, class... E>\n        struct select_xfunction_expression<xf::xaxis_expression_tag, F, E...>\n        {\n            using result_type = decltype(std::declval<F>()(std::declval<xvalue_type_t<std::decay_t<E>>>()...));\n            using type = xf::xaxis_function<F, result_type, E...>;\n        };\n    }\n}\n\nnamespace xf\n{\n    using xt::operator+;\n    using xt::operator-;\n    using xt::operator*;\n    using xt::operator/;\n    using xt::operator%;\n\n    using xt::operator||;\n    using xt::operator&&;\n    using xt::operator!;\n\n    using xt::operator&;\n    using xt::operator|;\n    using xt::operator^;\n    using xt::operator~;\n\n    using xt::operator!=;\n    using xt::operator<;\n    using xt::operator<=;\n    using xt::operator>;\n    using xt::operator>=;\n\n    using xt::equal;\n    using xt::not_equal;\n\n    using xt::abs;\n    using xt::fabs;\n    using xt::fmod;\n    using xt::remainder;\n    using xt::fma;\n    using xt::fmax;\n    using xt::fmin;\n    using xt::fdim;\n    using xt::maximum;\n    using xt::minimum;\n    using xt::clip;\n    using xt::sign;\n\n    using xt::exp;\n    using xt::exp2;\n    using xt::expm1;\n    using xt::log;\n    using xt::log10;\n    using xt::log2;\n    using xt::log1p;\n\n    using xt::pow;\n    using xt::sqrt;\n    using xt::cbrt;\n    using xt::hypot;\n\n    using xt::sin;\n    using xt::cos;\n    using xt::tan;\n    using xt::asin;\n    using xt::acos;\n    using xt::atan;\n    using xt::atan2;\n\n    using xt::sinh;\n    using xt::cosh;\n    using xt::tanh;\n    using xt::asinh;\n    using xt::acosh;\n    using xt::atanh;\n\n    using xt::erf;\n    using xt::erfc;\n    using xt::tgamma;\n    using xt::lgamma;\n\n    using xt::ceil;\n    using xt::floor;\n    using xt::trunc;\n    using xt::round;\n    using xt::nearbyint;\n    using xt::rint;\n\n    using xt::isfinite;\n    using xt::isinf;\n    using xt::isnan;\n    // Needs a fix in xtensor\n    /*using xt::isclose;\n    using xt::allclose;*/\n\n    using xt::where;\n}\n\n#endif\n"
  },
  {
    "path": "include/xframe/xaxis_meta.hpp",
    "content": "/***************************************************************************\n* Copyright (c) Johan Mabille, Sylvain Corlay, Wolf Vollprecht and         *\n* Martin Renou                                                             *\n* Copyright (c) QuantStack                                                 *\n*                                                                          *\n* Distributed under the terms of the BSD 3-Clause License.                 *\n*                                                                          *\n* The full license is in the file LICENSE, distributed with this software. *\n****************************************************************************/\n\n#ifndef XFRAME_XAXIS_META_HPP\n#define XFRAME_XAXIS_META_HPP\n\n#include \"xtl/xbasic_fixed_string.hpp\"\n#include \"xtl/xvariant.hpp\"\n#include \"xtl/xmeta_utils.hpp\"\n\n#include \"xframe_config.hpp\"\n#include \"xaxis_scalar.hpp\"\n\nnamespace xf\n{\n    template <class K, class T, class MT, class L, class LT>\n    class xnamed_axis;\n\n    template <class CTA>\n    class xaxis_expression_leaf;\n\n    namespace detail\n    {\n\n        template <class... Args>\n        struct common_name_type;\n\n        template <class T, class... Args>\n        struct common_name_type<T, Args...>\n        {\n            using tmp_type = typename common_name_type<Args...>::type;\n            using type = typename common_name_type<T, tmp_type>::type;\n        };\n\n        template <class T1, class T2>\n        struct common_name_type<T1, xaxis_scalar<T2>>\n        {\n            using type = typename T1::name_type;\n        };\n\n        template <class T1, class T2>\n        struct common_name_type<xaxis_scalar<T1>, T2>\n        {\n            using type = typename T2::name_type;\n        };\n\n        template <class T1, class T2>\n        struct common_name_type<xaxis_scalar<T1>, xaxis_scalar<T2>>\n        {\n            using type = xaxis_scalar_name;\n        };\n\n        template <class T1, class T2>\n        struct common_name_type<T1, T2>\n        {\n            using type = std::common_type_t<typename T1::name_type, typename T2::name_type>;\n        };\n\n        template <class... Args>\n        using common_name_type_t = typename common_name_type<Args...>::type;\n\n        template <class CTA, bool val>\n        struct axis_closure_getter\n        {\n            static auto get_axis_closure(CTA&& axis)\n            {\n                return xaxis_expression_leaf<CTA>(std::forward<CTA>(axis));\n            }\n        };\n\n        template <class CTA>\n        struct axis_closure_getter<CTA, false>\n        {\n            static auto get_axis_closure(CTA&& axis)\n            {\n                return std::forward<CTA>(axis);\n            }\n        };\n\n        template <class T>\n        struct is_named_axis : std::false_type\n        {\n        };\n\n        template <class K, class T, class MT, class L, class LT>\n        struct is_named_axis<xnamed_axis<K, T, MT, L, LT>> : std::true_type\n        {\n        };\n\n        template <class CTA>\n        auto get_axis_closure(CTA&& axis)\n        {\n            return axis_closure_getter<CTA, is_named_axis<std::decay_t<CTA>>::value>::get_axis_closure(std::forward<CTA>(axis));\n        }\n    }\n\n    /*****************\n     * xaxis_closure *\n     *****************/\n\n    template <class CT>\n    struct xaxis_closure\n    {\n        using type = CT;\n    };\n\n    template <class CT>\n    using xaxis_closure_t = typename xaxis_closure<CT>::type;\n\n    /****************************\n     * xaxis_expression_closure *\n     ****************************/\n\n    template <class CT, bool val>\n    struct axis_expression_closure_getter\n    {\n        using type = xaxis_expression_leaf<CT>;\n    };\n\n    template <class CT>\n    struct axis_expression_closure_getter<CT, false>\n    {\n        using type = CT;\n    };\n\n    template <class CT>\n    struct axis_expression_closure_getter<xt::xscalar<CT>, false>\n    {\n        using type = xaxis_scalar<CT>;\n    };\n\n    template <class CT>\n    struct xaxis_expression_closure\n    {\n        using type = typename axis_expression_closure_getter<CT, detail::is_named_axis<std::decay_t<CT>>::value>::type;\n    };\n\n    template <class CT>\n    using xaxis_expression_closure_t = typename xaxis_expression_closure<CT>::type;\n}\n\n#endif\n"
  },
  {
    "path": "include/xframe/xaxis_scalar.hpp",
    "content": "/***************************************************************************\n* Copyright (c) Johan Mabille, Sylvain Corlay, Wolf Vollprecht and         *\n* Martin Renou                                                             *\n* Copyright (c) QuantStack                                                 *\n*                                                                          *\n* Distributed under the terms of the BSD 3-Clause License.                 *\n*                                                                          *\n* The full license is in the file LICENSE, distributed with this software. *\n****************************************************************************/\n\n#ifndef XFRAME_XAXIS_SCALAR_HPP\n#define XFRAME_XAXIS_SCALAR_HPP\n\n#include \"xtl/xvariant.hpp\"\n#include \"xtl/xmeta_utils.hpp\"\n\n#include \"xtensor/xoptional.hpp\"\n\n#include \"xframe_config.hpp\"\n#include \"xframe_utils.hpp\"\n#include \"xframe_expression.hpp\"\n\nnamespace xf\n{\n    struct xaxis_scalar_name\n    {\n    };\n\n    /****************\n     * xaxis_scalar *\n     ****************/\n\n    template <class CT>\n    class xaxis_scalar\n    {\n    public:\n\n        using name_type = xaxis_scalar_name;\n\n        using data_type = xt::xscalar<CT>;\n        using value_type = typename data_type::value_type;\n        using reference = typename data_type::reference;\n        using const_reference = typename data_type::const_reference;\n        using pointer = typename data_type::pointer;\n        using const_pointer = typename data_type::const_pointer;\n        using size_type = typename data_type::size_type;\n\n        using expression_tag = xaxis_expression_tag;\n\n        xaxis_scalar(const xt::xscalar<CT>& v) noexcept;\n\n        template <std::size_t N = dynamic(), class S>\n        const_reference operator()(S&& /*selector*/) const;\n\n    private:\n\n        data_type m_data;\n    };\n\n    /*******************************\n     * xaxis_scalar implementation *\n     *******************************/\n\n    template <class CT>\n    xaxis_scalar<CT>::xaxis_scalar(const xt::xscalar<CT>& v) noexcept\n        : m_data(v)\n    {\n    }\n\n    template <class CT>\n    template <std::size_t N, class S>\n    auto xaxis_scalar<CT>::operator()(S&& /*selector*/) const -> const_reference\n    {\n        return m_data;\n    }\n}\n\n#endif\n"
  },
  {
    "path": "include/xframe/xaxis_variant.hpp",
    "content": "/***************************************************************************\n* Copyright (c) Johan Mabille, Sylvain Corlay, Wolf Vollprecht and         *\n* Martin Renou                                                             *\n* Copyright (c) QuantStack                                                 *\n*                                                                          *\n* Distributed under the terms of the BSD 3-Clause License.                 *\n*                                                                          *\n* The full license is in the file LICENSE, distributed with this software. *\n****************************************************************************/\n\n#ifndef XFRAME_XAXIS_VARIANT_HPP\n#define XFRAME_XAXIS_VARIANT_HPP\n\n#include <functional>\n#include \"xtl/xclosure.hpp\"\n#include \"xtl/xmeta_utils.hpp\"\n#include \"xtl/xvariant.hpp\"\n#include \"xaxis.hpp\"\n#include \"xaxis_default.hpp\"\n#include \"xvector_variant.hpp\"\n\nnamespace xf\n{\n\n    namespace detail\n    {\n        template <class V, class S, class... L>\n        struct add_default_axis;\n\n        template <class... A, class S>\n        struct add_default_axis<xtl::variant<A...>, S>\n        {\n            using type = xtl::variant<A...>;\n        };\n\n        template <class... A, class S, class L1, class... L>\n        struct add_default_axis<xtl::variant<A...>, S, L1, L...>\n        {\n            using type = typename xtl::mpl::if_t<std::is_integral<L1>,\n                add_default_axis<xtl::variant<A..., xaxis_default<L1, S>>, S, L...>,\n                add_default_axis<xtl::variant<A...>, S, L...>>::type;\n        };\n\n        template <class V, class S, class... L>\n        using add_default_axis_t = typename add_default_axis<V, S, L...>::type;\n\n        template <class V>\n        struct get_axis_variant_iterator;\n\n        template <class... A>\n        struct get_axis_variant_iterator<xtl::variant<A...>>\n        {\n            using type = xtl::variant<typename A::const_iterator...>;\n        };\n\n        template <class V>\n        using get_axis_variant_iterator_t = typename get_axis_variant_iterator<V>::type;\n\n        template <class S, class MT, class TL>\n        struct xaxis_variant_traits;\n\n        template <class S, class MT, template <class...> class TL, class... L>\n        struct xaxis_variant_traits<S, MT, TL<L...>>\n        {\n            using tmp_storage_type = xtl::variant<xaxis<L, S, MT>...>;\n            using storage_type = add_default_axis_t<tmp_storage_type, S, L...>;\n            using label_list = xvector_variant_cref<std::vector<L>...>;\n            using key_type = xtl::variant<typename xaxis<L, S, MT>::key_type...>;\n            using key_reference = xtl::variant<xtl::xclosure_wrapper<const typename xaxis<L, S, MT>::key_type&>...>;\n            using mapped_type = S;\n            using value_type = std::pair<key_type, mapped_type>;\n            using reference = std::pair<key_reference, mapped_type&>;\n            using const_reference = std::pair<key_reference, const mapped_type&>;\n            using pointer = xtl::xclosure_pointer<reference>;\n            using const_pointer = xtl::xclosure_pointer<const_reference>;\n            using size_type = typename label_list::size_type;\n            using difference_type = typename label_list::difference_type;\n            using subiterator = get_axis_variant_iterator_t<storage_type>;\n        };\n    }\n\n    template <class L, class T, class MT>\n    class xaxis_variant_iterator;\n\n    /*****************\n     * xaxis_variant *\n     *****************/\n\n    /**\n     * @class xaxis_variant\n     * @brief Axis whose label type is a variant\n     *\n     * The xaxis_variant holds a variant of axes with different label types. It\n     * provides the same API as a regular axis, wrapping the visitor mechanism\n     * required to access the underlying axis. This allows to store axes with\n     * different label types in a coordinate system.\n     *\n     * @tparam L the type list of labels\n     * @tparam T the integer type used to represent positions.\n     * @tparam MT the tag used for choosing the map type which holds the label-\n     *            position pairs. Possible values are \\c map_tag and \\c hash_map_tag.\n     *            Default value is \\c hash_map_tag.\n     */\n    template <class L, class T, class MT = hash_map_tag>\n    class xaxis_variant\n    {\n    public:\n\n        static_assert(std::is_integral<T>::value, \"index_type must be an integral type\");\n\n        using self_type = xaxis_variant<L, T, MT>;\n        using map_container_tag = MT;\n        using traits_type = detail::xaxis_variant_traits<T, MT, L>;\n        using storage_type = typename traits_type::storage_type;\n        using key_type = typename traits_type::key_type;\n        using key_reference = typename traits_type::key_reference;\n        using mapped_type = T;\n        using label_list = typename traits_type::label_list;\n        using value_type = typename traits_type::value_type;\n        using reference = typename traits_type::reference;\n        using const_reference = typename traits_type::const_reference;\n        using pointer = typename traits_type::pointer;\n        using const_pointer = typename traits_type::const_pointer;\n        using size_type = typename traits_type::size_type;\n        using difference_type = typename traits_type::difference_type;\n        using iterator = xaxis_variant_iterator<L, T, MT>;\n        using const_iterator = iterator;\n        using reverse_iterator = std::reverse_iterator<iterator>;\n        using const_reverse_iterator = std::reverse_iterator<const_iterator>;\n        using subiterator = typename traits_type::subiterator;\n\n        xaxis_variant() = default;\n        template <class LB>\n        xaxis_variant(const xaxis<LB, T, MT>& axis);\n        template <class LB>\n        xaxis_variant(xaxis<LB, T, MT>&& axis);\n        template <class LB>\n        xaxis_variant(const xaxis_default<LB, T>& axis);\n        template <class LB>\n        xaxis_variant(xaxis_default<LB, T>&& axis);\n\n        label_list labels() const;\n        key_type label(size_type i) const;\n\n        bool empty() const;\n        size_type size() const;\n\n        bool is_sorted() const noexcept;\n\n        bool contains(const key_type& key) const;\n        mapped_type operator[](const key_type& key) const;\n\n        template <class F>\n        self_type filter(const F& f) const;\n\n        template <class F>\n        self_type filter(const F& f, size_type size) const;\n\n        const_iterator find(const key_type& key) const;\n\n        const_iterator begin() const;\n        const_iterator end() const;\n\n        const_iterator cbegin() const;\n        const_iterator cend() const;\n\n        const_reverse_iterator rbegin() const;\n        const_reverse_iterator rend() const;\n\n        const_reverse_iterator crbegin() const;\n        const_reverse_iterator crend() const;\n\n        template <class... Args>\n        bool merge(const Args&... axes);\n\n        template <class... Args>\n        bool intersect(const Args&... axes);\n\n        self_type as_xaxis() const;\n\n        bool operator==(const self_type& rhs) const;\n        bool operator!=(const self_type& rhs) const;\n\n    private:\n\n        storage_type m_data;\n\n        template <class OS, class L1, class T1, class MT1>\n        friend OS& operator<<(OS&, const xaxis_variant<L1, T1, MT1>&);\n    };\n\n    template <class OS, class L, class T, class MT>\n    OS& operator<<(OS& out, const xaxis_variant<L, T, MT>& axis);\n\n    /**************************\n     * xaxis_variant_iterator *\n     **************************/\n\n    template <class L, class T, class MT>\n    class xaxis_variant_iterator : public xtl::xrandom_access_iterator_base<xaxis_variant_iterator<L, T, MT>,\n                                                                            typename xaxis_variant<L, T, MT>::value_type,\n                                                                            typename xaxis_variant<L, T, MT>::difference_type,\n                                                                            typename xaxis_variant<L, T, MT>::const_pointer,\n                                                                            typename xaxis_variant<L, T, MT>::const_reference>\n    {\n    public:\n\n        using self_type = xaxis_variant_iterator<L, T, MT>;\n        using container_type = xaxis_variant<L, T, MT>;\n        using key_reference = typename container_type::key_reference;\n        using value_type = typename container_type::value_type;\n        using reference = typename container_type::const_reference;\n        using pointer = typename container_type::const_pointer;\n        using difference_type = typename container_type::difference_type;\n        using iterator_category = std::random_access_iterator_tag;\n        using subiterator = typename container_type::subiterator;\n\n        xaxis_variant_iterator() = default;\n        xaxis_variant_iterator(subiterator it);\n\n        self_type& operator++();\n        self_type& operator--();\n\n        self_type& operator+=(difference_type n);\n        self_type& operator-=(difference_type n);\n\n        difference_type operator-(const self_type& rhs) const;\n\n        reference operator*() const;\n        pointer operator->() const;\n\n        bool equal(const self_type& rhs) const;\n        bool less_than(const self_type& rhs) const;\n\n    private:\n\n        subiterator m_it;\n    };\n\n    template <class L, class T, class MT>\n    typename xaxis_variant_iterator<L, T, MT>::difference_type operator-(const xaxis_variant_iterator<L, T, MT>& lhs,\n                                                                         const xaxis_variant_iterator<L, T, MT>& rhs);\n\n    template <class L, class T, class MT>\n    bool operator==(const xaxis_variant_iterator<L, T, MT>& lhs, const xaxis_variant_iterator<L, T, MT>& rhs);\n\n    template <class L, class T, class MT>\n    bool operator<(const xaxis_variant_iterator<L, T, MT>& lhs, const xaxis_variant_iterator<L, T, MT>& rhs);\n\n    /********************************\n     * xaxis_variant implementation *\n     ********************************/\n\n    /**\n     * @name Constructors\n     */\n    //@{\n    /**\n     * Constructs an xaxis_variant from the specified xaxis. This latter is copied\n     * in the variant.\n     * @tparam LB the label type of the axis argument.\n     * @param axis the axis to copy in the variant.\n     */\n    template <class L, class T, class MT>\n    template <class LB>\n    inline xaxis_variant<L, T, MT>::xaxis_variant(const xaxis<LB, T, MT>& axis)\n        : m_data(axis)\n    {\n    }\n\n    /**\n     * Constructs an xaxis_variant from the specified xaxis. This latter is moved in\n     * the variant.\n     * @tparam LB the label type of the axis argument.\n     * @param axis the axis to move in the variant.\n     */\n    template <class L, class T, class MT>\n    template <class LB>\n    inline xaxis_variant<L, T, MT>::xaxis_variant(xaxis<LB, T, MT>&& axis)\n        : m_data(std::move(axis))\n    {\n    }\n\n    /**\n     * Constructs an xaxis_variant from the specified xaxis_default. This latter is\n     * copied in the variant.\n     * @tparam LB the label type of the axis argument.\n     * @param axis the axis to copy in the variant.\n     */\n    template <class L, class T, class MT>\n    template <class LB>\n    inline xaxis_variant<L, T, MT>::xaxis_variant(const xaxis_default<LB, T>& axis)\n        : m_data(axis)\n    {\n    }\n\n    /**\n     * Constructs an xaxis_variant from the specified xaxis_default. This latter\n     * is moved in the variant.\n     * @tparam LB the label type of the axis argument.\n     * @param axis the axis to move in the variant.\n     */\n    template <class L, class T, class MT>\n    template <class LB>\n    inline xaxis_variant<L, T, MT>::xaxis_variant(xaxis_default<LB, T>&& axis)\n        : m_data(std::move(axis))\n    {\n    }\n\n    //@}\n\n    /**\n     * @name Labels\n     */\n    //@{\n    /**\n     * Returns the list of labels contained in the axis.\n     */\n    template <class L, class T, class MT>\n    inline auto xaxis_variant<L, T, MT>::labels() const -> label_list\n    {\n        return xtl::visit([](auto&& arg) -> label_list { return arg.labels(); }, m_data);\n    };\n\n    /**\n     * Return the i-th label of the axis.\n     * @param i the position of the label.\n     */\n    template <class L, class T, class MT>\n    inline auto xaxis_variant<L, T, MT>::label(size_type i) const -> key_type\n    {\n        return xtl::visit([i](auto&& arg) -> key_type { return arg.labels()[i]; }, m_data);\n    }\n\n    /**\n     * Checks if the axis has no labels.\n     */\n    template <class L, class T, class MT>\n    inline bool xaxis_variant<L, T, MT>::empty() const\n    {\n        return xtl::visit([](auto&& arg) { return arg.empty(); }, m_data);\n    }\n\n    /**\n     * Returns the number of labels in the axis.\n     */\n    template <class L, class T, class MT>\n    inline auto xaxis_variant<L, T, MT>::size() const -> size_type\n    {\n        return xtl::visit([](auto&& arg) { return arg.size(); }, m_data);\n    }\n\n    /**\n     * Returns true if the labels list is sorted.\n     */\n    template <class L, class T, class MT>\n    inline bool xaxis_variant<L, T, MT>::is_sorted() const noexcept\n    {\n        return xtl::visit([](auto&& arg) { return arg.is_sorted(); }, m_data);\n    }\n    //@}\n\n    /**\n      * @name Data\n     */\n    //@{\n    /**\n     * Returns true if the axis contains the speficied label.\n     * @param key the label to search for.\n     */\n    template <class L, class T, class MT>\n    inline bool xaxis_variant<L, T, MT>::contains(const key_type& key) const\n    {\n        auto lambda = [&key](auto&& arg) -> bool\n        {\n            using type = typename std::decay_t<decltype(arg)>::key_type;\n            return arg.contains(xtl::get<type>(key));\n        };\n        return xtl::visit(lambda, m_data);\n    }\n\n    /**\n     * Returns the position of the specified label. If this last one is\n     * not found, an exception is thrown.\n     * @param key the label to search for.\n     */\n    template <class L, class T, class MT>\n    inline auto xaxis_variant<L, T, MT>::operator[](const key_type& key) const -> mapped_type\n    {\n        auto lambda = [&key](auto&& arg) -> mapped_type\n        {\n            using type = typename std::decay_t<decltype(arg)>::key_type;\n            return arg[xtl::get<type>(key)];\n        };\n        return xtl::visit(lambda, m_data);\n    }\n    //@}\n\n    /**\n     * @name Filters\n     */\n    //@{\n    /**\n     * Builds an return a new axis by applying the given filter to the axis.\n     * @param f the filter used to select the labels to keep in the new axis.\n     */\n    template <class L, class T, class MT>\n    template <class F>\n    inline auto xaxis_variant<L, T, MT>::filter(const F& f) const -> self_type\n    {\n        return xtl::visit([&f](const auto& arg) { return self_type(arg.filter(f)); }, m_data);\n    }\n\n    /**\n     * Builds an return a new axis by applying the given filter to the axis. When\n     * the size of the new list of labels is known, this method allows some\n     * optimizations compared to the previous one.\n     * @param f the filter used to select the labels to keep in the new axis.\n     * @param size the size of the new label list.\n     */\n    template <class L, class T, class MT>\n    template <class F>\n    inline auto xaxis_variant<L, T, MT>::filter(const F& f, size_type size) const -> self_type\n    {\n        return xtl::visit([&f, size](const auto& arg) { return self_type(arg.filter(f, size)); }, m_data);\n    }\n    //@}\n\n    /**\n     * @name Iterators\n     */\n    //@{\n    /**\n     * Returns a constant iterator to the element with label equivalent to \\c key. If\n     * no such element is found, past-the-end iterator is returned.\n     * @param key the label to search for.\n     */\n    template <class L, class T, class MT>\n    inline auto xaxis_variant<L, T, MT>::find(const key_type& key) const -> const_iterator\n    {\n        auto lambda = [&key](auto&& arg) -> const_iterator\n        {\n            using type = typename std::decay_t<decltype(arg)>::key_type;\n            return subiterator(arg.find(xtl::get<type>(key)));\n        };\n        return xtl::visit(lambda, m_data);\n    }\n\n    /**\n     * Returns a constant iterator to the first element of the axis.\n     * This element is a pair label - position.\n     */\n    template <class L, class T, class MT>\n    inline auto xaxis_variant<L, T, MT>::begin() const -> const_iterator\n    {\n        return cbegin();\n    }\n\n    /**\n     * Returns a constant iterator to the element following the last element\n     * of the axis.\n     */\n    template <class L, class T, class MT>\n    inline auto xaxis_variant<L, T, MT>::end() const -> const_iterator\n    {\n        return cend();\n    }\n\n    /**\n     * Returns a constant iterator to the first element of the axis.\n     * This element is a pair label - position.\n     */\n    template <class L, class T, class MT>\n    inline auto xaxis_variant<L, T, MT>::cbegin() const -> const_iterator\n    {\n        return xtl::visit([](auto&& arg) { return subiterator(arg.cbegin()); }, m_data);\n    }\n\n    /**\n     * Returns a constant iterator to the element following the last element\n     * of the axis.\n     */\n    template <class L, class T, class MT>\n    inline auto xaxis_variant<L, T, MT>::cend() const -> const_iterator\n    {\n        return xtl::visit([](auto&& arg) { return subiterator(arg.cend()); }, m_data);\n    }\n\n    /**\n     * Returns a constant iterator to the first element of the reverse axis.\n     * This element is a pair labal - position.\n     */\n    template <class L, class T, class MT>\n    inline auto xaxis_variant<L, T, MT>::rbegin() const -> const_reverse_iterator\n    {\n        return crbegin();\n    }\n\n    /**\n     * Returns a constant iterator to the element following the last element\n     * of the reversed axis.\n     */\n    template <class L, class T, class MT>\n    inline auto xaxis_variant<L, T, MT>::rend() const -> const_reverse_iterator\n    {\n        return crend();\n    }\n\n    /**\n     * Returns a constant iterator to the first element of the reverse axis.\n     * This element is a pair labal - position.\n     */\n    template <class L, class T, class MT>\n    inline auto xaxis_variant<L, T, MT>::crbegin() const -> const_reverse_iterator\n    {\n        return xtl::visit([](auto&& arg) { return subiterator(arg.cend()); }, m_data);\n    }\n\n    /**\n     * Returns a constant iterator to the element following the last element\n     * of the reversed axis.\n     */\n    template <class L, class T, class MT>\n    inline auto xaxis_variant<L, T, MT>::crend() const -> const_reverse_iterator\n    {\n        return xtl::visit([](auto&& arg) { return subiterator(arg.cbegin()); }, m_data);\n    }\n    //@}\n\n    template <class L, class T, class MT, class K>\n    struct xaxis_variant_adaptor\n    {\n        using axis_variant_type = xaxis_variant<L, T, MT>;\n        using key_type = K;\n        using axis_type =  xaxis<K, T, MT>;\n        using label_list = typename axis_type::label_list;\n\n        xaxis_variant_adaptor(const axis_variant_type& axis)\n            : m_axis(axis)\n        {\n        };\n\n        inline const label_list& labels() const\n        {\n            return xget_vector<std::vector<key_type>>(m_axis.labels());\n        };\n\n        inline bool is_sorted() const noexcept\n        {\n            return m_axis.is_sorted();\n        };\n\n    private:\n\n        const axis_variant_type& m_axis;\n    };\n\n    /**\n     * @name Set operations\n     */\n    //@{\n    /**\n     * Merges all the axes arguments into this ones. After this function call,\n     * the axis contains all the labels from all the arguments.\n     * @param axes the axes to merge.\n     * @return true is the axis already contained all the labels.\n     */\n    template <class L, class T, class MT>\n    template <class... Args>\n    inline bool xaxis_variant<L, T, MT>::merge(const Args&... axes)\n    {\n        auto lambda = [&axes...](auto&& arg) -> bool\n        {\n            using key_type = typename std::decay_t<decltype(arg)>::key_type;\n            return arg.merge(xaxis_variant_adaptor<L, T, MT, key_type>(axes)...);\n        };\n        return xtl::visit(lambda, m_data);\n    }\n\n    /**\n     * Replaces the labels with the intersection of the labels of\n     * the axes arguments and the labels of this axis.\n     * @param axes the axes to intersect.\n     * @return true if the intersection is equivalent to this axis.\n     */\n    template <class L, class T, class MT>\n    template <class... Args>\n    inline bool xaxis_variant<L, T, MT>::intersect(const Args&... axes)\n    {\n        auto lambda = [&axes...](auto&& arg) -> bool\n        {\n            using key_type = typename std::decay_t<decltype(arg)>::key_type;\n            return arg.intersect(xaxis_variant_adaptor<L, T, MT, key_type>(axes)...);\n        };\n        return xtl::visit(lambda, m_data);\n    }\n    //@}\n\n    template <class L, class T, class MT>\n    inline auto xaxis_variant<L, T, MT>::as_xaxis() const -> self_type\n    {\n        return xtl::visit([](auto&& arg) { return self_type(xaxis<typename std::decay_t<decltype(arg)>::key_type, T, MT>(arg)); }, m_data);\n    }\n\n    /**\n     * Returns true is this axis and \\c rhs are equivalent axes, i.e. they contain the same\n     * label - position pairs.\n     * @param rhs an axis.\n     */\n    template <class L, class T, class MT>\n    inline bool xaxis_variant<L, T, MT>::operator==(const self_type& rhs) const\n    {\n        return m_data == rhs.m_data;\n    }\n\n    /**\n     * Returns true is this axis and \\c rhs are not equivalent axes, i.e. they contain different\n     * label - position pairs.\n     * @param rhs an axis.\n     */\n    template <class L, class T, class MT>\n    inline bool xaxis_variant<L, T, MT>::operator!=(const self_type& rhs) const\n    {\n        return m_data != rhs.m_data;\n    }\n\n    template <class OS, class L, class T, class MT>\n    inline OS& operator<<(OS& out, const xaxis_variant<L, T, MT>& axis)\n    {\n        xtl::visit([&out](auto&& arg) { out << arg; }, axis.m_data);\n        return out;\n    }\n\n    /*****************************************\n     * xaxis_variant_iterator implementation *\n     *****************************************/\n\n    template<class L, class T, class MT>\n    inline xaxis_variant_iterator<L, T, MT>::xaxis_variant_iterator(subiterator it)\n        : m_it(it)\n    {\n    }\n\n    template <class L, class T, class MT>\n    inline auto xaxis_variant_iterator<L, T, MT>::operator++() -> self_type&\n    {\n        xtl::visit([](auto&& arg) { ++arg; }, m_it);\n        return *this;\n    }\n\n    template <class L, class T, class MT>\n    inline auto xaxis_variant_iterator<L, T, MT>::operator--() -> self_type&\n    {\n        xtl::visit([](auto&& arg) { --arg; }, m_it);\n        return *this;\n    }\n\n    template <class L, class T, class MT>\n    inline auto xaxis_variant_iterator<L, T, MT>::operator+=(difference_type n) -> self_type&\n    {\n        xtl::visit([n](auto&& arg) { arg += n; }, m_it);\n        return *this;\n    }\n\n    template <class L, class T, class MT>\n    inline auto xaxis_variant_iterator<L, T, MT>::operator-=(difference_type n) -> self_type&\n    {\n        xtl::visit([n](auto&& arg) { arg -= n; }, m_it);\n        return *this;\n    }\n\n    template <class L, class T, class MT>\n    inline auto xaxis_variant_iterator<L, T, MT>::operator-(const self_type& rhs) const -> difference_type\n    {\n        xtl::visit([&rhs](auto&& arg) { return arg - std::get<std::decay_t<decltype(arg)>>(rhs); }, m_it);\n        return *this;\n    }\n\n    template <class L, class T, class MT>\n    inline auto xaxis_variant_iterator<L, T, MT>::operator*() const -> reference\n    {\n        return xtl::visit([](auto&& arg)\n        {\n            return reference(key_reference(xtl::closure(arg->first)), arg->second);\n        }, m_it);\n    }\n\n    template <class L, class T, class MT>\n    inline auto xaxis_variant_iterator<L, T, MT>::operator->() const -> pointer\n    {\n        return xtl::visit([](auto&& arg)\n        {\n            return pointer(reference(key_reference(xtl::closure(arg->first)), arg->second));\n        }, m_it);\n    }\n\n    template <class L, class T, class MT>\n    inline bool xaxis_variant_iterator<L, T, MT>::equal(const self_type& rhs) const\n    {\n        return m_it == rhs.m_it;\n    }\n\n    template <class L, class T, class MT>\n    inline bool xaxis_variant_iterator<L, T, MT>::less_than(const self_type& rhs) const\n    {\n        return m_it < rhs.m_it;\n    }\n\n    template <class L, class T, class MT>\n    inline auto operator-(const xaxis_variant_iterator<L, T, MT>& lhs, const xaxis_variant_iterator<L, T, MT>& rhs)\n        -> typename xaxis_variant_iterator<L, T, MT>::difference_type\n    {\n        return lhs.operator-(rhs);\n    }\n\n    template <class L, class T, class MT>\n    inline bool operator==(const xaxis_variant_iterator<L, T, MT>& lhs, const xaxis_variant_iterator<L, T, MT>& rhs)\n    {\n        return lhs.equal(rhs);\n    }\n\n    template <class L, class T, class MT>\n    inline bool operator<(const xaxis_variant_iterator<L, T, MT>& lhs, const xaxis_variant_iterator<L, T, MT>& rhs)\n    {\n        return lhs.less_than(rhs);\n    }\n\n    template <class LB, class L, class T, class MT>\n    auto get_labels(const xaxis_variant<L, T, MT>& axis_variant) -> const typename xaxis<LB, T, MT>::label_list&\n    {\n        using label_list = typename xaxis<LB, T, MT>::label_list;\n        return xtl::xget<const label_list&>(axis_variant.labels().storage());\n    }\n}\n\n#endif\n"
  },
  {
    "path": "include/xframe/xaxis_view.hpp",
    "content": "/***************************************************************************\n* Copyright (c) Johan Mabille, Sylvain Corlay, Wolf Vollprecht and         *\n* Martin Renou                                                             *\n* Copyright (c) QuantStack                                                 *\n*                                                                          *\n* Distributed under the terms of the BSD 3-Clause License.                 *\n*                                                                          *\n* The full license is in the file LICENSE, distributed with this software. *\n****************************************************************************/\n\n#ifndef XFRAME_XAXIS_VIEW_HPP\n#define XFRAME_XAXIS_VIEW_HPP\n\n#include \"xaxis_label_slice.hpp\"\n#include \"xaxis_variant.hpp\"\n#include \"xsequence_view.hpp\"\n\nnamespace xf\n{\n\n    template <class L, class T, class MT>\n    class xaxis_view_iterator;\n\n    /**************\n     * xaxis_view *\n     **************/\n\n    /**\n     * @class xaxis_view\n     * @brief View of an axis\n     *\n     * The xaxis_view class is used for modeling a view on an existing axis, i.e.\n     * a subset of this axis. This is done by filtering the labels of the axis.\n     * No copy is involved. This class is used as a building block for view on\n     * coordinates. This class is intended to be used with \\c xaxis_variant, so the\n     * label template parameter is a type list rather than a simple type.\n     *\n     * @tparam L the type list of labels.\n     * @tparam T the integer type used to represent positions.\n     * @tparam MT the tag used for choosing the map type which holds the label-\n     *            position pairs. Possible values are \\c map_tag and \\c hash_map_tag.\n     *            Default value is \\c hash_map_tag.\n     * @sa xaxis_variant\n     */\n    template <class L, class T, class MT = hash_map_tag>\n    class xaxis_view\n    {\n    public:\n\n        using self_type = xaxis_view<L, T, MT>;\n        using axis_type = xaxis_variant<L, T, MT>;\n        using slice_type = xaxis_index_slice<T>;\n\n        using key_type = typename axis_type::key_type;\n        using mapped_type = typename axis_type::mapped_type;\n        using value_type = typename axis_type::value_type;\n        using reference = typename axis_type::const_reference;\n        using const_reference = typename axis_type::const_reference;\n        using pointer = typename axis_type::const_pointer;\n        using const_pointer = typename axis_type::const_pointer;\n        using size_type = typename axis_type::size_type;\n        using difference_type = typename axis_type::difference_type;\n        using iterator = xaxis_view_iterator<L, T, MT>;\n        using const_iterator = iterator;\n        using reverse_iterator = std::reverse_iterator<iterator>;\n        using const_reverse_iterator = std::reverse_iterator<const_iterator>;\n        using subiterator = typename axis_type::const_iterator;\n\n        using label_list = xsequence_view<typename axis_type::label_list, slice_type>;\n\n        template <class S>\n        xaxis_view(const axis_type& axis, S&& slice);\n\n        explicit operator axis_type() const;\n\n        label_list labels() const;\n        key_type label(size_type i) const;\n\n        bool empty() const;\n        size_type size() const;\n\n        bool contains(const key_type& key) const;\n        mapped_type operator[](const key_type& key) const;\n        mapped_type index(size_type label_index) const;\n\n        template <class F>\n        axis_type filter(const F& f) const;\n\n        template <class F>\n        axis_type filter(const F& f, size_type size) const;\n\n        const_iterator find(const key_type& key) const;\n\n        const_iterator begin() const;\n        const_iterator end() const;\n\n        const_iterator cbegin() const;\n        const_iterator cend() const;\n\n        const_reverse_iterator rbegin() const;\n        const_reverse_iterator rend() const;\n\n        const_reverse_iterator crbegin() const;\n        const_reverse_iterator crend() const;\n\n        axis_type as_xaxis() const;\n\n    private:\n\n        const axis_type& m_axis;\n        slice_type m_slice;\n    };\n\n    template <class L, class T, class MT>\n    bool operator==(const xaxis_view<L, T, MT>& lhs, const xaxis_view<L, T, MT>& rhs) noexcept;\n\n    template <class L, class T, class MT>\n    bool operator!=(const xaxis_view<L, T, MT>& lhs, const xaxis_view<L, T, MT>& rhs) noexcept;\n\n    template <class L, class T, class MT>\n    bool operator==(const xaxis_view<L, T, MT>& lhs, const xaxis_variant<L, T, MT>& rhs) noexcept;\n\n    template <class L, class T, class MT>\n    bool operator==(const xaxis_variant<L, T, MT>& lhs, const xaxis_view<L, T, MT>& rhs) noexcept;\n\n    template <class L, class T, class MT>\n    bool operator!=(const xaxis_view<L, T, MT>& lhs, const xaxis_variant<L, T, MT>& rhs) noexcept;\n\n    template <class L, class T, class MT>\n    bool operator!=(const xaxis_variant<L, T, MT>& lhs, const xaxis_view<L, T, MT>& rhs) noexcept;\n\n    template <class OS, class L, class T, class MT>\n    OS& operator<<(OS& out, const xaxis_view<L, T, MT>& axis);\n\n    /***********************\n     * xaxis_view_iterator *\n     ***********************/\n\n    template <class L, class T, class MT>\n    class xaxis_view_iterator : public xtl::xrandom_access_iterator_base<xaxis_view_iterator<L, T, MT>,\n                                                                         typename xaxis_view<L, T, MT>::value_type,\n                                                                         typename xaxis_view<L, T, MT>::difference_type,\n                                                                         typename xaxis_view<L, T, MT>::const_pointer,\n                                                                         typename xaxis_view<L, T, MT>::const_reference>\n    {\n    public:\n\n        using self_type = xaxis_view_iterator<L, T, MT>;\n        using container_type = xaxis_view<L, T, MT>;\n        using value_type = typename container_type::value_type;\n        using reference = typename container_type::const_reference;\n        using pointer = typename container_type::const_pointer;\n        using difference_type = typename container_type::difference_type;\n        using iterator_category = std::random_access_iterator_tag;\n        using subiterator = typename container_type::subiterator;\n        using size_type = typename container_type::size_type;\n        using slice_type = typename container_type::slice_type;\n\n        xaxis_view_iterator() = default;\n        xaxis_view_iterator(subiterator it, const slice_type* sl, size_type index);\n\n        self_type& operator++();\n        self_type& operator--();\n\n        self_type& operator+=(difference_type n);\n        self_type& operator-=(difference_type n);\n\n        difference_type operator-(const self_type& rhs) const;\n\n        reference operator*() const;\n        pointer operator->() const;\n\n        bool equal(const self_type& rhs) const;\n        bool less_than(const self_type& rhs) const;\n\n    private:\n\n        subiterator m_it;\n        const slice_type* p_slice;\n        size_type m_index;\n    };\n\n    template <class L, class T, class MT>\n    typename xaxis_view_iterator<L, T, MT>::difference_type operator-(const xaxis_view_iterator<L, T, MT>& lhs,\n                                                                      const xaxis_view_iterator<L, T, MT>& rhs);\n\n    template <class L, class T, class MT>\n    bool operator==(const xaxis_view_iterator<L, T, MT>& lhs, const xaxis_view_iterator<L, T, MT>& rhs);\n\n    template <class L, class T, class MT>\n    bool operator<(const xaxis_view_iterator<L, T, MT>& lhs, const xaxis_view_iterator<L, T, MT>& rhs);\n\n    /*****************************\n     * xaxis_view implementation *\n     *****************************/\n\n    /**\n     * Builds a sliced view of the specified axis.\n     * @param axis the axis on which the view is built.\n     * @param slice the slice used for filtering labels.\n     */\n    template <class L, class T, class MT>\n    template <class S>\n    inline xaxis_view<L, T, MT>::xaxis_view(const axis_type& axis, S&& slice)\n        : m_axis(axis), m_slice(std::forward<S>(slice))\n    {\n    }\n\n    /**\n     * Converts this view into a real axis. The view itself is not modified,\n     * a new axis is created from the filtered labels. This conversion operator\n     * allows to pass a view to methods that accept regular axes, however it\n     * might not be convenient for explicit conversion. Prefer as_xaxis in this\n     * case.\n     * @sa as_xaxis\n     */\n    template <class L, class T, class MT>\n    inline xaxis_view<L, T, MT>::operator axis_type() const\n    {\n        return m_axis.filter([this](const auto& arg) { return this->contains(arg); }, size());\n    }\n\n    /**\n     * Returns the list of labels in the view. Since the view does not hold\n     * any data, this list is created upon demand. The filtered labels are\n     * copied into it.\n     */\n    template <class L, class T, class MT>\n    inline auto xaxis_view<L, T, MT>::labels() const -> label_list\n    {\n        return label_list(m_axis.labels(), m_slice);\n    }\n\n    /**\n     * Return the \\c i-th label of the view.\n     */\n    template <class L, class T, class MT>\n    inline auto xaxis_view<L, T, MT>::label(size_type i) const -> key_type\n    {\n        return m_axis.label(m_slice(i));\n    }\n\n    /**\n     * Checks if the view has no labels.\n     */\n    template <class L, class T, class MT>\n    inline bool xaxis_view<L, T, MT>::empty() const\n    {\n        return size() == 0;\n    }\n\n    /**\n     * Returns the number of labels in the axis.\n     */\n    template <class L, class T, class MT>\n    inline auto xaxis_view<L, T, MT>::size() const -> size_type\n    {\n        return m_slice.size();\n    }\n\n    /**\n     * Returns true if the view contains the speficied label.\n     * @param key the label to search for.\n     */\n    template <class L, class T, class MT>\n    inline bool xaxis_view<L, T, MT>::contains(const key_type& key) const\n    {\n        if (m_axis.contains(key))\n        {\n            mapped_type idx = m_axis[key];\n            return m_slice.contains(idx);\n        }\n        return false;\n    }\n\n    /**\n     * Returns the position of the specified label in the underlying axis.\n     * If this last one is not found, an exception is thrown.\n     * @param key the label to search for.\n     */\n    template <class L, class T, class MT>\n    inline auto xaxis_view<L, T, MT>::operator[](const key_type& key) const -> mapped_type\n    {\n        mapped_type idx = m_axis[key];\n        if (m_slice.contains(idx))\n        {\n            return idx;\n        }\n        else\n        {\n            throw std::out_of_range(\"invalid xaxis_view key\");\n        }\n    }\n\n    /**\n     * Get the label mapped to the specified position in the view, and returns\n     * it position in the underlying axis.\n     * @param label_index the index of the label in the view.\n     */\n    template <class L, class T, class MT>\n    inline auto xaxis_view<L, T, MT>::index(size_type label_index) const -> mapped_type\n    {\n        return this->operator[](label(label_index));\n    }\n\n    /**\n     * Builds an return a new axis by applying the given filter to the view.\n     * @param f the filter used to select the labels to keep in the new axis.\n     */\n    template <class L, class T, class MT>\n    template <class F>\n    inline auto xaxis_view<L, T, MT>::filter(const F& f) const -> axis_type\n    {\n        return m_axis.filter([&f, this](const auto& arg) { return f(arg) && this->contains(arg); });\n    }\n\n    /**\n     * Builds an return a new axis by applying the given filter to the view. When\n     * the size of the new list of labels is known, this method allows some\n     * optimizations compared to the previous one.\n     * @param f the filter used to select the labels to keep in the new axis.\n     * @param size the size of the new label list.\n     */\n    template <class L, class T, class MT>\n    template <class F>\n    inline auto xaxis_view<L, T, MT>::filter(const F& f, size_type size) const -> axis_type\n    {\n        return m_axis.filter([&f, this](const auto& arg) { return f(arg) && this->contains(arg); }, size);\n    }\n\n    /**\n     * Returns a constant iterator to the element with label equivalent to \\c key. If\n     * no such element is found, past-the-end iterator is returned.\n     * @param key the label to search for.\n     */\n    template <class L, class T, class MT>\n    inline auto xaxis_view<L, T, MT>::find(const key_type& key) const -> const_iterator\n    {\n        auto iter = m_axis.find(key);\n        if (iter != m_axis.end() && m_slice.contains(iter->second))\n        {\n            return const_iterator(iter, &m_slice, m_slice.revert_index(iter->second));\n        }\n        else\n        {\n            return cend();\n        }\n    }\n\n    /**\n     * Returns a constant iterator to the first element of the view.\n     * This element is a pair label - position.\n     */\n    template <class L, class T, class MT>\n    inline auto xaxis_view<L, T, MT>::begin() const -> const_iterator\n    {\n        return cbegin();\n    }\n\n    /**\n     * Returns a constant iterator to the element following the last element\n     * of the view.\n     */\n    template <class L, class T, class MT>\n    inline auto xaxis_view<L, T, MT>::end() const -> const_iterator\n    {\n        return cend();\n    }\n\n    /**\n     * Returns a constant iterator to the first element of the view.\n     * This element is a pair label - position.\n     */\n    template <class L, class T, class MT>\n    inline auto xaxis_view<L, T, MT>::cbegin() const -> const_iterator\n    {\n        return const_iterator(m_axis.cbegin() + m_slice(0u), &m_slice, 0u);\n    }\n\n    /**\n     * Returns a constant iterator to the element following the last element\n     * of the view.\n     */\n    template <class L, class T, class MT>\n    inline auto xaxis_view<L, T, MT>::cend() const -> const_iterator\n    {\n        size_type inc = m_slice(0u) + m_slice.step_size(0, m_slice.size());\n        return const_iterator(m_axis.cbegin() + inc, &m_slice, size());\n    }\n\n    /**\n     * Returns a constant iterator to the first element of the reverse view.\n     * This element is a pair labal - position.\n     */\n    template <class L, class T, class MT>\n    inline auto xaxis_view<L, T, MT>::rbegin() const -> const_reverse_iterator\n    {\n        return const_reverse_iterator(end());\n    }\n\n    /**\n     * Returns a constant iterator to the element following the last element\n     * of the reversed view.\n     */\n    template <class L, class T, class MT>\n    inline auto xaxis_view<L, T, MT>::rend() const -> const_reverse_iterator\n    {\n        return const_reverse_iterator(begin());\n    }\n\n    /**\n     * Returns a constant iterator to the first element of the reverse view.\n     * This element is a pair labal - position.\n     */\n    template <class L, class T, class MT>\n    inline auto xaxis_view<L, T, MT>::crbegin() const -> const_reverse_iterator\n    {\n        return const_reverse_iterator(cend());\n    }\n\n    /**\n     * Returns a constant iterator to the element following the last element\n     * of the reversed view.\n     */\n    template <class L, class T, class MT>\n    inline auto xaxis_view<L, T, MT>::crend() const -> const_reverse_iterator\n    {\n        return const_reverse_iterator(cbegin());\n    }\n\n    /**\n     * Converts this view into a real axis. The view itself is not modified,\n     * a new axis is created from the filtered labels.\n     */\n    template <class L, class T, class MT>\n    inline auto xaxis_view<L, T, MT>::as_xaxis() const -> axis_type\n    {\n        return m_axis.as_xaxis();\n    }\n\n    /**\n     * Returns true is \\c lhs and \\c d rhs are equivalent axes, i.e. they contain the same\n     * label - position pairs.\n     * @param lhs an axis.\n     * @param rhs an axis.\n     */\n    template <class L, class T, class MT>\n    inline bool operator==(const xaxis_view<L, T, MT>& lhs, const xaxis_view<L, T, MT>& rhs) noexcept\n    {\n        return lhs.labels() == rhs.labels();\n    }\n\n    /**\n     * Returns true is \\c lhs and \\c rhs are not equivalent axes, i.e. they contain different\n     * label - position pairs.\n     * @param lhs an axis.\n     * @param rhs an axis.\n     */\n    template <class L, class T, class MT>\n    inline bool operator!=(const xaxis_view<L, T, MT>& lhs, const xaxis_view<L, T, MT>& rhs) noexcept\n    {\n        return !(lhs == rhs);\n    }\n\n    /**\n     * Returns true is \\c lhs and \\c rhs are equivalent axes, i.e. they contain the same\n     * label - position pairs.\n     * @param lhs an axis.\n     * @param rhs an axis.\n     */\n    template <class L, class T, class MT>\n    inline bool operator==(const xaxis_view<L, T, MT>& lhs, const xaxis_variant<L, T, MT>& rhs) noexcept\n    {\n        return lhs.labels() == rhs.labels();\n    }\n\n    /**\n     * Returns true is \\c lhs and \\c rhs are equivalent axes, i.e. they contain the same\n     * label - position pairs.\n     * @param lhs an axis.\n     * @param rhs an axis.\n     */\n    template <class L, class T, class MT>\n    inline bool operator==(const xaxis_variant<L, T, MT>& lhs, const xaxis_view<L, T, MT>& rhs) noexcept\n    {\n        return rhs == lhs;\n    }\n\n    /**\n     * Returns true is \\c lhs and \\c rhs are not equivalent axes, i.e. they contain different\n     * label - position pairs.\n     * @param lhs an axis.\n     * @param rhs an axis.\n     */\n    template <class L, class T, class MT>\n    inline bool operator!=(const xaxis_view<L, T, MT>& lhs, const xaxis_variant<L, T, MT>& rhs) noexcept\n    {\n        return !(lhs == rhs);\n    }\n\n    /**\n     * Returns true is \\c lhs and \\c rhs are not equivalent axes, i.e. they contain different\n     * label - position pairs.\n     * @param lhs an axis.\n     * @param rhs an axis.\n     */\n    template <class L, class T, class MT>\n    inline bool operator!=(const xaxis_variant<L, T, MT>& lhs, const xaxis_view<L, T, MT>& rhs) noexcept\n    {\n        return !(lhs == rhs);\n    }\n\n    template <class OS, class L, class T, class MT>\n    inline OS& operator<<(OS& out, const xaxis_view<L, T, MT>& axis)\n    {\n        out << '(';\n        for (std::size_t i = 0; i < axis.size(); ++i)\n        {\n            xtl::visit([&out](const auto& v) { out << v << \", \"; }, axis.label(i));\n        }\n        out << ')';\n        return out;\n    }\n\n    /**************************************\n     * xaxis_view_iterator implementation *\n     **************************************/\n\n    template <class L, class T, class MT>\n    inline xaxis_view_iterator<L, T, MT>::xaxis_view_iterator(subiterator it, const slice_type* sl, size_type index)\n        : m_it(it), p_slice(sl), m_index(index)\n    {\n    }\n\n    template <class L, class T, class MT>\n    inline auto xaxis_view_iterator<L, T, MT>::operator++() -> self_type&\n    {\n        size_type step = p_slice->step_size(m_index);\n        m_it += static_cast<difference_type>(step);\n        ++m_index;\n        return *this;\n    }\n\n    template <class L, class T, class MT>\n    inline auto xaxis_view_iterator<L, T, MT>::operator--() -> self_type&\n    {\n        --m_index;\n        size_type step = p_slice->step_size(m_index);\n        m_it -= static_cast<difference_type>(step);\n        return *this;\n    }\n\n    template <class L, class T, class MT>\n    inline auto xaxis_view_iterator<L, T, MT>::operator+=(difference_type n) -> self_type&\n    {\n        size_type step = p_slice->step_size(m_index, n);\n        m_it += static_cast<difference_type>(step);\n        m_index += n;\n        return *this;\n    }\n\n    template <class L, class T, class MT>\n    inline auto xaxis_view_iterator<L, T, MT>::operator-=(difference_type n) -> self_type&\n    {\n        m_index -= n;\n        size_type step = p_slice->step_size(m_index, n);\n        m_it -= static_cast<difference_type>(step);\n        return *this;\n    }\n\n    template <class L, class T, class MT>\n    inline auto xaxis_view_iterator<L, T, MT>::operator-(const self_type& rhs) const -> difference_type\n    {\n        return static_cast<difference_type>(m_index) - static_cast<difference_type>(rhs.m_index);\n    }\n\n    template <class L, class T, class MT>\n    inline auto xaxis_view_iterator<L, T, MT>::operator*() const -> reference\n    {\n        return *m_it;\n    }\n\n    template <class L, class T, class MT>\n    inline auto xaxis_view_iterator<L, T, MT>::operator->() const -> pointer\n    {\n        return m_it.operator->();\n    }\n\n    template <class L, class T, class MT>\n    inline bool xaxis_view_iterator<L, T, MT>::equal(const self_type& rhs) const\n    {\n        return m_it == rhs.m_it && p_slice == rhs.p_slice;\n    }\n\n    template <class L, class T, class MT>\n    inline bool xaxis_view_iterator<L, T, MT>::less_than(const self_type& rhs) const\n    {\n        return p_slice == rhs.p_slice && m_it < rhs.m_it;\n    }\n\n    template <class L, class T, class MT>\n    inline typename xaxis_view_iterator<L, T, MT>::difference_type operator-(const xaxis_view_iterator<L, T, MT>& lhs,\n                                                                             const xaxis_view_iterator<L, T, MT>& rhs)\n    {\n        return lhs.operator-(rhs);\n    }\n\n    template <class L, class T, class MT>\n    inline bool operator==(const xaxis_view_iterator<L, T, MT>& lhs, const xaxis_view_iterator<L, T, MT>& rhs)\n    {\n        return lhs.equal(rhs);\n    }\n\n    template <class L, class T, class MT>\n    inline bool operator<(const xaxis_view_iterator<L, T, MT>& lhs, const xaxis_view_iterator<L, T, MT>& rhs)\n    {\n        return lhs.less_than(rhs);\n    }\n}\n\n#endif\n"
  },
  {
    "path": "include/xframe/xcoordinate.hpp",
    "content": "/***************************************************************************\n* Copyright (c) Johan Mabille, Sylvain Corlay, Wolf Vollprecht and         *\n* Martin Renou                                                             *\n* Copyright (c) QuantStack                                                 *\n*                                                                          *\n* Distributed under the terms of the BSD 3-Clause License.                 *\n*                                                                          *\n* The full license is in the file LICENSE, distributed with this software. *\n****************************************************************************/\n\n#ifndef XFRAME_XCOORDINATE_HPP\n#define XFRAME_XCOORDINATE_HPP\n\n#include \"xtensor/xutils.hpp\"\n#include \"xframe_config.hpp\"\n#include \"xcoordinate_view.hpp\"\n#include \"xnamed_axis.hpp\"\n\nnamespace xf\n{\n    namespace join\n    {\n        enum class join_id\n        {\n            outer_id,\n            inner_id\n        };\n\n        struct outer\n        {\n            static constexpr join_id id() { return join_id::outer_id; }\n        };\n\n        struct inner\n        {\n            static constexpr join_id id() { return join_id::inner_id; }\n        };\n    }\n\n    class xfull_coordinate {};\n\n    struct xtrivial_broadcast\n    {\n        xtrivial_broadcast() = default;\n        xtrivial_broadcast(bool same_dimensions, bool same_labels);\n        bool m_same_dimensions;\n        bool m_same_labels;\n    };\n\n    xtrivial_broadcast operator&&(const xtrivial_broadcast& lhs, const xtrivial_broadcast& rhs) noexcept;\n\n    /***************\n     * xcoordinate *\n     ***************/\n\n    /**\n     * @class xcoordinate\n     * @brief Class modeling coordinates\n     *\n     * The xcoordinate class is used for modeling coordinates. Coordinates are mapping\n     * of dimension names to axes. Axes in a xcoordinate object can have different label\n     * types.\n     *\n     * @tparam K the type of dimension names.\n     * @tparam L the type list of axes labels.\n     * @tparam S the integer type used to represent positions in axes. Default value\n     *           is \\c std::size_t.\n     * @tparam MT the tag used for choosing the map type which holds the label-\n     *            position pairs in the axes. Possible values are \\c map_tag and\n     *            \\c hash_map_tag. Default value is \\c hash_map_tag.\n     */\n    template <class K, class L = XFRAME_DEFAULT_LABEL_LIST, class S = std::size_t, class MT = hash_map_tag>\n    class xcoordinate : public xcoordinate_base<K, xaxis_variant<L, S, MT>>\n    {\n    public:\n\n        using self_type = xcoordinate<K, L, S, MT>;\n        using base_type = xcoordinate_base<K, xaxis_variant<L, S, MT>>;\n        using label_list = L;\n        using axis_type = typename base_type::axis_type;\n        using map_type = typename base_type::map_type;\n        using key_type = typename base_type::key_type;\n        using mapped_type = typename base_type::mapped_type;\n        using index_type = typename base_type::index_type;\n        using value_type = typename base_type::value_type;\n        using reference = typename base_type::reference;\n        using const_reference = typename base_type::const_reference;\n        using pointer = typename base_type::pointer;\n        using const_pointer = typename base_type::const_pointer;\n        using size_type = typename base_type::size_type;\n        using difference_type = typename base_type::difference_type;\n        using iterator = typename base_type::iterator;\n        using const_iterator = typename base_type::const_iterator;\n        using key_iterator = typename base_type::key_iterator;\n\n        explicit xcoordinate(const map_type& axes);\n        explicit xcoordinate(map_type&& axes);\n        xcoordinate(std::initializer_list<value_type> init);\n        template <class... K1, class... LT>\n        explicit xcoordinate(xnamed_axis<K1, S, MT, L, LT>... axes);\n\n        void clear();\n\n        template <class Join, class... Args>\n        xtrivial_broadcast broadcast(const Args&... coordinates);\n\n    private:\n\n        using coordinate_view_type = xcoordinate_view<K, L, S, MT>;\n\n        template <class Join, class... Args>\n        xtrivial_broadcast broadcast_impl(const self_type& c, const Args&... coordinates);\n        template <class Join, class... Args>\n        xtrivial_broadcast broadcast_impl(const coordinate_view_type& c, const Args&... coordinates);\n        template <class Join, class... Args>\n        xtrivial_broadcast broadcast_impl(const xfull_coordinate& c, const Args&... coordinates);\n        template <class Join>\n        xtrivial_broadcast broadcast_impl();\n\n        template <class Join, class... Args>\n        xtrivial_broadcast broadcast_empty(const self_type& c, const Args&... coordinates);\n        template <class Join, class... Args>\n        xtrivial_broadcast broadcast_empty(const coordinate_view_type& c, const Args&... coordinates);\n        template <class Join, class... Args>\n        xtrivial_broadcast broadcast_empty(const xfull_coordinate& c, const Args&... coordinates);\n        template <class Join>\n        xtrivial_broadcast broadcast_empty();\n    };\n\n    /************************\n     * xcoordinate builders *\n     ************************/\n\n    template <class K = fstring, class L = XFRAME_DEFAULT_LABEL_LIST, class S = std::size_t, class MT = hash_map_tag>\n    xcoordinate<K, L, S, MT> coordinate(const std::map<K, xaxis_variant<L, S, MT>>& axes);\n\n    template <class K = fstring, class L = XFRAME_DEFAULT_LABEL_LIST, class S = std::size_t, class MT = hash_map_tag>\n    xcoordinate<K, L, S, MT> coordinate(std::map<K, xaxis_variant<L, S, MT>>&& axes);\n\n    template <class K, class... K1, class S, class MT, class L, class LT, class... LT1>\n    xcoordinate<K, L, S, MT> coordinate(xnamed_axis<K, S, MT, L, LT> axis, xnamed_axis<K1, S, MT, L, LT1>... axes);\n\n    template <class Join, class K, class L, class S, class MT, class... Args>\n    xtrivial_broadcast broadcast_coordinates(xcoordinate<K, L, S, MT>& output, const Args&... coordinates);\n\n    /****************************\n     * coordinate metafunctions *\n     ****************************/\n\n    template <class C>\n    class xcoordinate_chain;\n\n    template <class C>\n    class xcoordinate_expanded;\n\n    namespace detail\n    {\n        template <class T>\n        struct is_coordinate_impl : std::false_type\n        {\n        };\n\n        template <class K, class L, class S, class MT>\n        struct is_coordinate_impl<xcoordinate<K, L, S, MT>> : std::true_type\n        {\n        };\n\n        template <class K, class L, class S, class MT>\n        struct is_coordinate_impl<xcoordinate_view<K, L, S, MT>> : std::true_type\n        {\n        };\n\n        template <class C>\n        struct is_coordinate_impl<xcoordinate_chain<C>> : std::true_type\n        {\n        };\n\n        template <class C>\n        struct is_coordinate_impl<xcoordinate_expanded<C>> : std::true_type\n        {\n        };\n\n        template <class T>\n        struct is_coordinate_map_impl : std::false_type\n        {\n        };\n\n        template <class K, class L, class S, class MT>\n        struct is_coordinate_map_impl<std::map<K, xaxis_variant<L, S, MT>>>\n            : std::true_type\n        {\n        };\n\n        template <class T>\n        struct get_coordinate_type_impl\n        {\n            using type = T;\n        };\n\n        template <class K, class L, class S, class MT>\n        struct get_coordinate_type_impl<std::map<K, xaxis_variant<L, S, MT>>>\n        {\n            using type = xcoordinate<K, L, S, MT>;\n        };\n    }\n\n    template <class T>\n    struct is_coordinate : detail::is_coordinate_impl<std::decay_t<T>>\n    {\n    };\n\n    template <class T>\n    struct is_coordinate_map : detail::is_coordinate_map_impl<std::decay_t<T>>\n    {\n    };\n\n    template <class T>\n    struct enable_coordinate_map\n        : std::enable_if<is_coordinate_map<T>::value, xt::void_t<>>\n    {\n    };\n\n    template <class T>\n    using enable_coordinate_map_t = typename enable_coordinate_map<T>::type;\n\n    template <class T>\n    struct get_coordinate_type : detail::get_coordinate_type_impl<std::decay_t<T>>\n    {\n    };\n\n    template <class T>\n    using get_coordinate_type_t = typename get_coordinate_type<T>::type;\n\n    /******************************\n     * xcoordinate implementation *\n     ******************************/\n\n    inline xtrivial_broadcast operator&&(const xtrivial_broadcast& lhs, const xtrivial_broadcast& rhs) noexcept\n    {\n        return xtrivial_broadcast(lhs.m_same_dimensions && rhs.m_same_dimensions,\n                                  lhs.m_same_labels && rhs.m_same_labels);\n    }\n\n    inline xtrivial_broadcast::xtrivial_broadcast(bool same_dimensions, bool same_labels)\n        : m_same_dimensions(same_dimensions), m_same_labels(same_labels)\n    {\n    }\n\n    /**\n     * Constructs an xcoordinate object with the given mapping of dimension names\n     * to axes. This mapping is copied.\n     * @param axes the dimension names to axes mapping.\n     */\n    template <class K, class L, class S, class MT>\n    inline xcoordinate<K, L, S, MT>::xcoordinate(const map_type& axes)\n        : base_type(axes)\n    {\n    }\n\n    /**\n     * Constructs an xcoordinate object with the given mapping of dimension names\n     * to axes. This mapping is moved and therefore it is invalid after the\n     * xcoordinate has been constructed.\n     * @param axes the dimension names to axes mapping.\n     */\n    template <class K, class L, class S, class MT>\n    inline xcoordinate<K, L, S, MT>::xcoordinate(map_type&& axes)\n        : base_type(std::move(axes))\n    {\n    }\n\n    /**\n     * Constructs an xcoordinate object from the given initializer list of\n     * dimension names - axes pairs.\n     */\n    template <class K, class L, class S, class MT>\n    inline xcoordinate<K, L, S, MT>::xcoordinate(std::initializer_list<value_type> init)\n        : base_type(init)\n    {\n    }\n\n    /**\n     * Constructs an xcoordinate object from the given named axes.\n     */\n    template <class K, class L, class S, class MT>\n    template <class... K1, class... LT>\n    inline xcoordinate<K, L, S, MT>::xcoordinate(xnamed_axis<K1, S, MT, L, LT>... axes)\n        : base_type({ value_type(std::move(axes).name(), std::move(axes).axis())... })\n    {\n    }\n\n    /**\n     * Removes all the elements from the xcoordinate. After this call, \\c size() returns\n     * zero.\n     */\n    template <class K, class L, class S, class MT>\n    inline void xcoordinate<K, L, S, MT>::clear()\n    {\n        this->coordinate().clear();\n    }\n\n    /**\n     * Broadcast the specified coordinates to this xcoordinate.\n     * @param coordinates the coordinates to broadcast.\n     * @return an object specifying if the labels and the dimension of\n     *         the coordinates are the same.\n     */\n    template <class K, class L, class S, class MT>\n    template <class Join, class... Args>\n    inline xtrivial_broadcast xcoordinate<K, L, S, MT>::broadcast(const Args&... coordinates)\n    {\n        return this->empty() ? broadcast_empty<Join>(coordinates...) : broadcast_impl<Join>(coordinates...);\n    }\n\n    namespace detail\n    {\n        template <class Join>\n        struct axis_broadcast;\n\n        template <>\n        struct axis_broadcast<join::outer>\n        {\n            template <class A>\n            static bool apply(A& output, const A& input)\n            {\n                return output.merge(input);\n            }\n        };\n\n        template <>\n        struct axis_broadcast<join::inner>\n        {\n            template <class A>\n            static bool apply(A& output, const A& input)\n            {\n                return output.intersect(input);\n            }\n        };\n    }\n\n    template <class K, class L, class S, class MT>\n    template <class Join, class... Args>\n    inline xtrivial_broadcast xcoordinate<K, L, S, MT>::broadcast_impl(const self_type& c, const Args&... coordinates)\n    {\n        auto res = broadcast_impl<Join>(coordinates...);\n        XFRAME_TRACE_BROADCAST_COORDINATES(*this, c);\n        for(auto iter = c.begin(); iter != c.end(); ++iter)\n        {\n            auto inserted = this->coordinate().insert(*iter);\n            if(inserted.second)\n            {\n                res.m_same_dimensions = false;\n            }\n            else\n            {\n                auto& axis = inserted.first->second;\n                res.m_same_labels &= detail::axis_broadcast<Join>::apply(axis, iter->second);\n            }\n        }\n        res.m_same_dimensions &= (this->size() == c.size());\n        XFRAME_TRACE_COORDINATES_RESULT(*this, res);\n        return res;\n    }\n\n    template <class K, class L, class S, class MT>\n    template <class Join, class... Args>\n    inline xtrivial_broadcast xcoordinate<K, L, S, MT>::broadcast_impl(const coordinate_view_type& c, const Args&... coordinates)\n    {\n        auto res = broadcast_impl<Join>(coordinates...);\n        XFRAME_TRACE_BROADCAST_COORDINATES(*this, c);\n        for (auto iter = c.begin(); iter != c.end(); ++iter)\n        {\n            mapped_type axis = mapped_type(iter->second);\n            auto it = this->coordinate().find(iter->first);\n            if (it == this->coordinate().end())\n            {\n                this->coordinate().insert(std::make_pair(iter->first, std::move(axis)));\n                res.m_same_dimensions = false;\n            }\n            else\n            {\n                res.m_same_labels &= detail::axis_broadcast<Join>::apply(it->second, axis);\n            }\n        }\n        res.m_same_dimensions &= (this->size() == c.size());\n        XFRAME_TRACE_COORDINATES_RESULT(*this, res);\n        return res;\n    }\n\n    template <class K, class L, class S, class MT>\n    template <class Join, class... Args>\n    inline xtrivial_broadcast xcoordinate<K, L, S, MT>::broadcast_impl(const xfull_coordinate& /*c*/, const Args&... coordinates)\n    {\n        return broadcast_impl<Join>(coordinates...);\n    }\n\n    template <class K, class L, class S, class MT>\n    template <class Join>\n    inline xtrivial_broadcast xcoordinate<K, L, S, MT>::broadcast_impl()\n    {\n        return xtrivial_broadcast(true, true);\n    }\n\n    template <class K, class L, class S, class MT>\n    template <class Join, class... Args>\n    inline xtrivial_broadcast xcoordinate<K, L, S, MT>::broadcast_empty(const self_type& c, const Args&... coordinates)\n    {\n        map_type& m = this->coordinate();\n        for (auto iter = c.data().cbegin(); iter != c.data().cend(); ++iter)\n        {\n            m.insert(std::make_pair(iter->first, mapped_type(iter->second.as_xaxis())));\n        }\n        return broadcast_impl<Join>(coordinates...);\n    }\n\n    template <class K, class L, class S, class MT>\n    template <class Join, class... Args>\n    inline xtrivial_broadcast xcoordinate<K, L, S, MT>::broadcast_empty(const coordinate_view_type& c, const Args&... coordinates)\n    {\n        map_type& m = this->coordinate();\n        for (auto iter = c.data().cbegin(); iter != c.data().cend(); ++iter)\n        {\n            m.insert(std::make_pair(iter->first, mapped_type(iter->second.as_xaxis())));\n        }\n        return broadcast_impl<Join>(coordinates...);\n    }\n\n    template <class K, class L, class S, class MT>\n    template <class Join, class... Args>\n    inline xtrivial_broadcast xcoordinate<K, L, S, MT>::broadcast_empty(const xfull_coordinate& /*c*/, const Args&... coordinates)\n    {\n        return broadcast_empty<Join>(coordinates...);\n    }\n\n    template <class K, class L, class S, class MT>\n    template <class Join>\n    inline xtrivial_broadcast xcoordinate<K, L, S, MT>::broadcast_empty()\n    {\n        return broadcast_impl<Join>();\n    }\n\n    /***************************************\n     * xcoordinate builders implementation *\n     ***************************************/\n\n    /**\n     * Builds and returns an xcoordinate object from the specified\n     * mapping of dimension names to axes. The map is copied.\n     * @param axes the dimension names to axes mapping.\n     */\n    template <class K, class L, class S, class MT>\n    xcoordinate<K, L, S, MT> coordinate(const std::map<K, xaxis_variant<L, S, MT>>& axes)\n    {\n        return xcoordinate<K, L, S, MT>(axes);\n    }\n\n    /**\n     * Builds and returns an xcoordinate object from the specified\n     * mapping of dimension names to axes. The map is moved, therefore\n     * it is invalid after the xcoordinate object has been built.\n     * @param axes the dimension names to axes mapping.\n     */\n    template <class K, class L, class S, class MT>\n    xcoordinate<K, L, S, MT> coordinate(std::map<K, xaxis_variant<L, S, MT>>&& axes)\n    {\n        return xcoordinate<K, L, S, MT>(std::move(axes));\n    }\n\n    /**\n     * Builds and returns an xcoordinate object from the specified\n     * list of named axes.\n     * @param axes the list of named axes.\n     */\n    template <class K, class... K1, class S, class MT, class L, class LT, class... LT1>\n    xcoordinate<K, L, S, MT> coordinate(xnamed_axis<K, S, MT, L, LT> axis, xnamed_axis<K1, S, MT, L, LT1>... axes)\n    {\n        return xcoordinate<K, L, S, MT>(axis, axes...);\n    };\n\n    /**\n     * Broadcast a list of coordinates to the specified output coordinate.\n     * @param output the xcoordinate result.\n     * @param coordinates the list of xcoordinate objects to broadcast.\n     */\n    template <class Join, class K, class L, class S, class MT, class... Args>\n    inline xtrivial_broadcast broadcast_coordinates(xcoordinate<K, L, S, MT>& output, const Args&... coordinates)\n    {\n        return output.template broadcast<Join>(coordinates...);\n    }\n}\n\n#endif\n"
  },
  {
    "path": "include/xframe/xcoordinate_base.hpp",
    "content": "/***************************************************************************\n* Copyright (c) Johan Mabille, Sylvain Corlay, Wolf Vollprecht and         *\n* Martin Renou                                                             *\n* Copyright (c) QuantStack                                                 *\n*                                                                          *\n* Distributed under the terms of the BSD 3-Clause License.                 *\n*                                                                          *\n* The full license is in the file LICENSE, distributed with this software. *\n****************************************************************************/\n\n#ifndef XFRAME_XCOORDINATE_BASE_HPP\n#define XFRAME_XCOORDINATE_BASE_HPP\n\n#include <map>\n\n#include \"xtl/xiterator_base.hpp\"\n#include \"xaxis_variant.hpp\"\n#include \"xframe_config.hpp\"\n\nnamespace xf\n{\n\n    /********************\n     * xcoordinate_base *\n     ********************/\n\n    /**\n     * @class xcoordinate_base\n     * @brief Base class for coordinates.\n     *\n     * The xcoordinate_base class defines the common interface for coordinates,\n     * which define the mapping of dimension names to axes.\n     *\n     * @tparam D The derived type, i.e. the inheriting class for which xcoordinate_base\n     *           provides the interface.\n     */\n    template <class K, class A>\n    class xcoordinate_base\n    {\n    public:\n\n        using self_type = xcoordinate_base<K, A>;\n        using axis_type = A;\n        using map_type = std::map<K, axis_type>;\n        using key_type = typename map_type::key_type;\n        using mapped_type = typename map_type::mapped_type;\n        using label_type = typename axis_type::key_type;\n        using index_type = typename axis_type::mapped_type;\n        using value_type = typename map_type::value_type;\n        using reference = typename map_type::reference;\n        using const_reference = typename map_type::const_reference;\n        using pointer = typename map_type::pointer;\n        using const_pointer = typename map_type::const_pointer;\n        using size_type = typename map_type::size_type;\n        using difference_type = typename map_type::difference_type;\n        using iterator = typename map_type::iterator;\n        using const_iterator = typename map_type::const_iterator;\n        using key_iterator = xtl::xkey_iterator<map_type>;\n\n        bool empty() const;\n        size_type size() const;\n\n        bool contains(const key_type& key) const;\n        bool contains(const key_type& key, const label_type& label) const;\n\n        const mapped_type& operator[](const key_type& key) const;\n        template <class KB, class LB>\n        index_type operator[](const std::pair<KB, LB>& key) const;\n\n        const map_type& data() const noexcept;\n\n        const_iterator find(const key_type& key) const;\n\n        const_iterator begin() const noexcept;\n        const_iterator end() const noexcept;\n\n        const_iterator cbegin() const noexcept;\n        const_iterator cend() const noexcept;\n\n        key_iterator key_begin() const noexcept;\n        key_iterator key_end() const noexcept;\n\n    protected:\n\n        xcoordinate_base(const map_type& axes);\n        xcoordinate_base(map_type&& axes);\n        xcoordinate_base(std::initializer_list<value_type> init);\n        template <class... AX>\n        xcoordinate_base(std::pair<K, AX>... axes);\n\n        ~xcoordinate_base() = default;\n\n        xcoordinate_base(const xcoordinate_base&) = default;\n        xcoordinate_base& operator=(const xcoordinate_base&) = default;\n\n        xcoordinate_base(xcoordinate_base&&) = default;\n        xcoordinate_base& operator=(xcoordinate_base&&) = default;\n\n        map_type& coordinate() noexcept;\n\n    private:\n\n        map_type m_coordinate;\n    };\n\n    template <class K, class A1, class A2>\n    bool operator==(const xcoordinate_base<K, A1>& lhs, const xcoordinate_base<K, A2>& rhs);\n\n    template <class K, class A1, class A2>\n    bool operator!=(const xcoordinate_base<K, A1>& lhs, const xcoordinate_base<K, A2>& rhs);\n\n    template <class OS, class K, class A>\n    OS& operator<<(OS& out, const xcoordinate_base<K, A>& c);\n\n    /***********************************\n     * xcoordinate_base implementation *\n     ***********************************/\n\n    template <class K, class A>\n    inline xcoordinate_base<K, A>::xcoordinate_base(const map_type& axes)\n        : m_coordinate(axes)\n    {\n    }\n\n    template <class K, class A>\n    inline xcoordinate_base<K, A>::xcoordinate_base(map_type&& axes)\n        : m_coordinate(std::move(axes))\n    {\n    }\n\n    template <class K, class A>\n    inline xcoordinate_base<K, A>::xcoordinate_base(std::initializer_list<value_type> init)\n        : m_coordinate(init)\n    {\n    }\n\n    template <class K, class A>\n    template <class... AX>\n    inline xcoordinate_base<K, A>::xcoordinate_base(std::pair<K, AX>... axes)\n        : m_coordinate({std::move(axes)...})\n    {\n    }\n\n    /**\n     * Returns true if the coordinates is empty, i.e. it contains no mapping\n     * of axes with dimension names.\n     */\n    template <class K, class A>\n    inline bool xcoordinate_base<K, A>::empty() const\n    {\n        return m_coordinate.empty();\n    }\n\n    /**\n     * Returns the number of axes in the coordinates.\n     */\n    template <class K, class A>\n    inline auto xcoordinate_base<K, A>::size() const -> size_type\n    {\n        return m_coordinate.size();\n    }\n\n    /**\n     * Returns true if the coordinates contains the specified dimension\n     * name.\n     * @param key the dimension name to search for.\n     */\n    template <class K, class A>\n    inline bool xcoordinate_base<K, A>::contains(const key_type& key) const\n    {\n        return m_coordinate.find(key) != m_coordinate.end();\n    }\n\n    /**\n     * Returns true if the coordinates contains the specified dimension\n     * name and if the axis mapped with this name contains the specified\n     * label.\n     * @param key the dimension name to search for.\n     * @param label the label to search for in the mapped axis.\n     */\n    template <class K, class A>\n    inline bool xcoordinate_base<K, A>::contains(const key_type& key, const label_type& label) const\n    {\n        auto iter = m_coordinate.find(key);\n        return iter != m_coordinate.end() ? (iter->second).contains(label) : false;\n    }\n\n    /**\n     * Returns the axis mapped to the specified dimension name. If this last one is not\n     * found, throws an exception.\n     * @param key the name of the dimension to search for.\n     */\n    template <class K, class A>\n    inline auto xcoordinate_base<K, A>::operator[](const key_type& key) const -> const mapped_type&\n    {\n        return m_coordinate.at(key);\n    }\n\n    /**\n     * Returns the position of the specified labels of the axis mapped to the specified\n     * dimension name. Throws an exception if either the dimension name or the label is\n     * not part of this coordinate.\n     * @param key the pair dimension name - label to search for.\n     */\n    template <class K, class A>\n    template <class KB, class LB>\n    inline auto xcoordinate_base<K, A>::operator[](const std::pair<KB, LB>& key) const -> index_type\n    {\n        return (*this)[key.first][key.second];\n    }\n\n    /**\n     * Returns the container of the dimension names to axes mapping.\n     */\n    template <class K, class A>\n    inline auto xcoordinate_base<K, A>::data() const noexcept -> const map_type&\n    {\n        return m_coordinate;\n    }\n\n    /**\n     * Returns a constant iterator to the axis mapped to the specified dimension name.\n     * If no such element is found, past-the-end iterator is returned.\n     * @param key the dimension name to search for.\n     */\n    template <class K, class A>\n    inline auto xcoordinate_base<K, A>::find(const key_type& key) const -> const_iterator\n    {\n        return m_coordinate.find(key);\n    }\n\n    /**\n     * Returns a constant iterator to the first element of the coordinates. Such an element\n     * is a pair dimension name - axis.\n     */\n    template <class K, class A>\n    inline auto xcoordinate_base<K, A>::begin() const noexcept -> const_iterator\n    {\n        return cbegin();\n    }\n\n    /**\n     * Returns a constant iterator to the element following the last element of\n     * the coordinates.\n     */\n    template <class K, class A>\n    inline auto xcoordinate_base<K, A>::end() const noexcept -> const_iterator\n    {\n        return cend();\n    }\n\n    /**\n     * Returns a constant iterator to the first element of the coordinates. Such an element\n     * is a pair dimension name - axis.\n     */\n    template <class K, class A>\n    inline auto xcoordinate_base<K, A>::cbegin() const noexcept -> const_iterator\n    {\n        return m_coordinate.cbegin();\n    }\n\n    /**\n     * Returns a constant iterator to the element following the last element of\n     * the coordinates.\n     */\n    template <class K, class A>\n    inline auto xcoordinate_base<K, A>::cend() const noexcept -> const_iterator\n    {\n        return m_coordinate.cend();\n    }\n\n    /**\n     * Returns a constant iterator to the first dimension name of the coordinates.\n     */\n    template <class K, class A>\n    inline auto xcoordinate_base<K, A>::key_begin() const noexcept -> key_iterator\n    {\n        return key_iterator(begin());\n    }\n\n    /**\n     * Returns a constant iterator to the element following the last dimension name of\n     * the coordinates.\n     */\n    template <class K, class A>\n    inline auto xcoordinate_base<K, A>::key_end() const noexcept -> key_iterator\n    {\n        return key_iterator(end());\n    }\n\n    template <class K, class A>\n    inline auto xcoordinate_base<K, A>::coordinate() noexcept -> map_type&\n    {\n        return m_coordinate;\n    }\n\n    /**\n     * Returns true if \\c lhs and \\c rhs are equivalent coordinates, i.e. they hold the same\n     * axes mapped to the same dimension names.\n     * @param lhs a coordinate object.\n     * @param rhs a coordinate object.\n     */\n    template <class K, class A1, class A2>\n    inline bool operator==(const xcoordinate_base<K, A1>& lhs, const xcoordinate_base<K, A2>& rhs)\n    {\n        bool res = lhs.size() == rhs.size();\n\n        auto liter = lhs.cbegin();\n        auto lend = lhs.cend();\n        auto riter = rhs.cbegin();\n        while(res && liter != lend)\n        {\n            res = (liter->second == riter->second);\n            ++liter;\n            ++riter;\n        }\n        return res;\n    }\n\n    /**\n     * Returns true if \\c lhs and \\c rhs are not equivalent coordinates, i.e. they hold different \n     * axes or the dimension names to axes mappings are different.\n     * @param lhs a coordinate object.\n     * @param rhs a coordinate object.\n     */\n    template <class K, class A1, class A2>\n    inline bool operator!=(const xcoordinate_base<K, A1>& lhs, const xcoordinate_base<K, A2>& rhs)\n    {\n        return !(lhs == rhs);\n    }\n\n    template <class OS, class K, class A>\n    inline OS& operator<<(OS& out, const xcoordinate_base<K, A>& c)\n    {\n        for (auto& v : c)\n        {\n            out << v.first << \": \" << v.second << std::endl;\n        }\n        return out;\n    }\n}\n\n#endif\n"
  },
  {
    "path": "include/xframe/xcoordinate_chain.hpp",
    "content": "/***************************************************************************\n* Copyright (c) Johan Mabille, Sylvain Corlay, Wolf Vollprecht and         *\n* Martin Renou                                                             *\n* Copyright (c) QuantStack                                                 *\n*                                                                          *\n* Distributed under the terms of the BSD 3-Clause License.                 *\n*                                                                          *\n* The full license is in the file LICENSE, distributed with this software. *\n****************************************************************************/\n\n#ifndef XFRAME_XCOORDINATE_CHAIN_HPP\n#define XFRAME_XCOORDINATE_CHAIN_HPP\n\n#include <type_traits>\n#include \"xtl/xiterator_base.hpp\"\n#include \"xcoordinate.hpp\"\n\nnamespace xf\n{\n    template <class M>\n    class xmap_chain_iterator;\n\n    /*********************\n     * xcoordinate_chain *\n     *********************/\n\n    /**\n     * @class xcoordinate_chain\n     * @brief reindexed view of an xcoordinate.\n     *\n     * The xcoordinate_chain is used for creating a reindexed view on an existing\n     * xcoordinate. This is done by holding new axes and keeping a reference to\n     * the underlying xcoordinate.\n     *\n     * @tparam C the type of the underlying xcoordinate.\n     * @sa xcoordinate\n     * @sa xcoordinate_expanded\n     */\n    template <class C>\n    class xcoordinate_chain\n    {\n    public:\n\n        using coordinate_type = C;\n        using self_type = xcoordinate_chain<C>;\n        using label_list = typename coordinate_type::label_list;\n        using key_type = typename coordinate_type::key_type;\n        using axis_type = typename coordinate_type::axis_type;\n        using label_type = typename axis_type::key_type;\n        using map_type = typename coordinate_type::map_type;\n        using mapped_type = typename coordinate_type::mapped_type;\n        using index_type = typename coordinate_type::index_type;\n        using value_type = typename coordinate_type::value_type;\n        using reference = typename coordinate_type::reference;\n        using const_reference = typename coordinate_type::const_reference;\n        using pointer = typename coordinate_type::pointer;\n        using const_pointer = typename coordinate_type::const_pointer;\n        using size_type = typename coordinate_type::size_type;\n        using difference_type = typename coordinate_type::difference_type;\n        using const_iterator = xmap_chain_iterator<map_type>;\n        using key_iterator = xtl::xkey_iterator<self_type>;\n\n        xcoordinate_chain(const coordinate_type& sub_coord, const map_type& new_coord);\n        xcoordinate_chain(const coordinate_type& sub_coord, map_type&& new_coord);\n\n        bool empty() const;\n        size_type size() const;\n\n        bool contains(const key_type& key) const;\n        bool contains(const key_type& key, const label_type& label) const;\n        const mapped_type& operator[](const key_type& key) const;\n\n        template <class KB, class LB>\n        index_type operator[](const std::pair<KB, LB>& key) const;\n\n        // TODO: check if that's required and why\n        //const map_type& data() const noexcept;\n\n        const coordinate_type& initial_coordinates() const;\n        const map_type& reindex_map() const;\n        bool is_reindexed(const key_type& key, const label_type& label) const;\n\n        const_iterator find(const key_type& key) const;\n\n        const_iterator begin() const noexcept;\n        const_iterator end() const noexcept;\n\n        const_iterator cbegin() const noexcept;\n        const_iterator cend() const noexcept;\n\n        key_iterator key_begin() const noexcept;\n        key_iterator key_end() const noexcept;\n\n        bool operator==(const self_type& rhs) const noexcept;\n        bool operator!=(const self_type& rhs) const noexcept;\n\n    private:\n\n        void check_consistency() const;\n\n        const coordinate_type& m_sub_coordinate;\n        map_type m_reindex;\n    };\n\n    template <class C, class K, class A>\n    bool operator==(const xcoordinate_chain<C>& lhs, const xcoordinate_base<K, A>& rhs);\n\n    template <class C, class K, class A>\n    bool operator==(const xcoordinate_base<K, A>& lhs, const xcoordinate_chain<C>& rhs);\n\n    template <class C, class K, class A>\n    bool operator!=(const xcoordinate_chain<C>& lhs, const xcoordinate_base<K, A>& rhs);\n\n    template <class C, class K, class A>\n    bool operator!=(const xcoordinate_base<K, A>& lhs, const xcoordinate_chain<C>& rhs);\n\n    template <class OS, class C>\n    std::ostream& operator<<(std::ostream& out, const xcoordinate_chain<C>& c);\n\n    template <class C>\n    xcoordinate_chain<C> reindex(const C& coordinate, const typename C::map_type& new_coord);\n\n    template <class C>\n    xcoordinate_chain<C> reindex(const C& coordinate, typename C::map_type&& new_coord);\n\n    /*******************\n     * xiterator_chain *\n     *******************/\n\n    template <class M>\n    class xmap_chain_iterator\n    {\n    public:\n\n        using self_type = xmap_chain_iterator<M>;\n        using map_type = M;\n        using map_iterator = typename M::const_iterator;\n        using value_type = typename map_iterator::value_type;\n        using reference = typename map_iterator::reference;\n        using pointer = typename map_iterator::pointer;\n        using difference_type = typename map_iterator::difference_type;\n        using iterator_category = typename map_iterator::iterator_category;\n\n        xmap_chain_iterator();\n        xmap_chain_iterator(map_iterator sub_it, map_iterator sub_end, const map_type* coordinate);\n\n        self_type& operator++();\n        self_type& operator--();\n\n        self_type operator++(int);\n        self_type operator--(int);\n\n        reference operator*() const;\n        pointer operator->() const;\n\n        bool operator==(const self_type& rhs) const;\n        bool operator!=(const self_type& rhs) const;\n\n    private:\n\n        void update_it();\n\n        map_iterator m_sub_it;\n        map_iterator m_sub_end;\n        map_iterator m_it;\n        const map_type* p_coordinate;\n    };\n\n    /************************************\n     * xcoordinate_chain implementation *\n     ************************************/\n\n    /**\n     * Constructs an xcoordinate_chain, given the reference to an xcoordinate\n     * and the reference to the additional coordinates.\n     * @param sub_coord the reference to the underlying xcoordinate.\n     * @param new_coord the `dimension name <-> axis` mapping of the new coordinates.\n     */\n    template <class C>\n    inline xcoordinate_chain<C>::xcoordinate_chain(const coordinate_type& sub_coord, const map_type& new_coord)\n        : m_sub_coordinate(sub_coord), m_reindex(new_coord)\n    {\n        check_consistency();\n    }\n\n    /**\n     * Constructs an xcoordinate_chain, given the reference to an xcoordinate\n     * and the reference to the additional coordinates.\n     * @param sub_coord the reference to the underlying xcoordinate.\n     * @param new_coord the `dimension name <-> axis` mapping of the new coordinates.\n     */\n    template <class C>\n    inline xcoordinate_chain<C>::xcoordinate_chain(const coordinate_type& sub_coord, map_type&& new_coord)\n        : m_sub_coordinate(sub_coord), m_reindex(std::move(new_coord))\n    {\n        check_consistency();\n    }\n\n    /**\n     * Returns true if the coordinates is empty, i.e. it contains no mapping\n     * of axes with dimension names.\n     */\n    template <class C>\n    inline bool xcoordinate_chain<C>::empty() const\n    {\n        return m_sub_coordinate.empty();\n    }\n\n    /**\n     * Returns the number of axes in the coordinates.\n     */\n    template <class C>\n    inline auto xcoordinate_chain<C>::size() const -> size_type\n    {\n        return m_sub_coordinate.size();\n    }\n\n    /**\n     * Returns true if the coordinates contains the specified dimension\n     * name.\n     * @param key the dimension name to search for.\n     */\n    template <class C>\n    inline bool xcoordinate_chain<C>::contains(const key_type& key) const\n    {\n        return (m_reindex.find(key) != m_reindex.end()) || m_sub_coordinate.contains(key);\n    }\n\n    /**\n     * Returns true if the coordinates contains the specified dimension\n     * name and if the axis mapped with this name contains the specified\n     * label.\n     * @param key the dimension name to search for.\n     * @param label the label to search for in the mapped axis.\n     */\n    template <class C>\n    inline bool xcoordinate_chain<C>::contains(const key_type& key, const label_type& label) const\n    {\n        auto iter = find(key);\n        return iter != end() ? (iter->second).contains(label) : false;\n    }\n\n    /**\n     * Returns the axis mapped to the specified dimension name. If this last one is not\n     * found, throws an exception.\n     * @param key the name of the dimension to search for.\n     */\n    template <class C>\n    inline auto xcoordinate_chain<C>::operator[](const key_type& key) const -> const mapped_type&\n    {\n        auto iter = m_reindex.find(key);\n        return iter != m_reindex.end() ? iter->second : m_sub_coordinate[key];\n    }\n\n    /**\n     * Returns the position of the specified labels of the axis mapped to the specified\n     * dimension name. Throws an exception if either the dimension name or the label is\n     * not part of this coordinate.\n     * @param key the pair dimension name - label to search for.\n     */\n    template <class C>\n    template <class KB, class LB>\n    inline auto xcoordinate_chain<C>::operator[](const std::pair<KB, LB>& key) const -> index_type\n    {\n        auto iter = m_reindex.find(key.first);\n        return iter != m_reindex.end() ? (iter->second)[key.second] : m_sub_coordinate[key.first][key.second];\n    }\n\n    template <class C>\n    inline auto xcoordinate_chain<C>::initial_coordinates() const -> const coordinate_type&\n    {\n        return m_sub_coordinate;\n    }\n\n    template <class C>\n    inline auto xcoordinate_chain<C>::reindex_map() const -> const map_type&\n    {\n        return m_reindex;\n    }\n\n    template <class C>\n    bool xcoordinate_chain<C>::is_reindexed(const key_type& key, const label_type& label) const\n    {\n        auto iter = m_reindex.find(key);\n        return iter != m_reindex.end() ? (iter->second).contains(label) : false;\n    }\n\n    /**\n     * Returns a constant iterator to the axis mapped to the specified dimension name.\n     * If no such element is found, past-the-end iterator is returned.\n     * @param key the dimension name to search for.\n     */\n    template <class C>\n    inline auto xcoordinate_chain<C>::find(const key_type& key) const -> const_iterator\n    {\n        auto iter = m_reindex.find(key);\n        if(iter == m_reindex.end())\n        {\n            iter = m_sub_coordinate.find(key);\n        }\n        return const_iterator(iter, m_sub_coordinate.cend(), &m_reindex);\n    }\n\n    /**\n     * Returns a constant iterator to the first element of the coordinates. Such an element\n     * is a pair dimension name - axis.\n     */\n    template <class C>\n    inline auto xcoordinate_chain<C>::begin() const noexcept -> const_iterator\n    {\n        return cbegin();\n    }\n\n    /**\n     * Returns a constant iterator to the element following the last element of\n     * the coordinates.\n     */\n    template <class C>\n    inline auto xcoordinate_chain<C>::end() const noexcept -> const_iterator\n    {\n        return cend();\n    }\n\n    /**\n     * Returns a constant iterator to the first element of the coordinates. Such an element\n     * is a pair dimension name - axis.\n     */\n    template <class C>\n    inline auto xcoordinate_chain<C>::cbegin() const noexcept -> const_iterator\n    {\n        return const_iterator(m_sub_coordinate.cbegin(), m_sub_coordinate.cend(), &m_reindex);\n    }\n\n    /**\n     * Returns a constant iterator to the element following the last element of\n     * the coordinates.\n     */\n    template <class C>\n    inline auto xcoordinate_chain<C>::cend() const noexcept -> const_iterator\n    {\n        return const_iterator(m_sub_coordinate.cend(), m_sub_coordinate.cend(), &m_reindex);\n    }\n\n    /**\n     * Returns a constant iterator to the first dimension name of the coordinates.\n     */\n    template <class C>\n    inline auto xcoordinate_chain<C>::key_begin() const noexcept -> key_iterator\n    {\n        return key_iterator(begin());\n    }\n\n    /**\n     * Returns a constant iterator to the element following the last dimension name of\n     * the coordinates.\n     */\n    template <class C>\n    inline auto xcoordinate_chain<C>::key_end() const noexcept -> key_iterator\n    {\n        return key_iterator(end());\n    }\n\n    template <class C>\n    inline bool xcoordinate_chain<C>::operator==(const self_type& rhs) const noexcept\n    {\n        return m_sub_coordinate == rhs.m_sub_coordinate\n            && m_reindex == rhs.m_reindex;\n    }\n\n    template <class C>\n    inline bool xcoordinate_chain<C>::operator!=(const self_type& rhs) const noexcept\n    {\n        return !(*this == rhs);\n    }\n\n    template <class C>\n    inline void xcoordinate_chain<C>::check_consistency() const\n    {\n        for(const auto& a: m_reindex)\n        {\n            if(!m_sub_coordinate.contains(a.first))\n            {\n                throw std::out_of_range(\"coordinate not found\");\n            }\n        }\n    }\n\n    template <class C, class K, class A>\n    inline bool operator==(const xcoordinate_chain<C>& lhs, const xcoordinate_base<K, A>& rhs)\n    {\n        bool res = lhs.size() == rhs.size();\n        auto iter = lhs.begin();\n        auto end = lhs.end();\n        auto rhs_end = rhs.end();\n        while(res && iter != end)\n        {\n            auto rhs_iter = rhs.find(iter->first);\n            res = (rhs_iter != rhs_end) && (iter->second == rhs_iter->second);\n            ++iter;\n        }\n        return res;\n    }\n\n    template <class C, class K, class A>\n    inline bool operator==(const xcoordinate_base<K, A>& lhs, const xcoordinate_chain<C>& rhs)\n    {\n        return rhs == lhs;\n    }\n\n    template <class C, class K, class A>\n    inline bool operator!=(const xcoordinate_chain<C>& lhs, const xcoordinate_base<K, A>& rhs)\n    {\n        return !(lhs == rhs);\n    }\n\n    template <class C, class K, class A>\n    inline bool operator!=(const xcoordinate_base<K, A>& lhs, const xcoordinate_chain<C>& rhs)\n    {\n        return rhs != lhs;\n    }\n\n    template <class C>\n    inline std::ostream& operator<<(std::ostream& out, const xcoordinate_chain<C>& c)\n    {\n        for (auto& v : c)\n        {\n            out << v.first << \": \" << v.second << std::endl;\n        }\n        return out;\n    }\n\n    /**\n     * Creates a reindexed view on an xcoordinate, given the reference on the\n     * xcoordinate and the new coordinates.\n     * @param sub_coord the reference to the underlying xcoordinate.\n     * @param new_coord the `dimension name <-> axis` mapping of the new coordinates.\n     */\n    template <class C>\n    inline xcoordinate_chain<C> reindex(const C& coordinate, const typename C::map_type& new_coord)\n    {\n        return xcoordinate_chain<C>(coordinate, new_coord);\n    }\n\n    /**\n     * Creates a reindexed view on an xcoordinate, given the reference on the\n     * xcoordinate and the new coordinates.\n     * @param sub_coord the reference to the underlying xcoordinate.\n     * @param new_coord the `dimension name <-> axis` mapping of the new coordinates.\n     */\n    template <class C>\n    inline xcoordinate_chain<C> reindex(const C& coordinate, typename C::map_type&& new_coord)\n    {\n        return xcoordinate_chain<C>(coordinate, std::move(new_coord));\n    }\n\n    /**************************************\n     * xmap_chain_iterator implementation *\n     **************************************/\n\n    template <class M>\n    inline xmap_chain_iterator<M>::xmap_chain_iterator()\n        : m_sub_it(), m_it(), p_coordinate(nullptr)\n    {\n    }\n\n    template <class M>\n    inline xmap_chain_iterator<M>::xmap_chain_iterator(map_iterator sub_it, map_iterator sub_end, const map_type* coordinate)\n        : m_sub_it(sub_it), m_sub_end(sub_end),m_it(), p_coordinate(coordinate)\n    {\n        update_it();\n    }\n\n    template <class M>\n    inline auto xmap_chain_iterator<M>::operator++() -> self_type&\n    {\n        ++m_sub_it;\n        update_it();\n        return *this;\n    }\n\n    template <class M>\n    inline auto xmap_chain_iterator<M>::operator--() -> self_type&\n    {\n        --m_sub_it;\n        update_it();\n        return *this;\n    }\n\n    template <class M>\n    inline auto xmap_chain_iterator<M>::operator++(int) -> self_type\n    {\n        self_type tmp(*this);\n        ++(*this);\n        return tmp;\n    }\n\n    template <class M>\n    inline auto xmap_chain_iterator<M>::operator--(int) -> self_type\n    {\n        self_type tmp(*this);\n        --(*this);\n        return tmp;\n    }\n\n    template <class M>\n    inline auto xmap_chain_iterator<M>::operator*() const -> reference\n    {\n        return *m_it;\n    }\n\n    template <class M>\n    inline auto xmap_chain_iterator<M>::operator->() const -> pointer\n    {\n        return m_it.operator->();\n    }\n\n    template <class M>\n    inline bool xmap_chain_iterator<M>::operator==(const self_type& rhs) const\n    {\n        return m_it == rhs.m_it;\n    }\n\n    template <class M>\n    inline bool xmap_chain_iterator<M>::operator!=(const self_type& rhs) const\n    {\n        return !(*this == rhs);\n    }\n\n    template <class M>\n    inline void xmap_chain_iterator<M>::update_it()\n    {\n        if (m_sub_it != m_sub_end)\n        {\n            m_it = p_coordinate->find(m_sub_it->first);\n            if (m_it == p_coordinate->end())\n            {\n                m_it = m_sub_it;\n            }\n        }\n        else\n        {\n            m_it = m_sub_it;\n        }\n    }\n}\n\n#endif\n"
  },
  {
    "path": "include/xframe/xcoordinate_expanded.hpp",
    "content": "/***************************************************************************\n* Copyright (c) Johan Mabille, Sylvain Corlay, Wolf Vollprecht and         *\n* Martin Renou                                                             *\n* Copyright (c) QuantStack                                                 *\n*                                                                          *\n* Distributed under the terms of the BSD 3-Clause License.                 *\n*                                                                          *\n* The full license is in the file LICENSE, distributed with this software. *\n****************************************************************************/\n\n#ifndef XFRAME_XCOORDINATE_EXPANDED_HPP\n#define XFRAME_XCOORDINATE_EXPANDED_HPP\n\n#include <type_traits>\n\n#include \"xtl/xiterator_base.hpp\"\n\n#include \"xcoordinate.hpp\"\n\nnamespace xf\n{\n    template <class C, class M>\n    class xmap_expanded_iterator;\n\n    /************************\n     * xcoordinate_expanded *\n     ************************/\n\n    /**\n     * @class xcoordinate_expanded\n     * @brief view of an xcoordinate which expands the xcoordinate dimensions\n     *\n     * The xcoordinate_expanded is used for modeling an expanded view on an existing\n     * xcoordinate, i.e. a superset of this xcoordinate. This is done by holding an\n     * extra coordinate map and keeping a reference to the underlying xcoordinate.\n     *\n     * @tparam C the type of the underlying xcoordinate.\n     * @sa xcoordinate\n     * @sa xcoordinate_chain\n     */\n    template <class C>\n    class xcoordinate_expanded\n    {\n    public:\n\n        using coordinate_type = C;\n        using self_type = xcoordinate_expanded<C>;\n        using label_list = typename coordinate_type::label_list;\n        using key_type = typename coordinate_type::key_type;\n        using axis_type = typename coordinate_type::axis_type;\n        using label_type = typename axis_type::key_type;\n        using map_type = typename coordinate_type::map_type;\n        using mapped_type = typename coordinate_type::mapped_type;\n        using index_type = typename coordinate_type::index_type;\n        using value_type = typename coordinate_type::value_type;\n        using reference = typename coordinate_type::reference;\n        using const_reference = typename coordinate_type::const_reference;\n        using pointer = typename coordinate_type::pointer;\n        using const_pointer = typename coordinate_type::const_pointer;\n        using size_type = typename coordinate_type::size_type;\n        using difference_type = typename coordinate_type::difference_type;\n        using const_iterator = xmap_expanded_iterator<coordinate_type, map_type>;\n        using key_iterator = xtl::xkey_iterator<self_type>;\n\n        xcoordinate_expanded(const coordinate_type& sub_coord, const map_type& new_coord);\n        xcoordinate_expanded(const coordinate_type& sub_coord, map_type&& new_coord);\n\n        bool empty() const;\n        size_type size() const;\n\n        bool contains(const key_type& key) const;\n        bool contains(const key_type& key, const label_type& label) const;\n        const mapped_type& operator[](const key_type& key) const;\n\n        template <class KB, class LB>\n        index_type operator[](const std::pair<KB, LB>& key) const;\n\n        // TODO: check if that's required and why\n        //const map_type& data() const noexcept;\n\n        const_iterator find(const key_type& key) const;\n\n        const_iterator begin() const noexcept;\n        const_iterator end() const noexcept;\n\n        const_iterator cbegin() const noexcept;\n        const_iterator cend() const noexcept;\n\n        key_iterator key_begin() const noexcept;\n        key_iterator key_end() const noexcept;\n\n        bool operator==(const self_type& rhs) const noexcept;\n        bool operator!=(const self_type& rhs) const noexcept;\n\n    private:\n\n        void check_consistency() const;\n\n        const coordinate_type& m_sub_coordinate;\n        map_type m_extra_coordinate;\n    };\n\n    template <class C, class K, class A>\n    bool operator==(const xcoordinate_expanded<C>& lhs, const xcoordinate_base<K, A>& rhs);\n\n    template <class C, class K, class A>\n    bool operator==(const xcoordinate_base<K, A>& lhs, const xcoordinate_expanded<C>& rhs);\n\n    template <class C, class K, class A>\n    bool operator!=(const xcoordinate_expanded<C>& lhs, const xcoordinate_base<K, A>& rhs);\n\n    template <class C, class K, class A>\n    bool operator!=(const xcoordinate_base<K, A>& lhs, const xcoordinate_expanded<C>& rhs);\n\n    template <class OS, class C>\n    std::ostream& operator<<(std::ostream& out, const xcoordinate_expanded<C>& c);\n\n    template <class C>\n    xcoordinate_expanded<C> expand_dims(const C& coordinate, const typename C::map_type& new_coord);\n\n    template <class C>\n    xcoordinate_expanded<C> expand_dims(const C& coordinate, typename C::map_type&& new_coord);\n\n    /**************************\n     * xmap_expanded_iterator *\n     **************************/\n\n    template <class C, class M>\n    class xmap_expanded_iterator\n    {\n    public:\n\n        using self_type = xmap_expanded_iterator<C, M>;\n        using coordinate_type = C;\n        using map_type = M;\n        using map_iterator = typename M::const_iterator;\n        using value_type = typename map_iterator::value_type;\n        using reference = typename map_iterator::reference;\n        using pointer = typename map_iterator::pointer;\n        using difference_type = typename map_iterator::difference_type;\n        using iterator_category = typename map_iterator::iterator_category;\n\n        xmap_expanded_iterator();\n        xmap_expanded_iterator(map_iterator it, const coordinate_type* sub_coordinate, const map_type* extra_coordinate);\n\n        self_type& operator++();\n        self_type& operator--();\n\n        self_type operator++(int);\n        self_type operator--(int);\n\n        reference operator*() const;\n        pointer operator->() const;\n\n        bool operator==(const self_type& rhs) const;\n        bool operator!=(const self_type& rhs) const;\n\n    private:\n\n        map_iterator m_it;\n        const coordinate_type* p_sub_coordinate;\n        const map_type* p_extra_coordinate;\n    };\n\n    /***************************************\n     * xcoordinate_expanded implementation *\n     ***************************************/\n\n    /**\n     * Constructs an xcoordinate_expanded, given the reference to an xcoordinate\n     * and the reference to the additional dimension mapping.\n     * @param sub_coord the reference to the underlying xcoordinate.\n     * @param new_coord the `dimension name <-> axis` mapping of the additional coordinates.\n     */\n    template <class C>\n    inline xcoordinate_expanded<C>::xcoordinate_expanded(const coordinate_type& sub_coord, const map_type& new_coord)\n        : m_sub_coordinate(sub_coord), m_extra_coordinate(new_coord)\n    {\n        check_consistency();\n    }\n\n    /**\n     * Constructs an xcoordinate_expanded, given the reference to an xcoordinate\n     * and the reference to the additional dimension mapping.\n     * @param sub_coord the reference to the underlying xcoordinate.\n     * @param new_coord the `dimension name <-> axis` mapping of the additional coordinates.\n     */\n    template <class C>\n    inline xcoordinate_expanded<C>::xcoordinate_expanded(const coordinate_type& sub_coord, map_type&& new_coord)\n        : m_sub_coordinate(sub_coord), m_extra_coordinate(std::move(new_coord))\n    {\n        check_consistency();\n    }\n\n    /**\n     * Returns true if the coordinates is empty, i.e. it contains no mapping\n     * of axes with dimension names.\n     */\n    template <class C>\n    inline bool xcoordinate_expanded<C>::empty() const\n    {\n        return m_sub_coordinate.empty() && m_extra_coordinate.empty();\n    }\n\n    /**\n     * Returns the number of axes in the coordinates.\n     */\n    template <class C>\n    inline auto xcoordinate_expanded<C>::size() const -> size_type\n    {\n        return m_sub_coordinate.size() + m_extra_coordinate.size();\n    }\n\n    /**\n     * Returns true if the coordinates contains the specified dimension\n     * name.\n     * @param key the dimension name to search for.\n     */\n    template <class C>\n    inline bool xcoordinate_expanded<C>::contains(const key_type& key) const\n    {\n        return (m_extra_coordinate.find(key) != m_extra_coordinate.end()) || m_sub_coordinate.contains(key);\n    }\n\n    /**\n     * Returns true if the coordinates contains the specified dimension\n     * name and if the axis mapped with this name contains the specified\n     * label.\n     * @param key the dimension name to search for.\n     * @param label the label to search for in the mapped axis.\n     */\n    template <class C>\n    inline bool xcoordinate_expanded<C>::contains(const key_type& key, const label_type& label) const\n    {\n        auto iter = find(key);\n        return iter != end() ? (iter->second).contains(label) : false;\n    }\n\n    /**\n     * Returns the axis mapped to the specified dimension name. If this last one is not\n     * found, throws an exception.\n     * @param key the name of the dimension to search for.\n     */\n    template <class C>\n    inline auto xcoordinate_expanded<C>::operator[](const key_type& key) const -> const mapped_type&\n    {\n        auto iter = m_extra_coordinate.find(key);\n        return iter != m_extra_coordinate.end() ? iter->second : m_sub_coordinate[key];\n    }\n\n    /**\n     * Returns the position of the specified labels of the axis mapped to the specified\n     * dimension name. Throws an exception if either the dimension name or the label is\n     * not part of this coordinate.\n     * @param key the pair dimension name - label to search for.\n     */\n    template <class C>\n    template <class KB, class LB>\n    inline auto xcoordinate_expanded<C>::operator[](const std::pair<KB, LB>& key) const -> index_type\n    {\n        auto iter = m_extra_coordinate.find(key.first);\n        return iter != m_extra_coordinate.end() ? (iter->second)[key.second] : m_sub_coordinate[key.first][key.second];\n    }\n\n    /**\n     * Returns a constant iterator to the axis mapped to the specified dimension name.\n     * If no such element is found, past-the-end iterator is returned.\n     * @param key the dimension name to search for.\n     */\n    template <class C>\n    inline auto xcoordinate_expanded<C>::find(const key_type& key) const -> const_iterator\n    {\n        auto iter = m_sub_coordinate.find(key);\n        if(iter == m_sub_coordinate.end())\n        {\n            iter = m_extra_coordinate.find(key);\n        }\n        return const_iterator(iter, &m_sub_coordinate, &m_extra_coordinate);\n    }\n\n    /**\n     * Returns a constant iterator to the first element of the coordinates. Such an element\n     * is a pair dimension name - axis.\n     */\n    template <class C>\n    inline auto xcoordinate_expanded<C>::begin() const noexcept -> const_iterator\n    {\n        return cbegin();\n    }\n\n    /**\n     * Returns a constant iterator to the element following the last element of\n     * the coordinates.\n     */\n    template <class C>\n    inline auto xcoordinate_expanded<C>::end() const noexcept -> const_iterator\n    {\n        return cend();\n    }\n\n    /**\n     * Returns a constant iterator to the first element of the coordinates. Such an element\n     * is a pair dimension name - axis.\n     */\n    template <class C>\n    inline auto xcoordinate_expanded<C>::cbegin() const noexcept -> const_iterator\n    {\n        return const_iterator(m_sub_coordinate.cbegin(), &m_sub_coordinate, &m_extra_coordinate);\n    }\n\n    /**\n     * Returns a constant iterator to the element following the last element of\n     * the coordinates.\n     */\n    template <class C>\n    inline auto xcoordinate_expanded<C>::cend() const noexcept -> const_iterator\n    {\n        return const_iterator(m_extra_coordinate.cend(), &m_sub_coordinate, &m_extra_coordinate);\n    }\n\n    /**\n     * Returns a constant iterator to the first dimension name of the coordinates.\n     */\n    template <class C>\n    inline auto xcoordinate_expanded<C>::key_begin() const noexcept -> key_iterator\n    {\n        return key_iterator(begin());\n    }\n\n    /**\n     * Returns a constant iterator to the element following the last dimension name of\n     * the coordinates.\n     */\n    template <class C>\n    inline auto xcoordinate_expanded<C>::key_end() const noexcept -> key_iterator\n    {\n        return key_iterator(end());\n    }\n\n    template <class C>\n    inline bool xcoordinate_expanded<C>::operator==(const self_type& rhs) const noexcept\n    {\n        return m_sub_coordinate == rhs.m_sub_coordinate\n            && m_extra_coordinate == rhs.m_extra_coordinate;\n    }\n\n    template <class C>\n    inline bool xcoordinate_expanded<C>::operator!=(const self_type& rhs) const noexcept\n    {\n        return !(*this == rhs);\n    }\n\n    template <class C>\n    inline void xcoordinate_expanded<C>::check_consistency() const\n    {\n        for(const auto& a: m_extra_coordinate)\n        {\n            if(m_sub_coordinate.contains(a.first))\n            {\n                throw std::out_of_range(\"coordinate already there\");\n            }\n        }\n    }\n\n    template <class C, class K, class A>\n    inline bool operator==(const xcoordinate_expanded<C>& lhs, const xcoordinate_base<K, A>& rhs)\n    {\n        bool res = lhs.size() == rhs.size();\n        auto iter = lhs.begin();\n        auto end = lhs.end();\n        auto rhs_end = rhs.end();\n        while(res && iter != end)\n        {\n            auto rhs_iter = rhs.find(iter->first);\n            res = (rhs_iter != rhs_end) && (iter->second == rhs_iter->second);\n            ++iter;\n        }\n        return res;\n    }\n\n    template <class C, class K, class A>\n    inline bool operator==(const xcoordinate_base<K, A>& lhs, const xcoordinate_expanded<C>& rhs)\n    {\n        return rhs == lhs;\n    }\n\n    template <class C, class K, class A>\n    inline bool operator!=(const xcoordinate_expanded<C>& lhs, const xcoordinate_base<K, A>& rhs)\n    {\n        return !(lhs == rhs);\n    }\n\n    template <class C, class K, class A>\n    inline bool operator!=(const xcoordinate_base<K, A>& lhs, const xcoordinate_expanded<C>& rhs)\n    {\n        return rhs != lhs;\n    }\n\n    template <class C>\n    inline std::ostream& operator<<(std::ostream& out, const xcoordinate_expanded<C>& c)\n    {\n        for (auto& v : c)\n        {\n            out << v.first << \": \" << v.second << std::endl;\n        }\n        return out;\n    }\n\n    /**\n     * Expand the dimensions of an xcoordinate, given the reference to an xcoordinate\n     * and the reference to the additional dimension mapping.\n     * @param sub_coord the reference to the underlying xcoordinate.\n     * @param new_coord the `dimension name <-> axis` mapping of the additional coordinates.\n     */\n    template <class C>\n    inline xcoordinate_expanded<C> expand_dims(const C& coordinate, const typename C::map_type& new_coord)\n    {\n        return xcoordinate_expanded<C>(coordinate, new_coord);\n    }\n\n    /**\n     * Expand the dimensions of an xcoordinate, given the reference to an xcoordinate\n     * and the reference to the additional dimension mapping.\n     * @param sub_coord the reference to the underlying xcoordinate.\n     * @param new_coord the `dimension name <-> axis` mapping of the additional coordinates.\n     */\n    template <class C>\n    inline xcoordinate_expanded<C> expand_dims(const C& coordinate, typename C::map_type&& new_coord)\n    {\n        return xcoordinate_expanded<C>(coordinate, std::move(new_coord));\n    }\n\n    /*****************************************\n     * xmap_expanded_iterator implementation *\n     *****************************************/\n\n    template <class C, class M>\n    inline xmap_expanded_iterator<C, M>::xmap_expanded_iterator()\n        : m_it(), p_sub_coordinate(nullptr), p_extra_coordinate(nullptr)\n    {\n    }\n\n    template <class C, class M>\n    inline xmap_expanded_iterator<C, M>::xmap_expanded_iterator(map_iterator it, const coordinate_type* sub_coordinate, const map_type* extra_coordinate)\n        : m_it(it), p_sub_coordinate(sub_coordinate), p_extra_coordinate(extra_coordinate)\n    {\n        if (m_it == p_sub_coordinate->cend())\n        {\n            m_it = p_extra_coordinate->cbegin();\n        }\n    }\n\n    template <class C, class M>\n    inline auto xmap_expanded_iterator<C, M>::operator++() -> self_type&\n    {\n        ++m_it;\n        if (m_it == p_sub_coordinate->cend())\n        {\n            m_it = p_extra_coordinate->cbegin();\n        }\n        return *this;\n    }\n\n    template <class C, class M>\n    inline auto xmap_expanded_iterator<C, M>::operator--() -> self_type&\n    {\n        if (m_it == p_extra_coordinate->cbegin())\n        {\n            m_it = p_sub_coordinate->cend();\n        }\n        --m_it;\n        return *this;\n    }\n\n    template <class C, class M>\n    inline auto xmap_expanded_iterator<C, M>::operator++(int) -> self_type\n    {\n        self_type tmp(*this);\n        ++(*this);\n        return tmp;\n    }\n\n    template <class C, class M>\n    inline auto xmap_expanded_iterator<C, M>::operator--(int) -> self_type\n    {\n        self_type tmp(*this);\n        --(*this);\n        return tmp;\n    }\n\n    template <class C, class M>\n    inline auto xmap_expanded_iterator<C, M>::operator*() const -> reference\n    {\n        return *m_it;\n    }\n\n    template <class C, class M>\n    inline auto xmap_expanded_iterator<C, M>::operator->() const -> pointer\n    {\n        return m_it.operator->();\n    }\n\n    template <class C, class M>\n    inline bool xmap_expanded_iterator<C, M>::operator==(const self_type& rhs) const\n    {\n        return m_it == rhs.m_it;\n    }\n\n    template <class C, class M>\n    inline bool xmap_expanded_iterator<C, M>::operator!=(const self_type& rhs) const\n    {\n        return !(*this == rhs);\n    }\n}\n\n#endif\n"
  },
  {
    "path": "include/xframe/xcoordinate_system.hpp",
    "content": "/***************************************************************************\n* Copyright (c) Johan Mabille, Sylvain Corlay, Wolf Vollprecht and         *\n* Martin Renou                                                             *\n* Copyright (c) QuantStack                                                 *\n*                                                                          *\n* Distributed under the terms of the BSD 3-Clause License.                 *\n*                                                                          *\n* The full license is in the file LICENSE, distributed with this software. *\n****************************************************************************/\n\n#ifndef XFRAME_XCOORDINATE_SYSTEM_HPP\n#define XFRAME_XCOORDINATE_SYSTEM_HPP\n\n#include <algorithm>\n#include \"xcoordinate.hpp\"\n#include \"xdimension.hpp\"\n\nnamespace xf\n{\n\n    /**********************\n     * xcoordinate_system *\n     **********************/\n\n    template <class D>\n    class xcoordinate_system\n    {\n    public:\n\n        using derived_type = D;\n        using inner_types = xt::xcontainer_inner_types<D>;\n        using coordinate_type = typename inner_types::coordinate_type;\n        using coordinate_closure_type = typename inner_types::coordinate_closure_type;\n        using dimension_type = typename inner_types::dimension_type;\n        using dimension_list = typename dimension_type::label_list;\n        using size_type = typename coordinate_type::size_type;\n\n        size_type size() const noexcept;\n        size_type dimension() const noexcept;\n        const dimension_list& dimension_labels() const noexcept;\n        const coordinate_type& coordinates() const noexcept;\n        const dimension_type& dimension_mapping() const noexcept;\n\n        template <class Join = XFRAME_DEFAULT_JOIN, class C = coordinate_type>\n        xtrivial_broadcast broadcast_coordinates(C& coords) const;\n        bool broadcast_dimensions(dimension_type& dims, bool trivial_bc = false) const;\n\n    protected:\n\n        xcoordinate_system() = default;\n        template <class C, class DM>\n        xcoordinate_system(C&& coords, DM&& dims);\n        ~xcoordinate_system() = default;\n\n        xcoordinate_system(const xcoordinate_system&) = default;\n        xcoordinate_system& operator=(const xcoordinate_system&) = default;\n\n        xcoordinate_system(xcoordinate_system&&) = default;\n        xcoordinate_system& operator=(xcoordinate_system&&) = default;\n\n        template <class C, class DM>\n        void resize(C&& coords, DM&& dims);\n\n    private:\n\n        coordinate_closure_type m_coordinate;\n        dimension_type m_dimension_mapping;\n    };\n\n    /*************************************\n     * xcoordinate_system implementation *\n     *************************************/\n\n    template <class D>\n    template <class C, class DM>\n    inline xcoordinate_system<D>::xcoordinate_system(C&& coords, DM&& dims)\n        : m_coordinate(std::forward<C>(coords)),\n          m_dimension_mapping(std::forward<DM>(dims))\n    {\n    }\n\n    template <class D>\n    template <class C, class DM>\n    inline void xcoordinate_system<D>::resize(C&& coords, DM&& dims)\n    {\n        m_coordinate = std::forward<C>(coords);\n        m_dimension_mapping = std::forward<DM>(dims);\n    }\n\n    template <class D>\n    inline auto xcoordinate_system<D>::size() const noexcept -> size_type\n    {\n        return std::accumulate(m_coordinate.cbegin(), m_coordinate.cend(), size_type(1),\n            [](size_type val, auto&& entry) { return val * entry.second.size(); });\n    }\n\n    template <class D>\n    inline auto xcoordinate_system<D>::dimension() const noexcept -> size_type\n    {\n        return m_dimension_mapping.size();\n    }\n\n    template <class D>\n    inline auto xcoordinate_system<D>::dimension_labels() const noexcept -> const dimension_list&\n    {\n        return m_dimension_mapping.labels();\n    }\n\n    template <class D>\n    inline auto xcoordinate_system<D>::coordinates() const noexcept -> const coordinate_type&\n    {\n        return m_coordinate;\n    }\n\n    template <class D>\n    inline auto xcoordinate_system<D>::dimension_mapping() const noexcept -> const dimension_type&\n    {\n        return m_dimension_mapping;\n    }\n\n    template <class D>\n    template <class Join, class C>\n    inline xtrivial_broadcast xcoordinate_system<D>::broadcast_coordinates(C& coords) const\n    {\n        return xf::broadcast_coordinates<Join>(coords, this->coordinates());\n    }\n\n    template <class D>\n    inline bool xcoordinate_system<D>::broadcast_dimensions(dimension_type& dims, bool trivial_bc) const\n    {\n        bool ret = true;\n        if (trivial_bc)\n        {\n            dims = this->dimension_mapping();\n        }\n        else\n        {\n            ret = xf::broadcast_dimensions(dims, this->dimension_mapping());\n        }\n        return ret;\n    }\n\n}\n\n#endif\n"
  },
  {
    "path": "include/xframe/xcoordinate_view.hpp",
    "content": "/***************************************************************************\n* Copyright (c) Johan Mabille, Sylvain Corlay, Wolf Vollprecht and         *\n* Martin Renou                                                             *\n* Copyright (c) QuantStack                                                 *\n*                                                                          *\n* Distributed under the terms of the BSD 3-Clause License.                 *\n*                                                                          *\n* The full license is in the file LICENSE, distributed with this software. *\n****************************************************************************/\n\n#ifndef XFRAME_XCOORDINATE_VIEW_HPP\n#define XFRAME_XCOORDINATE_VIEW_HPP\n\n#include \"xaxis_view.hpp\"\n#include \"xcoordinate_base.hpp\"\n\nnamespace xf\n{\n\n    /********************\n     * xcoordinate_view *\n     ********************/\n\n    /**\n     * @class xcoordinate_view\n     * @brief view of an xcoordinate\n     *\n     * The xcoordinate_view is used for modeling a view on an existing xcoordinate,\n     * i.e. a subset of this xcoordinate. This is done by either ignoring some axes,\n     * or by holding views on axes of the underlying xcoordinate.\n     * \n     * @tparam K the type of dimension names.\n     * @tparam L the type list of axes labels.\n     * @tparam S the integer type used to represent positions in axes. Default value\n     *           is \\c std::size_t.\n     * @tparam MT the tag used for choosing the map type which holds the label-\n     *            position pairs in the axes. Possible values are \\c map_tag and\n     *            \\c hash_map_tag. Default value is \\c hash_map_tag.\n     * @sa xaxis_view\n     */\n    template <class K, class L = XFRAME_DEFAULT_LABEL_LIST, class S = std::size_t, class MT = hash_map_tag>\n    class xcoordinate_view : public xcoordinate_base<K, xaxis_view<L, S, MT>>\n    {\n    public:\n\n        using self_type = xcoordinate_view<K, L, S, MT>;\n        using base_type = xcoordinate_base<K, xaxis_view<L, S, MT>>;\n        using label_list = L;\n        using axis_type = typename base_type::axis_type;\n        using map_type = typename base_type::map_type;\n        using key_type = typename base_type::key_type;\n        using mapped_type = typename base_type::mapped_type;\n        using index_type = typename base_type::index_type;\n        using value_type = typename base_type::value_type;\n        using reference = typename base_type::reference;\n        using const_reference = typename base_type::const_reference;\n        using pointer = typename base_type::pointer;\n        using const_pointer = typename base_type::const_pointer;\n        using size_type = typename base_type::size_type;\n        using difference_type = typename base_type::difference_type;\n        using iterator = typename base_type::iterator;\n        using const_iterator = typename base_type::const_iterator;\n        using key_iterator = typename base_type::key_iterator;\n\n        explicit xcoordinate_view(const map_type& axes);\n        explicit xcoordinate_view(map_type&& axes);\n    };\n\n    template <class K, class L, class S, class MT>\n    xcoordinate_view<K, L, S, MT> coordinate_view(const std::map<K, xaxis_view<L, S, MT>>& axes);\n\n    template <class K, class L, class S, class MT>\n    xcoordinate_view<K, L, S, MT> coordinate_view(std::map<K, xaxis_view<L, S, MT>>&& axes);\n\n    /*************************\n     * xcoordinate_view_type *\n     *************************/\n\n    template <class K, class L, class S, class MT>\n    class xcoordinate;\n\n    template <class C>\n    struct xcoordinate_view_type;\n\n    template <class K, class L, class S, class MT>\n    struct xcoordinate_view_type<xcoordinate<K, L, S, MT>>\n    {\n        using type = xcoordinate_view<K, L, S, MT>;\n    };\n\n    template <class C>\n    using xcoordinate_view_type_t = typename xcoordinate_view_type<C>::type;\n\n    /***********************************\n     * xcoordinate_view implementation *\n     ***********************************/\n\n    /**\n     * Constructs an xcoordinate_view with the given mapping of dumension names\n     * to views on axes. The mapping is copied.\n     * @param axes the dimension names to views on axes mapping.\n     */\n    template <class K, class L, class S, class MT>\n    inline xcoordinate_view<K, L, S, MT>::xcoordinate_view(const map_type& axes)\n        : base_type(axes)\n    {\n    }\n\n    /**\n     * Constructs an xcoordinate_view with the given mapping of dumension names\n     * to views on axes. This mapping is moved and therefore it is invalid after\n     * the xcoordinate_view has been constructed.\n     * @param axes the dimension names to views on axes mapping.\n     */\n    template <class K, class L, class S, class MT>\n    inline xcoordinate_view<K, L, S, MT>::xcoordinate_view(map_type&& axes)\n        : base_type(std::move(axes))\n    {\n    }\n\n    /**\n     * Builds and returns an xcoordinate_view from the specified mapping of\n     * dimension names to views on axes. The map is copied.\n     * @param axes the dimension names to views on axes mapping.\n     */\n    template <class K, class L, class S, class MT>\n    inline xcoordinate_view<K, L, S, MT> coordinate_view(const std::map<K, xaxis_view<L, S, MT>>& axes)\n    {\n        return xcoordinate_view<K, L, S, MT>(axes);\n    }\n\n    /**\n     * Builds and returns an xcoordinate_viewfrom the specified mapping of\n     * dimension names to views on axes. The map is moved, therefore it is\n     * invalid after the xcoordinate object has been built.\n     * @param axes the dimension names to views on axes mapping.\n     */\n    template <class K, class L, class S, class MT>\n    inline xcoordinate_view<K, L, S, MT> coordinate_view(std::map<K, xaxis_view<L, S, MT>>&& axes)\n    {\n        return xcoordinate_view<K, L, S, MT>(std::move(axes));\n    }\n}\n\n#endif\n"
  },
  {
    "path": "include/xframe/xdimension.hpp",
    "content": "/***************************************************************************\n* Copyright (c) Johan Mabille, Sylvain Corlay, Wolf Vollprecht and         *\n* Martin Renou                                                             *\n* Copyright (c) QuantStack                                                 *\n*                                                                          *\n* Distributed under the terms of the BSD 3-Clause License.                 *\n*                                                                          *\n* The full license is in the file LICENSE, distributed with this software. *\n****************************************************************************/\n\n#ifndef XFRAME_XDIMENSION_HPP\n#define XFRAME_XDIMENSION_HPP\n\n#include \"xaxis.hpp\"\n\nnamespace xf\n{\n    class xfull_coordinate;\n\n    /**************\n     * xdimension *\n     **************/\n\n    /**\n     * @class xdimension\n     * @brief Class modeling dimensions\n     *\n     * The xdimension class is used for modeling the mapping of dimension names\n     * to their positions in a data tensor. This class is a special axis with\n     * a broadcast method instead of merge and intersect, thus its API is really\n     * close the one of \\c xaxis.\n     *\n     * @tparam L the type of dimension name.\n     * @tparam T the integer type use to represent the positions of the dimensions.\n     *           Default value is \\c std::size_t.\n     * @sa xaxis\n     */\n    template <class L, class T = std::size_t>\n    class xdimension : private xaxis<L, T, map_tag>\n    {\n    public:\n\n        using self_type = xdimension<L, T>;\n        using base_type = xaxis<L, T, map_tag>;\n        using label_list = typename base_type::label_list;\n        using key_type = typename base_type::key_type;\n        using mapped_type = typename base_type::mapped_type;\n        using map_type = typename base_type::map_type;\n        using value_type = typename base_type::value_type;\n        using reference = typename base_type::reference;\n        using const_reference = typename base_type::const_reference;\n        using pointer = typename base_type::pointer;\n        using const_pointer = typename base_type::const_pointer;\n        using size_type = typename base_type::size_type;\n        using difference_type = typename base_type::difference_type;\n        using iterator = typename base_type::iterator;\n        using const_iterator = typename base_type::const_iterator;\n        using reverse_iterator = typename base_type::reverse_iterator;\n        using const_reverse_iterator = typename base_type::const_reverse_iterator;\n\n        xdimension();\n        explicit xdimension(const label_list& labels);\n        explicit xdimension(label_list&& labels);\n        xdimension(std::initializer_list<key_type> init);\n\n        template <class InputIt>\n        xdimension(InputIt first, InputIt last);\n\n        template <class... Args>\n        bool broadcast(const Args&... dims);\n\n        using base_type::labels;\n        using base_type::label;\n        using base_type::empty;\n        using base_type::size;\n        using base_type::contains;\n        using base_type::operator[];\n        using base_type::find;\n        using base_type::begin;\n        using base_type::end;\n        using base_type::cbegin;\n        using base_type::cend;\n        using base_type::rbegin;\n        using base_type::rend;\n        using base_type::crbegin;\n        using base_type::crend;\n\n    private:\n\n        template <class... Args>\n        bool broadcast_impl(const self_type& a, const Args&... dims);\n\n        template <class... Args>\n        bool broadcast_impl(const xfull_coordinate& a, const Args&... dims);\n\n        bool broadcast_impl();\n\n        template <class... Args>\n        bool broadcast_empty(const self_type& a, const Args&... dims);\n\n        template <class... Args>\n        bool broadcast_empty(const xfull_coordinate& a, const Args&... dims);\n\n        bool broadcast_empty();\n    };\n\n    template <class L, class T>\n    bool operator==(const xdimension<L, T>& lhs, const xdimension<L, T>& rhs) noexcept;\n\n    template <class L, class T>\n    bool operator!=(const xdimension<L, T>& lhs, const xdimension<L, T>& rhs) noexcept;\n\n    template <class OS, class L, class T>\n    OS& operator<<(OS& out, const xdimension<L, T>& dim);\n\n    template <class L, class T, class... Args>\n    bool broadcast_dimensions(xdimension<L, T>& output, const Args&... dims);\n\n    /**********************\n     * xdimension builder *\n     **********************/\n\n    template <class T = std::size_t, class L>\n    xdimension<L, T> dimension(std::initializer_list<L> init) noexcept;\n\n    template <class L = fstring, class T = std::size_t>\n    xdimension<L, T> dimension(std::initializer_list<const char*> init) noexcept;\n\n    /*****************************\n     * is_dimension metafunction *\n     *****************************/\n\n    namespace detail\n    {\n        template <class T>\n        struct is_dimension_impl : std::false_type\n        {\n        };\n\n        template <class L, class T>\n        struct is_dimension_impl<xdimension<L, T>> : std::true_type\n        {\n        };\n\n        template <class L>\n        struct is_dimension_list_impl : std::false_type\n        {\n        };\n\n        template <class L>\n        struct is_dimension_list_impl<std::vector<L>>\n            : std::true_type\n        {\n        };\n    }\n\n    template <class T>\n    struct is_dimension : detail::is_dimension_impl<std::decay_t<T>>\n    {\n    };\n\n    template <class T>\n    struct is_dimension_list : detail::is_dimension_list_impl<std::decay_t<T>>\n    {\n    };\n\n    /*****************************\n     * xdimension implementation *\n     *****************************/\n\n    /**\n     * Constructs an empty xdimension object.\n     */\n    template <class L, class T>\n    inline xdimension<L, T>::xdimension()\n        : base_type()\n    {\n    }\n\n    /**\n     * Constructs an xdimension object with the given list of dimension\n     * labels. This list is copied.\n     * @param labels the list of dimension names.\n     */\n    template <class L, class T>\n    inline xdimension<L, T>::xdimension(const label_list& labels)\n        : base_type(labels)\n    {\n    }\n\n    /**\n     * Constructs an xdimension object with the given list of dimension\n     * labels. This list is moved and therefore it is invalid after the\n     * xdimension object has been constructed.\n     * @param labels the list of dimension names.\n     */\n    template <class L, class T>\n    inline xdimension<L, T>::xdimension(label_list&& labels)\n        : base_type(std::move(labels))\n    {\n    }\n\n    /**\n     * Constructs an xdimension object from the given initializer list of\n     * dimension names.\n     * @param init the list of dimension names.\n     */\n    template <class L, class T>\n    inline xdimension<L, T>::xdimension(std::initializer_list<key_type> init)\n        : base_type(init)\n    {\n    }\n\n    /**\n     * Constructs an xdimension object from the content of the range [first, last)\n     * @param first An iterator to the first dimension name.\n     * @param last An iterator the the element following the last dimension name.\n     */\n    template <class L, class T>\n    template <class InputIt>\n    inline xdimension<L, T>::xdimension(InputIt first, InputIt last)\n        : base_type(first, last)\n    {\n    }\n\n\n    /**\n     * Broadcast the specified dimensions to this xdimension object.\n     * @param dims the xdimension objects to broadcast.\n     * @return true if the dimension objects are the same.\n     */\n    template <class L, class T>\n    template <class... Args>\n    inline bool xdimension<L, T>::broadcast(const Args&... dims)\n    {\n        return this->empty() ? broadcast_empty(dims...) : broadcast_impl(dims...);\n    }\n\n    template <class L, class T>\n    template <class... Args>\n    inline bool xdimension<L, T>::broadcast_impl(const self_type& a, const Args&... dims)\n    {\n        XFRAME_TRACE_BROADCAST_DIMENSIONS(*this, a);\n        bool res = base_type::merge_unsorted(true, a.labels());\n        XFRAME_TRACE_DIMENSIONS_RESULT(*this, res);\n        res &= broadcast_impl(dims...);\n        return res;\n    }\n\n    template <class L, class T>\n    template <class... Args>\n    inline bool xdimension<L, T>::broadcast_impl(const xfull_coordinate& /*a*/, const Args&... dims)\n    {\n        return broadcast_impl(dims...);\n    }\n\n    template <class L, class T>\n    inline bool xdimension<L, T>::broadcast_impl()\n    {\n        return true;\n    }\n\n    template <class L, class T>\n    template <class... Args>\n    bool xdimension<L, T>::broadcast_empty(const self_type& a, const Args&... dims)\n    {\n        base_type::set_labels(a.labels());\n        return broadcast_impl(dims...);\n    }\n\n    template <class L, class T>\n    template <class... Args>\n    bool xdimension<L, T>::broadcast_empty(const xfull_coordinate& /*a*/, const Args&... dims)\n    {\n        return broadcast_empty(dims...);\n    }\n\n    template <class L, class T>\n    bool xdimension<L, T>::broadcast_empty()\n    {\n        return true;\n    }\n\n    /**\n     * Returns true if \\c lhs and \\c rhs are equivalent dimension mappings, i.e. they contain\n     * the same dimension name - dimension position pairs.\n     * @param lhs an xdimension object.\n     * @param rhs an xdimension obejct.\n     */\n    template <class L, class T>\n    inline bool operator==(const xdimension<L, T>& lhs, const xdimension<L, T>& rhs) noexcept\n    {\n        return lhs.labels() == rhs.labels();\n    }\n\n    /**\n     * Returns true if \\c lhs and \\c rhs are not equivalent dimension mappings, i.e. they contain\n     * different dimension name - dimension position pairs.\n     * @param lhs an xdimension object.\n     * @param rhs an xdimension obejct.\n     */\n    template <class L, class T>\n    inline bool operator!=(const xdimension<L, T>& lhs, const xdimension<L, T>& rhs) noexcept\n    {\n        return !(lhs == rhs);\n    }\n\n    template <class OS, class L, class T>\n    inline OS& operator<<(OS& out, const xdimension<L, T>& dim)\n    {\n        using iterator = std::ostream_iterator<L, typename OS::char_type, typename OS::traits_type>;\n        out << '(';\n        std::copy(dim.labels().begin(), dim.labels().end(), iterator(out, \", \"));\n        out << ')';\n        return out;\n    }\n\n    template <class L, class T, class... Args>\n    inline bool broadcast_dimensions(xdimension<L, T>& output, const Args&... dims)\n    {\n        return output.broadcast(dims...);\n    }\n\n    /**************************************\n     * xdimension builders implementation *\n     **************************************/\n\n    template <class T, class L>\n    inline xdimension<L, T> dimension(std::initializer_list<L> init) noexcept\n    {\n        return xdimension<L, T>(init);\n    }\n\n    template <class L, class T>\n    inline xdimension<L, T> dimension(std::initializer_list<const char*> init) noexcept\n    {\n        return xdimension<L, T>(init.begin(), init.end());\n    }\n}\n\n#endif\n"
  },
  {
    "path": "include/xframe/xdynamic_variable.hpp",
    "content": "/***************************************************************************\n* Copyright (c) Johan Mabille, Sylvain Corlay, Wolf Vollprecht and         *\n* Martin Renou                                                             *\n* Copyright (c) QuantStack                                                 *\n*                                                                          *\n* Distributed under the terms of the BSD 3-Clause License.                 *\n*                                                                          *\n* The full license is in the file LICENSE, distributed with this software. *\n****************************************************************************/\n\n#ifndef XFRAME_XDYNAMIC_VARIABLE_HPP\n#define XFRAME_XDYNAMIC_VARIABLE_HPP\n\n#include \"xdynamic_variable_impl.hpp\"\n\nnamespace xf\n{\n\n    /*********************\n     * xdynamic_variable *\n     *********************/\n\n    // T should be one of the following options:\n    // - xtl::any\n    // - xtl::variant<T0, T1, ... Tn>\n    // - a simple value type\n    template <class C, class DM, class T = xtl::any>\n    class xdynamic_variable\n    {\n    public:\n\n        using self_type = xdynamic_variable<C, DM, T>;\n        using wrapper_type = xvariable_wrapper<C, DM, T>;\n        template <std::size_t N = dynamic()>\n        using index_type = typename wrapper_type::template index_type<N>;\n        template <std::size_t N = dynamic()>\n        using selector_sequence_type = typename wrapper_type::template selector_sequence_type<N>;\n        template <std::size_t N = dynamic()>\n        using iselector_sequence_type = typename wrapper_type::template iselector_sequence_type<N>;\n        template <std::size_t N = dynamic()>\n        using locator_sequence_type = typename wrapper_type::template locator_sequence_type<N>;\n\n        using value_type = typename wrapper_type::value_type;\n        using reference = typename wrapper_type::reference;\n        using const_reference = typename wrapper_type::const_reference;\n        using pointer = typename wrapper_type::pointer;\n        using const_pointer = typename wrapper_type::const_pointer;\n        using size_type = typename wrapper_type::size_type;\n        using difference_type = typename wrapper_type::difference_type;\n\n        using coordinate_type = typename wrapper_type::coordinate_type;\n        using dimension_type = typename wrapper_type::dimension_type;\n        using dimension_list = typename wrapper_type::dimension_list;\n        using shape_type = typename wrapper_type::shape_type;\n\n        template <class V, class = std::enable_if_t<!std::is_same<std::decay_t<V>, self_type>::value, void>>\n        explicit xdynamic_variable(V&&);\n\n        ~xdynamic_variable();\n\n        xdynamic_variable(const self_type&);\n        xdynamic_variable(self_type&&);\n\n        self_type& operator=(const self_type&);\n        self_type& operator=(self_type&&);\n\n        size_type size() const;\n        size_type dimension() const;\n        const dimension_list& dimension_labels() const;\n        const coordinate_type& coordinates() const;\n        const dimension_type& dimension_mapping() const;\n\n        template <class Join>\n        xtrivial_broadcast broadcast_coordinates(coordinate_type& coords) const;\n\n        bool broadcast_dimensions(dimension_type& dims, bool trivial_bc = false) const;\n\n        const shape_type& shape() const noexcept;\n\n        template <class... Args>\n        reference operator()(Args... args);\n\n        template <class... Args>\n        const_reference operator()(Args... args) const;\n\n        template <std::size_t N = dynamic()>\n        reference element(const index_type<N>& index);\n\n        template <std::size_t N = dynamic()>\n        const_reference element(const index_type<N>& index) const;\n\n        template <std::size_t N = dynamic()>\n        reference element(index_type<N>&& index);\n\n        template <std::size_t N = dynamic()>\n        const_reference element(index_type<N>&& index) const;\n\n        template <class... Args>\n        reference locate(Args&&... args);\n\n        template <class... Args>\n        const_reference locate(Args&&... args) const;\n\n        template <std::size_t N = dynamic()>\n        reference locate_element(const locator_sequence_type<N>& loc);\n\n        template <std::size_t N = dynamic()>\n        const_reference locate_element(const locator_sequence_type<N>& loc) const;\n\n        template <std::size_t N = dynamic()>\n        reference locate_element(locator_sequence_type<N>&& loc);\n\n        template <std::size_t N = dynamic()>\n        const_reference locate_element(locator_sequence_type<N>&& loc) const;\n\n        template <std::size_t N = dynamic()>\n        reference select(const selector_sequence_type<N>& sel);\n\n        template <class Join = XFRAME_DEFAULT_JOIN, std::size_t N = dynamic()>\n        const_reference select(const selector_sequence_type<N>& sel) const;\n\n        template <std::size_t N = dynamic()>\n        reference select(selector_sequence_type<N>&& sel);\n\n        template <class Join = XFRAME_DEFAULT_JOIN, std::size_t N = dynamic()>\n        const_reference select(selector_sequence_type<N>&& sel) const;\n\n        template <std::size_t N = dynamic()>\n        reference iselect(const iselector_sequence_type<N>& sel);\n\n        template <std::size_t N = dynamic()>\n        const_reference iselect(const iselector_sequence_type<N>& sel) const;\n\n        template <std::size_t N = dynamic()>\n        reference iselect(iselector_sequence_type<N>&& sel);\n\n        template <std::size_t N = dynamic()>\n        const_reference iselect(iselector_sequence_type<N>&& sel) const;\n\n        std::ostream& print(std::ostream& out) const;\n\n    private:\n\n        template <class... Args>\n        index_type<> make_index(Args... args);\n\n        wrapper_type* p_wrapper;\n    };\n\n    template <class C, class DM, class T>\n    std::ostream& operator<<(std::ostream& out, const xdynamic_variable<C, DM, T>& v);\n\n    template < class T = xtl::any, class V>\n    auto make_dynamic(V&& variable);\n\n    /************************************\n     * xdynamic_variable implementation *\n     ************************************/\n\n    template <class C, class DM, class T>\n    template <class V, class>\n    inline xdynamic_variable<C, DM, T>::xdynamic_variable(V&& variable)\n        : p_wrapper(new xdynamic_leaf<std::decay_t<V>, T>(std::forward<V>(variable)))\n    {\n    }\n\n    template <class C, class DM, class T>\n    inline xdynamic_variable<C, DM, T>::~xdynamic_variable()\n    {\n        delete p_wrapper;\n        p_wrapper = nullptr;\n    }\n\n    template <class C, class DM, class T>\n    inline xdynamic_variable<C, DM, T>::xdynamic_variable(const self_type& rhs)\n        : p_wrapper(rhs.p_wrapper->clone())\n    {\n    }\n\n    template <class C, class DM, class T>\n    inline xdynamic_variable<C, DM, T>::xdynamic_variable(self_type&& rhs)\n        : p_wrapper(rhs.p_wrapper)\n    {\n        rhs.p_wrapper = nullptr;\n    }\n\n    template <class C, class DM, class T>\n    inline auto xdynamic_variable<C, DM, T>::operator=(const self_type& rhs) -> self_type&\n    {\n        if (this != &rhs)\n        {\n            self_type tmp(rhs);\n            std::swap(p_wrapper, tmp.p_wrapper);\n        }\n        return *this;\n    }\n\n    template <class C, class DM, class T>\n    inline auto xdynamic_variable<C, DM, T>::operator=(self_type&& rhs) -> self_type&\n    {\n        std::swap(p_wrapper, rhs.p_wrapper);\n        return *this;\n    }\n\n    template <class C, class DM, class T>\n    inline auto xdynamic_variable<C, DM, T>::size() const -> size_type\n    {\n        return p_wrapper->size();\n    }\n\n    template <class C, class DM, class T>\n    inline auto xdynamic_variable<C, DM, T>::dimension() const -> size_type\n    {\n        return p_wrapper->dimension();\n    }\n\n    template <class C, class DM, class T>\n    inline auto xdynamic_variable<C, DM, T>::dimension_labels() const -> const dimension_list&\n    {\n        return p_wrapper->dimension_labels();\n    }\n\n    template <class C, class DM, class T>\n    inline auto xdynamic_variable<C, DM, T>::coordinates() const -> const coordinate_type&\n    {\n        return p_wrapper->coordinates();\n    }\n\n    template <class C, class DM, class T>\n    inline auto xdynamic_variable<C, DM, T>::dimension_mapping() const -> const dimension_type&\n    {\n        return p_wrapper->dimension_mapping();\n    }\n\n    template <class C, class DM, class T>\n    template <class Join>\n    inline xtrivial_broadcast xdynamic_variable<C, DM, T>::broadcast_coordinates(coordinate_type& coords) const\n    {\n        return p_wrapper->broadcast_coordinates(coords, Join());\n    }\n\n    template <class C, class DM, class T>\n    inline bool xdynamic_variable<C, DM, T>::broadcast_dimensions(dimension_type& dims, bool trivial_bc) const\n    {\n        return p_wrapper->broadcast_dimensions(dims, trivial_bc);\n    }\n\n    template <class C, class DM, class T>\n    inline auto xdynamic_variable<C, DM, T>::shape() const noexcept -> const shape_type&\n    {\n        return p_wrapper->shape();\n    }\n\n    template <class C, class DM, class T>\n    template <class... Args>\n    inline auto xdynamic_variable<C, DM, T>::operator()(Args... args) -> reference\n    {\n        return element(make_index(args...));\n    }\n\n    template <class C, class DM, class T>\n    template <class... Args>\n    inline auto xdynamic_variable<C, DM, T>::operator()(Args... args) const -> const_reference\n    {\n        return element(make_index(args...));\n    }\n\n    template <class C, class DM, class T>\n    template <std::size_t N>\n    inline auto xdynamic_variable<C, DM, T>::element(const index_type<N>& index) -> reference\n    {\n        return p_wrapper->template element<N>(index);\n    }\n\n    template <class C, class DM, class T>\n    template <std::size_t N>\n    inline auto xdynamic_variable<C, DM, T>::element(const index_type<N>& index) const -> const_reference\n    {\n        return p_wrapper->template element<N>(index);\n    }\n\n    template <class C, class DM, class T>\n    template <std::size_t N>\n    inline auto xdynamic_variable<C, DM, T>::element(index_type<N>&& index) -> reference\n    {\n        return p_wrapper->template element<N>(std::move(index));\n    }\n\n    template <class C, class DM, class T>\n    template <std::size_t N>\n    inline auto xdynamic_variable<C, DM, T>::element(index_type<N>&& index) const -> const_reference\n    {\n        return p_wrapper->template element<N>(std::move(index));\n    }\n\n    template <class C, class DM, class T>\n    template <class... Args>\n    inline auto xdynamic_variable<C, DM, T>::locate(Args&&... args) -> reference\n    {\n        locator_sequence_type<> loc = { std::forward<Args>(args)... };\n        return locate_element(std::move(loc));\n    }\n\n    template <class C, class DM, class T>\n    template <class... Args>\n    inline auto xdynamic_variable<C, DM, T>::locate(Args&&... args) const -> const_reference\n    {\n        locator_sequence_type<> loc = { std::forward<Args>(args)... };\n        return locate_element(std::move(loc));\n    }\n\n    template <class C, class DM, class T>\n    template <std::size_t N>\n    inline auto xdynamic_variable<C, DM, T>::locate_element(const locator_sequence_type<N>& loc) -> reference\n    {\n        return p_wrapper->template locate_element<N>(loc);\n    }\n\n    template <class C, class DM, class T>\n    template <std::size_t N>\n    inline auto xdynamic_variable<C, DM, T>::locate_element(const locator_sequence_type<N>& loc) const -> const_reference\n    {\n        return p_wrapper->template locate_element<N>(loc);\n    }\n\n    template <class C, class DM, class T>\n    template <std::size_t N>\n    inline auto xdynamic_variable<C, DM, T>::locate_element(locator_sequence_type<N>&& loc) -> reference\n    {\n        return p_wrapper->template locate_element<N>(std::move(loc));\n    }\n\n    template <class C, class DM, class T>\n    template <std::size_t N>\n    inline auto xdynamic_variable<C, DM, T>::locate_element(locator_sequence_type<N>&& loc) const -> const_reference\n    {\n        return p_wrapper->template locate_element<N>(std::move(loc));\n    }\n\n    template <class C, class DM, class T>\n    template <std::size_t N>\n    inline auto xdynamic_variable<C, DM, T>::select(const selector_sequence_type<N>& sel) -> reference\n    {\n        return p_wrapper->template select<N>(sel);\n    }\n\n    template <class C, class DM, class T>\n    template <class Join, std::size_t N>\n    inline auto xdynamic_variable<C, DM, T>::select(const selector_sequence_type<N>& sel) const -> const_reference\n    {\n        return p_wrapper->template select<Join, N>(sel);\n    }\n\n    template <class C, class DM, class T>\n    template <std::size_t N>\n    inline auto xdynamic_variable<C, DM, T>::select(selector_sequence_type<N>&& sel) -> reference\n    {\n        return p_wrapper->template select<N>(std::move(sel));\n    }\n\n    template <class C, class DM, class T>\n    template <class Join, std::size_t N>\n    inline auto xdynamic_variable<C, DM, T>::select(selector_sequence_type<N>&& sel) const -> const_reference\n    {\n        return p_wrapper->template select<Join, N>(std::move(sel));\n    }\n\n    template <class C, class DM, class T>\n    template <std::size_t N>\n    inline auto xdynamic_variable<C, DM, T>::iselect(const iselector_sequence_type<N>& sel) -> reference\n    {\n        return p_wrapper->template iselect<N>(sel);\n    }\n\n    template <class C, class DM, class T>\n    template <std::size_t N>\n    inline auto xdynamic_variable<C, DM, T>::iselect(const iselector_sequence_type<N>& sel) const -> const_reference\n    {\n        return p_wrapper->template iselect<N>(sel);\n    }\n\n    template <class C, class DM, class T>\n    template <std::size_t N>\n    inline auto xdynamic_variable<C, DM, T>::iselect(iselector_sequence_type<N>&& sel) -> reference\n    {\n        return p_wrapper->template iselect<N>(std::move(sel));\n    }\n\n    template <class C, class DM, class T>\n    template <std::size_t N>\n    inline auto xdynamic_variable<C, DM, T>::iselect(iselector_sequence_type<N>&& sel) const -> const_reference\n    {\n        return p_wrapper->template iselect<N>(std::move(sel));\n    }\n\n    template <class C, class DM, class T>\n    inline std::ostream& xdynamic_variable<C, DM, T>::print(std::ostream& out) const\n    {\n        return p_wrapper->print(out);\n    }\n\n    template <class C, class DM, class T>\n    template <class... Args>\n    inline auto xdynamic_variable<C, DM, T>::make_index(Args... args) -> index_type<>\n    {\n        using size_type = typename index_type<>::value_type;\n        index_type<> res = { static_cast<size_type>(args)... };\n        return res;\n    }\n\n    template <class C, class DM, class T>\n    inline std::ostream& operator<<(std::ostream& out, const xdynamic_variable<C, DM, T>& v)\n    {\n        return v.print(out);\n    }\n\n    template <class T, class V>\n    inline auto make_dynamic(V&& variable)\n    {\n        using coordinate_type = typename std::decay_t<V>::coordinate_type;\n        using dimension_type = typename std::decay_t<V>::dimension_type;\n        return xdynamic_variable<coordinate_type, dimension_type, T>(std::forward<V>(variable));\n    }\n}\n\n#endif\n"
  },
  {
    "path": "include/xframe/xdynamic_variable_impl.hpp",
    "content": "/***************************************************************************\n* Copyright (c) Johan Mabille, Sylvain Corlay, Wolf Vollprecht and         *\n* Martin Renou                                                             *\n* Copyright (c) QuantStack                                                 *\n*                                                                          *\n* Distributed under the terms of the BSD 3-Clause License.                 *\n*                                                                          *\n* The full license is in the file LICENSE, distributed with this software. *\n****************************************************************************/\n\n#ifndef XFRAME_XDYNAMIC_VARIABLE_IMPL_HPP\n#define XFRAME_XDYNAMIC_VARIABLE_IMPL_HPP\n\n#include \"xtl/xany.hpp\"\n#include \"xtl/xhierarchy_generator.hpp\"\n#include \"xtl/xvariant.hpp\"\n\n#include \"xvariable.hpp\"\n\nnamespace xf\n{\n    /********************************\n     * traits for dynamic variables *\n     ********************************/\n\n    namespace detail\n    {\n        template <class T>\n        struct xdynamic_traits_impl\n        {\n            using value_type = xtl::xoptional<T, bool>;\n            using reference = xtl::xoptional<T&, bool&>;\n            using const_reference = xtl::xoptional<const T&, const bool&>;\n            using pointer = xtl::xclosure_pointer<reference>;\n            using const_pointer = xtl::xclosure_pointer<const_reference>;\n        };\n\n        template <class T>\n        struct xdynamic_traits_impl<xtl::xoptional<T, bool>>\n            : xdynamic_traits_impl<T>\n        {\n        };\n\n        template <>\n        struct xdynamic_traits_impl<xtl::any>\n        {\n            using value_type = xtl::any;\n            using reference = xtl::any;\n            using const_reference = xtl::any;\n            using pointer = xtl::xclosure_pointer<reference>;\n            using const_pointer = xtl::xclosure_pointer<const_reference>;\n        };\n\n        template <class... T>\n        struct xdynamic_traits_impl<xtl::variant<T...>>\n        {\n            using value_type = xtl::variant<xtl::xoptional<T, bool>...>;\n            using reference = xtl::variant<xtl::xoptional<T&, bool&>...>;\n            using const_reference = xtl::variant<xtl::xoptional<const T&, const bool&>...>;\n            using pointer = xtl::xclosure_pointer<reference>;\n            using const_pointer = xtl::xclosure_pointer<const_reference>;\n        };\n    }\n\n    template <class C, class DM, class T, std::size_t N>\n    struct xdynamic_traits : xselector_traits<C, DM, N>\n    {\n        using return_type = T;\n        using traits_type = detail::xdynamic_traits_impl<T>;\n        using value_type = typename traits_type::value_type;\n        using reference = typename traits_type::reference;\n        using const_reference = typename traits_type::const_reference;\n        using pointer = typename traits_type::pointer;\n        using const_pointer = typename traits_type::const_pointer;\n    };\n\n    namespace detail\n    {\n        template <class C, class DM, class T, class L>\n        struct xdynamic_traits_list_impl;\n\n        template <class C, class DM, class T, std::size_t... I>\n        struct xdynamic_traits_list_impl<C, DM, T, std::index_sequence<I...>>\n        {\n            using type = xtl::mpl::vector<xdynamic_traits<C, DM, T, I + 1>..., xdynamic_traits<C, DM, T, dynamic()>>;\n        };\n    }\n\n    template <class C, class DM, class T, std::size_t N>\n    using xdynamic_traits_list = typename detail::xdynamic_traits_list_impl<C, DM, T, std::make_index_sequence<N>>::type;\n\n    /*****************\n     * xdynamic_base *\n     *****************/\n\n    template <class T>\n    class xdynamic_base\n    {\n    public:\n\n        using index_type = typename T::index_type;\n        using selector_sequence_type = typename T::selector_sequence_type;\n        using iselector_sequence_type = typename T::iselector_sequence_type;\n        using locator_sequence_type = typename T::locator_sequence_type;\n\n        using value_type = typename T::value_type;\n        using reference = typename T::reference;\n        using const_reference = typename T::const_reference;\n\n        virtual ~xdynamic_base() {}\n\n        virtual reference do_element(const index_type&) = 0;\n        virtual const_reference do_element(const index_type&) const = 0;\n        virtual reference do_element(index_type&&) = 0;\n        virtual const_reference do_element(index_type&&) const = 0;\n\n        virtual reference do_locate_element(const locator_sequence_type&) = 0;\n        virtual const_reference do_locate_element(const locator_sequence_type&) const = 0;\n        virtual reference do_locate_element(locator_sequence_type&&) = 0;\n        virtual const_reference do_locate_element(locator_sequence_type&&) const = 0;\n\n        virtual reference do_select(const selector_sequence_type&) = 0;\n        virtual const_reference do_select(const selector_sequence_type&, join::outer) const = 0;\n        virtual const_reference do_select(const selector_sequence_type&, join::inner) const = 0;\n        virtual reference do_select(selector_sequence_type&&) = 0;\n        virtual const_reference do_select(selector_sequence_type&&, join::outer) const = 0;\n        virtual const_reference do_select(selector_sequence_type&&, join::inner) const = 0;\n\n        virtual reference do_iselect(const iselector_sequence_type&) = 0;\n        virtual const_reference do_iselect(const iselector_sequence_type&) const = 0;\n        virtual reference do_iselect(iselector_sequence_type&&) = 0;\n        virtual const_reference do_iselect(iselector_sequence_type&&) const = 0;\n    };\n\n    /*********************\n     * xvariable_wrapper *\n     *********************/\n\n    template <class C, class DM, class T>\n    class xvariable_wrapper : public xtl::xscatter_hierarchy_generator<xdynamic_traits_list<C, DM, T, XFRAME_STATIC_DIMENSION_LIMIT>, xdynamic_base>\n    {\n    public:\n\n        using self_type = xvariable_wrapper<C, DM, T>;\n\n        template <std::size_t N = dynamic()>\n        using traits_type = xdynamic_traits<C, DM, T, N>;\n        template <std::size_t N = dynamic()>\n        using index_type = typename traits_type<N>::index_type;\n        template <std::size_t N = dynamic()>\n        using selector_sequence_type = typename traits_type<N>::selector_sequence_type;\n        template <std::size_t N = dynamic()>\n        using iselector_sequence_type = typename traits_type<N>::iselector_sequence_type;\n        template <std::size_t N = dynamic()>\n        using locator_sequence_type = typename traits_type<N>::locator_sequence_type;\n\n        using coordinate_type = C;\n        using dimension_type = DM;\n        using dimension_list = typename dimension_type::label_list;\n\n        using value_type = typename traits_type<>::value_type;\n        using reference = typename traits_type<>::reference;\n        using const_reference = typename traits_type<>::const_reference;\n        using pointer = typename traits_type<>::pointer;\n        using const_pointer = typename traits_type<>::const_pointer;\n        using size_type = typename coordinate_type::size_type;\n        using difference_type = typename coordinate_type::difference_type;\n\n        using shape_type = xt::svector<size_type>;\n\n        virtual ~xvariable_wrapper() {}\n\n        xvariable_wrapper(self_type&&) = delete;\n        xvariable_wrapper& operator=(const self_type&) = delete;\n        xvariable_wrapper& operator=(self_type&&) = delete;\n\n        virtual self_type* clone() const = 0;\n\n        virtual size_type size() const = 0;\n        virtual size_type dimension() const = 0;\n        virtual const dimension_list& dimension_labels() const = 0;\n        virtual const coordinate_type& coordinates() const = 0;\n        virtual const dimension_type& dimension_mapping() const = 0;\n\n        virtual xtrivial_broadcast broadcast_coordinates(coordinate_type& coords, join::outer) const = 0;\n        virtual xtrivial_broadcast broadcast_coordinates(coordinate_type& coords, join::inner) const = 0;\n        virtual bool broadcast_dimensions(dimension_type& dims, bool trivial_bc) const = 0;\n\n        virtual const shape_type& shape() const noexcept = 0;\n\n        template <std::size_t N>\n        reference element(const index_type<N>& index);\n\n        template <std::size_t N>\n        const_reference element(const index_type<N>& index) const;\n\n        template <std::size_t N>\n        reference element(index_type<N>&& index);\n\n        template <std::size_t N>\n        const_reference element(index_type<N>&& index) const;\n\n        template <std::size_t N>\n        reference locate_element(const locator_sequence_type<N>& loc);\n\n        template <std::size_t N>\n        const_reference locate_element(const locator_sequence_type<N>& loc) const;\n\n        template <std::size_t N>\n        reference locate_element(locator_sequence_type<N>&& loc);\n\n        template <std::size_t N>\n        const_reference locate_element(locator_sequence_type<N>&& loc) const;\n\n        template <std::size_t N>\n        reference select(const selector_sequence_type<N>& sel);\n\n        template <class Join, std::size_t N>\n        const_reference select(const selector_sequence_type<N>& sel) const;\n\n        template <std::size_t N>\n        reference select(selector_sequence_type<N>&& sel);\n\n        template <class Join, std::size_t N>\n        const_reference select(selector_sequence_type<N>&& sel) const;\n\n        template <std::size_t N>\n        reference iselect(const iselector_sequence_type<N>& sel);\n\n        template <std::size_t N>\n        const_reference iselect(const iselector_sequence_type<N>& sel) const;\n\n        template <std::size_t N>\n        reference iselect(iselector_sequence_type<N>&& sel);\n\n        template <std::size_t N>\n        const_reference iselect(iselector_sequence_type<N>&& sel) const;\n\n        virtual std::ostream& print(std::ostream& out) const = 0;\n\n    protected:\n\n        xvariable_wrapper() = default;\n        xvariable_wrapper(const self_type&) = default;\n    };\n\n    /**************************\n     * xvariable_wrapper_impl *\n     **************************/\n\n    template <class V, class T>\n    class xvariable_wrapper_impl : public xvariable_wrapper<typename V::coordinate_type, typename V::dimension_type, T>\n    {\n    public:\n\n        using variable_type = V;\n        using self_type = xvariable_wrapper_impl<variable_type, T>;\n        using base_type = xvariable_wrapper<typename V::coordinate_type, typename V::dimension_type, T>;\n        using size_type = typename base_type::size_type;\n        using coordinate_type = typename base_type::coordinate_type;\n        using dimension_type = typename base_type::dimension_type;\n        using dimension_list = typename base_type::dimension_list;\n        using shape_type = typename base_type::shape_type;\n\n        virtual ~xvariable_wrapper_impl() {}\n\n        xvariable_wrapper_impl(self_type&&) = delete;\n        xvariable_wrapper_impl& operator=(const self_type&) = delete;\n        xvariable_wrapper_impl& operator=(self_type&&) = delete;\n\n        size_type size() const override;\n        size_type dimension() const override;\n        const dimension_list& dimension_labels() const override;\n        const coordinate_type& coordinates() const override;\n        const dimension_type& dimension_mapping() const override;\n\n        xtrivial_broadcast broadcast_coordinates(coordinate_type& coords, join::outer) const override;\n        xtrivial_broadcast broadcast_coordinates(coordinate_type& coords, join::inner) const override;\n        bool broadcast_dimensions(dimension_type& dims, bool trivial_bc) const override;\n\n        const shape_type& shape() const noexcept override;\n\n        std::ostream& print(std::ostream& out) const override;\n\n    protected:\n\n        xvariable_wrapper_impl(const variable_type& variable);\n        xvariable_wrapper_impl(variable_type&& variable);\n        xvariable_wrapper_impl(const self_type& rhs) = default;\n\n        variable_type& get_variable();\n        const variable_type& get_variable() const;\n\n    private:\n\n        variable_type m_variable;\n    };\n\n    /***************************\n     * xdynamic_implementation *\n     ***************************/\n\n    template <class T, class B>\n    class xdynamic_implementation : public B\n    {\n    public:\n\n        using self_type = xdynamic_implementation<T, B>;\n        using base_type = B;\n        using index_type = typename T::index_type;\n        using selector_sequence_type = typename T::selector_sequence_type;\n        using iselector_sequence_type = typename T::iselector_sequence_type;\n        using locator_sequence_type = typename T::locator_sequence_type;\n\n        using value_type = typename T::value_type;\n        using reference = typename T::reference;\n        using const_reference = typename T::const_reference;\n\n        static constexpr std::size_t static_dimension = T::static_dimension;\n\n        virtual ~xdynamic_implementation() {}\n\n        xdynamic_implementation(self_type&&) = delete;\n        xdynamic_implementation& operator=(const self_type&) = delete;\n        xdynamic_implementation& operator=(self_type&&) = delete;\n\n        reference do_element(const index_type&) override;\n        const_reference do_element(const index_type&) const override;\n        reference do_element(index_type&&) override;\n        const_reference do_element(index_type&&) const override;\n\n        reference do_locate_element(const locator_sequence_type&) override;\n        const_reference do_locate_element(const locator_sequence_type&) const override;\n        reference do_locate_element(locator_sequence_type&&) override;\n        const_reference do_locate_element(locator_sequence_type&&) const override;\n\n        reference do_select(const selector_sequence_type&) override;\n        const_reference do_select(const selector_sequence_type&, join::outer) const override;\n        const_reference do_select(const selector_sequence_type&, join::inner) const override;\n        reference do_select(selector_sequence_type&&) override;\n        const_reference do_select(selector_sequence_type&&, join::outer) const override;\n        const_reference do_select(selector_sequence_type&&, join::inner) const override;\n\n        reference do_iselect(const iselector_sequence_type&) override;\n        const_reference do_iselect(const iselector_sequence_type&) const override;\n        reference do_iselect(iselector_sequence_type&&) override;\n        const_reference do_iselect(iselector_sequence_type&&) const override;\n\n    protected:\n\n        template <class V>\n        xdynamic_implementation(V&& variable);\n\n        xdynamic_implementation(const self_type&) = default;\n    };\n\n    /*****************\n     * xdynamic_leaf *\n     *****************/\n\n    namespace detail\n    {\n        template <class V, class T>\n        using xdynamic_linear_hierarchy = xtl::xlinear_hierarchy_generator<\n            xdynamic_traits_list<typename V::coordinate_type,\n            typename V::dimension_type,\n            T,\n            XFRAME_STATIC_DIMENSION_LIMIT>,\n            xdynamic_implementation,\n            xvariable_wrapper_impl<V, T>>;\n    }\n\n    template <class V, class T>\n    class xdynamic_leaf : public detail::xdynamic_linear_hierarchy<V, T>\n    {\n    public:\n\n        using self_type = xdynamic_leaf<V, T>;\n        using base_type = detail::xdynamic_linear_hierarchy<V, T>;\n\n        xdynamic_leaf(const V&);\n        xdynamic_leaf(V&&);\n        virtual ~xdynamic_leaf() {}\n\n        self_type* clone() const override;\n\n        xdynamic_leaf(self_type&&) = delete;\n        xdynamic_leaf& operator=(const self_type&) = delete;\n        xdynamic_leaf& operator=(self_type&&) = delete;\n\n    private:\n\n        xdynamic_leaf(const self_type&) = default;\n\n    };\n\n    /************************************\n     * xvariable_wrapper implementation *\n     ************************************/\n\n    template <class C, class DM, class T>\n    template <std::size_t N>\n    inline auto xvariable_wrapper<C, DM, T>::element(const index_type<N>& index) -> reference\n    {\n        xdynamic_base<xdynamic_traits<C, DM, T, N>>& base = *this;\n        return base.do_element(index);\n    }\n\n    template <class C, class DM, class T>\n    template <std::size_t N>\n    inline auto xvariable_wrapper<C, DM, T>::element(const index_type<N>& index) const -> const_reference\n    {\n        const xdynamic_base<xdynamic_traits<C, DM, T, N>>& base = *this;\n        return base.do_element(index);\n    }\n\n    template <class C, class DM, class T>\n    template <std::size_t N>\n    inline auto xvariable_wrapper<C, DM, T>::element(index_type<N>&& index) -> reference\n    {\n        xdynamic_base<xdynamic_traits<C, DM, T, N>>& base = *this;\n        return base.do_element(std::move(index));\n    }\n\n    template <class C, class DM, class T>\n    template <std::size_t N>\n    inline auto xvariable_wrapper<C, DM, T>::element(index_type<N>&& index) const -> const_reference\n    {\n        const xdynamic_base<xdynamic_traits<C, DM, T, N>>& base = *this;\n        return base.do_element(std::move(index));\n    }\n\n    template <class C, class DM, class T>\n    template <std::size_t N>\n    inline auto xvariable_wrapper<C, DM, T>::locate_element(const locator_sequence_type<N>& loc) -> reference\n    {\n        xdynamic_base<xdynamic_traits<C, DM, T, N>>& base = *this;\n        return base.do_locate_element(loc);\n    }\n\n    template <class C, class DM, class T>\n    template <std::size_t N>\n    inline auto xvariable_wrapper<C, DM, T>::locate_element(const locator_sequence_type<N>& loc) const -> const_reference\n    {\n        const xdynamic_base<xdynamic_traits<C, DM, T, N>>& base = *this;\n        return base.do_locate_element(loc);\n    }\n\n    template <class C, class DM, class T>\n    template <std::size_t N>\n    inline auto xvariable_wrapper<C, DM, T>::locate_element(locator_sequence_type<N>&& loc) -> reference\n    {\n        xdynamic_base<xdynamic_traits<C, DM, T, N>>& base = *this;\n        return base.do_locate_element(std::move(loc));\n    }\n\n    template <class C, class DM, class T>\n    template <std::size_t N>\n    inline auto xvariable_wrapper<C, DM, T>::locate_element(locator_sequence_type<N>&& loc) const -> const_reference\n    {\n        const xdynamic_base<xdynamic_traits<C, DM, T, N>>& base = *this;\n        return base.do_locate_element(std::move(loc));\n    }\n\n    template <class C, class DM, class T>\n    template <std::size_t N>\n    inline auto xvariable_wrapper<C, DM, T>::select(const selector_sequence_type<N>& sel) -> reference\n    {\n        xdynamic_base<xdynamic_traits<C, DM, T, N>>& base = *this;\n        return base.do_select(sel);\n    }\n\n    template <class C, class DM, class T>\n    template <class Join, std::size_t N>\n    inline auto xvariable_wrapper<C, DM, T>::select(const selector_sequence_type<N>& sel) const -> const_reference\n    {\n        const xdynamic_base<xdynamic_traits<C, DM, T, N>>& base = *this;\n        return base.do_select(sel, Join());\n    }\n\n    template <class C, class DM, class T>\n    template <std::size_t N>\n    inline auto xvariable_wrapper<C, DM, T>::select(selector_sequence_type<N>&& sel) -> reference\n    {\n        xdynamic_base<xdynamic_traits<C, DM, T, N>>& base = *this;\n        return base.do_select(std::move(sel));\n    }\n\n    template <class C, class DM, class T>\n    template <class Join, std::size_t N>\n    inline auto xvariable_wrapper<C, DM, T>::select(selector_sequence_type<N>&& sel) const -> const_reference\n    {\n        const xdynamic_base<xdynamic_traits<C, DM, T, N>>& base = *this;\n        return base.do_select(std::move(sel), Join());\n    }\n\n    template <class C, class DM, class T>\n    template <std::size_t N>\n    inline auto xvariable_wrapper<C, DM, T>::iselect(const iselector_sequence_type<N>& sel) -> reference\n    {\n        xdynamic_base<xdynamic_traits<C, DM, T, N>>& base = *this;\n        return base.do_iselect(sel);\n    }\n\n    template <class C, class DM, class T>\n    template <std::size_t N>\n    inline auto xvariable_wrapper<C, DM, T>::iselect(const iselector_sequence_type<N>& sel) const -> const_reference\n    {\n        const xdynamic_base<xdynamic_traits<C, DM, T, N>>& base = *this;\n        return base.do_iselect(sel);\n    }\n\n    template <class C, class DM, class T>\n    template <std::size_t N>\n    inline auto xvariable_wrapper<C, DM, T>::iselect(iselector_sequence_type<N>&& sel) -> reference\n    {\n        xdynamic_base<xdynamic_traits<C, DM, T, N>>& base = *this;\n        return base.do_iselect(std::move(sel));\n    }\n\n    template <class C, class DM, class T>\n    template <std::size_t N>\n    inline auto xvariable_wrapper<C, DM, T>::iselect(iselector_sequence_type<N>&& sel) const -> const_reference\n    {\n        const xdynamic_base<xdynamic_traits<C, DM, T, N>>& base = *this;\n        return base.do_iselect(std::move(sel));\n    }\n\n    /*****************************************\n     * xvariable_wrapper_impl implementation *\n     *****************************************/\n\n    template <class V, class T>\n    inline xvariable_wrapper_impl<V, T>::xvariable_wrapper_impl(const variable_type& variable)\n        : m_variable(variable)\n    {\n    }\n\n    template <class V, class T>\n    inline xvariable_wrapper_impl<V, T>::xvariable_wrapper_impl(variable_type&& variable)\n        : m_variable(std::move(variable))\n    {\n    }\n\n    template <class V, class T>\n    inline auto xvariable_wrapper_impl<V, T>::get_variable() -> variable_type&\n    {\n        return m_variable;\n    }\n\n    template <class V, class T>\n    inline auto xvariable_wrapper_impl<V, T>::get_variable() const -> const variable_type&\n    {\n        return m_variable;\n    }\n\n    template <class V, class T>\n    auto xvariable_wrapper_impl<V, T>::size() const -> size_type\n    {\n        return m_variable.size();\n    }\n\n    template <class V, class T>\n    auto xvariable_wrapper_impl<V, T>::dimension() const -> size_type\n    {\n        return m_variable.dimension();\n    }\n\n    template <class V, class T>\n    auto xvariable_wrapper_impl<V, T>::dimension_labels() const -> const dimension_list&\n    {\n        return m_variable.dimension_labels();\n    }\n\n    template <class V, class T>\n    auto xvariable_wrapper_impl<V, T>::coordinates() const -> const coordinate_type&\n    {\n        return m_variable.coordinates();\n    }\n\n    template <class V, class T>\n    auto xvariable_wrapper_impl<V, T>::dimension_mapping() const -> const dimension_type&\n    {\n        return m_variable.dimension_mapping();\n    }\n\n    template <class V, class T>\n    xtrivial_broadcast xvariable_wrapper_impl<V, T>::broadcast_coordinates(coordinate_type& coords, join::outer) const\n    {\n        return m_variable.template broadcast_coordinates<join::outer>(coords);\n    }\n\n    template <class V, class T>\n    xtrivial_broadcast xvariable_wrapper_impl<V, T>::broadcast_coordinates(coordinate_type& coords, join::inner) const\n    {\n        return m_variable.template broadcast_coordinates<join::inner>(coords);\n    }\n\n    template <class V, class T>\n    bool xvariable_wrapper_impl<V, T>::broadcast_dimensions(dimension_type& dims, bool trivial_bc) const\n    {\n        return m_variable.broadcast_dimensions(dims, trivial_bc);\n    }\n\n    template <class V, class T>\n    auto xvariable_wrapper_impl<V, T>::shape() const noexcept -> const shape_type&\n    {\n        return xtl::forward_sequence<shape_type, decltype(m_variable.shape())>(m_variable.shape());\n    }\n\n    template <class V, class T>\n    std::ostream& xvariable_wrapper_impl<V, T>::print(std::ostream& out) const\n    {\n        return out << m_variable;\n    }\n\n   /***************************\n    * xdynamic_implementation *\n    ***************************/\n\n    template <class T, class B>\n    template <class V>\n    inline xdynamic_implementation<T, B>::xdynamic_implementation(V&& variable)\n        : base_type(std::forward<V>(variable))\n    {\n    }\n\n    template <class T, class B>\n    auto xdynamic_implementation<T, B>::do_element(const index_type& index) -> reference\n    {\n        return this->get_variable().template element<static_dimension>(index);\n    }\n\n    template <class T, class B>\n    auto xdynamic_implementation<T, B>::do_element(const index_type& index) const -> const_reference\n    {\n        return this->get_variable().template element<static_dimension>(index);\n    }\n\n    template <class T, class B>\n    auto xdynamic_implementation<T, B>::do_element(index_type&& index) -> reference\n    {\n        return this->get_variable().template element<static_dimension>(std::move(index));\n    }\n\n    template <class T, class B>\n    auto xdynamic_implementation<T, B>::do_element(index_type&& index) const -> const_reference\n    {\n        return this->get_variable().template element<static_dimension>(std::move(index));\n    }\n\n    template <class T, class B>\n    auto xdynamic_implementation<T, B>::do_locate_element(const locator_sequence_type& loc) -> reference\n    {\n        return this->get_variable().template locate_element<static_dimension>(loc);\n    }\n\n    template <class T, class B>\n    auto xdynamic_implementation<T, B>::do_locate_element(const locator_sequence_type& loc) const -> const_reference\n    {\n        return this->get_variable().template locate_element<static_dimension>(loc);\n    }\n\n    template <class T, class B>\n    auto xdynamic_implementation<T, B>::do_locate_element(locator_sequence_type&& loc) -> reference\n    {\n        return this->get_variable().template locate_element<static_dimension>(std::move(loc));\n    }\n\n    template <class T, class B>\n    auto xdynamic_implementation<T, B>::do_locate_element(locator_sequence_type&& loc) const -> const_reference\n    {\n        return this->get_variable().template locate_element<static_dimension>(std::move(loc));\n    }\n\n    template <class T, class B>\n    auto xdynamic_implementation<T, B>::do_select(const selector_sequence_type& sel) -> reference\n    {\n        return this->get_variable().template select<static_dimension>(sel);\n    }\n\n    template <class T, class B>\n    auto xdynamic_implementation<T, B>::do_select(const selector_sequence_type& sel, join::outer) const -> const_reference\n    {\n        return this->get_variable().template select<join::outer, static_dimension>(sel);\n    }\n\n    template <class T, class B>\n    auto xdynamic_implementation<T, B>::do_select(const selector_sequence_type& sel, join::inner) const -> const_reference\n    {\n        return this->get_variable().template select<join::inner, static_dimension>(sel);\n    }\n\n    template <class T, class B>\n    auto xdynamic_implementation<T, B>::do_select(selector_sequence_type&& sel) -> reference\n    {\n        return this->get_variable().template select<static_dimension>(std::move(sel));\n    }\n\n    template <class T, class B>\n    auto xdynamic_implementation<T, B>::do_select(selector_sequence_type&& sel, join::outer) const -> const_reference\n    {\n        return this->get_variable().template select<join::outer, static_dimension>(std::move(sel));\n    }\n\n    template <class T, class B>\n    auto xdynamic_implementation<T, B>::do_select(selector_sequence_type&& sel, join::inner) const -> const_reference\n    {\n        return this->get_variable().template select<join::inner, static_dimension>(std::move(sel));\n    }\n\n    template <class T, class B>\n    auto xdynamic_implementation<T, B>::do_iselect(const iselector_sequence_type& sel) -> reference\n    {\n        return this->get_variable().template iselect<static_dimension>(sel);\n    }\n\n    template <class T, class B>\n    auto xdynamic_implementation<T, B>::do_iselect(const iselector_sequence_type& sel) const -> const_reference\n    {\n        return this->get_variable().template iselect<static_dimension>(sel);\n    }\n\n    template <class T, class B>\n    auto xdynamic_implementation<T, B>::do_iselect(iselector_sequence_type&& sel) -> reference\n    {\n        return this->get_variable().template iselect<static_dimension>(std::move(sel));\n    }\n\n    template <class T, class B>\n    auto xdynamic_implementation<T, B>::do_iselect(iselector_sequence_type&& sel) const -> const_reference\n    {\n        return this->get_variable().template iselect<static_dimension>(std::move(sel));\n    }\n\n    /********************************\n     * xdynamic_leaf implementation *\n     ********************************/\n\n    template <class V, class T>\n    inline xdynamic_leaf<V, T>::xdynamic_leaf(const V& variable)\n        : base_type(variable)\n    {\n    }\n\n    template <class V, class T>\n    inline xdynamic_leaf<V, T>::xdynamic_leaf(V&& variable)\n        : base_type(std::move(variable))\n    {\n    }\n\n    template <class V, class T>\n    inline auto xdynamic_leaf<V, T>::clone() const -> self_type*\n    {\n        return new self_type(*this);\n    }\n}\n\n#endif\n"
  },
  {
    "path": "include/xframe/xexpand_dims_view.hpp",
    "content": "/***************************************************************************\n* Copyright (c) Johan Mabille, Sylvain Corlay, Wolf Vollprecht and         *\n* Martin Renou                                                             *\n* Copyright (c) QuantStack                                                 *\n*                                                                          *\n* Distributed under the terms of the BSD 3-Clause License.                 *\n*                                                                          *\n* The full license is in the file LICENSE, distributed with this software. *\n****************************************************************************/\n\n#ifndef XFRAME_XEXPAND_DIMS_VIEW_HPP\n#define XFRAME_XEXPAND_DIMS_VIEW_HPP\n\n#include <vector>\n#include <utility>\n#include <string>\n#include <stdexcept>\n\n#include \"xtensor/xexpression.hpp\"\n#include \"xtensor/xstrided_view.hpp\"\n\n#include \"xaxis.hpp\"\n#include \"xcoordinate_expanded.hpp\"\n#include \"xvariable_base.hpp\"\n#include \"xvariable.hpp\"\n\nnamespace xf\n{\n\n    template <class CT>\n    class xexpand_dims_view;\n\n    template <class CT>\n    struct xvariable_inner_types<xexpand_dims_view<CT>>\n    {\n        using xexpression_type = std::decay_t<CT>;\n        using data_type = xt::xstrided_view<typename xexpression_type::data_type&, xt::svector<std::size_t>>;\n        using data_closure_type = data_type;\n\n        using subcoordinate_type = typename xexpression_type::coordinate_type;\n        using coordinate_type = xcoordinate_expanded<subcoordinate_type>;\n        using coordinate_closure_type = coordinate_type;\n        using dimension_type = typename xexpression_type::dimension_type;\n        using dimension_closure_type = dimension_type;\n        using key_type = typename coordinate_type::key_type;\n        using size_type = typename coordinate_type::size_type;\n        using label_list = typename coordinate_type::label_list;\n    };\n}\n\nnamespace xt\n{\n    template <class CT>\n    struct xcontainer_inner_types<xf::xexpand_dims_view<CT>>\n        : xf::xvariable_inner_types<xf::xexpand_dims_view<CT>>\n    {\n        using base_type = xf::xvariable_inner_types<xf::xexpand_dims_view<CT>>;\n\n        using data_type = typename base_type::data_type;\n\n        using temporary_coordinate_type = xf::xcoordinate<typename base_type::key_type,\n                                                          typename base_type::label_list,\n                                                          typename base_type::size_type>;\n        using temporary_data_type = typename std::decay_t<CT>::temporary_type::data_type;\n        using temporary_type = xf::xvariable_container<temporary_coordinate_type, temporary_data_type>;\n    };\n}\n\nnamespace xf\n{\n\n    /*********************\n     * xexpand_dims_view *\n     *********************/\n\n    /**\n     * @class xexpand_dims_view\n     * @brief View on a variable with additional axes\n     *\n     * The xvariable_masked_view class is used for creating a view on a variable\n     * with additional axes.\n     *\n     * @tparam CT the closure type on the underlying variable.\n     */\n    template <class CT>\n    class xexpand_dims_view : public xt::xexpression<xexpand_dims_view<CT>>,\n                              private xvariable_base<xexpand_dims_view<CT>>\n    {\n    public:\n\n        using self_type = xexpand_dims_view<CT>;\n        using base_type = xvariable_base<xexpand_dims_view<CT>>;\n        using inner_types = xvariable_inner_types<xexpand_dims_view<CT>>;\n\n        using xexpression_type = typename inner_types::xexpression_type;\n        using data_type = typename inner_types::data_type;\n        using value_type = typename xexpression_type::value_type;\n        using reference = typename xexpression_type::const_reference;\n        using const_reference = reference;\n        using pointer = typename xexpression_type::const_pointer;\n        using const_pointer = pointer;\n        using size_type = typename xexpression_type::size_type;\n        using difference_type = typename xexpression_type::difference_type;\n\n        using shape_type = typename xexpression_type::shape_type;\n\n        using coordinate_type = typename inner_types::coordinate_type;\n        using dimension_type = typename inner_types::dimension_type;\n        using dimension_list = typename dimension_type::label_list;\n        using coordinate_map = typename coordinate_type::map_type;\n        using key_type = typename coordinate_type::key_type;\n        using label_list = typename coordinate_type::label_list;\n\n        using expression_tag = xvariable_expression_tag;\n\n        using extra_dimensions_type = std::vector<std::pair<typename xexpression_type::key_type, std::size_t>>;\n\n        template <class E>\n        xexpand_dims_view(E&& e, const extra_dimensions_type& dims);\n\n        using base_type::missing;\n        using base_type::shape;\n        using base_type::size;\n        using base_type::dimension;\n        using base_type::data;\n        using base_type::coordinates;\n        using base_type::dimension_labels;\n        using base_type::dimension_mapping;\n        using base_type::broadcast_coordinates;\n        using base_type::broadcast_dimensions;\n        using base_type::operator();\n        using base_type::element;\n        using base_type::locate;\n        using base_type::locate_element;\n        using base_type::select;\n        using base_type::iselect;\n\n    private:\n\n        template <class E>\n        dimension_list init_dimension_mapping(E&& e, const extra_dimensions_type& dims) const noexcept;\n        template <class E>\n        coordinate_type init_coordinate(E&& e, const extra_dimensions_type& dims) const noexcept;\n        data_type init_data(const extra_dimensions_type& dims) const noexcept;\n\n        const data_type& data_impl() const noexcept;\n        data_type& data_impl() noexcept;\n\n        CT m_e;\n        data_type m_data;\n\n        friend class xvariable_base<self_type>;\n    };\n\n    template <class CT>\n    std::ostream& operator<<(std::ostream& out, const xexpand_dims_view<CT>& view);\n\n    /******************************\n     * xexpand_dims_view builders *\n     ******************************/\n\n    template <class E, class K>\n    auto expand_dims(E&& e, std::initializer_list<K> dim_names);\n\n    template <class E>\n    auto expand_dims(E&& e, std::initializer_list<std::pair<typename std::decay_t<E>::key_type, std::size_t>> dims);\n\n    template <class E>\n    auto expand_dims(E&& e, std::initializer_list<const char*> dim_names);\n\n    /************************************\n     * xexpand_dims_view implementation *\n     ************************************/\n\n    /**\n     * Constructs an xexpand_dims_view given a map of extra dimensions\n     * @param e the variable expression on which to create the view.\n     * @param dims the map of extra dimensions, the key being the dimension name,\n     * the value the position where to put the new dimension.\n     */\n    template <class CT>\n    template <class E>\n    inline xexpand_dims_view<CT>::xexpand_dims_view(E&& e, const extra_dimensions_type& dims)\n        : base_type(init_coordinate(std::forward<E>(e), dims), init_dimension_mapping(std::forward<E>(e), dims)),\n          m_e(std::forward<E>(e)),\n          m_data(init_data(dims))\n    {\n    }\n\n    template <class CT>\n    template <class E>\n    inline auto xexpand_dims_view<CT>::init_dimension_mapping(E&& e, const extra_dimensions_type& dims) const noexcept -> dimension_list\n    {\n        auto orig_dims_cp = e.dimension_mapping().labels();\n        for (const auto& dim : dims)\n        {\n            orig_dims_cp.insert(orig_dims_cp.cbegin() + dim.second, dim.first);\n        }\n        return orig_dims_cp;\n    }\n\n    template <class CT>\n    template <class E>\n    inline auto xexpand_dims_view<CT>::init_coordinate(E&& e, const extra_dimensions_type& dims) const noexcept -> coordinate_type\n    {\n        coordinate_map extra_dims;\n        for (const auto& dim : dims)\n        {\n            extra_dims.insert(std::make_pair(dim.first, ::xf::axis(1)));\n        }\n        return expand_dims(e.coordinates(), std::move(extra_dims));\n    }\n\n    template <class CT>\n    inline auto xexpand_dims_view<CT>::init_data(const extra_dimensions_type& dims) const noexcept -> data_type\n    {\n        xt::xstrided_slice_vector sv(m_e.data().dimension() + dims.size(), xt::all());\n        for (const auto& iter : dims)\n        {\n            sv[iter.second] = xt::newaxis();\n        }\n        return xt::strided_view(m_e.data(), std::move(sv));\n    }\n\n    template <class CT>\n    inline auto xexpand_dims_view<CT>::data_impl() const noexcept -> const data_type&\n    {\n        return m_data;\n    }\n\n    template <class CT>\n    inline auto xexpand_dims_view<CT>::data_impl() noexcept -> data_type&\n    {\n        return m_data;\n    }\n\n    /*********************************************\n     * xexpand_dims_view builders implementation *\n     *********************************************/\n\n    template <class E, class K>\n    inline auto expand_dims_impl(E&& e, std::initializer_list<K> dim_names)\n    {\n        using extra_dimensions_type = std::vector<std::pair<typename std::decay_t<E>::key_type, std::size_t>>;\n        extra_dimensions_type extra_dimensions;\n        for (const auto& dim_name : dim_names)\n        {\n            extra_dimensions.push_back(std::make_pair(dim_name, extra_dimensions.size()));\n        }\n\n        return xexpand_dims_view<xtl::closure_type_t<E>>(std::forward<E>(e), std::move(extra_dimensions));\n    }\n\n    /**\n     * Creates a view on a variable expression with additional axes, given a list\n     * of extra dimension names\n     * @param e the variable expression on which to create the view.\n     * @param dim_names the list of extra dimension names.\n     */\n    template <class E, class K>\n    inline auto expand_dims(E&& e, std::initializer_list<K> dim_names)\n    {\n        return expand_dims_impl(std::forward<E>(e), dim_names);\n    }\n\n    /**\n     * Creates a view on a variable expression with additional axes, given a list\n     * of extra dimensions\n     * @param e the variable expression on which to create the view.\n     * @param dims the extra dimensions as a mapping \"dimension name\" -> \"position\".\n     */\n    template <class E>\n    inline auto expand_dims(E&& e, std::initializer_list<std::pair<typename std::decay_t<E>::key_type, std::size_t>> dims)\n    {\n        return xexpand_dims_view<xtl::closure_type_t<E>>(std::forward<E>(e), dims);\n    }\n\n    template <class E>\n    inline auto expand_dims(E&& e, std::initializer_list<const char*> dim_names)\n    {\n        return expand_dims_impl(std::forward<E>(e), dim_names);\n    }\n\n    template <class CT>\n    inline std::ostream& operator<<(std::ostream& out, const xexpand_dims_view<CT>& view)\n    {\n        return print_variable_expression(out, view);\n    }\n}\n\n#endif\n"
  },
  {
    "path": "include/xframe/xframe_config.hpp",
    "content": "/***************************************************************************\n* Copyright (c) Johan Mabille, Sylvain Corlay, Wolf Vollprecht and         *\n* Martin Renou                                                             *\n* Copyright (c) QuantStack                                                 *\n*                                                                          *\n* Distributed under the terms of the BSD 3-Clause License.                 *\n*                                                                          *\n* The full license is in the file LICENSE, distributed with this software. *\n****************************************************************************/\n\n#ifndef XFRAME_CONFIG_HPP\n#define XFRAME_CONFIG_HPP\n\n#define XFRAME_VERSION_MAJOR 0\n#define XFRAME_VERSION_MINOR 3\n#define XFRAME_VERSION_PATCH 0\n\n#include \"xtl/xbasic_fixed_string.hpp\"\nnamespace xf\n{\n    using fstring = xtl::xfixed_string<55>;\n}\n\n#ifndef XFRAME_STRING_LABEL\n#define XFRAME_STRING_LABEL xf::fstring\n#endif\n\n#ifndef XFRAME_DEFAULT_LABEL_LIST\n#include <cstddef>\n#include \"xtl/xmeta_utils.hpp\"\n#define XFRAME_DEFAULT_LABEL_LIST xtl::mpl::vector<int, std::size_t, char, XFRAME_STRING_LABEL>\n#endif\n\n#ifndef XFRAME_DEFAULT_JOIN\n#define XFRAME_DEFAULT_JOIN join::inner\n#endif\n\n#ifndef XFRAME_DEFAULT_DATA_CONTAINER\n#include \"xtensor/xarray.hpp\"\n#include \"xtensor/xoptional_assembly.hpp\"\n#define XFRAME_DEFAULT_DATA_CONTAINER(T) xt::xoptional_assembly<xt::xarray<T>, xt::xarray<bool>>\n#endif\n\n// A higher number leads to an ICE on VS 2015\n#ifndef XFRAME_STATIC_DIMENSION_LIMIT\n#define XFRAME_STATIC_DIMENSION_LIMIT 4\n#endif\n\n#ifndef XFRAME_ENABLE_TRACE\n#define XFRAME_ENABLE_TRACE 0\n#endif\n\n#ifndef XFRAME_OUT\n#define XFRAME_OUT std::cout\n#endif\n\n#endif\n"
  },
  {
    "path": "include/xframe/xframe_expression.hpp",
    "content": "/***************************************************************************\n* Copyright (c) Johan Mabille, Sylvain Corlay, Wolf Vollprecht and         *\n* Martin Renou                                                             *\n* Copyright (c) QuantStack                                                 *\n*                                                                          *\n* Distributed under the terms of the BSD 3-Clause License.                 *\n*                                                                          *\n* The full license is in the file LICENSE, distributed with this software. *\n****************************************************************************/\n\n#ifndef XFRAME_XFRAME_EXPRESSION_HPP\n#define XFRAME_XFRAME_EXPRESSION_HPP\n\n#include \"xtl/xtype_traits.hpp\"\n\n#include \"xtensor/xexpression.hpp\"\n\nnamespace xf\n{\n    struct xvariable_expression_tag {};\n    struct xframe_expression_tag {};\n\n    template <class E>\n    struct is_xvariable_expression : std::is_same<xt::xexpression_tag_t<E>, xvariable_expression_tag>\n    {\n    };\n\n    template <class... E>\n    struct xvariable_comparable : xtl::conjunction<is_xvariable_expression<E>...>\n    {\n    };\n\n    struct xaxis_expression_tag {};\n\n    template <class E>\n    struct is_xaxis_expression : std::is_same<xt::xexpression_tag_t<E>, xaxis_expression_tag>\n    {\n    };\n\n    template <class... E>\n    struct xaxis_comparable : xtl::conjunction<is_xaxis_expression<E>...>\n    {\n    };\n}\n\nnamespace xt\n{\n    namespace extension\n    {\n        template <>\n        struct expression_tag_and<xf::xvariable_expression_tag, xoptional_expression_tag>\n        {\n            using type = xf::xvariable_expression_tag;\n        };\n\n        template <>\n        struct expression_tag_and<xoptional_expression_tag, xf::xvariable_expression_tag>\n            : expression_tag_and<xf::xvariable_expression_tag, xoptional_expression_tag>\n        {\n        };\n\n        template <>\n        struct expression_tag_and<xf::xvariable_expression_tag, xf::xvariable_expression_tag>\n        {\n            using type = xf::xvariable_expression_tag;\n        };\n    }\n}\n\n#endif\n"
  },
  {
    "path": "include/xframe/xframe_trace.hpp",
    "content": "/***************************************************************************\n* Copyright (c) Johan Mabille, Sylvain Corlay, Wolf Vollprecht and         *\n* Martin Renou                                                             *\n* Copyright (c) QuantStack                                                 *\n*                                                                          *\n* Distributed under the terms of the BSD 3-Clause License.                 *\n*                                                                          *\n* The full license is in the file LICENSE, distributed with this software. *\n****************************************************************************/\n\n#ifndef XFRAME_XFRAME_TRACE_HPP\n#define XFRAME_XFRAME_TRACE_HPP\n\n#include <string>\n\n#include \"xframe_config.hpp\"\n\nnamespace xf\n{\n\n#if XFRAME_ENABLE_TRACE\n\n#define XFRAME_TRACE(expr) XFRAME_OUT << expr << std::endl;\n\n#define XFRAME_TRACE_BROADCAST_DIMENSIONS(lhs, rhs)             \\\n    XFRAME_TRACE(\"BROADCASTING DIMENSIONS\");                    \\\n    XFRAME_TRACE(\"lhs = \" << lhs);                              \\\n    XFRAME_TRACE(\"rhs = \" << rhs);\n\n#define XFRAME_TRACE_DIMENSIONS_RESULT(res, trivial)            \\\n    XFRAME_TRACE(\"res = \" << res);                              \\\n    XFRAME_TRACE(\"trivial broadcasting = \" << trivial);\n\n#define XFRAME_TRACE_BROADCAST_COORDINATES(lhs, rhs)            \\\n    XFRAME_TRACE(\"BROADCASTING COORDINATES\");                   \\\n    XFRAME_TRACE(\"lhs:\")                                        \\\n    XFRAME_OUT << lhs;                                          \\\n    XFRAME_TRACE(\"rhs:\")                                        \\\n    XFRAME_OUT << rhs;\n\n#define XFRAME_TRACE_COORDINATES_RESULT(res, trivial)           \\\n    XFRAME_TRACE(\"res:\")                                        \\\n    XFRAME_OUT << res;                                          \\\n    XFRAME_TRACE(\"trivial broadcasting = (\" << trivial.m_same_dimensions << \", \" << trivial.m_same_labels << \")\");\n#else\n#define XFRAME_TRACE(expr)\n#define XFRAME_TRACE_BROADCAST_DIMENSIONS(lhs, rhs)\n#define XFRAME_TRACE_DIMENSIONS_RESULT(res, trivial)\n#define XFRAME_TRACE_BROADCAST_COORDINATES(lhs, rhs)\n#define XFRAME_TRACE_COORDINATES_RESULT(res, trivial)\n#endif\n\n}\n\n#endif\n"
  },
  {
    "path": "include/xframe/xframe_utils.hpp",
    "content": "/***************************************************************************\n* Copyright (c) Johan Mabille, Sylvain Corlay, Wolf Vollprecht and         *\n* Martin Renou                                                             *\n* Copyright (c) QuantStack                                                 *\n*                                                                          *\n* Distributed under the terms of the BSD 3-Clause License.                 *\n*                                                                          *\n* The full license is in the file LICENSE, distributed with this software. *\n****************************************************************************/\n\n#ifndef XFRAME_XFRAME_UTILS_HPP\n#define XFRAME_XFRAME_UTILS_HPP\n\n#include <iterator>\n#include <ostream>\n#include <string>\n\n#include \"xtensor/xio.hpp\"\n\n#include \"xframe_config.hpp\"\n#include \"xframe_trace.hpp\"\n\nnamespace xf\n{\n    constexpr std::size_t dynamic()\n    {\n        return std::numeric_limits<std::size_t>::max();\n    }\n\n    template <class CO, class... CI>\n    bool merge_to(CO& output, const CI&... input);\n\n    template <class CO, class... CI>\n    bool intersect_to(CO& output, const CI&... input);\n\n    /***************************\n     * merge_to implementation *\n     ***************************/\n\n    namespace detail\n    {\n        template <class C0, class C1>\n        inline bool merge_containers(C0& output, const C1& input)\n        {\n            bool res = !(input.size() < output.size());\n            auto output_iter = output.begin();\n            auto output_end = output.end();\n            auto first = input.begin();\n            auto last = input.end();\n            while(first != last && output_iter != output_end)\n            {\n                if(*first < *output_iter)\n                {\n                    output_iter = output.insert(output_iter, *first++);\n                    output_end = output.end();\n                    res = false;\n                }\n                else if(*first == *output_iter)\n                {\n                    ++first;\n                }\n                ++output_iter;\n            }\n            res &= output.empty() || (first == last);\n            std::copy(first, last, std::back_inserter(output));\n            return res;\n        }\n\n        template <class C0>\n        inline bool merge_to_impl(C0&)\n        {\n            return true;\n        }\n\n        template <class C0, class C1, class... C>\n        inline bool merge_to_impl(C0& out, C1& in, const C&... input)\n        {\n            bool res = merge_containers(out, in);\n            res &= merge_to_impl(out, input...);\n            return res;\n        }\n\n        template <class S, std::size_t N>\n        struct xselector_sequence\n        {\n            using type = std::conditional_t<N == std::numeric_limits<std::size_t>::max(), std::vector<S>, std::array<S, N>>;\n        };\n\n        template <class S, std::size_t N>\n        using xselector_sequence_t = typename xselector_sequence<S, N>::type;\n    }\n\n    template <class CO, class... CI>\n    inline bool merge_to(CO& output, const CI&... input)\n    {\n        return detail::merge_to_impl(output, input...);\n    }\n\n    /*******************************\n     * intersect_to implementation *\n     *******************************/\n\n    namespace detail\n    {\n        template <class C0, class C1>\n        inline bool intersect_containers(C0& output, const C1& input)\n        {\n            bool res = !(input.size() < output.size());\n            auto output_iter = output.begin();\n            auto output_end = output.end();\n            auto first = input.begin();\n            auto last = input.end();\n            while(first != last && output_iter != output_end)\n            {\n                if(*first < *output_iter)\n                {\n                    ++first;\n                }\n                else if(*first == *output_iter)\n                {\n                    ++first;\n                    ++output_iter;\n                }\n                else // *first > *output_iter\n                {\n                    output_iter = output.erase(output_iter);\n                    output_end = output.end();\n                    res = false;\n                }\n            }\n            res &= (output_iter == output_end);\n            output.erase(output_iter, output_end);\n            return res;\n        }\n\n        template <class C0>\n        inline bool intersect_to_impl(C0&)\n        {\n            return true;\n        }\n\n        template <class C0, class C1, class... C>\n        inline bool intersect_to_impl(C0& out, const C1& in, const C&... input)\n        {\n            bool res = intersect_containers(out, in);\n            res &= intersect_to_impl(out, input...);\n            return res;\n        }\n    }\n\n    template <class CO, class... CI>\n    inline bool intersect_to(CO& output, const CI&... input)\n    {\n        return detail::intersect_to_impl(output, input...);\n    }\n\n    /******************\n     * print function *\n     ******************/\n\n    template <class V>\n    inline std::ostream& print_variable_expression(std::ostream& out, const V& v)\n    {\n        const auto& dims = v.dimension_labels();\n        const auto& coords = v.coordinates();\n\n        out << v.data() << std::endl;\n        out << \"Coordinates:\" << std::endl;\n\n        std::size_t max_length = std::accumulate(dims.cbegin(), dims.cend(), std::size_t(0),\n            [](std::size_t res, const auto& d) { return std::max(res, d.size()); });\n\n        for (const auto& d : dims)\n        {\n            std::size_t nb_spaces = max_length - d.size();\n            std::string spaces(nb_spaces, ' ');\n            out << d << spaces << \": \" << coords[d] << std::endl;\n        }\n\n        return out;\n    }\n}\n\n#endif\n"
  },
  {
    "path": "include/xframe/xio.hpp",
    "content": "/***************************************************************************\n* Copyright (c) Johan Mabille, Sylvain Corlay, Wolf Vollprecht and         *\n* Martin Renou                                                             *\n* Copyright (c) QuantStack                                                 *\n*                                                                          *\n* Distributed under the terms of the BSD 3-Clause License.                 *\n*                                                                          *\n* The full license is in the file LICENSE, distributed with this software. *\n****************************************************************************/\n\n#ifndef XFRAME_IO_HPP\n#define XFRAME_IO_HPP\n\n#include <sstream>\n\n#include \"xtensor/xio.hpp\"\n\n#ifdef __CLING__\n\n#include <nlohmann/json.hpp>\n\nnamespace nl = nlohmann;\n\nnamespace xf\n{\n    template <class P, class T>\n    void compute_1d_row(std::stringstream& out, P& printer, const T& expr,\n                        const std::size_t& row_idx)\n    {\n        const auto& dim_name = expr.dimension_mapping().labels()[0];\n        std::stringstream label;\n        xtl::visit([&label](auto&& arg) { label << arg; }, expr.coordinates()[dim_name].label(row_idx));\n\n        out << \"<tr><th title='\" << dim_name << \"'>\" << label.str()\n            << \"</th><td style='font-family:monospace;' title='\"\n            << dim_name << \": \" << label.str() << \"'><pre>\";\n        printer.print_next(out);\n        out << \"</pre></td></tr>\";\n    }\n\n    template <class P, class T>\n    void compute_1d_table(std::stringstream& out, P& printer, const T& expr,\n                          const std::size_t& edge_items)\n    {\n        const auto& dim = expr.shape()[0];\n\n        out << \"<table style='border-style:solid;border-width:1px;'><tbody>\";\n        if (edge_items == 0 || 2 * edge_items >= dim)\n        {\n            for (std::size_t row_idx = 0; row_idx < dim; ++row_idx)\n            {\n                compute_1d_row(out, printer, expr, row_idx);\n            }\n        }\n        else\n        {\n            for (std::size_t row_idx = 0; row_idx < edge_items; ++row_idx)\n            {\n                compute_1d_row(out, printer, expr, row_idx);\n            }\n            out << \"<tr><th><center>...</center></th><td><center>...</center></td></tr>\";\n            for (std::size_t row_idx = dim - edge_items; row_idx < dim; ++row_idx)\n            {\n                compute_1d_row(out, printer, expr, row_idx);\n            }\n        }\n        out << \"</tbody></table>\";\n    }\n\n    template <class P, class T>\n    void compute_2d_element(std::stringstream& out, P& printer, const T& expr,\n                            const std::string& titles_str,\n                            const std::size_t& row_idx, const std::size_t& column_idx)\n    {\n        const auto& before_last_dim_name = expr.dimension_mapping().label(expr.dimension() - 2);\n        const auto& last_dim_name = expr.dimension_mapping().label(expr.dimension() - 1);\n\n        out << \"<td style='font-family:monospace;' title='(\" << titles_str;\n        xtl::visit([&before_last_dim_name, &out](auto&& arg) {\n            out << before_last_dim_name << \": \" << arg << \", \";\n        }, expr.coordinates()[before_last_dim_name].label(row_idx));\n        xtl::visit([&last_dim_name, &out](auto&& arg) {\n            out << last_dim_name << \": \" << arg << \")'>\";\n        }, expr.coordinates()[last_dim_name].label(column_idx));\n\n        out << \"<pre>\";\n        printer.print_next(out);\n        out << \"</pre></td>\";\n    }\n\n    template <class T>\n    std::size_t compute_nb_rows(const std::size_t& dim, const T& expr, const std::size_t& edge_items)\n    {\n        if (dim == expr.dimension() - 2)\n        {\n            if (edge_items == 0 || 2 * edge_items >= expr.shape()[dim])\n            {\n                return expr.shape()[dim];\n            }\n            /*else*/ return 2 * edge_items + 1;\n        }\n\n        if (edge_items == 0 || 2 * edge_items >= expr.shape()[dim])\n        {\n            return expr.shape()[dim] * compute_nb_rows(dim + 1, expr, edge_items);\n        }\n        /*else*/ return 2 * edge_items * compute_nb_rows(dim + 1, expr, edge_items) + 1;\n    }\n\n    template <class T, class I>\n    void compute_row_head(std::stringstream& out, const T& expr,\n                          const std::size_t& edge_items,\n                          const std::size_t& row_idx, const std::vector<I>& idx)\n    {\n        const auto& before_last_dim_name = expr.dimension_mapping().label(expr.dimension() - 2);\n\n        if (row_idx == 0)\n        {\n            std::stringstream heads;\n            std::size_t current_dim = 0;\n            for (auto it = idx.cbegin(); it != idx.cend(); ++it)\n            {\n                if (*(it + 1) == 0 || it + 1 == idx.cend())\n                {\n                    const auto& current_dim_name = expr.dimension_mapping().label(current_dim);\n\n                    std::size_t rowspan = compute_nb_rows(current_dim + 1, expr, edge_items);\n                    xtl::visit([&heads, &current_dim_name, &rowspan](auto&& arg) {\n                        heads << \"<th title='\" << current_dim_name\n                        << \"' scope='rowgroup' rowspan='\" << rowspan\n                        << \"'>\" << arg << \"</th>\";\n                    }, expr.coordinates()[current_dim_name].label(*it));\n                }\n\n                current_dim++;\n            }\n            out << heads.str();\n        }\n\n        xtl::visit([&out, &before_last_dim_name](auto&& arg) {\n            out << \"<th\"\n                << \" style='border-right-style:solid;border-right-width:1px;'\"\n                <<\" title='\" << before_last_dim_name << \"'>\" << arg << \"</th>\";\n        }, expr.coordinates()[before_last_dim_name].label(row_idx));\n    }\n\n    template <class P, class T, class I>\n    void compute_2d_row(std::stringstream& out, P& printer, const T& expr,\n                        const std::size_t& edge_items, const std::string& titles_str,\n                        const std::size_t& row_idx, const std::vector<I>& idx)\n    {\n        const auto& before_last_dim_name = expr.dimension_mapping().label(expr.dimension() - 2);\n        const auto& last_dim = expr.shape()[expr.dimension() - 1];\n\n        out << \"<tr>\";\n        compute_row_head(out, expr, edge_items, row_idx, idx);\n        if (edge_items == 0 || 2 * edge_items >= last_dim)\n        {\n            for (std::size_t column_idx = 0; column_idx < last_dim; ++column_idx)\n            {\n                xf::compute_2d_element(out, printer, expr, titles_str, row_idx, column_idx);\n            }\n        }\n        else\n        {\n            for (std::size_t column_idx = 0; column_idx < edge_items; ++column_idx)\n            {\n                xf::compute_2d_element(out, printer, expr, titles_str, row_idx, column_idx);\n            }\n            out << \"<td><center>...</center></td>\";\n            for (std::size_t column_idx = last_dim - edge_items; column_idx < last_dim; ++column_idx)\n            {\n                xf::compute_2d_element(out, printer, expr, titles_str, row_idx, column_idx);\n            }\n        }\n        out << \"</tr>\";\n    }\n\n    template <class P, class T, class I>\n    void compute_2d_table(std::stringstream& out, P& printer, const T& expr,\n                          const std::size_t& edge_items, const std::vector<I>& idx)\n    {\n        const auto& before_last_dim_name = expr.dimension_mapping().label(expr.dimension() - 2);\n        const auto& before_last_dim = expr.shape()[expr.dimension() - 2];\n        const auto& last_dim = expr.shape()[expr.dimension() - 1];\n\n        std::stringstream titles;\n        std::size_t current_dim = 0;\n        std::for_each(idx.cbegin(), idx.cend(), [&titles, &expr, &current_dim](const auto& i) {\n            const auto& dim_name = expr.dimension_mapping().label(current_dim);\n\n            xtl::visit([&titles, &dim_name](auto&& arg) {\n                titles << dim_name << \": \" << arg << \", \";\n            }, expr.coordinates()[dim_name].label(i));\n\n            current_dim++;\n        });\n        std::string titles_str = titles.str();\n\n        if (edge_items == 0 || 2 * edge_items >= before_last_dim)\n        {\n            for (std::size_t row_idx = 0; row_idx < before_last_dim; ++row_idx)\n            {\n                xf::compute_2d_row(out, printer, expr, edge_items, titles_str, row_idx, idx);\n            }\n        }\n        else\n        {\n            for (std::size_t row_idx = 0; row_idx < edge_items; ++row_idx)\n            {\n                xf::compute_2d_row(out, printer, expr, edge_items, titles_str, row_idx, idx);\n            }\n            out << \"<tr><th title='\" << before_last_dim_name\n                << \"' style='border-right-style:solid;border-right-width:1px;'>\"\n                << \"<center>...</center></th>\";\n            if (2 * edge_items >= last_dim)\n            {\n                for (std::size_t row_idx = 0; row_idx < last_dim; ++row_idx)\n                {\n                    out << \"<td><center>...</center></td>\";\n                }\n            }\n            else\n            {\n                for (std::size_t column_idx = 0; column_idx < 2 * edge_items + 1; ++column_idx)\n                {\n                    out << \"<td><center>...</center></td>\";\n                }\n            }\n            out << \"</tr>\";\n            for (std::size_t row_idx = before_last_dim - edge_items; row_idx < before_last_dim; ++row_idx)\n            {\n                xf::compute_2d_row(out, printer, expr, edge_items, titles_str, row_idx, idx);\n            }\n        }\n    }\n\n    template <class P, class T, class I>\n    void compute_sub_nd_table(std::stringstream& out, P& printer, const T& expr,\n                              const std::size_t& edge_items, const std::vector<I>& idx)\n    {\n        const auto& dim = expr.dimension();\n        const auto& displayed_dim = idx.size();\n        const auto& displayed_dim_size = expr.shape()[displayed_dim];\n        const auto& displayed_dim_name = expr.dimension_mapping().label(displayed_dim);\n\n        if (dim - displayed_dim == 2)\n        {\n            return xf::compute_2d_table(out, printer, expr, edge_items, idx);\n        }\n\n        std::vector<I> idx2 = idx;\n        idx2.resize(displayed_dim + 1);\n\n        if (edge_items == 0 || 2 * edge_items >= displayed_dim_size)\n        {\n            for (std::size_t i = 0; i < displayed_dim_size; ++i)\n            {\n                idx2[displayed_dim] = i;\n                xf::compute_sub_nd_table(out, printer, expr, edge_items, idx2);\n            }\n        }\n        else\n        {\n            for (std::size_t i = 0; i < edge_items; ++i)\n            {\n                idx2[displayed_dim] = i;\n                xf::compute_sub_nd_table(out, printer, expr, edge_items, idx2);\n            }\n            out << \"<tr><th title='\" << displayed_dim_name << \"'><center>...</center></th>\";\n            for (std::size_t i = displayed_dim + 1; i < dim - 1; ++i)\n            {\n                const auto& i_name = expr.dimension_mapping().label(i);\n                out << \"<th title='\" << i_name << \"'><center>...</center></th>\";\n            }\n            std::size_t num_ellipsis;\n            if (edge_items == 0 || 2 * edge_items >= expr.shape()[expr.dimension() - 1])\n            {\n                num_ellipsis = expr.shape()[expr.dimension() - 1];\n            }\n            else\n            {\n                num_ellipsis = 2 * edge_items + 1;\n            }\n            for (std::size_t i = 0; i < num_ellipsis; ++i)\n            {\n                out << \"<td><center>...</center></td>\";\n            }\n            out << \"</tr>\";\n            for (std::size_t i = displayed_dim_size - edge_items; i < displayed_dim_size; ++i)\n            {\n                idx2[displayed_dim] = i;\n                xf::compute_sub_nd_table(out, printer, expr, edge_items, idx2);\n            }\n        }\n    }\n\n    template <class P, class T>\n    void compute_nd_table_impl(std::stringstream& out, P& printer, const T& expr,\n                               const std::size_t& edge_items)\n    {\n        const auto& dim = expr.dimension();\n\n        out << \"<table style='border-style:solid;border-width:1px;'>\";\n\n        // Compute head of the table\n        out << \"<thead>\";\n        for (std::size_t d = 0; d < dim - 1; ++d)\n        {\n            out << \"<th></th>\";\n        }\n\n        const auto& last_dim_name = expr.dimension_mapping().labels()[dim - 1];\n        const auto& last_dim_size = expr.shape()[dim - 1];\n        if (edge_items == 0 || 2 * edge_items >= last_dim_size)\n        {\n            for (std::size_t d = 0; d < last_dim_size; ++d)\n            {\n                xtl::visit([&out, &last_dim_name](auto&& arg) {\n                    out << \"<th title='\" << last_dim_name << \"'>\" << arg << \"</th>\";\n                }, expr.coordinates()[last_dim_name].label(d));\n            }\n        }\n        else\n        {\n            for (std::size_t d = 0; d < edge_items; ++d)\n            {\n                xtl::visit([&out, &last_dim_name](auto&& arg) {\n                    out << \"<th title='\" << last_dim_name << \"'>\" << arg << \"</th>\";\n                }, expr.coordinates()[last_dim_name].label(d));\n            }\n            out << \"<th title='\" << last_dim_name << \"'><center>...</center></th>\";\n            for (std::size_t d = last_dim_size - edge_items; d < last_dim_size; ++d)\n            {\n                xtl::visit([&out, &last_dim_name](auto&& arg) {\n                    out << \"<th title='\" << last_dim_name << \"'>\" << arg << \"</th>\";\n                }, expr.coordinates()[last_dim_name].label(d));\n            }\n        }\n        out << \"</thead>\";\n\n        // Compute body of the table\n        out << \"<tbody>\";\n        std::vector<std::size_t> empty_vector;\n        xf::compute_sub_nd_table(out, printer, expr, edge_items, empty_vector);\n        out << \"</tbody>\";\n        out << \"</table>\";\n    }\n\n    template <class P, class T>\n    void compute_nd_table(std::stringstream& out, P& printer, const T& expr,\n                          const std::size_t& edge_items)\n    {\n        if (expr.dimension() == 1)\n        {\n            xf::compute_1d_table(out, printer, expr, edge_items);\n        }\n        else\n        {\n            xf::compute_nd_table_impl(out, printer, expr, edge_items);\n        }\n    }\n\n    template <class T>\n    nl::json mime_bundle_repr_impl(const T& expr)\n    {\n        std::stringstream out;\n\n        std::size_t edge_items = 0;\n        std::size_t size = xt::compute_size(expr.shape());\n        if (size > xt::print_options::print_options().threshold)\n        {\n            edge_items = xt::print_options::print_options().edge_items;\n        }\n\n        if (xt::print_options::print_options().precision != -1)\n        {\n            out.precision(xt::print_options::print_options().precision);\n        }\n\n        xt::detail::printer<typename T::data_type> printer(out.precision());\n\n        xt::xstrided_slice_vector slice_vector;\n        xt::detail::recurser_run(printer, expr.data(), slice_vector, edge_items);\n        printer.init();\n\n        xf::compute_nd_table(out, printer, expr, edge_items);\n\n        auto bundle = nl::json::object();\n        bundle[\"text/html\"] = out.str();\n        return bundle;\n    }\n\n    template <class CCT, class ECT>\n    class xvariable_container;\n\n    template <class CCT, class ECT>\n    nl::json mime_bundle_repr(const xvariable_container<CCT, ECT>& expr)\n    {\n        return xf::mime_bundle_repr_impl(expr);\n    }\n\n    template <class F, class R, class... CT>\n    class xvariable_function;\n\n    template <class F, class R, class... CT>\n    nl::json mime_bundle_repr(const xvariable_function<F, R, CT...>& expr)\n    {\n        using temporary_type = typename xvariable_function<F, R, CT...>::temporary_type;\n        temporary_type tmp(expr);\n        return xf::mime_bundle_repr_impl(tmp);\n    }\n\n    template <class CT>\n    class xvariable_view;\n\n    template <class CT>\n    nl::json mime_bundle_repr(const xvariable_view<CT>& expr)\n    {\n        return xf::mime_bundle_repr_impl(expr);\n    }\n\n    template <class CTV, class CTAX>\n    class xvariable_masked_view;\n\n    template <class CTV, class CTAX>\n    nl::json mime_bundle_repr(const xvariable_masked_view<CTV, CTAX>& expr)\n    {\n        return xf::mime_bundle_repr_impl(expr);\n    }\n\n    template <class E>\n    class xreindex_view;\n\n    template <class E>\n    nl::json mime_bundle_repr(const xreindex_view<E>& expr)\n    {\n        return xf::mime_bundle_repr_impl(expr);\n    }\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "include/xframe/xnamed_axis.hpp",
    "content": "/***************************************************************************\n* Copyright (c) Johan Mabille, Sylvain Corlay, Wolf Vollprecht and         *\n* Martin Renou                                                             *\n* Copyright (c) QuantStack                                                 *\n*                                                                          *\n* Distributed under the terms of the BSD 3-Clause License.                 *\n*                                                                          *\n* The full license is in the file LICENSE, distributed with this software. *\n****************************************************************************/\n\n#ifndef XFRAME_XNAMED_AXIS_HPP\n#define XFRAME_XNAMED_AXIS_HPP\n\n#include \"xaxis_math.hpp\"\n#include \"xaxis.hpp\"\n#include \"xaxis_default.hpp\"\n#include \"xaxis_variant.hpp\"\n\nnamespace xf\n{\n\n    /**\n     * @class xnamed_axis\n     * @brief Class modeling a dimension name - axis pair in a coordinate system.\n     *\n     * The xnamed_axis class stores a dimension name and an xaxis as an\n     * xaxis_variant.\n     *\n     * @tparam K the dimension name type.\n     * @tparam T the integer type used to represent positions in the underlying\n     *           xaxis_variant.\n     * @sa xaxis_variant, xaxis\n     */\n    template <class K, class T, class MT = hash_map_tag, class L = XFRAME_DEFAULT_LABEL_LIST, class LT = xtl::mpl::cast_t<L, xtl::variant>>\n    class xnamed_axis : public xt::xexpression<xnamed_axis<K, T, MT, L, LT>>\n    {\n    public:\n\n        using name_type = K;\n        using axis_variant_type = xaxis_variant<L, T, MT>;\n        using size_type = typename axis_variant_type::size_type;\n\n        using value_type = LT;\n        using reference = value_type;\n        using const_reference = const value_type;\n        using pointer = value_type*;\n        using const_pointer = const value_type*;\n\n        using expression_tag = xaxis_expression_tag;\n\n        template <class A>\n        xnamed_axis(const name_type& name, A&& axis);\n        template <class A>\n        xnamed_axis(name_type&& name, A&& axis);\n\n        const name_type& name() const & noexcept;\n        const axis_variant_type& axis() const & noexcept;\n        const value_type& label(size_type i) const & noexcept;\n\n    private:\n\n        name_type m_name;\n        axis_variant_type m_axis;\n    };\n\n    /******************************\n     * xnamed_axis implementation *\n     ******************************/\n\n    /**\n     * Builds an xnamed_axis.\n     * @param name the dimension name.\n     * @param axis the underlying xaxis.\n     */\n    template <class K, class T, class MT, class L, class LT>\n    template <class A>\n    inline xnamed_axis<K, T, MT, L, LT>::xnamed_axis(const name_type& name, A&& axis)\n        : m_name(name), m_axis(std::forward<A>(axis))\n    {\n    }\n\n    /**\n     * Builds an xnamed_axis.\n     * @param name the dimension name.\n     * @param axis the underlying xaxis.\n     */\n    template <class K, class T, class MT, class L, class LT>\n    template <class A>\n    inline xnamed_axis<K, T, MT, L, LT>::xnamed_axis(name_type&& name, A&& axis)\n        : m_name(std::move(name)), m_axis(std::forward<A>(axis))\n    {\n    }\n\n    /**\n     * Returns the name of the xnamed_axis.\n     * @return the dimension name.\n     */\n    template <class K, class T, class MT, class L, class LT>\n    inline auto xnamed_axis<K, T, MT, L, LT>::name() const & noexcept -> const name_type&\n    {\n        return m_name;\n    }\n\n    /**\n     * Returns the underlying xaxis_variant.\n     * @return the xaxis_variant.\n     * @sa xaxis_variant\n     */\n    template <class K, class T, class MT, class L, class LT>\n    inline auto xnamed_axis<K, T, MT, L, LT>::axis() const & noexcept -> const axis_variant_type&\n    {\n        return m_axis;\n    }\n\n    /**\n     * Returns the label at the given position of the underlying xaxis.\n     * @param i the position.\n     * @return the label at the given position of the underlying xaxis.\n     */\n    template <class K, class T, class MT, class L, class LT>\n    inline auto xnamed_axis<K, T, MT, L, LT>::label(size_type i) const & noexcept -> const LT&\n    {\n        return get_labels<LT>(m_axis)[i];\n    }\n\n    /******************\n     * xaxis builders *\n     ******************/\n\n    /**\n     * Builder function which creates an xnamed_axis.\n     * @param name the dimension name.\n     * @param axis the xaxis that you want to store in the xnamed_axis.\n     * @tparam K the dimension name type.\n     * @tparam A the axis type.\n     * @return the created xnamed_axis.\n     */\n    template <class K, class A>\n    inline auto named_axis(const K& name, A&& axis)\n    {\n        static_assert(is_axis<std::decay_t<A>>::value, \"axis must be an axis type\");\n\n        using key_type = typename std::decay_t<A>::key_type;\n        using mapped_type = typename std::decay_t<A>::mapped_type;\n\n        return xnamed_axis<K, mapped_type, hash_map_tag, XFRAME_DEFAULT_LABEL_LIST, key_type>(name, axis);\n    }\n\n    template <class A>\n    inline auto named_axis(const char* name, A&& axis)\n    {\n        static_assert(is_axis<std::decay_t<A>>::value, \"axis must be an axis type\");\n\n        using key_type = typename std::decay_t<A>::key_type;\n        using mapped_type = typename std::decay_t<A>::mapped_type;\n\n        return xnamed_axis<const char*, mapped_type, hash_map_tag, XFRAME_DEFAULT_LABEL_LIST, key_type>(name, axis);\n    }\n\n    template <class LB, class K, class T, class MT = hash_map_tag, class L = XFRAME_DEFAULT_LABEL_LIST>\n    auto get_labels(const xnamed_axis<K, T, MT, L, LB>& n_axis) -> const typename xaxis<LB, T, MT>::label_list&\n    {\n        return get_labels<LB>(n_axis.axis());\n    }\n}\n\n#endif\n"
  },
  {
    "path": "include/xframe/xreindex_data.hpp",
    "content": "/***************************************************************************\n* Copyright (c) Johan Mabille, Sylvain Corlay, Wolf Vollprecht and         *\n* Martin Renou                                                             *\n* Copyright (c) QuantStack                                                 *\n*                                                                          *\n* Distributed under the terms of the BSD 3-Clause License.                 *\n*                                                                          *\n* The full license is in the file LICENSE, distributed with this software. *\n****************************************************************************/\n\n#ifndef XREINDEX_DATA_HPP\n#define XREINDEX_DATA_HPP\n\n#include \"xtensor/xexpression.hpp\"\n#include \"xtensor/xiterable.hpp\"\n#include \"xtensor/xlayout.hpp\"\n\nnamespace xf\n{\n    template <class RV>\n    class xreindex_data;\n}\n\nnamespace xt\n{\n    template <class RV>\n    struct xiterable_inner_types<xf::xreindex_data<RV>>\n    {\n        using xexpression_type = std::decay_t<RV>;\n        using inner_shape_type = typename xexpression_type::shape_type;\n        using const_stepper = xindexed_stepper<xf::xreindex_data<RV>, true>;\n        using stepper = const_stepper;\n    };\n}\n\nnamespace xf\n{\n    template <class RV>\n    class xreindex_data : public xt::xexpression<xreindex_data<RV>>,\n                          public xt::xconst_iterable<xreindex_data<RV>>\n    {\n    public:\n\n        using self_type = xreindex_data<RV>;\n        using xexpression_type = std::decay_t<RV>;\n        using expression_tag = xt::xtensor_expression_tag;\n\n        using value_type = typename xexpression_type::value_type;\n        using reference = typename xexpression_type::reference;\n        using const_reference = typename xexpression_type::const_reference;\n        using pointer = typename xexpression_type::pointer;\n        using const_pointer = typename xexpression_type::const_pointer;\n        using size_type = typename xexpression_type::size_type;\n        using difference_type = typename xexpression_type::difference_type;\n\n        using iterable_base = xt::xconst_iterable<self_type>;\n        using inner_shape_type = typename iterable_base::inner_shape_type;\n        using shape_type = inner_shape_type;\n\n        using stepper = typename iterable_base::stepper;\n        using const_stepper = typename iterable_base::const_stepper;\n\n        static constexpr xt::layout_type static_layout = xt::layout_type::dynamic;\n        static constexpr bool contiguous_layout = false;\n\n        explicit xreindex_data(const xexpression_type& e);\n\n        size_type size() const noexcept;\n        size_type dimension() const noexcept;\n        const inner_shape_type& shape() const noexcept;\n        xt::layout_type layout() const noexcept;\n\n        template <class... Args>\n        const_reference operator()(Args... args) const;\n\n        template <class... Args>\n        const_reference at(Args... args) const;\n\n        template <class... Args>\n        const_reference unchecked(Args... args) const;\n\n        template <class S>\n        xt::disable_integral_t<S, const_reference> operator[](const S& index) const;\n        template <class I>\n        const_reference operator[](std::initializer_list<I> index) const;\n        const_reference operator[](size_type i) const;\n\n        template <class It>\n        const_reference element(It first, It last) const;\n\n        template <class S>\n        bool braodcast_shape(S& shape, bool reuse_cache = false) const;\n\n        template <class S>\n        bool has_linear_assign(const S& strides) const noexcept;\n\n        template <class S>\n        const_stepper stepper_begin(const S& shape) const noexcept;\n        template <class S>\n        const_stepper stepper_end(const S& shape, xt::layout_type l) const noexcept;\n\n    private:\n\n        using index_type = typename xexpression_type::template index_type<>;\n        const xexpression_type& m_e;\n    };\n\n    /********************************\n     * xreindex_data implementation *\n     ********************************/\n\n    template <class RV>\n    inline xreindex_data<RV>::xreindex_data(const xexpression_type& e)\n        : m_e(e)\n    {\n    }\n\n    template <class RV>\n    inline auto xreindex_data<RV>::size() const noexcept -> size_type\n    {\n        return m_e.size();\n    }\n\n    template <class RV>\n    inline auto xreindex_data<RV>::dimension() const noexcept -> size_type\n    {\n        return m_e.dimension();\n    }\n\n    template <class RV>\n    inline auto xreindex_data<RV>::shape() const noexcept -> const inner_shape_type&\n    {\n        return m_e.shape();\n    }\n\n    template <class RV>\n    inline auto xreindex_data<RV>::layout() const noexcept -> xt::layout_type\n    {\n        return xt::layout_type::dynamic;\n    }\n\n    template <class RV>\n    template <class... Args>\n    inline auto xreindex_data<RV>::operator()(Args... args) const -> const_reference\n    {\n        return m_e(args...);\n    }\n\n    template <class RV>\n    template <class... Args>\n    inline auto xreindex_data<RV>::at(Args... args) const -> const_reference\n    {\n        return m_e(args...);\n    }\n\n    template <class RV>\n    template <class... Args>\n    inline auto xreindex_data<RV>::unchecked(Args... args) const -> const_reference\n    {\n        return m_e(args...);\n    }\n\n    template <class RV>\n    template <class S>\n    inline auto xreindex_data<RV>::operator[](const S& index) const -> xt::disable_integral_t<S, const_reference>\n    {\n        index_type idx = xtl::forward_sequence<index_type, const S&>(index);\n        return m_e.element(std::move(idx));\n    }\n\n    template <class RV>\n    template <class I>\n    inline auto xreindex_data<RV>::operator[](std::initializer_list<I> index) const -> const_reference\n    {\n        index_type idx(index);\n        return m_e.element(std::move(idx));\n    }\n\n    template <class RV>\n    inline auto xreindex_data<RV>::operator[](size_type i) const -> const_reference\n    {\n        index_type idx = xtl::make_sequence<index_type>(size_type(1), i);\n        return m_e.element(std::move(idx));\n    }\n\n    template <class RV>\n    template <class It>\n    inline auto xreindex_data<RV>::element(It first, It last) const -> const_reference\n    {\n        index_type idx = xtl::make_sequence<index_type>(static_cast<size_type>(std::distance(first, last)));\n        std::copy(first, last, idx.begin());\n        return m_e.element(std::move(idx));\n    }\n\n    template <class RV>\n    template <class S>\n    inline bool xreindex_data<RV>::braodcast_shape(S& s, bool) const\n    {\n        return xt::broadcast_shape(shape(), s);\n    }\n\n    template <class RV>\n    template <class S>\n    inline bool xreindex_data<RV>::has_linear_assign(const S& strides) const noexcept\n    {\n        return false;\n    }\n\n    template <class RV>\n    template <class S>\n    inline auto xreindex_data<RV>::stepper_begin(const S& /*shape*/) const noexcept -> const_stepper\n    {\n        return const_stepper(this, size_type(0));\n    }\n\n    template <class RV>\n    template <class S>\n    inline auto xreindex_data<RV>::stepper_end(const S& /*shape*/, xt::layout_type /*l*/) const noexcept -> const_stepper\n    {\n        return const_stepper(this, size(), true);\n    }\n}\n\n#endif\n"
  },
  {
    "path": "include/xframe/xreindex_view.hpp",
    "content": "/***************************************************************************\n* Copyright (c) Johan Mabille, Sylvain Corlay, Wolf Vollprecht and         *\n* Martin Renou                                                             *\n* Copyright (c) QuantStack                                                 *\n*                                                                          *\n* Distributed under the terms of the BSD 3-Clause License.                 *\n*                                                                          *\n* The full license is in the file LICENSE, distributed with this software. *\n****************************************************************************/\n\n#ifndef XREINDEX_VIEW_HPP\n#define XREINDEX_VIEW_HPP\n\n#include \"xtensor/xexpression.hpp\"\n\n#include \"xcoordinate_chain.hpp\"\n#include \"xreindex_data.hpp\"\n#include \"xvariable.hpp\"\n\nnamespace xf\n{\n\n    /*****************\n     * xreindex_view *\n     *****************/\n\n    template <class CT>\n    class xreindex_view : public xt::xexpression<xreindex_view<CT>>\n    {\n    public:\n\n        using self_type = xreindex_view<CT>;\n        using xexpression_type = std::decay_t<CT>;\n        using value_type = typename xexpression_type::value_type;\n        using reference = typename xexpression_type::const_reference;\n        using const_reference = reference;\n        using pointer = typename xexpression_type::const_pointer;\n        using const_pointer = pointer;\n        using size_type = typename xexpression_type::size_type;\n        using difference_type = typename xexpression_type::difference_type;\n\n        using shape_type = typename xexpression_type::shape_type;\n        using data_type = xreindex_data<self_type>;\n\n        using subcoordinate_type = typename xexpression_type::coordinate_type;\n        using coordinate_type = xcoordinate_chain<subcoordinate_type>;\n        using dimension_type = typename xexpression_type::dimension_type;\n        using dimension_list = typename dimension_type::label_list;\n        using coordinate_map = typename coordinate_type::map_type;\n\n        using expression_tag = xvariable_expression_tag;\n\n        template <std::size_t N = dynamic()>\n        using selector_traits = xselector_traits<coordinate_type, dimension_type, N>;\n        template <std::size_t N = dynamic()>\n        using index_type = typename selector_traits<N>::index_type;\n        template <std::size_t N = dynamic()>\n        using selector_type = typename selector_traits<N>::selector_type;\n        template <std::size_t N = dynamic()>\n        using selector_sequence_type = typename selector_traits<N>::selector_sequence_type;\n        template <std::size_t N = dynamic()>\n        using iselector_type = typename selector_traits<N>::iselector_type;\n        template <std::size_t N = dynamic()>\n        using iselector_sequence_type = typename selector_traits<N>::iselector_sequence_type;\n        template <std::size_t N = dynamic()>\n        using locator_type = typename selector_traits<N>::locator_type;\n        template <std::size_t N = dynamic()>\n        using locator_sequence_type = typename selector_traits<N>::locator_sequence_type;\n\n        static const_reference missing();\n\n        xreindex_view(self_type&& rhs);\n        xreindex_view(const self_type& rhs);\n\n        template <class E>\n        xreindex_view(E&& e, const coordinate_map& new_coord);\n\n        template <class E>\n        xreindex_view(E&& e, coordinate_map&& new_coord);\n\n        size_type size() const noexcept;\n        size_type dimension() const noexcept;\n        const dimension_list& dimension_labels() const noexcept;\n        const coordinate_type& coordinates() const noexcept;\n        const dimension_type& dimension_mapping() const noexcept;\n\n        template <class Join = XFRAME_DEFAULT_JOIN, class C = coordinate_type>\n        xtrivial_broadcast broadcast_coordinates(C& coords) const;\n        bool broadcast_dimensions(dimension_type& dims, bool trivial_bc = false) const;\n\n        const shape_type& shape() const noexcept;\n        const data_type& data() const noexcept;\n\n        template <class... Args>\n        const_reference operator()(Args... args) const;\n\n        template <std::size_t N = dynamic()>\n        const_reference element(const index_type<N>& index) const;\n\n        template <std::size_t N = dynamic()>\n        const_reference element(index_type<N>&& index) const;\n\n        template <class... Args>\n        const_reference locate(Args&&... args) const;\n\n        template <std::size_t N = dynamic()>\n        const_reference locate_element(const locator_sequence_type<N>& locator) const;\n\n        template <std::size_t N = dynamic()>\n        const_reference locate_element(locator_sequence_type<N>&& locator) const;\n\n        template <class Join = XFRAME_DEFAULT_JOIN, std::size_t N = std::numeric_limits<size_type>::max()>\n        const_reference select(const selector_sequence_type<N>& selector) const;\n\n        template <class Join = XFRAME_DEFAULT_JOIN, std::size_t N = dynamic()>\n        const_reference select(selector_sequence_type<N>&& selector) const;\n\n        template <std::size_t N = dynamic()>\n        const_reference iselect(const iselector_sequence_type<N>& selector) const;\n\n        template <std::size_t N = dynamic()>\n        const_reference iselect(iselector_sequence_type<N>&& selector) const;\n\n    private:\n\n        void init_shape();\n\n        template <std::size_t N, class IDX>\n        const_reference element_impl(IDX&& index) const;\n\n        template <std::size_t N, class L>\n        const_reference locate_element_impl(L&& locator) const;\n\n        template <class S>\n        const_reference select_impl(S&& selector) const;\n\n        template <class Join, class S>\n        const_reference select_join(S&& selector) const;\n\n        template <std::size_t N, class S>\n        const_reference iselect_impl(S&& selector) const;\n\n        template <std::size_t N, class S>\n        std::pair<index_type<N>, bool> build_iselect_index(S&& selector) const;\n\n        CT m_e;\n        coordinate_type m_coordinate;\n        const dimension_type& m_dimension_mapping;\n        shape_type m_shape;\n        data_type m_data;\n    };\n\n    template <class CT>\n    std::ostream& operator<<(std::ostream& out, const xreindex_view<CT>& view);\n\n    /*************************\n     * reindex_view builders *\n     *************************/\n\n    template <class E>\n    auto reindex(E&& e, const typename std::decay_t<E>::coordinate_map& new_coord);\n\n    template <class E>\n    auto reindex(E&& e, typename std::decay_t<E>::coordinate_map&& new_coord);\n\n    template <class E1, class E2>\n    auto reindex_like(E1&& e1, const E2& e2);\n\n    template <class Join, class E1, class... E>\n    auto align(E1&& e1, E&&... e);\n\n    /********************************\n     * xreindex_view implementation *\n     ********************************/\n\n    template <class CT>\n    inline xreindex_view<CT>::xreindex_view(self_type&& rhs)\n        : m_e(std::forward<decltype(rhs.m_e)>(rhs.m_e)),\n          m_coordinate(std::move(rhs.m_coordinate)),\n          m_dimension_mapping(m_e.dimension_mapping()),\n          m_data(*this)\n    {\n        init_shape();\n    }\n\n    template <class CT>\n    inline xreindex_view<CT>::xreindex_view(const self_type& rhs)\n        : m_e(rhs.m_e),\n          m_coordinate(rhs.m_coordinate),\n          m_dimension_mapping(m_e.dimension_mapping()),\n          m_data(*this)\n    {\n        init_shape();\n    }\n\n    template <class CT>\n    template <class E>\n    inline xreindex_view<CT>::xreindex_view(E&& e, const coordinate_map& new_coord)\n        : m_e(std::forward<E>(e)),\n          m_coordinate(reindex(m_e.coordinates(), new_coord)),\n          m_dimension_mapping(m_e.dimension_mapping()),\n          m_data(*this)\n    {\n        init_shape();\n    }\n\n    template <class CT>\n    template <class E>\n    inline xreindex_view<CT>::xreindex_view(E&& e, coordinate_map&& new_coord)\n        : m_e(std::forward<E>(e)),\n          m_coordinate(reindex(m_e.coordinates(), std::move(new_coord))),\n          m_dimension_mapping(m_e.dimension_mapping()),\n          m_data(*this)\n    {\n        init_shape();\n    }\n\n    template <class CT>\n    inline auto xreindex_view<CT>::missing() -> const_reference\n    {\n        return detail::static_missing<const_reference>();\n    }\n\n    template <class CT>\n    inline auto xreindex_view<CT>::size() const noexcept -> size_type\n    {\n        return std::accumulate(m_coordinate.cbegin(), m_coordinate.cend(), size_type(1),\n            [](size_type val, auto&& entry) { return val * entry.second.size(); });\n    }\n\n    template <class CT>\n    inline auto xreindex_view<CT>::dimension() const noexcept -> size_type\n    {\n        return m_dimension_mapping.size();\n    }\n\n    template <class CT>\n    inline auto xreindex_view<CT>::dimension_labels() const noexcept -> const dimension_list&\n    {\n        return m_dimension_mapping.labels();\n    }\n\n    template <class CT>\n    inline auto xreindex_view<CT>::coordinates() const noexcept -> const coordinate_type&\n    {\n        return m_coordinate;\n    }\n\n    template <class CT>\n    inline auto xreindex_view<CT>::dimension_mapping() const noexcept -> const dimension_type&\n    {\n        return m_dimension_mapping;\n    }\n\n    template <class CT>\n    template <class Join, class C>\n    inline xtrivial_broadcast xreindex_view<CT>::broadcast_coordinates(C& coords) const\n    {\n        return xf::broadcast_coordinates<Join>(coords, this->coordinates());\n    }\n\n    template <class CT>\n    inline bool xreindex_view<CT>::broadcast_dimensions(dimension_type& dims, bool trivial_bc) const\n    {\n        bool ret = true;\n        if (trivial_bc)\n        {\n            dims = this->dimension_mapping();\n        }\n        else\n        {\n            ret = xf::broadcast_dimensions(dims, this->dimension_mapping());\n        }\n        return ret;\n    }\n\n    template <class CT>\n    inline auto xreindex_view<CT>::shape() const noexcept -> const shape_type&\n    {\n        return m_shape;\n    }\n\n    template <class CT>\n    inline auto xreindex_view<CT>::data() const noexcept -> const data_type&\n    {\n        return m_data;\n    }\n\n    template <class CT>\n    template <class... Args>\n    inline auto xreindex_view<CT>::operator()(Args... args) const -> const_reference\n    {\n        constexpr std::size_t N = sizeof...(Args);\n        using index_value_type = typename index_type<N>::value_type;\n        return element({static_cast<index_value_type>(args)...});\n    }\n\n    template <class CT>\n    template <std::size_t N>\n    inline auto xreindex_view<CT>::element(const index_type<N>& index) const -> const_reference\n    {\n        return element_impl<N>(index);\n    }\n\n    template <class CT>\n    template <std::size_t N>\n    inline auto xreindex_view<CT>::element(index_type<N>&& index) const -> const_reference\n    {\n        return element_impl<N>(std::move(index));\n    }\n\n    template <class CT>\n    template <class... Args>\n    inline auto xreindex_view<CT>::locate(Args&&... args) const -> const_reference\n    {\n        constexpr std::size_t N = sizeof...(Args);\n        using loc_value_type = typename locator_sequence_type<N>::value_type;\n        return locate_element_impl<N>(locator_sequence_type<N>{loc_value_type(args)...});\n    }\n\n    template <class CT>\n    template <std::size_t N>\n    inline auto xreindex_view<CT>::locate_element(const locator_sequence_type<N>& locator) const -> const_reference\n    {\n        return locate_element_impl<N>(locator);\n    }\n\n    template <class CT>\n    template <std::size_t N>\n    inline auto xreindex_view<CT>::locate_element(locator_sequence_type<N>&& locator) const -> const_reference\n    {\n        return locate_element_impl<N>(std::move(locator));\n    }\n\n    template <class CT>\n    template <class Join, std::size_t N>\n    inline auto xreindex_view<CT>::select(const selector_sequence_type<N>& selector) const -> const_reference\n    {\n        return select_join<Join>(selector);\n    }\n\n    template <class CT>\n    template <class Join, std::size_t N>\n    inline auto xreindex_view<CT>::select(selector_sequence_type<N>&& selector) const -> const_reference\n    {\n        return select_join<Join>(std::move(selector));\n    }\n\n    template <class CT>\n    template <std::size_t N>\n    inline auto xreindex_view<CT>::iselect(const iselector_sequence_type<N>& selector) const -> const_reference\n    {\n        return iselect_impl<N>(selector);\n    }\n\n    template <class CT>\n    template <std::size_t N>\n    inline auto xreindex_view<CT>::iselect(iselector_sequence_type<N>&& selector) const -> const_reference\n    {\n        return iselect_impl<N>(std::move(selector));\n    }\n\n    template <class CT>\n    inline void xreindex_view<CT>::init_shape()\n    {\n        size_type dim = dimension();\n        m_shape.resize(dim);\n        for(size_type i = 0; i < dim; ++i)\n        {\n            m_shape[i] = coordinates().find(dimension_labels()[i])->second.size();\n        }\n    }\n\n    template <class CT>\n    template <std::size_t N, class IDX>\n    inline auto xreindex_view<CT>::element_impl(IDX&& index) const -> const_reference\n    {\n        bool contained = true;\n        for(std::size_t i = 0; i < index.size(); ++i)\n        {\n            auto dim_name = m_dimension_mapping.label(i);\n            auto iter = m_coordinate.reindex_map().find(dim_name);\n            if(iter != m_coordinate.reindex_map().end())\n            {\n                auto label = (iter->second).label(index[i]);\n                auto subiter = m_coordinate.initial_coordinates().find(dim_name);\n                auto subindex = (subiter->second).find(label);\n                if(subindex == (subiter->second).end())\n                {\n                    contained = false;\n                    break;\n                }\n                else\n                {\n                    index[i] = subindex->second;\n                }\n            }\n        }\n        return contained ? m_e.template element<N>(std::forward<IDX>(index)) : missing();\n    }\n\n    template <class CT>\n    template <std::size_t N, class L>\n    inline auto xreindex_view<CT>::locate_element_impl(L&& locator) const -> const_reference\n    {\n        for(std::size_t i = 0; i < locator.size(); ++i)\n        {\n            auto dim_name = m_dimension_mapping.label(i);\n            bool contained = m_coordinate.is_reindexed(dim_name, locator[i]);\n            bool sub_contained = m_coordinate.initial_coordinates().contains(dim_name, locator[i]);\n            if(contained && !sub_contained)\n            {\n                return missing();\n            }\n        }\n        return m_e.template locate_element<N>(std::forward<L>(locator));\n    }\n\n    template <class CT>\n    template <class S>\n    inline auto xreindex_view<CT>::select_impl(S&& selector) const -> const_reference\n    {\n        for(const auto& c: selector)\n        {\n            bool contained = m_coordinate.is_reindexed(c.first, c.second);\n            bool sub_contained = m_e.coordinates().contains(c.first, c.second);\n            if(contained && !sub_contained)\n            {\n                return missing();\n            }\n        }\n        return m_e.select(std::forward<S>(selector));\n    }\n\n    template <class CT>\n    template <class Join, class S>\n    inline auto xreindex_view<CT>::select_join(S&& selector) const -> const_reference\n    {\n        return xtl::mpl::static_if<Join::id() == join::inner::id()>([&](auto self)\n        {\n            return self(*this).select_impl(std::forward<S>(selector));\n        }, /*else*/ [&](auto self)\n        {\n            return self(*this).m_e.template select<join::outer>(std::forward<S>(selector));\n        });\n    }\n\n    template <class CT>\n    template <std::size_t N, class S>\n    inline auto xreindex_view<CT>::iselect_impl(S&& iselector) const -> const_reference\n    {\n        auto outer_index = build_iselect_index<N>(std::forward<S>(iselector));\n        return outer_index.second ? m_e.element(outer_index.first) : missing();\n    }\n\n    template <class CT>\n    template <std::size_t N, class S>\n    inline auto xreindex_view<CT>::build_iselect_index(S&& selector) const -> std::pair<index_type<N>, bool>\n    {\n        auto res = std::make_pair(xtl::make_sequence<index_type<N>>(dimension(), size_type(0)), true);\n        auto reindex_end = m_coordinate.reindex_map().end();\n        for(const auto& c: selector)\n        {\n            auto iter = m_coordinate.reindex_map().find(c.first);\n            if(iter != reindex_end)\n            {\n                auto label = (iter->second).label(c.second);\n                auto subiter = m_coordinate.initial_coordinates().find(c.first);\n                auto subindex = (subiter->second).find(label);\n                if(subindex == (subiter->second).end())\n                {\n                    res.second = false;\n                    break;\n                }\n                else\n                {\n                    res.first[m_dimension_mapping[c.first]] = subindex->second;\n                }\n            }\n            else\n            {\n                res.first[m_dimension_mapping[c.first]] = c.second;\n            }\n        }\n        return res;\n    }\n\n    /****************************************\n     * reindex_view builders implementation *\n     ****************************************/\n\n    template <class E>\n    inline auto reindex(E&& e, const typename std::decay_t<E>::coordinate_map& new_coord)\n    {\n        using view_type = xreindex_view<xtl::closure_type_t<E>>;\n        return view_type(std::forward<E>(e), new_coord);\n    }\n\n    template <class E>\n    inline auto reindex(E&& e, typename std::decay_t<E>::coordinate_map&& new_coord)\n    {\n        using view_type = xreindex_view<xtl::closure_type_t<E>>;\n        return view_type(std::forward<E>(e), std::move(new_coord));\n    }\n\n    namespace detail\n    {\n        template <class E1, class C>\n        inline auto reindex_like_coord(E1&& e1, const C& coords)\n        {\n            using view_type = xreindex_view<xtl::closure_type_t<E1>>;\n            using coordinate_map = typename view_type::coordinate_map;\n\n            coordinate_map new_coord;\n            for(auto iter = e1.coordinates().begin(); iter != e1.coordinates().end(); ++iter)\n            {\n                const auto& axis = coords[iter->first];\n                if(axis != iter->second)\n                {\n                    new_coord.insert(std::make_pair(iter->first, axis));\n                }\n            }\n            return view_type(std::forward<E1>(e1), std::move(new_coord));\n        }\n    }\n\n    template <class E1, class E2>\n    inline auto reindex_like(E1&& e1, const E2& e2)\n    {\n        return detail::reindex_like_coord(std::forward<E1>(e1), e2.coordinates());\n    }\n\n    template <class Join, class E1, class... E>\n    inline auto align(E1&& e1, E&&... e)\n    {\n        auto coord = e1.coordinates();\n        broadcast_coordinates<Join>(coord, e.coordinates()...);\n        return std::make_tuple(detail::reindex_like_coord(std::forward<E1>(e1), coord),\n                               detail::reindex_like_coord(std::forward<E>(e), coord)...);\n    }\n\n    template <class CT>\n    inline std::ostream& operator<<(std::ostream& out, const xreindex_view<CT>& view)\n    {\n        return print_variable_expression(out, view);\n    }\n}\n\n#endif\n"
  },
  {
    "path": "include/xframe/xselecting.hpp",
    "content": "/***************************************************************************\n* Copyright (c) Johan Mabille, Sylvain Corlay, Wolf Vollprecht and         *\n* Martin Renou                                                             *\n* Copyright (c) QuantStack                                                 *\n*                                                                          *\n* Distributed under the terms of the BSD 3-Clause License.                 *\n*                                                                          *\n* The full license is in the file LICENSE, distributed with this software. *\n****************************************************************************/\n\n#ifndef XFRAME_XSELECTING_HPP\n#define XFRAME_XSELECTING_HPP\n\n#include <limits>\n\n#include \"xtl/xmasked_value.hpp\"\n#include \"xtl/xsequence.hpp\"\n#include \"xtl/xoptional.hpp\"\n\n#include \"xframe_utils.hpp\"\n#include \"xcoordinate.hpp\"\n#include \"xdimension.hpp\"\n\nnamespace xf\n{\n    namespace mpl = xtl::mpl;\n\n    namespace detail\n    {\n        template <class T>\n        struct static_missing_impl;\n\n        template <class T, class B>\n        struct static_missing_impl<xtl::xoptional<const T&, const B&>>\n        {\n            using return_type = xtl::xoptional<const T&, const B&>;\n            static inline return_type get()\n            {\n                static T val = T(0);\n                static B has_val = false;\n                return return_type(val, has_val);\n            }\n        };\n\n        template <class T, class B>\n        struct static_missing_impl<xtl::xmasked_value<T, B>>\n        {\n            using return_type = xtl::xmasked_value<T, B>;\n            static inline return_type get()\n            {\n                static T val = static_missing_impl<T>::get();\n                static B visible = true;\n                return return_type(val, visible);\n            }\n        };\n\n        template <class T>\n        T static_missing() noexcept\n        {\n            return static_missing_impl<T>::get();\n        }\n    }\n\n    /*************\n     * xselector *\n     *************/\n\n    template <class C, class D, std::size_t N>\n    class xselector\n    {\n    public:\n\n        static_assert(is_coordinate<C>::value, \"first parameter of xselector must be xcoordinate\");\n        static_assert(is_dimension<D>::value, \"second parameter of xselector must be xdimension\");\n\n        using coordinate_type = C;\n        using key_type = typename coordinate_type::key_type;\n        using label_list = typename coordinate_type::label_list;\n        using mapped_type = mpl::cast_t<label_list, xtl::variant>;\n        using size_type = typename coordinate_type::index_type;\n        using index_type = detail::xselector_sequence_t<size_type, N>;\n        using outer_index_type = std::pair<index_type, bool>;\n        using dimension_type = D;\n        using sequence_type = detail::xselector_sequence_t<std::pair<key_type, mapped_type>, N>;\n\n        xselector() = default;\n        xselector(const sequence_type& coord);\n        xselector(sequence_type&& coord);\n\n        index_type get_index(const coordinate_type& coord, const dimension_type& dim) const;\n        outer_index_type get_outer_index(const coordinate_type& coord, const dimension_type& dim) const;\n\n    private:\n\n        sequence_type m_coord;\n    };\n\n    /**************\n     * xiselector *\n     **************/\n\n    template <class C, class D, std::size_t N>\n    class xiselector\n    {\n    public:\n\n        static_assert(is_coordinate<C>::value, \"first parameter of xiselector must be xcoordinate\");\n        static_assert(is_dimension<D>::value, \"second parameter of xiselector must be xdimension\");\n\n        using coordinate_type = C;\n        using key_type = typename coordinate_type::key_type;\n        using size_type = typename coordinate_type::index_type;\n        using index_type = detail::xselector_sequence_t<size_type, N>;\n        using dimension_type = D;\n        using sequence_type = detail::xselector_sequence_t<std::pair<key_type, size_type>, N>;\n\n        xiselector() = default;\n        xiselector(const sequence_type& coord);\n        xiselector(sequence_type&& coord);\n\n        index_type get_index(const coordinate_type& coord, const dimension_type& dim) const;\n\n    private:\n\n        sequence_type m_coord;\n    };\n\n    /************\n     * xlocator *\n     ************/\n\n    template <class C, class D, std::size_t N>\n    class xlocator\n    {\n    public:\n\n        static_assert(is_coordinate<C>::value, \"first parameter of xlocator must be xcoordinate\");\n        static_assert(is_dimension<D>::value, \"second parameter of xlocator must be xdimension\");\n\n        using coordinate_type = C;\n        using key_type = typename coordinate_type::key_type;\n        using label_list = typename coordinate_type::label_list;\n        using mapped_type = mpl::cast_t<label_list, xtl::variant>;\n        using size_type = typename coordinate_type::index_type;\n        using index_type = detail::xselector_sequence_t<size_type, N>;\n        using dimension_type = D;\n        using sequence_type = detail::xselector_sequence_t<mapped_type, N>;\n\n        xlocator() = default;\n        xlocator(const sequence_type& coord);\n        xlocator(sequence_type&& coord);\n\n        index_type get_index(const coordinate_type& coord, const dimension_type& dim) const;\n\n    private:\n\n        sequence_type m_coord;\n    };\n\n    /********************\n     * xselector_traits *\n     ********************/\n\n    template <class C, class DM, std::size_t N>\n    struct xselector_traits\n    {\n        using coordinate_type = C;\n        using dimension_type = DM;\n\n        using size_type = typename coordinate_type::index_type;\n        using index_type = detail::xselector_sequence_t<size_type, N>;\n        using selector_type = xselector<coordinate_type, dimension_type, N>;\n        using selector_sequence_type = typename selector_type::sequence_type;\n        using iselector_type = xiselector<coordinate_type, dimension_type, N>;\n        using iselector_sequence_type = typename iselector_type::sequence_type;\n        using locator_type = xlocator<coordinate_type, dimension_type, N>;\n        using locator_sequence_type = typename locator_type::sequence_type;\n\n        static constexpr std::size_t static_dimension = N;\n    };\n\n    /****************************\n     * xselector implementation *\n     ****************************/\n\n    template <class C, class D, std::size_t N>\n    inline xselector<C, D, N>::xselector(const sequence_type& coord)\n        : m_coord(coord)\n    {\n    }\n\n    template <class C, class D, std::size_t N>\n    inline xselector<C, D, N>::xselector(sequence_type&& coord)\n        : m_coord(std::move(coord))\n    {\n    }\n\n    template <class C, class D, std::size_t N>\n    inline auto xselector<C, D, N>::get_index(const coordinate_type& coord, const dimension_type& dim) const\n        -> index_type\n    {\n        index_type res = xtl::make_sequence<index_type>(dim.size(), size_type(0));\n        for(const auto& c : m_coord)\n        {\n            auto iter = dim.find(c.first);\n            if(iter != dim.end())\n            {\n                res[iter->second] = coord[c.first][c.second];\n            }\n        }\n        return res;\n    }\n\n    template <class C, class D, std::size_t N>\n    inline auto xselector<C, D, N>::get_outer_index(const coordinate_type& coord, const dimension_type& dim) const\n        -> outer_index_type\n    {\n        outer_index_type res(xtl::make_sequence<index_type>(dim.size(), size_type(0)), true);\n        for(const auto& c : m_coord)\n        {\n            auto iter = dim.find(c.first);\n            if(iter != dim.end())\n            {\n                const auto& axis = coord[c.first];\n                if(axis.contains(c.second))\n                {\n                    res.first[iter->second]= axis[c.second];\n                }\n                else\n                {\n                    res.second = false;\n                    break;\n                }\n            }\n        }\n        return res;\n    }\n\n    /*****************************\n     * xiselector implementation *\n     *****************************/\n\n    template <class C, class D, std::size_t N>\n    inline xiselector<C, D, N>::xiselector(const sequence_type& coord)\n        : m_coord(coord)\n    {\n    }\n\n    template <class C, class D, std::size_t N>\n    inline xiselector<C, D, N>::xiselector(sequence_type&& coord)\n        : m_coord(std::move(coord))\n    {\n    }\n\n    template <class C, class D, std::size_t N>\n    inline auto xiselector<C, D, N>::get_index(const coordinate_type& /*coord*/, const dimension_type& dim) const\n        -> index_type\n    {\n        index_type res = xtl::make_sequence<index_type>(dim.size(), size_type(0));\n        for(const auto& c : m_coord)\n        {\n            auto iter = dim.find(c.first);\n            if (iter != dim.end())\n            {\n                res[iter->second] = c.second;\n            }\n        }\n        return res;\n    }\n\n    /***************************\n     * xlocator implementation *\n     ***************************/\n\n    template <class C, class D, std::size_t N>\n    inline xlocator<C, D, N>::xlocator(const sequence_type& coord)\n        : m_coord(coord)\n    {\n    }\n\n    template <class C, class D, std::size_t N>\n    inline xlocator<C, D, N>::xlocator(sequence_type&& coord)\n        : m_coord(std::move(coord))\n    {\n    }\n\n    template <class C, class D, std::size_t N>\n    inline auto xlocator<C, D, N>::get_index(const coordinate_type& coord, const dimension_type& dim) const\n        -> index_type\n    {\n        index_type res = xtl::make_sequence<index_type>(dim.size(), size_type(0));\n        for (std::size_t i = 0; i < m_coord.size(); ++i)\n        {\n            res[i] = coord[dim.labels()[i]][m_coord[i]];\n        }\n        return res;\n    }\n\n}\n\n#endif\n"
  },
  {
    "path": "include/xframe/xsequence_view.hpp",
    "content": "/***************************************************************************\n* Copyright (c) Johan Mabille, Sylvain Corlay, Wolf Vollprecht and         *\n* Martin Renou                                                             *\n* Copyright (c) QuantStack                                                 *\n*                                                                          *\n* Distributed under the terms of the BSD 3-Clause License.                 *\n*                                                                          *\n* The full license is in the file LICENSE, distributed with this software. *\n****************************************************************************/\n\n#ifndef XFRAME_XSEQUENCE_VIEW_HPP\n#define XFRAME_XSEQUENCE_VIEW_HPP\n\n#include <algorithm>\n#include \"xtl/xiterator_base.hpp\"\n\nnamespace xf\n{\n\n    template <class C, class S, bool is_const>\n    class xsequence_view_iterator;\n\n    /******************\n     * xsequence_view *\n     ******************/\n\n    template <class C, class S>\n    class xsequence_view\n    {\n    public:\n\n        using self_type = xsequence_view<C, S>;\n        using container_type = C;\n        using slice_type = S;\n\n        static constexpr bool is_const = std::is_const<std::remove_reference_t<C>>::value;\n        using value_type = typename container_type::value_type;\n        using reference = std::conditional_t<is_const,\n                                             typename container_type::const_reference,\n                                             typename container_type::reference>;\n        using const_reference = typename container_type::const_reference;\n        using pointer = typename container_type::pointer;\n        using const_pointer = std::conditional_t<is_const,\n                                                 typename container_type::const_pointer,\n                                                 typename container_type::pointer>;\n        using size_type = typename container_type::size_type;\n        using difference_type = typename container_type::difference_type;\n\n        using iterator = xsequence_view_iterator<C, S, false>;\n        using const_iterator = xsequence_view_iterator<C, S, true>;\n        using reverse_iterator = std::reverse_iterator<iterator>;\n        using const_reverse_iterator = std::reverse_iterator<const_iterator>;\n\n        template <class OC>\n        xsequence_view(OC&& c, slice_type slice) noexcept;\n\n        size_type size() const noexcept;\n        bool empty() const noexcept;\n\n        reference operator[](size_type i);\n        const_reference operator[](size_type i) const;\n\n        reference at(size_type i);\n        const_reference at(size_type i) const;\n\n        reference front();\n        const_reference front() const;\n\n        reference back();\n        const_reference back() const;\n\n        iterator begin() noexcept;\n        iterator end() noexcept;\n\n        const_iterator begin() const noexcept;\n        const_iterator end() const noexcept;\n\n        const_iterator cbegin() const noexcept;\n        const_iterator cend() const noexcept;\n\n        reverse_iterator rbegin() noexcept;\n        reverse_iterator rend() noexcept;\n\n        const_reverse_iterator rbegin() const noexcept;\n        const_reverse_iterator rend() const noexcept;\n\n        const_reverse_iterator crbegin() const noexcept;\n        const_reverse_iterator crend() const noexcept;\n\n    private:\n\n        container_type m_container;\n        slice_type m_slice;\n    };\n\n    template <class C, class S>\n    bool operator==(const xsequence_view<C, S>& lhs, const xsequence_view<C, S>& rhs);\n\n    template <class C, class S>\n    bool operator==(const xsequence_view<C, S>& lhs, const C& rhs);\n\n    template <class C, class S>\n    bool operator==(const C& lhs, const xsequence_view<C, S>& rhs);\n\n    template <class C, class S>\n    bool operator!=(const xsequence_view<C, S>& lhs, const xsequence_view<C, S>& rhs);\n\n    template <class C, class S>\n    bool operator!=(const xsequence_view<C, S>& lhs, const C& rhs);\n\n    template <class C, class S>\n    bool operator!=(const C& lhs, const xsequence_view<C, S>& rhs);\n\n    template <class C, class S, bool is_const>\n    struct xsequence_view_iterator_traits\n    {\n        using iterator_type = xsequence_view_iterator<C, S, is_const>;\n        using value_type = typename C::value_type;\n        using reference = std::conditional_t<is_const, typename C::const_reference, typename C::reference>;\n        using pointer = std::conditional_t<is_const, typename C::const_pointer, typename C::pointer>;\n        using difference_type = typename C::difference_type;\n    };\n\n    /***************************\n     * xsequence_view_iterator *\n     ***************************/\n\n    template <class C, class S, bool is_const>\n    class xsequence_view_iterator\n        : public xtl::xrandom_access_iterator_base2<xsequence_view_iterator_traits<C, S, is_const>>\n    {\n    public:\n\n        using self_type = xsequence_view_iterator<C, S, is_const>;\n        using base_type = xtl::xrandom_access_iterator_base2<xsequence_view_iterator_traits<C, S, is_const>>;\n        using view_type = std::conditional_t<is_const, const xsequence_view<C, S>, xsequence_view<C, S>>;\n        using slice_type = S;\n\n        using value_type = typename base_type::value_type;\n        using reference = typename base_type::reference;\n        using pointer = typename base_type::pointer;\n        using difference_type = typename base_type::difference_type;\n        using size_type = typename slice_type::size_type;\n\n        xsequence_view_iterator() = default;\n        xsequence_view_iterator(view_type* view, size_type index);\n\n        self_type& operator++();\n        self_type& operator--();\n\n        self_type& operator+=(difference_type n);\n        self_type& operator-=(difference_type n);\n\n        difference_type operator-(const self_type& rhs) const;\n\n        reference operator*() const;\n        pointer operator->() const;\n\n        bool operator==(const self_type& rhs) const;\n        bool operator<(const self_type& rhs) const;\n\n    private:\n\n        view_type* p_view;\n        size_type m_index;\n\n        // NB: another possible implementation is to store an iterator on the underlying\n        // sequence and calls step_size(m_index) on the slice to get the increment to apply\n        // to the iterator. Benchmark is required to check which method is faster.\n    };\n\n    /*********************************\n     * xsequence_view implementation *\n     *********************************/\n\n    template <class C, class S>\n    template <class OC>\n    inline xsequence_view<C, S>::xsequence_view(OC&& c, slice_type slice) noexcept\n        : m_container(std::forward<OC>(c)), m_slice(std::move(slice))\n    {\n    }\n\n    template <class C, class S>\n    inline auto xsequence_view<C, S>::size() const noexcept -> size_type\n    {\n        return m_slice.size();\n    }\n\n    template <class C, class S>\n    inline bool xsequence_view<C, S>::empty() const noexcept\n    {\n        return size() == 0;\n    }\n\n    template <class C, class S>\n    inline auto xsequence_view<C, S>::operator[](size_type i) -> reference\n    {\n        return m_container[m_slice(i)];\n    }\n\n    template <class C, class S>\n    inline auto xsequence_view<C, S>::operator[](size_type i) const -> const_reference\n    {\n        return m_container[m_slice(i)];\n    }\n\n    template <class C, class S>\n    inline auto xsequence_view<C, S>::at(size_type i) -> reference\n    {\n        return m_container.at(m_slice(i));\n    }\n\n    template <class C, class S>\n    inline auto xsequence_view<C, S>::at(size_type i) const -> const_reference\n    {\n        return m_container.at(m_slice(i));\n    }\n\n    template <class C, class S>\n    inline auto xsequence_view<C, S>::front() -> reference\n    {\n        return m_container[m_slice(0)];\n    }\n\n    template <class C, class S>\n    inline auto xsequence_view<C, S>::front() const -> const_reference\n    {\n        return m_container[m_slice(0)];\n    }\n\n    template <class C, class S>\n    inline auto xsequence_view<C, S>::back() -> reference\n    {\n        return m_container[m_slice(m_slice.size() - 1)];\n    }\n\n    template <class C, class S>\n    inline auto xsequence_view<C, S>::back() const -> const_reference\n    {\n        return m_container[m_slice(m_slice.size() - 1)];\n    }\n\n    template <class C, class S>\n    inline auto xsequence_view<C, S>::begin() noexcept -> iterator\n    {\n        return iterator(this, size_type(0));\n    }\n\n    template <class C, class S>\n    inline auto xsequence_view<C, S>::end() noexcept -> iterator\n    {\n        return iterator(this, size());\n    }\n\n    template <class C, class S>\n    inline auto xsequence_view<C, S>::begin() const noexcept -> const_iterator\n    {\n        return cbegin();\n    }\n\n    template <class C, class S>\n    inline auto xsequence_view<C, S>::end() const noexcept -> const_iterator\n    {\n        return cend();\n    }\n\n    template <class C, class S>\n    inline auto xsequence_view<C, S>::cbegin() const noexcept -> const_iterator\n    {\n        return const_iterator(this, size_type(0));\n    }\n\n    template <class C, class S>\n    inline auto xsequence_view<C, S>::cend() const noexcept -> const_iterator\n    {\n        return const_iterator(this, size());\n    }\n\n    template <class C, class S>\n    inline auto xsequence_view<C, S>::rbegin() noexcept -> reverse_iterator\n    {\n        return reverse_iterator(end());\n    }\n\n    template <class C, class S>\n    inline auto xsequence_view<C, S>::rend() noexcept -> reverse_iterator\n    {\n        return reverse_iterator(begin());\n    }\n\n    template <class C, class S>\n    inline auto xsequence_view<C, S>::rbegin() const noexcept -> const_reverse_iterator\n    {\n        return crbegin();\n    }\n\n    template <class C, class S>\n    inline auto xsequence_view<C, S>::rend() const noexcept -> const_reverse_iterator\n    {\n        return crend();\n    }\n\n    template <class C, class S>\n    inline auto xsequence_view<C, S>::crbegin() const noexcept -> const_reverse_iterator\n    {\n        return const_reverse_iterator(cend());\n    }\n\n    template <class C, class S>\n    inline auto xsequence_view<C, S>::crend() const noexcept -> const_reverse_iterator\n    {\n        return const_reverse_iterator(cbegin());\n    }\n\n    namespace detail\n    {\n        // clang complains on OSX that std::equal_to is not defined for mpark::variant\n#ifdef __APPLE__\n        template <class InputIt1, class InputIt2>\n        inline bool equal(InputIt1 first1, InputIt1 last1, InputIt2 first2)\n        {\n            for(; first1 != last1; ++first1, ++first2)\n            {\n                if(!(*first1 == *first2))\n                {\n                    return false;\n                }\n            }\n            return true;\n        }\n#endif\n        template <class C1, class C2>\n        inline bool compare_sequence_view(const C1& lhs, const C2& rhs)\n        {\n            // clang complains on OSX that std::equal_to is not defined for mpark::variant\n#ifdef __APPLE__\n            return lhs.size() == rhs.size() && detail::equal(lhs.cbegin(), lhs.cend(), rhs.cbegin());\n#else\n            return lhs.size() == rhs.size() && std::equal(lhs.cbegin(), lhs.cend(), rhs.cbegin());\n#endif\n        }\n    }\n\n    template <class C, class S>\n    inline bool operator==(const xsequence_view<C, S>& lhs, const xsequence_view<C, S>& rhs)\n    {\n        return detail::compare_sequence_view(lhs, rhs);\n    }\n\n    template <class C, class S>\n    inline bool operator==(const xsequence_view<C, S>& lhs, const C& rhs)\n    {\n        return detail::compare_sequence_view(lhs, rhs);\n    }\n\n    template <class C, class S>\n    inline bool operator==(const C& lhs, const xsequence_view<C, S>& rhs)\n    {\n        return detail::compare_sequence_view(lhs, rhs);\n    }\n\n    template <class C, class S>\n    inline bool operator!=(const xsequence_view<C, S>& lhs, const xsequence_view<C, S>& rhs)\n    {\n        return !(lhs == rhs);\n    }\n\n    template <class C, class S>\n    inline bool operator!=(const xsequence_view<C, S>& lhs, const C& rhs)\n    {\n        return !(lhs == rhs);\n    }\n\n    template <class C, class S>\n    inline bool operator!=(const C& lhs, const xsequence_view<C, S>& rhs)\n    {\n        return !(lhs == rhs);\n    }\n\n    /******************************************\n     * xsequence_view_iterator implementation *\n     ******************************************/\n\n    template <class C, class S, bool IC>\n    inline xsequence_view_iterator<C, S, IC>::xsequence_view_iterator(view_type* view, size_type index)\n        : p_view(view), m_index(index)\n    {\n    }\n\n    template <class C, class S, bool IC>\n    inline auto xsequence_view_iterator<C, S, IC>::operator++() -> self_type&\n    {\n        ++m_index;\n        return *this;\n    }\n\n    template <class C, class S, bool IC>\n    inline auto xsequence_view_iterator<C, S, IC>::operator--() -> self_type&\n    {\n        --m_index;\n        return *this;\n    }\n\n    template <class C, class S, bool IC>\n    inline auto xsequence_view_iterator<C, S, IC>::operator+=(difference_type n) -> self_type&\n    {\n        difference_type tmp = static_cast<difference_type>(m_index) + n;\n        m_index = static_cast<size_type>(tmp);\n        return *this;\n    }\n\n    template <class C, class S, bool IC>\n    inline auto xsequence_view_iterator<C, S, IC>::operator-=(difference_type n) -> self_type&\n    {\n        difference_type tmp = static_cast<difference_type>(m_index) - n;\n        m_index = static_cast<size_type>(tmp);\n        return *this;\n    }\n\n    template <class C, class S, bool IC>\n    inline auto xsequence_view_iterator<C, S, IC>::operator-(const self_type& rhs) const -> difference_type\n    {\n        return static_cast<difference_type>(m_index) - static_cast<difference_type>(rhs.m_index);\n    }\n\n    template <class C, class S, bool IC>\n    inline auto xsequence_view_iterator<C, S, IC>::operator*() const -> reference\n    {\n        return p_view->operator[](m_index);\n    }\n\n    template <class C, class S, bool IC>\n    inline auto xsequence_view_iterator<C, S, IC>::operator->() const -> pointer\n    {\n        return &(this->operator*());\n    }\n\n    template <class C, class S, bool IC>\n    inline bool xsequence_view_iterator<C, S, IC>::operator==(const self_type& rhs) const\n    {\n        return p_view == rhs.p_view && m_index == rhs.m_index;\n    }\n\n    template <class C, class S, bool IC>\n    inline bool xsequence_view_iterator<C, S, IC>::operator<(const self_type& rhs) const\n    {\n        return p_view == rhs.p_view && m_index < rhs.m_index;\n    }\n}\n\n#endif\n"
  },
  {
    "path": "include/xframe/xvariable.hpp",
    "content": "/***************************************************************************\n* Copyright (c) Johan Mabille, Sylvain Corlay, Wolf Vollprecht and         *\n* Martin Renou                                                             *\n* Copyright (c) QuantStack                                                 *\n*                                                                          *\n* Distributed under the terms of the BSD 3-Clause License.                 *\n*                                                                          *\n* The full license is in the file LICENSE, distributed with this software. *\n****************************************************************************/\n\n#ifndef XFRAME_XVARIABLE_HPP\n#define XFRAME_XVARIABLE_HPP\n\n#include \"xtensor/xoptional_assembly.hpp\"\n\n#include \"xvariable_assign.hpp\"\n#include \"xvariable_base.hpp\"\n#include \"xvariable_math.hpp\"\n\nnamespace xf\n{\n    /***********************\n     * xvariable_container *\n     ***********************/\n\n    template <class CCT, class ECT>\n    class xvariable_container;\n\n    template <class CCT, class ECT>\n    struct xvariable_inner_types<xvariable_container<CCT, ECT>>\n    {\n        using data_closure_type = ECT;\n        using coordinate_closure_type = CCT;\n        using data_type = std::remove_reference_t<ECT>;\n        using coordinate_type = std::decay_t<CCT>;\n        using key_type = typename coordinate_type::key_type;\n        using size_type = typename coordinate_type::size_type;\n        using dimension_type = xdimension<key_type, size_type>;\n        using dimension_closure_type = dimension_type;\n    };\n}\n\nnamespace xt\n{\n    template <class CCT, class ECT>\n    struct xcontainer_inner_types<xf::xvariable_container<CCT, ECT>>\n        : xf::xvariable_inner_types<xf::xvariable_container<CCT, ECT>>\n    {\n        using temporary_type = xf::xvariable_container<std::decay_t<CCT>, std::decay_t<ECT>>;\n    };\n}\n\nnamespace xf\n{\n    template <class CCT, class ECT>\n    class xvariable_container : public xvariable_base<xvariable_container<CCT, ECT>>,\n                                public xt::xcontainer_semantic<xvariable_container<CCT, ECT>>\n    {\n    public:\n\n        using self_type = xvariable_container<CCT, ECT>;\n        using base_type = xvariable_base<self_type>;\n        using semantic_base = xt::xcontainer_semantic<self_type>;\n\n        using data_type = typename base_type::data_type;\n        using data_closure_type = typename base_type::data_closure_type;\n        using coordinate_map = typename base_type::coordinate_map;\n        using coordinate_initializer = typename base_type::coordinate_initializer;\n        using dimension_list = typename base_type::dimension_list;\n        using temporary_type = typename semantic_base::temporary_type;\n\n        using expression_tag = xvariable_expression_tag;\n\n        xvariable_container() = default;\n\n        template <class C, class DM, class = enable_xvariable<C, DM>>\n        explicit xvariable_container(C&& coords, DM&& dims);\n        explicit xvariable_container(const coordinate_map& coords, const dimension_list& dims);\n        explicit xvariable_container(coordinate_map&& coords, dimension_list&& dims);\n        explicit xvariable_container(coordinate_initializer coords);\n\n        template <class D, class C, class DM, class = enable_xvariable_t<C, DM>>\n        explicit xvariable_container(D&& data, C&& coords, DM&& dims);\n\n        template <class D>\n        explicit xvariable_container(D&& data, const coordinate_map& coords, const dimension_list& dims);\n\n        template <class D>\n        explicit xvariable_container(D&& data, coordinate_map&& coords, dimension_list&& dims);\n\n        template <class D>\n        explicit xvariable_container(D&& data, coordinate_initializer coords);\n\n        xvariable_container(const xvariable_container&) = default;\n        xvariable_container& operator=(const xvariable_container&) = default;\n\n        xvariable_container(xvariable_container&&) = default;\n        xvariable_container& operator=(xvariable_container&&) = default;\n\n        template <class E>\n        xvariable_container(const xt::xexpression<E>& e);\n\n        template <class E>\n        xvariable_container& operator=(const xt::xexpression<E>& e);\n\n    private:\n\n        data_closure_type m_data;\n\n        data_type& data_impl() noexcept;\n        const data_type& data_impl() const noexcept;\n\n        friend class xvariable_base<xvariable_container<CCT, ECT>>;\n    };\n\n    template <class CCT, class ECT>\n    std::ostream& operator<<(std::ostream& out, const xvariable_container<CCT, ECT>& v);\n\n    template <class T, class CCT>\n    using xvariable = xvariable_container<CCT, XFRAME_DEFAULT_DATA_CONTAINER(T)>;\n\n    /********************************\n     * variable generator functions *\n     ********************************/\n\n    namespace detail\n    {\n        template <class D, class C, class DM>\n        struct xvariable_type1 : std::enable_if<is_coordinate_system<C, DM>::value,\n            xvariable_container<xtl::closure_type_t<C>, xtl::closure_type_t<D>>>\n        {\n        };\n\n        template <class D, class C, class DM>\n        using xvariable_type1_t = typename xvariable_type1<D, C, DM>::type;\n\n        template <class D, class C, class L>\n        struct xvariable_type2 : std::enable_if<is_coordinate_map<C>::value && is_dimension_list<L>::value,\n            xvariable_container<get_coordinate_type_t<C>, xtl::closure_type_t<D>>>\n        {\n        };\n\n        template <class D, class C, class L>\n        using xvariable_type2_t = typename xvariable_type2<D, C, L>::type;\n\n        template <class T, class C, class DM>\n        struct xvariable_type3 : std::enable_if<is_coordinate_system<C, DM>::value,\n            xvariable<T, xtl::closure_type_t<C>>>\n        {\n        };\n\n        template <class T, class C, class DM>\n        using xvariable_type3_t = typename xvariable_type3<T, C, DM>::type;\n\n        template <class T, class C, class L>\n        struct xvariable_type4 : std::enable_if<is_coordinate_map<C>::value && is_dimension_list<L>::value,\n            xvariable<T, get_coordinate_type_t<C>>>\n        {\n        };\n\n        template <class T, class C, class L>\n        using xvariable_type4_t = typename xvariable_type4<T, C, L>::type;\n    }\n\n    template <class D, class C, class DM>\n    detail::xvariable_type1_t<D, C, DM> variable(D&& data, C&& coord, DM&& dims);\n\n    template <class D, class C, class L>\n    detail::xvariable_type2_t<D, C, L> variable(D&& data, C&& coord_map, L&& dim_list);\n\n    template <class T, class C, class DM>\n    detail::xvariable_type3_t<T, C, DM> variable(C&& coord, DM&& dims);\n\n    template <class T, class C, class L>\n    detail::xvariable_type4_t<T, C, L> variable(C&& coord_map, L&& dim_list);\n\n    /**************************************\n     * xvariable_container implementation *\n     **************************************/\n\n    template <class CCT, class ECT>\n    template <class C, class DM, class>\n    inline xvariable_container<CCT, ECT>::xvariable_container(C&& coords, DM&& dims)\n        : base_type(std::forward<C>(coords), std::forward<DM>(dims)),\n          m_data(base_type::compute_shape())\n    {\n    }\n\n    template <class CCT, class ECT>\n    inline xvariable_container<CCT, ECT>::xvariable_container(const coordinate_map& coords, const dimension_list& dims)\n        : base_type(coords, dims),\n          m_data(base_type::compute_shape())\n    {\n    }\n\n    template <class CCT, class ECT>\n    inline xvariable_container<CCT, ECT>::xvariable_container(coordinate_map&& coords, dimension_list&& dims)\n        : base_type(std::move(coords), std::move(dims)),\n          m_data(base_type::compute_shape())\n    {\n    }\n\n    template <class CCT, class ECT>\n    inline xvariable_container<CCT, ECT>::xvariable_container(coordinate_initializer coords)\n        : base_type(coords),\n          m_data(base_type::compute_shape())\n    {\n    }\n\n    template <class CCT, class ECT>\n    template <class D, class C, class DM, class>\n    inline xvariable_container<CCT, ECT>::xvariable_container(D&& data, C&& coords, DM&& dims)\n        : base_type(std::forward<C>(coords), std::forward<DM>(dims)),\n          m_data(std::forward<D>(data))\n    {\n    }\n\n    template <class CCT, class ECT>\n    template <class D>\n    inline xvariable_container<CCT, ECT>::xvariable_container(D&& data, const coordinate_map& coords, const dimension_list& dims)\n        : base_type(coords, dims),\n          m_data(std::forward<D>(data))\n    {\n    }\n\n    template <class CCT, class ECT>\n    template <class D>\n    inline xvariable_container<CCT, ECT>::xvariable_container(D&& data, coordinate_map&& coords, dimension_list&& dims)\n        : base_type(std::move(coords), std::move(dims)),\n          m_data(std::forward<D>(data))\n    {\n    }\n\n    template <class CCT, class ECT>\n    template <class D>\n    inline xvariable_container<CCT, ECT>::xvariable_container(D&& data, coordinate_initializer coords)\n        : base_type(coords),\n          m_data(std::forward<D>(data))\n    {\n    }\n\n    template <class CCT, class ECT>\n    template <class E>\n    inline xvariable_container<CCT, ECT>::xvariable_container(const xt::xexpression<E>& e)\n        : base_type()\n    {\n        semantic_base::assign(e);\n    }\n\n    template <class CCT, class ECT>\n    template <class E>\n    inline auto xvariable_container<CCT, ECT>::operator=(const xt::xexpression<E>& e) -> self_type&\n    {\n        return semantic_base::assign(e);\n    }\n\n    template <class CCT, class ECT>\n    inline auto xvariable_container<CCT, ECT>::data_impl() noexcept -> data_type&\n    {\n        return m_data;\n    }\n\n    template <class CCT, class ECT>\n    inline auto xvariable_container<CCT, ECT>::data_impl() const noexcept -> const data_type&\n    {\n        return m_data;\n    }\n\n   /**************************************\n    * generator functions implementation *\n    **************************************/\n\n    template <class D, class C, class DM>\n    inline detail::xvariable_type1_t<D, C, DM> variable(D&& data, C&& coord, DM&& dims)\n    {\n        using type = detail::xvariable_type1_t<D, C, DM>;\n        return type(std::forward<D>(data), std::forward<C>(coord), std::forward<DM>(dims));\n    }\n\n    template <class D, class C, class L>\n    inline detail::xvariable_type2_t<D, C, L> variable(D&& data, C&& coord_map, L&& dim_list)\n    {\n        using type = detail::xvariable_type2_t<D, C, L>;\n        using axis_type = typename std::decay_t<C>::mapped_type;\n        using mapped_type = typename axis_type::mapped_type;\n        using dimension_type = xdimension<typename std::decay_t<L>::value_type, mapped_type>;\n        return type(std::forward<D>(data),\n                    coordinate(std::forward<C>(coord_map)),\n                    dimension_type(std::forward<L>(dim_list)));\n    }\n\n    template <class T, class C, class DM>\n    inline detail::xvariable_type3_t<T, C, DM> variable(C&& coord, DM&& dims)\n    {\n        using type = detail::xvariable_type3_t<T, C, DM>;\n        return type(std::forward<C>(coord), std::forward<DM>(dims));\n    }\n\n    template <class T, class C, class L>\n    inline detail::xvariable_type4_t<T, C, L> variable(C&& coord_map, L&& dim_list)\n    {\n        using type = detail::xvariable_type4_t<T, C, L>;\n        using axis_type = typename std::decay_t<C>::mapped_type;\n        using mapped_type = typename axis_type::mapped_type;\n        using dimension_type = xdimension<typename std::decay_t<L>::value_type, mapped_type>;\n        return type(coordinate(std::forward<C>(coord_map)),\n                    dimension_type(std::forward<L>(dim_list)));\n    }\n\n    template <class CCT, class ECT>\n    inline std::ostream& operator<<(std::ostream& out, const xvariable_container<CCT, ECT>& v)\n    {\n        return print_variable_expression(out, v);\n    }\n}\n\n#endif\n"
  },
  {
    "path": "include/xframe/xvariable_assign.hpp",
    "content": "/***************************************************************************\n* Copyright (c) Johan Mabille, Sylvain Corlay, Wolf Vollprecht and         *\n* Martin Renou                                                             *\n* Copyright (c) QuantStack                                                 *\n*                                                                          *\n* Distributed under the terms of the BSD 3-Clause License.                 *\n*                                                                          *\n* The full license is in the file LICENSE, distributed with this software. *\n****************************************************************************/\n\n#ifndef XFRAME_XVARIABLE_ASSIGN_HPP\n#define XFRAME_XVARIABLE_ASSIGN_HPP\n\n#include \"xtensor/xassign.hpp\"\n#include \"xcoordinate.hpp\"\n#include \"xframe_expression.hpp\"\n\nnamespace xt\n{\n    using xvariable_expression_tag = xf::xvariable_expression_tag;\n\n    template <>\n    class xexpression_assigner<xvariable_expression_tag>\n    {\n    public:\n\n        template <class E1, class E2>\n        static void assign_data(xexpression<E1>& e1, const xexpression<E2>& e2, bool trivial);\n\n        template <class E1, class E2>\n        static void assign_xexpression(xexpression<E1>& e1, const xexpression<E2>& e2);\n\n        template <class E1, class E2>\n        static void computed_assign(xexpression<E1>& e1, const xexpression<E2>& e2);\n\n        template <class E1, class E2, class F>\n        static void scalar_computed_assign(xexpression<E1>& e1, const E2& e2, F&& f);\n\n        template <class E1, class E2>\n        static void assert_compatible_shape(const xexpression<E1>& e1, const xexpression<E2>& e2);\n\n    private:\n\n        template <class E1, class E2>\n        static xf::xtrivial_broadcast resize(xexpression<E1>& e1, const xexpression<E2>& e2);\n\n        template <class E1, class E2>\n        static void assign_optional_tensor(xexpression<E1>& e1, const xexpression<E2>& e2, bool trivial);\n\n        template <class E1, class E2>\n        static void assign_resized_xexpression(xexpression<E1>& e1, const xexpression<E2>& e2,\n                                               xf::xtrivial_broadcast trivial);\n    };\n\n    /***************************************\n     * xexpression_assigner implementation *\n     ***************************************/\n\n    namespace detail\n    {\n        template <class IT, class ST>\n        bool increment_index(const ST& shape, IT& index)\n        {\n            using size_type = typename ST::size_type;\n            size_type i = index.size();\n            while(i != 0)\n            {\n                --i;\n                if(index[i] != shape[i] - 1)\n                {\n                    ++index[i];\n                    return false;\n                }\n                else\n                {\n                    index[i] = 0;\n                }\n            }\n            return true;\n        }\n    }\n\n    template <class E1, class E2>\n    inline void xexpression_assigner<xvariable_expression_tag>::assign_data(xexpression<E1>& e1,\n                                                                            const xexpression<E2>& e2,\n                                                                            bool /*trivial*/)\n    {\n        const auto& dim_label = e1.derived_cast().dimension_mapping().labels();\n        const auto& coords = e1.derived_cast().coordinates();\n        using size_type = typename E1::size_type;\n        std::vector<size_type> index(dim_label.size(), size_type(0));\n        using selector_sequence_type = typename E1::template selector_sequence_type<>;\n        selector_sequence_type selector(index.size());\n        bool end = false;\n        do\n        {\n            for(size_type i = 0; i < index.size(); ++i)\n            {\n                selector[i] = std::make_pair(dim_label[i], coords[dim_label[i]].label(index[i]));\n            }\n            e1.derived_cast().select(selector) = e2.derived_cast().select(selector);\n            end = detail::increment_index(e1.derived_cast().shape(), index);\n        }\n        while(!end);\n    }\n\n    template <class E1, class E2>\n    inline void xexpression_assigner<xvariable_expression_tag>::assign_xexpression(xexpression<E1>& e1,\n                                                                                   const xexpression<E2>& e2)\n    {\n        XFRAME_TRACE(\"ASSIGN EXPRESSION - BEGIN\");\n        xf::xtrivial_broadcast trivial = resize(e1, e2);\n        assign_resized_xexpression(e1, e2, trivial);\n        XFRAME_TRACE(\"ASSIGN EXPRESSION - END\" << std::endl);\n    }\n\n    template <class E1, class E2>\n    inline void xexpression_assigner<xvariable_expression_tag>::computed_assign(xexpression<E1>& e1,\n                                                                                const xexpression<E2>& e2)\n    {\n        using coordinate_type = typename E1::coordinate_type;\n        using dimension_type = typename E1::dimension_type;\n        coordinate_type c;\n        dimension_type d;\n        xf::xtrivial_broadcast trivial = e2.derived_cast().broadcast_coordinates(c);\n        bool dim_trivial = e2.derived_cast().broadcast_dimensions(d, trivial.m_same_dimensions);\n        trivial.m_same_labels &= dim_trivial;\n        if (d.size() > e1.derived_cast().dimension_mapping().size() || !trivial.m_same_labels)\n        {\n            typename E1::temporary_type tmp(std::move(c), std::move(d));\n            assign_resized_xexpression(tmp, e2, trivial);\n            e1.derived_cast().assign_temporary(std::move(tmp));\n        }\n        else\n        {\n            assign_resized_xexpression(e1, e2, trivial);\n        }\n    }\n\n    template <class E1, class E2, class F>\n    inline void xexpression_assigner<xvariable_expression_tag>::scalar_computed_assign(xexpression<E1>& e1,\n                                                                                       const E2& e2,\n                                                                                       F&& f)\n    {\n        E1& d = e1.derived_cast();\n        std::transform(d.data().cbegin(), d.data().cend(), d.data().begin(),\n            [e2, &f](const auto& v) { return f(v, e2); });\n    }\n\n    template <class E1, class E2>\n    inline void xexpression_assigner<xvariable_expression_tag>::assert_compatible_shape(const xexpression<E1>& e1,\n                                                                                        const xexpression<E2>& e2)\n    {\n        const auto& c1 = e1.derived_cast().coordinates();\n        const auto& l2 = e2.derived_cast().dimension_labels();\n        bool res = std::accumulate(l2.cbegin(), l2.cend(), true,\n            [&c1](bool res, const auto& arg) { return res && c1.contains(arg); });\n        if (!res)\n        {\n            throw std::runtime_error(\"Incompatible dimensions of expressions\");\n        }\n    }\n\n    template <class E1, class E2>\n    inline xf::xtrivial_broadcast xexpression_assigner<xvariable_expression_tag>::resize(xexpression<E1>& e1,\n                                                                                         const xexpression<E2>& e2)\n    {\n        using coordinate_type = typename E1::coordinate_type;\n        using dimension_type = typename E1::dimension_type;\n        coordinate_type c;\n        dimension_type d;\n        xf::xtrivial_broadcast res = e2.derived_cast().broadcast_coordinates(c);\n        bool dim_trivial = e2.derived_cast().broadcast_dimensions(d, res.m_same_dimensions);\n        res.m_same_labels &= dim_trivial;\n        e1.derived_cast().resize(c, d);\n        return res;\n    }\n\n    template <class E1, class E2>\n    inline void xexpression_assigner<xvariable_expression_tag>::assign_optional_tensor(xexpression<E1>& e1,\n                                                                                       const xexpression<E2>& e2,\n                                                                                       bool trivial)\n    {\n        xexpression_assigner<xoptional_expression_tag>::assign_data(e1.derived_cast().data(),\n                                                                    e2.derived_cast().data(),\n                                                                    trivial);\n    }\n\n    template <class E1, class E2>\n    inline void xexpression_assigner<xvariable_expression_tag>::assign_resized_xexpression(xexpression<E1>& e1,\n                                                                                           const xexpression<E2>& e2,\n                                                                                           xf::xtrivial_broadcast trivial)\n    {\n        if (trivial.m_same_labels)\n        {\n            assign_optional_tensor(e1, e2, trivial.m_same_dimensions);\n        }\n        else\n        {\n            assign_data(e1, e2, false);\n        }\n    }\n}\n\n#endif\n"
  },
  {
    "path": "include/xframe/xvariable_base.hpp",
    "content": "/***************************************************************************\n* Copyright (c) Johan Mabille, Sylvain Corlay, Wolf Vollprecht and         *\n* Martin Renou                                                             *\n* Copyright (c) QuantStack                                                 *\n*                                                                          *\n* Distributed under the terms of the BSD 3-Clause License.                 *\n*                                                                          *\n* The full license is in the file LICENSE, distributed with this software. *\n****************************************************************************/\n\n#ifndef XFRAME_XVARIABLE_BASE_HPP\n#define XFRAME_XVARIABLE_BASE_HPP\n\n#include \"xtensor/xnoalias.hpp\"\n\n#include \"xcoordinate_system.hpp\"\n#include \"xselecting.hpp\"\n#include \"xnamed_axis.hpp\"\n\nnamespace xf\n{\n    template <class CTV, class CTAX>\n    class xvariable_masked_view;\n\n    using xt::noalias;\n\n    template <class C, class DM>\n    struct is_coordinate_system\n    {\n        static constexpr bool value = is_coordinate<C>::value && is_dimension<DM>::value;\n    };\n\n    template <class C , class DM>\n    struct enable_xvariable\n        : std::enable_if<is_coordinate_system<C, DM>::value, xt::void_t<>>\n    {\n    };\n\n    template <class C, class DM>\n    using enable_xvariable_t = typename enable_xvariable<C, DM>::type;\n\n    template <class D>\n    struct xvariable_inner_types;\n\n    template <class D>\n    class xvariable_base : private xcoordinate_system<D>\n    {\n    public:\n\n        using self_type = xvariable_base<D>;\n        using derived_type = D;\n        using coordinate_base = xcoordinate_system<D>;\n        using inner_types = xvariable_inner_types<D>;\n\n        using data_closure_type = typename inner_types::data_closure_type;\n        using coordinate_closure_type = typename coordinate_base::coordinate_closure_type;\n        static constexpr bool is_data_const = std::is_const<std::remove_reference_t<data_closure_type>>::value;\n\n        using data_type = typename inner_types::data_type;\n        using value_type = typename data_type::value_type;\n        using reference = std::conditional_t<is_data_const,\n                                             typename data_type::const_reference,\n                                             typename data_type::reference>;\n        using const_reference = typename data_type::const_reference;\n        using pointer = std::conditional_t<is_data_const,\n                                           typename data_type::const_pointer,\n                                           typename data_type::pointer>;\n        using const_pointer = typename data_type::const_pointer;\n        using size_type = typename data_type::size_type;\n        using difference_type = typename data_type::difference_type;\n\n        using shape_type = typename data_type::shape_type;\n\n        using coordinate_type = typename coordinate_base::coordinate_type;\n        using dimension_type = typename coordinate_base::dimension_type;\n        using dimension_list = typename dimension_type::label_list;\n        using axis_type = typename coordinate_type::axis_type;\n\n        using coordinate_map = typename coordinate_type::map_type;\n        using coordinate_initializer = std::initializer_list<typename coordinate_type::value_type>;\n        using key_type = typename coordinate_map::key_type;\n\n        using named_axis_type = xnamed_axis<key_type, typename axis_type::mapped_type>;\n\n        template <std::size_t N = dynamic()>\n        using selector_traits = xselector_traits<coordinate_type, dimension_type, N>;\n        template <std::size_t N = dynamic()>\n        using index_type = typename selector_traits<N>::index_type;\n        template <std::size_t N = dynamic()>\n        using selector_type = typename selector_traits<N>::selector_type;\n        template <std::size_t N = dynamic()>\n        using selector_sequence_type = typename selector_traits<N>::selector_sequence_type;\n        template <std::size_t N = dynamic()>\n        using iselector_type = typename selector_traits<N>::iselector_type;\n        template <std::size_t N = dynamic()>\n        using iselector_sequence_type = typename selector_traits<N>::iselector_sequence_type;\n        template <std::size_t N = dynamic()>\n        using locator_type = typename selector_traits<N>::locator_type;\n        template <std::size_t N = dynamic()>\n        using locator_sequence_type = typename selector_traits<N>::locator_sequence_type;\n\n        static const_reference missing();\n\n        using coordinate_base::size;\n        using coordinate_base::dimension;\n        using coordinate_base::dimension_labels;\n        using coordinate_base::coordinates;\n        using coordinate_base::dimension_mapping;\n        using coordinate_base::broadcast_coordinates;\n        using coordinate_base::broadcast_dimensions;\n\n        const shape_type& shape() const;\n\n        void resize(const coordinate_type& coords, const dimension_type& dims);\n        void resize(coordinate_type&& coords, dimension_type&& dims);\n\n        void reshape(const coordinate_type& coords, const dimension_type& dims);\n        void reshape(coordinate_type&& coords, dimension_type&& dims);\n\n        data_type& data() noexcept;\n        const data_type& data() const noexcept;\n\n        named_axis_type operator[](const key_type& key) const;\n\n        template <class LT>\n        xnamed_axis<key_type, typename axis_type::mapped_type, hash_map_tag, XFRAME_DEFAULT_LABEL_LIST, LT> axis(const key_type& key) const;\n\n        template <class... Args>\n        reference operator()(Args... args);\n\n        template <class... Args>\n        const_reference operator()(Args... args) const;\n\n        template <std::size_t N = dynamic()>\n        reference element(const index_type<N>& index);\n\n        template <std::size_t N = dynamic()>\n        const_reference element(const index_type<N>& index) const;\n\n        template <std::size_t N = dynamic()>\n        reference element(index_type<N>&& index);\n\n        template <std::size_t N = dynamic()>\n        const_reference element(index_type<N>&& index) const;\n\n        template <class... Args>\n        reference locate(Args&&... args);\n\n        template <class... Args>\n        const_reference locate(Args&&... args) const;\n\n        template <std::size_t N = dynamic()>\n        reference locate_element(const locator_sequence_type<N>& locator);\n\n        template <std::size_t N = dynamic()>\n        const_reference locate_element(const locator_sequence_type<N>& locator) const;\n\n        template <std::size_t N = dynamic()>\n        reference locate_element(locator_sequence_type<N>&& locator);\n\n        template <std::size_t N = dynamic()>\n        const_reference locate_element(locator_sequence_type<N>&& locator) const;\n\n        template <std::size_t N = dynamic()>\n        reference select(const selector_sequence_type<N>& selector);\n\n        template <class Join = XFRAME_DEFAULT_JOIN, std::size_t N = dynamic()>\n        const_reference select(const selector_sequence_type<N>& selector) const;\n\n        template <std::size_t N = dynamic()>\n        reference select(selector_sequence_type<N>&& selector);\n\n        template <class Join = XFRAME_DEFAULT_JOIN, std::size_t N = dynamic()>\n        const_reference select(selector_sequence_type<N>&& selector) const;\n\n        template <std::size_t N = dynamic()>\n        reference iselect(const iselector_sequence_type<N>& selector);\n\n        template <std::size_t N = dynamic()>\n        const_reference iselect(const iselector_sequence_type<N>& selector) const;\n\n        template <std::size_t N = dynamic()>\n        reference iselect(iselector_sequence_type<N>&& selector);\n\n        template <std::size_t N = dynamic()>\n        const_reference iselect(iselector_sequence_type<N>&& selector) const;\n\n    protected:\n\n        xvariable_base() = default;\n        xvariable_base(coordinate_initializer coords);\n\n        template <class C, class DM, class = enable_xvariable<C, DM>>\n        xvariable_base(C&& coords, DM&& dims);\n        xvariable_base(const coordinate_map& coords, const dimension_list& dims);\n        xvariable_base(coordinate_map&& coords, dimension_list&& dims);\n\n        ~xvariable_base() = default;\n\n        xvariable_base(const xvariable_base&) = default;\n        xvariable_base& operator=(const xvariable_base&) = default;\n\n        xvariable_base(xvariable_base&&) = default;\n        xvariable_base& operator=(xvariable_base&&) = default;\n\n        typename data_type::shape_type compute_shape() const;\n\n    private:\n\n        static dimension_type make_dimension_mapping(coordinate_initializer coord);\n\n        template <class C, class DM>\n        void resize_impl(C&& coords, DM&& dims);\n\n        template <class C, class DM>\n        void reshape_impl(C&& coords, DM&& dims);\n\n        template <std::size_t... I, class... Args>\n        reference locate_impl(std::index_sequence<I...>, Args&&... args);\n\n        template <std::size_t... I, class... Args>\n        const_reference locate_impl(std::index_sequence<I...>, Args&&... args) const;\n\n        template <class S>\n        reference select_impl(const S& selector);\n\n        template <class S>\n        const_reference select_impl(const S& selector) const;\n\n        template <class S>\n        const_reference select_outer(const S& selector) const;\n\n        template <class Join, class S>\n        const_reference select_join(const S& selector) const;\n\n        derived_type& derived_cast() noexcept;\n        const derived_type& derived_cast() const noexcept;\n\n        template <class CTV, class CTAX>\n        friend class xvariable_masked_view;\n    };\n\n    /*********************************\n     * xvariable_base implementation *\n     *********************************/\n\n    template <class D>\n    template <class C, class DM, class>\n    inline xvariable_base<D>::xvariable_base(C&& coords, DM&& dims)\n        : coordinate_base(std::forward<C>(coords), std::forward<DM>(dims))\n    {\n        // TODO: add assertion on data.shape, coordinate and dimension_mapping\n        // consistency\n    }\n\n    template <class D>\n    inline xvariable_base<D>::xvariable_base(coordinate_initializer coords)\n        : xvariable_base(coordinate_type(coords), make_dimension_mapping(coords))\n    {\n    }\n\n    template <class D>\n    inline xvariable_base<D>::xvariable_base(const coordinate_map& coords, const dimension_list& dims)\n        : xvariable_base(coordinate_type(coords), dimension_type(dims))\n    {\n    }\n\n    template <class D>\n    inline xvariable_base<D>::xvariable_base(coordinate_map&& coords, dimension_list&& dims)\n        : xvariable_base(coordinate_type(std::move(coords)), dimension_type(std::move(dims)))\n    {\n    }\n\n    template <class D>\n    inline auto xvariable_base<D>::missing() -> const_reference\n    {\n        return detail::static_missing<const_reference>();\n    }\n\n    template <class D>\n    inline auto xvariable_base<D>::shape() const -> const shape_type&\n    {\n        return data().shape();\n    }\n\n    template <class D>\n    inline void xvariable_base<D>::resize(const coordinate_type& coords, const dimension_type& dims)\n    {\n        resize_impl(coords, dims);\n    }\n\n    template <class D>\n    inline void xvariable_base<D>::resize(coordinate_type&& coords, dimension_type&& dims)\n    {\n        resize_impl(std::move(coords), std::move(dims));\n    }\n\n    template <class D>\n    inline void xvariable_base<D>::reshape(const coordinate_type& coords, const dimension_type& dims)\n    {\n        reshape_impl(coords, dims);\n    }\n\n    template <class D>\n    inline void xvariable_base<D>::reshape(coordinate_type&& coords, dimension_type&& dims)\n    {\n        reshape_impl(std::move(coords), std::move(dims));\n    }\n\n    template <class D>\n    inline auto xvariable_base<D>::data() noexcept -> data_type&\n    {\n        return derived_cast().data_impl();\n    }\n\n    template <class D>\n    inline auto xvariable_base<D>::data() const noexcept -> const data_type&\n    {\n        return derived_cast().data_impl();\n    }\n\n    template <class D>\n    inline auto xvariable_base<D>::operator[](const key_type& key) const -> named_axis_type\n    {\n        return named_axis_type(key, coordinates()[key]);\n    }\n\n    template <class D>\n    template <class LT>\n    inline auto xvariable_base<D>::axis(const key_type& key) const -> xnamed_axis<key_type, typename axis_type::mapped_type, hash_map_tag, XFRAME_DEFAULT_LABEL_LIST, LT>\n    {\n        return xnamed_axis<key_type, typename axis_type::mapped_type, hash_map_tag, XFRAME_DEFAULT_LABEL_LIST, LT>(key, coordinates()[key]);\n    }\n\n    template <class D>\n    template <class... Args>\n    inline auto xvariable_base<D>::operator()(Args... args) -> reference\n    {\n        return data()(args...);\n    }\n\n    template <class D>\n    template <class... Args>\n    inline auto xvariable_base<D>::operator()(Args... args) const -> const_reference\n    {\n        return data()(args...);\n    }\n\n    template <class D>\n    template <std::size_t N>\n    inline auto xvariable_base<D>::element(const index_type<N>& index) -> reference\n    {\n        return data().element(index.cbegin(), index.cend());\n    }\n\n    template <class D>\n    template <std::size_t N>\n    inline auto xvariable_base<D>::element(const index_type<N>& index) const -> const_reference\n    {\n        return data().element(index.cbegin(), index.cend());\n    }\n\n    template <class D>\n    template <std::size_t N>\n    inline auto xvariable_base<D>::element(index_type<N>&& index) -> reference\n    {\n        return data().element(index.cbegin(), index.cend());\n    }\n\n    template <class D>\n    template <std::size_t N>\n    inline auto xvariable_base<D>::element(index_type<N>&& index) const -> const_reference\n    {\n        return data().element(index.cbegin(), index.cend());\n    }\n\n    template <class D>\n    template <class... Args>\n    inline auto xvariable_base<D>::locate(Args&&... args) -> reference\n    {\n        return locate_impl(std::make_index_sequence<sizeof...(Args)>(), std::forward<Args>(args)...);\n    }\n\n    template <class D>\n    template <class... Args>\n    inline auto xvariable_base<D>::locate(Args&&... args) const -> const_reference\n    {\n        return locate_impl(std::make_index_sequence<sizeof...(Args)>(), std::forward<Args>(args)...);\n    }\n\n    template <class D>\n    template <std::size_t N>\n    inline auto xvariable_base<D>::locate_element(const locator_sequence_type<N>& locator) -> reference\n    {\n        return select_impl(locator_type<N>(locator));\n    }\n\n    template <class D>\n    template <std::size_t N>\n    inline auto xvariable_base<D>::locate_element(const locator_sequence_type<N>& locator) const -> const_reference\n    {\n        return select_impl(locator_type<N>(locator));\n    }\n\n    template <class D>\n    template <std::size_t N>\n    inline auto xvariable_base<D>::locate_element(locator_sequence_type<N>&& locator) -> reference\n    {\n        return select_impl(locator_type<N>(std::move(locator)));\n    }\n\n    template <class D>\n    template <std::size_t N>\n    inline auto xvariable_base<D>::locate_element(locator_sequence_type<N>&& locator) const -> const_reference\n    {\n        return select_impl(locator_type<N>(std::move(locator)));\n    }\n\n    template <class D>\n    template <std::size_t N>\n    inline auto xvariable_base<D>::select(const selector_sequence_type<N>& selector) -> reference\n    {\n        return select_impl(selector_type<N>(selector));\n    }\n\n    template <class D>\n    template <class Join, std::size_t N>\n    inline auto xvariable_base<D>::select(const selector_sequence_type<N>& selector) const -> const_reference\n    {\n        return select_join<Join>(selector_type<N>(selector));\n    }\n\n    template <class D>\n    template <std::size_t N>\n    inline auto xvariable_base<D>::select(selector_sequence_type<N>&& selector) -> reference\n    {\n        return select_impl(selector_type<N>(std::move(selector)));\n    }\n\n    template <class D>\n    template <class Join, std::size_t N>\n    inline auto xvariable_base<D>::select(selector_sequence_type<N>&& selector) const -> const_reference\n    {\n        return select_join<Join>(selector_type<N>(std::move(selector)));\n    }\n\n    template <class D>\n    template <std::size_t N>\n    inline auto xvariable_base<D>::iselect(const iselector_sequence_type<N>& selector) -> reference\n    {\n        return select_impl(iselector_type<N>(selector));\n    }\n\n    template <class D>\n    template <std::size_t N>\n    inline auto xvariable_base<D>::iselect(const iselector_sequence_type<N>& selector) const -> const_reference\n    {\n        return select_impl(iselector_type<N>(selector));\n    }\n\n    template <class D>\n    template <std::size_t N>\n    inline auto xvariable_base<D>::iselect(iselector_sequence_type<N>&& selector) -> reference\n    {\n        return select_impl(iselector_type<N>(std::move(selector)));\n    }\n\n    template <class D>\n    template <std::size_t N>\n    inline auto xvariable_base<D>::iselect(iselector_sequence_type<N>&& selector) const -> const_reference\n    {\n        return select_impl(iselector_type<N>(std::move(selector)));\n    }\n\n    template <class D>\n    inline auto xvariable_base<D>::make_dimension_mapping(coordinate_initializer coord) -> dimension_type\n    {\n        dimension_list tmp(coord.size());\n        std::transform(coord.begin(), coord.end(), tmp.begin(), [](const auto& p) { return p.first; });\n        return dimension_type(std::move(tmp));\n    }\n\n    template <class D>\n    inline auto xvariable_base<D>::compute_shape() const -> typename data_type::shape_type\n    {\n        using shape_type = typename data_type::shape_type;\n        shape_type shape(dimension());\n        for (auto& c : coordinates())\n        {\n            shape[dimension_mapping()[c.first]] = c.second.size();\n        }\n        return shape;\n    }\n\n    template <class D>\n    template <class C, class DM>\n    inline void xvariable_base<D>::resize_impl(C&& coords, DM&& dims)\n    {\n        coordinate_base::resize(std::forward<C>(coords), std::forward<DM>(dims));\n        data().resize(compute_shape());\n    }\n\n    template <class D>\n    template <class C, class DM>\n    inline void xvariable_base<D>::reshape_impl(C&& coords, DM&& dims)\n    {\n        coordinate_base::resize(std::forward<C>(coords), std::forward<DM>(dims));\n        data().reshape(compute_shape());\n    }\n\n    template <class D>\n    template <std::size_t... I, class... Args>\n    inline auto xvariable_base<D>::locate_impl(std::index_sequence<I...>, Args&&... args) -> reference\n    {\n        return data()(coordinates()[dimension_mapping().labels()[I]][args]...);\n    }\n\n    template <class D>\n    template <std::size_t... I, class... Args>\n    inline auto xvariable_base<D>::locate_impl(std::index_sequence<I...>, Args&&... args) const -> const_reference\n    {\n        return data()(coordinates()[dimension_mapping().labels()[I]][args]...);\n    }\n\n    template <class D>\n    template <class S>\n    inline auto xvariable_base<D>::select_impl(const S& selector) -> reference\n    {\n        typename S::index_type idx = selector.get_index(coordinates(), dimension_mapping());\n        return data().element(idx.cbegin(), idx.cend());\n    }\n\n    template <class D>\n    template <class S>\n    inline auto xvariable_base<D>::select_impl(const S& selector) const -> const_reference\n    {\n        typename S::index_type idx = selector.get_index(coordinates(), dimension_mapping());\n        return data().element(idx.cbegin(), idx.cend());\n    }\n\n    template <class D>\n    template <class S>\n    inline auto xvariable_base<D>::select_outer(const S& selector) const -> const_reference\n    {\n        typename S::outer_index_type idx = selector.get_outer_index(coordinates(), dimension_mapping());\n        return idx.second ? data().element(idx.first.cbegin(), idx.first.cend()) : missing();\n    }\n\n    template <class D>\n    template <class Join, class S>\n    inline auto xvariable_base<D>::select_join(const S& selector) const -> const_reference\n    {\n        return xtl::mpl::static_if<Join::id() == join::inner::id()>([&](auto self)\n        {\n            return self(*this).select_impl(selector);\n        }, /*else*/ [&](auto self)\n        {\n            return self(*this).select_outer(selector);\n        });\n    }\n\n    template <class D>\n    inline auto xvariable_base<D>::derived_cast() noexcept -> derived_type&\n    {\n        return *static_cast<derived_type*>(this);\n    }\n\n    template <class D>\n    inline auto xvariable_base<D>::derived_cast() const noexcept -> const derived_type&\n    {\n        return *static_cast<const derived_type*>(this);\n    }\n}\n\n#endif\n"
  },
  {
    "path": "include/xframe/xvariable_function.hpp",
    "content": "/***************************************************************************\n* Copyright (c) Johan Mabille, Sylvain Corlay, Wolf Vollprecht and         *\n* Martin Renou                                                             *\n* Copyright (c) QuantStack                                                 *\n*                                                                          *\n* Distributed under the terms of the BSD 3-Clause License.                 *\n*                                                                          *\n* The full license is in the file LICENSE, distributed with this software. *\n****************************************************************************/\n\n#ifndef XFRAME_XVARIABLE_FUNCTION_HPP\n#define XFRAME_XVARIABLE_FUNCTION_HPP\n\n#include \"xtensor/xoptional.hpp\"\n\n#include \"xcoordinate.hpp\"\n#include \"xselecting.hpp\"\n#include \"xvariable_meta.hpp\"\n#include \"xvariable_scalar.hpp\"\n\nnamespace xf\n{\n\n    /**********************\n     * xvariable_function *\n     **********************/\n\n    namespace detail\n    {\n        template <class CT>\n        struct xvariable_data_closure\n        {\n            using data_type = decltype(std::declval<xvariable_closure_t<CT>>().data());\n            using type = xt::const_xclosure_t<data_type>;\n        };\n\n        template <class CT>\n        using xvariable_data_closure_t = typename xvariable_data_closure<CT>::type;\n    }\n\n    template <class CCT, class ECT>\n    class xvariable_container;\n\n    template <class F, class R, class... CT>\n    class xvariable_function : public xt::xexpression<xvariable_function<F, R, CT...>>\n    {\n    public:\n\n        using self_type = xvariable_function<F, R, CT...>;\n        using functor_type = std::remove_reference_t<F>;\n        using data_type = xt::xfunction<F, detail::xvariable_data_closure_t<CT>...>;\n        using value_type = R;\n        using reference = value_type;\n        using const_reference = value_type;\n        using pointer = value_type*;\n        using const_pointer = const value_type*;\n        using size_type = xt::common_size_type_t<std::decay_t<CT>...>;\n        using difference_type = xt::common_difference_type_t<std::decay_t<CT>...>;\n\n        using shape_type = typename data_type::shape_type;\n\n        using coordinate_type = xcommon_coordinate_type_t<CT...>;\n        using dimension_type = xcommon_dimension_type_t<CT...>;\n        using dimension_list = typename dimension_type::label_list;\n\n        using temporary_type = xvariable_container<coordinate_type, XFRAME_DEFAULT_DATA_CONTAINER(value_type)>;\n\n        template <std::size_t N = dynamic()>\n        using selector_type = xselector<coordinate_type, dimension_type, N>;\n        template <std::size_t N = dynamic()>\n        using selector_sequence_type = typename selector_type<N>::sequence_type;\n\n        using expression_tag = xvariable_expression_tag;\n\n        template <class Func, class U = std::enable_if<!std::is_base_of<Func, self_type>::value>>\n        xvariable_function(Func&& f, CT... e) noexcept;\n\n        template <class Join = XFRAME_DEFAULT_JOIN>\n        size_type size() const noexcept;\n\n        template <class Join = XFRAME_DEFAULT_JOIN>\n        size_type dimension() const noexcept;\n\n        template <class Join = XFRAME_DEFAULT_JOIN>\n        const dimension_list& dimension_labels() const;\n\n        template <class Join = XFRAME_DEFAULT_JOIN>\n        const coordinate_type& coordinates() const;\n\n        template <class Join = XFRAME_DEFAULT_JOIN>\n        const dimension_type& dimension_mapping() const;\n\n        template <class Join = XFRAME_DEFAULT_JOIN>\n        xtrivial_broadcast broadcast_coordinates(coordinate_type& coords) const;\n        bool broadcast_dimensions(dimension_type& dims, bool trivial_bc = false) const;\n\n        shape_type shape() const noexcept;\n        data_type data() const noexcept;\n\n        template <class... Args>\n        const_reference operator()(Args... args) const;\n\n        template <class Join = XFRAME_DEFAULT_JOIN, std::size_t N = std::numeric_limits<size_type>::max()>\n        const_reference select(const selector_sequence_type<N>& selector) const;\n\n        template <class Join = XFRAME_DEFAULT_JOIN, std::size_t N = dynamic()>\n        const_reference select(selector_sequence_type<N>&& selector) const;\n\n        const std::tuple<xvariable_closure_t<CT>...>& arguments() const { return m_e; }\n\n    private:\n\n        template <class Join>\n        void compute_coordinates() const;\n\n        template <std::size_t... I, class... Args>\n        const_reference access_impl(std::index_sequence<I...>, Args... args) const;\n\n        template <std::size_t... I>\n        data_type data_impl(std::index_sequence<I...>) const noexcept;\n\n        template <class Join, std::size_t... I, class S>\n        const_reference select_impl(std::index_sequence<I...>, S&& selector) const;\n\n        template <std::size_t...I>\n        bool merge_dimension_mapping(std::index_sequence<I...>, dimension_type& dims) const;\n\n        std::tuple<xvariable_closure_t<CT>...> m_e;\n        functor_type m_f;\n        mutable coordinate_type m_coordinate;\n        mutable dimension_type m_dimension_mapping;\n        mutable join::join_id m_join_id;\n        mutable bool m_coordinate_computed;\n        mutable xtrivial_broadcast m_trivial_broadcast;\n    };\n\n    template <class F, class R, class... CT>\n    std::ostream& operator<<(std::ostream& out, const xvariable_function<F, R, CT...>& f);\n\n    /*************************************\n     * xvariable_function implementation *\n     *************************************/\n\n    template <class F, class R, class... CT>\n    template <class Func, class>\n    inline xvariable_function<F, R, CT...>::xvariable_function(Func&& f, CT... e) noexcept\n        : m_e(e...),\n          m_f(std::forward<Func>(f)),\n          m_coordinate(),\n          m_dimension_mapping(),\n          m_join_id(join::inner::id()),\n          m_coordinate_computed(false)\n    {\n    }\n\n    template <class F, class R, class... CT>\n    template <class Join>\n    inline auto xvariable_function<F, R, CT...>::size() const noexcept -> size_type\n    {\n        const coordinate_type& coords = coordinates<Join>();\n        return std::accumulate(coords.begin(), coords.end(), size_type(1),\n                [](size_type init, auto&& arg) { return init * arg.second.size(); });\n    }\n\n    template <class F, class R, class... CT>\n    template <class Join>\n    inline auto xvariable_function<F, R, CT...>::dimension() const noexcept -> size_type\n    {\n        const coordinate_type& coords = coordinates<Join>();\n        return coords.size();\n    }\n\n    template <class F, class R, class... CT>\n    template <class Join>\n    inline auto xvariable_function<F, R, CT...>::dimension_labels() const-> const dimension_list&\n    {\n        return dimension_mapping<Join>().labels();\n    }\n\n    template <class F, class R, class... CT>\n    template <class Join>\n    inline auto xvariable_function<F, R, CT...>::coordinates() const -> const coordinate_type&\n    {\n        compute_coordinates<Join>();\n        return m_coordinate;\n    }\n\n    template <class F, class R, class... CT>\n    template <class Join>\n    inline auto xvariable_function<F, R, CT...>::dimension_mapping() const -> const dimension_type&\n    {\n        compute_coordinates<Join>();\n        return m_dimension_mapping;\n    }\n\n    template <class F, class R, class... CT>\n    template <class Join>\n    inline xtrivial_broadcast xvariable_function<F, R, CT...>::broadcast_coordinates(coordinate_type& coords) const\n    {\n        auto func = [&coords](xtrivial_broadcast trivial, const auto& arg) {\n            return arg.template broadcast_coordinates<Join>(coords) && trivial;\n        };\n        return xt::accumulate(func, xtrivial_broadcast(true, true), m_e);\n    }\n\n    namespace detail\n    {\n        template <class T, std::size_t I, bool C>\n        struct first_non_scalar_impl\n        {\n            using elem_type = std::tuple_element_t<I, T>;\n\n            static const elem_type& get(const T& t) noexcept\n            {\n                return std::get<I>(t);\n            }\n        };\n\n        template <class T, std::size_t I>\n        struct first_non_scalar_impl<T, I, false>\n            : first_non_scalar_impl<T, I + 1, !is_xvariable_scalar<std::tuple_element_t<I+1, T>>::value>\n        {\n        };\n\n        template <class T>\n        struct first_non_scalar\n            : first_non_scalar_impl<T, 0, !is_xvariable_scalar<std::tuple_element_t<0, T>>::value>\n        {\n        };\n\n        template <class T>\n        inline auto get_first_non_scalar(const T& t) noexcept\n        {\n            return first_non_scalar<T>::get(t);\n        }\n    }\n\n    template <class F, class R, class... CT>\n    inline bool xvariable_function<F, R, CT...>::broadcast_dimensions(dimension_type& dims, bool trivial_bc) const\n    {\n        bool ret = true;\n        if(trivial_bc)\n        {\n            dims = detail::get_first_non_scalar(m_e).dimension_mapping();\n        }\n        else\n        {\n            ret = merge_dimension_mapping(std::make_index_sequence<sizeof...(CT)>(), dims);\n        }\n        return ret;\n    }\n\n    template <class F, class R, class... CT>\n    inline auto xvariable_function<F, R, CT...>::shape() const noexcept -> shape_type\n    {\n        return data().shape();\n    }\n\n    template <class F, class R, class... CT>\n    inline auto xvariable_function<F, R, CT...>::data() const noexcept -> data_type\n    {\n        return data_impl(std::make_index_sequence<sizeof...(CT)>());\n    }\n\n    template <class F, class R, class... CT>\n    template <class... Args>\n    inline auto xvariable_function<F, R, CT...>::operator()(Args... args) const -> const_reference\n    {\n        return access_impl(std::make_index_sequence<sizeof...(CT)>(), static_cast<size_type>(args)...);\n    }\n\n    template <class F, class R, class... CT>\n    template <class Join, std::size_t N>\n    inline auto xvariable_function<F, R, CT...>::select(const selector_sequence_type<N>& selector) const -> const_reference\n    {\n        return select_impl<Join>(std::make_index_sequence<sizeof...(CT)>(), selector);\n    }\n\n    template <class F, class R, class... CT>\n    template <class Join, std::size_t N>\n    inline auto xvariable_function<F, R, CT...>::select(selector_sequence_type<N>&& selector) const -> const_reference\n    {\n        return select_impl<Join>(std::make_index_sequence<sizeof...(CT)>(), std::move(selector));\n    }\n\n    template <class F, class R, class... CT>\n    template <class Join>\n    inline void xvariable_function<F, R, CT...>::compute_coordinates() const\n    {\n        if(!m_coordinate_computed || m_join_id != Join::id())\n        {\n            m_coordinate.clear();\n            m_trivial_broadcast = broadcast_coordinates<Join>(m_coordinate);\n            broadcast_dimensions(m_dimension_mapping, m_trivial_broadcast.m_same_dimensions);\n            m_coordinate_computed = true;\n            m_join_id = Join::id();\n        }\n    }\n\n    template <class F, class R, class... CT>\n    template <std::size_t... I, class... Args>\n    inline auto xvariable_function<F, R, CT...>::access_impl(std::index_sequence<I...>, Args... args) const -> const_reference\n    {\n        return m_f(std::get<I>(m_e)(args...)...);\n    }\n\n    template <class F, class R, class... CT>\n    template <std::size_t... I>\n    inline auto xvariable_function<F, R, CT...>::data_impl(std::index_sequence<I...>) const noexcept -> data_type\n    {\n        return data_type(m_f, std::get<I>(m_e).data()...);\n    }\n\n    template <class F, class R, class... CT>\n    template <class Join, std::size_t... I, class S>\n    inline auto xvariable_function<F, R, CT...>::select_impl(std::index_sequence<I...>, S&& selector) const -> const_reference\n    {\n        return m_f(std::get<I>(m_e).template select<Join>(selector)...);\n    }\n\n    template <class F, class R, class... CT>\n    template <std::size_t...I>\n    bool xvariable_function<F, R, CT...>::merge_dimension_mapping(std::index_sequence<I...>, dimension_type& dims) const\n    {\n        return xf::broadcast_dimensions(dims, std::get<I>(m_e).dimension_mapping()...);\n    }\n\n    template <class F, class R, class... CT>\n    inline std::ostream& operator<<(std::ostream& out, const xvariable_function<F, R, CT...>& f)\n    {\n        using temporary_type = typename xvariable_function<F, R, CT...>::temporary_type;\n        temporary_type tmp(f);\n        return print_variable_expression(out, tmp);\n    }\n}\n\n#endif\n"
  },
  {
    "path": "include/xframe/xvariable_masked_view.hpp",
    "content": "/***************************************************************************\n* Copyright (c) Johan Mabille, Sylvain Corlay, Wolf Vollprecht and         *\n* Martin Renou                                                             *\n* Copyright (c) QuantStack                                                 *\n*                                                                          *\n* Distributed under the terms of the BSD 3-Clause License.                 *\n*                                                                          *\n* The full license is in the file LICENSE, distributed with this software. *\n****************************************************************************/\n\n#ifndef XFRAME_XWHERE_VIEW_HPP\n#define XFRAME_XWHERE_VIEW_HPP\n\n#include \"xtensor/xgenerator.hpp\"\n#include \"xtensor/xmasked_view.hpp\"\n\n#include \"xframe_utils.hpp\"\n#include \"xselecting.hpp\"\n#include \"xframe_config.hpp\"\n#include \"xvariable_base.hpp\"\n\nnamespace xf\n{\n\n    /**************************\n     * xvariable_masked_view  *\n     **************************/\n\n    template <class CTV, class CTAX>\n    class xvariable_masked_view;\n\n    template <class CTV, class CTAX>\n    struct xvariable_inner_types<xvariable_masked_view<CTV, CTAX>>\n    {\n        using xvariable_expression_type = std::remove_reference_t<CTV>;\n        using xaxis_expression_type = std::remove_reference_t<CTAX>;\n\n        using coordinate_type = typename xvariable_expression_type::coordinate_type;\n        using coordinate_closure_type = coordinate_type;\n        using dimension_type = typename xvariable_expression_type::dimension_type;\n        using dimension_closure_type = dimension_type;\n\n        using inner_data_type = typename xvariable_expression_type::data_type;\n\n        using axis_func_impl = detail::axis_function_mask_impl<xaxis_expression_type&, const dimension_type&>;\n        using mask_type = xt::xgenerator<axis_func_impl, typename axis_func_impl::value_type, typename xvariable_expression_type::shape_type>;\n        using data_type = xt::xmasked_view<inner_data_type&, mask_type>;\n        using data_closure_type = data_type;\n\n        using key_type = typename coordinate_type::key_type;\n        using size_type = typename coordinate_type::size_type;\n        using label_list = typename coordinate_type::label_list;\n    };\n\n}\n\nnamespace xt\n{\n    template <class CTV, class CTAX>\n    struct xcontainer_inner_types<xf::xvariable_masked_view<CTV, CTAX>>\n        : xf::xvariable_inner_types<xf::xvariable_masked_view<CTV, CTAX>>\n    {\n        using base_type = xf::xvariable_inner_types<xf::xvariable_masked_view<CTV, CTAX>>;\n\n        using xvariable_expression_type = typename base_type::xvariable_expression_type;\n\n        using data_type = typename base_type::data_type;\n        using inner_data_type = typename base_type::inner_data_type;\n\n        using xaxis_expression_type = typename base_type::xaxis_expression_type;\n        using temporary_coordinate_type = xf::xcoordinate<typename base_type::key_type,\n                                                          typename base_type::label_list,\n                                                          typename base_type::size_type>;\n        using temporary_data_type = typename xvariable_expression_type::temporary_type::data_type;\n        using temporary_type = xf::xvariable_container<temporary_coordinate_type, temporary_data_type>;\n    };\n}\n\nnamespace xf\n{\n\n    /************************************\n     * xvariable_masked_view definition *\n     ************************************/\n\n    /**\n     * @class xvariable_masked_view\n     * @brief View on a variable which will apply a mask on the variable, given\n     * an expression on the axes.\n     *\n     * The xvariable_masked_view class is used for applying a mask on a variable,\n     * avoiding assignment to masked values when assigning a scalar or an other\n     * variable to the view. The mask is created given an expression on the axes.\n     *\n     * @tparam CTV the closure type on the underlying variable.\n     * @tparam CTAX the closure type on the axes function.\n     */\n    template <class CTV, class CTAX>\n    class xvariable_masked_view : public xt::xview_semantic<xvariable_masked_view<CTV, CTAX>>,\n                                  private xvariable_base<xvariable_masked_view<CTV, CTAX>>\n    {\n    public:\n\n        using self_type = xvariable_masked_view<CTV, CTAX>;\n        using base_type = xvariable_base<self_type>;\n        using semantic_base = xt::xview_semantic<self_type>;\n\n        using inner_types = xt::xcontainer_inner_types<self_type>;\n        using xvariable_expression_type = typename inner_types::xvariable_expression_type;\n        using xaxis_expression_type = typename inner_types::xaxis_expression_type;\n        using temporary_type = typename inner_types::temporary_type;\n\n        using coordinate_type = typename inner_types::coordinate_type;\n        using dimension_type = typename inner_types::dimension_type;\n\n        using data_type = typename inner_types::data_type;\n        using value_type = typename data_type::value_type;\n        using reference = typename data_type::reference;\n        using const_reference = typename data_type::const_reference;\n        using pointer = typename data_type::pointer;\n        using const_pointer = typename data_type::const_pointer;\n\n        using size_type = typename xvariable_expression_type::size_type;\n        using difference_type = typename xvariable_expression_type::difference_type;\n\n        using dimension_list = typename dimension_type::label_list;\n        using shape_type = typename data_type::shape_type;\n        using squeeze_map = std::map<typename dimension_type::mapped_type, typename coordinate_type::index_type>;\n\n        using expression_tag = xvariable_expression_tag;\n\n        template <std::size_t N = dynamic()>\n        using selector_traits = xselector_traits<coordinate_type, dimension_type, N>;\n        template <std::size_t N = dynamic()>\n        using index_type = typename selector_traits<N>::index_type;\n        template <std::size_t N = dynamic()>\n        using selector_type = typename selector_traits<N>::selector_type;\n        template <std::size_t N = dynamic()>\n        using selector_sequence_type = typename selector_traits<N>::selector_sequence_type;\n        template <std::size_t N = dynamic()>\n        using iselector_type = typename selector_traits<N>::iselector_type;\n        template <std::size_t N = dynamic()>\n        using iselector_sequence_type = typename selector_traits<N>::iselector_sequence_type;\n        template <std::size_t N = dynamic()>\n        using locator_type = typename selector_traits<N>::locator_type;\n        template <std::size_t N = dynamic()>\n        using locator_sequence_type = typename selector_traits<N>::locator_sequence_type;\n\n        template <class V, class AX>\n        xvariable_masked_view(V&& variable_expr, AX&& axis_expr);\n\n        xvariable_masked_view(const xvariable_masked_view&) = default;\n        xvariable_masked_view& operator=(const xvariable_masked_view&);\n\n        template <class E>\n        xvariable_masked_view& operator=(const xt::xexpression<E>& e);\n\n        template <class E>\n        xt::disable_xexpression<E, xvariable_masked_view>& operator=(const E& e);\n\n        using base_type::missing;\n        using base_type::shape;\n        using base_type::size;\n        using base_type::dimension;\n        using base_type::data;\n        using base_type::coordinates;\n        using base_type::dimension_labels;\n        using base_type::dimension_mapping;\n        using base_type::broadcast_coordinates;\n        using base_type::broadcast_dimensions;\n        using base_type::operator();\n        using base_type::element;\n        using base_type::locate;\n        using base_type::locate_element;\n        using base_type::select;\n        using base_type::iselect;\n\n    private:\n\n        void assign_temporary_impl(temporary_type&& tmp);\n\n        data_type& data_impl() noexcept;\n        const data_type& data_impl() const noexcept;\n\n        CTV m_expr;\n        CTAX m_axis_expr;\n        data_type m_data;\n\n        friend class xt::xview_semantic<self_type>;\n        friend class xvariable_base<self_type>;\n    };\n\n    /****************************************\n     * xvariable_masked_view implementation *\n     ****************************************/\n\n    /**\n     * Builds an xvariable_masked_view.\n     * @param variable_expr the underlying variable.\n     * @param axis_expr the axis expression.\n     */\n    template <class CTV, class CTAX>\n    template <class V, class AX>\n    inline xvariable_masked_view<CTV, CTAX>::xvariable_masked_view(V&& variable_expr, AX&& axis_expr)\n        : base_type(variable_expr.coordinates(), variable_expr.dimension_mapping()),\n          m_expr(std::forward<V>(variable_expr)),\n          m_axis_expr(std::forward<AX>(axis_expr)),\n          m_data(m_expr.data(), axis_function_mask(\n              m_axis_expr,\n              m_expr.dimension_mapping(),\n              m_expr.shape()\n          ))\n    {\n    }\n\n    template <class CTV, class CTAX>\n    inline xvariable_masked_view<CTV, CTAX>& xvariable_masked_view<CTV, CTAX>::operator=(const xvariable_masked_view& rhs)\n    {\n        temporary_type tmp(rhs);\n        return this->assign_temporary(std::move(tmp));\n    }\n\n    template <class CTV, class CTAX>\n    template <class E>\n    inline xvariable_masked_view<CTV, CTAX>& xvariable_masked_view<CTV, CTAX>::operator=(const xt::xexpression<E>& e)\n    {\n        using root_semantic = typename semantic_base::base_type;\n        return root_semantic::operator=(e);\n    }\n\n    template <class CTV, class CTAX>\n    template <class E>\n    inline xt::disable_xexpression<E, xvariable_masked_view<CTV, CTAX>>& xvariable_masked_view<CTV, CTAX>::operator=(const E& e)\n    {\n        this->data().fill(e);\n        return *this;\n    }\n\n    template <class CTV, class CTAX>\n    inline void xvariable_masked_view<CTV, CTAX>::assign_temporary_impl(temporary_type&& tmp)\n    {\n        // TODO: improve this with iterators when they are available\n        const temporary_type& tmp2 = tmp;\n        const auto& dim_label = dimension_labels();\n        const auto& coords = coordinates();\n        std::vector<size_type> index(dim_label.size(), size_type(0));\n        selector_sequence_type<> selector(index.size());\n        bool end = false;\n        do\n        {\n            for (size_type i = 0; i < index.size(); ++i)\n            {\n                selector[i] = std::make_pair(dim_label[i], coords[dim_label[i]].label(index[i]));\n            }\n            this->select(selector) = tmp2.select(selector);\n            end = xt::detail::increment_index(tmp2.data().shape(), index);\n        } while (!end);\n    }\n\n    template <class CTV, class CTAX>\n    inline auto xvariable_masked_view<CTV, CTAX>::data_impl() noexcept -> data_type&\n    {\n        return m_data;\n    }\n\n    template <class CTV, class CTAX>\n    inline auto xvariable_masked_view<CTV, CTAX>::data_impl() const noexcept -> const data_type&\n    {\n        return m_data;\n    }\n\n    /**\n     * Apply a mask on a variable where the axis expression is false. e.g.\n     * ```\n     * // Will only assign 36 to values where the ordinate label is lower than 6\n     * where(var, var.axis<int>(\"ordinate\") < 6) = 36;\n     *\n     * // Will only add 2.4 to values where the abscissa is not equal to 'm' and the ordinate is not equal to 1\n     * where(\n     *      var,\n     *      not_equal(var.axis<char>(\"abscissa\"), 'm')) && not_equal(var.axis<int>(\"ordinate\"), 1)\n     * ) += 2.4;\n     * ```\n     * @param variable_expr the variable.\n     * @param axis_expr the axis expression.\n     * @return an xvariable_masked_view.\n     */\n    template <class EV, class EAX>\n    inline auto where(EV&& variable_expr, EAX&& axis_expr)\n    {\n        return xvariable_masked_view<EV, EAX>(std::forward<EV>(variable_expr), std::forward<EAX>(axis_expr));\n    }\n\n    template <class EV, class EAX>\n    inline std::ostream& operator<<(std::ostream& out, const xvariable_masked_view<EV, EAX>& v)\n    {\n        return print_variable_expression(out, v);\n    }\n}\n\n#endif\n"
  },
  {
    "path": "include/xframe/xvariable_math.hpp",
    "content": "/***************************************************************************\n* Copyright (c) Johan Mabille, Sylvain Corlay, Wolf Vollprecht and         *\n* Martin Renou                                                             *\n* Copyright (c) QuantStack                                                 *\n*                                                                          *\n* Distributed under the terms of the BSD 3-Clause License.                 *\n*                                                                          *\n* The full license is in the file LICENSE, distributed with this software. *\n****************************************************************************/\n\n#ifndef XFRAME_XVARIABLE_MATH_HPP\n#define XFRAME_XVARIABLE_MATH_HPP\n\n#include \"xframe_expression.hpp\"\n#include \"xaxis_math.hpp\"\n#include \"xvariable_function.hpp\"\n\nnamespace xt\n{\n    namespace detail\n    {\n        template <class F, class... E>\n        struct select_xfunction_expression<xf::xvariable_expression_tag, F, E...>\n        {\n            using result_type = decltype(std::declval<F>()(std::declval<xvalue_type_t<std::decay_t<E>>>()...));\n            using type = xf::xvariable_function<F, result_type, E...>;\n        };\n    }\n\n    template <class E1, class E2>\n    inline std::enable_if_t<xf::xvariable_comparable<E1, E2>::value, bool>\n    operator==(const xexpression<E1>& e1, const xexpression<E2>& e2)\n    {\n        const E1& de1 = e1.derived_cast();\n        const E2& de2 = e2.derived_cast();\n\n        return de1.data() == de2.data() &&\n            de1.coordinates() == de2.coordinates() &&\n            de1.dimension_mapping() == de2.dimension_mapping();\n    }\n}\n\n#endif\n"
  },
  {
    "path": "include/xframe/xvariable_meta.hpp",
    "content": "/***************************************************************************\n* Copyright (c) Johan Mabille, Sylvain Corlay, Wolf Vollprecht and         *\n* Martin Renou                                                             *\n* Copyright (c) QuantStack                                                 *\n*                                                                          *\n* Distributed under the terms of the BSD 3-Clause License.                 *\n*                                                                          *\n* The full license is in the file LICENSE, distributed with this software. *\n****************************************************************************/\n\n#ifndef XFRAME_XVARIABLE_META_HPP\n#define XFRAME_XVARIABLE_META_HPP\n\n#include \"xcoordinate.hpp\"\n#include \"xdimension.hpp\"\n#include \"xvariable_scalar.hpp\"\n\nnamespace xf\n{\n\n    /*********************\n     * xvariable_closure *\n     *********************/\n\n    template <class CT>\n    struct xvariable_closure\n    {\n        using type = CT;\n    };\n\n    template <class CT>\n    struct xvariable_closure<xt::xscalar<CT>>\n    {\n        using type = xvariable_scalar<CT>;\n    };\n\n    template <class CT>\n    using xvariable_closure_t = typename xvariable_closure<CT>::type;\n\n    /***************************\n     * xdecay_variable_closure *\n     ***************************/\n\n    template <class CT>\n    struct xdecay_variable_closure\n    {\n        using type = std::decay_t<xvariable_closure_t<CT>>;\n    };\n\n    template <class CT>\n    using xdecay_variable_closure_t = typename xdecay_variable_closure<CT>::type;\n\n    /***************************\n     * xcommon_coordinate_type *\n     ***************************/\n\n    namespace detail\n    {\n        template <class... C>\n        struct xcommon_coordinate_type_impl;\n\n        template <class C1, class C2>\n        struct xcommon_coordinate_type_impl<C1, C2>\n        {\n            using key_type = std::common_type_t<typename C1::key_type, typename C2::key_type>;\n            using label_list = xtl::mpl::merge_set_t<typename C1::label_list, typename C2::label_list>;\n            using index_type = std::common_type_t<typename C1::index_type, typename C2::index_type>;\n            using type = xcoordinate<key_type, label_list, index_type>;\n        };\n\n        template <class C>\n        struct xcommon_coordinate_type_impl<C, xfull_coordinate>\n        {\n            using key_type = typename C::key_type;\n            using label_list = typename C::label_list;\n            using index_type = typename C::index_type;\n            using type = xcoordinate<key_type, label_list, index_type>;\n        };\n\n        template <class C>\n        struct xcommon_coordinate_type_impl<xfull_coordinate, C>\n            : xcommon_coordinate_type_impl<C, xfull_coordinate>\n        {\n        };\n\n        template <>\n        struct xcommon_coordinate_type_impl<xfull_coordinate, xfull_coordinate>\n        {\n            using type = xfull_coordinate;\n        };\n\n        template <class C>\n        struct xcommon_coordinate_type_impl<C>\n            : xcommon_coordinate_type_impl<C, xfull_coordinate>\n        {\n        };\n\n        template <class C1, class C2, class... C>\n        struct xcommon_coordinate_type_impl<C1, C2, C...>\n            : xcommon_coordinate_type_impl<C1, typename xcommon_coordinate_type_impl<C2, C...>::type>\n        {\n        };\n    }\n\n    template <class... CT>\n    struct xcommon_coordinate_type\n    {\n        using type = typename detail::xcommon_coordinate_type_impl<typename xdecay_variable_closure_t<CT>::coordinate_type...>::type;\n    };\n\n    template <class... CT>\n    using xcommon_coordinate_type_t = typename xcommon_coordinate_type<CT...>::type;\n\n    /**************************\n     * xcommon_dimension_type *\n     **************************/\n\n    namespace detail\n    {\n        template <class... D>\n        struct xcommon_dimension_type_impl;\n\n        template <class D1, class D2>\n        struct xcommon_dimension_type_impl<D1, D2>\n        {\n            using key_type = std::common_type_t<typename D1::key_type, typename D2::key_type>;\n            using mapped_type = std::common_type_t<typename D1::mapped_type, typename D2::mapped_type>;\n            using type = xdimension<key_type, mapped_type>;\n        };\n\n        template <class D>\n        struct xcommon_dimension_type_impl<D, xfull_coordinate>\n        {\n            using key_type = typename D::key_type;\n            using mapped_type = typename D::mapped_type;\n            using type = xdimension<key_type, mapped_type>;\n        };\n\n        template <class D>\n        struct xcommon_dimension_type_impl<xfull_coordinate, D>\n            : xcommon_dimension_type_impl<D, xfull_coordinate>\n        {\n        };\n\n        template <>\n        struct xcommon_dimension_type_impl<xfull_coordinate, xfull_coordinate>\n        {\n            using type = xfull_coordinate;\n        };\n\n        template <class D>\n        struct xcommon_dimension_type_impl<D>\n            : xcommon_dimension_type_impl<D, xfull_coordinate>\n        {\n        };\n\n        template <class D1, class D2, class... D>\n        struct xcommon_dimension_type_impl<D1, D2, D...>\n            : xcommon_dimension_type_impl<D1, typename xcommon_dimension_type_impl<D2, D...>::type>\n        {\n        };\n    }\n\n    template <class... CT>\n    struct xcommon_dimension_type\n    {\n        using type = typename detail::xcommon_dimension_type_impl<typename xdecay_variable_closure_t<CT>::dimension_type...>::type;\n    };\n\n    template <class... CT>\n    using xcommon_dimension_type_t = typename xcommon_dimension_type<CT...>::type;\n}\n\n#endif\n"
  },
  {
    "path": "include/xframe/xvariable_scalar.hpp",
    "content": "/***************************************************************************\n* Copyright (c) Johan Mabille, Sylvain Corlay, Wolf Vollprecht and         *\n* Martin Renou                                                             *\n* Copyright (c) QuantStack                                                 *\n*                                                                          *\n* Distributed under the terms of the BSD 3-Clause License.                 *\n*                                                                          *\n* The full license is in the file LICENSE, distributed with this software. *\n****************************************************************************/\n\n#ifndef XFRAME_XVARIABLE_SCALAR_HPP\n#define XFRAME_XVARIABLE_SCALAR_HPP\n\n#include \"xtensor/xscalar.hpp\"\n#include \"xcoordinate.hpp\"\n\nnamespace xf\n{\n    template <class CT>\n    class xvariable_scalar\n    {\n    public:\n\n        using data_type = xt::xscalar<CT>;\n        using value_type = typename data_type::value_type;\n        using reference = typename data_type::reference;\n        using const_reference = typename data_type::const_reference;\n        using pointer = typename data_type::pointer;\n        using const_pointer = typename data_type::const_pointer;\n        using size_type = typename data_type::size_type;\n        using difference_type = typename data_type::difference_type;\n\n        using shape_type = std::array<size_type, 0>;\n\n        using coordinate_type = xfull_coordinate;\n        using dimension_type = xfull_coordinate;\n\n        using expression_tag = xvariable_expression_tag;\n\n        xvariable_scalar(const xt::xscalar<CT>& v) noexcept;\n\n        size_type size() const noexcept;\n        size_type dimension() const noexcept;\n        coordinate_type coordinates() const noexcept;\n        dimension_type dimension_mapping() const noexcept;\n        const shape_type& shape() const noexcept;\n\n        template <class... Args>\n        const_reference operator()(Args... args) const noexcept;\n\n        template <class Join = XFRAME_DEFAULT_JOIN, class C>\n        xtrivial_broadcast broadcast_coordinates(C& coords) const noexcept;\n\n        template <class D>\n        bool broadcast_dimensions(D& dims, bool trivial_bc = false) const noexcept;\n\n        data_type data() const noexcept;\n\n        template <class Join = XFRAME_DEFAULT_JOIN, std::size_t N = dynamic(), class S = std::size_t>\n        const_reference select(const S&) const noexcept;\n\n    private:\n\n        data_type m_data;\n    };\n\n    template <class T>\n    struct is_xvariable_scalar : std::false_type\n    {\n    };\n\n    template <class CT>\n    struct is_xvariable_scalar<xvariable_scalar<CT>> : std::true_type\n    {\n    };\n\n    /***********************************\n     * xvariable_scalar implementation *\n     ***********************************/\n\n    template <class CT>\n    xvariable_scalar<CT>::xvariable_scalar(const xt::xscalar<CT>& v) noexcept\n        : m_data(v)\n    {\n    }\n\n    template <class CT>\n    inline auto xvariable_scalar<CT>::size() const noexcept -> size_type\n    {\n        return data().size();\n    }\n\n    template <class CT>\n    inline auto xvariable_scalar<CT>::dimension() const noexcept -> size_type\n    {\n        return data().dimension();\n    }\n\n    template <class CT>\n    inline auto xvariable_scalar<CT>::coordinates() const noexcept -> coordinate_type\n    {\n        return xfull_coordinate();\n    }\n\n    template <class CT>\n    inline auto xvariable_scalar<CT>::dimension_mapping() const noexcept -> dimension_type\n    {\n        return xfull_coordinate();\n    }\n\n    template <class CT>\n    inline auto xvariable_scalar<CT>::shape() const noexcept -> const shape_type&\n    {\n        static shape_type zero_shape;\n        return zero_shape;\n    }\n\n    template <class CT>\n    template <class... Args>\n    inline auto xvariable_scalar<CT>::operator()(Args... args) const noexcept -> const_reference\n    {\n        return data()(args...);\n    }\n\n    template <class CT>\n    template <class Join, class C>\n    inline xtrivial_broadcast xvariable_scalar<CT>::broadcast_coordinates(C& /*coords*/) const noexcept\n    {\n        return xtrivial_broadcast(true, true);\n    }\n\n    template <class CT>\n    template <class D>\n    bool xvariable_scalar<CT>::broadcast_dimensions(D& /*dims*/, bool /*trivial_bc*/) const noexcept\n    {\n        return true;\n    }\n\n    template <class CT>\n    inline auto xvariable_scalar<CT>::data() const noexcept -> data_type\n    {\n        return m_data;\n    }\n\n    template <class CT>\n    template <class Join, std::size_t N, class S>\n    inline auto xvariable_scalar<CT>::select(const S&) const noexcept -> const_reference\n    {\n        // TODO: should return data()() but this requires update of xtensor/xoptional.hpp\n        // (split_optional_expression_impl needs to catch ref and const ref on xscalar)\n        return m_data();\n    }\n}\n\n#endif\n"
  },
  {
    "path": "include/xframe/xvariable_variant.hpp",
    "content": "/***************************************************************************\n* Copyright (c) Johan Mabille, Sylvain Corlay, Wolf Vollprecht and         *\n* Martin Renou                                                             *\n* Copyright (c) QuantStack                                                 *\n*                                                                          *\n* Distributed under the terms of the BSD 3-Clause License.                 *\n*                                                                          *\n* The full license is in the file LICENSE, distributed with this software. *\n****************************************************************************/\n\n#ifndef XFRAME_XVARIABLE_VARIANT_HPP\n#define XFRAME_XVARIABLE_VARIANT_HPP\n\n#include \"xvariable.hpp\"\n\nnamespace xf\n{\n\n\n    template <class... V>\n    class xvariable_variant\n    {\n    };\n\n    // vtype1 = variable<double, coord_type1>;\n    // vtype2 variable<int, coord_type2>;\n    // vtype1 v1;\n    // vtype2 v2;\n\n    // auto fr = (\"n1\", v1) | (\"n2\", v2);\n    // ftype = xframe<L, vtype1, vtype2>;\n    // ftype::vtype = variant<variable<double, coord_type1>&, variable<int, coord_type2>&>\n    // ftype::vtype::value_type = variant<vtype1::value_type, vtype1::value_type>;\n    // ftype::vtype::coordinate_type = variant<vtype1::coordinate_type, vtype2::coordinate_type>;\n    // ftype::vtype::dimension_type = variant<vtype1::dimension_type, vtype2::dimension_type>;\n    // ftype::vtype::data_type = variant<vtype1::data_type, vtype2::deta_type>\n    // ftype::ctype = xcommon_coordinate_type<coord_type1, coord_type2>;\n    // ftype::dtype = xcommon_dimension_type<typename vtype1::dimension_type, typename vtype2::dimension_type>;\n    //\n    // xframe not aligned:\n    // std::map<L, ftype::vtype>;\n    // ftype::ctype m_coord;\n    // ftype::dtype m_dims;\n    // f[\"n1\"] returns ??\n    //\n    // xframe aligned\n    // std::map<L, ftype::vtype::data_type>;\n    // ftype::ctype m_coord;\n    // ftype::dtype m_dims;\n    // f[\"n1\"]\n}\n\n#endif\n\n"
  },
  {
    "path": "include/xframe/xvariable_view.hpp",
    "content": "/***************************************************************************\n* Copyright (c) Johan Mabille, Sylvain Corlay, Wolf Vollprecht and         *\n* Martin Renou                                                             *\n* Copyright (c) QuantStack                                                 *\n*                                                                          *\n* Distributed under the terms of the BSD 3-Clause License.                 *\n*                                                                          *\n* The full license is in the file LICENSE, distributed with this software. *\n****************************************************************************/\n\n#ifndef XFRAME_XVARIABLE_VIEW_HPP\n#define XFRAME_XVARIABLE_VIEW_HPP\n\n#include \"xtensor/xdynamic_view.hpp\"\n\n#include \"xvariable.hpp\"\n#include \"xcoordinate_system.hpp\"\n#include \"xcoordinate_view.hpp\"\n\nnamespace xf\n{\n\n    /*******************\n     * xvariable_view  *\n     *******************/\n\n    template <class CT>\n    class xvariable_view;\n\n    template <class CT>\n    struct xvariable_inner_types<xvariable_view<CT>>\n    {\n        using xexpression_type = std::decay_t<CT>;\n        using coordinate_type = xcoordinate_view_type_t<typename xexpression_type::coordinate_type>;\n        using coordinate_closure_type = coordinate_type;\n        using dimension_type = typename xexpression_type::dimension_type;\n        using dimension_closure_type = dimension_type;\n        using key_type = typename coordinate_type::key_type;\n        using size_type = typename coordinate_type::size_type;\n        using label_list = typename coordinate_type::label_list;\n    };\n}\n\nnamespace xt\n{\n    template <class CT>\n    struct xcontainer_inner_types<xf::xvariable_view<CT>>\n        : xf::xvariable_inner_types<xf::xvariable_view<CT>>\n    {\n        using base_type = xf::xvariable_inner_types<xf::xvariable_view<CT>>;\n        using xexpression_type = typename base_type::xexpression_type;\n        using optional_type = typename xexpression_type::value_type;\n        using temporary_coordinate_type = xf::xcoordinate<typename base_type::key_type,\n                                                          typename base_type::label_list,\n                                                          typename base_type::size_type>;\n        using temporary_data_type = xoptional_assembly<xarray<typename optional_type::value_type>, xarray<bool>>;\n        using temporary_type = xf::xvariable_container<temporary_coordinate_type, temporary_data_type>;\n    };\n}\n\nnamespace xf\n{\n\n    template <class CT>\n    class xvariable_view : public xt::xview_semantic<xvariable_view<CT>>,\n                           private xcoordinate_system<xvariable_view<CT>>\n    {\n    public:\n\n        using self_type = xvariable_view<CT>;\n        using semantic_base = xt::xview_semantic<self_type>;\n        using coordinate_base = xcoordinate_system<xvariable_view<CT>>;\n        using inner_types = xt::xcontainer_inner_types<self_type>;\n        using xexpression_type = typename inner_types::xexpression_type;\n        using underlying_data_type = typename xexpression_type::data_type;\n        using data_type = xt::xdynamic_view<xt::apply_cv_t<CT, underlying_data_type>&, typename underlying_data_type::shape_type>;\n        using slice_vector = xt::xdynamic_slice_vector;\n\n        static constexpr bool is_const = std::is_const<std::remove_reference_t<CT>>::value;\n        using value_type = typename xexpression_type::value_type;\n        using reference = std::conditional_t<is_const,\n                                             typename xexpression_type::const_reference,\n                                             typename xexpression_type::reference>;\n        using const_reference = typename xexpression_type::const_reference;\n        using pointer = std::conditional_t<is_const,\n                                           typename xexpression_type::const_pointer,\n                                           typename xexpression_type::pointer>;\n        using const_pointer = typename xexpression_type::const_pointer;\n        using size_type = typename xexpression_type::size_type;\n        using difference_type = typename xexpression_type::difference_type;\n\n        using coordinate_type = typename coordinate_base::coordinate_type;\n        using dimension_type = typename coordinate_base::dimension_type;\n        using dimension_list = typename coordinate_base::dimension_list;\n        using shape_type = typename data_type::shape_type;\n        using squeeze_map = std::map<typename dimension_type::mapped_type, typename coordinate_type::index_type>;\n        using temporary_type = typename inner_types::temporary_type;\n\n        using expression_tag = xvariable_expression_tag;\n\n        template <std::size_t N = dynamic()>\n        using selector_traits = xselector_traits<coordinate_type, dimension_type, N>;\n        template <std::size_t N = dynamic()>\n        using index_type = typename selector_traits<N>::index_type;\n        template <std::size_t N = dynamic()>\n        using selector_type = typename selector_traits<N>::selector_type;\n        template <std::size_t N = dynamic()>\n        using selector_sequence_type = typename selector_traits<N>::selector_sequence_type;\n        template <std::size_t N = dynamic()>\n        using iselector_type = typename selector_traits<N>::iselector_type;\n        template <std::size_t N = dynamic()>\n        using iselector_sequence_type = typename selector_traits<N>::iselector_sequence_type;\n        template <std::size_t N = dynamic()>\n        using locator_type = typename selector_traits<N>::locator_type;\n        template <std::size_t N = dynamic()>\n        using locator_sequence_type = typename selector_traits<N>::locator_sequence_type;\n\n        static const_reference missing();\n\n        template <class E>\n        xvariable_view(E&& e, coordinate_type&& coord, dimension_type&& dim, squeeze_map&& squeeze, slice_vector&& slices);\n\n        xvariable_view(const xvariable_view&) = default;\n        xvariable_view& operator=(const xvariable_view&);\n\n        template <class E>\n        xvariable_view& operator=(const xt::xexpression<E>& e);\n\n        template <class E>\n        xt::disable_xexpression<E, xvariable_view>& operator=(const E& e);\n\n        using coordinate_base::size;\n        using coordinate_base::dimension;\n        using coordinate_base::dimension_labels;\n        using coordinate_base::coordinates;\n        using coordinate_base::dimension_mapping;\n        using coordinate_base::broadcast_coordinates;\n        using coordinate_base::broadcast_dimensions;\n\n        const shape_type& shape() const noexcept;\n\n        data_type& data() noexcept;\n        const data_type& data() const noexcept;\n\n        template <class... Args>\n        reference operator()(Args... args);\n\n        template <class... Args>\n        const_reference operator()(Args... args) const;\n\n        template <std::size_t N = dynamic()>\n        reference element(const index_type<N>& index);\n\n        template <std::size_t N = dynamic()>\n        const_reference element(const index_type<N>& index) const;\n\n        template <std::size_t N = dynamic()>\n        reference element(index_type<N>&& index);\n\n        template <std::size_t N = dynamic()>\n        const_reference element(index_type<N>&& index) const;\n\n        template <class... Args>\n        reference locate(Args&&... args);\n\n        template <class... Args>\n        const_reference locate(Args&&... args) const;\n\n        template <std::size_t N = dynamic()>\n        reference locate_element(const locator_sequence_type<N>& locator);\n\n        template <std::size_t N = dynamic()>\n        const_reference locate_element(const locator_sequence_type<N>& locator) const;\n\n        template <std::size_t N = dynamic()>\n        reference locate_element(locator_sequence_type<N>&& locator);\n\n        template <std::size_t N = dynamic()>\n        const_reference locate_element(locator_sequence_type<N>&& locator) const;\n\n        template <std::size_t N = dynamic()>\n        reference select(const selector_sequence_type<N>& selector);\n\n        template <class Join = XFRAME_DEFAULT_JOIN, std::size_t N = std::numeric_limits<size_type>::max()>\n        const_reference select(const selector_sequence_type<N>& selector) const;\n\n        template <std::size_t N = dynamic()>\n        reference select(selector_sequence_type<N>&& selector);\n\n        template <class Join = XFRAME_DEFAULT_JOIN, std::size_t N = dynamic()>\n        const_reference select(selector_sequence_type<N>&& selector) const;\n\n        template <std::size_t N = dynamic()>\n        reference iselect(const iselector_sequence_type<N>& selector);\n\n        template <std::size_t N = dynamic()>\n        const_reference iselect(const iselector_sequence_type<N>& selector) const;\n\n        template <std::size_t N = dynamic()>\n        reference iselect(iselector_sequence_type<N>&& selector);\n\n        template <std::size_t N = dynamic()>\n        const_reference iselect(iselector_sequence_type<N>&& selector) const;\n\n    private:\n\n        using internal_index_type = std::vector<size_type>;\n\n        template <std::size_t... I, class... Args>\n        reference access_impl(std::index_sequence<I...>, Args... args);\n\n        template <std::size_t... I, class... Args>\n        const_reference access_impl(std::index_sequence<I...>, Args... args) const;\n\n        template <class... Args>\n        internal_index_type build_accessor(Args&&... args) const;\n\n        template <std::size_t I, class T, class... Args>\n        void fill_accessor(internal_index_type& accessor, T idx, Args... args) const;\n\n        template <std::size_t I>\n        void fill_accessor(internal_index_type& accessor) const;\n\n        template <class It>\n        internal_index_type build_element_accessor(It first, It last) const;\n\n        template <std::size_t... I, class... Args>\n        reference locate_impl(std::index_sequence<I...>, Args&&... args);\n\n        template <std::size_t... I, class... Args>\n        const_reference locate_impl(std::index_sequence<I...>, Args&&... args) const;\n\n        template <class... Args>\n        internal_index_type build_locator(Args&&... args) const;\n\n        template <std::size_t I, class T, class... Args>\n        void fill_locator(internal_index_type& locator, T idx, Args&&... args) const;\n\n        template <std::size_t I>\n        void fill_locator(internal_index_type& locator) const;\n\n        template <std::size_t N>\n        internal_index_type build_element_locator(locator_sequence_type<N>&& locator) const;\n\n        template <class S>\n        reference select_impl(const S& selector);\n\n        template <class S>\n        const_reference select_impl(const S& selector) const;\n\n        template <class S>\n        const_reference select_outer(const S& selector) const;\n\n        template <class Join, class S>\n        const_reference select_join(const S& selector) const;\n\n        template <class Idx>\n        void fill_squeeze(Idx& index) const;\n\n        template <std::size_t N>\n        void adapt_iselector(iselector_sequence_type<N>& selector) const;\n\n        void assign_temporary_impl(temporary_type&& tmp);\n\n        CT m_e;\n        squeeze_map m_squeeze;\n        data_type m_data;\n\n        friend class xt::xview_semantic<xvariable_view<CT>>;\n    };\n\n    template <class CT>\n    std::ostream& operator<<(std::ostream& out, const xvariable_view<CT>& view);\n\n    /***************************\n     * xvariable_view builders *\n     ***************************/\n\n    template <class E, class... S>\n    auto ilocate(E&& e, S&&... slices);\n\n    template <class L = XFRAME_DEFAULT_LABEL_LIST, class E, class... S>\n    auto locate(E&& e, S&&... slices);\n\n    template <class E, class L = XFRAME_DEFAULT_LABEL_LIST>\n    auto select(E&& e, std::map<typename std::decay_t<E>::key_type, xaxis_slice<L>>&& slices);\n\n    template <class E, class T = typename std::decay_t<E>::difference_type>\n    auto iselect(E&& e, std::map<typename std::decay_t<E>::key_type, xt::xdynamic_slice<T>>&& slices);\n\n    /*********************************\n     * xvariable_view implementation *\n     *********************************/\n\n    template <class CT>\n    template <class E>\n    inline xvariable_view<CT>::xvariable_view(E&& e, coordinate_type&& coord, dimension_type&& dim, squeeze_map&& squeeze,\n                                              slice_vector&& slices)\n        : coordinate_base(std::move(coord), std::move(dim)),\n          m_e(std::forward<E>(e)),\n          m_squeeze(std::move(squeeze)),\n          m_data(xt::dynamic_view(m_e.data(), slices))\n    {\n    }\n\n    template <class CT>\n    inline auto xvariable_view<CT>::missing() -> const_reference\n    {\n        return detail::static_missing<const_reference>();\n    }\n\n    template <class CT>\n    inline xvariable_view<CT>& xvariable_view<CT>::operator=(const xvariable_view& rhs)\n    {\n        temporary_type tmp(rhs);\n        return this->assign_temporary(std::move(tmp));\n    }\n\n    template <class CT>\n    template <class E>\n    inline xvariable_view<CT>& xvariable_view<CT>::operator=(const xt::xexpression<E>& e)\n    {\n        using root_semantic = typename semantic_base::base_type;\n        return root_semantic::operator=(e);\n    }\n\n    template <class CT>\n    template <class E>\n    xt::disable_xexpression<E, xvariable_view<CT>>& xvariable_view<CT>::operator=(const E& e)\n    {\n        data().fill(e);\n        return *this;\n    }\n\n    template <class CT>\n    inline auto xvariable_view<CT>::shape() const noexcept -> const shape_type&\n    {\n        return data().shape();\n    }\n\n    template <class CT>\n    inline auto xvariable_view<CT>::data() noexcept -> data_type&\n    {\n        return m_data;\n    }\n\n    template <class CT>\n    inline auto xvariable_view<CT>::data() const noexcept -> const data_type&\n    {\n        return m_data;\n    }\n\n    template <class CT>\n    template <class... Args>\n    inline auto xvariable_view<CT>::operator()(Args... args) ->reference\n    {\n        if (m_squeeze.empty())\n        {\n            return access_impl(std::make_index_sequence<sizeof...(Args)>(), args...);\n        }\n        else\n        {\n            auto idx = build_accessor(std::forward<Args>(args)...);\n            return m_e.element(idx);\n        }\n    }\n\n    template <class CT>\n    template <class... Args>\n    inline auto xvariable_view<CT>::operator()(Args... args) const -> const_reference\n    {\n        if (m_squeeze.empty())\n        {\n            return access_impl(std::make_index_sequence<sizeof...(Args)>(), args...);\n        }\n        else\n        {\n            auto idx = build_accessor(std::forward<Args>(args)...);\n            return m_e.element(idx);\n        }\n    }\n\n    template <class CT>\n    template <std::size_t N>\n    inline auto xvariable_view<CT>::element(const index_type<N>& index) -> reference\n    {\n        auto idx = build_element_accessor(index.cbegin(), index.cend());\n        return m_e.element(idx.cbegin(), idx.cend());\n    }\n\n    template <class CT>\n    template <std::size_t N>\n    inline auto xvariable_view<CT>::element(const index_type<N>& index) const -> const_reference\n    {\n        auto idx = build_element_accessor(index.cbegin(), index.cend());\n        return m_e.element(idx.cbegin(), idx.cend());\n    }\n\n    template <class CT>\n    template <std::size_t N>\n    inline auto xvariable_view<CT>::element(index_type<N>&& index) -> reference\n    {\n        auto idx = build_element_accessor(index.cbegin(), index.cend());\n        return m_e.element(idx);\n    }\n\n    template <class CT>\n    template <std::size_t N>\n    inline auto xvariable_view<CT>::element(index_type<N>&& index) const -> const_reference\n    {\n        auto idx = build_element_accessor(index.cbegin(), index.cend());\n        return m_e.element(idx);\n    }\n\n    template <class CT>\n    template <class... Args>\n    inline auto xvariable_view<CT>::locate(Args&&... args) -> reference\n    {\n        if (m_squeeze.empty())\n        {\n            return locate_impl(std::make_index_sequence<sizeof...(Args)>(), std::forward<Args>(args)...);\n        }\n        else\n        {\n            auto idx = build_locator(std::forward<Args>(args)...);\n            return m_e.element(idx);\n        }\n    }\n\n    template <class CT>\n    template <class... Args>\n    inline auto xvariable_view<CT>::locate(Args&&... args) const -> const_reference\n    {\n        if (m_squeeze.empty())\n        {\n            return locate_impl(std::make_index_sequence<sizeof...(Args)>(), std::forward<Args>(args)...);\n        }\n        else\n        {\n            auto idx = build_locator(std::forward<Args>(args)...);\n            return m_e.element(idx);\n        }\n    }\n\n    template <class CT>\n    template <std::size_t N>\n    inline auto xvariable_view<CT>::locate_element(const locator_sequence_type<N>& locator) -> reference\n    {\n        locator_sequence_type<N> tmp(locator);\n        auto idx = build_element_locator<N>(std::move(tmp));\n        return m_e.element(idx);\n    }\n\n    template <class CT>\n    template <std::size_t N>\n    inline auto xvariable_view<CT>::locate_element(const locator_sequence_type<N>& locator) const -> const_reference\n    {\n        locator_sequence_type<N> tmp(locator);\n        auto idx = build_element_locator<N>(std::move(locator));\n        return m_e.element(idx);\n    }\n\n    template <class CT>\n    template <std::size_t N>\n    inline auto xvariable_view<CT>::locate_element(locator_sequence_type<N>&& locator) -> reference\n    {\n        auto idx = build_element_locator<N>(std::move(locator));\n        return m_e.element(idx);\n    }\n\n    template <class CT>\n    template <std::size_t N>\n    inline auto xvariable_view<CT>::locate_element(locator_sequence_type<N>&& locator) const -> const_reference\n    {\n        auto idx = build_element_locator<N>(std::move(locator));\n        return m_e.element(idx);\n    }\n\n    template <class CT>\n    template <std::size_t N>\n    inline auto xvariable_view<CT>::select(const selector_sequence_type<N>& selector) -> reference\n    {\n        return select_impl(selector_type<N>(selector));\n    }\n\n    template <class CT>\n    template <class Join, std::size_t N>\n    inline auto xvariable_view<CT>::select(const selector_sequence_type<N>& selector) const -> const_reference\n    {\n        return select_join<Join>(selector_type<N>(selector));\n    }\n\n    template <class CT>\n    template <std::size_t N>\n    inline auto xvariable_view<CT>::select(selector_sequence_type<N>&& selector) -> reference\n    {\n        return select_impl(selector_type<N>(std::move(selector)));\n    }\n\n    template <class CT>\n    template <class Join, std::size_t N>\n    inline auto xvariable_view<CT>::select(selector_sequence_type<N>&& selector) const -> const_reference\n    {\n        return select_join<Join>(selector_type<N>(std::move(selector)));\n    }\n\n    template <class CT>\n    template <std::size_t N>\n    inline auto xvariable_view<CT>::iselect(const iselector_sequence_type<N>& selector) -> reference\n    {\n        return iselect(iselector_sequence_type<N>(selector));\n    }\n\n    template <class CT>\n    template <std::size_t N>\n    inline auto xvariable_view<CT>::iselect(const iselector_sequence_type<N>& selector) const -> const_reference\n    {\n        return iselect(iselector_sequence_type<N>(selector));\n    }\n\n    template <class CT>\n    template <std::size_t N>\n    inline auto xvariable_view<CT>::iselect(iselector_sequence_type<N>&& selector) -> reference\n    {\n        iselector_sequence_type<N> tmp_selector(std::move(selector));\n        adapt_iselector<N>(tmp_selector);\n        return select_impl(iselector_type<N>(std::move(tmp_selector)));\n    }\n\n    template <class CT>\n    template <std::size_t N>\n    inline auto xvariable_view<CT>::iselect(iselector_sequence_type<N>&& selector) const -> const_reference\n    {\n        iselector_sequence_type<N> tmp_selector(std::move(selector));\n        adapt_iselector<N>(tmp_selector);\n        return select_impl(iselector_type<N>(std::move(tmp_selector)));\n    }\n\n    template <class CT>\n    template <std::size_t... I, class... Args>\n    inline auto xvariable_view<CT>::access_impl(std::index_sequence<I...>, Args... args) -> reference\n    {\n        return m_e(coordinates()[dimension_labels()[I]].index(args)...);\n    }\n\n    template <class CT>\n    template <std::size_t... I, class... Args>\n    inline auto xvariable_view<CT>::access_impl(std::index_sequence<I...>, Args... args) const -> const_reference\n    {\n        return m_e(coordinates()[dimension_labels()[I]].index(args)...);\n    }\n\n    template <class CT>\n    template <class... Args>\n    inline auto xvariable_view<CT>::build_accessor(Args&&... args) const -> internal_index_type\n    {\n        internal_index_type accessor(m_e.dimension());\n        fill_accessor<0>(accessor, std::forward<Args>(args)...);\n        fill_squeeze(accessor);\n        return accessor;\n    }\n\n    template <class CT>\n    template <std::size_t I, class T, class... Args>\n    inline void xvariable_view<CT>::fill_accessor(internal_index_type& accessor, T idx, Args... args) const\n    {\n        std::size_t new_index = m_e.dimension_mapping()[dimension_labels()[I]];\n        accessor[new_index] = coordinates()[dimension_labels()[I]].index(idx);\n        fill_accessor<I + 1>(accessor, std::forward<Args>(args)...);\n    }\n\n    template <class CT>\n    template <std::size_t I>\n    inline void xvariable_view<CT>::fill_accessor(internal_index_type& /*accessor*/) const\n    {\n    }\n\n    template <class CT>\n    template <class It>\n    inline auto xvariable_view<CT>::build_element_accessor(It first, It last) const -> internal_index_type\n    {\n        internal_index_type res(m_e.dimension());\n        size_type current_index = 0;\n        size_type i = 0;\n        while (first != last)\n        {\n            auto iter = m_squeeze.find(current_index);\n            if (iter != m_squeeze.end())\n            {\n                res[current_index++] = iter->second;\n            }\n            else\n            {\n                res[current_index++] = coordinates()[dimension_labels()[i++]].index(*first++);\n            }\n        }\n        while (current_index != res.size())\n        {\n            res[current_index] = m_squeeze.find(current_index)->second;\n            ++current_index;\n        }\n        return res;\n    }\n\n    template <class CT>\n    template <std::size_t... I, class... Args>\n    inline auto xvariable_view<CT>::locate_impl(std::index_sequence<I...>, Args&&... args) -> reference\n    {\n        return m_e(coordinates()[dimension_mapping().labels()[I]][args]...);\n    }\n\n    template <class CT>\n    template <std::size_t... I, class... Args>\n    inline auto xvariable_view<CT>::locate_impl(std::index_sequence<I...>, Args&&... args) const -> const_reference\n    {\n        m_e(coordinates()[dimension_mapping().labels()[I]][args]...);\n    }\n\n    template <class CT>\n    template <class... Args>\n    inline auto xvariable_view<CT>::build_locator(Args&&... args) const -> internal_index_type\n    {\n        internal_index_type locator(m_e.dimension());\n        fill_locator<0>(locator, std::forward<Args>(args)...);\n        fill_squeeze(locator);\n        return locator;\n    }\n\n    template <class CT>\n    template <std::size_t I, class T, class... Args>\n    inline void xvariable_view<CT>::fill_locator(internal_index_type& locator, T idx, Args&&... args) const\n    {\n        std::size_t new_index = m_e.dimension_mapping()[dimension_labels()[I]];\n        locator[new_index] = coordinates()[dimension_labels()[I]][idx];\n        fill_locator<I + 1>(locator, std::forward<Args>(args)...);\n    }\n\n    template <class CT>\n    template <std::size_t I>\n    inline void xvariable_view<CT>::fill_locator(internal_index_type&) const\n    {\n    }\n\n    template <class CT>\n    template <std::size_t N>\n    inline auto xvariable_view<CT>::build_element_locator(locator_sequence_type<N>&& locator) const -> internal_index_type\n    {\n        if (m_squeeze.empty())\n        {\n            locator_type<N> loc(std::move(locator));\n            return loc.get_index(coordinates(), dimension_mapping());\n        }\n        else\n        {\n            internal_index_type res(m_e.dimension());\n            size_type current_index = size_type(0);\n            size_type i = size_type(0);\n            const auto& coord = m_e.coordinates();\n            const auto& dims = m_e.dimension_mapping();\n            while (i != locator.size())\n            {\n                auto iter = m_squeeze.find(current_index);\n                if (iter != m_squeeze.cend())\n                {\n                    res[current_index] = iter->second;\n                }\n                else\n                {\n                    res[current_index] = coord[dims.labels()[current_index]][locator[i]];\n                    ++i;\n                }\n                ++current_index;\n            }\n            while (current_index != res.size())\n            {\n                res[current_index] = m_squeeze.find(current_index)->second;\n                ++current_index;\n            }\n            return res;\n        }\n    }\n\n    template <class CT>\n    template <class S>\n    inline auto xvariable_view<CT>::select_impl(const S& selector) -> reference\n    {\n        typename S::index_type idx = selector.get_index(coordinates(), m_e.dimension_mapping());\n        fill_squeeze(idx);\n        return m_e.element(idx);\n    }\n\n    template <class CT>\n    template <class S>\n    inline auto xvariable_view<CT>::select_impl(const S& selector) const -> const_reference\n    {\n        typename S::index_type idx = selector.get_index(coordinates(), m_e.dimension_mapping());\n        fill_squeeze(idx);\n        return m_e.element(idx);\n    }\n\n    template <class CT>\n    template <class S>\n    inline auto xvariable_view<CT>::select_outer(const S& selector) const -> const_reference\n    {\n        typename S::outer_index_type idx = selector.get_outer_index(coordinates(), m_e.dimension_mapping());\n        if (idx.second)\n        {\n            fill_squeeze(idx.first);\n            return m_e.element(idx.first);\n        }\n        else\n        {\n            return missing();\n        }\n    }\n\n    template <class CT>\n    template <class Join, class S>\n    inline auto xvariable_view<CT>::select_join(const S& selector) const -> const_reference\n    {\n        return xtl::mpl::static_if<Join::id() == join::inner::id()>([&](auto self)\n        {\n            return self(*this).select_impl(selector);\n        }, /*else*/ [&](auto self)\n        {\n            return self(*this).select_outer(selector);\n        });\n    }\n\n    template <class CT>\n    template <class Idx>\n    inline void xvariable_view<CT>::fill_squeeze(Idx& index) const\n    {\n        for (const auto& sq : m_squeeze)\n        {\n            index[sq.first] = sq.second;\n        }\n    }\n\n    template <class CT>\n    template <std::size_t N>\n    inline void xvariable_view<CT>::adapt_iselector(iselector_sequence_type<N>& selector) const\n    {\n        for (auto& sel : selector)\n        {\n            sel.second = coordinates()[sel.first].index(sel.second);\n        }\n    }\n\n    template <class CT>\n    inline void xvariable_view<CT>::assign_temporary_impl(temporary_type&& tmp)\n    {\n        // TODO: improve this with iterators when they are available\n        const temporary_type& tmp2 = tmp;\n        const auto& dim_label = dimension_labels();\n        const auto& coords = coordinates();\n        std::vector<size_type> index(dim_label.size(), size_type(0));\n        selector_sequence_type<> selector(index.size());\n        bool end = false;\n        do\n        {\n            for (size_type i = 0; i < index.size(); ++i)\n            {\n                selector[i] = std::make_pair(dim_label[i], coords[dim_label[i]].label(index[i]));\n            }\n            this->select(selector) = tmp2.select(selector);\n            end = xt::detail::increment_index(tmp2.data().shape(), index);\n        } while (!end);\n    }\n\n    template <class CT>\n    inline std::ostream& operator<<(std::ostream& out, const xvariable_view<CT>& v)\n    {\n        const auto& dims = v.dimension_labels();\n        const auto& coords = v.coordinates();\n\n        // TODO: fixe xio.hpp so it can prints expression without strides\n        //out << v.data() << std::endl;\n\n        const auto& data = v.data();\n        for (size_t i = 0; i < data.shape()[0]; ++i)\n        {\n            out << '(';\n            for (size_t j = 0; j < data.shape()[1]; ++j)\n            {\n                out << data(i, j) << \", \";\n            }\n            out << ')' << std::endl;\n        }\n        out << \"Coordinates:\" << std::endl;\n\n        std::size_t max_length = std::accumulate(dims.cbegin(), dims.cend(), std::size_t(0),\n            [](std::size_t res, const auto& d) { return std::max(res, d.size()); });\n\n        for (const auto& d : dims)\n        {\n            std::size_t nb_spaces = max_length - d.size();\n            std::string spaces(nb_spaces, ' ');\n            out << d << spaces << \": \" << coords[d] << std::endl;\n        }\n\n        return out;\n    }\n\n    /******************************************\n     * xvariable_view builders implementation *\n     ******************************************/\n\n    namespace detail\n    {\n        template <class R>\n        struct range_adaptor_getter\n        {\n            using return_type = typename xaxis_index_slice<R>::storage_type;\n            explicit range_adaptor_getter(std::size_t size)\n                : m_size(size)\n            {\n            }\n\n            template <class T>\n            return_type operator()(const T&) const\n            {\n                throw std::runtime_error(\"Unvalid slice where xrange_adaptor was expected\");\n            }\n\n            template <class A, class B, class C>\n            return_type operator()(const xt::xrange_adaptor<A, B, C>& r) const\n            {\n                return r.get(m_size);\n            }\n\n            std::size_t m_size;\n        };\n\n        template <class E>\n        struct view_params\n        {\n            using coordinate_type = typename std::decay_t<E>::coordinate_type;\n            using dimension_type = typename std::decay_t<E>::dimension_type;\n            using dimension_label_list = typename dimension_type::label_list;\n            using view_type = xvariable_view<xtl::closure_type_t<E>>;\n            using squeeze_map = typename view_type::squeeze_map;\n            using coordinate_view_type = typename view_type::coordinate_type;\n            using map_type = typename coordinate_view_type::map_type;\n            using axis_type = typename coordinate_view_type::axis_type;\n            using slice_vector = xt::xdynamic_slice_vector;\n\n            map_type coord_map;\n            squeeze_map sq_map;\n            dimension_label_list dim_label_list;\n            slice_vector dyn_slices;\n        };\n\n        template <class T, class E>\n        class slice_to_view_param\n        {\n        public:\n\n            using dimension_type = typename std::decay_t<E>::dimension_type;\n            using dimension_label_list = typename dimension_type::label_list;\n            using label_type = typename dimension_label_list::value_type;\n            using param_type = view_params<E>;\n            using view_type = xvariable_view<xtl::closure_type_t<E>>;\n            using coordinate_view_type = typename view_type::coordinate_type;\n            using axis_type = typename coordinate_view_type::axis_type;\n            using axis_slice_type = typename axis_type::slice_type;\n            using size_type = typename std::decay_t<E>::size_type;\n            using dynamic_slice = xt::xdynamic_slice<std::ptrdiff_t>;\n\n            slice_to_view_param(const E& e, param_type& param)\n                : m_e(e), m_param(param)\n            {\n            }\n\n            inline void operator()(T slice, const label_type& dim_label)\n            {\n                auto dim_idx = m_e.dimension_mapping()[dim_label];\n                m_param.sq_map[dim_idx] = slice;\n                m_param.dyn_slices[dim_idx] = static_cast<std::ptrdiff_t>(slice);\n            }\n\n            inline void operator()(const xt::xkeep_slice<T>& slice, const label_type& dim_label)\n            {\n                const auto& axis = m_e.coordinates()[dim_label];\n                xt::xkeep_slice<T> coord_slice(slice);\n                coord_slice.normalize(axis.size());\n                m_param.coord_map.emplace(dim_label, axis_type(axis, axis_slice_type(std::move(coord_slice))));\n                m_param.dim_label_list.push_back(dim_label);\n                auto dim_idx = m_e.dimension_mapping()[dim_label];\n                m_param.dyn_slices[dim_idx] = xt::xkeep_slice<std::ptrdiff_t>(slice);\n            }\n\n            inline void operator()(const xt::xdrop_slice<T>& slice, const label_type& dim_label)\n            {\n                const auto& axis = m_e.coordinates()[dim_label];\n                xt::xdrop_slice<T> coord_slice(slice);\n                coord_slice.normalize(axis.size());\n                m_param.coord_map.emplace(dim_label, axis_type(axis, axis_slice_type(std::move(coord_slice))));\n                m_param.dim_label_list.push_back(dim_label);\n                auto dim_idx = m_e.dimension_mapping()[dim_label];\n                m_param.dyn_slices[dim_idx] = xt::xdrop_slice<std::ptrdiff_t>(slice);\n            }\n\n            inline void operator()(xt::xall_tag, const label_type& dim_label)\n            {\n                const auto& axis = m_e.coordinates()[dim_label];\n                m_param.coord_map.emplace(dim_label, axis_type(axis, xt::xall<std::size_t>(axis.size())));\n                m_param.dim_label_list.push_back(dim_label);\n                auto dim_idx = m_e.dimension_mapping()[dim_label];\n                m_param.dyn_slices[dim_idx] = xt::xall_tag();\n            }\n\n            inline void operator()(xt::xellipsis_tag, const label_type&)\n            {\n                throw std::runtime_error(\"xellipsis_tag not supported\");\n            }\n\n            inline void operator()(xt::xnewaxis_tag, const label_type&)\n            {\n                throw std::runtime_error(\"xnewaxis_tag not supported\");\n            }\n\n            template <class A, class B, class C>\n            inline void operator()(const xt::xrange_adaptor<A, B, C>& slice, const label_type& dim_label)\n            {\n                const auto& axis = m_e.coordinates()[dim_label];\n                range_adaptor_getter<size_type> rag(axis.size());\n                auto ra = rag(slice);\n                m_param.coord_map.emplace(dim_label, axis_type(axis, axis_slice_type(ra)));\n                m_param.dim_label_list.push_back(dim_label);\n                auto dim_idx = m_e.dimension_mapping()[dim_label];\n                m_param.dyn_slices[dim_idx] = slice;\n            }\n\n            inline void operator()(const xt::xrange<T>& slice, const label_type& dim_label)\n            {\n                const auto& axis = m_e.coordinates()[dim_label];\n                m_param.coord_map.emplace(dim_label, axis_type(axis, axis_slice_type(slice)));\n                m_param.dim_label_list.push_back(dim_label);\n                auto dim_idx = m_e.dimension_mapping()[dim_label];\n                m_param.dyn_slices[dim_idx] = slice;\n            }\n\n            inline void operator()(const xt::xstepped_range<T>& slice, const label_type& dim_label)\n            {\n                const auto& axis = m_e.coordinates()[dim_label];\n                m_param.coord_map.emplace(dim_label, axis_type(axis, axis_slice_type(slice)));\n                m_param.dim_label_list.push_back(dim_label);\n                auto dim_idx = m_e.dimension_mapping()[dim_label];\n                m_param.dyn_slices[dim_idx] = slice;\n            }\n\n        private:\n\n            const E& m_e;\n            param_type& m_param;\n        };\n\n        template <class E>\n        struct locate_params_builder\n        {\n            using param_type = view_params<E>;\n\n            template <std::size_t I>\n            inline void fill_view_params(param_type& /*param*/, const E& /*e*/)\n            {\n            }\n\n            template <std::size_t I, class SL, class... S>\n            inline void fill_view_params(param_type& param, const E& e, SL&& sl, S&&... slices)\n            {\n                using axis_type = typename view_params<E>::axis_type;\n                using dynamic_slice = xt::xdynamic_slice<std::ptrdiff_t>;\n                const auto& dim_label = e.dimension_labels()[I];\n                const auto& axis = e.coordinates()[dim_label];\n                if (auto* sq = sl.get_squeeze())\n                {\n                    auto idx_sq = axis[*sq];\n                    param.sq_map[I] = idx_sq;\n                    param.dyn_slices[I] = static_cast<std::ptrdiff_t>(idx_sq);\n                }\n                else\n                {\n                    auto idx_slice = sl.build_index_slice(axis);\n                    param.dyn_slices[I] = idx_slice.template convert_storage<dynamic_slice, std::ptrdiff_t>();\n                    param.coord_map.emplace(dim_label, axis_type(axis, std::move(idx_slice)));\n                    param.dim_label_list.push_back(dim_label);\n                }\n                fill_view_params<I + 1>(param, e, std::forward<S>(slices)...);\n            }\n        };\n\n        template <class E>\n        struct ilocate_param_builder\n        {\n            using param_type = view_params<E>;\n\n            template <std::size_t I>\n            inline void fill_view_params(param_type& /*param*/, const E& /*e*/)\n            {\n            }\n\n            template <std::size_t I, class SL, class... S>\n            inline void fill_view_params(param_type& param, const E& e, SL&& sl, S&&... slices)\n            {\n                using size_type = typename std::decay_t<E>::size_type;\n                slice_to_view_param<size_type, E> visitor(e, param);\n                const auto& dim_label = e.dimension_labels()[I];\n                xtl::visit([&visitor, &dim_label](auto&& slice) { visitor(slice, dim_label); }, sl);\n                fill_view_params<I + 1>(param, e, std::forward<S>(slices)...);\n            }\n        };\n\n        template <std::size_t I, class V, class E>\n        inline void fill_view_params(V& /*param*/, E& /*e*/)\n        {\n        }\n\n        template <std::size_t I, class V, class E, class SL, class... S>\n        inline void fill_view_params(V& param, E& e, SL&& sl, S&&... slices)\n        {\n            using axis_type = typename view_params<E>::axis_type;\n            using size_type = typename std::decay_t<E>::size_type;\n\n            const auto& dim_label = e.dimension_labels()[I];\n            const auto& axis = e.coordinates()[dim_label];\n            if (auto* sq = sl.get_squeeze())\n            {\n                param.sq_map[I] = *sq;\n            }\n            else if (auto* sq = sl.get_all())\n            {\n                param.coord_map.emplace(dim_label, axis_type(axis, xt::xall<size_type>(axis.size())));\n                param.dim_label_list.push_back(dim_label);\n            }\n            else\n            {\n                param.coord_map.emplace(dim_label, axis_type(axis, *(sl.get_slice())));\n                param.dim_label_list.push_back(dim_label);\n            }\n            fill_view_params<I + 1>(param, e, std::forward<S>(slices)...);\n        }\n    }\n\n    template <class E, class... S>\n    inline auto ilocate(E&& e, S&&... slices)\n    {\n        using builder_type = detail::ilocate_param_builder<E>;\n        using view_param_type = detail::view_params<E>;\n        using coordinate_view_type = typename view_param_type::coordinate_view_type;\n        using dimension_type = typename view_param_type::dimension_type;\n        using view_type = typename view_param_type::view_type;\n\n        view_param_type params;\n        params.dyn_slices.resize(sizeof...(S));\n        builder_type builder;\n        builder.template fill_view_params<0>(params, e, xt::xdynamic_slice<std::ptrdiff_t>(std::forward<S>(slices))...);\n\n        coordinate_view_type coordinate_view(std::move(params.coord_map));\n        dimension_type view_dimension(std::move(params.dim_label_list));\n\n        return view_type(std::forward<E>(e),\n                         std::move(coordinate_view),\n                         std::move(view_dimension),\n                         std::move(params.sq_map),\n                         std::move(params.dyn_slices));\n    }\n\n    template <class L, class E, class... S>\n    inline auto locate(E&& e, S&&... slices)\n    {\n        using builder_type = detail::locate_params_builder<E>;\n        using view_param_type = typename builder_type::param_type;\n        using coordinate_view_type = typename view_param_type::coordinate_view_type;\n        using dimension_type = typename view_param_type::dimension_type;\n        using view_type = typename view_param_type::view_type;\n\n        view_param_type params;\n        params.dyn_slices.resize(sizeof...(S));\n        builder_type builder;\n        builder.template fill_view_params<0>(params, e, xaxis_slice<L>(std::forward<S>(slices))...);\n\n        coordinate_view_type coordinate_view(std::move(params.coord_map));\n        dimension_type view_dimension(std::move(params.dim_label_list));\n\n        return view_type(std::forward<E>(e),\n                         std::move(coordinate_view),\n                         std::move(view_dimension),\n                         std::move(params.sq_map),\n                         std::move(params.dyn_slices));\n    }\n\n    template <class E, class L>\n    inline auto select(E&& e, std::map<typename std::decay_t<E>::key_type, xaxis_slice<L>>&& slices)\n    {\n        using coordinate_type = typename std::decay_t<E>::coordinate_type;\n        using dimension_type = typename std::decay_t<E>::dimension_type;\n        using dimension_label_list = typename dimension_type::label_list;\n        using view_type = xvariable_view<xtl::closure_type_t<E>>;\n        using squeeze_map = typename view_type::squeeze_map;\n        using coordinate_view_type = typename view_type::coordinate_type;\n        using map_type = typename coordinate_view_type::map_type;\n        using axis_type = typename coordinate_view_type::axis_type;\n        using size_type = typename std::decay_t<E>::size_type;\n        using dynamic_slice = xt::xdynamic_slice<std::ptrdiff_t>;\n\n        const coordinate_type& underlying_coords = e.coordinates();\n        map_type coord_map;\n        squeeze_map sq_map;\n        dimension_label_list dim_label_list;\n        xt::xdynamic_slice_vector dsv(underlying_coords.size());\n\n        for(const auto& dim_label: e.dimension_labels())\n        {\n            auto dim_index = e.dimension_mapping()[dim_label];\n            const auto& axis = underlying_coords[dim_label];\n            auto slice_iter = slices.find(dim_label);\n            if (slice_iter != slices.end())\n            {\n                if (auto* sq = (slice_iter->second).get_squeeze())\n                {\n                    auto idx_sq = axis[*sq];\n                    dsv[dim_index] = static_cast<std::ptrdiff_t>(idx_sq);\n                    sq_map[dim_index] = idx_sq;\n                }\n                else\n                {\n                    auto idx_slice = (slice_iter->second).build_index_slice(axis);\n                    dsv[dim_index] = idx_slice.template convert_storage<dynamic_slice, std::ptrdiff_t>();\n                    coord_map.emplace(dim_label, axis_type(axis, std::move(idx_slice)));\n                    dim_label_list.push_back(dim_label);\n                }\n            }\n            else\n            {\n                dsv[dim_index] = xt::xall_tag();\n                coord_map.emplace(dim_label, axis_type(axis, xt::xall<size_type>(axis.size())));\n                dim_label_list.push_back(dim_label);\n            }\n        }\n\n        coordinate_view_type coordinate_view(std::move(coord_map));\n        dimension_type view_dimension(std::move(dim_label_list));\n\n        return view_type(std::forward<E>(e),\n                         std::move(coordinate_view),\n                         std::move(view_dimension),\n                         std::move(sq_map),\n                         std::move(dsv));\n    }\n\n    template <class E, class T>\n    inline auto iselect(E&& e, std::map<typename std::decay_t<E>::key_type, xt::xdynamic_slice<T>>&& slices)\n    {\n        using visitor_type = detail::slice_to_view_param<T, E>;\n        using view_param_type = typename visitor_type::param_type;\n        using view_type = xvariable_view<xtl::closure_type_t<E>>;\n        using coordinate_view_type = typename view_type::coordinate_type;\n        using dimension_type = typename std::decay_t<E>::dimension_type;\n        using axis_type = typename coordinate_view_type::axis_type;\n        using size_type = typename std::decay_t<E>::size_type;\n\n        view_param_type param;\n        param.dyn_slices.resize(slices.size());\n        visitor_type visitor(e, param);\n\n        for (const auto& dim_label : e.dimension_labels())\n        {\n            const auto& axis = e.coordinates()[dim_label];\n            auto slice_iter = slices.find(dim_label);\n            if (slice_iter != slices.end())\n            {\n                xtl::visit([&visitor, &dim_label](auto&& val) { visitor(val, dim_label); }, slice_iter->second);\n            }\n            else\n            {\n                param.coord_map.emplace(dim_label, axis_type(axis, xt::xall<size_type>(axis.size())));\n                param.dim_label_list.push_back(dim_label);\n            }\n        }\n\n        coordinate_view_type coordinate_view(std::move(param.coord_map));\n        dimension_type view_dimension(std::move(param.dim_label_list));\n\n        return view_type(std::forward<E>(e),\n                         std::move(coordinate_view),\n                         std::move(view_dimension),\n                         std::move(param.sq_map),\n                         std::move(param.dyn_slices));\n    }\n}\n\n#endif\n"
  },
  {
    "path": "include/xframe/xvector_variant.hpp",
    "content": "/***************************************************************************\n* Copyright (c) Johan Mabille, Sylvain Corlay, Wolf Vollprecht and         *\n* Martin Renou                                                             *\n* Copyright (c) QuantStack                                                 *\n*                                                                          *\n* Distributed under the terms of the BSD 3-Clause License.                 *\n*                                                                          *\n* The full license is in the file LICENSE, distributed with this software. *\n****************************************************************************/\n\n#ifndef XFRAME_XVECTOR_VARIANT_HPP\n#define XFRAME_XVECTOR_VARIANT_HPP\n\n#include \"xtl/xclosure.hpp\"\n#include \"xtl/xiterator_base.hpp\"\n#include \"xtl/xmeta_utils.hpp\"\n#include \"xtl/xvariant.hpp\"\n\nnamespace xf\n{\n    namespace mpl = xtl::mpl;\n\n    namespace detail\n    {\n        template <class L0, class...>\n        struct xvector_variant_size_traits\n        {\n            using size_type = typename std::vector<L0>::size_type;\n            using difference_type = typename std::vector<L0>::difference_type;\n        };\n\n        template <bool is_const, class L>\n        struct xvector_variant_value_traits;\n\n        template <bool is_const, class T>\n        struct xvector_variant_value_traits<is_const, mpl::vector<T>>\n        {\n            using value_type = T;\n            using const_reference = const T&;\n            using reference = std::conditional_t<is_const, const_reference, T&>;\n            using const_pointer = const T*;\n            using pointer = std::conditional_t<is_const, const_pointer, T*>;\n        };\n\n        template <bool is_const, class... T>\n        struct xvector_variant_value_traits<is_const, mpl::vector<T...>>\n        {\n            using value_type = xtl::variant<T...>;\n            using const_reference = xtl::variant<xtl::xclosure_wrapper<const T&>...>;\n            using reference = std::conditional_t<is_const,\n                                                 const_reference,\n                                                 xtl::variant<xtl::xclosure_wrapper<T&>...>>;\n            using const_pointer = xtl::variant<const T*...>;\n            using pointer = std::conditional_t<is_const,\n                                               const_pointer,\n                                               xtl::variant<T*...>>;\n        };\n\n        template <bool is_const, bool is_ref, class... V>\n        struct xvector_variant_traits\n        {\n            using storage_type = \n                std::conditional_t<is_ref,\n                                   std::conditional_t<is_const,\n                                                      xtl::variant<xtl::xclosure_wrapper<const V&>...>,\n                                                      xtl::variant<xtl::xclosure_wrapper<V&>...>>,\n                                   xtl::variant<V...>>;\n            using value_type_list = mpl::unique_t<mpl::vector<typename V::value_type...>>;\n            using value_traits = xvector_variant_value_traits<is_const, value_type_list>;\n            using size_traits = xvector_variant_size_traits<V...>;\n\n            using value_type = typename value_traits::value_type;\n            using reference = typename value_traits::reference;\n            using const_reference = typename value_traits::const_reference;\n            using pointer = typename value_traits::pointer;\n            using const_pointer = typename value_traits::const_pointer;\n            using size_type = typename size_traits::size_type;\n            using difference_type = typename size_traits::difference_type;\n\n            using const_iterator = xtl::variant<typename V::const_iterator...>;\n            using iterator = std::conditional_t<is_const,\n                                                const_iterator,\n                                                xtl::variant<typename V::iterator...>>;\n        };\n\n        template <bool is_const, class traits>\n        struct xvector_variant_iterator_traits\n        {\n            using value_type = typename traits::value_type;\n            using reference = std::conditional_t<is_const, typename traits::const_reference, typename traits::reference>;\n            using pointer = std::conditional_t<is_const, typename traits::const_pointer, typename traits::pointer>;\n            using difference_type = typename traits::difference_type;\n            using iterator = std::conditional_t<is_const, typename traits::const_iterator, typename traits::iterator>;\n        };\n\n        template <class T1, class T2>\n        using is_unlike = xtl::negation<std::is_same<std::decay_t<T1>, std::decay_t<T2>>>;\n    }\n\n    /************************\n     * xvector_variant_base *\n     ************************/\n\n    template <class traits>\n    class xvector_variant_iterator;\n\n    template <class traits>\n    class xvector_variant_base\n    {\n    public:\n\n        using self_type = xvector_variant_base;\n        using value_type = typename traits::value_type;\n        using reference = typename traits::reference;\n        using const_reference = typename traits::const_reference;\n        using pointer = typename traits::pointer;\n        using const_pointer = typename traits::const_pointer;\n        using size_type = typename traits::size_type;\n        using difference_type = typename traits::difference_type;\n        using storage_type = typename traits::storage_type;\n\n        using iterator_traits = detail::xvector_variant_iterator_traits<false, traits>;\n        using const_iterator_traits = detail::xvector_variant_iterator_traits<true, traits>;\n\n        using iterator = xvector_variant_iterator<iterator_traits>;\n        using const_iterator = xvector_variant_iterator<const_iterator_traits>;\n\n        // Size and capacity\n\n        bool empty() const;\n        size_type size() const;\n        void resize(size_type new_size);\n        size_type max_size() const;\n        size_type capacity() const;\n        void reserve(size_type new_cap);\n        void shrink_to_fit();\n        void clear();\n\n        // Element access\n\n        reference operator[](size_type i);\n        const_reference operator[](size_type i) const;\n\n        reference at(size_type i);\n        const_reference at(size_type i) const;\n\n        reference front();\n        const_reference front() const;\n\n        reference back();\n        const_reference back() const;\n\n        pointer data();\n        const_pointer data() const;\n\n        storage_type& storage();\n        const storage_type& storage() const;\n\n        // Iterators\n\n        iterator begin();\n        iterator end();\n\n        const_iterator begin() const;\n        const_iterator end() const;\n\n        const_iterator cbegin() const;\n        const_iterator cend() const;\n\n        // swap\n\n        void swap(self_type& rhs);\n\n        // Comparison\n\n        bool equal(const self_type& rhs) const;\n        bool less_than(const self_type& rhs) const;\n\n    protected:\n\n        template <class T,\n                  XTL_REQUIRES(detail::is_unlike<T, self_type>)>\n        xvector_variant_base(T&& v)\n            : m_storage(std::forward<T>(v))\n        {\n        }\n\n        ~xvector_variant_base() = default;\n\n        xvector_variant_base(const self_type&) = default;\n        xvector_variant_base(self_type&&) = default;\n\n        self_type& operator=(const self_type& rhs) = default;\n        self_type& operator=(self_type&& rhs) = default;\n\n\n    private:\n\n        storage_type m_storage;\n    };\n\n    template <class T>\n    bool operator==(const xvector_variant_base<T>& lhs, const xvector_variant_base<T>& rhs);\n\n    template <class T>\n    bool operator!=(const xvector_variant_base<T>& lhs, const xvector_variant_base<T>& rhs);\n\n    template <class T>\n    bool operator<(const xvector_variant_base<T>& lhs, const xvector_variant_base<T>& rhs);\n\n    template <class T>\n    bool operator<=(const xvector_variant_base<T>& lhs, const xvector_variant_base<T>& rhs);\n\n    template <class T>\n    bool operator>(const xvector_variant_base<T>& lhs, const xvector_variant_base<T>& rhs);\n\n    template <class T>\n    bool operator>=(const xvector_variant_base<T>& lhs, const xvector_variant_base<T>& rhs);\n\n    /****************************\n     * xvector_variant_iterator *\n     ****************************/\n\n    template <class traits>\n    class xvector_variant_iterator : public xtl::xrandom_access_iterator_base<xvector_variant_iterator<traits>,\n                                                                              typename traits::value_type,\n                                                                              typename traits::difference_type,\n                                                                              typename traits::pointer,\n                                                                              typename traits::reference>\n    {\n    public:\n\n        using self_type = xvector_variant_iterator<traits>;\n        using value_type = typename traits::value_type;\n        using reference = typename traits::reference;\n        using pointer = typename traits::pointer;\n        using difference_type = typename traits::difference_type;\n        using iterator_category = std::random_access_iterator_tag;\n        using subiterator = typename traits::iterator;\n\n        xvector_variant_iterator() = default;\n        xvector_variant_iterator(subiterator it);\n\n        self_type& operator++();\n        self_type& operator--();\n\n        self_type& operator+=(difference_type n);\n        self_type& operator-=(difference_type n);\n\n        difference_type operator-(const self_type& rhs) const;\n\n        reference operator*() const;\n        //pointer operator->() const;\n\n        bool equal(const self_type& rhs) const;\n        bool less_than(const self_type& rhs) const;\n\n    private:\n\n        subiterator m_it;\n    };\n\n    template <class T>\n    bool operator==(const xvector_variant_iterator<T>& lhs, const xvector_variant_iterator<T>& rhs);\n\n    template <class T>\n    bool operator<(const xvector_variant_iterator<T>& lhs, const xvector_variant_iterator<T>& rhs);\n\n    /*******************\n     * xvector_variant *\n     *******************/\n\n    template <class... V>\n    class xvector_variant : public xvector_variant_base<detail::xvector_variant_traits<false, false, V...>>\n    {\n    public:\n\n        using traits_type = detail::xvector_variant_traits<false, false, V...>;\n        using base_type = xvector_variant_base<traits_type>;\n        using self_type = xvector_variant<V...>;\n\n        template <class OV,\n                  XTL_REQUIRES(detail::is_unlike<OV, self_type>)>\n        inline xvector_variant(OV&& v)\n            : base_type(std::forward<OV>(v))\n        {\n        }\n\n        ~xvector_variant() = default;\n\n        xvector_variant(const self_type&) = default;\n        self_type& operator=(const self_type&) = default;\n\n        xvector_variant(self_type&&) = default;\n        self_type& operator=(self_type&&) = default;\n    };\n\n    template <class... V>\n    void swap(xvector_variant<V...>& lhs, xvector_variant<V...>& rhs);\n\n    template <class T, class... V>\n    T& xget_vector(xvector_variant<V...>& v);\n\n    template <class T, class... V>\n    const T& xget_vector(const xvector_variant<V...>& v);\n\n    template <class T, class... V>\n    T&& xget_vector(xvector_variant<V...>&& v);\n\n    template <class T, class... V>\n    const T&& xget_vector(const xvector_variant<V...>&& v);\n\n    /***********************\n     * xvector_variant_ref *\n     ***********************/\n\n    template <class ...V>\n    class xvector_variant_ref : public xvector_variant_base<detail::xvector_variant_traits<false, true, V...>>\n    {\n    public:\n\n        using traits_type = detail::xvector_variant_traits<false, true, V...>;\n        using base_type = xvector_variant_base<traits_type>;\n        using self_type = xvector_variant_ref<V...>;\n\n        template <class OV,\n                  XTL_REQUIRES(detail::is_unlike<OV, self_type>)>\n        inline xvector_variant_ref(OV& v)\n            : base_type(v)\n        {\n        }\n\n        ~xvector_variant_ref() = default;\n\n        xvector_variant_ref(const self_type&) = default;\n        self_type& operator=(const self_type& rhs) = default;\n\n        xvector_variant_ref(self_type&&) = default;\n        self_type& operator=(self_type&&) = default;\n    };\n\n    template <class... V>\n    void swap(xvector_variant_ref<V...>& lhs, xvector_variant_ref<V...>& rhs);\n\n    template <class T, class... V>\n    T& xget_vector(xvector_variant_ref<V...>& v);\n\n    template <class T, class... V>\n    const T& xget_vector(const xvector_variant_ref<V...>& v);\n\n    template <class T, class... V>\n    T& xget_vector(xvector_variant_ref<V...>&& v);\n\n    template <class T, class... V>\n    const T& xget_vector(const xvector_variant_ref<V...>&& v);\n\n    /************************\n     * xvector_variant_cref *\n     ************************/\n\n    template <class ...V>\n    class xvector_variant_cref : public xvector_variant_base<detail::xvector_variant_traits<true, true, V...>>\n    {\n    public:\n\n        using traits_type = detail::xvector_variant_traits<true, true, V...>;\n        using base_type = xvector_variant_base<traits_type>;\n        using self_type = xvector_variant_cref<V...>;\n\n        template <class OV,\n                  XTL_REQUIRES(detail::is_unlike<OV, self_type>)>\n        inline xvector_variant_cref(OV& v)\n            : base_type(v)\n        {\n        }\n\n        ~xvector_variant_cref() = default;\n\n        xvector_variant_cref(const self_type&) = default;\n        xvector_variant_cref(self_type&&) = default;\n    };\n\n    template <class T, class... V>\n    const T& xget_vector(xvector_variant_cref<V...>& v);\n\n    template <class T, class... V>\n    const T& xget_vector(const xvector_variant_cref<V...>& v);\n\n    template <class T, class... V>\n    const T& xget_vector(xvector_variant_cref<V...>&& v);\n\n    template <class T, class... V>\n    const T& xget_vector(const xvector_variant_cref<V...>&& v);\n\n    /***************************************\n     * xvector_variant_base implementation *\n     ***************************************/\n\n    namespace detail\n    {\n        template <class T>\n        inline T& unwrap(T& arg)\n        {\n            return arg;\n        }\n\n        template <class T>\n        inline const T& unwrap(const T& arg)\n        {\n            return arg;\n        }\n\n        template <class T>\n        inline T& unwrap(xtl::xclosure_wrapper<T&>& arg)\n        {\n            return arg.get();\n        }\n\n        template <class T>\n        inline const T& unwrap(const xtl::xclosure_wrapper<T&>& arg)\n        {\n            return arg.get();\n        }\n    }\n\n    template <class T>\n    inline bool xvector_variant_base<T>::empty() const\n    {\n        return xtl::visit([](const auto& arg) { return detail::unwrap(arg).empty(); }, m_storage);\n    }\n\n    template <class T>\n    inline auto xvector_variant_base<T>::size() const -> size_type\n    {\n        return xtl::visit([](const auto& arg) { return detail::unwrap(arg).size(); }, m_storage);\n    }\n\n    template <class T>\n    inline void xvector_variant_base<T>::resize(size_type size)\n    {\n        xtl::visit([size](auto& arg) { detail::unwrap(arg).resize(size); }, m_storage);\n    }\n\n    template <class T>\n    inline auto xvector_variant_base<T>::max_size() const -> size_type\n    {\n        return xtl::visit([](const auto& arg) { return detail::unwrap(arg).max_size(); }, m_storage);\n    }\n\n    template <class T>\n    inline auto xvector_variant_base<T>::capacity() const -> size_type\n    {\n        return xtl::visit([](const auto& arg) { return detail::unwrap(arg).capacity(); }, m_storage);\n    }\n\n    template <class T>\n    inline void xvector_variant_base<T>::reserve(size_type new_cap)\n    {\n        xtl::visit([new_cap](auto& arg) { detail::unwrap(arg).reserve(new_cap); }, m_storage);\n    }\n\n    template <class T>\n    inline void xvector_variant_base<T>::shrink_to_fit()\n    {\n        xtl::visit([](auto& arg) { detail::unwrap(arg).shrink_to_fit(); }, m_storage);\n    }\n\n    template <class T>\n    inline void xvector_variant_base<T>::clear()\n    {\n        xtl::visit([](auto& arg) { detail::unwrap(arg).clear(); }, m_storage);\n    }\n\n    template <class T>\n    inline auto xvector_variant_base<T>::operator[](size_type i) -> reference\n    {\n        return xtl::visit([i](auto& arg)\n        {\n            return reference(xtl::closure(detail::unwrap(arg)[i]));\n        },\n        m_storage);\n    }\n\n    template <class T>\n    inline auto xvector_variant_base<T>::operator[](size_type i) const -> const_reference\n    {\n        return xtl::visit([i](const auto& arg)\n        {\n            return const_reference(xtl::closure(detail::unwrap(arg)[i]));\n        },\n        m_storage);\n    }\n\n    template <class T>\n    inline auto xvector_variant_base<T>::at(size_type i) -> reference\n    {\n        return xtl::visit([i](auto& arg)\n        {\n            return reference(xtl::closure(detail::unwrap(arg).at(i)));\n        },\n        m_storage);\n    }\n\n    template <class T>\n    inline auto xvector_variant_base<T>::at(size_type i) const -> const_reference\n    {\n        return xtl::visit([i](const auto& arg)\n        {\n            return const_reference(xtl::closure(detail::unwrap(arg)[i]));\n        },\n        m_storage);\n    }\n\n    template <class T>\n    inline auto xvector_variant_base<T>::front() -> reference\n    {\n        return xtl::visit([](auto& arg)\n        {\n            return reference(xtl::closure(detail::unwrap(arg).front()));\n        },\n        m_storage);\n    }\n\n    template <class T>\n    inline auto xvector_variant_base<T>::front() const -> const_reference\n    {\n        return xtl::visit([](const auto& arg)\n        {\n            return const_reference(xtl::closure(detail::unwrap(arg).front()));\n        },\n        m_storage);\n    }\n\n    template <class T>\n    inline auto xvector_variant_base<T>::back() -> reference\n    {\n        return xtl::visit([](auto& arg)\n        {\n            return reference(xtl::closure(detail::unwrap(arg).back()));\n        },\n        m_storage);\n    }\n\n    template <class T>\n    inline auto xvector_variant_base<T>::back() const -> const_reference\n    {\n        return xtl::visit([](const auto& arg)\n        {\n            return const_reference(xtl::closure(detail::unwrap(arg).back()));\n        },\n        m_storage);\n    }\n\n    template <class T>\n    inline auto xvector_variant_base<T>::data() -> pointer\n    {\n        return xtl::visit([](auto& arg) { return pointer(detail::unwrap(arg).data()); }, m_storage);\n    }\n\n    template <class T>\n    inline auto xvector_variant_base<T>::data() const -> const_pointer\n    {\n        return xtl::visit([](const auto& arg) { return const_pointer(detail::unwrap(arg).data()); }, m_storage);\n    }\n\n    template <class T>\n    inline auto xvector_variant_base<T>::storage() -> storage_type&\n    {\n        return m_storage;\n    }\n\n    template <class T>\n    inline auto xvector_variant_base<T>::storage() const -> const storage_type&\n    {\n        return m_storage;\n    }\n\n    template <class T>\n    inline auto xvector_variant_base<T>::begin() -> iterator\n    {\n        return xtl::visit([](auto& arg) { return iterator(detail::unwrap(arg).begin()); }, m_storage);\n    }\n\n    template <class T>\n    inline auto xvector_variant_base<T>::end() -> iterator\n    {\n        return xtl::visit([](auto& arg) { return iterator(detail::unwrap(arg).end()); }, m_storage);\n    }\n\n    template <class T>\n    inline auto xvector_variant_base<T>::begin() const -> const_iterator\n    {\n        return cbegin();\n    }\n\n    template <class T>\n    inline auto xvector_variant_base<T>::end() const -> const_iterator\n    {\n        return cend();\n    }\n\n    template <class T>\n    inline auto xvector_variant_base<T>::cbegin() const -> const_iterator\n    {\n        return xtl::visit([](const auto& arg) { return const_iterator(detail::unwrap(arg).cbegin()); }, m_storage);\n    }\n\n    template <class T>\n    inline auto xvector_variant_base<T>::cend() const -> const_iterator\n    {\n        return xtl::visit([](const auto& arg) { return const_iterator(detail::unwrap(arg).cend()); }, m_storage);\n    }\n\n    template <class T>\n    inline void xvector_variant_base<T>::swap(self_type& rhs)\n    {\n        m_storage.swap(rhs.m_storage);\n    }\n\n    template <class T>\n    inline bool xvector_variant_base<T>::equal(const self_type& rhs) const\n    {\n        return m_storage == rhs.m_storage;\n    }\n\n    template <class T>\n    inline bool xvector_variant_base<T>::less_than(const self_type& rhs) const\n    {\n        return m_storage < rhs.m_storage;\n    }\n\n    template <class T>\n    inline bool operator==(const xvector_variant_base<T>& lhs, const xvector_variant_base<T>& rhs)\n    {\n        return lhs.equal(rhs);\n    }\n\n    template <class T>\n    inline bool operator!=(const xvector_variant_base<T>& lhs, const xvector_variant_base<T>& rhs)\n    {\n        return !(lhs == rhs);\n    }\n\n    template <class T>\n    inline bool operator<(const xvector_variant_base<T>& lhs, const xvector_variant_base<T>& rhs)\n    {\n        return lhs.less_than(rhs);\n    }\n\n    template <class T>\n    inline bool operator<=(const xvector_variant_base<T>& lhs, const xvector_variant_base<T>& rhs)\n    {\n        return !(rhs < lhs);\n    }\n\n    template <class T>\n    inline bool operator>(const xvector_variant_base<T>& lhs, const xvector_variant_base<T>& rhs)\n    {\n        return rhs < lhs;\n    }\n\n    template <class T>\n    inline bool operator>=(const xvector_variant_base<T>& lhs, const xvector_variant_base<T>& rhs)\n    {\n        return !(lhs < rhs);\n    }\n    \n    /****************************\n     * xvector_variant_iterator *\n     ****************************/\n\n    template <class T>\n    inline xvector_variant_iterator<T>::xvector_variant_iterator(subiterator it)\n        : m_it(it)\n    {\n    }\n\n    template <class T>\n    inline auto xvector_variant_iterator<T>::operator++() -> self_type&\n    {\n        xtl::visit([](auto& arg) { ++arg; }, m_it);\n        return *this;\n    }\n\n    template <class T>\n    inline auto xvector_variant_iterator<T>::operator--() -> self_type&\n    {\n        xtl::visit([](auto& arg) { --arg; }, m_it);\n        return *this;\n    }\n\n    template <class T>\n    inline auto xvector_variant_iterator<T>::operator+=(difference_type n) -> self_type&\n    {\n        xtl::visit([n](auto& arg) { arg += n; }, m_it);\n        return *this;\n    }\n\n    template <class T>\n    inline auto xvector_variant_iterator<T>::operator-=(difference_type n) -> self_type&\n    {\n        xtl::visit([n](auto& arg) { arg -= n; }, m_it);\n        return *this;\n    }\n\n    template <class T>\n    inline auto xvector_variant_iterator<T>::operator-(const self_type& rhs) const -> difference_type\n    {\n        return xtl::visit([&rhs](auto& arg) { return arg - xtl::xget<std::decay_t<decltype(arg)>>(rhs.m_it); }, m_it);\n    }\n\n    template <class T>\n    inline auto xvector_variant_iterator<T>::operator*() const -> reference\n    {\n        return xtl::visit([](auto& arg) { return reference(xtl::closure(*arg)); }, m_it);\n    }\n\n    template <class T>\n    inline bool xvector_variant_iterator<T>::equal(const self_type& rhs) const\n    {\n        return m_it == rhs.m_it;\n    }\n\n    template <class T>\n    inline bool xvector_variant_iterator<T>::less_than(const self_type& rhs) const\n    {\n        return m_it < rhs.m_it;\n    }\n\n    template <class T>\n    inline bool operator==(const xvector_variant_iterator<T>& lhs, const xvector_variant_iterator<T>& rhs)\n    {\n        return lhs.equal(rhs);\n    }\n\n    template <class T>\n    inline bool operator<(const xvector_variant_iterator<T>& lhs, const xvector_variant_iterator<T>& rhs)\n    {\n        return lhs.less_than(rhs);\n    }\n\n    /**********************************\n     * xvector_variant implementation *\n     **********************************/\n\n    template <class... V>\n    inline void swap(xvector_variant<V...>& lhs, xvector_variant<V...>& rhs)\n    {\n        lhs.swap(rhs);\n    }\n\n    template <class T, class... V>\n    inline T& xget_vector(xvector_variant<V...>& v)\n    {\n        return xtl::xget<T>(v.storage());\n    }\n\n    template <class T, class... V>\n    inline const T& xget_vector(const xvector_variant<V...>& v)\n    {\n        return xtl::xget<T>(v.storage());\n    }\n\n    template <class T, class... V>\n    inline T&& xget_vector(xvector_variant<V...>&& v)\n    {\n        return xtl::xget<T>(std::move(v.storage()));\n    }\n\n    template <class T, class... V>\n    inline const T&& xget_vector(const xvector_variant<V...>&& v)\n    {\n        return xtl::xget<T>(std::move(v.storage()));\n    }\n\n    /**************************************\n     * xvector_variant_ref implementation *\n     **************************************/\n\n    template <class... L>\n    inline void swap(xvector_variant_ref<L...>& lhs, xvector_variant_ref<L...>& rhs)\n    {\n        lhs.swap(rhs);\n    }\n\n    template <class T, class... V>\n    inline T& xget_vector(xvector_variant_ref<V...>& v)\n    {\n        return xtl::xget<T&>(v.storage());\n    }\n\n    template <class T, class... V>\n    inline const T& xget_vector(const xvector_variant_ref<V...>& v)\n    {\n        return xtl::xget<const T&>(v.storage());\n    }\n\n    template <class T, class... V>\n    inline T& xget_vector(xvector_variant_ref<V...>&& v)\n    {\n        return xtl::xget<T&>(std::move(v.storage()));\n    }\n\n    template <class T, class... V>\n    inline const T& xget_vector(const xvector_variant_ref<V...>&& v)\n    {\n        return xtl::xget<const T&>(std::move(v.storage()));\n    }\n\n    /***************************************\n     * xvector_variant_cref implementation *\n     ***************************************/\n\n    template <class T, class... V>\n    const T& xget_vector(xvector_variant_cref<V...>& v)\n    {\n        return xtl::xget<const T&>(v.storage());\n    }\n\n    template <class T, class... V>\n    const T& xget_vector(const xvector_variant_cref<V...>& v)\n    {\n        return xtl::xget<const T&>(v.storage());\n    }\n\n    template <class T, class... V>\n    const T& xget_vector(xvector_variant_cref<V...>&& v)\n    {\n        return xtl::xget<const T&>(std::move(v.storage()));\n    }\n\n    template <class T, class... V>\n    const T& xget_vector(const xvector_variant_cref<V...>&& v)\n    {\n        return xtl::xget<const T&>(std::move(v.storage()));\n    }\n}\n\n#endif\n\n"
  },
  {
    "path": "notebooks/xframe.ipynb",
    "content": "{\n \"cells\": [\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"![xframe](images/xframe.png)\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"<center> <h1>xframe is a dataframe for C++, based on xtensor and xtl</h1> </center>\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"#include <string>\\n\",\n    \"#include <iostream>\\n\",\n    \"\\n\",\n    \"#include \\\"xtensor/xrandom.hpp\\\"\\n\",\n    \"#include \\\"xtensor/xmath.hpp\\\"\\n\",\n    \"\\n\",\n    \"#include \\\"xframe/xio.hpp\\\"\\n\",\n    \"#include \\\"xframe/xvariable.hpp\\\"\\n\",\n    \"#include \\\"xframe/xvariable_view.hpp\\\"\\n\",\n    \"#include \\\"xframe/xvariable_masked_view.hpp\\\"\\n\",\n    \"#include \\\"xframe/xreindex_view.hpp\\\"\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Let's first define some useful type aliases so we can reduce the amount of typing\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"using coordinate_type = xf::xcoordinate<xf::fstring>;\\n\",\n    \"using variable_type = xf::xvariable<double, coordinate_type>;\\n\",\n    \"using data_type = variable_type::data_type;\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"# 1. Variables\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## 1.1. Creating variable\\n\",\n    \"\\n\",\n    \"In the following we define a 2D variable called `dry_temperature`. A variable in `xframe` is the composition of a tensor data and a coordinate system. It is the equivalent of `DataArray` from <a href=http://xarray.pydata.org/en/stable/data-structures.html>xarray</a>. The tensor data can be any valid `xtensor` expression whose `value_type` is `xoptional`. Common types are `xarray_optional`, `xtensor_optional` and `xoptional_assembly`, which allows to create an optional expression from existing regular tensor expressions.\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"![xframe_summary](images/xframe_summary.png)\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"data_type dry_temperature_data = xt::eval(xt::random::rand({6, 3}, 15., 25.));\\n\",\n    \"dry_temperature_data(0, 0).has_value() = false;\\n\",\n    \"dry_temperature_data(2, 1).has_value() = false;\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"dry_temperature_data\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Once the data is defined, we can define the coordinate system. A coordinate system is a mapping of dimension names with label axes. Although it is possible to create an axe from a vector of labels, then the coordinate system from a map containing axes and dimension names, and finally the variable from this coordinate system and the previously created data, `xframe` makes use of the initialize-list syntax so everything can be created in place with a very expressive syntax:\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"auto time_axis = xf::axis({\\\"2018-01-01\\\", \\\"2018-01-02\\\", \\\"2018-01-03\\\", \\\"2018-01-04\\\", \\\"2018-01-05\\\", \\\"2018-01-06\\\"});\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"auto dry_temperature = variable_type(\\n\",\n    \"    dry_temperature_data,\\n\",\n    \"    {\\n\",\n    \"        {\\\"date\\\", time_axis},\\n\",\n    \"        {\\\"city\\\", xf::axis({\\\"London\\\", \\\"Paris\\\", \\\"Brussels\\\"})}\\n\",\n    \"    }\\n\",\n    \");\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"dry_temperature\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## 1.2. Indexing and selecting data\\n\",\n    \"\\n\",\n    \"Like <a href=http://xarray.pydata.org/en/stable/indexing.html>xarray</a>, `xframe` supports four different kinds of indexing as described below:\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"**Dimension lookup:** Positional - **Index lookup:** By integer\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"dry_temperature(3, 0)\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"**Dimension lookup:** Positional - **Index lookup:** By label\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"dry_temperature.locate(\\\"2018-01-04\\\", \\\"London\\\")\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"**Dimension lookup:** By name - **Index lookup:** By integer\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"dry_temperature.iselect({{\\\"date\\\", 3}, {\\\"city\\\", 0}})\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"**Dimension lookup:** By name - **Index lookup:** By label\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"scrolled\": true\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"dry_temperature.select({{\\\"date\\\", \\\"2018-01-04\\\"}, {\\\"city\\\", \\\"London\\\"}})\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Contrary to <a href=http://xarray.pydata.org/en/stable/indexing.html>xarray</a>, these methods return a single value, they do not allow to create views of the variable by selecting many data points. This feature is possible with `xframe` though, by using the free function counterparts of the methods described above, and will be covered in a next section.\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## 1.3. Maths and broadcasting\\n\",\n    \"\\n\",\n    \"Variable support all the common mathematics operations and functions; like <a href=https://xtensor.readthedocs.io/en/latest/expression.html>xtensor</a>, these operations are lazy and return expressions. `xframe` supports operations on variables with different dimensions and labels thanks to broadcasting. This one is performed according the dimension names rather than the dimension positions as shown below.\\n\",\n    \"\\n\",\n    \"Let's first define a variable containing the relative humidity for cities:\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"data_type relative_humidity_data = xt::eval(xt::random::rand({3}, 50.0, 70.0));\\n\",\n    \"\\n\",\n    \"auto relative_humidity = variable_type(\\n\",\n    \"    relative_humidity_data,\\n\",\n    \"    {\\n\",\n    \"        {\\\"city\\\", xf::axis({\\\"Paris\\\", \\\"London\\\", \\\"Brussels\\\"})}\\n\",\n    \"    }\\n\",\n    \");\\n\",\n    \"\\n\",\n    \"relative_humidity\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"We will use it and the previously defined `dry_temperature` variable (that we show again below) to compute the water_pour_pressure\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"dry_temperature\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"auto water_vapour_pressure = 0.01 * relative_humidity * 6.1 * xt::exp((17.27 * dry_temperature) / (237.7 + dry_temperature));\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"water_vapour_pressure\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"The relative humidity has been broadcasted so its values are repeated for each date.\\n\",\n    \"When the labels of variables involved in an operation are not the same, the result contains the *intersection* of the label sets:\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"data_type coeff_data = xt::eval(xt::random::rand({6, 3}, 0.7, 0.9));\\n\",\n    \"dry_temperature_data(0, 0).has_value() = false;\\n\",\n    \"dry_temperature_data(2, 1).has_value() = false;\\n\",\n    \"\\n\",\n    \"auto coeff = variable_type(\\n\",\n    \"    coeff_data,\\n\",\n    \"    {\\n\",\n    \"        {\\\"date\\\", time_axis},\\n\",\n    \"        {\\\"city\\\", xf::axis({\\\"London\\\", \\\"New York\\\", \\\"Brussels\\\"})}\\n\",\n    \"    }\\n\",\n    \");\\n\",\n    \"coeff\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"auto res = coeff * dry_temperature;\\n\",\n    \"res\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## 1.4. Higher dimension variables\\n\",\n    \"\\n\",\n    \"The following code creates and displays a three-dimensional variable.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"data_type pressure_data = {{{ 1.,  2., 3. },\\n\",\n    \"                            { 4.,  5., 6. },\\n\",\n    \"                            { 7.,  8., 9. }},\\n\",\n    \"                           {{ 1.3, 1.5, 1.},\\n\",\n    \"                            { 2., 2.3, 2.4},\\n\",\n    \"                            { 3.1, 3.8, 3.}},\\n\",\n    \"                           {{ 8.5, 8.2, 8.6},\\n\",\n    \"                            { 7.5, 8.6, 9.7},\\n\",\n    \"                            { 4.5, 4.4, 4.3}}};\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"auto pressure = variable_type(\\n\",\n    \"    pressure_data,\\n\",\n    \"    {\\n\",\n    \"        {\\\"x\\\", xf::axis(3)},\\n\",\n    \"        {\\\"y\\\", xf::axis(3, 6, 1)},\\n\",\n    \"        {\\\"z\\\", xf::axis(3)},\\n\",\n    \"    }\\n\",\n    \");\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"pressure\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"# 2. Views\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## 2.1. Multiselection\\n\",\n    \"\\n\",\n    \"Views can be used to select many data points in a variable. The syntax is similar to the one used for selecting a single data point, excpet that it uses free functions instead of methods of variable.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"dry_temperature\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"**Dimension lookup:** Positional - **Index lookup:** By integer\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"auto v1 = ilocate(dry_temperature, xf::irange(0, 5, 2), xf::irange(1, 3));\\n\",\n    \"v1\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"**Dimension lookup:** Positional - **Index lookup:** By label\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"auto v2 = locate(dry_temperature, xf::range(\\\"2018-01-01\\\", \\\"2018-01-06\\\", 2), xf::range(\\\"Paris\\\", \\\"Brussels\\\"));\\n\",\n    \"v2\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"**Dimension lookup:** By name - **Index lookup:** By integer\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"auto v3 = iselect(dry_temperature, {{\\\"city\\\", xf::irange(1, 3)}, {\\\"date\\\", xf::irange(0, 5, 2)}});\\n\",\n    \"v3\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"**Dimension lookup:** By name - **Index lookup:** By label\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"auto v4 = select(dry_temperature, \\n\",\n    \"                 {{\\\"city\\\", xf::range(\\\"Paris\\\", \\\"Brussels\\\")},\\n\",\n    \"                  {\\\"date\\\", xf::range(\\\"2018-01-01\\\", \\\"2018-01-06\\\", 2)}});\\n\",\n    \"v4\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## 2.2. Keeping and dropping labels\\n\",\n    \"\\n\",\n    \"The previous selection made use of ranges (label range from `xframe` and index range from `xtensor`), however it is also possible to select data points by explicitly specifying a list of labels to keep or to drop.\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"**Dimension lookup:** Positional - **Index lookup:** By integer\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"auto v5 = ilocate(dry_temperature, xf::ikeep(0, 2, 4), xf::idrop(0));\\n\",\n    \"v5\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"**Dimension lookup:** By name - **Index lookup:** By integer\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"auto v6 = locate(dry_temperature, xf::keep(\\\"2018-01-01\\\", \\\"2018-01-03\\\", \\\"2018-01-05\\\"), xf::drop(\\\"London\\\"));\\n\",\n    \"v6\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"**Dimension lookup:** By name - **Index lookup:** By integer\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"auto v7 = iselect(dry_temperature, {{\\\"city\\\", xf::idrop(0)}, {\\\"date\\\", xf::ikeep(0, 2, 4)}});\\n\",\n    \"v7\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"**Dimension lookup:** By name - **Index lookup:** By label\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"auto v8 = select(dry_temperature,\\n\",\n    \"                 {{\\\"city\\\", xf::drop(\\\"London\\\")},\\n\",\n    \"                  {\\\"date\\\", xf::keep(\\\"2018-01-01\\\", \\\"2018-01-03\\\", \\\"2018-01-05\\\")}});\\n\",\n    \"v8\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## 2.3 Masking views\\n\",\n    \"\\n\",\n    \"Masking views allow to select data points based on conditions expressed on labels. These conditons can be complicated boolean expressions.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"pressure\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"auto masked_pressure = xf::where(\\n\",\n    \"    pressure,\\n\",\n    \"    not_equal(pressure.axis<int>(\\\"x\\\"), 2) && pressure.axis<int>(\\\"z\\\") < 2\\n\",\n    \");\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"masked_pressure\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"When assigning to a masking view, masked values are not changed. Like other views, a masking view is a proxy on its junderlying expression, no copy is made, so changing a unmasked value actually changes the corresponding value in the underlying expression.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"masked_pressure = 1.;\\n\",\n    \"masked_pressure\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"pressure\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## 2.4 Reindexing views\\n\",\n    \"\\n\",\n    \"Reindexing views give variables new set of coordinates to corresponding dimensions. Like other views, no copy is involved. Asking for values corresponding to new labels not found in the original set of coordinates returns missing values. In the next example, we reindex the `city` dimension.\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"dry_temperature\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {\n    \"scrolled\": true\n   },\n   \"outputs\": [],\n   \"source\": [\n    \"auto temp = reindex(dry_temperature, {{\\\"city\\\", xf::axis({\\\"London\\\", \\\"New York\\\", \\\"Brussels\\\"})}});\\n\",\n    \"temp\"\n   ]\n  },\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"The `reindex_like` is a shortcut that allows to reindex a variable given the set of coordinates of another variable\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": [\n    \"auto dry_temp2 = variable_type(\\n\",\n    \"    dry_temperature_data,\\n\",\n    \"    {\\n\",\n    \"        {\\\"date\\\", time_axis},\\n\",\n    \"        {\\\"city\\\", xf::axis({\\\"London\\\", \\\"New York\\\", \\\"Brussels\\\"})}\\n\",\n    \"    }\\n\",\n    \");\\n\",\n    \"auto temp2 = reindex_like(dry_temperature, dry_temp2);\\n\",\n    \"temp2\"\n   ]\n  },\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": null,\n   \"metadata\": {},\n   \"outputs\": [],\n   \"source\": []\n  }\n ],\n \"metadata\": {\n  \"kernelspec\": {\n   \"display_name\": \"C++14\",\n   \"language\": \"C++14\",\n   \"name\": \"xcpp14\"\n  },\n  \"language_info\": {\n   \"codemirror_mode\": \"text/x-c++src\",\n   \"file_extension\": \".cpp\",\n   \"mimetype\": \"text/x-c++src\",\n   \"name\": \"c++\",\n   \"version\": \"-std=c++14\"\n  }\n },\n \"nbformat\": 4,\n \"nbformat_minor\": 2\n}\n"
  },
  {
    "path": "readthedocs.yml",
    "content": "conda:\n    file: docs/environment.yml\n"
  },
  {
    "path": "test/CMakeLists.txt",
    "content": "############################################################################\n# Copyright (c) Johan Mabille and Sylvain Corlay                           #\n# Copyright (c) QuantStack                                                 #\n#                                                                          #\n# Distributed under the terms of the BSD 3-Clause License.                 #\n#                                                                          #\n# The full license is in the file LICENSE, distributed with this software. #\n############################################################################\n\ncmake_minimum_required(VERSION 3.1)\n\nif (CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR)\n    project(xframe-test)\n\n    find_package(xframe REQUIRED CONFIG)\n    set(XFRAME_INCLUDE_DIR ${xframe_INCLUDE_DIRS})\nendif ()\n\nmessage(STATUS \"Forcing tests build type to Release\")\nset(CMAKE_BUILD_TYPE Release CACHE STRING \"Choose the type of build.\" FORCE)\n\ninclude(CheckCXXCompilerFlag)\n\nstring(TOUPPER \"${CMAKE_BUILD_TYPE}\" U_CMAKE_BUILD_TYPE)\n\nif (CMAKE_CXX_COMPILER_ID MATCHES \"Clang\" OR CMAKE_CXX_COMPILER_ID MATCHES \"GNU\" OR CMAKE_CXX_COMPILER_ID MATCHES \"Intel\")\n    #set(CMAKE_CXX_FLAGS \"${CMAKE_CXX_FLAGS} -march=native -Wunused-parameter -Wextra -Wreorder -Wconversion -Wsign-conversion\")\n    set(CMAKE_CXX_FLAGS \"${CMAKE_CXX_FLAGS} -march=native -Wunused-parameter -Wextra -Wreorder -Wconversion\")\n    CHECK_CXX_COMPILER_FLAG(\"-std=c++14\" HAS_CPP14_FLAG)\n\n    if (HAS_CPP14_FLAG)\n        set(CMAKE_CXX_FLAGS \"${CMAKE_CXX_FLAGS} -std=c++14\")\n    else()\n        message(FATAL_ERROR \"Unsupported compiler -- xframe requires C++14 support!\")\n    endif()\nendif()\n\nif(MSVC)\n    set(CMAKE_CXX_FLAGS \"${CMAKE_CXX_FLAGS} /EHsc /MP /bigobj\")\n    set(CMAKE_EXE_LINKER_FLAGS /MANIFEST:NO)\nendif()\n\nif(DOWNLOAD_GTEST OR GTEST_SRC_DIR)\n    if(DOWNLOAD_GTEST)\n        # Download and unpack googletest at configure time\n        configure_file(downloadGTest.cmake.in googletest-download/CMakeLists.txt)\n    else()\n        # Copy local source of googletest at configure time\n        configure_file(copyGTest.cmake.in googletest-download/CMakeLists.txt)\n    endif()\n    execute_process(COMMAND ${CMAKE_COMMAND} -G \"${CMAKE_GENERATOR}\" .\n                    RESULT_VARIABLE result\n                    WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/googletest-download )\n    if(result)\n        message(FATAL_ERROR \"CMake step for googletest failed: ${result}\")\n    endif()\n    execute_process(COMMAND ${CMAKE_COMMAND} --build .\n                    RESULT_VARIABLE result\n                    WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/googletest-download )\n    if(result)\n        message(FATAL_ERROR \"Build step for googletest failed: ${result}\")\n    endif()\n\n    set(gtest_force_shared_crt ON CACHE BOOL \"\" FORCE)\n    # Add googletest directly to our build. This defines\n    # the gtest and gtest_main targets.\n    add_subdirectory(${CMAKE_CURRENT_BINARY_DIR}/googletest-src\n                     ${CMAKE_CURRENT_BINARY_DIR}/googletest-build EXCLUDE_FROM_ALL)\n\n    set(GTEST_INCLUDE_DIRS \"${gtest_SOURCE_DIR}/include\")\n    add_library(GTest::GTest INTERFACE IMPORTED)\n    target_link_libraries(GTest::GTest INTERFACE gtest)\n    add_library(GTest::Main INTERFACE IMPORTED)\n    target_link_libraries(GTest::Main INTERFACE gtest_main)\nelse()\n    find_package(GTest REQUIRED)\nendif()\n\nfind_package(Threads)\n\ninclude_directories(${XFRAME_INCLUDE_DIR})\ninclude_directories(${GTEST_INCLUDE_DIRS})\n\nset(XFRAME_TESTS\n    main.cpp\n    test_fixture.hpp\n    test_fixture_view.hpp\n    test_xaxis.cpp\n    test_xaxis_default.cpp\n    test_xaxis_function.cpp\n    test_xaxis_variant.cpp\n    test_xaxis_view.cpp\n    test_xcoordinate.cpp\n    test_xcoordinate_chain.cpp\n    test_xcoordinate_expanded.cpp\n    test_xcoordinate_view.cpp\n    test_xdimension.cpp\n    test_xdynamic_variable.cpp\n    test_xexpand_dims_view.cpp\n    test_xframe_utils.cpp\n    test_xnamed_axis.cpp\n    test_xreindex_view.cpp\n    test_xsequence_view.cpp\n    test_xvariable.cpp\n    test_xvariable_assign.cpp\n    test_xvariable_function.cpp\n    test_xvariable_masked_view.cpp\n    test_xvariable_math.cpp\n    test_xvariable_noalias.cpp\n    test_xvariable_scalar.cpp\n    test_xvariable_view.cpp\n    test_xvariable_view_assign.cpp\n    test_xvector_variant.cpp\n)\n\nadd_executable(test_xframe ${XFRAME_TESTS} ${XFRAME_HEADERS})\nif(DOWNLOAD_GTEST OR GTEST_SRC_DIR)\n    add_dependencies(test_xframe gtest_main)\nendif()\ntarget_link_libraries(test_xframe GTest::GTest GTest::Main ${CMAKE_THREAD_LIBS_INIT})\ntarget_include_directories(test_xframe PRIVATE ${XFRAME_INCLUDE_DIR})\n\nadd_custom_target(xtest COMMAND test_xframe DEPENDS test_xframe)\n"
  },
  {
    "path": "test/copyGTest.cmake.in",
    "content": "############################################################################\n# Copyright (c) Johan Mabille and Sylvain Corlay                           #\n# Copyright (c) QuantStack                                                 #\n#                                                                          #\n# Distributed under the terms of the BSD 3-Clause License.                 #\n#                                                                          #\n# The full license is in the file LICENSE, distributed with this software. #\n############################################################################\n\ncmake_minimum_required(VERSION 2.8.2)\n\nproject(googletest-download NONE)\n\ninclude(ExternalProject)\nExternalProject_Add(googletest\n    URL               \"${GTEST_SRC_DIR}\"\n    SOURCE_DIR        \"${CMAKE_CURRENT_BINARY_DIR}/googletest-src\"\n    BINARY_DIR        \"${CMAKE_CURRENT_BINARY_DIR}/googletest-build\"\n    CONFIGURE_COMMAND \"\"\n    BUILD_COMMAND     \"\"\n    INSTALL_COMMAND   \"\"\n    TEST_COMMAND      \"\"\n)\n\n"
  },
  {
    "path": "test/downloadGTest.cmake.in",
    "content": "############################################################################\n# Copyright (c) Johan Mabille and Sylvain Corlay                           #\n# Copyright (c) QuantStack                                                 #\n#                                                                          #\n# Distributed under the terms of the BSD 3-Clause License.                 #\n#                                                                          #\n# The full license is in the file LICENSE, distributed with this software. #\n############################################################################\n\ncmake_minimum_required(VERSION 2.8.2)\n\nproject(googletest-download NONE)\n\ninclude(ExternalProject)\nExternalProject_Add(googletest\n    GIT_REPOSITORY    https://github.com/JohanMabille/googletest.git\n    GIT_TAG           warnings\n    SOURCE_DIR        \"${CMAKE_CURRENT_BINARY_DIR}/googletest-src\"\n    BINARY_DIR        \"${CMAKE_CURRENT_BINARY_DIR}/googletest-build\"\n    CONFIGURE_COMMAND \"\"\n    BUILD_COMMAND     \"\"\n    INSTALL_COMMAND   \"\"\n    TEST_COMMAND      \"\"\n)\n\n"
  },
  {
    "path": "test/main.cpp",
    "content": "/***************************************************************************\n* Copyright (c) Johan Mabille, Sylvain Corlay, Wolf Vollprecht and         *\n* Martin Renou                                                             *\n* Copyright (c) QuantStack                                                 *\n*                                                                          *\n* Distributed under the terms of the BSD 3-Clause License.                 *\n*                                                                          *\n* The full license is in the file LICENSE, distributed with this software. *\n****************************************************************************/\n\n#include \"gtest/gtest.h\"\n\nint main(int argc, char* argv[])\n{\n    ::testing::InitGoogleTest(&argc, argv);\n    return RUN_ALL_TESTS();\n}\n"
  },
  {
    "path": "test/test_fixture.hpp",
    "content": "/***************************************************************************\n* Copyright (c) Johan Mabille, Sylvain Corlay, Wolf Vollprecht and         *\n* Martin Renou                                                             *\n* Copyright (c) QuantStack                                                 *\n*                                                                          *\n* Distributed under the terms of the BSD 3-Clause License.                 *\n*                                                                          *\n* The full license is in the file LICENSE, distributed with this software. *\n****************************************************************************/\n\n#ifndef XFRAME_TEST_FIXTURE_HPP\n#define XFRAME_TEST_FIXTURE_HPP\n\n#include <cstddef>\n#include \"xtl/xbasic_fixed_string.hpp\"\n#include \"xtensor/xmasked_view.hpp\"\n#include \"xframe/xvariable.hpp\"\n#include \"xframe/xnamed_axis.hpp\"\n\nnamespace xf\n{\n    using saxis_type = xaxis<fstring, std::size_t>;\n    using iaxis_type = xaxis<int, std::size_t>;\n    using daxis_type = xaxis_default<int, std::size_t>;\n    using dimension_type = xdimension<fstring, std::size_t>;\n    using data_type = xt::xoptional_assembly<xt::xarray<double>, xt::xarray<bool>>;\n    using int_data_type = xt::xoptional_assembly<xt::xarray<int>, xt::xarray<bool>>;\n    using bool_data_type = xt::xoptional_assembly<xt::xarray<bool>, xt::xarray<bool>>;\n    using coordinate_type = xcoordinate<fstring>;\n    using variable_type = xvariable_container<coordinate_type, data_type>;\n    using int_variable_type = xvariable_container<coordinate_type, int_data_type>;\n    using bool_variable_type = xvariable_container<coordinate_type, bool_data_type>;\n\n    /********\n     * axes *\n     ********/\n\n    // { \"a\", \"c\", \"d\" }\n    inline saxis_type make_test_saxis()\n    {\n        return saxis_type({\"a\", \"c\", \"d\"});\n    }\n\n    // { \"a\", \"d\", \"e\" }\n    inline saxis_type make_test_saxis2()\n    {\n        return saxis_type({\"a\", \"d\", \"e\"});\n    }\n\n    // { \"a\", \"b\", \"c\", \"d\" }\n    inline saxis_type make_test_saxis3()\n    {\n        return saxis_type({\"a\", \"b\", \"c\", \"d\"});\n    }\n\n    // { 1, 2, 4 }\n    inline iaxis_type make_test_iaxis()\n    {\n        return iaxis_type({1, 2, 4});\n    }\n\n    // { 1, 4, 5 }\n    inline iaxis_type make_test_iaxis2()\n    {\n        return iaxis_type({1, 4, 5});\n    }\n\n    // { 0, 1, 2 }\n    inline daxis_type make_test_daxis()\n    {\n        return daxis_type(3);\n    }\n\n    /***************\n     * coordinates *\n     ***************/\n\n    // abscissa: { \"a\", \"c\", \"d\" }\n    // ordinate: { 1, 2, 4 }\n    inline coordinate_type make_test_coordinate()\n    {\n        fstring s1 = \"abscissa\";\n        fstring s2 = \"ordinate\";\n        return coordinate<fstring>({\n            {s1, make_test_saxis()},\n            {s2, make_test_iaxis()}\n        });\n    }\n\n    // abscissa: { \"a\", \"d\", \"e\" }\n    // ordinate: { 1, 4, 5 }\n    inline coordinate_type make_test_coordinate2()\n    {\n        const fstring s1 = \"abscissa\";\n        return coordinate<fstring>(\n            named_axis(s1, make_test_saxis2()),\n            named_axis(\"ordinate\", make_test_iaxis2())\n        );\n    }\n\n    // abscissa: { \"a\", \"d\", \"e\" }\n    // ordinate: { 1, 4, 5 }\n    // altitude: { 1, 2, 4 }\n    inline coordinate_type make_test_coordinate3()\n    {\n        fstring s1 = \"abscissa\";\n        fstring s2 = \"ordinate\";\n        fstring s3 = \"altitude\";\n        return coordinate<fstring>({\n            {s1, make_test_saxis2()},\n            {s2, make_test_iaxis2()},\n            {s3, make_test_iaxis()}\n        });\n    }\n\n    // abscissa: { \"a\", \"d\", \"e\" }\n    // ordinate: { 1, 4, 5 }\n    // altitude: { 0, 1, 2 }\n    inline coordinate_type make_test_coordinate4()\n    {\n        fstring s1 = \"abscissa\";\n        fstring s2 = \"ordinate\";\n        fstring s3 = \"altitude\";\n        return coordinate<fstring>({\n            {s1, make_test_saxis2()},\n            {s2, make_test_iaxis2()},\n            {s3, make_test_daxis()}\n        });\n    }\n\n    // abscissa: { \"a\", \"c\", \"d\", \"e\" }\n    // ordinate: { 1, 2, 4, 5 }\n    // altitude: { 1, 2, 4 }\n    inline coordinate_type make_merge_coordinate()\n    {\n        saxis_type sres = { \"a\", \"c\", \"d\", \"e\" };\n        iaxis_type ires = { 1, 2, 4, 5 };\n        return coordinate<fstring>({\n            {fstring(\"abscissa\"), std::move(sres)},\n            {fstring(\"ordinate\"), std::move(ires)},\n            {fstring(\"altitude\"), make_test_iaxis()},\n        });\n    }\n\n    // abscissa: { \"a\", \"d\", \"e\" }\n    // ordinate: { 1, 4, 5 }\n    // altitude: { 0, 1, 2, 4 }\n    inline coordinate_type make_merge_coordinate2()\n    {\n        iaxis_type ires = { 0, 1, 2, 4 };\n        return coordinate<fstring>({\n            {fstring(\"abscissa\"), make_test_saxis2()},\n            {fstring(\"ordinate\"), make_test_iaxis2()},\n            {fstring(\"altitude\"), std::move(ires)},\n        });\n    }\n\n    // abscissa: { \"a\", \"d\" }\n    // ordinate: { 1, 4 }\n    // altitude: { 1, 2, 4 }\n    inline coordinate_type make_intersect_coordinate()\n    {\n        saxis_type sres = { \"a\", \"d\" };\n        iaxis_type ires = { 1, 4 };\n        return coordinate<fstring>({\n            {fstring(\"abscissa\"), std::move(sres)},\n            {fstring(\"ordinate\"), std::move(ires)},\n            {fstring(\"altitude\"), make_test_iaxis()}\n        });\n    }\n\n    // abscissa: { \"a\", \"d\", \"e\" }\n    // ordinate: { 1, 4, 5 }\n    // altitude: { 1, 2 }\n    inline coordinate_type make_intersect_coordinate2()\n    {\n        saxis_type sres = { \"a\", \"d\", \"e\" };\n        iaxis_type ires = { 1, 4, 5 };\n        iaxis_type ires2 = { 1, 2 };\n        return coordinate<fstring>({\n            {fstring(\"abscissa\"), std::move(sres)},\n            {fstring(\"ordinate\"), std::move(ires)},\n            {fstring(\"altitude\"), std::move(ires2)}\n        });\n    }\n\n    /*************\n     * variables *\n     *************/\n\n    // data = {{ 1. ,  2., N/A },\n    //         { N/A,  5.,  6. },\n    //         { 7. ,  8.,  9. }}\n    inline data_type make_test_data()\n    {\n        data_type d = {{ 1., 2., 3.},\n                       { 4., 5., 6.},\n                       { 7., 8., 9.}};\n        d(0, 2).has_value() = false;\n        d(1, 0).has_value() = false;\n        return d;\n    }\n\n    inline data_type make_test_data2()\n    {\n        data_type d2 = {{{ 1., 2., 3.},\n                         { 4., 5., 6.},\n                         { 7., 8., 9.}},\n                        {{ 11., 12., 13.},\n                         { 14., 15., 16.},\n                         { 17., 18., 19.}},\n                        {{ 21., 22., 23.},\n                         { 24., 25., 26.},\n                         { 27., 28., 29.}}};\n        d2(0, 0, 2).has_value() = false;\n        d2(1, 1, 0).has_value() = false;\n        return d2;\n    }\n\n    // data = {{ 1 ,  2, N/A },\n    //         { N/A, 5,  6 },\n    //         { 7 ,  8,  9 }}\n    inline int_data_type make_test_int_data()\n    {\n        int_data_type d = {{ 1, 2, 3 },\n                           { 4, 5, 6 },\n                           { 7, 8, 9 }};\n        d(0, 2).has_value() = false;\n        d(1, 0).has_value() = false;\n        return d;\n    }\n\n    // data = {{ true ,  true, N/A },\n    //         { N/A, true,  true },\n    //         { true ,  true,  true }}\n    inline bool_data_type make_test_bool_data()\n    {\n        bool_data_type d = {{ true, true, true },\n                            { true, true, true },\n                            { true, true, true }};\n        d(0, 2).has_value() = false;\n        d(1, 0).has_value() = false;\n        return d;\n    }\n\n    // masked_data = {{ 1. ,  2., N/A },\n    //                { N/A, N/A, N/A },\n    //                { 7. ,  8.,  9. }}\n    inline auto make_masked_data(data_type& data)\n    {\n        auto axis1 = named_axis(fstring(\"abs\"), axis({'x', 'y', 'z'}));\n\n        auto func = axis_function_mask(\n            not_equal(std::move(axis1), 'y'),\n            dimension_type({\"abs\", \"ord\"}),\n            std::array<int, 2>({3, 3})\n        );\n\n        return xt::masked_view(data, std::move(func));\n    }\n\n    // abscissa: { \"a\", \"c\", \"d\" }\n    // ordinate: { 1, 2, 4 }\n    // dims: {{ \"abscissa\", 0 }, { \"ordinate\", 1 }}\n    // data = {{ 1. ,  2., N/A },\n    //         { N/A,  5.,  6. },\n    //         { 7. ,  8.,  9. }}\n    inline variable_type make_test_variable()\n    {\n        return variable_type(make_test_data(), make_test_coordinate(), dimension_type({\"abscissa\", \"ordinate\"}));\n    }\n\n    // abscissa: { \"a\", \"d\", \"e\" }\n    // ordinate: { 1, 4, 5 }\n    // altitude: { 1, 2, 4 }\n    // dims: {{ \"abscissa\", 0 }, { \"ordinate\", 1 }, {\"altitude\", 2}}\n    // data = make_test_data2\n    inline variable_type make_test_variable2()\n    {\n        return variable_type(make_test_data2(), make_test_coordinate3(), dimension_type({\"abscissa\", \"ordinate\", \"altitude\"}));\n    }\n\n    // abscissa: { \"a\", \"d\", \"e\" }\n    // ordinate: { 1, 4, 5 }\n    // dims: {{ \"abscissa\", 0 }, { \"ordinate\", 1 }}\n    // data = {{ 1. ,  2., N/A },\n    //         { N/A,  5.,  6. },\n    //         { 7. ,  8.,  9. }}\n    inline variable_type make_test_variable3()\n    {\n        return variable_type(make_test_data(), make_test_coordinate2(), dimension_type({\"abscissa\", \"ordinate\"}));\n    }\n\n    // altitude: { 1, 2, 4 }\n    // abscissa: { \"a\", \"d\", \"e\" }\n    // ordinate: { 1, 4, 5 }\n    // dims: {{\"altitude\", 0}, { \"abscissa\", 1 }, { \"ordinate\", 2 }}\n    // data = make_test_data2\n    inline variable_type make_test_variable4()\n    {\n        return variable_type(make_test_data2(), make_test_coordinate3(), dimension_type({\"altitude\", \"abscissa\", \"ordinate\"}));\n    }\n\n    // abscissa: { \"a\", \"c\", \"d\" }\n    // ordinate: { 1, 2, 4 }\n    // dims: {{ \"abscissa\", 0 }, { \"ordinate\", 1 }}\n    // data = {{ 1 ,  2, N/A },\n    //         { N/A, 5,  6 },\n    //         { 7 ,  8,  9 }}\n    inline int_variable_type make_test_int_variable()\n    {\n        return int_variable_type(make_test_int_data(), make_test_coordinate(), dimension_type({ \"abscissa\", \"ordinate\" }));\n    }\n\n    inline bool_variable_type make_test_bool_variable()\n    {\n        return bool_variable_type(make_test_bool_data(), make_test_coordinate(), dimension_type({ \"abscissa\", \"ordinate\" }));\n    }\n\n    /*************\n     * selectors *\n     *************/\n\n    using dict_type = typename variable_type::selector_sequence_type<>;\n    using selector_list = std::vector<dict_type>;\n\n    inline dict_type make_selector_aa()\n    {\n        return { {\"abscissa\", \"a\"}, {\"ordinate\", 1} };\n    }\n\n    inline selector_list make_selector_list_aa()\n    {\n        selector_list sl(9);\n        sl[0] = { { \"abscissa\", \"a\" },{ \"ordinate\", 1 } };\n        sl[1] = { { \"abscissa\", \"a\" },{ \"ordinate\", 2 } };\n        sl[2] = { { \"abscissa\", \"a\" },{ \"ordinate\", 4 } };\n        sl[3] = { { \"abscissa\", \"c\" },{ \"ordinate\", 1 } };\n        sl[4] = { { \"abscissa\", \"c\" },{ \"ordinate\", 2 } };\n        sl[5] = { { \"abscissa\", \"c\" },{ \"ordinate\", 4 } };\n        sl[6] = { { \"abscissa\", \"d\" },{ \"ordinate\", 1 } };\n        sl[7] = { { \"abscissa\", \"d\" },{ \"ordinate\", 2 } };\n        sl[8] = { { \"abscissa\", \"d\" },{ \"ordinate\", 4 } };\n        return sl;\n    }\n\n    inline selector_list make_selector_list_ab()\n    {\n        selector_list sl(12);\n        sl[0] = { { \"abscissa\", \"a\" },{ \"ordinate\", 1 },{ \"altitude\", 1 } };\n        sl[1] = { { \"abscissa\", \"a\" },{ \"ordinate\", 1 },{ \"altitude\", 2 } };\n        sl[2] = { { \"abscissa\", \"a\" },{ \"ordinate\", 1 },{ \"altitude\", 4 } };\n        sl[3] = { { \"abscissa\", \"a\" },{ \"ordinate\", 4 },{ \"altitude\", 1 } };\n        sl[4] = { { \"abscissa\", \"a\" },{ \"ordinate\", 4 },{ \"altitude\", 2 } };\n        sl[5] = { { \"abscissa\", \"a\" },{ \"ordinate\", 4 },{ \"altitude\", 4 } };\n        sl[6] = { { \"abscissa\", \"d\" },{ \"ordinate\", 1 },{ \"altitude\", 1 } };\n        sl[7] = { { \"abscissa\", \"d\" },{ \"ordinate\", 1 },{ \"altitude\", 2 } };\n        sl[8] = { { \"abscissa\", \"d\" },{ \"ordinate\", 1 },{ \"altitude\", 4 } };\n        sl[9] = { { \"abscissa\", \"d\" },{ \"ordinate\", 4 },{ \"altitude\", 1 } };\n        sl[10] = { { \"abscissa\", \"d\" },{ \"ordinate\", 4 },{ \"altitude\", 2 } };\n        sl[11] = { { \"abscissa\", \"d\" },{ \"ordinate\", 4 },{ \"altitude\", 4 } };\n        return sl;\n    }\n\n    inline selector_list make_selector_list_cd()\n    {\n        selector_list sl(27);\n        sl[0] = { { \"altitude\", 1 },{ \"abscissa\", \"a\" },{ \"ordinate\", 1 } };\n        sl[1] = { { \"altitude\", 1 },{ \"abscissa\", \"a\" },{ \"ordinate\", 4 } };\n        sl[2] = { { \"altitude\", 1 },{ \"abscissa\", \"a\" },{ \"ordinate\", 5 } };\n        sl[3] = { { \"altitude\", 1 },{ \"abscissa\", \"d\" },{ \"ordinate\", 1 } };\n        sl[4] = { { \"altitude\", 1 },{ \"abscissa\", \"d\" },{ \"ordinate\", 4 } };\n        sl[5] = { { \"altitude\", 1 },{ \"abscissa\", \"d\" },{ \"ordinate\", 5 } };\n        sl[6] = { { \"altitude\", 1 },{ \"abscissa\", \"e\" },{ \"ordinate\", 1 } };\n        sl[7] = { { \"altitude\", 1 },{ \"abscissa\", \"e\" },{ \"ordinate\", 4 } };\n        sl[8] = { { \"altitude\", 1 },{ \"abscissa\", \"e\" },{ \"ordinate\", 5 } };\n        sl[9] = { { \"altitude\", 2 },{ \"abscissa\", \"a\" },{ \"ordinate\", 1 } };\n        sl[10] = { { \"altitude\", 2 },{ \"abscissa\", \"a\" },{ \"ordinate\", 4 } };\n        sl[11] = { { \"altitude\", 2 },{ \"abscissa\", \"a\" },{ \"ordinate\", 5 } };\n        sl[12] = { { \"altitude\", 2 },{ \"abscissa\", \"d\" },{ \"ordinate\", 1 } };\n        sl[13] = { { \"altitude\", 2 },{ \"abscissa\", \"d\" },{ \"ordinate\", 4 } };\n        sl[14] = { { \"altitude\", 2 },{ \"abscissa\", \"d\" },{ \"ordinate\", 5 } };\n        sl[15] = { { \"altitude\", 2 },{ \"abscissa\", \"e\" },{ \"ordinate\", 1 } };\n        sl[16] = { { \"altitude\", 2 },{ \"abscissa\", \"e\" },{ \"ordinate\", 4 } };\n        sl[17] = { { \"altitude\", 2 },{ \"abscissa\", \"e\" },{ \"ordinate\", 5 } };\n        sl[18] = { { \"altitude\", 4 },{ \"abscissa\", \"a\" },{ \"ordinate\", 1 } };\n        sl[19] = { { \"altitude\", 4 },{ \"abscissa\", \"a\" },{ \"ordinate\", 4 } };\n        sl[20] = { { \"altitude\", 4 },{ \"abscissa\", \"a\" },{ \"ordinate\", 5 } };\n        sl[21] = { { \"altitude\", 4 },{ \"abscissa\", \"d\" },{ \"ordinate\", 1 } };\n        sl[22] = { { \"altitude\", 4 },{ \"abscissa\", \"d\" },{ \"ordinate\", 4 } };\n        sl[23] = { { \"altitude\", 4 },{ \"abscissa\", \"d\" },{ \"ordinate\", 5 } };\n        sl[24] = { { \"altitude\", 4 },{ \"abscissa\", \"e\" },{ \"ordinate\", 1 } };\n        sl[25] = { { \"altitude\", 4 },{ \"abscissa\", \"e\" },{ \"ordinate\", 4 } };\n        sl[26] = { { \"altitude\", 4 },{ \"abscissa\", \"e\" },{ \"ordinate\", 5 } };\n        return sl;\n    }\n\n#define DEFINE_TEST_VARIABLES()                                           \\\n        variable_type a = make_test_variable();                           \\\n        variable_type b = make_test_variable2();                          \\\n        variable_type c = make_test_variable3();                          \\\n        variable_type d = make_test_variable4()\n\n#define CHECK_EQUALITY(RES, A, B, SL, OP)                                 \\\n    for(std::size_t i = 0; i < sl.size(); ++i)                            \\\n    {                                                                     \\\n        EXPECT_EQ(RES.select(SL[i]), A.select(SL[i]) OP B.select(SL[i])); \\\n    }\n\n#define CHECK_SCALAR2_EQUALITY(RES, A, B, SL, OP)                         \\\n    for(std::size_t i = 0; i < sl.size(); ++i)                            \\\n    {                                                                     \\\n        EXPECT_EQ(RES.select(SL[i]), A.select(SL[i]) OP B); \\\n    }\n\n#define CHECK_SCALAR1_EQUALITY(RES, A, B, SL, OP)                         \\\n    for(std::size_t i = 0; i < sl.size(); ++i)                            \\\n    {                                                                     \\\n        EXPECT_EQ(RES.select(SL[i]), A OP B.select(SL[i])); \\\n    }\n}\n\n#endif\n"
  },
  {
    "path": "test/test_fixture_view.hpp",
    "content": "/***************************************************************************\n* Copyright (c) Johan Mabille, Sylvain Corlay, Wolf Vollprecht and         *\n* Martin Renou                                                             *\n* Copyright (c) QuantStack                                                 *\n*                                                                          *\n* Distributed under the terms of the BSD 3-Clause License.                 *\n*                                                                          *\n* The full license is in the file LICENSE, distributed with this software. *\n****************************************************************************/\n\n#ifndef XFRAME_TEST_FIXTURE_VIEW_HPP\n#define XFRAME_TEST_FIXTURE_VIEW_HPP\n\n#include <cstddef>\n\n#include \"xtl/xbasic_fixed_string.hpp\"\n#include \"xtl/xmasked_value.hpp\"\n\n#include \"xframe/xvariable_view.hpp\"\n\nnamespace xf\n{\n    using saxis_type = xaxis<fstring, std::size_t>;\n    using iaxis_type = xaxis<int, std::size_t>;\n    using size_type = std::size_t;\n    using axis_variant = xaxis_variant<XFRAME_DEFAULT_LABEL_LIST, size_type>;\n    using axis_view_type = xaxis_view<XFRAME_DEFAULT_LABEL_LIST, size_type, typename axis_variant::map_container_tag>;\n    using coordinate_type = xcoordinate<fstring>;\n    using coordinate_view_type = xcoordinate_view<fstring>;\n    using dimension_type = xdimension<fstring, std::size_t>;\n    using data_type = xt::xoptional_assembly<xt::xarray<double>, xt::xarray<bool>>;\n    using masked_data_type = xt::xarray<xtl::xmasked_value<xtl::xoptional<double, bool>>>;\n    using variable_type = xvariable_container<coordinate_type, data_type>;\n    using variable_view_type = xvariable_view<variable_type&>;\n    using slice_vector = variable_view_type::slice_vector;\n\n    // { \"a\", \"c\", \"d\", \"f\", \"g\", \"h\", \"m\", \"n\" }\n    inline saxis_type make_test_view_saxis()\n    {\n        return saxis_type({ \"a\", \"c\", \"d\", \"f\", \"g\", \"h\", \"m\", \"n\" });\n    }\n\n    inline axis_variant make_variant_view_saxis()\n    {\n        return axis_variant(make_test_view_saxis());\n    }\n\n    // { 1, 2, 4, 5, 6, 8, 12, 13 }\n    inline iaxis_type make_test_view_iaxis()\n    {\n        return iaxis_type({ 1, 2, 4, 5, 6, 8, 12, 13 });\n    }\n\n    // abscissa: { \"a\", \"c\", \"d\", \"f\", \"g\", \"h\", \"m\", \"n\" }\n    // ordinate: { 1, 2, 4, 5, 6, 8, 12, 13 }\n    inline coordinate_type make_test_view_coordinate()\n    {\n        fstring s1 = \"abscissa\";\n        fstring s2 = \"ordinate\";\n        return coordinate<fstring>({\n            {s1, make_test_view_saxis()},\n            {s2, make_test_view_iaxis()}\n        });\n    }\n\n    //                              ordinate\n    //                 1,   2,   4,   5,   6,   8,  12,  13\n    //           a {{  0,   1,   2,   3,   4,   5,   6,   7},\n    //           c  {  8,   9,  10,  11,  12,  13,  14,  15},\n    //           d  { 16,  17,  18, N/A, N/A,  21,  22,  23},\n    // abscissa  f  { 24,  25,  26,  27,  28,  29,  30,  31},\n    //           g  { 32,  33,  34,  35,  36,  37,  38,  39},\n    //           h  { 40,  41,  42,  43,  44,  45,  46,  47},\n    //           m  { 48,  49,  50,  51,  52,  53,  54,  55},\n    //           n  { 56,  57,  58,  59,  60,  61,  62,  63}}\n    inline variable_type make_test_view_variable()\n    {\n        coordinate_type c = make_test_view_coordinate();\n        data_type d = data_type::from_shape({ c[\"abscissa\"].size(), c[\"ordinate\"].size() });\n        std::iota(d.begin(), d.end(), 0.);\n        d(2, 3).has_value() = false;\n        d(2, 4).has_value() = false;\n        return variable_type(std::move(d), std::move(c), dimension_type({ \"abscissa\", \"ordinate\" }));\n    }\n\n    //                              ordinate\n    //                 1,   2,   4,   5,      6,      8,     12,     13\n    //           a {{  0,   1,   2,   3, masked, masked, masked, masked},\n    //           c  {  8,   9,  10,  11, masked, masked, masked, masked},\n    //           d  { 16,  17,  18, N/A, masked, masked, masked, masked},\n    // abscissa  f  { 24,  25,  26,  27, masked, masked, masked, masked},\n    //           g  { 32,  33,  34,  35, masked, masked, masked, masked},\n    //           h  { 40,  41,  42,  43, masked, masked, masked, masked},\n    //           m  { 48,  49,  50,  51, masked, masked, masked, masked},\n    //           n  { 56,  57,  58,  59, masked, masked, masked, masked}\n    inline auto make_masked_data()\n    {\n        masked_data_type val = masked_data_type::from_shape({ 8, 8 });\n        std::iota(val.begin(), val.end(), 0.);\n        val(2, 3).value().has_value() = false;\n        val(2, 4).value().has_value() = false;\n\n        for (std::size_t a = 0; a < val.shape()[0]; ++a)\n        {\n            for (std::size_t o = 4; o < val.shape()[1]; ++o)\n            {\n                val(a, o) = xtl::masked<xtl::xoptional<double, bool>>();\n            }\n        }\n        return val;\n    }\n\n    //                              ordinate\n    //                    1,      2,      4,      5,      6,      8,     12,     13\n    //           a {{masked,      1,      2,      3,      4,      5,      6,      7},\n    //           c  {masked,      9,     10,     11,     12,     13,     14,     15},\n    //           d  {masked,     17,     18,    N/A,    N/A,     21,     22,     23},\n    // abscissa  f  {masked,     25,     26,     27,     28,     29,     30,     31},\n    //           g  {masked,     33,     34,     35,     36,     37,     38,     39},\n    //           h  {masked,     41,     42,     43,     44,     45,     46,     47},\n    //           m  {masked, masked, masked, masked, masked, masked, masked, masked},\n    //           n  {masked,     57,     58,     59,     60,     61,     62,     63}\n    inline auto make_masked_data2()\n    {\n        masked_data_type val = masked_data_type::from_shape({ 8, 8 });\n        std::iota(val.begin(), val.end(), 0.);\n        val(2, 3).value().has_value() = false;\n        val(2, 4).value().has_value() = false;\n\n        for (std::size_t o = 0; o < val.shape()[1]; ++o)\n        {\n            val(6, o) = xtl::masked<xtl::xoptional<double, bool>>();\n        }\n        for (std::size_t a = 0; a < val.shape()[0]; ++a)\n        {\n            val(a, 0) = xtl::masked<xtl::xoptional<double, bool>>();\n        }\n        return val;\n    }\n\n    //                              ordinate\n    //                 1,         2,      4,      5,      6,      8,     12,     13\n    //           a {{masked,    5.2,    5.2,    5.2,    5.2,    5.2,    5.2,    5.2},\n    //           c  {masked,    5.2,    5.2,    5.2,    5.2,    5.2,    5.2,    5.2},\n    //           d  {masked,    5.2,    5.2,    5.2,    5.2,    5.2,    5.2,    5.2},\n    // abscissa  f  {masked,    5.2,    5.2,    5.2,    5.2,    5.2,    5.2,    5.2},\n    //           g  {masked,    5.2,    5.2,    5.2,    5.2,    5.2,    5.2,    5.2},\n    //           h  {masked,    5.2,    5.2,    5.2,    5.2,    5.2,    5.2,    5.2},\n    //           m  {masked, masked, masked, masked, masked, masked, masked, masked},\n    //           n  {masked,    5.2,    5.2,    5.2,    5.2,    5.2,    5.2,    5.2}\n    inline auto make_masked_data3()\n    {\n        masked_data_type val = masked_data_type::from_shape({ 8, 8 });\n        std::iota(val.begin(), val.end(), 0.);\n        val(2, 3).value().has_value() = false;\n        val(2, 4).value().has_value() = false;\n\n        val.fill(5.2);\n        for (std::size_t o = 0; o < val.shape()[1]; ++o)\n        {\n            val(6, o) = xtl::masked<xtl::xoptional<double, bool>>();\n        }\n        for (std::size_t a = 0; a < val.shape()[0]; ++a)\n        {\n            val(a, 0) = xtl::masked<xtl::xoptional<double, bool>>();\n        }\n        return val;\n    }\n\n    // abscissa: { \"f\", \"g\", \"h\", \"m\", \"n\" }\n    // ordinate: { 1, 4, 6 }\n    inline coordinate_view_type build_coordinate_view(const coordinate_type& c)\n    {\n        using map_type = typename coordinate_view_type::map_type;\n        map_type nmap;\n\n        auto r = range(\"f\", \"n\");\n        auto sr = range(1, 6, 2);\n\n        const auto& abscissa = c[\"abscissa\"];\n        const auto& ordinate = c[\"ordinate\"];\n\n        nmap.emplace(std::make_pair(\"abscissa\", axis_view_type(abscissa, r.build_index_slice(abscissa))));\n        nmap.emplace(std::make_pair(\"ordinate\", axis_view_type(ordinate, sr.build_index_slice(ordinate))));\n\n        return coordinate_view(std::move(nmap));\n    }\n\n    inline coordinate_view_type build_coordinate_view(const coordinate_type& c, const dimension_type& dim,\n        slice_vector& sv)\n    {\n        using map_type = typename coordinate_view_type::map_type;\n        using dynamic_slice = xt::xdynamic_slice<std::ptrdiff_t>;\n        sv.resize(dim.size());\n        map_type nmap;\n\n        auto r = range(\"f\", \"n\");\n        auto sr = range(1, 6, 2);\n\n        const auto& abscissa = c[\"abscissa\"];\n        const auto& ordinate = c[\"ordinate\"];\n\n        auto rindex = r.build_index_slice(abscissa);\n        sv[dim[\"abscissa\"]] = rindex.convert_storage<dynamic_slice, std::ptrdiff_t>();\n        auto cindex = sr.build_index_slice(ordinate);\n        sv[dim[\"ordinate\"]] = cindex.convert_storage<dynamic_slice, std::ptrdiff_t>();\n\n        nmap.emplace(std::make_pair(\"abscissa\", axis_view_type(abscissa, std::move(rindex))));\n        nmap.emplace(std::make_pair(\"ordinate\", axis_view_type(ordinate, std::move(cindex))));\n\n        return coordinate_view(std::move(nmap));\n    }\n    // abscissa: { \"f\", \"g\", \"h\", \"m\", \"n\" }\n    // ordinate: { 1, 4, 6 }\n    // dims: {{ \"abscissa\", 0 }, { \"ordinate\", 1 }}\n    inline variable_view_type build_view(variable_type& v)\n    {\n        const coordinate_type& c = v.coordinates();\n        dimension_type dim = v.dimension_mapping();\n        slice_vector sv;\n        auto cv = build_coordinate_view(c, dim, sv);\n        return variable_view_type(v, std::move(cv), std::move(dim), {}, std::move(sv));\n    }\n}\n\n#endif\n"
  },
  {
    "path": "test/test_xaxis.cpp",
    "content": "/***************************************************************************\n* Copyright (c) Johan Mabille, Sylvain Corlay, Wolf Vollprecht and         *\n* Martin Renou                                                             *\n* Copyright (c) QuantStack                                                 *\n*                                                                          *\n* Distributed under the terms of the BSD 3-Clause License.                 *\n*                                                                          *\n* The full license is in the file LICENSE, distributed with this software. *\n****************************************************************************/\n\n#include <cstddef>\n#include <vector>\n#include \"gtest/gtest.h\"\n#include \"xframe/xaxis_base.hpp\"\n#include \"xframe/xaxis.hpp\"\n#include \"xtl/xbasic_fixed_string.hpp\"\n\nnamespace xf\n{\n    using label_type = std::vector<fstring>;\n    using axis_type = xaxis<fstring>;\n    using caxis_type = xaxis<char>;\n    using iaxis_type = xaxis<int>;\n    using daxis_type = xaxis<double>;\n\n    TEST(xaxis, constructors)\n    {\n        label_type l = { \"a\", \"b\", \"c\" };\n        // From const label_type&\n        {\n            axis_type a(l);\n            EXPECT_EQ(l, a.labels());\n        }\n\n        // From label_type&&\n        {\n            label_type tmp(l);\n            axis_type a(std::move(tmp));\n            EXPECT_EQ(l, a.labels());\n        }\n\n        // From initializer_list\n        {\n            axis_type a = { \"a\", \"b\", \"c\" };\n            EXPECT_EQ(l, a.labels());\n        }\n\n        // From iterators\n        {\n            axis_type a(l.cbegin(), l.cend());\n            EXPECT_EQ(l, a.labels());\n        }\n    }\n\n    TEST(xaxis, axis)\n    {\n        caxis_type a = axis('a', 'd');\n        EXPECT_EQ(a.size(), 3u);\n        EXPECT_EQ(a['a'], 0u);\n        EXPECT_EQ(a['b'], 1u);\n        EXPECT_EQ(a['c'], 2u);\n\n        caxis_type b = axis({'b', 'e', 'f', 'g'});\n        EXPECT_EQ(b.size(), 4u);\n        EXPECT_EQ(b['b'], 0u);\n        EXPECT_EQ(b['e'], 1u);\n        EXPECT_EQ(b['f'], 2u);\n        EXPECT_EQ(b['g'], 3u);\n\n        daxis_type c = axis(0., 1., 0.1);\n        EXPECT_EQ(c.size(), 10u);\n        EXPECT_EQ(c[0.], 0u);\n        EXPECT_EQ(c[0.1], 1u);\n        EXPECT_EQ(c[0.9], 9u);\n    }\n\n    TEST(xaxis, size)\n    {\n        axis_type a = { \"a\", \"b\", \"c\" };\n        EXPECT_EQ(3u, a.size());\n        EXPECT_FALSE(a.empty());\n\n        axis_type a2;\n        EXPECT_EQ(0u, a2.size());\n        EXPECT_TRUE(a2.empty());\n    }\n\n    TEST(xaxis, contains)\n    {\n        axis_type a = { \"a\", \"b\", \"c\" };\n        EXPECT_TRUE(a.contains(\"a\"));\n        EXPECT_FALSE(a.contains(\"d\"));\n    }\n\n    TEST(xaxis, access)\n    {\n        axis_type a = { \"a\", \"b\", \"c\" };\n        auto aa = a[\"a\"];\n        auto ab = a[\"b\"];\n        auto ac = a[\"c\"];\n        EXPECT_EQ(0u, aa);\n        EXPECT_EQ(1u, ab);\n        EXPECT_EQ(2u, ac);\n        EXPECT_THROW(a[\"d\"], std::out_of_range);\n    }\n\n    TEST(xaxis, iterator)\n    {\n        axis_type a = { \"a\", \"b\", \"c\" };\n\n        auto it = a.begin();\n\n        EXPECT_TRUE(it == a.cbegin());\n        EXPECT_TRUE(it != a.end());\n        EXPECT_TRUE(it < a.end());\n        EXPECT_TRUE(it <= a.end());\n        EXPECT_FALSE(it > a.end());\n        EXPECT_FALSE(it >= a.end());\n        EXPECT_EQ(a.end(), a.cend());\n\n        EXPECT_EQ(it->first, \"a\");\n        EXPECT_EQ(it->second, a[\"a\"]);\n        ++it;\n        EXPECT_EQ(it->first, \"b\");\n        EXPECT_EQ(it->second, a[\"b\"]);\n        auto tmp = it++;\n        EXPECT_EQ(tmp->first, \"b\");\n        EXPECT_EQ(it->first, \"c\");\n        EXPECT_EQ(tmp->second, a[\"b\"]);\n        EXPECT_EQ(it->second, a[\"c\"]);\n        ++it;\n        EXPECT_EQ(it, a.end());\n\n        EXPECT_EQ(a[\"c\"], (a.begin() + 2)->second);\n        EXPECT_EQ(a[\"b\"], (a.end() - 2)->second);\n        EXPECT_EQ(3, a.end() - a.begin());\n    }\n\n    TEST(xaxis, find)\n    {\n        axis_type a = { \"a\", \"b\", \"c\" };\n\n        auto ita = a.find(\"a\");\n        auto itb = a.find(\"b\");\n        auto itc = a.find(\"c\");\n        auto itd = a.find(\"d\");\n\n        EXPECT_EQ(ita->first, \"a\");\n        EXPECT_EQ(itb->first, \"b\");\n        EXPECT_EQ(itc->first, \"c\");\n        EXPECT_EQ(itd, a.end());\n    }\n\n    TEST(xaxis, is_sorted)\n    {\n        axis_type a = { \"a\", \"b\", \"c\" };\n        EXPECT_TRUE(a.is_sorted());\n\n        axis_type b = { \"b\", \"b\", \"c\" };\n        EXPECT_TRUE(b.is_sorted());\n\n        axis_type c = { \"c\", \"b\", \"a\" };\n        EXPECT_FALSE(c.is_sorted());\n    }\n\n    TEST(xaxis, merge)\n    {\n        axis_type a1 = { \"a\", \"b\", \"d\", \"e\" };\n        axis_type a2 = { \"b\", \"c\", \"d\" };\n        axis_type a3 = { \"c\", \"g\" };\n        axis_type res;\n        bool t1 = merge_axes(res, a1, a2, a3);\n        EXPECT_FALSE(t1);\n        EXPECT_EQ(res[\"a\"], 0u);\n        EXPECT_EQ(res[\"b\"], 1u);\n        EXPECT_EQ(res[\"c\"], 2u);\n        EXPECT_EQ(res[\"d\"], 3u);\n        EXPECT_EQ(res[\"e\"], 4u);\n        EXPECT_EQ(res[\"g\"], 5u);\n\n        axis_type a4;\n        axis_type res2;\n        bool t2 = merge_axes(res2, a1, a4);\n        EXPECT_FALSE(t2);\n        EXPECT_EQ(res2, a1);\n\n        axis_type a5 = { \"a\", \"b\", \"d\", \"e\" };\n        axis_type a6 = { \"a\", \"b\", \"d\", \"e\" };\n        axis_type res3;\n        bool t3 = merge_axes(res3, a5, a6);\n        EXPECT_TRUE(t3);\n\n        axis_type a7 = { \"e\", \"f\" };\n        axis_type a8 = { \"a\", \"b\", \"c\", \"d\" };\n        axis_type res4;\n        merge_axes(res4, a7, a8);\n        EXPECT_EQ(res4[\"a\"], 0u);\n        EXPECT_EQ(res4[\"b\"], 1u);\n        EXPECT_EQ(res4[\"c\"], 2u);\n        EXPECT_EQ(res4[\"d\"], 3u);\n        EXPECT_EQ(res4[\"e\"], 4u);\n        EXPECT_EQ(res4[\"f\"], 5u);\n\n        xaxis<int, std::size_t> ia1 = { 1, 2, 4};\n        xaxis<int, std::size_t> ia2 = { 1, 4, 5};\n        xaxis<int, std::size_t> iares;\n        bool t4 = merge_axes(iares, ia1, ia2);\n        EXPECT_FALSE(t4);\n        EXPECT_EQ(iares[1], 0u);\n        EXPECT_EQ(iares[2], 1u);\n        EXPECT_EQ(iares[4], 2u);\n        EXPECT_EQ(iares[5], 3u);\n    }\n\n    TEST(xaxis, merge_unsorted)\n    {\n        axis_type a1({ \"a\", \"b\", \"d\", \"e\" });\n        axis_type a2({ \"d\", \"e\" });\n        axis_type a3({ \"h\", \"c\", \"a\", \"b\", \"d\", \"e\" });\n        axis_type a4({ \"h\", \"b\", \"c\", \"e\" });\n\n        axis_type res1;\n        bool t1 = merge_axes(res1, a1, a2);\n        EXPECT_FALSE(t1);\n        EXPECT_TRUE(a1.is_sorted());\n        EXPECT_TRUE(a2.is_sorted());\n        EXPECT_TRUE(res1.is_sorted());\n        EXPECT_EQ(res1.size(), 4u);\n        EXPECT_EQ(res1[\"a\"], 0u);\n        EXPECT_EQ(res1[\"b\"], 1u);\n        EXPECT_EQ(res1[\"d\"], 2u);\n        EXPECT_EQ(res1[\"e\"], 3u);\n\n        axis_type res2;\n        bool t2 = merge_axes(res2, a1, a3);\n        EXPECT_FALSE(t2);\n        EXPECT_TRUE(a1.is_sorted());\n        EXPECT_FALSE(a3.is_sorted());\n        EXPECT_FALSE(res2.is_sorted());\n        EXPECT_EQ(res2.size(), 6u);\n        EXPECT_EQ(res2[\"h\"], 0u);\n        EXPECT_EQ(res2[\"c\"], 1u);\n        EXPECT_EQ(res2[\"a\"], 2u);\n        EXPECT_EQ(res2[\"b\"], 3u);\n        EXPECT_EQ(res2[\"d\"], 4u);\n        EXPECT_EQ(res2[\"e\"], 5u);\n\n        axis_type res3;\n        bool t3 = merge_axes(res3, a1, a4);\n        EXPECT_FALSE(t3);\n        EXPECT_TRUE(a1.is_sorted());\n        EXPECT_FALSE(a4.is_sorted());\n        EXPECT_FALSE(res3.is_sorted());\n        EXPECT_EQ(res3.size(), 6u);\n        EXPECT_EQ(res3[\"h\"], 0u);\n        EXPECT_EQ(res3[\"c\"], 1u);\n        EXPECT_EQ(res3[\"a\"], 2u);\n        EXPECT_EQ(res3[\"b\"], 3u);\n        EXPECT_EQ(res3[\"d\"], 4u);\n        EXPECT_EQ(res3[\"e\"], 5u);\n    }\n\n    TEST(xaxis, intersect)\n    {\n        axis_type a1 = { \"a\", \"b\", \"d\", \"e\" };\n        axis_type a2 = { \"b\", \"c\", \"d\" };\n        axis_type a3 = { \"a\", \"b\", \"d\", \"f\" };\n        axis_type res = { \"b\", \"d\" };\n        axis_type tmp = a1;\n        bool t1 = intersect_axes(tmp, a2, a3);\n        EXPECT_FALSE(t1);\n        EXPECT_EQ(tmp, res);\n\n        tmp = a1;\n        bool t2 = intersect_axes(tmp, a1);\n        EXPECT_TRUE(t2);\n        EXPECT_EQ(tmp, a1);\n\n        axis_type a4 = { \"a\", \"b\", \"c\" };\n        axis_type a5 = { \"b\", \"a\", \"c\" };\n        tmp = a4;\n        bool t3 = intersect_axes(tmp, a5);\n        EXPECT_FALSE(t3);\n\n        axis_type a6 = { \"a\", \"c\" };\n        tmp = a4;\n        bool t4 = intersect_axes(tmp, a6);\n        EXPECT_FALSE(t4);\n    }\n\n    TEST(xaxis, filter)\n    {\n        axis_type a = { \"a\", \"b\", \"d\", \"e\" };\n        axis_type filtered_a = a.filter([](const auto& arg) { return arg < \"d\"; });\n        EXPECT_EQ(filtered_a.size(), 2u);\n        EXPECT_EQ(a[\"a\"], 0u);\n        EXPECT_EQ(a[\"b\"], 1u);\n    }\n}\n"
  },
  {
    "path": "test/test_xaxis_default.cpp",
    "content": "/***************************************************************************\n* Copyright (c) Johan Mabille, Sylvain Corlay, Wolf Vollprecht and         *\n* Martin Renou                                                             *\n* Copyright (c) QuantStack                                                 *\n*                                                                          *\n* Distributed under the terms of the BSD 3-Clause License.                 *\n*                                                                          *\n* The full license is in the file LICENSE, distributed with this software. *\n****************************************************************************/\n\n#include <cstddef>\n#include <vector>\n#include \"gtest/gtest.h\"\n\n#include \"xframe/xaxis.hpp\"\n#include \"xframe/xaxis_default.hpp\"\n\nnamespace xf\n{\n    using axis_type = xaxis<int>;\n    using label_type = std::vector<int>;\n    using axis_default_type = xaxis_default<int>;\n\n    TEST(xaxis_default, axis)\n    {\n        auto a = axis(4);\n        auto labels = a.labels();\n\n        EXPECT_EQ(0, labels[0]);\n        EXPECT_EQ(1, labels[1]);\n        EXPECT_EQ(2, labels[2]);\n        EXPECT_EQ(3, labels[3]);\n        EXPECT_EQ(4u, labels.size());\n    }\n\n    TEST(xaxis_default, labels)\n    {\n        axis_default_type a(4);\n        label_type labels = a.labels();\n\n        EXPECT_EQ(0, labels[0]);\n        EXPECT_EQ(1, labels[1]);\n        EXPECT_EQ(2, labels[2]);\n        EXPECT_EQ(3, labels[3]);\n        EXPECT_EQ(4u, labels.size());\n    }\n\n    TEST(xaxis_default, size)\n    {\n        axis_default_type a(36);\n        EXPECT_EQ(36u, a.size());\n        EXPECT_EQ(a.labels().size(), a.size());\n        EXPECT_FALSE(a.empty());\n\n        axis_default_type a2;\n        EXPECT_EQ(0u, a2.size());\n        EXPECT_TRUE(a2.empty());\n    }\n\n    TEST(xaxis_default, is_sorted)\n    {\n        axis_default_type a(36);\n        EXPECT_TRUE(a.is_sorted());\n    }\n\n    TEST(xaxis_default, contains)\n    {\n        axis_default_type a(36);\n        EXPECT_TRUE(a.contains(0));\n        EXPECT_TRUE(a.contains(15));\n        EXPECT_TRUE(a.contains(35));\n        EXPECT_FALSE(a.contains(36));\n        EXPECT_FALSE(a.contains(126));\n        EXPECT_FALSE(a.contains(-2));\n    }\n\n    TEST(xaxis_default, access)\n    {\n        axis_default_type a(3);\n        auto a0 = a[0];\n        auto a1 = a[1];\n        auto a2 = a[2];\n        EXPECT_EQ(0u, a0);\n        EXPECT_EQ(1u, a1);\n        EXPECT_EQ(2u, a2);\n        EXPECT_THROW(a[3], std::out_of_range);\n    }\n\n    TEST(xaxis_default, iterator)\n    {\n        axis_default_type a(3);\n\n        auto it = a.begin();\n\n        EXPECT_TRUE(it == a.cbegin());\n        EXPECT_TRUE(it != a.end());\n        EXPECT_TRUE(it < a.end());\n        EXPECT_TRUE(it <= a.end());\n        EXPECT_FALSE(it > a.end());\n        EXPECT_FALSE(it >= a.end());\n        EXPECT_EQ(a.end(), a.cend());\n\n        EXPECT_EQ(it->first, 0);\n        EXPECT_EQ(it->second, a[0]);\n        ++it;\n        EXPECT_EQ(it->first, 1);\n        EXPECT_EQ(it->second, a[1]);\n        auto tmp = it++;\n        EXPECT_EQ(tmp->first, 1);\n        EXPECT_EQ(it->first, 2);\n        EXPECT_EQ(tmp->second, a[1]);\n        EXPECT_EQ(it->second, a[2]);\n        ++it;\n        EXPECT_EQ(it, a.end());\n\n        EXPECT_EQ(a[2], (a.begin() + 2)->second);\n        EXPECT_EQ(a[1], (a.end() - 2)->second);\n        EXPECT_EQ(3, a.end() - a.begin());\n    }\n\n    TEST(xaxis_default, find)\n    {\n        axis_default_type a(3);\n\n        auto it0 = a.find(0);\n        auto it1 = a.find(1);\n        auto it2 = a.find(2);\n        auto it3 = a.find(3);\n\n        EXPECT_EQ(it0->first, 0);\n        EXPECT_EQ(it1->first, 1);\n        EXPECT_EQ(it2->first, 2);\n        EXPECT_EQ(it3, a.end());\n    }\n\n    TEST(xaxis_default, merge)\n    {\n        axis_type a1 = { 3, 4, 5, 6 };\n        axis_default_type a2(3);\n        axis_default_type a3(5);\n        axis_type res;\n        bool t1 = merge_axes(res, a1, a2, a3);\n        EXPECT_FALSE(t1);\n        EXPECT_EQ(res[0], 0u);\n        EXPECT_EQ(res[1], 1u);\n        EXPECT_EQ(res[2], 2u);\n        EXPECT_EQ(res[3], 3u);\n        EXPECT_EQ(res[4], 4u);\n        EXPECT_EQ(res[5], 5u);\n        EXPECT_EQ(res[6], 6u);\n\n        // Merging and xaxis_default with an xaxis\n        axis_type a4;\n        axis_type res2;\n        bool t2 = merge_axes(res2, a2, a4);\n        EXPECT_FALSE(t2);\n        EXPECT_EQ(res2, a2);\n\n        // Merging two xaxis_default together returns an xaxis\n        axis_default_type a5(4);\n        axis_default_type a6(4);\n        axis_type res3;\n        bool t3 = merge_axes(res3, a5, a6);\n        EXPECT_TRUE(t3);\n    }\n\n    TEST(xaxis_default, filter)\n    {\n        axis_default_type a(36);\n        axis_type res = a.filter([](const auto& arg) { return arg >= 16; });\n        EXPECT_TRUE(res.is_sorted());\n        EXPECT_EQ(res.size(), 20u);\n        EXPECT_EQ(res.labels()[0], 16);\n        EXPECT_EQ(res[16], 0u);\n        EXPECT_EQ(res[35], 19u);\n    }\n\n    TEST(xaxis_default, filter_size)\n    {\n        axis_default_type a(36);\n        axis_type res = a.filter([](const auto& arg) { return arg >= 26; }, std::size_t(10));\n        EXPECT_TRUE(res.is_sorted());\n        EXPECT_EQ(res.size(), 10u);\n        EXPECT_EQ(res.labels()[0], 26);\n        EXPECT_EQ(res[26], 0u);\n        EXPECT_EQ(res[35], 9u);\n    }\n}\n"
  },
  {
    "path": "test/test_xaxis_function.cpp",
    "content": "/***************************************************************************\n* Copyright (c) Johan Mabille, Sylvain Corlay, Wolf Vollprecht and         *\n* Martin Renou                                                             *\n* Copyright (c) QuantStack                                                 *\n*                                                                          *\n* Distributed under the terms of the BSD 3-Clause License.                 *\n*                                                                          *\n* The full license is in the file LICENSE, distributed with this software. *\n****************************************************************************/\n\n#include \"gtest/gtest.h\"\n\n#include \"xtensor/xarray.hpp\"\n#include \"xtensor/xfunction.hpp\"\n\n#include \"xframe/xnamed_axis.hpp\"\n\n#include \"test_fixture.hpp\"\n\nnamespace xf\n{\n    TEST(xaxis_function, plus_operator)\n    {\n        auto axis1 = named_axis(\"abs\", axis(16));\n        auto axis2 = named_axis(\"ord\", axis(10, 20, 1));\n\n        auto func1 = axis1 + axis2;\n        EXPECT_EQ(func1({{\"abs\", 10}, {\"ord\", 5}}), 25);\n        EXPECT_EQ(func1({{\"abs\", 15}, {\"ord\", 9}}), 34);\n    }\n\n    TEST(xaxis_function, pow_operator)\n    {\n        auto axis1 = named_axis(\"abs\", axis(15));\n        auto axis2 = named_axis(\"ord\", axis(10, 20, 1));\n\n        auto func1 = pow(axis2, axis1);\n        EXPECT_EQ(func1({{\"abs\", 2}, {\"ord\", 5}}), 225);\n\n        auto func2 = axis1 + axis2 + pow(axis2, axis1);\n        EXPECT_EQ(func2({{\"abs\", 2}, {\"ord\", 5}}), 242);\n    }\n\n    TEST(xaxis_function, bool_operator)\n    {\n        auto axis1 = named_axis(\"abs\", axis(15));\n        auto axis2 = named_axis(\"ord\", axis(10, 20, 1));\n        auto axis3 = named_axis(\"alt\", axis('b', 'j'));\n\n        auto func1 = axis1 < 13;\n        EXPECT_EQ(func1({{\"abs\", 10}}), true);\n        EXPECT_EQ(func1({{\"abs\", 14}}), false);\n\n        auto func2 = axis1 > axis2;\n        EXPECT_EQ(func2({{\"abs\", 10}, {\"ord\", 3}}), false);\n        EXPECT_EQ(func2({{\"abs\", 14}, {\"ord\", 3}}), true);\n\n        auto func3 = equal(axis3, 'b') || axis3 >= 'g' && not_equal(axis3, 'i');\n        EXPECT_EQ(func3({{\"alt\", 0}}), true);  // b\n        EXPECT_EQ(func3({{\"alt\", 1}}), false); // c\n        EXPECT_EQ(func3({{\"alt\", 2}}), false); // d\n        EXPECT_EQ(func3({{\"alt\", 3}}), false); // e\n        EXPECT_EQ(func3({{\"alt\", 4}}), false); // f\n        EXPECT_EQ(func3({{\"alt\", 5}}), true);  // g\n        EXPECT_EQ(func3({{\"alt\", 6}}), true);  // h\n        EXPECT_EQ(func3({{\"alt\", 7}}), false); // i\n    }\n\n    TEST(xaxis_function, xaxis_scalar)\n    {\n        auto axis1 = named_axis(\"abs\", axis(15));\n        auto axis2 = named_axis(\"ord\", axis(10, 20, 1));\n\n        auto func1 = axis1 < 13;\n        EXPECT_EQ(func1({{\"abs\", 10}}), true);\n        EXPECT_EQ(func1({{\"abs\", 14}}), false);\n\n        auto func2 = axis1 + axis2 + 4;\n        EXPECT_EQ(func2({{\"abs\", 10}, {\"ord\", 5}}), 29);\n    }\n\n    TEST(xaxis_function, mask)\n    {\n        auto axis1 = named_axis(fstring(\"abs\"), axis({0, 2, 5}));\n        auto axis2 = named_axis(fstring(\"ord\"), axis({'a', 'c', 'i'}));\n\n        auto array = xt::xarray<bool>({\n            {true, true, true},\n            {true, true, true},\n            {true, true, true}\n        });\n\n        auto mask = axis_function_mask(\n            equal(axis2, 'c') || equal(axis1, 0),\n            dimension_type({\"abs\", \"ord\"}),\n            array.shape()\n        );\n\n        auto expected = xt::xarray<bool>({\n            { true,  true,  true},\n            {false,  true, false},\n            {false,  true, false}\n        });\n\n        EXPECT_EQ(mask, expected);\n    }\n\n    TEST(xaxis_function, mask_op)\n    {\n        auto axis1 = named_axis(fstring(\"abs\"), axis({0, 2, 5}));\n        auto axis2 = named_axis(fstring(\"ord\"), axis({'a', 'c', 'i'}));\n\n        auto array = xt::xarray<bool>({\n            { true,  true, false},\n            { true,  true,  true},\n            { true,  true,  true}\n        });\n\n        auto mask = axis_function_mask(\n            equal(axis2, 'i') || equal(axis1, 0),\n            dimension_type({\"abs\", \"ord\"}),\n            array.shape()\n        );\n\n        auto expected = xt::xarray<bool>({\n            { true,  true, false},\n            {false, false,  true},\n            {false, false,  true}\n        });\n\n        xt::xarray<bool> val = array && mask;\n        EXPECT_EQ(val, expected);\n    }\n}\n"
  },
  {
    "path": "test/test_xaxis_variant.cpp",
    "content": "/***************************************************************************\n* Copyright (c) Johan Mabille, Sylvain Corlay, Wolf Vollprecht and         *\n* Martin Renou                                                             *\n* Copyright (c) QuantStack                                                 *\n*                                                                          *\n* Distributed under the terms of the BSD 3-Clause License.                 *\n*                                                                          *\n* The full license is in the file LICENSE, distributed with this software. *\n****************************************************************************/\n\n#include <cstddef>\n#include <vector>\n#include \"gtest/gtest.h\"\n\n#include \"xframe/xframe_config.hpp\"\n#include \"xframe/xaxis_variant.hpp\"\n\nnamespace xf\n{\n    using axis_variant_type = xaxis_variant<XFRAME_DEFAULT_LABEL_LIST, std::size_t>;\n\n    TEST(xaxis_variant, get_labels)\n    {\n        auto a = axis_variant_type(axis(56));\n        auto labels = get_labels<int>(a);\n\n        EXPECT_EQ(0, labels[0]);\n        EXPECT_EQ(56u, labels.size());\n    }\n\n    TEST(xaxis_variant, size)\n    {\n        auto a = axis_variant_type(axis(56));\n        EXPECT_EQ(56u, a.size());\n        EXPECT_FALSE(a.empty());\n\n        auto a2 = axis_variant_type(axis(0));\n        EXPECT_EQ(0u, a2.size());\n        EXPECT_TRUE(a2.empty());\n    }\n\n    TEST(xaxis_variant, is_sorted)\n    {\n        auto a = axis_variant_type(axis(36, 56, 2));\n        EXPECT_TRUE(a.is_sorted());\n    }\n\n    TEST(xaxis_variant, contains)\n    {\n        auto a = axis_variant_type(axis(36));\n        EXPECT_TRUE(a.contains(0));\n        EXPECT_TRUE(a.contains(15));\n        EXPECT_TRUE(a.contains(35));\n        EXPECT_FALSE(a.contains(36));\n        EXPECT_FALSE(a.contains(126));\n        EXPECT_FALSE(a.contains(-2));\n    }\n\n    TEST(xaxis_variant, access)\n    {\n        auto a = axis_variant_type(axis(3));\n        auto a0 = a[0];\n        auto a1 = a[1];\n        auto a2 = a[2];\n        EXPECT_EQ(0u, a0);\n        EXPECT_EQ(1u, a1);\n        EXPECT_EQ(2u, a2);\n        EXPECT_THROW(a[3], std::out_of_range);\n    }\n}\n"
  },
  {
    "path": "test/test_xaxis_view.cpp",
    "content": "/***************************************************************************\n* Copyright (c) Johan Mabille, Sylvain Corlay, Wolf Vollprecht and         *\n* Martin Renou                                                             *\n* Copyright (c) QuantStack                                                 *\n*                                                                          *\n* Distributed under the terms of the BSD 3-Clause License.                 *\n*                                                                          *\n* The full license is in the file LICENSE, distributed with this software. *\n****************************************************************************/\n\n#include <cstddef>\n#include <vector>\n#include \"gtest/gtest.h\"\n#include \"xtl/xbasic_fixed_string.hpp\"\n#include \"test_fixture_view.hpp\"\n\nnamespace xf\n{\n    using slice_type = xt::xstepped_range<size_type>;\n\n    // stepped_range(1, 7, 2)\n    inline slice_type make_slice()\n    {\n        return slice_type(size_type(1), size_type(7), size_type(2));\n    }\n\n    TEST(xaxis_view, label)\n    {\n        auto a = make_variant_view_saxis();\n        axis_view_type v = axis_view_type(a, make_slice());\n        EXPECT_EQ(xtl::get<fstring>(v.label(0)), xtl::xget<const fstring&>(v.labels()[0]));\n        EXPECT_EQ(xtl::get<fstring>(v.label(0)), xtl::xget<const fstring&>(v.labels()[0]));\n    }\n\n    TEST(xaxis_view, size)\n    {\n        auto a = make_variant_view_saxis();\n        axis_view_type v = axis_view_type(a, make_slice());\n        EXPECT_EQ(v.size(), 3u);\n        EXPECT_FALSE(v.empty());\n\n        axis_view_type v2 = axis_view_type(a, slice_type(size_type(1), size_type(1), size_type(2)));\n        EXPECT_EQ(v2.size(), 0u);\n        EXPECT_TRUE(v2.empty());\n    }\n\n    TEST(xaxis_view, contains)\n    {\n        auto a = make_variant_view_saxis();\n        axis_view_type v = axis_view_type(a, make_slice());\n\n        EXPECT_TRUE(v.contains(\"c\"));\n        EXPECT_FALSE(v.contains(\"d\"));\n    }\n\n    TEST(xaxis_view, access)\n    {\n        auto a = make_variant_view_saxis();\n        axis_view_type v = axis_view_type(a, make_slice());\n\n        auto vc = v[\"c\"];\n        auto vf = v[\"f\"];\n        auto vh = v[\"h\"];\n\n        EXPECT_EQ(vc, 1u);\n        EXPECT_EQ(vf, 3u);\n        EXPECT_EQ(vh, 5u);\n        EXPECT_THROW(v[\"m\"], std::out_of_range);\n    }\n\n    TEST(xaxis_view, iterator)\n    {\n        auto a = make_variant_view_saxis();\n        axis_view_type v = axis_view_type(a, make_slice());\n\n        auto it = v.begin();\n\n        EXPECT_TRUE(it == v.cbegin());\n        bool res = (it != v.end());\n        EXPECT_TRUE(it != v.end());\n        EXPECT_TRUE(it < v.end());\n        EXPECT_TRUE(it <= v.end());\n        EXPECT_FALSE(it > v.end());\n        EXPECT_FALSE(it >= v.end());\n        EXPECT_EQ(v.end(), v.cend());\n\n        // TODO: fix xaxis_variant iterator\n        EXPECT_EQ(xtl::xget<const fstring&>(it->first), \"c\");\n        auto val = *it;\n        EXPECT_EQ(xtl::xget<const fstring&>(val.first), \"c\");\n        EXPECT_EQ(val.second, v[\"c\"]);\n        ++it;\n        EXPECT_EQ(xtl::xget<const fstring&>(it->first), \"f\");\n        EXPECT_EQ(it->second, v[\"f\"]);\n        auto tmp = it++;\n        EXPECT_EQ(xtl::xget<const fstring&>(tmp->first), \"f\");\n        EXPECT_EQ(tmp->second, v[\"f\"]);\n        EXPECT_EQ(xtl::xget<const fstring&>(it->first), \"h\");\n        EXPECT_EQ(it->second, v[\"h\"]);\n        ++it;\n        EXPECT_EQ(it, v.end());\n\n        EXPECT_EQ(v[\"h\"], (v.begin() + 2)->second);\n        EXPECT_EQ(v[\"f\"], (v.end() - 2)->second);\n        EXPECT_EQ(3, v.end() - v.begin());\n\n        auto f1 = v.find(\"c\");\n        EXPECT_EQ(f1->second, v[\"c\"]);\n        auto f2 = v.find(\"a\");\n        EXPECT_EQ(f2, v.cend());\n    }\n\n    TEST(xaxis_view, range)\n    {\n        // { \"a\", \"c\", \"d\", \"f\", \"g\", \"h\", \"m\", \"n\" }\n        auto a = make_variant_view_saxis();\n\n        auto r = range(\"c\", \"f\");\n        axis_view_type vr = axis_view_type(a, r.build_index_slice(a));\n        auto vrit = vr.cbegin();\n        EXPECT_EQ(xtl::xget<const fstring&>(vrit->first), \"c\");\n        ++vrit;\n        EXPECT_EQ(xtl::xget<const fstring&>(vrit->first), \"d\");\n        ++vrit;\n        EXPECT_EQ(xtl::xget<const fstring&>(vrit->first), \"f\");\n        ++vrit;\n        EXPECT_EQ(vrit, vr.cend());\n\n        auto sr = range(\"c\", \"h\", 2);\n        axis_view_type vsr = axis_view_type(a, sr.build_index_slice(a));\n        auto vsrit = vsr.cbegin();\n        EXPECT_EQ(xtl::xget<const fstring&>(vsrit->first), \"c\");\n        ++vsrit;\n        EXPECT_EQ(xtl::xget<const fstring&>(vsrit->first), \"f\");\n        ++vsrit;\n        EXPECT_EQ(xtl::xget<const fstring&>(vsrit->first), \"h\");\n        ++vsrit;\n        EXPECT_EQ(vsrit, vsr.cend());\n    }\n\n    TEST(xaxis_view, conversion)\n    {\n        auto a = make_variant_view_saxis();\n        axis_view_type v = axis_view_type(a, make_slice());\n        axis_variant vf = axis_variant(v);\n        EXPECT_EQ(vf[\"c\"], 0u);\n        EXPECT_EQ(vf[\"f\"], 1u);\n        EXPECT_EQ(vf[\"h\"], 2u);\n    }\n\n    TEST(xaxis_view, comparison)\n    {\n        // { \"a\", \"c\", \"d\", \"f\", \"g\", \"h\", \"m\", \"n\" }\n        auto a = make_variant_view_saxis();\n        auto r = range(\"c\", \"f\");\n        axis_view_type vr = axis_view_type(a, r.build_index_slice(a));\n\n        axis_variant b(saxis_type({\"c\", \"d\", \"f\"}));\n        axis_variant c(saxis_type({\"c\", \"e\", \"f\"}));\n\n        EXPECT_TRUE(vr == b);\n        EXPECT_TRUE(b == vr);\n\n        EXPECT_TRUE(vr != c);\n        EXPECT_TRUE(c != vr);\n    }\n}\n"
  },
  {
    "path": "test/test_xcoordinate.cpp",
    "content": "/***************************************************************************\n* Copyright (c) Johan Mabille, Sylvain Corlay, Wolf Vollprecht and         *\n* Martin Renou                                                             *\n* Copyright (c) QuantStack                                                 *\n*                                                                          *\n* Distributed under the terms of the BSD 3-Clause License.                 *\n*                                                                          *\n* The full license is in the file LICENSE, distributed with this software. *\n****************************************************************************/\n\n#include \"gtest/gtest.h\"\n#include \"test_fixture.hpp\"\n\nnamespace xf\n{\n    using slabel_type = std::vector<fstring>;\n    using ilabel_type = std::vector<int>;\n\n    TEST(xcoordinate, constructor)\n    {\n        auto c1 = make_test_coordinate();\n\n        using map_type = typename std::decay_t<decltype(c1)>::map_type;\n        map_type m;\n        m[\"abscissa\"] = make_test_saxis();\n        m[\"ordinate\"] = make_test_iaxis();\n\n        auto c2 = coordinate(m);\n        auto c3 = coordinate(std::move(m));\n\n        EXPECT_EQ(c1, c2);\n        EXPECT_EQ(c1, c3);\n        EXPECT_FALSE(c1 != c2);\n\n        decltype(c1) c4 = {{ fstring(\"abscissa\"), make_test_saxis() }, { fstring(\"ordinate\"), make_test_iaxis() }};\n        EXPECT_EQ(c1, c4);\n\n        decltype(c1) c5 = {{\"abscissa\", make_test_saxis()}, {\"ordinate\", make_test_iaxis()}};\n        EXPECT_EQ(c1, c5);\n\n        auto c6 = coordinate({{\"abscissa\", make_test_saxis()}, {\"ordinate\", make_test_iaxis() }});\n        EXPECT_EQ(c1, c6);\n    }\n\n    TEST(xcoordinate, size)\n    {\n        auto c1 = make_test_coordinate();\n        EXPECT_EQ(2u, c1.size());\n        EXPECT_FALSE(c1.empty());\n\n        decltype(c1) c2;\n        EXPECT_EQ(0u, c2.size());\n        EXPECT_TRUE(c2.empty());\n    }\n\n    TEST(xcoordinate, contains)\n    {\n        auto c = make_test_coordinate();\n        EXPECT_TRUE(c.contains(\"abscissa\"));\n        EXPECT_FALSE(c.contains(\"humidity\"));\n    }\n\n    TEST(xcoordinate, access)\n    {\n        auto c = make_test_coordinate();\n        EXPECT_EQ(c[\"abscissa\"][\"a\"], 0u);\n        EXPECT_EQ(c[\"abscissa\"][\"c\"], 1u);\n        EXPECT_EQ(c[\"abscissa\"][\"d\"], 2u);\n        EXPECT_EQ(c[\"ordinate\"][1], 0u);\n        EXPECT_EQ(c[\"ordinate\"][2], 1u);\n        EXPECT_EQ(c[\"ordinate\"][4], 2u);\n\n        EXPECT_EQ(c[std::make_pair(\"abscissa\", fstring(\"a\"))], 0u);\n        EXPECT_EQ(c[std::make_pair(\"abscissa\", fstring(\"c\"))], 1u);\n        EXPECT_EQ(c[std::make_pair(\"abscissa\", fstring(\"d\"))], 2u);\n        EXPECT_EQ(c[std::make_pair(\"ordinate\", 1)], 0u);\n        EXPECT_EQ(c[std::make_pair(\"ordinate\", 2)], 1u);\n        EXPECT_EQ(c[std::make_pair(\"ordinate\", 4)], 2u);\n    }\n\n    TEST(xcoordinate, iterator)\n    {\n        auto c = make_test_coordinate();\n        auto iter = c.begin();\n        EXPECT_EQ((iter->second)[\"d\"], 2u);\n        ++iter;\n        EXPECT_EQ((iter->second)[2], 1u);\n        ++iter;\n        EXPECT_EQ(iter, c.end());\n    }\n\n    TEST(xcoordinate, find)\n    {\n        auto c = make_test_coordinate();\n        auto iter = c.find(\"abscissa\");\n        EXPECT_EQ((iter->second)[\"d\"], 2u);\n        auto iter2 = c.find(\"not_here\");\n        EXPECT_EQ(iter2, c.end());\n    }\n\n    TEST(xcoordinate, key_iterator)\n    {\n        auto c = make_test_coordinate();\n        auto iter = c.key_begin();\n        EXPECT_EQ(*iter, \"abscissa\");\n        ++iter;\n        EXPECT_EQ(*iter, \"ordinate\");\n        ++iter;\n        EXPECT_EQ(iter, c.key_end());\n    }\n\n    TEST(xcoordinate, merge)\n    {\n        auto coord_res = make_merge_coordinate();\n        auto c1 = make_test_coordinate();\n        decltype(c1) cres1;\n        auto res1 = broadcast_coordinates<join::outer>(cres1, c1, c1);\n        EXPECT_TRUE(res1.m_same_dimensions);\n        EXPECT_TRUE(res1.m_same_labels);\n        EXPECT_EQ(c1, cres1);\n\n        auto c2 = make_test_coordinate3();\n        decltype(c2) cres2;\n        auto res2 = broadcast_coordinates<join::outer>(cres2, c1, c2);\n        EXPECT_FALSE(res2.m_same_dimensions);\n        EXPECT_FALSE(res2.m_same_labels);\n        EXPECT_EQ(cres2, coord_res);\n    }\n\n    TEST(xcoordinate, merge_axis_default)\n    {\n        auto coord_res = make_merge_coordinate2();\n        auto c1 = make_test_coordinate3();\n        auto c2 = make_test_coordinate4();\n        decltype(c1) cres1;\n        broadcast_coordinates<join::outer>(cres1, c1, c2);\n        EXPECT_EQ(cres1, coord_res);\n\n        decltype(c1) cres2;\n        broadcast_coordinates<join::outer>(cres2, c2, c1);\n        EXPECT_EQ(cres1, cres2);\n    }\n\n    TEST(xcoordinate, intersect)\n    {\n        auto c1 = make_test_coordinate();\n        auto c2 = make_test_coordinate3();\n\n        auto coord_res = make_intersect_coordinate();\n\n        auto cres = c1;\n        auto res = broadcast_coordinates<join::inner>(cres, c2);\n        EXPECT_FALSE(res.m_same_dimensions);\n        EXPECT_FALSE(res.m_same_labels);\n        EXPECT_EQ(cres, coord_res);\n    }\n\n    TEST(xcoordinate, intersect_axis_default)\n    {\n        auto c1 = make_test_coordinate3();\n        auto c2 = make_test_coordinate4();\n\n        auto coord_res = make_intersect_coordinate2();\n\n        decltype(c1) cres1;\n        broadcast_coordinates<join::inner>(cres1, c1, c2);\n        EXPECT_EQ(cres1, coord_res);\n\n        decltype(c1) cres2;\n        broadcast_coordinates<join::inner>(cres2, c2, c1);\n        EXPECT_EQ(cres2, coord_res);\n    }\n}\n"
  },
  {
    "path": "test/test_xcoordinate_chain.cpp",
    "content": "/***************************************************************************\n* Copyright (c) Johan Mabille, Sylvain Corlay, Wolf Vollprecht and         *\n* Martin Renou                                                             *\n* Copyright (c) QuantStack                                                 *\n*                                                                          *\n* Distributed under the terms of the BSD 3-Clause License.                 *\n*                                                                          *\n* The full license is in the file LICENSE, distributed with this software. *\n****************************************************************************/\n\n#include \"gtest/gtest.h\"\n#include \"test_fixture.hpp\"\n\n#include \"xframe/xcoordinate_chain.hpp\"\n\nnamespace xf\n{\n    using slabel_type = std::vector<fstring>;\n    using ilabel_type = std::vector<int>;\n\n    TEST(xcoordinate_chain, constructor)\n    {\n        auto c = make_test_coordinate();\n        using map_type = typename std::decay_t<decltype(c)>::map_type;\n        map_type m;\n        m[\"altitude\"] = make_test_saxis3();\n\n        EXPECT_ANY_THROW(reindex(c, m));\n    }\n\n    template <class C>\n    inline xcoordinate_chain<C> make_coordinate_chain(const C& c)\n    {\n        using map_type = typename std::decay_t<C>::map_type;\n        map_type m;\n        m[\"abscissa\"] = make_test_saxis3();\n        return reindex(c, std::move(m));\n    }\n\n    TEST(xcoordinate_chain, size)\n    {\n        auto c = make_test_coordinate();\n        auto cc = make_coordinate_chain(c);\n\n        EXPECT_EQ(2u, cc.size());\n        EXPECT_FALSE(cc.empty());\n    }\n\n    TEST(xcoordinate_chain, contains)\n    {\n        auto c = make_test_coordinate();\n        auto cc = make_coordinate_chain(c);\n\n        EXPECT_TRUE(cc.contains(\"abscissa\"));\n        EXPECT_TRUE(cc.contains(\"ordinate\"));\n        EXPECT_FALSE(cc.contains(\"altitude\"));\n\n        EXPECT_TRUE(cc.contains(\"abscissa\", \"c\"));\n        EXPECT_FALSE(cc.contains(\"abscissa\", \"e\"));\n        EXPECT_TRUE(cc.contains(\"ordinate\", 2));\n        EXPECT_TRUE(cc.contains(\"ordinate\", 4));\n        EXPECT_FALSE(cc.contains(\"ordinate\", 6));\n        EXPECT_FALSE(cc.contains(\"altitude\", \"a\"));\n    }\n\n    TEST(xcoordinate_chain, access)\n    {\n        auto c = make_test_coordinate();\n        auto cc = make_coordinate_chain(c);\n\n        EXPECT_EQ(cc[\"abscissa\"][\"a\"], 0u);\n        EXPECT_EQ(cc[\"abscissa\"][\"b\"], 1u);\n        EXPECT_EQ(cc[\"abscissa\"][\"c\"], 2u);\n        EXPECT_EQ(cc[\"abscissa\"][\"d\"], 3u);\n        EXPECT_EQ(cc[\"ordinate\"][1], 0u);\n        EXPECT_EQ(cc[\"ordinate\"][2], 1u);\n        EXPECT_EQ(cc[\"ordinate\"][4], 2u);\n\n        EXPECT_EQ(cc[std::make_pair(\"abscissa\", fstring(\"a\"))], 0u);\n        EXPECT_EQ(cc[std::make_pair(\"abscissa\", fstring(\"b\"))], 1u);\n        EXPECT_EQ(cc[std::make_pair(\"abscissa\", fstring(\"c\"))], 2u);\n        EXPECT_EQ(cc[std::make_pair(\"abscissa\", fstring(\"d\"))], 3u);\n        EXPECT_EQ(cc[std::make_pair(\"ordinate\", 1)], 0u);\n        EXPECT_EQ(cc[std::make_pair(\"ordinate\", 2)], 1u);\n        EXPECT_EQ(cc[std::make_pair(\"ordinate\", 4)], 2u);\n    }\n\n    TEST(xcoordinate_chain, iterator)\n    {\n        auto c = make_test_coordinate();\n        auto cc = make_coordinate_chain(c);\n\n        auto iter = cc.begin();\n        EXPECT_EQ((iter->second)[\"b\"], 1u);\n        EXPECT_EQ((iter->second)[\"c\"], 2u);\n        ++iter;\n        EXPECT_EQ((iter->second)[2], 1u);\n        ++iter;\n        EXPECT_EQ(iter, cc.end());\n    }\n\n    TEST(xcoordinate_chain, find)\n    {\n        auto c = make_test_coordinate();\n        auto cc = make_coordinate_chain(c);\n\n        auto iter = cc.find(\"abscissa\");\n        EXPECT_EQ((iter->second)[\"a\"], 0u);\n        auto iter2 = cc.find(\"not_here\");\n        EXPECT_EQ(iter2, cc.end());\n    }\n\n    TEST(xcoordinate_chain, key_iterator)\n    {\n        auto c = make_test_coordinate();\n        auto cc = make_coordinate_chain(c);\n\n        auto iter = cc.key_begin();\n        EXPECT_EQ(*iter, \"abscissa\");\n        ++iter;\n        EXPECT_EQ(*iter, \"ordinate\");\n        ++iter;\n        EXPECT_EQ(iter, cc.key_end());\n    }\n\n    TEST(xcoordinate_chain, comparison)\n    {\n        auto c = make_test_coordinate();\n        auto cc = make_coordinate_chain(c);\n\n        EXPECT_TRUE(cc == cc);\n        EXPECT_FALSE(cc != cc);\n\n        using map_type = typename std::decay_t<decltype(c)>::map_type;\n        map_type m;\n        m[\"abscissa\"] = saxis_type({\"a\", \"d\", \"e\", \"f\"});\n        auto cc2 = reindex(c, std::move(m));\n        EXPECT_FALSE(cc == cc2);\n        EXPECT_TRUE(cc != cc2);\n    }\n\n    TEST(xcoordinate_chain, mixed_comparison)\n    {\n        auto c = make_test_coordinate();\n        auto cc = make_coordinate_chain(c);\n        coordinate_type c2 = {{\"abscissa\", make_test_saxis3()}, {\"ordinate\", make_test_iaxis()}};\n\n        using xf::operator<<;\n        EXPECT_NE(cc, c);\n        EXPECT_EQ(cc, c2);\n    }\n}\n"
  },
  {
    "path": "test/test_xcoordinate_expanded.cpp",
    "content": "/***************************************************************************\n* Copyright (c) Johan Mabille, Sylvain Corlay, Wolf Vollprecht and         *\n* Martin Renou                                                             *\n* Copyright (c) QuantStack                                                 *\n*                                                                          *\n* Distributed under the terms of the BSD 3-Clause License.                 *\n*                                                                          *\n* The full license is in the file LICENSE, distributed with this software. *\n****************************************************************************/\n\n#include \"gtest/gtest.h\"\n#include \"test_fixture.hpp\"\n\n#include \"xframe/xcoordinate_expanded.hpp\"\n\nnamespace xf\n{\n    using slabel_type = std::vector<fstring>;\n    using ilabel_type = std::vector<int>;\n\n    TEST(xcoordinate_expanded, constructor)\n    {\n        auto c = make_test_coordinate();\n        using map_type = typename std::decay_t<decltype(c)>::map_type;\n        map_type m;\n        m[\"abscissa\"] = make_test_saxis3();\n\n        EXPECT_ANY_THROW(expand_dims(c, m));\n    }\n\n    template <class C>\n    inline xcoordinate_expanded<C> make_coordinate_expanded(const C& c)\n    {\n        using map_type = typename std::decay_t<C>::map_type;\n        map_type m;\n        m[\"new_dim\"] = make_test_saxis3();\n        return expand_dims(c, std::move(m));\n    }\n\n    TEST(xcoordinate_expanded, size)\n    {\n        auto c = make_test_coordinate();\n        auto cc = make_coordinate_expanded(c);\n\n        EXPECT_EQ(3u, cc.size());\n        EXPECT_FALSE(cc.empty());\n    }\n\n    TEST(xcoordinate_expanded, contains)\n    {\n        auto c = make_test_coordinate();\n        auto cc = make_coordinate_expanded(c);\n\n        EXPECT_TRUE(cc.contains(\"new_dim\"));\n        EXPECT_TRUE(cc.contains(\"ordinate\"));\n        EXPECT_TRUE(cc.contains(\"abscissa\"));\n        EXPECT_FALSE(cc.contains(\"unknown\"));\n\n        EXPECT_TRUE(cc.contains(\"new_dim\", \"a\"));\n        EXPECT_FALSE(cc.contains(\"new_dim\", \"e\"));\n        EXPECT_TRUE(cc.contains(\"ordinate\", 2));\n        EXPECT_TRUE(cc.contains(\"ordinate\", 4));\n        EXPECT_FALSE(cc.contains(\"ordinate\", 6));\n        EXPECT_TRUE(cc.contains(\"abscissa\", \"c\"));\n        EXPECT_FALSE(cc.contains(\"abscissa\", \"e\"));\n    }\n\n    TEST(xcoordinate_expanded, access)\n    {\n        auto c = make_test_coordinate();\n        auto cc = make_coordinate_expanded(c);\n\n        EXPECT_EQ(cc[\"new_dim\"][\"a\"], 0u);\n        EXPECT_EQ(cc[\"new_dim\"][\"b\"], 1u);\n        EXPECT_EQ(cc[\"new_dim\"][\"c\"], 2u);\n        EXPECT_EQ(cc[\"new_dim\"][\"d\"], 3u);\n        EXPECT_EQ(cc[\"ordinate\"][1], 0u);\n        EXPECT_EQ(cc[\"ordinate\"][2], 1u);\n        EXPECT_EQ(cc[\"ordinate\"][4], 2u);\n\n        EXPECT_EQ(cc[std::make_pair(\"new_dim\", fstring(\"a\"))], 0u);\n        EXPECT_EQ(cc[std::make_pair(\"new_dim\", fstring(\"b\"))], 1u);\n        EXPECT_EQ(cc[std::make_pair(\"new_dim\", fstring(\"c\"))], 2u);\n        EXPECT_EQ(cc[std::make_pair(\"new_dim\", fstring(\"d\"))], 3u);\n        EXPECT_EQ(cc[std::make_pair(\"ordinate\", 1)], 0u);\n        EXPECT_EQ(cc[std::make_pair(\"ordinate\", 2)], 1u);\n        EXPECT_EQ(cc[std::make_pair(\"ordinate\", 4)], 2u);\n    }\n\n    TEST(xcoordinate_expanded, iterator)\n    {\n        auto c = make_test_coordinate();\n        auto cc = make_coordinate_expanded(c);\n\n        auto iter = cc.begin();\n        EXPECT_EQ(iter->first, \"abscissa\");\n        ++iter;\n        EXPECT_EQ(iter->first, \"ordinate\");\n        ++iter;\n        EXPECT_EQ(iter->first, \"new_dim\");\n        ++iter;\n        EXPECT_EQ(iter, cc.end());\n        --iter;\n        EXPECT_EQ(iter->first, \"new_dim\");\n        --iter;\n        EXPECT_EQ(iter->first, \"ordinate\");\n        --iter;\n        EXPECT_EQ(iter->first, \"abscissa\");\n        EXPECT_EQ(iter, cc.begin());\n    }\n\n    TEST(xcoordinate_expanded, find)\n    {\n        auto c = make_test_coordinate();\n        auto cc = make_coordinate_expanded(c);\n\n        auto iter = cc.find(\"new_dim\");\n        EXPECT_EQ((iter->second)[\"a\"], 0u);\n        auto iter2 = cc.find(\"not_here\");\n        EXPECT_EQ(iter2, cc.end());\n    }\n\n    TEST(xcoordinate_expanded, key_iterator)\n    {\n        auto c = make_test_coordinate();\n        auto cc = make_coordinate_expanded(c);\n\n        auto iter = cc.key_begin();\n\n        EXPECT_EQ(*iter, \"abscissa\");\n        ++iter;\n        EXPECT_EQ(*iter, \"ordinate\");\n        ++iter;\n        EXPECT_EQ(*iter, \"new_dim\");\n        ++iter;\n        EXPECT_EQ(iter, cc.key_end());\n    }\n\n    TEST(xcoordinate_expanded, comparison)\n    {\n        auto c = make_test_coordinate();\n        auto cc = make_coordinate_expanded(c);\n\n        EXPECT_TRUE(cc == cc);\n        EXPECT_FALSE(cc != cc);\n\n        using map_type = typename std::decay_t<decltype(c)>::map_type;\n        map_type m;\n        m[\"new_dim\"] = saxis_type({\"a\", \"d\", \"e\", \"f\"});\n        auto cc2 = expand_dims(c, std::move(m));\n        EXPECT_FALSE(cc == cc2);\n        EXPECT_TRUE(cc != cc2);\n    }\n\n    TEST(xcoordinate_expanded, mixed_comparison)\n    {\n        auto c = make_test_coordinate();\n        auto cc = make_coordinate_expanded(c);\n        coordinate_type c2 = {{\"abscissa\", make_test_saxis()}, {\"ordinate\", make_test_iaxis()}, {\"new_dim\", make_test_saxis3()}};\n\n        using xf::operator<<;\n        EXPECT_NE(cc, c);\n        EXPECT_EQ(cc, c2);\n    }\n}\n"
  },
  {
    "path": "test/test_xcoordinate_view.cpp",
    "content": "/***************************************************************************\n* Copyright (c) Johan Mabille, Sylvain Corlay, Wolf Vollprecht and         *\n* Martin Renou                                                             *\n* Copyright (c) QuantStack                                                 *\n*                                                                          *\n* Distributed under the terms of the BSD 3-Clause License.                 *\n*                                                                          *\n* The full license is in the file LICENSE, distributed with this software. *\n****************************************************************************/\n\n#include <cstddef>\n#include <vector>\n#include \"gtest/gtest.h\"\n#include \"test_fixture_view.hpp\"\n\nnamespace xf\n{\n    TEST(xcoordinate_view, size)\n    {\n        auto c = make_test_view_coordinate();\n        auto cv = build_coordinate_view(c);\n\n        EXPECT_EQ(2u, cv.size());\n        EXPECT_FALSE(cv.empty());\n    }\n\n    TEST(xcoordinate_view, contains)\n    {\n        auto c = make_test_view_coordinate();\n        auto cv = build_coordinate_view(c);\n\n        EXPECT_TRUE(cv.contains(\"abscissa\"));\n        EXPECT_FALSE(cv.contains(\"humidity\"));\n    }\n\n    TEST(xcoordinate_view, access)\n    {\n        auto c = make_test_view_coordinate();\n        auto cv = build_coordinate_view(c);\n\n        EXPECT_EQ(c[\"abscissa\"][\"f\"], 3u);\n        EXPECT_EQ(c[\"abscissa\"][\"g\"], 4u);\n        EXPECT_EQ(c[\"abscissa\"][\"h\"], 5u);\n        EXPECT_EQ(c[\"abscissa\"][\"m\"], 6u);\n        EXPECT_EQ(c[\"abscissa\"][\"n\"], 7u);\n        EXPECT_EQ(c[\"ordinate\"][1], 0u);\n        EXPECT_EQ(c[\"ordinate\"][4], 2u);\n        EXPECT_EQ(c[\"ordinate\"][6], 4u);\n\n        EXPECT_EQ(c[std::make_pair(\"abscissa\", \"f\")], 3u);\n        EXPECT_EQ(c[std::make_pair(\"abscissa\", \"g\")], 4u);\n        EXPECT_EQ(c[std::make_pair(\"abscissa\", \"h\")], 5u);\n        EXPECT_EQ(c[std::make_pair(\"abscissa\", \"m\")], 6u);\n        EXPECT_EQ(c[std::make_pair(\"abscissa\", \"n\")], 7u);\n        EXPECT_EQ(c[std::make_pair(\"ordinate\", 1)], 0u);\n        EXPECT_EQ(c[std::make_pair(\"ordinate\", 4)], 2u);\n        EXPECT_EQ(c[std::make_pair(\"ordinate\", 6)], 4u);\n    }\n\n    TEST(xcoordinate_view, iterator)\n    {\n        auto c = make_test_view_coordinate();\n        auto cv = build_coordinate_view(c);\n\n        auto iter = cv.cbegin();\n        EXPECT_EQ((iter->second)[\"f\"], 3u);\n        ++iter;\n        EXPECT_EQ((iter->second)[1], 0u);\n        ++iter;\n        EXPECT_EQ(iter, cv.cend());\n    }\n\n    TEST(xcoordinate_view, key_iterator)\n    {\n        auto c = make_test_view_coordinate();\n        auto cv = build_coordinate_view(c);\n\n        auto iter = cv.key_begin();\n        EXPECT_EQ(*iter, \"abscissa\");\n        ++iter;\n        EXPECT_EQ(*iter, \"ordinate\");\n        ++iter;\n        EXPECT_EQ(iter, cv.key_end());\n    }\n\n    TEST(xcoordinate_view, broadcasting)\n    {\n        auto c = make_test_view_coordinate();\n        auto vc = build_coordinate_view(c);\n\n        auto c2 = coordinate<fstring>({{fstring(\"altitude\"), make_test_view_saxis()}});\n        xtrivial_broadcast res = c2.broadcast<join::inner>(vc);\n        EXPECT_TRUE(res.m_same_labels);\n        EXPECT_FALSE(res.m_same_dimensions);\n\n        const axis_variant& c2abscissa = c2[\"abscissa\"];\n        axis_variant vcabscissa = axis_variant(vc[\"abscissa\"]);\n        const axis_variant& c2ordinate = c2[\"ordinate\"];\n        axis_variant vcordinate = axis_variant(vc[\"ordinate\"]);\n        EXPECT_EQ(c2abscissa, vcabscissa);\n        EXPECT_EQ(c2ordinate, vcordinate);\n\n\n        auto c3 = c;\n        xtrivial_broadcast res2 = c3.broadcast<join::inner>(vc);\n        EXPECT_FALSE(res2.m_same_labels);\n        EXPECT_TRUE(res2.m_same_dimensions);\n        const axis_variant& c3abscissa = c3[\"abscissa\"];\n        const axis_variant& c3ordinate = c3[\"ordinate\"];\n        EXPECT_EQ(c3abscissa, vcabscissa);\n        EXPECT_EQ(c3ordinate, vcordinate);\n    }\n\n    TEST(xcoordinate_view, comparison)\n    {\n        // abscissa: { \"f\", \"g\", \"h\", \"m\", \"n\" }\n        // ordinate: { 1, 4, 6 }\n        auto c = make_test_view_coordinate();\n        auto vc = build_coordinate_view(c);\n\n        coordinate_type co =\n        {\n            { \"abscissa\", xf::axis({ \"f\", \"g\", \"h\", \"m\", \"n\" }) },\n            { \"ordinate\", xf::axis({ 1, 4, 6}) }\n        };\n\n        EXPECT_TRUE(vc == co);\n        EXPECT_TRUE(co == vc);\n\n        EXPECT_TRUE(vc != c);\n        EXPECT_TRUE(c != vc);\n    }\n}\n"
  },
  {
    "path": "test/test_xdimension.cpp",
    "content": "/***************************************************************************\n* Copyright (c) Johan Mabille, Sylvain Corlay, Wolf Vollprecht and         *\n* Martin Renou                                                             *\n* Copyright (c) QuantStack                                                 *\n*                                                                          *\n* Distributed under the terms of the BSD 3-Clause License.                 *\n*                                                                          *\n* The full license is in the file LICENSE, distributed with this software. *\n****************************************************************************/\n\n#include \"gtest/gtest.h\"\n#include \"xframe/xdimension.hpp\"\n#include \"xtl/xbasic_fixed_string.hpp\"\n\nnamespace xf\n{\n    using label_type = std::vector<fstring>;\n    using dimension_type = xdimension<fstring, std::size_t>;\n    \n    TEST(xdimension, broadcast)\n    {\n        dimension_type d1 = { \"a\", \"b\", \"d\", \"e\" };\n        dimension_type d2 = { \"d\", \"e\" };\n        dimension_type d3 = { \"h\", \"c\", \"a\", \"b\", \"d\", \"e\" };\n        dimension_type d4 = { \"h\", \"b\", \"c\", \"e\" };\n\n        dimension_type res1;\n        bool t1 = broadcast_dimensions(res1, d1, d2);\n        EXPECT_TRUE(t1);\n        EXPECT_EQ(res1.size(), 4u);\n        EXPECT_EQ(res1[\"a\"], 0u);\n        EXPECT_EQ(res1[\"b\"], 1u);\n        EXPECT_EQ(res1[\"d\"], 2u);\n        EXPECT_EQ(res1[\"e\"], 3u);\n\n        dimension_type res2;\n        bool t2 = broadcast_dimensions(res2, d1, d3);\n        EXPECT_TRUE(t2);\n        EXPECT_EQ(res2.size(), 6u);\n        EXPECT_EQ(res2[\"h\"], 0u);\n        EXPECT_EQ(res2[\"c\"], 1u);\n        EXPECT_EQ(res2[\"a\"], 2u);\n        EXPECT_EQ(res2[\"b\"], 3u);\n        EXPECT_EQ(res2[\"d\"], 4u);\n        EXPECT_EQ(res2[\"e\"], 5u);\n\n        dimension_type res3;\n        bool t3 = broadcast_dimensions(res3, d1, d4);\n        EXPECT_FALSE(t3);\n        EXPECT_EQ(res3.size(), 6u);\n        EXPECT_EQ(res3[\"h\"], 0u);\n        EXPECT_EQ(res3[\"c\"], 1u);\n        EXPECT_EQ(res3[\"a\"], 2u);\n        EXPECT_EQ(res3[\"b\"], 3u);\n        EXPECT_EQ(res3[\"d\"], 4u);\n        EXPECT_EQ(res3[\"e\"], 5u);\n    }\n\n    TEST(xdimension, builder)\n    {\n        dimension_type d1 = { \"a\", \"b\", \"c\" };\n        auto d2 = dimension({ \"a\", \"b\", \"c\" });\n\n        EXPECT_EQ(d1, d2);\n    }\n}\n\n"
  },
  {
    "path": "test/test_xdynamic_variable.cpp",
    "content": "/***************************************************************************\n* Copyright (c) Johan Mabille, Sylvain Corlay, Wolf Vollprecht and         *\n* Martin Renou                                                             *\n* Copyright (c) QuantStack                                                 *\n*                                                                          *\n* Distributed under the terms of the BSD 3-Clause License.                 *\n*                                                                          *\n* The full license is in the file LICENSE, distributed with this software. *\n****************************************************************************/\n\n#include \"gtest/gtest.h\"\n#include \"test_fixture.hpp\"\n#include \"xframe/xdynamic_variable.hpp\"\n\nnamespace xf\n{\n    inline xtl::xoptional<double&, bool&> opt_cast(xtl::any arg)\n    {\n        return xtl::any_cast<xtl::xoptional<double&, bool&>>(arg);\n    }\n\n    inline xtl::xoptional<const double&, const bool&> const_opt_cast(xtl::any arg)\n    {\n        return xtl::any_cast<xtl::xoptional<const double&, const bool&>>(arg);\n    }\n\n    TEST(xdynamic_variable, size)\n    {\n        auto v = make_test_variable();\n        auto dv = make_dynamic(v);\n        EXPECT_EQ(dv.size(), v.size());\n    }\n\n    TEST(xdynamic_variable, dimension)\n    {\n        auto v = make_test_variable();\n        auto dv = make_dynamic(v);\n        EXPECT_EQ(dv.dimension(), v.dimension());\n    }\n\n    TEST(xdynamic_variable, dimension_labels)\n    {\n        auto v = make_test_variable();\n        auto dv = make_dynamic(v);\n        EXPECT_EQ(dv.dimension_labels(), v.dimension_labels());\n    }\n\n    TEST(xdynamic_variable, coordinates)\n    {\n        auto v = make_test_variable();\n        auto dv = make_dynamic(v);\n        EXPECT_EQ(dv.coordinates(), v.coordinates());\n    }\n\n    TEST(xdynamic_variable, dimension_mapping)\n    {\n        auto v = make_test_variable();\n        auto dv = make_dynamic(v);\n        EXPECT_EQ(dv.dimension_mapping(), v.dimension_mapping());\n    }\n\n    TEST(xdynamic_variable, broadcast_coordinates)\n    {\n        auto coord_res = make_merge_coordinate();\n        auto v = make_test_variable2();\n        auto dv = make_dynamic(v);\n\n        auto c = make_test_coordinate();\n        auto res = dv.template broadcast_coordinates<join::outer>(c);\n\n        EXPECT_FALSE(res.m_same_dimensions);\n        EXPECT_FALSE(res.m_same_labels);\n        EXPECT_EQ(c, coord_res);\n\n        auto coord_res2 = make_intersect_coordinate();\n        auto c2 = make_test_coordinate();\n        auto res2 = dv.template broadcast_coordinates<join::inner>(c2);\n\n        EXPECT_FALSE(res2.m_same_dimensions);\n        EXPECT_FALSE(res2.m_same_labels);\n        EXPECT_EQ(c2, coord_res2);\n    }\n\n    TEST(xdynamic_variable, broadcast_dimensions)\n    {\n        auto v = make_test_variable2();\n        auto dv = make_dynamic(v);\n\n        auto c = dimension_type({ \"abscissa\", \"ordinate\" });\n        bool res = dv.broadcast_dimensions(c);\n        EXPECT_EQ(c, dv.dimension_mapping());\n    }\n\n    TEST(xdynamic_variable, shape)\n    {\n        auto v = make_test_variable();\n        auto dv = make_dynamic<double>(v);\n\n        auto shape = dv.shape();\n        std::decay_t<decltype(dv.shape())> expected = { 3, 3 };\n        EXPECT_EQ(shape, expected);\n    }\n\n    TEST(xdynamic_variable, access)\n    {\n        auto v = make_test_variable();\n        auto dv = make_dynamic(v);\n\n        auto t00 = dv(0, 0);\n        auto t01 = dv(0, 1);\n        auto t02 = dv(0, 2);\n        auto t10 = dv(1, 0);\n        auto t11 = dv(1, 1);\n        auto t12 = dv(1, 2);\n        auto t20 = dv(2, 0);\n        auto t21 = dv(2, 1);\n        auto t22 = dv(2, 2);\n\n        EXPECT_EQ(opt_cast(t00), v(0, 0));\n        EXPECT_EQ(opt_cast(t01), v(0, 1));\n        EXPECT_EQ(opt_cast(t02), v(0, 2));\n        EXPECT_EQ(opt_cast(t10), v(1, 0));\n        EXPECT_EQ(opt_cast(t11), v(1, 1));\n        EXPECT_EQ(opt_cast(t12), v(1, 2));\n        EXPECT_EQ(opt_cast(t20), v(2, 0));\n        EXPECT_EQ(opt_cast(t21), v(2, 1));\n        EXPECT_EQ(opt_cast(t22), v(2, 2));\n    }\n\n    TEST(xdynamic_variable, element)\n    {\n        auto v = make_test_variable();\n        auto dv = make_dynamic(v);\n\n        auto t00 = dv.element({ 0, 0 });\n        auto t01 = dv.element({ 0, 1 });\n        auto t02 = dv.element({ 0, 2 });\n        auto t10 = dv.element({ 1, 0 });\n        auto t11 = dv.element({ 1, 1 });\n        auto t12 = dv.element({ 1, 2 });\n        auto t20 = dv.element({ 2, 0 });\n        auto t21 = dv.element({ 2, 1 });\n        auto t22 = dv.element({ 2, 2 });\n\n        EXPECT_EQ(opt_cast(t00), v(0, 0));\n        EXPECT_EQ(opt_cast(t01), v(0, 1));\n        EXPECT_EQ(opt_cast(t02), v(0, 2));\n        EXPECT_EQ(opt_cast(t10), v(1, 0));\n        EXPECT_EQ(opt_cast(t11), v(1, 1));\n        EXPECT_EQ(opt_cast(t12), v(1, 2));\n        EXPECT_EQ(opt_cast(t20), v(2, 0));\n        EXPECT_EQ(opt_cast(t21), v(2, 1));\n        EXPECT_EQ(opt_cast(t22), v(2, 2));\n    }\n\n    TEST(xdynamic_variable, select_inner)\n    {\n        auto v = make_test_variable();\n        auto dv = make_dynamic(v);\n\n        auto t00 = dv.select({ { \"abscissa\", \"a\" },{ \"ordinate\", 1 } });\n        auto t01 = dv.select({ { \"abscissa\", \"a\" },{ \"ordinate\", 2 } });\n        auto t02 = dv.select({ { \"abscissa\", \"a\" },{ \"ordinate\", 4 } });\n        auto t10 = dv.select({ { \"abscissa\", \"c\" },{ \"ordinate\", 1 } });\n        auto t11 = dv.select({ { \"abscissa\", \"c\" },{ \"ordinate\", 2 } });\n        auto t12 = dv.select({ { \"abscissa\", \"c\" },{ \"ordinate\", 4 } });\n        auto t20 = dv.select({ { \"abscissa\", \"d\" },{ \"ordinate\", 1 } });\n        auto t21 = dv.select({ { \"abscissa\", \"d\" },{ \"ordinate\", 2 } });\n        auto t22 = dv.select({ { \"abscissa\", \"d\" },{ \"ordinate\", 4 } });\n\n        EXPECT_EQ(opt_cast(t00), v(0, 0));\n        EXPECT_EQ(opt_cast(t01), v(0, 1));\n        EXPECT_EQ(opt_cast(t02), v(0, 2));\n        EXPECT_EQ(opt_cast(t10), v(1, 0));\n        EXPECT_EQ(opt_cast(t11), v(1, 1));\n        EXPECT_EQ(opt_cast(t12), v(1, 2));\n        EXPECT_EQ(opt_cast(t20), v(2, 0));\n        EXPECT_EQ(opt_cast(t21), v(2, 1));\n        EXPECT_EQ(opt_cast(t22), v(2, 2));\n    }\n\n    TEST(xdynamic_variable, select_outer)\n    {\n        const auto v = make_test_variable();\n        auto dv = make_dynamic(v);\n\n        auto t00 = dv.select<join::outer>({ { \"abscissa\", \"a\" },{ \"ordinate\", 1 } });\n        auto t01 = dv.select<join::outer>({ { \"abscissa\", \"a\" },{ \"ordinate\", 2 } });\n        auto t02 = dv.select<join::outer>({ { \"abscissa\", \"a\" },{ \"ordinate\", 4 } });\n        auto t10 = dv.select<join::outer>({ { \"abscissa\", \"c\" },{ \"ordinate\", 1 } });\n        auto t11 = dv.select<join::outer>({ { \"abscissa\", \"c\" },{ \"ordinate\", 2 } });\n        auto t12 = dv.select<join::outer>({ { \"abscissa\", \"c\" },{ \"ordinate\", 4 } });\n        auto t20 = dv.select<join::outer>({ { \"abscissa\", \"d\" },{ \"ordinate\", 1 } });\n        auto t21 = dv.select<join::outer>({ { \"abscissa\", \"d\" },{ \"ordinate\", 2 } });\n        auto t22 = dv.select<join::outer>({ { \"abscissa\", \"d\" },{ \"ordinate\", 4 } });\n\n        EXPECT_EQ(const_opt_cast(t00), v(0, 0));\n        EXPECT_EQ(const_opt_cast(t01), v(0, 1));\n        EXPECT_EQ(const_opt_cast(t02), v(0, 2));\n        EXPECT_EQ(const_opt_cast(t10), v(1, 0));\n        EXPECT_EQ(const_opt_cast(t11), v(1, 1));\n        EXPECT_EQ(const_opt_cast(t12), v(1, 2));\n        EXPECT_EQ(const_opt_cast(t20), v(2, 0));\n        EXPECT_EQ(const_opt_cast(t21), v(2, 1));\n        EXPECT_EQ(const_opt_cast(t22), v(2, 2));\n\n        auto t100 = dv.select<join::outer>({ { \"abscissa\", \"a\" },{ \"ordinate\", 1 },{ \"altitude\", 1 } });\n        EXPECT_EQ(const_opt_cast(t100), const_opt_cast(t00));\n\n        auto mis = dv.select<join::outer>({ { \"abscissa\", \"e\" },{ \"ordinate\", 1 } });\n        EXPECT_EQ(const_opt_cast(mis), v.missing());\n    }\n\n    TEST(xdynamic_variable, iselect)\n    {\n        auto v = make_test_variable();\n        auto dv = make_dynamic(v);\n\n        auto t00 = dv.iselect({ { \"abscissa\", 0 },{ \"ordinate\", 0 } });\n        auto t01 = dv.iselect({ { \"abscissa\", 0 },{ \"ordinate\", 1 } });\n        auto t02 = dv.iselect({ { \"abscissa\", 0 },{ \"ordinate\", 2 } });\n        auto t10 = dv.iselect({ { \"abscissa\", 1 },{ \"ordinate\", 0 } });\n        auto t11 = dv.iselect({ { \"abscissa\", 1 },{ \"ordinate\", 1 } });\n        auto t12 = dv.iselect({ { \"abscissa\", 1 },{ \"ordinate\", 2 } });\n        auto t20 = dv.iselect({ { \"abscissa\", 2 },{ \"ordinate\", 0 } });\n        auto t21 = dv.iselect({ { \"abscissa\", 2 },{ \"ordinate\", 1 } });\n        auto t22 = dv.iselect({ { \"abscissa\", 2 },{ \"ordinate\", 2 } });\n\n        EXPECT_EQ(opt_cast(t00), v(0, 0));\n        EXPECT_EQ(opt_cast(t01), v(0, 1));\n        EXPECT_EQ(opt_cast(t02), v(0, 2));\n        EXPECT_EQ(opt_cast(t10), v(1, 0));\n        EXPECT_EQ(opt_cast(t11), v(1, 1));\n        EXPECT_EQ(opt_cast(t12), v(1, 2));\n        EXPECT_EQ(opt_cast(t20), v(2, 0));\n        EXPECT_EQ(opt_cast(t21), v(2, 1));\n        EXPECT_EQ(opt_cast(t22), v(2, 2));\n    }\n\n    TEST(xdynamic_variable, locate)\n    {\n        auto v = make_test_variable();\n        auto dv = make_dynamic(v);\n\n        auto t00 = dv.locate(\"a\", 1);\n        auto t01 = dv.locate(\"a\", 2);\n        auto t02 = dv.locate(\"a\", 4);\n        auto t10 = dv.locate(\"c\", 1);\n        auto t11 = dv.locate(\"c\", 2);\n        auto t12 = dv.locate(\"c\", 4);\n        auto t20 = dv.locate(\"d\", 1);\n        auto t21 = dv.locate(\"d\", 2);\n        auto t22 = dv.locate(\"d\", 4);\n\n        EXPECT_EQ(opt_cast(t00), v(0, 0));\n        EXPECT_EQ(opt_cast(t01), v(0, 1));\n        EXPECT_EQ(opt_cast(t02), v(0, 2));\n        EXPECT_EQ(opt_cast(t10), v(1, 0));\n        EXPECT_EQ(opt_cast(t11), v(1, 1));\n        EXPECT_EQ(opt_cast(t12), v(1, 2));\n        EXPECT_EQ(opt_cast(t20), v(2, 0));\n        EXPECT_EQ(opt_cast(t21), v(2, 1));\n        EXPECT_EQ(opt_cast(t22), v(2, 2));\n    }\n\n    TEST(xdynamic_variable, locate_element)\n    {\n        auto v = make_test_variable();\n        auto dv = make_dynamic(v);\n\n        auto t00 = dv.locate_element({ \"a\", 1 });\n        auto t01 = dv.locate_element({ \"a\", 2 });\n        auto t02 = dv.locate_element({ \"a\", 4 });\n        auto t10 = dv.locate_element({ \"c\", 1 });\n        auto t11 = dv.locate_element({ \"c\", 2 });\n        auto t12 = dv.locate_element({ \"c\", 4 });\n        auto t20 = dv.locate_element({ \"d\", 1 });\n        auto t21 = dv.locate_element({ \"d\", 2 });\n        auto t22 = dv.locate_element({ \"d\", 4 });\n\n        EXPECT_EQ(opt_cast(t00), v(0, 0));\n        EXPECT_EQ(opt_cast(t01), v(0, 1));\n        EXPECT_EQ(opt_cast(t02), v(0, 2));\n        EXPECT_EQ(opt_cast(t10), v(1, 0));\n        EXPECT_EQ(opt_cast(t11), v(1, 1));\n        EXPECT_EQ(opt_cast(t12), v(1, 2));\n        EXPECT_EQ(opt_cast(t20), v(2, 0));\n        EXPECT_EQ(opt_cast(t21), v(2, 1));\n        EXPECT_EQ(opt_cast(t22), v(2, 2));\n    }\n\n    template <class V>\n    inline xtl::xoptional<double&, bool&> variant_get(V& v)\n    {\n        return xtl::get<xtl::xoptional<double&, bool&>>(v);\n    }\n\n    template <class V>\n    inline xtl::xoptional<const double&, const bool&> const_variant_get(V& v)\n    {\n        return xtl::get<xtl::xoptional<const double&, const bool&>>(v);\n    }\n\n    TEST(xdynamic_variable, make_variant)\n    {\n        auto v = make_test_variable();\n        auto dv = make_dynamic<xtl::variant<double, int>>(v);\n        \n        auto ta00 = dv(0, 0);\n        EXPECT_EQ(variant_get(ta00), v(0, 0));\n\n        auto t00 = dv.element({ 0, 0 });\n        EXPECT_EQ(variant_get(t00), v(0, 0));\n\n        auto ts00 = dv.select({ { \"abscissa\", \"a\" },{ \"ordinate\", 1 } });\n        EXPECT_EQ(variant_get(ts00), v(0, 0));\n\n        auto tsc00 = dv.select<join::outer>({ { \"abscissa\", \"a\" },{ \"ordinate\", 1 } });\n        EXPECT_EQ(const_variant_get(tsc00), v(0, 0));\n\n        auto tis00 = dv.iselect({ { \"abscissa\", 0 },{ \"ordinate\", 0 } });\n        EXPECT_EQ(variant_get(tis00), v(0, 0));\n\n        auto tl00 = dv.locate(\"a\", 1);\n        EXPECT_EQ(variant_get(tl00), v(0, 0));\n\n        auto tle00 = dv.locate_element({ \"a\", 1 });\n        EXPECT_EQ(variant_get(tle00), v(0, 0));\n    }\n\n    TEST(xdynamic_variable, make_simple)\n    {\n        auto v = make_test_variable();\n        auto dv = make_dynamic<double>(v);\n\n        auto ta00 = dv(0, 0);\n        EXPECT_EQ(ta00, v(0, 0));\n\n        auto t00 = dv.element({ 0, 0 });\n        EXPECT_EQ(t00, v(0, 0));\n\n        auto ts00 = dv.select({ { \"abscissa\", \"a\" },{ \"ordinate\", 1 } });\n        EXPECT_EQ(ts00, v(0, 0));\n\n        auto tsc00 = dv.select<join::outer>({ { \"abscissa\", \"a\" },{ \"ordinate\", 1 } });\n        EXPECT_EQ(tsc00, v(0, 0));\n\n        auto tis00 = dv.iselect({ { \"abscissa\", 0 },{ \"ordinate\", 0 } });\n        EXPECT_EQ(tis00, v(0, 0));\n\n        auto tl00 = dv.locate(\"a\", 1);\n        EXPECT_EQ(tl00, v(0, 0));\n\n        auto tle00 = dv.locate_element({ \"a\", 1 });\n        EXPECT_EQ(tle00, v(0, 0));\n    }\n\n    TEST(xdynamic_variable, print)\n    {\n        auto v = make_test_variable();\n        auto dv = make_dynamic<double>(v);\n\n        std::string expected =\nR\"variable({{  1,   2, N/A},\n {N/A,   5,   6},\n {  7,   8,   9}}\nCoordinates:\nabscissa: (a, c, d, )\nordinate: (1, 2, 4, )\n)variable\";\n\n        std::ostringstream oss;\n        oss << dv;\n        std::string res = oss.str();\n        EXPECT_EQ(res, expected);\n    }\n}\n"
  },
  {
    "path": "test/test_xexpand_dims_view.cpp",
    "content": "/***************************************************************************\n* Copyright (c) Johan Mabille, Sylvain Corlay, Wolf Vollprecht and         *\n* Martin Renou                                                             *\n* Copyright (c) QuantStack                                                 *\n*                                                                          *\n* Distributed under the terms of the BSD 3-Clause License.                 *\n*                                                                          *\n* The full license is in the file LICENSE, distributed with this software. *\n****************************************************************************/\n\n#include <vector>\n\n#include \"gtest/gtest.h\"\n\n#include \"test_fixture.hpp\"\n\n#include \"xframe/xexpand_dims_view.hpp\"\n\nnamespace xf\n{\n    TEST(xexpand_dims, ctor)\n    {\n        auto var = make_test_variable();\n\n        auto res1 = expand_dims(var, {\"new_dim\"});\n        auto res2 = expand_dims(var, {\"new_dim\", \"new_dim2\"});\n        auto res3 = expand_dims(var, {{\"new_dim\", 0}, {\"new_dim2\", 2}});\n    }\n\n    TEST(xexpand_dims, size)\n    {\n        auto var = make_test_variable();\n\n        auto res = expand_dims(var, {\"new_dim\", \"new_dim2\"});\n\n        EXPECT_EQ(var.size(), res.size());\n    }\n\n    TEST(xexpand_dims, dimension)\n    {\n        auto var = make_test_variable();\n\n        auto res = expand_dims(var, {\"new_dim\", \"new_dim2\"});\n\n        EXPECT_EQ(res.dimension(), std::size_t(4));\n    }\n\n    TEST(xexpand_dims, dimension_labels)\n    {\n        auto var = make_test_variable();\n\n        auto res = expand_dims(var, {\"new_dim\"});\n        auto expected_dim_mapping = std::vector<fstring>({\"new_dim\", \"abscissa\", \"ordinate\"});\n        EXPECT_EQ(res.dimension_labels(), expected_dim_mapping);\n\n        auto res1 = expand_dims(var, {\"new_dim\", \"new_dim2\"});\n        expected_dim_mapping = {\"new_dim\", \"new_dim2\", \"abscissa\", \"ordinate\"};\n        EXPECT_EQ(res1.dimension_labels(), expected_dim_mapping);\n\n        auto res2 = expand_dims(var, {{\"new_dim\", 1}, {\"new_dim2\", 2}});\n        expected_dim_mapping = {\"abscissa\", \"new_dim\", \"new_dim2\", \"ordinate\"};\n        EXPECT_EQ(res2.dimension_labels(), expected_dim_mapping);\n\n        auto res3 = expand_dims(var, {{\"new_dim\", 2}});\n        expected_dim_mapping = {\"abscissa\", \"ordinate\", \"new_dim\"};\n        EXPECT_EQ(res3.dimension_labels(), expected_dim_mapping);\n    }\n\n    TEST(xexpand_dims, coordinates)\n    {\n        auto var = make_test_variable();\n\n        auto res = expand_dims(var, {\"new_dim\"});\n        const auto& coords = res.coordinates();\n        EXPECT_NE(coords.find(\"new_dim\"), coords.cend());\n        EXPECT_NE(coords.find(\"abscissa\"), coords.cend());\n        EXPECT_NE(coords.find(\"ordinate\"), coords.cend());\n        EXPECT_EQ(coords.size(), std::size_t(3));\n        EXPECT_EQ(coords.find(\"new_dim\")->second.size(), std::size_t(1));\n        EXPECT_EQ(coords.find(\"new_dim\")->second[0], std::size_t(0));\n    }\n\n    TEST(xexpand_dims, dimension_mapping)\n    {\n        auto var = make_test_variable();\n\n        auto res = expand_dims(var, {\"new_dim\"});\n        auto expected_dim_mapping = xdimension<fstring>({\"new_dim\", \"abscissa\", \"ordinate\"});\n        EXPECT_EQ(res.dimension_mapping(), expected_dim_mapping);\n\n        auto res1 = expand_dims(var, {\"new_dim\", \"new_dim2\"});\n        auto expected_dim_mapping1 = xdimension<fstring>({\"new_dim\", \"new_dim2\", \"abscissa\", \"ordinate\"});\n        EXPECT_EQ(res1.dimension_mapping(), expected_dim_mapping1);\n\n        auto res2 = expand_dims(var, {{\"new_dim\", 1}, {\"new_dim2\", 2}});\n        auto expected_dim_mapping2 = xdimension<fstring>({\"abscissa\", \"new_dim\", \"new_dim2\", \"ordinate\"});\n        EXPECT_EQ(res2.dimension_mapping(), expected_dim_mapping2);\n\n        auto res3 = expand_dims(var, {{\"new_dim\", 2}});\n        auto expected_dim_mapping3 = xdimension<fstring>({\"abscissa\", \"ordinate\", \"new_dim\"});\n        EXPECT_EQ(res3.dimension_mapping(), expected_dim_mapping3);\n    }\n\n    TEST(xexpand_dims, shape)\n    {\n        auto var = make_test_variable();\n\n        auto res = expand_dims(var, {\"new_dim\", \"new_dim2\"});\n        std::vector<std::size_t> expected_shape = {1, 1, 3, 3};\n\n        EXPECT_EQ(res.shape(), expected_shape);\n    }\n\n    TEST(xexpand_dims, data)\n    {\n        auto var = make_test_variable();\n\n        auto res = expand_dims(var, {\"new_dim\"});\n        const auto& expanded_data_view = res.data();\n        std::vector<std::size_t> expected_shape = {1, 3, 3};\n\n        EXPECT_EQ(expanded_data_view.dimension(), std::size_t(3));\n        EXPECT_EQ(expanded_data_view.shape(), expected_shape);\n\n        auto res1 = expand_dims(var, {\"new_dim\", \"new_dim2\"});\n        const auto& expanded_data_view1 = res1.data();\n        expected_shape = {1, 1, 3, 3};\n\n        EXPECT_EQ(expanded_data_view1.dimension(), std::size_t(4));\n        EXPECT_EQ(expanded_data_view1.shape(), expected_shape);\n\n        auto res2 = expand_dims(var, {{\"new_dim\", 1}, {\"new_dim2\", 2}});\n        const auto& expanded_data_view2 = res2.data();\n        expected_shape = {3, 1, 1, 3};\n\n        EXPECT_EQ(expanded_data_view2.dimension(), std::size_t(4));\n        EXPECT_EQ(expanded_data_view2.shape(), expected_shape);\n\n        auto res3 = expand_dims(var, {{\"new_dim\", 2}});\n        const auto& expanded_data_view3 = res3.data();\n        expected_shape = {3, 3, 1};\n\n        EXPECT_EQ(expanded_data_view3.dimension(), std::size_t(3));\n        EXPECT_EQ(expanded_data_view3.shape(), expected_shape);\n    }\n\n    TEST(xexpand_dims, access)\n    {\n        auto var = make_test_variable();\n\n        auto res = expand_dims(var, {\"new_dim\"});\n        EXPECT_EQ(res(0, 2, 0), 7.0);\n        EXPECT_EQ(res(0, 2, 1), 8.0);\n        EXPECT_EQ(res(0, 2, 2), 9.0);\n\n        auto res1 = expand_dims(var, {\"new_dim\", \"new_dim2\"});\n        EXPECT_EQ(res1(0, 0, 2, 0), 7.0);\n        EXPECT_EQ(res1(0, 0, 2, 1), 8.0);\n        EXPECT_EQ(res1(0, 0, 2, 2), 9.0);\n\n        auto res2 = expand_dims(var, {{\"new_dim\", 1}, {\"new_dim2\", 2}});\n        EXPECT_EQ(res2(2, 0, 0, 0), 7.0);\n        EXPECT_EQ(res2(2, 0, 0, 1), 8.0);\n        EXPECT_EQ(res2(2, 0, 0, 2), 9.0);\n\n        auto res3 = expand_dims(var, {{\"new_dim\", 2}});\n        EXPECT_EQ(res3(2, 0, 0), 7.0);\n        EXPECT_EQ(res3(2, 1, 0), 8.0);\n        EXPECT_EQ(res3(2, 2, 0), 9.0);\n    }\n\n    TEST(xexpand_dims, element)\n    {\n        auto var = make_test_variable();\n\n        auto res = expand_dims(var, {\"new_dim\"});\n        EXPECT_EQ(res.element({0, 2, 0}), 7.0);\n        EXPECT_EQ(res.element({0, 2, 1}), 8.0);\n        EXPECT_EQ(res.element({0, 2, 2}), 9.0);\n\n        auto res1 = expand_dims(var, {\"new_dim\", \"new_dim2\"});\n        EXPECT_EQ(res1.element({0, 0, 2, 0}), 7.0);\n        EXPECT_EQ(res1.element({0, 0, 2, 1}), 8.0);\n        EXPECT_EQ(res1.element({0, 0, 2, 2}), 9.0);\n\n        auto res2 = expand_dims(var, {{\"new_dim\", 1}, {\"new_dim2\", 2}});\n        EXPECT_EQ(res2.element({2, 0, 0, 0}), 7.0);\n        EXPECT_EQ(res2.element({2, 0, 0, 1}), 8.0);\n        EXPECT_EQ(res2.element({2, 0, 0, 2}), 9.0);\n\n        auto res3 = expand_dims(var, {{\"new_dim\", 2}});\n        EXPECT_EQ(res3.element({2, 0, 0}), 7.0);\n        EXPECT_EQ(res3.element({2, 1, 0}), 8.0);\n        EXPECT_EQ(res3.element({2, 2, 0}), 9.0);\n    }\n\n    TEST(xexpand_dims, locate)\n    {\n        auto var = make_test_variable();\n\n        auto res = expand_dims(var, {\"new_dim\"});\n        EXPECT_EQ(res.locate(0, \"d\", 1), 7.0);\n        EXPECT_EQ(res.locate(0, \"d\", 2), 8.0);\n        EXPECT_EQ(res.locate(0, \"d\", 4), 9.0);\n\n        auto res1 = expand_dims(var, {\"new_dim\", \"new_dim2\"});\n        EXPECT_EQ(res1.locate(0, 0, \"d\", 1), 7.0);\n        EXPECT_EQ(res1.locate(0, 0, \"d\", 2), 8.0);\n        EXPECT_EQ(res1.locate(0, 0, \"d\", 4), 9.0);\n\n        auto res2 = expand_dims(var, {{\"new_dim\", 1}, {\"new_dim2\", 2}});\n        EXPECT_EQ(res2.locate(\"d\", 0, 0, 1), 7.0);\n        EXPECT_EQ(res2.locate(\"d\", 0, 0, 2), 8.0);\n        EXPECT_EQ(res2.locate(\"d\", 0, 0, 4), 9.0);\n\n        auto res3 = expand_dims(var, {{\"new_dim\", 2}});\n        EXPECT_EQ(res3.locate(\"d\", 1, 0), 7.0);\n        EXPECT_EQ(res3.locate(\"d\", 2, 0), 8.0);\n        EXPECT_EQ(res3.locate(\"d\", 4, 0), 9.0);\n    }\n\n    TEST(xexpand_dims, iselect)\n    {\n        auto var = make_test_variable();\n\n        auto res = expand_dims(var, {{\"new_dim\", 2}});\n        EXPECT_EQ(res.iselect({{\"abscissa\", 2}, {\"ordinate\", 0}}), 7.0);\n        EXPECT_EQ(res.iselect({{\"new_dim\", 0}, {\"abscissa\", 2}, {\"ordinate\", 1}}), 8.0);\n        EXPECT_EQ(res.iselect({{\"new_dim\", 0}, {\"abscissa\", 2}, {\"ordinate\", 2}}), 9.0);\n\n        auto res1 = expand_dims(var, {\"new_dim\", \"new_dim2\"});\n        EXPECT_EQ(res1.iselect({{\"abscissa\", 2}, {\"ordinate\", 0}}), 7.0);\n        EXPECT_EQ(res1.iselect({{\"new_dim2\", 0}, {\"abscissa\", 2}, {\"ordinate\", 1}}), 8.0);\n        EXPECT_EQ(res1.iselect({{\"new_dim\", 0}, {\"new_dim2\", 0}, {\"abscissa\", 2}, {\"ordinate\", 2}}), 9.0);\n    }\n\n    TEST(xexpand_dims, select)\n    {\n        auto var = make_test_variable();\n        auto missing = xtl::missing<double>();\n\n        auto res = expand_dims(var, {{\"new_dim\", 2}});\n        EXPECT_EQ(res.select({{\"abscissa\", \"d\"}, {\"ordinate\", 1}}), 7.0);\n        EXPECT_EQ(res.select({{\"new_dim\", 0}, {\"abscissa\", \"d\"}, {\"ordinate\", 2}}), 8.0);\n        EXPECT_EQ(res.select({{\"new_dim\", 0}, {\"abscissa\", \"d\"}, {\"ordinate\", 4}}), 9.0);\n\n        auto res1 = expand_dims(var, {\"new_dim\", \"new_dim2\"});\n        EXPECT_EQ(res1.select({{\"abscissa\", \"d\"}, {\"ordinate\", 1}}), 7.0);\n        EXPECT_EQ(res1.select({{\"new_dim2\", 0}, {\"abscissa\", \"d\"}, {\"ordinate\", 2}}), 8.0);\n        EXPECT_EQ(res1.select({{\"new_dim\", 0}, {\"new_dim2\", 0}, {\"abscissa\", \"d\"}, {\"ordinate\", 4}}), 9.0);\n        EXPECT_ANY_THROW(res1.select({{\"new_dim\", 2}, {\"new_dim2\", 0}, {\"abscissa\", \"d\"}, {\"ordinate\", 4}}));\n        EXPECT_EQ(res1.select<join::outer>({{\"new_dim\", 2}, {\"new_dim2\", 0}, {\"abscissa\", \"d\"}, {\"ordinate\", 4}}), missing);\n    }\n}\n"
  },
  {
    "path": "test/test_xframe_utils.cpp",
    "content": "/***************************************************************************\n* Copyright (c) Johan Mabille, Sylvain Corlay, Wolf Vollprecht and         *\n* Martin Renou                                                             *\n* Copyright (c) QuantStack                                                 *\n*                                                                          *\n* Distributed under the terms of the BSD 3-Clause License.                 *\n*                                                                          *\n* The full license is in the file LICENSE, distributed with this software. *\n****************************************************************************/\n\n#include \"gtest/gtest.h\"\n#include \"xframe/xframe_utils.hpp\"\n\n#include <vector>\n\nnamespace xf\n{\n    TEST(xframe_utils, merge_to)\n    {\n        std::vector<int> v1 = { 1, 3, 4, 5, 7, 9, 10 };\n        std::vector<int> v2 = { 1, 2, 4, 5, 6, 10, 11 };\n        std::vector<int> v3 = { 4, 5, 8, 10 };\n        std::vector<int> vres = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };\n\n        bool res1 = merge_to(v1, v2, v3);\n        EXPECT_EQ(vres, v1);\n        EXPECT_FALSE(res1);\n\n        bool res2 = merge_to(vres, v1);\n        EXPECT_EQ(vres, v1);\n        EXPECT_TRUE(res2);\n\n        std::vector<int> v4 = {};\n        bool res3 = merge_to(v4, vres);\n        EXPECT_EQ(vres, v4);\n        EXPECT_TRUE(res3);\n\n        std::vector<int> v5 = {};\n        bool res4 = merge_to(v1, v5);\n        EXPECT_EQ(v1, vres);\n        EXPECT_FALSE(res4);\n    }\n\n    TEST(xframe_utils, intersect_to)\n    {\n        std::vector<int> v1 = { 1, 3, 4, 5, 7, 9, 10 };\n        std::vector<int> v2 = { 1, 2, 4, 5, 6, 10, 11 };\n        std::vector<int> v3 = { 1, 4, 10 };\n        std::vector<int> vres = { 1, 4, 10 };\n\n        bool res1 = intersect_to(v1, v2, v3);\n        EXPECT_EQ(v1, vres);\n        EXPECT_FALSE(res1);\n\n        auto v4 = vres;\n        auto v5 = v4;\n        bool res2 = intersect_to(v5, v4);\n        EXPECT_EQ(v5, vres);\n        EXPECT_TRUE(res2);\n\n        std::vector<int> v6 = {};\n        bool res3 = intersect_to(v5, v6);\n        EXPECT_TRUE(v5.empty());\n        EXPECT_FALSE(res3);\n    }\n\n}\n\n"
  },
  {
    "path": "test/test_xnamed_axis.cpp",
    "content": "/***************************************************************************\n* Copyright (c) Johan Mabille, Sylvain Corlay, Wolf Vollprecht and         *\n* Martin Renou                                                             *\n* Copyright (c) QuantStack                                                 *\n*                                                                          *\n* Distributed under the terms of the BSD 3-Clause License.                 *\n*                                                                          *\n* The full license is in the file LICENSE, distributed with this software. *\n****************************************************************************/\n\n#include <string>\n#include \"gtest/gtest.h\"\n\n#include \"xframe/xnamed_axis.hpp\"\n\nnamespace xf\n{\n    TEST(xnamed_axis, get_labels)\n    {\n        auto a = axis(56);\n        auto n_a = named_axis(\"axis_a\", a);\n        auto labels = get_labels<int>(n_a);\n\n        EXPECT_EQ(labels, a.labels());\n        EXPECT_EQ(0, labels[0]);\n        EXPECT_EQ(56u, labels.size());\n    }\n\n    TEST(xnamed_axis, name)\n    {\n        auto a = axis(56);\n        auto n_a = named_axis(\"axis_a\", a);\n        EXPECT_EQ(\"axis_a\", n_a.name());\n    }\n}\n"
  },
  {
    "path": "test/test_xreindex_view.cpp",
    "content": "/***************************************************************************\n* Copyright (c) Johan Mabille, Sylvain Corlay, Wolf Vollprecht and         *\n* Martin Renou                                                             *\n* Copyright (c) QuantStack                                                 *\n*                                                                          *\n* Distributed under the terms of the BSD 3-Clause License.                 *\n*                                                                          *\n* The full license is in the file LICENSE, distributed with this software. *\n****************************************************************************/\n\n#include \"gtest/gtest.h\"\n#include \"test_fixture.hpp\"\n#include \"xframe/xreindex_view.hpp\"\n\nnamespace xf\n{\n    using coordinate_map = typename coordinate_type::map_type;\n\n    coordinate_map make_new_coordinate()\n    {\n        coordinate_map m;\n        m[\"abscissa\"] = make_test_saxis3();\n        return m;\n    }\n\n    TEST(xreindex_view, builders)\n    {\n        auto var = make_test_variable();\n        coordinate_map new_coord = make_new_coordinate();\n        coordinate_type coordinate_res = {{\"abscissa\", make_test_saxis3()}, {\"ordinate\", make_test_iaxis()}};\n\n        auto view = reindex(var, new_coord);\n        EXPECT_TRUE(view.coordinates() == coordinate_res);\n        EXPECT_EQ(view.dimension_mapping(), var.dimension_mapping());\n\n        auto view2 = reindex(var, {{ \"abscissa\", xf::axis({\"a\", \"b\", \"c\", \"d\"})}});\n        EXPECT_TRUE(view2.coordinates() == coordinate_res);\n        EXPECT_EQ(view2.dimension_mapping(), var.dimension_mapping());\n\n        auto var3 = make_test_variable3();\n        auto res1 = align<join::inner>(var, var3);\n        auto coord = coordinate<fstring>({\n                {fstring(\"abscissa\"), saxis_type({\"a\", \"d\"})},\n                {fstring(\"ordinate\"), iaxis_type({1, 4})}\n        });\n        EXPECT_EQ(std::get<0>(res1).coordinates(), coord);\n        EXPECT_EQ(std::get<1>(res1).coordinates(), coord);\n\n        auto res2 = align<join::outer>(var, var3);\n        auto coord2 = coordinate<fstring>({\n                {fstring(\"abscissa\"), saxis_type({\"a\", \"c\", \"d\", \"e\"})},\n                {fstring(\"ordinate\"), iaxis_type({1, 2, 4, 5})}\n        });\n    }\n\n    TEST(xreindex_view, size)\n    {\n        auto var = make_test_variable();\n        coordinate_map new_coord = make_new_coordinate();\n        auto view = reindex(var, new_coord);\n        EXPECT_EQ(12u, view.size());\n    }\n\n    TEST(xreindex_view, dimension)\n    {\n        auto var = make_test_variable();\n        coordinate_map new_coord = make_new_coordinate();\n        auto view = reindex(var, new_coord);\n        EXPECT_EQ(2u, view.dimension());\n    }\n\n    TEST(xreindex_view, dimension_labels)\n    {\n        auto var = make_test_variable();\n        coordinate_map new_coord = make_new_coordinate();\n        auto view = reindex(var, new_coord);\n        saxis_type s = { \"abscissa\", \"ordinate\" };\n        EXPECT_EQ(view.dimension_labels(), s.labels());\n    }\n\n    TEST(xreindex_view, shape)\n    {\n        auto var = make_test_variable();\n        coordinate_map new_coord = make_new_coordinate();\n        auto view = reindex(var, new_coord);\n        auto shape = view.shape();\n        std::decay_t<decltype(view.shape())> expected = { 4, 3 };\n        EXPECT_EQ(shape, expected);\n    }\n\n    TEST(xreindex_view, access)\n    {\n        auto var = make_test_variable();\n        coordinate_map new_coord = make_new_coordinate();\n        auto view = reindex(var, new_coord);\n\n        EXPECT_EQ(view(0, 0), 1.);\n        EXPECT_EQ(view(0, 1), 2);\n        EXPECT_EQ(view(0, 2), view.missing());\n        EXPECT_EQ(view(1, 0), view.missing());\n        EXPECT_EQ(view(1, 1), view.missing());\n        EXPECT_EQ(view(1, 2), view.missing());\n        EXPECT_EQ(view(2, 0), view.missing());\n        EXPECT_EQ(view(2, 1), 5);\n        EXPECT_EQ(view(2, 2), 6);\n        EXPECT_EQ(view(3, 0), 7);\n        EXPECT_EQ(view(3, 1), 8);\n        EXPECT_EQ(view(3, 2), 9);\n    }\n\n    TEST(xreindex_view, element)\n    {\n        auto var = make_test_variable();\n        coordinate_map new_coord = make_new_coordinate();\n        auto view = reindex(var, new_coord);\n\n        EXPECT_EQ(view.element({0, 0}), 1.);\n        EXPECT_EQ(view.element({0, 1}), 2);\n        EXPECT_EQ(view.element({0, 2}), view.missing());\n        EXPECT_EQ(view.element({1, 0}), view.missing());\n        EXPECT_EQ(view.element({1, 1}), view.missing());\n        EXPECT_EQ(view.element({1, 2}), view.missing());\n        EXPECT_EQ(view.element({2, 0}), view.missing());\n        EXPECT_EQ(view.element({2, 1}), 5);\n        EXPECT_EQ(view.element({2, 2}), 6);\n        EXPECT_EQ(view.element({3, 0}), 7);\n        EXPECT_EQ(view.element({3, 1}), 8);\n        EXPECT_EQ(view.element({3, 2}), 9);\n    }\n\n    TEST(xreindex_view, locate)\n    {\n        auto var = make_test_variable();\n        coordinate_map new_coord = make_new_coordinate();\n        auto view = reindex(var, new_coord);\n\n        auto t00 = view.locate(\"a\", 1);\n        auto t01 = view.locate(\"a\", 2);\n        auto t02 = view.locate(\"a\", 4);\n        auto t10 = view.locate(\"b\", 1);\n        auto t11 = view.locate(\"b\", 2);\n        auto t12 = view.locate(\"b\", 4);\n        auto t20 = view.locate(\"c\", 1);\n        auto t21 = view.locate(\"c\", 2);\n        auto t22 = view.locate(\"c\", 4);\n        auto t30 = view.locate(\"d\", 1);\n        auto t31 = view.locate(\"d\", 2);\n        auto t32 = view.locate(\"d\", 4);\n\n        EXPECT_EQ(t00, view(0, 0));\n        EXPECT_EQ(t01, view(0, 1));\n        EXPECT_EQ(t02, view(0, 2));\n        EXPECT_EQ(t10, view(1, 0));\n        EXPECT_EQ(t11, view(1, 1));\n        EXPECT_EQ(t12, view(1, 2));\n        EXPECT_EQ(t20, view(2, 0));\n        EXPECT_EQ(t21, view(2, 1));\n        EXPECT_EQ(t22, view(2, 2));\n        EXPECT_EQ(t30, view(3, 0));\n        EXPECT_EQ(t31, view(3, 1));\n        EXPECT_EQ(t32, view(3, 2));\n    }\n\n    TEST(xreindex_view, locate_element)\n    {\n        auto var = make_test_variable();\n        coordinate_map new_coord = make_new_coordinate();\n        auto view = reindex(var, new_coord);\n\n        auto t00 = view.locate_element({ \"a\", 1 });\n        auto t01 = view.locate_element({ \"a\", 2 });\n        auto t02 = view.locate_element({ \"a\", 4 });\n        auto t10 = view.locate_element({ \"b\", 1 });\n        auto t11 = view.locate_element({ \"b\", 2 });\n        auto t12 = view.locate_element({ \"b\", 4 });\n        auto t20 = view.locate_element({ \"c\", 1 });\n        auto t21 = view.locate_element({ \"c\", 2 });\n        auto t22 = view.locate_element({ \"c\", 4 });\n        auto t30 = view.locate_element({ \"d\", 1 });\n        auto t31 = view.locate_element({ \"d\", 2 });\n        auto t32 = view.locate_element({ \"d\", 4 });\n\n        EXPECT_EQ(t00, view(0, 0));\n        EXPECT_EQ(t01, view(0, 1));\n        EXPECT_EQ(t02, view(0, 2));\n        EXPECT_EQ(t10, view(1, 0));\n        EXPECT_EQ(t11, view(1, 1));\n        EXPECT_EQ(t12, view(1, 2));\n        EXPECT_EQ(t20, view(2, 0));\n        EXPECT_EQ(t21, view(2, 1));\n        EXPECT_EQ(t22, view(2, 2));\n        EXPECT_EQ(t30, view(3, 0));\n        EXPECT_EQ(t31, view(3, 1));\n        EXPECT_EQ(t32, view(3, 2));\n    }\n\n    TEST(xreindex_view, select_inner)\n    {\n        auto var = make_test_variable();\n        coordinate_map new_coord = make_new_coordinate();\n        auto view = reindex(var, new_coord);\n\n        auto t00 = view.select({{\"abscissa\", \"a\"},{\"ordinate\", 1}});\n        auto t01 = view.select({{\"abscissa\", \"a\"},{\"ordinate\", 2}});\n        auto t02 = view.select({{\"abscissa\", \"a\"},{\"ordinate\", 4}});\n        auto t10 = view.select({{\"abscissa\", \"b\"},{\"ordinate\", 1}});\n        auto t11 = view.select({{\"abscissa\", \"b\"},{\"ordinate\", 2}});\n        auto t12 = view.select({{\"abscissa\", \"b\"},{\"ordinate\", 4}});\n        auto t20 = view.select({{\"abscissa\", \"c\"},{\"ordinate\", 1}});\n        auto t21 = view.select({{\"abscissa\", \"c\"},{\"ordinate\", 2}});\n        auto t22 = view.select({{\"abscissa\", \"c\"},{\"ordinate\", 4}});\n        auto t30 = view.select({{\"abscissa\", \"d\"},{\"ordinate\", 1}});\n        auto t31 = view.select({{\"abscissa\", \"d\"},{\"ordinate\", 2}});\n        auto t32 = view.select({{\"abscissa\", \"d\"},{\"ordinate\", 4}});\n\n        EXPECT_EQ(t00, view(0, 0));\n        EXPECT_EQ(t01, view(0, 1));\n        EXPECT_EQ(t02, view(0, 2));\n        EXPECT_EQ(t10, view(1, 0));\n        EXPECT_EQ(t11, view(1, 1));\n        EXPECT_EQ(t12, view(1, 2));\n        EXPECT_EQ(t20, view(2, 0));\n        EXPECT_EQ(t21, view(2, 1));\n        EXPECT_EQ(t22, view(2, 2));\n        EXPECT_EQ(t30, view(3, 0));\n        EXPECT_EQ(t31, view(3, 1));\n        EXPECT_EQ(t32, view(3, 2));\n\n        auto t100 = view.select({{\"abscissa\", \"a\"}, {\"ordinate\", 1}, {\"altitude\", 1}});\n        EXPECT_EQ(t100, t00);\n\n        EXPECT_ANY_THROW(view.select({{\"abscissa\", \"e\"}, {\"ordinate\", 1}}));\n    }\n\n    TEST(xreindex_view, select_outer)\n    {\n        auto var = make_test_variable();\n        coordinate_map new_coord = make_new_coordinate();\n        auto view = reindex(var, new_coord);\n\n        auto t00 = view.select<join::outer>({{\"abscissa\", \"a\"},{\"ordinate\", 1}});\n        auto t01 = view.select<join::outer>({{\"abscissa\", \"a\"},{\"ordinate\", 2}});\n        auto t02 = view.select<join::outer>({{\"abscissa\", \"a\"},{\"ordinate\", 4}});\n        auto t10 = view.select<join::outer>({{\"abscissa\", \"b\"},{\"ordinate\", 1}});\n        auto t11 = view.select<join::outer>({{\"abscissa\", \"b\"},{\"ordinate\", 2}});\n        auto t12 = view.select<join::outer>({{\"abscissa\", \"b\"},{\"ordinate\", 4}});\n        auto t20 = view.select<join::outer>({{\"abscissa\", \"c\"},{\"ordinate\", 1}});\n        auto t21 = view.select<join::outer>({{\"abscissa\", \"c\"},{\"ordinate\", 2}});\n        auto t22 = view.select<join::outer>({{\"abscissa\", \"c\"},{\"ordinate\", 4}});\n        auto t30 = view.select<join::outer>({{\"abscissa\", \"d\"},{\"ordinate\", 1}});\n        auto t31 = view.select<join::outer>({{\"abscissa\", \"d\"},{\"ordinate\", 2}});\n        auto t32 = view.select<join::outer>({{\"abscissa\", \"d\"},{\"ordinate\", 4}});\n\n        EXPECT_EQ(t00, view(0, 0));\n        EXPECT_EQ(t01, view(0, 1));\n        EXPECT_EQ(t02, view(0, 2));\n        EXPECT_EQ(t10, view(1, 0));\n        EXPECT_EQ(t11, view(1, 1));\n        EXPECT_EQ(t12, view(1, 2));\n        EXPECT_EQ(t20, view(2, 0));\n        EXPECT_EQ(t21, view(2, 1));\n        EXPECT_EQ(t22, view(2, 2));\n        EXPECT_EQ(t30, view(3, 0));\n        EXPECT_EQ(t31, view(3, 1));\n        EXPECT_EQ(t32, view(3, 2));\n\n        auto t100 = view.select<join::outer>({{\"abscissa\", \"a\"}, {\"ordinate\", 1}, {\"altitude\", 1}});\n        EXPECT_EQ(t100, t00);\n\n        auto mis = view.select<join::outer>({{\"abscissa\", \"e\"}, {\"ordinate\", 1}});\n        EXPECT_EQ(mis, view.missing());\n    }\n\n    TEST(xreindex_view, iselect)\n    {\n        auto var = make_test_variable();\n        coordinate_map new_coord = make_new_coordinate();\n        auto view = reindex(var, new_coord);\n\n        auto t00 = view.iselect({{\"abscissa\", 0},{\"ordinate\", 0}});\n        auto t01 = view.iselect({{\"abscissa\", 0},{\"ordinate\", 1}});\n        auto t02 = view.iselect({{\"abscissa\", 0},{\"ordinate\", 2}});\n        auto t10 = view.iselect({{\"abscissa\", 1},{\"ordinate\", 0}});\n        auto t11 = view.iselect({{\"abscissa\", 1},{\"ordinate\", 1}});\n        auto t12 = view.iselect({{\"abscissa\", 1},{\"ordinate\", 2}});\n        auto t20 = view.iselect({{\"abscissa\", 2},{\"ordinate\", 0}});\n        auto t21 = view.iselect({{\"abscissa\", 2},{\"ordinate\", 1}});\n        auto t22 = view.iselect({{\"abscissa\", 2},{\"ordinate\", 2}});\n        auto t30 = view.iselect({{\"abscissa\", 3},{\"ordinate\", 0}});\n        auto t31 = view.iselect({{\"abscissa\", 3},{\"ordinate\", 1}});\n        auto t32 = view.iselect({{\"abscissa\", 3},{\"ordinate\", 2}});\n\n        EXPECT_EQ(t00, view(0, 0));\n        EXPECT_EQ(t01, view(0, 1));\n        EXPECT_EQ(t02, view(0, 2));\n        EXPECT_EQ(t10, view(1, 0));\n        EXPECT_EQ(t11, view(1, 1));\n        EXPECT_EQ(t12, view(1, 2));\n        EXPECT_EQ(t20, view(2, 0));\n        EXPECT_EQ(t21, view(2, 1));\n        EXPECT_EQ(t22, view(2, 2));\n        EXPECT_EQ(t30, view(3, 0));\n        EXPECT_EQ(t31, view(3, 1));\n        EXPECT_EQ(t32, view(3, 2));\n    }\n\n    TEST(xreindex_view, data)\n    {\n        auto missing = xtl::missing<double>();\n        using data_type = xt::xoptional_assembly<xt::xarray<double>, xt::xarray<bool>>;\n        auto var = make_test_variable();\n        coordinate_map new_coord = make_new_coordinate();\n        auto view = reindex(var, new_coord);\n\n        const auto& d = view.data();\n        EXPECT_EQ(d.shape(), view.shape());\n        EXPECT_EQ(d(0, 0), view(0, 0));\n        std::array<size_t, 2> idx = {0u, 1u};\n        EXPECT_EQ(d[idx], view(0, 1));\n\n        auto var3 = make_test_variable3();\n        auto res = align<join::inner>(var, var3);\n        data_type exp0 = {{1., missing}, {7., 9.}};\n        data_type exp1 = {{1., 2.}, {missing, 5.}};\n        EXPECT_EQ(std::get<0>(res).data(), exp0);\n        EXPECT_EQ(std::get<1>(res).data(), exp1);\n    }\n}\n"
  },
  {
    "path": "test/test_xsequence_view.cpp",
    "content": "/***************************************************************************\n* Copyright (c) Johan Mabille, Sylvain Corlay, Wolf Vollprecht and         *\n* Martin Renou                                                             *\n* Copyright (c) QuantStack                                                 *\n*                                                                          *\n* Distributed under the terms of the BSD 3-Clause License.                 *\n*                                                                          *\n* The full license is in the file LICENSE, distributed with this software. *\n****************************************************************************/\n\n#include <cmath>\n#include \"gtest/gtest.h\"\n#include \"xframe/xsequence_view.hpp\"\n\nnamespace xf\n{\n    class slice_test\n    {\n    public:\n\n        using size_type = std::size_t;\n\n        slice_test() = default;\n        slice_test(size_type min_val, size_type max_val, size_type step) noexcept\n            : m_min(min_val), m_size(size_type(std::ceil(double(max_val - min_val) / double(step)))), m_step(step)\n        {\n        }\n\n        std::size_t size() const noexcept { return m_size; }\n        size_type operator()(size_type i) const noexcept { return m_min + i * m_step; }\n\n    private:\n\n        size_type m_min;\n        size_type m_size;\n        size_type m_step;\n    };\n\n    struct xsequence_view_feature\n    {\n        xsequence_view_feature();\n\n        using data_type = std::vector<int>;\n        using view_type = xsequence_view<data_type, slice_test>;\n        data_type m_data;\n        slice_test m_slice;\n        view_type m_view;\n    };\n\n    xsequence_view_feature::xsequence_view_feature()\n        : m_data({ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }), m_slice(0, 10, 2), m_view(m_data, m_slice)\n    {\n    }\n\n    TEST(xsequence_view, size)\n    {\n        xsequence_view_feature m_feature;\n        EXPECT_EQ(m_feature.m_view.size(), 5u);\n    }\n\n    TEST(xsequence_view, empty)\n    {\n        xsequence_view_feature m_feature;\n        EXPECT_FALSE(m_feature.m_view.empty());\n    }\n\n    TEST(xsequence_view, access)\n    {\n        xsequence_view_feature m_feature;\n        EXPECT_EQ(m_feature.m_view[0], 0);\n        EXPECT_EQ(m_feature.m_view[1], 2);\n        EXPECT_EQ(m_feature.m_view[2], 4);\n        EXPECT_EQ(m_feature.m_view[3], 6);\n        EXPECT_EQ(m_feature.m_view[4], 8);\n\n        EXPECT_EQ(m_feature.m_view.at(0), 0);\n        EXPECT_EQ(m_feature.m_view.at(1), 2);\n        EXPECT_EQ(m_feature.m_view.at(2), 4);\n        EXPECT_EQ(m_feature.m_view.at(3), 6);\n        EXPECT_EQ(m_feature.m_view.at(4), 8);\n        EXPECT_ANY_THROW(m_feature.m_view.at(5));\n\n        EXPECT_EQ(m_feature.m_view.front(), 0);\n        EXPECT_EQ(m_feature.m_view.back(), 8);\n    }\n\n    TEST(xsequence_view, iterator)\n    {\n        xsequence_view_feature m_feature;\n        auto iter = m_feature.m_view.begin();\n        auto citer = m_feature.m_view.cbegin();\n\n        for (size_t i = 0; i < m_feature.m_view.size(); ++i)\n        {\n            EXPECT_EQ(*iter, m_feature.m_view[i]);\n            EXPECT_EQ(*citer, m_feature.m_view[i]);\n            ++iter, ++citer;\n        }\n\n        EXPECT_EQ(iter, m_feature.m_view.end());\n        EXPECT_EQ(citer, m_feature.m_view.cend());\n\n        iter = m_feature.m_view.begin();\n        citer = m_feature.m_view.cbegin();\n        iter += 2;\n        citer += 2;\n        EXPECT_EQ(*iter, m_feature.m_view[2]);\n        EXPECT_EQ(*citer, m_feature.m_view[2]);\n        EXPECT_EQ(m_feature.m_view.end() - iter, 3);\n        EXPECT_EQ(m_feature.m_view.cend() - citer, 3);\n    }\n\n    TEST(xsequence_view, comparison)\n    {\n        xsequence_view_feature m_feature;\n        xsequence_view_feature::data_type data = { 0, 2, 4, 6, 8 };\n        xsequence_view_feature::data_type data2 = { 0, 2, 5, 6, 8 };\n\n        EXPECT_TRUE(m_feature.m_view == data);\n        EXPECT_TRUE(m_feature.m_view != data2);\n\n        EXPECT_TRUE(data == m_feature.m_view);\n        EXPECT_TRUE(data2 != m_feature.m_view);\n    }\n}\n"
  },
  {
    "path": "test/test_xvariable.cpp",
    "content": "/***************************************************************************\n* Copyright (c) Johan Mabille, Sylvain Corlay, Wolf Vollprecht and         *\n* Martin Renou                                                             *\n* Copyright (c) QuantStack                                                 *\n*                                                                          *\n* Distributed under the terms of the BSD 3-Clause License.                 *\n*                                                                          *\n* The full license is in the file LICENSE, distributed with this software. *\n****************************************************************************/\n\n#include <array>\n#include <cstddef>\n#include \"gtest/gtest.h\"\n#include \"test_fixture.hpp\"\n#include \"xframe/xnamed_axis.hpp\"\n\nnamespace xf\n{\n    TEST(xvariable, empty_data_constructor)\n    {\n        variable_type::coordinate_map m;\n        m[\"abscissa\"] = make_test_saxis();\n        m[\"ordinate\"] = make_test_iaxis();\n        variable_type::coordinate_map m2(m);\n\n        dimension_type::label_list dim_map = { \"abscissa\", \"ordinate\" };\n        dimension_type::label_list dim_map2(dim_map);\n\n        auto v1 = variable_type(m, dim_map);\n        auto v2 = variable_type(std::move(m2), std::move(dim_map2));\n        auto v3 = variable_type({ {\"abscissa\", make_test_saxis()}, {\"ordinate\", make_test_iaxis()} });\n\n        using shape_type = std::decay_t<decltype(v1.data().shape())>;\n        shape_type shape = { 3, 3 };\n        EXPECT_EQ(v1.data().shape(), shape);\n        EXPECT_EQ(v2.data().shape(), shape);\n        EXPECT_EQ(v3.data().shape(), shape);\n        EXPECT_EQ(v3.dimension_labels()[0], \"abscissa\");\n        EXPECT_EQ(v3.dimension_labels()[1], \"ordinate\");\n    }\n\n    TEST(xvariable, constructor)\n    {\n        auto v1 = variable_type(make_test_data(), make_test_coordinate(), dimension_type({\"abscissa\", \"ordinate\"}));\n\n        variable_type::coordinate_map m;\n        m[\"abscissa\"] = make_test_saxis();\n        m[\"ordinate\"] = make_test_iaxis();\n        variable_type::coordinate_map m2(m);\n\n        data_type d = make_test_data();\n        dimension_type::label_list dim_map = {\"abscissa\", \"ordinate\"};\n        dimension_type::label_list dim_map2(dim_map);\n        auto v2 = variable_type(d, m, dim_map);\n        auto v3 = variable_type(d, std::move(m), std::move(dim_map));\n\n        EXPECT_EQ(v1, v2);\n        EXPECT_EQ(v1, v3);\n        EXPECT_FALSE(v1 != v2);\n\n        auto v4 = variable_type(std::move(d), {{\"abscissa\", make_test_saxis()}, {\"ordinate\", make_test_iaxis()}});\n        EXPECT_EQ(v1, v4);\n\n        auto v5 = variable_type(make_test_coordinate(), dimension_type({ \"abscissa\", \"ordinate\" }));\n        EXPECT_EQ(v5.data().shape(), data_type::shape_type({ 3, 3 }));\n\n        auto v6 = variable_type(m2, dim_map2);\n        EXPECT_EQ(v6.data().shape(), data_type::shape_type({ 3, 3 }));\n\n        auto v7 = variable_type(std::move(m2), std::move(dim_map2));\n        EXPECT_EQ(v7.data().shape(), data_type::shape_type({ 3, 3 }));\n\n        auto v8 = variable_type(make_test_data(), make_test_coordinate(), dimension({\"abscissa\", \"ordinate\"}));\n        EXPECT_EQ(v1, v8);\n    }\n\n    TEST(xvariable, size)\n    {\n        auto v1 = make_test_variable();\n        EXPECT_EQ(9u, v1.size());\n\n        auto v2 = variable_type();\n        EXPECT_EQ(1u, v2.size());\n    }\n\n    TEST(xvariable, axis_accessor)\n    {\n        auto v1 = make_test_variable();\n        auto a = v1[\"ordinate\"].axis();\n        EXPECT_EQ(a.size(), 3u);\n    }\n\n    TEST(xvariable, dimension)\n    {\n        auto v1 = make_test_variable();\n        EXPECT_EQ(2u, v1.dimension());\n\n        auto v2 = variable_type();\n        EXPECT_EQ(0u, v2.dimension());\n    }\n\n    TEST(xvariable, dimension_labels)\n    {\n        auto v = make_test_variable();\n        saxis_type s = { \"abscissa\", \"ordinate\" };\n\n        EXPECT_EQ(v.dimension_labels(), s.labels());\n    }\n\n    TEST(xvariable, shape)\n    {\n        auto v = make_test_variable();\n        auto shape = v.shape();\n        std::decay_t<decltype(v.shape())> expected = { 3, 3 };\n        EXPECT_EQ(shape, expected);\n    }\n\n    TEST(xvariable, resize)\n    {\n        auto v1 = make_test_variable();\n        auto shape1 = v1.data().shape();\n        decltype(shape1) res1 = { 3, 3 };\n        EXPECT_EQ(shape1, res1);\n\n        saxis_type a = { \"a\", \"c\" };\n        dimension_type dim = { \"abscissa\" };\n        auto c = coordinate<fstring>({{fstring(\"abscissa\"), a}});\n        v1.resize(c, dim);\n        auto shape2 = v1.data().shape();\n        decltype(shape2) res2 = { 2 };\n        EXPECT_EQ(shape2, res2);\n    }\n\n    TEST(xvariable, access)\n    {\n        auto v = make_test_variable();\n        EXPECT_EQ(v(0, 0), 1.0);\n        EXPECT_EQ(v(0, 1), 2.0);\n        EXPECT_EQ(v(0, 2), xtl::missing<double>());\n        EXPECT_EQ(v(1, 0), xtl::missing<double>());\n        EXPECT_EQ(v(1, 1), 5.0);\n        EXPECT_EQ(v(1, 2), 6.0);\n        EXPECT_EQ(v(2, 0), 7.0);\n        EXPECT_EQ(v(2, 1), 8.0);\n        EXPECT_EQ(v(2, 2), 9.0);\n    }\n\n    TEST(xvariable, element)\n    {\n        auto v = make_test_variable();\n        EXPECT_EQ(v.element({ 0, 0 }), 1.0);\n        EXPECT_EQ(v.element({ 0, 1 }), 2.0);\n        EXPECT_EQ(v.element({ 0, 2 }), xtl::missing<double>());\n        EXPECT_EQ(v.element({ 1, 0 }), xtl::missing<double>());\n        EXPECT_EQ(v.element({ 1, 1 }), 5.0);\n        EXPECT_EQ(v.element({ 1, 2 }), 6.0);\n        EXPECT_EQ(v.element({ 2, 0 }), 7.0);\n        EXPECT_EQ(v.element({ 2, 1 }), 8.0);\n        EXPECT_EQ(v.element({ 2, 2 }), 9.0);\n    }\n\n    TEST(xvariable, select_inner)\n    {\n        auto v = make_test_variable();\n        auto t00 = v.select({{\"abscissa\", \"a\"}, {\"ordinate\", 1}});\n        auto t01 = v.select({{\"abscissa\", \"a\"}, {\"ordinate\", 2}});\n        auto t02 = v.select({{\"abscissa\", \"a\"}, {\"ordinate\", 4}});\n        auto t10 = v.select({{\"abscissa\", \"c\"}, {\"ordinate\", 1}});\n        auto t11 = v.select({{\"abscissa\", \"c\"}, {\"ordinate\", 2}});\n        auto t12 = v.select({{\"abscissa\", \"c\"}, {\"ordinate\", 4}});\n        auto t20 = v.select({{\"abscissa\", \"d\"}, {\"ordinate\", 1}});\n        auto t21 = v.select({{\"abscissa\", \"d\"}, {\"ordinate\", 2}});\n        auto t22 = v.select({{\"abscissa\", \"d\"}, {\"ordinate\", 4}});\n\n        EXPECT_EQ(t00, v(0, 0));\n        EXPECT_EQ(t01, v(0, 1));\n        EXPECT_EQ(t02, v(0, 2));\n        EXPECT_EQ(t10, v(1, 0));\n        EXPECT_EQ(t11, v(1, 1));\n        EXPECT_EQ(t12, v(1, 2));\n        EXPECT_EQ(t20, v(2, 0));\n        EXPECT_EQ(t21, v(2, 1));\n        EXPECT_EQ(t22, v(2, 2));\n\n        auto t100 = v.select({{\"abscissa\", \"a\"}, {\"ordinate\", 1}, {\"altitude\", 1}});\n        EXPECT_EQ(t100, t00);\n\n        EXPECT_ANY_THROW(v.select({{\"abscissa\", \"e\"}, {\"ordinate\", 1}}));\n    }\n\n    TEST(xvariable, select_outer)\n    {\n        const auto v = make_test_variable();\n        auto t00 = v.select<join::outer>({{\"abscissa\", \"a\"}, {\"ordinate\", 1}});\n        auto t01 = v.select<join::outer>({{\"abscissa\", \"a\"}, {\"ordinate\", 2}});\n        auto t02 = v.select<join::outer>({{\"abscissa\", \"a\"}, {\"ordinate\", 4}});\n        auto t10 = v.select<join::outer>({{\"abscissa\", \"c\"}, {\"ordinate\", 1}});\n        auto t11 = v.select<join::outer>({{\"abscissa\", \"c\"}, {\"ordinate\", 2}});\n        auto t12 = v.select<join::outer>({{\"abscissa\", \"c\"}, {\"ordinate\", 4}});\n        auto t20 = v.select<join::outer>({{\"abscissa\", \"d\"}, {\"ordinate\", 1}});\n        auto t21 = v.select<join::outer>({{\"abscissa\", \"d\"}, {\"ordinate\", 2}});\n        auto t22 = v.select<join::outer>({{\"abscissa\", \"d\"}, {\"ordinate\", 4}});\n\n        EXPECT_EQ(t00, v(0, 0));\n        EXPECT_EQ(t01, v(0, 1));\n        EXPECT_EQ(t02, v(0, 2));\n        EXPECT_EQ(t10, v(1, 0));\n        EXPECT_EQ(t11, v(1, 1));\n        EXPECT_EQ(t12, v(1, 2));\n        EXPECT_EQ(t20, v(2, 0));\n        EXPECT_EQ(t21, v(2, 1));\n        EXPECT_EQ(t22, v(2, 2));\n\n        auto t100 = v.select<join::outer>({{\"abscissa\", \"a\"}, {\"ordinate\", 1}, {\"altitude\", 1}});\n        EXPECT_EQ(t100, t00);\n\n        auto mis = v.select<join::outer>({{\"abscissa\", \"e\"}, {\"ordinate\", 1}});\n        EXPECT_EQ(mis, v.missing());\n    }\n\n    TEST(xvariable, iselect)\n    {\n        auto v = make_test_variable();\n        auto t00 = v.iselect({{\"abscissa\", 0}, {\"ordinate\", 0}});\n        auto t01 = v.iselect({{\"abscissa\", 0}, {\"ordinate\", 1}});\n        auto t02 = v.iselect({{\"abscissa\", 0}, {\"ordinate\", 2}});\n        auto t10 = v.iselect({{\"abscissa\", 1}, {\"ordinate\", 0}});\n        auto t11 = v.iselect({{\"abscissa\", 1}, {\"ordinate\", 1}});\n        auto t12 = v.iselect({{\"abscissa\", 1}, {\"ordinate\", 2}});\n        auto t20 = v.iselect({{\"abscissa\", 2}, {\"ordinate\", 0}});\n        auto t21 = v.iselect({{\"abscissa\", 2}, {\"ordinate\", 1}});\n        auto t22 = v.iselect({{\"abscissa\", 2}, {\"ordinate\", 2}});\n        auto t221 = v.iselect({{\"abscissa\", 2}, {\"ordinate\", 2}, {\"missing_dimension\", 1}});\n\n        EXPECT_EQ(t00, v(0, 0));\n        EXPECT_EQ(t01, v(0, 1));\n        EXPECT_EQ(t02, v(0, 2));\n        EXPECT_EQ(t10, v(1, 0));\n        EXPECT_EQ(t11, v(1, 1));\n        EXPECT_EQ(t12, v(1, 2));\n        EXPECT_EQ(t20, v(2, 0));\n        EXPECT_EQ(t21, v(2, 1));\n        EXPECT_EQ(t22, v(2, 2));\n        EXPECT_EQ(t221, v(2, 2));\n    }\n\n    TEST(xvariable, locate)\n    {\n        auto v = make_test_variable();\n        auto t00 = v.locate(\"a\", 1);\n        auto t01 = v.locate(\"a\", 2);\n        auto t02 = v.locate(\"a\", 4);\n        auto t10 = v.locate(\"c\", 1);\n        auto t11 = v.locate(\"c\", 2);\n        auto t12 = v.locate(\"c\", 4);\n        auto t20 = v.locate(\"d\", 1);\n        auto t21 = v.locate(\"d\", 2);\n        auto t22 = v.locate(\"d\", 4);\n\n        EXPECT_EQ(t00, v(0, 0));\n        EXPECT_EQ(t01, v(0, 1));\n        EXPECT_EQ(t02, v(0, 2));\n        EXPECT_EQ(t10, v(1, 0));\n        EXPECT_EQ(t11, v(1, 1));\n        EXPECT_EQ(t12, v(1, 2));\n        EXPECT_EQ(t20, v(2, 0));\n        EXPECT_EQ(t21, v(2, 1));\n        EXPECT_EQ(t22, v(2, 2));\n    }\n\n    TEST(xvariable, locate_element)\n    {\n        auto v = make_test_variable();\n\n        auto t00 = v.locate_element({ \"a\", 1 });\n        auto t01 = v.locate_element({ \"a\", 2 });\n        auto t02 = v.locate_element({ \"a\", 4 });\n        auto t10 = v.locate_element({ \"c\", 1 });\n        auto t11 = v.locate_element({ \"c\", 2 });\n        auto t12 = v.locate_element({ \"c\", 4 });\n        auto t20 = v.locate_element({ \"d\", 1 });\n        auto t21 = v.locate_element({ \"d\", 2 });\n        auto t22 = v.locate_element({ \"d\", 4 });\n\n        EXPECT_EQ(t00, v(0, 0));\n        EXPECT_EQ(t01, v(0, 1));\n        EXPECT_EQ(t02, v(0, 2));\n        EXPECT_EQ(t10, v(1, 0));\n        EXPECT_EQ(t11, v(1, 1));\n        EXPECT_EQ(t12, v(1, 2));\n        EXPECT_EQ(t20, v(2, 0));\n        EXPECT_EQ(t21, v(2, 1));\n        EXPECT_EQ(t22, v(2, 2));\n    }\n\n    TEST(xvariable, generator)\n    {\n        dimension_type dim({ \"abscissa\", \"ordinate\" });\n        coordinate_type coord1 = make_test_coordinate();\n        data_type data1 = make_test_data();\n        using shape_type = std::decay_t<decltype(data1.shape())>;\n        shape_type shape = { 3, 3 };\n\n        auto var1 = variable(data1, coord1, dim);\n        using var1_type = decltype(var1);\n        bool coord1_res = std::is_same<var1_type::coordinate_closure_type, var1_type::coordinate_type&>::value;\n        bool data1_res = std::is_same<var1_type::data_closure_type, var1_type::data_type&>::value;\n        EXPECT_TRUE(coord1_res);\n        EXPECT_TRUE(data1_res);\n        EXPECT_EQ(var1(0, 0), 1.0);\n        EXPECT_EQ(var1.shape(), shape);\n\n        const coordinate_type coord2 = make_test_coordinate();\n        const data_type data2 = make_test_data();\n        auto var2 = variable(data2, coord2, dim);\n        using var2_type = decltype(var2);\n        bool coord2_res = std::is_same<var2_type::coordinate_closure_type, const var2_type::coordinate_type&>::value;\n        bool data2_res = std::is_same<var2_type::data_closure_type, const var2_type::data_type&>::value;\n        EXPECT_TRUE(coord2_res);\n        EXPECT_TRUE(data2_res);\n        EXPECT_EQ(var2(0, 0), 1.0);\n        EXPECT_EQ(var2.shape(), shape);\n\n        auto var3 = variable(make_test_data(), make_test_coordinate(), dim);\n        using var3_type = decltype(var3);\n        bool coord3_res = std::is_same<var3_type::coordinate_closure_type, var3_type::coordinate_type>::value;\n        bool data3_res = std::is_same<var3_type::data_closure_type, var3_type::data_type>::value;\n        EXPECT_TRUE(coord3_res);\n        EXPECT_TRUE(data3_res);\n        EXPECT_EQ(var3(0, 0), 1.0);\n        EXPECT_EQ(var3.shape(), shape);\n\n        auto var4 = variable<double>(make_test_coordinate(), dim);\n        using var4_type = decltype(var4);\n        bool coord4_res = std::is_same<var4_type::coordinate_closure_type, var4_type::coordinate_type>::value;\n        bool data4_res = std::is_same<var4_type::data_closure_type, var4_type::data_type>::value;\n        EXPECT_TRUE(coord4_res);\n        EXPECT_TRUE(data4_res);\n        EXPECT_EQ(var4.shape(), shape);\n    }\n\n    TEST(xvariable, map_generator)\n    {\n        dimension_type::label_list dim({ \"abscissa\", \"ordinate\" });\n        coordinate_type coord1 = make_test_coordinate();\n        data_type data1 = make_test_data();\n        coordinate_type::map_type coord_map = coord1.data();\n        using shape_type = std::decay_t<decltype(data1.shape())>;\n        shape_type shape = { 3, 3 };\n\n        auto var1 = variable(data1, coord_map, dim);\n        using var1_type = decltype(var1);\n        bool coord1_res = std::is_same<var1_type::coordinate_closure_type, var1_type::coordinate_type>::value;\n        bool data1_res = std::is_same<var1_type::data_closure_type, var1_type::data_type&>::value;\n        EXPECT_TRUE(coord1_res);\n        EXPECT_TRUE(data1_res);\n        EXPECT_EQ(var1(0, 0), 1.0);\n        EXPECT_EQ(var1.shape(), shape);\n\n        auto var2 = variable<double>(coord_map, dim);\n        using var2_type = decltype(var2);\n        bool coord2_res = std::is_same<var2_type::coordinate_closure_type, var2_type::coordinate_type>::value;\n        bool data2_res = std::is_same<var2_type::data_closure_type, var2_type::data_type>::value;\n        EXPECT_TRUE(coord2_res);\n        EXPECT_TRUE(data2_res);\n        EXPECT_EQ(var2.shape(), shape);\n    }\n\n    TEST(xvariable, print)\n    {\n        auto var = make_test_variable();\n        std::string expected =\nR\"variable({{  1,   2, N/A},\n {N/A,   5,   6},\n {  7,   8,   9}}\nCoordinates:\nabscissa: (a, c, d, )\nordinate: (1, 2, 4, )\n)variable\";\n\n        std::ostringstream oss;\n        oss << var;\n        std::string res = oss.str();\n        EXPECT_EQ(res, expected);\n    }\n}\n"
  },
  {
    "path": "test/test_xvariable_assign.cpp",
    "content": "/***************************************************************************\n* Copyright (c) Johan Mabille, Sylvain Corlay, Wolf Vollprecht and         *\n* Martin Renou                                                             *\n* Copyright (c) QuantStack                                                 *\n*                                                                          *\n* Distributed under the terms of the BSD 3-Clause License.                 *\n*                                                                          *\n* The full license is in the file LICENSE, distributed with this software. *\n****************************************************************************/\n\n#include \"gtest/gtest.h\"\n#include \"test_fixture.hpp\"\n\nnamespace xf\n{\n\n    TEST(xvariable_assign, a_plus_b)\n    {\n        DEFINE_TEST_VARIABLES();\n        {\n            SCOPED_TRACE(\"same coordinate\");\n            variable_type res = a + a;\n            selector_list sl = make_selector_list_aa();\n            CHECK_EQUALITY(res, a, a, sl, +)\n        }\n\n        {\n            SCOPED_TRACE(\"different coordinates\");\n            variable_type res = a + b;\n            selector_list sl = make_selector_list_ab();\n            CHECK_EQUALITY(res, a, b, sl, +)\n        }\n\n        {\n            SCOPED_TRACE(\"broadcasting coordinates\");\n            variable_type res = c + d;\n            selector_list sl = make_selector_list_cd();\n            CHECK_EQUALITY(res, c, d, sl, +)\n        }\n    }\n\n    TEST(xvariable_assign, a_minus_b)\n    {\n        DEFINE_TEST_VARIABLES();\n        {\n            SCOPED_TRACE(\"same coordinate\");\n            variable_type res = a - a;\n            selector_list sl = make_selector_list_aa();\n            CHECK_EQUALITY(res, a, a, sl, -)\n        }\n\n        {\n            SCOPED_TRACE(\"different coordinates\");\n            variable_type res = a - b;\n            selector_list sl = make_selector_list_ab();\n            CHECK_EQUALITY(res, a, b, sl, -)\n        }\n\n        {\n            SCOPED_TRACE(\"broadcasting coordinates\");\n            variable_type res = c - d;\n            selector_list sl = make_selector_list_cd();\n            CHECK_EQUALITY(res, c, d, sl, -)\n        }\n    }\n\n    TEST(xvariable_assign, a_times_b)\n    {\n        DEFINE_TEST_VARIABLES();\n        {\n            SCOPED_TRACE(\"same coordinate\");\n            variable_type res = a * a;\n            selector_list sl = make_selector_list_aa();\n            CHECK_EQUALITY(res, a, a, sl, *)\n        }\n\n        {\n            SCOPED_TRACE(\"different coordinates\");\n            variable_type res = a * b;\n            selector_list sl = make_selector_list_ab();\n            CHECK_EQUALITY(res, a, b, sl, *)\n        }\n\n        {\n            SCOPED_TRACE(\"broadcasting coordinates\");\n            variable_type res = c * d;\n            selector_list sl = make_selector_list_cd();\n            CHECK_EQUALITY(res, c, d, sl, *)\n        }\n    }\n\n    TEST(xvariable_assign, a_divided_by_b)\n    {\n        DEFINE_TEST_VARIABLES();\n        {\n            SCOPED_TRACE(\"same coordinate\");\n            variable_type res = a / a;\n            selector_list sl = make_selector_list_aa();\n            CHECK_EQUALITY(res, a, a, sl, /)\n        }\n\n        {\n            SCOPED_TRACE(\"different coordinates\");\n            variable_type res = a / b;\n            selector_list sl = make_selector_list_ab();\n            CHECK_EQUALITY(res, a, b, sl, /)\n        }\n\n        {\n            SCOPED_TRACE(\"broadcasting coordinates\");\n            variable_type res = c / d;\n            selector_list sl = make_selector_list_cd();\n            CHECK_EQUALITY(res, c, d, sl, /)\n        }\n    }\n\n    TEST(xvariable_assign, a_plus_equal_b)\n    {\n        DEFINE_TEST_VARIABLES();\n        {\n            SCOPED_TRACE(\"same coordinate\");\n            variable_type res = a;\n            res += a;\n            selector_list sl = make_selector_list_aa();\n            CHECK_EQUALITY(res, a, a, sl, +)\n        }\n\n        {\n            SCOPED_TRACE(\"different coordinates\");\n            variable_type res = a;\n            res += b;\n            selector_list sl = make_selector_list_ab();\n            CHECK_EQUALITY(res, a, b, sl, +)\n        }\n\n        {\n            SCOPED_TRACE(\"broadcasting coordinates\");\n            variable_type res = c;\n            res += d;\n            selector_list sl = make_selector_list_cd();\n            CHECK_EQUALITY(res, c, d, sl, +)\n        }\n    }\n\n    TEST(xvariable_assign, a_minus_equal_b)\n    {\n        DEFINE_TEST_VARIABLES();\n        {\n            SCOPED_TRACE(\"same coordinate\");\n            variable_type res = a;\n            res -= a;\n            selector_list sl = make_selector_list_aa();\n            CHECK_EQUALITY(res, a, a, sl, -)\n        }\n\n        {\n            SCOPED_TRACE(\"different coordinates\");\n            variable_type res = a;\n            res -= b;\n            selector_list sl = make_selector_list_ab();\n            CHECK_EQUALITY(res, a, b, sl, -)\n        }\n\n        {\n            SCOPED_TRACE(\"broadcasting coordinates\");\n            variable_type res = c;\n            res -= d;\n            selector_list sl = make_selector_list_cd();\n            CHECK_EQUALITY(res, c, d, sl, -)\n        }\n    }\n\n    TEST(xvariable_assign, a_times_equal_b)\n    {\n        DEFINE_TEST_VARIABLES();\n        {\n            SCOPED_TRACE(\"same coordinate\");\n            variable_type res = a;\n            res *= a;\n            selector_list sl = make_selector_list_aa();\n            CHECK_EQUALITY(res, a, a, sl, *)\n        }\n\n        {\n            SCOPED_TRACE(\"different coordinates\");\n            variable_type res = a;\n            res *= b;\n            selector_list sl = make_selector_list_ab();\n            CHECK_EQUALITY(res, a, b, sl, *)\n        }\n\n        {\n            SCOPED_TRACE(\"broadcasting coordinates\");\n            variable_type res = c;\n            res *= d;\n            selector_list sl = make_selector_list_cd();\n            CHECK_EQUALITY(res, c, d, sl, *)\n        }\n    }\n\n    TEST(xvariable_assign, a_divided_by_equal_b)\n    {\n        DEFINE_TEST_VARIABLES();\n        {\n            SCOPED_TRACE(\"same coordinate\");\n            variable_type res = a;\n            res /= a;\n            selector_list sl = make_selector_list_aa();\n            CHECK_EQUALITY(res, a, a, sl, /)\n        }\n\n        {\n            SCOPED_TRACE(\"different coordinates\");\n            variable_type res = a;\n            res /= b;\n            selector_list sl = make_selector_list_ab();\n            CHECK_EQUALITY(res, a, b, sl, /)\n        }\n\n        {\n            SCOPED_TRACE(\"broadcasting coordinates\");\n            variable_type res = c;\n            res /= d;\n            selector_list sl = make_selector_list_cd();\n            CHECK_EQUALITY(res, c, d, sl, /)\n        }\n    }\n\n    TEST(xvariable_assign, assign_a_plus_b)\n    {\n        DEFINE_TEST_VARIABLES();\n        {\n            SCOPED_TRACE(\"same coordinate\");\n            variable_type res = a;\n            EXPECT_EQ(res(0, 0), a(0, 0));\n            res = a + a;\n            selector_list sl = make_selector_list_aa();\n            CHECK_EQUALITY(res, a, a, sl, +)\n        }\n\n        {\n            SCOPED_TRACE(\"different coordinates\");\n            variable_type res = a;\n            EXPECT_EQ(res(0, 0), a(0, 0));\n            res = a + b;\n            selector_list sl = make_selector_list_ab();\n            CHECK_EQUALITY(res, a, b, sl, +)\n        }\n\n        {\n            SCOPED_TRACE(\"broadcasting coordinates\");\n            variable_type res = a;\n            EXPECT_EQ(res(0, 0), a(0, 0));\n            res = c + d;\n            selector_list sl = make_selector_list_cd();\n            CHECK_EQUALITY(res, c, d, sl, +)\n        }\n    }\n\n    TEST(xvariable_assign, assign_a_minus_b)\n    {\n        DEFINE_TEST_VARIABLES();\n        {\n            SCOPED_TRACE(\"same coordinate\");\n            variable_type res = a;\n            EXPECT_EQ(res(0, 0), a(0, 0));\n            res = a - a;\n            selector_list sl = make_selector_list_aa();\n            CHECK_EQUALITY(res, a, a, sl, -)\n        }\n\n        {\n            SCOPED_TRACE(\"different coordinates\");\n            variable_type res = a;\n            EXPECT_EQ(res(0, 0), a(0, 0));\n            res = a - b;\n            selector_list sl = make_selector_list_ab();\n            CHECK_EQUALITY(res, a, b, sl, -)\n        }\n\n        {\n            SCOPED_TRACE(\"broadcasting coordinates\");\n            variable_type res = a;\n            EXPECT_EQ(res(0, 0), a(0, 0));\n            res = c - d;\n            selector_list sl = make_selector_list_cd();\n            CHECK_EQUALITY(res, c, d, sl, -)\n        }\n    }\n\n    TEST(xvariable_assign, assign_a_times_b)\n    {\n        DEFINE_TEST_VARIABLES();\n        {\n            SCOPED_TRACE(\"same coordinate\");\n            variable_type res = a;\n            EXPECT_EQ(res(0, 0), a(0, 0));\n            res = a * a;\n            selector_list sl = make_selector_list_aa();\n            CHECK_EQUALITY(res, a, a, sl, *)\n        }\n\n        {\n            SCOPED_TRACE(\"different coordinates\");\n            variable_type res = a;\n            EXPECT_EQ(res(0, 0), a(0, 0));\n            res = a * b;\n            selector_list sl = make_selector_list_ab();\n            CHECK_EQUALITY(res, a, b, sl, *)\n        }\n\n        {\n            SCOPED_TRACE(\"broadcasting coordinates\");\n            variable_type res = a;\n            EXPECT_EQ(res(0, 0), a(0, 0));\n            res = c * d;\n            selector_list sl = make_selector_list_cd();\n            CHECK_EQUALITY(res, c, d, sl, *)\n        }\n    }\n\n    TEST(xvariable_assign, assign_a_divided_by_b)\n    {\n        DEFINE_TEST_VARIABLES();\n        {\n            SCOPED_TRACE(\"same coordinate\");\n            variable_type res = a;\n            EXPECT_EQ(res(0, 0), a(0, 0));\n            res = a / a;\n            selector_list sl = make_selector_list_aa();\n            CHECK_EQUALITY(res, a, a, sl, /)\n        }\n\n        {\n            SCOPED_TRACE(\"different coordinates\");\n            variable_type res = a;\n            EXPECT_EQ(res(0, 0), a(0, 0));\n            res = a / b;\n            selector_list sl = make_selector_list_ab();\n            CHECK_EQUALITY(res, a, b, sl, /)\n        }\n\n        {\n            SCOPED_TRACE(\"broadcasting coordinates\");\n            variable_type res = a;\n            EXPECT_EQ(res(0, 0), a(0, 0));\n            res = c / d;\n            selector_list sl = make_selector_list_cd();\n            CHECK_EQUALITY(res, c, d, sl, /)\n        }\n    }\n\n\n#define CHECK_COMPOSED_EQUALITY(RES, A, B, SL)                                 \\\n    for(std::size_t i = 0; i < sl.size(); ++i)                                 \\\n    {                                                                          \\\n        EXPECT_EQ(RES.select(SL[i]), 3 * (A.select(SL[i]) + B.select(SL[i]))); \\\n    }\n\n    TEST(xvariable_assign, composed_function)\n    {\n        DEFINE_TEST_VARIABLES();\n        {\n            SCOPED_TRACE(\"same coordinate\");\n            variable_type res = a;\n            EXPECT_EQ(res(0, 0), a(0, 0));\n            res = 3 * (a + a);\n            selector_list sl = make_selector_list_aa();\n            CHECK_COMPOSED_EQUALITY(res, a, a, sl)\n        }\n\n        {\n            SCOPED_TRACE(\"different coordinates\");\n            variable_type res = a;\n            EXPECT_EQ(res(0, 0), a(0, 0));\n            res = 3 * (a + b);\n            selector_list sl = make_selector_list_ab();\n            CHECK_COMPOSED_EQUALITY(res, a, b, sl)\n        }\n\n        {\n            SCOPED_TRACE(\"broadcasting coordinates\");\n            variable_type res = a;\n            EXPECT_EQ(res(0, 0), a(0, 0));\n            res = 3 * (c + d);\n            selector_list sl = make_selector_list_cd();\n            CHECK_COMPOSED_EQUALITY(res, c, d, sl)\n        }\n    }\n\n    TEST(xvariable_assign, unsorted_labels)\n    {\n        auto a = variable_type(\n            make_test_data(),\n            {\n                {\"day\", xf::axis({ \"Monday\", \"Tuesday\", \"Wednesday\" })},\n                {\"city\", xf::axis({ \"London\", \"Paris\", \"Brussels\" })}\n            }\n        );\n        \n        auto b = variable_type(\n            make_test_data(),\n            {\n                { \"day\", xf::axis({ \"Monday\", \"Tuesday\", \"Wednesday\" })},\n                { \"city\", xf::axis({ \"Paris\", \"London\", \"Brussels\" })}\n            }\n        );\n\n        variable_type res = a + b;\n        EXPECT_EQ(res.locate(\"Monday\", \"Paris\"), a.locate(\"Monday\", \"Paris\") + b.locate(\"Monday\", \"Paris\"));\n        EXPECT_EQ(res.locate(\"Monday\", \"London\"), a.locate(\"Monday\", \"London\") + b.locate(\"Monday\", \"London\"));\n        EXPECT_EQ(res.locate(\"Monday\", \"Brussels\"), a.locate(\"Monday\", \"Brussels\") + b.locate(\"Monday\", \"Brussels\"));\n        EXPECT_EQ(res.locate(\"Tuesday\", \"Paris\"), a.locate(\"Tuesday\", \"Paris\") + b.locate(\"Tuesday\", \"Paris\"));\n        EXPECT_EQ(res.locate(\"Tuesday\", \"London\"), a.locate(\"Tuesday\", \"London\") + b.locate(\"Tuesday\", \"London\"));\n        EXPECT_EQ(res.locate(\"Tuesday\", \"Brussels\"), a.locate(\"Tuesday\", \"Brussels\") + b.locate(\"Tuesday\", \"Brussels\"));\n        EXPECT_EQ(res.locate(\"Wednesday\", \"Paris\"), a.locate(\"Wednesday\", \"Paris\") + b.locate(\"Wednesday\", \"Paris\"));\n        EXPECT_EQ(res.locate(\"Wednesday\", \"London\"), a.locate(\"Wednesday\", \"London\") + b.locate(\"Wednesday\", \"London\"));\n        EXPECT_EQ(res.locate(\"Wednesday\", \"Brussels\"), a.locate(\"Wednesday\", \"Brussels\") + b.locate(\"Wednesday\", \"Brussels\"));\n    }\n\n    TEST(xvariable_assign, broadcast_unsorted)\n    {\n        auto a = variable_type(\n            make_test_data(),\n            {\n                { \"day\", xf::axis({ \"Monday\", \"Tuesday\", \"Wednesday\" }) },\n                { \"city\", xf::axis({ \"London\", \"Paris\", \"Brussels\" }) }\n            }\n        );\n\n        data_type db = { 1., 2., 3. };\n        auto b = variable_type(\n            db,\n            {\n                { \"city\", xf::axis({\"Paris\", \"London\", \"Brussels\"})}\n            }\n        );\n\n        variable_type res = a + b;\n        EXPECT_EQ(res.locate(\"Monday\", \"Paris\"), a.locate(\"Monday\", \"Paris\") + b.locate(\"Paris\"));\n        EXPECT_EQ(res.locate(\"Monday\", \"London\"), a.locate(\"Monday\", \"London\") + b.locate(\"London\"));\n        EXPECT_EQ(res.locate(\"Monday\", \"Brussels\"), a.locate(\"Monday\", \"Brussels\") + b.locate(\"Brussels\"));\n        EXPECT_EQ(res.locate(\"Tuesday\", \"Paris\"), a.locate(\"Tuesday\", \"Paris\") + b.locate(\"Paris\"));\n        EXPECT_EQ(res.locate(\"Tuesday\", \"London\"), a.locate(\"Tuesday\", \"London\") + b.locate(\"London\"));\n        EXPECT_EQ(res.locate(\"Tuesday\", \"Brussels\"), a.locate(\"Tuesday\", \"Brussels\") + b.locate(\"Brussels\"));\n        EXPECT_EQ(res.locate(\"Wednesday\", \"Paris\"), a.locate(\"Wednesday\", \"Paris\") + b.locate(\"Paris\"));\n        EXPECT_EQ(res.locate(\"Wednesday\", \"London\"), a.locate(\"Wednesday\", \"London\") + b.locate(\"London\"));\n        EXPECT_EQ(res.locate(\"Wednesday\", \"Brussels\"), a.locate(\"Wednesday\", \"Brussels\") + b.locate(\"Brussels\"));\n    }\n\n    TEST(xvariable_assign, broadcast)\n    {\n        data_type d1 = {1., 2.};\n        auto v1 = variable_type(d1, {{\"x\", xf::axis({1, 3})}});\n\n        // TODO: investigate why data_type d2 = {{1., 3.}, {5., 7.}} is ambiguous\n        xt::xarray<double> a2 = {{1., 3.}, {5., 7.}};\n        data_type d2 = a2;\n        auto v2 = variable_type(d2, {{\"y\", xf::axis({2, 5})}, {\"x\", xf::axis({1, 3})}});\n\n        variable_type res = v2 + v1;\n        EXPECT_EQ(res.dimension_labels()[0], \"y\");\n        EXPECT_EQ(res.dimension_labels()[1], \"x\");\n        EXPECT_EQ(res(0, 0), 2.);\n        EXPECT_EQ(res(0, 1), 5.);\n        EXPECT_EQ(res(1, 0), 6.);\n        EXPECT_EQ(res(1, 1), 9.);\n    }\n}\n\n"
  },
  {
    "path": "test/test_xvariable_function.cpp",
    "content": "/***************************************************************************\n* Copyright (c) Johan Mabille, Sylvain Corlay, Wolf Vollprecht and         *\n* Martin Renou                                                             *\n* Copyright (c) QuantStack                                                 *\n*                                                                          *\n* Distributed under the terms of the BSD 3-Clause License.                 *\n*                                                                          *\n* The full license is in the file LICENSE, distributed with this software. *\n****************************************************************************/\n\n#include \"gtest/gtest.h\"\n#include \"test_fixture.hpp\"\n\nnamespace xf\n{\n    struct xfunction_features\n    {\n        variable_type m_a;\n        variable_type m_b;\n\n        xfunction_features();\n    };\n\n    xfunction_features::xfunction_features()\n    {\n        m_a = make_test_variable();\n        m_b = make_test_variable2();\n    }\n\n    TEST(xvariable_function, size)\n    {\n        xfunction_features f;\n        std::size_t s1 = (f.m_a + f.m_a).size();\n        EXPECT_EQ(s1, 9u);\n        std::size_t s2 = (f.m_a + f.m_b).size();\n        EXPECT_EQ(s2, 12u);\n        std::size_t s3 = (f.m_a + f.m_a).template size<join::outer>();\n        EXPECT_EQ(s3, 9u);\n        std::size_t s4 = (f.m_a + f.m_b).template size<join::outer>();\n        EXPECT_EQ(s4, 48u);\n    }\n\n    TEST(xvariable_function, dimension)\n    {\n        xfunction_features f;\n        std::size_t s1 = (f.m_a + f.m_a).dimension();\n        EXPECT_EQ(s1, 2u);\n        std::size_t s2 = (f.m_a + f.m_b).dimension();\n        EXPECT_EQ(s2, 3u);\n        std::size_t s3 = (f.m_a + f.m_a).template dimension<join::outer>();\n        EXPECT_EQ(s3, 2u);\n        std::size_t s4 = (f.m_a + f.m_b).template dimension<join::outer>();\n        EXPECT_EQ(s4, 3u);\n    }\n\n    TEST(xvariable_function, dimension_labels)\n    {\n        xfunction_features f;\n        auto l1 = (f.m_a + f.m_a).dimension_labels();\n        EXPECT_EQ(l1, f.m_a.dimension_labels());\n        auto l2 = (f.m_a + f.m_a).dimension_labels<join::outer>();\n        EXPECT_EQ(l2, f.m_a.dimension_labels());\n        auto l3 = (f.m_a + f.m_b).dimension_labels();\n        EXPECT_EQ(l3, f.m_b.dimension_labels());\n        auto l4 = (f.m_a + f.m_b).dimension_labels<join::outer>();\n        EXPECT_EQ(l4, f.m_b.dimension_labels());\n    }\n\n    TEST(xvariable_function, coordinates)\n    {\n        xfunction_features f;\n        auto c1 = (f.m_a + f.m_a).coordinates();\n        EXPECT_EQ(c1, f.m_a.coordinates());\n        auto c2 = (f.m_a + f.m_a).coordinates<join::outer>();\n        EXPECT_EQ(c2, f.m_a.coordinates());\n        auto c3 = (f.m_a + f.m_b).coordinates();\n        EXPECT_EQ(c3, make_intersect_coordinate());\n        auto c4 = (f.m_a + f.m_b).coordinates<join::outer>();\n        EXPECT_EQ(c4, make_merge_coordinate());\n    }\n\n    TEST(xvariable_function, dimension_mapping)\n    {\n        xfunction_features f;\n        auto d1 = (f.m_a + f.m_a).dimension_mapping();\n        EXPECT_EQ(d1, f.m_a.dimension_mapping());\n        auto d2 = (f.m_a + f.m_a).dimension_mapping<join::outer>();\n        EXPECT_EQ(d2, f.m_a.dimension_mapping());\n        auto d3 = (f.m_a + f.m_b).dimension_mapping();\n        EXPECT_EQ(d3, f.m_b.dimension_mapping());\n        auto d4 = (f.m_a + f.m_b).dimension_mapping<join::outer>();\n        EXPECT_EQ(d4, f.m_b.dimension_mapping());\n    }\n\n    TEST(xvariable_function, shape)\n    {\n        xfunction_features f;\n        using shape_type = std::decay_t<decltype(f.m_a.shape())>;\n        auto s1 = (f.m_a + f.m_a).shape();\n        EXPECT_EQ(s1, shape_type({ 3, 3 }));\n        auto s2 = (f.m_a + f.m_b).shape();\n        EXPECT_EQ(s2, shape_type({ 3, 3, 3 }));\n    }\n\n    TEST(xvariable_function, access)\n    {\n        xfunction_features f;\n        std::size_t i = f.m_a.data().shape()[0] - 1;\n        std::size_t j = f.m_a.data().shape()[1] - 1;\n\n        {\n            SCOPED_TRACE(\"same shape\");\n            xtl::xoptional<double> a = (f.m_a + f.m_a)(i, j);\n            xtl::xoptional<double> b = f.m_a(i, j) + f.m_a(i, j);\n            EXPECT_EQ(a, b);\n        }\n\n        {\n            SCOPED_TRACE(\"different shape\");\n            xtl::xoptional<double> a = (f.m_a + f.m_b)(1, i, j);\n            xtl::xoptional<double> b = f.m_a(1, i, j) + f.m_b(1, i, j);\n            EXPECT_EQ(a, b);\n        }\n    }\n\n    TEST(xvariable_function, broadcast_coordinate)\n    {\n        xfunction_features f;\n\n        coordinate_type c1;\n        xtrivial_broadcast res1 = (f.m_a + f.m_a).broadcast_coordinates(c1);\n        EXPECT_EQ(c1, f.m_a.coordinates());\n        EXPECT_TRUE(res1.m_same_dimensions);\n        EXPECT_TRUE(res1.m_same_labels);\n\n        coordinate_type c2;\n        xtrivial_broadcast res2 = (f.m_a + f.m_a).broadcast_coordinates<join::outer>(c2);\n        EXPECT_EQ(c2, f.m_a.coordinates());\n        EXPECT_TRUE(res2.m_same_dimensions);\n        EXPECT_TRUE(res2.m_same_labels);\n\n        coordinate_type c3;\n        xtrivial_broadcast res3 = (f.m_a + f.m_b).broadcast_coordinates(c3);\n        EXPECT_EQ(c3, make_intersect_coordinate());\n        EXPECT_FALSE(res3.m_same_dimensions);\n        EXPECT_FALSE(res3.m_same_labels);\n\n        coordinate_type c4;\n        xtrivial_broadcast res4 = (f.m_a + f.m_b).broadcast_coordinates<join::outer>(c4);\n        EXPECT_EQ(c4, make_merge_coordinate());\n        EXPECT_FALSE(res4.m_same_dimensions);\n        EXPECT_FALSE(res4.m_same_labels);\n    }\n\n    TEST(xvariable_function, select_inner)\n    {\n        xfunction_features f;\n\n        {\n            SCOPED_TRACE(\"same shape\");\n            xtl::xoptional<double> a = (f.m_a + f.m_a).select({{\"abscissa\", \"d\"}, {\"ordinate\", 4}});\n            xtl::xoptional<double> b = 2 * f.m_a.select({{\"abscissa\", \"d\"}, {\"ordinate\", 4}});\n            EXPECT_EQ(a, b);\n            EXPECT_ANY_THROW((f.m_a + f.m_a).select({{\"abscissa\", \"e\"}, {\"ordinate\", 4}}));\n        }\n\n        {\n            SCOPED_TRACE(\"different shape\");\n            \n            xtl::xoptional<double> a = (f.m_a + f.m_b).select({{\"abscissa\", \"d\"}, {\"ordinate\", 4}, {\"altitude\", 2}});\n            xtl::xoptional<double> b = f.m_a.select({{\"abscissa\", \"d\"}, {\"ordinate\", 4}, {\"altitude\", 2}}) +\n                                       f.m_b.select({{\"abscissa\", \"d\"}, {\"ordinate\", 4}, {\"altitude\", 2}});\n            EXPECT_EQ(a, b);\n            EXPECT_ANY_THROW((f.m_a + f.m_b).select({{\"abscissa\", \"e\"}, {\"ordinate\", 4}, {\"altitude\", 2}}));\n        }\n    }\n\n    TEST(xvariable_function, select_outer)\n    {\n        xfunction_features f;\n\n        {\n            SCOPED_TRACE(\"same shape\");\n            xtl::xoptional<double> a = (f.m_a + f.m_a).select<join::outer>({{\"abscissa\", \"d\"}, {\"ordinate\", 4}});\n            xtl::xoptional<double> b = 2 * f.m_a.select<join::outer>({{\"abscissa\", \"d\"}, {\"ordinate\", 4}});\n            EXPECT_EQ(a, b);\n            EXPECT_EQ((f.m_a + f.m_a).select<join::outer>({{\"abscissa\", \"e\"}, {\"ordinate\", 4}}), f.m_a.missing());\n        }\n\n        {\n            SCOPED_TRACE(\"different shape\");\n            \n            xtl::xoptional<double> a = (f.m_a + f.m_b).select<join::outer>({{\"abscissa\", \"d\"}, {\"ordinate\", 4}, {\"altitude\", 2}});\n            xtl::xoptional<double> b = f.m_a.select<join::outer>({{\"abscissa\", \"d\"}, {\"ordinate\", 4}, {\"altitude\", 2}}) +\n                                       f.m_b.select<join::outer>({{\"abscissa\", \"d\"}, {\"ordinate\", 4}, {\"altitude\", 2}});\n            EXPECT_EQ(a, b);\n            EXPECT_EQ((f.m_a + f.m_b).select<join::outer>({{\"abscissa\", \"e\"}, {\"ordinate\", 4}, {\"altitude\", 2}}), f.m_a.missing());\n        }\n    }\n\n    TEST(xvariable_function, print)\n    {\n        auto a = variable_type(\n            make_test_data(),\n            {\n                { \"day\", xf::axis({ \"Monday\", \"Tuesday\", \"Wednesday\" }) },\n                { \"city\", xf::axis({ \"London\", \"Paris\", \"Brussels\" }) }\n            }\n        );\n\n        data_type db = { 1., 2., 3. };\n        auto b = variable_type(\n            db,\n            {\n                { \"city\", xf::axis({ \"Paris\", \"London\", \"Brussels\" }) }\n            }\n        );\n\n        auto f = a + b;\n        std::string expected =\nR\"variable({{  3,   3, N/A},\n {N/A,   6,   9},\n {  9,   9,  12}}\nCoordinates:\nday : (Monday, Tuesday, Wednesday, )\ncity: (London, Paris, Brussels, )\n)variable\";\n\n        std::ostringstream oss;\n        oss << f;\n        std::string res = oss.str();\n        EXPECT_EQ(res, expected);\n    }\n}\n\n"
  },
  {
    "path": "test/test_xvariable_masked_view.cpp",
    "content": "/***************************************************************************\n* Copyright (c) Johan Mabille, Sylvain Corlay, Wolf Vollprecht and         *\n* Martin Renou                                                             *\n* Copyright (c) QuantStack                                                 *\n*                                                                          *\n* Distributed under the terms of the BSD 3-Clause License.                 *\n*                                                                          *\n* The full license is in the file LICENSE, distributed with this software. *\n****************************************************************************/\n\n#include \"gtest/gtest.h\"\n\n#include \"test_fixture_view.hpp\"\n\n#include \"xframe/xvariable_masked_view.hpp\"\n\nnamespace xf\n{\n    TEST(xvariable_masked_view, iselect)\n    {\n        variable_type var = make_test_view_variable();\n        auto masked_var = where(var, var.axis<int>(\"ordinate\") < 6);\n\n        auto expected = make_masked_data();\n        for (std::size_t a = 0; a < expected.shape()[0]; ++a)\n        {\n            for (std::size_t o = 0; o < expected.shape()[1]; ++o)\n            {\n                EXPECT_EQ(masked_var.iselect({{\"abscissa\", a}, {\"ordinate\", o}}), expected(a, o));\n            }\n        }\n\n        auto masked_var2 = where(var, not_equal(var.axis<fstring>(\"abscissa\"), fstring(\"m\")) && not_equal(var.axis<int>(\"ordinate\"), 1));\n        auto expected2 = make_masked_data2();\n\n        using const_masked_var_type = const std::decay_t<decltype(masked_var2)>;\n        const_masked_var_type const_masked_var = where(var,\n            not_equal(var.axis<fstring>(\"abscissa\"), fstring(\"m\")) &&\n            not_equal(var.axis<int>(\"ordinate\"), 1)\n        );\n\n        for (std::size_t a = 0; a < expected2.shape()[0]; ++a)\n        {\n            for (std::size_t o = 0; o < expected2.shape()[1]; ++o)\n            {\n                auto val = const_masked_var.iselect<2>({{{\"abscissa\", a}, {\"ordinate\", o}}});\n                EXPECT_EQ(val, expected2(a, o));\n            }\n        }\n    }\n\n    TEST(xvariable_masked_view, select_inner)\n    {\n        variable_type var = make_test_view_variable();\n        auto masked_var = where(var,\n            not_equal(var.axis<fstring>(\"abscissa\"), fstring(\"m\")) &&\n            not_equal(var.axis<int>(\"ordinate\"), 1)\n        );\n\n        using const_masked_var_type = const std::decay_t<decltype(masked_var)>;\n        const_masked_var_type const_masked_var = where(var,\n            not_equal(var.axis<fstring>(\"abscissa\"), fstring(\"m\")) &&\n            not_equal(var.axis<int>(\"ordinate\"), 1)\n        );\n\n        auto masked_value = xtl::masked<xtl::xoptional<double, bool>>();\n\n        auto expected = masked_var.select<join::inner, 2>({{{\"abscissa\", \"a\"}, {\"ordinate\", 12}}});\n        EXPECT_EQ(expected, 6);\n        EXPECT_EQ(masked_var.select({{\"abscissa\", \"g\"}, {\"ordinate\", 5}}), 35);\n\n        EXPECT_EQ(masked_var.select({{\"abscissa\", \"d\"}, {\"ordinate\", 1}}), masked_value);\n        EXPECT_EQ(masked_var.select({{\"abscissa\", \"m\"}, {\"ordinate\", 5}}), masked_value);\n\n        var.select({{\"abscissa\", \"g\"}, {\"ordinate\", 5}}) = 123;\n        EXPECT_EQ(masked_var.select({{\"abscissa\", \"g\"}, {\"ordinate\", 5}}), 123);\n        masked_var.select({{\"abscissa\", \"g\"}, {\"ordinate\", 5}}) = 124;\n        EXPECT_EQ(var.select({{\"abscissa\", \"g\"}, {\"ordinate\", 5}}), 124);\n\n        EXPECT_ANY_THROW(masked_var.select({{\"abscissa\", \"e\"}, {\"ordinate\", 4}}));\n        EXPECT_ANY_THROW(masked_var.select({{\"abscissa\", \"a\"}, {\"ordinate\", 3}}));\n    }\n\n    TEST(xvariable_masked_view, select_outer)\n    {\n        variable_type var = make_test_view_variable();\n        auto masked_var = where(var,\n            not_equal(var.axis<fstring>(\"abscissa\"), fstring(\"m\")) &&\n            not_equal(var.axis<int>(\"ordinate\"), 1)\n        );\n\n        auto masked_value = xtl::masked<xtl::xoptional<double, bool>>();\n\n        auto expected = masked_var.select<join::outer, 2>({{{\"abscissa\", \"a\"}, {\"ordinate\", 12}}});\n        EXPECT_EQ(expected, 6);\n        EXPECT_EQ(masked_var.select<join::outer>({{\"abscissa\", \"g\"}, {\"ordinate\", 5}}), 35);\n        EXPECT_EQ(masked_var.select<join::outer>({{\"abscissa\", \"m\"}, {\"ordinate\", 5}}), masked_value);\n        EXPECT_EQ(masked_var.select<join::outer>({{\"abscissa\", \"d\"}, {\"ordinate\", 1}}), masked_value);\n\n        EXPECT_EQ(masked_var.select<join::outer>({{\"abscissa\", \"e\"}, {\"ordinate\", 4}}), xtl::missing<double>());\n        EXPECT_EQ(masked_var.select<join::outer>({{\"abscissa\", \"a\"}, {\"ordinate\", 3}}), xtl::missing<double>());\n    }\n\n    TEST(xvariable_masked_view, shape)\n    {\n        variable_type var = make_test_view_variable();\n        auto masked_var = where(var, var.axis<int>(\"ordinate\") < 6);\n\n        EXPECT_EQ(masked_var.shape(), var.shape());\n    }\n\n    TEST(xvariable_masked_view, access)\n    {\n        variable_type var = make_test_view_variable();\n        auto masked_var = where(var,\n            not_equal(var.axis<fstring>(\"abscissa\"), fstring(\"m\")) &&\n            not_equal(var.axis<int>(\"ordinate\"), 1)\n        );\n\n        using const_masked_var_type = const std::decay_t<decltype(masked_var)>;\n        const_masked_var_type const_masked_var = where(var,\n            not_equal(var.axis<fstring>(\"abscissa\"), fstring(\"m\")) &&\n            not_equal(var.axis<int>(\"ordinate\"), 1)\n        );\n\n        auto masked_value = xtl::masked<xtl::xoptional<double, bool>>();\n\n        EXPECT_EQ(masked_var(0, 6), 6);\n        masked_var(0, 6) = 7;\n        EXPECT_EQ(masked_var(0, 6), 7);\n\n        EXPECT_EQ(masked_var(4, 3), 35);\n        EXPECT_EQ(const_masked_var(4, 3), 35);\n        EXPECT_EQ(masked_var(6, 3), masked_value);\n        EXPECT_EQ(masked_var(2, 0), masked_value);\n    }\n\n    TEST(xvariable_masked_view, element)\n    {\n        variable_type var = make_test_view_variable();\n        auto masked_var = where(var,\n            not_equal(var.axis<fstring>(\"abscissa\"), fstring(\"m\")) &&\n            not_equal(var.axis<int>(\"ordinate\"), 1)\n        );\n\n        using const_masked_var_type = const std::decay_t<decltype(masked_var)>;\n        const_masked_var_type const_masked_var = where(var,\n            not_equal(var.axis<fstring>(\"abscissa\"), fstring(\"m\")) &&\n            not_equal(var.axis<int>(\"ordinate\"), 1)\n        );\n\n        auto masked_value = xtl::masked<xtl::xoptional<double, bool>>();\n        EXPECT_EQ(masked_var.element<2>({0, 6}), 6);\n        EXPECT_EQ(const_masked_var.element({4, 3}), 35);\n        EXPECT_EQ(masked_var.element({6, 3}), masked_value);\n        EXPECT_EQ(masked_var.element({2, 0}), masked_value);\n    }\n\n    TEST(xvariable_masked_view, locate)\n    {\n        variable_type var = make_test_view_variable();\n        auto masked_var = where(var,\n            not_equal(var.axis<fstring>(\"abscissa\"), fstring(\"m\")) &&\n            not_equal(var.axis<int>(\"ordinate\"), 1)\n        );\n\n        using const_masked_var_type = const std::decay_t<decltype(masked_var)>;\n        const_masked_var_type const_masked_var = where(var,\n            not_equal(var.axis<fstring>(\"abscissa\"), fstring(\"m\")) &&\n            not_equal(var.axis<int>(\"ordinate\"), 1)\n        );\n\n        auto masked_value = xtl::masked<xtl::xoptional<double, bool>>();\n        EXPECT_EQ(masked_var.locate(\"a\", 12), 6);\n        EXPECT_EQ(const_masked_var.locate(\"g\", 5), 35);\n        EXPECT_EQ(masked_var.locate(\"m\", 5), masked_value);\n        EXPECT_EQ(masked_var.locate(\"d\", 1), masked_value);\n        EXPECT_ANY_THROW(masked_var.locate(\"e\", 4));\n    }\n\n    TEST(xvariable_masked_view, locate_element)\n    {\n        variable_type var = make_test_view_variable();\n        auto masked_var = where(var,\n            not_equal(var.axis<fstring>(\"abscissa\"), fstring(\"m\")) &&\n            not_equal(var.axis<int>(\"ordinate\"), 1)\n        );\n\n        using const_masked_var_type = const std::decay_t<decltype(masked_var)>;\n        const_masked_var_type const_masked_var = where(var,\n            not_equal(var.axis<fstring>(\"abscissa\"), fstring(\"m\")) &&\n            not_equal(var.axis<int>(\"ordinate\"), 1)\n        );\n\n        auto masked_value = xtl::masked<xtl::xoptional<double, bool>>();\n        EXPECT_EQ(masked_var.locate_element({\"a\", 12}), 6);\n        EXPECT_EQ(const_masked_var.locate_element({\"g\", 5}), 35);\n        EXPECT_EQ(masked_var.locate_element({\"m\", 5}), masked_value);\n        EXPECT_EQ(masked_var.locate_element({\"d\", 1}), masked_value);\n        EXPECT_ANY_THROW(masked_var.locate_element({\"e\", 4}));\n    }\n\n    TEST(xvariable_masked_view, scalar_assign)\n    {\n        variable_type var = make_test_view_variable();\n        variable_type test_var = make_test_view_variable();\n        auto expected = make_masked_data2();\n        auto expected2 = make_masked_data3();\n\n        auto masked_var = where(\n            var,\n            not_equal(var.axis<fstring>(\"abscissa\"), fstring(\"m\")) &&\n            not_equal(var.axis<int>(\"ordinate\"), 1)\n        );\n\n        // Check that the data didn't change\n        ASSERT_EQ(var.data(), test_var.data());\n\n        ASSERT_NE(var.data(), masked_var.data());\n\n        ASSERT_EQ(expected, masked_var.data());\n\n        masked_var = 5.2;\n\n        ASSERT_EQ(expected2, masked_var.data());\n    }\n\n    TEST(xvariable_masked_view, variable_assign)\n    {\n        variable_type var = make_test_view_variable();\n        variable_type test_var = make_test_view_variable();\n\n        auto masked_var = where(\n            var,\n            not_equal(var.axis<fstring>(\"abscissa\"), fstring(\"m\")) &&\n            not_equal(var.axis<int>(\"ordinate\"), 1)\n        );\n\n        masked_var = test_var + 2;\n\n        ASSERT_NE(masked_var.data(), test_var.data());\n        ASSERT_NE(var.data(), test_var.data());\n    }\n}\n"
  },
  {
    "path": "test/test_xvariable_math.cpp",
    "content": "/***************************************************************************\n* Copyright (c) Johan Mabille, Sylvain Corlay, Wolf Vollprecht and         *\n* Martin Renou                                                             *\n* Copyright (c) QuantStack                                                 *\n*                                                                          *\n* Distributed under the terms of the BSD 3-Clause License.                 *\n*                                                                          *\n* The full license is in the file LICENSE, distributed with this software. *\n****************************************************************************/\n\n#include <algorithm>\n\n#include \"gtest/gtest.h\"\n\n#include \"xtensor/xarray.hpp\"\n#include \"xtensor/xoptional_assembly.hpp\"\n\n#include \"test_fixture.hpp\"\n\nnamespace xf\n{\n    TEST(xvariable_math, plus)\n    {\n        variable_type a = make_test_variable();\n        dict_type sel = make_selector_aa();\n        EXPECT_EQ(+(a.select(sel)), (+a).select(sel));\n    }\n\n    TEST(xvariable_math, minus)\n    {\n        variable_type a = make_test_variable();\n        dict_type sel = make_selector_aa();\n        EXPECT_EQ(-(a.select(sel)), (-a).select(sel));\n    }\n\n    TEST(xvariable_math, add)\n    {\n        variable_type a = make_test_variable();\n        dict_type sel = make_selector_aa();\n        EXPECT_EQ(a.select(sel) + a.select(sel), (a + a).select(sel));\n\n        double sb = 1.2;\n        EXPECT_EQ(a.select(sel) + sb, (a + sb).select(sel));\n\n        double sa = 1.2;\n        EXPECT_EQ(sa + a.select(sel), (sa + a).select(sel));\n    }\n\n    TEST(xvariable_math, substract)\n    {\n        variable_type a = make_test_variable();\n        dict_type sel = make_selector_aa();\n        EXPECT_EQ(a.select(sel) - a.select(sel), (a - a).select(sel));\n\n        double sb = 1.2;\n        EXPECT_EQ(a.select(sel) - sb, (a - sb).select(sel));\n\n        double sa = 1.2;\n        EXPECT_EQ(sa - a.select(sel), (sa - a).select(sel));\n    }\n\n    TEST(xvariable_math, multiply)\n    {\n        variable_type a = make_test_variable();\n        dict_type sel = make_selector_aa();\n        EXPECT_EQ(a.select(sel) * a.select(sel), (a * a).select(sel));\n\n        double sb = 1.2;\n        EXPECT_EQ(a.select(sel) * sb, (a * sb).select(sel));\n\n        double sa = 1.2;\n        EXPECT_EQ(sa * a.select(sel), (sa * a).select(sel));\n    }\n\n    TEST(xvariable_math, divide)\n    {\n        variable_type a = make_test_variable();\n        dict_type sel = make_selector_aa();\n        EXPECT_EQ(a.select(sel) / a.select(sel), (a / a).select(sel));\n\n        double sb = 1.2;\n        EXPECT_EQ(a.select(sel) / sb, (a / sb).select(sel));\n\n        double sa = 1.2;\n        EXPECT_EQ(sa / a.select(sel), (sa / a).select(sel));\n    }\n\n    TEST(xvariable_math, modulus)\n    {\n        int_variable_type a = make_test_int_variable();\n        dict_type sel = make_selector_aa();\n        EXPECT_EQ(a.select(sel) % a.select(sel), (a % a).select(sel));\n\n        int sb = 2;\n        EXPECT_EQ(a.select(sel) % sb, (a % sb).select(sel));\n\n        int sa = 4;\n        EXPECT_EQ(sa % a.select(sel), (sa % a).select(sel));\n    }\n\n    TEST(xvariable_math, logical_and)\n    {\n        bool_variable_type a = make_test_bool_variable();\n        dict_type sel = make_selector_aa();\n        EXPECT_EQ(a.select(sel) && a.select(sel), (a && a).select(sel));\n\n        bool sb = false;\n        EXPECT_EQ(a.select(sel) && sb, (a && sb).select(sel));\n\n        bool sa = false;\n        EXPECT_EQ(sa && a.select(sel), (sa && a).select(sel));\n    }\n\n    TEST(xvariable_math, logical_or)\n    {\n        bool_variable_type a = make_test_bool_variable();\n        dict_type sel = make_selector_aa();\n        EXPECT_EQ(a.select(sel) || a.select(sel), (a || a).select(sel));\n\n        bool sb = false;\n        EXPECT_EQ(a.select(sel) || sb, (a || sb).select(sel));\n\n        bool sa = false;\n        EXPECT_EQ(sa || a.select(sel), (sa || a).select(sel));\n    }\n\n    TEST(xvariable_math, logical_not)\n    {\n        bool_variable_type a = make_test_bool_variable();\n        dict_type sel = make_selector_aa();\n        EXPECT_EQ(!(a.select(sel)), (!a).select(sel));\n    }\n\n    TEST(xvariable_math, bitwise_and)\n    {\n        int_variable_type a = make_test_int_variable();\n        dict_type sel = make_selector_aa();\n        EXPECT_EQ(a.select(sel) & a.select(sel), (a & a).select(sel));\n\n        int sb = 4;\n        EXPECT_EQ(a.select(sel) & sb, (a & sb).select(sel));\n\n        int sa = 9;\n        EXPECT_EQ(sa & a.select(sel), (sa & a).select(sel));\n    }\n\n    TEST(xvariable_math, bitwise_or)\n    {\n        int_variable_type a = make_test_int_variable();\n        dict_type sel = make_selector_aa();\n        EXPECT_EQ(a.select(sel) | a.select(sel), (a | a).select(sel));\n\n        int sb = 4;\n        EXPECT_EQ(a.select(sel) | sb, (a | sb).select(sel));\n\n        int sa = 9;\n        EXPECT_EQ(sa | a.select(sel), (sa | a).select(sel));\n    }\n\n    TEST(xvariable_math, bitwise_xor)\n    {\n        int_variable_type a = make_test_int_variable();\n        dict_type sel = make_selector_aa();\n        EXPECT_EQ(a.select(sel) ^ a.select(sel), (a ^ a).select(sel));\n\n        int sb = 4;\n        EXPECT_EQ(a.select(sel) ^ sb, (a ^ sb).select(sel));\n\n        int sa = 9;\n        EXPECT_EQ(sa ^ a.select(sel), (sa ^ a).select(sel));\n    }\n\n    TEST(xvariable_math, bitwise_not)\n    {\n        int_variable_type a = make_test_int_variable();\n        dict_type sel = make_selector_aa();\n        EXPECT_EQ(~(a.select(sel)), (~a).select(sel));\n    }\n\n    TEST(xvariable_math, equal)\n    {\n        variable_type a = make_test_variable();\n        EXPECT_TRUE(a == a);\n    }\n\n    TEST(xvariable_math, not_equal)\n    {\n        variable_type a = make_test_variable();\n        EXPECT_FALSE(a != a);\n    }\n\n    TEST(xvariable_math, less)\n    {\n        variable_type a = make_test_variable();\n        dict_type sel = make_selector_aa();\n        EXPECT_EQ(xtl::xoptional<bool>(false), (a < a).select(sel));\n    }\n\n    TEST(xvariable_math, less_equal)\n    {\n        variable_type a = make_test_variable();\n        dict_type sel = make_selector_aa();\n        EXPECT_EQ(xtl::xoptional<bool>(true), (a <= a).select(sel));\n    }\n\n    TEST(xvariable_math, greater)\n    {\n        variable_type a = make_test_variable();\n        dict_type sel = make_selector_aa();\n        EXPECT_EQ(xtl::xoptional<bool>(false), (a > a).select(sel));\n    }\n\n    TEST(xvariable_math, greater_equal)\n    {\n        variable_type a = make_test_variable();\n        dict_type sel = make_selector_aa();\n        EXPECT_EQ(xtl::xoptional<bool>(true), (a >= a).select(sel));\n    }\n\n    TEST(xvariable_math, element_wise_equal)\n    {\n        variable_type a = make_test_variable();\n        dict_type sel = make_selector_aa();\n        EXPECT_EQ(xtl::xoptional<bool>(true), equal(a, a).select(sel));\n    }\n\n    TEST(xvariable_math, element_wise_not_equal)\n    {\n        variable_type a = make_test_variable();\n        dict_type sel = make_selector_aa();\n        EXPECT_EQ(xtl::xoptional<bool>(false), not_equal(a, a).select(sel));\n    }\n\n    TEST(xvariable_math, abs)\n    {\n        variable_type a = make_test_variable();\n        dict_type sel = make_selector_aa();\n        EXPECT_EQ(abs(a.select(sel)), (abs(a)).select(sel));\n    }\n\n    TEST(xvariable_math, fabs)\n    {\n        variable_type a = make_test_variable();\n        dict_type sel = make_selector_aa();\n        EXPECT_EQ(fabs(a.select(sel)), (fabs(a)).select(sel));\n    }\n\n    TEST(xvariable_math, fmod)\n    {\n        variable_type a = make_test_variable();\n        dict_type sel = make_selector_aa();\n        EXPECT_EQ(fmod(a.select(sel), a.select(sel)), fmod(a, a).select(sel));\n\n        double sb = 1.2;\n        EXPECT_EQ(fmod(a.select(sel), sb), fmod(a, sb).select(sel));\n\n        double sa = 1.2;\n        EXPECT_EQ(fmod(sa, a.select(sel)), fmod(sa, a).select(sel));\n    }\n\n    TEST(xvariable_math, remainder)\n    {\n        variable_type a = make_test_variable();\n        dict_type sel = make_selector_aa();\n        EXPECT_EQ(remainder(a.select(sel), a.select(sel)), remainder(a, a).select(sel));\n\n        double sb = 1.2;\n        EXPECT_EQ(remainder(a.select(sel), sb), remainder(a, sb).select(sel));\n\n        double sa = 1.2;\n        EXPECT_EQ(remainder(sa, a.select(sel)), remainder(sa, a).select(sel));\n    }\n\n    TEST(xvariable_math, fma)\n    {\n        variable_type a = make_test_variable();\n        dict_type sel = make_selector_aa();\n        EXPECT_EQ(fma(a.select(sel), a.select(sel), a.select(sel)), xf::fma(a, a, a).select(sel));\n\n        double sb = 1.2;\n        EXPECT_EQ(fma(a.select(sel), sb, a.select(sel)), xf::fma(a, sb, a).select(sel));\n\n        double sa = 1.2;\n        EXPECT_EQ(fma(sa, a.select(sel), a.select(sel)), xf::fma(sa, a, a).select(sel));\n\n        EXPECT_EQ(fma(sa, sb, a.select(sel)), xf::fma(sa, sb, a).select(sel));\n    }\n\n    TEST(xvariable_math, fmax)\n    {\n        variable_type a = make_test_variable();\n        dict_type sel = make_selector_aa();\n        EXPECT_EQ(fmax(a.select(sel), a.select(sel)), fmax(a, a).select(sel));\n\n        double sb = 1.2;\n        EXPECT_EQ(fmax(a.select(sel), sb), fmax(a, sb).select(sel));\n\n        double sa = 1.2;\n        EXPECT_EQ(fmax(sa, a.select(sel)), fmax(sa, a).select(sel));\n    }\n\n    TEST(xvariable_math, fmin)\n    {\n        variable_type a = make_test_variable();\n        dict_type sel = make_selector_aa();\n        EXPECT_EQ(fmin(a.select(sel), a.select(sel)), fmin(a, a).select(sel));\n\n        double sb = 1.2;\n        EXPECT_EQ(fmin(a.select(sel), sb), fmin(a, sb).select(sel));\n\n        double sa = 1.2;\n        EXPECT_EQ(fmin(sa, a.select(sel)), fmin(sa, a).select(sel));\n    }\n\n    TEST(xvariable_math, fdim)\n    {\n        variable_type a = make_test_variable();\n        dict_type sel = make_selector_aa();\n        EXPECT_EQ(fdim(a.select(sel), a.select(sel)), fdim(a, a).select(sel));\n\n        double sb = 1.2;\n        EXPECT_EQ(fdim(a.select(sel), sb), fdim(a, sb).select(sel));\n\n        double sa = 1.2;\n        EXPECT_EQ(fdim(sa, a.select(sel)), fdim(sa, a).select(sel));\n    }\n\n    TEST(xvariable_math, maximum)\n    {\n        auto missing = xtl::missing<double>();\n        using data_type = xt::xoptional_assembly<xt::xarray<double>, xt::xarray<bool>>;\n\n        variable_type a = make_test_variable();\n        variable_type b = make_test_variable2();\n\n        variable_type res = maximum(a, b);\n        data_type expected = {{{      1,       2, missing},\n                               {missing, missing, missing}},\n                              {{     11,      12,      13},\n                               {missing,      15,      16}}};\n        EXPECT_EQ(res.data(), expected);\n    }\n\n    TEST(xvariable_math, minimum)\n    {\n        auto missing = xtl::missing<double>();\n        using data_type = xt::xoptional_assembly<xt::xarray<double>, xt::xarray<bool>>;\n\n        variable_type a = make_test_variable();\n        variable_type b = make_test_variable2();\n\n        variable_type res = minimum(a, b);\n        data_type expected = {{{      1,       1, missing},\n                               {missing, missing, missing}},\n                              {{      7,       7,       7},\n                               {missing,       9,       9}}};\n        EXPECT_EQ(res.data(), expected);\n    }\n\n    TEST(xvariable_math, clip)\n    {\n        auto missing = xtl::missing<double>();\n        using data_type = xt::xoptional_assembly<xt::xarray<double>, xt::xarray<bool>>;\n\n        variable_type a = make_test_variable();\n\n        variable_type res = clip(a, 2., 8.0);\n        data_type expected = {{      2,   2, missing},\n                              {missing,   5,       6},\n                              {      7,   8,       8}};\n        EXPECT_EQ(res.data(), expected);\n\n        variable_type res2 = clip(a, missing, missing);\n        data_type expected2 = {{missing, missing, missing},\n                               {missing, missing, missing},\n                               {missing, missing, missing}};\n        EXPECT_EQ(res2.data(), expected2);\n\n        variable_type res3 = clip(a, missing, 4.);\n        data_type expected3 = {{missing, missing, missing},\n                               {missing, missing, missing},\n                               {missing, missing, missing}};\n        EXPECT_EQ(res3.data(), expected3);\n    }\n\n    TEST(xvariable_math, sign)\n    {\n        auto missing = xtl::missing<double>();\n        using data_type = xt::xoptional_assembly<xt::xarray<double>, xt::xarray<bool>>;\n\n        variable_type a = make_test_variable();\n        a(0, 0) = -5.;\n\n        variable_type res = sign(a);\n        data_type expected = {{     -1,   1, missing},\n                              {missing,   1,       1},\n                              {      1,   1,       1}};\n        EXPECT_EQ(res.data(), expected);\n    }\n\n    TEST(xvariable_math, exp)\n    {\n        variable_type a = make_test_variable();\n        dict_type sel = make_selector_aa();\n        EXPECT_EQ(exp(a.select(sel)), exp(a).select(sel));\n    }\n\n    TEST(xvariable_math, exp2)\n    {\n        variable_type a = make_test_variable();\n        dict_type sel = make_selector_aa();\n        EXPECT_EQ(exp2(a.select(sel)), exp2(a).select(sel));\n    }\n\n    TEST(xvariable_math, expm1)\n    {\n        variable_type a = make_test_variable();\n        dict_type sel = make_selector_aa();\n        EXPECT_EQ(expm1(a.select(sel)), expm1(a).select(sel));\n    }\n\n    TEST(xvariable_math, log)\n    {\n        variable_type a = make_test_variable();\n        dict_type sel = make_selector_aa();\n        EXPECT_EQ(log(a.select(sel)), log(a).select(sel));\n    }\n\n    TEST(xvariable_math, log10)\n    {\n        variable_type a = make_test_variable();\n        dict_type sel = make_selector_aa();\n        EXPECT_EQ(log10(a.select(sel)), log10(a).select(sel));\n    }\n\n    TEST(xvariable_math, log2)\n    {\n        variable_type a = make_test_variable();\n        dict_type sel = make_selector_aa();\n        EXPECT_EQ(log2(a.select(sel)), log2(a).select(sel));\n    }\n\n    TEST(xvariable_math, log1p)\n    {\n        variable_type a = make_test_variable();\n        dict_type sel = make_selector_aa();\n        EXPECT_EQ(log1p(a.select(sel)), log1p(a).select(sel));\n    }\n\n    TEST(xvariable_math, pow)\n    {\n        variable_type a = make_test_variable();\n        dict_type sel = make_selector_aa();\n        EXPECT_EQ(pow(a.select(sel), a.select(sel)), pow(a, a).select(sel));\n\n        double sb = 1.2;\n        EXPECT_EQ(pow(a.select(sel), sb), pow(a, sb).select(sel));\n\n        double sa = 1.2;\n        EXPECT_EQ(pow(sa, a.select(sel)), pow(sa, a).select(sel));\n    }\n\n    TEST(xvariable_math, sqrt)\n    {\n        variable_type a = make_test_variable();\n        dict_type sel = make_selector_aa();\n        EXPECT_EQ(sqrt(a.select(sel)), sqrt(a).select(sel));\n    }\n\n    TEST(xvariable_math, cbrt)\n    {\n        variable_type a = make_test_variable();\n        dict_type sel = make_selector_aa();\n        EXPECT_EQ(cbrt(a.select(sel)), cbrt(a).select(sel));\n    }\n\n    TEST(xvariable_math, hypot)\n    {\n        variable_type a = make_test_variable();\n        dict_type sel = make_selector_aa();\n        EXPECT_EQ(hypot(a.select(sel), a.select(sel)), hypot(a, a).select(sel));\n\n        double sb = 1.2;\n        EXPECT_EQ(hypot(a.select(sel), sb), hypot(a, sb).select(sel));\n\n        double sa = 1.2;\n        EXPECT_EQ(hypot(sa, a.select(sel)), hypot(sa, a).select(sel));\n    }\n\n    TEST(xvariable_math, sin)\n    {\n        variable_type a = make_test_variable();\n        dict_type sel = make_selector_aa();\n        EXPECT_EQ(sin(a.select(sel)), sin(a).select(sel));\n    }\n\n    TEST(xvariable_math, cos)\n    {\n        variable_type a = make_test_variable();\n        dict_type sel = make_selector_aa();\n        EXPECT_EQ(cos(a.select(sel)), cos(a).select(sel));\n    }\n\n    TEST(xvariable_math, tan)\n    {\n        variable_type a = make_test_variable();\n        dict_type sel = make_selector_aa();\n        EXPECT_EQ(tan(a.select(sel)), tan(a).select(sel));\n    }\n\n    TEST(xvariable_math, asin)\n    {\n        variable_type a = make_test_variable() / 10.;\n        dict_type sel = make_selector_aa();\n        EXPECT_EQ(asin(a.select(sel)), asin(a).select(sel));\n    }\n\n    TEST(xvariable_math, acos)\n    {\n        variable_type a = make_test_variable() / 10.;\n        dict_type sel = make_selector_aa();\n        EXPECT_EQ(acos(a.select(sel)), acos(a).select(sel));\n    }\n\n    TEST(xvariable_math, atan)\n    {\n        variable_type a = make_test_variable() / 10.;\n        dict_type sel = make_selector_aa();\n        EXPECT_EQ(atan(a.select(sel)), atan(a).select(sel));\n    }\n\n    TEST(xvariable_math, atan2)\n    {\n        variable_type a = make_test_variable();\n        dict_type sel = make_selector_aa();\n        EXPECT_EQ(atan2(a.select(sel), 2. * a.select(sel)), atan2(a, 2. * a).select(sel));\n    }\n\n    TEST(xvariable_math, sinh)\n    {\n        variable_type a = make_test_variable();\n        dict_type sel = make_selector_aa();\n        EXPECT_EQ(sinh(a.select(sel)), sinh(a).select(sel));\n    }\n\n    TEST(xvariable_math, cosh)\n    {\n        variable_type a = make_test_variable();\n        dict_type sel = make_selector_aa();\n        EXPECT_EQ(cosh(a.select(sel)), cosh(a).select(sel));\n    }\n\n    TEST(xvariable_math, tanh)\n    {\n        variable_type a = make_test_variable();\n        dict_type sel = make_selector_aa();\n        EXPECT_EQ(tanh(a.select(sel)), tanh(a).select(sel));\n    }\n\n    TEST(xvariable_math, asinh)\n    {\n        variable_type a = make_test_variable() / 10.;\n        dict_type sel = make_selector_aa();\n        EXPECT_EQ(asinh(a.select(sel)), asinh(a).select(sel));\n    }\n\n    TEST(xvariable_math, acosh)\n    {\n        variable_type a = make_test_variable();\n        dict_type sel = make_selector_aa();\n        EXPECT_EQ(acosh(a.select(sel)), acosh(a).select(sel));\n    }\n\n    TEST(xvariable_math, atanh)\n    {\n        variable_type a = make_test_variable() / 10.;\n        dict_type sel = make_selector_aa();\n        EXPECT_EQ(atanh(a.select(sel)), atanh(a).select(sel));\n    }\n\n    TEST(xvariable_math, erf)\n    {\n        variable_type a = make_test_variable();\n        dict_type sel = make_selector_aa();\n        EXPECT_EQ(erf(a.select(sel)), erf(a).select(sel));\n    }\n\n    TEST(xvariable_math, erfc)\n    {\n        variable_type a = make_test_variable();\n        dict_type sel = make_selector_aa();\n        EXPECT_EQ(erfc(a.select(sel)), erfc(a).select(sel));\n    }\n\n    TEST(xvariable_math, tgamma)\n    {\n        variable_type a = make_test_variable();\n        dict_type sel = make_selector_aa();\n        EXPECT_EQ(tgamma(a.select(sel)), tgamma(a).select(sel));\n    }\n\n    TEST(xvariable_math, lgamma)\n    {\n        variable_type a = make_test_variable();\n        dict_type sel = make_selector_aa();\n        EXPECT_EQ(lgamma(a.select(sel)), lgamma(a).select(sel));\n    }\n\n    TEST(xvariable_math, ceil)\n    {\n        variable_type a = make_test_variable();\n        dict_type sel = make_selector_aa();\n        EXPECT_EQ(ceil(a.select(sel)), ceil(a).select(sel));\n    }\n\n    TEST(xvariable_math, floor)\n    {\n        variable_type a = make_test_variable();\n        dict_type sel = make_selector_aa();\n        EXPECT_EQ(floor(a.select(sel)), floor(a).select(sel));\n    }\n\n    TEST(xvariable_math, trunc)\n    {\n        variable_type a = make_test_variable();\n        dict_type sel = make_selector_aa();\n        EXPECT_EQ(trunc(a.select(sel)), trunc(a).select(sel));\n    }\n\n    TEST(xvariable_math, round)\n    {\n        variable_type a = make_test_variable();\n        dict_type sel = make_selector_aa();\n        EXPECT_EQ(round(a.select(sel)), round(a).select(sel));\n    }\n\n    TEST(xvariable_math, nearbyint)\n    {\n        variable_type a = make_test_variable();\n        dict_type sel = make_selector_aa();\n        EXPECT_EQ(nearbyint(a.select(sel)), nearbyint(a).select(sel));\n    }\n\n    TEST(xvariable_math, rint)\n    {\n        variable_type a = make_test_variable();\n        dict_type sel = make_selector_aa();\n        EXPECT_EQ(rint(a.select(sel)), rint(a).select(sel));\n    }\n\n    TEST(xvariable_math, isfinite)\n    {\n        variable_type a = make_test_variable();\n        dict_type sel = make_selector_aa();\n        EXPECT_EQ(isfinite(a.select(sel)), xf::isfinite(a).select(sel));\n    }\n\n    TEST(xvariable_math, isinf)\n    {\n        variable_type a = make_test_variable();\n        dict_type sel = make_selector_aa();\n        EXPECT_EQ(isinf(a.select(sel)), xf::isinf(a).select(sel));\n    }\n\n    TEST(xvariable_math, isnan)\n    {\n        variable_type a = make_test_variable();\n        dict_type sel = make_selector_aa();\n        EXPECT_EQ(isnan(a.select(sel)), xf::isnan(a).select(sel));\n    }\n\n    TEST(xvariable_math, where)\n    {\n        auto missing = xtl::missing<double>();\n        using data_type = xt::xoptional_assembly<xt::xarray<double>, xt::xarray<bool>>;\n\n        variable_type a = make_test_variable();\n        variable_type b = make_test_variable2();\n\n        variable_type res = where(a < 6, b, a);\n\n        data_type expected = {{{     1.,      2., missing},\n                               {missing, missing, missing}},\n                              {{     7.,      7.,      7.},\n                               {     9.,      9.,      9.}}};\n        EXPECT_EQ(res.data(), expected);\n\n        variable_type res2 = where(a < 6, 0., a);\n        data_type expected2 = {{      0,   0, missing},\n                               {missing,   0,       6},\n                               {      7,   8,       9}};\n        EXPECT_EQ(res2.data(), expected2);\n    }\n\n    // Needs a fix in xtensor\n    /*TEST(xvariable_math, isclose)\n    {\n        variable_type a = make_test_variable();\n        dict_type sel = make_selector_aa();\n        EXPECT_TRUE(isclose(a, a).select(sel));\n    }*/\n}\n"
  },
  {
    "path": "test/test_xvariable_noalias.cpp",
    "content": "/***************************************************************************\n* Copyright (c) Johan Mabille, Sylvain Corlay, Wolf Vollprecht and         *\n* Martin Renou                                                             *\n* Copyright (c) QuantStack                                                 *\n*                                                                          *\n* Distributed under the terms of the BSD 3-Clause License.                 *\n*                                                                          *\n* The full license is in the file LICENSE, distributed with this software. *\n****************************************************************************/\n\n#include \"gtest/gtest.h\"\n#include \"test_fixture.hpp\"\n\nnamespace xf\n{\n    TEST(xvariable_noalias, a_plus_b)\n    {\n        DEFINE_TEST_VARIABLES();\n        {\n            SCOPED_TRACE(\"same coordinate\");\n            variable_type res = a;\n            noalias(res) = a + a;\n            selector_list sl = make_selector_list_aa();\n            CHECK_EQUALITY(res, a, a, sl, +)\n        }\n\n        {\n            SCOPED_TRACE(\"different coordinates\");\n            variable_type res = a;\n            noalias(res) = a + b;\n            selector_list sl = make_selector_list_ab();\n            CHECK_EQUALITY(res, a, b, sl, +)\n        }\n\n        {\n            SCOPED_TRACE(\"broadcasting coordinates\");\n            variable_type res = c;\n            noalias(res) = c + d;\n            selector_list sl = make_selector_list_cd();\n            CHECK_EQUALITY(res, c, d, sl, +)\n        }\n    }\n\n    TEST(xvariable_noalias, a_minus_b)\n    {\n        DEFINE_TEST_VARIABLES();\n        {\n            SCOPED_TRACE(\"same coordinate\");\n            variable_type res = a;\n            noalias(res) = a - a;\n            selector_list sl = make_selector_list_aa();\n            CHECK_EQUALITY(res, a, a, sl, -)\n        }\n\n        {\n            SCOPED_TRACE(\"different coordinates\");\n            variable_type res = a;\n            noalias(res) = a - b;\n            selector_list sl = make_selector_list_ab();\n            CHECK_EQUALITY(res, a, b, sl, -)\n        }\n\n        {\n            SCOPED_TRACE(\"broadcasting coordinates\");\n            variable_type res = c;\n            noalias(res) = c - d;\n            selector_list sl = make_selector_list_cd();\n            CHECK_EQUALITY(res, c, d, sl, -)\n        }\n    }\n\n    TEST(xvariable_noalias, a_times_b)\n    {\n        DEFINE_TEST_VARIABLES();\n        {\n            SCOPED_TRACE(\"same coordinate\");\n            variable_type res = a;\n            noalias(res) = a * a;\n            selector_list sl = make_selector_list_aa();\n            CHECK_EQUALITY(res, a, a, sl, *)\n        }\n\n        {\n            SCOPED_TRACE(\"different coordinates\");\n            variable_type res = a;\n            noalias(res) = a * b;\n            selector_list sl = make_selector_list_ab();\n            CHECK_EQUALITY(res, a, b, sl, *)\n        }\n\n        {\n            SCOPED_TRACE(\"broadcasting coordinates\");\n            variable_type res = c;\n            noalias(res) = c * d;\n            selector_list sl = make_selector_list_cd();\n            CHECK_EQUALITY(res, c, d, sl, *)\n        }\n    }\n\n    TEST(xvariable_noalias, a_divided_by__b)\n    {\n        DEFINE_TEST_VARIABLES();\n        {\n            SCOPED_TRACE(\"same coordinate\");\n            variable_type res = a;\n            noalias(res) = a / a;\n            selector_list sl = make_selector_list_aa();\n            CHECK_EQUALITY(res, a, a, sl, /)\n        }\n\n        {\n            SCOPED_TRACE(\"different coordinates\");\n            variable_type res = a;\n            noalias(res) = a / b;\n            selector_list sl = make_selector_list_ab();\n            CHECK_EQUALITY(res, a, b, sl, /)\n        }\n\n        {\n            SCOPED_TRACE(\"broadcasting coordinates\");\n            variable_type res = c;\n            noalias(res) = c / d;\n            selector_list sl = make_selector_list_cd();\n            CHECK_EQUALITY(res, c, d, sl, /)\n        }\n    }\n\n    TEST(xvariable_noalias, a_plus_equal_b)\n    {\n        DEFINE_TEST_VARIABLES();\n        {\n            SCOPED_TRACE(\"same coordinate\");\n            variable_type res = a;\n            noalias(res) += a;\n            selector_list sl = make_selector_list_aa();\n            CHECK_EQUALITY(res, a, a, sl, +)\n        }\n\n        {\n            SCOPED_TRACE(\"different coordinates\");\n            variable_type res = a;\n            noalias(res) += b;\n            selector_list sl = make_selector_list_ab();\n            CHECK_EQUALITY(res, a, b, sl, +)\n        }\n\n        {\n            SCOPED_TRACE(\"broadcasting coordinates\");\n            variable_type res = c;\n            noalias(res) += d;\n            selector_list sl = make_selector_list_cd();\n            CHECK_EQUALITY(res, c, d, sl, +)\n        }\n    }\n\n    TEST(xvariable_noalias, a_minus_equal_b)\n    {\n        DEFINE_TEST_VARIABLES();\n        {\n            SCOPED_TRACE(\"same coordinate\");\n            variable_type res = a;\n            noalias(res) -= a;\n            selector_list sl = make_selector_list_aa();\n            CHECK_EQUALITY(res, a, a, sl, -)\n        }\n\n        {\n            SCOPED_TRACE(\"different coordinates\");\n            variable_type res = a;\n            noalias(res) -= b;\n            selector_list sl = make_selector_list_ab();\n            CHECK_EQUALITY(res, a, b, sl, -)\n        }\n\n        {\n            SCOPED_TRACE(\"broadcasting coordinates\");\n            variable_type res = c;\n            noalias(res) -= d;\n            selector_list sl = make_selector_list_cd();\n            CHECK_EQUALITY(res, c, d, sl, -)\n        }\n    }\n\n    TEST(xvariable_noalias, a_times_equal_b)\n    {\n        DEFINE_TEST_VARIABLES();\n        {\n            SCOPED_TRACE(\"same coordinate\");\n            variable_type res = a;\n            noalias(res) *= a;\n            selector_list sl = make_selector_list_aa();\n            CHECK_EQUALITY(res, a, a, sl, *)\n        }\n\n        {\n            SCOPED_TRACE(\"different coordinates\");\n            variable_type res = a;\n            noalias(res) *= b;\n            selector_list sl = make_selector_list_ab();\n            CHECK_EQUALITY(res, a, b, sl, *)\n        }\n\n        {\n            SCOPED_TRACE(\"broadcasting coordinates\");\n            variable_type res = c;\n            noalias(res) *= d;\n            selector_list sl = make_selector_list_cd();\n            CHECK_EQUALITY(res, c, d, sl, *)\n        }\n    }\n\n    TEST(xvariable_noalias, a_divided_by_equal_b)\n    {\n        DEFINE_TEST_VARIABLES();\n        {\n            SCOPED_TRACE(\"same coordinate\");\n            variable_type res = a;\n            noalias(res) /= a;\n            selector_list sl = make_selector_list_aa();\n            CHECK_EQUALITY(res, a, a, sl, /)\n        }\n\n        {\n            SCOPED_TRACE(\"different coordinates\");\n            variable_type res = a;\n            noalias(res) /= b;\n            selector_list sl = make_selector_list_ab();\n            CHECK_EQUALITY(res, a, b, sl, /)\n        }\n\n        {\n            SCOPED_TRACE(\"broadcasting coordinates\");\n            variable_type res = c;\n            noalias(res) /= d;\n            selector_list sl = make_selector_list_cd();\n            CHECK_EQUALITY(res, c, d, sl, /)\n        }\n    }\n}\n"
  },
  {
    "path": "test/test_xvariable_scalar.cpp",
    "content": "/***************************************************************************\n* Copyright (c) Johan Mabille, Sylvain Corlay, Wolf Vollprecht and         *\n* Martin Renou                                                             *\n* Copyright (c) QuantStack                                                 *\n*                                                                          *\n* Distributed under the terms of the BSD 3-Clause License.                 *\n*                                                                          *\n* The full license is in the file LICENSE, distributed with this software. *\n****************************************************************************/\n\n#include \"gtest/gtest.h\"\n#include \"test_fixture.hpp\"\n\nnamespace xf\n{\n    template <class T>\n    struct DEBUG;\n\n    TEST(xvariable_scalar, a_plus_b)\n    {\n        variable_type a = make_test_variable();\n        selector_list sl = make_selector_list_aa();\n        variable_type res = 2. + a;\n        CHECK_SCALAR1_EQUALITY(res, 2, a, sl, +)\n        variable_type res2 = a + 2.;\n        CHECK_SCALAR2_EQUALITY(res2, a, 2, sl, +)\n    }\n\n    TEST(xvariable_scalar, a_minus_b)\n    {\n        variable_type a = make_test_variable();\n        selector_list sl = make_selector_list_aa();\n        variable_type res = 2. - a;\n        CHECK_SCALAR1_EQUALITY(res, 2, a, sl, -)\n        variable_type res2 = a - 2.;\n        CHECK_SCALAR2_EQUALITY(res2, a, 2, sl, -)\n    }\n\n    TEST(xvariable_scalar, a_times_b)\n    {\n        variable_type a = make_test_variable();\n        selector_list sl = make_selector_list_aa();\n        variable_type res = 2. * a;\n        CHECK_SCALAR1_EQUALITY(res, 2, a, sl, *)\n        variable_type res2 = a * 2.;\n        CHECK_SCALAR2_EQUALITY(res2, a, 2, sl, *)\n    }\n\n    TEST(xvariable_scalar, a_divided_by_b)\n    {\n        variable_type a = make_test_variable();\n        selector_list sl = make_selector_list_aa();\n        variable_type res = 2. / a;\n        CHECK_SCALAR1_EQUALITY(res, 2, a, sl, /)\n        variable_type res2 = a / 2.;\n        CHECK_SCALAR2_EQUALITY(res2, a, 2, sl, /)\n    }\n\n    TEST(xvariable_scalar, a_plus_equal_b)\n    {\n        variable_type a = make_test_variable();\n        variable_type b = a;\n        selector_list sl = make_selector_list_aa();\n        a += 2.;\n        CHECK_SCALAR2_EQUALITY(a, b, 2, sl, +)\n    }\n\n    TEST(xvariable_scalar, a_minus_equal_b)\n    {\n        variable_type a = make_test_variable();\n        variable_type b = a;\n        selector_list sl = make_selector_list_aa();\n        a -= 2.;\n        CHECK_SCALAR2_EQUALITY(a, b, 2, sl, -)\n    }\n\n    TEST(xvariable_scalar, a_times_equal_b)\n    {\n        variable_type a = make_test_variable();\n        variable_type b = a;\n        selector_list sl = make_selector_list_aa();\n        a *= 2.;\n        CHECK_SCALAR2_EQUALITY(a, b, 2, sl, *)\n    }\n\n    TEST(xvariable_scalar, a_divided_by_equal_b)\n    {\n        variable_type a = make_test_variable();\n        variable_type b = a;\n        selector_list sl = make_selector_list_aa();\n        a /= 2.;\n        CHECK_SCALAR2_EQUALITY(a, b, 2, sl, /)\n    }\n}\n"
  },
  {
    "path": "test/test_xvariable_view.cpp",
    "content": "/***************************************************************************\n* Copyright (c) Johan Mabille, Sylvain Corlay, Wolf Vollprecht and         *\n* Martin Renou                                                             *\n* Copyright (c) QuantStack                                                 *\n*                                                                          *\n* Distributed under the terms of the BSD 3-Clause License.                 *\n*                                                                          *\n* The full license is in the file LICENSE, distributed with this software. *\n****************************************************************************/\n\n#include \"gtest/gtest.h\"\n#include \"test_fixture_view.hpp\"\n\nnamespace xf\n{\n    TEST(xvariable_view, select_builder)\n    {\n        variable_type var = make_test_view_variable();\n        variable_view_type view = build_view(var);\n        variable_view_type view2 = select(var, {{ \"abscissa\", range(\"f\", \"n\") }, { \"ordinate\", range(1, 6, 2) }});\n        EXPECT_EQ(view, view2);\n    }\n\n    TEST(xvariable_view, size)\n    {\n        variable_type var = make_test_view_variable();\n        variable_view_type view = build_view(var);\n        EXPECT_EQ(view.size(), 15u);\n    }\n\n    TEST(xvariable_view, dimension)\n    {\n        variable_type var = make_test_view_variable();\n        variable_view_type view = build_view(var);\n        EXPECT_EQ(2u, view.dimension());\n    }\n\n    TEST(xvariable_view, dimension_labels)\n    {\n        variable_type var = make_test_view_variable();\n        variable_view_type view = build_view(var);\n        saxis_type s = { \"abscissa\", \"ordinate\" };\n\n        EXPECT_EQ(view.dimension_labels(), s.labels());\n    }\n\n    TEST(xvariable_view, access)\n    {\n        variable_type var = make_test_view_variable();\n        variable_view_type view = build_view(var);\n\n        auto vi00 = view(0, 0);\n        auto vi01 = view(0, 1);\n        auto vi02 = view(0, 2);\n        auto vi10 = view(1, 0);\n        auto vi11 = view(1, 1);\n        auto vi12 = view(1, 2);\n        auto vi20 = view(2, 0);\n        auto vi21 = view(2, 1);\n        auto vi22 = view(2, 2);\n        auto vi30 = view(3, 0);\n        auto vi31 = view(3, 1);\n        auto vi32 = view(3, 2);\n        auto vi40 = view(4, 0);\n        auto vi41 = view(4, 1);\n        auto vi42 = view(4, 2);\n\n        auto v00 = var(3, 0);\n        auto v01 = var(3, 2);\n        auto v02 = var(3, 4);\n        auto v10 = var(4, 0);\n        auto v11 = var(4, 2);\n        auto v12 = var(4, 4);\n        auto v20 = var(5, 0);\n        auto v21 = var(5, 2);\n        auto v22 = var(5, 4);\n        auto v30 = var(6, 0);\n        auto v31 = var(6, 2);\n        auto v32 = var(6, 4);\n        auto v40 = var(7, 0);\n        auto v41 = var(7, 2);\n        auto v42 = var(7, 4);\n\n        EXPECT_EQ(v00, vi00);\n        EXPECT_EQ(v01, vi01);\n        EXPECT_EQ(v02, vi02);\n        EXPECT_EQ(v10, vi10);\n        EXPECT_EQ(v11, vi11);\n        EXPECT_EQ(v12, vi12);\n        EXPECT_EQ(v20, vi20);\n        EXPECT_EQ(v21, vi21);\n        EXPECT_EQ(v22, vi22);\n        EXPECT_EQ(v30, vi30);\n        EXPECT_EQ(v31, vi31);\n        EXPECT_EQ(v32, vi32);\n        EXPECT_EQ(v40, vi40);\n        EXPECT_EQ(v41, vi41);\n        EXPECT_EQ(v42, vi42);\n    }\n\n    TEST(xvariable_view, element)\n    {\n        variable_type var = make_test_view_variable();\n        variable_view_type view = build_view(var);\n\n        EXPECT_EQ(view.element({ 0, 0 }), var(3, 0));\n        EXPECT_EQ(view.element({ 0, 1 }), var(3, 2));\n        EXPECT_EQ(view.element({ 0, 2 }), var(3, 4));\n        EXPECT_EQ(view.element({ 1, 0 }), var(4, 0));\n        EXPECT_EQ(view.element({ 1, 1 }), var(4, 2));\n        EXPECT_EQ(view.element({ 1, 2 }), var(4, 4));\n        EXPECT_EQ(view.element({ 2, 0 }), var(5, 0));\n        EXPECT_EQ(view.element({ 2, 1 }), var(5, 2));\n        EXPECT_EQ(view.element({ 2, 2 }), var(5, 4));\n        EXPECT_EQ(view.element({ 3, 0 }), var(6, 0));\n        EXPECT_EQ(view.element({ 3, 1 }), var(6, 2));\n        EXPECT_EQ(view.element({ 3, 2 }), var(6, 4));\n        EXPECT_EQ(view.element({ 4, 0 }), var(7, 0));\n        EXPECT_EQ(view.element({ 4, 1 }), var(7, 2));\n        EXPECT_EQ(view.element({ 4, 2 }), var(7, 4));\n    }\n\n    TEST(xvariable_view, select_inner)\n    {\n        variable_type var = make_test_view_variable();\n        variable_view_type view = build_view(var);\n\n        auto vi00 = view.select({ { \"abscissa\", \"f\" },{ \"ordinate\", 1 } });\n        auto vi01 = view.select({ { \"abscissa\", \"f\" },{ \"ordinate\", 4 } });\n        auto vi02 = view.select({ { \"abscissa\", \"f\" },{ \"ordinate\", 6 } });\n        auto vi10 = view.select({ { \"abscissa\", \"g\" },{ \"ordinate\", 1 } });\n        auto vi11 = view.select({ { \"abscissa\", \"g\" },{ \"ordinate\", 4 } });\n        auto vi12 = view.select({ { \"abscissa\", \"g\" },{ \"ordinate\", 6 } });\n        auto vi20 = view.select({ { \"abscissa\", \"h\" },{ \"ordinate\", 1 } });\n        auto vi21 = view.select({ { \"abscissa\", \"h\" },{ \"ordinate\", 4 } });\n        auto vi22 = view.select({ { \"abscissa\", \"h\" },{ \"ordinate\", 6 } });\n        auto vi30 = view.select({ { \"abscissa\", \"m\" },{ \"ordinate\", 1 } });\n        auto vi31 = view.select({ { \"abscissa\", \"m\" },{ \"ordinate\", 4 } });\n        auto vi32 = view.select({ { \"abscissa\", \"m\" },{ \"ordinate\", 6 } });\n        auto vi40 = view.select({ { \"abscissa\", \"n\" },{ \"ordinate\", 1 } });\n        auto vi41 = view.select({ { \"abscissa\", \"n\" },{ \"ordinate\", 4 } });\n        auto vi42 = view.select({ { \"abscissa\", \"n\" },{ \"ordinate\", 6 } });\n\n        auto v00 = var.select({ { \"abscissa\", \"f\" },{ \"ordinate\", 1 } });\n        auto v01 = var.select({ { \"abscissa\", \"f\" },{ \"ordinate\", 4 } });\n        auto v02 = var.select({ { \"abscissa\", \"f\" },{ \"ordinate\", 6 } });\n        auto v10 = var.select({ { \"abscissa\", \"g\" },{ \"ordinate\", 1 } });\n        auto v11 = var.select({ { \"abscissa\", \"g\" },{ \"ordinate\", 4 } });\n        auto v12 = var.select({ { \"abscissa\", \"g\" },{ \"ordinate\", 6 } });\n        auto v20 = var.select({ { \"abscissa\", \"h\" },{ \"ordinate\", 1 } });\n        auto v21 = var.select({ { \"abscissa\", \"h\" },{ \"ordinate\", 4 } });\n        auto v22 = var.select({ { \"abscissa\", \"h\" },{ \"ordinate\", 6 } });\n        auto v30 = var.select({ { \"abscissa\", \"m\" },{ \"ordinate\", 1 } });\n        auto v31 = var.select({ { \"abscissa\", \"m\" },{ \"ordinate\", 4 } });\n        auto v32 = var.select({ { \"abscissa\", \"m\" },{ \"ordinate\", 6 } });\n        auto v40 = var.select({ { \"abscissa\", \"n\" },{ \"ordinate\", 1 } });\n        auto v41 = var.select({ { \"abscissa\", \"n\" },{ \"ordinate\", 4 } });\n        auto v42 = var.select({ { \"abscissa\", \"n\" },{ \"ordinate\", 6 } });\n\n        EXPECT_EQ(v00, vi00);\n        EXPECT_EQ(v01, vi01);\n        EXPECT_EQ(v02, vi02);\n        EXPECT_EQ(v10, vi10);\n        EXPECT_EQ(v11, vi11);\n        EXPECT_EQ(v12, vi12);\n        EXPECT_EQ(v20, vi20);\n        EXPECT_EQ(v21, vi21);\n        EXPECT_EQ(v22, vi22);\n        EXPECT_EQ(v30, vi30);\n        EXPECT_EQ(v31, vi31);\n        EXPECT_EQ(v32, vi32);\n        EXPECT_EQ(v40, vi40);\n        EXPECT_EQ(v41, vi41);\n        EXPECT_EQ(v42, vi42);\n\n        auto vi100 = view.select({{ \"abscissa\", \"f\" },{ \"ordinate\", 1 }, { \"altitude\", 1 }});\n        EXPECT_EQ(vi100, vi00);\n\n        EXPECT_NO_THROW(var.select({{ \"abscissa\", \"d\" }, { \"ordinate\", 1 }}));\n        EXPECT_ANY_THROW(view.select({{ \"abscissa\", \"d\" }, { \"ordinate\", 1 }}));\n        EXPECT_ANY_THROW(view.select({{ \"abscissa\", \"e\" }, { \"ordinate\", 1 }}));\n    }\n\n    TEST(xvariable_view, select_outer)\n    {\n        variable_type var = make_test_view_variable();\n        variable_view_type view = build_view(var);\n\n        auto vi00 = view.select<join::outer>({ { \"abscissa\", \"f\" },{ \"ordinate\", 1 } });\n        auto vi01 = view.select<join::outer>({ { \"abscissa\", \"f\" },{ \"ordinate\", 4 } });\n        auto vi02 = view.select<join::outer>({ { \"abscissa\", \"f\" },{ \"ordinate\", 6 } });\n        auto vi10 = view.select<join::outer>({ { \"abscissa\", \"g\" },{ \"ordinate\", 1 } });\n        auto vi11 = view.select<join::outer>({ { \"abscissa\", \"g\" },{ \"ordinate\", 4 } });\n        auto vi12 = view.select<join::outer>({ { \"abscissa\", \"g\" },{ \"ordinate\", 6 } });\n        auto vi20 = view.select<join::outer>({ { \"abscissa\", \"h\" },{ \"ordinate\", 1 } });\n        auto vi21 = view.select<join::outer>({ { \"abscissa\", \"h\" },{ \"ordinate\", 4 } });\n        auto vi22 = view.select<join::outer>({ { \"abscissa\", \"h\" },{ \"ordinate\", 6 } });\n        auto vi30 = view.select<join::outer>({ { \"abscissa\", \"m\" },{ \"ordinate\", 1 } });\n        auto vi31 = view.select<join::outer>({ { \"abscissa\", \"m\" },{ \"ordinate\", 4 } });\n        auto vi32 = view.select<join::outer>({ { \"abscissa\", \"m\" },{ \"ordinate\", 6 } });\n        auto vi40 = view.select<join::outer>({ { \"abscissa\", \"n\" },{ \"ordinate\", 1 } });\n        auto vi41 = view.select<join::outer>({ { \"abscissa\", \"n\" },{ \"ordinate\", 4 } });\n        auto vi42 = view.select<join::outer>({ { \"abscissa\", \"n\" },{ \"ordinate\", 6 } });\n\n        auto v00 = var.select({ { \"abscissa\", \"f\" },{ \"ordinate\", 1 } });\n        auto v01 = var.select({ { \"abscissa\", \"f\" },{ \"ordinate\", 4 } });\n        auto v02 = var.select({ { \"abscissa\", \"f\" },{ \"ordinate\", 6 } });\n        auto v10 = var.select({ { \"abscissa\", \"g\" },{ \"ordinate\", 1 } });\n        auto v11 = var.select({ { \"abscissa\", \"g\" },{ \"ordinate\", 4 } });\n        auto v12 = var.select({ { \"abscissa\", \"g\" },{ \"ordinate\", 6 } });\n        auto v20 = var.select({ { \"abscissa\", \"h\" },{ \"ordinate\", 1 } });\n        auto v21 = var.select({ { \"abscissa\", \"h\" },{ \"ordinate\", 4 } });\n        auto v22 = var.select({ { \"abscissa\", \"h\" },{ \"ordinate\", 6 } });\n        auto v30 = var.select({ { \"abscissa\", \"m\" },{ \"ordinate\", 1 } });\n        auto v31 = var.select({ { \"abscissa\", \"m\" },{ \"ordinate\", 4 } });\n        auto v32 = var.select({ { \"abscissa\", \"m\" },{ \"ordinate\", 6 } });\n        auto v40 = var.select({ { \"abscissa\", \"n\" },{ \"ordinate\", 1 } });\n        auto v41 = var.select({ { \"abscissa\", \"n\" },{ \"ordinate\", 4 } });\n        auto v42 = var.select({ { \"abscissa\", \"n\" },{ \"ordinate\", 6 } });\n\n        EXPECT_EQ(v00, vi00);\n        EXPECT_EQ(v01, vi01);\n        EXPECT_EQ(v02, vi02);\n        EXPECT_EQ(v10, vi10);\n        EXPECT_EQ(v11, vi11);\n        EXPECT_EQ(v12, vi12);\n        EXPECT_EQ(v20, vi20);\n        EXPECT_EQ(v21, vi21);\n        EXPECT_EQ(v22, vi22);\n        EXPECT_EQ(v30, vi30);\n        EXPECT_EQ(v31, vi31);\n        EXPECT_EQ(v32, vi32);\n        EXPECT_EQ(v40, vi40);\n        EXPECT_EQ(v41, vi41);\n        EXPECT_EQ(v42, vi42);\n\n        auto vi100 = view.select<join::outer>({{ \"abscissa\", \"f\" },{ \"ordinate\", 1 },{ \"altitude\", 1 }});\n        EXPECT_EQ(vi100, vi00);\n\n        auto mis = view.select<join::outer>({{ \"abscissa\", \"e\" },{ \"ordinate\", 1 }});\n        EXPECT_EQ(mis, view.missing());\n    }\n\n    TEST(xvariable_view, iselect)\n    {\n        variable_type var = make_test_view_variable();\n        variable_view_type view = build_view(var);\n\n        auto vi00 = view.iselect({ { \"abscissa\", 0 },{ \"ordinate\", 0 } });\n        auto vi01 = view.iselect({ { \"abscissa\", 0 },{ \"ordinate\", 1 } });\n        auto vi02 = view.iselect({ { \"abscissa\", 0 },{ \"ordinate\", 2 } });\n        auto vi10 = view.iselect({ { \"abscissa\", 1 },{ \"ordinate\", 0 } });\n        auto vi11 = view.iselect({ { \"abscissa\", 1 },{ \"ordinate\", 1 } });\n        auto vi12 = view.iselect({ { \"abscissa\", 1 },{ \"ordinate\", 2 } });\n        auto vi20 = view.iselect({ { \"abscissa\", 2 },{ \"ordinate\", 0 } });\n        auto vi21 = view.iselect({ { \"abscissa\", 2 },{ \"ordinate\", 1 } });\n        auto vi22 = view.iselect({ { \"abscissa\", 2 },{ \"ordinate\", 2 } });\n        auto vi30 = view.iselect({ { \"abscissa\", 3 },{ \"ordinate\", 0 } });\n        auto vi31 = view.iselect({ { \"abscissa\", 3 },{ \"ordinate\", 1 } });\n        auto vi32 = view.iselect({ { \"abscissa\", 3 },{ \"ordinate\", 2 } });\n        auto vi40 = view.iselect({ { \"abscissa\", 4 },{ \"ordinate\", 0 } });\n        auto vi41 = view.iselect({ { \"abscissa\", 4 },{ \"ordinate\", 1 } });\n        auto vi42 = view.iselect({ { \"abscissa\", 4 },{ \"ordinate\", 2 } });\n\n        auto v00 = var.iselect({ { \"abscissa\", 3 },{ \"ordinate\", 0 } });\n        auto v01 = var.iselect({ { \"abscissa\", 3 },{ \"ordinate\", 2 } });\n        auto v02 = var.iselect({ { \"abscissa\", 3 },{ \"ordinate\", 4 } });\n        auto v10 = var.iselect({ { \"abscissa\", 4 },{ \"ordinate\", 0 } });\n        auto v11 = var.iselect({ { \"abscissa\", 4 },{ \"ordinate\", 2 } });\n        auto v12 = var.iselect({ { \"abscissa\", 4 },{ \"ordinate\", 4 } });\n        auto v20 = var.iselect({ { \"abscissa\", 5 },{ \"ordinate\", 0 } });\n        auto v21 = var.iselect({ { \"abscissa\", 5 },{ \"ordinate\", 2 } });\n        auto v22 = var.iselect({ { \"abscissa\", 5 },{ \"ordinate\", 4 } });\n        auto v30 = var.iselect({ { \"abscissa\", 6 },{ \"ordinate\", 0 } });\n        auto v31 = var.iselect({ { \"abscissa\", 6 },{ \"ordinate\", 2 } });\n        auto v32 = var.iselect({ { \"abscissa\", 6 },{ \"ordinate\", 4 } });\n        auto v40 = var.iselect({ { \"abscissa\", 7 },{ \"ordinate\", 0 } });\n        auto v41 = var.iselect({ { \"abscissa\", 7 },{ \"ordinate\", 2 } });\n        auto v42 = var.iselect({ { \"abscissa\", 7 },{ \"ordinate\", 4 } });\n\n        EXPECT_EQ(v00, vi00);\n        EXPECT_EQ(v01, vi01);\n        EXPECT_EQ(v02, vi02);\n        EXPECT_EQ(v10, vi10);\n        EXPECT_EQ(v11, vi11);\n        EXPECT_EQ(v12, vi12);\n        EXPECT_EQ(v20, vi20);\n        EXPECT_EQ(v21, vi21);\n        EXPECT_EQ(v22, vi22);\n        EXPECT_EQ(v30, vi30);\n        EXPECT_EQ(v31, vi31);\n        EXPECT_EQ(v32, vi32);\n        EXPECT_EQ(v40, vi40);\n        EXPECT_EQ(v41, vi41);\n        EXPECT_EQ(v42, vi42);\n    }\n\n    TEST(xvariable_view, locate)\n    {\n        variable_type var = make_test_view_variable();\n        variable_view_type view = build_view(var);\n\n        auto vi00 = view.locate(\"f\", 1);\n        auto vi01 = view.locate(\"f\", 4);\n        auto vi02 = view.locate(\"f\", 6);\n        auto vi10 = view.locate(\"g\", 1);\n        auto vi11 = view.locate(\"g\", 4);\n        auto vi12 = view.locate(\"g\", 6);\n        auto vi20 = view.locate(\"h\", 1);\n        auto vi21 = view.locate(\"h\", 4);\n        auto vi22 = view.locate(\"h\", 6);\n        auto vi30 = view.locate(\"m\", 1);\n        auto vi31 = view.locate(\"m\", 4);\n        auto vi32 = view.locate(\"m\", 6);\n        auto vi40 = view.locate(\"n\", 1);\n        auto vi41 = view.locate(\"n\", 4);\n        auto vi42 = view.locate(\"n\", 6);\n\n        auto v00 = var.locate(\"f\", 1);\n        auto v01 = var.locate(\"f\", 4);\n        auto v02 = var.locate(\"f\", 6);\n        auto v10 = var.locate(\"g\", 1);\n        auto v11 = var.locate(\"g\", 4);\n        auto v12 = var.locate(\"g\", 6);\n        auto v20 = var.locate(\"h\", 1);\n        auto v21 = var.locate(\"h\", 4);\n        auto v22 = var.locate(\"h\", 6);\n        auto v30 = var.locate(\"m\", 1);\n        auto v31 = var.locate(\"m\", 4);\n        auto v32 = var.locate(\"m\", 6);\n        auto v40 = var.locate(\"n\", 1);\n        auto v41 = var.locate(\"n\", 4);\n        auto v42 = var.locate(\"n\", 6);\n\n        EXPECT_EQ(v00, vi00);\n        EXPECT_EQ(v01, vi01);\n        EXPECT_EQ(v02, vi02);\n        EXPECT_EQ(v10, vi10);\n        EXPECT_EQ(v11, vi11);\n        EXPECT_EQ(v12, vi12);\n        EXPECT_EQ(v20, vi20);\n        EXPECT_EQ(v21, vi21);\n        EXPECT_EQ(v22, vi22);\n        EXPECT_EQ(v30, vi30);\n        EXPECT_EQ(v31, vi31);\n        EXPECT_EQ(v32, vi32);\n        EXPECT_EQ(v40, vi40);\n        EXPECT_EQ(v41, vi41);\n        EXPECT_EQ(v42, vi42);\n    }\n\n    TEST(xvariable_view, locate_element)\n    {\n        variable_type var = make_test_view_variable();\n        variable_view_type view = build_view(var);\n\n        auto vi00 = view.locate_element({ \"f\", 1 });\n        auto vi01 = view.locate_element({ \"f\", 4 });\n        auto vi02 = view.locate_element({ \"f\", 6 });\n        auto vi10 = view.locate_element({ \"g\", 1 });\n        auto vi11 = view.locate_element({ \"g\", 4 });\n        auto vi12 = view.locate_element({ \"g\", 6 });\n        auto vi20 = view.locate_element({ \"h\", 1 });\n        auto vi21 = view.locate_element({ \"h\", 4 });\n        auto vi22 = view.locate_element({ \"h\", 6 });\n        auto vi30 = view.locate_element({ \"m\", 1 });\n        auto vi31 = view.locate_element({ \"m\", 4 });\n        auto vi32 = view.locate_element({ \"m\", 6 });\n        auto vi40 = view.locate_element({ \"n\", 1 });\n        auto vi41 = view.locate_element({ \"n\", 4 });\n        auto vi42 = view.locate_element({ \"n\", 6 });\n\n        auto v00 = var.locate(\"f\", 1);\n        auto v01 = var.locate(\"f\", 4);\n        auto v02 = var.locate(\"f\", 6);\n        auto v10 = var.locate(\"g\", 1);\n        auto v11 = var.locate(\"g\", 4);\n        auto v12 = var.locate(\"g\", 6);\n        auto v20 = var.locate(\"h\", 1);\n        auto v21 = var.locate(\"h\", 4);\n        auto v22 = var.locate(\"h\", 6);\n        auto v30 = var.locate(\"m\", 1);\n        auto v31 = var.locate(\"m\", 4);\n        auto v32 = var.locate(\"m\", 6);\n        auto v40 = var.locate(\"n\", 1);\n        auto v41 = var.locate(\"n\", 4);\n        auto v42 = var.locate(\"n\", 6);\n\n        EXPECT_EQ(v00, vi00);\n        EXPECT_EQ(v01, vi01);\n        EXPECT_EQ(v02, vi02);\n        EXPECT_EQ(v10, vi10);\n        EXPECT_EQ(v11, vi11);\n        EXPECT_EQ(v12, vi12);\n        EXPECT_EQ(v20, vi20);\n        EXPECT_EQ(v21, vi21);\n        EXPECT_EQ(v22, vi22);\n        EXPECT_EQ(v30, vi30);\n        EXPECT_EQ(v31, vi31);\n        EXPECT_EQ(v32, vi32);\n        EXPECT_EQ(v40, vi40);\n        EXPECT_EQ(v41, vi41);\n        EXPECT_EQ(v42, vi42);\n    }\n\n    TEST(xvariable_view, view_squeeze)\n    {\n        variable_type var = make_test_view_variable();\n        variable_view_type view = select(var, { { \"abscissa\", \"f\"}, { \"ordinate\", range(1, 6, 2) } });\n        EXPECT_EQ(view.size(), 3u);\n        EXPECT_EQ(view.dimension(), 1u);\n        saxis_type s = { \"ordinate\" };\n        EXPECT_EQ(view.dimension_labels(), s.labels());\n\n        auto v0 = var.select({ { \"abscissa\", \"f\" },{ \"ordinate\", 1 } });\n        auto v1 = var.select({ { \"abscissa\", \"f\" },{ \"ordinate\", 4 } });\n        auto v2 = var.select({ { \"abscissa\", \"f\" },{ \"ordinate\", 6 } });\n\n        auto via0 = view(0);\n        auto via1 = view(1);\n        auto via2 = view(2);\n\n        EXPECT_EQ(via0, v0);\n        EXPECT_EQ(via1, v1);\n        EXPECT_EQ(via2, v2);\n\n        auto viae0 = view.element({ 0 });\n        auto viae1 = view.element({ 1 });\n        auto viae2 = view.element({ 2 });\n\n        EXPECT_EQ(viae0, v0);\n        EXPECT_EQ(viae1, v1);\n        EXPECT_EQ(viae2, v2);\n\n        auto vi0 = view.select({ { \"ordinate\", 1 } });\n        auto vi1 = view.select({ { \"ordinate\", 4 } });\n        auto vi2 = view.select({ { \"ordinate\", 6 } });\n\n        EXPECT_EQ(vi0, v0);\n        EXPECT_EQ(vi1, v1);\n        EXPECT_EQ(vi2, v2);\n\n        EXPECT_NO_THROW(var.select({ { \"abscissa\", \"f\" },{ \"ordinate\", 5 } }));\n        EXPECT_ANY_THROW(view.select({ { \"ordinate\", 5 } }));\n\n        auto vio0 = view.select<join::outer>({ { \"ordinate\", 1 } });\n        auto vio1 = view.select<join::outer>({ { \"ordinate\", 4 } });\n        auto vio2 = view.select<join::outer>({ { \"ordinate\", 6 } });\n\n        EXPECT_EQ(vio0, v0);\n        EXPECT_EQ(vio1, v1);\n        EXPECT_EQ(vio2, v2);\n\n        EXPECT_EQ(view.missing(), view.select<join::outer>({ { \"ordinate\", 2 } }));\n\n        auto vil0 = view.locate(1);\n        auto vil1 = view.locate(4);\n        auto vil2 = view.locate(6);\n\n        EXPECT_EQ(vil0, v0);\n        EXPECT_EQ(vil1, v1);\n        EXPECT_EQ(vil2, v2);\n\n        auto vile0 = view.locate_element({ 1 });\n        auto vile1 = view.locate_element({ 4 });\n        auto vile2 = view.locate_element({ 6 });\n\n        EXPECT_EQ(vile0, v0);\n        EXPECT_EQ(vile1, v1);\n        EXPECT_EQ(vile2, v2);\n\n        auto vii0 = view.iselect({ { \"ordinate\", 0 } });\n        auto vii1 = view.iselect({ { \"ordinate\", 1 } });\n        auto vii2 = view.iselect({ { \"ordinate\", 2 } });\n\n        EXPECT_EQ(vii0, v0);\n        EXPECT_EQ(vii1, v1);\n        EXPECT_EQ(vii2, v2);\n    }\n\n    TEST(xvariable_view, locate_builder)\n    {\n        variable_type var = make_test_view_variable();\n        variable_view_type view = build_view(var);\n        variable_view_type view2 = locate(var, range(\"f\", \"n\"), range(1, 6, 2));\n        EXPECT_EQ(view, view2);\n\n        variable_view_type view3 = select(var, { { \"abscissa\", \"f\" },{ \"ordinate\", range(1, 6, 2) } });\n        variable_view_type view4 = locate(var, \"f\", range(1, 6, 2));\n        EXPECT_EQ(view3, view4);\n\n        variable_view_type view5 = select(var, { {\"abscissa\", \"f\"} });\n        variable_view_type view6 = locate(var, \"f\", all());\n        EXPECT_EQ(view5, view6);\n    }\n\n    TEST(xvariable_view, iselect_builder)\n    {\n        variable_type var = make_test_view_variable();\n        variable_view_type view = build_view(var);\n        variable_view_type view2 = iselect(var, { {\"abscissa\", irange(3, 8)},\n                                                  {\"ordinate\", irange(0, 5, 2)} });\n        EXPECT_EQ(view, view2);\n\n        variable_view_type view3 = select(var, { { \"abscissa\", \"f\" },{ \"ordinate\", range(1, 6, 2) } });\n        variable_view_type view4 = iselect(var, { { \"abscissa\", 3 },{ \"ordinate\", irange(0, 5, 2) } });\n        EXPECT_EQ(view3, view4);\n\n        variable_view_type view5 = select(var, { { \"abscissa\", \"f\" } });\n        variable_view_type view6 = iselect(var, { { \"abscissa\", 3 } });\n        EXPECT_EQ(view5, view6);\n    }\n\n    TEST(xvariable_view, view_builder)\n    {\n        variable_type var = make_test_view_variable();\n        variable_view_type view = build_view(var);\n        variable_view_type view2 = ilocate(var, irange(3, 8), irange(0, 5, 2));\n        EXPECT_EQ(view, view2);\n\n        variable_view_type view3 = select(var, { { \"abscissa\", \"f\" },{ \"ordinate\", range(1, 6, 2) } });\n        variable_view_type view4 = ilocate(var, 3, irange(0, 5, 2));\n        EXPECT_EQ(view3, view4);\n\n        variable_view_type view5 = select(var, { { \"abscissa\", \"f\" } });\n        variable_view_type view6 = ilocate(var, 3, iall());\n        EXPECT_EQ(view5, view6);\n    }\n\n    TEST(xvariable_view, keep_slice)\n    {\n        variable_type var = make_test_view_variable();\n        variable_view_type view = locate(var, range(\"f\", \"n\"), range(1, 6, 2));\n        variable_view_type view2 = locate(var, xf::keep(\"f\", \"g\", \"h\", \"m\", \"n\"), range(1, 6, 2));\n        variable_view_type view3 = ilocate(var, ikeep(3, 4, 5, 6, 7), irange(0, 5, 2));\n        variable_view_type view4 = select(var, { { \"abscissa\", xf::keep(\"f\", \"g\", \"h\", \"m\", \"n\") },\n                                                 { \"ordinate\", range(1, 6, 2) } });\n        variable_view_type view5 = iselect(var, { { \"abscissa\", ikeep(3, 4, 5, 6, 7) },\n                                                  { \"ordinate\", irange(0, 5, 2) } });\n        \n        EXPECT_EQ(view, view2);\n        EXPECT_EQ(view, view3);\n        EXPECT_EQ(view, view4);\n        EXPECT_EQ(view, view5);\n    }\n\n    TEST(xvariable_view, drop_slice)\n    {\n        variable_type var = make_test_view_variable();\n        variable_view_type view = locate(var, range(\"f\", \"n\"), range(1, 6, 2));\n        variable_view_type view2 = locate(var, xf::drop(\"a\", \"c\", \"d\"), range(1, 6, 2));\n        variable_view_type view3 = ilocate(var, idrop(0, 1, 2), irange(0, 5, 2));\n        variable_view_type view4 = select(var, { { \"abscissa\", xf::drop(\"a\", \"c\", \"d\") },\n                                                 { \"ordinate\", range(1, 6, 2) } });\n        variable_view_type view5 = iselect(var, { { \"abscissa\", idrop(0, 1, 2) },\n                                                  { \"ordinate\", irange(0, 5, 2) } });\n\n        EXPECT_EQ(view, view2);\n        EXPECT_EQ(view, view3);\n        EXPECT_EQ(view, view4);\n        EXPECT_EQ(view, view5);\n    }\n}\n"
  },
  {
    "path": "test/test_xvariable_view_assign.cpp",
    "content": "/***************************************************************************\n* Copyright (c) Johan Mabille, Sylvain Corlay, Wolf Vollprecht and         *\n* Martin Renou                                                             *\n* Copyright (c) QuantStack                                                 *\n*                                                                          *\n* Distributed under the terms of the BSD 3-Clause License.                 *\n*                                                                          *\n* The full license is in the file LICENSE, distributed with this software. *\n****************************************************************************/\n\n#include \"gtest/gtest.h\"\n#include \"test_fixture.hpp\"\n#include \"xframe/xvariable_view.hpp\"\n\nnamespace xf\n{\n#define DEFINE_TEST_VIEW_VARIABLES()                                                              \\\n    DEFINE_TEST_VARIABLES();                                                                      \\\n    variable_type resaa =  3 * a;                                                                 \\\n    variable_type resab = 3 * (a + b);                                                            \\\n    variable_type rescd = 3 * (c + d);                                                            \\\n    auto va = select(a, { { \"abscissa\", range(\"a\", \"d\") },{ \"ordinate\", range(1, 4) } });         \\\n    auto vresaa = select(resaa, { { \"abscissa\", range(\"a\", \"d\") },{ \"ordinate\", range(1, 4) } }); \\\n    auto vb = select(b, { { \"abscissa\", range(\"a\", \"d\") },{ \"ordinate\", range(1, 4) } });         \\\n    auto vresab = select(resab, { { \"abscissa\", range(\"a\", \"d\") },{ \"ordinate\", range(1, 4) } }); \\\n    auto vc = select(c, {{\"abscissa\", range(\"a\", \"e\")}, {\"ordinate\", range(1, 5)}});              \\\n    auto vd = select(d, {{\"abscissa\", range(\"a\", \"e\")}, {\"ordinate\", range(1, 5)}});              \\\n    auto vrescd = select(rescd, {{\"abscissa\", range(\"a\", \"e\")}, {\"ordinate\", range(1, 5)}})\n\n    TEST(xvariable_view_assign, a_plus_b)\n    {\n        DEFINE_TEST_VIEW_VARIABLES();\n        {\n            SCOPED_TRACE(\"same coordinate\");\n            vresaa = va + va;\n            selector_list sl = make_selector_list_aa();\n            CHECK_EQUALITY(vresaa, va, va, sl, +)\n        }\n\n        {\n            SCOPED_TRACE(\"different coordinates\");\n            vresab = va + vb;\n            selector_list sl = make_selector_list_ab();\n            CHECK_EQUALITY(vresab, va, vb, sl, +)\n        }\n\n        {\n            SCOPED_TRACE(\"broadcasting coordinates\");\n            vrescd = vc + vd;\n            selector_list sl = make_selector_list_cd();\n            CHECK_EQUALITY(vrescd, vc, vd, sl, +)\n        }\n    }\n\n    TEST(xvariable_view_assign, assign_a_plus_b)\n    {\n        DEFINE_TEST_VIEW_VARIABLES();\n        {\n            SCOPED_TRACE(\"same coordinate\");\n            xt::noalias(vresaa) = va + va;\n            selector_list sl = make_selector_list_aa();\n            CHECK_EQUALITY(vresaa, va, va, sl, +)\n        }\n\n        {\n            SCOPED_TRACE(\"different coordinates\");\n            xt::noalias(vresab) = va + vb;\n            selector_list sl = make_selector_list_ab();\n            CHECK_EQUALITY(vresab, va, vb, sl, +)\n        }\n\n        {\n            SCOPED_TRACE(\"broadcasting coordinates\");\n            xt::noalias(vrescd) = vc + vd;\n            selector_list sl = make_selector_list_cd();\n            CHECK_EQUALITY(vrescd, vc, vd, sl, +)\n        }\n\n        {\n            SCOPED_TRACE(\"Incompatible shapes\");\n            EXPECT_ANY_THROW(xt::noalias(vresaa) = va + vb);\n        }\n    }\n}\n"
  },
  {
    "path": "test/test_xvector_variant.cpp",
    "content": "/***************************************************************************\n* Copyright (c) Johan Mabille, Sylvain Corlay, Wolf Vollprecht and         *\n* Martin Renou                                                             *\n* Copyright (c) QuantStack                                                 *\n*                                                                          *\n* Distributed under the terms of the BSD 3-Clause License.                 *\n*                                                                          *\n* The full license is in the file LICENSE, distributed with this software. *\n****************************************************************************/\n\n#include <string>\n#include <vector>\n\n#include \"gtest/gtest.h\"\n\n#include \"xtensor/xstorage.hpp\"\n#include \"xframe/xvector_variant.hpp\"\n\nnamespace xf\n{\n    TEST(xvector_variant, types)\n    {\n        using vector_type1 = xvector_variant<std::vector<double>, xt::svector<double>, xt::uvector<double>>;\n        using vector_type2 = xvector_variant<std::vector<double>, std::vector<int>>;\n        using vector_type3 = xvector_variant<std::vector<double>, xt::svector<int>>;\n\n        constexpr bool res1 = std::is_same<vector_type1::value_type, double>::value;\n        constexpr bool res2 = std::is_same<vector_type2::value_type, xtl::variant<double, int>>::value;\n        constexpr bool res3 = std::is_same<vector_type3::value_type, xtl::variant<double, int>>::value;\n\n        EXPECT_TRUE(res1);\n        EXPECT_TRUE(res2);\n        EXPECT_TRUE(res3);\n    }\n\n    TEST(xvector_variant_ref, types)\n    {\n        using vector_type1 = xvector_variant_ref<std::vector<double>, xt::svector<double>, xt::uvector<double>>;\n        using vector_type2 = xvector_variant_ref<std::vector<double>, std::vector<int>>;\n        using vector_type3 = xvector_variant_ref<std::vector<double>, xt::svector<int>>;\n\n        constexpr bool res1 = std::is_same<vector_type1::value_type, double>::value;\n        constexpr bool res2 = std::is_same<vector_type2::value_type, xtl::variant<double, int>>::value;\n        constexpr bool res3 = std::is_same<vector_type3::value_type, xtl::variant<double, int>>::value;\n\n        EXPECT_TRUE(res1);\n        EXPECT_TRUE(res2);\n        EXPECT_TRUE(res3);\n    }\n\n    TEST(xvector_variant_cref, types)\n    {\n        using vector_type1 = xvector_variant_cref<std::vector<double>, xt::svector<double>, xt::uvector<double>>;\n        using vector_type2 = xvector_variant_cref<std::vector<double>, std::vector<int>>;\n        using vector_type3 = xvector_variant_cref<std::vector<double>, xt::svector<int>>;\n\n        constexpr bool res1 = std::is_same<vector_type1::value_type, double>::value;\n        constexpr bool res2 = std::is_same<vector_type2::value_type, xtl::variant<double, int>>::value;\n        constexpr bool res3 = std::is_same<vector_type3::value_type, xtl::variant<double, int>>::value;\n\n        EXPECT_TRUE(res1);\n        EXPECT_TRUE(res2);\n        EXPECT_TRUE(res3);\n    }\n\n    using variant_type = xvector_variant<std::vector<double>, xt::svector<int>, xt::uvector<double>>;\n    using variant_ref_type = xvector_variant_ref<std::vector<double>, xt::svector<int>, xt::uvector<double>>;\n    using variant_cref_type = xvector_variant_cref<std::vector<double>, xt::svector<int>, xt::uvector<double>>;\n\n    std::vector<double> build_vector()\n    {\n        return {1., 3., 4., 6., 7.};\n    }\n\n    xt::svector<int> build_svector()\n    {\n        return {1, 3, 4, 6, 7};\n    }\n\n    xt::uvector<double> build_uvector()\n    {\n        return {1., 3., 4., 6., 7.};\n    }\n\n    /*****************************\n     * constructors / assignment *\n     *****************************/\n    \n    TEST(xvector_variant, constructor)\n    {\n        auto v = build_vector();\n        variant_type v1(v);\n        variant_type v2(std::move(v));\n        EXPECT_EQ(v1, v2);\n\n        auto sv = build_svector();\n        variant_type v3(sv);\n        variant_type v4(std::move(sv));\n        EXPECT_EQ(v3, v4);\n\n        auto uv = build_uvector();\n        variant_type v5(uv);\n        variant_type v6(std::move(uv));\n        EXPECT_EQ(v5, v6);\n    }\n\n    TEST(xvector_variant, copy_constructor)\n    {\n        auto v = build_vector();\n        variant_type v1(v);\n        variant_type v2(v1);\n        EXPECT_EQ(v1, v2);\n\n        auto sv = build_svector();\n        variant_type v3(sv);\n        variant_type v4(v3);\n        EXPECT_EQ(v3, v4);\n\n        auto uv = build_uvector();\n        variant_type v5(uv);\n        variant_type v6(v5);\n        EXPECT_EQ(v5, v6);\n    }\n\n    TEST(xvector_variant_ref, copy_constructor)\n    {\n        auto v = build_vector();\n        variant_ref_type v1(v);\n        variant_ref_type v2(v1);\n        EXPECT_EQ(v1, v2);\n\n        auto sv = build_svector();\n        variant_ref_type v3(sv);\n        variant_ref_type v4(v3);\n        EXPECT_EQ(v3, v4);\n\n        auto uv = build_uvector();\n        variant_ref_type v5(uv);\n        variant_ref_type v6(v5);\n        EXPECT_EQ(v5, v6);\n    }\n\n    TEST(xvector_variant_cref, copy_constructor)\n    {\n        auto v = build_vector();\n        variant_cref_type v1(v);\n        variant_cref_type v2(v1);\n        EXPECT_EQ(v1, v2);\n\n        auto sv = build_svector();\n        variant_cref_type v3(sv);\n        variant_cref_type v4(v3);\n        EXPECT_EQ(v3, v4);\n\n        auto uv = build_uvector();\n        variant_cref_type v5(uv);\n        variant_cref_type v6(v5);\n        EXPECT_EQ(v5, v6);\n    }\n\n    TEST(xvector_variant, move_constructor)\n    {\n        auto v = build_vector();\n        variant_type v1(v);\n        variant_type v1_bis(v1);\n        variant_type v2(std::move(v1_bis));\n        EXPECT_EQ(v1, v2);\n\n        auto sv = build_svector();\n        variant_type v3(sv);\n        variant_type v3_bis(v3);\n        variant_type v4(std::move(v3_bis));\n        EXPECT_EQ(v3, v4);\n\n        auto uv = build_uvector();\n        variant_type v5(uv);\n        variant_type v5_bis(v5);\n        variant_type v6(std::move(v5_bis));\n        EXPECT_EQ(v5, v6);\n    }\n\n    TEST(xvector_variant_ref, move_constructor)\n    {\n        auto v = build_vector();\n        variant_ref_type v1(v);\n        variant_ref_type v1_bis(v1);\n        variant_ref_type v2(std::move(v1_bis));\n        EXPECT_EQ(v1, v2);\n\n        auto sv = build_svector();\n        variant_ref_type v3(sv);\n        variant_ref_type v3_bis(v3);\n        variant_ref_type v4(std::move(v3_bis));\n        EXPECT_EQ(v3, v4);\n\n        auto uv = build_uvector();\n        variant_ref_type v5(uv);\n        variant_ref_type v5_bis(v5);\n        variant_ref_type v6(std::move(v5_bis));\n        EXPECT_EQ(v5, v6);\n    }\n\n    TEST(xvector_variant_cref, move_constructor)\n    {\n        auto v = build_vector();\n        variant_cref_type v1(v);\n        variant_cref_type v1_bis(v1);\n        variant_cref_type v2(std::move(v1_bis));\n        EXPECT_EQ(v1, v2);\n\n        auto sv = build_svector();\n        variant_cref_type v3(sv);\n        variant_cref_type v3_bis(v3);\n        variant_cref_type v4(std::move(v3_bis));\n        EXPECT_EQ(v3, v4);\n\n        auto uv = build_uvector();\n        variant_cref_type v5(uv);\n        variant_cref_type v5_bis(v5);\n        variant_cref_type v6(std::move(v5_bis));\n        EXPECT_EQ(v5, v6);\n    }\n\n    TEST(xvector_variant, assign)\n    {\n        auto v = build_vector();\n        variant_type v1(v);\n\n        auto uv = build_uvector();\n        variant_type v2(uv);\n        v1 = v2;\n        EXPECT_EQ(v1, v2);\n    }\n    \n    TEST(xvector_variant_ref, assign)\n    {\n        auto v = build_vector();\n        variant_ref_type v1(v);\n\n        auto uv = build_uvector();\n        variant_ref_type v2(uv);\n        v1 = v2;\n        EXPECT_EQ(v1, v2);\n    }\n\n    TEST(xvector_variant, move_assign)\n    {\n        auto v = build_vector();\n        variant_type v1(v);\n\n        auto uv = build_uvector();\n        variant_type v2_bis(uv);\n        variant_type v2(v2_bis);\n        v1 = std::move(v2_bis);\n        EXPECT_EQ(v1, v2);\n    }\n\n    TEST(xvector_variant_ref, move_assign)\n    {\n        auto v = build_vector();\n        variant_ref_type v1(v);\n\n        auto uv = build_uvector();\n        variant_ref_type v2_bis(uv);\n        variant_ref_type v2(v2_bis);\n        v1 = std::move(v2_bis);\n        EXPECT_EQ(v1, v2);\n    }\n\n    /*********************\n     * size and capacity *\n     *********************/\n\n    TEST(xvector_variant, empty)\n    {\n        auto v = build_vector();\n        variant_type vt(v);\n        EXPECT_FALSE(vt.empty());\n\n        std::vector<double> v2;\n        variant_type vt2(v2);\n        EXPECT_TRUE(vt2.empty());\n    }\n\n    TEST(xvector_variant_ref, empty)\n    {\n        auto v = build_vector();\n        variant_ref_type vt(v);\n        EXPECT_FALSE(vt.empty());\n\n        std::vector<double> v2;\n        variant_ref_type vt2(v2);\n        EXPECT_TRUE(vt2.empty());\n    }\n\n    TEST(xvector_variant_cref, empty)\n    {\n        auto v = build_vector();\n        variant_cref_type vt(v);\n        EXPECT_FALSE(vt.empty());\n\n        std::vector<double> v2;\n        variant_cref_type vt2(v2);\n        EXPECT_TRUE(vt2.empty());\n    }\n\n    TEST(xvector_variant, size)\n    {\n        auto v = build_vector();\n        variant_type vt(v);\n        variant_type vt2(build_vector());\n\n        EXPECT_EQ(vt.size(), v.size());\n        EXPECT_EQ(vt2.size(), v.size());\n    }\n\n    TEST(xvector_variant_ref, size)\n    {\n        auto v = build_vector();\n        auto v2= build_vector();\n        variant_ref_type vt(v);\n        variant_ref_type vt2(v2);\n\n        EXPECT_EQ(vt.size(), v.size());\n        EXPECT_EQ(vt2.size(), v.size());\n    }\n\n    TEST(xvector_variant_cref, size)\n    {\n        auto v = build_vector();\n        auto v2= build_vector();\n        variant_cref_type vt(v);\n        variant_cref_type vt2(v2);\n\n        EXPECT_EQ(vt.size(), v.size());\n        EXPECT_EQ(vt2.size(), v.size());\n    }\n\n    TEST(xvector_variant, resize)\n    {\n        auto v = build_vector();\n        variant_type vt(v);\n\n        vt.resize(8u);\n        EXPECT_EQ(vt.size(), 8u);\n    }\n\n    TEST(xvector_variant_ref, resize)\n    {\n        auto v = build_vector();\n        variant_ref_type vt(v);\n\n        vt.resize(8u);\n        EXPECT_EQ(vt.size(), 8u);\n        EXPECT_EQ(v.size(), 8u);\n    }\n\n    TEST(xvector_variant, max_size)\n    {\n        auto v = build_vector();\n        variant_type vt(v);\n        variant_type vt2(build_vector());\n\n        EXPECT_EQ(vt.max_size(), v.max_size());\n        EXPECT_EQ(vt2.max_size(), v.max_size());\n    }\n\n    TEST(xvector_variant, capacity)\n    {\n        auto v = build_vector();\n        variant_type vt(v);\n        variant_type vt2(build_vector());\n\n        EXPECT_EQ(vt.capacity(), v.capacity());\n        EXPECT_EQ(vt2.capacity(), v.capacity());\n    }\n\n    TEST(xvector_variant, reserve)\n    {\n        auto v = build_vector();\n        variant_type vt(v);\n        vt.reserve(20u);\n        EXPECT_EQ(vt.capacity(), 20u);\n    }\n\n    TEST(xvector_variant, shrink_to_fit)\n    {\n        auto v = build_vector();\n        variant_type vt(v);\n        vt.resize(2);\n        vt.shrink_to_fit();\n        EXPECT_EQ(vt.size(), vt.capacity());\n    }\n\n    TEST(xvector_variant, clear)\n    {\n        auto v = build_vector();\n        variant_type vt(v);\n\n        vt.clear();\n        EXPECT_TRUE(vt.empty());\n    }\n\n    /**********\n     * Access *\n     **********/\n    \n    TEST(xvector_variant, access)\n    {\n        auto v = build_svector();\n        variant_type vt(v);\n        const variant_type& vt2(vt);\n\n        xtl::xget<int&>(vt[0]) = 4;\n        int d = xtl::xget<const int&>(vt[0]);\n        EXPECT_EQ(d, 4);\n\n        int d2 = xtl::xget<const int&>(vt2[1]);\n        EXPECT_EQ(d2, v[1]);\n    }\n\n    TEST(xvector_variant_ref, access)\n    {\n        auto v = build_svector();\n        variant_ref_type vt(v);\n\n        xtl::xget<int&>(vt[0]) = 4;\n        int d = xtl::xget<const int&>(vt[0]);\n        EXPECT_EQ(d, 4);\n        EXPECT_EQ(v[0], 4);\n    }\n\n    TEST(xvector_variant_cref, access)\n    {\n        auto v = build_svector();\n        variant_cref_type vt(v);\n\n        int d = xtl::xget<const int&>(vt[0]);\n        EXPECT_EQ(v[0], d);\n    }\n\n    TEST(xvector_variant, at)\n    {\n        auto v = build_svector();\n        variant_type vt(v);\n        const variant_type& vt2(vt);\n\n        xtl::xget<int&>(vt.at(0)) = 4;\n        int d = xtl::xget<const int&>(vt.at(0));\n        EXPECT_EQ(d, 4);\n\n        int d2 = xtl::xget<const int&>(vt2.at(1));\n        EXPECT_EQ(d2, v[1]);\n\n        EXPECT_ANY_THROW(vt.at(6));\n    }\n\n    TEST(xvector_variant_ref, at)\n    {\n        auto v = build_svector();\n        variant_ref_type vt(v);\n\n        xtl::xget<int&>(vt.at(0)) = 4;\n        int d = xtl::xget<const int&>(vt.at(0));\n        EXPECT_EQ(d, 4);\n        EXPECT_EQ(v[0], 4);\n\n        EXPECT_ANY_THROW(vt.at(6));\n    }\n\n    TEST(xvector_variant_cref, at)\n    {\n        auto v = build_svector();\n        variant_ref_type vt(v);\n\n        int d = xtl::xget<const int&>(vt.at(0));\n        EXPECT_EQ(v[0], d);\n\n        EXPECT_ANY_THROW(vt.at(6));\n    }\n\n    TEST(xvector_variant, front)\n    {\n        auto v = build_svector();\n        variant_type vt(v);\n        const variant_type& vt2(vt);\n\n        xtl::xget<int&>(vt.front()) = 4;\n        int d = xtl::xget<const int&>(vt.front());\n        EXPECT_EQ(d, 4);\n\n        int d2 = xtl::xget<const int&>(vt2.front());\n        EXPECT_EQ(d2, 4);\n    }\n\n    TEST(xvector_variant_ref, front)\n    {\n        auto v = build_svector();\n        variant_ref_type vt(v);\n\n        xtl::xget<int&>(vt.front()) = 4;\n        int d = xtl::xget<const int&>(vt.front());\n        EXPECT_EQ(d, 4);\n        EXPECT_EQ(v.front(), 4);\n    }\n\n    TEST(xvector_variant_cref, front)\n    {\n        auto v = build_svector();\n        variant_ref_type vt(v);\n\n        int d = xtl::xget<const int&>(vt.front());\n        EXPECT_EQ(v.front(), d);\n    }\n\n    TEST(xvector_variant, back)\n    {\n        auto v = build_svector();\n        variant_type vt(v);\n        const variant_type& vt2(vt);\n\n        xtl::xget<int&>(vt.back()) = 4;\n        int d = xtl::xget<const int&>(vt.back());\n        EXPECT_EQ(d, 4);\n\n        int d2 = xtl::xget<const int&>(vt2.back());\n        EXPECT_EQ(d2, 4);\n    }\n\n    TEST(xvector_variant_ref, back)\n    {\n        auto v = build_svector();\n        variant_ref_type vt(v);\n\n        xtl::xget<int&>(vt.back()) = 4;\n        int d = xtl::xget<const int&>(vt.back());\n        EXPECT_EQ(d, 4);\n        EXPECT_EQ(v.back(), 4);\n    }\n\n    TEST(xvector_variant_cref, back)\n    {\n        auto v = build_svector();\n        variant_ref_type vt(v);\n\n        int d = xtl::xget<const int&>(vt.back());\n        EXPECT_EQ(v.back(), d);\n    }\n\n    TEST(xvector_variant, data)\n    {\n        auto v = build_svector();\n        variant_type vt(v);\n        const variant_type& vt2 = vt;\n\n        xtl::xget<int*>(vt.data())[0] = 4;\n        int d = xtl::xget<const int*>(vt2.data())[0];\n        EXPECT_EQ(d, 4);\n    }\n\n    TEST(xvector_variant_ref, data)\n    {\n        auto v = build_svector();\n        variant_ref_type vt(v);\n        const variant_ref_type& vt2 = vt;\n\n        xtl::xget<int*>(vt.data())[0] = 4;\n        int d = xtl::xget<const int*>(vt2.data())[0];\n        EXPECT_EQ(d, 4);\n        EXPECT_EQ(v[0], 4);\n    }\n\n    TEST(xvector_variant_cref, data)\n    {\n        auto v = build_svector();\n        variant_cref_type vt(v);\n\n        int d = xtl::xget<const int*>(vt.data())[0];\n        EXPECT_EQ(v[0], d);\n    }\n\n    TEST(xvector_variant, storage)\n    {\n        auto v = build_svector();\n        variant_type vt(v);\n        const variant_type& vt2 = vt;\n\n        xtl::xget<xt::svector<int>>(vt.storage())[0] = 4;\n        int d = xtl::xget<xt::svector<int>>(vt2.storage())[0];\n        EXPECT_EQ(d, 4);\n    }\n\n    TEST(xvector_variant_ref, storage)\n    {\n        auto v = build_svector();\n        variant_ref_type vt(v);\n        const variant_ref_type& vt2 = vt;\n\n        xtl::xget<xt::svector<int>&>(vt.storage())[0] = 4;\n        int d = xtl::xget<const xt::svector<int>&>(vt2.storage())[0];\n        EXPECT_EQ(d, 4);\n        EXPECT_EQ(v[0], 4);\n    }\n\n    TEST(xvector_variant_cref, storage)\n    {\n        auto v = build_svector();\n        variant_cref_type vt(v);\n\n        int d = xtl::xget<const xt::svector<int>&>(vt.storage())[0];\n        EXPECT_EQ(v[0], d);\n    }\n\n    /************\n     * Iterator *\n     ************/\n\n    TEST(xvector_variant_ref, iterator)\n    {\n        // 1, 3, 4, 6, 7\n        auto v = build_svector();\n        variant_ref_type vt(v);\n\n        auto iter = vt.begin();\n        xtl::xget<int&>(*iter) = 2;\n        EXPECT_EQ(v[0], 2);\n        ++iter;\n        xtl::xget<int&>(*iter) = 4;\n        EXPECT_EQ(v[1], 4);\n        iter += 2;\n        xtl::xget<int&>(*iter) = 21;\n        EXPECT_EQ(v[3], 21);\n        iter++;\n        iter -= 2;\n        xtl::xget<int&>(*iter) = 35;\n        EXPECT_EQ(v[2], 35);\n        --iter;\n        iter--;\n        iter += 5;\n        EXPECT_EQ(iter, vt.end());\n\n        EXPECT_EQ(vt.end() - vt.begin(), 5);\n        EXPECT_TRUE(vt.begin() < vt.end());\n    }\n\n    TEST(xvector_variant_ref, const_iterator)\n    {\n        // 1, 3, 4, 6, 7\n        auto v = build_svector();\n        variant_ref_type vt(v);\n\n        auto iter = vt.cbegin();\n        auto d0 = xtl::xget<const int&>(*iter);\n        EXPECT_EQ(d0, 1);\n        ++iter;\n        auto d1 = xtl::xget<const int&>(*iter);\n        EXPECT_EQ(d1, 3);\n        iter += 2;\n        auto d2 = xtl::xget<const int&>(*iter);\n        EXPECT_EQ(d2, 6);\n        iter++;\n        iter -= 2;\n        auto d3 = xtl::xget<const int&>(*iter);\n        EXPECT_EQ(d3, 4);\n        --iter;\n        iter--;\n        iter += 5;\n        EXPECT_EQ(iter, vt.cend());\n\n        EXPECT_EQ(vt.cend() - vt.cbegin(), 5);\n        EXPECT_TRUE(vt.cbegin() < vt.cend());\n    }\n\n    TEST(xvector_variant_cref, const_iterator)\n    {\n        // 1, 3, 4, 6, 7\n        auto v = build_svector();\n        variant_cref_type vt(v);\n\n        auto iter = vt.cbegin();\n        auto d0 = xtl::xget<const int&>(*iter);\n        EXPECT_EQ(d0, 1);\n        ++iter;\n        auto d1 = xtl::xget<const int&>(*iter);\n        EXPECT_EQ(d1, 3);\n        iter += 2;\n        auto d2 = xtl::xget<const int&>(*iter);\n        EXPECT_EQ(d2, 6);\n        iter++;\n        iter -= 2;\n        auto d3 = xtl::xget<const int&>(*iter);\n        EXPECT_EQ(d3, 4);\n        --iter;\n        iter--;\n        iter += 5;\n        EXPECT_EQ(iter, vt.cend());\n\n        EXPECT_EQ(vt.cend() - vt.cbegin(), 5);\n        EXPECT_TRUE(vt.cbegin() < vt.cend());\n    }\n\n    /********\n     * swap *\n     ********/\n\n    TEST(xvector_variant, swap)\n    {\n        auto v1 = build_svector();\n        auto v2 = xt::svector<int>();\n\n        variant_type vt1(v1);\n        variant_type vt2(v2);\n\n        variant_type vt1_bu(v1);\n        variant_type vt2_bu(v2);\n\n        using std::swap;\n        swap(vt1, vt2);\n\n        EXPECT_EQ(vt1, vt2_bu);\n        EXPECT_EQ(vt2, vt1_bu);\n    }\n\n    TEST(xvector_variant_ref, swap)\n    {\n        auto v1 = build_svector();\n        auto v2 = xt::svector<int>();\n\n        auto v1_bu = v1;\n        auto v2_bu = v2;\n\n        variant_ref_type vt1(v1);\n        variant_ref_type vt2(v2);\n\n        using std::swap;\n        swap(vt1, vt2);\n        \n        EXPECT_EQ(v1, v2_bu);\n        EXPECT_EQ(v2, v1_bu);\n    }\n\n    /***************\n     * xget_vector *\n     ***************/\n\n    TEST(xvector_variant, xget_vector)\n    {\n        auto v = build_svector();\n        variant_type vt(v);\n        const variant_type& vt2(vt);\n\n        auto& vl = xget_vector<xt::svector<int>>(vt);\n        vl[0] = 4;\n        const auto& cvl = xget_vector<xt::svector<int>>(vt2);\n        EXPECT_EQ(cvl[0], 4);\n\n        xt::svector<int>&& rvl = xget_vector<xt::svector<int>>(std::move(vt));\n        EXPECT_EQ(rvl[0], 4);\n\n        const xt::svector<int>&& crvl = xget_vector<xt::svector<int>>(std::move(vt2));\n        EXPECT_EQ(crvl[0], 4);\n    }\n\n    TEST(xvector_variant_ref, xget_vector)\n    {\n        auto v = build_svector();\n        variant_ref_type vt(v);\n        const variant_ref_type& vt2(vt);\n\n        auto& vl = xget_vector<xt::svector<int>>(vt);\n        vl[0] = 4;\n        const auto& cvl = xget_vector<xt::svector<int>>(vt2);\n        EXPECT_EQ(cvl[0], 4);\n        EXPECT_EQ(v[0], 4);\n\n        auto& rvl = xget_vector<xt::svector<int>>(std::move(vt));\n        EXPECT_EQ(rvl[0], 4);\n\n        const auto& crvl = xget_vector<xt::svector<int>>(std::move(vt2));\n        EXPECT_EQ(crvl[0], 4);\n    }\n\n    TEST(xvector_variant_cref, xget_vector)\n    {\n        auto v = build_svector();\n        variant_cref_type vt(v);\n        const variant_cref_type& vt2(vt);\n\n        auto& vl = xget_vector<xt::svector<int>>(vt);\n        EXPECT_EQ(vl, v);\n\n        const auto& cvl = xget_vector<xt::svector<int>>(vt2);\n        EXPECT_EQ(cvl, v);\n\n        auto& rvl = xget_vector<xt::svector<int>>(std::move(vt));\n        EXPECT_EQ(rvl, v);\n\n        const auto& crvl = xget_vector<xt::svector<int>>(std::move(vt2));\n        EXPECT_EQ(crvl, v);\n    }\n}\n\n"
  },
  {
    "path": "xframe.pc.in",
    "content": "prefix=@CMAKE_INSTALL_PREFIX@\nlibdir=${prefix}/@CMAKE_INSTALL_LIBDIR@\nincludedir=${prefix}/include\n\nName: xframe\nDescription: xframe is a C++ library meant for numerical analysis with Multi-dimensional labeled arrays and data frame based on xtensor.\nVersion: @xframe_VERSION@\nCflags: -I${includedir}\n"
  },
  {
    "path": "xframeConfig.cmake.in",
    "content": "############################################################################\n# Copyright (c) Johan Mabille and Sylvain Corlay                           #\n# Copyright (c) QuantStack                                                 #\n#                                                                          #\n# Distributed under the terms of the BSD 3-Clause License.                 #\n#                                                                          #\n# The full license is in the file LICENSE, distributed with this software. #\n############################################################################\n\n# xframe cmake module\n# This module sets the following variables in your project:\n#\n#   xframe_FOUND - true if xframe found on the system\n#   xframe_INCLUDE_DIRS - the directory containing xframe headers\n#   xframe_LIBRARY - empty\n\n@PACKAGE_INIT@\n\nset(PN xframe)\nset_and_check(${PN}_INCLUDE_DIRS \"${PACKAGE_PREFIX_DIR}/@CMAKE_INSTALL_INCLUDEDIR@\")\nset(${PN}_LIBRARY \"\")\ncheck_required_components(${PN})\n"
  }
]