diff --git a/.appveyor.yml b/.appveyor.yml index 91cebe4..13f51e0 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -3,33 +3,33 @@ build: false os: Visual Studio 2015 platform: - - x64 +- x64 environment: matrix: - - MINICONDA: C:\xtensor-conda + - MINICONDA: C:\xtensor-conda init: - - "ECHO %MINICONDA%" - - C:\"Program Files (x86)"\"Microsoft Visual Studio 14.0"\VC\vcvarsall.bat %PLATFORM% - - ps: if($env:Platform -eq "x64"){Start-FileDownload 'http://repo.continuum.io/miniconda/Miniconda3-latest-Windows-x86_64.exe' C:\Miniconda.exe; echo "Done"} - - ps: if($env:Platform -eq "x86"){Start-FileDownload 'http://repo.continuum.io/miniconda/Miniconda3-latest-Windows-x86.exe' C:\Miniconda.exe; echo "Done"} - - cmd: C:\Miniconda.exe /S /D=C:\xtensor-conda - - "set PATH=%MINICONDA%;%MINICONDA%\\Scripts;%MINICONDA%\\Library\\bin;%PATH%" +- ECHO %MINICONDA% +- C:\"Program Files (x86)"\"Microsoft Visual Studio 14.0"\VC\vcvarsall.bat %PLATFORM% +- ps: if($env:Platform -eq "x64"){Start-FileDownload 'http://repo.continuum.io/miniconda/Miniconda3-latest-Windows-x86_64.exe' C:\Miniconda.exe; echo "Done"} +- ps: if($env:Platform -eq "x86"){Start-FileDownload 'http://repo.continuum.io/miniconda/Miniconda3-latest-Windows-x86.exe' C:\Miniconda.exe; echo "Done"} +- cmd: C:\Miniconda.exe /S /D=C:\xtensor-conda +- set PATH=%MINICONDA%;%MINICONDA%\Scripts;%MINICONDA%\Library\bin;%PATH% install: - - conda config --set always_yes yes --set changeps1 no - - conda update -q conda - - conda info -a - - conda install mamba -c conda-forge - - mamba install cmake pytest numpy pybind11 xtensor==0.24.0 -c conda-forge - - "set PYTHONHOME=%MINICONDA%" - - cmake -G "NMake Makefiles" -D CMAKE_INSTALL_PREFIX=%MINICONDA%\\Library -D BUILD_TESTS=ON -D PYTHON_EXECUTABLE=%MINICONDA%\\python.exe -DDOWNLOAD_GTEST=ON . - - nmake test_xtensor_python - - nmake install - - rmdir /s/q "test/googletest-src" +- conda config --set always_yes yes --set changeps1 no +- conda update -q conda +- conda info -a +- conda install mamba -c conda-forge +- mamba install cmake pytest numpy pybind11 xtensor==0.24.0 -c conda-forge +- set PYTHONHOME=%MINICONDA% +- cmake -G "NMake Makefiles" -D CMAKE_INSTALL_PREFIX=%MINICONDA%\\Library -D BUILD_TESTS=ON -D PYTHON_EXECUTABLE=%MINICONDA%\\python.exe -DDOWNLOAD_GTEST=ON . +- nmake test_xtensor_python +- nmake install +- rmdir /s/q "test/googletest-src" build_script: - - py.test -s - - cd test - - .\test_xtensor_python +- py.test -s +- cd test +- .\test_xtensor_python diff --git a/.azure-pipelines/azure-pipelines-linux-clang.yml b/.azure-pipelines/azure-pipelines-linux-clang.yml index 87d7592..54d3c8c 100644 --- a/.azure-pipelines/azure-pipelines-linux-clang.yml +++ b/.azure-pipelines/azure-pipelines-linux-clang.yml @@ -1,38 +1,38 @@ jobs: - - job: 'Linux_0' - strategy: - matrix: - clang_6: - llvm_version: '6.0' - clang_7: - llvm_version: '7' - clang_8: - llvm_version: '8' - clang_9: - llvm_version: '9' - pool: - vmImage: ubuntu-18.04 - variables: - CC: clang-$(llvm_version) - CXX: clang++-$(llvm_version) - timeoutInMinutes: 360 - steps: +- job: Linux_0 + strategy: + matrix: + clang_6: + llvm_version: '6.0' + clang_7: + llvm_version: '7' + clang_8: + llvm_version: '8' + clang_9: + llvm_version: '9' + pool: + vmImage: ubuntu-18.04 + variables: + CC: clang-$(llvm_version) + CXX: clang++-$(llvm_version) + timeoutInMinutes: 360 + steps: - - script: | - sudo add-apt-repository ppa:ubuntu-toolchain-r/test - if [[ $(llvm_version) == '4.0' || $(llvm_version) == '5.0' ]]; then - sudo apt-get update - sudo apt-get --no-install-suggests --no-install-recommends install gcc-4.9 clang-$(llvm_version) - else - LLVM_VERSION=$(llvm_version) - get -O - http://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add - - sudo add-apt-repository "deb http://apt.llvm.org/xenial/ llvm-toolchain-xenial-$LLVM_VERSION main" - sudo apt-get update - sudo apt-get --no-install-suggests --no-install-recommends install clang-$(llvm_version) - fi - displayName: Install build toolchain + - script: | + sudo add-apt-repository ppa:ubuntu-toolchain-r/test + if [[ $(llvm_version) == '4.0' || $(llvm_version) == '5.0' ]]; then + sudo apt-get update + sudo apt-get --no-install-suggests --no-install-recommends install gcc-4.9 clang-$(llvm_version) + else + LLVM_VERSION=$(llvm_version) + get -O - http://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add - + sudo add-apt-repository "deb http://apt.llvm.org/xenial/ llvm-toolchain-xenial-$LLVM_VERSION main" + sudo apt-get update + sudo apt-get --no-install-suggests --no-install-recommends install clang-$(llvm_version) + fi + displayName: Install build toolchain - - bash: echo "##vso[task.prependpath]$CONDA/bin" - displayName: Add conda to PATH + - bash: echo "##vso[task.prependpath]$CONDA/bin" + displayName: Add conda to PATH - - template: unix-build.yml + - template: unix-build.yml diff --git a/.azure-pipelines/azure-pipelines-linux-gcc.yml b/.azure-pipelines/azure-pipelines-linux-gcc.yml index e0a6aa0..1e16b6a 100644 --- a/.azure-pipelines/azure-pipelines-linux-gcc.yml +++ b/.azure-pipelines/azure-pipelines-linux-gcc.yml @@ -1,33 +1,32 @@ jobs: - - job: 'Linux_1' - strategy: - matrix: - gcc_6: - gcc_version: '6' - gcc_7: - gcc_version: '7' - gcc_8: - gcc_version: '8' - gcc_9: - gcc_version: '9' - pool: - vmImage: ubuntu-18.04 - variables: - CC: gcc-$(gcc_version) - CXX: g++-$(gcc_version) - timeoutInMinutes: 360 - steps: +- job: Linux_1 + strategy: + matrix: + gcc_6: + gcc_version: '6' + gcc_7: + gcc_version: '7' + gcc_8: + gcc_version: '8' + gcc_9: + gcc_version: '9' + pool: + vmImage: ubuntu-18.04 + variables: + CC: gcc-$(gcc_version) + CXX: g++-$(gcc_version) + timeoutInMinutes: 360 + steps: - - script: | - if [[ $(gcc_version) == '4.9' || $(gcc_version) == '6' || $(gcc_version) == '7' || $(gcc_version) == '8' ]]; then - sudo add-apt-repository ppa:ubuntu-toolchain-r/test - sudo apt-get update - sudo apt-get --no-install-suggests --no-install-recommends install g++-$(gcc_version) - fi - displayName: Install build toolchain + - script: | + if [[ $(gcc_version) == '4.9' || $(gcc_version) == '6' || $(gcc_version) == '7' || $(gcc_version) == '8' ]]; then + sudo add-apt-repository ppa:ubuntu-toolchain-r/test + sudo apt-get update + sudo apt-get --no-install-suggests --no-install-recommends install g++-$(gcc_version) + fi + displayName: Install build toolchain - - bash: echo "##vso[task.prependpath]$CONDA/bin" - displayName: Add conda to PATH - - - template: unix-build.yml + - bash: echo "##vso[task.prependpath]$CONDA/bin" + displayName: Add conda to PATH + - template: unix-build.yml diff --git a/.azure-pipelines/azure-pipelines-osx.yml b/.azure-pipelines/azure-pipelines-osx.yml index beeafce..9da09c8 100644 --- a/.azure-pipelines/azure-pipelines-osx.yml +++ b/.azure-pipelines/azure-pipelines-osx.yml @@ -1,28 +1,28 @@ jobs: - - job: 'OSX' - strategy: - matrix: - macOS_10_15: - image_name: 'macOS-10.15' - macOS_11: - image_name: 'macOS-11' - pool: - vmImage: $(image_name) - variables: - CC: clang - CXX: clang++ - timeoutInMinutes: 360 - steps: - - script: | - echo "Removing homebrew for Azure to avoid conflicts with conda" - curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/uninstall > ~/uninstall_homebrew - chmod +x ~/uninstall_homebrew - ~/uninstall_homebrew -f -q - displayName: Remove homebrew +- job: OSX + strategy: + matrix: + macOS_10_15: + image_name: macOS-10.15 + macOS_11: + image_name: macOS-11 + pool: + vmImage: $(image_name) + variables: + CC: clang + CXX: clang++ + timeoutInMinutes: 360 + steps: + - script: | + echo "Removing homebrew for Azure to avoid conflicts with conda" + curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/uninstall > ~/uninstall_homebrew + chmod +x ~/uninstall_homebrew + ~/uninstall_homebrew -f -q + displayName: Remove homebrew - - bash: | - echo "##vso[task.prependpath]$CONDA/bin" - sudo chown -R $USER $CONDA - displayName: Add conda to PATH + - bash: | + echo "##vso[task.prependpath]$CONDA/bin" + sudo chown -R $USER $CONDA + displayName: Add conda to PATH - - template: unix-build.yml + - template: unix-build.yml diff --git a/.azure-pipelines/unix-build.yml b/.azure-pipelines/unix-build.yml index 97cb405..e5b9b4f 100644 --- a/.azure-pipelines/unix-build.yml +++ b/.azure-pipelines/unix-build.yml @@ -1,68 +1,68 @@ steps: - - script: | - conda config --set always_yes yes --set changeps1 no - conda update -q conda - conda env create --file environment-dev.yml - source activate xtensor-python - displayName: Install dependencies +- script: | + conda config --set always_yes yes --set changeps1 no + conda update -q conda + conda env create --file environment-dev.yml + source activate xtensor-python + displayName: Install dependencies - - script: | - source activate xtensor-python - mkdir build - cd build - cmake -DCMAKE_INSTALL_PREFIX=$CONDA_PREFIX -DPYTHON_EXECUTABLE=`which python` -DDOWNLOAD_GTEST=ON $(Build.SourcesDirectory) - make install - displayName: Configure xtensor-python - workingDirectory: $(Build.BinariesDirectory) +- script: | + source activate xtensor-python + mkdir build + cd build + cmake -DCMAKE_INSTALL_PREFIX=$CONDA_PREFIX -DPYTHON_EXECUTABLE=`which python` -DDOWNLOAD_GTEST=ON $(Build.SourcesDirectory) + make install + displayName: Configure xtensor-python + workingDirectory: $(Build.BinariesDirectory) - - script: | - source activate xtensor-python - make -j2 test_xtensor_python - displayName: Build xtensor-python - workingDirectory: $(Build.BinariesDirectory)/build +- script: | + source activate xtensor-python + make -j2 test_xtensor_python + displayName: Build xtensor-python + workingDirectory: $(Build.BinariesDirectory)/build - - script: | - source activate xtensor-python - cd test - ./test_xtensor_python - displayName: Test xtensor-python (C++) - workingDirectory: $(Build.BinariesDirectory)/build/test +- script: | + source activate xtensor-python + cd test + ./test_xtensor_python + displayName: Test xtensor-python (C++) + workingDirectory: $(Build.BinariesDirectory)/build/test - - script: | - source activate xtensor-python - py.test -s - displayName: Test xtensor-python (Python) - workingDirectory: $(Build.SourcesDirectory) +- script: | + source activate xtensor-python + py.test -s + displayName: Test xtensor-python (Python) + workingDirectory: $(Build.SourcesDirectory) - - script: | - source activate xtensor-python - cmake -Bbuild -DPython_EXECUTABLE=`which python` - cd build - cmake --build . - cp ../example.py . - python example.py - cd .. - displayName: Example - readme 1 - workingDirectory: $(Build.SourcesDirectory)/docs/source/examples/readme_example_1 +- script: | + source activate xtensor-python + cmake -Bbuild -DPython_EXECUTABLE=`which python` + cd build + cmake --build . + cp ../example.py . + python example.py + cd .. + displayName: Example - readme 1 + workingDirectory: $(Build.SourcesDirectory)/docs/source/examples/readme_example_1 - - script: | - source activate xtensor-python - cmake -Bbuild -DPython_EXECUTABLE=`which python` - cd build - cmake --build . - cp ../example.py . - python example.py - cd .. - displayName: Example - Copy 'cast' - workingDirectory: $(Build.SourcesDirectory)/docs/source/examples/copy_cast +- script: | + source activate xtensor-python + cmake -Bbuild -DPython_EXECUTABLE=`which python` + cd build + cmake --build . + cp ../example.py . + python example.py + cd .. + displayName: Example - Copy 'cast' + workingDirectory: $(Build.SourcesDirectory)/docs/source/examples/copy_cast - - script: | - source activate xtensor-python - cmake -Bbuild -DPython_EXECUTABLE=`which python` - cd build - cmake --build . - cp ../example.py . - python example.py - cd .. - displayName: Example - SFINAE - workingDirectory: $(Build.SourcesDirectory)/docs/source/examples/sfinae +- script: | + source activate xtensor-python + cmake -Bbuild -DPython_EXECUTABLE=`which python` + cd build + cmake --build . + cp ../example.py . + python example.py + cd .. + displayName: Example - SFINAE + workingDirectory: $(Build.SourcesDirectory)/docs/source/examples/sfinae diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..d092c07 --- /dev/null +++ b/.clang-format @@ -0,0 +1,90 @@ +BasedOnStyle: Mozilla + +AccessModifierOffset: '-4' +AlignAfterOpenBracket: BlockIndent +AlignEscapedNewlines: Left +AllowAllArgumentsOnNextLine: false +AllowAllParametersOfDeclarationOnNextLine: false +AllowShortBlocksOnASingleLine: false +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: false +AllowShortIfStatementsOnASingleLine: false +# Forbid one line lambdas because clang-format makes a weird split when +# single instructions lambdas are too long. +AllowShortLambdasOnASingleLine: Empty +AllowShortLoopsOnASingleLine: false +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakAfterReturnType: None +AlwaysBreakTemplateDeclarations: Yes +BinPackArguments: false +BinPackParameters: false +BreakBeforeBinaryOperators: NonAssignment +BreakBeforeBraces: Allman +BreakBeforeTernaryOperators: true +BreakConstructorInitializers: BeforeComma +BreakInheritanceList: AfterComma +BreakStringLiterals: false +ColumnLimit: '110' +ConstructorInitializerIndentWidth: '4' +ContinuationIndentWidth: '4' +Cpp11BracedListStyle: true +DerivePointerAlignment: false +DisableFormat: false +EmptyLineAfterAccessModifier: Always +EmptyLineBeforeAccessModifier: Always +ExperimentalAutoDetectBinPacking: true +IncludeBlocks: Regroup +IncludeCategories: +- Regex: <[^.]+> + Priority: 1 +- Regex: + Priority: 3 +- Regex: <.+> + Priority: 2 +- Regex: '"xtensor/.+"' + Priority: 4 +- Regex: '".+"' + Priority: 5 +IndentCaseLabels: true +IndentWidth: '4' +IndentWrappedFunctionNames: false +InsertBraces: true +InsertTrailingCommas: Wrapped +KeepEmptyLinesAtTheStartOfBlocks: false +LambdaBodyIndentation: Signature +Language: Cpp +MaxEmptyLinesToKeep: '2' +NamespaceIndentation: All +ObjCBlockIndentWidth: '4' +ObjCSpaceAfterProperty: false +ObjCSpaceBeforeProtocolList: false +PackConstructorInitializers: Never +PenaltyBreakAssignment: 100000 +PenaltyBreakBeforeFirstCallParameter: 0 +PenaltyBreakComment: 10 +PenaltyBreakOpenParenthesis: 0 +PenaltyBreakTemplateDeclaration: 0 +PenaltyExcessCharacter: 10 +PenaltyIndentedWhitespace: 0 +PenaltyReturnTypeOnItsOwnLine: 10 +PointerAlignment: Left +QualifierAlignment: Custom # Experimental +QualifierOrder: [inline, static, constexpr, const, volatile, type] +ReflowComments: true +SeparateDefinitionBlocks: Always +SortIncludes: CaseInsensitive +SortUsingDeclarations: true +SpaceAfterCStyleCast: true +SpaceAfterTemplateKeyword: true +SpaceBeforeAssignmentOperators: true +SpaceBeforeParens: ControlStatements +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: '2' +SpacesInAngles: false +SpacesInCStyleCastParentheses: false +SpacesInContainerLiterals: false +SpacesInParentheses: false +SpacesInSquareBrackets: false +Standard: c++14 +TabWidth: '4' +UseTab: Never diff --git a/.github/workflows/static-analysis.yml b/.github/workflows/static-analysis.yml new file mode 100644 index 0000000..5441a33 --- /dev/null +++ b/.github/workflows/static-analysis.yml @@ -0,0 +1,14 @@ +name: Static Analysis + +on: + push: + branches: [master] + pull_request: + branches: [master] + +jobs: + pre-commit: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: pre-commit/action@v3.0.0 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..a0e9260 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,47 @@ +repos: +- repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.4.0 + hooks: + - id: check-added-large-files + - id: check-case-conflict + - id: end-of-file-fixer + - id: trailing-whitespace + - id: mixed-line-ending + args: [--fix=lf] + exclude: \.bat$ + - id: check-json + - id: pretty-format-json + args: [--autofix, --top-keys=version] + - id: check-yaml + types: [file] + files: \.(yaml|yml|clang-format) + - id: detect-private-key + - id: check-merge-conflict +- repo: https://github.com/Lucas-C/pre-commit-hooks + rev: v1.4.2 + hooks: + - id: forbid-tabs + - id: remove-tabs + args: [--whitespaces-count, '4'] +- repo: https://github.com/macisamuele/language-formatters-pre-commit-hooks + rev: v2.7.0 + hooks: + - id: pretty-format-yaml + args: [--autofix, --indent, '2'] + types: [file] + files: \.(yaml|yml|clang-format) +- repo: https://github.com/tdegeus/cpp_comment_format + rev: v0.2.0 + hooks: + - id: cpp_comment_format +- repo: https://github.com/tdegeus/conda_envfile + rev: v0.4.2 + hooks: + - id: conda_envfile_parse + files: environment.yaml +# Externally provided executables (so we can use them with editors as well). +- repo: https://github.com/pre-commit/mirrors-clang-format + rev: v15.0.7 + hooks: + - id: clang-format + files: .*\.[hc]pp$ diff --git a/CMakeLists.txt b/CMakeLists.txt index e1bd077..1b51174 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -25,7 +25,7 @@ foreach(ver ${xtensor_python_version_defines}) set(XTENSOR_PYTHON_VERSION_${CMAKE_MATCH_1} "${CMAKE_MATCH_2}" CACHE INTERNAL "") endif() endforeach() -set(${PROJECT_NAME}_VERSION +set(${PROJECT_NAME}_VERSION ${XTENSOR_PYTHON_VERSION_MAJOR}.${XTENSOR_PYTHON_VERSION_MINOR}.${XTENSOR_PYTHON_VERSION_PATCH}) message(STATUS "xtensor-python v${${PROJECT_NAME}_VERSION}") @@ -45,7 +45,7 @@ else() find_package(xtensor ${xtensor_REQUIRED_VERSION} REQUIRED) message(STATUS "Found xtensor: ${xtensor_INCLUDE_DIRS}/xtensor") endif() - + # Currently no required version for pybind11 if(TARGET pybind11 OR TARGET pybind11::headers) # pybind11 has a variable that indicates its version already, so use that @@ -136,4 +136,3 @@ install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake install(EXPORT ${PROJECT_NAME}-targets FILE ${PROJECT_NAME}Targets.cmake DESTINATION ${XTENSOR_PYTHON_CMAKECONFIG_INSTALL_DIR}) - diff --git a/azure-pipelines.yml b/azure-pipelines.yml index e930dbe..a7dcef7 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -1,8 +1,7 @@ trigger: - - master +- master jobs: - - template: ./.azure-pipelines/azure-pipelines-linux-clang.yml - - template: ./.azure-pipelines/azure-pipelines-linux-gcc.yml - - template: ./.azure-pipelines/azure-pipelines-osx.yml - +- template: ./.azure-pipelines/azure-pipelines-linux-clang.yml +- template: ./.azure-pipelines/azure-pipelines-linux-gcc.yml +- template: ./.azure-pipelines/azure-pipelines-osx.yml diff --git a/benchmark/CMakeLists.txt b/benchmark/CMakeLists.txt index 28589df..99253ff 100644 --- a/benchmark/CMakeLists.txt +++ b/benchmark/CMakeLists.txt @@ -95,4 +95,3 @@ add_custom_target(xbenchmark COMMAND "${PYTHON_EXECUTABLE}" "benchmark_pyvectorize.py" COMMAND "${PYTHON_EXECUTABLE}" "benchmark_pybind_vectorize.py" DEPENDS ${XTENSOR_PYTHON_BENCHMARK_TARGET}) - diff --git a/benchmark/main.cpp b/benchmark/main.cpp index d1d787e..92f188f 100644 --- a/benchmark/main.cpp +++ b/benchmark/main.cpp @@ -1,9 +1,11 @@ -#include "pybind11/pybind11.h" #include "pybind11/numpy.h" +#include "pybind11/pybind11.h" + #define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION -#include "numpy/arrayobject.h" -#include "xtensor/xtensor.hpp" #include "xtensor/xarray.hpp" +#include "xtensor/xtensor.hpp" + +#include "numpy/arrayobject.h" #include "xtensor-python/pyarray.hpp" #include "xtensor-python/pytensor.hpp" #include "xtensor-python/pyvectorize.hpp" @@ -14,44 +16,84 @@ namespace py = pybind11; PYBIND11_MODULE(benchmark_xtensor_python, m) { - if(_import_array() < 0) + if (_import_array() < 0) { PyErr_SetString(PyExc_ImportError, "numpy.core.multiarray failed to import"); } m.doc() = "Benchmark module for xtensor python bindings"; - m.def("sum_array", [](xt::pyarray const& x) { - double sum = 0; - for(auto e : x) - sum += e; - return sum; - }); - - m.def("sum_tensor", [](xt::pytensor const& x) { - double sum = 0; - for(auto e : x) - sum += e; - return sum; - }); - - m.def("pybind_sum_array", [](py::array_t const& x) { - double sum = 0; - size_t size = x.size(); - const double* data = x.data(0); - for(size_t i = 0; i < size; ++i) - sum += data[i]; - return sum; - }); - - m.def("rect_to_polar", [](xt::pyarray const& a) { - return py::vectorize([](complex_t x) { return std::abs(x); })(a); - }); - - m.def("pybind_rect_to_polar", [](py::array a) { - if (py::isinstance>(a)) - return py::vectorize([](complex_t x) { return std::abs(x); })(a); - else - throw py::type_error("rect_to_polar unhandled type"); - }); + m.def( + "sum_array", + [](const xt::pyarray& x) + { + double sum = 0; + for (auto e : x) + { + sum += e; + } + return sum; + } + ); + + m.def( + "sum_tensor", + [](const xt::pytensor& x) + { + double sum = 0; + for (auto e : x) + { + sum += e; + } + return sum; + } + ); + + m.def( + "pybind_sum_array", + [](const py::array_t& x) + { + double sum = 0; + size_t size = x.size(); + const double* data = x.data(0); + for (size_t i = 0; i < size; ++i) + { + sum += data[i]; + } + return sum; + } + ); + + m.def( + "rect_to_polar", + [](const xt::pyarray& a) + { + return py::vectorize( + [](complex_t x) + { + return std::abs(x); + } + )(a); + } + ); + + m.def( + "pybind_rect_to_polar", + [](py::array a) + { + if (py::isinstance>(a)) + { + return py::vectorize( + [](complex_t x) + { + return std::abs(x); + } + )(a); + } + else + { + throw py::type_error("rect_to_polar unhandled type"); + } + } + ); } diff --git a/cmake/FindNumPy.cmake b/cmake/FindNumPy.cmake index f043566..48a1046 100644 --- a/cmake/FindNumPy.cmake +++ b/cmake/FindNumPy.cmake @@ -24,10 +24,10 @@ # distribute, sublicense, and/or sell copies of the Software, and to permit # persons to whom the Software is furnished to do so, subject to # the following conditions: -# +# # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. -# +# # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL @@ -35,7 +35,7 @@ # OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, # ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR # OTHER DEALINGS IN THE SOFTWARE. -# +# #============================================================================ # Finding NumPy involves calling the Python interpreter diff --git a/docs/environment.yml b/docs/environment.yml index 47e93f7..65d263f 100644 --- a/docs/environment.yml +++ b/docs/environment.yml @@ -1,7 +1,7 @@ name: xtensor-python-docs channels: - - conda-forge +- conda-forge dependencies: - - breathe +- breathe diff --git a/docs/make.bat b/docs/make.bat index 0df92b4..07de332 100644 --- a/docs/make.bat +++ b/docs/make.bat @@ -3,48 +3,48 @@ REM Command file for Sphinx documentation if "%SPHINXBUILD%" == "" ( - set SPHINXBUILD=sphinx-build + set SPHINXBUILD=sphinx-build ) set BUILDDIR=build set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% source set I18NSPHINXOPTS=%SPHINXOPTS% source if NOT "%PAPER%" == "" ( - set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% - set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS% + set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% + set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS% ) if "%1" == "" goto help if "%1" == "help" ( - :help - echo.Please use `make ^` where ^ is one of - echo. html to make standalone HTML files - echo. dirhtml to make HTML files named index.html in directories - echo. singlehtml to make a single large HTML file - echo. pickle to make pickle files - echo. json to make JSON files - echo. htmlhelp to make HTML files and a HTML help project - echo. qthelp to make HTML files and a qthelp project - echo. devhelp to make HTML files and a Devhelp project - echo. epub to make an epub - echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter - echo. text to make text files - echo. man to make manual pages - echo. texinfo to make Texinfo files - echo. gettext to make PO message catalogs - echo. changes to make an overview over all changed/added/deprecated items - echo. xml to make Docutils-native XML files - echo. pseudoxml to make pseudoxml-XML files for display purposes - echo. linkcheck to check all external links for integrity - echo. doctest to run all doctests embedded in the documentation if enabled - echo. coverage to run coverage check of the documentation if enabled - goto end + :help + echo.Please use `make ^` where ^ is one of + echo. html to make standalone HTML files + echo. dirhtml to make HTML files named index.html in directories + echo. singlehtml to make a single large HTML file + echo. pickle to make pickle files + echo. json to make JSON files + echo. htmlhelp to make HTML files and a HTML help project + echo. qthelp to make HTML files and a qthelp project + echo. devhelp to make HTML files and a Devhelp project + echo. epub to make an epub + echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter + echo. text to make text files + echo. man to make manual pages + echo. texinfo to make Texinfo files + echo. gettext to make PO message catalogs + echo. changes to make an overview over all changed/added/deprecated items + echo. xml to make Docutils-native XML files + echo. pseudoxml to make pseudoxml-XML files for display purposes + echo. linkcheck to check all external links for integrity + echo. doctest to run all doctests embedded in the documentation if enabled + echo. coverage to run coverage check of the documentation if enabled + goto end ) if "%1" == "clean" ( - for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i - del /q /s %BUILDDIR%\* - goto end + for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i + del /q /s %BUILDDIR%\* + goto end ) @@ -58,15 +58,15 @@ goto sphinx_ok set SPHINXBUILD=python -m sphinx.__init__ %SPHINXBUILD% 2> nul if errorlevel 9009 ( - echo. - echo.The 'sphinx-build' command was not found. Make sure you have Sphinx - echo.installed, then set the SPHINXBUILD environment variable to point - echo.to the full path of the 'sphinx-build' executable. Alternatively you - echo.may add the Sphinx directory to PATH. - echo. - echo.If you don't have Sphinx installed, grab it from - echo.http://sphinx-doc.org/ - exit /b 1 + echo. + echo.The 'sphinx-build' command was not found. Make sure you have Sphinx + echo.installed, then set the SPHINXBUILD environment variable to point + echo.to the full path of the 'sphinx-build' executable. Alternatively you + echo.may add the Sphinx directory to PATH. + echo. + echo.If you don't have Sphinx installed, grab it from + echo.http://sphinx-doc.org/ + exit /b 1 ) :sphinx_ok @@ -74,191 +74,191 @@ if errorlevel 9009 ( if "%1" == "html" ( doxygen - %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The HTML pages are in %BUILDDIR%/html. - goto end + %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The HTML pages are in %BUILDDIR%/html. + goto end ) if "%1" == "dirhtml" ( - %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml. - goto end + %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml. + goto end ) if "%1" == "singlehtml" ( - %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml. - goto end + %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml. + goto end ) if "%1" == "pickle" ( - %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle - if errorlevel 1 exit /b 1 - echo. - echo.Build finished; now you can process the pickle files. - goto end + %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can process the pickle files. + goto end ) if "%1" == "json" ( - %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json - if errorlevel 1 exit /b 1 - echo. - echo.Build finished; now you can process the JSON files. - goto end + %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can process the JSON files. + goto end ) if "%1" == "htmlhelp" ( - %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp - if errorlevel 1 exit /b 1 - echo. - echo.Build finished; now you can run HTML Help Workshop with the ^ + %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can run HTML Help Workshop with the ^ .hhp project file in %BUILDDIR%/htmlhelp. - goto end + goto end ) if "%1" == "qthelp" ( - %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp - if errorlevel 1 exit /b 1 - echo. - echo.Build finished; now you can run "qcollectiongenerator" with the ^ + %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can run "qcollectiongenerator" with the ^ .qhcp project file in %BUILDDIR%/qthelp, like this: - echo.^> qcollectiongenerator %BUILDDIR%\qthelp\packagename.qhcp - echo.To view the help file: - echo.^> assistant -collectionFile %BUILDDIR%\qthelp\packagename.ghc - goto end + echo.^> qcollectiongenerator %BUILDDIR%\qthelp\packagename.qhcp + echo.To view the help file: + echo.^> assistant -collectionFile %BUILDDIR%\qthelp\packagename.ghc + goto end ) if "%1" == "devhelp" ( - %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. - goto end + %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. + goto end ) if "%1" == "epub" ( - %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The epub file is in %BUILDDIR%/epub. - goto end + %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The epub file is in %BUILDDIR%/epub. + goto end ) if "%1" == "latex" ( - %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex - if errorlevel 1 exit /b 1 - echo. - echo.Build finished; the LaTeX files are in %BUILDDIR%/latex. - goto end + %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; the LaTeX files are in %BUILDDIR%/latex. + goto end ) if "%1" == "latexpdf" ( - %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex - cd %BUILDDIR%/latex - make all-pdf - cd %~dp0 - echo. - echo.Build finished; the PDF files are in %BUILDDIR%/latex. - goto end + %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex + cd %BUILDDIR%/latex + make all-pdf + cd %~dp0 + echo. + echo.Build finished; the PDF files are in %BUILDDIR%/latex. + goto end ) if "%1" == "latexpdfja" ( - %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex - cd %BUILDDIR%/latex - make all-pdf-ja - cd %~dp0 - echo. - echo.Build finished; the PDF files are in %BUILDDIR%/latex. - goto end + %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex + cd %BUILDDIR%/latex + make all-pdf-ja + cd %~dp0 + echo. + echo.Build finished; the PDF files are in %BUILDDIR%/latex. + goto end ) if "%1" == "text" ( - %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The text files are in %BUILDDIR%/text. - goto end + %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The text files are in %BUILDDIR%/text. + goto end ) if "%1" == "man" ( - %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The manual pages are in %BUILDDIR%/man. - goto end + %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The manual pages are in %BUILDDIR%/man. + goto end ) if "%1" == "texinfo" ( - %SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo. - goto end + %SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo. + goto end ) if "%1" == "gettext" ( - %SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The message catalogs are in %BUILDDIR%/locale. - goto end + %SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The message catalogs are in %BUILDDIR%/locale. + goto end ) if "%1" == "changes" ( - %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes - if errorlevel 1 exit /b 1 - echo. - echo.The overview file is in %BUILDDIR%/changes. - goto end + %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes + if errorlevel 1 exit /b 1 + echo. + echo.The overview file is in %BUILDDIR%/changes. + goto end ) if "%1" == "linkcheck" ( - %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck - if errorlevel 1 exit /b 1 - echo. - echo.Link check complete; look for any errors in the above output ^ + %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck + if errorlevel 1 exit /b 1 + echo. + echo.Link check complete; look for any errors in the above output ^ or in %BUILDDIR%/linkcheck/output.txt. - goto end + goto end ) if "%1" == "doctest" ( - %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest - if errorlevel 1 exit /b 1 - echo. - echo.Testing of doctests in the sources finished, look at the ^ + %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest + if errorlevel 1 exit /b 1 + echo. + echo.Testing of doctests in the sources finished, look at the ^ results in %BUILDDIR%/doctest/output.txt. - goto end + goto end ) if "%1" == "coverage" ( - %SPHINXBUILD% -b coverage %ALLSPHINXOPTS% %BUILDDIR%/coverage - if errorlevel 1 exit /b 1 - echo. - echo.Testing of coverage in the sources finished, look at the ^ + %SPHINXBUILD% -b coverage %ALLSPHINXOPTS% %BUILDDIR%/coverage + if errorlevel 1 exit /b 1 + echo. + echo.Testing of coverage in the sources finished, look at the ^ results in %BUILDDIR%/coverage/python.txt. - goto end + goto end ) if "%1" == "xml" ( - %SPHINXBUILD% -b xml %ALLSPHINXOPTS% %BUILDDIR%/xml - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The XML files are in %BUILDDIR%/xml. - goto end + %SPHINXBUILD% -b xml %ALLSPHINXOPTS% %BUILDDIR%/xml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The XML files are in %BUILDDIR%/xml. + goto end ) if "%1" == "pseudoxml" ( - %SPHINXBUILD% -b pseudoxml %ALLSPHINXOPTS% %BUILDDIR%/pseudoxml - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The pseudo-XML files are in %BUILDDIR%/pseudoxml. - goto end + %SPHINXBUILD% -b pseudoxml %ALLSPHINXOPTS% %BUILDDIR%/pseudoxml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The pseudo-XML files are in %BUILDDIR%/pseudoxml. + goto end ) :end diff --git a/docs/source/array_tensor.rst b/docs/source/array_tensor.rst index e00889f..be45b40 100644 --- a/docs/source/array_tensor.rst +++ b/docs/source/array_tensor.rst @@ -24,4 +24,3 @@ pytensor Like ``xtensor``, ``pytensor`` has a static stack-allocated shape. This means that the shape of the numpy array is copied into the shape of the ``pytensor`` upon creation. As a consequence, reshapes are not reflected across languages. However, this drawback is offset by a more effective computation of shape and broadcast. - diff --git a/docs/source/basic_usage.rst b/docs/source/basic_usage.rst index c97c9ac..fd32012 100644 --- a/docs/source/basic_usage.rst +++ b/docs/source/basic_usage.rst @@ -99,4 +99,3 @@ Example 2: Create a numpy-style universal function from a C++ scalar function [[-0.540302, 1.257618, 1.89929 , 0.794764, -1.040465], [-1.499227, 0.136731, 1.646979, 1.643002, 0.128456], [-1.084323, -0.583843, 0.45342 , 1.073811, 0.706945]] - diff --git a/docs/source/conda.svg b/docs/source/conda.svg index 0755b2f..643a653 100644 --- a/docs/source/conda.svg +++ b/docs/source/conda.svg @@ -1 +1 @@ - \ No newline at end of file + diff --git a/docs/source/conf.py b/docs/source/conf.py index 3b428b8..08c3872 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -35,4 +35,3 @@ def setup(app): pygments_style = 'sphinx' todo_include_todos = False htmlhelp_basename = 'xtensorpythondoc' - diff --git a/docs/source/cookiecutter.rst b/docs/source/cookiecutter.rst index e725106..221f3bd 100644 --- a/docs/source/cookiecutter.rst +++ b/docs/source/cookiecutter.rst @@ -45,7 +45,7 @@ information: - ``python_package_name``: name of the Python package created by your extension, - ``cpp_namespace``: name for the cpp namespace holding the implementation of your extension, - ``project_short_description``: a short description for your project. - + This will produce a directory containing all the required content for a minimal extension project making use of xtensor with all the required boilerplate for package management, together with a few basic examples. diff --git a/docs/source/debian.svg b/docs/source/debian.svg index 50dcb70..9232651 100644 --- a/docs/source/debian.svg +++ b/docs/source/debian.svg @@ -1,86 +1,86 @@ - - - - - - - - - - - - - -]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + +]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/source/examples/copy_cast/main.cpp b/docs/source/examples/copy_cast/main.cpp index 2e12609..f1c9f1f 100644 --- a/docs/source/examples/copy_cast/main.cpp +++ b/docs/source/examples/copy_cast/main.cpp @@ -1,6 +1,7 @@ #include -#include + #include +#include #define FORCE_IMPORT_ARRAY #include diff --git a/docs/source/examples/readme_example_1/example.py b/docs/source/examples/readme_example_1/example.py index 1ae033d..b71f825 100644 --- a/docs/source/examples/readme_example_1/example.py +++ b/docs/source/examples/readme_example_1/example.py @@ -3,4 +3,3 @@ a = np.array([1, 2, 3]) assert np.isclose(np.sum(np.sin(a)), mymodule.sum_of_sines(a)) - diff --git a/docs/source/examples/readme_example_1/main.cpp b/docs/source/examples/readme_example_1/main.cpp index 6175ed8..d1af2ee 100644 --- a/docs/source/examples/readme_example_1/main.cpp +++ b/docs/source/examples/readme_example_1/main.cpp @@ -1,6 +1,7 @@ #include -#include + #include +#include #define FORCE_IMPORT_ARRAY #include diff --git a/docs/source/examples/sfinae/example.py b/docs/source/examples/sfinae/example.py index 1929f0b..348fc93 100644 --- a/docs/source/examples/sfinae/example.py +++ b/docs/source/examples/sfinae/example.py @@ -5,4 +5,3 @@ b = np.array(a, copy=True) mymodule.times_dimension(b) # changing in-place! assert np.allclose(2 * a, b) - diff --git a/docs/source/examples/sfinae/main.cpp b/docs/source/examples/sfinae/main.cpp index a146cdd..2278f00 100644 --- a/docs/source/examples/sfinae/main.cpp +++ b/docs/source/examples/sfinae/main.cpp @@ -1,6 +1,7 @@ -#include "mymodule.hpp" #include +#include "mymodule.hpp" + int main() { xt::xtensor a = xt::arange(2 * 3).reshape({2, 3}); diff --git a/docs/source/examples/sfinae/mymodule.hpp b/docs/source/examples/sfinae/mymodule.hpp index 5127eff..ad3d004 100644 --- a/docs/source/examples/sfinae/mymodule.hpp +++ b/docs/source/examples/sfinae/mymodule.hpp @@ -1,32 +1,33 @@ #include -namespace mymodule { - -template -struct is_std_vector +namespace mymodule { - static const bool value = false; -}; -template -struct is_std_vector > -{ - static const bool value = true; -}; + template + struct is_std_vector + { + static const bool value = false; + }; -// any xtensor object -template ::value, bool> = true> -void times_dimension(T& t) -{ - using value_type = typename T::value_type; - t *= (value_type)(t.dimension()); -} + template + struct is_std_vector> + { + static const bool value = true; + }; -// an std::vector -template ::value, bool> = true> -void times_dimension(T& t) -{ - // do nothing -} + // any xtensor object + template ::value, bool> = true> + void times_dimension(T& t) + { + using value_type = typename T::value_type; + t *= (value_type) (t.dimension()); + } + + // an std::vector + template ::value, bool> = true> + void times_dimension(T& t) + { + // do nothing + } } diff --git a/docs/source/examples/sfinae/python.cpp b/docs/source/examples/sfinae/python.cpp index 081f625..f719248 100644 --- a/docs/source/examples/sfinae/python.cpp +++ b/docs/source/examples/sfinae/python.cpp @@ -1,5 +1,6 @@ -#include "mymodule.hpp" #include + +#include "mymodule.hpp" #define FORCE_IMPORT_ARRAY #include diff --git a/docs/source/numpy_capi.rst b/docs/source/numpy_capi.rst index d489be2..a84364d 100644 --- a/docs/source/numpy_capi.rst +++ b/docs/source/numpy_capi.rst @@ -90,6 +90,3 @@ you can override the behavior of ``xtensor-python`` by explicitly defining ``PY_ // in every source file #define PY_ARRAY_UNIQUE_SYMBOL my_uniqe_array_api #include "xtensor-python/pyarray.hpp" - - - diff --git a/docs/source/quantstack-white.svg b/docs/source/quantstack-white.svg index d527db1..1f03ebb 100644 --- a/docs/source/quantstack-white.svg +++ b/docs/source/quantstack-white.svg @@ -49,4 +49,4 @@ d="m 85.3,16 c 1.2,0.6 2.4,1.3 3.4,2.2 l 0,22.2 c 0,9.2 -1.8,19.7 -14.2,19.7 l -1.9,0 C 60.1,60.1 58.4,49.6 58.4,40.4 l 0,-22.2 c 1,-0.9 2.2,-1.6 3.4,-2.2 l 0,23.4 c 0,10.4 1.5,17.7 11.4,17.7 l 0.9,0 c 9.8,0 11.4,-7.3 11.4,-17.7 L 85.5,16 Z M 133,38.1 c 0,15 -5.1,22.1 -18.1,22.1 -0.1,0 -0.6,0 -0.7,0 -11,0 -14.2,-5.1 -14.2,-12.4 0,-10.2 9.7,-12.6 29.5,-13.4 -0.6,-9.3 -3.7,-15.2 -14.6,-15.2 -3,0 -5.8,0.5 -8.6,1.8 l -1.5,-2.9 c 3.3,-1.7 6.7,-2.1 10.1,-2.1 13,0 18.1,7 18.1,22.1 z m -3.4,-0.7 c -16.6,0.8 -26.1,2.2 -26.1,10.5 0,2.8 0.5,4.9 1.9,6.4 0.4,0.5 1,0.9 1.7,1.2 2.6,1.1 5.2,1.5 7.9,1.5 12.2,0 14.7,-7.4 14.7,-18.9 -0.1,-0.3 -0.1,-0.5 -0.1,-0.7 z m 201.7,0.7 c 0,15 -5.1,22.1 -18.1,22.1 -0.1,0 -0.6,0 -0.7,0 -11,0 -14.2,-5.1 -14.2,-12.4 0,-10.2 9.7,-12.6 29.5,-13.4 -0.6,-9.3 -3.7,-15.2 -14.6,-15.2 -3,0 -5.8,0.5 -8.6,1.8 l -1.5,-2.9 c 3.3,-1.7 6.7,-2.1 10.1,-2.1 13,0 18.1,7 18.1,22.1 z m -3.4,-0.7 c -16.6,0.8 -26.1,2.2 -26.1,10.5 0,2.8 0.5,4.9 1.9,6.4 0.4,0.5 1,0.9 1.7,1.2 2.6,1.1 5.2,1.5 7.9,1.5 12.2,0 14.7,-7.4 14.7,-18.9 -0.1,-0.3 -0.1,-0.5 -0.1,-0.7 z M 57.2,82.2 c -0.9,0.9 -1.8,1.7 -2.9,2.3 C 45,79.7 38.3,71.4 34.9,60.6 31.7,62.2 27.8,63 23.1,63 6.5,63 0,53.3 0,32.3 0,11.4 6.5,1.6 23.1,1.6 c 16.6,0 23.1,9.7 23.1,30.7 0,13 -2.5,21.6 -8.4,26.4 3.2,10.9 10,19 19.4,23.5 z M 42.7,32.3 C 42.7,15.9 39.4,4.8 23,4.8 6.6,4.8 3.3,15.8 3.3,32.3 c 0,16.4 3.3,27.5 19.7,27.5 16.4,0 19.7,-11 19.7,-27.5 z m 366,-10.4 C 408,21 407.2,20.2 406.3,19.5 l -18.3,18.2 0,-22 -0.4,0 c -1.1,0.2 -2,0.5 -3,0.8 l 0,42.6 c 1.1,0.4 2.2,0.6 3.4,0.9 l 0,-21.3 17.8,17.8 c 0.9,-0.7 1.7,-1.4 2.5,-2.3 l -16,-16 16.4,-16.3 z M 360.6,57 c -12.2,0 -14.7,-7.4 -14.7,-18.9 0,-11.5 2.5,-18.9 14.7,-18.9 3.1,0 6,0.5 8.8,1.9 l 1.5,-2.9 c -3.4,-1.7 -6.9,-2.1 -10.2,-2.1 -13,0 -18.1,7 -18.1,22.1 0,15 5.1,22.1 18.1,22.1 3.4,0 6.9,-0.4 10.3,-2.1 l -1.5,-2.9 c -3,1.2 -5.9,1.7 -8.9,1.7 z m -198,-41.1 -1.9,0 c -12.5,0 -14.2,10.5 -14.2,19.7 l 0,22.2 c 1,0.9 2.2,1.6 3.4,2.2 l 0,-23.3 c 0,-10.4 1.5,-17.7 11.4,-17.7 l 0.9,0 c 9.8,0 11.4,7.3 11.4,17.7 l 0,23.4 c 1.2,-0.6 2.4,-1.3 3.4,-2.2 l 0,-22.2 c -0.2,-9.3 -2,-19.8 -14.4,-19.8 z m 127.7,4.3 -1.6,-3.1 -10.4,0 0,-10.9 -3.3,0 0,10.8 -10.5,0 -1.6,3.1 12.1,0 c 0,0 0,22.4 0,23.7 l 0,0 c -0.1,2.6 0.3,5.1 1.2,7.3 0,0.1 1,2.2 2.6,4.1 0.8,0.9 2.4,2.3 4.6,3.8 l 1.5,-3.1 c -1.7,-1.2 -2.9,-2.2 -3.5,-2.9 -1.3,-1.5 -2,-3.2 -2,-3.2 -0.7,-1.6 -1,-3.3 -1,-5 0,-1.2 0,-24.7 0,-24.7 l 11.9,0 z M 197.8,6 l -3.3,0 0,10.8 -12,0 1.6,3.1 10.4,0 c 0,0 0,12.2 0,13.5 l 0,0 c -0.1,2.6 0.3,5.1 1.2,7.3 0,0.1 1,2.2 2.6,4.1 0.8,0.9 2.3,2.2 4.4,3.7 l 1.6,-3.1 c -1.7,-1.2 -2.9,-2.2 -3.4,-2.9 -1.3,-1.5 -2,-3.2 -2,-3.2 -0.7,-1.6 -1,-3.3 -1,-5 0,-1.2 0,-14.5 0,-14.5 l 10.4,0 1.6,-3.1 -12.1,0 0,-10.7 z m 40.3,22.2 c -1.9,-0.7 -3.6,-1.3 -5.3,-2.1 l 0,0 c -5.1,-2.1 -8.7,-4.8 -8.7,-10.8 0,-9.2 6.4,-12.1 14.5,-12.1 3.8,0 7.5,0.4 11.2,1.7 L 251.3,2 c -4,-1.5 -8.3,-2 -12.8,-2 -9.4,0 -17.7,4.1 -17.7,15.4 0,6.7 3.4,10.4 8.6,12.9 l 0,0 c 0.8,0.3 1.4,0.6 2.1,0.9 0,0 0,0 0,0 l 0,0 c 1.9,0.8 3.3,1.4 5.1,2 8.4,3 12.3,3.5 15.1,6.6 0.2,0.2 4.1,4.8 3.1,10.4 -0.5,2.9 -2.2,5.5 -4.9,7.8 -6.2,5.1 -15.9,4 -25.2,0.9 l -1.6,3.1 c 5.1,1.8 10.4,3 15.4,3 5.1,0 9.7,-1.2 13.5,-4.3 4.2,-3.5 5.7,-7.2 6.1,-9.8 1.3,-7.1 -3.3,-12.6 -3.8,-13.2 -2.7,-2.9 -7.6,-4.4 -16.2,-7.5 z" id="path3" inkscape:connector-curvature="0" - style="fill:#ffffff" /> \ No newline at end of file + style="fill:#ffffff" /> diff --git a/docs/source/xtensor-python.svg b/docs/source/xtensor-python.svg index 181465f..7a29ffd 100644 --- a/docs/source/xtensor-python.svg +++ b/docs/source/xtensor-python.svg @@ -1,60 +1,60 @@ - - - - - - - - - - - - + + + + + + + + + + + + diff --git a/environment-dev.yml b/environment-dev.yml index 6dff19f..7b55617 100644 --- a/environment-dev.yml +++ b/environment-dev.yml @@ -1,13 +1,12 @@ name: xtensor-python channels: - - conda-forge +- conda-forge dependencies: # Build dependencies - - cmake +- cmake # Host dependencies - - xtensor=0.24.0 - - numpy - - pybind11=2.4.3 +- xtensor=0.24.0 +- numpy +- pybind11=2.4.3 # Test dependencies - - pytest - +- pytest diff --git a/include/xtensor-python/pyarray.hpp b/include/xtensor-python/pyarray.hpp index 6df73cf..569da90 100644 --- a/include/xtensor-python/pyarray.hpp +++ b/include/xtensor-python/pyarray.hpp @@ -1,11 +1,11 @@ /*************************************************************************** -* Copyright (c) Wolf Vollprecht, Johan Mabille and Sylvain Corlay * -* Copyright (c) QuantStack * -* * -* Distributed under the terms of the BSD 3-Clause License. * -* * -* The full license is in the file LICENSE, distributed with this software. * -****************************************************************************/ + * Copyright (c) Wolf Vollprecht, Johan Mabille and Sylvain Corlay * + * Copyright (c) QuantStack * + * * + * Distributed under the terms of the BSD 3-Clause License. * + * * + * The full license is in the file LICENSE, distributed with this software. * + ****************************************************************************/ #ifndef PY_ARRAY_HPP #define PY_ARRAY_HPP @@ -20,10 +20,10 @@ #include "pyarray_backstrides.hpp" #include "pycontainer.hpp" -#include "pystrides_adaptor.hpp" #include "pynative_casters.hpp" -#include "xtensor_type_caster_base.hpp" +#include "pystrides_adaptor.hpp" #include "xtensor_python_config.hpp" +#include "xtensor_type_caster_base.hpp" namespace xt { @@ -35,7 +35,7 @@ namespace pybind11 { namespace detail { -#ifdef PYBIND11_DESCR // The macro is removed from pybind11 since 2.3 +#ifdef PYBIND11_DESCR // The macro is removed from pybind11 since 2.3 template struct handle_type_name> { @@ -69,7 +69,7 @@ namespace pybind11 return src.inc_ref(); } -#ifdef PYBIND11_DESCR // The macro is removed from pybind11 since 2.3 +#ifdef PYBIND11_DESCR // The macro is removed from pybind11 since 2.3 PYBIND11_TYPE_CASTER(type, handle_type_name::name()); #else PYBIND11_TYPE_CASTER(type, _("numpy.ndarray[") + npy_format_descriptor::name + _("]")); @@ -99,8 +99,7 @@ namespace pybind11 namespace xt { template - struct xiterable_inner_types> - : xcontainer_iterable_types> + struct xiterable_inner_types> : xcontainer_iterable_types> { }; @@ -155,7 +154,7 @@ namespace xt using inner_shape_type = typename base_type::inner_shape_type; using inner_strides_type = typename base_type::inner_strides_type; using inner_backstrides_type = typename base_type::inner_backstrides_type; - constexpr static std::size_t rank = SIZE_MAX; + static constexpr std::size_t rank = SIZE_MAX; pyarray(); pyarray(const value_type& t); @@ -267,7 +266,8 @@ namespace xt : base_type() { base_type::resize(xt::shape(t), default_dynamic_layout()); - L == layout_type::row_major ? nested_copy(m_storage.begin(), t) : nested_copy(this->template begin(), t); + L == layout_type::row_major ? nested_copy(m_storage.begin(), t) + : nested_copy(this->template begin(), t); } template @@ -275,7 +275,8 @@ namespace xt : base_type() { base_type::resize(xt::shape(t), default_dynamic_layout()); - L == layout_type::row_major ? nested_copy(m_storage.begin(), t) : nested_copy(this->template begin(), t); + L == layout_type::row_major ? nested_copy(m_storage.begin(), t) + : nested_copy(this->template begin(), t); } template @@ -283,7 +284,8 @@ namespace xt : base_type() { base_type::resize(xt::shape(t), default_dynamic_layout()); - L == layout_type::row_major ? nested_copy(m_storage.begin(), t) : nested_copy(this->template begin(), t); + L == layout_type::row_major ? nested_copy(m_storage.begin(), t) + : nested_copy(this->template begin(), t); } template @@ -291,7 +293,8 @@ namespace xt : base_type() { base_type::resize(xt::shape(t), default_dynamic_layout()); - L == layout_type::row_major ? nested_copy(m_storage.begin(), t) : nested_copy(this->template begin(), t); + L == layout_type::row_major ? nested_copy(m_storage.begin(), t) + : nested_copy(this->template begin(), t); } template @@ -299,7 +302,8 @@ namespace xt : base_type() { base_type::resize(xt::shape(t), default_dynamic_layout()); - L == layout_type::row_major ? nested_copy(m_storage.begin(), t) : nested_copy(this->template begin(), t); + L == layout_type::row_major ? nested_copy(m_storage.begin(), t) + : nested_copy(this->template begin(), t); } template @@ -393,6 +397,7 @@ namespace xt auto shp = xtl::forward_sequence(shape); return self_type(shp); } + //@} /** @@ -404,10 +409,12 @@ namespace xt */ template inline pyarray::pyarray(const self_type& rhs) - : base_type(), semantic_base(rhs) + : base_type() + , semantic_base(rhs) { auto tmp = pybind11::reinterpret_steal( - PyArray_NewLikeArray(rhs.python_array(), NPY_KEEPORDER, nullptr, 1)); + PyArray_NewLikeArray(rhs.python_array(), NPY_KEEPORDER, nullptr, 1) + ); if (!tmp) { @@ -445,7 +452,9 @@ namespace xt : base_type() { // TODO: prevent intermediary shape allocation - shape_type shape = xtl::forward_sequence(e.derived_cast().shape()); + shape_type shape = xtl::forward_sequence( + e.derived_cast().shape() + ); strides_type strides = xtl::make_sequence(shape.size(), size_type(0)); layout_type layout = default_dynamic_layout(); @@ -463,6 +472,7 @@ namespace xt { return semantic_base::operator=(e); } + //@} template @@ -482,8 +492,15 @@ namespace xt { strides_type adapted_strides(strides); - std::transform(strides.begin(), strides.end(), adapted_strides.begin(), - [](auto v) { return sizeof(T) * v; }); + std::transform( + strides.begin(), + strides.end(), + adapted_strides.begin(), + [](auto v) + { + return sizeof(T) * v; + } + ); int flags = NPY_ARRAY_ALIGNED; if (!std::is_const::value) @@ -496,9 +513,16 @@ namespace xt npy_intp* shape_data = reinterpret_cast(const_cast(shape.data())); npy_intp* strides_data = reinterpret_cast(adapted_strides.data()); - auto tmp = pybind11::reinterpret_steal( - PyArray_NewFromDescr(&PyArray_Type, (PyArray_Descr*) dtype.release().ptr(), static_cast(shape.size()), shape_data, strides_data, - nullptr, flags, nullptr)); + auto tmp = pybind11::reinterpret_steal(PyArray_NewFromDescr( + &PyArray_Type, + (PyArray_Descr*) dtype.release().ptr(), + static_cast(shape.size()), + shape_data, + strides_data, + nullptr, + flags, + nullptr + )); if (!tmp) { @@ -517,11 +541,15 @@ namespace xt return; } - m_shape = inner_shape_type(reinterpret_cast(PyArray_SHAPE(this->python_array())), - static_cast(PyArray_NDIM(this->python_array()))); - m_strides = inner_strides_type(reinterpret_cast(PyArray_STRIDES(this->python_array())), - static_cast(PyArray_NDIM(this->python_array())), - reinterpret_cast(PyArray_SHAPE(this->python_array()))); + m_shape = inner_shape_type( + reinterpret_cast(PyArray_SHAPE(this->python_array())), + static_cast(PyArray_NDIM(this->python_array())) + ); + m_strides = inner_strides_type( + reinterpret_cast(PyArray_STRIDES(this->python_array())), + static_cast(PyArray_NDIM(this->python_array())), + reinterpret_cast(PyArray_SHAPE(this->python_array())) + ); if (L != layout_type::dynamic && !do_strides_match(m_shape, m_strides, L, 1)) { @@ -529,8 +557,10 @@ namespace xt } m_backstrides = backstrides_type(*this); - m_storage = storage_type(reinterpret_cast(PyArray_DATA(this->python_array())), - this->get_buffer_size()); + m_storage = storage_type( + reinterpret_cast(PyArray_DATA(this->python_array())), + this->get_buffer_size() + ); } template @@ -549,8 +579,9 @@ namespace xt inline auto pyarray::backstrides_impl() const noexcept -> const inner_backstrides_type& { // m_backstrides wraps the numpy array backstrides, which is a raw pointer. - // The address of the raw pointer stored in the wrapper would be invalidated when the pyarray is copied. - // Hence, we build a new backstrides object (cheap wrapper around the underlying pointer) upon access. + // The address of the raw pointer stored in the wrapper would be invalidated when the pyarray is + // copied. Hence, we build a new backstrides object (cheap wrapper around the underlying pointer) upon + // access. m_backstrides = backstrides_type(*this); return m_backstrides; } diff --git a/include/xtensor-python/pyarray_backstrides.hpp b/include/xtensor-python/pyarray_backstrides.hpp index 4dfdab9..c672619 100644 --- a/include/xtensor-python/pyarray_backstrides.hpp +++ b/include/xtensor-python/pyarray_backstrides.hpp @@ -1,11 +1,11 @@ /*************************************************************************** -* Copyright (c) Wolf Vollprecht, Johan Mabille and Sylvain Corlay * -* Copyright (c) QuantStack * -* * -* Distributed under the terms of the BSD 3-Clause License. * -* * -* The full license is in the file LICENSE, distributed with this software. * -****************************************************************************/ + * Copyright (c) Wolf Vollprecht, Johan Mabille and Sylvain Corlay * + * Copyright (c) QuantStack * + * * + * Distributed under the terms of the BSD 3-Clause License. * + * * + * The full license is in the file LICENSE, distributed with this software. * + ****************************************************************************/ #ifndef PY_ARRAY_BACKSTRIDES_HPP #define PY_ARRAY_BACKSTRIDES_HPP @@ -62,28 +62,22 @@ namespace xt }; template - inline bool operator==(const pybackstrides_iterator& lhs, - const pybackstrides_iterator& rhs); + inline bool operator==(const pybackstrides_iterator& lhs, const pybackstrides_iterator& rhs); template - inline bool operator!=(const pybackstrides_iterator& lhs, - const pybackstrides_iterator& rhs); + inline bool operator!=(const pybackstrides_iterator& lhs, const pybackstrides_iterator& rhs); template - inline bool operator<(const pybackstrides_iterator& lhs, - const pybackstrides_iterator& rhs); + inline bool operator<(const pybackstrides_iterator& lhs, const pybackstrides_iterator& rhs); template - inline bool operator<=(const pybackstrides_iterator& lhs, - const pybackstrides_iterator& rhs); + inline bool operator<=(const pybackstrides_iterator& lhs, const pybackstrides_iterator& rhs); template - inline bool operator>(const pybackstrides_iterator& lhs, - const pybackstrides_iterator& rhs); + inline bool operator>(const pybackstrides_iterator& lhs, const pybackstrides_iterator& rhs); template - inline bool operator>=(const pybackstrides_iterator& lhs, - const pybackstrides_iterator& rhs); + inline bool operator>=(const pybackstrides_iterator& lhs, const pybackstrides_iterator& rhs); /*********************** * pyarray_backstrides * @@ -138,10 +132,11 @@ namespace xt /***************************************** * pybackstrides_iterator implementation * *****************************************/ - + template inline pybackstrides_iterator::pybackstrides_iterator(const B* b, std::size_t offset) - : p_b(b), m_offset(offset) + : p_b(b) + , m_offset(offset) { } @@ -176,11 +171,11 @@ namespace xt inline auto pybackstrides_iterator::operator--() -> self_type& { --m_offset; - return *this; + return *this; } template - inline auto pybackstrides_iterator::operator++(int )-> self_type + inline auto pybackstrides_iterator::operator++(int) -> self_type { self_type tmp(*this); ++m_offset; @@ -236,43 +231,37 @@ namespace xt } template - inline bool operator==(const pybackstrides_iterator& lhs, - const pybackstrides_iterator& rhs) + inline bool operator==(const pybackstrides_iterator& lhs, const pybackstrides_iterator& rhs) { return lhs.offset() == rhs.offset(); } template - inline bool operator!=(const pybackstrides_iterator& lhs, - const pybackstrides_iterator& rhs) + inline bool operator!=(const pybackstrides_iterator& lhs, const pybackstrides_iterator& rhs) { return !(lhs == rhs); } template - inline bool operator<(const pybackstrides_iterator& lhs, - const pybackstrides_iterator& rhs) + inline bool operator<(const pybackstrides_iterator& lhs, const pybackstrides_iterator& rhs) { return lhs.offset() < rhs.offset(); } template - inline bool operator<=(const pybackstrides_iterator& lhs, - const pybackstrides_iterator& rhs) + inline bool operator<=(const pybackstrides_iterator& lhs, const pybackstrides_iterator& rhs) { return (lhs < rhs) || (lhs == rhs); } template - inline bool operator>(const pybackstrides_iterator& lhs, - const pybackstrides_iterator& rhs) + inline bool operator>(const pybackstrides_iterator& lhs, const pybackstrides_iterator& rhs) { return !(lhs <= rhs); } template - inline bool operator>=(const pybackstrides_iterator& lhs, - const pybackstrides_iterator& rhs) + inline bool operator>=(const pybackstrides_iterator& lhs, const pybackstrides_iterator& rhs) { return !(lhs < rhs); } diff --git a/include/xtensor-python/pycontainer.hpp b/include/xtensor-python/pycontainer.hpp index 1617d03..13574bb 100644 --- a/include/xtensor-python/pycontainer.hpp +++ b/include/xtensor-python/pycontainer.hpp @@ -1,11 +1,11 @@ /*************************************************************************** -* Copyright (c) Wolf Vollprecht, Johan Mabille and Sylvain Corlay * -* Copyright (c) QuantStack * -* * -* Distributed under the terms of the BSD 3-Clause License. * -* * -* The full license is in the file LICENSE, distributed with this software. * -****************************************************************************/ + * Copyright (c) Wolf Vollprecht, Johan Mabille and Sylvain Corlay * + * Copyright (c) QuantStack * + * * + * Distributed under the terms of the BSD 3-Clause License. * + * * + * The full license is in the file LICENSE, distributed with this software. * + ****************************************************************************/ #ifndef PY_CONTAINER_HPP #define PY_CONTAINER_HPP @@ -16,8 +16,8 @@ #include #include "pybind11/complex.h" -#include "pybind11/pybind11.h" #include "pybind11/numpy.h" +#include "pybind11/pybind11.h" #ifndef FORCE_IMPORT_ARRAY #define NO_IMPORT_ARRAY @@ -32,6 +32,7 @@ #undef copysign #include + #include "xtensor/xcontainer.hpp" #include "xtl/xsequence.hpp" @@ -151,7 +152,9 @@ namespace xt struct numpy_traits; template - struct numpy_traits::value>> + struct numpy_traits< + T, + std::enable_if_t::value>> { private: @@ -161,12 +164,22 @@ namespace xt // On Linux x64, NPY_INT64 != NPY_LONGLONG and NPY_UINT64 != NPY_ULONGLONG, // we use the values of NPY_INT64 and NPY_UINT64 which are consistent with the // values of NPY_LONG and NPY_ULONG. - constexpr static const int value_list[15] = { + static constexpr const int value_list[15] = { NPY_BOOL, - NPY_BYTE, NPY_UBYTE, NPY_SHORT, NPY_USHORT, - NPY_INT32, NPY_UINT32, NPY_INT64, NPY_UINT64, - NPY_FLOAT, NPY_DOUBLE, NPY_LONGDOUBLE, - NPY_CFLOAT, NPY_CDOUBLE, NPY_CLONGDOUBLE}; + NPY_BYTE, + NPY_UBYTE, + NPY_SHORT, + NPY_USHORT, + NPY_INT32, + NPY_UINT32, + NPY_INT64, + NPY_UINT64, + NPY_FLOAT, + NPY_DOUBLE, + NPY_LONGDOUBLE, + NPY_CFLOAT, + NPY_CDOUBLE, + NPY_CLONGDOUBLE}; public: @@ -181,7 +194,7 @@ namespace xt template struct numpy_enum_adjuster { - static inline int pyarray_type(PyArrayObject* obj) + inline static int pyarray_type(PyArrayObject* obj) { return PyArray_TYPE(obj); } @@ -190,10 +203,10 @@ namespace xt template <> struct numpy_enum_adjuster { - static inline int pyarray_type(PyArrayObject* obj) + inline static int pyarray_type(PyArrayObject* obj) { int res = PyArray_TYPE(obj); - if(res == NPY_LONGLONG || res == NPY_ULONGLONG) + if (res == NPY_LONGLONG || res == NPY_ULONGLONG) { res -= 2; } @@ -235,14 +248,18 @@ namespace xt template bool check_array_type(const pybind11::handle& src, std::false_type) { - return PyArray_EquivTypes((PyArray_Descr*) pybind11::detail::array_proxy(src.ptr())->descr, - (PyArray_Descr*) pybind11::dtype::of().ptr()); + return PyArray_EquivTypes( + (PyArray_Descr*) pybind11::detail::array_proxy(src.ptr())->descr, + (PyArray_Descr*) pybind11::dtype::of().ptr() + ); } template bool check_array(const pybind11::handle& src) { - using is_arithmetic_type = std::integral_constant::value)>; + using is_arithmetic_type = std::integral_constant< + bool, + bool(pybind11::detail::satisfies_any_of::value)>; return PyArray_Check(src.ptr()) && check_array_type(src, is_arithmetic_type{}); } } @@ -305,8 +322,14 @@ namespace xt } auto dtype = pybind11::detail::npy_format_descriptor::dtype(); - auto res = PyArray_FromAny(ptr, (PyArray_Descr *) dtype.release().ptr(), 0, 0, - NPY_ARRAY_ENSUREARRAY | NPY_ARRAY_FORCECAST, nullptr); + auto res = PyArray_FromAny( + ptr, + (PyArray_Descr*) dtype.release().ptr(), + 0, + 0, + NPY_ARRAY_ENSUREARRAY | NPY_ARRAY_FORCECAST, + nullptr + ); return res; } @@ -320,11 +343,16 @@ namespace xt inline auto pycontainer::get_buffer_size() const -> size_type { const size_type& (*min)(const size_type&, const size_type&) = std::min; - size_type min_stride = this->strides().empty() ? size_type(1) : - std::max(size_type(1), std::accumulate(this->strides().cbegin(), - this->strides().cend(), - std::numeric_limits::max(), - min)); + size_type min_stride = this->strides().empty() ? size_type(1) + : std::max( + size_type(1), + std::accumulate( + this->strides().cbegin(), + this->strides().cend(), + std::numeric_limits::max(), + min + ) + ); return min_stride * static_cast(PyArray_SIZE(this->python_array())); } @@ -356,11 +384,11 @@ namespace xt { static bool run(std::size_t new_dim) { - if(new_dim != N) + if (new_dim != N) { std::ostringstream err_msg; - err_msg << "Invalid conversion to pycontainer, expecting a container of dimension " - << N << ", got a container of dimension " << new_dim << "."; + err_msg << "Invalid conversion to pycontainer, expecting a container of dimension " << N + << ", got a container of dimension " << new_dim << "."; throw std::runtime_error(err_msg.str()); } return new_dim == N; @@ -376,7 +404,8 @@ namespace xt template inline void pycontainer::resize(const S& shape) { - if (shape.size() != this->dimension() || !std::equal(std::begin(shape), std::end(shape), std::begin(this->shape()))) + if (shape.size() != this->dimension() + || !std::equal(std::begin(shape), std::end(shape), std::begin(this->shape()))) { resize(shape, layout_type::row_major); } @@ -416,7 +445,10 @@ namespace xt { if (compute_size(shape) != this->size()) { - throw std::runtime_error("Cannot reshape with incorrect number of elements (" + std::to_string(this->size()) + " vs " + std::to_string(compute_size(shape)) + ")"); + throw std::runtime_error( + "Cannot reshape with incorrect number of elements (" + std::to_string(this->size()) + " vs " + + std::to_string(compute_size(shape)) + ")" + ); } detail::check_dims::run(shape.size()); layout = default_assignable_layout(layout); @@ -436,7 +468,9 @@ namespace xt } using shape_ptr = typename std::decay_t::pointer; - PyArray_Dims dims = {reinterpret_cast(const_cast(shape.data())), static_cast(shape.size())}; + PyArray_Dims dims = { + reinterpret_cast(const_cast(shape.data())), + static_cast(shape.size())}; auto new_ptr = PyArray_Newshape((PyArrayObject*) this->ptr(), &dims, npy_layout); auto old_ptr = this->ptr(); this->ptr() = new_ptr; diff --git a/include/xtensor-python/pynative_casters.hpp b/include/xtensor-python/pynative_casters.hpp index aa19604..89cebea 100644 --- a/include/xtensor-python/pynative_casters.hpp +++ b/include/xtensor-python/pynative_casters.hpp @@ -1,11 +1,11 @@ /*************************************************************************** -* Copyright (c) Wolf Vollprecht, Johan Mabille and Sylvain Corlay * -* Copyright (c) QuantStack * -* * -* Distributed under the terms of the BSD 3-Clause License. * -* * -* The full license is in the file LICENSE, distributed with this software. * -****************************************************************************/ + * Copyright (c) Wolf Vollprecht, Johan Mabille and Sylvain Corlay * + * Copyright (c) QuantStack * + * * + * Distributed under the terms of the BSD 3-Clause License. * + * * + * The full license is in the file LICENSE, distributed with this software. * + ****************************************************************************/ #ifndef PYNATIVE_CASTERS_HPP #define PYNATIVE_CASTERS_HPP @@ -30,25 +30,29 @@ namespace pybind11 // Type caster for casting xt::xtensor_fixed to ndarray template - struct type_caster> : xtensor_type_caster_base> + struct type_caster> + : xtensor_type_caster_base> { }; // Type caster for casting xt::xstrided_view to ndarray template - struct type_caster> : xtensor_type_caster_base> + struct type_caster> + : xtensor_type_caster_base> { }; // Type caster for casting xt::xarray_adaptor to ndarray template - struct type_caster> : xtensor_type_caster_base> + struct type_caster> + : xtensor_type_caster_base> { }; // Type caster for casting xt::xtensor_adaptor to ndarray template - struct type_caster> : xtensor_type_caster_base> + struct type_caster> + : xtensor_type_caster_base> { }; } diff --git a/include/xtensor-python/pystrides_adaptor.hpp b/include/xtensor-python/pystrides_adaptor.hpp index fde929a..5031e0e 100644 --- a/include/xtensor-python/pystrides_adaptor.hpp +++ b/include/xtensor-python/pystrides_adaptor.hpp @@ -1,11 +1,11 @@ /*************************************************************************** -* Copyright (c) Wolf Vollprecht, Johan Mabille and Sylvain Corlay * -* Copyright (c) QuantStack * -* * -* Distributed under the terms of the BSD 3-Clause License. * -* * -* The full license is in the file LICENSE, distributed with this software. * -****************************************************************************/ + * Copyright (c) Wolf Vollprecht, Johan Mabille and Sylvain Corlay * + * Copyright (c) QuantStack * + * * + * Distributed under the terms of the BSD 3-Clause License. * + * * + * The full license is in the file LICENSE, distributed with this software. * + ****************************************************************************/ #ifndef PYSTRIDES_ADAPTOR_HPP #define PYSTRIDES_ADAPTOR_HPP @@ -172,7 +172,10 @@ namespace xt return p_current - rhs.p_current; } - pointer get_pointer() const { return p_current; } + pointer get_pointer() const + { + return p_current; + } private: @@ -181,43 +184,37 @@ namespace xt }; template - inline bool operator==(const pystrides_iterator& lhs, - const pystrides_iterator& rhs) + inline bool operator==(const pystrides_iterator& lhs, const pystrides_iterator& rhs) { return lhs.get_pointer() == rhs.get_pointer(); } template - inline bool operator!=(const pystrides_iterator& lhs, - const pystrides_iterator& rhs) + inline bool operator!=(const pystrides_iterator& lhs, const pystrides_iterator& rhs) { return !(lhs == rhs); } template - inline bool operator<(const pystrides_iterator& lhs, - const pystrides_iterator& rhs) + inline bool operator<(const pystrides_iterator& lhs, const pystrides_iterator& rhs) { return lhs.get_pointer() < rhs.get_pointer(); } template - inline bool operator<=(const pystrides_iterator& lhs, - const pystrides_iterator& rhs) + inline bool operator<=(const pystrides_iterator& lhs, const pystrides_iterator& rhs) { return (lhs < rhs) || (lhs == rhs); } template - inline bool operator>(const pystrides_iterator& lhs, - const pystrides_iterator& rhs) + inline bool operator>(const pystrides_iterator& lhs, const pystrides_iterator& rhs) { return !(lhs <= rhs); } template - inline bool operator>=(const pystrides_iterator& lhs, - const pystrides_iterator& rhs) + inline bool operator>=(const pystrides_iterator& lhs, const pystrides_iterator& rhs) { return !(lhs < rhs); } @@ -228,7 +225,9 @@ namespace xt template inline pystrides_adaptor::pystrides_adaptor(const_pointer data, size_type size, shape_type shape) - : p_data(data), m_size(size), p_shape(shape) + : p_data(data) + , m_size(size) + , p_shape(shape) { } diff --git a/include/xtensor-python/pytensor.hpp b/include/xtensor-python/pytensor.hpp index acf05b8..e047e81 100644 --- a/include/xtensor-python/pytensor.hpp +++ b/include/xtensor-python/pytensor.hpp @@ -1,11 +1,11 @@ /*************************************************************************** -* Copyright (c) Wolf Vollprecht, Johan Mabille and Sylvain Corlay * -* Copyright (c) QuantStack * -* * -* Distributed under the terms of the BSD 3-Clause License. * -* * -* The full license is in the file LICENSE, distributed with this software. * -****************************************************************************/ + * Copyright (c) Wolf Vollprecht, Johan Mabille and Sylvain Corlay * + * Copyright (c) QuantStack * + * * + * Distributed under the terms of the BSD 3-Clause License. * + * * + * The full license is in the file LICENSE, distributed with this software. * + ****************************************************************************/ #ifndef PY_TENSOR_HPP #define PY_TENSOR_HPP @@ -20,10 +20,10 @@ #include "xtensor/xutils.hpp" #include "pycontainer.hpp" -#include "pystrides_adaptor.hpp" #include "pynative_casters.hpp" -#include "xtensor_type_caster_base.hpp" +#include "pystrides_adaptor.hpp" #include "xtensor_python_config.hpp" +#include "xtensor_type_caster_base.hpp" namespace xt { @@ -35,7 +35,7 @@ namespace pybind11 { namespace detail { -#ifdef PYBIND11_DESCR // The macro is removed from pybind11 since 2.3 +#ifdef PYBIND11_DESCR // The macro is removed from pybind11 since 2.3 template struct handle_type_name> { @@ -77,7 +77,7 @@ namespace pybind11 return src.inc_ref(); } -#ifdef PYBIND11_DESCR // The macro is removed from pybind11 since 2.3 +#ifdef PYBIND11_DESCR // The macro is removed from pybind11 since 2.3 PYBIND11_TYPE_CASTER(type, handle_type_name::name()); #else PYBIND11_TYPE_CASTER(type, _("numpy.ndarray[") + npy_format_descriptor::name + _("]")); @@ -101,12 +101,13 @@ namespace pybind11 } }; - } // namespace detail + } // namespace detail } namespace xt { - namespace detail { + namespace detail + { template struct numpy_strides @@ -120,11 +121,10 @@ namespace xt npy_intp* value = nullptr; }; - } // namespace detail + } // namespace detail template - struct xiterable_inner_types> - : xcontainer_iterable_types> + struct xiterable_inner_types> : xcontainer_iterable_types> { }; @@ -180,7 +180,7 @@ namespace xt using inner_shape_type = typename base_type::inner_shape_type; using inner_strides_type = typename base_type::inner_strides_type; using inner_backstrides_type = typename base_type::inner_backstrides_type; - constexpr static std::size_t rank = N; + static constexpr std::size_t rank = N; pytensor(); pytensor(nested_initializer_list_t t); @@ -326,9 +326,7 @@ namespace xt * @param l the layout_type of the pytensor */ template - inline pytensor::pytensor(const shape_type& shape, - const_reference value, - layout_type l) + inline pytensor::pytensor(const shape_type& shape, const_reference value, layout_type l) { compute_strides(shape, l, m_strides); init_tensor(shape, m_strides); @@ -343,9 +341,7 @@ namespace xt * @param value the value of the elements */ template - inline pytensor::pytensor(const shape_type& shape, - const strides_type& strides, - const_reference value) + inline pytensor::pytensor(const shape_type& shape, const strides_type& strides, const_reference value) { init_tensor(shape, strides); std::fill(m_storage.begin(), m_storage.end(), value); @@ -357,8 +353,7 @@ namespace xt * @param strides the strides of the pytensor */ template - inline pytensor::pytensor(const shape_type& shape, - const strides_type& strides) + inline pytensor::pytensor(const shape_type& shape, const strides_type& strides) { init_tensor(shape, strides); } @@ -375,6 +370,7 @@ namespace xt auto shp = xtl::forward_sequence(shape); return self_type(shp); } + //@} /** @@ -386,7 +382,8 @@ namespace xt */ template inline pytensor::pytensor(const self_type& rhs) - : base_type(), semantic_base(rhs) + : base_type() + , semantic_base(rhs) { init_tensor(rhs.shape(), rhs.strides()); std::copy(rhs.storage().cbegin(), rhs.storage().cend(), this->storage().begin()); @@ -402,6 +399,7 @@ namespace xt *this = std::move(tmp); return *this; } + //@} /** @@ -416,7 +414,9 @@ namespace xt inline pytensor::pytensor(const xexpression& e) : base_type() { - shape_type shape = xtl::forward_sequence(e.derived_cast().shape()); + shape_type shape = xtl::forward_sequence( + e.derived_cast().shape() + ); strides_type strides = xtl::make_sequence(N, size_type(0)); compute_strides(shape, layout_type::row_major, strides); init_tensor(shape, strides); @@ -432,6 +432,7 @@ namespace xt { return semantic_base::operator=(e); } + //@} template @@ -450,8 +451,15 @@ namespace xt inline void pytensor::init_tensor(const shape_type& shape, const strides_type& strides) { detail::numpy_strides python_strides; - std::transform(strides.begin(), strides.end(), python_strides.value, - [](auto v) { return sizeof(T) * v; }); + std::transform( + strides.begin(), + strides.end(), + python_strides.value, + [](auto v) + { + return sizeof(T) * v; + } + ); int flags = NPY_ARRAY_ALIGNED; if (!std::is_const::value) { @@ -459,10 +467,16 @@ namespace xt } auto dtype = pybind11::detail::npy_format_descriptor::dtype(); - auto tmp = pybind11::reinterpret_steal( - PyArray_NewFromDescr(&PyArray_Type, (PyArray_Descr*) dtype.release().ptr(), static_cast(shape.size()), - const_cast(shape.data()), python_strides.value, - nullptr, flags, nullptr)); + auto tmp = pybind11::reinterpret_steal(PyArray_NewFromDescr( + &PyArray_Type, + (PyArray_Descr*) dtype.release().ptr(), + static_cast(shape.size()), + const_cast(shape.data()), + python_strides.value, + nullptr, + flags, + nullptr + )); if (!tmp) { @@ -473,8 +487,10 @@ namespace xt m_shape = shape; m_strides = strides; adapt_strides(m_shape, m_strides, m_backstrides); - m_storage = storage_type(reinterpret_cast(PyArray_DATA(this->python_array())), - static_cast(PyArray_SIZE(this->python_array()))); + m_storage = storage_type( + reinterpret_cast(PyArray_DATA(this->python_array())), + static_cast(PyArray_SIZE(this->python_array())) + ); } template @@ -491,8 +507,15 @@ namespace xt } std::copy(PyArray_DIMS(this->python_array()), PyArray_DIMS(this->python_array()) + N, m_shape.begin()); - std::transform(PyArray_STRIDES(this->python_array()), PyArray_STRIDES(this->python_array()) + N, m_strides.begin(), - [](auto v) { return v / sizeof(T); }); + std::transform( + PyArray_STRIDES(this->python_array()), + PyArray_STRIDES(this->python_array()) + N, + m_strides.begin(), + [](auto v) + { + return v / sizeof(T); + } + ); adapt_strides(m_shape, m_strides, m_backstrides); if (L != layout_type::dynamic && !do_strides_match(m_shape, m_strides, L, 1)) @@ -500,8 +523,10 @@ namespace xt throw std::runtime_error("NumPy: passing container with bad strides for layout (is it a view?)."); } - m_storage = storage_type(reinterpret_cast(PyArray_DATA(this->python_array())), - this->get_buffer_size()); + m_storage = storage_type( + reinterpret_cast(PyArray_DATA(this->python_array())), + this->get_buffer_size() + ); } template diff --git a/include/xtensor-python/pyvectorize.hpp b/include/xtensor-python/pyvectorize.hpp index 9c7d107..97d6600 100644 --- a/include/xtensor-python/pyvectorize.hpp +++ b/include/xtensor-python/pyvectorize.hpp @@ -1,20 +1,21 @@ /*************************************************************************** -* Copyright (c) Wolf Vollprecht, Johan Mabille and Sylvain Corlay * -* Copyright (c) QuantStack * -* * -* Distributed under the terms of the BSD 3-Clause License. * -* * -* The full license is in the file LICENSE, distributed with this software. * -****************************************************************************/ + * Copyright (c) Wolf Vollprecht, Johan Mabille and Sylvain Corlay * + * Copyright (c) QuantStack * + * * + * Distributed under the terms of the BSD 3-Clause License. * + * * + * The full license is in the file LICENSE, distributed with this software. * + ****************************************************************************/ #ifndef PY_VECTORIZE_HPP #define PY_VECTORIZE_HPP #include -#include "pyarray.hpp" #include "xtensor/xvectorize.hpp" +#include "pyarray.hpp" + namespace xt { @@ -53,10 +54,12 @@ namespace xt } template - inline auto pyvectorize(F&& f) -> decltype(pyvectorize(std::forward(f), (detail::get_function_type*)nullptr)) + inline auto pyvectorize(F&& f) + -> decltype(pyvectorize(std::forward(f), (detail::get_function_type*) nullptr)) { - return pyvectorize(std::forward(f), (detail::get_function_type*)nullptr); + return pyvectorize(std::forward(f), (detail::get_function_type*) nullptr); } + /// @endcond } diff --git a/include/xtensor-python/xtensor_python_config.hpp b/include/xtensor-python/xtensor_python_config.hpp index 7466f14..492b963 100644 --- a/include/xtensor-python/xtensor_python_config.hpp +++ b/include/xtensor-python/xtensor_python_config.hpp @@ -1,11 +1,11 @@ /*************************************************************************** -* Copyright (c) Wolf Vollprecht, Johan Mabille and Sylvain Corlay * -* Copyright (c) QuantStack * -* * -* Distributed under the terms of the BSD 3-Clause License. * -* * -* The full license is in the file LICENSE, distributed with this software. * -****************************************************************************/ + * Copyright (c) Wolf Vollprecht, Johan Mabille and Sylvain Corlay * + * Copyright (c) QuantStack * + * * + * Distributed under the terms of the BSD 3-Clause License. * + * * + * The full license is in the file LICENSE, distributed with this software. * + ****************************************************************************/ #ifndef XTENSOR_PYTHON_CONFIG_HPP #define XTENSOR_PYTHON_CONFIG_HPP diff --git a/include/xtensor-python/xtensor_type_caster_base.hpp b/include/xtensor-python/xtensor_type_caster_base.hpp index 840e28c..1c1f85b 100644 --- a/include/xtensor-python/xtensor_type_caster_base.hpp +++ b/include/xtensor-python/xtensor_type_caster_base.hpp @@ -1,25 +1,25 @@ /*************************************************************************** -* Copyright (c) Wolf Vollprecht, Johan Mabille and Sylvain Corlay * -* Copyright (c) QuantStack * -* * -* Distributed under the terms of the BSD 3-Clause License. * -* * -* The full license is in the file LICENSE, distributed with this software. * -****************************************************************************/ + * Copyright (c) Wolf Vollprecht, Johan Mabille and Sylvain Corlay * + * Copyright (c) QuantStack * + * * + * Distributed under the terms of the BSD 3-Clause License. * + * * + * The full license is in the file LICENSE, distributed with this software. * + ****************************************************************************/ #ifndef XTENSOR_TYPE_CASTER_HPP #define XTENSOR_TYPE_CASTER_HPP -#include #include +#include #include -#include "xtensor/xtensor.hpp" -#include "xtensor/xfixed.hpp" - #include #include +#include "xtensor/xfixed.hpp" +#include "xtensor/xtensor.hpp" + namespace pybind11 { namespace detail @@ -102,7 +102,6 @@ namespace pybind11 } }; - template struct pybind_array_dim_checker { @@ -133,7 +132,6 @@ namespace pybind11 } }; - template struct pybind_array_shape_checker { @@ -163,10 +161,15 @@ namespace pybind11 { // TODO: make use of xt::pyarray instead of array. std::vector python_strides(src.strides().size()); - std::transform(src.strides().begin(), src.strides().end(), - python_strides.begin(), [](auto v) { - return sizeof(typename Type::value_type) * v; - }); + std::transform( + src.strides().begin(), + src.strides().end(), + python_strides.begin(), + [](auto v) + { + return sizeof(typename Type::value_type) * v; + } + ); std::vector python_shape(src.shape().size()); std::copy(src.shape().begin(), src.shape().end(), python_shape.begin()); @@ -181,10 +184,10 @@ namespace pybind11 return a.release(); } - // Takes an lvalue ref to some strided expression type and a (python) base object, creating a numpy array that - // reference the expression object's data with `base` as the python-registered base class (if omitted, - // the base will be set to None, and lifetime management is up to the caller). The numpy array is - // non-writeable if the given type is const. + // Takes an lvalue ref to some strided expression type and a (python) base object, creating a numpy + // array that reference the expression object's data with `base` as the python-registered base class + // (if omitted, the base will be set to None, and lifetime management is up to the caller). The numpy + // array is non-writeable if the given type is const. template handle xtensor_ref_array(CType& src, handle parent = none()) { @@ -198,7 +201,13 @@ namespace pybind11 template handle xtensor_encapsulate(CType* src) { - capsule base(src, [](void* o) { delete static_cast(o); }); + capsule base( + src, + [](void* o) + { + delete static_cast(o); + } + ); return xtensor_ref_array(*src, base); } @@ -206,7 +215,6 @@ namespace pybind11 template struct xtensor_type_caster_base { - private: // Cast implementation @@ -215,26 +223,29 @@ namespace pybind11 { switch (policy) { - case return_value_policy::take_ownership: - case return_value_policy::automatic: - return xtensor_encapsulate(src); - case return_value_policy::move: - return xtensor_encapsulate(new CType(std::move(*src))); - case return_value_policy::copy: - return xtensor_array_cast(*src); - case return_value_policy::reference: - case return_value_policy::automatic_reference: - return xtensor_ref_array(*src); - case return_value_policy::reference_internal: - return xtensor_ref_array(*src, parent); - default: - throw cast_error("unhandled return_value_policy: should not happen!"); + case return_value_policy::take_ownership: + case return_value_policy::automatic: + return xtensor_encapsulate(src); + case return_value_policy::move: + return xtensor_encapsulate(new CType(std::move(*src))); + case return_value_policy::copy: + return xtensor_array_cast(*src); + case return_value_policy::reference: + case return_value_policy::automatic_reference: + return xtensor_ref_array(*src); + case return_value_policy::reference_internal: + return xtensor_ref_array(*src, parent); + default: + throw cast_error("unhandled return_value_policy: should not happen!"); }; } public: - PYBIND11_TYPE_CASTER(Type, _("numpy.ndarray[") + npy_format_descriptor::name + _("]")); + PYBIND11_TYPE_CASTER( + Type, + _("numpy.ndarray[") + npy_format_descriptor::name + _("]") + ); bool load(handle src, bool convert) { @@ -284,7 +295,8 @@ namespace pybind11 // lvalue reference return; default (automatic) becomes copy static handle cast(Type& src, return_value_policy policy, handle parent) { - if (policy == return_value_policy::automatic || policy == return_value_policy::automatic_reference) + if (policy == return_value_policy::automatic + || policy == return_value_policy::automatic_reference) { policy = return_value_policy::copy; } @@ -295,7 +307,8 @@ namespace pybind11 // const lvalue reference return; default (automatic) becomes copy static handle cast(const Type& src, return_value_policy policy, handle parent) { - if (policy == return_value_policy::automatic || policy == return_value_policy::automatic_reference) + if (policy == return_value_policy::automatic + || policy == return_value_policy::automatic_reference) { policy = return_value_policy::copy; } diff --git a/readthedocs.yml b/readthedocs.yml index 02f0e7b..004a03a 100644 --- a/readthedocs.yml +++ b/readthedocs.yml @@ -1,2 +1,2 @@ conda: - file: docs/environment.yml + file: docs/environment.yml diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 0c77b0d..91bebfd 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -100,4 +100,3 @@ if(DOWNLOAD_GTEST OR GTEST_SRC_DIR) endif() add_custom_target(xtest COMMAND ./test_xtensor_python DEPENDS test_xtensor_python) - diff --git a/test/copyGTest.cmake.in b/test/copyGTest.cmake.in index 8341a74..aeb2e2a 100644 --- a/test/copyGTest.cmake.in +++ b/test/copyGTest.cmake.in @@ -21,4 +21,3 @@ ExternalProject_Add(googletest INSTALL_COMMAND "" TEST_COMMAND "" ) - diff --git a/test/downloadGTest.cmake.in b/test/downloadGTest.cmake.in index 2d5cc5b..ba525b7 100644 --- a/test/downloadGTest.cmake.in +++ b/test/downloadGTest.cmake.in @@ -22,4 +22,3 @@ ExternalProject_Add(googletest INSTALL_COMMAND "" TEST_COMMAND "" ) - diff --git a/test/main.cpp b/test/main.cpp index d3cc6c4..37a5ac4 100644 --- a/test/main.cpp +++ b/test/main.cpp @@ -1,19 +1,19 @@ /*************************************************************************** -* Copyright (c) Wolf Vollprecht, Johan Mabille and Sylvain Corlay * -* Copyright (c) QuantStack * -* * -* Distributed under the terms of the BSD 3-Clause License. * -* * -* The full license is in the file LICENSE, distributed with this software. * -****************************************************************************/ + * Copyright (c) Wolf Vollprecht, Johan Mabille and Sylvain Corlay * + * Copyright (c) QuantStack * + * * + * Distributed under the terms of the BSD 3-Clause License. * + * * + * The full license is in the file LICENSE, distributed with this software. * + ****************************************************************************/ // Required to avoid the error "std does not have member copysign" #include -#include "gtest/gtest.h" - #include +#include "gtest/gtest.h" + #define FORCE_IMPORT_ARRAY #include "xtensor-python/pyarray.hpp" @@ -32,4 +32,3 @@ int main(int argc, char* argv[]) // Return test results return ret; } - diff --git a/test/test_common.hpp b/test/test_common.hpp index 07a0992..ff2b49b 100644 --- a/test/test_common.hpp +++ b/test/test_common.hpp @@ -1,11 +1,11 @@ /*************************************************************************** -* Copyright (c) Wolf Vollprecht, Johan Mabille and Sylvain Corlay * -* Copyright (c) QuantStack * -* * -* Distributed under the terms of the BSD 3-Clause License. * -* * -* The full license is in the file LICENSE, distributed with this software. * -****************************************************************************/ + * Copyright (c) Wolf Vollprecht, Johan Mabille and Sylvain Corlay * + * Copyright (c) QuantStack * + * * + * Distributed under the terms of the BSD 3-Clause License. * + * * + * The full license is in the file LICENSE, distributed with this software. * + ****************************************************************************/ #ifndef TEST_COMMON_HPP #define TEST_COMMON_HPP @@ -62,12 +62,35 @@ namespace xt layout_type m_layout; assigner_type m_assigner; - inline size_type size() const { return m_data.size(); } - inline const shape_type& shape() const { return m_shape; } - inline const strides_type& strides() const { return m_strides; } - inline const strides_type& backstrides() const { return m_backstrides; } - inline layout_type layout() const { return m_layout; } - inline const vector_type& data() const { return m_data; } + inline size_type size() const + { + return m_data.size(); + } + + inline const shape_type& shape() const + { + return m_shape; + } + + inline const strides_type& strides() const + { + return m_strides; + } + + inline const strides_type& backstrides() const + { + return m_backstrides; + } + + inline layout_type layout() const + { + return m_layout; + } + + inline const vector_type& data() const + { + return m_data; + } }; template > @@ -77,9 +100,8 @@ namespace xt { this->m_strides = {8, 4, 1}; this->m_backstrides = {16, 4, 3}; - this->m_data = {-1, 1, 2, 3, 4, 5, 6, 7, 8, 9, - 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, - 20, 21, 22, 23}; + this->m_data = { + -1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23}; this->m_layout = layout_type::row_major; } }; @@ -91,10 +113,8 @@ namespace xt { this->m_strides = {1, 3, 6}; this->m_backstrides = {2, 3, 18}; - this->m_data = {-1, 8, 16, 4, 12, 20, - 1, 9, 17, 5, 13, 21, - 2, 10, 18, 6, 14, 22, - 3, 11, 19, 7, 15, 23}; + this->m_data = { + -1, 8, 16, 4, 12, 20, 1, 9, 17, 5, 13, 21, 2, 10, 18, 6, 14, 22, 3, 11, 19, 7, 15, 23}; this->m_layout = layout_type::column_major; } }; @@ -106,9 +126,8 @@ namespace xt { this->m_strides = {8, 1, 2}; this->m_backstrides = {16, 1, 6}; - this->m_data = {-1, 4, 1, 5, 2, 6, 3, 7, - 8, 12, 9, 13, 10, 14, 11, 15, - 16, 20, 17, 21, 18, 22, 19, 23}; + this->m_data = { + -1, 4, 1, 5, 2, 6, 3, 7, 8, 12, 9, 13, 10, 14, 11, 15, 16, 20, 17, 21, 18, 22, 19, 23}; this->m_layout = layout_type::dynamic; } }; @@ -147,12 +166,35 @@ namespace xt layout_type m_layout; assigner_type m_assigner; - inline size_type size() const { return m_data.size(); } - inline const shape_type& shape() const { return m_shape; } - inline const strides_type& strides() const { return m_strides; } - inline const strides_type& backstrides() const { return m_backstrides; } - inline layout_type layout() const { return m_layout; } - inline const vector_type& data() const { return m_data; } + inline size_type size() const + { + return m_data.size(); + } + + inline const shape_type& shape() const + { + return m_shape; + } + + inline const strides_type& strides() const + { + return m_strides; + } + + inline const strides_type& backstrides() const + { + return m_backstrides; + } + + inline layout_type layout() const + { + return m_layout; + } + + inline const vector_type& data() const + { + return m_data; + } }; template @@ -160,7 +202,9 @@ namespace xt { EXPECT_TRUE(std::equal(vec.shape().cbegin(), vec.shape().cend(), result.shape().cbegin())); EXPECT_TRUE(std::equal(vec.strides().cbegin(), vec.strides().cend(), result.strides().cbegin())); - EXPECT_TRUE(std::equal(vec.backstrides().cbegin(), vec.backstrides().cend(), result.backstrides().cbegin())); + EXPECT_TRUE( + std::equal(vec.backstrides().cbegin(), vec.backstrides().cend(), result.backstrides().cbegin()) + ); EXPECT_EQ(vec.size(), result.size()); if (compare_layout) { @@ -245,14 +289,10 @@ namespace xt EXPECT_EQ(vt.shape(), shape_new); EXPECT_TRUE(std::equal(vt.storage().cbegin(), vt.storage().cend(), rm.m_data.cbegin())); - strides_type new_strides = {rm.m_strides[2], - rm.m_strides[1], - rm.m_strides[0]}; + strides_type new_strides = {rm.m_strides[2], rm.m_strides[1], rm.m_strides[0]}; EXPECT_EQ(vt.strides(), new_strides); - strides_type new_backstrides = {rm.m_backstrides[2], - rm.m_backstrides[1], - rm.m_backstrides[0]}; + strides_type new_backstrides = {rm.m_backstrides[2], rm.m_backstrides[1], rm.m_backstrides[0]}; EXPECT_EQ(vt.backstrides(), new_backstrides); EXPECT_EQ(vec_copy(0, 0, 0), vt(0, 0, 0)); @@ -278,9 +318,7 @@ namespace xt EXPECT_TRUE(std::equal(vt.shape().cbegin(), vt.shape().cend(), shape_new.begin())); EXPECT_TRUE(std::equal(vt.storage().cbegin(), vt.storage().cend(), rm.m_data.cbegin())); - strides_type new_strides = {rm.m_strides[1], - rm.m_strides[0], - rm.m_strides[2]}; + strides_type new_strides = {rm.m_strides[1], rm.m_strides[0], rm.m_strides[2]}; EXPECT_EQ(vt.strides(), new_strides); // strides_type new_backstrides = {rm.m_backstrides[1], @@ -331,7 +369,7 @@ namespace xt #ifdef XTENSOR_ENABLE_ASSERT EXPECT_ANY_THROW(vec(10, 10, 10)); #else - (void)vec; + (void) vec; #endif } @@ -582,7 +620,7 @@ namespace xt vecrm.resize(rm.m_shape, layout_type::row_major); std::copy(rm.data().cbegin(), rm.data().cend(), vecrm.template begin()); EXPECT_TRUE(std::equal(rm.data().cbegin(), rm.data().cend(), vecrm.storage().cbegin())); - //EXPECT_EQ(vecrm.template end(), vecrm.data().end()); + // EXPECT_EQ(vecrm.template end(), vecrm.data().end()); } { @@ -591,7 +629,7 @@ namespace xt veccm.resize(cm.m_shape, layout_type::column_major); std::copy(cm.data().cbegin(), cm.data().cend(), veccm.template begin()); EXPECT_TRUE(std::equal(cm.data().cbegin(), cm.data().cend(), veccm.storage().cbegin())); - //EXPECT_EQ(veccm.template end(), veccm.data().end()); + // EXPECT_EQ(veccm.template end(), veccm.data().end()); } } diff --git a/test/test_pyarray.cpp b/test/test_pyarray.cpp index 3f509e3..73e295d 100644 --- a/test/test_pyarray.cpp +++ b/test/test_pyarray.cpp @@ -1,20 +1,18 @@ /*************************************************************************** -* Copyright (c) Wolf Vollprecht, Johan Mabille and Sylvain Corlay * -* Copyright (c) QuantStack * -* * -* Distributed under the terms of the BSD 3-Clause License. * -* * -* The full license is in the file LICENSE, distributed with this software. * -****************************************************************************/ - -#include "gtest/gtest.h" - -#include "xtensor-python/pyarray.hpp" + * Copyright (c) Wolf Vollprecht, Johan Mabille and Sylvain Corlay * + * Copyright (c) QuantStack * + * * + * Distributed under the terms of the BSD 3-Clause License. * + * * + * The full license is in the file LICENSE, distributed with this software. * + ****************************************************************************/ #include "xtensor/xarray.hpp" #include "xtensor/xview.hpp" +#include "gtest/gtest.h" #include "test_common.hpp" +#include "xtensor-python/pyarray.hpp" namespace xt { @@ -23,53 +21,39 @@ namespace xt template using ndarray = pyarray; - void test1 (ndarrayconst& x) + void test1(const ndarray& x) { ndarray y = x; ndarray z = xt::zeros({10}); } - double compute(ndarray const& xs) + double compute(const ndarray& xs) { - auto v = xt::view (xs, 0, xt::all()); + auto v = xt::view(xs, 0, xt::all()); return v(0); } TEST(pyarray, initializer_constructor) { - pyarray r - {{{ 0, 1, 2}, - { 3, 4, 5}, - { 6, 7, 8}}, - {{ 9, 10, 11}, - {12, 13, 14}, - {15, 16, 17}}}; + pyarray r{{{0, 1, 2}, {3, 4, 5}, {6, 7, 8}}, {{9, 10, 11}, {12, 13, 14}, {15, 16, 17}}}; EXPECT_EQ(r.layout(), xt::layout_type::row_major); EXPECT_EQ(r.dimension(), 3); EXPECT_EQ(r(0, 0, 1), 1); EXPECT_EQ(r.shape()[0], 2); - pyarray c - {{{ 0, 1, 2}, - { 3, 4, 5}, - { 6, 7, 8}}, - {{ 9, 10, 11}, - {12, 13, 14}, - {15, 16, 17}}}; + pyarray c{ + {{0, 1, 2}, {3, 4, 5}, {6, 7, 8}}, + {{9, 10, 11}, {12, 13, 14}, {15, 16, 17}}}; EXPECT_EQ(c.layout(), xt::layout_type::column_major); EXPECT_EQ(c.dimension(), 3); EXPECT_EQ(c(0, 0, 1), 1); EXPECT_EQ(c.shape()[0], 2); - pyarray d - {{{ 0, 1, 2}, - { 3, 4, 5}, - { 6, 7, 8}}, - {{ 9, 10, 11}, - {12, 13, 14}, - {15, 16, 17}}}; + pyarray d{ + {{0, 1, 2}, {3, 4, 5}, {6, 7, 8}}, + {{9, 10, 11}, {12, 13, 14}, {15, 16, 17}}}; EXPECT_EQ(d.layout(), xt::layout_type::row_major); EXPECT_EQ(d.dimension(), 3); @@ -86,7 +70,7 @@ namespace xt compare_shape(ra, rm); EXPECT_EQ(layout_type::row_major, ra.layout()); } - + { SCOPED_TRACE("column_major constructor"); column_major_result<> cm; @@ -150,7 +134,7 @@ namespace xt central_major_result<> res; int value = 2; pyarray a(res.m_shape, res.m_strides, value); - + { SCOPED_TRACE("copy constructor"); pyarray b(a); @@ -201,8 +185,8 @@ namespace xt TEST(pyarray, extended_constructor) { - xt::xarray a1 = { { 1, 2 },{ 3, 4 } }; - xt::xarray a2 = { { 1, 2 },{ 3, 4 } }; + xt::xarray a1 = {{1, 2}, {3, 4}}; + xt::xarray a2 = {{1, 2}, {3, 4}}; pyarray c = a1 + a2; EXPECT_EQ(c(0, 0), a1(0, 0) + a2(0, 0)); EXPECT_EQ(c(0, 1), a1(0, 1) + a2(0, 1)); @@ -227,7 +211,7 @@ namespace xt pyarray a; test_resize(a); - pyarray b = { {1, 2}, {3, 4} }; + pyarray b = {{1, 2}, {3, 4}}; a.resize(b.shape()); EXPECT_EQ(a.shape(), b.shape()); } @@ -277,7 +261,7 @@ namespace xt EXPECT_EQ(2, a1(1)); EXPECT_EQ(4, a2(1, 1)); } - + TEST(pyarray, zerod) { pyarray a; @@ -286,7 +270,7 @@ namespace xt TEST(pyarray, reshape) { - pyarray a = {{1,2,3}, {4,5,6}}; + pyarray a = {{1, 2, 3}, {4, 5, 6}}; auto ptr = a.data(); a.reshape({1, 6}); std::vector sc1({1, 6}); @@ -300,7 +284,7 @@ namespace xt TEST(pyarray, view) { - xt::pyarray arr = xt::zeros({ 10 }); + xt::pyarray arr = xt::zeros({10}); auto v = xt::view(arr, xt::all()); EXPECT_EQ(v(0), 0.); } diff --git a/test/test_pyarray_traits.cpp b/test/test_pyarray_traits.cpp index fe9ef6a..a4d2b25 100644 --- a/test/test_pyarray_traits.cpp +++ b/test/test_pyarray_traits.cpp @@ -1,26 +1,23 @@ /*************************************************************************** -* Copyright (c) Wolf Vollprecht, Johan Mabille and Sylvain Corlay * -* Copyright (c) QuantStack * -* * -* Distributed under the terms of the BSD 3-Clause License. * -* * -* The full license is in the file LICENSE, distributed with this software. * -****************************************************************************/ + * Copyright (c) Wolf Vollprecht, Johan Mabille and Sylvain Corlay * + * Copyright (c) QuantStack * + * * + * Distributed under the terms of the BSD 3-Clause License. * + * * + * The full license is in the file LICENSE, distributed with this software. * + ****************************************************************************/ #include "gtest/gtest.h" - #include "xtensor-python/pyarray.hpp" - - namespace xt { namespace testing { - class pyarray_traits: public ::testing::Test + class pyarray_traits : public ::testing::Test { protected: - + using dynamic_type = xt::pyarray; using row_major_type = xt::pyarray; using column_major_type = xt::pyarray; @@ -35,13 +32,13 @@ namespace xt column_major_type c2 = {{0., 2.}, {0., 20.}, {0., 200.}}; template - bool test_has_strides(T const&) + bool test_has_strides(const T&) { return xt::has_strides::value; } template - xt::layout_type test_result_layout(T const& a1, T const& a2) + xt::layout_type test_result_layout(const T& a1, const T& a2) { auto tmp1 = pow(sin((a2 - a1) / 2.), 2.); auto tmp2 = cos(a1); @@ -49,7 +46,7 @@ namespace xt } template - bool test_linear_assign(T const& a1, T const& a2) + bool test_linear_assign(const T& a1, const T& a2) { auto tmp1 = pow(sin((a2 - a1) / 2.), 2.); auto tmp2 = cos(a1); @@ -58,7 +55,7 @@ namespace xt } template - bool test_static_simd_linear_assign(T const& a1, T const& a2) + bool test_static_simd_linear_assign(const T& a1, const T& a2) { auto tmp1 = pow(sin((a2 - a1) / 2.), 2.); auto tmp2 = cos(a1); @@ -66,7 +63,7 @@ namespace xt } template - bool test_dynamic_simd_linear_assign(T const& a1, T const& a2) + bool test_dynamic_simd_linear_assign(const T& a1, const T& a2) { auto tmp1 = pow(sin((a2 - a1) / 2.), 2.); auto tmp2 = cos(a1); @@ -74,7 +71,7 @@ namespace xt } template - bool test_linear_static_layout(T const& a1, T const& a2) + bool test_linear_static_layout(const T& a1, const T& a2) { auto tmp1 = pow(sin((a2 - a1) / 2.), 2.); auto tmp2 = cos(a1); @@ -82,7 +79,7 @@ namespace xt } template - bool test_contiguous_layout(T const& a1, T const& a2) + bool test_contiguous_layout(const T& a1, const T& a2) { auto tmp1 = pow(sin((a2 - a1) / 2.), 2.); auto tmp2 = cos(a1); diff --git a/test/test_pytensor.cpp b/test/test_pytensor.cpp index f2ac013..e1aa4f3 100644 --- a/test/test_pytensor.cpp +++ b/test/test_pytensor.cpp @@ -1,20 +1,18 @@ /*************************************************************************** -* Copyright (c) Wolf Vollprecht, Johan Mabille and Sylvain Corlay * -* Copyright (c) QuantStack * -* * -* Distributed under the terms of the BSD 3-Clause License. * -* * -* The full license is in the file LICENSE, distributed with this software. * -****************************************************************************/ - -#include "gtest/gtest.h" - -#include "xtensor-python/pytensor.hpp" + * Copyright (c) Wolf Vollprecht, Johan Mabille and Sylvain Corlay * + * Copyright (c) QuantStack * + * * + * Distributed under the terms of the BSD 3-Clause License. * + * * + * The full license is in the file LICENSE, distributed with this software. * + ****************************************************************************/ #include "xtensor/xtensor.hpp" #include "xtensor/xview.hpp" +#include "gtest/gtest.h" #include "test_common.hpp" +#include "xtensor-python/pytensor.hpp" namespace xt { @@ -22,13 +20,7 @@ namespace xt TEST(pytensor, initializer_constructor) { - pytensor t - {{{ 0, 1, 2}, - { 3, 4, 5}, - { 6, 7, 8}}, - {{ 9, 10, 11}, - {12, 13, 14}, - {15, 16, 17}}}; + pytensor t{{{0, 1, 2}, {3, 4, 5}, {6, 7, 8}}, {{9, 10, 11}, {12, 13, 14}, {15, 16, 17}}}; EXPECT_EQ(t.dimension(), 3); EXPECT_EQ(t(0, 0, 1), 1); EXPECT_EQ(t.shape()[0], 2); @@ -170,8 +162,8 @@ namespace xt TEST(pytensor, extended_constructor) { - xt::xtensor a1 = { {1, 2}, {3, 4} }; - xt::xtensor a2 = { {1, 2}, {3, 4} }; + xt::xtensor a1 = {{1, 2}, {3, 4}}; + xt::xtensor a2 = {{1, 2}, {3, 4}}; pytensor c = a1 + a2; EXPECT_EQ(c(0, 0), a1(0, 0) + a2(0, 0)); EXPECT_EQ(c(0, 1), a1(0, 1) + a2(0, 1)); @@ -184,7 +176,7 @@ namespace xt pytensor a; test_resize, container_type>(a); - pytensor b = { { { 1, 2 },{ 3, 4 } } }; + pytensor b = {{{1, 2}, {3, 4}}}; a.resize(b.shape()); EXPECT_EQ(a.shape(), b.shape()); } @@ -232,9 +224,9 @@ namespace xt TEST(pytensor, reshape) { - pytensor a = {{1,2,3}, {4,5,6}}; + pytensor a = {{1, 2, 3}, {4, 5, 6}}; auto ptr = a.data(); - a.reshape(a.shape()); // compilation check + a.reshape(a.shape()); // compilation check a.reshape({1, 6}); EXPECT_EQ(ptr, a.data()); EXPECT_THROW(a.reshape(std::vector{6}), std::runtime_error); @@ -245,16 +237,16 @@ namespace xt TEST(pytensor, view) { - xt::pytensor arr = xt::zeros({ 10 }); + xt::pytensor arr = xt::zeros({10}); auto v = xt::view(arr, xt::all()); EXPECT_EQ(v(0), 0.); } TEST(pytensor, unary) { - pytensor a = { 1, 2, 3 }; + pytensor a = {1, 2, 3}; pytensor res = -a; - pytensor ref = { -1, -2, -3 }; + pytensor ref = {-1, -2, -3}; EXPECT_EQ(ref(0), res(0)); EXPECT_EQ(ref(1), res(1)); EXPECT_EQ(ref(1), res(1)); @@ -264,9 +256,9 @@ namespace xt { // pybind11 overrrides a number of operators in pybind11::object. // This is testing that the right overload is picked up. - pytensor a = { 1.0, 2.0, 3.0 }; + pytensor a = {1.0, 2.0, 3.0}; a /= 2; - pytensor ref = { 0.5, 1.0, 1.5 }; + pytensor ref = {0.5, 1.0, 1.5}; EXPECT_EQ(ref(0), a(0)); EXPECT_EQ(ref(1), a(1)); EXPECT_EQ(ref(1), a(1)); diff --git a/test/test_pyvectorize.cpp b/test/test_pyvectorize.cpp index 30378e6..f11133a 100644 --- a/test/test_pyvectorize.cpp +++ b/test/test_pyvectorize.cpp @@ -1,18 +1,18 @@ /*************************************************************************** -* Copyright (c) Wolf Vollprecht, Johan Mabille and Sylvain Corlay * -* Copyright (c) QuantStack * -* * -* Distributed under the terms of the BSD 3-Clause License. * -* * -* The full license is in the file LICENSE, distributed with this software. * -****************************************************************************/ + * Copyright (c) Wolf Vollprecht, Johan Mabille and Sylvain Corlay * + * Copyright (c) QuantStack * + * * + * Distributed under the terms of the BSD 3-Clause License. * + * * + * The full license is in the file LICENSE, distributed with this software. * + ****************************************************************************/ #include "gtest/gtest.h" +#include "pybind11/numpy.h" +#include "pybind11/pybind11.h" #include "test_common.hpp" #include "xtensor-python/pytensor.hpp" #include "xtensor-python/pyvectorize.hpp" -#include "pybind11/pybind11.h" -#include "pybind11/numpy.h" namespace xt { @@ -27,7 +27,7 @@ namespace xt TEST(pyvectorize, function) { auto vecf1 = pyvectorize(f1); - shape_type shape = { 3, 2 }; + shape_type shape = {3, 2}; pyarray a(shape, 1.5); pyarray b(shape, 2.3); pyarray c = vecf1(a, b); @@ -36,8 +36,13 @@ namespace xt TEST(pyvectorize, lambda) { - auto vecf1 = pyvectorize([](double a, double b) { return a + b; }); - shape_type shape = { 3, 2 }; + auto vecf1 = pyvectorize( + [](double a, double b) + { + return a + b; + } + ); + shape_type shape = {3, 2}; pyarray a(shape, 1.5); pyarray b(shape, 2.3); pyarray c = vecf1(a, b); @@ -47,9 +52,14 @@ namespace xt TEST(pyvectorize, complex) { using complex_t = std::complex; - shape_type shape = { 3, 2 }; + shape_type shape = {3, 2}; pyarray a(shape, complex_t(1.2, 2.5)); - auto f = pyvectorize([](complex_t x) { return std::abs(x); }); + auto f = pyvectorize( + [](complex_t x) + { + return std::abs(x); + } + ); auto res = f(a); double exp = std::abs(a(1, 1)); EXPECT_EQ(exp, res(1, 1)); diff --git a/test/test_sfinae.cpp b/test/test_sfinae.cpp index a614485..4577afd 100644 --- a/test/test_sfinae.cpp +++ b/test/test_sfinae.cpp @@ -1,20 +1,21 @@ /*************************************************************************** -* Copyright (c) Wolf Vollprecht, Johan Mabille and Sylvain Corlay * -* Copyright (c) QuantStack * -* * -* Distributed under the terms of the BSD 3-Clause License. * -* * -* The full license is in the file LICENSE, distributed with this software. * -****************************************************************************/ + * Copyright (c) Wolf Vollprecht, Johan Mabille and Sylvain Corlay * + * Copyright (c) QuantStack * + * * + * Distributed under the terms of the BSD 3-Clause License. * + * * + * The full license is in the file LICENSE, distributed with this software. * + ****************************************************************************/ #include -#include "gtest/gtest.h" -#include "xtensor-python/pytensor.hpp" -#include "xtensor-python/pyarray.hpp" #include "xtensor/xarray.hpp" #include "xtensor/xtensor.hpp" +#include "gtest/gtest.h" +#include "xtensor-python/pyarray.hpp" +#include "xtensor-python/pytensor.hpp" + namespace xt { template ::value, int> = 0> diff --git a/test_python/main.cpp b/test_python/main.cpp index 7a0c524..961df4e 100644 --- a/test_python/main.cpp +++ b/test_python/main.cpp @@ -1,23 +1,24 @@ /*************************************************************************** -* Copyright (c) Wolf Vollprecht, Johan Mabille and Sylvain Corlay * -* Copyright (c) QuantStack * -* * -* Distributed under the terms of the BSD 3-Clause License. * -* * -* The full license is in the file LICENSE, distributed with this software. * -****************************************************************************/ + * Copyright (c) Wolf Vollprecht, Johan Mabille and Sylvain Corlay * + * Copyright (c) QuantStack * + * * + * Distributed under the terms of the BSD 3-Clause License. * + * * + * The full license is in the file LICENSE, distributed with this software. * + ****************************************************************************/ #include -#include "xtensor/xmath.hpp" #include "xtensor/xarray.hpp" #include "xtensor/xfixed.hpp" +#include "xtensor/xmath.hpp" #define FORCE_IMPORT_ARRAY +#include "xtensor/xadapt.hpp" +#include "xtensor/xstrided_view.hpp" + #include "xtensor-python/pyarray.hpp" #include "xtensor-python/pytensor.hpp" #include "xtensor-python/pyvectorize.hpp" -#include "xtensor/xadapt.hpp" -#include "xtensor/xstrided_view.hpp" namespace py = pybind11; using complex_t = std::complex; @@ -39,8 +40,8 @@ xt::xarray example3_xarray(const xt::xarray& m) return xt::transpose(m) + 2; } -xt::xarray example3_xarray_colmajor( - const xt::xarray& m) +xt::xarray +example3_xarray_colmajor(const xt::xarray& m) { return xt::transpose(m) + 2; } @@ -55,13 +56,14 @@ xt::xtensor example3_xtensor2(const xt::xtensor& m) return xt::transpose(m) + 2; } -xt::xtensor example3_xtensor2_colmajor( - const xt::xtensor& m) +xt::xtensor +example3_xtensor2_colmajor(const xt::xtensor& m) { return xt::transpose(m) + 2; } -xt::xtensor_fixed> example3_xfixed3(const xt::xtensor_fixed>& m) +xt::xtensor_fixed> +example3_xfixed3(const xt::xtensor_fixed>& m) { return xt::transpose(m) + 2; } @@ -71,8 +73,8 @@ xt::xtensor_fixed> example3_xfixed2(const xt::xtensor_fixe return xt::transpose(m) + 2; } -xt::xtensor_fixed, xt::layout_type::column_major> example3_xfixed2_colmajor( - const xt::xtensor_fixed, xt::layout_type::column_major>& m) +xt::xtensor_fixed, xt::layout_type::column_major> +example3_xfixed2_colmajor(const xt::xtensor_fixed, xt::layout_type::column_major>& m) { return xt::transpose(m) + 2; } @@ -87,13 +89,14 @@ double readme_example1(xt::pyarray& m) double readme_example2(double i, double j) { - return std::sin(i) - std::cos(j); + return std::sin(i) - std::cos(j); } auto complex_overload(const xt::pyarray>& a) { return a; } + auto no_complex_overload(const xt::pyarray& a) { return a; @@ -108,6 +111,7 @@ auto no_complex_overload_reg(const double& a) { return a; } + // // Operator examples // @@ -138,15 +142,59 @@ int add(int i, int j) return i + j; } -template std::string typestring() { return "Unknown"; } -template <> std::string typestring() { return "uint8"; } -template <> std::string typestring() { return "int8"; } -template <> std::string typestring() { return "uint16"; } -template <> std::string typestring() { return "int16"; } -template <> std::string typestring() { return "uint32"; } -template <> std::string typestring() { return "int32"; } -template <> std::string typestring() { return "uint64"; } -template <> std::string typestring() { return "int64"; } +template +std::string typestring() +{ + return "Unknown"; +} + +template <> +std::string typestring() +{ + return "uint8"; +} + +template <> +std::string typestring() +{ + return "int8"; +} + +template <> +std::string typestring() +{ + return "uint16"; +} + +template <> +std::string typestring() +{ + return "int16"; +} + +template <> +std::string typestring() +{ + return "uint32"; +} + +template <> +std::string typestring() +{ + return "int32"; +} + +template <> +std::string typestring() +{ + return "uint64"; +} + +template <> +std::string typestring() +{ + return "int64"; +} template inline std::string int_overload(xt::pyarray& m) @@ -194,10 +242,21 @@ struct B class C { public: + using array_type = xt::xarray; - C() : m_array{0, 0, 0, 0} {} - array_type & array() { return m_array; } + + C() + : m_array{0, 0, 0, 0} + { + } + + array_type& array() + { + return m_array; + } + private: + array_type m_array; }; @@ -206,7 +265,7 @@ struct test_native_casters using array_type = xt::xarray; array_type a = xt::ones({50, 50}); - const auto & get_array() + const auto& get_array() { return a; } @@ -235,7 +294,7 @@ struct test_native_casters auto get_owning_array_adapter() { size_t size = 100; - int * data = new int[size]; + int* data = new int[size]; std::fill(data, data + size, 1); using shape_type = std::vector; @@ -301,7 +360,7 @@ xt::pytensor xscalar(const xt::pytensor& arg) template using ndarray = xt::pyarray; -void test_rm(ndarrayconst& x) +void test_rm(const ndarray& x) { ndarray y = x; ndarray z = xt::zeros({10}); @@ -336,14 +395,26 @@ PYBIND11_MODULE(xtensor_python_test, m) m.def("array_subtraction", array_subtraction); m.def("array_multiplication", array_multiplication); m.def("array_division", array_division); - + m.def("vectorize_example1", xt::pyvectorize(add)); - m.def("rect_to_polar", xt::pyvectorize([](complex_t x) { return std::abs(x); })); + m.def( + "rect_to_polar", + xt::pyvectorize( + [](complex_t x) + { + return std::abs(x); + } + ) + ); - m.def("compare_shapes", [](const xt::pyarray& a, const xt::pyarray& b) { - return a.shape() == b.shape(); - }); + m.def( + "compare_shapes", + [](const xt::pyarray& a, const xt::pyarray& b) + { + return a.shape() == b.shape(); + } + ); m.def("test_rm", test_rm); @@ -375,28 +446,101 @@ PYBIND11_MODULE(xtensor_python_test, m) .def(py::init<>()) .def_property_readonly( "copy", - [](C & self) { return self.array(); } + [](C& self) + { + return self.array(); + } ) .def_property_readonly( "ref", - [](C & self) -> C::array_type & { return self.array(); } - ) - ; - - m.def("simple_array", [](xt::pyarray) { return 1; } ); - m.def("simple_tensor", [](xt::pytensor) { return 2; } ); - - m.def("diff_shape_overload", [](xt::pytensor a) { return 1; }); - m.def("diff_shape_overload", [](xt::pytensor a) { return 2; }); + [](C& self) -> C::array_type& + { + return self.array(); + } + ); + + m.def( + "simple_array", + [](xt::pyarray) + { + return 1; + } + ); + m.def( + "simple_tensor", + [](xt::pytensor) + { + return 2; + } + ); + + m.def( + "diff_shape_overload", + [](xt::pytensor a) + { + return 1; + } + ); + m.def( + "diff_shape_overload", + [](xt::pytensor a) + { + return 2; + } + ); py::class_(m, "test_native_casters") - .def(py::init<>()) - .def("get_array", &test_native_casters::get_array, py::return_value_policy::reference_internal) // memory managed by the class instance - .def("get_strided_view", &test_native_casters::get_strided_view, py::keep_alive<0, 1>()) // keep_alive<0, 1>() => do not free "self" before the returned view - .def("get_array_adapter", &test_native_casters::get_array_adapter, py::keep_alive<0, 1>()) // keep_alive<0, 1>() => do not free "self" before the returned adapter - .def("get_tensor_adapter", &test_native_casters::get_tensor_adapter, py::keep_alive<0, 1>()) // keep_alive<0, 1>() => do not free "self" before the returned adapter - .def("get_owning_array_adapter", &test_native_casters::get_owning_array_adapter) // auto memory management as the adapter owns its memory - .def("view_keep_alive_member_function", [](test_native_casters & self, xt::pyarray & a) // keep_alive<0, 2>() => do not free second parameter before the returned view - {return xt::reshape_view(a, {a.size(), });}, - py::keep_alive<0, 2>()); + .def(py::init<>()) + .def("get_array", &test_native_casters::get_array, py::return_value_policy::reference_internal) // memory + // managed + // by + // the + // class + // instance + .def("get_strided_view", &test_native_casters::get_strided_view, py::keep_alive<0, 1>()) // keep_alive<0, + // 1>() => + // do not + // free + // "self" + // before + // the + // returned + // view + .def("get_array_adapter", &test_native_casters::get_array_adapter, py::keep_alive<0, 1>()) // keep_alive<0, + // 1>() => + // do not + // free + // "self" + // before + // the + // returned + // adapter + .def("get_tensor_adapter", &test_native_casters::get_tensor_adapter, py::keep_alive<0, 1>()) // keep_alive<0, + // 1>() + // => do + // not + // free + // "self" + // before + // the + // returned + // adapter + .def("get_owning_array_adapter", &test_native_casters::get_owning_array_adapter) // auto memory + // management as the + // adapter owns its + // memory + .def( + "view_keep_alive_member_function", + [](test_native_casters& self, xt::pyarray& a) // keep_alive<0, 2>() => do not free second + // parameter before the returned view + { + return xt::reshape_view( + a, + { + a.size(), + } + ); + }, + py::keep_alive<0, 2>() + ); }