├── notebooks └── images │ └── xframe.png ├── test ├── main.cpp ├── copyGTest.cmake.in ├── downloadGTest.cmake.in ├── test_xnamed_axis.cpp ├── test_xdimension.cpp ├── test_xaxis_variant.cpp ├── test_xframe_utils.cpp ├── test_xvariable_scalar.cpp ├── test_xvariable_view_assign.cpp ├── test_xsequence_view.cpp ├── test_xcoordinate_view.cpp ├── CMakeLists.txt ├── test_xaxis_function.cpp ├── test_xcoordinate.cpp ├── test_xaxis_default.cpp ├── test_xaxis_view.cpp ├── test_xvariable_noalias.cpp ├── test_xvariable_function.cpp ├── test_xaxis.cpp └── test_fixture_view.hpp ├── .gitignore ├── xframeConfig.cmake.in ├── README.md ├── .appveyor.yml ├── include └── xframe │ ├── xframe_config.hpp │ ├── xframe_expression.hpp │ ├── xvariable_math.hpp │ ├── xframe_trace.hpp │ ├── xaxis_scalar.hpp │ ├── xaxis_expression_leaf.hpp │ ├── xaxis_math.hpp │ ├── xvariable_meta.hpp │ ├── xaxis_index_slice.hpp │ ├── xnamed_axis.hpp │ ├── xaxis_meta.hpp │ ├── xcoordinate_view.hpp │ ├── xcoordinate_system.hpp │ ├── xvariable_scalar.hpp │ ├── xframe_utils.hpp │ ├── xaxis_function.hpp │ ├── xcoordinate_base.hpp │ ├── xaxis_label_slice.hpp │ ├── xdimension.hpp │ ├── xaxis_base.hpp │ ├── xvariable_assign.hpp │ └── xselecting.hpp ├── LICENSE ├── .travis.yml ├── CMakeLists.txt └── docs └── source └── xframe.svg /notebooks/images/xframe.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/D-K-E/xframe/master/notebooks/images/xframe.png -------------------------------------------------------------------------------- /test/main.cpp: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (c) 2017, Johan Mabille, Sylvain Corlay and Wolf Vollprecht * 3 | * * 4 | * Distributed under the terms of the BSD 3-Clause License. * 5 | * * 6 | * The full license is in the file LICENSE, distributed with this software. * 7 | ****************************************************************************/ 8 | 9 | #include "gtest/gtest.h" 10 | 11 | int main(int argc, char* argv[]) 12 | { 13 | ::testing::InitGoogleTest(&argc, argv); 14 | return RUN_ALL_TESTS(); 15 | } 16 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Compiled Object files 5 | *.slo 6 | *.lo 7 | *.o 8 | *.obj 9 | 10 | # Precompiled Headers 11 | *.gch 12 | *.pch 13 | 14 | # Compiled Dynamic libraries 15 | *.so 16 | *.dylib 17 | *.dll 18 | 19 | # Compiled Static libraries 20 | *.lai 21 | *.la 22 | *.a 23 | *.lib 24 | 25 | # Executables 26 | *.exe 27 | *.out 28 | *.app 29 | 30 | # Vim tmp files 31 | *.swp 32 | 33 | # Build directory 34 | build/ 35 | 36 | # Test build artefacts 37 | test/test_xtensor 38 | test/CMakeCache.txt 39 | test/Makefile 40 | test/CMakeFiles/ 41 | test/cmake_install.cmake 42 | 43 | # Documentation build artefacts 44 | docs/CMakeCache.txt 45 | docs/xml/ 46 | docs/build/ 47 | 48 | # Jupyter artefacts 49 | .ipynb_checkpoints/ 50 | 51 | # Generated files 52 | *.pc 53 | -------------------------------------------------------------------------------- /xframeConfig.cmake.in: -------------------------------------------------------------------------------- 1 | ############################################################################ 2 | # Copyright (c) 2017, Johan Mabille and Sylvain Corlay # 3 | # # 4 | # Distributed under the terms of the BSD 3-Clause License. # 5 | # # 6 | # The full license is in the file LICENSE, distributed with this software. # 7 | ############################################################################ 8 | 9 | # xframe cmake module 10 | # This module sets the following variables in your project: 11 | # 12 | # xframe_FOUND - true if xframe found on the system 13 | # xframe_INCLUDE_DIRS - the directory containing xframe headers 14 | # xframe_LIBRARY - empty 15 | 16 | @PACKAGE_INIT@ 17 | 18 | set(PN xframe) 19 | set_and_check(${PN}_INCLUDE_DIRS "${PACKAGE_PREFIX_DIR}/@CMAKE_INSTALL_INCLUDEDIR@") 20 | set(${PN}_LIBRARY "") 21 | check_required_components(${PN}) 22 | -------------------------------------------------------------------------------- /test/copyGTest.cmake.in: -------------------------------------------------------------------------------- 1 | ############################################################################ 2 | # Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht # 3 | # # 4 | # Distributed under the terms of the BSD 3-Clause License. # 5 | # # 6 | # The full license is in the file LICENSE, distributed with this software. # 7 | ############################################################################ 8 | 9 | cmake_minimum_required(VERSION 2.8.2) 10 | 11 | project(googletest-download NONE) 12 | 13 | include(ExternalProject) 14 | ExternalProject_Add(googletest 15 | URL "${GTEST_SRC_DIR}" 16 | SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/googletest-src" 17 | BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/googletest-build" 18 | CONFIGURE_COMMAND "" 19 | BUILD_COMMAND "" 20 | INSTALL_COMMAND "" 21 | TEST_COMMAND "" 22 | ) 23 | 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ![xframe](docs/source/xframe.svg) 2 | 3 | [![Travis](https://travis-ci.org/QuantStack/xframe.svg?branch=master)](https://travis-ci.org/QuantStack/xframe) 4 | [![Appveyor](https://ci.appveyor.com/api/projects/status/ob700oy60ee23r3q/branch/master?svg=true)](https://ci.appveyor.com/project/QuantStack/xframe/branch/master) 5 | [![Join the Gitter Chat](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/QuantStack/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) 6 | 7 | ## Introduction 8 | 9 | **xframe is an early developer preview, and is not suitable for general usage yet. Features and implementation are subject to change.** 10 | 11 | `xframe` is a dataframe for C++, based on [xtensor](https://github.com/QuantStack/xtensor) and [xtl](https://github.com/QuantStack/xtl). 12 | 13 | ## License 14 | 15 | We use a shared copyright model that enables all contributors to maintain the 16 | copyright on their contributions. 17 | 18 | This software is licensed under the BSD-3-Clause license. See the [LICENSE](LICENSE) file for details. 19 | -------------------------------------------------------------------------------- /test/downloadGTest.cmake.in: -------------------------------------------------------------------------------- 1 | ############################################################################ 2 | # Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht # 3 | # # 4 | # Distributed under the terms of the BSD 3-Clause License. # 5 | # # 6 | # The full license is in the file LICENSE, distributed with this software. # 7 | ############################################################################ 8 | 9 | cmake_minimum_required(VERSION 2.8.2) 10 | 11 | project(googletest-download NONE) 12 | 13 | include(ExternalProject) 14 | ExternalProject_Add(googletest 15 | GIT_REPOSITORY https://github.com/google/googletest.git 16 | GIT_TAG release-1.8.0 17 | SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/googletest-src" 18 | BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/googletest-build" 19 | CONFIGURE_COMMAND "" 20 | BUILD_COMMAND "" 21 | INSTALL_COMMAND "" 22 | TEST_COMMAND "" 23 | ) 24 | 25 | -------------------------------------------------------------------------------- /.appveyor.yml: -------------------------------------------------------------------------------- 1 | build: false 2 | 3 | os: Visual Studio 2015 4 | 5 | platform: 6 | - x64 7 | - x86 8 | 9 | environment: 10 | matrix: 11 | - MINICONDA: C:\xframe-conda 12 | 13 | init: 14 | - "ECHO %MINICONDA%" 15 | - C:\"Program Files (x86)"\"Microsoft Visual Studio 14.0"\VC\vcvarsall.bat %PLATFORM% 16 | - ps: if($env:Platform -eq "x64"){Start-FileDownload 'http://repo.continuum.io/miniconda/Miniconda3-latest-Windows-x86_64.exe' C:\Miniconda.exe; echo "Done"} 17 | - ps: if($env:Platform -eq "x86"){Start-FileDownload 'http://repo.continuum.io/miniconda/Miniconda3-latest-Windows-x86.exe' C:\Miniconda.exe; echo "Done"} 18 | - cmd: C:\Miniconda.exe /S /D=C:\xframe-conda 19 | - "set PATH=%MINICONDA%;%MINICONDA%\\Scripts;%MINICONDA%\\Library\\bin;%PATH%" 20 | 21 | install: 22 | - conda config --set always_yes yes --set changeps1 no 23 | - conda update -q conda 24 | - conda info -a 25 | - conda install gtest cmake -c conda-forge 26 | - conda install xtensor=0.18.0 -c QuantStack 27 | - cmake -G "NMake Makefiles" -D CMAKE_INSTALL_PREFIX=%MINICONDA%\\LIBRARY -DBUILD_TESTS=ON . 28 | - nmake test_xframe 29 | - cd test 30 | 31 | build_script: 32 | - .\test_xframe 33 | -------------------------------------------------------------------------------- /test/test_xnamed_axis.cpp: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (c) 2017, Johan Mabille, Sylvain Corlay and Wolf Vollprecht * 3 | * * 4 | * Distributed under the terms of the BSD 3-Clause License. * 5 | * * 6 | * The full license is in the file LICENSE, distributed with this software. * 7 | ****************************************************************************/ 8 | 9 | #include 10 | #include "gtest/gtest.h" 11 | 12 | #include "xframe/xnamed_axis.hpp" 13 | 14 | namespace xf 15 | { 16 | TEST(xnamed_axis, get_labels) 17 | { 18 | auto a = axis(56); 19 | auto n_a = named_axis("axis_a", a); 20 | auto labels = get_labels(n_a); 21 | 22 | EXPECT_EQ(labels, a.labels()); 23 | EXPECT_EQ(0u, labels[0]); 24 | EXPECT_EQ(56u, labels.size()); 25 | } 26 | 27 | TEST(xnamed_axis, name) 28 | { 29 | auto a = axis(56); 30 | auto n_a = named_axis("axis_a", a); 31 | EXPECT_EQ("axis_a", n_a.name()); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /include/xframe/xframe_config.hpp: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (c) 2017, Johan Mabille, Sylvain Corlay and Wolf Vollprecht * 3 | * * 4 | * Distributed under the terms of the BSD 3-Clause License. * 5 | * * 6 | * The full license is in the file LICENSE, distributed with this software. * 7 | ****************************************************************************/ 8 | 9 | #ifndef XFRAME_CONFIG_HPP 10 | #define XFRAME_CONFIG_HPP 11 | 12 | #define XFRAME_VERSION_MAJOR 0 13 | #define XFRAME_VERSION_MINOR 0 14 | #define XFRAME_VERSION_PATCH 1 15 | 16 | #ifndef DEFAULT_LABEL_LIST 17 | #include 18 | #include "xtl/xbasic_fixed_string.hpp" 19 | #include "xtl/xmeta_utils.hpp" 20 | #define DEFAULT_LABEL_LIST xtl::mpl::vector> 21 | #endif 22 | 23 | #ifndef DEFAULT_JOIN 24 | #define DEFAULT_JOIN join::inner 25 | #endif 26 | 27 | // A higher number leads to an ICE on VS 2015 28 | #ifndef STATIC_DIMENSION_LIMIT 29 | #define STATIC_DIMENSION_LIMIT 4 30 | #endif 31 | 32 | #ifndef XFRAME_ENABLE_TRACE 33 | #define XFRAME_ENABLE_TRACE 0 34 | #endif 35 | 36 | #ifndef XFRAME_OUT 37 | #define XFRAME_OUT std::cout 38 | #endif 39 | 40 | #endif 41 | -------------------------------------------------------------------------------- /include/xframe/xframe_expression.hpp: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (c) 2017, Johan Mabille, Sylvain Corlay and Wolf Vollprecht * 3 | * * 4 | * Distributed under the terms of the BSD 3-Clause License. * 5 | * * 6 | * The full license is in the file LICENSE, distributed with this software. * 7 | ****************************************************************************/ 8 | 9 | #ifndef XFRAME_XFRAME_EXPRESSION_HPP 10 | #define XFRAME_XFRAME_EXPRESSION_HPP 11 | 12 | #include "xtensor/xexpression.hpp" 13 | #include "xtl/xtype_traits.hpp" 14 | 15 | namespace xf 16 | { 17 | struct xvariable_expression_tag {}; 18 | struct xframe_expression_tag {}; 19 | 20 | template 21 | struct is_xvariable_expression : std::is_same, xvariable_expression_tag> 22 | { 23 | }; 24 | 25 | template 26 | struct xvariable_comparable : xtl::conjunction...> 27 | { 28 | }; 29 | 30 | struct xaxis_expression_tag {}; 31 | 32 | template 33 | struct is_xaxis_expression : std::is_same, xaxis_expression_tag> 34 | { 35 | }; 36 | 37 | template 38 | struct xaxis_comparable : xtl::conjunction...> 39 | { 40 | }; 41 | } 42 | 43 | #endif 44 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2017, 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | * Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /include/xframe/xvariable_math.hpp: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (c) 2017, Johan Mabille, Sylvain Corlay, Wolf Vollprecht and * 3 | * Martin Renou * 4 | * * 5 | * Distributed under the terms of the BSD 3-Clause License. * 6 | * * 7 | * The full license is in the file LICENSE, distributed with this software. * 8 | ****************************************************************************/ 9 | 10 | #ifndef XFRAME_XVARIABLE_MATH_HPP 11 | #define XFRAME_XVARIABLE_MATH_HPP 12 | 13 | #include "xframe_expression.hpp" 14 | #include "xaxis_math.hpp" 15 | #include "xvariable_function.hpp" 16 | 17 | namespace xt 18 | { 19 | namespace detail 20 | { 21 | template 22 | struct build_functor_type 23 | { 24 | using type = F; 25 | }; 26 | 27 | template 28 | struct select_xfunction_expression 29 | { 30 | using result_type = decltype(std::declval()(std::declval>>()...)); 31 | using type = xf::xvariable_function; 32 | }; 33 | } 34 | 35 | template 36 | inline std::enable_if_t::value, bool> 37 | operator==(const xexpression& e1, const xexpression& e2) 38 | { 39 | const E1& de1 = e1.derived_cast(); 40 | const E2& de2 = e2.derived_cast(); 41 | 42 | return de1.data() == de2.data() && 43 | de1.coordinates() == de2.coordinates() && 44 | de1.dimension_mapping() == de2.dimension_mapping(); 45 | } 46 | } 47 | 48 | #endif 49 | -------------------------------------------------------------------------------- /test/test_xdimension.cpp: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (c) 2017, Johan Mabille, Sylvain Corlay and Wolf Vollprecht * 3 | * * 4 | * Distributed under the terms of the BSD 3-Clause License. * 5 | * * 6 | * The full license is in the file LICENSE, distributed with this software. * 7 | ****************************************************************************/ 8 | 9 | #include "gtest/gtest.h" 10 | #include "xframe/xdimension.hpp" 11 | #include "xtl/xbasic_fixed_string.hpp" 12 | 13 | namespace xf 14 | { 15 | using fstring = xtl::xfixed_string<55>; 16 | using label_type = std::vector; 17 | using dimension_type = xdimension; 18 | 19 | TEST(xdimension, broadcast) 20 | { 21 | dimension_type d1 = { "a", "b", "d", "e" }; 22 | dimension_type d2 = { "d", "e" }; 23 | dimension_type d3 = { "h", "c", "a", "b", "d", "e" }; 24 | dimension_type d4 = { "h", "b", "c", "e" }; 25 | 26 | dimension_type res1; 27 | bool t1 = broadcast_dimensions(res1, d1, d2); 28 | EXPECT_TRUE(t1); 29 | EXPECT_EQ(res1.size(), 4u); 30 | EXPECT_EQ(res1["a"], 0); 31 | EXPECT_EQ(res1["b"], 1); 32 | EXPECT_EQ(res1["d"], 2); 33 | EXPECT_EQ(res1["e"], 3); 34 | 35 | dimension_type res2; 36 | bool t2 = broadcast_dimensions(res2, d1, d3); 37 | EXPECT_TRUE(t2); 38 | EXPECT_EQ(res2.size(), 6u); 39 | EXPECT_EQ(res2["h"], 0); 40 | EXPECT_EQ(res2["c"], 1); 41 | EXPECT_EQ(res2["a"], 2); 42 | EXPECT_EQ(res2["b"], 3); 43 | EXPECT_EQ(res2["d"], 4); 44 | EXPECT_EQ(res2["e"], 5); 45 | 46 | dimension_type res3; 47 | bool t3 = broadcast_dimensions(res3, d1, d4); 48 | EXPECT_FALSE(t3); 49 | EXPECT_EQ(res3.size(), 6u); 50 | EXPECT_EQ(res3["h"], 0); 51 | EXPECT_EQ(res3["c"], 1); 52 | EXPECT_EQ(res3["a"], 2); 53 | EXPECT_EQ(res3["b"], 3); 54 | EXPECT_EQ(res3["d"], 4); 55 | EXPECT_EQ(res3["e"], 5); 56 | } 57 | } 58 | 59 | -------------------------------------------------------------------------------- /test/test_xaxis_variant.cpp: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (c) 2017, Johan Mabille, Sylvain Corlay and Wolf Vollprecht * 3 | * * 4 | * Distributed under the terms of the BSD 3-Clause License. * 5 | * * 6 | * The full license is in the file LICENSE, distributed with this software. * 7 | ****************************************************************************/ 8 | 9 | #include 10 | #include 11 | #include "gtest/gtest.h" 12 | 13 | #include "xframe/xframe_config.hpp" 14 | #include "xframe/xaxis_variant.hpp" 15 | 16 | namespace xf 17 | { 18 | using axis_variant_type = xaxis_variant; 19 | 20 | TEST(xaxis_variant, get_labels) 21 | { 22 | auto a = axis_variant_type(axis(56)); 23 | auto labels = get_labels(a); 24 | 25 | EXPECT_EQ(0u, labels[0]); 26 | EXPECT_EQ(56u, labels.size()); 27 | } 28 | 29 | TEST(xaxis_variant, size) 30 | { 31 | auto a = axis_variant_type(axis(56)); 32 | EXPECT_EQ(56u, a.size()); 33 | EXPECT_FALSE(a.empty()); 34 | 35 | auto a2 = axis_variant_type(axis(0)); 36 | EXPECT_EQ(0u, a2.size()); 37 | EXPECT_TRUE(a2.empty()); 38 | } 39 | 40 | TEST(xaxis_variant, is_sorted) 41 | { 42 | auto a = axis_variant_type(axis(36, 56, 2)); 43 | EXPECT_TRUE(a.is_sorted()); 44 | } 45 | 46 | TEST(xaxis_variant, contains) 47 | { 48 | auto a = axis_variant_type(axis(36)); 49 | EXPECT_TRUE(a.contains(0)); 50 | EXPECT_TRUE(a.contains(15)); 51 | EXPECT_TRUE(a.contains(35)); 52 | EXPECT_FALSE(a.contains(36)); 53 | EXPECT_FALSE(a.contains(126)); 54 | EXPECT_FALSE(a.contains(-2)); 55 | } 56 | 57 | TEST(xaxis_variant, access) 58 | { 59 | auto a = axis_variant_type(axis(3)); 60 | auto a0 = a[0]; 61 | auto a1 = a[1]; 62 | auto a2 = a[2]; 63 | EXPECT_EQ(0u, a0); 64 | EXPECT_EQ(1u, a1); 65 | EXPECT_EQ(2u, a2); 66 | EXPECT_THROW(a[3], std::out_of_range); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /test/test_xframe_utils.cpp: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (c) 2017, Johan Mabille, Sylvain Corlay and Wolf Vollprecht * 3 | * * 4 | * Distributed under the terms of the BSD 3-Clause License. * 5 | * * 6 | * The full license is in the file LICENSE, distributed with this software. * 7 | ****************************************************************************/ 8 | 9 | #include "gtest/gtest.h" 10 | #include "xframe/xframe_utils.hpp" 11 | 12 | #include 13 | 14 | namespace xf 15 | { 16 | TEST(xframe_utils, merge_to) 17 | { 18 | std::vector v1 = { 1, 3, 4, 5, 7, 9, 10 }; 19 | std::vector v2 = { 1, 2, 4, 5, 6, 10, 11 }; 20 | std::vector v3 = { 4, 5, 8, 10 }; 21 | std::vector vres = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }; 22 | 23 | bool res1 = merge_to(v1, v2, v3); 24 | EXPECT_EQ(vres, v1); 25 | EXPECT_FALSE(res1); 26 | 27 | bool res2 = merge_to(vres, v1); 28 | EXPECT_EQ(vres, v1); 29 | EXPECT_TRUE(res2); 30 | 31 | std::vector v4 = {}; 32 | bool res3 = merge_to(v4, vres); 33 | EXPECT_EQ(vres, v4); 34 | EXPECT_TRUE(res3); 35 | 36 | std::vector v5 = {}; 37 | bool res4 = merge_to(v1, v5); 38 | EXPECT_EQ(v1, vres); 39 | EXPECT_FALSE(res4); 40 | } 41 | 42 | TEST(xframe_utils, intersect_to) 43 | { 44 | std::vector v1 = { 1, 3, 4, 5, 7, 9, 10 }; 45 | std::vector v2 = { 1, 2, 4, 5, 6, 10, 11 }; 46 | std::vector v3 = { 1, 4, 10 }; 47 | std::vector vres = { 1, 4, 10 }; 48 | 49 | bool res1 = intersect_to(v1, v2, v3); 50 | EXPECT_EQ(v1, vres); 51 | EXPECT_FALSE(res1); 52 | 53 | auto v4 = vres; 54 | auto v5 = v4; 55 | bool res2 = intersect_to(v5, v4); 56 | EXPECT_EQ(v5, vres); 57 | EXPECT_TRUE(res2); 58 | 59 | std::vector v6 = {}; 60 | bool res3 = intersect_to(v5, v6); 61 | EXPECT_TRUE(v5.empty()); 62 | EXPECT_FALSE(res3); 63 | } 64 | 65 | } 66 | 67 | -------------------------------------------------------------------------------- /include/xframe/xframe_trace.hpp: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (c) 2017, Johan Mabille, Sylvain Corlay and Wolf Vollprecht * 3 | * * 4 | * Distributed under the terms of the BSD 3-Clause License. * 5 | * * 6 | * The full license is in the file LICENSE, distributed with this software. * 7 | ****************************************************************************/ 8 | 9 | #ifndef XFRAME_XFRAME_TRACE_HPP 10 | #define XFRAME_XFRAME_TRACE_HPP 11 | 12 | #include 13 | 14 | #include "xframe_config.hpp" 15 | 16 | namespace xf 17 | { 18 | 19 | #if XFRAME_ENABLE_TRACE 20 | 21 | #define XFRAME_TRACE(expr) XFRAME_OUT << expr << std::endl; 22 | 23 | #define XFRAME_TRACE_BROADCAST_DIMENSIONS(lhs, rhs) \ 24 | XFRAME_TRACE("BROADCASTING DIMENSIONS"); \ 25 | XFRAME_TRACE("lhs = " << lhs); \ 26 | XFRAME_TRACE("rhs = " << rhs); 27 | 28 | #define XFRAME_TRACE_DIMENSIONS_RESULT(res, trivial) \ 29 | XFRAME_TRACE("res = " << res); \ 30 | XFRAME_TRACE("trivial broadcasting = " << trivial); 31 | 32 | #define XFRAME_TRACE_BROADCAST_COORDINATES(lhs, rhs) \ 33 | XFRAME_TRACE("BROADCASTING COORDINATES"); \ 34 | XFRAME_TRACE("lhs:") \ 35 | XFRAME_OUT << lhs; \ 36 | XFRAME_TRACE("rhs:") \ 37 | XFRAME_OUT << rhs; 38 | 39 | #define XFRAME_TRACE_COORDINATES_RESULT(res, trivial) \ 40 | XFRAME_TRACE("res:") \ 41 | XFRAME_OUT << res; \ 42 | XFRAME_TRACE("trivial broadcasting = (" << trivial.m_xtensor_trivial << ", " << trivial.m_xframe_trivial << ")"); 43 | #else 44 | #define XFRAME_TRACE(expr) 45 | #define XFRAME_TRACE_BROADCAST_DIMENSIONS(lhs, rhs) 46 | #define XFRAME_TRACE_DIMENSIONS_RESULT(res, trivial) 47 | #define XFRAME_TRACE_BROADCAST_COORDINATES(lhs, rhs) 48 | #define XFRAME_TRACE_COORDINATES_RESULT(res, trivial) 49 | #endif 50 | 51 | } 52 | 53 | #endif 54 | -------------------------------------------------------------------------------- /include/xframe/xaxis_scalar.hpp: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (c) 2017, Johan Mabille, Sylvain Corlay, Wolf Vollprecht and * 3 | * Martin Renou * 4 | * * 5 | * Distributed under the terms of the BSD 3-Clause License. * 6 | * * 7 | * The full license is in the file LICENSE, distributed with this software. * 8 | ****************************************************************************/ 9 | 10 | #ifndef XFRAME_XAXIS_SCALAR_HPP 11 | #define XFRAME_XAXIS_SCALAR_HPP 12 | 13 | #include "xtl/xvariant.hpp" 14 | #include "xtl/xmeta_utils.hpp" 15 | 16 | #include "xtensor/xoptional.hpp" 17 | 18 | #include "xframe_config.hpp" 19 | #include "xframe_utils.hpp" 20 | #include "xframe_expression.hpp" 21 | 22 | namespace xf 23 | { 24 | struct xaxis_scalar_name 25 | { 26 | }; 27 | 28 | /**************** 29 | * xaxis_scalar * 30 | ****************/ 31 | 32 | template 33 | class xaxis_scalar 34 | { 35 | public: 36 | 37 | using name_type = xaxis_scalar_name; 38 | 39 | using data_type = xt::xscalar; 40 | using value_type = typename data_type::value_type; 41 | using reference = typename data_type::reference; 42 | using const_reference = typename data_type::const_reference; 43 | using pointer = typename data_type::pointer; 44 | using const_pointer = typename data_type::const_pointer; 45 | using size_type = typename data_type::size_type; 46 | 47 | using expression_tag = xaxis_expression_tag; 48 | 49 | xaxis_scalar(const xt::xscalar& v) noexcept; 50 | 51 | template 52 | const_reference operator()(S&& /*selector*/) const; 53 | 54 | private: 55 | 56 | data_type m_data; 57 | }; 58 | 59 | /******************************* 60 | * xaxis_scalar implementation * 61 | *******************************/ 62 | 63 | template 64 | xaxis_scalar::xaxis_scalar(const xt::xscalar& v) noexcept 65 | : m_data(v) 66 | { 67 | } 68 | 69 | template 70 | template 71 | auto xaxis_scalar::operator()(S&& /*selector*/) const -> const_reference 72 | { 73 | return m_data; 74 | } 75 | } 76 | 77 | #endif 78 | -------------------------------------------------------------------------------- /include/xframe/xaxis_expression_leaf.hpp: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (c) 2017, Johan Mabille, Sylvain Corlay, Wolf Vollprecht and * 3 | * Martin Renou * 4 | * * 5 | * Distributed under the terms of the BSD 3-Clause License. * 6 | * * 7 | * The full license is in the file LICENSE, distributed with this software. * 8 | ****************************************************************************/ 9 | 10 | #ifndef XFRAME_XAXIS_EXPRESSION_LEAF_HPP 11 | #define XFRAME_XAXIS_EXPRESSION_LEAF_HPP 12 | 13 | #include "xtl/xvariant.hpp" 14 | #include "xtl/xmeta_utils.hpp" 15 | 16 | #include "xtensor/xoptional.hpp" 17 | 18 | #include "xframe_config.hpp" 19 | #include "xframe_utils.hpp" 20 | #include "xframe_expression.hpp" 21 | 22 | namespace xf 23 | { 24 | /************************* 25 | * xaxis_expression_leaf * 26 | *************************/ 27 | 28 | template 29 | class xaxis_expression_leaf : public xt::xexpression> 30 | { 31 | public: 32 | 33 | using named_axis_type = std::decay_t; 34 | using name_type = typename named_axis_type::name_type; 35 | using size_type = typename named_axis_type::size_type; 36 | 37 | using value_type = typename named_axis_type::value_type; 38 | using reference = typename named_axis_type::reference; 39 | using const_reference = typename named_axis_type::const_reference; 40 | using pointer = typename named_axis_type::pointer; 41 | using const_pointer = typename named_axis_type::const_pointer; 42 | 43 | template 44 | using selector_sequence_type = detail::xselector_sequence_t, N>; 45 | 46 | using expression_tag = xaxis_expression_tag; 47 | 48 | template 49 | xaxis_expression_leaf(AX&& n_axis) noexcept; 50 | 51 | template ::max()> 52 | const_reference operator()(const selector_sequence_type& selector) const; 53 | 54 | private: 55 | 56 | xaxis_closure_t m_named_axis; 57 | }; 58 | 59 | /**************************************** 60 | * xaxis_expression_leaf implementation * 61 | ****************************************/ 62 | 63 | template 64 | template 65 | inline xaxis_expression_leaf::xaxis_expression_leaf(AX&& n_axis) noexcept 66 | : m_named_axis(std::forward(n_axis)) 67 | { 68 | } 69 | 70 | template 71 | template 72 | auto xaxis_expression_leaf::operator()(const selector_sequence_type& selector) const -> const_reference 73 | { 74 | for (const auto& sel: selector) 75 | { 76 | if (m_named_axis.name() == sel.first) 77 | { 78 | return m_named_axis.label(sel.second); 79 | } 80 | } 81 | throw std::runtime_error(std::string("Missing label for axis ") + std::string(m_named_axis.name())); 82 | } 83 | } 84 | 85 | #endif 86 | -------------------------------------------------------------------------------- /test/test_xvariable_scalar.cpp: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (c) 2017, Johan Mabille, Sylvain Corlay and Wolf Vollprecht * 3 | * * 4 | * Distributed under the terms of the BSD 3-Clause License. * 5 | * * 6 | * The full license is in the file LICENSE, distributed with this software. * 7 | ****************************************************************************/ 8 | 9 | #include "gtest/gtest.h" 10 | #include "test_fixture.hpp" 11 | 12 | namespace xf 13 | { 14 | template 15 | struct DEBUG; 16 | 17 | TEST(xvariable_scalar, a_plus_b) 18 | { 19 | variable_type a = make_test_variable(); 20 | selector_list sl = make_selector_list_aa(); 21 | variable_type res = 2. + a; 22 | CHECK_SCALAR1_EQUALITY(res, 2, a, sl, +) 23 | variable_type res2 = a + 2.; 24 | CHECK_SCALAR2_EQUALITY(res2, a, 2, sl, +) 25 | } 26 | 27 | TEST(xvariable_scalar, a_minus_b) 28 | { 29 | variable_type a = make_test_variable(); 30 | selector_list sl = make_selector_list_aa(); 31 | variable_type res = 2. - a; 32 | CHECK_SCALAR1_EQUALITY(res, 2, a, sl, -) 33 | variable_type res2 = a - 2.; 34 | CHECK_SCALAR2_EQUALITY(res2, a, 2, sl, -) 35 | } 36 | 37 | TEST(xvariable_scalar, a_times_b) 38 | { 39 | variable_type a = make_test_variable(); 40 | selector_list sl = make_selector_list_aa(); 41 | variable_type res = 2. * a; 42 | CHECK_SCALAR1_EQUALITY(res, 2, a, sl, *) 43 | variable_type res2 = a * 2.; 44 | CHECK_SCALAR2_EQUALITY(res2, a, 2, sl, *) 45 | } 46 | 47 | TEST(xvariable_scalar, a_divided_by_b) 48 | { 49 | variable_type a = make_test_variable(); 50 | selector_list sl = make_selector_list_aa(); 51 | variable_type res = 2. / a; 52 | CHECK_SCALAR1_EQUALITY(res, 2, a, sl, /) 53 | variable_type res2 = a / 2.; 54 | CHECK_SCALAR2_EQUALITY(res2, a, 2, sl, /) 55 | } 56 | 57 | TEST(xvariable_scalar, a_plus_equal_b) 58 | { 59 | variable_type a = make_test_variable(); 60 | variable_type b = a; 61 | selector_list sl = make_selector_list_aa(); 62 | a += 2.; 63 | CHECK_SCALAR2_EQUALITY(a, b, 2, sl, +) 64 | } 65 | 66 | TEST(xvariable_scalar, a_minus_equal_b) 67 | { 68 | variable_type a = make_test_variable(); 69 | variable_type b = a; 70 | selector_list sl = make_selector_list_aa(); 71 | a -= 2.; 72 | CHECK_SCALAR2_EQUALITY(a, b, 2, sl, -) 73 | } 74 | 75 | TEST(xvariable_scalar, a_times_equal_b) 76 | { 77 | variable_type a = make_test_variable(); 78 | variable_type b = a; 79 | selector_list sl = make_selector_list_aa(); 80 | a *= 2.; 81 | CHECK_SCALAR2_EQUALITY(a, b, 2, sl, *) 82 | } 83 | 84 | TEST(xvariable_scalar, a_divided_by_equal_b) 85 | { 86 | variable_type a = make_test_variable(); 87 | variable_type b = a; 88 | selector_list sl = make_selector_list_aa(); 89 | a /= 2.; 90 | CHECK_SCALAR2_EQUALITY(a, b, 2, sl, /) 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /include/xframe/xaxis_math.hpp: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (c) 2017, Johan Mabille, Sylvain Corlay, Wolf Vollprecht and * 3 | * Martin Renou * 4 | * * 5 | * Distributed under the terms of the BSD 3-Clause License. * 6 | * * 7 | * The full license is in the file LICENSE, distributed with this software. * 8 | ****************************************************************************/ 9 | 10 | #ifndef XFRAME_XAXIS_MATH_HPP 11 | #define XFRAME_XAXIS_MATH_HPP 12 | 13 | #include "xtensor/xconcepts.hpp" 14 | #include "xtensor/xmath.hpp" 15 | 16 | #include "xframe_expression.hpp" 17 | #include "xaxis_function.hpp" 18 | 19 | namespace xt 20 | { 21 | namespace detail 22 | { 23 | template 24 | struct build_functor_type 25 | { 26 | using type = F; 27 | }; 28 | 29 | template 30 | struct select_xfunction_expression 31 | { 32 | using result_type = decltype(std::declval()(std::declval>>()...)); 33 | using type = xf::xaxis_function; 34 | }; 35 | } 36 | } 37 | 38 | namespace xf 39 | { 40 | using xt::operator+; 41 | using xt::operator-; 42 | using xt::operator*; 43 | using xt::operator/; 44 | using xt::operator%; 45 | 46 | using xt::operator||; 47 | using xt::operator&&; 48 | using xt::operator!; 49 | 50 | using xt::operator&; 51 | using xt::operator|; 52 | using xt::operator^; 53 | using xt::operator~; 54 | 55 | using xt::operator!=; 56 | using xt::operator<; 57 | using xt::operator<=; 58 | using xt::operator>; 59 | using xt::operator>=; 60 | 61 | using xt::equal; 62 | using xt::not_equal; 63 | 64 | using xt::abs; 65 | using xt::fabs; 66 | using xt::fmod; 67 | using xt::remainder; 68 | using xt::fma; 69 | using xt::fmax; 70 | using xt::fmin; 71 | using xt::fdim; 72 | // Needs a fix in xtensor 73 | //using xt::maximum; 74 | //using xt::minimum; 75 | //using xt::clip; 76 | using xt::sign; 77 | 78 | using xt::exp; 79 | using xt::exp2; 80 | using xt::expm1; 81 | using xt::log; 82 | using xt::log10; 83 | using xt::log2; 84 | using xt::log1p; 85 | 86 | using xt::pow; 87 | using xt::sqrt; 88 | using xt::cbrt; 89 | using xt::hypot; 90 | 91 | using xt::sin; 92 | using xt::cos; 93 | using xt::tan; 94 | using xt::asin; 95 | using xt::acos; 96 | using xt::atan; 97 | using xt::atan2; 98 | 99 | using xt::sinh; 100 | using xt::cosh; 101 | using xt::tanh; 102 | using xt::asinh; 103 | using xt::acosh; 104 | using xt::atanh; 105 | 106 | using xt::erf; 107 | using xt::erfc; 108 | using xt::tgamma; 109 | using xt::lgamma; 110 | 111 | using xt::ceil; 112 | using xt::floor; 113 | using xt::trunc; 114 | using xt::round; 115 | using xt::nearbyint; 116 | using xt::rint; 117 | 118 | using xt::isfinite; 119 | using xt::isinf; 120 | using xt::isnan; 121 | // Needs a fix in xtensor 122 | /*using xt::isclose; 123 | using xt::allclose;*/ 124 | } 125 | 126 | #endif 127 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: cpp 2 | dist: trusty 3 | matrix: 4 | include: 5 | - os: linux 6 | addons: 7 | apt: 8 | sources: 9 | - ubuntu-toolchain-r-test 10 | packages: 11 | - g++-4.9 12 | env: COMPILER=gcc GCC=4.9 13 | - os: linux 14 | addons: 15 | apt: 16 | sources: 17 | - ubuntu-toolchain-r-test 18 | packages: 19 | - g++-5 20 | env: COMPILER=gcc GCC=5 21 | - os: linux 22 | addons: 23 | apt: 24 | sources: 25 | - ubuntu-toolchain-r-test 26 | packages: 27 | - g++-6 28 | env: COMPILER=gcc GCC=6 29 | - os: linux 30 | addons: 31 | apt: 32 | sources: 33 | - ubuntu-toolchain-r-test 34 | packages: 35 | - g++-4.9 36 | - clang-3.6 37 | env: COMPILER=clang CLANG=3.6 38 | - os: linux 39 | addons: 40 | apt: 41 | sources: 42 | - ubuntu-toolchain-r-test 43 | - llvm-toolchain-trusty-3.9 44 | packages: 45 | - g++-4.9 46 | - clang-3.9 47 | env: COMPILER=clang CLANG=3.9 48 | - os: linux 49 | addons: 50 | apt: 51 | sources: 52 | - ubuntu-toolchain-r-test 53 | - llvm-toolchain-trusty-4.0 54 | packages: 55 | - g++-4.9 56 | - clang-4.0 57 | env: COMPILER=clang CLANG=4.0 58 | - os: linux 59 | addons: 60 | apt: 61 | sources: 62 | - ubuntu-toolchain-r-test 63 | - llvm-toolchain-trusty-5.0 64 | packages: 65 | - g++-4.9 66 | - clang-5.0 67 | env: COMPILER=clang CLANG=5.0 68 | - os: linux 69 | addons: 70 | apt: 71 | sources: 72 | - ubuntu-toolchain-r-test 73 | - llvm-toolchain-trusty-6.0 74 | packages: 75 | - clang-6.0 76 | env: COMPILER=clang CLANG=6.0 77 | - os: osx 78 | osx_image: xcode8 79 | compiler: clang 80 | env: 81 | global: 82 | - MINCONDA_VERSION="latest" 83 | - MINCONDA_LINUX="Linux-x86_64" 84 | - MINCONDA_OSX="MacOSX-x86_64" 85 | before_install: 86 | - | 87 | # Configure build variables 88 | if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then 89 | if [[ "$COMPILER" == "gcc" ]]; then 90 | export CXX=g++-$GCC CC=gcc-$GCC; 91 | fi 92 | if [[ "$COMPILER" == "clang" ]]; then 93 | export CXX=clang++-$CLANG CC=clang-$CLANG; 94 | fi 95 | elif [[ "$TRAVIS_OS_NAME" == "osx" ]]; then 96 | export CXX=clang++ CC=clang; 97 | fi 98 | install: 99 | # Define the version of miniconda to download 100 | - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then 101 | MINCONDA_OS=$MINCONDA_LINUX; 102 | elif [[ "$TRAVIS_OS_NAME" == "osx" ]]; then 103 | MINCONDA_OS=$MINCONDA_OSX; 104 | fi 105 | - wget "http://repo.continuum.io/miniconda/Miniconda3-$MINCONDA_VERSION-$MINCONDA_OS.sh" -O miniconda.sh; 106 | - bash miniconda.sh -b -p $HOME/miniconda 107 | - export PATH="$HOME/miniconda/bin:$PATH" 108 | - hash -r 109 | - conda config --set always_yes yes --set changeps1 no 110 | - conda update -q conda 111 | - conda install gtest cmake -c conda-forge 112 | - conda install xtensor=0.18.0 -c QuantStack 113 | # Testing 114 | - mkdir build 115 | - cd build 116 | - cmake -DBUILD_TESTS=ON ..; 117 | - make -j2 test_xframe 118 | - cd test 119 | script: 120 | - ./test_xframe 121 | -------------------------------------------------------------------------------- /test/test_xvariable_view_assign.cpp: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (c) 2017, Johan Mabille, Sylvain Corlay and Wolf Vollprecht * 3 | * * 4 | * Distributed under the terms of the BSD 3-Clause License. * 5 | * * 6 | * The full license is in the file LICENSE, distributed with this software. * 7 | ****************************************************************************/ 8 | 9 | #include "gtest/gtest.h" 10 | #include "test_fixture.hpp" 11 | #include "xframe/xvariable_view.hpp" 12 | 13 | namespace xf 14 | { 15 | #define DEFINE_TEST_VIEW_VARIABLES() \ 16 | DEFINE_TEST_VARIABLES(); \ 17 | variable_type resaa = 3 * a; \ 18 | variable_type resab = 3 * (a + b); \ 19 | variable_type rescd = 3 * (c + d); \ 20 | auto va = select(a, { { "abscissa", range("a", "d") },{ "ordinate", range(1, 4) } }); \ 21 | auto vresaa = select(resaa, { { "abscissa", range("a", "d") },{ "ordinate", range(1, 4) } }); \ 22 | auto vb = select(b, { { "abscissa", range("a", "d") },{ "ordinate", range(1, 4) } }); \ 23 | auto vresab = select(resab, { { "abscissa", range("a", "d") },{ "ordinate", range(1, 4) } }); \ 24 | auto vc = select(c, {{"abscissa", range("a", "e")}, {"ordinate", range(1, 5)}}); \ 25 | auto vd = select(d, {{"abscissa", range("a", "e")}, {"ordinate", range(1, 5)}}); \ 26 | auto vrescd = select(rescd, {{"abscissa", range("a", "e")}, {"ordinate", range(1, 5)}}) 27 | 28 | TEST(xvariable_view_assign, a_plus_b) 29 | { 30 | DEFINE_TEST_VIEW_VARIABLES(); 31 | { 32 | SCOPED_TRACE("same coordinate"); 33 | vresaa = va + va; 34 | selector_list sl = make_selector_list_aa(); 35 | CHECK_EQUALITY(vresaa, va, va, sl, +) 36 | } 37 | 38 | { 39 | SCOPED_TRACE("different coordinates"); 40 | vresab = va + vb; 41 | selector_list sl = make_selector_list_ab(); 42 | CHECK_EQUALITY(vresab, va, vb, sl, +) 43 | } 44 | 45 | { 46 | SCOPED_TRACE("broadcasting coordinates"); 47 | vrescd = vc + vd; 48 | selector_list sl = make_selector_list_cd(); 49 | CHECK_EQUALITY(vrescd, vc, vd, sl, +) 50 | } 51 | } 52 | 53 | TEST(xvariable_view_assign, assign_a_plus_b) 54 | { 55 | DEFINE_TEST_VIEW_VARIABLES(); 56 | { 57 | SCOPED_TRACE("same coordinate"); 58 | xt::noalias(vresaa) = va + va; 59 | selector_list sl = make_selector_list_aa(); 60 | CHECK_EQUALITY(vresaa, va, va, sl, +) 61 | } 62 | 63 | { 64 | SCOPED_TRACE("different coordinates"); 65 | xt::noalias(vresab) = va + vb; 66 | selector_list sl = make_selector_list_ab(); 67 | CHECK_EQUALITY(vresab, va, vb, sl, +) 68 | } 69 | 70 | { 71 | SCOPED_TRACE("broadcasting coordinates"); 72 | xt::noalias(vrescd) = vc + vd; 73 | selector_list sl = make_selector_list_cd(); 74 | CHECK_EQUALITY(vrescd, vc, vd, sl, +) 75 | } 76 | 77 | { 78 | SCOPED_TRACE("Incompatible shapes"); 79 | EXPECT_ANY_THROW(xt::noalias(vresaa) = va + vb); 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /test/test_xsequence_view.cpp: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (c) 2017, Johan Mabille, Sylvain Corlay and Wolf Vollprecht * 3 | * * 4 | * Distributed under the terms of the BSD 3-Clause License. * 5 | * * 6 | * The full license is in the file LICENSE, distributed with this software. * 7 | ****************************************************************************/ 8 | 9 | #include 10 | #include "gtest/gtest.h" 11 | #include "xframe/xsequence_view.hpp" 12 | 13 | namespace xf 14 | { 15 | class slice_test 16 | { 17 | public: 18 | 19 | using size_type = std::size_t; 20 | 21 | slice_test() = default; 22 | slice_test(size_type min_val, size_type max_val, size_type step) noexcept 23 | : m_min(min_val), m_size(size_type(std::ceil(double(max_val - min_val) / double(step)))), m_step(step) 24 | { 25 | } 26 | 27 | std::size_t size() const noexcept { return m_size; } 28 | size_type operator()(size_type i) const noexcept { return m_min + i * m_step; } 29 | 30 | private: 31 | 32 | size_type m_min; 33 | size_type m_size; 34 | size_type m_step; 35 | }; 36 | 37 | struct xsequence_view_feature 38 | { 39 | xsequence_view_feature(); 40 | 41 | using data_type = std::vector; 42 | using view_type = xsequence_view; 43 | data_type m_data; 44 | slice_test m_slice; 45 | view_type m_view; 46 | }; 47 | 48 | xsequence_view_feature::xsequence_view_feature() 49 | : m_data({ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }), m_slice(0, 10, 2), m_view(m_data, m_slice) 50 | { 51 | } 52 | 53 | TEST(xsequence_view, size) 54 | { 55 | xsequence_view_feature m_feature; 56 | EXPECT_EQ(m_feature.m_view.size(), 5); 57 | } 58 | 59 | TEST(xsequence_view, empty) 60 | { 61 | xsequence_view_feature m_feature; 62 | EXPECT_FALSE(m_feature.m_view.empty()); 63 | } 64 | 65 | TEST(xsequence_view, access) 66 | { 67 | xsequence_view_feature m_feature; 68 | EXPECT_EQ(m_feature.m_view[0], 0); 69 | EXPECT_EQ(m_feature.m_view[1], 2); 70 | EXPECT_EQ(m_feature.m_view[2], 4); 71 | EXPECT_EQ(m_feature.m_view[3], 6); 72 | EXPECT_EQ(m_feature.m_view[4], 8); 73 | 74 | EXPECT_EQ(m_feature.m_view.at(0), 0); 75 | EXPECT_EQ(m_feature.m_view.at(1), 2); 76 | EXPECT_EQ(m_feature.m_view.at(2), 4); 77 | EXPECT_EQ(m_feature.m_view.at(3), 6); 78 | EXPECT_EQ(m_feature.m_view.at(4), 8); 79 | EXPECT_ANY_THROW(m_feature.m_view.at(5)); 80 | 81 | EXPECT_EQ(m_feature.m_view.front(), 0); 82 | EXPECT_EQ(m_feature.m_view.back(), 8); 83 | } 84 | 85 | TEST(xsequence_view, iterator) 86 | { 87 | xsequence_view_feature m_feature; 88 | auto iter = m_feature.m_view.begin(); 89 | auto citer = m_feature.m_view.cbegin(); 90 | 91 | for (size_t i = 0; i < m_feature.m_view.size(); ++i) 92 | { 93 | EXPECT_EQ(*iter, m_feature.m_view[i]); 94 | EXPECT_EQ(*citer, m_feature.m_view[i]); 95 | ++iter, ++citer; 96 | } 97 | 98 | EXPECT_EQ(iter, m_feature.m_view.end()); 99 | EXPECT_EQ(citer, m_feature.m_view.cend()); 100 | 101 | iter = m_feature.m_view.begin(); 102 | citer = m_feature.m_view.cbegin(); 103 | iter += 2; 104 | citer += 2; 105 | EXPECT_EQ(*iter, m_feature.m_view[2]); 106 | EXPECT_EQ(*citer, m_feature.m_view[2]); 107 | EXPECT_EQ(m_feature.m_view.end() - iter, 3); 108 | EXPECT_EQ(m_feature.m_view.cend() - citer, 3); 109 | } 110 | } -------------------------------------------------------------------------------- /test/test_xcoordinate_view.cpp: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (c) 2017, Johan Mabille, Sylvain Corlay and Wolf Vollprecht * 3 | * * 4 | * Distributed under the terms of the BSD 3-Clause License. * 5 | * * 6 | * The full license is in the file LICENSE, distributed with this software. * 7 | ****************************************************************************/ 8 | 9 | #include 10 | #include 11 | #include "gtest/gtest.h" 12 | #include "test_fixture_view.hpp" 13 | 14 | namespace xf 15 | { 16 | TEST(xcoordinate_view, size) 17 | { 18 | auto c = make_test_view_coordinate(); 19 | auto cv = build_coordinate_view(c); 20 | 21 | EXPECT_EQ(2u, cv.size()); 22 | EXPECT_FALSE(cv.empty()); 23 | } 24 | 25 | TEST(xcoordinate_view, contains) 26 | { 27 | auto c = make_test_view_coordinate(); 28 | auto cv = build_coordinate_view(c); 29 | 30 | EXPECT_TRUE(cv.contains("abscissa")); 31 | EXPECT_FALSE(cv.contains("humidity")); 32 | } 33 | 34 | TEST(xcoordinate_view, access) 35 | { 36 | auto c = make_test_view_coordinate(); 37 | auto cv = build_coordinate_view(c); 38 | 39 | EXPECT_EQ(c["abscissa"]["f"], 3); 40 | EXPECT_EQ(c["abscissa"]["g"], 4); 41 | EXPECT_EQ(c["abscissa"]["h"], 5); 42 | EXPECT_EQ(c["abscissa"]["m"], 6); 43 | EXPECT_EQ(c["abscissa"]["n"], 7); 44 | EXPECT_EQ(c["ordinate"][1], 0); 45 | EXPECT_EQ(c["ordinate"][4], 2); 46 | EXPECT_EQ(c["ordinate"][6], 4); 47 | 48 | EXPECT_EQ(c[std::make_pair("abscissa", "f")], 3); 49 | EXPECT_EQ(c[std::make_pair("abscissa", "g")], 4); 50 | EXPECT_EQ(c[std::make_pair("abscissa", "h")], 5); 51 | EXPECT_EQ(c[std::make_pair("abscissa", "m")], 6); 52 | EXPECT_EQ(c[std::make_pair("abscissa", "n")], 7); 53 | EXPECT_EQ(c[std::make_pair("ordinate", 1)], 0); 54 | EXPECT_EQ(c[std::make_pair("ordinate", 4)], 2); 55 | EXPECT_EQ(c[std::make_pair("ordinate", 6)], 4); 56 | } 57 | 58 | TEST(xcoordinate_view, iterator) 59 | { 60 | auto c = make_test_view_coordinate(); 61 | auto cv = build_coordinate_view(c); 62 | 63 | auto iter = cv.cbegin(); 64 | EXPECT_EQ((iter->second)["f"], 3); 65 | ++iter; 66 | EXPECT_EQ((iter->second)[1], 0); 67 | ++iter; 68 | EXPECT_EQ(iter, cv.cend()); 69 | } 70 | 71 | TEST(xcoordinate_view, key_iterator) 72 | { 73 | auto c = make_test_view_coordinate(); 74 | auto cv = build_coordinate_view(c); 75 | 76 | auto iter = cv.key_begin(); 77 | EXPECT_EQ(*iter, "abscissa"); 78 | ++iter; 79 | EXPECT_EQ(*iter, "ordinate"); 80 | ++iter; 81 | EXPECT_EQ(iter, cv.key_end()); 82 | } 83 | 84 | TEST(xcoordinate_view, broadcasting) 85 | { 86 | auto c = make_test_view_coordinate(); 87 | auto vc = build_coordinate_view(c); 88 | 89 | auto c2 = coordinate({{fstring("altitude"), make_test_view_saxis()}}); 90 | xtrivial_broadcast res = c2.broadcast(vc); 91 | EXPECT_TRUE(res.m_xframe_trivial); 92 | EXPECT_FALSE(res.m_xtensor_trivial); 93 | 94 | const axis_variant& c2abscissa = c2["abscissa"]; 95 | axis_variant vcabscissa = axis_variant(vc["abscissa"]); 96 | const axis_variant& c2ordinate = c2["ordinate"]; 97 | axis_variant vcordinate = axis_variant(vc["ordinate"]); 98 | EXPECT_EQ(c2abscissa, vcabscissa); 99 | EXPECT_EQ(c2ordinate, vcordinate); 100 | 101 | 102 | auto c3 = c; 103 | xtrivial_broadcast res2 = c3.broadcast(vc); 104 | EXPECT_FALSE(res2.m_xframe_trivial); 105 | EXPECT_TRUE(res2.m_xtensor_trivial); 106 | const axis_variant& c3abscissa = c3["abscissa"]; 107 | const axis_variant& c3ordinate = c3["ordinate"]; 108 | EXPECT_EQ(c3abscissa, vcabscissa); 109 | EXPECT_EQ(c3ordinate, vcordinate); 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /include/xframe/xvariable_meta.hpp: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (c) 2017, Johan Mabille, Sylvain Corlay and Wolf Vollprecht * 3 | * * 4 | * Distributed under the terms of the BSD 3-Clause License. * 5 | * * 6 | * The full license is in the file LICENSE, distributed with this software. * 7 | ****************************************************************************/ 8 | 9 | #ifndef XFRAME_XVARIABLE_META_HPP 10 | #define XFRAME_XVARIABLE_META_HPP 11 | 12 | #include "xcoordinate.hpp" 13 | #include "xdimension.hpp" 14 | #include "xvariable_scalar.hpp" 15 | 16 | namespace xf 17 | { 18 | 19 | /********************* 20 | * xvariable_closure * 21 | *********************/ 22 | 23 | template 24 | struct xvariable_closure 25 | { 26 | using type = CT; 27 | }; 28 | 29 | template 30 | struct xvariable_closure> 31 | { 32 | using type = xvariable_scalar; 33 | }; 34 | 35 | template 36 | using xvariable_closure_t = typename xvariable_closure::type; 37 | 38 | /*************************** 39 | * xdecay_variable_closure * 40 | ***************************/ 41 | 42 | template 43 | struct xdecay_variable_closure 44 | { 45 | using type = std::decay_t>; 46 | }; 47 | 48 | template 49 | using xdecay_variable_closure_t = typename xdecay_variable_closure::type; 50 | 51 | /*************************** 52 | * xcommon_coordinate_type * 53 | ***************************/ 54 | 55 | namespace detail 56 | { 57 | template 58 | struct xcommon_coordinate_dimension; 59 | 60 | template 61 | struct xcommon_coordinate_dimension 62 | { 63 | using key_type = std::common_type_t; 64 | using mapped_type = std::common_type_t; 65 | using coordinate_type = xcoordinate; 66 | using dimension_type = xdimension; 67 | }; 68 | 69 | template 70 | struct xcommon_coordinate_dimension 71 | { 72 | using key_type = typename D::key_type; 73 | using mapped_type = typename D::mapped_type; 74 | using coordinate_type = xcoordinate; 75 | using dimension_type = xdimension; 76 | }; 77 | 78 | template 79 | struct xcommon_coordinate_dimension 80 | : xcommon_coordinate_dimension 81 | { 82 | }; 83 | 84 | template <> 85 | struct xcommon_coordinate_dimension 86 | { 87 | using coordinate_type = xfull_coordinate; 88 | using dimension_type = xfull_coordinate; 89 | }; 90 | 91 | template 92 | struct xcommon_coordinate_dimension 93 | : xcommon_coordinate_dimension 94 | { 95 | }; 96 | 97 | template 98 | struct xcommon_coordinate_dimension 99 | : xcommon_coordinate_dimension::dimension_type> 100 | { 101 | }; 102 | } 103 | 104 | template 105 | struct xcommon_coordinate_type 106 | { 107 | using type = typename detail::xcommon_coordinate_dimension::dimension_type...>::coordinate_type; 108 | }; 109 | 110 | template 111 | using xcommon_coordinate_type_t = typename xcommon_coordinate_type::type; 112 | 113 | template 114 | struct xcommon_dimension_type 115 | { 116 | using type = typename detail::xcommon_coordinate_dimension::dimension_type...>::dimension_type; 117 | }; 118 | 119 | template 120 | using xcommon_dimension_type_t = typename xcommon_dimension_type::type; 121 | } 122 | 123 | #endif 124 | -------------------------------------------------------------------------------- /include/xframe/xaxis_index_slice.hpp: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (c) 2017, Johan Mabille, Sylvain Corlay and Wolf Vollprecht * 3 | * * 4 | * Distributed under the terms of the BSD 3-Clause License. * 5 | * * 6 | * The full license is in the file LICENSE, distributed with this software. * 7 | ****************************************************************************/ 8 | 9 | #ifndef XFRAME_XAXIS_INDEX_SLICE_HPP 10 | #define XFRAME_XAXIS_INDEX_SLICE_HPP 11 | 12 | #include 13 | #include 14 | #include "xtl/xvariant.hpp" 15 | #include "xtensor/xstorage.hpp" 16 | #include "xtensor/xslice.hpp" 17 | 18 | namespace xf 19 | { 20 | 21 | /********************* 22 | * xaxis_index_slice * 23 | *********************/ 24 | 25 | template 26 | class xaxis_index_slice; 27 | 28 | namespace detail 29 | { 30 | template 31 | struct is_xaxis_index_slice : std::false_type 32 | { 33 | }; 34 | 35 | template 36 | struct is_xaxis_index_slice> : std::true_type 37 | { 38 | }; 39 | 40 | template 41 | using disable_xaxis_index_slice_t = std::enable_if_t>::value, void>; 42 | } 43 | 44 | template 45 | class xaxis_index_slice 46 | { 47 | public: 48 | 49 | using self_type = xaxis_index_slice; 50 | using size_type = T; 51 | using storage_type = xtl::variant, 52 | xt::xstepped_range, 53 | xt::xkeep_slice, 54 | xt::xdrop_slice, 55 | xt::xall>; 56 | 57 | xaxis_index_slice() = default; 58 | template > 59 | xaxis_index_slice(S&& slice) noexcept; 60 | 61 | size_type size() const noexcept; 62 | bool contains(size_type i) const noexcept; 63 | 64 | size_type operator()(size_type i) const noexcept; 65 | size_type step_size(size_type i, size_type n = 1) const noexcept; 66 | 67 | size_type revert_index(size_type i) const noexcept; 68 | 69 | bool operator==(const self_type& rhs) const noexcept; 70 | bool operator!=(const self_type& rhs) const noexcept; 71 | 72 | private: 73 | 74 | storage_type m_slice; 75 | }; 76 | 77 | /************************************ 78 | * xaxis_index_slice implementation * 79 | ************************************/ 80 | 81 | template 82 | template 83 | inline xaxis_index_slice::xaxis_index_slice(S&& slice) noexcept 84 | : m_slice(std::forward(slice)) 85 | { 86 | } 87 | 88 | template 89 | inline auto xaxis_index_slice::size() const noexcept -> size_type 90 | { 91 | return xtl::visit([](auto&& arg) { return arg.size(); }, m_slice); 92 | } 93 | 94 | template 95 | inline bool xaxis_index_slice::contains(size_type i) const noexcept 96 | { 97 | return xtl::visit([i](auto&& arg) { return arg.contains(i); }, m_slice); 98 | } 99 | 100 | template 101 | inline auto xaxis_index_slice::operator()(size_type i) const noexcept -> size_type 102 | { 103 | return xtl::visit([i](auto&& arg) { return arg(i); }, m_slice); 104 | } 105 | 106 | template 107 | inline auto xaxis_index_slice::step_size(size_type i, size_type n) const noexcept -> size_type 108 | { 109 | return xtl::visit([i, n](auto&& arg) { return arg.step_size(i, n); }, m_slice); 110 | } 111 | 112 | template 113 | inline auto xaxis_index_slice::revert_index(size_type i) const noexcept -> size_type 114 | { 115 | return xtl::visit([i](auto&& arg) { return arg.revert_index(i); }, m_slice); 116 | } 117 | 118 | template 119 | inline bool xaxis_index_slice::operator==(const self_type& rhs) const noexcept 120 | { 121 | return m_slice == rhs.m_slice; 122 | } 123 | 124 | template 125 | inline bool xaxis_index_slice::operator!=(const self_type& rhs) const noexcept 126 | { 127 | return !(*this == rhs); 128 | } 129 | } 130 | 131 | #endif 132 | -------------------------------------------------------------------------------- /test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ############################################################################ 2 | # Copyright (c) 2016, Johan Mabille and Sylvain Corlay # 3 | # # 4 | # Distributed under the terms of the BSD 3-Clause License. # 5 | # # 6 | # The full license is in the file LICENSE, distributed with this software. # 7 | ############################################################################ 8 | 9 | cmake_minimum_required(VERSION 3.1) 10 | 11 | if (CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR) 12 | project(xframe-test) 13 | 14 | find_package(xframe REQUIRED CONFIG) 15 | set(XFRAME_INCLUDE_DIR ${xframe_INCLUDE_DIRS}) 16 | endif () 17 | 18 | message(STATUS "Forcing tests build type to Release") 19 | set(CMAKE_BUILD_TYPE Release CACHE STRING "Choose the type of build." FORCE) 20 | 21 | include(CheckCXXCompilerFlag) 22 | 23 | string(TOUPPER "${CMAKE_BUILD_TYPE}" U_CMAKE_BUILD_TYPE) 24 | 25 | if (CMAKE_CXX_COMPILER_ID MATCHES "Clang" OR CMAKE_CXX_COMPILER_ID MATCHES "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES "Intel") 26 | #set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native -Wunused-parameter -Wextra -Wreorder -Wconversion -Wsign-conversion") 27 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native -Wunused-parameter -Wextra -Wreorder -Wconversion") 28 | CHECK_CXX_COMPILER_FLAG("-std=c++14" HAS_CPP14_FLAG) 29 | 30 | if (HAS_CPP14_FLAG) 31 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14") 32 | else() 33 | message(FATAL_ERROR "Unsupported compiler -- xframe requires C++14 support!") 34 | endif() 35 | endif() 36 | 37 | if(MSVC) 38 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /EHsc /MP /bigobj") 39 | set(CMAKE_EXE_LINKER_FLAGS /MANIFEST:NO) 40 | endif() 41 | 42 | if(DOWNLOAD_GTEST OR GTEST_SRC_DIR) 43 | if(DOWNLOAD_GTEST) 44 | # Download and unpack googletest at configure time 45 | configure_file(downloadGTest.cmake.in googletest-download/CMakeLists.txt) 46 | else() 47 | # Copy local source of googletest at configure time 48 | configure_file(copyGTest.cmake.in googletest-download/CMakeLists.txt) 49 | endif() 50 | execute_process(COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" . 51 | RESULT_VARIABLE result 52 | WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/googletest-download ) 53 | if(result) 54 | message(FATAL_ERROR "CMake step for googletest failed: ${result}") 55 | endif() 56 | execute_process(COMMAND ${CMAKE_COMMAND} --build . 57 | RESULT_VARIABLE result 58 | WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/googletest-download ) 59 | if(result) 60 | message(FATAL_ERROR "Build step for googletest failed: ${result}") 61 | endif() 62 | 63 | # Add googletest directly to our build. This defines 64 | # the gtest and gtest_main targets. 65 | add_subdirectory(${CMAKE_CURRENT_BINARY_DIR}/googletest-src 66 | ${CMAKE_CURRENT_BINARY_DIR}/googletest-build) 67 | 68 | set(GTEST_INCLUDE_DIRS "${gtest_SOURCE_DIR}/include") 69 | set(GTEST_BOTH_LIBRARIES gtest_main gtest) 70 | else() 71 | find_package(GTest REQUIRED) 72 | endif() 73 | 74 | find_package(Threads) 75 | 76 | include_directories(${XFRAME_INCLUDE_DIR}) 77 | include_directories(${GTEST_INCLUDE_DIRS}) 78 | 79 | set(XFRAME_TESTS 80 | main.cpp 81 | test_fixture.hpp 82 | test_fixture_view.hpp 83 | test_xaxis.cpp 84 | test_xaxis_default.cpp 85 | test_xaxis_function.cpp 86 | test_xaxis_variant.cpp 87 | test_xaxis_view.cpp 88 | test_xcoordinate.cpp 89 | test_xcoordinate_view.cpp 90 | test_xdimension.cpp 91 | test_xdynamic_variable.cpp 92 | test_xframe_utils.cpp 93 | test_xnamed_axis.cpp 94 | test_xsequence_view.cpp 95 | test_xvariable.cpp 96 | test_xvariable_assign.cpp 97 | test_xvariable_function.cpp 98 | test_xvariable_masked_view.cpp 99 | test_xvariable_noalias.cpp 100 | test_xvariable_scalar.cpp 101 | test_xvariable_view.cpp 102 | test_xvariable_view_assign.cpp 103 | ) 104 | 105 | set(XFRAME_TARGET test_xframe) 106 | 107 | add_executable(${XFRAME_TARGET} ${XFRAME_TESTS} ${XFRAME_HEADERS}) 108 | if(DOWNLOAD_GTEST OR GTEST_SRC_DIR) 109 | add_dependencies(${XFRAME_TARGET} gtest_main) 110 | endif() 111 | target_link_libraries(${XFRAME_TARGET} ${GTEST_BOTH_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}) 112 | 113 | add_custom_target(xtest COMMAND test_xframe DEPENDS ${XFRAME_TARGET}) 114 | -------------------------------------------------------------------------------- /include/xframe/xnamed_axis.hpp: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (c) 2017, Johan Mabille, Sylvain Corlay Wolf Vollprecht and * 3 | * Martin Renou * 4 | * * 5 | * Distributed under the terms of the BSD 3-Clause License. * 6 | * * 7 | * The full license is in the file LICENSE, distributed with this software. * 8 | ****************************************************************************/ 9 | 10 | #ifndef XFRAME_XNAMED_AXIS_HPP 11 | #define XFRAME_XNAMED_AXIS_HPP 12 | 13 | #include "xaxis_math.hpp" 14 | #include "xaxis.hpp" 15 | #include "xaxis_default.hpp" 16 | #include "xaxis_variant.hpp" 17 | 18 | namespace xf 19 | { 20 | 21 | /*************** 22 | * xnamed_axis * 23 | ***************/ 24 | 25 | template > 26 | class xnamed_axis : public xt::xexpression> 27 | { 28 | public: 29 | 30 | using name_type = K; 31 | using axis_variant_type = xaxis_variant; 32 | using size_type = typename axis_variant_type::size_type; 33 | 34 | using value_type = LT; 35 | using reference = value_type; 36 | using const_reference = const value_type; 37 | using pointer = value_type*; 38 | using const_pointer = const value_type*; 39 | 40 | using expression_tag = xaxis_expression_tag; 41 | 42 | template 43 | xnamed_axis(const name_type& name, A&& axis); 44 | template 45 | xnamed_axis(name_type&& name, A&& axis); 46 | 47 | const name_type& name() const & noexcept; 48 | 49 | const axis_variant_type& axis() const & noexcept; 50 | 51 | const value_type& label(size_type i) const & noexcept; 52 | 53 | private: 54 | 55 | name_type m_name; 56 | axis_variant_type m_axis; 57 | }; 58 | 59 | /****************************** 60 | * xnamed_axis implementation * 61 | ******************************/ 62 | 63 | template 64 | template 65 | inline xnamed_axis::xnamed_axis(const name_type& name, A&& axis) 66 | : m_name(name), m_axis(std::forward(axis)) 67 | { 68 | } 69 | 70 | template 71 | template 72 | inline xnamed_axis::xnamed_axis(name_type&& name, A&& axis) 73 | : m_name(std::move(name)), m_axis(std::forward(axis)) 74 | { 75 | } 76 | 77 | template 78 | inline auto xnamed_axis::name() const & noexcept -> const name_type& 79 | { 80 | return m_name; 81 | } 82 | 83 | template 84 | inline auto xnamed_axis::axis() const & noexcept -> const axis_variant_type& 85 | { 86 | return m_axis; 87 | } 88 | 89 | template 90 | inline auto xnamed_axis::label(size_type i) const & noexcept -> const LT& 91 | { 92 | return get_labels(m_axis)[i]; 93 | } 94 | 95 | template 96 | inline auto named_axis(const K& name, A&& axis) 97 | { 98 | static_assert(is_axis>::value, "axis must be an axis type"); 99 | 100 | using key_type = typename std::decay_t::key_type; 101 | using mapped_type = typename std::decay_t::mapped_type; 102 | 103 | return xnamed_axis(name, axis); 104 | } 105 | 106 | template 107 | inline auto named_axis(const char* name, A&& axis) 108 | { 109 | static_assert(is_axis>::value, "axis must be an axis type"); 110 | 111 | using key_type = typename std::decay_t::key_type; 112 | using mapped_type = typename std::decay_t::mapped_type; 113 | 114 | return xnamed_axis(name, axis); 115 | } 116 | 117 | template 118 | auto get_labels(const xnamed_axis& n_axis) -> const typename xaxis::label_list& 119 | { 120 | return get_labels(n_axis.axis()); 121 | } 122 | } 123 | 124 | #endif 125 | -------------------------------------------------------------------------------- /include/xframe/xaxis_meta.hpp: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (c) 2017, Johan Mabille, Sylvain Corlay, Wolf Vollprecht and * 3 | * Martin Renou * 4 | * * 5 | * Distributed under the terms of the BSD 3-Clause License. * 6 | * * 7 | * The full license is in the file LICENSE, distributed with this software. * 8 | ****************************************************************************/ 9 | 10 | #ifndef XFRAME_XAXIS_META_HPP 11 | #define XFRAME_XAXIS_META_HPP 12 | 13 | #include "xtl/xbasic_fixed_string.hpp" 14 | #include "xtl/xvariant.hpp" 15 | #include "xtl/xmeta_utils.hpp" 16 | 17 | #include "xframe_config.hpp" 18 | #include "xaxis_scalar.hpp" 19 | 20 | namespace xf 21 | { 22 | template 23 | class xnamed_axis; 24 | 25 | template 26 | class xaxis_expression_leaf; 27 | 28 | namespace detail 29 | { 30 | 31 | template 32 | struct common_name_type; 33 | 34 | template 35 | struct common_name_type 36 | { 37 | using tmp_type = typename common_name_type::type; 38 | using type = typename common_name_type::type; 39 | }; 40 | 41 | template 42 | struct common_name_type> 43 | { 44 | using type = typename T1::name_type; 45 | }; 46 | 47 | template 48 | struct common_name_type, T2> 49 | { 50 | using type = typename T2::name_type; 51 | }; 52 | 53 | template 54 | struct common_name_type, xaxis_scalar> 55 | { 56 | using type = xaxis_scalar_name; 57 | }; 58 | 59 | template 60 | struct common_name_type 61 | { 62 | using type = std::common_type_t; 63 | }; 64 | 65 | template 66 | using common_name_type_t = typename common_name_type::type; 67 | 68 | template 69 | struct axis_closure_getter 70 | { 71 | static auto get_axis_closure(CTA&& axis) 72 | { 73 | return xaxis_expression_leaf(std::forward(axis)); 74 | } 75 | }; 76 | 77 | template 78 | struct axis_closure_getter 79 | { 80 | static auto get_axis_closure(CTA&& axis) 81 | { 82 | return std::forward(axis); 83 | } 84 | }; 85 | 86 | template 87 | struct is_named_axis : std::false_type 88 | { 89 | }; 90 | 91 | template 92 | struct is_named_axis> : std::true_type 93 | { 94 | }; 95 | 96 | template 97 | auto get_axis_closure(CTA&& axis) 98 | { 99 | return axis_closure_getter>::value>::get_axis_closure(std::forward(axis)); 100 | } 101 | } 102 | 103 | /***************** 104 | * xaxis_closure * 105 | *****************/ 106 | 107 | template 108 | struct xaxis_closure 109 | { 110 | using type = CT; 111 | }; 112 | 113 | template 114 | using xaxis_closure_t = typename xaxis_closure::type; 115 | 116 | /**************************** 117 | * xaxis_expression_closure * 118 | ****************************/ 119 | 120 | template 121 | struct axis_expression_closure_getter 122 | { 123 | using type = xaxis_expression_leaf; 124 | }; 125 | 126 | template 127 | struct axis_expression_closure_getter 128 | { 129 | using type = CT; 130 | }; 131 | 132 | template 133 | struct axis_expression_closure_getter, false> 134 | { 135 | using type = xaxis_scalar; 136 | }; 137 | 138 | template 139 | struct xaxis_expression_closure 140 | { 141 | using type = typename axis_expression_closure_getter>::value>::type; 142 | }; 143 | 144 | template 145 | using xaxis_expression_closure_t = typename xaxis_expression_closure::type; 146 | } 147 | 148 | #endif 149 | -------------------------------------------------------------------------------- /include/xframe/xcoordinate_view.hpp: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (c) 2017, Johan Mabille, Sylvain Corlay and Wolf Vollprecht * 3 | * * 4 | * Distributed under the terms of the BSD 3-Clause License. * 5 | * * 6 | * The full license is in the file LICENSE, distributed with this software. * 7 | ****************************************************************************/ 8 | 9 | #ifndef XFRAME_XCOORDINATE_VIEW_HPP 10 | #define XFRAME_XCOORDINATE_VIEW_HPP 11 | 12 | #include "xaxis_view.hpp" 13 | #include "xcoordinate_base.hpp" 14 | 15 | namespace xf 16 | { 17 | 18 | /******************** 19 | * xcoordinate_view * 20 | ********************/ 21 | 22 | template 23 | class xcoordinate_view : public xcoordinate_base> 24 | { 25 | public: 26 | 27 | using self_type = xcoordinate_view; 28 | using base_type = xcoordinate_base>; 29 | using label_list = L; 30 | using axis_type = typename base_type::axis_type; 31 | using map_type = typename base_type::map_type; 32 | using key_type = typename base_type::key_type; 33 | using mapped_type = typename base_type::mapped_type; 34 | using index_type = typename base_type::index_type; 35 | using value_type = typename base_type::value_type; 36 | using reference = typename base_type::reference; 37 | using const_reference = typename base_type::const_reference; 38 | using pointer = typename base_type::pointer; 39 | using const_pointer = typename base_type::const_pointer; 40 | using size_type = typename base_type::size_type; 41 | using difference_type = typename base_type::difference_type; 42 | using iterator = typename base_type::iterator; 43 | using const_iterator = typename base_type::const_iterator; 44 | using key_iterator = typename base_type::key_iterator; 45 | 46 | explicit xcoordinate_view(const map_type& axes); 47 | explicit xcoordinate_view(map_type&& axes); 48 | 49 | bool operator==(const self_type& rhs) const noexcept; 50 | bool operator!=(const self_type& rhs) const noexcept; 51 | }; 52 | 53 | template 54 | xcoordinate_view coordinate_view(const std::map>& axes); 55 | 56 | template 57 | xcoordinate_view coordinate_view(std::map>&& axes); 58 | 59 | /************************* 60 | * xcoordinate_view_type * 61 | *************************/ 62 | 63 | template 64 | class xcoordinate; 65 | 66 | template 67 | struct xcoordinate_view_type; 68 | 69 | template 70 | struct xcoordinate_view_type> 71 | { 72 | using type = xcoordinate_view; 73 | }; 74 | 75 | template 76 | using xcoordinate_view_type_t = typename xcoordinate_view_type::type; 77 | 78 | /*********************************** 79 | * xcoordinate_view implementation * 80 | ***********************************/ 81 | 82 | template 83 | inline xcoordinate_view::xcoordinate_view(const map_type& axes) 84 | : base_type(axes) 85 | { 86 | } 87 | 88 | template 89 | inline xcoordinate_view::xcoordinate_view(map_type&& axes) 90 | : base_type(std::move(axes)) 91 | { 92 | } 93 | 94 | template 95 | inline bool xcoordinate_view::operator==(const self_type& rhs) const noexcept 96 | { 97 | return this->data() == rhs.data(); 98 | } 99 | 100 | template 101 | inline bool xcoordinate_view::operator!=(const self_type& rhs) const noexcept 102 | { 103 | return !(*this == rhs); 104 | } 105 | 106 | template 107 | inline xcoordinate_view coordinate_view(const std::map>& axes) 108 | { 109 | return xcoordinate_view(axes); 110 | } 111 | 112 | template 113 | inline xcoordinate_view coordinate_view(std::map>&& axes) 114 | { 115 | return xcoordinate_view(std::move(axes)); 116 | } 117 | } 118 | 119 | #endif 120 | -------------------------------------------------------------------------------- /test/test_xaxis_function.cpp: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (c) 2017, Johan Mabille, Sylvain Corlay Wolf Vollprecht and * 3 | * Martin Renou * 4 | * * 5 | * Distributed under the terms of the BSD 3-Clause License. * 6 | * * 7 | * The full license is in the file LICENSE, distributed with this software. * 8 | ****************************************************************************/ 9 | 10 | #include "gtest/gtest.h" 11 | 12 | #include "xtensor/xarray.hpp" 13 | #include "xtensor/xfunction.hpp" 14 | 15 | #include "xframe/xnamed_axis.hpp" 16 | 17 | #include "test_fixture.hpp" 18 | 19 | namespace xf 20 | { 21 | TEST(xaxis_function, plus_operator) 22 | { 23 | auto axis1 = named_axis("abs", axis(16)); 24 | auto axis2 = named_axis("ord", axis(10, 20, 1)); 25 | 26 | auto func1 = axis1 + axis2; 27 | EXPECT_EQ(func1({{"abs", 10}, {"ord", 5}}), 25); 28 | EXPECT_EQ(func1({{"abs", 15}, {"ord", 9}}), 34); 29 | } 30 | 31 | TEST(xaxis_function, pow_operator) 32 | { 33 | auto axis1 = named_axis("abs", axis(15)); 34 | auto axis2 = named_axis("ord", axis(10, 20, 1)); 35 | 36 | auto func1 = pow(axis2, axis1); 37 | EXPECT_EQ(func1({{"abs", 2}, {"ord", 5}}), 225); 38 | 39 | auto func2 = axis1 + axis2 + pow(axis2, axis1); 40 | EXPECT_EQ(func2({{"abs", 2}, {"ord", 5}}), 242); 41 | } 42 | 43 | TEST(xaxis_function, bool_operator) 44 | { 45 | auto axis1 = named_axis("abs", axis(15)); 46 | auto axis2 = named_axis("ord", axis(10, 20, 1)); 47 | auto axis3 = named_axis("alt", axis('b', 'j')); 48 | 49 | auto func1 = axis1 < 13u; 50 | EXPECT_EQ(func1({{"abs", 10}}), true); 51 | EXPECT_EQ(func1({{"abs", 14}}), false); 52 | 53 | auto func2 = axis1 > axis2; 54 | EXPECT_EQ(func2({{"abs", 10}, {"ord", 3}}), false); 55 | EXPECT_EQ(func2({{"abs", 14}, {"ord", 3}}), true); 56 | 57 | auto func3 = equal(axis3, 'b') || axis3 >= 'g' && not_equal(axis3, 'i'); 58 | EXPECT_EQ(func3({{"alt", 0}}), true); // b 59 | EXPECT_EQ(func3({{"alt", 1}}), false); // c 60 | EXPECT_EQ(func3({{"alt", 2}}), false); // d 61 | EXPECT_EQ(func3({{"alt", 3}}), false); // e 62 | EXPECT_EQ(func3({{"alt", 4}}), false); // f 63 | EXPECT_EQ(func3({{"alt", 5}}), true); // g 64 | EXPECT_EQ(func3({{"alt", 6}}), true); // h 65 | EXPECT_EQ(func3({{"alt", 7}}), false); // i 66 | } 67 | 68 | TEST(xaxis_function, xaxis_scalar) 69 | { 70 | auto axis1 = named_axis("abs", axis(15)); 71 | auto axis2 = named_axis("ord", axis(10, 20, 1)); 72 | 73 | auto func1 = axis1 < 13u; 74 | EXPECT_EQ(func1({{"abs", 10}}), true); 75 | EXPECT_EQ(func1({{"abs", 14}}), false); 76 | 77 | auto func2 = axis1 + axis2 + 4u; 78 | EXPECT_EQ(func2({{"abs", 10}, {"ord", 5}}), 29); 79 | } 80 | 81 | TEST(xaxis_function, mask) 82 | { 83 | auto axis1 = named_axis(fstring("abs"), axis({0, 2, 5})); 84 | auto axis2 = named_axis(fstring("ord"), axis({'a', 'c', 'i'})); 85 | 86 | auto array = xt::xarray({ 87 | {true, true, true}, 88 | {true, true, true}, 89 | {true, true, true} 90 | }); 91 | 92 | auto mask = axis_function_mask( 93 | equal(axis2, 'c') || equal(axis1, 0), 94 | dimension_type({"abs", "ord"}), 95 | array.shape() 96 | ); 97 | 98 | auto expected = xt::xarray({ 99 | { true, true, true}, 100 | {false, true, false}, 101 | {false, true, false} 102 | }); 103 | 104 | EXPECT_EQ(mask, expected); 105 | } 106 | 107 | TEST(xaxis_function, mask_op) 108 | { 109 | auto axis1 = named_axis(fstring("abs"), axis({0, 2, 5})); 110 | auto axis2 = named_axis(fstring("ord"), axis({'a', 'c', 'i'})); 111 | 112 | auto array = xt::xarray({ 113 | { true, true, false}, 114 | { true, true, true}, 115 | { true, true, true} 116 | }); 117 | 118 | auto mask = axis_function_mask( 119 | equal(axis2, 'i') || equal(axis1, 0), 120 | dimension_type({"abs", "ord"}), 121 | array.shape() 122 | ); 123 | 124 | auto expected = xt::xarray({ 125 | { true, true, false}, 126 | {false, false, true}, 127 | {false, false, true} 128 | }); 129 | 130 | xt::xarray val = array && mask; 131 | EXPECT_EQ(val, expected); 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /include/xframe/xcoordinate_system.hpp: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (c) 2017, Johan Mabille, Sylvain Corlay and Wolf Vollprecht * 3 | * * 4 | * Distributed under the terms of the BSD 3-Clause License. * 5 | * * 6 | * The full license is in the file LICENSE, distributed with this software. * 7 | ****************************************************************************/ 8 | 9 | #ifndef XFRAME_XCOORDINATE_SYSTEM_HPP 10 | #define XFRAME_XCOORDINATE_SYSTEM_HPP 11 | 12 | #include 13 | #include "xcoordinate.hpp" 14 | #include "xdimension.hpp" 15 | 16 | namespace xf 17 | { 18 | 19 | /********************** 20 | * xcoordinate_system * 21 | **********************/ 22 | 23 | template 24 | class xcoordinate_system 25 | { 26 | public: 27 | 28 | using derived_type = D; 29 | using inner_types = xt::xcontainer_inner_types; 30 | using coordinate_type = typename inner_types::coordinate_type; 31 | using coordinate_closure_type = typename inner_types::coordinate_closure_type; 32 | using dimension_type = typename inner_types::dimension_type; 33 | using dimension_list = typename dimension_type::label_list; 34 | using size_type = typename coordinate_type::size_type; 35 | 36 | size_type size() const noexcept; 37 | size_type dimension() const noexcept; 38 | const dimension_list& dimension_labels() const noexcept; 39 | const coordinate_type& coordinates() const noexcept; 40 | const dimension_type& dimension_mapping() const noexcept; 41 | 42 | template 43 | xtrivial_broadcast broadcast_coordinates(C& coords) const; 44 | bool broadcast_dimensions(dimension_type& dims, bool trivial_bc = false) const; 45 | 46 | protected: 47 | 48 | xcoordinate_system() = default; 49 | template 50 | xcoordinate_system(C&& coords, DM&& dims); 51 | ~xcoordinate_system() = default; 52 | 53 | xcoordinate_system(const xcoordinate_system&) = default; 54 | xcoordinate_system& operator=(const xcoordinate_system&) = default; 55 | 56 | xcoordinate_system(xcoordinate_system&&) = default; 57 | xcoordinate_system& operator=(xcoordinate_system&&) = default; 58 | 59 | template 60 | void resize(C&& coords, DM&& dims); 61 | 62 | private: 63 | 64 | coordinate_closure_type m_coordinate; 65 | dimension_type m_dimension_mapping; 66 | }; 67 | 68 | /************************************* 69 | * xcoordinate_system implementation * 70 | *************************************/ 71 | 72 | template 73 | template 74 | inline xcoordinate_system::xcoordinate_system(C&& coords, DM&& dims) 75 | : m_coordinate(std::forward(coords)), 76 | m_dimension_mapping(std::forward(dims)) 77 | { 78 | } 79 | 80 | template 81 | template 82 | inline void xcoordinate_system::resize(C&& coords, DM&& dims) 83 | { 84 | m_coordinate = std::forward(coords); 85 | m_dimension_mapping = std::forward(dims); 86 | } 87 | 88 | template 89 | inline auto xcoordinate_system::size() const noexcept -> size_type 90 | { 91 | return std::accumulate(m_coordinate.cbegin(), m_coordinate.cend(), size_type(1), 92 | [](size_type val, auto&& entry) { return val * entry.second.size(); }); 93 | } 94 | 95 | template 96 | inline auto xcoordinate_system::dimension() const noexcept -> size_type 97 | { 98 | return m_dimension_mapping.size(); 99 | } 100 | 101 | template 102 | inline auto xcoordinate_system::dimension_labels() const noexcept -> const dimension_list& 103 | { 104 | return m_dimension_mapping.labels(); 105 | } 106 | 107 | template 108 | inline auto xcoordinate_system::coordinates() const noexcept -> const coordinate_type& 109 | { 110 | return m_coordinate; 111 | } 112 | 113 | template 114 | inline auto xcoordinate_system::dimension_mapping() const noexcept -> const dimension_type& 115 | { 116 | return m_dimension_mapping; 117 | } 118 | 119 | template 120 | template 121 | inline xtrivial_broadcast xcoordinate_system::broadcast_coordinates(C& coords) const 122 | { 123 | return xf::broadcast_coordinates(coords, this->coordinates()); 124 | } 125 | 126 | template 127 | inline bool xcoordinate_system::broadcast_dimensions(dimension_type& dims, bool trivial_bc) const 128 | { 129 | bool ret = true; 130 | if (trivial_bc) 131 | { 132 | dims = this->dimension_mapping(); 133 | } 134 | else 135 | { 136 | ret = xf::broadcast_dimensions(dims, this->dimension_mapping()); 137 | } 138 | return ret; 139 | } 140 | 141 | } 142 | 143 | #endif 144 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ############################################################################ 2 | # Copyright (c) 2017, Johan Mabille and Sylvain Corlay # 3 | # # 4 | # Distributed under the terms of the BSD 3-Clause License. # 5 | # # 6 | # The full license is in the file LICENSE, distributed with this software. # 7 | ############################################################################ 8 | 9 | cmake_minimum_required(VERSION 3.1) 10 | project(xframe) 11 | 12 | set(XFRAME_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/include) 13 | 14 | # Versionning 15 | # =========== 16 | 17 | file(STRINGS "${XFRAME_INCLUDE_DIR}/xframe/xframe_config.hpp" xframe_version_defines 18 | REGEX "#define XFRAME_VERSION_(MAJOR|MINOR|PATCH)") 19 | foreach(ver ${xframe_version_defines}) 20 | if(ver MATCHES "#define XFRAME_VERSION_(MAJOR|MINOR|PATCH) +([^ ]+)$") 21 | set(XFRAME_VERSION_${CMAKE_MATCH_1} "${CMAKE_MATCH_2}" CACHE INTERNAL "") 22 | endif() 23 | endforeach() 24 | set(${PROJECT_NAME}_VERSION 25 | ${XFRAME_VERSION_MAJOR}.${XFRAME_VERSION_MINOR}.${XFRAME_VERSION_PATCH}) 26 | message(STATUS "xframe v${${PROJECT_NAME}_VERSION}") 27 | 28 | # Dependencies 29 | # ============ 30 | 31 | find_package(xtensor REQUIRED) 32 | include_directories(${xtensor_INCLUDE_DIRS}) 33 | 34 | find_package(xtl REQUIRED) 35 | include_directories(${xtl_INCLUDE_DIRS}) 36 | 37 | # Build 38 | # ===== 39 | 40 | set(XFRAME_HEADERS 41 | ${XFRAME_INCLUDE_DIR}/xframe/xaxis.hpp 42 | ${XFRAME_INCLUDE_DIR}/xframe/xaxis_base.hpp 43 | ${XFRAME_INCLUDE_DIR}/xframe/xaxis_default.hpp 44 | ${XFRAME_INCLUDE_DIR}/xframe/xaxis_expression_leaf.hpp 45 | ${XFRAME_INCLUDE_DIR}/xframe/xaxis_function.hpp 46 | ${XFRAME_INCLUDE_DIR}/xframe/xaxis_index_slice.hpp 47 | ${XFRAME_INCLUDE_DIR}/xframe/xaxis_label_slice.hpp 48 | ${XFRAME_INCLUDE_DIR}/xframe/xaxis_math.hpp 49 | ${XFRAME_INCLUDE_DIR}/xframe/xaxis_meta.hpp 50 | ${XFRAME_INCLUDE_DIR}/xframe/xaxis_scalar.hpp 51 | ${XFRAME_INCLUDE_DIR}/xframe/xaxis_variant.hpp 52 | ${XFRAME_INCLUDE_DIR}/xframe/xaxis_view.hpp 53 | ${XFRAME_INCLUDE_DIR}/xframe/xcoordinate.hpp 54 | ${XFRAME_INCLUDE_DIR}/xframe/xcoordinate_base.hpp 55 | ${XFRAME_INCLUDE_DIR}/xframe/xcoordinate_system.hpp 56 | ${XFRAME_INCLUDE_DIR}/xframe/xcoordinate_view.hpp 57 | ${XFRAME_INCLUDE_DIR}/xframe/xdimension.hpp 58 | ${XFRAME_INCLUDE_DIR}/xframe/xdynamic_variable.hpp 59 | ${XFRAME_INCLUDE_DIR}/xframe/xdynamic_variable_impl.hpp 60 | ${XFRAME_INCLUDE_DIR}/xframe/xframe_config.hpp 61 | ${XFRAME_INCLUDE_DIR}/xframe/xframe_expression.hpp 62 | ${XFRAME_INCLUDE_DIR}/xframe/xframe_trace.hpp 63 | ${XFRAME_INCLUDE_DIR}/xframe/xframe_utils.hpp 64 | ${XFRAME_INCLUDE_DIR}/xframe/xio.hpp 65 | ${XFRAME_INCLUDE_DIR}/xframe/xnamed_axis.hpp 66 | ${XFRAME_INCLUDE_DIR}/xframe/xselecting.hpp 67 | ${XFRAME_INCLUDE_DIR}/xframe/xsequence_view.hpp 68 | ${XFRAME_INCLUDE_DIR}/xframe/xvariable.hpp 69 | ${XFRAME_INCLUDE_DIR}/xframe/xvariable_assign.hpp 70 | ${XFRAME_INCLUDE_DIR}/xframe/xvariable_base.hpp 71 | ${XFRAME_INCLUDE_DIR}/xframe/xvariable_function.hpp 72 | ${XFRAME_INCLUDE_DIR}/xframe/xvariable_masked_view.hpp 73 | ${XFRAME_INCLUDE_DIR}/xframe/xvariable_math.hpp 74 | ${XFRAME_INCLUDE_DIR}/xframe/xvariable_meta.hpp 75 | ${XFRAME_INCLUDE_DIR}/xframe/xvariable_scalar.hpp 76 | ${XFRAME_INCLUDE_DIR}/xframe/xvariable_view.hpp 77 | ) 78 | 79 | OPTION(BUILD_TESTS "xframe test suite" OFF) 80 | OPTION(DOWNLOAD_GTEST "build gtest from downloaded sources" OFF) 81 | 82 | if(DOWNLOAD_GTEST OR GTEST_SRC_DIR) 83 | set(BUILD_TESTS ON) 84 | endif() 85 | 86 | if(BUILD_TESTS) 87 | add_subdirectory(test) 88 | endif() 89 | 90 | # Installation 91 | # ============ 92 | 93 | include(GNUInstallDirs) 94 | include(CMakePackageConfigHelpers) 95 | 96 | install(FILES ${XFRAME_HEADERS} 97 | DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/xframe) 98 | 99 | set(XFRAME_CMAKECONFIG_INSTALL_DIR "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}" CACHE 100 | STRING "install path for xframeConfig.cmake") 101 | 102 | configure_package_config_file(${PROJECT_NAME}Config.cmake.in 103 | "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake" 104 | INSTALL_DESTINATION ${XFRAME_CMAKECONFIG_INSTALL_DIR}) 105 | 106 | # xframe is header-only and does not depend on the architecture. 107 | # Remove CMAKE_SIZEOF_VOID_P from xframeConfigVersion.cmake so that an xframeConfig.cmake 108 | # generated for a 64 bit target can be used for 32 bit targets and vice versa. 109 | set(_XFRAME_CMAKE_SIZEOF_VOID_P ${CMAKE_SIZEOF_VOID_P}) 110 | unset(CMAKE_SIZEOF_VOID_P) 111 | write_basic_package_version_file(${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake 112 | VERSION ${${PROJECT_NAME}_VERSION} 113 | COMPATIBILITY AnyNewerVersion) 114 | set(CMAKE_SIZEOF_VOID_P ${_XFRAME_CMAKE_SIZEOF_VOID_P}) 115 | install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake 116 | ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake 117 | DESTINATION ${XFRAME_CMAKECONFIG_INSTALL_DIR}) 118 | -------------------------------------------------------------------------------- /docs/source/xframe.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | image/svg+xml 64 | -------------------------------------------------------------------------------- /include/xframe/xvariable_scalar.hpp: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (c) 2017, Johan Mabille, Sylvain Corlay and Wolf Vollprecht * 3 | * * 4 | * Distributed under the terms of the BSD 3-Clause License. * 5 | * * 6 | * The full license is in the file LICENSE, distributed with this software. * 7 | ****************************************************************************/ 8 | 9 | #ifndef XFRAME_XVARIABLE_SCALAR_HPP 10 | #define XFRAME_XVARIABLE_SCALAR_HPP 11 | 12 | #include "xtensor/xscalar.hpp" 13 | #include "xcoordinate.hpp" 14 | 15 | namespace xf 16 | { 17 | template 18 | class xvariable_scalar 19 | { 20 | public: 21 | 22 | using data_type = xt::xscalar; 23 | using value_type = typename data_type::value_type; 24 | using reference = typename data_type::reference; 25 | using const_reference = typename data_type::const_reference; 26 | using pointer = typename data_type::pointer; 27 | using const_pointer = typename data_type::const_pointer; 28 | using size_type = typename data_type::size_type; 29 | using difference_type = typename data_type::difference_type; 30 | 31 | using shape_type = std::array; 32 | 33 | using coordinate_type = xfull_coordinate; 34 | using dimension_type = xfull_coordinate; 35 | 36 | using expression_tag = xvariable_expression_tag; 37 | 38 | xvariable_scalar(const xt::xscalar& v) noexcept; 39 | 40 | size_type size() const noexcept; 41 | size_type dimension() const noexcept; 42 | coordinate_type coordinates() const noexcept; 43 | dimension_type dimension_mapping() const noexcept; 44 | const shape_type& shape() const noexcept; 45 | 46 | template 47 | const_reference operator()(Args... args) const noexcept; 48 | 49 | template 50 | xtrivial_broadcast broadcast_coordinates(C& coords) const noexcept; 51 | 52 | template 53 | bool broadcast_dimensions(D& dims, bool trivial_bc = false) const noexcept; 54 | 55 | data_type data() const noexcept; 56 | 57 | template 58 | const_reference select(const S&) const noexcept; 59 | 60 | private: 61 | 62 | data_type m_data; 63 | }; 64 | 65 | template 66 | struct is_xvariable_scalar : std::false_type 67 | { 68 | }; 69 | 70 | template 71 | struct is_xvariable_scalar> : std::true_type 72 | { 73 | }; 74 | 75 | /*********************************** 76 | * xvariable_scalar implementation * 77 | ***********************************/ 78 | 79 | template 80 | xvariable_scalar::xvariable_scalar(const xt::xscalar& v) noexcept 81 | : m_data(v) 82 | { 83 | } 84 | 85 | template 86 | inline auto xvariable_scalar::size() const noexcept -> size_type 87 | { 88 | return data().size(); 89 | } 90 | 91 | template 92 | inline auto xvariable_scalar::dimension() const noexcept -> size_type 93 | { 94 | return data().dimension(); 95 | } 96 | 97 | template 98 | inline auto xvariable_scalar::coordinates() const noexcept -> coordinate_type 99 | { 100 | return xfull_coordinate(); 101 | } 102 | 103 | template 104 | inline auto xvariable_scalar::dimension_mapping() const noexcept -> dimension_type 105 | { 106 | return xfull_coordinate(); 107 | } 108 | 109 | template 110 | inline auto xvariable_scalar::shape() const noexcept -> const shape_type& 111 | { 112 | static shape_type zero_shape; 113 | return zero_shape; 114 | } 115 | 116 | template 117 | template 118 | inline auto xvariable_scalar::operator()(Args... args) const noexcept -> const_reference 119 | { 120 | return data()(args...); 121 | } 122 | 123 | template 124 | template 125 | inline xtrivial_broadcast xvariable_scalar::broadcast_coordinates(C& /*coords*/) const noexcept 126 | { 127 | return xtrivial_broadcast(true, true); 128 | } 129 | 130 | template 131 | template 132 | bool xvariable_scalar::broadcast_dimensions(D& /*dims*/, bool /*trivial_bc*/) const noexcept 133 | { 134 | return true; 135 | } 136 | 137 | template 138 | inline auto xvariable_scalar::data() const noexcept -> data_type 139 | { 140 | return m_data; 141 | } 142 | 143 | template 144 | template 145 | inline auto xvariable_scalar::select(const S&) const noexcept -> const_reference 146 | { 147 | // TODO: should return data()() but this requires update of xtensor/xoptional.hpp 148 | // (split_optional_expression_impl needs to catch ref and const ref on xscalar) 149 | return m_data(); 150 | } 151 | } 152 | 153 | #endif 154 | -------------------------------------------------------------------------------- /test/test_xcoordinate.cpp: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (c) 2017, Johan Mabille, Sylvain Corlay and Wolf Vollprecht * 3 | * * 4 | * Distributed under the terms of the BSD 3-Clause License. * 5 | * * 6 | * The full license is in the file LICENSE, distributed with this software. * 7 | ****************************************************************************/ 8 | 9 | 10 | #include "gtest/gtest.h" 11 | #include "test_fixture.hpp" 12 | 13 | namespace xf 14 | { 15 | using slabel_type = std::vector; 16 | using ilabel_type = std::vector; 17 | 18 | TEST(xcoordinate, constructor) 19 | { 20 | auto c1 = make_test_coordinate(); 21 | 22 | using map_type = typename std::decay_t::map_type; 23 | map_type m; 24 | m["abscissa"] = make_test_saxis(); 25 | m["ordinate"] = make_test_iaxis(); 26 | 27 | auto c2 = coordinate(m); 28 | auto c3 = coordinate(std::move(m)); 29 | 30 | EXPECT_EQ(c1, c2); 31 | EXPECT_EQ(c1, c3); 32 | EXPECT_FALSE(c1 != c2); 33 | 34 | decltype(c1) c4 = {{ fstring("abscissa"), make_test_saxis() }, { fstring("ordinate"), make_test_iaxis() }}; 35 | EXPECT_EQ(c1, c4); 36 | 37 | decltype(c1) c5 = {{"abscissa", make_test_saxis()}, {"ordinate", make_test_iaxis()}}; 38 | EXPECT_EQ(c1, c5); 39 | } 40 | 41 | TEST(xcoordinate, size) 42 | { 43 | auto c1 = make_test_coordinate(); 44 | EXPECT_EQ(2u, c1.size()); 45 | EXPECT_FALSE(c1.empty()); 46 | 47 | decltype(c1) c2; 48 | EXPECT_EQ(0u, c2.size()); 49 | EXPECT_TRUE(c2.empty()); 50 | } 51 | 52 | TEST(xcoordinate, contains) 53 | { 54 | auto c = make_test_coordinate(); 55 | EXPECT_TRUE(c.contains("abscissa")); 56 | EXPECT_FALSE(c.contains("humidity")); 57 | } 58 | 59 | TEST(xcoordinate, access) 60 | { 61 | auto c = make_test_coordinate(); 62 | EXPECT_EQ(c["abscissa"]["a"], 0); 63 | EXPECT_EQ(c["abscissa"]["c"], 1); 64 | EXPECT_EQ(c["abscissa"]["d"], 2); 65 | EXPECT_EQ(c["ordinate"][1], 0); 66 | EXPECT_EQ(c["ordinate"][2], 1); 67 | EXPECT_EQ(c["ordinate"][4], 2); 68 | 69 | EXPECT_EQ(c[std::make_pair("abscissa", fstring("a"))], 0); 70 | EXPECT_EQ(c[std::make_pair("abscissa", fstring("c"))], 1); 71 | EXPECT_EQ(c[std::make_pair("abscissa", fstring("d"))], 2); 72 | EXPECT_EQ(c[std::make_pair("ordinate", 1)], 0); 73 | EXPECT_EQ(c[std::make_pair("ordinate", 2)], 1); 74 | EXPECT_EQ(c[std::make_pair("ordinate", 4)], 2); 75 | } 76 | 77 | TEST(xcoordinate, iterator) 78 | { 79 | auto c = make_test_coordinate(); 80 | auto iter = c.begin(); 81 | EXPECT_EQ((iter->second)["d"], 2); 82 | ++iter; 83 | EXPECT_EQ((iter->second)[2], 1); 84 | ++iter; 85 | EXPECT_EQ(iter, c.end()); 86 | } 87 | 88 | TEST(xcoordinate, key_iterator) 89 | { 90 | auto c = make_test_coordinate(); 91 | auto iter = c.key_begin(); 92 | EXPECT_EQ(*iter, "abscissa"); 93 | ++iter; 94 | EXPECT_EQ(*iter, "ordinate"); 95 | ++iter; 96 | EXPECT_EQ(iter, c.key_end()); 97 | } 98 | 99 | TEST(xcoordinate, merge) 100 | { 101 | auto coord_res = make_merge_coordinate(); 102 | auto c1 = make_test_coordinate(); 103 | decltype(c1) cres1; 104 | auto res1 = broadcast_coordinates(cres1, c1, c1); 105 | EXPECT_TRUE(res1.m_xtensor_trivial); 106 | EXPECT_TRUE(res1.m_xframe_trivial); 107 | EXPECT_EQ(c1, cres1); 108 | 109 | auto c2 = make_test_coordinate3(); 110 | decltype(c2) cres2; 111 | auto res2 = broadcast_coordinates(cres2, c1, c2); 112 | EXPECT_FALSE(res2.m_xtensor_trivial); 113 | EXPECT_FALSE(res2.m_xframe_trivial); 114 | EXPECT_EQ(cres2, coord_res); 115 | } 116 | 117 | TEST(xcoordinate, merge_axis_default) 118 | { 119 | auto coord_res = make_merge_coordinate2(); 120 | auto c1 = make_test_coordinate3(); 121 | auto c2 = make_test_coordinate4(); 122 | decltype(c1) cres1; 123 | broadcast_coordinates(cres1, c1, c2); 124 | EXPECT_EQ(cres1, coord_res); 125 | 126 | decltype(c1) cres2; 127 | broadcast_coordinates(cres2, c2, c1); 128 | EXPECT_EQ(cres1, cres2); 129 | } 130 | 131 | TEST(xcoordinate, intersect) 132 | { 133 | auto c1 = make_test_coordinate(); 134 | auto c2 = make_test_coordinate3(); 135 | 136 | auto coord_res = make_intersect_coordinate(); 137 | 138 | auto cres = c1; 139 | auto res = broadcast_coordinates(cres, c2); 140 | EXPECT_FALSE(res.m_xtensor_trivial); 141 | EXPECT_FALSE(res.m_xframe_trivial); 142 | EXPECT_EQ(cres, coord_res); 143 | } 144 | 145 | TEST(xcoordinate, intersect_axis_default) 146 | { 147 | auto c1 = make_test_coordinate3(); 148 | auto c2 = make_test_coordinate4(); 149 | 150 | auto coord_res = make_intersect_coordinate2(); 151 | 152 | decltype(c1) cres1; 153 | broadcast_coordinates(cres1, c1, c2); 154 | EXPECT_EQ(cres1, coord_res); 155 | 156 | decltype(c1) cres2; 157 | broadcast_coordinates(cres2, c2, c1); 158 | EXPECT_EQ(cres2, coord_res); 159 | } 160 | } 161 | -------------------------------------------------------------------------------- /test/test_xaxis_default.cpp: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (c) 2017, Johan Mabille, Sylvain Corlay and Wolf Vollprecht * 3 | * * 4 | * Distributed under the terms of the BSD 3-Clause License. * 5 | * * 6 | * The full license is in the file LICENSE, distributed with this software. * 7 | ****************************************************************************/ 8 | 9 | #include 10 | #include 11 | #include "gtest/gtest.h" 12 | 13 | #include "xframe/xaxis.hpp" 14 | #include "xframe/xaxis_default.hpp" 15 | 16 | namespace xf 17 | { 18 | using axis_type = xaxis; 19 | using label_type = std::vector; 20 | using axis_default_type = xaxis_default; 21 | 22 | TEST(xaxis_default, axis) 23 | { 24 | auto a = axis(4); 25 | auto labels = a.labels(); 26 | 27 | EXPECT_EQ(0u, labels[0]); 28 | EXPECT_EQ(1u, labels[1]); 29 | EXPECT_EQ(2u, labels[2]); 30 | EXPECT_EQ(3u, labels[3]); 31 | EXPECT_EQ(4u, labels.size()); 32 | } 33 | 34 | TEST(xaxis_default, labels) 35 | { 36 | axis_default_type a(4); 37 | label_type labels = a.labels(); 38 | 39 | EXPECT_EQ(0u, labels[0]); 40 | EXPECT_EQ(1u, labels[1]); 41 | EXPECT_EQ(2u, labels[2]); 42 | EXPECT_EQ(3u, labels[3]); 43 | EXPECT_EQ(4u, labels.size()); 44 | } 45 | 46 | TEST(xaxis_default, size) 47 | { 48 | axis_default_type a(36); 49 | EXPECT_EQ(36u, a.size()); 50 | EXPECT_EQ(a.labels().size(), a.size()); 51 | EXPECT_FALSE(a.empty()); 52 | 53 | axis_default_type a2; 54 | EXPECT_EQ(0u, a2.size()); 55 | EXPECT_TRUE(a2.empty()); 56 | } 57 | 58 | TEST(xaxis_default, is_sorted) 59 | { 60 | axis_default_type a(36); 61 | EXPECT_TRUE(a.is_sorted()); 62 | } 63 | 64 | TEST(xaxis_default, contains) 65 | { 66 | axis_default_type a(36); 67 | EXPECT_TRUE(a.contains(0)); 68 | EXPECT_TRUE(a.contains(15)); 69 | EXPECT_TRUE(a.contains(35)); 70 | EXPECT_FALSE(a.contains(36)); 71 | EXPECT_FALSE(a.contains(126)); 72 | EXPECT_FALSE(a.contains(-2)); 73 | } 74 | 75 | TEST(xaxis_default, access) 76 | { 77 | axis_default_type a(3); 78 | auto a0 = a[0]; 79 | auto a1 = a[1]; 80 | auto a2 = a[2]; 81 | EXPECT_EQ(0u, a0); 82 | EXPECT_EQ(1u, a1); 83 | EXPECT_EQ(2u, a2); 84 | EXPECT_THROW(a[3], std::out_of_range); 85 | } 86 | 87 | TEST(xaxis_default, iterator) 88 | { 89 | axis_default_type a(3); 90 | 91 | auto it = a.begin(); 92 | 93 | EXPECT_TRUE(it == a.cbegin()); 94 | EXPECT_TRUE(it != a.end()); 95 | EXPECT_TRUE(it < a.end()); 96 | EXPECT_TRUE(it <= a.end()); 97 | EXPECT_FALSE(it > a.end()); 98 | EXPECT_FALSE(it >= a.end()); 99 | EXPECT_EQ(a.end(), a.cend()); 100 | 101 | EXPECT_EQ(it->first, 0); 102 | EXPECT_EQ(it->second, a[0]); 103 | ++it; 104 | EXPECT_EQ(it->first, 1); 105 | EXPECT_EQ(it->second, a[1]); 106 | auto tmp = it++; 107 | EXPECT_EQ(tmp->first, 1); 108 | EXPECT_EQ(it->first, 2); 109 | EXPECT_EQ(tmp->second, a[1]); 110 | EXPECT_EQ(it->second, a[2]); 111 | ++it; 112 | EXPECT_EQ(it, a.end()); 113 | 114 | EXPECT_EQ(a[2], (a.begin() + 2)->second); 115 | EXPECT_EQ(a[1], (a.end() - 2)->second); 116 | EXPECT_EQ(3, a.end() - a.begin()); 117 | } 118 | 119 | TEST(xaxis_default, find) 120 | { 121 | axis_default_type a(3); 122 | 123 | auto it0 = a.find(0); 124 | auto it1 = a.find(1); 125 | auto it2 = a.find(2); 126 | auto it3 = a.find(3); 127 | 128 | EXPECT_EQ(it0->first, 0); 129 | EXPECT_EQ(it1->first, 1); 130 | EXPECT_EQ(it2->first, 2); 131 | EXPECT_EQ(it3, a.end()); 132 | } 133 | 134 | TEST(xaxis_default, merge) 135 | { 136 | axis_type a1 = { 3, 4, 5, 6 }; 137 | axis_default_type a2(3); 138 | axis_default_type a3(5); 139 | axis_type res; 140 | bool t1 = merge_axes(res, a1, a2, a3); 141 | EXPECT_FALSE(t1); 142 | EXPECT_EQ(res[0], 0); 143 | EXPECT_EQ(res[1], 1); 144 | EXPECT_EQ(res[2], 2); 145 | EXPECT_EQ(res[3], 3); 146 | EXPECT_EQ(res[4], 4); 147 | EXPECT_EQ(res[5], 5); 148 | EXPECT_EQ(res[6], 6); 149 | 150 | // Merging and xaxis_default with an xaxis 151 | axis_type a4; 152 | axis_type res2; 153 | bool t2 = merge_axes(res2, a2, a4); 154 | EXPECT_FALSE(t2); 155 | EXPECT_EQ(res2, a2); 156 | 157 | // Merging two xaxis_default together returns an xaxis 158 | axis_default_type a5(4); 159 | axis_default_type a6(4); 160 | axis_type res3; 161 | bool t3 = merge_axes(res3, a5, a6); 162 | EXPECT_TRUE(t3); 163 | } 164 | 165 | TEST(xaxis_default, filter) 166 | { 167 | axis_default_type a(36); 168 | axis_type res = a.filter([](const auto& arg) { return arg >= 16; }); 169 | EXPECT_TRUE(res.is_sorted()); 170 | EXPECT_EQ(res.size(), 20); 171 | EXPECT_EQ(res.labels()[0], 16); 172 | EXPECT_EQ(res[16], 0); 173 | EXPECT_EQ(res[35], 19); 174 | } 175 | 176 | TEST(xaxis_default, filter_size) 177 | { 178 | axis_default_type a(36); 179 | axis_type res = a.filter([](const auto& arg) { return arg >= 26; }, std::size_t(10)); 180 | EXPECT_TRUE(res.is_sorted()); 181 | EXPECT_EQ(res.size(), 10); 182 | EXPECT_EQ(res.labels()[0], 26); 183 | EXPECT_EQ(res[26], 0); 184 | EXPECT_EQ(res[35], 9); 185 | } 186 | } 187 | -------------------------------------------------------------------------------- /include/xframe/xframe_utils.hpp: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (c) 2017, Johan Mabille, Sylvain Corlay and Wolf Vollprecht * 3 | * * 4 | * Distributed under the terms of the BSD 3-Clause License. * 5 | * * 6 | * The full license is in the file LICENSE, distributed with this software. * 7 | ****************************************************************************/ 8 | 9 | #ifndef XFRAME_XFRAME_UTILS_HPP 10 | #define XFRAME_XFRAME_UTILS_HPP 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | #include "xtensor/xio.hpp" 17 | 18 | #include "xframe_config.hpp" 19 | #include "xframe_trace.hpp" 20 | 21 | namespace xf 22 | { 23 | constexpr std::size_t dynamic() 24 | { 25 | return std::numeric_limits::max(); 26 | } 27 | 28 | template 29 | bool merge_to(CO& output, const CI&... input); 30 | 31 | template 32 | bool intersect_to(CO& output, const CI&... input); 33 | 34 | /*************************** 35 | * merge_to implementation * 36 | ***************************/ 37 | 38 | namespace detail 39 | { 40 | template 41 | inline bool merge_containers(C0& output, const C1& input) 42 | { 43 | bool res = !(input.size() < output.size()); 44 | auto output_iter = output.begin(); 45 | auto output_end = output.end(); 46 | auto first = input.begin(); 47 | auto last = input.end(); 48 | while(first != last && output_iter != output_end) 49 | { 50 | if(*first < *output_iter) 51 | { 52 | output_iter = output.insert(output_iter, *first++); 53 | output_end = output.end(); 54 | res = false; 55 | } 56 | else if(*first == *output_iter) 57 | { 58 | ++first; 59 | } 60 | ++output_iter; 61 | } 62 | res &= output.empty() || (first == last); 63 | std::copy(first, last, std::back_inserter(output)); 64 | return res; 65 | } 66 | 67 | template 68 | inline bool merge_to_impl(C0&) 69 | { 70 | return true; 71 | } 72 | 73 | template 74 | inline bool merge_to_impl(C0& out, C1& in, const C&... input) 75 | { 76 | bool res = merge_containers(out, in); 77 | res &= merge_to_impl(out, input...); 78 | return res; 79 | } 80 | 81 | template 82 | struct xselector_sequence 83 | { 84 | using type = std::conditional_t::max(), std::vector, std::array>; 85 | }; 86 | 87 | template 88 | using xselector_sequence_t = typename xselector_sequence::type; 89 | } 90 | 91 | template 92 | inline bool merge_to(CO& output, const CI&... input) 93 | { 94 | return detail::merge_to_impl(output, input...); 95 | } 96 | 97 | /******************************* 98 | * intersect_to implementation * 99 | *******************************/ 100 | 101 | namespace detail 102 | { 103 | template 104 | inline bool intersect_containers(C0& output, const C1& input) 105 | { 106 | bool res = !(input.size() < output.size()); 107 | auto output_iter = output.begin(); 108 | auto output_end = output.end(); 109 | auto first = input.begin(); 110 | auto last = input.end(); 111 | while(first != last && output_iter != output_end) 112 | { 113 | if(*first < *output_iter) 114 | { 115 | ++first; 116 | } 117 | else if(*first == *output_iter) 118 | { 119 | ++first; 120 | ++output_iter; 121 | } 122 | else // *first > *output_iter 123 | { 124 | output_iter = output.erase(output_iter); 125 | output_end = output.end(); 126 | res = false; 127 | } 128 | } 129 | res &= (output_iter == output_end); 130 | output.erase(output_iter, output_end); 131 | return res; 132 | } 133 | 134 | template 135 | inline bool intersect_to_impl(C0&) 136 | { 137 | return true; 138 | } 139 | 140 | template 141 | inline bool intersect_to_impl(C0& out, const C1& in, const C&... input) 142 | { 143 | bool res = intersect_containers(out, in); 144 | res &= intersect_to_impl(out, input...); 145 | return res; 146 | } 147 | } 148 | 149 | template 150 | inline bool intersect_to(CO& output, const CI&... input) 151 | { 152 | return detail::intersect_to_impl(output, input...); 153 | } 154 | 155 | /****************** 156 | * print function * 157 | ******************/ 158 | 159 | template 160 | inline std::ostream& print_variable_expression(std::ostream& out, const V& v) 161 | { 162 | const auto& dims = v.dimension_labels(); 163 | const auto& coords = v.coordinates(); 164 | 165 | out << v.data() << std::endl; 166 | out << "Coordinates:" << std::endl; 167 | 168 | std::size_t max_length = std::accumulate(dims.cbegin(), dims.cend(), std::size_t(0), 169 | [](std::size_t res, const auto& d) { return std::max(res, d.size()); }); 170 | 171 | for (const auto& d : dims) 172 | { 173 | std::size_t nb_spaces = max_length - d.size(); 174 | std::string spaces(nb_spaces, ' '); 175 | out << d << spaces << ": " << coords[d] << std::endl; 176 | } 177 | 178 | return out; 179 | } 180 | } 181 | 182 | #endif 183 | -------------------------------------------------------------------------------- /test/test_xaxis_view.cpp: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (c) 2017, Johan Mabille, Sylvain Corlay and Wolf Vollprecht * 3 | * * 4 | * Distributed under the terms of the BSD 3-Clause License. * 5 | * * 6 | * The full license is in the file LICENSE, distributed with this software. * 7 | ****************************************************************************/ 8 | 9 | #include 10 | #include 11 | #include "gtest/gtest.h" 12 | #include "xtl/xbasic_fixed_string.hpp" 13 | #include "test_fixture_view.hpp" 14 | 15 | namespace xf 16 | { 17 | using slice_type = xt::xstepped_range; 18 | 19 | // stepped_range(1, 7, 2) 20 | inline slice_type make_slice() 21 | { 22 | return slice_type(size_type(1), size_type(7), size_type(2)); 23 | } 24 | 25 | TEST(xaxis_view, label) 26 | { 27 | auto a = make_variant_view_saxis(); 28 | axis_view_type v = axis_view_type(a, make_slice()); 29 | EXPECT_EQ(xtl::get(v.label(0)), v.labels()[0]); 30 | } 31 | 32 | TEST(xaxis_view, size) 33 | { 34 | auto a = make_variant_view_saxis(); 35 | axis_view_type v = axis_view_type(a, make_slice()); 36 | EXPECT_EQ(v.size(), 3); 37 | EXPECT_FALSE(v.empty()); 38 | 39 | axis_view_type v2 = axis_view_type(a, slice_type(size_type(1), size_type(1), size_type(2))); 40 | EXPECT_EQ(v2.size(), 0u); 41 | EXPECT_TRUE(v2.empty()); 42 | } 43 | 44 | TEST(xaxis_view, contains) 45 | { 46 | auto a = make_variant_view_saxis(); 47 | axis_view_type v = axis_view_type(a, make_slice()); 48 | 49 | EXPECT_TRUE(v.contains("c")); 50 | EXPECT_FALSE(v.contains("d")); 51 | } 52 | 53 | TEST(xaxis_view, access) 54 | { 55 | auto a = make_variant_view_saxis(); 56 | axis_view_type v = axis_view_type(a, make_slice()); 57 | 58 | auto vc = v["c"]; 59 | auto vf = v["f"]; 60 | auto vh = v["h"]; 61 | 62 | EXPECT_EQ(vc, 1u); 63 | EXPECT_EQ(vf, 3u); 64 | EXPECT_EQ(vh, 5u); 65 | EXPECT_THROW(v["m"], std::out_of_range); 66 | } 67 | 68 | TEST(xaxis_view, iterator) 69 | { 70 | auto a = make_variant_view_saxis(); 71 | axis_view_type v = axis_view_type(a, make_slice()); 72 | 73 | auto it = v.begin(); 74 | 75 | EXPECT_TRUE(it == v.cbegin()); 76 | bool res = (it != v.end()); 77 | EXPECT_TRUE(it != v.end()); 78 | EXPECT_TRUE(it < v.end()); 79 | EXPECT_TRUE(it <= v.end()); 80 | EXPECT_FALSE(it > v.end()); 81 | EXPECT_FALSE(it >= v.end()); 82 | EXPECT_EQ(v.end(), v.cend()); 83 | 84 | // TODO: fix xaxis_variant iterator 85 | EXPECT_EQ(xtl::xget(it->first), "c"); 86 | auto val = *it; 87 | EXPECT_EQ(xtl::xget(val.first), "c"); 88 | EXPECT_EQ(val.second, v["c"]); 89 | ++it; 90 | EXPECT_EQ(xtl::xget(it->first), "f"); 91 | EXPECT_EQ(it->second, v["f"]); 92 | auto tmp = it++; 93 | EXPECT_EQ(xtl::xget(tmp->first), "f"); 94 | EXPECT_EQ(tmp->second, v["f"]); 95 | EXPECT_EQ(xtl::xget(it->first), "h"); 96 | EXPECT_EQ(it->second, v["h"]); 97 | ++it; 98 | EXPECT_EQ(it, v.end()); 99 | 100 | EXPECT_EQ(v["h"], (v.begin() + 2)->second); 101 | EXPECT_EQ(v["f"], (v.end() - 2)->second); 102 | EXPECT_EQ(3, v.end() - v.begin()); 103 | 104 | auto f1 = v.find("c"); 105 | EXPECT_EQ(f1->second, v["c"]); 106 | auto f2 = v.find("a"); 107 | EXPECT_EQ(f2, v.cend()); 108 | } 109 | 110 | TEST(xaxis_view, range) 111 | { 112 | // { "a", "c", "d", "f", "g", "h", "m", "n" } 113 | auto a = make_variant_view_saxis(); 114 | 115 | auto r = range("c", "f"); 116 | axis_view_type vr = axis_view_type(a, r.build_index_slice(a)); 117 | auto vrit = vr.cbegin(); 118 | EXPECT_EQ(xtl::xget(vrit->first), "c"); 119 | ++vrit; 120 | EXPECT_EQ(xtl::xget(vrit->first), "d"); 121 | ++vrit; 122 | EXPECT_EQ(xtl::xget(vrit->first), "f"); 123 | ++vrit; 124 | EXPECT_EQ(vrit, vr.cend()); 125 | 126 | auto sr = range("c", "h", 2); 127 | axis_view_type vsr = axis_view_type(a, sr.build_index_slice(a)); 128 | auto vsrit = vsr.cbegin(); 129 | EXPECT_EQ(xtl::xget(vsrit->first), "c"); 130 | ++vsrit; 131 | EXPECT_EQ(xtl::xget(vsrit->first), "f"); 132 | ++vsrit; 133 | EXPECT_EQ(xtl::xget(vsrit->first), "h"); 134 | ++vsrit; 135 | EXPECT_EQ(vsrit, vsr.cend()); 136 | } 137 | 138 | /*TEST(xaxis_view, slice_conversion) 139 | { 140 | using saxis_slice_type = xt::xaxis_index_slice; 141 | using iaxis_slice_type = xt::xaxis_index_slice; 142 | 143 | iaxis_slice_type is1 = xt::xall(4); 144 | saxis_slice_type ss1(is1); 145 | EXPECT_EQ(ss1.size(), std::size_t(4)); 146 | 147 | iaxis_slice_type is2 = xt::variant_range(2, 4); 148 | saxis_slice_type ss2(is2); 149 | EXPECT_EQ(ss2.size(), std::size_t(is2.size())); 150 | 151 | iaxis_slice_type is3 = xt::variant_range(2, 9, 2); 152 | saxis_slice_type ss3(is3); 153 | EXPECT_EQ(ss3.size(), std::size_t(is3.size())); 154 | EXPECT_EQ(ss3.step_size(0), std::size_t(is3.step_size(0))); 155 | 156 | using sextended_type = xt::xslice_extended; 157 | using iextended_type = xt::xslice_extended; 158 | 159 | iextended_type is4 = is3; 160 | sextended_type ss4 = is4; 161 | sextended_type res = ss3; 162 | EXPECT_EQ(*(ss4.get_slice()), *(res.get_slice())); 163 | 164 | iextended_type is5 = 2; 165 | sextended_type ss5 = is5; 166 | sextended_type res2 = std::size_t(2); 167 | EXPECT_EQ(*(is5.get_squeeze()), *(ss5.get_squeeze())); 168 | }*/ 169 | 170 | TEST(xaxis_view, conversion) 171 | { 172 | auto a = make_variant_view_saxis(); 173 | axis_view_type v = axis_view_type(a, make_slice()); 174 | axis_variant vf = axis_variant(v); 175 | EXPECT_EQ(vf["c"], 0u); 176 | EXPECT_EQ(vf["f"], 1u); 177 | EXPECT_EQ(vf["h"], 2u); 178 | } 179 | } 180 | -------------------------------------------------------------------------------- /include/xframe/xaxis_function.hpp: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (c) 2017, Johan Mabille, Sylvain Corlay, Wolf Vollprecht and * 3 | * Martin Renou * 4 | * * 5 | * Distributed under the terms of the BSD 3-Clause License. * 6 | * * 7 | * The full license is in the file LICENSE, distributed with this software. * 8 | ****************************************************************************/ 9 | 10 | #ifndef XFRAME_XAXIS_FUNCTION_HPP 11 | #define XFRAME_XAXIS_FUNCTION_HPP 12 | 13 | #include "xtensor/xoptional.hpp" 14 | #include "xtensor/xgenerator.hpp" 15 | 16 | #include "xframe_expression.hpp" 17 | #include "xframe_utils.hpp" 18 | #include "xaxis_meta.hpp" 19 | #include "xaxis_expression_leaf.hpp" 20 | 21 | namespace xf 22 | { 23 | /****************** 24 | * xaxis_function * 25 | ******************/ 26 | 27 | template 28 | class xaxis_function : public xt::xexpression> 29 | { 30 | public: 31 | 32 | using self_type = xaxis_function; 33 | using functor_type = std::remove_reference_t; 34 | 35 | using value_type = R; 36 | using reference = value_type; 37 | using const_reference = value_type; 38 | using pointer = value_type*; 39 | using const_pointer = const value_type*; 40 | using name_type = detail::common_name_type_t>...>; 41 | using size_type = xt::detail::common_size_type_t>...>; 42 | 43 | template 44 | using selector_sequence_type = detail::xselector_sequence_t, N>; 45 | 46 | using expression_tag = xaxis_expression_tag; 47 | 48 | template ::value>> 49 | xaxis_function(Func&& f, CT... e) noexcept; 50 | 51 | template 52 | const_reference operator()(const selector_sequence_type& selector) const; 53 | 54 | private: 55 | 56 | template 57 | const_reference evaluate(std::index_sequence, const selector_sequence_type& selector) const; 58 | 59 | std::tuple...> m_e; 60 | functor_type m_f; 61 | }; 62 | 63 | /********************************* 64 | * xaxis_function implementation * 65 | *********************************/ 66 | 67 | template 68 | template 69 | inline xaxis_function::xaxis_function(Func&& f, CT... e) noexcept 70 | : m_e(detail::get_axis_closure(std::forward(e))...), 71 | m_f(std::forward(f)) 72 | { 73 | } 74 | 75 | template 76 | template 77 | inline auto xaxis_function::operator()(const selector_sequence_type& selector) const -> const_reference 78 | { 79 | return evaluate(std::make_index_sequence(), selector); 80 | } 81 | 82 | template 83 | template 84 | inline auto xaxis_function::evaluate(std::index_sequence, const selector_sequence_type& selector) const -> const_reference 85 | { 86 | #ifdef _MSC_VER 87 | return m_f(std::get(m_e).operator()(selector)...); 88 | #else 89 | return m_f(std::get(m_e).template operator()(selector)...); 90 | #endif 91 | } 92 | 93 | /********************** 94 | * axis_function_mask * 95 | **********************/ 96 | 97 | namespace detail 98 | { 99 | template 100 | class axis_function_mask_impl 101 | { 102 | public: 103 | 104 | using axis_function_type = std::remove_reference_t; 105 | 106 | using value_type = typename axis_function_type::value_type; 107 | using name_type = typename axis_function_type::name_type; 108 | using size_type = typename axis_function_type::size_type; 109 | 110 | template 111 | using selector_sequence_type = detail::xselector_sequence_t, N>; 112 | 113 | axis_function_mask_impl(AF&& axis_function, DM&& dim_mapping) 114 | : m_axis_function(std::forward(axis_function)), 115 | m_dimension_mapping(std::forward(dim_mapping)) 116 | { 117 | } 118 | 119 | template 120 | inline value_type operator()(Args... args) const 121 | { 122 | auto selector = make_selector(std::make_index_sequence(), args...); 123 | #ifdef _MSC_VER 124 | return m_axis_function.operator()(selector); 125 | #else 126 | return m_axis_function.template operator()(selector); 127 | #endif 128 | } 129 | 130 | template 131 | inline value_type element(It first, It last) const 132 | { 133 | // TODO avoid dynamic allocation 134 | auto selector = selector_sequence_type(); 135 | std::size_t i = 0; 136 | for (It it = first; it != last; ++it) 137 | { 138 | selector.push_back(std::make_pair(m_dimension_mapping.label(i++), static_cast(*it))); 139 | } 140 | #ifdef _MSC_VER 141 | return m_axis_function.operator()(selector); 142 | #else 143 | return m_axis_function.template operator()(selector); 144 | #endif 145 | } 146 | 147 | private: 148 | 149 | AF m_axis_function; 150 | DM m_dimension_mapping; 151 | 152 | template 153 | inline selector_sequence_type make_selector(std::index_sequence, Args&&... args) const 154 | { 155 | return {std::make_pair(m_dimension_mapping.label(I), static_cast(args))...}; 156 | } 157 | }; 158 | } 159 | 160 | template 161 | inline auto axis_function_mask(AF&& axis_function, DM&& dim_mapping, const S& shape) noexcept 162 | { 163 | return xt::detail::make_xgenerator( 164 | detail::axis_function_mask_impl(std::forward(axis_function), std::forward(dim_mapping)), 165 | shape 166 | ); 167 | } 168 | } 169 | 170 | #endif 171 | -------------------------------------------------------------------------------- /include/xframe/xcoordinate_base.hpp: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (c) 2017, Johan Mabille, Sylvain Corlay and Wolf Vollprecht * 3 | * * 4 | * Distributed under the terms of the BSD 3-Clause License. * 5 | * * 6 | * The full license is in the file LICENSE, distributed with this software. * 7 | ****************************************************************************/ 8 | 9 | #ifndef XFRAME_XCOORDINATE_BASE_HPP 10 | #define XFRAME_XCOORDINATE_BASE_HPP 11 | 12 | #include 13 | 14 | #include "xtl/xiterator_base.hpp" 15 | #include "xaxis_variant.hpp" 16 | #include "xframe_config.hpp" 17 | 18 | namespace xf 19 | { 20 | 21 | /******************** 22 | * xcoordinate_base * 23 | ********************/ 24 | 25 | template 26 | class xcoordinate_base 27 | { 28 | public: 29 | 30 | using self_type = xcoordinate_base; 31 | using axis_type = A; 32 | using map_type = std::map; 33 | using key_type = typename map_type::key_type; 34 | using mapped_type = typename map_type::mapped_type; 35 | using index_type = typename axis_type::mapped_type; 36 | using value_type = typename map_type::value_type; 37 | using reference = typename map_type::reference; 38 | using const_reference = typename map_type::const_reference; 39 | using pointer = typename map_type::pointer; 40 | using const_pointer = typename map_type::const_pointer; 41 | using size_type = typename map_type::size_type; 42 | using difference_type = typename map_type::difference_type; 43 | using iterator = typename map_type::iterator; 44 | using const_iterator = typename map_type::const_iterator; 45 | using key_iterator = xtl::xkey_iterator; 46 | 47 | bool empty() const; 48 | size_type size() const; 49 | 50 | bool contains(const key_type& key) const; 51 | const mapped_type& operator[](const key_type& key) const; 52 | 53 | template 54 | index_type operator[](const std::pair& key) const; 55 | 56 | const map_type& data() const noexcept; 57 | 58 | const_iterator find(const key_type& key) const; 59 | 60 | const_iterator begin() const noexcept; 61 | const_iterator end() const noexcept; 62 | 63 | const_iterator cbegin() const noexcept; 64 | const_iterator cend() const noexcept; 65 | 66 | key_iterator key_begin() const noexcept; 67 | key_iterator key_end() const noexcept; 68 | 69 | protected: 70 | 71 | xcoordinate_base(const map_type& axes); 72 | xcoordinate_base(map_type&& axes); 73 | xcoordinate_base(std::initializer_list init); 74 | template 75 | xcoordinate_base(std::pair... axes); 76 | 77 | ~xcoordinate_base() = default; 78 | 79 | xcoordinate_base(const xcoordinate_base&) = default; 80 | xcoordinate_base& operator=(const xcoordinate_base&) = default; 81 | 82 | xcoordinate_base(xcoordinate_base&&) = default; 83 | xcoordinate_base& operator=(xcoordinate_base&&) = default; 84 | 85 | map_type& coordinate() noexcept; 86 | 87 | private: 88 | 89 | map_type m_coordinate; 90 | }; 91 | 92 | template 93 | OS& operator<<(OS& out, const xcoordinate_base& c); 94 | 95 | /*********************************** 96 | * xcoordinate_base implementation * 97 | ***********************************/ 98 | 99 | template 100 | inline xcoordinate_base::xcoordinate_base(const map_type& axes) 101 | : m_coordinate(axes) 102 | { 103 | } 104 | 105 | template 106 | inline xcoordinate_base::xcoordinate_base(map_type&& axes) 107 | : m_coordinate(std::move(axes)) 108 | { 109 | } 110 | 111 | template 112 | inline xcoordinate_base::xcoordinate_base(std::initializer_list init) 113 | : m_coordinate(init) 114 | { 115 | } 116 | 117 | template 118 | template 119 | inline xcoordinate_base::xcoordinate_base(std::pair... axes) 120 | : m_coordinate({std::move(axes)...}) 121 | { 122 | } 123 | 124 | template 125 | inline bool xcoordinate_base::empty() const 126 | { 127 | return m_coordinate.empty(); 128 | } 129 | 130 | template 131 | inline auto xcoordinate_base::size() const -> size_type 132 | { 133 | return m_coordinate.size(); 134 | } 135 | 136 | template 137 | inline bool xcoordinate_base::contains(const key_type& key) const 138 | { 139 | return m_coordinate.find(key) != m_coordinate.end(); 140 | } 141 | 142 | template 143 | inline auto xcoordinate_base::operator[](const key_type& key) const -> const mapped_type& 144 | { 145 | return m_coordinate.at(key); 146 | } 147 | 148 | template 149 | template 150 | inline auto xcoordinate_base::operator[](const std::pair& key) const -> index_type 151 | { 152 | return (*this)[key.first][key.second]; 153 | } 154 | 155 | template 156 | inline auto xcoordinate_base::data() const noexcept -> const map_type& 157 | { 158 | return m_coordinate; 159 | } 160 | 161 | template 162 | inline auto xcoordinate_base::find(const key_type& key) const -> const_iterator 163 | { 164 | return m_coordinate.find(key); 165 | } 166 | 167 | template 168 | inline auto xcoordinate_base::begin() const noexcept -> const_iterator 169 | { 170 | return cbegin(); 171 | } 172 | 173 | template 174 | inline auto xcoordinate_base::end() const noexcept -> const_iterator 175 | { 176 | return cend(); 177 | } 178 | 179 | template 180 | inline auto xcoordinate_base::cbegin() const noexcept -> const_iterator 181 | { 182 | return m_coordinate.cbegin(); 183 | } 184 | 185 | template 186 | inline auto xcoordinate_base::cend() const noexcept -> const_iterator 187 | { 188 | return m_coordinate.cend(); 189 | } 190 | 191 | template 192 | inline auto xcoordinate_base::key_begin() const noexcept -> key_iterator 193 | { 194 | return key_iterator(begin()); 195 | } 196 | 197 | template 198 | inline auto xcoordinate_base::key_end() const noexcept -> key_iterator 199 | { 200 | return key_iterator(end()); 201 | } 202 | 203 | template 204 | inline auto xcoordinate_base::coordinate() noexcept -> map_type& 205 | { 206 | return m_coordinate; 207 | } 208 | 209 | template 210 | inline OS& operator<<(OS& out, const xcoordinate_base& c) 211 | { 212 | for (auto& v : c) 213 | { 214 | out << v.first << ": " << v.second << std::endl; 215 | } 216 | return out; 217 | } 218 | } 219 | 220 | #endif 221 | -------------------------------------------------------------------------------- /test/test_xvariable_noalias.cpp: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (c) 2017, Johan Mabille, Sylvain Corlay and Wolf Vollprecht * 3 | * * 4 | * Distributed under the terms of the BSD 3-Clause License. * 5 | * * 6 | * The full license is in the file LICENSE, distributed with this software. * 7 | ****************************************************************************/ 8 | 9 | #include "gtest/gtest.h" 10 | #include "test_fixture.hpp" 11 | 12 | namespace xf 13 | { 14 | TEST(xvariable_noalias, a_plus_b) 15 | { 16 | DEFINE_TEST_VARIABLES(); 17 | { 18 | SCOPED_TRACE("same coordinate"); 19 | variable_type res = a; 20 | noalias(res) = a + a; 21 | selector_list sl = make_selector_list_aa(); 22 | CHECK_EQUALITY(res, a, a, sl, +) 23 | } 24 | 25 | { 26 | SCOPED_TRACE("different coordinates"); 27 | variable_type res = a; 28 | noalias(res) = a + b; 29 | selector_list sl = make_selector_list_ab(); 30 | CHECK_EQUALITY(res, a, b, sl, +) 31 | } 32 | 33 | { 34 | SCOPED_TRACE("broadcasting coordinates"); 35 | variable_type res = c; 36 | noalias(res) = c + d; 37 | selector_list sl = make_selector_list_cd(); 38 | CHECK_EQUALITY(res, c, d, sl, +) 39 | } 40 | } 41 | 42 | TEST(xvariable_noalias, a_minus_b) 43 | { 44 | DEFINE_TEST_VARIABLES(); 45 | { 46 | SCOPED_TRACE("same coordinate"); 47 | variable_type res = a; 48 | noalias(res) = a - a; 49 | selector_list sl = make_selector_list_aa(); 50 | CHECK_EQUALITY(res, a, a, sl, -) 51 | } 52 | 53 | { 54 | SCOPED_TRACE("different coordinates"); 55 | variable_type res = a; 56 | noalias(res) = a - b; 57 | selector_list sl = make_selector_list_ab(); 58 | CHECK_EQUALITY(res, a, b, sl, -) 59 | } 60 | 61 | { 62 | SCOPED_TRACE("broadcasting coordinates"); 63 | variable_type res = c; 64 | noalias(res) = c - d; 65 | selector_list sl = make_selector_list_cd(); 66 | CHECK_EQUALITY(res, c, d, sl, -) 67 | } 68 | } 69 | 70 | TEST(xvariable_noalias, a_times_b) 71 | { 72 | DEFINE_TEST_VARIABLES(); 73 | { 74 | SCOPED_TRACE("same coordinate"); 75 | variable_type res = a; 76 | noalias(res) = a * a; 77 | selector_list sl = make_selector_list_aa(); 78 | CHECK_EQUALITY(res, a, a, sl, *) 79 | } 80 | 81 | { 82 | SCOPED_TRACE("different coordinates"); 83 | variable_type res = a; 84 | noalias(res) = a * b; 85 | selector_list sl = make_selector_list_ab(); 86 | CHECK_EQUALITY(res, a, b, sl, *) 87 | } 88 | 89 | { 90 | SCOPED_TRACE("broadcasting coordinates"); 91 | variable_type res = c; 92 | noalias(res) = c * d; 93 | selector_list sl = make_selector_list_cd(); 94 | CHECK_EQUALITY(res, c, d, sl, *) 95 | } 96 | } 97 | 98 | TEST(xvariable_noalias, a_divided_by__b) 99 | { 100 | DEFINE_TEST_VARIABLES(); 101 | { 102 | SCOPED_TRACE("same coordinate"); 103 | variable_type res = a; 104 | noalias(res) = a / a; 105 | selector_list sl = make_selector_list_aa(); 106 | CHECK_EQUALITY(res, a, a, sl, /) 107 | } 108 | 109 | { 110 | SCOPED_TRACE("different coordinates"); 111 | variable_type res = a; 112 | noalias(res) = a / b; 113 | selector_list sl = make_selector_list_ab(); 114 | CHECK_EQUALITY(res, a, b, sl, /) 115 | } 116 | 117 | { 118 | SCOPED_TRACE("broadcasting coordinates"); 119 | variable_type res = c; 120 | noalias(res) = c / d; 121 | selector_list sl = make_selector_list_cd(); 122 | CHECK_EQUALITY(res, c, d, sl, /) 123 | } 124 | } 125 | 126 | TEST(xvariable_noalias, a_plus_equal_b) 127 | { 128 | DEFINE_TEST_VARIABLES(); 129 | { 130 | SCOPED_TRACE("same coordinate"); 131 | variable_type res = a; 132 | noalias(res) += a; 133 | selector_list sl = make_selector_list_aa(); 134 | CHECK_EQUALITY(res, a, a, sl, +) 135 | } 136 | 137 | { 138 | SCOPED_TRACE("different coordinates"); 139 | variable_type res = a; 140 | noalias(res) += b; 141 | selector_list sl = make_selector_list_ab(); 142 | CHECK_EQUALITY(res, a, b, sl, +) 143 | } 144 | 145 | { 146 | SCOPED_TRACE("broadcasting coordinates"); 147 | variable_type res = c; 148 | noalias(res) += d; 149 | selector_list sl = make_selector_list_cd(); 150 | CHECK_EQUALITY(res, c, d, sl, +) 151 | } 152 | } 153 | 154 | TEST(xvariable_noalias, a_minus_equal_b) 155 | { 156 | DEFINE_TEST_VARIABLES(); 157 | { 158 | SCOPED_TRACE("same coordinate"); 159 | variable_type res = a; 160 | noalias(res) -= a; 161 | selector_list sl = make_selector_list_aa(); 162 | CHECK_EQUALITY(res, a, a, sl, -) 163 | } 164 | 165 | { 166 | SCOPED_TRACE("different coordinates"); 167 | variable_type res = a; 168 | noalias(res) -= b; 169 | selector_list sl = make_selector_list_ab(); 170 | CHECK_EQUALITY(res, a, b, sl, -) 171 | } 172 | 173 | { 174 | SCOPED_TRACE("broadcasting coordinates"); 175 | variable_type res = c; 176 | noalias(res) -= d; 177 | selector_list sl = make_selector_list_cd(); 178 | CHECK_EQUALITY(res, c, d, sl, -) 179 | } 180 | } 181 | 182 | TEST(xvariable_noalias, a_times_equal_b) 183 | { 184 | DEFINE_TEST_VARIABLES(); 185 | { 186 | SCOPED_TRACE("same coordinate"); 187 | variable_type res = a; 188 | noalias(res) *= a; 189 | selector_list sl = make_selector_list_aa(); 190 | CHECK_EQUALITY(res, a, a, sl, *) 191 | } 192 | 193 | { 194 | SCOPED_TRACE("different coordinates"); 195 | variable_type res = a; 196 | noalias(res) *= b; 197 | selector_list sl = make_selector_list_ab(); 198 | CHECK_EQUALITY(res, a, b, sl, *) 199 | } 200 | 201 | { 202 | SCOPED_TRACE("broadcasting coordinates"); 203 | variable_type res = c; 204 | noalias(res) *= d; 205 | selector_list sl = make_selector_list_cd(); 206 | CHECK_EQUALITY(res, c, d, sl, *) 207 | } 208 | } 209 | 210 | TEST(xvariable_noalias, a_divided_by_equal_b) 211 | { 212 | DEFINE_TEST_VARIABLES(); 213 | { 214 | SCOPED_TRACE("same coordinate"); 215 | variable_type res = a; 216 | noalias(res) /= a; 217 | selector_list sl = make_selector_list_aa(); 218 | CHECK_EQUALITY(res, a, a, sl, /) 219 | } 220 | 221 | { 222 | SCOPED_TRACE("different coordinates"); 223 | variable_type res = a; 224 | noalias(res) /= b; 225 | selector_list sl = make_selector_list_ab(); 226 | CHECK_EQUALITY(res, a, b, sl, /) 227 | } 228 | 229 | { 230 | SCOPED_TRACE("broadcasting coordinates"); 231 | variable_type res = c; 232 | noalias(res) /= d; 233 | selector_list sl = make_selector_list_cd(); 234 | CHECK_EQUALITY(res, c, d, sl, /) 235 | } 236 | } 237 | } 238 | -------------------------------------------------------------------------------- /test/test_xvariable_function.cpp: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (c) 2017, Johan Mabille, Sylvain Corlay and Wolf Vollprecht * 3 | * * 4 | * Distributed under the terms of the BSD 3-Clause License. * 5 | * * 6 | * The full license is in the file LICENSE, distributed with this software. * 7 | ****************************************************************************/ 8 | 9 | #include "gtest/gtest.h" 10 | #include "test_fixture.hpp" 11 | 12 | namespace xf 13 | { 14 | struct xfunction_features 15 | { 16 | variable_type m_a; 17 | variable_type m_b; 18 | 19 | xfunction_features(); 20 | }; 21 | 22 | xfunction_features::xfunction_features() 23 | { 24 | m_a = make_test_variable(); 25 | m_b = make_test_variable2(); 26 | } 27 | 28 | TEST(xvariable_function, size) 29 | { 30 | xfunction_features f; 31 | std::size_t s1 = (f.m_a + f.m_a).size(); 32 | EXPECT_EQ(s1, 9u); 33 | std::size_t s2 = (f.m_a + f.m_b).size(); 34 | EXPECT_EQ(s2, 12u); 35 | std::size_t s3 = (f.m_a + f.m_a).template size(); 36 | EXPECT_EQ(s3, 9u); 37 | std::size_t s4 = (f.m_a + f.m_b).template size(); 38 | EXPECT_EQ(s4, 48u); 39 | } 40 | 41 | TEST(xvariable_function, dimension) 42 | { 43 | xfunction_features f; 44 | std::size_t s1 = (f.m_a + f.m_a).dimension(); 45 | EXPECT_EQ(s1, 2u); 46 | std::size_t s2 = (f.m_a + f.m_b).dimension(); 47 | EXPECT_EQ(s2, 3u); 48 | std::size_t s3 = (f.m_a + f.m_a).template dimension(); 49 | EXPECT_EQ(s3, 2u); 50 | std::size_t s4 = (f.m_a + f.m_b).template dimension(); 51 | EXPECT_EQ(s4, 3u); 52 | } 53 | 54 | TEST(xvariable_function, dimension_labels) 55 | { 56 | xfunction_features f; 57 | auto l1 = (f.m_a + f.m_a).dimension_labels(); 58 | EXPECT_EQ(l1, f.m_a.dimension_labels()); 59 | auto l2 = (f.m_a + f.m_a).dimension_labels(); 60 | EXPECT_EQ(l2, f.m_a.dimension_labels()); 61 | auto l3 = (f.m_a + f.m_b).dimension_labels(); 62 | EXPECT_EQ(l3, f.m_b.dimension_labels()); 63 | auto l4 = (f.m_a + f.m_b).dimension_labels(); 64 | EXPECT_EQ(l4, f.m_b.dimension_labels()); 65 | } 66 | 67 | TEST(xvariable_function, coordinates) 68 | { 69 | xfunction_features f; 70 | auto c1 = (f.m_a + f.m_a).coordinates(); 71 | EXPECT_EQ(c1, f.m_a.coordinates()); 72 | auto c2 = (f.m_a + f.m_a).coordinates(); 73 | EXPECT_EQ(c2, f.m_a.coordinates()); 74 | auto c3 = (f.m_a + f.m_b).coordinates(); 75 | EXPECT_EQ(c3, make_intersect_coordinate()); 76 | auto c4 = (f.m_a + f.m_b).coordinates(); 77 | EXPECT_EQ(c4, make_merge_coordinate()); 78 | } 79 | 80 | TEST(xvariable_function, dimension_mapping) 81 | { 82 | xfunction_features f; 83 | auto d1 = (f.m_a + f.m_a).dimension_mapping(); 84 | EXPECT_EQ(d1, f.m_a.dimension_mapping()); 85 | auto d2 = (f.m_a + f.m_a).dimension_mapping(); 86 | EXPECT_EQ(d2, f.m_a.dimension_mapping()); 87 | auto d3 = (f.m_a + f.m_b).dimension_mapping(); 88 | EXPECT_EQ(d3, f.m_b.dimension_mapping()); 89 | auto d4 = (f.m_a + f.m_b).dimension_mapping(); 90 | EXPECT_EQ(d4, f.m_b.dimension_mapping()); 91 | } 92 | 93 | TEST(xvariable_function, shape) 94 | { 95 | xfunction_features f; 96 | using shape_type = std::decay_t; 97 | auto s1 = (f.m_a + f.m_a).shape(); 98 | EXPECT_EQ(s1, shape_type({ 3, 3 })); 99 | auto s2 = (f.m_a + f.m_b).shape(); 100 | EXPECT_EQ(s2, shape_type({ 3, 3, 3 })); 101 | } 102 | 103 | TEST(xvariable_function, access) 104 | { 105 | xfunction_features f; 106 | std::size_t i = f.m_a.data().shape()[0] - 1; 107 | std::size_t j = f.m_a.data().shape()[1] - 1; 108 | 109 | { 110 | SCOPED_TRACE("same shape"); 111 | xtl::xoptional a = (f.m_a + f.m_a)(i, j); 112 | xtl::xoptional b = f.m_a(i, j) + f.m_a(i, j); 113 | EXPECT_EQ(a, b); 114 | } 115 | 116 | { 117 | SCOPED_TRACE("different shape"); 118 | xtl::xoptional a = (f.m_a + f.m_b)(1, i, j); 119 | xtl::xoptional b = f.m_a(1, i, j) + f.m_b(1, i, j); 120 | EXPECT_EQ(a, b); 121 | } 122 | } 123 | 124 | TEST(xvariable_function, broadcast_coordinate) 125 | { 126 | xfunction_features f; 127 | 128 | coordinate_type c1; 129 | xtrivial_broadcast res1 = (f.m_a + f.m_a).broadcast_coordinates(c1); 130 | EXPECT_EQ(c1, f.m_a.coordinates()); 131 | EXPECT_TRUE(res1.m_xtensor_trivial); 132 | EXPECT_TRUE(res1.m_xframe_trivial); 133 | 134 | coordinate_type c2; 135 | xtrivial_broadcast res2 = (f.m_a + f.m_a).broadcast_coordinates(c2); 136 | EXPECT_EQ(c2, f.m_a.coordinates()); 137 | EXPECT_TRUE(res2.m_xtensor_trivial); 138 | EXPECT_TRUE(res2.m_xframe_trivial); 139 | 140 | coordinate_type c3; 141 | xtrivial_broadcast res3 = (f.m_a + f.m_b).broadcast_coordinates(c3); 142 | EXPECT_EQ(c3, make_intersect_coordinate()); 143 | EXPECT_FALSE(res3.m_xtensor_trivial); 144 | EXPECT_FALSE(res3.m_xframe_trivial); 145 | 146 | coordinate_type c4; 147 | xtrivial_broadcast res4 = (f.m_a + f.m_b).broadcast_coordinates(c4); 148 | EXPECT_EQ(c4, make_merge_coordinate()); 149 | EXPECT_FALSE(res4.m_xtensor_trivial); 150 | EXPECT_FALSE(res4.m_xframe_trivial); 151 | } 152 | 153 | TEST(xvariable_function, select_inner) 154 | { 155 | xfunction_features f; 156 | 157 | { 158 | SCOPED_TRACE("same shape"); 159 | xtl::xoptional a = (f.m_a + f.m_a).select({{"abscissa", "d"}, {"ordinate", 4}}); 160 | xtl::xoptional b = 2 * f.m_a.select({{"abscissa", "d"}, {"ordinate", 4}}); 161 | EXPECT_EQ(a, b); 162 | EXPECT_ANY_THROW((f.m_a + f.m_a).select({{"abscissa", "e"}, {"ordinate", 4}})); 163 | } 164 | 165 | { 166 | SCOPED_TRACE("different shape"); 167 | 168 | xtl::xoptional a = (f.m_a + f.m_b).select({{"abscissa", "d"}, {"ordinate", 4}, {"altitude", 2}}); 169 | xtl::xoptional b = f.m_a.select({{"abscissa", "d"}, {"ordinate", 4}, {"altitude", 2}}) + 170 | f.m_b.select({{"abscissa", "d"}, {"ordinate", 4}, {"altitude", 2}}); 171 | EXPECT_EQ(a, b); 172 | EXPECT_ANY_THROW((f.m_a + f.m_b).select({{"abscissa", "e"}, {"ordinate", 4}, {"altitude", 2}})); 173 | } 174 | } 175 | 176 | TEST(xvariable_function, select_outer) 177 | { 178 | xfunction_features f; 179 | 180 | { 181 | SCOPED_TRACE("same shape"); 182 | xtl::xoptional a = (f.m_a + f.m_a).select({{"abscissa", "d"}, {"ordinate", 4}}); 183 | xtl::xoptional b = 2 * f.m_a.select({{"abscissa", "d"}, {"ordinate", 4}}); 184 | EXPECT_EQ(a, b); 185 | EXPECT_EQ((f.m_a + f.m_a).select({{"abscissa", "e"}, {"ordinate", 4}}), f.m_a.missing()); 186 | } 187 | 188 | { 189 | SCOPED_TRACE("different shape"); 190 | 191 | xtl::xoptional a = (f.m_a + f.m_b).select({{"abscissa", "d"}, {"ordinate", 4}, {"altitude", 2}}); 192 | xtl::xoptional b = f.m_a.select({{"abscissa", "d"}, {"ordinate", 4}, {"altitude", 2}}) + 193 | f.m_b.select({{"abscissa", "d"}, {"ordinate", 4}, {"altitude", 2}}); 194 | EXPECT_EQ(a, b); 195 | EXPECT_EQ((f.m_a + f.m_b).select({{"abscissa", "e"}, {"ordinate", 4}, {"altitude", 2}}), f.m_a.missing()); 196 | } 197 | } 198 | } 199 | 200 | -------------------------------------------------------------------------------- /include/xframe/xaxis_label_slice.hpp: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (c) 2017, Johan Mabille, Sylvain Corlay and Wolf Vollprecht * 3 | * * 4 | * Distributed under the terms of the BSD 3-Clause License. * 5 | * * 6 | * The full license is in the file LICENSE, distributed with this software. * 7 | ****************************************************************************/ 8 | 9 | #ifndef XFRAME_XAXIS_LABEL_SLICE_HPP 10 | #define XFRAME_XAXIS_LABEL_SLICE_HPP 11 | 12 | #include 13 | #include 14 | #include "xaxis_index_slice.hpp" 15 | #include "xframe_config.hpp" 16 | 17 | namespace xf 18 | { 19 | /************************** 20 | * xlabel_slice_variant_t * 21 | **************************/ 22 | 23 | template 24 | using xlabel_variant_t = xtl::mpl::cast_t; 25 | 26 | /*************** 27 | * xaxis_range * 28 | ***************/ 29 | 30 | template 31 | class xaxis_range 32 | { 33 | public: 34 | 35 | using value_type = xlabel_variant_t; 36 | 37 | xaxis_range(const value_type& first, const value_type& last) noexcept; 38 | xaxis_range(value_type&& first, value_type&& last) noexcept; 39 | 40 | template 41 | using index_slice_type = xt::xrange; 42 | 43 | template 44 | index_slice_type build_index_slice(const A& axis) const; 45 | 46 | private: 47 | 48 | value_type m_first; 49 | value_type m_last; 50 | }; 51 | 52 | /*********************** 53 | * xaxis_stepped_range * 54 | ***********************/ 55 | 56 | template 57 | class xaxis_stepped_range 58 | { 59 | public: 60 | 61 | using value_type = xlabel_variant_t; 62 | using size_type = std::size_t; 63 | 64 | xaxis_stepped_range(const value_type& first, const value_type& last, size_type step) noexcept; 65 | xaxis_stepped_range(value_type&& first, value_type&& last, size_type step) noexcept; 66 | 67 | template 68 | using index_slice_type = xt::xstepped_range; 69 | 70 | template 71 | index_slice_type build_index_slice(const A& axis) const; 72 | 73 | private: 74 | 75 | value_type m_first; 76 | value_type m_last; 77 | size_type m_step; 78 | }; 79 | 80 | /************* 81 | * xaxis_all * 82 | *************/ 83 | 84 | class xaxis_all 85 | { 86 | public: 87 | 88 | template 89 | using index_slice_type = xt::xall; 90 | 91 | template 92 | index_slice_type build_index_slice(const A& axis) const; 93 | }; 94 | 95 | /*************** 96 | * xaxis_slice * 97 | ***************/ 98 | 99 | template 100 | class xaxis_slice 101 | { 102 | public: 103 | 104 | using squeeze_type = xlabel_variant_t; 105 | using storage_type = xtl::variant, xaxis_stepped_range, xaxis_all, squeeze_type>; 106 | 107 | xaxis_slice() = default; 108 | template 109 | xaxis_slice(const V& slice); 110 | template 111 | xaxis_slice(V&& slice); 112 | 113 | template 114 | using index_slice_type = xaxis_index_slice; 115 | 116 | template 117 | index_slice_type build_index_slice(const A& axis) const; 118 | 119 | const squeeze_type* get_squeeze() const noexcept; 120 | 121 | private: 122 | 123 | storage_type m_data; 124 | }; 125 | 126 | template 127 | xaxis_slice range(const xlabel_variant_t& first, const xlabel_variant_t& last); 128 | 129 | template 130 | xaxis_slice range(xlabel_variant_t&& first, xlabel_variant_t&& last); 131 | 132 | template 133 | xaxis_slice range(const xlabel_variant_t& first, const xlabel_variant_t& last, S step); 134 | 135 | template 136 | xaxis_slice range(xlabel_variant_t&& first, xlabel_variant_t&& last, S step); 137 | 138 | /****************************** 139 | * xaxis_range implementation * 140 | ******************************/ 141 | 142 | template 143 | inline xaxis_range::xaxis_range(const value_type& first, const value_type& last) noexcept 144 | : m_first(first), m_last(last) 145 | { 146 | } 147 | 148 | template 149 | inline xaxis_range::xaxis_range(value_type&& first, value_type&& last) noexcept 150 | : m_first(std::move(first)), m_last(std::move(last)) 151 | { 152 | } 153 | 154 | template 155 | template 156 | inline auto xaxis_range::build_index_slice(const A& axis) const -> index_slice_type 157 | { 158 | return index_slice_type(axis[m_first], axis[m_last] + 1); 159 | } 160 | 161 | /************************************** 162 | * xaxis_stepped_range implementation * 163 | **************************************/ 164 | 165 | template 166 | inline xaxis_stepped_range::xaxis_stepped_range(const value_type& first, const value_type& last, size_type step) noexcept 167 | : m_first(first), m_last(last), m_step(step) 168 | { 169 | } 170 | 171 | template 172 | inline xaxis_stepped_range::xaxis_stepped_range(value_type&& first, value_type&& last, size_type step) noexcept 173 | : m_first(std::move(first)), m_last(std::move(last)), m_step(step) 174 | { 175 | } 176 | 177 | template 178 | template 179 | inline auto xaxis_stepped_range::build_index_slice(const A& axis) const -> index_slice_type 180 | { 181 | return index_slice_type(axis[m_first], axis[m_last] + 1, m_step); 182 | } 183 | 184 | /**************************** 185 | * xaxis_all implementation * 186 | ****************************/ 187 | 188 | template 189 | inline auto xaxis_all::build_index_slice(const A& axis) const -> index_slice_type 190 | { 191 | return index_slice_type(axis.size()); 192 | } 193 | 194 | /****************************** 195 | * xaxis_slice implementation * 196 | ******************************/ 197 | 198 | template 199 | template 200 | inline xaxis_slice::xaxis_slice(const V& slice) 201 | : m_data(slice) 202 | { 203 | } 204 | 205 | template 206 | template 207 | inline xaxis_slice::xaxis_slice(V&& slice) 208 | : m_data(std::move(slice)) 209 | { 210 | } 211 | 212 | template 213 | template 214 | inline auto xaxis_slice::build_index_slice(const A& axis) const -> index_slice_type 215 | { 216 | return xtl::visit( 217 | xtl::make_overload([&axis](const auto& arg) { return index_slice_type(arg.build_index_slice(axis)); }, 218 | [&axis](const squeeze_type&) -> index_slice_type { throw std::runtime_error("build_islice forbidden for squeeze"); }), 219 | m_data); 220 | } 221 | 222 | template 223 | inline auto xaxis_slice::get_squeeze() const noexcept -> const squeeze_type* 224 | { 225 | return xtl::get_if(&m_data); 226 | } 227 | 228 | /*********************************** 229 | * helper functions implementation * 230 | ***********************************/ 231 | 232 | template 233 | inline xaxis_slice range(const xlabel_variant_t& first, const xlabel_variant_t& last) 234 | { 235 | return xaxis_slice(xaxis_range(first, last)); 236 | } 237 | 238 | template 239 | inline xaxis_slice range(xlabel_variant_t&& first, xlabel_variant_t&& last) 240 | { 241 | return xaxis_slice(xaxis_range(std::move(first), std::move(last))); 242 | } 243 | 244 | template 245 | inline xaxis_slice range(const xlabel_variant_t& first, const xlabel_variant_t& last, S step) 246 | { 247 | return xaxis_slice(xaxis_stepped_range(first, last, step)); 248 | } 249 | 250 | template 251 | inline xaxis_slice range(xlabel_variant_t&& first, xlabel_variant_t&& last, S step) 252 | { 253 | return xaxis_slice(xaxis_stepped_range(std::move(first), std::move(last), step)); 254 | } 255 | } 256 | 257 | #endif 258 | -------------------------------------------------------------------------------- /include/xframe/xdimension.hpp: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (c) 2017, Johan Mabille, Sylvain Corlay and Wolf Vollprecht * 3 | * * 4 | * Distributed under the terms of the BSD 3-Clause License. * 5 | * * 6 | * The full license is in the file LICENSE, distributed with this software. * 7 | ****************************************************************************/ 8 | 9 | #ifndef XFRAME_XDIMENSION_HPP 10 | #define XFRAME_XDIMENSION_HPP 11 | 12 | #include "xaxis.hpp" 13 | 14 | namespace xf 15 | { 16 | class xfull_coordinate; 17 | 18 | /************** 19 | * xdimension * 20 | **************/ 21 | 22 | template 23 | class xdimension : private xaxis 24 | { 25 | public: 26 | 27 | using self_type = xdimension; 28 | using base_type = xaxis; 29 | using label_list = typename base_type::label_list; 30 | using key_type = typename base_type::key_type; 31 | using mapped_type = typename base_type::mapped_type; 32 | using map_type = typename base_type::map_type; 33 | using value_type = typename base_type::value_type; 34 | using reference = typename base_type::reference; 35 | using const_reference = typename base_type::const_reference; 36 | using pointer = typename base_type::pointer; 37 | using const_pointer = typename base_type::const_pointer; 38 | using size_type = typename base_type::size_type; 39 | using difference_type = typename base_type::difference_type; 40 | using iterator = typename base_type::iterator; 41 | using const_iterator = typename base_type::const_iterator; 42 | using reverse_iterator = typename base_type::reverse_iterator; 43 | using const_reverse_iterator = typename base_type::const_reverse_iterator; 44 | 45 | xdimension(); 46 | explicit xdimension(const label_list& labels); 47 | explicit xdimension(label_list&& labels); 48 | xdimension(std::initializer_list init); 49 | 50 | template 51 | xdimension(InputIt first, InputIt last); 52 | 53 | template 54 | bool broadcast(const Args&... dims); 55 | 56 | using base_type::labels; 57 | using base_type::label; 58 | using base_type::empty; 59 | using base_type::size; 60 | using base_type::contains; 61 | using base_type::operator[]; 62 | using base_type::find; 63 | using base_type::begin; 64 | using base_type::end; 65 | using base_type::cbegin; 66 | using base_type::cend; 67 | using base_type::rbegin; 68 | using base_type::rend; 69 | using base_type::crbegin; 70 | using base_type::crend; 71 | 72 | private: 73 | 74 | template 75 | bool broadcast_impl(const self_type& a, const Args&... dims); 76 | 77 | template 78 | bool broadcast_impl(const xfull_coordinate& a, const Args&... dims); 79 | 80 | bool broadcast_impl(); 81 | 82 | template 83 | bool broadcast_empty(const self_type& a, const Args&... dims); 84 | 85 | template 86 | bool broadcast_empty(const xfull_coordinate& a, const Args&... dims); 87 | 88 | bool broadcast_empty(); 89 | }; 90 | 91 | template 92 | bool operator==(const xdimension& lhs, const xdimension& rhs) noexcept; 93 | 94 | template 95 | bool operator!=(const xdimension& lhs, const xdimension& rhs) noexcept; 96 | 97 | template 98 | OS& operator<<(OS& out, const xdimension& dim); 99 | 100 | template 101 | bool broadcast_dimensions(xdimension& output, const Args&... dims); 102 | 103 | /***************************** 104 | * is_dimension metafunction * 105 | *****************************/ 106 | 107 | namespace detail 108 | { 109 | template 110 | struct is_dimension_impl : std::false_type 111 | { 112 | }; 113 | 114 | template 115 | struct is_dimension_impl> : std::true_type 116 | { 117 | }; 118 | 119 | template 120 | struct is_dimension_list_impl : std::false_type 121 | { 122 | }; 123 | 124 | template 125 | struct is_dimension_list_impl> 126 | : std::true_type 127 | { 128 | }; 129 | } 130 | 131 | template 132 | struct is_dimension : detail::is_dimension_impl> 133 | { 134 | }; 135 | 136 | template 137 | struct is_dimension_list : detail::is_dimension_list_impl> 138 | { 139 | }; 140 | 141 | /***************************** 142 | * xdimension implementation * 143 | *****************************/ 144 | 145 | template 146 | inline xdimension::xdimension() 147 | : base_type() 148 | { 149 | } 150 | 151 | template 152 | inline xdimension::xdimension(const label_list& labels) 153 | : base_type(labels) 154 | { 155 | } 156 | 157 | template 158 | inline xdimension::xdimension(label_list&& labels) 159 | : base_type(std::move(labels)) 160 | { 161 | } 162 | 163 | template 164 | inline xdimension::xdimension(std::initializer_list init) 165 | : base_type(init) 166 | { 167 | } 168 | 169 | template 170 | template 171 | inline xdimension::xdimension(InputIt first, InputIt last) 172 | : base_type(first, last) 173 | { 174 | } 175 | 176 | 177 | template 178 | template 179 | inline bool xdimension::broadcast(const Args&... dims) 180 | { 181 | return this->empty() ? broadcast_empty(dims...) : broadcast_impl(dims...); 182 | } 183 | 184 | template 185 | template 186 | inline bool xdimension::broadcast_impl(const self_type& a, const Args&... dims) 187 | { 188 | XFRAME_TRACE_BROADCAST_DIMENSIONS(*this, a); 189 | bool res = base_type::merge_unsorted(true, a.labels()); 190 | XFRAME_TRACE_DIMENSIONS_RESULT(*this, res); 191 | res &= broadcast_impl(dims...); 192 | return res; 193 | } 194 | 195 | template 196 | template 197 | inline bool xdimension::broadcast_impl(const xfull_coordinate& /*a*/, const Args&... dims) 198 | { 199 | return broadcast_impl(dims...); 200 | } 201 | 202 | template 203 | inline bool xdimension::broadcast_impl() 204 | { 205 | return true; 206 | } 207 | 208 | template 209 | template 210 | bool xdimension::broadcast_empty(const self_type& a, const Args&... dims) 211 | { 212 | base_type::set_labels(a.labels()); 213 | return broadcast_impl(dims...); 214 | } 215 | 216 | template 217 | template 218 | bool xdimension::broadcast_empty(const xfull_coordinate& /*a*/, const Args&... dims) 219 | { 220 | return broadcast_empty(dims...); 221 | } 222 | 223 | template 224 | bool xdimension::broadcast_empty() 225 | { 226 | return true; 227 | } 228 | 229 | template 230 | inline bool operator==(const xdimension& lhs, const xdimension& rhs) noexcept 231 | { 232 | return lhs.labels() == rhs.labels(); 233 | } 234 | 235 | template 236 | inline bool operator!=(const xdimension& lhs, const xdimension& rhs) noexcept 237 | { 238 | return !(lhs == rhs); 239 | } 240 | 241 | template 242 | inline OS& operator<<(OS& out, const xdimension& dim) 243 | { 244 | using iterator = std::ostream_iterator; 245 | out << '('; 246 | std::copy(dim.labels().begin(), dim.labels().end(), iterator(out, ", ")); 247 | out << ')'; 248 | return out; 249 | } 250 | 251 | template 252 | inline bool broadcast_dimensions(xdimension& output, const Args&... dims) 253 | { 254 | return output.broadcast(dims...); 255 | } 256 | } 257 | 258 | #endif 259 | -------------------------------------------------------------------------------- /include/xframe/xaxis_base.hpp: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (c) 2017, Johan Mabille, Sylvain Corlay, Wolf Vollprecht and * 3 | * Martin Renou * 4 | * * 5 | * Distributed under the terms of the BSD 3-Clause License. * 6 | * * 7 | * The full license is in the file LICENSE, distributed with this software. * 8 | ****************************************************************************/ 9 | 10 | #ifndef XFRAME_XAXIS_BASE_HPP 11 | #define XFRAME_XAXIS_BASE_HPP 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | namespace xf 18 | { 19 | 20 | template 21 | struct xaxis_inner_types; 22 | 23 | /************** 24 | * xaxis_base * 25 | **************/ 26 | 27 | template 28 | class xaxis_base 29 | { 30 | public: 31 | 32 | using derived_type = D; 33 | using inner_types = xaxis_inner_types; 34 | 35 | using key_type = typename inner_types::key_type; 36 | using mapped_type = typename inner_types::mapped_type; 37 | using label_list = std::vector; 38 | using size_type = typename label_list::size_type; 39 | using difference_type = typename label_list::difference_type; 40 | using iterator = typename inner_types::iterator; 41 | using const_iterator = iterator; 42 | using reverse_iterator = std::reverse_iterator; 43 | using const_reverse_iterator = reverse_iterator; 44 | 45 | static_assert(std::is_integral::value, "mapped_type T must be an integral type"); 46 | 47 | derived_type& derived_cast() & noexcept; 48 | const derived_type& derived_cast() const & noexcept; 49 | derived_type derived_cast() && noexcept; 50 | 51 | const label_list& labels() const noexcept; 52 | key_type label(size_type i) const; 53 | 54 | bool empty() const noexcept; 55 | size_type size() const noexcept; 56 | 57 | const_iterator begin() const noexcept; 58 | const_iterator end() const noexcept; 59 | 60 | const_reverse_iterator rbegin() const noexcept; 61 | const_reverse_iterator rend() const noexcept; 62 | 63 | const_reverse_iterator crbegin() const noexcept; 64 | const_reverse_iterator crend() const noexcept; 65 | 66 | protected: 67 | 68 | xaxis_base(); 69 | xaxis_base(const label_list& labels); 70 | xaxis_base(label_list&& labels); 71 | xaxis_base(std::initializer_list init); 72 | 73 | template 74 | xaxis_base(InputIt first, InputIt last); 75 | 76 | ~xaxis_base() = default; 77 | 78 | xaxis_base(const xaxis_base&) = default; 79 | xaxis_base& operator=(const xaxis_base&) = default; 80 | 81 | xaxis_base(xaxis_base&&) = default; 82 | xaxis_base& operator=(xaxis_base&&) = default; 83 | 84 | label_list& mutable_labels() noexcept; 85 | 86 | template 87 | label_list filter_labels(const F& f) const noexcept; 88 | 89 | template 90 | label_list filter_labels(const F& f, size_type size) const noexcept; 91 | 92 | label_list m_labels; 93 | }; 94 | 95 | template 96 | bool operator==(const xaxis_base& lhs, const xaxis_base& rhs) noexcept; 97 | 98 | template 99 | bool operator!=(const xaxis_base& lhs, const xaxis_base& rhs) noexcept; 100 | 101 | template 102 | OS& operator<<(OS& out, const xaxis_base& axis); 103 | 104 | template 105 | bool merge_axes(xaxis_base& output, const Args&... axes); 106 | 107 | template 108 | bool intersect_axes(xaxis_base& output, const Args&... axes); 109 | 110 | /************************ 111 | * is_axis metafunction * 112 | ************************/ 113 | 114 | template 115 | struct is_axis : std::is_base_of, T> 116 | { 117 | }; 118 | 119 | /***************************** 120 | * xaxis_base implementation * 121 | *****************************/ 122 | 123 | template 124 | inline xaxis_base::xaxis_base() 125 | : m_labels() 126 | { 127 | } 128 | 129 | template 130 | inline xaxis_base::xaxis_base(const label_list& labels) 131 | : m_labels(labels) 132 | { 133 | } 134 | 135 | template 136 | inline xaxis_base::xaxis_base(label_list&& labels) 137 | : m_labels(std::move(labels)) 138 | { 139 | } 140 | 141 | template 142 | inline xaxis_base::xaxis_base(std::initializer_list init) 143 | : m_labels(init) 144 | { 145 | } 146 | 147 | template 148 | template 149 | inline xaxis_base::xaxis_base(InputIt first, InputIt last) 150 | : m_labels(first, last) 151 | { 152 | } 153 | 154 | template 155 | inline auto xaxis_base::derived_cast() & noexcept -> derived_type& 156 | { 157 | return *static_cast(this); 158 | } 159 | 160 | template 161 | inline auto xaxis_base::derived_cast() const & noexcept -> const derived_type& 162 | { 163 | return *static_cast(this); 164 | } 165 | 166 | template 167 | inline auto xaxis_base::derived_cast() && noexcept -> derived_type 168 | { 169 | return *static_cast(this); 170 | } 171 | 172 | template 173 | inline auto xaxis_base::labels() const noexcept -> const label_list& 174 | { 175 | return m_labels; 176 | } 177 | 178 | template 179 | inline auto xaxis_base::label(size_type i) const -> key_type 180 | { 181 | return m_labels[i]; 182 | } 183 | 184 | template 185 | inline bool xaxis_base::empty() const noexcept 186 | { 187 | return m_labels.empty(); 188 | } 189 | 190 | template 191 | inline auto xaxis_base::size() const noexcept -> size_type 192 | { 193 | return m_labels.size(); 194 | } 195 | 196 | template 197 | inline auto xaxis_base::begin() const noexcept -> const_iterator 198 | { 199 | return derived_cast().cbegin(); 200 | } 201 | 202 | template 203 | inline auto xaxis_base::end() const noexcept -> const_iterator 204 | { 205 | return derived_cast().cend(); 206 | } 207 | 208 | template 209 | inline auto xaxis_base::rbegin() const noexcept -> const_reverse_iterator 210 | { 211 | return crbegin(); 212 | } 213 | 214 | template 215 | inline auto xaxis_base::rend() const noexcept -> const_reverse_iterator 216 | { 217 | return crend(); 218 | } 219 | 220 | template 221 | inline auto xaxis_base::crbegin() const noexcept -> const_reverse_iterator 222 | { 223 | return const_reverse_iterator(derived_cast().cend()); 224 | } 225 | 226 | template 227 | inline auto xaxis_base::crend() const noexcept -> const_reverse_iterator 228 | { 229 | return const_reverse_iterator(derived_cast().cbegin()); 230 | } 231 | 232 | template 233 | inline auto xaxis_base::mutable_labels() noexcept -> label_list& 234 | { 235 | return m_labels; 236 | } 237 | 238 | template 239 | template 240 | inline auto xaxis_base::filter_labels(const F& f) const noexcept -> label_list 241 | { 242 | label_list l; 243 | std::copy_if(m_labels.cbegin(), m_labels.cend(), std::back_inserter(l), f); 244 | return l; 245 | } 246 | 247 | template 248 | template 249 | inline auto xaxis_base::filter_labels(const F& f, size_type size) const noexcept -> label_list 250 | { 251 | label_list l(size); 252 | std::copy_if(m_labels.cbegin(), m_labels.cend(), l.begin(), f); 253 | return l; 254 | } 255 | 256 | template 257 | inline bool operator==(const xaxis_base& lhs, const xaxis_base& rhs) noexcept 258 | { 259 | return lhs.labels() == rhs.labels(); 260 | } 261 | 262 | template 263 | inline bool operator!=(const xaxis_base& lhs, const xaxis_base& rhs) noexcept 264 | { 265 | return !(lhs == rhs); 266 | } 267 | 268 | template 269 | inline OS& operator<<(OS& out, const xaxis_base& axis) 270 | { 271 | using iterator = std::ostream_iterator::key_type, typename OS::char_type, typename OS::traits_type>; 272 | out << '('; 273 | std::copy(axis.labels().begin(), axis.labels().end(), iterator(out, ", ")); 274 | out << ')'; 275 | return out; 276 | } 277 | } 278 | 279 | #endif 280 | -------------------------------------------------------------------------------- /test/test_xaxis.cpp: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (c) 2017, Johan Mabille, Sylvain Corlay and Wolf Vollprecht * 3 | * * 4 | * Distributed under the terms of the BSD 3-Clause License. * 5 | * * 6 | * The full license is in the file LICENSE, distributed with this software. * 7 | ****************************************************************************/ 8 | 9 | #include 10 | #include 11 | #include "gtest/gtest.h" 12 | #include "xframe/xaxis_base.hpp" 13 | #include "xframe/xaxis.hpp" 14 | #include "xtl/xbasic_fixed_string.hpp" 15 | 16 | namespace xf 17 | { 18 | using fstring = xtl::xfixed_string<55>; 19 | using label_type = std::vector; 20 | using axis_type = xaxis; 21 | using caxis_type = xaxis; 22 | using iaxis_type = xaxis; 23 | using daxis_type = xaxis; 24 | 25 | TEST(xaxis, constructors) 26 | { 27 | label_type l = { "a", "b", "c" }; 28 | // From const label_type& 29 | { 30 | axis_type a(l); 31 | EXPECT_EQ(l, a.labels()); 32 | } 33 | 34 | // From label_type&& 35 | { 36 | label_type tmp(l); 37 | axis_type a(std::move(tmp)); 38 | EXPECT_EQ(l, a.labels()); 39 | } 40 | 41 | // From initializer_list 42 | { 43 | axis_type a = { "a", "b", "c" }; 44 | EXPECT_EQ(l, a.labels()); 45 | } 46 | 47 | // From iterators 48 | { 49 | axis_type a(l.cbegin(), l.cend()); 50 | EXPECT_EQ(l, a.labels()); 51 | } 52 | } 53 | 54 | TEST(xaxis, axis) 55 | { 56 | caxis_type a = axis('a', 'd'); 57 | EXPECT_EQ(a.size(), 3); 58 | EXPECT_EQ(a['a'], 0); 59 | EXPECT_EQ(a['b'], 1); 60 | EXPECT_EQ(a['c'], 2); 61 | 62 | caxis_type b = axis({'b', 'e', 'f', 'g'}); 63 | EXPECT_EQ(b.size(), 4); 64 | EXPECT_EQ(b['b'], 0); 65 | EXPECT_EQ(b['e'], 1); 66 | EXPECT_EQ(b['f'], 2); 67 | EXPECT_EQ(b['g'], 3); 68 | 69 | daxis_type c = axis(0., 1., 0.1); 70 | EXPECT_EQ(c.size(), 10); 71 | EXPECT_EQ(c[0.], 0); 72 | EXPECT_EQ(c[0.1], 1); 73 | EXPECT_EQ(c[0.9], 9); 74 | } 75 | 76 | TEST(xaxis, size) 77 | { 78 | axis_type a = { "a", "b", "c" }; 79 | EXPECT_EQ(3u, a.size()); 80 | EXPECT_FALSE(a.empty()); 81 | 82 | axis_type a2; 83 | EXPECT_EQ(0u, a2.size()); 84 | EXPECT_TRUE(a2.empty()); 85 | } 86 | 87 | TEST(xaxis, contains) 88 | { 89 | axis_type a = { "a", "b", "c" }; 90 | EXPECT_TRUE(a.contains("a")); 91 | EXPECT_FALSE(a.contains("d")); 92 | } 93 | 94 | TEST(xaxis, access) 95 | { 96 | axis_type a = { "a", "b", "c" }; 97 | auto aa = a["a"]; 98 | auto ab = a["b"]; 99 | auto ac = a["c"]; 100 | EXPECT_EQ(0u, aa); 101 | EXPECT_EQ(1u, ab); 102 | EXPECT_EQ(2u, ac); 103 | EXPECT_THROW(a["d"], std::out_of_range); 104 | } 105 | 106 | TEST(xaxis, iterator) 107 | { 108 | axis_type a = { "a", "b", "c" }; 109 | 110 | auto it = a.begin(); 111 | 112 | EXPECT_TRUE(it == a.cbegin()); 113 | EXPECT_TRUE(it != a.end()); 114 | EXPECT_TRUE(it < a.end()); 115 | EXPECT_TRUE(it <= a.end()); 116 | EXPECT_FALSE(it > a.end()); 117 | EXPECT_FALSE(it >= a.end()); 118 | EXPECT_EQ(a.end(), a.cend()); 119 | 120 | EXPECT_EQ(it->first, "a"); 121 | EXPECT_EQ(it->second, a["a"]); 122 | ++it; 123 | EXPECT_EQ(it->first, "b"); 124 | EXPECT_EQ(it->second, a["b"]); 125 | auto tmp = it++; 126 | EXPECT_EQ(tmp->first, "b"); 127 | EXPECT_EQ(it->first, "c"); 128 | EXPECT_EQ(tmp->second, a["b"]); 129 | EXPECT_EQ(it->second, a["c"]); 130 | ++it; 131 | EXPECT_EQ(it, a.end()); 132 | 133 | EXPECT_EQ(a["c"], (a.begin() + 2)->second); 134 | EXPECT_EQ(a["b"], (a.end() - 2)->second); 135 | EXPECT_EQ(3, a.end() - a.begin()); 136 | } 137 | 138 | TEST(xaxis, find) 139 | { 140 | axis_type a = { "a", "b", "c" }; 141 | 142 | auto ita = a.find("a"); 143 | auto itb = a.find("b"); 144 | auto itc = a.find("c"); 145 | auto itd = a.find("d"); 146 | 147 | EXPECT_EQ(ita->first, "a"); 148 | EXPECT_EQ(itb->first, "b"); 149 | EXPECT_EQ(itc->first, "c"); 150 | EXPECT_EQ(itd, a.end()); 151 | } 152 | 153 | TEST(xaxis, is_sorted) 154 | { 155 | axis_type a = { "a", "b", "c" }; 156 | EXPECT_TRUE(a.is_sorted()); 157 | 158 | axis_type b = { "b", "b", "c" }; 159 | EXPECT_TRUE(b.is_sorted()); 160 | 161 | axis_type c = { "c", "b", "a" }; 162 | EXPECT_FALSE(c.is_sorted()); 163 | } 164 | 165 | TEST(xaxis, merge) 166 | { 167 | axis_type a1 = { "a", "b", "d", "e" }; 168 | axis_type a2 = { "b", "c", "d" }; 169 | axis_type a3 = { "c", "g" }; 170 | axis_type res; 171 | bool t1 = merge_axes(res, a1, a2, a3); 172 | EXPECT_FALSE(t1); 173 | EXPECT_EQ(res["a"], 0); 174 | EXPECT_EQ(res["b"], 1); 175 | EXPECT_EQ(res["c"], 2); 176 | EXPECT_EQ(res["d"], 3); 177 | EXPECT_EQ(res["e"], 4); 178 | EXPECT_EQ(res["g"], 5); 179 | 180 | axis_type a4; 181 | axis_type res2; 182 | bool t2 = merge_axes(res2, a1, a4); 183 | EXPECT_FALSE(t2); 184 | EXPECT_EQ(res2, a1); 185 | 186 | axis_type a5 = { "a", "b", "d", "e" }; 187 | axis_type a6 = { "a", "b", "d", "e" }; 188 | axis_type res3; 189 | bool t3 = merge_axes(res3, a5, a6); 190 | EXPECT_TRUE(t3); 191 | 192 | axis_type a7 = { "e", "f" }; 193 | axis_type a8 = { "a", "b", "c", "d" }; 194 | axis_type res4; 195 | merge_axes(res4, a7, a8); 196 | EXPECT_EQ(res4["a"], 0); 197 | EXPECT_EQ(res4["b"], 1); 198 | EXPECT_EQ(res4["c"], 2); 199 | EXPECT_EQ(res4["d"], 3); 200 | EXPECT_EQ(res4["e"], 4); 201 | EXPECT_EQ(res4["f"], 5); 202 | 203 | xaxis ia1 = { 1, 2, 4}; 204 | xaxis ia2 = { 1, 4, 5}; 205 | xaxis iares; 206 | bool t4 = merge_axes(iares, ia1, ia2); 207 | EXPECT_FALSE(t4); 208 | EXPECT_EQ(iares[1], 0); 209 | EXPECT_EQ(iares[2], 1); 210 | EXPECT_EQ(iares[4], 2); 211 | EXPECT_EQ(iares[5], 3); 212 | } 213 | 214 | TEST(xaxis, merge_unsorted) 215 | { 216 | axis_type a1({ "a", "b", "d", "e" }); 217 | axis_type a2({ "d", "e" }); 218 | axis_type a3({ "h", "c", "a", "b", "d", "e" }); 219 | axis_type a4({ "h", "b", "c", "e" }); 220 | 221 | axis_type res1; 222 | bool t1 = merge_axes(res1, a1, a2); 223 | EXPECT_FALSE(t1); 224 | EXPECT_TRUE(a1.is_sorted()); 225 | EXPECT_TRUE(a2.is_sorted()); 226 | EXPECT_TRUE(res1.is_sorted()); 227 | EXPECT_EQ(res1.size(), 4u); 228 | EXPECT_EQ(res1["a"], 0); 229 | EXPECT_EQ(res1["b"], 1); 230 | EXPECT_EQ(res1["d"], 2); 231 | EXPECT_EQ(res1["e"], 3); 232 | 233 | axis_type res2; 234 | bool t2 = merge_axes(res2, a1, a3); 235 | EXPECT_FALSE(t2); 236 | EXPECT_TRUE(a1.is_sorted()); 237 | EXPECT_FALSE(a3.is_sorted()); 238 | EXPECT_FALSE(res2.is_sorted()); 239 | EXPECT_EQ(res2.size(), 6u); 240 | EXPECT_EQ(res2["h"], 0); 241 | EXPECT_EQ(res2["c"], 1); 242 | EXPECT_EQ(res2["a"], 2); 243 | EXPECT_EQ(res2["b"], 3); 244 | EXPECT_EQ(res2["d"], 4); 245 | EXPECT_EQ(res2["e"], 5); 246 | 247 | axis_type res3; 248 | bool t3 = merge_axes(res3, a1, a4); 249 | EXPECT_FALSE(t3); 250 | EXPECT_TRUE(a1.is_sorted()); 251 | EXPECT_FALSE(a4.is_sorted()); 252 | EXPECT_FALSE(res3.is_sorted()); 253 | EXPECT_EQ(res3.size(), 6u); 254 | EXPECT_EQ(res3["h"], 0); 255 | EXPECT_EQ(res3["c"], 1); 256 | EXPECT_EQ(res3["a"], 2); 257 | EXPECT_EQ(res3["b"], 3); 258 | EXPECT_EQ(res3["d"], 4); 259 | EXPECT_EQ(res3["e"], 5); 260 | } 261 | 262 | TEST(xaxis, intersect) 263 | { 264 | axis_type a1 = { "a", "b", "d", "e" }; 265 | axis_type a2 = { "b", "c", "d" }; 266 | axis_type a3 = { "a", "b", "d", "f" }; 267 | axis_type res = { "b", "d" }; 268 | axis_type tmp = a1; 269 | bool t1 = intersect_axes(tmp, a2, a3); 270 | EXPECT_FALSE(t1); 271 | EXPECT_EQ(tmp, res); 272 | 273 | tmp = a1; 274 | bool t2 = intersect_axes(tmp, a1); 275 | EXPECT_TRUE(t2); 276 | EXPECT_EQ(tmp, a1); 277 | } 278 | 279 | TEST(xaxis, filter) 280 | { 281 | axis_type a = { "a", "b", "d", "e" }; 282 | axis_type filtered_a = a.filter([](const auto& arg) { return arg < "d"; }); 283 | EXPECT_EQ(filtered_a.size(), 2); 284 | EXPECT_EQ(a["a"], 0); 285 | EXPECT_EQ(a["b"], 1); 286 | } 287 | } 288 | -------------------------------------------------------------------------------- /test/test_fixture_view.hpp: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (c) 2017, Johan Mabille, Sylvain Corlay and Wolf Vollprecht * 3 | * * 4 | * Distributed under the terms of the BSD 3-Clause License. * 5 | * * 6 | * The full license is in the file LICENSE, distributed with this software. * 7 | ****************************************************************************/ 8 | 9 | #ifndef XFRAME_TEST_FIXTURE_VIEW_HPP 10 | #define XFRAME_TEST_FIXTURE_VIEW_HPP 11 | 12 | #include 13 | 14 | #include "xtl/xbasic_fixed_string.hpp" 15 | 16 | #include "xtensor/xmasked_value.hpp" 17 | 18 | #include "xframe/xvariable_view.hpp" 19 | 20 | namespace xf 21 | { 22 | using fstring = xtl::xfixed_string<55>; 23 | using saxis_type = xaxis; 24 | using iaxis_type = xaxis; 25 | using size_type = std::size_t; 26 | using axis_variant = xaxis_variant; 27 | using axis_view_type = xaxis_view; 28 | using coordinate_type = xcoordinate; 29 | using coordinate_view_type = xcoordinate_view; 30 | using dimension_type = xdimension; 31 | using data_type = xt::xoptional_assembly, xt::xarray>; 32 | using masked_data_type = xt::xarray>>; 33 | using variable_type = xvariable; 34 | using variable_view_type = xvariable_view; 35 | 36 | // { "a", "c", "d", "f", "g", "h", "m", "n" } 37 | inline saxis_type make_test_view_saxis() 38 | { 39 | return saxis_type({ "a", "c", "d", "f", "g", "h", "m", "n" }); 40 | } 41 | 42 | inline axis_variant make_variant_view_saxis() 43 | { 44 | return axis_variant(make_test_view_saxis()); 45 | } 46 | 47 | // { 1, 2, 4, 5, 6, 8, 12, 13 } 48 | inline iaxis_type make_test_view_iaxis() 49 | { 50 | return iaxis_type({ 1, 2, 4, 5, 6, 8, 12, 13 }); 51 | } 52 | 53 | // abscissa: { "a", "c", "d", "f", "g", "h", "m", "n" } 54 | // ordinate: { 1, 2, 4, 5, 6, 8, 12, 13 } 55 | inline coordinate_type make_test_view_coordinate() 56 | { 57 | fstring s1 = "abscissa"; 58 | fstring s2 = "ordinate"; 59 | return coordinate({ 60 | {s1, make_test_view_saxis()}, 61 | {s2, make_test_view_iaxis()} 62 | }); 63 | } 64 | 65 | // ordinate 66 | // 1, 2, 4, 5, 6, 8, 12, 13 67 | // a {{ 0, 1, 2, 3, 4, 5, 6, 7}, 68 | // c { 8, 9, 10, 11, 12, 13, 14, 15}, 69 | // d { 16, 17, 18, N/A, N/A, 21, 22, 23}, 70 | // abscissa f { 24, 25, 26, 27, 28, 29, 30, 31}, 71 | // g { 32, 33, 34, 35, 36, 37, 38, 39}, 72 | // h { 40, 41, 42, 43, 44, 45, 46, 47}, 73 | // m { 48, 49, 50, 51, 52, 53, 54, 55}, 74 | // n { 56, 57, 58, 59, 60, 61, 62, 63}} 75 | inline variable_type make_test_view_variable() 76 | { 77 | coordinate_type c = make_test_view_coordinate(); 78 | data_type d = data_type::from_shape({ c["abscissa"].size(), c["ordinate"].size() }); 79 | std::iota(d.begin(), d.end(), 0.); 80 | d(2, 3).has_value() = false; 81 | d(2, 4).has_value() = false; 82 | return variable_type(std::move(d), std::move(c), dimension_type({ "abscissa", "ordinate" })); 83 | } 84 | 85 | // ordinate 86 | // 1, 2, 4, 5, 6, 8, 12, 13 87 | // a {{ 0, 1, 2, 3, masked, masked, masked, masked}, 88 | // c { 8, 9, 10, 11, masked, masked, masked, masked}, 89 | // d { 16, 17, 18, N/A, masked, masked, masked, masked}, 90 | // abscissa f { 24, 25, 26, 27, masked, masked, masked, masked}, 91 | // g { 32, 33, 34, 35, masked, masked, masked, masked}, 92 | // h { 40, 41, 42, 43, masked, masked, masked, masked}, 93 | // m { 48, 49, 50, 51, masked, masked, masked, masked}, 94 | // n { 56, 57, 58, 59, masked, masked, masked, masked} 95 | inline auto make_masked_data() 96 | { 97 | masked_data_type val = masked_data_type::from_shape({ 8, 8 }); 98 | std::iota(val.begin(), val.end(), 0.); 99 | val(2, 3).value().has_value() = false; 100 | val(2, 4).value().has_value() = false; 101 | 102 | for (std::size_t a = 0; a < val.shape()[0]; ++a) 103 | { 104 | for (std::size_t o = 4; o < val.shape()[1]; ++o) 105 | { 106 | val(a, o) = xt::masked>(); 107 | } 108 | } 109 | return val; 110 | } 111 | 112 | // ordinate 113 | // 1, 2, 4, 5, 6, 8, 12, 13 114 | // a {{masked, 1, 2, 3, 4, 5, 6, 7}, 115 | // c {masked, 9, 10, 11, 12, 13, 14, 15}, 116 | // d {masked, 17, 18, N/A, N/A, 21, 22, 23}, 117 | // abscissa f {masked, 25, 26, 27, 28, 29, 30, 31}, 118 | // g {masked, 33, 34, 35, 36, 37, 38, 39}, 119 | // h {masked, 41, 42, 43, 44, 45, 46, 47}, 120 | // m {masked, masked, masked, masked, masked, masked, masked, masked}, 121 | // n {masked, 57, 58, 59, 60, 61, 62, 63} 122 | inline auto make_masked_data2() 123 | { 124 | masked_data_type val = masked_data_type::from_shape({ 8, 8 }); 125 | std::iota(val.begin(), val.end(), 0.); 126 | val(2, 3).value().has_value() = false; 127 | val(2, 4).value().has_value() = false; 128 | 129 | for (std::size_t o = 0; o < val.shape()[1]; ++o) 130 | { 131 | val(6, o) = xt::masked>(); 132 | } 133 | for (std::size_t a = 0; a < val.shape()[0]; ++a) 134 | { 135 | val(a, 0) = xt::masked>(); 136 | } 137 | return val; 138 | } 139 | 140 | // ordinate 141 | // 1, 2, 4, 5, 6, 8, 12, 13 142 | // a {{masked, 5.2, 5.2, 5.2, 5.2, 5.2, 5.2, 5.2}, 143 | // c {masked, 5.2, 5.2, 5.2, 5.2, 5.2, 5.2, 5.2}, 144 | // d {masked, 5.2, 5.2, 5.2, 5.2, 5.2, 5.2, 5.2}, 145 | // abscissa f {masked, 5.2, 5.2, 5.2, 5.2, 5.2, 5.2, 5.2}, 146 | // g {masked, 5.2, 5.2, 5.2, 5.2, 5.2, 5.2, 5.2}, 147 | // h {masked, 5.2, 5.2, 5.2, 5.2, 5.2, 5.2, 5.2}, 148 | // m {masked, masked, masked, masked, masked, masked, masked, masked}, 149 | // n {masked, 5.2, 5.2, 5.2, 5.2, 5.2, 5.2, 5.2} 150 | inline auto make_masked_data3() 151 | { 152 | masked_data_type val = masked_data_type::from_shape({ 8, 8 }); 153 | std::iota(val.begin(), val.end(), 0.); 154 | val(2, 3).value().has_value() = false; 155 | val(2, 4).value().has_value() = false; 156 | 157 | val.fill(5.2); 158 | for (std::size_t o = 0; o < val.shape()[1]; ++o) 159 | { 160 | val(6, o) = xt::masked>(); 161 | } 162 | for (std::size_t a = 0; a < val.shape()[0]; ++a) 163 | { 164 | val(a, 0) = xt::masked>(); 165 | } 166 | return val; 167 | } 168 | 169 | // abscissa: { "f", "g", "h", "m", "n" } 170 | // ordinate: { 1, 4, 6 } 171 | inline coordinate_view_type build_coordinate_view(const coordinate_type& c) 172 | { 173 | using map_type = typename coordinate_view_type::map_type; 174 | map_type nmap; 175 | 176 | auto r = range("f", "n"); 177 | auto sr = range(1, 6, 2); 178 | 179 | const auto& abscissa = c["abscissa"]; 180 | const auto& ordinate = c["ordinate"]; 181 | 182 | nmap.emplace(std::make_pair("abscissa", axis_view_type(abscissa, r.build_index_slice(abscissa)))); 183 | nmap.emplace(std::make_pair("ordinate", axis_view_type(ordinate, sr.build_index_slice(ordinate)))); 184 | 185 | return coordinate_view(std::move(nmap)); 186 | } 187 | 188 | // abscissa: { "f", "g", "h", "m", "n" } 189 | // ordinate: { 1, 4, 6 } 190 | // dims: {{ "abscissa", 0 }, { "ordinate", 1 }} 191 | inline variable_view_type build_view(variable_type& v) 192 | { 193 | const coordinate_type& c = v.coordinates(); 194 | dimension_type dim = v.dimension_mapping(); 195 | return variable_view_type(v, build_coordinate_view(c), std::move(dim), {}); 196 | } 197 | } 198 | 199 | #endif 200 | -------------------------------------------------------------------------------- /include/xframe/xvariable_assign.hpp: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (c) 2017, Johan Mabille, Sylvain Corlay and Wolf Vollprecht * 3 | * * 4 | * Distributed under the terms of the BSD 3-Clause License. * 5 | * * 6 | * The full license is in the file LICENSE, distributed with this software. * 7 | ****************************************************************************/ 8 | 9 | #ifndef XFRAME_XVARIABLE_ASSIGN_HPP 10 | #define XFRAME_XVARIABLE_ASSIGN_HPP 11 | 12 | #include "xtensor/xassign.hpp" 13 | #include "xcoordinate.hpp" 14 | #include "xframe_expression.hpp" 15 | 16 | namespace xt 17 | { 18 | using xvariable_expression_tag = xf::xvariable_expression_tag; 19 | 20 | template <> 21 | class xexpression_assigner 22 | { 23 | public: 24 | 25 | template 26 | static void assign_data(xexpression& e1, const xexpression& e2, bool trivial); 27 | 28 | template 29 | static void assign_xexpression(xexpression& e1, const xexpression& e2); 30 | 31 | template 32 | static void computed_assign(xexpression& e1, const xexpression& e2); 33 | 34 | template 35 | static void scalar_computed_assign(xexpression& e1, const E2& e2, F&& f); 36 | 37 | template 38 | static void assert_compatible_shape(const xexpression& e1, const xexpression& e2); 39 | 40 | private: 41 | 42 | template 43 | static xf::xtrivial_broadcast resize(xexpression& e1, const xexpression& e2); 44 | 45 | template 46 | static void assign_optional_tensor(xexpression& e1, const xexpression& e2, bool trivial); 47 | 48 | template 49 | static void assign_resized_xexpression(xexpression& e1, const xexpression& e2, 50 | xf::xtrivial_broadcast trivial); 51 | }; 52 | 53 | /*************************************** 54 | * xexpression_assigner implementation * 55 | ***************************************/ 56 | 57 | namespace detail 58 | { 59 | template 60 | bool increment_index(const ST& shape, IT& index) 61 | { 62 | using size_type = typename ST::size_type; 63 | size_type i = index.size(); 64 | while(i != 0) 65 | { 66 | --i; 67 | if(index[i] != shape[i] - 1) 68 | { 69 | ++index[i]; 70 | return false; 71 | } 72 | else 73 | { 74 | index[i] = 0; 75 | } 76 | } 77 | return true; 78 | } 79 | } 80 | 81 | template 82 | inline void xexpression_assigner::assign_data(xexpression& e1, 83 | const xexpression& e2, 84 | bool /*trivial*/) 85 | { 86 | const auto& dim_label = e1.derived_cast().dimension_mapping().labels(); 87 | const auto& coords = e1.derived_cast().coordinates(); 88 | using size_type = typename E1::size_type; 89 | std::vector index(dim_label.size(), size_type(0)); 90 | using selector_sequence_type = typename E1::template selector_sequence_type<>; 91 | selector_sequence_type selector(index.size()); 92 | bool end = false; 93 | do 94 | { 95 | for(size_type i = 0; i < index.size(); ++i) 96 | { 97 | selector[i] = std::make_pair(dim_label[i], coords[dim_label[i]].label(index[i])); 98 | } 99 | e1.derived_cast().select(selector) = e2.derived_cast().select(selector); 100 | end = detail::increment_index(e1.derived_cast().shape(), index); 101 | } 102 | while(!end); 103 | } 104 | 105 | template 106 | inline void xexpression_assigner::assign_xexpression(xexpression& e1, 107 | const xexpression& e2) 108 | { 109 | XFRAME_TRACE("ASSIGN EXPRESSION - BEGIN"); 110 | xf::xtrivial_broadcast trivial = resize(e1, e2); 111 | assign_resized_xexpression(e1, e2, trivial); 112 | XFRAME_TRACE("ASSIGN EXPRESSION - END" << std::endl); 113 | } 114 | 115 | template 116 | inline void xexpression_assigner::computed_assign(xexpression& e1, 117 | const xexpression& e2) 118 | { 119 | using coordinate_type = typename E1::coordinate_type; 120 | using dimension_type = typename E1::dimension_type; 121 | coordinate_type c; 122 | dimension_type d; 123 | xf::xtrivial_broadcast trivial = e2.derived_cast().broadcast_coordinates(c); 124 | bool dim_trivial = e2.derived_cast().broadcast_dimensions(d, trivial.m_xtensor_trivial); 125 | trivial.m_xframe_trivial &= dim_trivial; 126 | if (d.size() > e1.derived_cast().dimension_mapping().size() || !trivial.m_xframe_trivial) 127 | { 128 | typename E1::temporary_type tmp(std::move(c), std::move(d)); 129 | assign_resized_xexpression(tmp, e2, trivial); 130 | e1.derived_cast().assign_temporary(std::move(tmp)); 131 | } 132 | else 133 | { 134 | assign_resized_xexpression(e1, e2, trivial); 135 | } 136 | } 137 | 138 | template 139 | inline void xexpression_assigner::scalar_computed_assign(xexpression& e1, 140 | const E2& e2, 141 | F&& f) 142 | { 143 | E1& d = e1.derived_cast(); 144 | std::transform(d.data().cbegin(), d.data().cend(), d.data().begin(), 145 | [e2, &f](const auto& v) { return f(v, e2); }); 146 | } 147 | 148 | template 149 | inline void xexpression_assigner::assert_compatible_shape(const xexpression& e1, 150 | const xexpression& e2) 151 | { 152 | const auto& c1 = e1.derived_cast().coordinates(); 153 | const auto& l2 = e2.derived_cast().dimension_labels(); 154 | bool res = std::accumulate(l2.cbegin(), l2.cend(), true, 155 | [&c1](bool res, const auto& arg) { return res && c1.contains(arg); }); 156 | if (!res) 157 | { 158 | throw std::runtime_error("Incompatible dimensions of expressions"); 159 | } 160 | } 161 | 162 | template 163 | inline xf::xtrivial_broadcast xexpression_assigner::resize(xexpression& e1, 164 | const xexpression& e2) 165 | { 166 | using coordinate_type = typename E1::coordinate_type; 167 | using dimension_type = typename E1::dimension_type; 168 | coordinate_type c; 169 | dimension_type d; 170 | xf::xtrivial_broadcast res = e2.derived_cast().broadcast_coordinates(c); 171 | bool dim_trivial = e2.derived_cast().broadcast_dimensions(d, res.m_xtensor_trivial); 172 | res.m_xframe_trivial &= dim_trivial; 173 | e1.derived_cast().resize(c, d); 174 | return res; 175 | } 176 | 177 | template 178 | inline void xexpression_assigner::assign_optional_tensor(xexpression& e1, 179 | const xexpression& e2, 180 | bool trivial) 181 | { 182 | xexpression_assigner::assign_data(e1.derived_cast().data(), 183 | e2.derived_cast().data(), 184 | trivial); 185 | } 186 | 187 | template 188 | inline void xexpression_assigner::assign_resized_xexpression(xexpression& e1, 189 | const xexpression& e2, 190 | xf::xtrivial_broadcast trivial) 191 | { 192 | if (trivial.m_xframe_trivial) 193 | { 194 | assign_optional_tensor(e1, e2, trivial.m_xtensor_trivial); 195 | } 196 | else 197 | { 198 | assign_data(e1, e2, false); 199 | } 200 | } 201 | } 202 | 203 | #endif 204 | -------------------------------------------------------------------------------- /include/xframe/xselecting.hpp: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (c) 2017, Johan Mabille, Sylvain Corlay and Wolf Vollprecht * 3 | * * 4 | * Distributed under the terms of the BSD 3-Clause License. * 5 | * * 6 | * The full license is in the file LICENSE, distributed with this software. * 7 | ****************************************************************************/ 8 | 9 | #ifndef XFRAME_XSELECTING_HPP 10 | #define XFRAME_XSELECTING_HPP 11 | 12 | #include 13 | 14 | #include "xtl/xsequence.hpp" 15 | #include "xtl/xoptional.hpp" 16 | 17 | #include "xframe_utils.hpp" 18 | #include "xcoordinate.hpp" 19 | #include "xdimension.hpp" 20 | 21 | namespace xf 22 | { 23 | namespace mpl = xtl::mpl; 24 | 25 | namespace detail 26 | { 27 | template 28 | struct static_missing_impl; 29 | 30 | template 31 | struct static_missing_impl> 32 | { 33 | using return_type = xtl::xoptional; 34 | static inline return_type get() 35 | { 36 | static T val = T(0); 37 | static B has_val = false; 38 | return return_type(val, has_val); 39 | } 40 | }; 41 | 42 | template 43 | T static_missing() noexcept 44 | { 45 | return static_missing_impl::get(); 46 | } 47 | } 48 | 49 | /************* 50 | * xselector * 51 | *************/ 52 | 53 | template 54 | class xselector 55 | { 56 | public: 57 | 58 | static_assert(is_coordinate::value, "first parameter of xselector must be xcoordinate"); 59 | static_assert(is_dimension::value, "second parameter of xselector must be xdimension"); 60 | 61 | using coordinate_type = C; 62 | using key_type = typename coordinate_type::key_type; 63 | using label_list = typename coordinate_type::label_list; 64 | using mapped_type = mpl::cast_t; 65 | using size_type = typename coordinate_type::index_type; 66 | using index_type = detail::xselector_sequence_t; 67 | using outer_index_type = std::pair; 68 | using dimension_type = D; 69 | using sequence_type = detail::xselector_sequence_t, N>; 70 | 71 | xselector() = default; 72 | xselector(const sequence_type& coord); 73 | xselector(sequence_type&& coord); 74 | 75 | index_type get_index(const coordinate_type& coord, const dimension_type& dim) const; 76 | outer_index_type get_outer_index(const coordinate_type& coord, const dimension_type& dim) const; 77 | 78 | private: 79 | 80 | sequence_type m_coord; 81 | }; 82 | 83 | /************** 84 | * xiselector * 85 | **************/ 86 | 87 | template 88 | class xiselector 89 | { 90 | public: 91 | 92 | static_assert(is_coordinate::value, "first parameter of xiselector must be xcoordinate"); 93 | static_assert(is_dimension::value, "second parameter of xiselector must be xdimension"); 94 | 95 | using coordinate_type = C; 96 | using key_type = typename coordinate_type::key_type; 97 | using size_type = typename coordinate_type::index_type; 98 | using index_type = detail::xselector_sequence_t; 99 | using dimension_type = D; 100 | using sequence_type = detail::xselector_sequence_t, N>; 101 | 102 | xiselector() = default; 103 | xiselector(const sequence_type& coord); 104 | xiselector(sequence_type&& coord); 105 | 106 | index_type get_index(const coordinate_type& coord, const dimension_type& dim) const; 107 | 108 | private: 109 | 110 | sequence_type m_coord; 111 | }; 112 | 113 | /************ 114 | * xlocator * 115 | ************/ 116 | 117 | template 118 | class xlocator 119 | { 120 | public: 121 | 122 | static_assert(is_coordinate::value, "first parameter of xlocator must be xcoordinate"); 123 | static_assert(is_dimension::value, "second parameter of xlocator must be xdimension"); 124 | 125 | using coordinate_type = C; 126 | using key_type = typename coordinate_type::key_type; 127 | using label_list = typename coordinate_type::label_list; 128 | using mapped_type = mpl::cast_t; 129 | using size_type = typename coordinate_type::index_type; 130 | using index_type = detail::xselector_sequence_t; 131 | using dimension_type = D; 132 | using sequence_type = detail::xselector_sequence_t; 133 | 134 | xlocator() = default; 135 | xlocator(const sequence_type& coord); 136 | xlocator(sequence_type&& coord); 137 | 138 | index_type get_index(const coordinate_type& coord, const dimension_type& dim) const; 139 | 140 | private: 141 | 142 | sequence_type m_coord; 143 | }; 144 | 145 | /******************** 146 | * xselector_traits * 147 | ********************/ 148 | 149 | template 150 | struct xselector_traits 151 | { 152 | using coordinate_type = C; 153 | using dimension_type = DM; 154 | 155 | using size_type = typename coordinate_type::index_type; 156 | using index_type = detail::xselector_sequence_t; 157 | using selector_type = xselector; 158 | using selector_sequence_type = typename selector_type::sequence_type; 159 | using iselector_type = xiselector; 160 | using iselector_sequence_type = typename iselector_type::sequence_type; 161 | using locator_type = xlocator; 162 | using locator_sequence_type = typename locator_type::sequence_type; 163 | 164 | static constexpr std::size_t static_dimension = N; 165 | }; 166 | 167 | /**************************** 168 | * xselector implementation * 169 | ****************************/ 170 | 171 | template 172 | inline xselector::xselector(const sequence_type& coord) 173 | : m_coord(coord) 174 | { 175 | } 176 | 177 | template 178 | inline xselector::xselector(sequence_type&& coord) 179 | : m_coord(std::move(coord)) 180 | { 181 | } 182 | 183 | template 184 | inline auto xselector::get_index(const coordinate_type& coord, const dimension_type& dim) const 185 | -> index_type 186 | { 187 | index_type res = xtl::make_sequence(dim.size(), size_type(0)); 188 | for(const auto& c : m_coord) 189 | { 190 | auto iter = dim.find(c.first); 191 | if(iter != dim.end()) 192 | { 193 | res[iter->second] = coord[c.first][c.second]; 194 | } 195 | } 196 | return res; 197 | } 198 | 199 | template 200 | inline auto xselector::get_outer_index(const coordinate_type& coord, const dimension_type& dim) const 201 | -> outer_index_type 202 | { 203 | outer_index_type res(xtl::make_sequence(dim.size(), size_type(0)), true); 204 | for(const auto& c : m_coord) 205 | { 206 | auto iter = dim.find(c.first); 207 | if(iter != dim.end()) 208 | { 209 | const auto& axis = coord[c.first]; 210 | if(axis.contains(c.second)) 211 | { 212 | res.first[iter->second]= axis[c.second]; 213 | } 214 | else 215 | { 216 | res.second = false; 217 | break; 218 | } 219 | } 220 | } 221 | return res; 222 | } 223 | 224 | /***************************** 225 | * xiselector implementation * 226 | *****************************/ 227 | 228 | template 229 | inline xiselector::xiselector(const sequence_type& coord) 230 | : m_coord(coord) 231 | { 232 | } 233 | 234 | template 235 | inline xiselector::xiselector(sequence_type&& coord) 236 | : m_coord(std::move(coord)) 237 | { 238 | } 239 | 240 | template 241 | inline auto xiselector::get_index(const coordinate_type& /*coord*/, const dimension_type& dim) const 242 | -> index_type 243 | { 244 | index_type res = xtl::make_sequence(dim.size(), size_type(0)); 245 | for(const auto& c : m_coord) 246 | { 247 | res[dim[c.first]] = c.second; 248 | } 249 | return res; 250 | } 251 | 252 | /*************************** 253 | * xlocator implementation * 254 | ***************************/ 255 | 256 | template 257 | inline xlocator::xlocator(const sequence_type& coord) 258 | : m_coord(coord) 259 | { 260 | } 261 | 262 | template 263 | inline xlocator::xlocator(sequence_type&& coord) 264 | : m_coord(std::move(coord)) 265 | { 266 | } 267 | 268 | template 269 | inline auto xlocator::get_index(const coordinate_type& coord, const dimension_type& dim) const 270 | -> index_type 271 | { 272 | index_type res = xtl::make_sequence(dim.size(), size_type(0)); 273 | for (std::size_t i = 0; i < m_coord.size(); ++i) 274 | { 275 | res[i] = coord[dim.labels()[i]][m_coord[i]]; 276 | } 277 | return res; 278 | } 279 | 280 | } 281 | 282 | #endif 283 | --------------------------------------------------------------------------------