diff --git a/external_codes/boost_multi/README b/external_codes/boost_multi/README index 18f566edfc..7eaa3cc89e 100644 --- a/external_codes/boost_multi/README +++ b/external_codes/boost_multi/README @@ -1,3 +1,3 @@ command to update subtree to v0.80.1 tag. Run from top level QMCPACK source directory -git subtree pull --squash -P external_codes/boost_multi/multi https://gitlab.com/correaa/boost-multi.git v0.80.1 +git subtree pull --squash -P external_codes/boost_multi/multi https://gitlab.com/correaa/boost-multi.git v0.86.0 diff --git a/external_codes/boost_multi/multi/.clang-format b/external_codes/boost_multi/multi/.clang-format index adcb8acec3..3d1ed5e4c7 100644 --- a/external_codes/boost_multi/multi/.clang-format +++ b/external_codes/boost_multi/multi/.clang-format @@ -1,230 +1,64 @@ +# https://clang-format-configurator.site +# Copyright 2020-2024 Alfredo A. Correa --- -Language: Cpp -# BasedOnStyle: Google -#AccessModifierOffset: -1 -AlignAfterOpenBracket: BlockIndent # Align +Language: Cpp +AccessModifierOffset: -3 +AlignAfterOpenBracket: BlockIndent AlignArrayOfStructures: Right -#AlignConsecutiveMacros: None -AlignConsecutiveAssignments: Consecutive # None -#AlignConsecutiveBitFields: None -AlignConsecutiveDeclarations: Consecutive -#AlignEscapedNewlines: Left -AlignOperands: AlignAfterOperator -AlignTrailingComments: false -#AllowAllArgumentsOnNextLine: true -#AllowAllParametersOfDeclarationOnNextLine: true -#AllowShortEnumsOnASingleLine: true -#AllowShortBlocksOnASingleLine: Never -AllowShortCaseLabelsOnASingleLine: true # false -#AllowShortFunctionsOnASingleLine: All -#AllowShortLambdasOnASingleLine: All -#AllowShortIfStatementsOnASingleLine: WithoutElse -#AllowShortLoopsOnASingleLine: true -#AlwaysBreakAfterDefinitionReturnType: None -#AlwaysBreakAfterReturnType: None -#AlwaysBreakBeforeMultilineStrings: true -AlwaysBreakTemplateDeclarations: No # Yes -#AttributeMacros: -# - __capability -#BinPackArguments: true -#BinPackParameters: true -#BraceWrapping: -# AfterCaseLabel: false -# AfterClass: false -# AfterControlStatement: Never -# AfterEnum: false -# AfterFunction: false -# AfterNamespace: false -# AfterObjCDeclaration: false -# AfterStruct: false -# AfterUnion: false -# AfterExternBlock: false -# BeforeCatch: false -# BeforeElse: false -# BeforeLambdaBody: false -# BeforeWhile: false -# IndentBraces: false -# SplitEmptyFunction: true -# SplitEmptyRecord: true -# SplitEmptyNamespace: true -#BreakBeforeBinaryOperators: None -#BreakBeforeConceptDeclarations: true -#BreakBeforeBraces: Attach -#BreakBeforeInheritanceComma: false +AlignConsecutiveAssignments: + Enabled: true + AcrossEmptyLines: false + AcrossComments: false +AlignConsecutiveDeclarations: + Enabled: true + AcrossEmptyLines: false + AcrossComments: false +AlignOperands: AlignAfterOperator +AllowAllArgumentsOnNextLine: false +AllowShortLambdasOnASingleLine: Inline +AllowShortCaseLabelsOnASingleLine: true +AlwaysBreakTemplateDeclarations: No BreakInheritanceList: BeforeComma -#BreakBeforeTernaryOperators: true -#BreakConstructorInitializersBeforeComma: false -#BreakConstructorInitializers: BeforeColon -#BreakAfterJavaFieldAnnotations: false -#BreakStringLiterals: true -ColumnLimit: 0 -#CommentPragmas: '^ IWYU pragma:' -QualifierAlignment: Right # Leave -#CompactNamespaces: false +BraceWrapping: + BeforeLambdaBody: false +ColumnLimit: 0 +QualifierAlignment: Right ConstructorInitializerIndentWidth: 0 -ContinuationIndentWidth: 99 -#Cpp11BracedListStyle: true -#DeriveLineEnding: true -#DerivePointerAlignment: true -#DisableFormat: false -#EmptyLineAfterAccessModifier: Never -#EmptyLineBeforeAccessModifier: LogicalBlock -#ExperimentalAutoDetectBinPacking: false -#PackConstructorInitializers: NextLine -#BasedOnStyle: '' -#ConstructorInitializerAllOnOneLineOrOnePerLine: false -#AllowAllConstructorInitializersOnNextLine: true +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: true FixNamespaceComments: true -#ForEachMacros: -# - foreach -# - Q_FOREACH -# - BOOST_FOREACH -#IfMacros: -# - KJ_IF_MAYBE -#IncludeBlocks: Regroup -#IncludeCategories: -# - Regex: '^' -# Priority: 2 -# SortPriority: 0 -# CaseSensitive: false -# - Regex: '^<.*\.h>' -# Priority: 1 -# SortPriority: 0 -# CaseSensitive: false -# - Regex: '^<.*' -# Priority: 2 -# SortPriority: 0 -# CaseSensitive: false -# - Regex: '.*' -# Priority: 3 -# SortPriority: 0 -# CaseSensitive: false -#IncludeIsMainRegex: '([-_](test|unittest))?$' -#IncludeIsMainSourceRegex: '' -#IndentAccessModifiers: true # false -AccessModifierOffset: -98 # 2 -#IndentCaseLabels: true -#IndentCaseBlocks: false -#IndentGotoLabels: true -#IndentPPDirectives: None -#IndentExternBlock: AfterExternBlock -#IndentRequires: false -IndentWidth: 99 -#IndentWrappedFunctionNames: false -#InsertTrailingCommas: None -#JavaScriptQuotes: Leave -#JavaScriptWrapImports: true -#KeepEmptyLinesAtTheStartOfBlocks: false -#LambdaBodyIndentation: Signature -#MacroBlockBegin: '' -#MacroBlockEnd: '' -#MaxEmptyLinesToKeep: 1 -#NamespaceIndentation: None -#ObjCBinPackProtocolList: Never -#ObjCBlockIndentWidth: 2 -#ObjCBreakBeforeNestedBlockParam: true -#ObjCSpaceAfterProperty: false -#ObjCSpaceBeforeProtocolList: true -#PenaltyBreakAssignment: 2 -#PenaltyBreakBeforeFirstCallParameter: 1 -#PenaltyBreakComment: 300 -#PenaltyBreakFirstLessLess: 120 -#PenaltyBreakOpenParenthesis: 0 -#PenaltyBreakString: 1000 +IncludeBlocks: Regroup +IncludeCategories: + - Regex: + Priority: 1 + - Regex: <(boost\/multi)\/ + Priority: 2 + - Regex: <([A-Za-z0-9\Q/-_\E])+> + Priority: 6 + - Regex: <(catch2|boost)\/ + Priority: 5 + - Regex: <([A-Za-z0-9.\Q/-_\E])+> + Priority: 4 + - Regex: '"([A-Za-z0-9.\Q/-_\E])+"' + Priority: 3 +IndentPPDirectives: BeforeHash +IndentWidth: 4 +# LambdaBodyIndentation: Signature PenaltyBreakTemplateDeclaration: 10 -#PenaltyExcessCharacter: 1000000 -#PenaltyReturnTypeOnItsOwnLine: 200 -#PenaltyIndentedWhitespace: 0 PointerAlignment: Left -#PPIndentWidth: -1 -#RawStringFormats: -# - Language: Cpp -# Delimiters: -# - cc -# - CC -# - cpp -# - Cpp -# - CPP -# - 'c++' -# - 'C++' -# CanonicalDelimiter: '' -# BasedOnStyle: google -# - Language: TextProto -# Delimiters: -# - pb -# - PB -# - proto -# - PROTO -# EnclosingFunctions: -# - EqualsProto -# - EquivToProto -# - PARSE_PARTIAL_TEXT_PROTO -# - PARSE_TEST_PROTO -# - PARSE_TEXT_PROTO -# - ParseTextOrDie -# - ParseTextProtoOrDie -# - ParseTestProto -# - ParsePartialTestProto -# CanonicalDelimiter: pb -# BasedOnStyle: google -#ReferenceAlignment: Pointer -#ReflowComments: true -#RemoveBracesLLVM: false -#SeparateDefinitionBlocks: Leave -#ShortNamespaceLines: 1 -#SortIncludes: CaseSensitive -#SortJavaStaticImport: Before -#SortUsingDeclarations: true -#SpaceAfterCStyleCast: false -#SpaceAfterLogicalNot: false -SpaceAfterTemplateKeyword: false # true -#SpaceBeforeAssignmentOperators: true -#SpaceBeforeCaseColon: false -#SpaceBeforeCpp11BracedList: false -#SpaceBeforeCtorInitializerColon: true -#SpaceBeforeInheritanceColon: true -SpaceBeforeParens: Custom # ControlStatements +SpaceAfterTemplateKeyword: false +SpaceBeforeAssignmentOperators: true +SpaceBeforeParens: Custom SpaceBeforeParensOptions: - AfterControlStatements: false # true -# AfterForeachMacros: true -# AfterFunctionDefinitionName: false -# AfterFunctionDeclarationName: false -# AfterIfMacros: true -# AfterOverloadedOperator: false -# BeforeNonEmptyParentheses: false -#SpaceAroundPointerQualifiers: Default -#SpaceBeforeRangeBasedForLoopColon: true -#SpaceInEmptyBlock: false -#SpaceInEmptyParentheses: false + AfterControlStatements: false SpacesBeforeTrailingComments: 2 -#SpacesInAngles: Never -#SpacesInConditionalStatement: false -#SpacesInContainerLiterals: true -#SpacesInCStyleCastParentheses: false SpacesInLineCommentPrefix: - Minimum: 1 -# Maximum: -1 -#SpacesInParentheses: false -#SpacesInSquareBrackets: false -#SpaceBeforeSquareBrackets: false -#BitFieldColonSpacing: Both -Standard: c++17 -#StatementAttributeLikeMacros: -# - Q_EMIT -#StatementMacros: -# - Q_UNUSED -# - QT_REQUIRE_VERSION -TabWidth: 99 -#UseCRLF: false -UseTab: ForContinuationAndIndentation # Never + Minimum: 1 +Standard: c++17 +TabWidth: 4 +UseTab: ForContinuationAndIndentation WhitespaceSensitiveMacros: - BOOST_REQUIRE - BOOST_TEST - BOOST_TEST_REQUIRE -#WhitespaceSensitiveMacros: -# - STRINGIZE -# - PP_STRINGIZE -# - BOOST_PP_STRINGIZE -# - NS_SWIFT_NAME -# - CF_SWIFT_NAME -... + - BOOST_AUTO_TEST_CASE diff --git a/external_codes/boost_multi/multi/.clang-tidy b/external_codes/boost_multi/multi/.clang-tidy index 37ecad7d62..226241ef0f 100644 --- a/external_codes/boost_multi/multi/.clang-tidy +++ b/external_codes/boost_multi/multi/.clang-tidy @@ -1,4 +1,4 @@ -# -*-indent-tabs-mode:nil;c-basic-offset:2;tab-width:2;autowrap:nil;-*- +# Copyright 2020-2024 Alfredo A. Correa WarningsAsErrors: '*' HeaderFilterRegex: '.' @@ -14,9 +14,6 @@ CheckOptions: - { key: readability-identifier-length.MinimumLoopCounterNameLength , value: 2 } - { key: readability-identifier-length.MinimumParameterNameLength , value: 2 } - { key: readability-identifier-length.MinimumVariableNameLength , value: 2 } - - { key: readability-identifier-naming.MacroDefinitionCase , value: UPPER_CASE } - - { key: readability-identifier-naming.MacroDefinitionPrefix, , value: BOOST_MULTI_ } - - { key: readability-identifier-naming.MacroDefinitionSuffix, , value: * } - { key: readability-identifier-naming.NamespaceCase , value: lower_case } - { key: readability-identifier-naming.PrivateMemberPrefix , value: '' } - { key: readability-identifier-naming.PrivateMemberSuffix , value: _ } @@ -32,25 +29,22 @@ CheckOptions: Checks: '*, -altera-struct-pack-align, - -clang-diagnostic-deprecated-declarations, -cppcoreguidelines-avoid-magic-numbers, -cppcoreguidelines-macro-usage, -fuchsia-overloaded-operator, -fuchsia-trailing-return, -llvmlibc-*, - -misc-include-cleaner, -modernize-use-nodiscard, - -readability-magic-numbers -' + -readability-magic-numbers' ## explanation of the suppressed rules above: # -altera-struct-pack-align, // this asks to use non-standard pragmas such as __attribute__((aligned(0))) and _attribute__((packed)), may interfeere with gcc/nvcc compatibility? -# -clang-diagnostic-deprecated-declarations // some test run deprecated functions on purposes +# -clang-diagnostic-deprecated-declarations // some test run deprecated functions on purpose # -cppcoreguidelines-avoid-magic-numbers, // all tests use magic numbers # -cppcoreguidelines-macro-usage, // BLAS adaptors uses a lot of macros # -fuchsia-overloaded-operator, // this library overloads operators (==, <, +, &) -# -fuchsia-trailing-return, // to allow any '-> decltype(auto)', contradicts modernize trailing # -llvmlibc-*, // nonsense warnings, for llvm developers -# -misc-include-cleaner, // using Boost.Test +# -llvm-header-guard, // allow PCH +# -misc-include-cleaner // allow PCH # -modernize-use-nodiscard, // this would add [[nodiscard]] to almost all functions, adding a lot of noise -# -readability-magic-numbers, // all tests use magic numbers +# -readability-magic-numbers, // many tests use magic numbers diff --git a/external_codes/boost_multi/multi/.github/pull_request_template.md b/external_codes/boost_multi/multi/.github/pull_request_template.md new file mode 100644 index 0000000000..91063c7249 --- /dev/null +++ b/external_codes/boost_multi/multi/.github/pull_request_template.md @@ -0,0 +1,4 @@ +[gl pipelines](https://gitlab.com/correaa/boost-multi/-/pipelines?page=1&scope=all) +[gl merge request](https://gitlab.com/correaa/boost-multi/-/merge_requests/new) + +[![gitlabci](https://gitlab.com/correaa/boost-multi/badges/master/pipeline.svg)](https://gitlab.com/correaa/boost-multi/-/pipelines?page=1&scope=all) diff --git a/external_codes/boost_multi/multi/.github/workflows/ci.yml b/external_codes/boost_multi/multi/.github/workflows/ci.yml index 3e9e6981fb..c00722d0d9 100644 --- a/external_codes/boost_multi/multi/.github/workflows/ci.yml +++ b/external_codes/boost_multi/multi/.github/workflows/ci.yml @@ -22,6 +22,7 @@ env: GIT_FETCH_JOBS: 8 NET_RETRY_COUNT: 5 DEFAULT_BUILD_VARIANT: debug,release + ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION: true jobs: posix: @@ -470,6 +471,7 @@ jobs: addrmd: "64" os: windows-2019 + timeout-minutes: 120 runs-on: ${{matrix.os}} steps: @@ -517,6 +519,7 @@ jobs: addrmd: "64" os: windows-2022 + timeout-minutes: 120 runs-on: ${{matrix.os}} steps: diff --git a/external_codes/boost_multi/multi/.github/workflows/cmake.yml b/external_codes/boost_multi/multi/.github/workflows/cmake.yml index c3fc75f104..44c2b18a48 100644 --- a/external_codes/boost_multi/multi/.github/workflows/cmake.yml +++ b/external_codes/boost_multi/multi/.github/workflows/cmake.yml @@ -4,12 +4,20 @@ name: CMake on: push: - branches: [ "master" ] - pull_request: - branches: [ "master" ] + branches: + - '**' # matches every branch + # pull_request: + # branches: [ "master" ] + +# on: +# push: +# branches: [ "master" ] +# pull_request: +# branches: [ "master" ] env: BUILD_TYPE: Release + ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION: true jobs: latest-cpp: @@ -21,7 +29,7 @@ jobs: - name: Configure system run: | sudo apt-get -y update - sudo apt-get -y install libboost-test-dev + sudo apt-get -y install libboost-dev - name: Configure CMake run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} @@ -41,13 +49,14 @@ jobs: - name: Configure system run: | + sudo dpkg --add-architecture i386 sudo apt-get -y update - sudo apt-get -y install g++-multilib libboost-test-dev - wget https://downloads.sourceforge.net/project/boost/boost/1.84.0/boost_1_84_0.tar.gz --no-verbose - tar -xf boost_1_84_0.tar.gz - cd boost_1_84_0 - ./bootstrap.sh - sudo ./b2 cxxflags=-m32 --with-serialization --with-test --with-timer install -j4 + sudo apt-get -y install g++-multilib gfortran libboost-serialization-dev:i386 wget + # wget https://downloads.sourceforge.net/project/boost/boost/1.84.0/boost_1_84_0.tar.gz --no-verbose + # tar -xf boost_1_84_0.tar.gz + # cd boost_1_84_0 + # ./bootstrap.sh + # sudo ./b2 cxxflags=-m32 --with-serialization --with-timer install -j4 - name: Configure CMake run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DCMAKE_CXX_FLAGS="-m32" @@ -68,10 +77,10 @@ jobs: - name: Configure system run: | sudo apt-get -y update - sudo apt-get -y install clang libboost-test-dev + sudo apt-get -y install clang clang-tidy libboost-dev - name: Configure CMake - run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DCMAKE_CXX_COMPILER=clang++ + run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_CXX_CLANG_TIDY=clang-tidy - name: Build run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} @@ -143,7 +152,7 @@ jobs: .\vcpkg\bootstrap-vcpkg.bat - name: Install Boost - run: .\vcpkg\vcpkg install boost + run: .\vcpkg\vcpkg install boost-multi-array boost-timer boost-serialization - name: Set up Boost environment variables run: | @@ -153,10 +162,12 @@ jobs: echo "PATH=$(Get-Location)\vcpkg\installed\x64-windows\bin;$env:PATH" >> $env:GITHUB_ENV - name: Configure CMake - run: cmake -S . -B build -A x64 -DCMAKE_TOOLCHAIN_FILE=.\vcpkg\scripts\buildsystems\vcpkg.cmake -DBOOST_ROOT=.\vcpkg\installed\x64-windows + run: cmake -S . -B build -A x64 -DCMAKE_CXX_STANDARD=20 -DCMAKE_TOOLCHAIN_FILE=.\vcpkg\scripts\buildsystems\vcpkg.cmake -DBOOST_ROOT=.\vcpkg\installed\x64-windows - name: Build run: cmake --build build --config Release - name: Run tests - run: ctest --test-dir build --output-on-failure -C Release + run: ctest --test-dir build --timeout 120 --output-on-failure -C Release + timeout-minutes: 10 + diff --git a/external_codes/boost_multi/multi/.github/workflows/codecov.yml b/external_codes/boost_multi/multi/.github/workflows/codecov.yml deleted file mode 100644 index 278a2b8666..0000000000 --- a/external_codes/boost_multi/multi/.github/workflows/codecov.yml +++ /dev/null @@ -1,200 +0,0 @@ -# Copyright 2020-2021 Peter Dimov -# Copyright 2021 Andrey Semashev -# Copyright 2021 Alexander Grund -# Copyright 2022 James E. King III -# Copyright 2023 Matt Borland -# -# Distributed under the Boost Software License, Version 1.0. -# (See accompanying file LICENSE_1_0.txt or copy at http://boost.org/LICENSE_1_0.txt) ---- -name: codecov - -on: - pull_request: - push: - branches: - - master - - develop - - bugfix/** - - feature/** - - fix/** - - pr/** - -env: - GIT_FETCH_JOBS: 8 - NET_RETRY_COUNT: 5 - B2_CI_VERSION: 1 - B2_VARIANT: debug,release - B2_LINK: shared,static - LCOV_BRANCH_COVERAGE: 0 - CODECOV_NAME: Github Actions - -jobs: - posix: - defaults: - run: - shell: bash - - strategy: - fail-fast: false - matrix: - include: - - { name: Collect coverage, coverage: yes, - compiler: gcc-12, cxxstd: '20', os: ubuntu-22.04, install: 'g++-12-multilib', address-model: '32,64' } - - timeout-minutes: 120 - runs-on: ${{matrix.os}} - container: ${{matrix.container}} - env: {B2_USE_CCACHE: 1} - - steps: - - name: Setup environment - run: | - if [ -f "/etc/debian_version" ]; then - echo "DEBIAN_FRONTEND=noninteractive" >> $GITHUB_ENV - export DEBIAN_FRONTEND=noninteractive - fi - if [ -n "${{matrix.container}}" ] && [ -f "/etc/debian_version" ]; then - apt-get -o Acquire::Retries=$NET_RETRY_COUNT update - apt-get -o Acquire::Retries=$NET_RETRY_COUNT install -y sudo software-properties-common curl - # Need (newer) git, and the older Ubuntu container may require requesting the key manually using port 80 - curl -sSL --retry ${NET_RETRY_COUNT:-5} 'http://keyserver.ubuntu.com/pks/lookup?op=get&search=0xE1DD270288B4E6030699E45FA1715D88E1DF1F24' | sudo gpg --dearmor -o /etc/apt/trusted.gpg.d/git-core_ubuntu_ppa.gpg - for i in {1..${NET_RETRY_COUNT:-3}}; do sudo -E add-apt-repository -y ppa:git-core/ppa && break || sleep 10; done - apt-get -o Acquire::Retries=$NET_RETRY_COUNT update - osver=$(lsb_release -sr | cut -f1 -d.) - pkgs="g++ git" - # Ubuntu 22+ has only Python 3 in the repos - if [ -n "$osver" ] && [ "$osver" -ge "22" ]; then - pkgs+=" python-is-python3 libpython3-dev" - else - pkgs+=" python libpython-dev" - fi - apt-get -o Acquire::Retries=$NET_RETRY_COUNT install -y $pkgs - fi - # For jobs not compatible with ccache, use "ccache: no" in the matrix - if [[ "${{ matrix.ccache }}" == "no" ]]; then - echo "B2_USE_CCACHE=0" >> $GITHUB_ENV - fi - git config --global pack.threads 0 - - - uses: actions/checkout@v3 - with: - # For coverage builds fetch the whole history, else only 1 commit using a 'fake ternary' - fetch-depth: ${{ matrix.coverage && '0' || '1' }} - - - name: Cache ccache - uses: actions/cache@v3 - if: env.B2_USE_CCACHE - with: - path: ~/.ccache - key: ${{matrix.os}}-${{matrix.container}}-${{matrix.compiler}}-${{github.sha}} - restore-keys: ${{matrix.os}}-${{matrix.container}}-${{matrix.compiler}}- - - - name: Fetch Boost.CI - uses: actions/checkout@v3 - with: - repository: boostorg/boost-ci - ref: master - path: boost-ci-cloned - - - name: Get CI scripts folder - run: | - # Copy ci folder if not testing Boost.CI - [[ "$GITHUB_REPOSITORY" =~ "boost-ci" ]] || cp -r boost-ci-cloned/ci . - rm -rf boost-ci-cloned - - - name: Install packages - if: startsWith(matrix.os, 'ubuntu') - run: | - SOURCE_KEYS=(${{join(matrix.source_keys, ' ')}}) - SOURCES=(${{join(matrix.sources, ' ')}}) - # Add this by default - SOURCES+=(ppa:ubuntu-toolchain-r/test) - for key in "${SOURCE_KEYS[@]}"; do - for i in {1..$NET_RETRY_COUNT}; do - keyfilename=$(basename -s .key $key) - curl -sSL --retry ${NET_RETRY_COUNT:-5} "$key" | sudo gpg --dearmor > /etc/apt/trusted.gpg.d/${keyfilename} && break || sleep 10 - done - done - for source in "${SOURCES[@]}"; do - for i in {1..$NET_RETRY_COUNT}; do - sudo add-apt-repository $source && break || sleep 10 - done - done - sudo apt-get -o Acquire::Retries=$NET_RETRY_COUNT update - if [[ -z "${{matrix.install}}" ]]; then - pkgs="${{matrix.compiler}}" - pkgs="${pkgs/gcc-/g++-}" - else - pkgs="${{matrix.install}}" - fi - sudo apt-get -o Acquire::Retries=$NET_RETRY_COUNT install -y $pkgs locales - sudo locale-gen de_DE.UTF-8 - sudo update-locale - - - name: Setup GCC Toolchain - if: matrix.gcc_toolchain - run: | - GCC_TOOLCHAIN_ROOT="$HOME/gcc-toolchain" - echo "GCC_TOOLCHAIN_ROOT=$GCC_TOOLCHAIN_ROOT" >> $GITHUB_ENV - if ! command -v dpkg-architecture; then - apt-get install -y dpkg-dev - fi - MULTIARCH_TRIPLET="$(dpkg-architecture -qDEB_HOST_MULTIARCH)" - mkdir -p "$GCC_TOOLCHAIN_ROOT" - ln -s /usr/include "$GCC_TOOLCHAIN_ROOT/include" - ln -s /usr/bin "$GCC_TOOLCHAIN_ROOT/bin" - mkdir -p "$GCC_TOOLCHAIN_ROOT/lib/gcc/$MULTIARCH_TRIPLET" - ln -s "/usr/lib/gcc/$MULTIARCH_TRIPLET/${{matrix.gcc_toolchain}}" "$GCC_TOOLCHAIN_ROOT/lib/gcc/$MULTIARCH_TRIPLET/${{matrix.gcc_toolchain}}" - - - name: Setup multiarch - if: matrix.multiarch - run: | - sudo apt-get install --no-install-recommends -y binfmt-support qemu-user-static - sudo docker run --rm --privileged multiarch/qemu-user-static --reset -p yes - git clone https://github.com/jeking3/bdde.git - echo "$(pwd)/bdde/bin/linux" >> ${GITHUB_PATH} - echo "BDDE_DISTRO=${{ matrix.distro }}" >> ${GITHUB_ENV} - echo "BDDE_EDITION=${{ matrix.edition }}" >> ${GITHUB_ENV} - echo "BDDE_ARCH=${{ matrix.arch }}" >> ${GITHUB_ENV} - echo "B2_WRAPPER=bdde" >> ${GITHUB_ENV} - - - name: Setup Boost - env: - B2_ADDRESS_MODEL: ${{matrix.address-model}} - B2_COMPILER: ${{matrix.compiler}} - B2_CXXSTD: ${{matrix.cxxstd}} - B2_SANITIZE: ${{matrix.sanitize}} - B2_STDLIB: ${{matrix.stdlib}} - # More entries can be added in the same way, see the B2_ARGS assignment in ci/enforce.sh for the possible keys. - # B2_DEFINES: ${{matrix.defines}} - # Variables set here (to non-empty) will override the top-level environment variables, e.g. - # B2_VARIANT: ${{matrix.variant}} - # Set the (B2) target(s) to build, defaults to the test folder of the current library - # Can alternatively be done like this in the build step or in the build command of the build step, e.g. `run: B2_TARGETS=libs/$SELF/doc ci/build.sh` - # B2_TARGETS: libs/foo/test//bar - run: source ci/github/install.sh - - - name: Setup coverage collection - if: matrix.coverage - run: ci/github/codecov.sh "setup" - - - name: Run tests - if: '!matrix.coverity' - run: ci/build.sh - - - name: Upload coverage - if: matrix.coverage - run: ci/codecov.sh "upload" - env: - BOOST_CI_CODECOV_IO_UPLOAD: skip - - - name: Upload coverage - if: matrix.coverage - uses: codecov/codecov-action@v4 - with: - disable_search: true - file: coverage.info - name: Github Actions - token: ${{secrets.CODECOV_TOKEN}} - verbose: true diff --git a/external_codes/boost_multi/multi/.github/workflows/pull_request_template.md b/external_codes/boost_multi/multi/.github/workflows/pull_request_template.md new file mode 100644 index 0000000000..cb76161811 --- /dev/null +++ b/external_codes/boost_multi/multi/.github/workflows/pull_request_template.md @@ -0,0 +1,2 @@ +[![gitlab](https://gitlab.com/correaa/boost-multi/badges/constexpr-fill/pipeline.svg)](https://gitlab.com/correaa/boost-multi/-/pipelines) +https://gitlab.com/correaa/boost-multi diff --git a/external_codes/boost_multi/multi/.gitignore b/external_codes/boost_multi/multi/.gitignore index ed96246007..4ce3855eeb 100644 --- a/external_codes/boost_multi/multi/.gitignore +++ b/external_codes/boost_multi/multi/.gitignore @@ -1,6 +1,7 @@ build* .build* .vscode +.cache/clangd/* # Prerequisites *.d diff --git a/external_codes/boost_multi/multi/.gitlab-ci.yml b/external_codes/boost_multi/multi/.gitlab-ci.yml index f49ad2478e..52a68d9223 100644 --- a/external_codes/boost_multi/multi/.gitlab-ci.yml +++ b/external_codes/boost_multi/multi/.gitlab-ci.yml @@ -7,19 +7,25 @@ # sudo apt-get install gitlab-runner image: debian:stable +# image: npneq/debian_inq_deps:bookworm workflow: auto_cancel: on_new_commit: interruptible + rules: + - if: $CI_COMMIT_TAG + - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH + - if: $CI_PIPELINE_SOURCE == 'merge_request_event' + +# https://stackoverflow.com/a/78636529/225186 variables: GIT_SUBMODULE_STRATEGY: recursive CODECOV_TOKEN: "999feb5b-a599-4d02-b9c5-46d977247f3a" RT_VERSION: "0.1" - NVIDIA_DISABLE_REQUIRE: 1 + NVIDIA_DISABLE_REQUIRE: 1 # disable nvidia driver check SONAR_USER_HOME: "${CI_PROJECT_DIR}/.sonar" # Defines the location of the analysis task cache GIT_DEPTH: "0" # Tells git to fetch all the branches of the project, required by the analysis task - msbuild: 'C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\MSBuild\Current\Bin\MSBuild.exe' g++: # debian-stable: default is gcc 12.2.0 as of April 2024 stage: build @@ -27,81 +33,47 @@ g++: # debian-stable: default is gcc 12.2.0 as of April 2024 tags: - non-shared script: - - apt-get -qq update && apt-get -qq install --no-install-recommends -y --quiet ca-certificates cmake g++ make libboost-test-dev libboost-timer-dev libboost-serialization-dev libblas-dev liblapack-dev libfftw3-dev pkg-config + - apt-get -qq update && apt-get -qq install --no-install-recommends -y --quiet ca-certificates cmake g++ make libboost-timer-dev libboost-serialization-dev libblas-dev liblapack-dev libfftw3-dev pkg-config - g++ --version - mkdir build && cd build - - cmake .. -DCMAKE_BUILD_TYPE=Debug -DBOOST_MULTI_STANDALONE=1 -DBUILD_TESTING=0 -DCMAKE_CXX_FLAGS="-D_GLIBCXX_DEBUG=1" + - cmake .. -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_FLAGS="-D_GLIBCXX_DEBUG=1" - cmake --build . --parallel 2 || cmake --build . --verbose - ctest -j 2 --output-on-failure -T Test -g++-m32: +g++-m32 sanitize: stage: build image: debian:latest tags: - non-shared - - high-bandwidth + - high-bandwidth # for boost source download + - x86_64 # for g++-multilib in image interruptible: true script: - - apt-get -qq update && apt-get -qq install --no-install-recommends -y --quiet ca-certificates g++ g++-multilib cmake make tar wget - - wget https://downloads.sourceforge.net/project/boost/boost/1.84.0/boost_1_84_0.tar.gz --no-verbose # 1.70 doesn't install boost timer well, there is no version 1.71 in sourceforge - - tar -xf boost_1_84_0.tar.gz - - cd boost_1_84_0 - - ./bootstrap.sh - - ./b2 cxxflags=-m32 --with-serialization --with-test --with-timer install -j4 # libc++ only works with boost test compiled with libc++ - - cd .. + - dpkg --add-architecture i386 + - apt-get -qq update + - apt-get -qq install --no-install-recommends -y --quiet ca-certificates g++ g++-multilib cmake libboost-serialization-dev:i386 make tar wget - mkdir build && cd build - c++ --version - - cmake .. -DCMAKE_BUILD_TYPE=Debug -DBOOST_MULTI_STANDALONE=1 -DBUILD_TESTING=0 -DCMAKE_CXX_FLAGS="-m32" - - cmake --build . - - ctest -j 2 --output-on-failure - needs: ["g++"] - -g++-10: - stage: build - image: ubuntu:20.04 - tags: - - high-bandwidth - interruptible: true - script: - - apt-get -qq update && apt-get -qq install --no-install-recommends -y --quiet ca-certificates g++-10 cmake libboost-test-dev libboost-timer-dev libboost-serialization-dev make tar wget # linux-libc-dev:i386 - - mkdir build && cd build - - g++-10 --version - - CXX=g++-10 cmake .. -DCMAKE_BUILD_TYPE=Debug # -DCMAKE_CXX_FLAGS="-m32" + - cmake .. -DCMAKE_CXX_FLAGS="-m32 -fsanitize=address -D_GLIBCXX_SANITIZE_VECTOR" -DCMAKE_BUILD_TYPE=Debug - cmake --build . - - ctest -j 2 --output-on-failure + - ctest -j 1 --output-on-failure needs: ["g++"] -clang++-9: - stage: build - image: ubuntu:20.04 - tags: - - non-shared - - high-bandwidth - interruptible: true - script: - - apt-get -qq update && apt-get -qq install --no-install-recommends -y --quiet ca-certificates clang-9 cmake libboost-test-dev libboost-timer-dev libboost-serialization-dev make tar wget - - mkdir build && cd build - - clang++-9 --version - - CXX=clang++-9 cmake .. -DCMAKE_BUILD_TYPE=Debug - - cmake --build . - - ctest -j 2 --output-on-failure - needs: ["clang++"] - -clang++-11: +arm64: stage: build - image: ubuntu:22.04 + image: arm64v8/debian:latest tags: - non-shared - - high-bandwidth + - arm # for image interruptible: true script: - - apt-get -qq update && apt-get -qq install --no-install-recommends -y --quiet ca-certificates clang-11 cmake libboost-test-dev libboost-timer-dev libboost-serialization-dev make tar wget + - apt-get -qq update && apt-get -qq install --no-install-recommends -y --quiet ca-certificates g++ cmake make libblas-dev liblapack-dev libboost-timer-dev libboost-serialization-dev libopenmpi-dev pkg-config libfftw3-dev tar wget - mkdir build && cd build - - clang++-11 --version - - CXX=clang++-11 cmake .. -DCMAKE_BUILD_TYPE=Debug + - c++ --version + - cmake .. -DCMAKE_BUILD_TYPE=Debug - cmake --build . - - ctest -j 2 --output-on-failure - needs: ["clang++"] + - OMPI_ALLOW_RUN_AS_ROOT=1 OMPI_ALLOW_RUN_AS_ROOT_CONFIRM=1 ctest -j 2 --output-on-failure + needs: ["g++"] coverage: stage: build @@ -111,9 +83,9 @@ coverage: allow_failure: true interruptible: true script: - - apt-get -qq update && apt-get -qq install --no-install-recommends -y --quiet ca-certificates cmake curl g++ gcovr git make lcov libboost-test-dev libboost-timer-dev libboost-serialization-dev libblas-dev libfftw3-dev pkg-config wget + - apt-get -qq update && apt-get -qq install --no-install-recommends -y --quiet ca-certificates cmake curl g++ gcovr git make lcov libboost-timer-dev libboost-serialization-dev libblas-dev libfftw3-dev pkg-config wget - mkdir build && cd build - - cmake .. -DCMAKE_BUILD_TYPE=Debug -DBOOST_MULTI_STANDALONE=1 -DBUILD_TESTING=0 -DCMAKE_CXX_FLAGS="-DNDEBUG --coverage -O0 -fno-inline -fno-inline-small-functions -fno-default-inline" -DCMAKE_EXE_LINKER_FLAGS="--coverage" + - cmake .. -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_FLAGS="--coverage -O0 -fno-inline -fno-inline-small-functions -fno-default-inline" -DCMAKE_EXE_LINKER_FLAGS="--coverage" - cmake --build . --parallel 2 || cmake --build . --verbose - ctest -j 1 --output-on-failure -T Test - ctest -j 1 --output-on-failure -T Coverage @@ -135,38 +107,56 @@ coverage: g++ cppcheck cpplint memcheck: # debian-stable: gcc 12 as of Dec 2023 stage: build - allow_failure: true + allow_failure: false interruptible: true tags: - non-shared - docker script: - - apt-get -qq update && apt-get -qq install --no-install-recommends -y --quiet ca-certificates cmake cppcheck cpplint g++ make libboost-test-dev libboost-timer-dev libboost-serialization-dev libblas-dev libfftw3-dev pkg-config valgrind + - apt-get -qq update && apt-get -qq install --no-install-recommends -y --quiet ca-certificates cmake cppcheck cpplint g++ make libboost-timer-dev libboost-serialization-dev libblas-dev libfftw3-dev liblapack-dev libmpich-dev pkg-config valgrind - g++ --version - cpplint --version - cppcheck --version - valgrind --version - mkdir build && cd build - - export VALGRIND_EXE="valgrind --leak-check=full --track-origins=yes --show-leak-kinds=all --suppressions=.valgrind_suppressions --gen-suppressions=all --error-exitcode=1 " + - export VALGRIND_EXE="valgrind --trace-children=yes --leak-check=full --track-origins=yes --show-leak-kinds=all --suppressions=.valgrind-suppressions --gen-suppressions=all --error-exitcode=1 " - cmake .. -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_CPPLINT="cpplint;--quiet" -DCMAKE_CXX_CPPCHECK="cppcheck;--enable=all;--suppress=missingIncludeSystem;--inline-suppr;--std=c++17;--check-config;--error-exitcode=1" - cmake --build . --parallel 2 || cmake --build . --verbose - - ctest -j 2 --output-on-failure -T memcheck + - export OMPI_ALLOW_RUN_AS_ROOT=1 + - export OMPI_ALLOW_RUN_AS_ROOT_CONFIRM=1 + - ctest -j 2 --output-on-failure -T memcheck || ctest --verbose --output-on-failure --rerun-failed -T memcheck needs: ["g++"] -g++-testing sanitizer: - stage: build - tags: - - non-shared - - docker - image: debian:testing - interruptible: true - script: - - apt-get -qq update && apt-get -qq install --no-install-recommends -y --quiet ca-certificates cmake g++ make libboost-test-dev libboost-timer-dev libboost-serialization-dev libblas-dev libfftw3-dev pkg-config - - mkdir build && cd build - - cmake .. -DCMAKE_BUILD_TYPE=Debug -DBOOST_MULTI_STANDALONE=1 -DBUILD_TESTING=0 -DCMAKE_CXX_FLAGS="-fsanitize=address" -fno-omit-frame-pointer # ,undefined,pointer-compare,pointer-subtract,float-divide-by-zero -fno-omit-frame-pointer -fno-sanitize-recover=all" - - cmake --build . --parallel 2 || cmake --build . --verbose - - ASAN_OPTIONS="new_delete_type_mismatch=true:check_initialization_order=true:strict_init_order=true:detect_stack_use_after_return=true:detect_odr_violation=true" ctest -j 2 --output-on-failure -T Test - needs: ["g++"] +# clang++ sanitizer: +# stage: build +# tags: +# - non-shared +# - docker +# # image: debian:testing +# allow_failure: true +# interruptible: true +# script: +# - apt-get -qq update && apt-get -qq install --no-install-recommends -y --quiet ca-certificates cmake clang make libasan8 libasan6 libclang-rt-dev libboost-timer-dev libboost-serialization-dev libblas-dev libfftw3-dev pkg-config +# - mkdir build && cd build +# - CXX=clang++ cmake .. -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_FLAGS="-fsanitize=address -fno-omit-frame-pointer" # ,undefined,pointer-compare,pointer-subtract,float-divide-by-zero -fno-omit-frame-pointer -fno-sanitize-recover=all" +# - cmake --build . --parallel 2 || cmake --build . --verbose +# - ctest -j 2 --output-on-failure -T Test +# needs: ["clang++"] + +# g++ sanitizer: +# stage: build +# # image: debian:testing +# tags: +# - non-shared +# - docker +# interruptible: true +# script: +# - apt-get -qq update && apt-get -qq install --no-install-recommends -y --quiet ca-certificates cmake g++ make libboost-timer-dev libboost-serialization-dev libblas-dev libfftw3-dev pkg-config +# - mkdir build && cd build +# - cmake .. -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_FLAGS="-fsanitize=address,undefined,pointer-compare,pointer-subtract,float-divide-by-zero -fno-sanitize-recover=all" +# - cmake --build . --parallel 2 || cmake --build . --verbose +# - ctest -j 2 --output-on-failure -T Test +# needs: ["g++"] g++-7: stage: build @@ -176,49 +166,19 @@ g++-7: - docker interruptible: true script: - - apt-get -qq update && apt-get -qq install --no-install-recommends -y --quiet ca-certificates cmake g++-7 make libboost-test-dev libboost-timer-dev libboost-serialization-dev libblas-dev libfftw3-dev pkg-config wget - - wget https://github.com/Kitware/CMake/releases/download/v3.27.0-rc3/cmake-3.27.0-rc3-linux-x86_64.sh --no-verbose - - sh ./cmake-3.27.0-rc3-linux-x86_64.sh --skip-license --prefix=/usr + - arch + - apt-get -qq update && apt-get -qq install --no-install-recommends -y --quiet ca-certificates cmake g++-7 make libboost-serialization-dev libblas-dev libfftw3-dev libopenmpi-dev pkg-config wget + - wget https://github.com/Kitware/CMake/releases/download/v3.27.0-rc3/cmake-3.27.0-rc3-linux-`arch`.sh --no-verbose + - sh ./cmake-*.sh --skip-license --prefix=/usr - cmake --version - g++-7 --version - mkdir build && cd build - - CXX=g++-7 CXXFLAGS="-DBOOST_TEST_MAIN -DBOOST_TEST_DYN_LINK" cmake .. -DBOOST_MULTI_STANDALONE=1 -DBUILD_TESTING=0 -DCMAKE_BUILD_TYPE=Debug - - cmake --build . --parallel 2 || cmake --build . --verbose - - ctest -j 2 --output-on-failure -T Test - needs: ["g++"] - -g++-testing c++20: - stage: build - image: debian:testing - tags: - - non-shared - - docker - interruptible: true - script: - - apt-get -qq update && apt-get -qq install --no-install-recommends -y --quiet g++ pkg-config cmake make libboost-test-dev libboost-timer-dev libboost-serialization-dev libblas-dev libfftw3-dev - - mkdir build && cd build - - cmake .. -DCMAKE_BUILD_TYPE=Debug -DBOOST_MULTI_STANDALONE=1 -DBUILD_TESTING=0 -DCMAKE_CXX_STANDARD=20 + - CXX=g++-7 cmake .. -DCMAKE_BUILD_TYPE=Debug -DDISABLE_MPI=ON - cmake --build . --parallel 2 || cmake --build . --verbose - - ctest --output-on-failure + - ctest -j 2 --output-on-failure needs: ["g++"] -g++-13 c++23 par: # debian-testing: default is gcc 13.2.0 as of Dec 2023 - stage: build - image: debian:unstable - tags: - - non-shared - - docker - interruptible: true - script: - - apt-get -qq update && apt-get -qq install --no-install-recommends -y --quiet g++ g++-14 pkg-config cmake make libboost-test-dev libboost-timer-dev libboost-serialization-dev libblas-dev libfftw3-dev libtbb-dev - - mkdir build && cd build - - g++-13 --version - - CXX=g++-13 cmake .. -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_STANDARD=23 - - cmake --build . --parallel 2 || cmake --build . --verbose - - ctest --output-on-failure - needs: ["g++-testing c++20"] - -g++-14 c++23 par: # debian-testing: default is gcc 13.2.0 as of Dec 2023 +g++-unstable c++23 par: # debian-testing: default is gcc 14.2.0 as of Sep 2022 stage: build image: debian:unstable tags: @@ -227,12 +187,12 @@ g++-14 c++23 par: # debian-testing: default is gcc 13.2.0 as of Dec 2023 allow_failure: true interruptible: true script: - - apt-get -qq update && apt-get -qq install --no-install-recommends -y --quiet g++ g++-14 pkg-config cmake make libboost-test-dev libboost-timer-dev libboost-serialization-dev libblas-dev libfftw3-dev libtbb-dev + - apt-get -qq update && apt-get -qq install --no-install-recommends -y --quiet g++ pkg-config cmake make libboost-timer-dev libboost-serialization-dev libblas-dev libfftw3-dev libopenmpi-dev libtbb-dev - mkdir build && cd build - - g++-14 --version - - CXX=g++-14 cmake .. -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_STANDARD=23 + - g++ --version + - CXX=g++ cmake .. -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_STANDARD=23 -DCMAKE_CXX_FLAGS="-fimplicit-constexpr" - cmake --build . --parallel 2 || cmake --build . --verbose - - ctest --output-on-failure + - OMPI_ALLOW_RUN_AS_ROOT=1 OMPI_ALLOW_RUN_AS_ROOT_CONFIRM=1 ctest --output-on-failure needs: ["g++-testing c++20"] clang++: @@ -241,17 +201,17 @@ clang++: - non-shared interruptible: false script: - - apt-get -qq update && apt-get -qq install --no-install-recommends -y --quiet clang cmake make libboost-test-dev libboost-timer-dev libboost-serialization-dev libblas-dev libfftw3-dev pkg-config + - apt-get -qq update && apt-get -qq install --no-install-recommends -y --quiet clang cmake make libboost-timer-dev libboost-serialization-dev libblas-dev libfftw3-dev liblapack-dev pkg-config - mkdir build && cd build - clang++ --version - - CXX=clang++ cmake .. -DCMAKE_BUILD_TYPE=Debug -DBOOST_MULTI_STANDALONE=1 -DBUILD_TESTING=0 -DCMAKE_CXX_FLAGS="-D_GLIBCXX_DEBUG=1" - - cmake --build . --parallel 2 || cmake --build . --verbose + - CXX=clang++ cmake .. -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_FLAGS="-D_GLIBCXX_DEBUG=1" + - cmake --build . --parallel 2 || cmake --build . --parallel 1 --verbose - ctest -j 2 --output-on-failure # deb: # stage: build # script: -# - apt-get -qq update && apt-get -qq install --no-install-recommends -y --quiet ca-certificates cmake g++ make libboost-test-dev libboost-timer-dev libboost-serialization-dev libblas-dev libfftw3-dev pkg-config +# - apt-get -qq update && apt-get -qq install --no-install-recommends -y --quiet ca-certificates cmake g++ make libboost-timer-dev libboost-serialization-dev libblas-dev libfftw3-dev pkg-config # - mkdir build && cd build # - cmake .. -DCMAKE_BUILD_TYPE=Release # - cmake --build . --parallel 2 || cmake --build . --verbose @@ -275,13 +235,13 @@ clang++-latest libc++: - high-bandwidth interruptible: true script: - - apt-get -qq update && apt-get -qq install --no-install-recommends -y --quiet ca-certificates clang cmake make libblas-dev libc++-dev libc++abi-dev libfftw3-dev pkg-config tar wget - - wget https://downloads.sourceforge.net/project/boost/boost/1.72.0/boost_1_72_0.tar.gz --no-verbose # 1.70 doesn't install boost timer well, there is no version 1.72 in sourceforge - - tar -xf boost_1_72_0.tar.gz - - cd boost_1_72_0 - - ./bootstrap.sh --with-toolset=clang - - ./b2 toolset=clang cxxflags=-stdlib=libc++ linkflags=-stdlib=libc++ --with-serialization --with-test --with-timer install -j4 # libc++ only works with boost test compiled with libc++ - - cd .. + - apt-get -qq update && apt-get -qq install --no-install-recommends -y --quiet ca-certificates clang cmake make libboost-timer-dev libboost-serialization-dev libblas-dev libc++-dev libc++abi-dev libfftw3-dev liblapack-dev pkg-config tar wget + # - wget https://downloads.sourceforge.net/project/boost/boost/1.72.0/boost_1_72_0.tar.gz --no-verbose # 1.70 doesn't install boost timer well + # - tar -xf boost_1_72_0.tar.gz + # - cd boost_1_72_0 + # - ./bootstrap.sh --with-toolset=clang + # - ./b2 toolset=clang cxxflags=-stdlib=libc++ linkflags=-stdlib=libc++ --with-serialization --with-timer install -j4 # libc++ only works with boost test compiled with libc++ + # - cd .. - mkdir build && cd build - clang++ --version - CXX=clang++ cmake .. -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_FLAGS="-stdlib=libc++ -DBOOST_NO_CXX98_FUNCTION_BASE -D_LIBCPP_ENABLE_CXX17_REMOVED_AUTO_PTR -D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_DEBUG" @@ -289,27 +249,103 @@ clang++-latest libc++: - ctest -j 2 --output-on-failure needs: ["clang++"] -# build_windows: +# - name: Install vcpkg +# run: | +# git clone https://github.com/microsoft/vcpkg.git +# .\vcpkg\bootstrap-vcpkg.bat + +# - name: Install Boost +# run: .\vcpkg\vcpkg install boost-multi-array boost-timer boost-serialization + +# - name: Set up Boost environment variables +# run: | +# echo "BOOST_ROOT=$(Get-Location)\vcpkg\installed\x64-windows" >> $env:GITHUB_ENV +# echo "BOOST_INCLUDEDIR=$(Get-Location)\vcpkg\installed\x64-windows\include" >> $env:GITHUB_ENV +# echo "BOOST_LIBRARYDIR=$(Get-Location)\vcpkg\installed\x64-windows\lib" >> $env:GITHUB_ENV +# echo "PATH=$(Get-Location)\vcpkg\installed\x64-windows\bin;$env:PATH" >> $env:GITHUB_ENV + +# - name: Configure CMake +# run: cmake -S . -B build -A x64 -DCMAKE_TOOLCHAIN_FILE=.\vcpkg\scripts\buildsystems\vcpkg.cmake -DBOOST_ROOT=.\vcpkg\installed\x64-windows + +vs2019-windows: + stage: build + only: + refs: + - master + allow_failure: true + interruptible: true + variables: + BOOST_ROOT: ${CI_PROJECT_DIR}/vcpkg/installed/x64-windows + # BOOST_INCLUDEDIR: ${CI_PROJECT_DIR}/vcpkg/installed/x64-windows/include + # BOOST_LIBRARYDIR: ${CI_PROJECT_DIR}/vcpkg/installed/x64-windows/lib + script: + - choco --version + - choco install -y visualstudio2019community poshgit + - git clone --depth=1 https://github.com/microsoft/vcpkg.git + - .\vcpkg\bootstrap-vcpkg.bat + - .\vcpkg\vcpkg install boost-multi-array boost-timer + - mkdir build + - cmake --version + - cmake -S . -B build -DCMAKE_CXX_STANDARD=23 + - cmake --build build --config Release --parallel 2 --verbose + - $env:Path += ";${CI_PROJECT_DIR}/vcpkg/installed/x64-windows/bin" + - ctest --test-dir build --output-on-failure -C Release + tags: + - saas-windows-medium-amd64 + needs: ["clang++", "g++"] + timeout: 30 minutes + +# vs2022-windows: # stage: build # allow_failure: true # script: -# - '& "$msbuild" -help' -# - '& "$msbuild" -version' -# - choco install -y cmake -# - $env:Path += ';C:\Program Files\CMake\bin' +# # - choco --version +# # - choco upgrade -y chocolatey +# - choco --version +# - choco install -y visualstudio2022community +# - choco install -y boost-msvc-14.2 --version 1.74.0 # --params "/StaticBuild" +# - mkdir build # - cmake --version +# - cmake -S . -B build -DCMAKE_BUILD_TYPE=Release -A x64 # -DBOOST_ROOT="C:\local\boost_1_74_0" -DBOOST_LIBRARYDIR="C:\local\boost_1_74_0\lib64-msvc-14.2" # c:/local/boost_1_74_0/lib64-msvc-14.2 +# - cmake --build build --config Release +# - $env:Path += ';C:\local\boost_1_74_0\lib64-msvc-14.2' # C:\local\boost_1_74_0; ;C:\Program Files\CMake\bin +# - ctest --test-dir build --output-on-failure -C Release # tags: -# - shared-windows -# - windows -# - windows-1809 +# - saas-windows-medium-amd64 +# timeout: 30 # minutes +# # rules: +# # - if: '$CI_PIPELINE_SOURCE == "merge_request_event"' +# needs: ["vs2019-windows"] + +# vs2017-windows: +# stage: build +# allow_failure: true +# script: +# - choco --version +# - choco install -y visualstudio2017community +# - choco install -y boost-msvc-14.2 --version 1.74.0 # --params "/StaticBuild" +# - mkdir build +# - cmake --version +# - cmake -S . -B build -DCMAKE_BUILD_TYPE=Release -A x64 # -DBOOST_ROOT="C:\local\boost_1_74_0" -DBOOST_LIBRARYDIR="C:\local\boost_1_74_0\lib64-msvc-14.2" # c:/local/boost_1_74_0/lib64-msvc-14.2 +# - cmake --build build --config Release +# - $env:Path += ';C:\local\boost_1_74_0\lib64-msvc-14.2' # C:\local\boost_1_74_0; ;C:\Program Files\CMake\bin +# - ctest --test-dir build --output-on-failure -C Release +# tags: +# - saas-windows-medium-amd64 +# # rules: +# # - if: '$CI_PIPELINE_SOURCE == "merge_request_event"' +# needs: ["vs2019-windows"] # clang++-macos: +# interruptible: true # stage: build -# image: macos-14-xcode-15 -# # variables: -# # HOMEBREW_NO_AUTO_UPDATE: 1 +# # image: macos-14-xcode-15 +# # variables: +# # HOMEBREW_NO_AUTO_UPDATE: 1 # tags: -# - saas-macos-medium-m1 +# - shared-macos-amd64 +# # - saas-macos-medium-m1 +# # - saas-macos-large-m2pro # allow_failure: true # script: # #- apt-get -qq update && apt-get -qq install --no-install-recommends -y --quiet ca-certificates clang cmake make libblas-dev libc++-dev libc++abi-dev libfftw3-dev pkg-config tar wget @@ -321,7 +357,7 @@ clang++-latest libc++: # #- cd .. # - mkdir build && cd build # - c++ --version -# - CXX=c++ cmake .. -DCMAKE_BUILD_TYPE=Debug -DBOOST_MULTI_STANDALONE=1 -DBUILD_TESTING=0 # -DCMAKE_CXX_FLAGS="-stdlib=libc++ -DBOOST_NO_CXX98_FUNCTION_BASE -D_LIBCPP_ENABLE_CXX17_REMOVED_AUTO_PTR -D_LIBCPP_ENABLE_DEBUG_MODE=1 -D_LIBCPP_DEBUG_RANDOMIZE_UNSPECIFIED_STABILITY=1 -D_LIBCPP_DEBUG_STRICT_WEAK_ORDERING_CHECK=1" +# - CXX=c++ cmake .. -DCMAKE_BUILD_TYPE=Debug # -DCMAKE_CXX_FLAGS="-stdlib=libc++ -DBOOST_NO_CXX98_FUNCTION_BASE -D_LIBCPP_ENABLE_CXX17_REMOVED_AUTO_PTR -D_LIBCPP_ENABLE_DEBUG_MODE=1 -D_LIBCPP_DEBUG_RANDOMIZE_UNSPECIFIED_STABILITY=1 -D_LIBCPP_DEBUG_STRICT_WEAK_ORDERING_CHECK=1" # - cmake --build . # - ctest -j 2 --output-on-failure # needs: ["clang++"] @@ -330,36 +366,34 @@ clang++-m32: stage: build image: debian:latest tags: - - high-bandwidth + - non-shared + - high-bandwidth # for boost source download + - x86_64 # for g++-multilib in image interruptible: true script: - - apt-get -qq update && apt-get -qq install --no-install-recommends -y --quiet ca-certificates clang g++ g++-multilib cmake make tar wget - - wget https://downloads.sourceforge.net/project/boost/boost/1.84.0/boost_1_84_0.tar.gz --no-verbose # 1.70 doesn't install boost timer well, there is no version 1.71 in sourceforge - - tar -xf boost_1_84_0.tar.gz - - cd boost_1_84_0 - - ./bootstrap.sh --with-toolset=clang - - ./b2 toolset=clang cxxflags=-m32 --with-serialization --with-test --with-timer install -j4 # libc++ only works with boost test compiled with libc++ - - cd .. + - dpkg --add-architecture i386 + - apt-get -qq update && apt-get -qq install --no-install-recommends -y --quiet ca-certificates clang g++ g++-multilib git cmake make libboost-serialization-dev:i386 tar wget - mkdir build && cd build - c++ --version - - CXX=clang++ cmake .. -DCMAKE_BUILD_TYPE=Debug -DBOOST_MULTI_STANDALONE=1 -DBUILD_TESTING=0 -DCMAKE_CXX_FLAGS="-m32" + - CXX=clang++ cmake .. -DCMAKE_CXX_FLAGS="-m32" -DCMAKE_BUILD_TYPE=Debug - cmake --build . - ctest -j 2 --output-on-failure needs: ["clang++"] -clang++-testing tidy: +clang++-latest tidy iwyu: stage: build - image: debian:unstable # clang 18 as of Apr 2024 + image: debian:latest # clang 18 as of Apr 2024 tags: - non-shared - docker interruptible: true script: - - apt-get -qq update && apt-get -qq install --no-install-recommends -y --quiet clang-18 clang-tidy-18 cmake make libboost-test-dev libboost-timer-dev libboost-serialization-dev libblas-dev libfftw3-dev pkg-config + - apt-get -qq update && apt-get -qq install --no-install-recommends -y --quiet clang clang-tidy cmake iwyu make libboost-timer-dev libboost-serialization-dev libblas-dev libfftw3-dev liblapack-dev pkg-config - mkdir build && cd build - - clang++-18 --version - - clang-tidy-18 --version - - CXX=clang++-18 cmake .. -DCMAKE_BUILD_TYPE=Debug -DBOOST_MULTI_STANDALONE=1 -DBUILD_TESTING=0 -DCMAKE_CXX_CLANG_TIDY=clang-tidy-18 + - clang++ --version + - clang-tidy --version + - iwyu --version + - CXX=clang++ cmake .. -DCMAKE_CXX_STANDARD=20 -DCMAKE_BUILD_TYPE=Debug -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DCMAKE_CXX_CLANG_TIDY=clang-tidy -DCMAKE_CXX_INCLUDE_WHAT_YOU_USE="iwyu;-Xiwyu;--mapping_file=$PWD/../.iwyu-test.imp;-Xiwyu;--no_fwd_decls;-Xiwyu;--error" - cmake --build . --parallel 2 || cmake --build . --verbose - ctest -j 2 --output-on-failure needs: ["clang++"] @@ -372,28 +406,13 @@ g++-testing c++20: - docker interruptible: true script: - - apt-get -qq update && apt-get -qq install --no-install-recommends -y --quiet g++ pkg-config cmake make libboost-test-dev libboost-timer-dev libboost-serialization-dev libblas-dev libfftw3-dev + - apt-get -qq update && apt-get -qq install --no-install-recommends -y --quiet g++ pkg-config cmake make libboost-timer-dev libboost-serialization-dev libblas-dev libfftw3-dev - mkdir build && cd build - - cmake .. -DCMAKE_BUILD_TYPE=Debug -DBOOST_MULTI_STANDALONE=1 -DBUILD_TESTING=0 -DCMAKE_CXX_STANDARD=20 + - cmake .. -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_STANDARD=20 -DCMAKE_CXX_FLAGS=-fimplicit-constexpr - cmake --build . --parallel 2 || cmake --build . --verbose - ctest --output-on-failure needs: ["g++"] -g++-testing sanitizer: - stage: build - image: debian:testing - tags: - - non-shared - - docker - interruptible: true - script: - - apt-get -qq update && apt-get -qq install --no-install-recommends -y --quiet ca-certificates cmake g++ make libboost-test-dev libboost-timer-dev libboost-serialization-dev libblas-dev libfftw3-dev pkg-config - - mkdir build && cd build - - cmake .. -DCMAKE_BUILD_TYPE=Debug -DBOOST_MULTI_STANDALONE=1 -DBUILD_TESTING=0 -DCMAKE_CXX_FLAGS="-fsanitize=address,undefined,pointer-compare,pointer-subtract,float-divide-by-zero -fno-sanitize-recover=all" - - cmake --build . --parallel 2 || cmake --build . --verbose - - ASAN_OPTIONS="new_delete_type_mismatch=0:check_initialization_order=true:strict_init_order=true:detect_stack_use_after_return=true:detect_odr_violation=1" ctest -j 2 --output-on-failure -T Test - needs: ["g++"] - clang++-17-unstable libc++ c++23 boost_1_84: stage: build image: debian:unstable # clang 17 as of March 2024 @@ -424,12 +443,13 @@ clang++-oldoldstable: - docker interruptible: true script: - - apt-get -qq update && apt-get -qq install --no-install-recommends -y --quiet ca-certificates clang cmake make libboost-test-dev libboost-timer-dev libboost-serialization-dev libblas-dev libfftw3-dev pkg-config wget - - wget https://github.com/Kitware/CMake/releases/download/v3.27.0-rc3/cmake-3.27.0-rc3-linux-x86_64.sh --no-verbose - - sh ./cmake-3.27.0-rc3-linux-x86_64.sh --skip-license --prefix=/usr + - arch + - apt-get -qq update && apt-get -qq install --no-install-recommends -y --quiet ca-certificates clang cmake make libboost-timer-dev libboost-serialization-dev libblas-dev libfftw3-dev pkg-config wget + - wget --no-verbose -O cmake-install.sh https://github.com/Kitware/CMake/releases/download/v3.30.0-rc4/cmake-3.30.0-rc4-linux-`arch`.sh # https://cmake.org/files/v3.18/cmake-3.18.0-rc1-Linux-`arch`.sh --no-verbose + - sh cmake-install.sh --skip-license --prefix=/usr - mkdir build && cd build - clang++ --version - - CXX=clang++ CXXFLAGS="-DBOOST_TEST_DYN_LINK" cmake .. -DCMAKE_BUILD_TYPE=Release -DBOOST_MULTI_STANDALONE=1 -DBUILD_TESTING=0 + - CXX=clang++ cmake .. -DCMAKE_BUILD_TYPE=Release - cmake --build . --parallel 2 || cmake --build . --verbose - ctest -j 2 --output-on-failure needs: ["clang++"] @@ -440,14 +460,15 @@ oneapi: tags: - non-shared - large-disk-space + - x86_64 interruptible: true script: - - apt-get update && apt-get install --no-install-recommends -y --quiet ca-certificates cmake curl libboost-test-dev libboost-serialization-dev libboost-timer-dev libblas-dev liblapack-dev libfftw3-dev make pkg-config + - apt-get update && apt-get install --no-install-recommends -y --quiet ca-certificates cmake curl libboost-serialization-dev libboost-timer-dev libblas-dev liblapack-dev libfftw3-dev make pkg-config - mkdir build && cd build - icpx --version - - CXX=icpx cmake .. -DCMAKE_BUILD_TYPE=Release -DBOOST_MULTI_STANDALONE=1 -DBUILD_TESTING=0 + - CXX=icpx cmake .. -DCMAKE_BUILD_TYPE=Release -DDISABLE_MPI=ON # Intel MPI doesn't work on CI - cmake --build . --parallel 2 || cmake --build . --verbose - - ctest --parallel 2 --output-on-failure + - ctest --output-on-failure oneapi-2022.2: stage: build @@ -455,14 +476,16 @@ oneapi-2022.2: tags: - non-shared - large-disk-space + - x86_64 + allow_failure: true interruptible: true script: - - apt-get update && apt-get install --no-install-recommends -y --quiet ca-certificates cmake curl g++ libboost-test-dev libboost-serialization-dev libboost-timer-dev libblas-dev liblapack-dev libfftw3-dev make pkg-config + - apt-get update && apt-get install --no-install-recommends -y --quiet ca-certificates cmake curl g++ libboost-serialization-dev libboost-timer-dev libblas-dev liblapack-dev libfftw3-dev make pkg-config - mkdir build && cd build - icpx --version - - CXX=icpx CXXFLAGS="-DPSTL_USE_PARALLEL_POLICIES=0" cmake .. -DCMAKE_BUILD_TYPE=Release + - CXX=icpx CXXFLAGS="-DPSTL_USE_PARALLEL_POLICIES=0" cmake .. -DCMAKE_BUILD_TYPE=Release -DDISABLE_MPI=ON # Intel MPI doesn't work on CI - cmake --build . --parallel 2 || cmake --build . --verbose - - ctest --parallel 2 --output-on-failure + - ctest --parallel 2 || ctest --verbose --rerun-failed --output-on-failure needs: ["oneapi"] oneapi-latest c++20: @@ -473,16 +496,17 @@ oneapi-latest c++20: - non-shared - large-disk-space - high-bandwidth + - x86_64 interruptible: true script: # - wget -O- https://apt.repos.intel.com/intel-gpg-keys/GPG-PUB-KEY-INTEL-SW-PRODUCTS.PUB | gpg --dearmor | tee /usr/share/keyrings/oneapi-archive-keyring.gpg > /dev/null # - echo "deb [signed-by=/usr/share/keyrings/oneapi-archive-keyring.gpg] https://apt.repos.intel.com/oneapi all main" | tee /etc/apt/sources.list.d/oneAPI.list - - apt-get update && apt-get install --no-install-recommends -y --quiet ca-certificates cmake curl g++ libboost-test-dev libboost-serialization-dev libboost-timer-dev libblas-dev liblapack-dev libfftw3-dev make pkg-config + - apt-get update && apt-get install --no-install-recommends -y --quiet ca-certificates cmake curl g++ libboost-serialization-dev libboost-timer-dev libblas-dev liblapack-dev libfftw3-dev make pkg-config - mkdir build && cd build - icpx --version - - CXX=icpx cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_STANDARD=20 + - CXX=icpx cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_STANDARD=20 -DDISABLE_MPI=ON # Intel MPI doesn't work on CI - cmake --build . --parallel 2 || cmake --build . --verbose - - ctest --parallel 2 --output-on-failure + - ctest --parallel 2 || ctest --verbose --rerun-failed --output-on-failure needs: ["oneapi"] nvhpc: @@ -491,15 +515,16 @@ nvhpc: tags: - non-shared - large-disk-space - interruptible: true + - x86_64 script: - - nvidia-smi - - apt-get update && apt-get install --no-install-recommends -y cmake make libboost-test-dev libboost-serialization-dev + - apt-get update && apt-get install --no-install-recommends -y cmake make libboost-serialization-dev - /opt/nvidia/hpc_sdk/Linux_x86_64/2022/compilers/bin/nvc++ --version - mkdir build && cd build - - CXX=/opt/nvidia/hpc_sdk/Linux_x86_64/2022/compilers/bin/nvc++ cmake .. -DBOOST_MULTI_STANDALONE=1 -DBUILD_TESTING=0 + - CXX=/opt/nvidia/hpc_sdk/Linux_x86_64/2022/compilers/bin/nvc++ cmake .. - cmake --build . --parallel 2 || cmake --build . --verbose - - ctest --output-on-failure + - export OMPI_ALLOW_RUN_AS_ROOT=1 + - export OMPI_ALLOW_RUN_AS_ROOT_CONFIRM=1 + - ctest --parallel 2 --output-on-failure || ctest --verbose --rerun-failed --output-on-failure nvhpc-22.7: stage: build @@ -507,78 +532,118 @@ nvhpc-22.7: tags: - non-shared - large-disk-space + - x86_64 interruptible: true script: - - nvidia-smi - - apt-get update && apt-get install --no-install-recommends -y cmake make libboost-test-dev libboost-timer-dev libboost-serialization-dev + - apt-get update && apt-get install --no-install-recommends -y cmake make libboost-timer-dev libboost-serialization-dev - /opt/nvidia/hpc_sdk/Linux_x86_64/2022/compilers/bin/nvc++ --version - mkdir build && cd build - - CXX=/opt/nvidia/hpc_sdk/Linux_x86_64/2022/compilers/bin/nvc++ cmake .. -DBOOST_MULTI_STANDALONE=1 -DBUILD_TESTING=0 # TODO(correaa) add -DCMAKE_BUILD_TYPE=Release + - CXX=/opt/nvidia/hpc_sdk/Linux_x86_64/2022/compilers/bin/nvc++ cmake .. # TODO(correaa) add -DCMAKE_BUILD_TYPE=Release - cmake --build . --parallel 2 || cmake --build . --verbose - - ctest --output-on-failure + - OMPI_ALLOW_RUN_AS_ROOT=1 OMPI_ALLOW_RUN_AS_ROOT_CONFIRM=1 ctest --output-on-failure needs: ["nvhpc"] -nvhpc-24.3 c++20 par: +# nvhpc-24.5 c++20 par: +# stage: build +# image: nvcr.io/nvidia/nvhpc:24.5-devel-cuda12.4-ubuntu22.04 # https://catalog.ngc.nvidia.com/orgs/nvidia/containers/nvhpc/tags +# tags: +# - non-shared +# - large-disk-space +# - x86_64 +# interruptible: true +# script: +# - apt-get update && apt-get install --no-install-recommends -y cmake make libboost-timer-dev libboost-serialization-dev libfftw3-dev pkg-config +# - /opt/nvidia/hpc_sdk/Linux_x86_64/2024/compilers/bin/nvc++ --version +# - mkdir build && cd build +# - CXX=/opt/nvidia/hpc_sdk/Linux_x86_64/2024/compilers/bin/nvc++ cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_STANDARD=20 -DCMAKE_CXX_FLAGS="-stdpar=multicore" +# - cmake --build . --parallel 2 || cmake --build . --verbose +# - OMPI_ALLOW_RUN_AS_ROOT=1 OMPI_ALLOW_RUN_AS_ROOT_CONFIRM=1 ctest --output-on-failure +# needs: ["nvhpc"] + +nvhpc-24.7 c++20 par: stage: build - image: nvcr.io/nvidia/nvhpc:24.3-devel-cuda12.3-ubuntu22.04 # https://catalog.ngc.nvidia.com/orgs/nvidia/containers/nvhpc/tags + image: nvcr.io/nvidia/nvhpc:24.7-devel-cuda12.5-ubuntu24.04 # https://catalog.ngc.nvidia.com/orgs/nvidia/containers/nvhpc/tags tags: - non-shared - large-disk-space + - x86_64 interruptible: true script: - - nvidia-smi - - apt-get update && apt-get install --no-install-recommends -y cmake make libboost-test-dev libboost-timer-dev libboost-serialization-dev libfftw3-dev pkg-config + - apt-get update && apt-get install --no-install-recommends -y cmake make libboost-timer-dev libboost-serialization-dev libfftw3-dev pkg-config - /opt/nvidia/hpc_sdk/Linux_x86_64/2024/compilers/bin/nvc++ --version - mkdir build && cd build - - CXX=/opt/nvidia/hpc_sdk/Linux_x86_64/2024/compilers/bin/nvc++ cmake .. -DCMAKE_BUILD_TYPE=Release -DBOOST_MULTI_STANDALONE=1 -DBUILD_TESTING=0 -DCMAKE_CXX_STANDARD=20 -DCMAKE_CXX_FLAGS="-stdpar=multicore" + - CXX=/opt/nvidia/hpc_sdk/Linux_x86_64/2024/compilers/bin/nvc++ cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_STANDARD=20 -DCMAKE_CXX_FLAGS="-stdpar=multicore" - cmake --build . --parallel 2 || cmake --build . --verbose - - ctest --output-on-failure + - OMPI_ALLOW_RUN_AS_ROOT=1 OMPI_ALLOW_RUN_AS_ROOT_CONFIRM=1 ctest --output-on-failure needs: ["nvhpc"] cuda: stage: build - image: nvcr.io/nvidia/cuda:11.8.0-devel-ubuntu22.04 + allow_failure: false + image: nvcr.io/nvidia/cuda:12.0.1-devel-ubuntu22.04 tags: - non-shared - nvidia-gpu interruptible: true script: - nvidia-smi - - apt-get -qq update && apt-get install --no-install-recommends -y cmake wget pkg-config make libboost-test-dev libboost-serialization-dev libboost-timer-dev libblas-dev libfftw3-dev + - apt-get -qq update && apt-get install --no-install-recommends -y cmake g++-12 wget pkg-config make libboost-serialization-dev libboost-timer-dev libblas-dev libfftw3-dev - mkdir build && cd build - - ls /usr/local - - ls /usr/local/cuda-11/bin - - /usr/local/cuda-11/bin/nvcc --version - - CUDACXX=/usr/local/cuda-11/bin/nvcc cmake .. -DCMAKE_BUILD_TYPE=Release -DENABLE_CUDA=1 -DCMAKE_CUDA_ARCHITECTURES=61 + - g++-12 --version + - /usr/local/cuda/bin/nvcc --version + - CUDACXX=/usr/local/cuda/bin/nvcc cmake .. -DCMAKE_BUILD_TYPE=Release -DENABLE_CUDA=1 -DCMAKE_CUDA_ARCHITECTURES=61 -DCMAKE_CUDA_HOST_COMPILER=g++-12 -DCMAKE_CUDA_FLAGS="-allow-unsupported-compiler" - cmake --build . --parallel 2 || cmake --build . --verbose - - ctest -j 2 --output-on-failure - - ../build/include/boost/multi/adaptors/thrust/test/speed.cu.x - - ../build/include/boost/multi/adaptors/thrust/test/speed_algo.cu.x - - ../build/include/boost/multi/adaptors/fftw/test/combinations.cpp.x + - ctest || ctest --rerun-failed --output-on-failure needs: ["g++"] -cuda-11.8 mkl: - stage: build - image: nvcr.io/nvidia/cuda:11.8.0-devel-ubuntu22.04 - tags: - - non-shared - - nvidia-gpu - interruptible: true - script: - - nvidia-smi - - apt-get -qq update && apt-get install --no-install-recommends -y cmake wget pkg-config make libboost-test-dev libboost-serialization-dev libboost-timer-dev libblas-dev libfftw3-dev - - DEBIAN_FRONTEND=interactive apt-get install --no-install-recommends --yes --force-yes -y libmkl-full-dev - - mkdir build && cd build - - ls /usr/local - - ls /usr/local/cuda-11/bin - - /usr/local/cuda-11/bin/nvcc --version - - CUDACXX=/usr/local/cuda-11/bin/nvcc cmake .. -DCMAKE_BUILD_TYPE=Release -DENABLE_CUDA=1 -DCMAKE_CUDA_ARCHITECTURES=61 - - cmake --build . --parallel 2 || cmake --build . --verbose - - ctest -j 2 --output-on-failure - - ../build/include/boost/multi/adaptors/thrust/test/speed.cu.x - - ../build/include/boost/multi/adaptors/thrust/test/speed_algo.cu.x - - ../build/include/boost/multi/adaptors/fftw/test/combinations.cpp.x - needs: ["cuda"] +# cuda-11.8: +# stage: build +# image: nvcr.io/nvidia/cuda:11.8.0-devel-ubuntu22.04 +# tags: +# - non-shared +# - nvidia-gpu +# interruptible: true +# script: +# - nvidia-smi +# - apt-get -qq update && apt-get install --no-install-recommends -y cmake wget pkg-config make libboost-serialization-dev libboost-timer-dev libblas-dev libfftw3-dev +# - mkdir build && cd build +# - ls /usr/local +# - ls /usr/local/cuda-11/bin +# - /usr/local/cuda-11/bin/nvcc --version +# - CUDACXX=/usr/local/cuda-11/bin/nvcc cmake .. -DCMAKE_BUILD_TYPE=Release -DENABLE_CUDA=1 -DCMAKE_CUDA_ARCHITECTURES=61 +# - cmake --build . --parallel 2 || cmake --build . --verbose +# - ctest -j 2 --output-on-failure +# # - ../build/include/boost/multi/adaptors/thrust/test/speed.cu.x +# # - ../build/include/boost/multi/adaptors/thrust/test/speed_algo.cu.x +# # - ../build/include/boost/multi/adaptors/fftw/test/combinations.cpp.x +# needs: ["cuda"] + +# cuda-11.8 mkl: +# stage: build +# image: nvcr.io/nvidia/cuda:11.8.0-devel-ubuntu22.04 +# tags: +# - non-shared +# - nvidia-gpu +# - high-bandwidth +# - x86_64 +# interruptible: true +# script: +# - nvidia-smi +# - apt-get -qq update && apt-get install --no-install-recommends -y cmake wget pkg-config make libboost-serialization-dev libboost-timer-dev libblas-dev libfftw3-dev +# - DEBIAN_FRONTEND=interactive apt-get install --no-install-recommends --yes --force-yes -y libmkl-full-dev +# - cmake --version +# - wget --no-verbose -O cmake-install.sh https://github.com/Kitware/CMake/releases/download/v3.27.0-rc3/cmake-3.27.0-rc3-linux-x86_64.sh +# - sh ./cmake-install.sh --skip-license --prefix=/usr +# - cmake --version +# - mkdir build && cd build +# - /usr/local/cuda-11/bin/nvcc --version +# - CUDACXX=/usr/local/cuda-11/bin/nvcc cmake .. -DCMAKE_BUILD_TYPE=Release -DENABLE_CUDA=1 -DCMAKE_CUDA_ARCHITECTURES=61 +# - cmake --build . --parallel 2 || cmake --build . --verbose +# - ctest -j 2 --output-on-failure +# # - ../build/include/boost/multi/adaptors/thrust/test/speed.cu.x +# # - ../build/include/boost/multi/adaptors/thrust/test/speed_algo.cu.x +# # - ../build/include/boost/multi/adaptors/fftw/test/combinations.cpp.x +# needs: ["cuda"] cuda-11.4.3: stage: build @@ -586,14 +651,15 @@ cuda-11.4.3: tags: - non-shared - nvidia-gpu + - x86_64 interruptible: true script: - nvidia-smi # - export CUDA_VISIBLE_DEVICES=2 - apt-get -qq update - - DEBIAN_FRONTEND=noninteractive apt-get install --no-install-recommends -y cmake wget pkg-config make libboost-test-dev libboost-serialization-dev libboost-timer-dev libblas-dev libfftw3-dev - - wget https://github.com/Kitware/CMake/releases/download/v3.27.0-rc3/cmake-3.27.0-rc3-linux-x86_64.sh --no-verbose - - sh ./cmake-3.27.0-rc3-linux-x86_64.sh --skip-license --prefix=/usr + - DEBIAN_FRONTEND=noninteractive apt-get install --no-install-recommends -y cmake wget pkg-config make libboost-serialization-dev libboost-timer-dev libblas-dev libfftw3-dev libtbb-dev + - wget --no-verbose -O cmake-install.sh https://github.com/Kitware/CMake/releases/download/v3.27.0-rc3/cmake-3.27.0-rc3-linux-x86_64.sh + - sh ./cmake-install.sh --skip-license --prefix=/usr - cmake --version - mkdir build && cd build - /usr/local/cuda/bin/nvcc --version @@ -602,7 +668,26 @@ cuda-11.4.3: - ctest -j 2 --output-on-failure needs: ["cuda"] -cuclang++-16 cuda-11.4.3: +# cuda-12.3.1: +# stage: build +# allow_failure: false +# image: nvcr.io/nvidia/cuda:12.3.1-devel-ubuntu22.04 +# tags: +# - non-shared +# - nvidia-gpu +# interruptible: true +# script: +# - nvidia-smi +# - apt-get -qq update && apt-get install --no-install-recommends -y cmake g++-12 wget pkg-config make libboost-serialization-dev libboost-timer-dev libblas-dev libfftw3-dev +# - mkdir build && cd build +# - g++-12 --version +# - /usr/local/cuda/bin/nvcc --version +# - CUDACXX=/usr/local/cuda/bin/nvcc cmake .. -DCMAKE_BUILD_TYPE=Release -DENABLE_CUDA=1 -DCMAKE_CUDA_ARCHITECTURES=61 -DCMAKE_CUDA_HOST_COMPILER=g++-12 -DCMAKE_CUDA_FLAGS="-allow-unsupported-compiler" +# - cmake --build . --parallel 2 || cmake --build . --verbose +# - ctest -j 2 || ctest --rerun-failed --output-on-failure +# needs: ["cuda"] + +culang++-16 cuda-11.4.3: stage: build image: nvcr.io/nvidia/cuda:11.4.3-devel-ubuntu20.04 tags: @@ -612,7 +697,7 @@ cuclang++-16 cuda-11.4.3: script: - nvidia-smi - apt-get -qq update - - DEBIAN_FRONTEND=noninteractive apt-get install --no-install-recommends -y cmake wget pkg-config make libboost-test-dev libboost-serialization-dev libboost-timer-dev libblas-dev libfftw3-dev + - DEBIAN_FRONTEND=noninteractive apt-get install --no-install-recommends -y cmake wget pkg-config make libboost-serialization-dev libboost-timer-dev libblas-dev libfftw3-dev - apt-get install --no-install-recommends -y lsb-release software-properties-common - wget https://github.com/Kitware/CMake/releases/download/v3.27.0-rc3/cmake-3.27.0-rc3-linux-x86_64.sh --no-verbose - sh ./cmake-3.27.0-rc3-linux-x86_64.sh --skip-license --prefix=/usr @@ -637,11 +722,15 @@ culang++-17 cuda-11.8: interruptible: true script: - nvidia-smi - - apt-get -qq update && apt-get install --no-install-recommends -y cmake wget pkg-config make libboost-test-dev libboost-serialization-dev libboost-timer-dev libblas-dev libfftw3-dev + - apt-get -qq update && apt-get install --no-install-recommends -y cmake wget pkg-config make libboost-serialization-dev libboost-timer-dev libblas-dev libfftw3-dev libtbb-dev - apt-get install --no-install-recommends -y lsb-release software-properties-common - wget https://apt.llvm.org/llvm.sh - chmod u+x llvm.sh - ./llvm.sh 17 + - cmake --version + - wget https://github.com/Kitware/CMake/releases/download/v3.27.0-rc3/cmake-3.27.0-rc3-linux-x86_64.sh --no-verbose + - sh ./cmake-3.27.0-rc3-linux-x86_64.sh --skip-license --prefix=/usr # for CMAKE_CUDA_STANDARD=20 + - cmake --version - mkdir build && cd build - clang++-17 --version - cmake .. -DCMAKE_BUILD_TYPE=Release -DBOOST_MULTI_STANDALONE=1 -DBUILD_TESTING=0 -DENABLE_CUDA=1 -DCMAKE_CUDA_COMPILER=clang++-17 -DCMAKE_CXX_COMPILER=clang++-17 @@ -660,37 +749,42 @@ culang++-19 cuda-12.1.1 tidy: interruptible: true script: - nvidia-smi - - apt-get -qq update && apt-get install --no-install-recommends -y cmake wget pkg-config make libboost-test-dev libboost-serialization-dev libboost-timer-dev libblas-dev libfftw3-dev + - apt-get -qq update && apt-get install --no-install-recommends -y cmake wget pkg-config make libboost-serialization-dev libboost-timer-dev libblas-dev libfftw3-dev - apt-get install --no-install-recommends -y lsb-release software-properties-common - wget https://apt.llvm.org/llvm.sh - chmod u+x llvm.sh - - ./llvm.sh 19 - - apt-get install --no-install-recommends -y clang-tidy-19 + - ./llvm.sh 18 + - apt-get install --no-install-recommends -y clang-tidy-18 - mkdir build && cd build - - clang++-19 --version - - clang-tidy-19 --version - - cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_CLANG_TIDY=clang-tidy-19 -DENABLE_CUDA=1 -DCMAKE_CUDA_COMPILER=clang++-19 -DCMAKE_CXX_COMPILER=clang++-19 + - clang++-18 --version + - clang-tidy-18 --version + - cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_CLANG_TIDY=clang-tidy-18 -DENABLE_CUDA=1 -DCMAKE_CUDA_COMPILER=clang++-18 -DCMAKE_CXX_COMPILER=clang++-18 - cmake --build . --parallel 2 || cmake --build . --verbose - ctest -j 2 --output-on-failure needs: ["cuda", "clang++"] -cuda-12.3.1: +cuda-12.5.0: stage: build - allow_failure: false - image: nvcr.io/nvidia/cuda:12.3.1-devel-ubuntu22.04 + allow_failure: true + image: nvcr.io/nvidia/cuda:12.5.0-devel-ubuntu22.04 tags: - non-shared - nvidia-gpu interruptible: true script: - nvidia-smi - - apt-get -qq update && apt-get install --no-install-recommends -y cmake g++-12 wget pkg-config make libboost-test-dev libboost-serialization-dev libboost-timer-dev libblas-dev libfftw3-dev + - apt-get -qq update + - apt-get install --no-install-recommends -y cmake g++ wget pkg-config make libboost-serialization-dev libboost-timer-dev libblas-dev libfftw3-dev + - cmake --version + - wget https://github.com/Kitware/CMake/releases/download/v3.27.0-rc3/cmake-3.27.0-rc3-linux-x86_64.sh --no-verbose + - sh ./cmake-3.27.0-rc3-linux-x86_64.sh --skip-license --prefix=/usr # for CMAKE_CUDA_STANDARD=20 + - cmake --version - mkdir build && cd build - - g++-12 --version + - g++ --version - /usr/local/cuda/bin/nvcc --version - - CUDACXX=/usr/local/cuda/bin/nvcc cmake .. -DCMAKE_BUILD_TYPE=Release -DENABLE_CUDA=1 -DCMAKE_CUDA_ARCHITECTURES=61 -DCMAKE_CUDA_HOST_COMPILER=g++-12 -DCMAKE_CUDA_FLAGS="-allow-unsupported-compiler" - - cmake --build . --parallel 2 || cmake --build . --verbose - - ctest || ctest --rerun-failed --output-on-failure || echo "ctest failed, probably due to lack of drivers" + - CUDACXX=/usr/local/cuda/bin/nvcc cmake .. -DCMAKE_BUILD_TYPE=Release -DENABLE_CUDA=1 -DCMAKE_CUDA_STANDARD=20 -DCMAKE_CUDA_ARCHITECTURES=61 -DCMAKE_CUDA_HOST_COMPILER=g++ + - cmake --verbose --build . --parallel 2 || cmake --build . --verbose + - ctest || ctest --rerun-failed --output-on-failure needs: ["cuda"] rocm: @@ -700,11 +794,12 @@ rocm: tags: - non-shared - docker - - high-bandwidth + - high-bandwidth # for download rocm extras + - x86_64 # for rocm image interruptible: true script: - apt-get -qq update - - apt-get install --no-install-recommends -y cmake wget pkg-config make libboost-test-dev libboost-serialization-dev libboost-timer-dev libblas-dev libfftw3-dev wget gpg + - apt-get install --no-install-recommends -y cmake wget pkg-config make libboost-serialization-dev libboost-timer-dev libblas-dev libfftw3-dev wget gpg - apt-get install --no-install-recommends -y rocthrust-dev hipblas-dev hipfft-dev rocm-device-libs - /opt/rocm/bin/hipconfig --full - HIPCC_VERBOSE=1 /opt/rocm/bin/hipcc --version @@ -717,70 +812,40 @@ rocm: - export CMAKE_PREFIX_PATH=/opt/rocm:${CMAKE_PREFIX_PATH} - export ROCM_PATH=/opt/rocm - export HIP_PATH=/opt/rocm - - cmake .. -DBOOST_MULTI_STANDALONE=1 -DBUILD_TESTING=0 -DCMAKE_HIP_COMPILER=/opt/rocm/llvm/bin/clang++ -DCMAKE_CXX_FLAGS="-DMULTI_USE_HIP" -DCMAKE_HIP_FLAGS="-DMULTI_USE_HIP" -DENABLE_HIP=1 -DCMAKE_HIP_ARCHITECTURES=gfx90a # TODO(correaa) add CMAKE_BUILD_TYPE + - cmake .. -DCMAKE_HIP_COMPILER=/opt/rocm/llvm/bin/clang++ -DCMAKE_CXX_FLAGS="-DMULTI_USE_HIP" -DCMAKE_HIP_FLAGS="-DMULTI_USE_HIP" -DENABLE_HIP=1 -DCMAKE_HIP_ARCHITECTURES=gfx90a # TODO(correaa) add CMAKE_BUILD_TYPE - cmake --build . --parallel 2 || cmake --build . --verbose --parallel 1 - ctest || ctest --rerun-failed --output-on-failure || echo "ctest failed, probably due to lack of hardware" needs: ["clang++", "g++"] -# clang++-fedora c++23: -# stage: build -# image: fedora:rawhide # clang 17.0.6 as of Dec 2023 -# script: # clang 17 doesn't work with gcc 13 libstd -# - dnf install --setopt=install_weak_deps=False -y ca-certificates blas-devel boost-devel clang cmake fftw-devel make pkg-config -# - mkdir build && cd build -# - CXX=clang++ cmake .. -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_STANDARD=23 # -DBoost_INCLUDE_DIR=../boost_1_84_0 -DBoost_LIBRARY_DIR=../boost_1_84_0/stage/lib -DBoost_NO_SYSTEM_PATHS=ON -# - cmake --build . --parallel 2 || cmake --build . --verbose -# - ctest --output-on-failure -# needs: ["clang++-testing c++20"] - circle: stage: build + allow_failure: true tags: - non-shared - - docker - # interruptible: false + - x86_64 # for circle executable script: - - apt-get -qq update && apt-get -qq install --no-install-recommends -y --quiet ca-certificates clang cmake g++-11 gzip libboost-test-dev libboost-timer-dev libboost-serialization-dev libblas-dev libelf1 libfftw3-dev make pkg-config tar wget + - apt-get -qq update + - apt-get -qq install --no-install-recommends -y --quiet ca-certificates clang cmake g++-11 gzip libboost-timer-dev libboost-serialization-dev libblas-dev libelf1 libfftw3-dev make pkg-config tar wget - mkdir -p build_latest ; cd build_latest - - wget https://www.circle-lang.org/linux/build_200.tgz --no-verbose - - tar -zxvf build_???.tgz + - wget https://www.circle-lang.org/linux/build_202.tgz --no-verbose + - tar -zxvf build_*.tgz - cd .. - - ls - ./build_latest/circle --version - mkdir build && cd build - CXX=`pwd`/../build_latest/circle cmake .. -DCMAKE_BUILD_TYPE=Debug -DENABLE_CIRCLE=1 - - cmake --build . --parallel 2 || make VERBOSE=1 + - cmake --build . --parallel 4 || make VERBOSE=1 - ctest -j 2 --output-on-failure -circle-187: - stage: build - tags: - - non-shared - - docker - interruptible: true - script: - - apt-get -qq update && apt-get -qq install --no-install-recommends -y --quiet ca-certificates clang cmake g++-11 gzip libboost-test-dev libboost-timer-dev libboost-serialization-dev libblas-dev libelf1 libfftw3-dev make pkg-config tar wget - - mkdir -p build_latest ; cd build_latest - - wget https://www.circle-lang.org/linux/build_187.tgz --no-verbose - - tar -zxvf build_???.tgz - - cd .. - - ls - - ./build_latest/circle --version - - mkdir build && cd build - - CXX=`pwd`/../build_latest/circle cmake .. -DCMAKE_BUILD_TYPE=Debug -DBOOST_MULTI_STANDALONE=1 -DBUILD_TESTING=0 -DENABLE_CIRCLE=1 - - cmake --build . --parallel 2 || make VERBOSE=1 - - ctest -j 2 --output-on-failure - needs: ["circle"] - -circle-latest: +circle-latest c++20: stage: build allow_failure: true tags: - non-shared - - docker + - x86_64 # for circle executable interruptible: true script: - - apt-get -qq update && apt-get -qq install --no-install-recommends -y --quiet ca-certificates clang cmake g++-11 gzip libboost-test-dev libboost-timer-dev libboost-serialization-dev libblas-dev libelf1 libfftw3-dev make pkg-config tar wget + - apt-get -qq update + - apt-get -qq install --no-install-recommends -y --quiet ca-certificates clang cmake g++-12 gzip libboost-timer-dev libboost-serialization-dev libblas-dev libelf1 libfftw3-dev make pkg-config tar wget - mkdir -p build_latest ; cd build_latest - wget https://www.circle-lang.org/linux/build_latest.tgz --no-verbose - tar -zxvf build_*.tgz @@ -788,22 +853,22 @@ circle-latest: - ls - ./build_latest/circle --version - mkdir build && cd build - - CXX=`pwd`/../build_latest/circle cmake .. -DCMAKE_BUILD_TYPE=Debug -DENABLE_CIRCLE=1 + - CXX=`pwd`/../build_latest/circle cmake .. -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_EXTENSIONS=OFF -DCMAKE_CXX_STANDARD=20 -DENABLE_CIRCLE=1 - cmake --build . --parallel 2 || make VERBOSE=1 - ctest -j 2 --output-on-failure needs: ["circle"] inq: stage: test - image: debian:stable + # image: debian:stable tags: - non-shared - large-memory-space interruptible: true script: - - apt-get -qq update && apt-get -qq install --no-install-recommends -y ca-certificates cmake g++ git gfortran libopenmpi-dev libblas-dev libboost-filesystem-dev libboost-iostreams-dev libboost-serialization-dev libfftw3-dev libhdf5-dev liblapack-dev make ninja-build pkg-config python3-dev + - apt-get -qq update && apt-get -qq install --no-install-recommends -y ca-certificates cmake g++ git gfortran libopenmpi-dev libblas-dev libboost-filesystem-dev libboost-iostreams-dev libboost-serialization-dev libfftw3-dev libhdf5-dev liblapack-dev make ninja-build pkg-config python3-dev - export PREFIX=`mktemp -d` - - git clone --recurse-submodules https://gitlab.com/npneq/inq.git + - git clone --recurse-submodules https://gitlab.com/npneq/inq.git --branch update-multi-get - cd inq - git submodule update - cd external_libs/multi @@ -812,6 +877,7 @@ inq: - mkdir build && cd build - cmake .. -G Ninja --install-prefix=$PREFIX -DCMAKE_BUILD_TYPE=Release - cmake --build . || cmake --build . --parallel 1 + - apt-get -qq --no-install-recommends -y install python3-numpy - cmake --install . - export OMPI_ALLOW_RUN_AS_ROOT=1 - export OMPI_ALLOW_RUN_AS_ROOT_CONFIRM=1 @@ -836,7 +902,7 @@ inq cuda: # - export CUDA_VISIBLE_DEVICES=0,1 - __nvcc_device_query - export PREFIX=`mktemp -d` - - git clone --recurse-submodules https://gitlab.com/npneq/inq.git + - git clone --recurse-submodules https://gitlab.com/npneq/inq.git --branch update-multi-get - cd inq - cd external_libs/multi - git checkout $CI_COMMIT_SHA @@ -846,6 +912,7 @@ inq cuda: - /usr/local/cuda/bin/nvcc --version - CUDACXX=/usr/local/cuda/bin/nvcc cmake .. --install-prefix=$PREFIX -DENABLE_CUDA=1 -DCMAKE_BUILD_TYPE=Release -DCMAKE_CUDA_ARCHITECTURES=61 # =75 # =80 - cmake --build . --parallel 4 || cmake --build . --parallel 1 + - apt-get -qq --no-install-recommends -y install python3-numpy - cmake --install . - export OMPI_ALLOW_RUN_AS_ROOT=1 - export OMPI_ALLOW_RUN_AS_ROOT_CONFIRM=1 @@ -863,6 +930,7 @@ inq rocm: tags: - non-shared - large-disk-space + - x86_64 # for image interruptible: true script: - apt-get -qq update @@ -874,7 +942,7 @@ inq rocm: - sh ./cmake-3.27.0-rc3-linux-x86_64.sh --skip-license --prefix=/usr - cmake --version - export PREFIX=`mktemp -d` - - git clone --recurse-submodules https://gitlab.com/npneq/inq.git + - git clone --recurse-submodules https://gitlab.com/npneq/inq.git --branch update-multi-get - cd inq - cd external_libs/multi - git checkout $CI_COMMIT_SHA @@ -901,12 +969,11 @@ qmcpack: tags: - non-shared - docker - - high-bandwidth interruptible: true before_script: - apt-get -qq update && apt-get -qq install --no-install-recommends -y ca-certificates cmake g++ git gfortran libblas-dev libboost-serialization-dev libfftw3-dev libhdf5-dev liblapack-dev libopenmpi-dev make numdiff pkg-config python3 python3-h5py python3-numpy python3-mpi4py python3-scipy libxml2-dev script: - - git clone --depth=1 https://github.com/QMCPACK/qmcpack.git # --branch fix_afqmc_pointer_traits + - git clone --depth=1 https://github.com/correaa/qmcpack.git --branch correaa-patch-use-adl-get # https://github.com/QMCPACK/qmcpack.git - cd qmcpack - git config --global user.email "alfredo.correa@gmail.com" && git config --global user.name "Alfredo Correa" - git rm -r external_codes/boost_multi/multi && git commit -m "remove multi subtree" @@ -954,7 +1021,7 @@ qmcpack cuda-12.3.1: - apt-get -qq update && apt-get -qq install --no-install-recommends -y ca-certificates cmake git libopenmpi-dev cmake g++ git gfortran libblas-dev libboost-serialization-dev libfftw3-dev libhdf5-dev liblapack-dev libopenmpi-dev make numdiff pkg-config python3 python3-h5py python3-numpy python3-mpi4py python3-scipy libxml2-dev script: - nvidia-smi - - git clone --depth 1 https://github.com/QMCPACK/qmcpack.git # --branch fix_afqmc_pointer_traits + - git clone --depth 1 https://github.com/correaa/qmcpack.git --branch correaa-patch-use-adl-get # https://github.com/QMCPACK/qmcpack.git # --branch fix_afqmc_pointer_traits - cd qmcpack - git config --global user.email "alfredo.correa@gmail.com" && git config --global user.name "Alfredo Correa" - git rm -r external_codes/boost_multi/multi && git commit -m "remove multi subtree" @@ -1003,6 +1070,7 @@ sonar: tags: - non-shared - docker + - x86_64 # for executable # cache: # policy: pull-push # key: "${CI_COMMIT_SHORT_SHA}" @@ -1013,17 +1081,18 @@ sonar: interruptible: true script: # Run the build inside the build wrapper - - apt-get -qq update && apt-get -qq install --no-install-recommends -y --quiet ca-certificates cmake curl unzip g++ make libboost-test-dev libboost-timer-dev libboost-serialization-dev libblas-dev libfftw3-dev pkg-config gcovr lcov + - apt-get -qq update && apt-get -qq install --no-install-recommends -y --quiet ca-certificates cmake curl unzip g++ gcovr make lcov libboost-timer-dev libboost-serialization-dev libblas-dev libfftw3-dev pkg-config wget - g++ --version - mkdir build # Download sonar-scanner - - curl -sSLo ./sonar-scanner.zip 'https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-5.0.1.3006-linux.zip' + - wget https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-6.2.1.4610-linux-x64.zip -O sonar-scanner.zip + # - curl -sSLo ./sonar-scanner.zip 'https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-5.0.1.3006-linux.zip' - unzip -o sonar-scanner.zip - - mv sonar-scanner-5.0.1.3006-linux sonar-scanner - # Download build-wrapper + - mv sonar-scanner-6.2.1.4610-linux-x64 sonar-scanner + # - Download build-wrapper - curl -sSLo ./build-wrapper-linux-x86.zip "${SONAR_HOST_URL}/static/cpp/build-wrapper-linux-x86.zip" - unzip -oj build-wrapper-linux-x86.zip -d ./build-wrapper - - cmake -S . -B build -DCMAKE_BUILD_TYPE=Debug -DBOOST_MULTI_STANDALONE=1 -DBUILD_TESTING=0 -DCMAKE_CXX_FLAGS="--coverage -O0 -fno-inline -fno-inline-small-functions -fno-default-inline" -DCMAKE_EXE_LINKER_FLAGS="--coverage" + - cmake -S . -B build -DCMAKE_BUILD_TYPE=Debug -DBUILD_TESTING=1 -DCMAKE_CXX_FLAGS="--coverage -O0 -fno-inline -fno-inline-small-functions -fno-default-inline" -DCMAKE_EXE_LINKER_FLAGS="--coverage" - build-wrapper/build-wrapper-linux-x86-64 --out-dir bw-output cmake --build build/ --verbose - cd build - ctest -j 1 --output-on-failure -T Test diff --git a/external_codes/boost_multi/multi/.gitlab/merge_request_templates/default.md b/external_codes/boost_multi/multi/.gitlab/merge_request_templates/default.md new file mode 100644 index 0000000000..178502be6d --- /dev/null +++ b/external_codes/boost_multi/multi/.gitlab/merge_request_templates/default.md @@ -0,0 +1,3 @@ +[![cmakeworkflow](https://github.com/correaa/boost-multi/actions/workflows/cmake.yml/badge.svg?branch=%{source_branch})](https://github.com/correaa/boost-multi/actions?query=workflow%3ACMake+branch%3A%{source_branch}++) +[![ciworkflow](https://github.com/correaa/boost-multi/actions/workflows/ci.yml/badge.svg?branch=%{source_branch})](https://github.com/correaa/boost-multi/actions?query=workflow%3ACI+branch%3A%{source_branch}++) +[Create GitHub PR](https://github.com/correaa/boost-multi/compare/%{source_branch}) diff --git a/external_codes/boost_multi/multi/.iwyu-test.imp b/external_codes/boost_multi/multi/.iwyu-test.imp new file mode 100644 index 0000000000..66afd9b8b6 --- /dev/null +++ b/external_codes/boost_multi/multi/.iwyu-test.imp @@ -0,0 +1,63 @@ +[ + { "include": ["@", "private", "", "public"] }, + { "include": ["@", "private", "", "public"] }, + { "include": ["@", "private", "", "public"] }, + { "include": ["@", "private", "", "public"] }, + { "include": ["@", "private", "", "public"] }, + { "include": ["@", "private", "", "public"] }, + { "include": ["@", "private", "", "public"] }, + { "include": ["@", "private", "", "public"] }, + { "include": ["@", "private", "", "public"] }, + { "include": ["@", "private", "", "public"] }, + { "include": ["@", "private", "", "public"] }, + { "include": ["@", "private", "", "public"] }, + { "include": ["@", "private", "", "public"] }, + { "include": ["@", "private", "", "public"] }, + { "include": ["@", "private", "", "public"] }, + { "include": ["@", "private", "", "public"] }, + { "include": ["@", "private", "", "public"] }, + { "include": ["@", "private", "", "public"] }, + { "include": ["@", "private", "", "public"] }, + { "include": ["@", "private", "", "public"] }, + { "include": ["@", "private", "", "public"] }, + { "include": ["@", "private", "", "public"] }, + { "include": ["@", "private", "", "public"] }, + { "include": ["@", "private", "", "public"] }, + { "include": ["@", "private", "", "public"] }, + { "include": ["@", "private", "", "public"] }, + { "include": ["@", "private", "", "public"] }, + { "include": ["@", "private", "", "public"] }, + { "include": ["@", "private", "", "public"] }, + { "include": ["@", "private", "", "public"] }, + { "include": ["@", "private", "", "public"] }, + { "include": ["@", "private", "", "public"] }, + { "include": ["@", "public", "", "public"] }, + { "include": ["@", "public", "", "public"] }, + { "include": ["@", "public", "", "public"] }, + { "include": ["@", "public", "", "public"] }, + { "include": ["@", "public", "", "public"] }, + { "include": ["@", "public", "", "public"] }, + { "include": ["@", "private", "", "public"] }, + { "include": ["@", "private", "", "public"] }, + { "include": ["@", "private", "", "public"] }, + { "include": ["@", "public", "", "public"] }, + { "include": ["@", "private", "", "public"] }, + { "include": ["@", "private", "", "public"] }, + { "include": ["@", "private", "", "public"] }, + { "include": ["@", "private", "", "public"] }, + { "include": ["@", "private", "", "public"] }, + { "include": ["@", "public", "", "public"] }, + { "include": ["@", "public", "", "public"] }, + { "include": ["@", "public", "", "public"] }, + { "include": ["@", "public", "", "public"] }, + { "include": ["@", "public", "", "public"] }, + { "include": ["@", "private", "", "public"]}, + { "include": ["@", "public", "", "public"]}, + { "include": ["@<__assert>", "private", "", "public"] }, + { "include": ["@<__fwd/ostream.h>", "private", "", "public"] }, + { "include": ["@<__fwd/sstream.h>", "private", "", "public"] }, + { "include": ["@", "public", "", "public"] }, + { "include": ["@", "private", "", "public"] }, + { "include": ["@<__bit_reference>", "private", "", "public"] }, + { "include": ["@<__fwd/string_view.h>", "private", "", "public"] } +] diff --git a/external_codes/boost_multi/multi/.valgrind-suppressions b/external_codes/boost_multi/multi/.valgrind-suppressions index 75230f7d02..b3a942c177 100644 --- a/external_codes/boost_multi/multi/.valgrind-suppressions +++ b/external_codes/boost_multi/multi/.valgrind-suppressions @@ -13,3 +13,105 @@ fun:cudaMalloc* ... } +{ + + Memcheck:Leak + match-leak-kinds: reachable + fun:calloc + obj:/usr/lib/x86_64-linux-gnu/libnvidia-opencl.so.* + obj:/usr/lib/x86_64-linux-gnu/libnvidia-opencl.so.* + obj:/usr/lib/x86_64-linux-gnu/libOpenCL.so.1.0.0 + fun:clGetPlatformIDs + obj:/usr/lib/x86_64-linux-gnu/hwloc/hwloc_opencl.so + obj:/usr/lib/x86_64-linux-gnu/libhwloc.so.* + fun:hwloc_topology_load + fun:opal_hwloc_base_get_topology + obj:* + fun:orte_init + fun:orte_submit_init +} +{ + + Memcheck:Leak + match-leak-kinds: reachable + fun:* + obj:/usr/lib/x86_64-linux-gnu/libpciaccess.so.0.* + ... + fun:pci_get_strings + obj:/usr/lib/x86_64-linux-gnu/hwloc/hwloc_pci.so + ... + obj:/usr/lib/x86_64-linux-gnu/libhwloc.so.* + fun:hwloc_topology_load + fun:opal_hwloc_base_get_topology + obj:* + fun:orte_init + fun:orte_submit_init +} +{ + + Memcheck:Leak + match-leak-kinds: reachable + fun:* + fun:* + obj:/usr/lib/x86_64-linux-gnu/libpciaccess.so.0.* + ... + fun:pci_get_strings + obj:/usr/lib/x86_64-linux-gnu/hwloc/hwloc_pci.so + ... + obj:/usr/lib/x86_64-linux-gnu/libhwloc.so.* + fun:hwloc_topology_load + fun:opal_hwloc_base_get_topology + obj:* + fun:* + fun:* +} +{ + + Memcheck:Leak + match-leak-kinds: reachable + fun:malloc + obj:/usr/lib/x86_64-linux-gnu/libnvidia-opencl.so.* + ... + obj:/usr/lib/x86_64-linux-gnu/libOpenCL.so.1.0.0 + fun:clGetPlatformIDs + obj:/usr/lib/x86_64-linux-gnu/hwloc/hwloc_opencl.so + obj:/usr/lib/x86_64-linux-gnu/libhwloc.so.* + fun:hwloc_topology_load + fun:opal_hwloc_base_get_topology + obj:* +} +{ + + Memcheck:Leak + match-leak-kinds: reachable + fun:calloc + obj:/usr/lib/x86_64-linux-gnu/libnvidia-opencl.so.* + ... + obj:/usr/lib/x86_64-linux-gnu/libOpenCL.so.1.0.0 + fun:clGetPlatformIDs + obj:/usr/lib/x86_64-linux-gnu/hwloc/hwloc_opencl.so + obj:/usr/lib/x86_64-linux-gnu/libhwloc.so.* + fun:hwloc_topology_load + fun:opal_hwloc_base_get_topology + obj:* + fun:* +} +{ + + Memcheck:Leak + match-leak-kinds: reachable + fun:malloc + obj:/usr/lib/x86_64-linux-gnu/libstdc++.so.* + fun:call_init* + ... + fun:_dl_init + fun:_dl_catch_exception + fun:dl_open_worker + ... + fun:_dl_catch_exception + fun:_dl_open + fun:dlopen_doit + fun:_dl_catch_exception + fun:_dl_catch_error + fun:_dlerror_run +} diff --git a/external_codes/boost_multi/multi/CMakeLists.txt b/external_codes/boost_multi/multi/CMakeLists.txt index 10ada484f6..e29c2820b8 100644 --- a/external_codes/boost_multi/multi/CMakeLists.txt +++ b/external_codes/boost_multi/multi/CMakeLists.txt @@ -5,18 +5,6 @@ cmake_minimum_required(VERSION 3.16) -# Library doesn't require installation, to still install this project: -# ~~~ -# $ cmake .. --install-prefix=$HOME && cmake --build . --config Release --target test --target install -- -j $(nproc) -# ~~~ -# to use this library in another CMake project -# ~~~ -# project("Your project") -# find_package(boost-multi CONFIG REQUIRED) -# add_executable(${PROJECT_NAME} src/your_main.cpp) -# target_link_libraries(${PROJECT_NAME} boost-multi::boost-multi) -# ~~~ - if (DEFINED BOOST_SUPERPROJECT_VERSION AND NOT DEFINED BOOST_MULTI_STANDALONE) project(boost_multi VERSION "${BOOST_SUPERPROJECT_VERSION}" LANGUAGES CXX) @@ -37,171 +25,180 @@ if (DEFINED BOOST_SUPERPROJECT_VERSION AND NOT DEFINED BOOST_MULTI_STANDALONE) endif() -else() + return() +endif() - project( - multi - HOMEPAGE_URL "https://gitlab.com/correaa/boost-multi" - DESCRIPTION "A header-only modern C++ library that provides access and manipulation of data in multidimensional arrays." - VERSION 0.80.1 - LANGUAGES CXX) +# Library doesn't require installation, to still install this project: +# ~~~ +# $ cmake .. --install-prefix=$HOME && cmake --build . --config Release --target test --target install -- --parallel +# ~~~ +# to use this library in another CMake project +# ~~~ +# project("Your project") +# find_package(boost-multi CONFIG REQUIRED) +# add_executable(${PROJECT_NAME} src/your_main.cpp) +# target_link_libraries(${PROJECT_NAME} boost-multi::boost-multi) +# ~~~ - message(STATUS "Boost.Multi: standalone mode ON") - message("current binary directory: ${CMAKE_CURRENT_BINARY_DIR}") +message("current binary directory: ${CMAKE_CURRENT_BINARY_DIR}") - include_directories(${PROJECT_SOURCE_DIR}/include) # workaround for vscode to detect headers https://stackoverflow.com/a/68139743/225186 +project( + multi + HOMEPAGE_URL "https://gitlab.com/correaa/boost-multi" + DESCRIPTION "A header-only modern C++ library that provides access and manipulation of data in multidimensional arrays." + VERSION 0.80.1 + LANGUAGES CXX) - include(CMakePackageConfigHelpers) - include(CMakeDependentOption) - include(GNUInstallDirs) +message(STATUS "Boost.Multi: standalone mode ON") - find_program(MEMORYCHECK_COMMAND valgrind) - set(VALGRIND_COMMAND_OPTIONS "-q --tool=memcheck --leak-check=yes --num-callers=51 --trace-children=yes --leak-check=full --track-origins=yes --gen-suppressions=all") +add_library(multi INTERFACE) - # must go before `include(CTest)` - set(MEMORYCHECK_COMMAND_OPTIONS "-q --tool=memcheck --leak-check=yes --num-callers=52 --trace-children=yes --leak-check=full --track-origins=yes --gen-suppressions=all") - set(MEMORYCHECK_SUPPRESSIONS_FILE "${PROJECT_SOURCE_DIR}/.valgrind-suppressions") +target_include_directories(multi INTERFACE $ $) +target_compile_options(multi INTERFACE $<$: --expt-relaxed-constexpr --extended-lambda>) - include(CTest) +# https://youtrack.jetbrains.com/issue/CPP-25608 +target_compile_features(multi INTERFACE cxx_std_17) # $<$>:cxx_std_17>) +if(ENABLE_CUDA) + target_compile_features(multi INTERFACE cuda_std_17) # $<$>:cxx_std_17>) +endif() - option(MULTI_BUILD_PACKAGE "Build package files as well" ON) +# target_compile_options(multi INTERFACE $<$:-std=c++17>) - cmake_dependent_option(MULTI_BUILD_TESTS "Enable multi tests" ON "BUILD_TESTING" OFF) +if(NOT CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR) + add_library(correaa::multi ALIAS multi) +endif() - cmake_dependent_option(MULTI_BUILD_PACKAGE_DEB "Create a DEB" ON "MULTI_BUILD_PACKAGE" OFF) +# this makes CM FetchContent friendly https://www.foonathan.net/2022/06/cmake-fetchcontent/ +if(NOT CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR) + return() +endif() +################################################################################ - add_library(multi INTERFACE) - #target_compile_features(multi PUBLIC cxx_std_17) +include(CMakePackageConfigHelpers) +include(CMakeDependentOption) +include(GNUInstallDirs) - target_include_directories(multi INTERFACE $ $) - target_compile_options(multi INTERFACE $<$: --expt-relaxed-constexpr --extended-lambda>) +include(CTest) - if(NOT CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR) - add_library(correaa::multi ALIAS multi) - endif() +option(MULTI_BUILD_PACKAGE "Build package files as well" ON) - # https://youtrack.jetbrains.com/issue/CPP-25608 - target_compile_features(${PROJECT_NAME} INTERFACE $<$>:cxx_std_17>) - target_compile_options(${PROJECT_NAME} INTERFACE $<$:-std=c++17>) +cmake_dependent_option(MULTI_BUILD_TESTS "Enable multi tests" ON "BUILD_TESTING" OFF) - # this makes CM FetchContent friendly https://www.foonathan.net/2022/06/cmake-fetchcontent/ - if(NOT CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR) - return() - endif() +cmake_dependent_option(MULTI_BUILD_PACKAGE_DEB "Create a DEB" ON "MULTI_BUILD_PACKAGE" OFF) - # Installation help - configure_package_config_file("${PROJECT_SOURCE_DIR}/cmake/multi-config.cmake.in" "${PROJECT_BINARY_DIR}/multi-config.cmake" INSTALL_DESTINATION "share/cmake/multi") +# Installation help +configure_package_config_file("${PROJECT_SOURCE_DIR}/cmake/multi-config.cmake.in" "${PROJECT_BINARY_DIR}/multi-config.cmake" INSTALL_DESTINATION "share/cmake/multi") - write_basic_package_version_file("${PROJECT_BINARY_DIR}/multi-config-version.cmake" COMPATIBILITY SameMajorVersion ARCH_INDEPENDENT) +write_basic_package_version_file("${PROJECT_BINARY_DIR}/multi-config-version.cmake" COMPATIBILITY SameMajorVersion ARCH_INDEPENDENT) - message("current install prefix directory: ${CMAKE_INSTALL_PREFIX}") +message("current install prefix directory: ${CMAKE_INSTALL_PREFIX}") - install( - TARGETS multi - EXPORT multi-targets - INCLUDES - DESTINATION "${CMAKE_INSTALL_DATADIR}") +install( + TARGETS multi + EXPORT multi-targets + INCLUDES + DESTINATION "${CMAKE_INSTALL_DATADIR}") - install( - EXPORT ${PROJECT_NAME}-targets - DESTINATION "${CMAKE_INSTALL_DATADIR}/cmake/${PROJECT_NAME}" - NAMESPACE multi:: - FILE "${PROJECT_NAME}-targets.cmake") +install( + EXPORT ${PROJECT_NAME}-targets + DESTINATION "${CMAKE_INSTALL_DATADIR}/cmake/${PROJECT_NAME}" + NAMESPACE multi:: + FILE "${PROJECT_NAME}-targets.cmake") - install(FILES "${PROJECT_BINARY_DIR}/${PROJECT_NAME}-config-version.cmake" "${PROJECT_BINARY_DIR}/${PROJECT_NAME}-config.cmake" DESTINATION "${CMAKE_INSTALL_DATADIR}/cmake/${PROJECT_NAME}") +install(FILES "${PROJECT_BINARY_DIR}/${PROJECT_NAME}-config-version.cmake" "${PROJECT_BINARY_DIR}/${PROJECT_NAME}-config.cmake" DESTINATION "${CMAKE_INSTALL_DATADIR}/cmake/${PROJECT_NAME}") - install(DIRECTORY "include/" TYPE INCLUDE) +install(DIRECTORY "include/" TYPE INCLUDE) - add_subdirectory(test) +if(MULTI_BUILD_TESTS) + find_package(Boost COMPONENTS) # you can use your own Boost and use `cmake -DBOOST_ROOT=$HOME/local` + if(NOT Boost_FOUND) + message(WARNING "Cannot find Boost, Multi library will not be fully tested.") + else() + enable_testing() - # if(MULTI_BUILD_TESTS) - find_package(Boost 1.65 COMPONENTS unit_test_framework) # 1.65 needed for BOOST_TEST_GLOBAL_FIXTURE, you can use your own Boost and use `cmake -DBOOST_ROOT=$HOME/local` - if(NOT Boost_FOUND) - message(WARNING "Cannot find Boost 1.65+, Multi library will not be fully tested.") - else() - enable_testing() + add_subdirectory(test) - add_subdirectory(include/boost/multi/adaptors/blas) - # add_subdirectory(include/boost/multi/adaptors/complex) - add_subdirectory(include/boost/multi/adaptors/cuda) - add_subdirectory(include/boost/multi/adaptors/fftw) + add_subdirectory(include/boost/multi/adaptors/blas) + # # add_subdirectory(include/boost/multi/adaptors/complex) + add_subdirectory(include/boost/multi/adaptors/fftw) - find_package(LAPACK) - if(LAPACK_FOUND) - add_subdirectory(include/boost/multi/adaptors/lapack) - endif() + find_package(LAPACK) + if(LAPACK_FOUND) + add_subdirectory(include/boost/multi/adaptors/lapack) + endif() + if(ENABLE_CUDA) add_subdirectory(include/boost/multi/adaptors/thrust) - if(ENABLE_CUDA) - add_subdirectory(include/boost/multi/adaptors/cufft) - endif() - if(ENABLE_HIP) - add_subdirectory(include/boost/multi/adaptors/hipfft) - add_subdirectory(include/boost/multi/adaptors/hipthrust/test) - endif() + add_subdirectory(include/boost/multi/adaptors/cuda) + # add_subdirectory(include/boost/multi/adaptors/cufft) + endif() + if(ENABLE_HIP) + # add_subdirectory(include/boost/multi/adaptors/hipfft) + # add_subdirectory(include/boost/multi/adaptors/hipthrust/test) endif() - # endif() - if(MULTI_BUILD_PACKAGE) - list(APPEND source-generators TBZ2 TGZ TXZ ZIP) + add_subdirectory(include/boost/multi/adaptors) + endif() +endif() - if(CMAKE_HOST_WIN32) - list(APPEND binary-generators "WIX") - endif() +if(MULTI_BUILD_PACKAGE) + list(APPEND source-generators TBZ2 TGZ TXZ ZIP) - if(MULTI_BUILD_PACKAGE_DEB) - list(APPEND binary-generators "DEB") - endif() + if(CMAKE_HOST_WIN32) + list(APPEND binary-generators "WIX") + endif() - if(MULTI_BUILD_RPM) - list(APPEND binary-generators "RPM") - endif() + if(MULTI_BUILD_PACKAGE_DEB) + list(APPEND binary-generators "DEB") + endif() - set(CPACK_PACKAGE_NAME ${PROJECT_NAME} - CACHE STRING "The resulting package name" - ) - set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "all") - set(CPACK_PACKAGE_ARCHITECTURE "all") - set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Multidimensional arrays for C++" - CACHE STRING "Package description for the package metadata" - ) - - set(CPACK_PACKAGE_VENDOR "alfredo.correa@gmail.com") - # set(CPACK_PACKAGE_INSTALL_DIRECTORY ${CPACK_PACKAGE_NAME}) - # SET(CPACK_OUTPUT_FILE_PREFIX "${CMAKE_SOURCE_DIR}/_packages") - # set(CPACK_PACKAGING_INSTALL_PREFIX "/opt/some")#/${CMAKE_PROJECT_VERSION}") - - # set(CPACK_PACKAGE_VERSION_MAJOR ${PROJECT_VERSION_MAJOR}) - # set(CPACK_PACKAGE_VERSION_MINOR ${PROJECT_VERSION_MINOR}) - # set(CPACK_PACKAGE_VERSION_PATCH ${PROJECT_VERSION_PATCH}) - - set(CPACK_PACKAGE_CONTACT "alfredo.correa@gmail.com") - set(CPACK_DEBIAN_PACKAGE_MAINTAINER "Alfredo A. Correa") - - set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE") - set(CPACK_RESOURCE_FILE_README "${CMAKE_CURRENT_SOURCE_DIR}/README.md") - - set(CPACK_DEBIAN_FILE_NAME "multi_all.deb") - # set(CPACK_COMPONENTS_GROUPING ALL_COMPONENTS_IN_ONE)#ONE_PER_GROUP) - # set(CPACK_DEB_COMPONENT_INSTALL YES) - - set(CPACK_SOURCE_GENERATOR ${source-generators}) - set(CPACK_GENERATOR ${binary-generators}) - - # set(CPACK_PACKAGE_FILE_NAME "${PROJECT_NAME}-${PROJECT_VERSION}") - # set(CPACK_SOURCE_PACKAGE_FILE_NAME "${CPACK_PACKAGE_FILE_NAME}") - - list( - APPEND - CPACK_SOURCE_IGNORE_FILES - /.git/ - /.build*/ - /build/ - .gitignore - .DS_Store) - - include(CPack) + if(MULTI_BUILD_RPM) + list(APPEND binary-generators "RPM") endif() + set(CPACK_PACKAGE_NAME ${PROJECT_NAME} + CACHE STRING "The resulting package name" + ) + set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "all") + set(CPACK_PACKAGE_ARCHITECTURE "all") + set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Multidimensional arrays for C++" + CACHE STRING "Package description for the package metadata" + ) + + set(CPACK_PACKAGE_VENDOR "alfredo.correa@gmail.com") + # set(CPACK_PACKAGE_INSTALL_DIRECTORY ${CPACK_PACKAGE_NAME}) + # SET(CPACK_OUTPUT_FILE_PREFIX "${CMAKE_SOURCE_DIR}/_packages") + # set(CPACK_PACKAGING_INSTALL_PREFIX "/opt/some")#/${CMAKE_PROJECT_VERSION}") + + # set(CPACK_PACKAGE_VERSION_MAJOR ${PROJECT_VERSION_MAJOR}) + # set(CPACK_PACKAGE_VERSION_MINOR ${PROJECT_VERSION_MINOR}) + # set(CPACK_PACKAGE_VERSION_PATCH ${PROJECT_VERSION_PATCH}) + + set(CPACK_PACKAGE_CONTACT "alfredo.correa@gmail.com") + set(CPACK_DEBIAN_PACKAGE_MAINTAINER "Alfredo A. Correa") + + set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE") + set(CPACK_RESOURCE_FILE_README "${CMAKE_CURRENT_SOURCE_DIR}/README.md") + + set(CPACK_DEBIAN_FILE_NAME "multi_all.deb") + # set(CPACK_COMPONENTS_GROUPING ALL_COMPONENTS_IN_ONE)#ONE_PER_GROUP) + # set(CPACK_DEB_COMPONENT_INSTALL YES) + + set(CPACK_SOURCE_GENERATOR ${source-generators}) + set(CPACK_GENERATOR ${binary-generators}) + + # set(CPACK_PACKAGE_FILE_NAME "${PROJECT_NAME}-${PROJECT_VERSION}") + # set(CPACK_SOURCE_PACKAGE_FILE_NAME "${CPACK_PACKAGE_FILE_NAME}") + + list( + APPEND + CPACK_SOURCE_IGNORE_FILES + /.git/ + /.build*/ + /build/ + .gitignore + .DS_Store) + + include(CPack) endif() diff --git a/external_codes/boost_multi/multi/CPPLINT.cfg b/external_codes/boost_multi/multi/CPPLINT.cfg index 7bf7ea8b9c..b05c72bf92 100644 --- a/external_codes/boost_multi/multi/CPPLINT.cfg +++ b/external_codes/boost_multi/multi/CPPLINT.cfg @@ -1,17 +1,14 @@ set noparent root=./include/ -linelength=240 +linelength=160 -filter=-build/include_order +filter=-build/include_order # this library uses this order of inclusion: local headers / third pary heders / boost headers / standard headers -filter=-readability/alt_tokens -filter=-readability/nolint +filter=-runtime/references # this library uses references -filter=-runtime/references +filter=-readability/nolint # accept NOLINT from other linters -filter=-whitespace/braces -filter=-whitespace/operators -filter=-whitespace/parens -filter=-whitespace/semicolon -filter=-whitespace/tab +filter=-whitespace/braces # braces unfortunately makes local scopes need an extra space {} +filter=-whitespace/parens # otherwise it will complain about whitespace in MACRO args +filter=-whitespace/tab # this library uses tabs for indentation diff --git a/external_codes/boost_multi/multi/README.md b/external_codes/boost_multi/multi/README.md index dc2f5032d7..2ef1e57887 100644 --- a/external_codes/boost_multi/multi/README.md +++ b/external_codes/boost_multi/multi/README.md @@ -1,48 +1,51 @@ -# [Boost.]Multi +# [Boost.] Multi -> **Disclosure: This is not an official or accepted Boost library and is unrelated to the std::mdspan proposal.** +> **Disclosure: This is not an official or accepted Boost library and is unrelated to the std::mdspan proposal. It is in the process of being proposed for inclusion in [Boost](https://www.boost.org/).** _© Alfredo A. Correa, 2018-2024_ -_Multi_ is a modern C++ library that provides access and manipulation of data in multidimensional arrays, for both CPU and GPU memory. +_Multi_ is a modern C++ library that provides manipulation and access of data in multidimensional arrays for both CPU and GPU memory. Multidimensional array data structures are fundamental to several branches of computing, such as data analysis, image processing, and scientific simulations, and in combination with GPUs to Artificial Intelligence and Machine Learning. This library offers array containers and subarrays in arbitrary dimensions with well-behaved value semantics, featuring logical access recursively across dimensions and to elements through indices and iterators. -The data structure is stride-based, which makes it compatible with low-level C-libraries. +The internal data structure layout is stride-based, which makes it compatible with low-level C libraries. The library interface is designed to be compatible with standard algorithms and ranges (STL) and special memory (including GPUs) and follows modern C++ design principles. -The library's primary concern is with the storage and logic structure of data; -it doesn't make algebraic or geometric assumptions about the arrays and their elements. -In this sense, it is instead a building block to implement algorithms to represent mathematical operations, specifically on numeric data. -Although most of the examples use numeric elements for conciseness, the library is designed to hold general types (e.g. non-numeric, non-trivial types, like `std::string`, other containers or, in general, user-defined value-types.) +Features of this library that aim to facilitate the manipulation of multidimensional arrays include: -Some features of this library: - -* Value semantics of multidimensional array containers -* Well-defined referential semantics of subarray (also called "view") types -* Interoperability with other libraries, STL, ranges, thrust (CUDA and AMD GPUs), Boost, and C-libraries -* Fast access to elements and subarrays (views) types -* Arbitrary pointer types (fancy pointers, memory spaces) +* Value semantics of multidimensional array containers and well-defined referential semantics to avoid unnecessary copies if possible. +* Availability of different access patterns to the elements in the multidimensional structure, as nested sequences or as a single sequence of elements. +A D-dimensional array can be interpreted either as an (STL-compatible) sequence of (D-1)-dimensional subarrays or as a flattened one-dimensional (also STL-compatible) sequence of elements. +* Interoperability with both legacy C and modern C++ libraries (e.g., STL, ranges, Thrust --CUDA and AMD GPUs--, Boost). +* Memory management and allocation to exploit modern memory spaces, including GPU memory, mapped memory, and fancy pointers. Do not confuse this library with [Boost.MultiArray](https://www.boost.org/doc/libs/1_69_0/libs/multi_array/doc/index.html) or with the standard MDSpan proposal `std::mdspan`. -This library shares some of their goals and is compatible with them, but it is otherwise designed at a different level of generality. +This library shares some of their goals and is compatible with them, but it is designed at a different level of generality and with other priorities (such as the features listed above). The code is entirely independent and has fundamental implementation and semantics differences. -It requires, at least, C++17. +The library's primary concern is with the storage and logic structure of data; +it doesn't make algebraic or geometric assumptions about the arrays and their elements. +(It is still a good building block for implementing mathematical algorithms, such as representing algebraic dense matrices in the 2D case.) + +The library does not throw exceptions and provides basic guarantees (such as no memory leaks) in their presence (e.g., thrown from allocations). +Indexing and other logical errors result in undefined behavior, which this library attempts to reflect via assertions. + +The library requires C++17 or higher. + +**Contents:** -## Contents [[_TOC_]] ## Using the library, installation and tests -You can try the library [online](https://godbolt.org/z/dvacqK8jE) before using it. +Before using the library, you can try it [online](https://godbolt.org/z/dvacqK8jE). _Multi_ doesn't require installation; a single header `#include ` is enough to use the entire core library. _Multi_ has no dependencies (except for the standard C++ library) and can be used immediately after downloading. @@ -51,8 +54,8 @@ _Multi_ has no dependencies (except for the standard C++ library) and can be use git clone https://gitlab.com/correaa/boost-multi.git ``` -Although installation is not necessary, the library can still be installed with CMake. -The header (and cmake) files will typically end up in `/usr/local/include/multi` and `/usr/local/share/multi`. +Although installation is unnecessary, the library can still be installed with CMake. +The header (and CMake) files will be installed in the chosen prefix location (by default, `/usr/local/include/multi` and `/usr/local/share/multi`). ```bash cd boost-multi @@ -61,7 +64,7 @@ cmake .. # --install-prefix=$HOME/.local cmake --install . # or sudo ... ``` -_Testing_ the library requires Boost.Test library, installed for example via `sudo apt install cmake git g++ libboost-test-dev make` or `sudo dnf install boost-devel cmake gcc-c++ git`. +_Testing_ the library requires the Boost.Test library, installed for example, via `sudo apt install cmake git g++ libboost-test-dev make` or `sudo dnf install boost-devel cmake gcc-c++ git`. A CMake build system is provided to compile and run basic tests. ```bash @@ -75,7 +78,7 @@ Once installed, other CMake projects (targets) can depend on Multi by adding a s find_package(multi) # see https://gitlab.com/correaa/boost-multi#using-the-library-installation-and-tests ``` -Alternatively to `find_package` the library can be fetched on demand: +As an alternatively to using `find_package`, the library can be fetched on demand: ```cmake include(FetchContent) FetchContent_Declare(multi GIT_REPOSITORY https://gitlab.com/correaa/boost-multi.git) @@ -87,254 +90,24 @@ target_link_libraries(my_target PUBLIC multi) The code requires compilers with standard C++17 support; for reference any of: LLVM's `clang` [(5.0+)](https://godbolt.org/z/51E1hjfnn) (`libc++` and `libstdc++`), GNU's `g++` [(7.1+)](https://godbolt.org/z/1nGEbKc5a), -Nvidia's [`nvcc`](https://godbolt.org/z/abdT73PqM) (11.4+) and `nvc++` (22.7+), -Intel's `icpc` (2021.2.0+) and `icpx` (2022.0.0+), -Baxter's [`circle`](https://www.circle-lang.org/) (build 187+), -[Zig](https://zig.news/kristoff/compile-a-c-c-project-with-zig-368j) in [c++ mode (v0.9.0+)](https://godbolt.org/z/cKGebsWMG), and -Microsoft's [MSVC](https://visualstudio.microsoft.com/vs/features/cplusplus/) ([+14.2](https://godbolt.org/z/vrfh1fxWK)). +Nvidia's [`nvcc`](https://godbolt.org/z/abdT73PqM) (11.4+) +and + [`nvc++`](https://godbolt.org/z/6z39PjT47) (22.7+), +Intel's `icpx` (2022.0.0+), +Baxter's [`circle`](https://www.circle-lang.org/) (build 202+), +[Zig](https://zig.news/kristoff/compile-a-c-c-project-with-zig-368j) in [c++ mode (v0.9.0+)](https://godbolt.org/z/cKGebsWMG), +Edison Desing's [EDG]() [(6.5+)](https://godbolt.org/z/693fxPedx) +and +Microsoft's [MSVC](https://visualstudio.microsoft.com/vs/features/cplusplus/) ([+14.1](https://godbolt.org/z/vrfh1fxWK)). (Multi code inside CUDA kernel can be compiled with `nvcc` and with [`clang` (in CUDA mode)](https://godbolt.org/z/7dTKdPTxc). Inside HIP code, it can be compiled with AMD's clang rocm (5.0+).) -Optional "adaptor" sublibraries (included in `multi/adaptors/`) have specific dependencies: fftw, blas, lapack, thurst, or CUDA -(all can be installed with `sudo apt install libfftw3-dev libblas64-dev liblapack64-dev libthrust-dev nvidia-cuda-dev` or `sudo dnf install blas-devel fftw-devel`.) - -## Reference of types - -The library interface presents several closely related C++ types (classes) representing arrays. -The most important types represent multidimensional containers (called `array`), references that can refer to subsets of these containers (called `subarray`), and iterators. -In addition, there are other classes for advanced uses, such as multidimensional views of existing buffers (called `array_ref`) and non-resizable owning containers (called `static_array`). - -When using the library, it is simpler to start from `array`, and other types are rarely explicitly used, especially if using `auto`; -however, it is convenient for documentation to present the classes in a different order since the classes `subarray`, `array_ref`, `static_array`, and `array` have a *is-a* relationship (from left to right). -For example, `array_ref` has all the methods available to `subarray`, and `array` has all the operations of `array_ref`. - -### class `multi::subarray` - -An instance of this class represents a part (or a whole) of another `subarray` (including an `array`). -These have reference semantics, and in essence, they behave like language-references. -As references, they cannot be rebinded or resized; assignments are always "deep". -They are characterized by a size that does not change. -They are usually the result of indexing over other `subarray`s and `array`s (generally of higher dimensions); therefore, the library doesn't expose constructors for this class. -The whole object can be invalidated if the original array is destroyed. - -| Member types | | -|--- |--- | -| `value_type` | `multi::array` or, for `D == 1`, `iterator_traits

::value_type` (usually `T`) -| `size_type` | `multi::size_t` (usually signed size) -| `difference_type` | `multi::diffptr_t` (usually signed size) -| `reference` | `multi::subarray` or, for `D == 1`, `pointer_traits

::reference` (usually `T&`) -| `const_reference` | `multi::const_subarray` or, for `D == 1`, `pointer_traits

::rebind::reference` (usually `T const&`) -| `pointer` | `multi::subarray_ptr or, for `D == 1, `P` (usually `T*`) -| `const_pointer` | `multi::const_subarray_ptr` or, for `D == 1, `pointer_traits

::rebind` (usually `T const*`) -| `iterator` | `multi::array_iterator_t` -| `const_iterator` | `multi::const_array_iterator_t` - -| Member fuctions | | -|--- |--- | -| (constructors) | Not exposed; copy constructor is not available since the instances are not copyable; destructors are trivial since it doesn't own the elements. | -| `operator=` | assigns the elements from the source, sizes must match. - -It is important to note that assignments in this library are always "deep," and reference-like types cannot be rebound after construction. -(Reference-like types have corresponding pointer-like types that provide an extra level of indirection and can be rebound (just like language pointers); -these types are `multi::array_ptr` and `multi::subarray_ptr` corresponding to `multi::array_ref` and `multi::subarray` respectively.) - -| Relational fuctions | | -|--- |--- | -| `operator==`/`operator!=` | Tells if elements of two `subarray` are equal (and if extensions of the subarrays are the same) -| `operator<`/`operator<=` | Less-than lexicographical comparison (requires elements to be comparable) -| `operator>`/`operator>=` | Less-than lexicographical comparison (requires elements to be comparable) - -It is important to note that, in this library, comparisons are always "deep". - -| Element access | | -|--- |--- | -|`operator[]` | access specified element by index, returns a `reference` (see above), for `D > 1` it can be used recursively | -|`front` | access first element (undefined result if array is empty). -|`back` | access last element (undefined result if array is empty). -|`operator()` | When used with zero arguments, it returns a `subarray` representing the whole array. When used with one argument, access a specified element by index (return a `reference`) or by range (return a `subarray` of equal dimension). For more than one, arguments are positional and reproduce expected array access syntax from Fortran or Matlab: | - -- `subarray::operator()(i, j, k, ...)`, as in `S(i, j, k)` for indices `i`, `j`, `k` is a synonym for `A`[i][j][k]`, the number of indices can be lower than the total dimension (e.g., `S` can be 4D). -Each index argument lowers the dimension by one. -- `subarray::operator()(ii, jj, kk)`, the arguments can be indices or ranges. -This function allows positional-aware ranges. Each index argument lowers the rank by one. -A special range is given by `multi::_`, which means "the whole range" (also spelled `multi::all`). -For example, if `S` is 3D, `S(3, {2, 8}, {3, 5})` gives a reference to a 2D array where the first index is fixed at 3, with sizes `6` by `2` referring the subblock in the second and third dimension. Note that `S(3, {2, 8}, {3, 5})` is not equivalent to `S[3]({2, 8})({3, 5})`. -- `operator()()` (no arguments) gives the same array but always as a subarray (for consistency), `S()` is equivalent to `S(S.extension())` and, in turn to`S(multi::_)` or `S(multi::all)`. - -| Structure access | (Generally used for interfacing with C-libraries) | -|--- |--- | -| `base` | direct access to underlying memory pointer (`S[i][j]... == S.base() + std::get<0>(S.strides())*i + std::get<1>(S.strides())*j + ...`) -| `stride` | return the stride value of the leading dimension, e.g `(&A[1][0][0]... - &A[0][0]...)` -| `strides` | returns a tuple with the strides defining the internal layout -| `layout` | returns a single layout object with stride and size information | - -| Iterators | | -|--- |--- | -| `begin/cbegin` | returns (const) iterator to the beginning -| `end/cend` | returns (const) iterator to the end - -| Capacity | | -|--- |--- | -| `sizes` | returns a tuple with the sizes in each dimension -| `extensions` | returns a tuple with the extensions in each dimension -| `size` | returns the number of subarrays contained in the first dimension | -| `extension` | returns a contiguous range describing the set of valid indices -| `num_elements` | returns the total number of elements - -| Creating views | (this operations do not copy elements or allocate) | -|--- |--- | -| `broadcasted` | returns an infinite view of the array of higher dimensions obtained by repeating elements. This returns a special kind of subarray with a degenerate layout and no size operation -| `dropped` | returns a subarray with the first n-elements (in the first dimension) dropped from the original subarray. This doesn't remove or destroy elements or resize the original array -| `element_transformed` | creates a view of the array, where each element is transformed according to a function | -| `elements` | a flatted view of all the elements rearranged in a canonical way. `A.elements()[0] -> A[0][0]`, `A.elements()[1] -> A[0][1]`, etc. The type of the result is not a subarray but a special kind of range. -| `rotated/unrotated` | a view (`subarray`) of the original array with indices (un)rotated from right to left (left to right), for `D = 1` returns the same `subarray`. For given `i`, `j`, `k`, `A[i][j][k]` gives the same element as `A.rotated()[j][k][i]` and, in turn the same as `A.unrotated()[k][i][j])`. Preserves dimension. The function is cyclic; `D` applications will give the original view. | -| `transposed` (same as `operator~`) | a view (`subarray`) of the original array with the first two indices exchanged, only available for `D > 1`; for `D = 2`, `rotated`, `unrotated` and `transposed` give same view | -| `sliced` | returns a subarray with elements from index `a`to index `b` (non-inclusive) `{S[a], ... S[b-1]}`. Preserves the dimension. -| `strided` | returns a subarray skipping `s` elements. Preserves the dimension. - -| Creating views by pointer manipulation | | -|--- |--- | -| `static_cast_array(args...)` | produces a view where the underlying pointer constructed by `P2{A.base(), args...}`. Usually, `args...` is empty. Non-empty arguments are useful for stateful fancy pointers, such as transformer iterators. -| `reinterpret_cast_array` | underlying elements are reinterpreted as type T2, element sizes (`sizeof`) have to be equal; `reinterpret_cast_array(n)` produces a view where the underlying elements are interpreted as an array of `n` elements of type `T2`. - -| Creating arrays | | -|--- |--- | -| `decay` (same as prefix `operator+`) | creates a concrete independent `array` with the same dimension and elements as the view. Usually used to force a copy of the elements or in combination with `auto` (e.g., `auto A2_copy = + A[2];`). - -A reference `subarray` can be invalidated when its origin array is invalidated or destroyed. -For example, if the `array` from which it originates is destroyed or resized. - -### class `multi::array_ref` - -A D-dimensional view of the contiguous pre-existing memory buffer. -This class doesn't manage the elements it contains, and it has reference semantics (it can't be rebound, assignments are deep, and have the same size restrictions as `subarray`) - -Since `array_ref` is-a `subarray`, it inherits all the class methods and types described before, in addition it defines these members below. - -| Member types | same as for `subarray` | -|--- |--- | - -| Member functions | same as for `subarray` plus ... | -|--- |--- | -| (constructors) | `array_ref::array_ref({e1, e2, ...}, p)` constructs a D-dimensional view of the contiguous range starting at p and ending at least after the size size of the multidimensional array (product of sizes). The default constructor and copy constructor are not exposed. Destructor is trivial since elements are not owned or managed. | - -| Element access | same as for `subarray` | -|--- |--- | - -| Structure access | same as for `subarray` | -|--- |--- | - -| Iterators | same as for `subarray` | -|--- |--- | - -| Capacity | same as for `subarray` | -|--- |--- | - -| Creating views | same as for `subarray` | -|--- |--- | - -| Creating arrays | same as for `subarray` | -|--- |--- | - -| Relational functions | same as for `subarray` | -|--- |--- | - -An `array_ref` can be invalidated if the original buffer is deallocated. - -### class `multi::static_array, ...>` - -A D-dimensional array that manages an internal memory buffer. -This class owns the elements it contains; it has restricted value semantics because assignments are restricted to sources with equal sizes. -Memory is requested by an allocator of type Alloc (standard allocator by default). -It supports stateful and polymorphic allocators, which are the default for the special type `multi::pmr::static_array`. - -The main feature of this class is that its iterators, subarrays, and pointers do not get invalidated unless the whole object is destroyed. -In this sense, it is semantically similar to a C-array, except that elements are allocated from the heap. -It can be useful for scoped uses of arrays and multi-threaded programming and to ensure that assignments do not incur allocations. -The C++ coreguiles proposed a similar (albeith one-dimensional) class, called [`gsl::dyn_array`](http://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#gslowner-ownership-pointers). - -For most uses, a `multi::array` should be preferred instead. - -| Member types | same as for `array_ref` | -|--- |--- | - -| Member fuctions | same as for `array_ref` plus ... | -|--- |--- | -| (constructors) | `static_array::static_array({e1, e2, ...}, T val = {}, Alloc = {})` constructs a D-dimensional array by allocating elements. `static_array::static_array(std::initializer_list<...>` constructs the array with elements initialized from a nested list. -| (destructor) | Destructor deallocates memory and destroy the elements | -| `operator=` | assigns the elements from the source, sizes must match. - -| Element access | same as for `array_ref` | -|--- |--- | - -| Structure access | same as for `array_ref` | -|--- |--- | - -| Iterators | same as for `array_ref` | -|--- |--- | - -| Capacity | same as for `array_ref` | -|--- |--- | - -| Creating views | same as for `array_ref` | -|--- |--- | - -| Creating arrays | same as for `array_ref` | -|--- |--- | - -| Relational fuctions | same as for `array_ref` | -|--- |--- | - -### class `multi::array, ...>` - -An array of integer positive dimension D has value semantics if element type T has value semantics. -It supports stateful and polymorphic allocators, the default for the special type `multi::pmr::static_array`. - -| Member types | same as for `static_array` | -|--- |--- | - -| Member fuctions | | -|--- |--- | -| (constructors) | `array::array({e1, e2, ...}, T val = {}, Alloc = {})` constructs a D-dimensional array by allocating elements;`array::array(It first, It last)` and `array::array(Range const& rng)`, same for a range of subarrays. `static_array::static_array(std::initializer_list<...>, Alloc = {})` constructs the array with elements initialized from a nested list. -| (destructor) | Destructor deallocates memory and destroy the elements | -| `operator=` | assigns for a source `subarray`, or from another `array`. `array`s can be moved | - -| Element access | same as for `static_array` | -|--- |--- | +Optional "adaptor" sublibraries (included in `multi/adaptors/`) have specific dependencies: fftw, , lapack, thurst, or CUDA +(all of them can be installed with `sudo apt install libfftw3-dev lib64-dev liblapack64-dev libthrust-dev nvidia-cuda-dev` or `sudo dnf install -devel fftw-devel ...`.) -| Structure access | same as for `static_array` | -|--- |--- | - -| Iterators | same as for `static_array` | -|--- |--- | - -| Capacity | same as for `static_array` | -|--- |--- | - -| Creating views | same as for `static_array` | -|--- |--- | - -| Creating arrays | same as for `static_array` | -|--- |--- | - -| Relational fuctions | same as for `static_array` | -|--- |--- | - -| Manipulation | | -|--- |--- | -| `clear` | Erases all elements from the container. The array is resized to zero size. | -| `reextent` | Changes the size of the array to new extensions. `reextent({e1, e2, ...})` elements are preserved when possible. New elements are initialized with `reextent({e1, e2, ...}, val)`. - -### class `multi::subarray::(const_)iterator` - -A random-access iterator to subarrays of dimension `D - 1`, generaly used to interact with or implement algorithms. -They can be default constructed but do not expose other constructors since they are generally created from `begin` or `end`, manipulated arithmetically, `operator--`, `operator++` (pre and postfix), or random jumps `operator+`/`operator-` and `operator+=`/`operator-=`. -They can be dereferenced by `operator*` and index access `operator[]`, returning objects of lower dimension `subarray::reference` (see above). -Note that this is the same type for all related arrays, for example, `multi::array::(const_)iterator`. - -`iterator` can be invalidated when its original array is invalidated, destroyed or resized. -An `iterator` that stems from `static_array` becomes invalid only if the original array was destroyed or out-of-scope. +In the following sections we present basic and advanced uses of the libraries. +Feel free to jump to the "Reference of fundamental types" section to explore a more exhaustive description of the classes provided by the library. ## Basic Usage @@ -380,34 +153,37 @@ assert( num_elements(C) == 3*4*5 ); // 60 elements with unspecified values ``` Arrays can be passed by value or by reference. -Most of the time, arguments should be passed through generic parameters to also allow functions work with parts (subblocks, slices, etc.) of an array. -Usually, the most useful functions work on the _concept_ of an array rather than on a concrete type, for example: +Most of the time, arguments should be passed through generic parameters to also allow functions to work with parts (subblocks, slices, etc.) of an array. +The most useful functions work on the _concept_ of an array rather than on a concrete type, for example: ```cpp template // instead of the overspecific argument std::array -auto element_1_1(ArrayDouble2D const& m) -> double const& {return m[1][1];} +auto element_1_1(ArrayDouble2D const& m) -> double const& { return m[1][1]; } ... assert( &element_1_1(A) == &A[1][1] ); ``` -The function expects any array or subarray of dimension 2 and return an element with type `double`. +The function expects any array or subarray of dimension 2 and returns an element with type `double`. The generic function template arguments that are not intended to be modified are passed by `const&`; otherwise, they are passed by forward-reference `&&`. -In this way, the functions can be applied on subblocks of larger matrices. +In this way, the functions can be applied to subblocks of larger matrices. ```cpp assert( &element_1_1(C3D[0]) == &C3D[0][1][1] ); ``` +(Although most of the examples use numeric elements for conciseness, the library is designed to hold general types (e.g. non-numeric, non-trivial types, like `std::string`, other containers or, in general, user-defined value-types.) + ## Advanced Usage +In this example, we are going to use memory that is not managed by the library and manipulate the elements. We can create a static C-array of `double`s, and refer to it via a bidimensional array `multi::array_ref`. ```cpp -#include "multi/array.hpp" +#include -#include // for sort -#include // for print +#include // for sort +#include // for print namespace multi = boost::multi; @@ -453,7 +229,7 @@ Presumably, if one can sort over a range, one can perform any other standard alg ```cpp ... - std::stable_sort( begin(d2D_ref), end(d2D_ref) ); + std::stable_sort( d2D_ref.begin(), d2D_ref.end() ); ... ``` @@ -472,7 +248,7 @@ Since the sorted array is a reference to the original data, the original C-array (Note that `std::sort` cannot be applied directly to a multidimensional C-array or to other libraries, such as Boost.MultiArray. The arrays implemented by this library are, to the best of my knowledge, the only ones that support all STL algorithms directly.) -If we want to order the matrix in a per-column basis, we need to "view" the matrix as range of columns. +If we want to order the matrix on a per-column basis, we need to "view" the matrix as a range of columns. This is done in the bidimensional case, by accessing the matrix as a range of columns: ```cpp @@ -486,17 +262,17 @@ The `rotate` operation rotates indices, providing a new logical view of the orig In this case, the original array will be transformed by sorting the matrix into: > ``` -> 1 2 3 4 30 -> 6 7 8 9 50 -> 11 12 13 14 100 -> 16 17 18 19 150 +> 1 2 3 4 30 +> 6 7 8 9 50 +> 11 12 13 14 100 +> 16 17 18 19 150 > ``` By combining index rotations and transpositions, an array of dimension `D` can be viewed simultaneously as `D!` (D-factorial) different ranges of different "transpositions" (rotation/permutation of indices.) ## Initialization -`array_ref` is initialized from a preexisting contiguous range, the index extensions should compatible with the total number of elements. +`array_ref` is initialized from a preexisting contiguous range, the index extensions should be compatible with the total number of elements. ```cpp double* dp = new double[12]; @@ -506,11 +282,11 @@ multi::array_ref B({2, 6}, dp); delete[] dp; ``` -Array references do not own memory and, just as language references, can not be rebinded (resized or "reseated") to refer to a different memory location. -Since `array_ref` is an array reference, it can "dangle" if the the original memory is deallocated. +Array references do not own memory and, just as language references, can not be rebinded (i.e. resized or "reseated") to refer to a different memory location. +Since `array_ref` is an array reference, it can "dangle" if the original memory is deallocated. -Array objects (`multi::array`), in constrast, own the elements it contains and can be resized; -`array` is initialized by specifying the index extensions (and optionally a default value). +Array objects (`multi::array`), in contrast, own the elements they contain and can be resized later. +An `array` is initialized by specifying the index extensions and, optionally, a default value). ```cpp multi::array A1({3} , 11.0); // {11.0, 11.0, 11.0} @@ -526,16 +302,16 @@ multi::array A1 = {1.0, 2.0, 3.0}; assert( num_elements(A1)==3 ); multi::array A2 { - { 1.0, 2.0, 3.0}, - { 4.0, 5.0, 6.0} + { 1.0, 2.0, 3.0}, + { 4.0, 5.0, 6.0} }; assert( num_elements(A2) == 2*3); multi::array const A3 = { - {{ 1.2, 0.0}, { 2.4, 1.0}}, - {{11.2, 3.0}, {34.4, 4.0}}, - {{15.2, 99.0}, {32.4, 2.0}} + {{ 1.2, 0.0}, { 2.4, 1.0}}, + {{11.2, 3.0}, {34.4, 4.0}}, + {{15.2, 99.0}, {32.4, 2.0}} }; assert( A3.num_elements() == 3 * 2 * 2 ); @@ -543,10 +319,10 @@ assert( A3.num_elements() == 3 * 2 * 2 ); In all cases, constness (`const` declaration) is honored in the expected way. -## Copy and assigment +## Copy and assigment (and aliasing) -The library offer value semantics for the `multi::array` family of classes. -Constructing or assigning from an existing array generates a copy of the original object, that is, and object that is independent but equal in value. +The library offers value semantics for the `multi::array` family of classes. +Constructing or assigning from an existing array generates a copy of the original object, independent of the original one but equal in value. ```cpp auto B2 = A2; // same as multi::array B2 = A2; (A2 is defined above) @@ -566,15 +342,15 @@ Sometimes it is necessary to generate copies from views or subblocks. ```cpp multi::array C2 = A2( {0, 2}, {0, 2} ); ``` -or equivalently,: +or equivalently, ```cpp auto C2 = + A2( {0, 2}, {0, 2} ); ``` Note the use of the prefix `+` as an indicator that a copy must be created (it has no arithmetic implications). -Due to limitations of the language, omiting the `+` will create effectively another reference non-indepdent view of the left-hand-side, which is generally undesired. +Due to a language limitation, omitting the `+`` will create another non-independent reference view of the left-hand side, which is generally undesired. -Subviews can also assigned, but only if the shape of the left-hand side (LHS) and right-hand side (RHS) match. -Otherwise, the behavior is undefined (in debug mode, the program will fail with an `assert`). +Subarray-references can also assigned, but only if the shapes of the left-hand side (LHS) and right-hand side (RHS) match. +Otherwise, the behavior is undefined (in debug mode, the program will fail an assertion). ```cpp C2( {0, 2}, {0, 2} ) = A2( {0, 2}, {0, 2} ); // both are 2x2 views of arrays, *elements* are copied @@ -584,7 +360,7 @@ Using the same or overlapping arrays in the RHS and LHS of assignment produces u Notably, this instruction does not transpose the array but produces an undefined result: ```cpp -A2 = A2.transposed(); +A2 = A2.transposed(); ``` While this below instead does produce a transposition, at the cost of making one copy (implied by `+`) of the transposed array first and assigning (or moving) it back to the original array. @@ -593,7 +369,14 @@ While this below instead does produce a transposition, at the cost of making one A2 = + A2.transposed(); ``` -In-place transposition is an active subject of research; +This is an instance of the problem of _data aliasing_, which describes a common situation in which a data location in memory can be accessed through different parts of an expression or function call. +Within the confines of the library interface, this pitfall can only occur on assignment as illustrated above. + +However the problem of aliasing can persist when taking mutable array-references in function arguments. +The most general solution to this problem is to make copies or directly work with completely disjoint objects; +but other case-by-case solutions might be possible. + +For example, in-place transposition is an active subject of research; _optimal_ speed and memory transpositions might require specially designed libraries. Finally, arrays can be efficiently moved by transferring ownership of the internal data. @@ -602,7 +385,7 @@ Finally, arrays can be efficiently moved by transferring ownership of the intern auto B2 = std::move(A2); // A2 is empty after this ``` -Subarrays do not own the data; therefore they cannot be moved in the same sense. +Subarrays do not own the data; therefore they cannot directly take advantage of this feature. However, individual elements of a view can be moved; this is particularly useful if the elements are expensive to copy. A "moved" subview is simply another kind of view of the elements. @@ -610,33 +393,36 @@ A "moved" subview is simply another kind of view of the elements. multi::array, 2> A({10, 10}, std::vector(1000)); multi::array, 2> B({10, 10}); ... -B[1] = A[2].element_moved(); // 10 *elements* of the third row of A is moved into the second row of B. A[2] still has 10 (moved-from) empty vectors +B[1] = A[2].element_moved(); ``` +Each of the 10 *elements* of the third row of A is moved into the second row of B. A[2] still has 10 (moved-from) empty vectors + + ## Change sizes (extents) -Arrays can change their size while _preserving elements_ with the `rextent` method. +Arrays can change their size while _preserving elements_ with the `reextent` method. ```cpp -multi::array A { - {1.0, 2.0, 3.0}, - {4.0, 5.0, 6.0} +multi::array A = { + {1, 2, 3}, + {4, 5, 6} }; A.rextent({4, 4}); -assert( A[0][0] == 1.0 ); +assert( A[0][0] == 1 ); ``` Arrays can be emptied (to zero-size) with `.clear()` (equivalent to `.rextent({0, 0, ...})`). -The main purpose of `rextent` is element preservation. +The main purpose of `reextent` is element preservation. Allocations are not amortized; except for trivial cases, all calls to reextend allocate and deallocate memory. -If element preservation is not desired, a simple assignment (move) from a new array expresses the intention better and it is more efficient since it doesn't need to copy preexisiting elements. +If element preservation is not desired, a simple assignment (move) from a new array expresses the intention better and it is more efficient since it doesn't need to copy preexisting elements. ```cpp -A = multi::array({4, 4}); // like A.rextent({4, 4}) but elements are not preserved. +A = multi::array({4, 4}); // like A.rextent({4, 4}) but elements are not preserved. ``` An alternative syntax, `.rextent({...}, value)` sets _new_ (not preexisting) elements to a specific value. @@ -644,34 +430,69 @@ An alternative syntax, `.rextent({...}, value)` sets _new_ (not preexisting) ele Subarrays or views cannot change their size or be emptied (e.g. `A[1].rextent({4})` or `A[1].clear()` will not compile). For the same reason, subarrays cannot be assigned from an array or another subarray of a different size. -Changing the size of arrays by `rextent`, `clear`, or assignment generally invalidates existing iterators and ranges/views. +Changing the size of arrays by `reextent`, `clear`, or assignment generally invalidates existing iterators and ranges/views. + +## Iteration (range-based loops vs iterators) -## Iteration +Historically, iteration over arrays has been done with `for`-loops, where each nesting level is associated with each dimension. +The valid range of indices in all the dimensions of an array is extracted with `.extensions()`. +In the 2D case, `.extensions()` can be conveniently decomposed into two ranges, one for each dimension. +``` + multi::array A = { + {1, 2, 3}, + {4, 5, 6} + }; + + auto [is, js] = A.extensions(); + for(auto i : is) { // is == {0, 1} (range from 0 to 2, not included) + for(auto j : js) { // ij = {0, 1, 2} (range from 0 to 3, not included) + A[i][j] *= 2; + } + } +``` + +The elements of the 2D array can be accessed directly without intermediate indices: + +```cpp + for(auto&& row : A) { + for(int& e: row) { + e *= 2; + } + } +``` + +However, in some cases it is better to use the iterator-based interface. +The iterator-based interface is more convenient to express and interact with generic algorithms, which in turn can be parallelized and less prone to index errors (such as off-by-one, and out-of-range access.) + +Array (and subarray-references) provide a members `.begin()` and `.end()` that produce random-access iterators that access the multidimensional structure through the first dimension (leftmost index). Accessing arrays by iterators (`begin`/`end`) enables the use of many iterator-based algorithms (see the sort example above). `begin(A)/end(A)` (or equivalently `A.begin()/A.end()`) gives iterators that are linear and random access in the leading dimension. -Other non-leading dimensions can be obtained by "rotating" indices first. -`A.rotated().begin()/.end()` gives access to a range of subarrays in second dimension number (first dimension is put at the end). +As an alternative the elements can be iterated in a flat manner, using the `.elements()` member. +This flattening is done in a canonical order (rightmost index changes fastest) and it is provided whether the elements are contiguous or not in memory. +This "elements" range also provides the begin and end iterators (`.elements().begin()`). -`cbegin/cend` give constant (read-only) access. +Other non-leading dimensions can be obtained by "rotating" indices first. +`A.rotated().begin()/.end()` gives access to a range of subarrays in the second dimension number (the first dimension is put at the end). +(`.cbegin()/.cend()` give constant (read-only) access.) -As an example, this function allows printing arrays of arbitrary dimension into a linear comma-separated form. +As an example, this function allows printing arrays of arbitrary dimensionality into a linear comma-separated form. ```cpp -void flat_print(double const& d) { cout< -void flat_print(Array const& ma) { +void recursive_print(Array const& ma) { cout << "{"; - if(not ma.empty()) { - flat_print(*cbegin(ma)); // first element - std::for_each(cbegin(ma)+1, cend(ma), [](auto&& e) { cout<<", "; flat_print(e);}); // rest + if(! ma.empty()) { + flat_print(*ma.begin()); // first element + std::for_each(ma.begin() + 1, ma.end(), [](auto const& e) { cout<<", "; flat_print(e);}); // rest } cout << "}"; } ... -print(A); +recursive_print(A); ``` > ``` > {{{1.2, 1.1}, {2.4, 1}}, {{11.2, 3}, {34.4, 4}}, {{15.2, 99}, {32.4, 2}}} @@ -681,14 +502,14 @@ Except for those corresponding to the one-dimensional case, dereferencing iterat These references can be given a name; using `auto` can be misleading since the resulting variable does not have value semantics. ```cpp -auto row = *begin(A); // accepted by the language but misleading, row is not an independent value +auto row = *A.begin(); // accepted by the language but misleading, row is not an independent value ``` In my experience, however, the following usage pattern produces a more consistent idiom for generating references (still without copying elements): ```cpp -auto&& row0 = * begin(A); // same as decltype(A):: reference row0 = * begin(A); -auto const& crow0 = *cbegin(A); // same as decltype(A)::const_reference crow0 = *cbegin(A); +auto&& row0 = *A.begin() ; // same as decltype(A):: reference row0 = * begin(A); +auto const& crow0 = *A.cbegin(); // same as decltype(A)::const_reference crow0 = *cbegin(A); auto&& row1 = A [1]; // same as decltype(A):: reference row1 = A [1]; auto const& crow1 = std::as_const(A)[1]; // same as decltype(A)::const_reference crow0 = std::as_const(A)[1]; @@ -701,6 +522,27 @@ decltype(A)::value_type row = *begin(A); // there is a real copy of the row auto row = + *begin(A); // there is another copy, note the use of '+' (unary plus) ``` +In the examples above all elements are accessed in a nested way, recursively down the dimensions. +To iterate over all the elements regardless of the multidimensional structure the following function can print all the elements. + +```cpp +template +void flat_print(Array const& ma) { + cout << "["; + std::for_each(ma.elements().begin(), ma.elements().end(), [](auto&& e) { cout<< e << ", ";}); + cout << "]"; +} +... +recursive_print(A); +``` +> ``` +> [1.2, 1.1, 2.4, 1, 11.2, 3, 34.4, 4, 15.2, 99, 32.4, 2] +> ``` + +This feature allows to view the array as a flat sequence using the `.elements()` range, which also has `.begin()`/`.end()` and indexing. +For example array element at indices 1,1 is the same as the element + + ### "Pointer" to subarray The library strongly relies on value-sematics, and it doesn't entertain the concept of "shallow" copy; however, it supports refenece- and pointer-sematics. @@ -715,8 +557,8 @@ auto row2_ptr = &A[2]; // A[2] is a row of A (not an element) assert( row2_ptr == &*(A.begin() + 2) ); ``` -The expression `A[2]` above is technically a C++ temporary object, and therefore it doesn't have a C++ address (taking `std::addressof` gives a compilation error). -However, in the library's abstraction, `A[2]` references an existing part of the original array, i.e. it is a "library reference", whose "library address" can be obtained operator `&`. +The expression `A[2]` above is technically a C++ temporary object, and therefore it doesn't have a C++ address (taking `std::addressof` gives a compilation error). +However, in the library's abstraction, `A[2]` references an existing part of the original array, i.e. it is a "library reference", whose "library address" can be obtained with the `&` operator. The case is an illustration that, in the library, operator `&` is, for subarrays, different than the `std::addressof` operator; the latter may not be defined and even not compile for some expressions. Comparing these markers/pointers with different provenance, i.e., originating from different arrays, is generally undefined. @@ -987,7 +829,7 @@ Broadcasting is a technique by which arrays are reinterpreted as having a higher The technique allows the reuse of operations designed for high dimensionality and effectively apply them to arrays of lower dimensionality. The result is generally an economy in the number of distinct operations that need to be provided in exchange for understanding how and where to exploit the broadcast operations. -Broadcasting is popular in array-based languages, such as Julia and NumPy, and the broadcast is generally applied automatically to match the dimension expected by the operation and other operation inputs. +Broadcasting is popular in array-based languages, such as Julia and NumPy, and the broadcast operation is generally applied automatically to match the dimension expected by the operation and other operation inputs. The library provides a basic form of broadcasting with certain limitations. Here is an example of an algorithm designed for two 2D arrays to obtain the row-by-row inner product. @@ -1034,7 +876,7 @@ First, broadcasted arrays are infinite in the broadcasted dimension; iteration w Explicit loops or algorithms that depend on reaching `.end()` from `.begin()` will effectively be non-terminating. Second, these array views are strictly read-only and alias their element addresses, e.g. `&b.broadcasted()[1][0] == &b.broadcasted()[2][0]` (since internal layouts' strides can be zero). -For illustration purposes only, `fill` here is replaced by `copy`; problematic uses are highlighted: + -Unlike popular languages, broadcasting is not automatic in the library and is applied to the leading dimension only, one dimension at a time. +Unlike in popular languages, broadcasting is not automatic in the library and is applied to the leading dimension only, one dimension at a time. Broadcasting in non-leading dimensions can be achieved by transpositions and index rotation. -Abuse of broadcast can make it harder to reason about operations; its primary use is to reuse existing efficient implementations of algorithms when implementations for a specific lower dimensions are not available. +Abuse of broadcast can make it harder to reason about operations; +its primary use is to reuse existing efficient implementations of algorithms when implementations for a specific lower dimensions are not available. These algorithms need to be compatible with broadcasted views (e.g., no explicit use of `.size()` or infinite loops stemming from problematic use of `.begin()/end()`.) +(In STL, algorithms ending with `_n` should be friendly to broadcast arrays, unfortunately `std::copy_n` is sometimes internally implemented in terms of `std::copy` causing a problematic iterator arithmetic on infinite arrays. +NB: `thrust::copy_n` can be used instead.) + As a final example, consider a function that computes the elements-by-element product of two 2D arrays, ```cpp @@ -1076,23 +922,26 @@ Note that the function `hadamard`, acting on 2D arrays, doesn't use the undefine ## Uninitialized vs. initialized elements -The library can take advantage of trivial initialization if it is available for specific element types. -Such types can be primitive types or used defined with trivial default constructor. -These types are characterized for having trivial default construction, i.e. a constructor that doesn't define or performs any operation, not even setting values. +If available, the library can take advantage of trivial initialization for the specific element type. +These types can be primitive or user-defined and come with "trivial default constructors". In simple terms, these constructors are not specified and do nothing, not even set values. -When used in the stack these types can be declared with no initialization (e.g. `double x;`, initial value is not well defined or partially-formed) or with initialization (e.g. `double x{};`, same as `double x = 0.0;`). -Analogously, `multi::array` does not initialize individual elements of this kind of types, unless specified. +When used in the stack, these types can be declared with no initialization (e.g., `double x;`, the initial value is not well defined or partially-formed) or with initialization (e.g., `double x{};`, same as `double x = 0.0;`). +Analogously, `multi::array` does not initialize individual elements of this kind of type unless specified. For example, after this construction of the array, the values of the six elements of this array are unspecified (partially-formed). ```cpp -multi::array A2({2, 3}); +multi::array A2({2, 3}); // A2 elements have unspecified value ``` No behavior of the program should depend on these values. -(Address sanitizers and memory checkers can detect this.) +(Address sanitizers and memory checkers can detect use of uninitialized values.) This design is a slight departure from the STL's design, which [eagerly initializes elements in containers](https://lemire.me/blog/2012/06/20/do-not-waste-time-with-stl-vectors/). If trivial construction is unavailable, the library uses the default initialization. +```cpp +multi::array A2({2, 3}); // A2 elements have specified value, the empty value std::string{} +``` + For types that afford this partially formed states, elements can be later specified via assignment or assigning algorithms (e.g., copy or transform destination). Initialization can be enforced by passing a single value argument after the extensions. @@ -1104,7 +953,7 @@ This design is particularly advantageous for *numeric* types for which external (or when data sits in GPUs, where the initialization step would require an expensive kernel launch and subsequent synchronization). Unfortunately, regarding the numeric types, STL's `std::complex` was standardized as not-trivially constructible. -A workaround is possible by forcing a particular flag on the client code in global scope, for example, immediately after including the library: +A workaround built-in this library is available by forcing a particular flag on the client code in global scope, for example, immediately after including the library: ```cpp #include @@ -1117,7 +966,7 @@ The rule will only apply to this library's containers (`multi::array`, etc), and ## Type Requirements -Thelibrary design tries to impose the minimum possible requirements over the types that parameterize the arrays. +The library design tries to impose the minimum possible requirements over the types that parameterize the arrays. Array operations assume that the contained type (element type) are regular (i.e. different element represent disjoint entities that behave like values). Pointer-like random access types can be used as substitutes of built-in pointers. (Therefore pointers to special memory and fancy-pointers are supported.) @@ -1141,7 +990,6 @@ Since `array_ref` does not manage the memory associated with it, the reference c `array`s manage their memory behind the scenes through allocators, which can be specified at construction. It can handle special memory, as long as the underlying types behave coherently, these include [fancy pointers](https://en.cppreference.com/w/cpp/named_req/Allocator#Fancy_pointers) (and fancy references). Associated fancy pointers and fancy reference (if any) are deduced from the allocator types. -Another use of fancy pointer is to create by-element "projections". #### Allocators and Fancy Pointers @@ -1174,20 +1022,21 @@ int main() { } } ``` +([live](https://godbolt.org/z/oeTss3s35)) (See also, examples of interactions with the CUDA Thrust library to see more uses of special pointer types to handle special memory.) #### Transformed views -Another kind of fancy-pointer is one that transforms the underlying values. +Another kind of use of the internal pointer-like type is to transform underlying values. These are useful to create "projections" or "views" of data elements. In the following example a "transforming pointer" is used to create a conjugated view of the elements. -In combination with transposed view, it can create a hermitic (transposed-conjugate) view of the matrix (without copying elements). +In combination with a transposed view, it can create a hermitic (transposed-conjugate) view of the matrix (without copying elements). We can adapt the library type `boost::transform_iterator` to save coding, but other libraries can be used also. -The hermitized view is read-only, but with additional work a read-write view can be created (see `multi::blas::hermitized` in multi-adaptors). +The hermitized view is read-only, but with additional work, a read-write view can be created (see `multi::::hermitized` in multi-adaptors). ```cpp -constexpr auto conj = [](auto const& c) -> auto const {return std::conj(c);}; +constexpr auto conj = [](auto const& c) {return std::conj(c);}; template struct conjr : boost::transform_iterator { template conjr(As const&... as) : boost::transform_iterator{as...} {} @@ -1202,7 +1051,7 @@ auto hermitized(Array2D const& arr) { } int main() { - using namespace std::complex_literals; + using namespace std::complex_literals; multi::array A = { { 1.0 + 2.0i, 3.0 + 4.0i}, { 8.0 + 9.0i, 10.0 + 11.0i} @@ -1215,23 +1064,23 @@ int main() { ``` To simplify this boilerplate, the library provides the `.element_transformed(F)` method that will apply a transformation `F` to each element of the array. -In this example the original arrays is transformed into a transposed array with duplicated elements. +In this example, the original array is transformed into a transposed array with duplicated elements. ```cpp - multi::array A = { - {1.0, 2.0}, - {3.0, 4.0}, - }; + multi::array A = { + {1.0, 2.0}, + {3.0, 4.0}, + }; - auto const scale = [](auto x) { return x * 2.0; }; + auto const scale = [](auto x) { return x * 2.0; }; - auto B = + A.rotated().element_transformed(scale); + auto B = + A.transposed().element_transformed(scale); assert( B[1][0] == A[0][1] * 2 ); ``` -([live](https://godbolt.org/z/b7E56Mjc8)) +([live](https://godbolt.org/z/TYavYEG1T)) -Since `elements_transformed` is a reference (transformed view) to the original data, it is important to understand the semantics of evaluation and possible allocations incurred. +Since `element_transformed` is a reference-like object (transformed view) to the original data, it is important to understand the semantics of evaluation and possible allocations incurred. As mentioned in other sections using `auto` and/or `+` appropriately can lead to simple and efficient expressions. | Construction | Allocation of `T`s | Initialization (of `T`s) | Evaluation (of `fun`) | Notes | @@ -1249,6 +1098,263 @@ As mentioned in other sections using `auto` and/or `+` appropriately can lead to | `B = A.elements_transformed(fun);` | No, if sizes match | Possibly (when `B` was initialized) | Yes | `B` can't be declared `const`, it can be a writable subarray, preferred | | `B = + A.elements_transformed(fun);` | Yes | Possibly (when `B` was initialized) | Yes | Not recommended. | +## Reference documentation of fundamental types + +The library interface presents several closely related C++ types (classes) representing arrays. +The fundamental types represent multidimensional containers (called `array`), references that can refer to subsets of these containers (called `subarray`), and iterators. +In addition, there are other classes for advanced uses, such as multidimensional views of existing buffers (called `array_ref`) and non-resizable owning containers (called `static_array`). + +When using the library, it is simpler to start from `array`, and other types are rarely explicitly used, especially if using `auto`; +however, it is convenient for documentation to present the classes in a different order since the classes `subarray`, `array_ref`, `static_array`, and `array` have an *is-a* relationship (from left to right). +For example, `array_ref` has all the methods available to `subarray`, and `array` has all the operations of `array_ref`. +Furthermore, the *is-a* relationship is implemented through C++ public inheritance, so, for example, a reference of type `subarray&` can refer to a variable of type `array`. + +### class `multi::subarray` + +A subarray-reference is part (or a whole) of another larger array. +It is important to understand that `subarray`s have referential semantics, their elements are not independent of the values of the larger arrays they are part of. +To recover value semantics, the elements and structure of a `subarray` can be copied into a new array (type `array`, see later). +An instance of this class represents a subarray with elements of type `T` and dimensionality `D`, stored in memory described by the pointer type `P`. +(`T`, `D`, and `P` initials are used in this sense across the documentation unless indicated otherwise.) + +Instances of this class have reference semantics and behave like "language references" as much as possible. +As references, they cannot be rebinded or resized; assignments are always "deep". +They are characterized by a size that does not change. +They are usually the result of indexing over other `subarray`s and `array`s (generally of higher dimensions); +therefore, the library doesn't expose constructors for this class. +The whole object can be invalidated if the original array is destroyed. + +| Member types | | +|--- |--- | +| `value_type` | `multi::array` or, for `D == 1`, `iterator_traits

::value_type` (usually `T`) +| `reference` | `multi::subarray` or, for `D == 1`, `pointer_traits

::reference` (usually `T&`) +| `const_reference` | `multi::const_subarray` or, for `D == 1`, `pointer_traits

::rebind::reference` (usually `T const&`) +| `index` | indexing type in the leading dimension (usually `std::diffptr_t`) +| `size_type` | describe size (number of subarrays) in the leading dimension (signed version of pointer size type, usually `std::diffptr_t`) +| `index_range` | describe ranges of indices, constructible from braced indices types or from an `extension_type`. Can be continuous (e.g. `{2, 14}`) or strided (e.g. `{2, 14, /*every*/ 3}`) +| `extesion_type` | describe a contiguous range of indices, constructible from braced index (e.g. `{0, 10}`) or from a single integer size (e.g. 10, equivalent to `{0, 10}`). +| `difference_type` | describe index differences in leading dimension (signed version of pointer size type, usually `std::diffptr_t`) +| `pointer` | `multi::subarray_ptr or, for `D == 1, `P` (usually `T*`) +| `const_pointer` | `multi::const_subarray_ptr` or, for `D == 1, `pointer_traits

::rebind` (usually `T const*`) +| `iterator` | `multi::array_iterator_t` +| `const_iterator` | `multi::const_array_iterator_t` + +| Member fuctions | | +|--- |--- | +| (constructors) | not exposed; copy constructor is not available since the instances are not copyable; destructors are trivial since it doesn't own the elements | +| `size` | returns the size of the leading dimension | +| `extension` | returns a range that generates valid indices for the leading dimension, for example `{0, ... size() - 1}` | +| `sizes` | returns a tuple with the sizes in all dimensions, `std::get<0>(A.sizes()) == A.size()` | +| `extensions` | returns a tuple of ranges in all dimensions, `std::get<0>(A.extensions()) == A.extension()` | +| `operator=` | assigns the elements from the source; the sizes must match | + +It is important to note that assignments in this library are always "deep," and reference-like types cannot be rebound after construction. +(Reference-like types have corresponding pointer-like types that provide an extra level of indirection and can be rebound (just like language pointers); +these types are `multi::array_ptr` and `multi::subarray_ptr` corresponding to `multi::array_ref` and `multi::subarray` respectively.) + +| Relational fuctions | | +|--- |--- | +| `operator==`/`operator!=` | Tells if elements of two `subarray` are equal (and if extensions of the subarrays are the same) +| `operator<`/`operator<=` | Less-than/less-or-equal lexicographical comparison (requires elements to be comparable) +| `operator>`/`operator>=` | Greater-than/grater-or-equal lexicographical comparison (requires elements to be comparable) + +It is important to note that, in this library, comparisons are always "deep". +Lexicographical order is defined recursively, starting from the first dimension index and from left to right. +For example, `A < B` if `A[0] < B[0]`, or `A[0] == B[0]` and `A[1] < B[1]`, or ..., etc. +Lexicographical order applies naturally if the extensions of `A` and `B` are different; however, their dimensionalities must match. +(See sort examples). + +| Element access | | +|--- |--- | +|`operator[]` | access specified element by index (single argument), returns a `reference` (see above), for `D > 1` it can be used recursively | +|`front` | access first element (undefined result if array is empty). Takes no argument. +|`back` | access last element (undefined result if array is empty). Takes no argument. +|`operator()` | When used with zero arguments, it returns a `subarray` representing the whole array. When used with one argument, access a specified element by index (return a `reference`) or by range (return a `subarray` of equal dimension). For more than one, arguments are positional and reproduce expected array access syntax from Fortran or Matlab: | + +- `subarray::operator()(i, j, k, ...)`, as in `S(i, j, k)` for indices `i`, `j`, `k` is a synonym for `A[i][j][k]`, the number of indices can be lower than the total dimension (e.g., `S` can be 4D). +Each index argument lowers the dimension by one. +- `subarray::operator()(ii, jj, kk)`, the arguments can be indices or ranges of indices (`index_range` member type). +This function allows positional-aware ranges. +Each index argument lowers the rank by one. +A special range is given by `multi::_`, which means "the whole range" (also spelled `multi::all`). +For example, if `S` is a 3D of sizes 10-by-10-by-10, `S(3, {2, 8}, {3, 5})` gives a reference to a 2D array where the first index is fixed at 3, with sizes 6-by-2 referring the subblock in the second and third dimension. +Note that `S(3, {2, 8}, {3, 5})` (6-by-2) is not equivalent to `S[3]({2, 8})({3, 5})` (2-by-10). +- `operator()()` (no arguments) gives the same array but always as a subarray type (for consistency), `S()` is equivalent to `S(S.extension())` and, in turn to `S(multi::_)` or `S(multi::all)`. + +| Structure access | (Generally used for interfacing with C-libraries) | +|--- |--- | +| `base` | direct access to underlying memory pointer (`S[i][j]... == S.base() + std::get<0>(S.strides())*i + std::get<1>(S.strides())*j + ...`) +| `stride` | return the stride value of the leading dimension, e.g `(&A[1][0][0]... - &A[0][0]...)` +| `strides` | returns a tuple with the strides defining the internal layout +| `layout` | returns a single layout object with stride and size information | + +| Iterators | | +|--- |--- | +| `begin/cbegin` | returns (const) iterator to the beginning +| `end/cend` | returns (const) iterator to the end + +| Capacity | | +|--- |--- | +| `sizes` | returns a tuple with the sizes in each dimension +| `extensions` | returns a tuple with the extensions in each dimension +| `size` | returns the number of subarrays contained in the first dimension | +| `extension` | returns a contiguous index range describing the set of valid indices +| `num_elements` | returns the total number of elements + +| Creating views | (these operations do not copy elements or allocate) | +|--- |--- | +| `broadcasted` | returns a view of dimensionality `D + 1` obtained by infinite repetition of the original array. (This returns a special kind of subarray with a degenerate layout and no size operation. Takes no argument.) +| `dropped` | (takes one integer argument `n`) returns a subarray with the first n-elements (in the first dimension) dropped from the original subarray. This doesn't remove or destroy elements or resize the original array +| `element_transformed` | creates a view of the array, where each element is transformed according to a function (first and only argument) | +| `elements` | a flatted view of all the elements rearranged canonically. `A.elements()[0] -> A[0][0]`, `A.elements()[1] -> A[0][1]`, etc. The type of the result is not a subarray but a special kind of range. Takes no argument. +| `rotated/unrotated` | a view (`subarray`) of the original array with indices (un)rotated from right to left (left to right), for `D = 1` returns the same `subarray`. For given `i`, `j`, `k`, `A[i][j][k]` gives the same element as `A.rotated()[j][k][i]` and, in turn the same as `A.unrotated()[k][i][j])`. Preserves dimension. The function is cyclic; `D` applications will give the original view. Takes no argument. | +| `transposed` (same as `operator~`) | a view (`subarray`) of the original array with the first two indices exchanged, only available for `D > 1`; for `D = 2`, `rotated`, `unrotated` and `transposed` give same view. Takes no argument. | +| `sliced` | (takes two index arguments `a` and `b`) returns a subarray with elements from index `a` to index `b` (non-inclusive) `{S[a], ... S[b-1]}`. Preserves the dimension. +| `strided` | (takes one integer argument `s`) returns a subarray skipping `s` elements. Preserves the dimension. + +| Creating views by pointer manipulation | | +|--- |--- | +| `static_cast_array(args...)` | produces a view where the underlying pointer constructed by `P2{A.base(), args...}`. Usually, `args...` is empty. Non-empty arguments are useful for stateful fancy pointers, such as transformer iterators. +| `reinterpret_cast_array` | underlying elements are reinterpreted as type T2, element sizes (`sizeof`) have to be equal; `reinterpret_cast_array(n)` produces a view where the underlying elements are interpreted as an array of `n` elements of type `T2`. + +| Creating arrays | | +|--- |--- | +| `decay` (same as prefix unary `operator+`) | creates a concrete independent `array` with the same dimension and elements as the view. Usually used to force a value type (and forcing a copy of the elements) and avoid the propagation of a reference type in combination with `auto` (e.g., `auto A2_copy = + A[2];`). + +A reference `subarray` can be invalidated when its origin array is invalidated or destroyed. +For example, if the `array` from which it originates is destroyed or resized. + +### class `multi::array_ref` + +A D-dimensional view of the contiguous pre-existing memory buffer. +This class doesn't manage the elements it contains, and it has reference semantics (it can't be rebound, assignments are deep, and have the same size restrictions as `subarray`) + +Since `array_ref` is-a `subarray`, it inherits all the class methods and types described before and, in addition, it defines these members below. + +| Member types | same as for `subarray` | +|--- |--- | + +| Member functions | same as for `subarray` plus ... | +|--- |--- | +| (constructors) | `array_ref::array_ref({e1, e2, ...}, p)` constructs a D-dimensional view of the contiguous range starting at p and ending at least after the size size of the multidimensional array (product of sizes). The default constructor and copy constructor are not exposed. Destructor is trivial since elements are not owned or managed. | + +| Element access | same as for `subarray` | +|--- |--- | + +| Structure access | same as for `subarray` | +|--- |--- | + +| Iterators | same as for `subarray` | +|--- |--- | + +| Capacity | same as for `subarray` | +|--- |--- | + +| Creating views | same as for `subarray` | +|--- |--- | + +| Creating arrays | same as for `subarray` | +|--- |--- | + +| Relational functions | same as for `subarray` | +|--- |--- | + +An `array_ref` can be invalidated if the original buffer is deallocated. + +### class `multi::static_array >` + +A D-dimensional array that manages an internal memory buffer. +This class owns the elements it contains; it has restricted value semantics because assignments are restricted to sources with equal sizes. +Memory is requested by an allocator of type Alloc (standard allocator by default). +It supports stateful and polymorphic allocators, which are the default for the special type `multi::pmr::static_array`. + +The main feature of this class is that its iterators, subarrays, and pointers do not get invalidated unless the whole object is destroyed. +In this sense, it is semantically similar to a C-array, except that elements are allocated from the heap. +It can be useful for scoped uses of arrays and multi-threaded programming and to ensure that assignments do not incur allocations. +The C++ coreguiles proposed a similar (albeith one-dimensional) class, called [`gsl::dyn_array`](http://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#gslowner-ownership-pointers). + +For most uses, a `multi::array` should be preferred instead. + +| Member types | same as for `array_ref` | +|--- |--- | + +| Member fuctions | same as for `array_ref` plus ... | +|--- |--- | +| (constructors) | `static_array::static_array({e1, e2, ...}, T val = {}, Alloc = {})` constructs a D-dimensional array by allocating elements. `static_array::static_array(std::initializer_list<...>` constructs the array with elements initialized from a nested list. +| (destructor) | Destructor deallocates memory and destroy the elements | +| `operator=` | assigns the elements from the source, sizes must match. + +| Element access | same as for `array_ref` | +|--- |--- | + +| Structure access | same as for `array_ref` | +|--- |--- | + +| Iterators | same as for `array_ref` | +|--- |--- | + +| Capacity | same as for `array_ref` | +|--- |--- | + +| Creating views | same as for `array_ref` | +|--- |--- | + +| Creating arrays | same as for `array_ref` | +|--- |--- | + +| Relational fuctions | same as for `array_ref` | +|--- |--- | + +### class `multi::array >` + +An array of integer positive dimension D has value semantics if element type T has value semantics. +It supports stateful and polymorphic allocators, which is implied for the special type `multi::pmr::array`. + +| Member types | same as for `static_array` | +|--- |--- | + +| Member fuctions | | +|--- |--- | +| (constructors) | `array::array({e1, e2, ...}, T val = {}, Alloc = {})` constructs a D-dimensional array by allocating elements;`array::array(It first, It last)` and `array::array(Range const& rng)`, same for a range of subarrays. `static_array::static_array(std::initializer_list<...>, Alloc = {})` constructs the array with elements initialized from a nested list. +| (destructor) | Destructor deallocates memory and destroy the elements | +| `operator=` | assigns for a source `subarray`, or from another `array`. `array`s can be moved | + +| Element access | same as for `static_array` | +|--- |--- | + +| Structure access | same as for `static_array` | +|--- |--- | + +| Iterators | same as for `static_array` | +|--- |--- | + +| Capacity | same as for `static_array` | +|--- |--- | + +| Creating views | same as for `static_array` | +|--- |--- | + +| Creating arrays | same as for `static_array` | +|--- |--- | + +| Relational fuctions | same as for `static_array` | +|--- |--- | + +| Manipulation | | +|--- |--- | +| `clear` | Erases all elements from the container. The array is resized to zero size. | +| `reextent` | Changes the size of the array to new extensions. `reextent({e1, e2, ...})` elements are preserved when possible. New elements are initialized with a default value `v` with a second argument `reextent({e1, e2, ...}, v)`. The first argument is of `extensions_type`, and the second is optional for element types with a default constructor. + +### class `multi::subarray::(const_)iterator` + +A random-access iterator to subarrays of dimension `D - 1`, that is generally used to interact with or implement algorithms. +They can be default constructed but do not expose other constructors since they are generally created from `begin` or `end`, manipulated arithmetically, `operator--`, `operator++` (pre and postfix), or random jumps `operator+`/`operator-` and `operator+=`/`operator-=`. +They can be dereferenced by `operator*` and index access `operator[]`, returning objects of lower dimension `subarray::reference` (see above). +Note that this is the same type for all related arrays, for example, `multi::array::(const_)iterator`. + +`iterator` can be invalidated when its original array is invalidated, destroyed or resized. +An `iterator` that stems from `static_array` becomes invalid only if the original array was destroyed or out-of-scope. + # Interoperability with other software ## STL (Standard Template Library) @@ -1273,7 +1379,7 @@ In this example, we replace the values of the first row for which the sum of the {2, 2, 0, 4}, }; - auto const row = std::ranges::find_if(arr, [](auto const& r) { return accumulate(r) %2 == 1; }); + auto const row = std::ranges::find_if(arr, [](auto const& r) { return accumulate(r) % 2 == 1; }); if(row != arr.end()) std::ranges::fill(*row, 9); assert(arr[1][0] == 9 ); @@ -1309,11 +1415,11 @@ for example, lexicographical sorting on rows can be performed with the `std::ran {'A', 'l', 'e', 'x', ' ', ' '}, {'B', 'j', 'a', 'r', 'n', 'e'}, }; - assert(not std::ranges::is_sorted(A)); + assert(!std::ranges::is_sorted(A)); - std::ranges::sort(A); + std::ranges::sort(A); // will sort on rows - assert( std::ranges::is_sorted(A)); + assert( std::ranges::is_sorted(A)); assert( A == multi::array{ @@ -1380,9 +1486,9 @@ auto dot_product(X1D const& x, Y1D const& y) { ### Polymorphic Memory Resources -In addition to supporting classic allocators (`std::allocator` by default), the library is compatible with C++17's [polymorphic memory resources (PMR)](https://en.cppreference.com/w/cpp/header/memory_resource) which allows using advanced allocation strategies, including preallocated buffers. +In addition to supporting classic allocators (`std::allocator` by default), the library is compatible with C++17's [polymorphic memory resources (PMR)](https://en.cppreference.com/w/cpp/header/memory_resource), which allows using advanced allocation strategies, including preallocated buffers. This example code uses a buffer as memory for two arrays; -in it a predefined buffer ends up containing the data of the arrays, something like `"aaaabbbbbbXX"`. +in it, a predefined buffer will contain the arrays' data (something like `"aaaabbbbbbXX"`). ```cpp #include // for polymorphic memory resource, monotonic buffer @@ -1401,7 +1507,7 @@ int main() { `multi::pmr::array` is a synonym for `multi::array>`. In this particular example, the technique can be used to avoid dynamic memory allocations of small local arrays. [(live)](https://godbolt.org/z/fP9P5Ksvb) -The library also supports memory resources from other libraries, including those returning special pointer types (see [CUDA Thrust](#cuda-thrust) Thurst section, and Boost.Interprocess section). +The library also supports memory resources from other libraries, including those returning special pointer types (see the [CUDA Thrust](#cuda-thrust) section and the Boost.Interprocess section). ### Substitutability with standard vector and span @@ -1766,12 +1872,12 @@ More targeted usage patterns may require locally (non-globally) defined memory r ## CUDA C++ -CUDA is a dialect of C++ that allows writing pieces of code directly for GPU execution, known as "CUDA kernels". +CUDA is a dialect of C++ that allows writing pieces of code for GPU execution, known as "CUDA kernels". CUDA code is generally "low level" (less abstracted) but it can be used in combination with CUDA Thrust or the CUDA runtime library, specially to implement custom algorithms. -Although code inside kernels has certain restrictions, most Multi expressions can be used. +Although code inside kernels has certain restrictions, most Multi features can be used. (Most functions in Multi, except those involving memory allocations, are marked `__device__` to allow this.) -Calling kernels involves a special syntax (`<<< ... >>>`), and they cannot take arguments by reference (or by values that are not trivial, e.g. not entirely contained in the stack). +Calling kernels involves a special syntax (`<<< ... >>>`), and they cannot take arguments by reference (or by values that are not trivial). Since arrays are usually passed by reference (e.g. `multi::array&` or `Array&&`), a different idiom needs to be used. (Large arrays are not passed by value to avoid copies, but even if a copy would be fine, kernel arguments cannot allocate memory themselves.) Iterators (e.g. `.begin()/.end()`) and "cursors" (e.g. `.home()`) are "trivial to copy" and can be passed by value and represent a "proxy" to an array, including allowing the normal index syntax and other transformations. @@ -1779,6 +1885,7 @@ Iterators (e.g. `.begin()/.end()`) and "cursors" (e.g. `.home()`) are "trivial t Cursors are a generalization of iterators for multiple dimensions. They are cheaply copied (like iterators) and they allow indexing. Also, they have no associated `.size()` or `.extensions()`, but this is generally fine for kernels. +(Since `cursors` have minimal information for indexing, they can save stack/register space in individual kernels.) Here it is an example implementation for matrix multiplication, in combination with Thrust and Multi, @@ -1818,6 +1925,8 @@ int main() { ``` [(live)](https://godbolt.org/z/eKbeosrWa) +Expressions such as `A.begin()` (iterators) can also be passed to kernels, but they could unnecessarely occupy more kernel "stack space" when size information is not needed (e.g. `A.begin()->size()`). + ## SYCL The SYCL library promises the unify CPU, GPU and FPGA code. @@ -1848,8 +1957,9 @@ Algorithms are expected to work with oneAPI execution policies as well (not test ## Formatting ({fmt} pretty printing) -The library doesn't have a "pretty" printing facility to display arrays; -fortunatelly it automatically works with the external library [{fmt}](https://fmt.dev/latest/index.html), both for arrays and subarrays. +The library doesn't have a "pretty" printing facility to display arrays. +Although not ideal, arrays can be printed and formatting by looping over elements and dimensions, as shown as examples in this documentation, +Fortunatelly the library automatically works with the external library [{fmt}](https://fmt.dev/latest/index.html), both for arrays and subarrays. The fmt library is not a dependency of the Multi library; they simply work well together using the "ranges" part of the formatting library. This example prints a 2-dimensional subblock of a larger array. @@ -1868,8 +1978,6 @@ This example prints a 2-dimensional subblock of a larger array. ``` with the "flat" output `A2 subblock = [[3, 4], [6, 7]]` -https://godbolt.org/z/EE5sqTdvf - For 2 or more dimensions the output can be conveniently structured in different lines using the `fmt::join` facility: ```cpp @@ -1881,47 +1989,61 @@ with the output: > [3, 4] > [6, 7] > ``` +https://godbolt.org/z/vjc6n1ove + When saving arrays to files, consider using serialization (see section) instead. ## Legacy libraries (C-APIs) -Multi dimensional array data structures exists in all languages, whether implicitly defined by its strided structure or at the language level. -Functions written in C tend to receive arrays by pointer arguments (e.g. to "first" element) and memory layout (sizes and strides). +Multi-dimensional array data structures exist in all languages, whether implicitly defined by its strides structure or explicitly at the language level. +Functions written in C tend to receive arrays by pointer arguments (e.g., to the "first" element) and memory layout (sizes and strides). A C-function taking a 2D array with a concrete type might look like this in the general case: - ```c void fun(double* data, int size1, int size2, int stride1, int stride2); ``` - -The function can be called from C++ using arguments derived from Multi arrays: - +such a function can be called from C++ on Multi array (`arr`), by extracting the size and layout information, ```cpp fun(arr.base(), std::get<0>(arr.sizes()), std::get<1>(arr.sizes()), std::get<0>(arr.strides()), std::get<1>(arr.strides()); ``` - or - ```cpp auto const [size1, size2] = arr.sizes(); auto const [stride1, stride2] = arr.strides(); fun(arr.base(), size1, size2, stride1, stride2); ``` -Although the recipe can be applied straightforward, different libraries have various assumptions about memory layouts (e.g. BLAS 2D-arrays assume that the second stride is 1) and some might take stride information in a different way (e.g. FFTW doesn't use strides but stride-products). -Furthermore, some arguments may need to be permutted if the function expects arrays in column-major (Fortran) ordering. -For this reason the library is acompained with a series of adaptor libraries to popular C-based libraries, that can be found in the `include/multi/adaptors/` directory. -* BLAS -* Lapack -* FFTW/cuFFT +Although the recipe can be applied straightforwardly, different libraries make various assumptions about memory layouts (e.g., 2D arrays assume that the second stride is 1), and some might take stride information in a different way (e.g., FFTW doesn't use strides but stride products). +Furthermore, some arguments may need to be permuted if the function expects arrays in column-major (Fortran) ordering. + +For these reasons, the library is accompanied by a series of adaptor libraries to popular C-based libraries, which can be found in the `include/multi/adaptors/` subdirectory: + +- ##### [BLAS/cuBLAS Adator 🔗](include/boost/multi/adaptors/blas/README.md) + +Interface for BLAS-like linear algebra libraries, such as openblas, Apple's Accelerate, MKL and hipBLAS/cuBLAS (GPUs). +Simply `#include "multi/adaptors/blas.hpp"` (and link your program with `-lblas` for example). + +- ##### Lapack + +Interface for Lapack linear solver libraries. +Simply `#include "multi/adaptors/lapack.hpp"` (and link your program with `-llapack` for example). + +- ##### FFTW/cuFFT + +Interface for FFTW libraries, including FFTW 3, MKL, cuFFT/hipFFT (for GPU). +Simply `#include "multi/adaptors/fftw.hpp"` (and link your program with `-lfftw3` for example). + +- ##### [MPI Adaptor 🔗](include/boost/multi/adaptors/mpi/README.md) + +Use arrays (and subarrays) as messages for distributed interprocess communication (GPU and CPU) that can be passed to MPI functions through datatypes. +Simply `#include "multi/adaptors/mpi.hpp"`. -* cuBLAS -* cuFFT +- ##### TotalView: visual debugger (commercial) -* TotalView: visual debugger (commercial), popular in HPC environments, can display arrays in human-readable form (for simple types, like `double` or `std::complex`). -To use it, simply `#include "multi/adaptors/totalview.hpp"` and link to the TotalView libraries, compile and run the code with the TotalView debugger. +Popular in HPC environments, can display arrays in human-readable form (for simple types, like `double` or `std::complex`). +Simply `#include "multi/adaptors/totalview.hpp"` and link to the TotalView libraries, compile and run the code with the TotalView debugger. # Technical points @@ -1931,7 +2053,7 @@ The chained bracket notation (`A[i][j][k]`) allows to refer to elements and suba It is a frequently raised question whether the chained bracket notation is good for performance, since it appears that each utilization of the bracket leads to the creation of a temporary object which in turn generates a partial copy of the layout. Moreover, this goes against [historical recommendations](https://isocpp.org/wiki/faq/operator-overloading#matrix-subscript-op). -It turns out that modern compilers with a fair level of optimization (`-O2`) can elide these temporary objects, so that `A[i][j][k]` generates identical assembly code as `A.base() + i*stride1 + j*stride2 + k*stride3` (+offsets not shown). +It turns out that modern compilers with a fair level of optimization (`-O2`) can elide these temporary objects, so that `A[i][j][k]` generates identical machine code as `A.base() + i*stride1 + j*stride2 + k*stride3` (+offsets not shown). In a subsequent optimization, constant indices can have their "partial stride" computation removed from loops. As a result, these two loops lead to the [same machine code](https://godbolt.org/z/ncqrjnMvo): @@ -1944,7 +2066,8 @@ As a result, these two loops lead to the [same machine code](https://godbolt.org for(long j = 0; j != M; ++j) {acc += *(base + j*std::get<1>(A.strides()));} ``` -Incidentally, the library also supports parenthesis notation with multiple indices `A(i, j, k)` for element or partial access, but it does so as part of a more general syntax to generate sub-blocks. +Incidentally, the library also supports parenthesis notation with multiple indices `A(i, j, k)` for element or partial access; +it does so as part of a more general syntax to generate sub-blocks. In any case `A(i, j, k)` is expanded to `A[i][j][k]` internally in the library when `i`, `j`, `k` are normal integer indices. For this reason, `A(i, j, k)`, `A(i, j)(k)`, `A(i)(j)(k)`, `A[i](j)[k]` are examples of equivalent expressions. @@ -1954,13 +2077,14 @@ Note also that `A({i0, i1}, j, k)` is not equivalent to `A({i0, i1})(j, k)`; the Additionally, array coordinates can be directly stored in tuple-like data structures, allowing this functional syntax: ```cpp -std::array p = {2, 3, 4}; +std::array p = {2, 3, 4}; std::apply(A, p) = 234; // same as assignment A(2, 3, 4) = 234; and same as A[2][3][4] = 234; ``` ### Iteration past-end in the abstract machine -It's crucial to grasp that pointers are limited to referencing valid memory in the strict C abstract machine, such as allocated memory. This understanding is key to avoiding undefined behavior in your code. +It's crucial to grasp that pointers are limited to referencing valid memory in the strict C abstract machine, such as allocated memory. +This understanding is key to avoiding undefined behavior in your code. Since the library iteration is pointer-based, the iterators replicate these restrictions. There are three cases to consider; the first two can be illustrated with one-dimensional arrays, and one is intrinsic to multiple dimensions. @@ -1992,42 +2116,121 @@ This library can replace Boost.MultiArray in most contexts, it even fulfillis th Boost.MultiArray has technical and semantic limitations that are overcome in this library, regarding layouts and references; it doesn't support value-semantics, iterator support is limited and it has other technical problems. -[Eigen](https://eigen.tuxfamily.org/index.php?title=Main_Page) is a very popular matrix linear algebra library, and as such, it only handles the special 2D (and 1D) array case. -Instead, the Multi library is dimension-generic and doesn't make any algebraic assumptions for arrays or contained elements (but still can be used to _implement_ dense linear algebra algorithms.) +[Eigen](https://eigen.tuxfamily.org/index.php?title=Main_Page) is a very popular matrix linear algebra framework library, and as such, it only handles the special 2D (and 1D) array case. +Instead, the Multi library is dimension-generic and doesn't make any algebraic assumptions for arrays or contained elements (but still can be used to _implement_, or in combination, with dense linear algebra algorithms.) + +Other frameworks includes the OpenCV (Open Computing Vision) framework, which is too specialized to make a comparison here. Here is a table comparing with `mdspan`, R. Garcia's [Boost.MultiArray](https://www.boost.org/doc/libs/1_82_0/libs/multi_array/doc/user.html) and Eigen. [(online)](https://godbolt.org/z/555893MqW). -| | Multi | mdspan | Boost.MultiArray (R. Garcia) | Inria's Eigen | +| | Multi | mdspan/mdarray | Boost.MultiArray (R. Garcia) | Inria's Eigen | |--- | --- | --- | --- | --- | -| No external Deps | **yes** (only Standard Library C++17) | **yes** (only Standard Library) | **yes** (only Boost) | **yes** | +| No external Deps | **yes** (only Standard Library C++17) | **yes** (only Standard Library C++17/C++26) | **yes** (only Boost) | **yes** | | Arbritary number of dims | **yes**, via positive dimension (compile-time) parameter `D` | **yes** | **yes** | no (only 1D and 2D) | | Non-owning view of data | **yes**, via `multi::array_ref(ptr, {n1, n2, ..., nD})` | **yes**, via `mdspan m{T*, extents{n1, n2, ..., nD}};` | **yes**, via `boost::multi_array_ref(T*, boost::extents[n1][n2]...[nD])` | **yes**, via `Eigen::Map>(ptr, n1, n2)` | | Compile-time dim size | no | **yes**, via template paramaters `mdspan{T*, extent<16, dynamic_extents>{32} }` | no | **yes**, via `Eigen::Array` | -| Array values (owning data) | **yes**, via `multi::array({n1, n2, ..., nD})` | no, (planned `mdarray`) | **yes**, via `boost::multi_array(boost::extents[n1][n2]...[nD])` | **yes**, via `Eigen::Array(n1, n2)` | -| Value semantic (Regular) | **yes**, via cctor, mctor, assign, massign, auto decay of views | no, and not planned | partial, assigment on equal extensions | **yes** (?) | -| Move semantic | **yes**, via mctor and massign | no | no (C++98 library) | **yes** (?) | -| const-propagation semantics | **yes**, via `const` or `const&` | no, const mdspan elements are assignable! | no, inconsistent | (?) | -| Element initialization | **yes**, via nested init-list | no | no | no, only delayed init via `A << v1, v2, ...;` | -| References w/no-rebinding | **yes**, assignment is deep | no, assignment of mdspan rebinds! | **yes** | **yes** (?) | -| Element access | **yes**, via `A(i, j, ...)` or `A[i][j]...` | **yes**, via `A(i, j, ...)` | **yes**, via `A[i][j]...` | **yes**, via `A(i, j)` (2D only) | -| Partial element access | **yes**, via `A[i]` or `A(i, multi::all)` | **yes**, via `submdspan(A, i, full_extent)` | **yes**, via `A[i]` | **yes**, via `A.row(i)` | +| Array values (owning data) | **yes**, via `multi::array({n1, n2, ..., nD})` | yes for `mdarray` | **yes**, via `boost::multi_array(boost::extents[n1][n2]...[nD])` | **yes**, via `Eigen::Array(n1, n2)` | +| Value semantic (Regular) | **yes**, via cctor, mctor, assign, massign, auto decay of views | yes (?) for `mdarray` planned | partial, assigment on equal extensions | **yes** (?) | +| Move semantic | **yes**, via mctor and massign | yes (?) for `mdarray` (depends on adapted container) | no (C++98 library) | **yes** (?) | +| const-propagation semantics | **yes**, via `const` or `const&` | no, const mdspan elements are assignable! | no, inconsistent | (?) | +| Element initialization | **yes**, via nested init-list | no (?) | no | no, only delayed init via `A << v1, v2, ...;` | +| References w/no-rebinding | **yes**, assignment is deep | no, assignment of mdspan rebinds! | **yes** | **yes** (?) | +| Element access | **yes**, via `A(i, j, ...)` or `A[i][j]...` | **yes**, via `A[i, j, ...]` | **yes**, via `A[i][j]...` | **yes**, via `A(i, j)` (2D only) | +| Partial element access | **yes**, via `A[i]` or `A(i, multi::all)` | no, only via `submdspan(A, i, full_extent)` | **yes**, via `A[i]` | **yes**, via `A.row(i)` | | Subarray views | **yes**, via `A({0, 2}, {1, 3})` or `A(1, {1, 3})` | **yes**, via `submdspan(A, std::tuple{0, 2}, std::tuple{1, 3})` | **yes**, via `A[indices[range(0, 2)][range(1, 3)]]` | **yes**, via `A.block(i, j, di, dj)` | -| Subarray with lower dim | **yes**, via `A(1, {1, 3})` | **yes**, via `submdspan(A, 1, std::tuple{1, 3})` | **yes**, via `A[1][indices[range(1, 3)]]` | **yes**, via `A(1, Eigen::placeholders::all)` | -| Subarray w/well def layout | **yes** (strided layout) | no | **yes** (strided layout) | **yes** (strided) | -| Recursive subarray | **yes** (layout is stack-based and owned by the view) | **yes** (?) | no (subarray may dangle layout, design bug?) | **yes** (?) (1D only) | -| Custom Alloctors | **yes**, via `multi::array` | no (no allocation or ownership) | **yes** (stateless?) | no | -| PMR Alloctors | **yes**, via `multi::pmr::array` | no (no allocation or ownership) | no | no | -| Fancy pointers / references | **yes**, via `multi::array` or views | no | no | no | -| Strided Layout | **yes** | **yes** | **yes** | **yes** | -| Fortran-ordering | **yes**, only for views, e.g. resulted from transposed views | **yes** (only views are supported) | **yes** | **yes** | -| Zig-zag / Hilbert ordering | no | **yes**, via arbitrary layouts (no inverse or flattening) | no | no | -| Arbitrary layout | no | **yes**, possibly inneficient, no efficient slicing | no | no | +| Subarray with lower dim | **yes**, via `A(1, {1, 3})` | **yes**, via `submdspan(A, 1, std::tuple{1, 3})` | **yes**, via `A[1][indices[range(1, 3)]]` | **yes**, via `A(1, Eigen::placeholders::all)` | +| Subarray w/well def layout | **yes** (strided layout) | no | **yes** (strided layout) | **yes** (strided) | +| Recursive subarray | **yes** (layout is stack-based and owned by the view) | **yes** (?) | no (subarray may dangle layout, design bug?) | **yes** (?) (1D only) | +| Custom Alloctors | **yes**, via `multi::array` | yes(?) through `mdarray`'s adapted container | **yes** (stateless?) | no | +| PMR Alloctors | **yes**, via `multi::pmr::array` | yes(?) through `mdarray`'s adapted container | no | no | +| Fancy pointers / references | **yes**, via `multi::array` or views | no | no | no | +| Stride-based Layout | **yes** | **yes** | **yes** | **yes** | +| Fortran-ordering | **yes**, only for views, e.g. resulted from transposed views | **yes** | **yes**. | **yes** | +| Zig-zag / Hilbert ordering | no | **yes**, via arbitrary layouts (no inverse or flattening) | no | no | +| Arbitrary layout | no | **yes**, possibly inneficient, no efficient slicing | no | no | | Flattening of elements | **yes**, via `A.elements()` range (efficient representation) | **yes**, but via indices roundtrip (inefficient) | no, only for allocated arrays | no, not for subblocks (?) | -| Iterators | **yes**, standard compliant, random-access-iterator | no, or very limited | **yes**, limited | no | +| Iterators | **yes**, standard compliant, random-access-iterator | no | **yes**, limited | no | | Multidimensional iterators (cursors) | **yes** (experimental) | no | no | no | | STL algorithms or Ranges | **yes** | no, limited via `std::cartesian_product` | **yes**, some do not work | no | | Compatibility with Boost | **yes**, serialization, interprocess (see below) | no | no | no | -| Compatibility with Thrust or GPUs | **yes**, via flatten views (loop fusion), thrust-pointers/-refs | no | no | no | -| Used in production | [QMCPACK](https://qmcpack.org/), [INQ](https://gitlab.com/npneq/inq) | (?) , experience from Kokkos incarnation | **yes** (?) | [**yes**](https://eigen.tuxfamily.org/index.php?title=Main_Page#Projects_using_Eigen) | +| Compatibility with Thrust or GPUs | **yes**, via flatten views (loop fusion), thrust-pointers/-refs | no | no | no | +| Used in production | [QMCPACK](https://qmcpack.org/), [INQ](https://gitlab.com/npneq/inq) | (?) , experience from Kokkos incarnation | **yes** (?) | [**yes**](https://eigen.tuxfamily.org/index.php?title=Main_Page#Projects_using_Eigen) | + +# Appendix: Multi for FORTRAN programmers + +This section summarizes simple cases translated from FORTRAN syntax to C++ using the library. +The library strives to give a familiar feeling to those who use arrays in FORTRAN, including the manipulation of arrays with arbitrary dimensionality (e.g. 1D, 2D, 3D, etc.) +Arrays can be indexes arrays using square-brakers or using parenthesis, which would be more familiar to FORTRAN syntax. +The most significant difference is that in FORTRAN, array indices start at `1` by default, while in Multi, they start at `0` by default, following C++ conventions. +Like in FORTRAN, for simple types (e.g., numeric), Multi arrays are not initialized automatically; such initialization needs to be explicit. + +| | FORTRAN | C++ Multi | +|--- | --- | --- | +| Declaration/Construction 1D | `real, dimension(2) :: numbers` (at top) | `multi::array numbers(2);` (at scope) | +| Initialization (2 elements) | `real, dimension(2) :: numbers = [ 1.0, 2.0 ]` | `multi::array numbers = { 1.0, 2.0 };` | +| Element assignment | `numbers(2) = 99.0` | `numbers(1) = 99.0;` (or `numbers[1]`) | +| Element access (print 2nd) | `Print *, numbers(2)` | `std::cout << numbers(1) << '\n';` | +| Initialization | `DATA numbers / 10.0 20.0 /` | `numbers = {10.0, 20.0};` | + +In the more general case for the dimensionality, we have the following correspondance: + +| | FORTRAN | C++ Multi | +|--- | --- | --- | +| Construction 2D (3 by 3) | `real*8 :: A2D(3,3)` (at top) | `multi::array A2D({3, 3});` (at scope) | +| Construction 2D (2 by 2) | `real*8 :: B2D(2,2)` (at top) | `multi::array B2D({2, 2});` (at scope) | +| Construction 1D (3 elements) | `real*8 :: v1D(3)` (at top) | `multi::array v1D({3});` (at scope) | +| Assign the 1st column of A2D | `v1D(:) = A2D(:,1)` | `v1( _ ) = A2D( _ , 0 );` | +| Assign the 1st row of A2D | `v1D(:) = A2D(1,:)` | `v1( _ ) = A2D( 0 , _ );` | +| Assign upper part of A2D | `B2D(:,:) = A2D(1:2,1:2)` | `B2D( _ , _ ) = A2D({0, 2}, {0, 2});` | + +Note that these correspondences are notationally logical. +Internal representation (memory ordering) can still be different, and this could affect operations that interpret 2D arrays as contiguous elements in memory. + +Range notation such as `1:2` is replaced by `{0, 2}`, which takes into account both the difference in the start index and the half-open interval notation in the C++ conventions. +Stride notation such as `1:10:2` (i.e. from first to tenth included, every 2 elements), is replaced by `{0, 10, 2}`. +Complete range interval (single `:` notation) is replaced by `multi::_`, which can be used simply as `_` after the declaration `using multi::_;`. +These rules extend to higher dimesionality, such as 3 dimensions. + +Unlike FORTRAN, Multi doesn't provide algebraic operators, using algorithms is encouraged instead. +For example a FORTRAN statement like `A = A + B` is translated as this in the one-dimensional case: + +```cpp +std::transform(A.begin(), A.end(), B.begin(), A.begin(), std::plus{}); // valid for 1D arrays only +``` + +In the general dimensionality case we can write: + +```cpp +auto&& Aelems = A.elements(); +auto const& Belems = B.elements(); +std::transform(Aelems.begin(), A.elems.end(), Belems.begin(), Aelems.begin(), std::plus{}); // valid for arbitrary dimension +``` + +or +``` +std::ranges::transform(Aelems, Belems, Aelems.begin(), std::plus{}); // alternative using C++20 ranges +``` + +A FORTRAN statement like `C = 2.0*C` is rewritten as `std::ranges::transform(C.elements(), C.elements().begin(), [](auto const& e) {return 2.0*e;});`. + +It is possible to use C++ operator overloading for functions such as `operartor+=` (`A += B;`) or `operator*=` (`C *= 2.0;`); however, this possibility can become unwindenly complicated beyond simple cases. +Also it can become inefficient if implemented naively. + +Simple loops can be mapped as well, taking into account indexing differences: +```fortran +do i = 1, 5 ! for(int i = 0; i != 5; ++i) { + do j = 1, 5 ! for(int j = 0; j != 5; ++j) { + D2D(i, j) = 0 ! D2D(i, j) = 0; + end do ! } +end do ! } +``` + +However, algorithms like `transform`, `reduce`, `transform_reduce`and `for_each`, and offer a higher degree of control over operations, including memory allocations if needed, and even enable parallelization, providing a higher level of flexibility. + + +[(live)](https://godbolt.org/z/77onne46W) + + +> Thanks to Joaquín López Muñoz and Andrzej Krzemienski for the critical reading of the documentation and to Matt Borland for his help integrating Boost practices in the testing code. diff --git a/external_codes/boost_multi/multi/benchmark/algorithms_gemm.cpp b/external_codes/boost_multi/multi/benchmark/algorithms_gemm.cpp index df0e85f233..bcacbbb9ce 100644 --- a/external_codes/boost_multi/multi/benchmark/algorithms_gemm.cpp +++ b/external_codes/boost_multi/multi/benchmark/algorithms_gemm.cpp @@ -1,13 +1,12 @@ -// -*-indent-tabs-mode:t;c-basic-offset:4;tab-width:4;autowrap:nil;-*- -// © Alfredo Correa 2021 +// Copyright 2019-2024 Alfredo A. Correa +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt -#define BOOST_TEST_MODULE "C++ Unit Tests for Multi gemm (not blas)" -#define BOOST_TEST_DYN_LINK #include -#include "../array.hpp" +#include -#include "../algorithms/gemm.hpp" +#include #include #include diff --git a/external_codes/boost_multi/multi/examples/bip_mapped_file.cpp b/external_codes/boost_multi/multi/examples/bip_mapped_file.cpp index 79b8602c81..163f5b2556 100644 --- a/external_codes/boost_multi/multi/examples/bip_mapped_file.cpp +++ b/external_codes/boost_multi/multi/examples/bip_mapped_file.cpp @@ -1,22 +1,14 @@ -#ifdef COMPILATION // clang-format off -${CXX:-c++} -std=c++17 $CXXFLAGS -I../include $0 -o $0.$X -lboost_unit_test_framework&&$0.$X&&rm $0.$X;exit -#endif // clang-format on // Copyright 2019-2024 Alfredo A. Correa - -#define BOOST_TEST_MODULE "C++ Unit Tests for Multi interacting with Boost Interprocess" -#define BOOST_TEST_DYN_LINK - -#include - -#include +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt #include +#include #include #include -#include - #include +#include namespace bip = boost::interprocess; @@ -39,7 +31,7 @@ auto objects_directory(manager& m) { return ret; } -#include +#include #include // iota @@ -48,121 +40,127 @@ namespace multi = boost::multi; template using marray = multi::array>; -BOOST_AUTO_TEST_CASE(const multi_test_bip) { +template using alloc = bip::adaptive_pool< + T, bip::managed_shared_memory::segment_manager>; - path const file = "bip_mapped_file.bin"; - { - mremove(file); - manager m{bip::create_only, file.c_str(), 1 << 25}; // objects with same name produce boost::interprocess_exception::library_error - auto&& arr1d = *m.construct>("arr1d")(std::tuple{10}, 99, get_allocator(m)); - auto&& arr2d = *m.construct>("arr2d")(std::tuple{10, 10}, 0.0, get_allocator(m)); - auto&& arr3d = *m.construct>("arr3d")(std::tuple{10, 10, 10}, 0u, get_allocator(m)); +#include +#define BOOST_AUTO_TEST_CASE(CasenamE) /**/ - arr1d[3] = 33; - arr2d[4][5] = 45.001; +auto main() -> int { // NOLINT(readability-function-cognitive-complexity,bugprone-exception-escape) - std::iota(arr3d[6][7].begin(), arr3d[6][7].end(), 100); + BOOST_AUTO_TEST_CASE(multi_test_bip const) { - auto const& arr3d_copy = *m.construct>("arr3d_copy")(arr3d, get_allocator(m)); - BOOST_REQUIRE( arr3d == arr3d_copy ); + path const file = "bip_mapped_file.bin"; + { + mremove(file); + manager m{bip::create_only, file.c_str(), 1 << 25}; // objects with same name produce boost::interprocess_exception::library_error + auto&& arr1d = *m.construct>("arr1d")(multi::extensions_t{10}, 99, get_allocator(m)); + auto&& arr2d = *m.construct>("arr2d")(multi::extensions_t{10, 10}, 0.0, get_allocator(m)); + auto&& arr3d = *m.construct>("arr3d")(multi::extensions_t{10, 10, 10}, 0u, get_allocator(m)); - // m.flush(); // this produces uninitialized access in icpc 19.1 and might not be necessary - } - { - manager m{bip::open_only, file.c_str()}; + arr1d[3] = 33; + arr2d[4][5] = 45.001; - auto const s = objects_directory(m); - BOOST_REQUIRE( s.find("arr1d") != s.end() ); - BOOST_REQUIRE( s.find("arr2d") != s.end() ); - BOOST_REQUIRE( s.find("arr3d") != s.end() ); + std::iota(arr3d[6][7].begin(), arr3d[6][7].end(), 100); - auto&& arr1d = *m.find>("arr1d").first; - BOOST_REQUIRE(std::addressof(arr1d)); + auto const& arr3d_copy = *m.construct>("arr3d_copy")(arr3d, get_allocator(m)); + BOOST_TEST( arr3d == arr3d_copy ); + } + { + manager m{bip::open_only, file.c_str()}; - auto&& arr2d = *m.find>("arr2d").first; - BOOST_REQUIRE(std::addressof(arr2d)); + auto const s = objects_directory(m); + BOOST_TEST( s.find("arr1d") != s.end() ); + BOOST_TEST( s.find("arr2d") != s.end() ); + BOOST_TEST( s.find("arr3d") != s.end() ); - auto&& arr3d = *m.find>("arr3d").first; - BOOST_REQUIRE(std::addressof(arr3d)); + auto&& arr1d = *m.find>("arr1d").first; + BOOST_TEST(std::addressof(arr1d)); - BOOST_REQUIRE( arr1d[5] == 99 ); - BOOST_REQUIRE( arr1d[3] == 33 ); + auto&& arr2d = *m.find>("arr2d").first; + BOOST_TEST(std::addressof(arr2d)); - BOOST_REQUIRE( arr2d[7][8] == 0.0 ); - BOOST_REQUIRE( arr2d[4][5] == 45.001 ); + auto&& arr3d = *m.find>("arr3d").first; + BOOST_TEST(std::addressof(arr3d)); - BOOST_REQUIRE( arr3d[6][7][3] == 103 ); + BOOST_TEST( arr1d[5] == 99 ); + BOOST_TEST( arr1d[3] == 33 ); - auto&& arr3d_copy = *m.find>("arr3d_copy").first; - BOOST_REQUIRE(std::addressof(arr3d_copy)); + BOOST_TEST( arr2d[7][8] == 0.0 ); + BOOST_TEST( arr2d[4][5] == 45.001 ); - BOOST_REQUIRE( arr3d == arr3d_copy ); + BOOST_TEST( arr3d[6][7][3] == 103 ); - m.destroy>("arr1d"); - m.destroy>("arr2d"); - m.destroy>("arr3d"); - mremove(file); - } -} + auto&& arr3d_copy = *m.find>("arr3d_copy").first; + BOOST_TEST(std::addressof(arr3d_copy)); -template using alloc = bip::adaptive_pool< - T, bip::managed_shared_memory::segment_manager>; + BOOST_TEST( arr3d == arr3d_copy ); -BOOST_AUTO_TEST_CASE(const scoped_allocator_vector_of_arrays) { + m.destroy>("arr1d"); + m.destroy>("arr2d"); + m.destroy>("arr3d"); + mremove(file); + } + } - using bipc_row = multi::array>; - using bipc_matrix = std::vector>>; + BOOST_AUTO_TEST_CASE(scoped_allocator_vector_of_arrays const) { - bip::shared_memory_object::remove("Demo"); - { - bip::managed_shared_memory s{bip::create_only, "Demo", 65536}; + using bipc_row = multi::array>; + using bipc_matrix = std::vector>>; - bipc_matrix v(s.get_segment_manager()); + bip::shared_memory_object::remove("Demo"); + { + bip::managed_shared_memory s{bip::create_only, "Demo", 65536}; - v.emplace_back(multi::extensions_t<1>(3), 99.); - std::iota(v[0].begin(), v[0].end(), 42); + bipc_matrix v(s.get_segment_manager()); - assert(v[0][1] == 43); - bip::shared_memory_object::remove("Demo"); + v.emplace_back(multi::extensions_t<1>(3), 99.); + std::iota(v[0].begin(), v[0].end(), 42); + + assert(v[0][1] == 43); + bip::shared_memory_object::remove("Demo"); + } } -} -BOOST_AUTO_TEST_CASE(const scoped_allocator_arrays_of_vector) { + BOOST_AUTO_TEST_CASE(scoped_allocator_arrays_of_vector const) { - using bipc_row = std::vector>; - using bipc_matrix = multi::array>>; + using bipc_row = std::vector>; + using bipc_matrix = multi::array>>; - bip::shared_memory_object::remove("Demo"); - { - bip::managed_shared_memory s{bip::create_only, "Demo", 65536}; + bip::shared_memory_object::remove("Demo"); + { + bip::managed_shared_memory s{bip::create_only, "Demo", 65536}; - bipc_matrix v(bipc_matrix::extensions_type(10), bipc_row{s.get_segment_manager()}, s.get_segment_manager()); - std::vector row(3, 99); - v[0].assign(row.begin(), row.end()); + bipc_matrix v(bipc_matrix::extensions_type(10), bipc_row{s.get_segment_manager()}, s.get_segment_manager()); + std::vector row(3, 99); + v[0].assign(row.begin(), row.end()); - BOOST_REQUIRE( v[0][1] == 99 ); - bip::shared_memory_object::remove("Demo"); + BOOST_TEST( v[0][1] == 99 ); + bip::shared_memory_object::remove("Demo"); + } } -} -BOOST_AUTO_TEST_CASE(const scoped_allocator_arrays_of_array) { + BOOST_AUTO_TEST_CASE(scoped_allocator_arrays_of_array const) { - using bipc_row = multi::array>; - using bipc_matrix = multi::array>>; + using bipc_row = multi::array>; + using bipc_matrix = multi::array>>; - bip::shared_memory_object::remove("Demo"); - { - bip::managed_shared_memory s{bip::create_only, "Demo", 165536}; + bip::shared_memory_object::remove("Demo"); + { + bip::managed_shared_memory s{bip::create_only, "Demo", 165536}; - bipc_matrix v(bipc_matrix::extensions_type(10), bipc_row{bipc_matrix::extensions_type(3), 5, s.get_segment_manager()}, s.get_segment_manager()); - multi::array row = {97, 98, 99}; - std::copy(row.begin(), row.end(), v[0].begin()); + bipc_matrix v(bipc_matrix::extensions_type(10), bipc_row{bipc_matrix::extensions_type(3), 5, s.get_segment_manager()}, s.get_segment_manager()); + multi::array row = {97, 98, 99}; + std::copy(row.begin(), row.end(), v[0].begin()); - BOOST_REQUIRE( v[0][1] == 98 ); - BOOST_REQUIRE( v[1][1] == 5 ); + BOOST_TEST( v[0][1] == 98 ); + BOOST_TEST( v[1][1] == 5 ); - v.reextent(bipc_matrix::extensions_type(12), bipc_row{bipc_matrix::extensions_type(3), 5, s.get_segment_manager()}); + v.reextent(bipc_matrix::extensions_type(12), bipc_row{bipc_matrix::extensions_type(3), 5, s.get_segment_manager()}); - bip::shared_memory_object::remove("Demo"); + bip::shared_memory_object::remove("Demo"); + } } -} + + return boost::report_errors(); +} \ No newline at end of file diff --git a/external_codes/boost_multi/multi/examples/cai_1d_heat.cpp b/external_codes/boost_multi/multi/examples/cai_1d_heat.cpp new file mode 100644 index 0000000000..dbed041cd1 --- /dev/null +++ b/external_codes/boost_multi/multi/examples/cai_1d_heat.cpp @@ -0,0 +1,75 @@ +#if COMPILE_RUN_INSTRUCTIONS +${CXX:-c++} -std=c++2b $0 -I../include && ./a.out; exit +#endif +#include + +#include // for std::exp +#include +#include + +namespace multi = boost::multi; +namespace stv = std::views; + +void plot(auto const& x, auto const& f, std::string const& title = "") { + assert(x.size() == f.size()); + std::cout << "set title '" << title << "'\n" + << "plot '-' with linespoints\n"; + for(auto i : x.extension()) { + std::cout << x[i] << " " << f[i] << "\n"; + } + std::cout << 'e' << std::endl + << "pause 0.1\n"; +} + +template +auto append(Range const& range, T const& value) { + return stv::iota(typename Range::size_type{}, range.size() + 1) | stv::transform([&](auto i) -> decltype(auto) {return (i +auto prepend(Range const& range, T const& value) { + return stv::iota(typename Range::size_type{}, range.size() + 1) | stv::transform([&](auto i) -> decltype(auto) {return (i==0)?value:range[i-1];}); +} + +auto main() -> int { + + using multi::operator+; + + // dx = 0.2; + // x = [0:1:20]*dx; + // f = x.*exp(-x.^2); + // plot(x, f, 'ro'); + + auto dx = 0.2; + auto x = +(stv::iota(0, 20) | stv::transform([dx](auto i) { return i * dx; })); + auto f = +(x | stv::transform([](auto e) { return e * std::exp(-e * e); })); + plot(x, f); + + // f_my_left = [NaN, f(1:end-1)]; + // f_my_right = [f(2:end), NaN]; + // d2f = (f_my_right - 2*f + f_my_left)/(dx^2); + auto f_my_left = +prepend(f.taked(f.size() - 1), NAN); + auto f_my_right = +append(f.dropped(1), NAN); + auto d2f = +stv::zip_transform([dx2 = dx * dx](auto r, auto m, auto l) { return (r - 2 * m + l) / dx2; }, f_my_right, f, f_my_left); + + // dt = 0.01; D = 1; + // for k=1:100, + // f_my_left = [NaN, f(1:end-1)]; + // f_my_right = [f(2:end), NaN]; + // d2f = (f_my_right - 2*f + f_my_left)/(dx^2); + // f(2:end-1) = f(2:end-1) + D*dt*d2f(2:end-1); + // plot(x, f, 'ro-'); ylim([0 0.45]); drawnow + // pause(0.1) + // end + + auto dt = 0.01; + auto D = 1.0; + for(auto k = 0; k != 100; ++k) { + f_my_left({1, f.size()}) = f({0, f.size() - 1}); + f_my_right({0, f.size() - 1}) = f({1, f.size()}); + + d2f = stv::zip_transform([dx2 = dx * dx](auto r, auto m, auto l) { return (r - 2 * m + l) / dx2; }, f_my_right, f, f_my_left); + f({1, f.size() - 1}) = stv::zip_transform([&](auto eff, auto d2) { return eff + D * dt * d2; }, f({1, f.size() - 1}), d2f({1, f.size() - 1})); + plot(x, f, "k=" + std::to_string(k)); + } +} diff --git a/external_codes/boost_multi/multi/examples/loops_timings.cpp b/external_codes/boost_multi/multi/examples/loops_timings.cpp index 0564c00ba6..196cf388e9 100644 --- a/external_codes/boost_multi/multi/examples/loops_timings.cpp +++ b/external_codes/boost_multi/multi/examples/loops_timings.cpp @@ -12,9 +12,7 @@ #include #include #include -#if __cplusplus >= 201703L #include -#endif #include #include @@ -199,14 +197,14 @@ cout<<"------------"<= 201603 { auto tic = watch::now(); @@ -232,11 +230,11 @@ for(auto&& p : timings) cout<< p.first.count()/1e9 <<"\t...."<< p.second <> vbs(nbasis, vector(nstates)); // v[basis][state] + vector> vbs(nbasis, vector(nstates)); // v[basis][state] for_each(begin(vbs), end(vbs), [&](auto& e){generate(begin(e), end(e), gen);}); vector d(nstates); { - cout<<"\traw loops state/basis\n"; + cout<<"\traw loops state/basis\n"; auto tic = watch::now(); fill(begin(d), end(d), 0.); for(std::size_t s = 0; s != nstates; ++s){ @@ -245,7 +243,7 @@ return 0; cout<<"\t\t"<< ns{watch::now()-tic}.count()/1e9 <<" seconds\t"<= 201603 { - cout<<"\traw loop basis, parallel transform states\n"; + cout<<"\traw loop basis, parallel transform states\n"; auto tic = watch::now(); fill(begin(d), end(d), 0.); for(std::size_t b = 0; b != nbasis; ++b) // cannot parallelize this loop @@ -274,11 +272,11 @@ return 0; } { cout<<"v[state][basis] storage\n"; - vector> vsb(nstates, vector(nbasis)); // v[state][basis] + vector> vsb(nstates, vector(nbasis)); // v[state][basis] for_each(begin(vsb), end(vsb), [&](auto& e){generate(begin(e), end(e), gen);}); vector d(nstates); { - cout<<"\traw loops state/basis\n"; + cout<<"\traw loops state/basis\n"; auto tic = watch::now(); fill(begin(d), end(d), 0.); for(std::size_t s = 0; s != nstates; ++s){ @@ -288,7 +286,7 @@ return 0; cout<<"\t\t"<< ns{toc-tic}.count()/1e9 <<" sec\t"<= 201603 { - cout<<"\traw loop basis transform state\n"; + cout<<"\traw loop basis transform state\n"; auto tic = watch::now(); fill(begin(d), end(d), 0.); for(std::size_t b = 0; b != nbasis; ++b) @@ -318,7 +316,7 @@ return 0; } #endif { - cout<<"\traw loop basis transform state\n"; + cout<<"\traw loop basis transform state\n"; auto tic = watch::now(); fill(begin(d), end(d), 0.); for(std::size_t b = 0; b != nbasis; ++b) @@ -328,7 +326,7 @@ return 0; } #if 0 { - cout<<"\traw loops basis/state\n"; + cout<<"\traw loops basis/state\n"; auto tic = watch::now(); fill(begin(d), end(d), 0.); for(std::size_t b = 0; b != nbasis; ++b){ @@ -337,7 +335,7 @@ return 0; cout<<"\t\t"<< ns{watch::now()-tic}.count()/1e9 <<" seconds\t"< A(v.data(), {100, 100}); assert(size(A) == 100); begin(A)[4][3] = 2.; // ok using multi::static_array_cast; - // auto const& A_const = static_array_cast(A); - // begin(A_const)[4][3] = 2.; // error, read only + // auto const& A_const = static_array_cast(A); + // begin(A_const)[4][3] = 2.; // error, read only } { std::vector dd(10000); multi::array_ref::iterator> arr(begin(dd), {100, 100}); assert(size(arr) == 100); begin(arr)[4][3] = 2.; - // assert( cbegin(arr)/2 ); - // assert( cbegin(arr) < cend(arr) ); + // assert( cbegin(arr)/2 ); + // assert( cbegin(arr) < cend(arr) ); } return 0; @@ -412,8 +410,8 @@ return 0; assert( begin(A) < end(A) ); assert( cbegin(A) < cend(A) ); -// assert( crbegin(A) < crend(A) ); -// assert( crend(A) > crbegin(A) ); +// assert( crbegin(A) < crend(A) ); +// assert( crend(A) > crbegin(A) ); assert( end(A) - begin(A) == size(A) ); assert( rend(A) - rbegin(A) == size(A) ); diff --git a/external_codes/boost_multi/multi/examples/lu_solve.cpp b/external_codes/boost_multi/multi/examples/lu_solve.cpp index 752f74d332..3a2bc36f88 100644 --- a/external_codes/boost_multi/multi/examples/lu_solve.cpp +++ b/external_codes/boost_multi/multi/examples/lu_solve.cpp @@ -1,113 +1,186 @@ -#ifdef COMPILATION// -*-indent-tabs-mode:t;c-basic-offset:4;tab-width:4-*- -$CXX -DNDEBUG $0 -o $0x -lboost_timer&&$0x&&rm $0x;exit -#endif -// © Alfredo A. Correa 2021 - -#include "../array.hpp" - -#include // for std::abs -#include // for std::iota - -struct lup{ // LU method for decomposition and solution - -// translated from https://en.wikipedia.org/wiki/LU_decomposition#C_code_example -template -static auto decompose(Matrix&& A, Permutation&& P, double tol = std::numeric_limits::epsilon()){ - std::iota(begin(P), end(P), typename std::decay_t::value_type{0}); - auto const N = std::min(size(A), size(~A)); - assert( P.size() >= N ); - - auto&& ret = A({0, N}, {0, N}); - for(auto i : extension(ret)){ - if(lup::permute_max_diagonal(A, P, i) < tol) return A({0, i}, {0, i}); - - for(auto&& row : A({i + 1, N})){ - auto&& urow = row({i + 1, N}); - std::transform( - cbegin(urow), cend(urow), cbegin(A[i]({i + 1, N})), begin(urow), - [f = row[i] /= A[i][i]](auto const& a, auto const& b){return a - f*b;} - ); +#ifdef COMPILATION // clang-format off +set -x;${CXX:-c++} -std=c++20 -O3 -DNDEBUG -I../include $0 -o $0x &&time $0x&&rm $0x;exit +#endif // clang-format on + +// Copyright 2021-2024 Alfredo A. Correa + +#include + +#include // for std::abs +#include +#include // for std::iota +#include +#include + + namespace { + struct lup { // LU method for decomposition and solution + + // translated from https://en.wikipedia.org/wiki/LU_decomposition#C_code_example + template + static auto decompose(Matrix&& A, Permutation&& P, double tol = std::numeric_limits::epsilon()) { + auto const N = std::min(size(A), size(~A)); + assert(P.size() >= N); + + if(A.size() == 0) + return A({0, 1}, {0, 1}); + + auto&& ret = A({0, N}, {0, N}); + + // if(lup::permute_max(A, P) < tol) return A({0, 1}, {0, 1}); + // for(auto&& row : A({1, N})) { + // auto&& urow = row({1, N}); + // std::transform( + // cbegin(urow), cend(urow), cbegin(A[0]({1, N})), begin(urow), + // [f = row[i] /= A[0][0]](auto const& a, auto const& b) { return a - f * b; } + // ); + // } + + // decompose(A({1, N}, {1, N}), P({1, N})); + + for(auto i : extension(ret)) { + auto&& A_rest = A({i, N}); + auto&& P_rest = P({i, N}); + auto&& A_rest_rest = A_rest({0, N - i}, {i, N}); + if(lup::permute_max_diagonal(A_rest({0, N - i}, {0, N}), P_rest({0, N - i}), i) < tol) + return A({0, i}, {0, i}); + + for(auto&& row : A_rest({1, N - i})) { + auto&& urow = row({i + 1, N}); + std::transform( + cbegin(urow), cend(urow), cbegin(A_rest_rest[0]({1, N - i})), begin(urow), + [f = row[i] /= A_rest_rest[0][0]](auto const& a, auto const& b) { return a - f * b; } + ); + } + } + return std::move(ret); } - } - return std::move(ret); -} -template -static auto solve(Matrix const& LU, Permutation const& P, VectorSol&& x) -> VectorSol&&{ - return upper_solve(LU, lower_solve(LU, permute(P, x))); -} + // translated from https://en.wikipedia.org/wiki/LU_decomposition#C_code_example + template< + class Permutation, class Matrix> + static auto decompose(Matrix&& A, double tol = std::numeric_limits::epsilon()) { + Permutation P(A.size()); + std::iota(begin(P), end(P), typename std::decay_t::value_type{0}); -private: + decompose(A, P, tol); + return std::pair(std::forward(A), std::move(P)); + } -template -static auto permute_max_diagonal(Matrix&& LU, Permutation&& P, Index i){ - auto mi = std::max_element(begin(LU) + i, end(LU), [i](auto const& a, auto const& b){return std::abs(a[i]) < std::abs(b[i]);}) - begin(LU); - swap(LU[i], LU[mi]); - std::swap(P [i], P [mi]); - return std::abs(LU[i][i]); -} + template + static auto solve(Matrix const& LU, Permutation const& P, VectorSol&& x) -> VectorSol&& { + return upper_solve(LU, lower_solve(LU, permute(P, x))); + } -template -static auto permute(Permutation const& p, Vector&& data) -> Vector&&{ - assert(size(p) <= size(data)); - using index = typename Permutation::size_type; - for(index i = 0; i != size(p); ++i){ - index k = p[i]; - for( ; k > i; k = p[k]){} - index pk = p[k]; - if(k >=i and pk != i){ - auto const t = data[i]; - for( ; pk != i; k = pk, pk = p[k]){ - data[k] = data[pk]; - }; - data[k] = t; + private: + template + static auto permute_max_diagonal(Matrix&& LU, Permutation&& P, Index i) { + auto mi = std::max_element(begin(LU), end(LU), [i](auto const& a, auto const& b) { return std::abs(a[i]) < std::abs(b[i]); }) - begin(LU); + using std::swap; + swap(LU[0], LU[mi]); + swap(P[0], P[mi]); + return std::abs(LU[0][i]); } - } - return std::forward(data); -} -template -static auto lower_solve(LUMatrix const& LU, Vector&& x) -> Vector&&{ - assert(size(LU) <= size(x)); - auto const N = size(LU); - for(typename LUMatrix::size_type i = 0; i != N; ++i){ - auto const& Lrowi = LU[i]({0, i}); - x[i] -= std::inner_product(begin(Lrowi), end(Lrowi), cbegin(x), 0.); - } - return std::forward(x); + template + static auto permute_max(Matrix&& LU, Permutation&& P) { + auto mi = std::max_element(begin(LU), end(LU), [](auto const& a, auto const& b) { return std::abs(a[0]) < std::abs(b[0]); }) - begin(LU); + if(mi != 0) { + using std::swap; + swap(LU[0], LU[mi]); + swap(P[0], P[mi]); + } + return std::abs(LU[0][0]); + } + + template + static auto permute(Permutation const& p, Vector&& data) -> Vector&& { + assert(size(p) <= size(data)); + using index = typename Permutation::size_type; + for(index i = 0; i != size(p); ++i) { + index k = p[i]; + for(; k > i; k = p[k]) { + } + index pk = p[k]; + if(k >= i and pk != i) { + auto const t = data[i]; + for(; pk != i; k = pk, pk = p[k]) { + data[k] = data[pk]; + }; + data[k] = t; + } + } + return std::forward(data); + } + + template + static auto lower_solve(LUMatrix const& LU, Vector&& x) -> Vector&& { + assert(size(LU) <= size(x)); + auto const N = size(LU); + for(typename LUMatrix::size_type i = 0; i != N; ++i) { + auto const& Lrowi = LU[i]({0, i}); + x[i] -= std::inner_product(begin(Lrowi), end(Lrowi), cbegin(x), 0.); + } + return std::forward(x); + } + + template + static auto upper_solve(LUMatrix const& LU, Vector&& x) -> Vector&& { + assert(size(LU) <= size(x)); + auto const N = size(LU); + for(typename LUMatrix::size_type i = N - 1; i >= 0; --i) { + auto const& Urowi = LU[i]({i + 1, N}); + (x[i] -= std::inner_product(begin(Urowi), end(Urowi), cbegin(x) + i + 1, 0.)) /= LU[i][i]; + } + return std::forward(x); + } + }; } -template -static auto upper_solve(LUMatrix const& LU, Vector&& x) -> Vector&&{ - assert(size(LU) <= size(x)); - auto const N = size(LU); - for(typename LUMatrix::size_type i = N - 1; i >= 0; --i){ - auto const& Urowi = LU[i]({i + 1, N}); - (x[i] -= std::inner_product(begin(Urowi), end(Urowi), cbegin(x) + i + 1, 0.)) /= LU[i][i]; +namespace multi = boost::multi; + +int main() try { + { + multi::array const Aconst = { + { 6.80, -6.05, -0.45, 8.32, -9.67}, + {-2.11, -3.30, 2.58, 2.71, -5.14}, + { 5.66, 5.36, -2.70, 4.35, -7.26}, + { 5.97, -4.44, 0.27, -7.17, 6.08}, + { 8.23, 1.08, 9.04, 2.14, -6.87} + }; + auto A = Aconst; + // multi::array P(multi::array::extensions_type{5}); + auto P = std::get<1>(lup::decompose>(A)); + + multi::array x = {4.02, 6.19, -8.22, -7.57, -3.03}; + + lup::solve(A, P, x); + + std::cout << std::abs(x[4]) << std::endl; + (std::abs(x[4] - 0.565756) < 1e-4) ?: throw std::source_location::current(); } - return std::forward(x); -} + { + multi::array A({4000, 4000}); -}; + std::random_device rd; // Non-deterministic random number generator + std::mt19937 gen(rd()); // Mersenne Twister engine seeded with rd() -namespace multi = boost::multi; + std::uniform_real_distribution dist(-1.0, 1.0); + for(auto&& e : A.elements()) { + e = dist(gen); + } -int main(){ - multi::array const Aconst = { - { 6.80, -6.05, -0.45, 8.32, -9.67}, - {-2.11, -3.30, 2.58, 2.71, -5.14}, - { 5.66, 5.36, -2.70, 4.35, -7.26}, - { 5.97, -4.44, 0.27,-7.17, 6.08}, - { 8.23, 1.08, 9.04, 2.14, -6.87} - }; - auto A = Aconst; - multi::array P({5}, 0.); - lup::decompose(A, P); + multi::array P(multi::array::extensions_type{A.size()}); + std::iota(P.begin(), P.end(), int{}); + lup::decompose(A, P); - multi::array x = {4.02, 6.19, -8.22, -7.57, -3.03}; + multi::array x(A.size()); + for(auto&& e : x.elements()) { + e = dist(gen); + } - lup::solve(A, P, x); - - assert( std::abs(x[4] - 0.565756) < 1e-4); + lup::solve(A, P, x); + } +} catch(std::source_location const& loc) { + std::cerr << loc.file_name() << ':' << loc.line() << '\n'; + throw; } - diff --git a/external_codes/boost_multi/multi/examples/serialization.cpp b/external_codes/boost_multi/multi/examples/serialization.cpp index a69c7ddbdd..5575be2d2f 100644 --- a/external_codes/boost_multi/multi/examples/serialization.cpp +++ b/external_codes/boost_multi/multi/examples/serialization.cpp @@ -1,15 +1,11 @@ #if 0 && defined(COMPILATION) -${CXX:-c++} $0 -o $0x -I../include -lboost_unit_test_framework -lstdc++fs -lboost_serialization -lboost_iostreams&& $0x&& rm $0x; +${CXX:-c++} $0 -o $0x -I../include -lstdc++fs -lboost_serialization -lboost_iostreams&& $0x&& rm $0x; exit #endif // Copyright 2018-2024 Alfredo A. Correa -#define BOOST_TEST_MODULE "C++ Unit Tests for Multi serialization" -#define BOOST_TEST_DYN_LINK +#include -#include - -// #include "../adaptors/serialization/xml_archive.hpp" #include #include @@ -43,13 +39,14 @@ namespace fs = std::experimental::filesystem; struct watch : private std::chrono::high_resolution_clock { std::string name_; - time_point start_; + time_point start_ = std::chrono::high_resolution_clock::now(); mutable bool engaged = true; - watch(std::string name = "") : name_{std::move(name)}, start_{now()} {} + watch(std::string name = "") : name_{std::move(name)} {} auto operator*() const { engaged = false; return std::chrono::duration(now() - start_).count(); } + auto operator=(watch const&) = delete; ~watch() { if(engaged) { auto count = operator*(); @@ -58,6 +55,10 @@ struct watch : private std::chrono::high_resolution_clock { } }; +#define BOOST_AUTO_TEST_CASE(CasenamE) /**/ + +auto main() -> int { // NOLINT(readability-function-cognitive-complexity,bugprone-exception-escape) + BOOST_AUTO_TEST_CASE(print_xml) { multi::array A{ {"w", "x"}, @@ -74,7 +75,7 @@ BOOST_AUTO_TEST_CASE(multi_serialization_static_small_xml) { auto gen = [&]() { return std::uniform_real_distribution<>{}(eng); }; - std::for_each(begin(d2D), end(d2D), [&](auto&& r) { std::generate(begin(r), end(r), gen); }); + std::for_each(begin(d2D), end(d2D), [&](auto& r) { std::generate(begin(r), end(r), gen); }); std::string const filename = "serialization-static-small.xml"; { std::ofstream ofs{filename}; @@ -84,7 +85,7 @@ BOOST_AUTO_TEST_CASE(multi_serialization_static_small_xml) { { std::ifstream ifs{filename}; assert(ifs); - decltype(d2D) d2D_copy(extensions(d2D), 99.); + decltype(d2D) d2D_copy(extensions(d2D), 99.0); boost::archive::xml_iarchive{ifs} >> BOOST_SERIALIZATION_NVP(d2D_copy); BOOST_REQUIRE( d2D_copy == d2D ); } @@ -111,7 +112,7 @@ BOOST_AUTO_TEST_CASE(multi_serialization_small_xml) { // auto g = std::bind(std::uniform_real_distribution<>{}, e);// auto g = [&]() { return std::uniform_real_distribution<>{}(e); }; - std::for_each(begin(d2D), end(d2D), [&](auto&& r) { std::generate(begin(r), end(r), g); }); + std::for_each(begin(d2D), end(d2D), [&](auto& r) { std::generate(begin(r), end(r), g); }); std::string const filename = "serialization-small.xml"; { std::ofstream ofs{filename}; @@ -141,7 +142,7 @@ BOOST_AUTO_TEST_CASE(multi_serialization_static_large_xml) { multi::static_array d2D({1000, 1000}); auto gen = [e = std::mt19937_64(std::random_device{}())]() mutable { return std::uniform_real_distribution<>{}(e); }; - std::for_each(begin(d2D), end(d2D), [&](auto&& r) { std::generate(begin(r), end(r), gen); }); + std::for_each(begin(d2D), end(d2D), [&](auto& r) { std::generate(begin(r), end(r), gen); }); watch w("static_large_xml"); @@ -182,7 +183,7 @@ BOOST_AUTO_TEST_CASE(multi_serialization_static_small) { auto gen = [d = std::uniform_real_distribution{-1, 1}, e = std::mt19937{std::random_device{}()}]() mutable { return d(e); }; std::for_each( begin(d2D), end(d2D), - [&](auto&& r) { std::generate(begin(r), end(r), gen); } + [&](auto& r) { std::generate(begin(r), end(r), gen); } ); std::string const filename = "serialization-small-double2D.xml"; [&, _ = watch("xml write double")] { @@ -388,3 +389,5 @@ BOOST_AUTO_TEST_CASE(test_utility_serialization_2d) { // arxiv::xml_oarchive{ofs} << BOOST_SERIALIZATION_NVP(Marr); } } + +return boost::report_errors();} diff --git a/external_codes/boost_multi/multi/include/boost/multi/adaptors/CMakeLists.txt b/external_codes/boost_multi/multi/include/boost/multi/adaptors/CMakeLists.txt new file mode 100644 index 0000000000..b9b248a4ef --- /dev/null +++ b/external_codes/boost_multi/multi/include/boost/multi/adaptors/CMakeLists.txt @@ -0,0 +1,13 @@ +cmake_minimum_required(VERSION 3.5) + +find_package(MPI) + +if(DISABLE_MPI) + message(WARNING "MPI disabled, MPI adaptor will not be tested.") +else() + if(MPI_FOUND) + add_subdirectory(./mpi) + else() + message(WARNING "MPI not found, MPI adaptor will not be tested.") + endif() +endif() diff --git a/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas.hpp b/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas.hpp index 8f6482912d..55e391d850 100644 --- a/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas.hpp +++ b/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas.hpp @@ -6,19 +6,18 @@ #define BOOST_MULTI_ADAPTORS_BLAS_HPP #pragma once -#include "../adaptors/blas/asum.hpp" -#include "../adaptors/blas/axpy.hpp" -#include "../adaptors/blas/copy.hpp" -#include "../adaptors/blas/dot.hpp" -#include "../adaptors/blas/gemm.hpp" -#include "../adaptors/blas/gemv.hpp" -//#include "../adaptors/blas/ger.hpp" -#include "../adaptors/blas/herk.hpp" -#include "../adaptors/blas/iamax.hpp" -#include "../adaptors/blas/nrm2.hpp" -#include "../adaptors/blas/scal.hpp" -#include "../adaptors/blas/swap.hpp" -#include "../adaptors/blas/syrk.hpp" -#include "../adaptors/blas/trsm.hpp" +#include +#include +#include +#include +#include +#include // IWYU pragma: export +#include +#include +#include +#include +#include +#include +#include #endif // BOOST_MULTI_ADAPTORS_BLAS_HPP diff --git a/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/CMakeLists.txt b/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/CMakeLists.txt index af45955095..4f5e2ed908 100644 --- a/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/CMakeLists.txt +++ b/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/CMakeLists.txt @@ -30,29 +30,30 @@ if(BLAS_FOUND) target_compile_definitions(multi INTERFACE BLAS_DOT_RETURNS_VOID) endif() if(${lib} MATCHES "Accelerate") - message("Some BLAS found matches Accelerate (Apple)") - message(WARNING "Apple Accelerate BLAS is know to have bugs in single precission function `sdot` and `smrm2`, be careful: https://stackoverflow.com/a/77017238/225186, https://fortran-lang.discourse.group/t/how-many-blas-libraries-have-this-error/4454/23, https://forums.developer.apple.com/forums/thread/717757") - add_definitions(-DBLAS_DOT_RETURNS_VOID) + message("Some BLAS found matches Accelerate (Apple) [beware of sdot and snrm2 bugs]") + # message(WARNING "Apple Accelerate BLAS is known to have bugs in single precission function `sdot` and `smrm2`, be careful: https://stackoverflow.com/a/77017238/225186, https://fortran-lang.discourse.group/t/how-many-blas-libraries-have-this-error/4454/23, https://forums.developer.apple.com/forums/thread/717757") + # add_definitions(-DBLAS_DOT_RETURNS_VOID) target_compile_definitions(multi INTERFACE BLAS_DOT_RETURNS_VOID) endif() endforeach() endif() # this makes CM FetchContent friendly https://www.foonathan.net/2022/06/cmake-fetchcontent/ -if(NOT CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR) - return() -endif() +# if(NOT CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR) +# return() +# endif() if(BLAS_FOUND) - find_package(Boost COMPONENTS unit_test_framework) - if(Boost_unit_test_framework_FOUND) + find_package(Boost) # COMPONENTS boost) # headers unit_test_framework) + if(Boost_FOUND) add_subdirectory(test) else() message(WARNING "Boost Unit Test Framework not found, BLAS-adaptor tests will not be compiled and run. If you want this feature, install Boost") endif() else() - message(WARNING "BLAS not found, BLAS-adaptor tests will not be compiled and run. If you want this feature install BLAS, for example please run:" - "\n sudo apt install libblas-dev" + message(WARNING + "BLAS not found, BLAS-adaptor tests will not be compiled and run. If you want this feature install BLAS, for example please run:" + "\n sudo apt install libblas-dev # in Ubuntu" "\n sudo dnf install blas-devel # in Fedora") message(WARNING "BLA_VENDOR was set to ${BLA_VENDOR}\n") endif() diff --git a/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/README.md b/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/README.md index 5a69accb15..aa069e1be4 100644 --- a/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/README.md +++ b/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/README.md @@ -7,76 +7,297 @@ _© Alfredo A. Correa, 2018-2024_ (documentation in progress) -The BLAS Adaptor provides an interface for BLAS and BLAS-like libraries (namely cuBLAS). +The BLAS Adaptor provides an interface for the BLAS and BLAS-like linear algebra libraries (cuBLAS and hipBLAS). +Although BLAS is not strictly a multidimensional array library, as it only works on 1D (vectors) and 2D arrays (matrices), it is an extremely popular numeric library. + +The adaptor library has a two-fold purpose: + +First, it allows the abstracting of the stride information and the conjugation/transposition in the BLAS calls, simplifying the interface enormously and making it consistent with their GPU counterparts, such as cuBLAS. +"View manipulators" automatically handle cases related to conjugation, transposition, and real and imaginary parts. + +Second, it provides a functional interface to the BLAS calls, which is easier to use than the C-style interface and plays well with STL algorithms that assume a functional programming style. + +This functions in this adaptor library strictly uses BLAS operations, the data is not processed outside the BLAS calls. ## Contents [[_TOC_]] +## Interfaces + +In the _functional_ interface, most functions return special "views" rather than direct results. +The results are computed when converted to value types or assigned to other views. +Value types can be 2D (`multi::array`), 1D (`multi::array`) or 0D (`multi::array` or scalars `T`). +Views can be assigned to subarrays (e.g. `multi::subarray` or `multi::subarray`). + +In this interface, functions like `gemv` generates views that can be assigned to values or from which constructors can be called in the library without unnecessary copies or allocations. +Expressions such as `multi::blas::gemv(alpha, A, x)` produce a range object that can be used in larger expressions, such as construction and assignemnt. + +- Construction: +```cpp +multi::array const y = multi::blas::gemv(alpha, A, x); // same effect as multi::array y({A.size()}); multi::blas::gemv(alpha, A, x, 0.0, y); +``` +Among other advantages, the functional style gives the possibility of creating constant variables for results. + +Like other parts of the library, when using `auto` and the unary `operator+` help generating concrete values. + +```cpp +auto const y = +multi::blas::gemv(alpha, A, x); // y variable is deduced as multi::array and latter constructed from the gemv operation +``` + +- Assignment: +```cpp + multi::array y; // empty vector + y = multi::blas::gemv(alpha, A, x); // same as multi::blas::gemv(alpha, A, x, 0.0, y), y is resized if necessary +``` + +- Assignment (to subarray): +```cpp +multi::array Y; // empty vector +Y[0] = multi::blas::gemv(alpha, A, x); // same as multi::blas::gemv(alpha, A, x, 0.0, Y[0]), Y[0] can't be resized because it is a subarray must have the correct size, +``` + +- Compound-assign: +```cpp +multi::array y(A.size()); +y += multi::blas::gemv(alpha, A, x); // same as multi::blas::gemv(alpha, A, x, 1.0, y) +``` + +This interface plays well with the style of the STL algorithms. +For example, suppose we have a container of vectors, all of which need to be multiplied by a given array. + +```cpp +std::list > vs = ...; // using std::list to avoid confusion +std::list > ws = ...; +multi::array const A = ...; + +std::transform(vs.begin(), vs.end(), ws.begin(), [&A](auto const& v) {return multi::blas::gemv(1.0, A, v);}) +``` + +Although it shares some of the goals, this interface is independent of the [C++26 Linear Algebra Proposal](https://en.cppreference.com/w/cpp/numeric/linalg). +The main difference with other BLAS adaptors is that this library aims to offer a functional interface. + ## Numeric Arrays, Conjugation Real and Imaginary parts -These functions produce views (not copies) related to conjugation, real and imaginary parts. +Just as with BLAS, the library supports element of real (`double` and `float`) and complex (`std::complex` and `std::complex`) types. +Other types that are semantically equivalent and binary-compatible (such as `thrust::complex`) also work directly. + +## View manipulators + +These functions produce views (not copies) related to conjugation, and transposition. +These typically replace the 'T', 'C' and 'N' characted arguments of the BLAS calls in the C or Fortran interfaces. + +### `auto multi::blas::C(`_complex/real vector/matrix_`) -> `_complex/real vector/matrix view_ + +The conjugation operation is a unary operation that conjugates each element of the array, producing a view of the array that preserves the shape of the original array. + +### `multi::blas::T(`_complex/real vector/matrix_`) -> `_complex/real vector/matrix view_ + +The transposition operation is a unary operation that transposes an array, producing a view of the array that transposed the elements (and the shape) of the original array. + +### `multi::blas::N(`_complex/real vector/matrix_`) -> `_complex/real vector/matrix view_ + +This view returns the same array, implies no operations on the array; it is provided for completeness. + +### `multi::blas::H(`_complex/real vector/matrix_`) -> `_complex/real vector/matrix view_ + +```cpp +using complex = std::complex; +complex const I{0.0, 1.0}; + +multi::array B = { + {1.0 - 3.0*I, 6.0 + 2.0*I}, + {8.0 + 2.0*I, 2.0 + 4.0*I}, + {2.0 - 1.0*I, 1.0 + 1.0*I} +}; +namespace blas = multi::blas; +multi::array conjB = blas::C(B); + +assert( blas::C(B)[1][2] == std::conj(B[1][2]) ); +assert( blas::T(B)[1][2] == B[2][1] ); +assert( blas::N(B)[1][2] == N[1][2] ); +assert( blas::H(B)[1][2] == std::conj(B[2][1]) ); +``` + +Note that views do not play well with self-assignment. ```cpp - using complex = std::complex; - complex const I{0.0, 1.0}; - multi::array B = { - {1.0 - 3.0*I, 6.0 + 2.0*I}, - {8.0 + 2.0*I, 2.0 + 4.0*I}, - {2.0 - 1.0*I, 1.0 + 1.0*I} - }; +multi::array A({10, 10}); +A = multi::blas::T(A); // undefined behavior, this is not the right way to transpose a matrix in-place +``` +The main purpose of these functions is to manipulate arguments to BLAS interface functions. + +## BLAS level 1 - namespace blas = multi::blas; - multi::array conjB = blas::conj(B); +(https://godbolt.org/z/Kjfa48d4P) - assert( blas::conj(B)[2][1] == std::conj(B[2][1]) ); +The functions in this level operate on one-dimensional arrays (vectors). +Here, we use `multi::array` as representative of a vector, but a one-dimensional subarray, such as a row or a column of a 2D array, can also be used as a vector. - assert( blas::transposed(B)[1][2] == B[2][1] ); - assert( blas::transposed(B) == ~B ); +### `auto multi::blas::copy(`_complex/real vector_`) -> `_convertible to complex/real vector_ - assert( blas::hermitized(B)[2][1] == blas::conj(B)[1][2] ); - assert( blas::hermitized(B) == blas::conj(blas::transposed(B)) ); +Copies the values of a vector to another. - assert( blas::real(B)[2][1] == std::real(B[2][1]) ); - assert( blas::imag(B)[2][1] == std::imag(B[2][1]) ); +This is similar to assigment, except that it used the underlying BLAS function (including parallelization if offered by the BLAS implementation) and has marginal utility. +However, this case serves as illustration of the _functional_ interface, used in the rest of the library: +`multi::blas::copy(v)` doesn't copy or allocates anything, it creates a "view" that can serve different purposes, illustrated in 3 different cases: +1) The view can be used to construct a new vector (needing allocation), +Once again `operator+` helps with automatic type deduction. - multi::array B_real_doubled = { - { 1.0, -3.0, 6.0, 2.0}, - { 8.0, 2.0, 2.0, 4.0}, - { 2.0, -1.0, 1.0, 1.0} - }; - assert( blas::real_doubled(B) == B_real_doubled ); +```cpp +multi::array const v = {1.0, 2.0, 3.0}; +multi::array const v2 = multi::blas::copy(v); // case 1: allocates space for 3 elements and copies (using BLAS) +// auto const v2 = +v_copy; // same effect as line above ``` +(Note that `auto const v2 = v_copy;` would not create a value or perform a copy, it will simply hold a variable with the "copy range". +This is not recommended as it can be confused and create a dangling range.) + +2) to assign to an existing vector (and resize it if is needed and possible) + ```cpp - multi::array const a_real = { - { 1.0, 3.0, 1.0}, - { 9.0, 7.0, 1.0}, - }; +multi::array v3; // mutable vector +v3 = multi::blas::copy(v); // case 2: resizes v3 (allocates space for 3 elements) and copies +``` - multi::array const b = { - { 11.0 + 1.0*I, 12.0 + 1.0*I, 4.0 + 1.0*I, 8.0 - 2.0*I}, - { 7.0 + 8.0*I, 19.0 - 2.0*I, 2.0 + 1.0*I, 7.0 + 1.0*I}, - { 5.0 + 1.0*I, 3.0 - 1.0*I, 3.0 + 8.0*I, 1.0 + 1.0*I} - }; +```cpp +multi::array v4({3}, 0.0); // allocates space for 3 elements +v4 = multi::blas::copy(v); // case 2: assigns copies (no allocation necessary) +``` - multi::array c({2, 4}); +3) to assign to a 1D subarray vector that is _not_ resizable. +The importance of this case is that it guarantees that no allocations are performed. - blas::real_doubled(c) = blas::gemm(1., a_real, blas::real_doubled(b)); // c = a_real*b +```cpp + multi::array cA({3}, 0.0); // allocates space for 3 elements + v4({0, 2}) = multi::blas::copy(v); // case 3: LHS is not resizable, assigns copies to subrange (resizing is not possible or necessary, no allocations) +``` + +### `auto multi::blas::swap(`_complex/real vector_`, `_complex/real vector_`) -> void` + +Swaps the values of two vectors. +Vector extensions must match. + +Note that the utility of `multi::blas::copy` and `multi::blas::swap` is redundant with native features of the library (such as plain assignment, copy construction and swap), the only difference is that these operations will be performed using the BLAS operations elementwise one dimensional arrays (vectors) on real or complex data only. + +These function do not work on 2D arrays (matrices) as the BLAS functions do not support this. +Copying or swapping 2D arrays with arbitrary layouts using BLAS could be done row-by-row: `std::transform(A2.begin(), A2.end(), B2.begin(), [](auto const& arow) {return multi::blas::copy(arow);})` (or, for efficiency column-by-column depending on the layout). + +### `auto multi::blas::nrm2(`_complex/real vector_`) -> `_convertible to real scalar_ + +Unary operation that computes the norm-2 (Euclidean norm) of a vector. +The result is convertible to a real scalar + +```cpp +multi::array const v = {1.0, 2.0, 3.0}; +double const n = multi::blas::nrm2(v); +// auto const n = +multi::blas::nrm2(v); +``` + +```cpp +multi::array, 2> const v = { {1.0, 2.0}, {2.0, 3.0}, {3.0, 4.0} }; +double const n = multi::blas::nrm2(v[0]); // acting on a row view +// auto const n = +multi::blas::nrm2(v[0]); ``` -## GEMM +### `auto multi::blas::asum(`_complex/real vector_`) -> `_convertible to real scalar_ +Returns the sum of the absolute values of the elements of a vector (norm-1). + +### `auto multi::blas::iamax(`_complex/real vector_`) -> `_index_type_ + +Index of the element with the largest absolute value (zero-based) + +### `auto multi::blas::dot(`_complex/real vector_, _complex/real vector_`) -> `_convertible to complex/real scalar_ + +Returns the dot product of two vectors with complex or real elements (`T`). + +```cpp +multi::array const v = {1.0, 2.0, 3.0}; +multi::array const w = {4.0, 5.0, 6.0}; +double const d = multi::blas::dot(v, w); +// auto const d = +multi::blas::dot(v, w); ``` + +Conjugation can be applied to either vector argument, + +```cpp + using multi::blas::dot; + using multi::blas::C; + + auto const d1 = +dot( v , w ); + auto const d2 = +dot(C(v), w ); + auto const d3 = +dot( v , C(w)); + auto const d4 = +dot(C(v), C(w)); +``` + +It is important to note that the left hand side of the assignment can be a scalar that is part of a heap allocation. +In this case, the result is going to directly put at this location. + +```cpp +multi::array z = {0.0, 0.0, 0.0}; +z[1] = multi::blas::dot(v, w); +``` + +This feature regarding scalar results is essential when operating on GPU memory since the whole operation can be performed on the device. + +> In CPUs BLAS `dot` functions has known bugs in different implementations. +> For example BLAS Apple Accelerate has bug in `sdot` while BLAS 32bit has a bug in `cdot`. +> In addition, some implementations of BLAS functions return the complex result in the stack and other write into a pointer. +> For this reason and for consistency, the library uses BLAS's `gemv` functions in place of `dot` in these cases. +> This should not affect the results. + +### `auto multi::blas::scal(`_complex/real scalar`, `_complex/real vector_`)` + +Scales a vector. + +### `auto multi::blas::axpy(`_complex/real scalar`, `_complex/real vector_`) -> `_convertible to complex/real_ + +Vector addition. + +```cpp +multi::array const x = ...; +multi::array y = ...; +y += blas::axpy(2.0, x); // same as blas:::axpy(+2.0, x, y) +y -= blas::axpy(2.0, x); // same as blas:::axpy(-2.0, x, y) +``` + +## BLAS level 2 + +These functions operate on vectors and arrays. +Again, we use `multi::array` as representative of a vector, but a one-dimensional subarray, such as a row or a column of a 2D array, can also be used as a vector. +`multi::array` as representative of a matrices, but a two-dimensional subarray or larger of higher dimensional arrays can be used as long as one of the two interternal strides in 1. +This is limitation of BLAS, that only acts on certain layouts of 2D arrays. + +### `auto multi::blas::gemv(`_complex/real scalar_ `,` _complex/real matrix_`) -> `_convertible to complex/real vector_ + +```cpp +multi::array const A({4, 3}); +multi::array const x = {1.0, 2.0, 3.0}; +multi::array const x = {1.0, 2.0, 3.0, 4.0}; + +y = blas::gemv(5.0, A, x); // y <- 5.0 A * x +``` + +The gemv expression can be used for addition and subtraction, + +``` +y += blas::gemv(1.0, A, x); // y <- + A * x + y +y -= blas::gemv(1.0, A, x); // y <- - A * x + y +``` + +### GEMM + +```cpp #include #include namespace multi = boost::multi; int main() { - multi::array const A({2, 2}); - multi::array const B({2, 2}); + multi::array const A({2, 2}); + multi::array const B({2, 2}); - multi::array const C1 = multi::blas::gemm(1.0, A, B); + multi::array const C1 = multi::blas::gemm(1.0, A, B); auto const C2 = + multi::blas::gemm(1.0, A, B); } ``` @@ -98,15 +319,15 @@ matrix operations: `J` (`*`) conjugation (element-wise) (use `C` for vectors), ` | BLAS | mutable form | effect | operator form [³] | functional form | thrust/STL [¹] | |--- |--- | --- | --- | --- | --- | -| SWAP |`blas::swap(x, y)` | $`x_i \leftrightarrow y_i`$ | `(x^y)` | | `swap_ranges(begin(x), end(x), begin(y))` | -| COPY |`blas::copy(x, y)` | $`y_i \leftrightarrow x_i`$ | `y << x` | `y = blas::copy(x)` | `copy(begin(x), end(x), begin(y))` | -| ASUM |`blas::asum(x, res)` | $`r \leftarrow \sum_i \|\Re x_i\| + \|\Im x_i\|`$ | `x==0`/`x!=0` `isinf(x)` `isnan(x)`[²] | `res = blas::asum(x)` | `transform_reduce(begin(x), end(x), 0.0, plus<>{}, [](auto const& e){return abs(e.real()) + abs(e.imag());})` | +| SWAP |`blas::swap(x, y)` | $x_i \leftrightarrow y_i$ | `(x^y)` | | `swap_ranges(begin(x), end(x), begin(y))` | +| COPY |`blas::copy(x, y)` | $`y_i \leftarrow x_i`$ | `y << x` | `y = blas::copy(x)` | `copy(begin(x), end(x), begin(y))` | +| ASUM |`blas::asum(x, res)` | $`r \leftarrow \sum_i \|\Re x_i\| + \|\Im x_i\|`$ | `x==0`/`x!=0` `isinf(x)` `is an(x)`[²] | `res = blas::asum(x)` | `transform_reduce(begin(x), end(x), 0.0, plus<>{}, [](auto const& e){return abs(e.real()) + abs(e.imag());})` | | NRM2 |`blas::nrm2(x, res)` | $`r \leftarrow \sqrt{\sum_i \|x_i\|^2}`$ | `abs(x)` | `res = blas::nrm2(x);` | `sqrt(trasnform_reduce(begin(x), end(x), 0.0, plus<>{}, [](auto const& e){return norm(e);}));` | | SCAL |`blas::scal(aa, x);` | $`x_i \leftarrow \alpha x_i`$ | `x*=aa;` | | `for_each(begin(x), end(x), [aa](auto& e){return e*=aa;})` | | AXPY |`blas::axpy(aa, x, y)` | $`y_i \leftarrow \alpha x_i + y_i`$ | `y+=x` `y-=x` `y+=aa*x` `y-=aa*x` | | `transform(x.begin(), x.end(), y.begin(), y.begin(), [aa](auto ex, auto ey) {return aa*ex + ey;}` | | DOT | `blas::dot(x, y, res)` | $`r = \sum_i x_i y_i`$ | `res = (x, y);` | `res = blas::dot(x, y)` | `inner_product(begin(x), end(x), begin(y), T{});` | -| | `blas::dot(blas::C(x), y, res)` | $`r = \sum_i \bar x_i y_i`$ | `res = (*x, y);` | `res = blas::dot(blas::C(x), y)` | `inner_product(begin(x), end(x), begin(y), T{}, plus<>{}, [](T const& t1, T const& t2) {return conj(t1)*t2;});` | -| | `blas::dot(x, blas::C(y), res)` | $`r = \sum_i x_i \bar y_i`$ | `res = (x, *y);` | `res = blas::dot(x, blas::C(y));` | `inner_product(x.begin(), x.end(), y.begin(), T{}, plus<>{}, [](T const& t1, T const& t2) {return t1*conj(t2);});` | +| | `blas::dot(blas::C(x), y, res)` | $`r = \sum_i \bar x_i y_i`$ | `res = (*x, y);` | `res = blas::dot(blas::C(x), y)` | `inner_product(begin(x), end(x), begin(y), T{}, plus<>{}, [](T const& t1, T const& t2) {return conj(t1)*t2;});` | +| | `blas::dot(x, blas::C(y), res)` | $`r = \sum_i x_i \bar y_i`$ | `res = (x, *y);` | `res = blas::dot(x, blas::C(y));` | `inner_product(x.begin(), x.end(), y.begin(), T{}, plus<>{}, [](T const& t1, T const& t2) {return t1*conj(t2);});` | | | ~~`blas::dot(blas::C(x), blas::C(y), res)`~~ | $`r = \sum_i \bar x_i \bar y_i`$ not implemented in BLAS, conjugate result | | | `auto res = conj(inner_product(x.begin(), x.end(), y.begin(), T{});` | | GEMV | `blas::gemv(aa, A, x, bb, y)` | $`y_i \leftarrow \alpha\sum_j A_{ij}x_j + \beta y_i`$ | `y=A%x` `y=aa*A%x` `y+=A%x` `y+=aa*A%x`[¤] | `y=blas::gemv(aa, A, x)` `y+=blas::gemv(aa, A, x)` | `transform(begin(A), end(A), begin(y), [&x, aa] (auto const& Ac) {return aa*blas::dot(Ac, x);})` | | | `blas::gemv(aa, blas::T(A), x, bb, y)` | $`y_i \leftarrow \alpha\sum_j A_{ji}x_j + \beta y_i`$ | `y= ~A % x` `y=aa*(~A)%x` `y+=(~A)%x` `y+=aa*(~A)%x` | `y=blas::gemv(aa, blas::T(A), x)` `y+=blas::gemv(aa, blas::T(A), x)` | `transform(begin(transposed(A)), end(transposed(A)), begin(y), [&x, aa] (auto const& Ac) {return aa*blas::dot(Ac, x);})` | diff --git a/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/asum.hpp b/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/asum.hpp index 864883c433..78ee1c06ca 100644 --- a/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/asum.hpp +++ b/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/asum.hpp @@ -6,7 +6,7 @@ #define BOOST_MULTI_ADAPTORS_BLAS_ASUM_HPP #pragma once -#include "../blas/core.hpp" +#include namespace boost::multi::blas { diff --git a/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/axpy.hpp b/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/axpy.hpp index d9834e4b4e..82a99f4839 100644 --- a/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/axpy.hpp +++ b/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/axpy.hpp @@ -6,14 +6,19 @@ #define BOOST_MULTI_ADAPTORS_BLAS_AXPY_HPP #pragma once +#include +// #include + #include -#include -#include +#include // for assert +#include // for complex +#include // for iterator_traits, rando... +#include // for enable_if_t, decay_t +#include // for forward, declval #define BOOST_MULTI_DECLRETURN(ExpR) -> decltype(ExpR) {return ExpR;} // NOLINT(cppcoreguidelines-macro-usage) saves a lot of typing -#define JUSTRETURN(ExpR) {return ExpR;} // NOLINT(cppcoreguidelines-macro-usage) saves a lot of typing -// TODO(correaa) ^^^ fix macro name +#define BOOST_MULTI_JUSTRETURN(ExpR) {return ExpR;} // NOLINT(cppcoreguidelines-macro-usage) saves a lot of typing namespace boost::multi::blas { @@ -22,12 +27,12 @@ using core::axpy; template auto axpy_n(typename It1::value_type alpha, It1 first, Size n, OutIt d_first) ->decltype(axpy(n, &alpha, first.base(), first.stride(), d_first.base(), d_first.stride()), d_first + n) { - return axpy(n, &alpha, base(first) , stride(first) , base(d_first) , stride(d_first) ), d_first + n; } + return axpy(n, &alpha, first.base(), first.stride(), d_first.base() , stride(d_first) ), d_first + n; } template//, class=std::enable_if_t{}>> auto axpy_n(Context ctxt, typename It1::value_type alpha, It1 first, Size n, OutIt d_first) ->decltype(ctxt->axpy(n, &alpha, first.base(), first.stride(), d_first.base(), d_first.stride()), d_first + n) { - return ctxt->axpy(n, &alpha, base(first) , stride(first) , base(d_first) , stride(d_first) ), d_first + n; } + return ctxt->axpy(n, &alpha, first.base(), first.stride(), d_first.base(), d_first.stride()), d_first + n; } template()[0] = 0.0, *X1DIt{} )> auto axpy(Context ctxt, typename X1DIt::element alpha, X1DIt x, Y1D&& y) // NOLINT(readability-identifier-length) conventional BLAS names @@ -37,7 +42,7 @@ auto axpy(Context ctxt, typename X1DIt::element alpha, X1DIt x, Y1D&& y) // NOL template()[0] = 0.0, size(std::declval()) )> auto axpy(Context ctxt, typename X1D::element alpha, X1D const& x, Y1D&& y) // NOLINT(readability-identifier-length) conventional BLAS names ->decltype( std::forward(y)) { assert(x.size() == y.size() ); - return axpy_n(ctxt, alpha, begin(x), size(y), begin(y)), std::forward(y); } + return axpy_n(ctxt, alpha, x.begin(), y.size(), y.begin()), std::forward(y); } template()[0] = 0.0 )> auto axpy(typename X1D::element alpha, X1D const& x, Y1D&& y) // NOLINT(readability-identifier-length) conventional BLAS names @@ -109,7 +114,8 @@ class axpy_range { auto begin() const -> iterator{ return {ctxt_, alpha_, x_begin_ }; } auto end() const -> iterator{ return {ctxt_, alpha_, x_begin_ + count_}; } - auto size() const -> size_type{return end() - begin();} + auto size() const -> size_type { return end() - begin(); } + auto extensions() const { return extensions_t<1>{ {0, size()} }; } template friend auto operator+=(Other&& other, axpy_range const& self) -> Other&& { @@ -126,7 +132,8 @@ class axpy_range { auto operator*=(Scale s) & -> axpy_range& {alpha_ *= s; return *this;} // NOLINT(readability-identifier-length) conventional BLAS naming }; -template{}>> +template{}>> // NOLINT(modernize-use-constraints) for C++20 auto axpy(Context&& ctxt, Scalar a, X1D const& x) // NOLINT(readability-identifier-length) conventional BLAS naming -> axpy_range { // NOLINT(readability-identifier-length) conventional BLAS naming return {std::forward(ctxt), a, begin(x), end(x)}; @@ -136,7 +143,7 @@ template auto axpy(Scalar a, X1D const& x) // NOLINT(readability-identifier-length) conventional BLAS naming { auto ctxtp = blas::default_context_of(x.base()); - return axpy_range{ctxtp, a, begin(x), end(x)}; // TODO(correaa) fix temporary + return axpy_range{ctxtp, a, begin(x), end(x)}; } template @@ -154,15 +161,16 @@ class scaled { namespace operators { -template struct algebraic_traits {static auto one() {return T{1.0};}}; +template struct algebraic_traits {static auto one() { return T{1.0}; }}; template struct algebraic_traits> {static auto one() {return std ::complex{T{1}, T{0}};}}; -template struct algebraic_traits> {static auto one() {return multi::complex{T{1}, T{0}};}}; +// template struct algebraic_traits> {static auto one() {return multi::complex{T{1}, T{0}};}}; template auto operator+=(X1D&& x, Y1D const& other) BOOST_MULTI_DECLRETURN(axpy(+algebraic_traits::one(), other, std::forward(x))) // NOLINT(fuchsia-default-arguments-calls,readability-identifier-length) conventional name in BLAS template auto operator-=(X1D&& x, Y1D const& other) BOOST_MULTI_DECLRETURN(axpy(-algebraic_traits::one(), other, std::forward(x))) // NOLINT(fuchsia-default-arguments-calls,readability-identifier-length) conventional name in BLAS -template =0> +template =0> // NOLINT(modernize-use-constraints) for C++20 auto operator*(typename X::element_type a, X const& x) {return scaled{a, x};} // NOLINT(readability-identifier-length) conventional BLAS naming template auto operator+(X1D const& x, Y1D const& y) -> std::decay_t {auto X = x.decay(); X += y; return X;} // NOLINT(readability-identifier-length) conventional name in BLAS @@ -173,6 +181,6 @@ template auto operator-(X1D const& x, Y1D const& y) -> std } // end namespace boost::multi::blas #undef BOOST_MULTI_DECLRETURN -#undef JUSTRETURN +#undef BOOST_MULTI_JUSTRETURN #endif // BOOST_MULTI_ADAPTORS_BLAS_AXPY_HPP diff --git a/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/complex_traits.hpp b/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/complex_traits.hpp index 6a7df6247a..41c82c34aa 100644 --- a/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/complex_traits.hpp +++ b/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/complex_traits.hpp @@ -34,7 +34,6 @@ struct complex_traits<::thrust::complex> { }; #endif - } // end namespace boost::multi::blas #endif diff --git a/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/copy.hpp b/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/copy.hpp index ebba4cfeb8..613e5e6bd9 100644 --- a/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/copy.hpp +++ b/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/copy.hpp @@ -6,10 +6,12 @@ #define BOOST_MULTI_ADAPTORS_BLAS_COPY_HPP #pragma once -#include -#include +#include // for copy, default_context_of // IWYU pragma: export +// IWYU pragma: no_include "boost/multi/adaptors/blas/core.hpp" // bug in iwyu 18.1.8? -#include +#include // for assert +#include // for iterator_traits, outpu... +#include // for forward namespace boost::multi::blas { @@ -17,44 +19,46 @@ using core::copy; template auto copy_n(It first, Size n, OutIt d_first) -->decltype(blas::default_context_of(first.base())->copy(n, first.base(), first.stride(), d_first.base(), d_first.stride()), d_first + n) { - return blas::default_context_of(first.base())->copy(n, first.base(), first.stride(), d_first.base(), d_first.stride()), d_first + n; } + -> decltype(blas::default_context_of(first.base())->copy(n, first.base(), first.stride(), d_first.base(), d_first.stride()), d_first + n) { + /**/ return blas::default_context_of(first.base())->copy(n, first.base(), first.stride(), d_first.base(), d_first.stride()), d_first + n; +} template auto copy(X1D const& x, Y1D&& y) // NOLINT(readability-identifier-length) BLAS naming -->decltype(blas::copy_n(x.begin(), size(x), y.begin()), std::forward(y)) { - assert( (x.size() == y.size()) ); // NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay) : assert - return blas::copy_n(x.begin(), x.size(), y.begin()), std::forward(y); } + -> decltype(blas::copy_n(x.begin(), size(x), y.begin()), std::forward(y)) { + assert((x.size() == y.size())); // NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay) : assert + /**/ return blas::copy_n(x.begin(), x.size(), y.begin()), std::forward(y); +} template struct copy_it { It it_; // NOLINT(misc-non-private-member-variables-in-classes) - using difference_type = typename std::iterator_traits::difference_type; - using value_type = typename std::iterator_traits::value_type; - using pointer = void; - using reference = void; + using difference_type = typename std::iterator_traits::difference_type; + using value_type = typename std::iterator_traits::value_type; + using pointer = void; + using reference = void; using iterator_category = std::output_iterator_tag; - using iterator_type = copy_it; + using iterator_type = copy_it; - friend auto operator-(copy_it const& c1, copy_it const& c2) {return c1.it_ - c2.it_;} + friend auto operator-(copy_it const& c1, copy_it const& c2) { return c1.it_ - c2.it_; } template - friend constexpr auto copy_n(copy_it first, difference_type count, It1DOut result) -> It1DOut{ + friend constexpr auto copy_n(copy_it first, difference_type count, It1DOut result) -> It1DOut { return blas::copy_n(first.it_, count, result); } - template - friend constexpr auto copy(copy_it first, copy_it last, It1DOut d_first) -> It1DOut{ + template + friend constexpr auto copy(copy_it first, copy_it last, It1DOut d_first) -> It1DOut { return copy_n(first, distance(first, last), d_first); } template - friend constexpr auto uninitialized_copy(copy_it first, copy_it last, It1DOut d_first) -> It1DOut{ + friend constexpr auto uninitialized_copy(copy_it first, copy_it last, It1DOut d_first) -> It1DOut { return copy_n(first, distance(first, last), d_first); } friend constexpr auto distance(copy_it const& self, copy_it const& other) -> difference_type { return other.it_ - self.it_; } - constexpr auto operator*() const -> value_type {return *it_;} + constexpr auto operator*() const -> value_type { return *it_; } }; template [[nodiscard]] @@ -62,19 +66,21 @@ auto copy(A1D const& x) { // NOLINT(readability-identifier-length) BLAS naming struct ref { A1D const& x_; // NOLINT(misc-non-private-member-variables-in-classes,cppcoreguidelines-avoid-const-or-ref-data-members) using iterator = copy_it; - auto begin() const {return iterator{x_.begin()};} - auto end() const {return iterator{x_.end() };} - auto size() const {return x_.size();} - auto extensions() const {return x_.extensions();} + auto begin() const { return iterator{x_.begin()}; } + auto end() const { return iterator{x_.end()}; } + auto size() const { return x_.size(); } + auto extensions() const { return x_.extensions(); } }; return ref{x}; } namespace operators { - template - auto operator<<(A1D&& lhs, B1D const& rhs) -> A1D&& { - return boost::multi::blas::copy(rhs, std::forward(lhs)); - } + +template +auto operator<<(A1D&& lhs, B1D const& rhs) -> A1D&& { + return boost::multi::blas::copy(rhs, std::forward(lhs)); +} + } // end namespace operators } // end namespace boost::multi::blas diff --git a/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/core.hpp b/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/core.hpp index 4b250b0854..0efc832814 100644 --- a/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/core.hpp +++ b/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/core.hpp @@ -8,6 +8,7 @@ // https://software.intel.com/en-us/articles/intel-mkl-link-line-advisor +#include #include #include #include // int64_t @@ -18,7 +19,7 @@ // #include "../../config/MARK.hpp" -#include "../blas/traits.hpp" +#include // IWYU pragma: export #if ! defined(NDEBUG) #include @@ -214,48 +215,54 @@ xTRSM(s); xTRSM(d); xTRSM(c) ; xTRSM(z) ; namespace boost::multi::blas { -using s = float; -using d = double; -using c = std::complex; -using z = std::complex; -using v = void; - // Boundary Checked value #define BC(value) [](auto checked) {assert(checked >= std::numeric_limits::min() && checked < std::numeric_limits::max()); return checked;}(value) /*NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay)*/ namespace core { +using s = float; +using d = double; +using c = std::complex; +using z = std::complex; +using v = void; + using std::enable_if_t; using std::is_assignable; +using ::core::ssize_t; + // TODO(correaa) implement xrotg, xrotmg, xrot, xrotm -template{} && is_s{} && is_assignable{},int> =0> void swap(ssize_t n, SX* x, ptrdiff_t incx, SY* y, ptrdiff_t incy) noexcept {BLAS(sswap)(n, reinterpret_cast< float *>(x), incx, ( float *)(y), incy);} // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast,cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays,google-readability-casting,readability-identifier-length) // NOSONAR -template{} && is_d{} && is_assignable{},int> =0> void swap(ssize_t n, DX* x, ptrdiff_t incx, DY* y, ptrdiff_t incy) noexcept {BLAS(dswap)(n, reinterpret_cast< double *>(x), incx, ( double *)(y), incy);} // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast,cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays,google-readability-casting,readability-identifier-length) // NOSONAR -template{} && is_c{} && is_assignable{},int> =0> void swap(ssize_t n, CX* x, ptrdiff_t incx, CY* y, ptrdiff_t incy) noexcept {BLAS(cswap)(n, reinterpret_cast*>(x), incx, (std::complex*)(y), incy);} // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast,cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays,google-readability-casting,readability-identifier-length) // NOSONAR -template{} && is_z{} && is_assignable{},int> =0> void swap(ssize_t n, ZX* x, ptrdiff_t incx, ZY* y, ptrdiff_t incy) noexcept {BLAS(zswap)(n, reinterpret_cast*>(x), incx, (std::complex*)(y), incy);} // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast,cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays,google-readability-casting,readability-identifier-length) // NOSONAR +// NOLINTBEGIN(modernize-use-constraints) TODO(correaa) for C++20 +template{} && is_s{} && is_assignable{},int> =0> void swap(ssize_t n, SX* x, ptrdiff_t incx, SY* y, ptrdiff_t incy) noexcept {BLAS(sswap)(n, reinterpret_cast< float *>(x), incx, reinterpret_cast< float *>(y), incy);} // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast,cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays,google-readability-casting,readability-identifier-length) // NOSONAR +template{} && is_d{} && is_assignable{},int> =0> void swap(ssize_t n, DX* x, ptrdiff_t incx, DY* y, ptrdiff_t incy) noexcept {BLAS(dswap)(n, reinterpret_cast< double *>(x), incx, reinterpret_cast< double *>(y), incy);} // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast,cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays,google-readability-casting,readability-identifier-length) // NOSONAR +template{} && is_c{} && is_assignable{},int> =0> void swap(ssize_t n, CX* x, ptrdiff_t incx, CY* y, ptrdiff_t incy) noexcept {BLAS(cswap)(n, reinterpret_cast*>(x), incx, reinterpret_cast*>(y), incy);} // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast,cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays,google-readability-casting,readability-identifier-length) // NOSONAR +template{} && is_z{} && is_assignable{},int> =0> void swap(ssize_t n, ZX* x, ptrdiff_t incx, ZY* y, ptrdiff_t incy) noexcept {BLAS(zswap)(n, reinterpret_cast*>(x), incx, reinterpret_cast*>(y), incy);} // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast,cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays,google-readability-casting,readability-identifier-length) // NOSONAR -template{} && is_s{} && is_assignable{},int> =0> void copy(ssize_t n, SX* x, ptrdiff_t incx, SY* y, ptrdiff_t incy) {BLAS(scopy)(n, ( float const*)(x), incx, ( float *)(y), incy);} // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast,cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays,google-readability-casting,readability-identifier-length) -template{} && is_d{} && is_assignable{},int> =0> void copy(ssize_t n, DX* x, ptrdiff_t incx, DY* y, ptrdiff_t incy) {BLAS(dcopy)(n, ( double const*)(x), incx, ( double *)(y), incy);} // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast,cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays,google-readability-casting,readability-identifier-length) -template{} && is_c{} && is_assignable{},int> =0> void copy(ssize_t n, CX* x, ptrdiff_t incx, CY* y, ptrdiff_t incy) {BLAS(ccopy)(n, (std::complex const*)(x), incx, (std::complex*)(y), incy);} // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast,cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays,google-readability-casting,readability-identifier-length) -template{} && is_z{} && is_assignable{},int> =0> void copy(ssize_t n, ZX* x, ptrdiff_t incx, ZY* y, ptrdiff_t incy) {BLAS(zcopy)(n, (std::complex const*)(x), incx, (std::complex*)(y), incy);} // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast,cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays,google-readability-casting,readability-identifier-length) +template{} && is_s{} && is_assignable{},int> =0> void copy(ssize_t n, SX* x, ptrdiff_t incx, SY* y, ptrdiff_t incy) {BLAS(scopy)(n, reinterpret_cast< float const*>(x), incx, reinterpret_cast< float *>(y), incy);} // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast,cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays,google-readability-casting,readability-identifier-length) +template{} && is_d{} && is_assignable{},int> =0> void copy(ssize_t n, DX* x, ptrdiff_t incx, DY* y, ptrdiff_t incy) {BLAS(dcopy)(n, reinterpret_cast< double const*>(x), incx, reinterpret_cast< double *>(y), incy);} // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast,cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays,google-readability-casting,readability-identifier-length) +template{} && is_c{} && is_assignable{},int> =0> void copy(ssize_t n, CX* x, ptrdiff_t incx, CY* y, ptrdiff_t incy) {BLAS(ccopy)(n, reinterpret_cast const*>(x), incx, reinterpret_cast*>(y), incy);} // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast,cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays,google-readability-casting,readability-identifier-length) +template{} && is_z{} && is_assignable{},int> =0> void copy(ssize_t n, ZX* x, ptrdiff_t incx, ZY* y, ptrdiff_t incy) {BLAS(zcopy)(n, reinterpret_cast const*>(x), incx, reinterpret_cast*>(y), incy);} // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast,cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays,google-readability-casting,readability-identifier-length) +// NOLINTEND(modernize-use-constraints) TODO(correaa) for C++20 // TODO(correaa) : add mixed-type scal (zdscal, csscal) -template::element_type, class ALPHA = typename std::pointer_traits::element_type, enable_if_t{} && is_s{} && is_assignable{}>* = nullptr> void scal(ssize_t n, ALPHAP a, SXP xp, ptrdiff_t incx) {BLAS(sscal)(n, *( float const*)a, ( float *)xp, incx);} // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast,cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays,google-readability-casting,readability-identifier-length) -template::element_type, class ALPHA = typename std::pointer_traits::element_type, enable_if_t{} && is_d{} && is_assignable{}>* = nullptr> void scal(ssize_t n, ALPHAP a, DXP xp, ptrdiff_t incx) {BLAS(dscal)(n, *( double const*)a, ( double *)xp, incx);} // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast,cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays,google-readability-casting,readability-identifier-length) -template::element_type, class ALPHA = typename std::pointer_traits::element_type, enable_if_t{} && is_c{} && is_assignable{}>* = nullptr> void scal(ssize_t n, ALPHAP a, CXP xp, ptrdiff_t incx) {BLAS(cscal)(n, *(std::complex const*)a, (std::complex*)xp, incx);} // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast,cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays,google-readability-casting,readability-identifier-length) -template::element_type, class ALPHA = typename std::pointer_traits::element_type, enable_if_t{} && is_z{} && is_assignable{}>* = nullptr> void scal(ssize_t n, ALPHAP a, ZXP xp, ptrdiff_t incx) {BLAS(zscal)(n, *(std::complex const*)a, (std::complex*)xp, incx);} // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast,cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays,google-readability-casting,readability-identifier-length) +// NOLINTBEGIN(modernize-use-constraints) TODO(correaa) for C++20 +template::element_type, class ALPHA = typename std::pointer_traits::element_type, enable_if_t{} && is_s{} && is_assignable{}>* = nullptr> void scal(ssize_t n, ALPHAP a, SXP xp, ptrdiff_t incx) {BLAS(sscal)(n, *reinterpret_cast< float const*>(a), reinterpret_cast< float *>(xp), incx);} // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast,cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays,google-readability-casting,readability-identifier-length) +template::element_type, class ALPHA = typename std::pointer_traits::element_type, enable_if_t{} && is_d{} && is_assignable{}>* = nullptr> void scal(ssize_t n, ALPHAP a, DXP xp, ptrdiff_t incx) {BLAS(dscal)(n, *reinterpret_cast< double const*>(a), reinterpret_cast< double *>(xp), incx);} // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast,cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays,google-readability-casting,readability-identifier-length) +template::element_type, class ALPHA = typename std::pointer_traits::element_type, enable_if_t{} && is_c{} && is_assignable{}>* = nullptr> void scal(ssize_t n, ALPHAP a, CXP xp, ptrdiff_t incx) {BLAS(cscal)(n, *reinterpret_cast const*>(a), reinterpret_cast*>(xp), incx);} // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast,cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays,google-readability-casting,readability-identifier-length) +template::element_type, class ALPHA = typename std::pointer_traits::element_type, enable_if_t{} && is_z{} && is_assignable{}>* = nullptr> void scal(ssize_t n, ALPHAP a, ZXP xp, ptrdiff_t incx) {BLAS(zscal)(n, *reinterpret_cast const*>(a), reinterpret_cast*>(xp), incx);} // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast,cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays,google-readability-casting,readability-identifier-length) +// NOLINTEND(modernize-use-constraints) TODO(correaa) for C++20 using std::pointer_traits; using std::enable_if_t; using std::is_convertible_v; #define xaxpy(T) \ -template::element_type, class SYP, class SY = typename pointer_traits::element_type, enable_if_t< \ +template::element_type, class SYP, class SY = typename pointer_traits::element_type, enable_if_t< /* NOLINT(modernize-use-constraints) */ \ is_##T{} && is_##T{} && is_##T{} && is_assignable{} \ && is_convertible_v && is_convertible_v \ , int> =0> \ -void axpy(size_t n, ALPHA const* a, SXP x, size_t incx, SYP y, size_t incy) {BLAS(T##axpy)(n, (T const *)a, (T const*)static_cast(x), incx, (T*)static_cast(y), incy);} /*NOLINT(readability-identifier-length) NOLINT(readability-identifier-length) conventional BLAS name*/ +void axpy(size_t n, ALPHA const* a, SXP x, size_t incx, SYP y, size_t incy) {BLAS(T##axpy)(n, reinterpret_cast(a), reinterpret_cast(static_cast(x)), incx, reinterpret_cast(static_cast(y)), incy);} /*NOLINT(readability-identifier-length,cppcoreguidelines-pro-type-reinterpret-cast,bugprone-macro-parentheses) conventional BLAS name*/ xaxpy(s) xaxpy(d) xaxpy(c) xaxpy(z) #undef xaxpy @@ -276,26 +283,99 @@ namespace core { using std::enable_if_t; using std::is_assignable; -template::element_type, class YP, class Y = typename std::pointer_traits::element_type, class RP, class R = typename std::pointer_traits::element_type, enable_if_t{} && is_s{} && is_assignable{}, int> =0> void dot (ssize_t n, XP* x, ptrdiff_t incx, YP* y, ptrdiff_t incy, RP* r) {auto const rr = BLAS(sdot )(n, (s const*)static_cast(x), incx, (s const*)static_cast(y), incy); std::memcpy(reinterpret_cast(static_cast(r)), &rr, sizeof(rr)); static_assert(sizeof(rr)==sizeof(*r));} // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast,cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays,google-readability-casting,readability-identifier-length) // NOSONAR -template::element_type, class YP, class Y = typename std::pointer_traits::element_type, class RP, class R = typename std::pointer_traits::element_type, enable_if_t{} && is_d{} && is_assignable{}, int> =0> void dot (ssize_t n, XP* x, ptrdiff_t incx, YP* y, ptrdiff_t incy, RP* r) {auto const rr = BLAS(ddot )(n, (d const*)static_cast(x), incx, (d const*)static_cast(y), incy); std::memcpy(reinterpret_cast(static_cast(r)), &rr, sizeof(rr)); static_assert(sizeof(rr)==sizeof(*r));} // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast,cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays,google-readability-casting,readability-identifier-length) // NOSONAR +// NOLINTBEGIN(modernize-use-constraints) TODO(correaa) for C++20 +template::element_type, class YP, class Y = typename std::pointer_traits::element_type, class RP, class R = typename std::pointer_traits::element_type, enable_if_t{} && is_s{} && is_assignable{}, int> =0> void dot (ssize_t n, XP* xp, ptrdiff_t incx, YP* yp, ptrdiff_t incy, RP* rp) { + // Apple Accelerate BLAS is known to have bugs in single precission function + // `sdot` and `smrm2`, be careful: + // https://stackoverflow.com/a/77017238/225186, + // https://fortran-lang.discourse.group/t/how-many-blas-libraries-have-this-error/4454/23, + // https://forums.developer.apple.com/forums/thread/717757 +#ifdef MULTI_BLAS_USE_SDOT // disable workararound for Apple Accelerate framework bug + auto const rr = BLAS(sdot )(n, reinterpret_cast(static_cast(xp)), incx, reinterpret_cast(static_cast(yp)), incy); std::memcpy(reinterpret_cast(static_cast(r)), &rr, sizeof(rr)); static_assert(sizeof(rr)==sizeof(*r)); +#else + BLAS(sgemv)('N', 1, n, 1.0F, reinterpret_cast(static_cast(xp)), incx, reinterpret_cast(static_cast(yp)), incy, 0.0F, reinterpret_cast(static_cast(rp)), 1); // NOLINT(readability-suspicious-call-argument,cppcoreguidelines-pro-type-reinterpret-cast) +#endif +} +template::element_type, class YP, class Y = typename std::pointer_traits::element_type, class RP, class R = typename std::pointer_traits::element_type, enable_if_t{} && is_d{} && is_assignable{}, int> =0> void dot (ssize_t n, XP* xp, ptrdiff_t incx, YP* yp, ptrdiff_t incy, RP* r) {auto const rr = BLAS(ddot )(n, reinterpret_cast(static_cast(xp)), incx, reinterpret_cast(static_cast(yp)), incy); std::memcpy(reinterpret_cast(static_cast(r)), &rr, sizeof(rr)); static_assert(sizeof(rr)==sizeof(*r));} // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast,cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays,google-readability-casting,readability-identifier-length) // NOSONAR +// NOLINTEND(modernize-use-constraints) TODO(correaa) for C++20 // PGI/NVC++ compiler uses a blas version that needs -DRETURN_BY_STACK +// NOLINTBEGIN(modernize-use-constraints) TODO(correaa) for C++20 #if defined(BLAS_DOT_RETURNS_VOID) -template::element_type, class YP, class Y = typename std::pointer_traits::element_type, class RP, class R = typename std::pointer_traits::element_type, enable_if_t{} && is_c{} && is_assignable{}, int> =0> void dotu(ssize_t n, XP xp, ptrdiff_t incx, YP yp, ptrdiff_t incy, RP rp) { BLAS(cdotu)(reinterpret_cast(rp), n, (c const*)static_cast(xp), incx, (c const*)static_cast(yp), incy);} // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast,google-readability-casting) : adapt types -template::element_type, class YP, class Y = typename std::pointer_traits::element_type, class RP, class R = typename std::pointer_traits::element_type, enable_if_t{} && is_z{} && is_assignable{}, int> =0> void dotu(ssize_t n, XP xp, ptrdiff_t incx, YP yp, ptrdiff_t incy, RP rp) { BLAS(zdotu)(reinterpret_cast(rp), n, (z const*)static_cast(xp), incx, (z const*)static_cast(yp), incy);} // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast,google-readability-casting) : adapt types - -template::element_type, class YP, class Y = typename std::pointer_traits::element_type, class RP, class R = typename std::pointer_traits::element_type, enable_if_t{} && is_c{} && is_assignable{}, int> =0> void dotc(ssize_t n, XP xp, ptrdiff_t incx, YP yp, ptrdiff_t incy, RP rp) { BLAS(cdotc)(reinterpret_cast(rp), n, (c const*)static_cast(xp), incx, (c const*)static_cast(yp), incy);} // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast,google-readability-casting) : adapt types -template::element_type, class YP, class Y = typename std::pointer_traits::element_type, class RP, class R = typename std::pointer_traits::element_type, enable_if_t{} && is_z{} && is_assignable{}, int> =0> void dotc(ssize_t n, XP xp, ptrdiff_t incx, YP yp, ptrdiff_t incy, RP rp) { BLAS(zdotc)(reinterpret_cast(rp), n, (z const*)static_cast(xp), incx, (z const*)static_cast(yp), incy);} // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast,google-readability-casting) : adapt types +template::element_type, class YP, class Y = typename std::pointer_traits::element_type, class RP, class R = typename std::pointer_traits::element_type, enable_if_t{} && is_c{} && is_assignable{}, int> =0> void dotu(ssize_t n, XP xp, ptrdiff_t incx, YP yp, ptrdiff_t incy, RP rp) { + [[maybe_unused]] static bool const check = []{ + std::array, 3> const v1 = {std::complex{1.0F, 2.0F}, std::complex{3.0F, 4.0F}, std::complex{ 5.0F, 6.0F}}; + std::array, 3> const v2 = {std::complex{7.0F, 8.0F}, std::complex{9.0F, 10.0F}, std::complex{11.0F, 12.0F}}; + Complex_float rr{-1.0F, -2.0F}; + BLAS(cdotu)(&rr, 3, v1.data(), 1, v2.data(), 1); + if( std::abs(rr.real - std::real(v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2])) > 1.0e-8 ) { throw std::logic_error("[real] cdotu should be configured as non-void returing"); } + if( std::abs(rr.imag - std::imag(v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2])) > 1.0e-8 ) { throw std::logic_error("[imag] cdotu should be configured as non-void returing"); } + return true; + }(); + // BLAS(cdotu)(reinterpret_cast(rp), n, reinterpret_cast(static_cast(xp)), incx, reinterpret_cast(static_cast(yp)), incy); // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast) + BLAS(cgemv)('N', 1, n, std::complex{1.0F, 0.0F}, reinterpret_cast(static_cast(xp)), incx, reinterpret_cast(static_cast(yp)), incy, std::complex{0.0F, 0.0F}, reinterpret_cast(static_cast(rp)), 1); // NOLINT(readability-suspicious-call-argument,cppcoreguidelines-pro-type-reinterpret-cast) +} // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast,google-readability-casting) : adapt types +template::element_type, class YP, class Y = typename std::pointer_traits::element_type, class RP, class R = typename std::pointer_traits::element_type, enable_if_t{} && is_z{} && is_assignable{}, int> =0> void dotu(ssize_t n, XP xp, ptrdiff_t incx, YP yp, ptrdiff_t incy, RP rp) { BLAS(zdotu)(reinterpret_cast(rp), n, reinterpret_cast(static_cast(xp)), incx, reinterpret_cast(static_cast(yp)), incy);} // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast,google-readability-casting) : adapt types + +template::element_type, class YP, class Y = typename std::pointer_traits::element_type, class RP, class R = typename std::pointer_traits::element_type, enable_if_t{} && is_c{} && is_assignable{}, int> =0> void dotc(ssize_t n, XP xp, ptrdiff_t incx, YP yp, ptrdiff_t incy, RP rp) { + std::clog << "using cdotc void\n"; + BLAS(cdotc)(reinterpret_cast(rp), n, reinterpret_cast(static_cast(xp)), incx, reinterpret_cast(static_cast(yp)), incy); // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast) + // BLAS(cgemv)('C', n, 1, std::complex{1.0F, 0.0F}, reinterpret_cast(static_cast(xp)), incx, reinterpret_cast(static_cast(yp)), incy, std::complex{0.0F, 0.0F}, reinterpret_cast(static_cast(rp)), 1); // NOLINT(readability-suspicious-call-argument) +} // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast,google-readability-casting) : adapt types +template::element_type, class YP, class Y = typename std::pointer_traits::element_type, class RP, class R = typename std::pointer_traits::element_type, enable_if_t{} && is_z{} && is_assignable{}, int> =0> void dotc(ssize_t n, XP xp, ptrdiff_t incx, YP yp, ptrdiff_t incy, RP rp) { BLAS(zdotc)(reinterpret_cast(rp), n, reinterpret_cast(static_cast(xp)), incx, reinterpret_cast(static_cast(yp)), incy);} // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast,google-readability-casting) : adapt types #else // NOLINTBEGIN(cppcoreguidelines-pro-type-reinterpret-cast,cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays,google-readability-casting,readability-identifier-length) // TODO(correaa) implement workaround for bug in Apple Accelerate BLAS ? https://stackoverflow.com/a/77017238/225186 -template::element_type, class YP, class Y = typename std::pointer_traits::element_type, class RP, class R = typename std::pointer_traits::element_type, enable_if_t{} && is_c{} && is_assignable{}, int> =0> void dotu(ssize_t n, XP x, ptrdiff_t incx, YP y, ptrdiff_t incy, RP r) {auto const rr = BLAS(cdotu)( n, (c const*)static_cast(x), incx, (c const*)static_cast(y), incy); std::memcpy(reinterpret_cast*>(static_cast(r))->data(), &rr, sizeof(rr)); static_assert(sizeof(rr)==sizeof(*r));} // NOSONAR -template::element_type, class YP, class Y = typename std::pointer_traits::element_type, class RP, class R = typename std::pointer_traits::element_type, enable_if_t{} && is_z{} && is_assignable{}, int> =0> void dotu(ssize_t n, XP x, ptrdiff_t incx, YP y, ptrdiff_t incy, RP r) {auto const rr = BLAS(zdotu)( n, (z const*)static_cast(x), incx, (z const*)static_cast(y), incy); std::memcpy(reinterpret_cast*>(static_cast(r))->data(), &rr, sizeof(rr)); static_assert(sizeof(rr)==sizeof(*r));} // NOSONAR +template::element_type, class YP, class Y = typename std::pointer_traits::element_type, class RP, class R = typename std::pointer_traits::element_type, enable_if_t{} && is_c{} && is_assignable{}, int> =0> void dotu(ssize_t n, XP xp, ptrdiff_t incx, YP yp, ptrdiff_t incy, RP rp) { + // [[maybe_unused]] static bool const use_cdotu = []{ + // std::array, 3> const v1 = {std::complex{1.0F, 2.0F}, std::complex{3.0F, 4.0F}, std::complex{ 5.0F, 6.0F}}; + // std::array, 3> const v2 = {std::complex{7.0F, 8.0F}, std::complex{9.0F, 10.0F}, std::complex{11.0F, 12.0F}}; + + // Complex_float rr{-1.0F, -2.0F}; + // rr = BLAS(cdotu)(3, v1.data(), 1, v2.data(), 1); + + // if( !(std::abs(rr.real - std::real(v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2])) < 1.0e-8) + // || !(std::abs(rr.imag - std::imag(v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2])) < 1.0e-8) ) { + // std::clog + // << "multi::blas setup warning: when using cdotu that returns non-void,\n" + // << "cdotu returned (" << rr.real << ", " << rr.imag << ", it should return " << v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2] << '\n' + // << "This problem appears with BLAS and OpenBLAS 32bit.\n" + // << "... falling back to cgemv\n"; + // { + // std::complex gemv_rr{-12.345F, -54.321F}; + // BLAS(cgemv)('N', 1, v1.size(), std::complex{1.0F, 0.0F}, v1.data(), 1, v2.data(), 1, std::complex{0.0F, 0.0F}, &gemv_rr, 1); + // std::clog << "cgemv gives " << gemv_rr << ", it should give " << v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2] << '\n'; + + // if( !(std::abs(gemv_rr - (v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2])) < 1.0e-8) ) { + // std::clog << "gemv also failed" << '\n'; + // } + // return false; // dot not use cdotu + // } + // } + // return true; // use cdotu + // }(); + // if(use_cdotu) { + // Complex_float const rr = BLAS(cdotu)( n, reinterpret_cast(static_cast(x)), incx, reinterpret_cast(static_cast(y)), incy); std::memcpy(reinterpret_cast*>(static_cast(rp))->data(), &rr, sizeof(rr)); static_assert(sizeof(rr)==sizeof(*rp)); + // } else { + BLAS(cgemv)('N', 1, n, std::complex{1.0F, 0.0F}, reinterpret_cast(static_cast(xp)), incx, reinterpret_cast(static_cast(yp)), incy, std::complex{0.0F, 0.0F}, reinterpret_cast(static_cast(rp)), 1); // NOLINT(readability-suspicious-call-argument) + // } +} +template::element_type, class YP, class Y = typename std::pointer_traits::element_type, class RP, class R = typename std::pointer_traits::element_type, enable_if_t{} && is_z{} && is_assignable{}, int> =0> void dotu(ssize_t n, XP xp, ptrdiff_t incx, YP yp, ptrdiff_t incy, RP rp) { + // auto const rr = BLAS(zdotu)( n, reinterpret_cast(static_cast(xp)), incx, reinterpret_cast(static_cast(yp)), incy); std::memcpy(reinterpret_cast*>(static_cast(rp))->data(), &rr, sizeof(rr)); static_assert(sizeof(rr)==sizeof(*rp)); + BLAS(zgemv)('N', 1, n, std::complex{1.0, 0.0}, reinterpret_cast(static_cast(xp)), incx, reinterpret_cast(static_cast(yp)), incy, std::complex{0.0, 0.0}, reinterpret_cast(static_cast(rp)), 1); // NOLINT(readability-suspicious-call-argument) +} -template::element_type, class YP, class Y = typename std::pointer_traits::element_type, class RP, class R = typename std::pointer_traits::element_type, enable_if_t{} && is_c{} && is_assignable{}, int> =0> void dotc(ssize_t n, XP x, ptrdiff_t incx, YP y, ptrdiff_t incy, RP r) {auto const rr = BLAS(cdotc)( n, (c const*)static_cast(x), incx, (c const*)static_cast(y), incy); std::memcpy(reinterpret_cast*>(static_cast(r))->data(), &rr, sizeof(rr)); static_assert(sizeof(rr)==sizeof(*r));} // NOSONAR -template::element_type, class YP, class Y = typename std::pointer_traits::element_type, class RP, class R = typename std::pointer_traits::element_type, enable_if_t{} && is_z{} && is_assignable{}, int> =0> void dotc(ssize_t n, XP x, ptrdiff_t incx, YP y, ptrdiff_t incy, RP r) {auto const rr = BLAS(zdotc)( n, (z const*)static_cast(x), incx, (z const*)static_cast(y), incy); std::memcpy(reinterpret_cast*>(static_cast(r))->data(), &rr, sizeof(rr)); static_assert(sizeof(rr)==sizeof(*r));} // NOSONAR +template::element_type, class YP, class Y = typename std::pointer_traits::element_type, class RP, class R = typename std::pointer_traits::element_type, enable_if_t{} && is_c{} && is_assignable{}, int> =0> void dotc(ssize_t n, XP xp, ptrdiff_t incx, YP yp, ptrdiff_t incy, RP rp) { + // std::clog << "using cdotc non void\n"; + // c + auto const rr = BLAS(cdotc)( n, reinterpret_cast(static_cast(xp)), incx, reinterpret_cast(static_cast(yp)), incy); std::memcpy(reinterpret_cast*>(static_cast(rp))->data(), &rr, sizeof(rr)); static_assert(sizeof(rr)==sizeof(*rp)); + // BLAS(cgemv)('N', 1, n, std::complex{1.0F, 0.0F}, reinterpret_cast(static_cast(xp)), incx, reinterpret_cast(static_cast(yp)), incy, std::complex{0.0F, 0.0F}, reinterpret_cast(static_cast(rp)), 1); // NOLINT(readability-suspicious-call-argument) +} + +template::element_type, class YP, class Y = typename std::pointer_traits::element_type, class RP, class R = typename std::pointer_traits::element_type, enable_if_t{} && is_z{} && is_assignable{}, int> =0> void dotc(ssize_t n, XP x, ptrdiff_t incx, YP y, ptrdiff_t incy, RP r) {auto const rr = BLAS(zdotc)( n, reinterpret_cast(static_cast(x)), incx, reinterpret_cast(static_cast(y)), incy); std::memcpy(reinterpret_cast*>(static_cast(r))->data(), &rr, sizeof(rr)); static_assert(sizeof(rr)==sizeof(*r));} // NOSONAR // NOLINTEND(cppcoreguidelines-pro-type-reinterpret-cast,cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays,google-readability-casting,readability-identifier-length) #endif +// NOLINTEND(modernize-use-constraints) } // end namespace core #else @@ -321,18 +401,20 @@ namespace core { namespace core { -template::element_type, class RP, class R = typename std::pointer_traits::element_type, enable_if_t{} && is_s{} && std::is_assignable{} , int> =0> void asum(ssize_t n, XP x, ptrdiff_t incx, RP r) {auto rr = BLAS(sasum) (n, (s const*)static_cast(x), incx); std::memcpy((s*)static_cast(r), &rr, sizeof(s));} // NOLINT(google-readability-casting,readability-identifier-length) -template::element_type, class RP, class R = typename std::pointer_traits::element_type, enable_if_t{} && is_d{} && std::is_assignable{} , int> =0> void asum(ssize_t n, XP x, ptrdiff_t incx, RP r) {auto rr = BLAS(dasum) (n, (d const*)static_cast(x), incx); std::memcpy((s*)static_cast(r), &rr, sizeof(d));} // NOLINT(google-readability-casting,readability-identifier-length) +// NOLINTBEGIN(modernize-use-constraints) TODO(correaa) for C++20 +template::element_type, class RP, class R = typename std::pointer_traits::element_type, enable_if_t{} && is_s{} && std::is_assignable{} , int> =0> void asum(ssize_t n, XP x, ptrdiff_t incx, RP r) {auto rr = BLAS(sasum) (n, reinterpret_cast(static_cast(x)), incx); std::memcpy(reinterpret_cast(static_cast(r)), &rr, sizeof(s));} // NOLINT(google-readability-casting,readability-identifier-length,cppcoreguidelines-pro-type-reinterpret-cast) +template::element_type, class RP, class R = typename std::pointer_traits::element_type, enable_if_t{} && is_d{} && std::is_assignable{} , int> =0> void asum(ssize_t n, XP x, ptrdiff_t incx, RP r) {auto rr = BLAS(dasum) (n, reinterpret_cast(static_cast(x)), incx); std::memcpy(reinterpret_cast(static_cast(r)), &rr, sizeof(d));} // NOLINT(google-readability-casting,readability-identifier-length,cppcoreguidelines-pro-type-reinterpret-cast) -template::element_type, class RP, class R = typename std::pointer_traits::element_type, enable_if_t{} && is_s{} && std::is_assignable{}, int> =0> void asum(ssize_t n, XP x, ptrdiff_t incx, RP r) {auto rr = BLAS(scasum)(n, (c const*)static_cast(x), incx); std::memcpy((s*)static_cast(r), &rr, sizeof(s));} // NOLINT(google-readability-casting,readability-identifier-length) -template::element_type, class RP, class R = typename std::pointer_traits::element_type, enable_if_t{} && is_d{} && std::is_assignable{}, int> =0> void asum(ssize_t n, XP x, ptrdiff_t incx, RP r) {auto rr = BLAS(dzasum)(n, (z const*)static_cast(x), incx); std::memcpy((s*)static_cast(r), &rr, sizeof(d));} // NOLINT(google-readability-casting,readability-identifier-length) +template::element_type, class RP, class R = typename std::pointer_traits::element_type, enable_if_t{} && is_s{} && std::is_assignable{}, int> =0> void asum(ssize_t n, XP x, ptrdiff_t incx, RP r) {auto rr = BLAS(scasum)(n, reinterpret_cast(static_cast(x)), incx); std::memcpy(reinterpret_cast(static_cast(r)), &rr, sizeof(s));} // NOLINT(google-readability-casting,readability-identifier-length,cppcoreguidelines-pro-type-reinterpret-cast) +template::element_type, class RP, class R = typename std::pointer_traits::element_type, enable_if_t{} && is_d{} && std::is_assignable{}, int> =0> void asum(ssize_t n, XP x, ptrdiff_t incx, RP r) {auto rr = BLAS(dzasum)(n, reinterpret_cast(static_cast(x)), incx); std::memcpy(reinterpret_cast(static_cast(r)), &rr, sizeof(d));} // NOLINT(google-readability-casting,readability-identifier-length,cppcoreguidelines-pro-type-reinterpret-cast) // TODO(correaa) implement workaround for bug in Apple Accelerate BLAS ? https://stackoverflow.com/a/77017238/225186 -template::element_type, class RP, class R = typename std::pointer_traits::element_type, enable_if_t{} && is_s{} && std::is_assignable{} , int> =0> void nrm2(ssize_t n, XP x, ptrdiff_t incx, RP r) {auto rr = BLAS(snrm2) (n, (s const*)static_cast(x), incx); std::memcpy((s*)static_cast(r), &rr, sizeof(s));} // NOLINT(google-readability-casting,readability-identifier-length) -template::element_type, class RP, class R = typename std::pointer_traits::element_type, enable_if_t{} && is_d{} && std::is_assignable{} , int> =0> void nrm2(ssize_t n, XP x, ptrdiff_t incx, RP r) {auto rr = BLAS(dnrm2) (n, (d const*)static_cast(x), incx); std::memcpy((s*)static_cast(r), &rr, sizeof(d));} // NOLINT(google-readability-casting,readability-identifier-length) +template::element_type, class RP, class R = typename std::pointer_traits::element_type, enable_if_t{} && is_s{} && std::is_assignable{} , int> =0> void nrm2(ssize_t n, XP x, ptrdiff_t incx, RP r) {auto rr = BLAS(snrm2) (n, reinterpret_cast(static_cast(x)), incx); std::memcpy(reinterpret_cast(static_cast(r)), &rr, sizeof(s));} // NOLINT(google-readability-casting,readability-identifier-length,cppcoreguidelines-pro-type-reinterpret-cast) +template::element_type, class RP, class R = typename std::pointer_traits::element_type, enable_if_t{} && is_d{} && std::is_assignable{} , int> =0> void nrm2(ssize_t n, XP x, ptrdiff_t incx, RP r) {auto rr = BLAS(dnrm2) (n, reinterpret_cast(static_cast(x)), incx); std::memcpy(reinterpret_cast(static_cast(r)), &rr, sizeof(d));} // NOLINT(google-readability-casting,readability-identifier-length,cppcoreguidelines-pro-type-reinterpret-cast) -template::element_type, class RP, class R = typename std::pointer_traits::element_type, enable_if_t{} && is_s{} && std::is_assignable{}, int> =0> void nrm2(ssize_t n, XP x, ptrdiff_t incx, RP r) {auto rr = BLAS(scnrm2)(n, (c const*)static_cast(x), incx); std::memcpy((s*)static_cast(r), &rr, sizeof(s));} // NOLINT(google-readability-casting,readability-identifier-length) -template::element_type, class RP, class R = typename std::pointer_traits::element_type, enable_if_t{} && is_d{} && std::is_assignable{}, int> =0> void nrm2(ssize_t n, XP x, ptrdiff_t incx, RP r) {auto rr = BLAS(dznrm2)(n, (z const*)static_cast(x), incx); std::memcpy((s*)static_cast(r), &rr, sizeof(d));} // NOLINT(google-readability-casting,readability-identifier-length) +template::element_type, class RP, class R = typename std::pointer_traits::element_type, enable_if_t{} && is_s{} && std::is_assignable{}, int> =0> void nrm2(ssize_t n, XP x, ptrdiff_t incx, RP r) {auto rr = BLAS(scnrm2)(n, reinterpret_cast(static_cast(x)), incx); std::memcpy(reinterpret_cast(static_cast(r)), &rr, sizeof(s));} // NOLINT(google-readability-casting,readability-identifier-length,cppcoreguidelines-pro-type-reinterpret-cast) +template::element_type, class RP, class R = typename std::pointer_traits::element_type, enable_if_t{} && is_d{} && std::is_assignable{}, int> =0> void nrm2(ssize_t n, XP x, ptrdiff_t incx, RP r) {auto rr = BLAS(dznrm2)(n, reinterpret_cast(static_cast(x)), incx); std::memcpy(reinterpret_cast(static_cast(r)), &rr, sizeof(d));} // NOLINT(google-readability-casting,readability-identifier-length,cppcoreguidelines-pro-type-reinterpret-cast) +// NOLINTEND(modernize-use-constraints) TODO(correaa) for C++20 ixamax(s) ixamax(d) ixamax(c) ixamax(z) } // end namespace core @@ -354,16 +436,25 @@ namespace core { using std::enable_if_t; using std::is_assignable; +using size_t = INT; +using ssize_t = std::make_signed_t; + +// NOLINTBEGIN(modernize-use-constraints) TODO(correaa) for C++20 template{} && is_s{} && is_s{} && is_assignable{}, int> =0> void gemv(char trans, size_t m, size_t n, A const* a, M* ma, size_t lda, X* x, size_t incx, B const* b, Y* y, size_t incy) {BLAS(sgemv)(trans, m, n, *a, reinterpret_cast(ma), lda, reinterpret_cast(x), incx, *b, reinterpret_cast(y), incy);} // NOLINT(google-readability-casting,readability-identifier-length,cppcoreguidelines-pro-type-reinterpret-cast) // NOSONAR wrapped func has 11 params template{} && is_d{} && is_d{} && is_assignable{}, int> =0> void gemv(char trans, size_t m, size_t n, A const* a, M* ma, size_t lda, X* x, size_t incx, B const* b, Y* y, size_t incy) {BLAS(dgemv)(trans, m, n, *a, reinterpret_cast(ma), lda, reinterpret_cast(x), incx, *b, reinterpret_cast(y), incy);} // NOLINT(google-readability-casting,readability-identifier-length,cppcoreguidelines-pro-type-reinterpret-cast) // NOSONAR wrapped func has 11 params template{} && is_c{} && is_c{} && is_assignable{}, int> =0> void gemv(char trans, size_t m, size_t n, A const* a, M* ma, size_t lda, X* x, size_t incx, B const* b, Y* y, size_t incy) {BLAS(cgemv)(trans, m, n, *a, reinterpret_cast(ma), lda, reinterpret_cast(x), incx, *b, reinterpret_cast(y), incy);} // NOLINT(google-readability-casting,readability-identifier-length,cppcoreguidelines-pro-type-reinterpret-cast) // NOSONAR wrapped func has 11 params template{} && is_z{} && is_z{} && is_assignable()*std::declval()*std::declval()+std::declval()*std::declval())>{}, int> =0> void gemv(char trans, size_t m, size_t n, A const* a, M* ma, size_t lda, X* x, size_t incx, B const* b, Y* y, size_t incy) { // NOLINT(google-readability-casting,readability-identifier-length,cppcoreguidelines-pro-type-reinterpret-cast) //NOSONAR wrapped func has 11 params BLAS(zgemv)(trans, m, n, *a, reinterpret_cast(ma), lda, reinterpret_cast(x), incx, *b, reinterpret_cast(y), incy); // NOLINT(fuchsia-default-arguments-calls,google-readability-casting,readability-identifier-length,cppcoreguidelines-pro-type-reinterpret-cast) // NOSONAR } +// NOLINTEND(modernize-use-constraints) TODO(correaa) for C++20 // TODO(correaa) implement get, geru, gerc -} // end namespace core +using s = float; +using d = double; +using c = std::complex; +using z = std::complex; +using v = void; template struct blas2 {}; @@ -373,6 +464,8 @@ template<> struct blas2 {template static v trsv(As... args) template<> struct blas2 {template static v trsv(As... args) {BLAS(ctrsv)(args...);}}; template<> struct blas2 {template static auto trsv(As... args) -> decltype(BLAS(ztrsv)(args...)) {BLAS(ztrsv)(args...);}}; +} // end namespace core + /////////////////////////////////////////////////////////////////////////////// // LEVEL 3 @@ -385,61 +478,63 @@ using std::max; #define xsyrk(T) \ template::element_type, class BETA, class CCP, class CC = typename pointer_traits::element_type, \ -enable_if_t< \ +enable_if_t< /* NOLINT(modernize-use-constraints) TODO(correaa) for C++20 */ \ is_##T{} && is_##T{} && is_assignable{} && \ is_convertible_v && is_convertible_v \ , int> =0> \ v syrk( UL uplo, C transA, S n, S k, ALPHA const* alpha, AAP aa, S lda, BETA const* beta, CCP cc, S ldc) /*NOLINT(bugprone-easily-swappable-parameters,readability-identifier-length)*/ \ /*=delete;*/ \ { \ - if(transA == 'N' || transA == 'n') {BOOST_MULTI_ASSERT1( lda >= max(1L, n) );} \ - if(transA != 'N' && transA != 'n') {BOOST_MULTI_ASSERT1( lda >= max(1L, k) );} \ - BOOST_MULTI_ASSERT1( ldc >= max(1L, n) ); \ + if(transA == 'N' || transA == 'n') { BOOST_MULTI_ASSERT1( lda >= max(S{1}, n) ); } \ + if(transA != 'N' && transA != 'n') { BOOST_MULTI_ASSERT1( lda >= max(S{1}, k) ); } \ + BOOST_MULTI_ASSERT1( ldc >= max(S{1}, n) ); \ BLAS(T##syrk)( uplo, transA, BC(n), BC(k), *reinterpret_cast(alpha), aa, BC(lda), *reinterpret_cast(beta), cc, BC(ldc)); /*NOLINT(cppcoreguidelines-pro-type-reinterpret-cast)*/ \ } \ #define xherk(T) \ template::element_type, class BETA, class CCP, class CC = typename pointer_traits::element_type, class Real = typename T::value_type, \ -enable_if_t< \ +enable_if_t< /* NOLINT(modernize-use-constraints) TODO(correaa) for C++20 */ \ is_##T{} && is_##T{} && is_assignable{} && \ is_convertible_v && is_convertible_v \ , int> =0> \ v herk( UL uplo, C transA, S n, S k, ALPHA const* alpha, AAP aa, S lda, BETA const* beta, CCP cc, S ldc) /*NOLINT(bugprone-easily-swappable-parameters,readability-identifier-length)*/ \ /*=delete;*/ \ { \ - if(transA == 'N' || transA == 'n') {BOOST_MULTI_ASSERT1( lda >= max(1L, n) );} /* NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay)*/ \ - if(transA != 'N' && transA != 'n') {BOOST_MULTI_ASSERT1( lda >= max(1L, k) );} \ - BOOST_MULTI_ASSERT1( ldc >= max(1L, n) ); /* NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay)*/ \ + if(transA == 'N' || transA == 'n') {BOOST_MULTI_ASSERT1( lda >= max(S{1}, n) );} /* NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay)*/ \ + if(transA != 'N' && transA != 'n') {BOOST_MULTI_ASSERT1( lda >= max(S{1}, k) );} \ + BOOST_MULTI_ASSERT1( ldc >= max(S{1}, n) ); /* NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay)*/ \ /*BOOST_MULTI_MARK_SCOPE("cpu_herk");*/ \ BLAS(T##herk)( uplo, transA, BC(n), BC(k), *reinterpret_cast(alpha), aa, BC(lda), *reinterpret_cast(beta), cc, BC(ldc)); /*NOLINT(cppcoreguidelines-pro-type-reinterpret-cast)*/ \ } \ #define xgemm(T) \ template::element_type, class BBP, class BB = typename pointer_traits::element_type, class BETA, class CCP, class CC = typename pointer_traits::element_type, \ -enable_if_t< \ +enable_if_t< /* NOLINT(modernize-use-constraints) TODO(correaa) for C++20 */ \ is_##T{} && is_##T{} && is_##T{} && \ is_convertible_v && is_convertible_v && is_convertible_v \ , int> =0> \ v gemm(char transA, char transB, ssize_t m, ssize_t n, ssize_t k, ALPHA const* alpha, AAP aa, ssize_t lda, BBP bb, ssize_t ldb, BETA const* beta, CCP cc, ssize_t ldc) { /*NOLINT(bugprone-easily-swappable-parameters)*/ \ using std::max; \ - if(transA == 'N') {BOOST_MULTI_ASSERT1(lda >= max(1L, m));} \ - if(transA != 'N') {BOOST_MULTI_ASSERT1(lda >= max(1L, k));} \ - if(transB == 'N') {BOOST_MULTI_ASSERT1(ldb >= max(1L, k));} \ - if(transB != 'N') {BOOST_MULTI_ASSERT1(ldb >= max(1L, n));} \ + BOOST_MULTI_ASSERT1((transA != 'N') || (lda >= max(ssize_t{1}, m))); \ + BOOST_MULTI_ASSERT1((transA == 'N') || (lda >= max(ssize_t{1}, k))); \ + BOOST_MULTI_ASSERT1((transB != 'N') || (ldb >= max(ssize_t{1}, k))); \ + BOOST_MULTI_ASSERT1((transB == 'N') || (ldb >= max(ssize_t{1}, n))); \ +\ BOOST_MULTI_ASSERT1( aa != cc ); \ BOOST_MULTI_ASSERT1( bb != cc ); \ - if(!( ldc >= max(1L, m) )) {throw std::logic_error("failed 'ldc >= max(1L, m)' with ldc = "+ std::to_string(ldc) +" and m = "+ std::to_string(m));} \ +\ + if(!( ldc >= max(ssize_t{1}, m) )) {throw std::logic_error("failed 'ldc >= max(1, m)' with ldc = "+ std::to_string(ldc) +" and m = "+ std::to_string(m));} \ if(*beta != 0.0) {BOOST_MULTI_ASSERT1((is_assignable()*std::declval()*std::declval() + std::declval()*std::declval())> {}));} \ - BLAS(T##gemm)(transA, transB, BC(m), BC(n), BC(k), *reinterpret_cast(alpha), reinterpret_cast(static_cast(aa)), BC(lda), reinterpret_cast(static_cast(bb)), BC(ldb), *reinterpret_cast(beta), (T*)(static_cast(cc)) /*NOLINT(cppcoreguidelines-pro-type-reinterpret-cast)*/ /*TODO(correaa) check constness*/, BC(ldc)); \ + BLAS(T##gemm)(transA, transB, BC(m), BC(n), BC(k), *reinterpret_cast(alpha), reinterpret_cast(static_cast(aa)), BC(lda), reinterpret_cast(static_cast(bb)), BC(ldb), *reinterpret_cast(beta), reinterpret_cast(static_cast(cc)) /*NOLINT(cppcoreguidelines-pro-type-reinterpret-cast,bugprone-macro-parentheses)*/ /*TODO(correaa) check constness*/, BC(ldc)); \ } \ // NOLINTNEXTLINE(readability-identifier-length) conventional BLAS name -xgemm(s) xgemm(d) xgemm(c) xgemm(z) // NOLINT(readability-function-cognitive-complexity) : 36 of 25 +xgemm(s) xgemm(d) xgemm(c) xgemm(z) // NOLINT(modernize-use-constraints,readability-function-cognitive-complexity) : 36 of 25 #undef xgemm #define xtrsm(T) \ template::element_type, class BBP, class BB = typename pointer_traits::element_type, \ -enable_if_t< \ +enable_if_t< /* NOLINT(modernize-use-constraints) TODO(correaa) for C++20 */ \ is_##T{} && is_##T{} && is_assignable{} && is_assignable{} && \ is_convertible_v && is_convertible_v \ ,int> =0> \ @@ -456,12 +551,12 @@ v trsm(char side, char uplo, char transA, char diag, ssize_t m, ssize_t n, ALPHA BLAS(T##trsm)(side, uplo, transA, diag, BC(m), BC(n), alpha, reinterpret_cast(static_cast(aa)), BC(lda), reinterpret_cast(static_cast(bb)), BC(ldb)); /*NOLINT(cppcoreguidelines-pro-type-reinterpret-cast,bugprone-macro-parentheses)*/ \ } \ -xtrsm(s) xtrsm(d) xtrsm(c) xtrsm(z) // NOLINT(readability-function-cognitive-complexity) : 29 of 25 +xtrsm(s) xtrsm(d) xtrsm(c) xtrsm(z) // NOLINT(modernize-use-constraints,readability-function-cognitive-complexity) : 29 of 25 #undef xtrsm -xsyrk(s) xsyrk(d) xsyrk(c) xsyrk(z) +xsyrk(s) xsyrk(d) xsyrk(c) xsyrk(z) // NOLINT(modernize-use-constraints) TODO(correaa) for C++20 #undef xsyrk - xherk(c) xherk(z) + xherk(c) xherk(z) // NOLINT(modernize-use-constraints) TODO(correaa) for C++20 } // end namespace core @@ -522,8 +617,9 @@ struct context { // stateless (and thread safe) template static auto nrm2(As... args) - ->decltype(core::nrm2(args...)) { - return core::nrm2(args...); } + -> decltype(auto) + //->decltype(core::nrm2(args...)) { + { return core::nrm2(args...); } template static auto trsm(As&&... args) // TODO(correaa) remove && @@ -545,7 +641,8 @@ template<> struct is_context : std::true_type {}; template<> struct is_context : std::true_type {}; -template::element_type*>{}, int> =0> +template::element_type*>, int> =0> // NOLINT(modernize-use-constraints) TODO(correaa) for C++20 auto default_context_of(TPtr const& /*unused*/) -> blas::context* { static blas::context dc; return &dc; diff --git a/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/cuda/tests/gemm.cpp b/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/cuda/tests/gemm.cpp index 0d77b46c25..a2bbf5ca8c 100644 --- a/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/cuda/tests/gemm.cpp +++ b/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/cuda/tests/gemm.cpp @@ -1,20 +1,17 @@ -#ifdef COMPILATION_INSTRUCTIONS -/usr/local/cuda-11.1/bin/nvcc -x cu -std=c++17 -use_fast_math -lpthread -D_REENTRANT -DBOOST_PP_VARIADICS -Xcudafe "--diag_suppress=implicit_return_from_non_void_function" --extended-lambda --expt-relaxed-constexpr $0 -o $0x `pkg-config --cflags --libs cudart-11.0 cublas-11.0 blas` -lboost_unit_test_framework -DBOOST_LOG_DYN_LINK -lboost_log -lboost_thread -lboost_system -lboost_log_setup -lpthread -lboost_timer&&$0x&&rm $0x; exit -#endif -// © Alfredo A. Correa 2020-2024 +// Copyright 2020-2024 Alfredo A. Correa +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt -#define BOOST_TEST_MODULE "C++ Unit Tests for Multi cuBLAS gemm" -#define BOOST_TEST_DYN_LINK -#include +#include // TODO(correaa) convert into lightweight test #include -#include "../../../cuda/cublas.hpp" -#include "../../../../array.hpp" +#include +#include -#include "../../../../adaptors/cuda.hpp" -#include "../../../../adaptors/blas.hpp" +#include +#include -#include +#include namespace multi = boost::multi; @@ -67,54 +64,54 @@ BOOST_AUTO_TEST_CASE(const multi_adaptors_blas_cuda_gemm_complex_3x2_3x2){ } //BOOST_AUTO_TEST_CASE(multi_adaptors_blas_cuda_gemm_complex_3x2_3x2_with_context){ -// using complex = std::complex; complex const I{0, 1}; -// namespace blas = multi::blas; -// multi::array const a = { -// {1. + 2.*I, 5. + 2.*I}, -// {9. - 1.*I, 9. + 1.*I}, -// {1. + 1.*I, 2. + 2.*I} -// }; -// multi::array const b = { -// { 11. - 2.*I, 5. + 2.*I}, -// { 7. - 3.*I, 2. + 1.*I}, -// { 8. - 1.*I, 1. + 1.*I} -// }; -// { -// { -// multi::blas::context ctx; -// multi::array c({2, 2}); -// blas::gemm(ctx, 1., blas::H(a), b, 0., c); // c=ab, c⸆=b⸆a⸆ -// BOOST_REQUIRE( c[1][0] == 125.-84.*I ); -// } -// } -// { -// multi::cublas::context ctx; -// multi::cuda::array const a_gpu = a; -// multi::cuda::array const b_gpu = b; -// { -// multi::cuda::array c_gpu({2, 2}); -// blas::gemm(ctx, 1., blas::H(a_gpu), b_gpu, 0., c_gpu); // c=ab, c⸆=b⸆a⸆ -// BOOST_REQUIRE( c_gpu[1][0] == 125.-84.*I ); -// } -// { -// auto c_gpu =+ blas::gemm(&ctx, blas::H(a_gpu), b_gpu); -// BOOST_REQUIRE( c_gpu[1][0] == 125.-84.*I ); -// } -// } -// { -// multi::cublas::context ctx; -// multi::cuda::managed::array const a_gpu = a; -// multi::cuda::managed::array const b_gpu = b; -// { -// multi::cuda::managed::array c_gpu({2, 2}); -// blas::gemm(ctx, 1., blas::H(a_gpu), b_gpu, 0., c_gpu); // c=ab, c⸆=b⸆a⸆ -// BOOST_REQUIRE( c_gpu[1][0] == 125.-84.*I ); -// } -// { -// auto c_gpu =+ blas::gemm(&ctx, blas::H(a_gpu), b_gpu); -// BOOST_REQUIRE( c_gpu[1][0] == 125.-84.*I ); -// } -// } +// using complex = std::complex; complex const I{0, 1}; +// namespace blas = multi::blas; +// multi::array const a = { +// {1. + 2.*I, 5. + 2.*I}, +// {9. - 1.*I, 9. + 1.*I}, +// {1. + 1.*I, 2. + 2.*I} +// }; +// multi::array const b = { +// { 11. - 2.*I, 5. + 2.*I}, +// { 7. - 3.*I, 2. + 1.*I}, +// { 8. - 1.*I, 1. + 1.*I} +// }; +// { +// { +// multi::blas::context ctx; +// multi::array c({2, 2}); +// blas::gemm(ctx, 1., blas::H(a), b, 0., c); // c=ab, c⸆=b⸆a⸆ +// BOOST_REQUIRE( c[1][0] == 125.-84.*I ); +// } +// } +// { +// multi::cublas::context ctx; +// multi::cuda::array const a_gpu = a; +// multi::cuda::array const b_gpu = b; +// { +// multi::cuda::array c_gpu({2, 2}); +// blas::gemm(ctx, 1., blas::H(a_gpu), b_gpu, 0., c_gpu); // c=ab, c⸆=b⸆a⸆ +// BOOST_REQUIRE( c_gpu[1][0] == 125.-84.*I ); +// } +// { +// auto c_gpu =+ blas::gemm(&ctx, blas::H(a_gpu), b_gpu); +// BOOST_REQUIRE( c_gpu[1][0] == 125.-84.*I ); +// } +// } +// { +// multi::cublas::context ctx; +// multi::cuda::managed::array const a_gpu = a; +// multi::cuda::managed::array const b_gpu = b; +// { +// multi::cuda::managed::array c_gpu({2, 2}); +// blas::gemm(ctx, 1., blas::H(a_gpu), b_gpu, 0., c_gpu); // c=ab, c⸆=b⸆a⸆ +// BOOST_REQUIRE( c_gpu[1][0] == 125.-84.*I ); +// } +// { +// auto c_gpu =+ blas::gemm(&ctx, blas::H(a_gpu), b_gpu); +// BOOST_REQUIRE( c_gpu[1][0] == 125.-84.*I ); +// } +// } //} #if 0 diff --git a/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/dot.hpp b/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/dot.hpp index 43a3aac718..15ef320091 100644 --- a/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/dot.hpp +++ b/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/dot.hpp @@ -5,9 +5,9 @@ #ifndef BOOST_MULTI_ADAPTORS_BLAS_DOT_HPP #define BOOST_MULTI_ADAPTORS_BLAS_DOT_HPP -#include "../blas/core.hpp" -#include "../blas/numeric.hpp" // for is_complex -#include "../blas/operations.hpp" // for blas::C +#include +#include // for is_complex +#include // for blas::C namespace boost::multi::blas { @@ -18,11 +18,11 @@ using core::dotc; template auto dot_n(Context&& ctxt, XIt x_first, Size count, YIt y_first, RPtr rp) { if constexpr(! is_complex{}) { - std::forward(ctxt)->dot (count, base(x_first) , stride(x_first), base(y_first), stride(y_first), rp); + std::forward(ctxt)->dot (count, x_first.base() , stride(x_first), y_first.base(), stride(y_first), rp); } else { - if constexpr(!is_conjugated{} && !is_conjugated{}) {std::forward(ctxt)->dotu(count, base(x_first) , stride(x_first), base(y_first), stride(y_first), rp);} - else if constexpr(!is_conjugated{} && is_conjugated{}) {std::forward(ctxt)->dotc(count, underlying(base(y_first)), stride(y_first), base(x_first), stride(x_first), rp);} - else if constexpr( is_conjugated{} && !is_conjugated{}) {std::forward(ctxt)->dotc(count, underlying(base(x_first)), stride(x_first), base(y_first), stride(y_first), rp);} + if constexpr(!is_conjugated{} && !is_conjugated{}) {std::forward(ctxt)->dotu(count, x_first.base() , stride(x_first), y_first.base(), stride(y_first), rp);} + else if constexpr(!is_conjugated{} && is_conjugated{}) {std::forward(ctxt)->dotc(count, underlying(y_first.base()), stride(y_first), x_first.base(), stride(x_first), rp);} + else if constexpr( is_conjugated{} && !is_conjugated{}) {std::forward(ctxt)->dotc(count, underlying(x_first.base()), stride(x_first), y_first.base(), stride(y_first), rp);} else if constexpr( is_conjugated{} && is_conjugated{}) {static_assert(!sizeof(XIt*), "not implemented in blas");} } @@ -31,7 +31,7 @@ auto dot_n(Context&& ctxt, XIt x_first, Size count, YIt y_first, RPtr rp) { } template -auto dot_n(XIt x_first, Size count, YIt y_first, RPtr rp) {//->decltype(dot_n(blas::context{}, x_first, count, y_first, rp)){ +auto dot_n(XIt x_first, Size count, YIt y_first, RPtr rp) { //->decltype(dot_n(blas::context{}, x_first, count, y_first, rp)){ if constexpr(is_conjugated{}) { auto ctxtp = blas::default_context_of(underlying(x_first.base())); return dot_n(ctxtp, x_first, count, y_first, rp); @@ -41,13 +41,15 @@ auto dot_n(XIt x_first, Size count, YIt y_first, RPtr rp) {//->decltype(dot_n(bl } } -template>::value, int> =0> +template>::value, int> =0> // NOLINT(modernize-use-constraints) TODO(correaa) for C++20 auto dot(Context ctxt, X1D const& x, Y1D const& y, R&& res) -> R&& { // NOLINT(readability-identifier-length) res = \sum_i x_i y_i assert( size(x) == size(y) ); // NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay) return blas::dot_n(ctxt, begin(x), size(x), begin(y), &res), std::forward(res); } -template>::value, int> =0> +template>::value, int> =0> // NOLINT(modernize-use-constraints) TODO(correaa) for C++20 auto dot(Context ctxt, X1D const& x, Y1D const& y, R&& res) -> R&& { // NOLINT(readability-identifier-length) res = \sum_i x_i y_i assert( size(x) == size(y) ); // NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay) return blas::dot_n(ctxt, begin(x), size(x), begin(y), res.base()), std::forward(res); @@ -107,17 +109,35 @@ struct dot_ref : private Ptr { #endif auto operator+() const -> decay_type {return decay();} - auto operator==(dot_ref const& other) const -> bool {return decay() == other.decay();} - auto operator!=(dot_ref const& other) const -> bool {return decay() != other.decay();} - - template - auto operator==(Other const& other) const - ->decltype(decay()==other) { - return decay()==other; } - template - auto operator!=(Other const& other) const - ->decltype(decay()!=other) { - return decay()!=other; } + // friend auto operator==(dot_ref const& self, dot_ref const& other) -> bool {return self.decay() == other.decay();} + // friend auto operator!=(dot_ref const& self, dot_ref const& other) -> bool {return self.decay() != other.decay();} + + friend auto operator==(dot_ref const& self, dot_ref const& other) -> bool { + return self.decay() == other.decay(); + } + friend auto operator!=(dot_ref const& self, dot_ref const& other) -> bool { + return self.decay() != other.decay(); + } + + template // , class = std::enable_if_t > > + friend auto operator==(dot_ref const& self, Other const& other) -> bool { + return self.decay() == other; + } + template // , class = std::enable_if_t > > + friend auto operator!=(dot_ref const& self, Other const& other) -> bool { + return self.decay() != other; + } + template > > // NOLINT(modernize-use-constraints) TODO(correaa) for C++20 + friend auto operator==(Other const& other, dot_ref const& self) -> bool { + return other == self.decay(); + } + template > > // NOLINT(modernize-use-constraints) TODO(correaa) for C++20 + friend auto operator!=(Other const& other, dot_ref const& self) -> bool { + return other != self.decay(); + } + }; template [[nodiscard]] diff --git a/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/filling.hpp b/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/filling.hpp index 4d686bc2aa..62d42c970a 100644 --- a/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/filling.hpp +++ b/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/filling.hpp @@ -21,7 +21,8 @@ inline auto flip(filling side) -> filling { switch(side) { case filling::lower: return filling::upper; case filling::upper: return filling::lower; - } __builtin_unreachable(); // LCOV_EXCL_LINE + } // __builtin_unreachable(); // LCOV_EXCL_LINE + return {}; } inline auto operator-(filling side) -> filling {return flip(side);} diff --git a/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/gemm.hpp b/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/gemm.hpp index 65f669704d..ef49433873 100644 --- a/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/gemm.hpp +++ b/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/gemm.hpp @@ -5,10 +5,21 @@ #ifndef BOOST_MULTI_ADAPTORS_BLAS_GEMM_HPP #define BOOST_MULTI_ADAPTORS_BLAS_GEMM_HPP -#include "../blas/core.hpp" -#include "../blas/gemv.hpp" -#include "../blas/numeric.hpp" -#include "../blas/operations.hpp" +#include +// #include +#include +// #include + +#include // for base, size, begin + +#include // for assert +#include // for nullptr_t +#include // for exception +#include // for iterator_traits +#include // for logic_error +#include // for to_string, operator""s +#include // for enable_if_t, integr... +#include // for forward, declval namespace boost::multi::blas { @@ -32,110 +43,106 @@ auto xbase(It const& it) #define CTXT std::forward(ctxt) template{} && !is_conjugated{}), int> = 0 -> + std::enable_if_t<(!is_conjugated{} && !is_conjugated{}), int> = 0> // NOLINT(modernize-use-constraints) TODO(correaa) for C++20 auto gemm_n(Context&& ctxt, typename It2DA::element alpha, It2DA a_first, Size a_count, It2DB b_first, typename It2DA::element beta, It2DC c_first) // NOLINT(readability-function-cognitive-complexity) : 125 { - assert( b_first->size() == c_first->size() ); // NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay) - assert( a_first.stride()==1 || a_first->stride()==1 ); // NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay) - assert( b_first.stride()==1 || b_first->stride()==1 ); // NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay) - assert( c_first.stride()==1 || c_first->stride()==1 ); // NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay) + assert( (*b_first).size() == (*c_first).size() ); // NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay) + assert( a_first.stride()==1 || (*a_first).stride()==1 ); // NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay) + assert( b_first.stride()==1 || (*b_first).stride()==1 ); // NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay) + assert( c_first.stride()==1 || (*c_first).stride()==1 ); // NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay) if(a_count == 0) { return c_first; } - if (a_first->stride()==1 && b_first->stride()==1 && c_first->stride()==1) { - if ( a_count==1 && b_first->size()==1 ) {CTXT->gemm('N', 'N', b_first->size(), a_count, a_first->size(), &alpha, base(b_first), b_first->size() , base(a_first), a_first->size() , &beta, base(c_first), c_first->size() );} - else if( a_count==1 ) {CTXT->gemm('N', 'N', b_first->size(), a_count, a_first->size(), &alpha, base(b_first), b_first. stride(), base(a_first), a_first->size() , &beta, base(c_first), c_first->size() );} - else {CTXT->gemm('N', 'N', b_first->size(), a_count, a_first->size(), &alpha, base(b_first), b_first. stride(), base(a_first), a_first. stride(), &beta, base(c_first), c_first. stride());} - }else if(a_first->stride()==1 && b_first->stride()==1 && c_first. stride()==1) { - if (a_count==1) {CTXT->gemm('T', 'T', a_count, b_first->size(), a_first->size(), &alpha, base(a_first), a_first. stride(), base(b_first), b_first->size() , &beta, base(c_first), a_first->size() );} - else {CTXT->gemm('T', 'T', a_count, b_first->size(), a_first->size(), &alpha, base(a_first), a_first. stride(), base(b_first), b_first. stride(), &beta, base(c_first), c_first->stride());} - }else if(a_first. stride()==1 && b_first->stride()==1 && c_first->stride()==1) { - if (a_count==1) {CTXT->gemm('N', 'T', c_first->size(), a_count, a_first->size(), &alpha, base(b_first), b_first. stride(), base(a_first), a_first->stride(), &beta, base(c_first), a_count );} - else {CTXT->gemm('N', 'T', c_first->size(), a_count, a_first->size(), &alpha, base(b_first), b_first. stride(), base(a_first), a_first->stride(), &beta, base(c_first), c_first.stride());} - }else if(a_first. stride()==1 && b_first->stride()==1 && c_first. stride()==1) { - if (a_count==1) {CTXT->gemm('N', 'T', a_count, b_first->size(), a_first->size(), &alpha, base(a_first), a_first->stride(), base(b_first), a_first->size() , &beta, base(c_first), b_first->size() );} - else {CTXT->gemm('N', 'T', a_count, b_first->size(), a_first->size(), &alpha, base(a_first), a_first->stride(), base(b_first), b_first. stride(), &beta, base(c_first), c_first->stride());} - }else if(a_first->stride()==1 && b_first.stride()==1 && c_first. stride()==1) { - if (a_count==1 && b_first->size()==1 ) {CTXT->gemm('N', 'N', c_first->size(), a_count, a_first->size(), &alpha, base(b_first), b_first->size() , base(a_first), a_first->size() , &beta, base(c_first), c_first->stride());} - else if(a_count==1) {CTXT->gemm('N', 'T', c_first->size(), a_count, a_first->size(), &alpha, base(b_first), b_first->stride(), base(a_first), a_first->size() , &beta, base(c_first), c_first->stride());} - else if(a_first->size() == 1 && b_first->size() == 1) - {CTXT->gemm('N', 'N', c_first->size(), a_count, a_first->size(), &alpha, base(b_first), b_first->stride(), base(a_first), a_first. stride(), &beta, base(c_first), c_first->stride());} - else {CTXT->gemm('N', 'T', c_first->size(), a_count, a_first->size(), &alpha, base(b_first), b_first->stride(), base(a_first), a_first. stride(), &beta, base(c_first), c_first->stride());} - }else if(a_first->stride()==1 && b_first. stride()==1 && c_first->stride()==1) { - if (a_count==1) {CTXT->gemm('T', 'N', a_count, c_first->size(), a_first->size(), &alpha, base(b_first), b_first->stride(), base(a_first), a_first->size() , &beta, base(c_first), c_first. stride());} - else {CTXT->gemm('T', 'N', c_first->size(), a_count, a_first->size(), &alpha, base(b_first), b_first->stride(), base(a_first), a_first. stride(), &beta, base(c_first), c_first. stride());} + if ((*a_first).stride()==1 && (*b_first).stride()==1 && (*c_first).stride()==1) { + if ( a_count==1 && (*b_first).size()==1 ) {CTXT->gemm('N', 'N', (*b_first).size(), a_count, (*a_first).size(), &alpha, b_first.base(), (*b_first).size(), a_first.base(), (*a_first).size() , &beta, c_first.base(), (*c_first).size() );} + else if( a_count==1 ) {CTXT->gemm('N', 'N', (*b_first).size(), a_count, (*a_first).size(), &alpha, b_first.base(), b_first. stride(), a_first.base(), (*a_first).size() , &beta, c_first.base(), (*c_first).size() );} + else {CTXT->gemm('N', 'N', (*b_first).size(), a_count, (*a_first).size(), &alpha, b_first.base(), b_first. stride(), a_first.base(), a_first. stride(), &beta, c_first.base(), c_first. stride());} + }else if((*a_first).stride()==1 && (*b_first).stride()==1 && c_first. stride()==1) { + if (a_count==1) {CTXT->gemm('T', 'T', a_count, (*b_first).size(), (*a_first).size(), &alpha, a_first.base(), a_first. stride(), b_first.base(), (*b_first).size() , &beta, c_first.base(), (*a_first).size() );} + else {CTXT->gemm('T', 'T', a_count, (*b_first).size(), (*a_first).size(), &alpha, a_first.base(), a_first. stride(), b_first.base(), b_first. stride(), &beta, c_first.base(), (*c_first).stride());} + }else if(a_first. stride()==1 && (*b_first).stride()==1 && (*c_first).stride()==1) { + if (a_count==1) {CTXT->gemm('N', 'T', (*c_first).size(), a_count, (*a_first).size(), &alpha, b_first.base(), b_first. stride(), a_first.base(), (*a_first).stride(), &beta, c_first.base(), a_count );} + else {CTXT->gemm('N', 'T', (*c_first).size(), a_count, (*a_first).size(), &alpha, b_first.base(), b_first. stride(), a_first.base(), (*a_first).stride(), &beta, c_first.base(), c_first.stride());} + }else if(a_first. stride()==1 && (*b_first).stride()==1 && c_first. stride()==1) { + if (a_count==1) {CTXT->gemm('N', 'T', a_count, (*b_first).size(), (*a_first).size(), &alpha, a_first.base(), (*a_first).stride(), b_first.base(), (*a_first).size() , &beta, c_first.base(), (*b_first).size() );} + else {CTXT->gemm('N', 'T', a_count, (*b_first).size(), (*a_first).size(), &alpha, a_first.base(), (*a_first).stride(), b_first.base(), b_first. stride(), &beta, c_first.base(), (*c_first).stride());} + }else if((*a_first).stride()==1 && b_first.stride()==1 && c_first. stride()==1) { + if (a_count==1 && (*b_first).size()==1) {CTXT->gemm('N', 'N', (*c_first).size(), a_count, (*a_first).size(), &alpha, b_first.base(), (*b_first).size() , a_first.base(), (*a_first).size() , &beta, c_first.base(), (*c_first).stride());} + else if(a_count==1) {CTXT->gemm('N', 'T', (*c_first).size(), a_count, (*a_first).size(), &alpha, b_first.base(), (*b_first).stride(), a_first.base(), (*a_first).size() , &beta, c_first.base(), (*c_first).stride());} + else if((*a_first).size() == 1 && (*b_first).size() == 1) + {CTXT->gemm('N', 'N', (*c_first).size(), a_count, (*a_first).size(), &alpha, b_first.base(), (*b_first).stride(), a_first.base(), a_first. stride(), &beta, c_first.base(), (*c_first).stride());} + else {CTXT->gemm('N', 'T', (*c_first).size(), a_count, (*a_first).size(), &alpha, b_first.base(), (*b_first).stride(), a_first.base(), a_first. stride(), &beta, c_first.base(), (*c_first).stride());} + }else if((*a_first).stride()==1 && b_first. stride()==1 && (*c_first).stride()==1) { + if (a_count==1) {CTXT->gemm('T', 'N', a_count, (*c_first).size(), (*a_first).size(), &alpha, b_first.base(), (*b_first).stride(), a_first.base(), (*a_first).size(), &beta, c_first.base(), c_first. stride());} + else {CTXT->gemm('T', 'N', (*c_first).size(), a_count, (*a_first).size(), &alpha, b_first.base(), (*b_first).stride(), a_first.base(), a_first. stride(), &beta, c_first.base(), c_first. stride());} }else if(a_first. stride()==1 && b_first.stride( )==1 && c_first. stride()==1) { - if (b_first->size()==1) {CTXT->gemm('N', 'N', a_count, b_first->size(), a_first->size(), &alpha, base(a_first), a_first->stride(), base(b_first), b_first->stride(), &beta, base(c_first), a_count );} - else {CTXT->gemm('N', 'N', a_count, b_first->size(), a_first->size(), &alpha, base(a_first), a_first->stride(), base(b_first), b_first->stride(), &beta, base(c_first), c_first->stride());} - }else if(a_first. stride()==1 && b_first.stride( )==1 && c_first->stride()==1) { - {CTXT->gemm('T', 'T', b_first->size(), a_count, a_first->size(), &alpha, base(b_first), b_first->stride(), base(a_first), a_first->stride(), &beta, base(c_first), c_first. stride());} + if ((*b_first).size()==1) {CTXT->gemm('N', 'N', a_count, (*b_first).size(), (*a_first).size(), &alpha, a_first.base(), (*a_first).stride(), b_first.base(), (*b_first).stride(), &beta, c_first.base(), a_count );} + else {CTXT->gemm('N', 'N', a_count, (*b_first).size(), (*a_first).size(), &alpha, a_first.base(), (*a_first).stride(), b_first.base(), (*b_first).stride(), &beta, c_first.base(), (*c_first).stride());} + }else if(a_first. stride()==1 && b_first.stride( )==1 && (*c_first).stride()==1) { + {CTXT->gemm('T', 'T', (*b_first).size(), a_count, (*a_first).size(), &alpha, b_first.base(), (*b_first).stride(), a_first.base(), (*a_first).stride(), &beta, c_first.base(), c_first. stride());} } else {assert(0);} // NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay) return c_first + a_count; } template{} && is_conjugated{}), int> =0 -> + std::enable_if_t<(!is_conjugated{} && is_conjugated{}), int> =0> // NOLINT(modernize-use-constraints) TODO(correaa) for C++20 auto gemm_n(Context&& ctxt, typename It2DA::element alpha, It2DA a_first, Size a_count, It2DB b_first, typename It2DA::element beta, It2DC c_first) // NOLINT(readability-function-cognitive-complexity) : 125 { - assert( b_first->size() == c_first->size() ); // NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay) - assert( a_first.stride()==1 || a_first->stride()==1 ); // NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay) - assert( b_first.stride()==1 || b_first->stride()==1 ); // NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay) - assert( c_first.stride()==1 || c_first->stride()==1 ); // NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay) + assert( (*b_first).size() == (*c_first).size() ); // NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay) + assert( a_first.stride()==1 || (*a_first).stride()==1 ); // NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay) + assert( b_first.stride()==1 || (*b_first).stride()==1 ); // NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay) + assert( c_first.stride()==1 || (*c_first).stride()==1 ); // NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay) if(a_count == 0) { return c_first; } - if (a_first->stride()==1 && b_first->stride()==1 && c_first->stride()==1){ - {CTXT->gemm('C', 'N', c_first->size(), a_count, a_first->size(), &alpha, underlying(base(b_first)), b_first->stride(), base(a_first), a_first->size() , &beta, base(c_first), c_first.stride());} - }else if(a_first->stride()==1 && b_first. stride()==1 && c_first->stride()==1){ - if (a_count==1) {CTXT->gemm('C', 'N', a_count, c_first->size(), a_first->size(), &alpha, underlying(base(b_first)), b_first->stride(), base(a_first), a_first->size() , &beta, base(c_first), c_first.stride());} - else {CTXT->gemm('C', 'N', c_first->size(), a_count, a_first->size(), &alpha, underlying(base(b_first)), b_first->stride(), base(a_first), a_first.stride(), &beta, base(c_first), c_first.stride());} - }else if(a_first->stride()==1 && b_first. stride()==1 && c_first. stride()==1){ - {CTXT->gemm('C', 'N', c_first->size(), a_count, a_first->size(), &alpha, underlying(base(b_first)), b_first->stride(), base(a_first), a_first. stride(), &beta, base(c_first), c_first->stride());} + if ((*a_first).stride()==1 && (*b_first).stride()==1 && (*c_first).stride()==1) { + {CTXT->gemm('C', 'N', (*c_first).size(), a_count, (*a_first).size(), &alpha, underlying(b_first.base()), (*b_first).stride(), a_first.base(), (*a_first).size() , &beta, c_first.base(), c_first.stride());} + }else if((*a_first).stride()==1 && b_first. stride()==1 && (*c_first).stride()==1){ + if (a_count==1) {CTXT->gemm('C', 'N', a_count, (*c_first).size(), (*a_first).size(), &alpha, underlying(b_first.base()), (*b_first).stride(), a_first.base(), (*a_first).size() , &beta, c_first.base(), c_first.stride());} + else {CTXT->gemm('C', 'N', (*c_first).size(), a_count, (*a_first).size(), &alpha, underlying(b_first.base()), (*b_first).stride(), a_first.base(), a_first.stride(), &beta, c_first.base(), c_first.stride());} + }else if((*a_first).stride()==1 && b_first. stride()==1 && c_first. stride()==1){ + {CTXT->gemm('C', 'N', (*c_first).size(), a_count, (*a_first).size(), &alpha, underlying(b_first.base()), (*b_first).stride(), a_first.base(), a_first. stride(), &beta, c_first.base(), (*c_first).stride());} }else if(a_first. stride()==1 && b_first. stride()==1 && c_first. stride()==1){ - {CTXT->gemm('C', 'T', c_first->size(), a_count, a_first->size(), &alpha, underlying(base(b_first)), b_first->stride(), base(a_first), a_first->stride(), &beta, base(c_first), c_first->stride());} - }else if(a_first. stride()==1 && b_first. stride()==1 && c_first->stride()==1){ - {CTXT->gemm('C', 'T', a_count, c_first->size(), a_first->size(), &alpha, underlying(base(b_first)), b_first->stride(), base(a_first), a_first->stride(), &beta, base(c_first), c_first. stride());} + {CTXT->gemm('C', 'T', (*c_first).size(), a_count, (*a_first).size(), &alpha, underlying(b_first.base()), (*b_first).stride(), a_first.base(), (*a_first).stride(), &beta, c_first.base(), (*c_first).stride());} + }else if(a_first. stride()==1 && b_first. stride()==1 && (*c_first).stride()==1){ + {CTXT->gemm('C', 'T', a_count, (*c_first).size(), (*a_first).size(), &alpha, underlying(b_first.base()), (*b_first).stride(), a_first.base(), (*a_first).stride(), &beta, c_first.base(), c_first. stride());} }else{assert(0);} // NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay) return c_first + a_count; } template{} && !is_conjugated{}), int> =0 -> + std::enable_if_t<(is_conjugated{} && !is_conjugated{}), int> =0> // NOLINT(modernize-use-constraints) TODO(correaa) for C++20 auto gemm_n(Context&& ctxt, typename It2DA::element alpha, It2DA a_first, Size a_count, It2DB b_first, typename It2DA::element beta, It2DC c_first) // NOLINT(readability-function-cognitive-complexity) : 125 { - assert( b_first->size() == c_first->size() ); // NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay) - assert( a_first.stride()==1 || a_first->stride()==1 ); // NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay) - assert( b_first.stride()==1 || b_first->stride()==1 ); // NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay) - assert( c_first.stride()==1 || c_first->stride()==1 ); // NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay) + assert( (*b_first).size() == (*c_first).size() ); // NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay) + assert( a_first.stride()==1 || (*a_first).stride()==1 ); // NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay) + assert( b_first.stride()==1 || (*b_first).stride()==1 ); // NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay) + assert( c_first.stride()==1 || (*c_first).stride()==1 ); // NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay) if(a_count == 0) { return c_first; } - if (a_first. stride()==1 && b_first->stride()==1 && c_first->stride()==1){ - if (a_count==1) {CTXT->gemm('N', 'C', c_first->size(), a_count, a_first->size(), &alpha, base(b_first), b_first. stride(), underlying(base(a_first)), a_first->stride(), &beta, base(c_first), a_first->size() );} - else {CTXT->gemm('N', 'C', c_first->size(), a_count, a_first->size(), &alpha, base(b_first), b_first. stride(), underlying(base(a_first)), a_first->stride(), &beta, base(c_first), c_first.stride());} + if (a_first. stride()==1 && (*b_first).stride()==1 && (*c_first).stride()==1){ + if (a_count==1) {CTXT->gemm('N', 'C', (*c_first).size(), a_count, (*a_first).size(), &alpha, b_first.base(), b_first. stride(), underlying(a_first.base()), (*a_first).stride(), &beta, base(c_first), (*a_first).size()); } + else {CTXT->gemm('N', 'C', (*c_first).size(), a_count, (*a_first).size(), &alpha, b_first.base(), b_first. stride(), underlying(a_first.base()), (*a_first).stride(), &beta, base(c_first), c_first.stride() ); } } else {throw std::logic_error{"not BLAS-implemented"};} return c_first + a_count; } template{} && is_conjugated{}), int> =0 -> + std::enable_if_t<(is_conjugated{} && is_conjugated{}), int> =0> // NOLINT(modernize-use-constraints) TODO(correaa) for C++20 auto gemm_n(Context&& ctxt, typename It2DA::element alpha, It2DA a_first, Size a_count, It2DB b_first, typename It2DA::element beta, It2DC c_first) // NOLINT(readability-function-cognitive-complexity) : 125 { - assert( b_first->size() == c_first->size() ); // NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay) - assert( a_first.stride()==1 || a_first->stride()==1 ); // NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay) - assert( b_first.stride()==1 || b_first->stride()==1 ); // NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay) - assert( c_first.stride()==1 || c_first->stride()==1 ); // NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay) + assert( (*b_first).size() == (*c_first).size() ); // NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay) + assert( a_first.stride()==1 || (*a_first).stride()==1 ); // NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay) + assert( b_first.stride()==1 || (*b_first).stride()==1 ); // NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay) + assert( c_first.stride()==1 || (*c_first).stride()==1 ); // NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay) if(a_count == 0) { return c_first; } - if (a_first. stride()==1 && b_first. stride()==1 && c_first->stride()==1){ - {CTXT->gemm('C', 'C', a_count, c_first->size(), a_first->size(), &alpha, underlying(base(b_first)), b_first->stride(), underlying(base(a_first)), a_first->stride(), &beta, base(c_first), c_first. stride());} + if (a_first. stride()==1 && b_first. stride()==1 && (*c_first).stride()==1){ + {CTXT->gemm('C', 'C', a_count, (*c_first).size(), (*a_first).size(), &alpha, underlying(base(b_first)), (*b_first).stride(), underlying(base(a_first)), (*a_first).stride(), &beta, base(c_first), c_first. stride());} } else {throw std::logic_error{"not BLAS-implemented"};} return c_first + a_count; } @@ -167,8 +174,7 @@ auto gemm(typename A::element alpha, A const& a, B const& b, typename A::element } } -template -class gemm_range; +// template class gemm_range; template class gemm_reference { // TODO(correaa) implement this in terms of gemv_range? @@ -201,18 +207,16 @@ class gemm_iterator { using difference_type = typename std::iterator_traits::difference_type; using value_type = typename std::iterator_traits::value_type; using pointer = std::nullptr_t; - using reference = gemm_referenceextensions())>; + using reference = gemm_reference; using iterator_category = std::random_access_iterator_tag; - static_assert( std::is_base_of::iterator_category>{} ); - auto operator+=(difference_type n) -> gemm_iterator& {a_it_ += n; return *this;} auto operator-=(difference_type n) -> gemm_iterator& {a_it_ -= n; return *this;} - auto operator++() -> gemm_iterator& {return operator+=(1);} // required by random access concept requires even if not used explicitly - auto operator--() -> gemm_iterator& {return operator-=(1);} + auto operator++() -> gemm_iterator& { return operator+=(1); } // required by random access concept requires even if not used explicitly + auto operator--() -> gemm_iterator& { return operator-=(1); } - auto operator+(difference_type n) const {gemm_iterator ret{*this}; ret+=n; return ret;} + friend auto operator+(gemm_iterator ret, difference_type n) { return ret += n; } friend auto operator-(gemm_iterator const& a, gemm_iterator const& b) -> difference_type { // NOLINT(readability-identifier-length) BLAS naming assert(a.b_begin_ == b.b_begin_); // NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay) @@ -226,10 +230,9 @@ class gemm_iterator { ->decltype(blas::gemm_n(std::declval(), std::declval() , std::declval(), count, std::declval(), 0.0, d_first)) try { // std::complex NOLINT(fuchsia-default-arguments-calls) return blas::gemm_n(first.ctxtp_ , static_cast(first.s_), first.a_it_ , count, first.b_begin_ , 0.0, d_first); // NOLINT(fuchsia-default-arguments-calls) } catch(std::exception const& e) { - using namespace std::string_literals; throw std::logic_error( - "in "s + __PRETTY_FUNCTION__ +"\nCouldn't decay product of arrays of size "+ std::to_string(count) +"x"+ std::to_string(first.a_it_->size()) + " and " + // NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay) - std::to_string(first.a_it_->size())+ "x" +std::to_string(first.b_begin_->size()) + " into " + std::to_string(count) +"x" + std::to_string(first.b_begin_->size()) + + "in `copy_n`\nCouldn't decay product of arrays of size "+ std::to_string(count) +"x"+ std::to_string((*first.a_it_).size()) + " and " + // NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay) + std::to_string((*first.a_it_).size())+ "x" +std::to_string((*first.b_begin_).size()) + " into " + std::to_string(count) +"x" + std::to_string((*first.b_begin_).size()) + "\nbecause\n" + e.what() ); } @@ -250,7 +253,7 @@ class gemm_iterator { return uninitialized_copy_n(first, last - first, d_first); } - auto operator*() const {return reference{b_begin_->extensions()};} + auto operator*() const {return reference{(*b_begin_).extensions()};} }; template @@ -285,7 +288,7 @@ class gemm_range { auto size() const -> size_type {return a_end_ - a_begin_;} - auto extensions() const -> typename decay_type::extensions_type {return size()*b_begin_->extensions();} + auto extensions() const -> typename decay_type::extensions_type {return size()*(*b_begin_).extensions();} friend auto extensions(gemm_range const& self) {return self.extensions();} auto operator+() const -> decay_type {return *this;} // TODO(correaa) : investigate why return decay_type{*this} doesn't work @@ -299,11 +302,15 @@ class gemm_range { } }; -template())>{}> > +template())>{}> > // NOLINT(modernize-use-constraints) TODO(correaa) for C++20 auto gemm(ContextPtr ctxtp, Scalar s, A2D const& a, B2D const& b) // NOLINT(readability-identifier-length) BLAS naming ->gemm_range { - return {ctxtp, s, begin(a), end(a), begin(b)}; + return + gemm_range + (ctxtp, s, a.begin(), a.end(), b.begin()) + ; } #if defined __NVCC__ @@ -339,7 +346,8 @@ auto gemm(Scalar s, A2D const& a, B2D const& b) { // NOLINT(readability-identif #endif namespace operators { - template =0> + template =0> // NOLINT(modernize-use-constraints) TODO(correaa) for C++20 auto operator*(A2D const& A, B2D const& B) // NOLINT(readability-identifier-length) conventional BLAS names ->decltype(blas::gemm(1.0, A, B)) { return blas::gemm(1.0, A, B); } diff --git a/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/gemv.hpp b/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/gemv.hpp index 09c815cf82..3b56ed44de 100644 --- a/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/gemv.hpp +++ b/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/gemv.hpp @@ -5,10 +5,10 @@ #ifndef BOOST_MULTI_ADAPTORS_BLAS_GEMV_HPP #define BOOST_MULTI_ADAPTORS_BLAS_GEMV_HPP -#include "../blas/core.hpp" -#include "../blas/dot.hpp" +#include +#include -#include "./../../detail/../utility.hpp" +#include namespace boost::multi::blas { @@ -20,16 +20,17 @@ struct gemv_stride_error : std::logic_error { template auto gemv_n(Context ctxt, typename MIt::element a, MIt m_first, Size count, XIt x_first, typename MIt::element b, YIt y_first) { // NOLINT(readability-identifier-length) BLAS naming - assert(m_first->stride()==1 || m_first.stride()==1); // blas doesn't implement this case + assert((*m_first).stride()==1 || m_first.stride()==1); // blas doesn't implement this case assert( x_first.base() != y_first.base() ); + assert( y_first.stride() != 0 ); // BLAS generally doesn't support stride zero if constexpr(! is_conjugated::value) { - if (m_first .stride()==1) {ctxt->gemv('N', count, m_first->size(), &a, m_first.base() , m_first->stride(), x_first.base(), x_first.stride(), &b, y_first.base(), y_first.stride());} - else if(m_first->stride()==1) {ctxt->gemv('T', m_first->size(), count, &a, m_first.base() , m_first. stride(), x_first.base(), x_first.stride(), &b, y_first.base(), y_first.stride());} - else {throw gemv_stride_error{"not BLAS-implemented"};} // LCOV_EXCL_LINE + if (m_first .stride()==1) {ctxt->gemv('N', count, (*m_first).size(), &a, m_first.base() , (*m_first).stride(), x_first.base(), x_first.stride(), &b, y_first.base(), y_first.stride());} + else if((*m_first).stride()==1) {ctxt->gemv('T', (*m_first).size(), count, &a, m_first.base() , m_first .stride(), x_first.base(), x_first.stride(), &b, y_first.base(), y_first.stride());} + else {assert(0); /*throw gemv_stride_error{"not BLAS-implemented"};*/} // LCOV_EXCL_LINE } else { - if (m_first->stride()==1) {ctxt->gemv('C', m_first->size(), count, &a, underlying(m_first.base()), m_first. stride(), x_first.base(), x_first.stride(), &b, y_first.base(), y_first.stride());} - else {throw gemv_stride_error{"not BLAS-implemented"};} // LCOV_EXCL_LINE + if ((*m_first).stride()==1) {ctxt->gemv('C', (*m_first).size(), count, &a, underlying(m_first.base()), m_first. stride(), x_first.base(), x_first.stride(), &b, y_first.base(), y_first.stride());} + else {assert(0); /*throw gemv_stride_error{"not BLAS-implemented"};*/} // LCOV_EXCL_LINE } struct { @@ -190,7 +191,8 @@ namespace operators { ->decltype(+blas::gemv(1.0, m, v)) { return +blas::gemv(1.0, m, v); } - template =0> + template =0> // NOLINT(modernize-use-constraints) TODO(correaa) for C++20 auto operator*(typename Matrix::element_type aa, Matrix const& A) { // NOLINT(readability-identifier-length) BLAS naming return scaled_matrix{aa, A}; } diff --git a/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/herk.hpp b/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/herk.hpp index dee621b679..2548dc1e35 100644 --- a/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/herk.hpp +++ b/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/herk.hpp @@ -4,31 +4,112 @@ #define BOOST_MULTI_ADAPTORS_BLAS_HERK_HPP #pragma once -#include "../blas/copy.hpp" -#include "../blas/core.hpp" -#include "../blas/filling.hpp" -#include "../blas/operations.hpp" -#include "../blas/side.hpp" -#include "../blas/syrk.hpp" // fallback to real case +#include +#include +#include +#include +#include +#include // fallback to real case + +// IWYU pragma: no_include "boost/multi/adaptors/blas/traits.hpp" // for blas namespace boost::multi::blas { -template{}, int> =0> +template{}, int> =0> // NOLINT(modernize-use-constraints) TODO(correaa) for C++20 auto base_aux(A&& array) -->decltype(base(std::forward(array))) { - return base(std::forward(array)); } +->decltype((std::forward(array)).base()) { + return (std::forward(array)).base(); } -template{}, int> =0> +template{}, int> =0> // NOLINT(modernize-use-constraints) TODO(correaa) for C++20 auto base_aux(A&& array) -->decltype(underlying(base(std::forward(array)))) { - return underlying(base(std::forward(array))); } +->decltype(underlying((std::forward(array)).base())) { + return underlying((std::forward(array)).base()); } using core::herk; -template{}, int> =0> +template +auto herk_nm(filling c_side, AA alpha, A2DCursor a_home, Size n, Size m, BB beta, C2DCursor c_home) { // NOLINT(readability-function-cognitive-complexity,readability-identifier-length) BLAS naming + auto a_base = base_aux(a_home); // NOLINT(llvm-qualified-auto,readability-qualified-auto) TODO(correaa) + auto c_base = base_aux(c_home); // NOLINT(llvm-qualified-auto,readability-qualified-auto) TODO(correaa) + + if constexpr(is_conjugated::value) { + assert(0); // TODO(correaa) implement + } else { + if (a_home.stride()!=1 && c_home.stride()!=1) { + herk(c_side==filling::upper?'L':'U', 'C', n, m, &alpha, a_base, a_home.template stride<0>(), &beta, c_base, c_home.template stride<0>() ); + } else if(a_home.stride()!=1 && c_home.stride()==1) { + if(n==1) { herk(c_side==filling::upper?'L':'U', 'N', n, m, &alpha, a_base, a_home.template stride<1>(), &beta, c_base, c_home.template stride<1>() ); } + else { assert(0);} // NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay) + } + else if(a_home.stride()==1 && c_home.stride()!=1) { assert(0);} // NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay) + else if(a_home.stride()==1 && c_home.stride()==1) { herk(c_side==filling::upper?'U':'L', 'N', n, m, &alpha, a_base, a_home.template stride<1>(), &beta, c_base, c_home.template stride<1>() );} + } + + return c_home; +} + +template +class herk_range { + // ContextPtr ctxtp_; + multi::blas::filling cs_; + Scalar scale_; + A2DCursor a_home_; + Size a_rows_; + Size a_cols_; + + public: + herk_range(herk_range const&) = delete; + herk_range(herk_range&&) = delete; + auto operator=(herk_range const&) -> herk_range& = delete; + auto operator=(herk_range&&) -> herk_range& = delete; + ~herk_range() = default; + + herk_range(multi::blas::filling cs, Scalar scale, A2DCursor a_home, Size a_rows, Size a_cols) : cs_{cs}, scale_{scale}, a_home_{a_home}, a_rows_{a_rows}, a_cols_{a_cols} {} // NOLINT(bugprone-easily-swappable-parameters) TODO(correaa) + +// herk_range(ContextPtr ctxtp, Scalar s, A2D&& a) // NOLINT(bugprone-easily-swappable-parameters,readability-identifier-length) BLAS naming +// : ctxtp_{ctxtp} +// , s_{s}, a_{std::forward<2D>(a_first)}, a_end_{std::move(a_last)} +// {} + + struct iterator { + herk_range const* self_; + Size index_; + }; + +// // using iterator = herk_iterator; +// using decay_type = DecayType; +// using size_type = typename decay_type::size_type; + + auto begin() const { return iterator{this, 0}; } + auto end() const { return iterator{this, a_rows_}; } + + auto size() const { return a_rows_;} + auto extensions() const { return multi::extensions_t<2>{a_rows_, a_rows_}; } + + // template + // friend auto copy(iterator const& first, iterator const& last, ItOut d_first) { + // auto const& a = multi::ref(first.self_, last); + // blas::herk_nm(first.self_->cs_, a.home(), a.size(), (~a).size(), 0.0, d_first); // NOLINT(fuchsia-default-arguments-calls) + // } + +// // auto operator+() const -> decay_type {return *this;} // TODO(correaa) : investigate why return decay_type{*this} doesn't work +// // template +// // friend auto operator+=(Arr&& a, gemm_range const& self) -> Arr&& { // NOLINT(readability-identifier-length) BLAS naming +// // blas::gemm_n(self.ctxtp_, self.s_, self.a_begin_, self.a_end_ - self.a_begin_, self.b_begin_, 1., a.begin()); +// // return std::forward(a); +// // } +// // friend auto operator*(Scalar factor, gemm_range const& self) { +// // return gemm_range{self.ctxtp_, factor*self.s_, self.a_begin_, self.a_end_, self.b_begin_}; +// // } +}; + +template{}, int> =0> // NOLINT(modernize-use-constraints) TODO(correaa) for C++20 auto herk(filling c_side, AA alpha, A2D const& a, BB beta, C2D&& c) -> C2D&& { // NOLINT(readability-function-cognitive-complexity,readability-identifier-length) 74, BLAS naming assert( a.size() == c.size() ); // NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay) - assert( c.size() == rotated(c).size() ); // NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay) + assert( c.size() == c.rotated().size() ); // NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay) if(c.is_empty()) {return std::forward(c);} if constexpr(is_conjugated{}) { herk(flip(c_side), alpha, a, beta, hermitized(c)); @@ -40,48 +121,49 @@ auto herk(filling c_side, AA alpha, A2D const& a, BB beta, C2D&& c) -> C2D&& { if constexpr(is_conjugated{}) { // auto& ctxt = *blas::default_context_of(underlying(a.base())); // if you get an error here might be due to lack of inclusion of a header file with the backend appropriate for your type of iterator - if (stride(a)==1 && stride(c)!=1) {herk(c_side==filling::upper?'L':'U', 'N', size(c), size(rotated(a)), &alpha, base_a, stride(rotated(a)), &beta, base_c, stride(c));} - else if(stride(a)==1 && stride(c)==1) { - if(size(a)==1) {herk(c_side==filling::upper?'L':'U', 'N', size(c), size(rotated(a)), &alpha, base_a, stride(rotated(a)), &beta, base_c, stride(c));} + if (stride(a)==1 && c.stride()!=1) {herk(c_side==filling::upper?'L':'U', 'N', c.size(), a.rotated().size(), &alpha, base_a, a.rotated().stride(), &beta, base_c, c.stride());} + else if(stride(a)==1 && c.stride()==1) { + if(size(a)==1) {herk(c_side==filling::upper?'L':'U', 'N', c.size(), a.rotated().size(), &alpha, base_a, a.rotated().stride(), &beta, base_c, c.stride());} else {assert(0);} // NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay) } - else if(stride(a)!=1 && stride(c)==1) {herk(c_side==filling::upper?'U':'L', 'C', size(c), size(rotated(a)), &alpha, base_a, stride( a ), &beta, base_c, stride(rotated(c)));} - else if(stride(a)!=1 && stride(c)!=1) {herk(c_side==filling::upper?'L':'U', 'C', size(c), size(rotated(a)), &alpha, base_a, stride( a ), &beta, base_c, stride( c ));} - else {assert(0);} // NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay) + else if(stride(a)!=1 && c.stride()==1) { herk(c_side==filling::upper?'U':'L', 'C', c.size(), a.rotated().size(), &alpha, base_a, stride( a ), &beta, base_c, c.rotated().stride());} + else if(stride(a)!=1 && c.stride()!=1) { herk(c_side==filling::upper?'L':'U', 'C', c.size(), a.rotated().size(), &alpha, base_a, stride( a ), &beta, base_c, c .stride());} + else { assert(0);} // NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay) } else { // auto& ctxt = *blas::default_context_of( a.base() ); - if (stride(a)!=1 && stride(c)!=1) {herk(c_side==filling::upper?'L':'U', 'C', size(c), size(rotated(a)), &alpha, base_a, stride( a ), &beta, base_c, stride(c));} - else if(stride(a)!=1 && stride(c)==1) { - if(size(a)==1) {herk(c_side==filling::upper?'L':'U', 'N', size(c), size(rotated(a)), &alpha, base_a, stride(rotated(a)), &beta, base_c, stride(rotated(c)));} - else {assert(0);} // NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay) + if (stride(a)!=1 && c.stride()!=1) { herk(c_side==filling::upper?'L':'U', 'C', c.size(), a.rotated().size(), &alpha, base_a, stride( a ), &beta, base_c, c.stride());} + else if(stride(a)!=1 && c.stride()==1) { + if(size(a)==1) { herk(c_side==filling::upper?'L':'U', 'N', c.size(), a.rotated().size(), &alpha, base_a, a.rotated().stride(), &beta, base_c, c.rotated().stride());} + else { assert(0);} // NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay) } - else if(stride(a)==1 && stride(c)!=1) {assert(0);} // NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay) - else if(stride(a)==1 && stride(c)==1) {herk(c_side==filling::upper?'U':'L', 'N', size(c), size(rotated(a)), &alpha, base_a, stride(rotated(a)), &beta, base_c, stride(rotated(c)));} + else if(stride(a)==1 && c.stride()!=1) {assert(0);} // NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay) + else if(stride(a)==1 && c.stride()==1) {herk(c_side==filling::upper?'U':'L', 'N', c.size(), a.rotated().size(), &alpha, base_a, a.rotated().stride(), &beta, base_c, c.rotated().stride());} // else {assert(0);} // NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay) } return std::forward(c); } -template{}, int> =0> -auto herk(filling c_side, AA alpha, A2D const& a, BB beta, C2D&& c) // NOLINT(readability-identifier-length) BLAS naming -->decltype(syrk(c_side, alpha, a, beta, std::forward(c))) { - return syrk(c_side, alpha, a, beta, std::forward(c)); } +template{}, int> =0> // NOLINT(modernize-use-constraints) TODO(correaa) for C++20 +auto herk(filling c_side, AA alpha, A2D const& a, BB beta, C2D&& C) // NOLINT(readability-identifier-length) BLAS naming +->decltype(syrk(c_side, alpha, a, beta, std::forward(C))) { + return syrk(c_side, alpha, a, beta, std::forward(C)); } template -auto herk(filling c_side, AA alpha, A2D const& a, C2D&& c) // NOLINT(readability-identifier-length) BLAS naming -->decltype(herk(c_side, alpha, a, 0., std::forward(c))) { - return herk(c_side, alpha, a, 0., std::forward(c)); } +auto herk(filling c_side, AA alpha, A2D const& a, C2D&& C) // NOLINT(readability-identifier-length) BLAS naming +->decltype(herk(c_side, alpha, a, 0., std::forward(C))) { + return herk(c_side, alpha, a, 0., std::forward(C)); } template -auto herk(AA alpha, A2D const& a, C2D&& c) // NOLINT(readability-identifier-length) BLAS naming -->decltype(herk(filling::lower, alpha, a, herk(filling::upper, alpha, a, std::forward(c)))) { - return herk(filling::lower, alpha, a, herk(filling::upper, alpha, a, std::forward(c))); } +auto herk(AA alpha, A2D const& a, C2D&& C) // NOLINT(readability-identifier-length) BLAS naming +->decltype(herk(filling::lower, alpha, a, herk(filling::upper, alpha, a, std::forward(C)))) { + return herk(filling::lower, alpha, a, herk(filling::upper, alpha, a, std::forward(C))); } template -auto herk(A2D const& a, C2D&& c) // NOLINT(readability-identifier-length) BLAS naming -->decltype(herk(1., a, std::forward(c))) { - return herk(1., a, std::forward(c)); } +auto herk(A2D const& A, C2D&& C) // NOLINT(readability-identifier-length) BLAS naming +->decltype(herk(1.0, A, std::forward(C))) { + return herk(1.0, A, std::forward(C)); } template [[nodiscard]] // ("when argument is read-only") @@ -97,22 +179,25 @@ template struct numeric_limits> : std::numeric_limits [[nodiscard]] // ("because argument is read-only")]] auto herk(filling cs, AA alpha, A2D const& a) // NOLINT(readability-identifier-length) BLAS naming -->std::decay_t< -decltype( herk(cs, alpha, a, Ret({size(a), size(a)}, 0., get_allocator(a))))> { - return herk(cs, alpha, a, Ret({size(a), size(a)}, -#ifdef NDEBUG - numeric_limits::quiet_NaN(), -#endif - get_allocator(a) - )); +{ + return herk_range(cs, alpha, a.home(), std::get<0>(a.sizes()), std::get<1>(a.sizes()) ); } - -template auto herk(filling s, A2D const& a) // NOLINT(readability-identifier-length) BLAS naming -->decltype(herk(s, 1., a)) { - return herk(s, 1., a); } +// ->std::decay_t< +// decltype( herk(cs, alpha, a, Ret({size(a), size(a)}, 0.0, get_allocator(a))))> { +// return herk(cs, alpha, a, Ret({size(a), size(a)}, +// #ifdef NDEBUG +// numeric_limits::quiet_NaN(), +// #endif +// get_allocator(a) +// )); +// } + +template auto herk(filling f, A2D const& a) // NOLINT(readability-identifier-length) BLAS naming +->decltype(herk(f, 1.0, a)) { + return herk(f, 1.0, a); } template auto herk(A2D const& array) { - return herk(1., array); + return herk(1.0, array); } } // end namespace boost::multi::blas diff --git a/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/iamax.hpp b/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/iamax.hpp index fef8158725..cf6db746ba 100644 --- a/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/iamax.hpp +++ b/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/iamax.hpp @@ -5,7 +5,7 @@ #ifndef BOOST_MULTI_ADAPTORS_BLAS_IAMAX_HPP #define BOOST_MULTI_ADAPTORS_BLAS_IAMAX_HPP -#include "../blas/core.hpp" +#include namespace boost::multi::blas { diff --git a/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/nrm2.hpp b/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/nrm2.hpp index 5b0dfe583e..57a350027b 100644 --- a/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/nrm2.hpp +++ b/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/nrm2.hpp @@ -19,15 +19,33 @@ using core::nrm2; using multi::base; using std::norm; // nvcc11 needs using std::FUNCTION and the FUNCTION (and it works in clang, gcc, culang, icc) +template +auto nrm2_n(Context&& ctxt, XIt x_first, Size count, RPtr rp) { + std::forward(ctxt)->nrm2(count, x_first.base(), x_first.stride(), rp); +} + template auto nrm2_n(It const& x, Size n, A0D res) // NOLINT(readability-identifier-length) conventional BLAS naming //->decltype(blas::default_context_of(x.base())->nrm2(n, x.base(), x.stride(), res), std::next(res)) { // NOLINT(fuchsia-default-arguments-calls) { return blas::default_context_of(x.base())->nrm2(n, x.base(), x.stride(), res), std::next(res); } // NOLINT(fuchsia-default-arguments-calls) -template -auto nrm2(A1D const& x, A0D&& res) // NOLINT(readability-identifier-length) conventional BLAS naming -//->decltype(nrm2_n(x.begin(), x.size(), &res)) { -{ return nrm2_n(std::begin(x), x.size(), &std::forward(res)); } +template>::value, int> =0> // NOLINT(modernize-use-constraints) TODO(correaa) for C++20 +auto nrm2(Context ctxt, X1D const& x, R&& res) -> R&& { // NOLINT(readability-identifier-length) res = \sum_i x_i y_i + return blas::nrm2_n(ctxt, x.begin(), size(x), &res), std::forward(res); +} + +template>::value, int> =0> // NOLINT(modernize-use-constraints) TODO(correaa) for C++20 +auto nrm2(Context ctxt, X1D const& x, R&& res) -> R&& { // NOLINT(readability-identifier-length) res = \sum_i x_i y_i + return blas::nrm2_n(ctxt, begin(x), size(x), res.base()), std::forward(res); +} + +template +auto nrm2(X1D const& x, R&& res) -> R&& { // NOLINT(readability-identifier-length) BLAS naming + auto ctxtp = blas::default_context_of(x.base()); + return blas::nrm2(ctxtp, x, std::forward(res)); +} template class nrm2_ptr { @@ -65,14 +83,17 @@ struct nrm2_ref : private Ptr { constexpr auto operator&() const& -> Ptr const& {return *this;} // NOLINT(google-runtime-operator) reference type //NOSONAR auto decay() const -> decay_type {decay_type ret; copy_n(operator&(), 1, &ret); return ret;} // NOLINT(fuchsia-default-arguments-calls) complex - operator decay_type() const {return decay();} // NOLINT(google-explicit-constructor,hicpp-explicit-conversions,hicpp-explicit-conversion) //NOSONAR to allow terse syntax + operator decay_type() const { return decay(); } // NOLINT(google-explicit-constructor,hicpp-explicit-conversions,hicpp-explicit-conversion) //NOSONAR to allow terse syntax // #if ! defined(__CUDACC__) || ! defined(__INTEL_COMPILER) // friend auto operator*(decay_type const& lhs, dot_ref const& self) {return lhs*self.decay();} // #endif - auto operator+() const -> decay_type {return decay();} + auto operator+() const -> decay_type { return decay(); } + + // auto operator==(nrm2_ref const& other) const { return decay() == other.decay(); } + // auto operator!=(nrm2_ref const& other) const { return decay() != other.decay(); } - auto operator==(nrm2_ref const& other) const -> bool {return decay() == other.decay();} - auto operator!=(nrm2_ref const& other) const -> bool {return decay() != other.decay();} + friend auto operator==(nrm2_ref const& self, nrm2_ref const& other) { return self.decay() == other.decay(); } + friend auto operator!=(nrm2_ref const& self, nrm2_ref const& other) { return self.decay() != other.decay(); } }; template diff --git a/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/numeric.hpp b/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/numeric.hpp index 0ff3b392f9..038da1b397 100644 --- a/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/numeric.hpp +++ b/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/numeric.hpp @@ -6,19 +6,25 @@ #define BOOST_MULTI_ADAPTORS_BLAS_NUMERIC_HPP #pragma once -#include "../../adaptors/complex.hpp" +// #include #include #include -#include "../blas/complex_traits.hpp" +#include -#include "../../detail/pointer_traits.hpp" +// #include -#include "numeric/is_complex.hpp" +#include -#include +// #include + +#include // for negate +#include // for iterator... +#include // for pointer_... +#include // for decay_t +#include // for declval #if defined(__NVCC__) #define BOOST_MULTI_HD __host__ __device__ @@ -36,7 +42,7 @@ template struct complex_dummy { template< class A, typename Complex = typename std::decay_t::element, typename T = typename multi::blas::complex_traits::real_type, - class = std::enable_if_t::value>> + class = std::enable_if_t::value>> // NOLINT(modernize-use-constraints) TODO(correaa) for C++20 auto real(A&& array) -> decltype(std::forward(array).template reinterpret_array_cast>().template member_cast(&complex_dummy::real)) { return std::forward(array).template reinterpret_array_cast>().template member_cast(&complex_dummy::real); @@ -44,21 +50,21 @@ auto real(A&& array) template< class A, class Complex = typename std::decay_t::element_type, typename T = typename complex_traits::real_type, - class = std::enable_if_t::value>> + class = std::enable_if_t::value>> // NOLINT(modernize-use-constraints) TODO(correaa) for C++20 auto imag(A&& array) -> decltype(std::forward(array).template reinterpret_array_cast>().template member_cast(&complex_dummy::imag)) { return std::forward(array).template reinterpret_array_cast>().template member_cast(&complex_dummy::imag); } template::element, typename RealElem = typename ComplexElem::value_type, - class = std::enable_if_t::value>> + class = std::enable_if_t::value>> // NOLINT(modernize-use-constraints) TODO(correaa) for C++20 auto real_doubled(ComplexArr&& array) { // produces a real view of complex array with the last dimension duplicated and with interleaved real imaginary parts return std::forward(array).template reinterpret_array_cast(2).rotated().flatted().unrotated(); } template class involuted; -template::reference, F>> class involuter; +template::reference, F>> class involuter; // IWYU pragma: keep // bug in iwyu 0.22/18.1.8? template class involuted { @@ -85,7 +91,8 @@ class involuted { constexpr explicit operator decay_type() const& { return f_(r_); } constexpr /*plct*/ operator decay_type() && { return f_(r_); } // NOLINT(google-explicit-constructor,hicpp-explicit-conversions) //NOSONAR to allow terse syntax - constexpr auto operator*(decay_type const& other) const { return f_(r_) * other; } + // constexpr auto operator*(decay_type const& other) const { return f_(r_) * other; } + constexpr friend auto operator*(involuted const& self, decay_type const& other) { return self.f_(self.r_) * other; } template() = (std::declval())(std::declval()))> constexpr auto operator=(DecayType&& other) & -> involuted& { @@ -118,11 +125,13 @@ class involuted { return other != self.operator decay_type(); } - template{}, int> = 0> + template, int> =0> // NOLINT(modernize-use-constraints) TODO(correaa) for C++20 friend constexpr auto operator==(DecayType const& other, involuted const& self) { return other == self.operator decay_type(); } - template{}, int> = 0> + template, int> =0> // NOLINT(modernize-use-constraints) TODO(correaa) for C++20 friend constexpr auto operator!=(DecayType const& other, involuted const& self) { return other != self.operator decay_type(); } @@ -178,8 +187,10 @@ class involuter { constexpr auto operator*() const { return reference{*it_, f_}; } constexpr auto operator[](difference_type n) const { return reference{*(it_ + n), f_}; } - auto operator==(involuter const& other) const -> bool { return it_ == other.it_; } - auto operator!=(involuter const& other) const -> bool { return it_ != other.it_; } + // auto operator==(involuter const& other) const -> bool { return it_ == other.it_; } + // auto operator!=(involuter const& other) const -> bool { return it_ != other.it_; } + friend auto operator==(involuter const& slf, involuter const& thr) { return slf.it_ == thr.it_; } + friend auto operator!=(involuter const& slf, involuter const& thr) { return slf.it_ != thr.it_; } constexpr auto operator+=(difference_type n) -> involuter& { it_ += n; @@ -190,8 +201,10 @@ class involuter { return *this; } - constexpr auto operator+(difference_type n) const { return involuter{it_ + n, f_}; } - constexpr auto operator-(difference_type n) const { return involuter{it_ - n, f_}; } + template // workaround for nvcc + constexpr friend auto operator+(involuter lhs, difference_type n) { return lhs += n; } + template // workaround for nvcc + constexpr friend auto operator-(involuter lhs, difference_type n) { return lhs -= n; } auto operator-(involuter const& other) const { return it_ - other.it_; } @@ -271,20 +284,22 @@ template struct is_conjugated : decltype(is_conjugated_aux((std: }; template, typename Elem = typename D::element_type, typename Ptr = typename D::element_ptr, - std::enable_if_t{}, int> = 0> + std::enable_if_t{}, int> =0> // NOLINT(modernize-use-constraints) TODO(correaa) for C++20 auto conj(A&& array) -> A&& { return std::forward(array); } template< class A, class D = std::decay_t, typename Elem = typename D::element_type, - typename Ptr = std::decay_t().base())>, std::enable_if_t{} && is_complex_array{}, int> = 0> + typename Ptr = std::decay_t().base())>, + std::enable_if_t{} && is_complex_array{}, int> =0> // NOLINT(modernize-use-constraints) TODO(correaa) for C++20 auto conj(A&& array) -> decltype(auto) { return std::forward(array).template static_array_cast>(); } template, typename Elem = typename D::element_type, - typename Ptr = typename decltype(std::declval().base())::underlying_type, std::enable_if_t{}, int> = 0> + typename Ptr = typename decltype(std::declval().base())::underlying_type, + std::enable_if_t{}, int> =0> // NOLINT(modernize-use-constraints) TODO(correaa) for C++20 auto conj(A&& array) -> decltype(std::forward(array).template static_array_cast()) { return std::forward(array).template static_array_cast(); diff --git a/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/operations.hpp b/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/operations.hpp index 1638524bbc..f0938d4576 100644 --- a/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/operations.hpp +++ b/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/operations.hpp @@ -4,21 +4,27 @@ #ifndef BOOST_MULTI_ADAPTORS_BLAS_OPERATIONS_HPP #define BOOST_MULTI_ADAPTORS_BLAS_OPERATIONS_HPP -#pragma once #include namespace boost::multi::blas { -template auto transposed(M const& array) -> decltype(auto){return rotated(array);} +// template auto transposed(M&& arr) -> decltype(auto) {return rotated(std::forward(arr));} -template, typename E=typename D::element_type> -auto conjugated_transposed(A&& array) -> decltype(auto) { - return transposed(blas::conj(std::forward(array))); -} +template +[[deprecated("use blas::T to avoid conflict with multi::transposed")]] +auto transposed(A&& arr) -> decltype(auto) {return std::forward(arr).rotated();} template auto identity(A&& array) -> decltype(auto) {return std::forward(array);} +template auto T(A&& arr) -> decltype(auto) {return std::forward(arr).rotated();} // NOLINT(readability-identifier-naming) : conventional one-letter operation BLAS +template auto N(A&& arr) -> decltype(auto) {return std::forward(arr) ;} // NOLINT(readability-identifier-naming) : conventional one-letter operation BLAS + +template, typename E=typename D::element_type> +auto conjugated_transposed(A&& arr) -> decltype(auto) { + return blas::T(blas::conj(std::forward(arr))); +} + // template, typename E=typename D::element_type> // auto conjugated(A&& array) -> decltype(auto) { // return blas::conj(std::forward(array)); @@ -37,21 +43,21 @@ auto hermitized(A&& array, std::false_type /*false*/) -> decltype(auto) { template auto hermitized(A&& array) -> decltype(auto) {return conjugated_transposed(std::forward(array));} -template -auto transposed(A&& array) -> decltype(auto) {return rotated(std::forward(array));} - namespace operators { -[[maybe_unused]] constexpr static struct { +struct H_t { // NOLINT(readability-identifier-naming) blas naming - template::rank::value == 2, int> =0> + template::rank::value == 2, int> =0> // NOLINT(modernize-use-constraints) TODO(correaa) for C++20 [[nodiscard]] auto operator()(A&& array) const -> decltype(auto) { return hermitized(std::forward(array)); } - template::rank::value == 1, int> =0> + template::rank::value == 1, int> =0> // NOLINT(modernize-use-constraints) TODO(correaa) for C++20 [[deprecated("use blas::C instead of blas::H for conjugated vectors to avoid confusions")]] [[nodiscard]] auto operator()(A&& array) const -> decltype(auto) { return blas::conj(std::forward(array)); } -} H; // NOLINT(readability-identifier-length) conventional name in BLAS +}; + +inline constexpr H_t H; // NOLINT(readability-identifier-length) conventional name in BLAS template auto operator^(A&& array, Op op) @@ -62,15 +68,18 @@ auto operator^(A&& array, Op op) using operators::H; -template::rank::value == 1, int> =0> -auto C(A&& array) -> decltype(auto) {return blas::conj(std::forward(array));} // NOLINT(readability-identifier-naming,readability-identifier-length) : conventional one-letter operation BLAS +template::rank::value == 1, int> =0> // NOLINT(modernize-use-constraints) TODO(correaa) for C++20 +auto C(A&& array) -> decltype(auto) { return blas::conj(std::forward(array)); } // NOLINT(readability-identifier-naming,readability-identifier-length) : conventional one-letter operation BLAS -template::rank::value == 2, int> =0> +template::rank::value == 2, int> =0> // NOLINT(modernize-use-constraints) TODO(correaa) for C++20 [[deprecated("use blas::H instead of blas::C for conjugated transposed matrices to avoid confusion, use blas::J for only-conjugation of matrices")]] -auto C(A&& array) -> decltype(auto) {return hermitized(std::forward(array));} // NOLINT(readability-identifier-naming,readability-identifier-length) : conventional one-letter operation BLAS +auto C(A&& array) -> decltype(auto) { return hermitized(std::forward(array)); } // NOLINT(readability-identifier-naming,readability-identifier-length) : conventional one-letter operation BLAS -template::rank::value == 2, int> =0> -auto J(A&& array) -> decltype(auto) {return blas::conj(std::forward(array));} // NOLINT(readability-identifier-naming,readability-identifier-length) : conventional one-letter operation BLAS +template::rank::value == 2, int> =0> // NOLINT(modernize-use-constraints) for C++20 +auto J(A&& array) -> decltype(auto) { return blas::conj(std::forward(array)); } // NOLINT(readability-identifier-naming,readability-identifier-length) : conventional one-letter operation BLAS namespace operators { @@ -81,14 +90,11 @@ namespace operators { template auto operator~(A&& array) - ->decltype(blas::transposed(std::forward(array))) { - return blas::transposed(std::forward(array)); } + ->decltype(blas::T(std::forward(array))) { + return blas::T(std::forward(array)); } } // end namespace operators -template auto T(A&& array) -> decltype(auto) {return transposed(std::forward(array));} // NOLINT(readability-identifier-naming) : conventional one-letter operation BLAS -template auto N(A&& array) -> decltype(auto) {return identity (std::forward(array));} // NOLINT(readability-identifier-naming) : conventional one-letter operation BLAS - } // end namespace boost::multi::blas #endif diff --git a/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/scal.hpp b/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/scal.hpp index 40187c2dae..67831ab933 100644 --- a/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/scal.hpp +++ b/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/scal.hpp @@ -6,7 +6,11 @@ #define BOOST_MULTI_ADAPTORS_BLAS_SCAL_HPP #pragma once -#include "../blas/core.hpp" +#include +// IWYU pragma: no_include "boost/multi/adaptors/blas/traits.hpp" // for blas, multi + +// IWYU pragma: no_include // for declval // needed by iwyu-clang-linux +#include // for forward, declval namespace boost::multi::blas { diff --git a/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/side.hpp b/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/side.hpp index c3fe0bb0f0..20048b2d2d 100644 --- a/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/side.hpp +++ b/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/side.hpp @@ -17,7 +17,8 @@ inline auto swap(side sid) noexcept -> side { switch(sid) { case side::left : return side::right; case side::right: return side::left ; - } __builtin_unreachable(); // LCOV_EXCL_LINE + } // __builtin_unreachable(); // LCOV_EXCL_LINE + return {}; } } // end namespace boost::multi::blas diff --git a/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/syrk.hpp b/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/syrk.hpp index 46686f1fe2..9608b5002e 100644 --- a/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/syrk.hpp +++ b/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/syrk.hpp @@ -6,38 +6,39 @@ #define BOOST_MULTI_ADAPTORS_BLAS_SYRK_HPP #pragma once -#include "../blas/core.hpp" -#include "../blas/filling.hpp" -#include "../blas/numeric.hpp" +#include +#include +#include namespace boost::multi::blas { using core::syrk; template -auto syrk(filling c_side, typename A2D::element alpha, A2D const& a, typename A2D::element beta, C2D&& c) { // NOLINT(readability-identifier-length) BLAS naming +auto syrk(filling c_side, typename A2D::element alpha, A2D const& a, typename A2D::element beta, C2D&& cc) { // NOLINT(readability-identifier-length) BLAS naming //->decltype(syrk('\0', '\0', size(c), size(a), alpha, base(a), stride(rotated(a)), beta, base(c), stride(c)), std::forward(c)){ - assert(size(c) == size(rotated(c))); + using std::get; + assert( cc.size() == get<1>(cc.sizes()) ); if(stride(a) == 1) { - if(stride(c) == 1) { - syrk(flip(c_side) == filling::upper ? 'L' : 'U', 'N', size(c), size(a), &alpha, base(a), stride(rotated(a)), &beta, base(c), stride(rotated(c))); + if(cc.stride() == 1) { + syrk(flip(c_side) == filling::upper ? 'L' : 'U', 'N', cc.size(), size(a), &alpha, a.base(), a.rotated().stride(), &beta, cc.base(), cc.rotated().size()); } else { - syrk(c_side == filling::upper ? 'L' : 'U', 'N', size(c), size(rotated(a)), &alpha, base(a), stride(rotated(a)), &beta, base(c), stride(c)); + syrk(c_side == filling::upper ? 'L' : 'U', 'N', cc.size(), a.rotated().size(), &alpha, a.base(), a.rotated().stride(), &beta, cc.base(), cc.stride()); } } else { - if(stride(c) == 1) { - syrk(flip(c_side) == filling::upper ? 'L' : 'U', 'T', size(c), size(rotated(a)), &alpha, base(a), stride(a), &beta, base(c), stride(rotated(c))); + if(cc.stride() == 1) { + syrk(flip(c_side) == filling::upper ? 'L' : 'U', 'T', cc.size(), a.rotated().size(), &alpha, a.base(), stride(a), &beta, cc.base(), cc.rotated().stride()); } else { - syrk(c_side == filling::upper ? 'L' : 'U', 'T', size(c), size(rotated(a)), &alpha, base(a), stride(a), &beta, base(c), stride(c)); + syrk(c_side == filling::upper ? 'L' : 'U', 'T', cc.size(), a.rotated().size(), &alpha, a.base(), a.stride(), &beta, cc.base(), cc.stride()); } } - return std::forward(c); + return std::forward(cc); } template -auto syrk(filling c_side, AA alpha, A2D const& a, C2D&& c) // NOLINT(readability-identifier-length) BLAS naming - -> decltype(syrk(c_side, alpha, a, 0.0, std::forward(c))) { - return syrk(c_side, alpha, a, 0.0, std::forward(c)); +auto syrk(filling c_side, AA alpha, A2D const& a, C2D&& cc) // NOLINT(readability-identifier-length) BLAS naming + -> decltype(syrk(c_side, alpha, a, 0.0, std::forward(cc))) { + return syrk(c_side, alpha, a, 0.0, std::forward(cc)); } // template diff --git a/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/test/CMakeLists.txt b/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/test/CMakeLists.txt index 0848f44875..9cc30f3fc3 100644 --- a/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/test/CMakeLists.txt +++ b/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/test/CMakeLists.txt @@ -21,7 +21,7 @@ if((NOT "icpc" ) ) - find_package(Boost REQUIRED COMPONENTS unit_test_framework) + find_package(Boost REQUIRED) # COMPONENTS boost) # headers unit_test_framework) # link_libraries("-lboost_unit_test_framework") find_package(BLAS REQUIRED) @@ -36,7 +36,7 @@ if((NOT link_libraries(${BLAS_LIBRARIES}) else() find_package(Boost REQUIRED) # cmake cannot detect this component with pgi compiler - link_libraries("-lboost_unit_test_framework") + # link_libraries("-lboost_unit_test_framework") link_libraries("-lblas") # cmake cannot detect BLAS with pgi/nvc++ but it ships with its own version endif() @@ -51,7 +51,6 @@ if(CMAKE_CXX_COMPILER_ID STREQUAL "NVHPC") # nvhpc will find its own blas versi add_definitions(-DBLAS_DOT_RETURNS_VOID) endif() - if(ENABLE_CUDA OR DEFINED CXXCUDA) enable_language(CUDA) if(NOT DEFINED CMAKE_CUDA_ARCHITECTURES) @@ -60,10 +59,9 @@ if(ENABLE_CUDA OR DEFINED CXXCUDA) endif() enable_testing() -list(APPEND CMAKE_CTEST_ARGUMENTS "--output-on-failure") # needs cmake 3.17 include(CTest) -configure_file("config.hpp.in" ${CMAKE_BINARY_DIR}/config.hpp) +# configure_file("config.hpp.in" ${CMAKE_BINARY_DIR}/config.hpp) include_directories(${CMAKE_BINARY_DIR}) @@ -83,30 +81,33 @@ set(TEST_SRCS trsm.cpp ) +find_package(TBB) + foreach(TEST_FILE ${TEST_SRCS}) set(TEST_EXE "${TEST_FILE}.x") add_executable(${TEST_EXE} ${TEST_FILE}) if(ENABLE_CUDA OR DEFINED CXXCUDA) set_source_files_properties(${TEST_FILE} PROPERTIES LANGUAGE CUDA) #set_property(TARGET ${TEST_EXE} PROPERTY "${CUDA_ARCH_LIST}") - target_compile_options(${TEST_EXE} PRIVATE -std=c++17) + set_property(TARGET ${TEST_EXE} PROPERTY CUDA_STANDARD 17) endif() target_include_directories(${TEST_EXE} PRIVATE ${PROJECT_SOURCE_DIR}/include) - target_link_libraries (${TEST_EXE} PRIVATE Boost::unit_test_framework ) - # target_include_directories(${TEST_EXE} SYSTEM PRIVATE ${Boost_INCLUDE_DIRS} ) - - target_compile_definitions(${TEST_EXE} PRIVATE "BOOST_PP_VARIADICS") - target_compile_definitions(${TEST_EXE} PRIVATE BOOST_TEST_DYN_LINK=1) - target_compile_definitions(${TEST_EXE} PRIVATE BOOST_TEST_MODULE="C++ Unit Tests for Multi BLAS") - target_compile_options( - ${TEST_EXE} PRIVATE - $<$: - -Wno-unknown-warning-option # for -Wno-enum-constexpr-conversion in older versions - -Wno-enum-constexpr-conversion # for Boost.Test - > - ) + # target_link_libraries (${TEST_EXE} PRIVATE Boost::boost) # headers) # unit_test_framework ) + target_include_directories(${TEST_EXE} SYSTEM PRIVATE ${Boost_INCLUDE_DIRS} ) + + if(TBB_FOUND) + target_link_libraries(${TEST_EXE} PRIVATE TBB::tbb) + endif() + + # target_compile_options( + # ${TEST_EXE} PRIVATE + # $<$: + # -Wno-unknown-warning-option # for -Wno-enum-constexpr-conversion in older versions + # -Wno-enum-constexpr-conversion # for Boost.Test + # > + # ) target_link_libraries(${TEST_EXE} PRIVATE ${BLAS_LIBRARIES}) # there is no BLAS_INCLUDE_DIRS @@ -144,12 +145,20 @@ foreach(TEST_FILE ${TEST_SRCS}) -Wextra -Wpedantic -Wformat-truncation - -Wno-unknown-pragmas> # -Wconversion + -Wno-unknown-pragmas + -Wparentheses + > # -Wconversion $<$,$>: + # -Weverything -Wextra -Wpedantic -Wmove - -Wno-error=\#warnings> + -Wno-error=\#warnings + > # -Wno-c++98-compat # use of constexpr + $<$: + -Wno-unknown-warning-option # for -Wno-enum-constexpr-conversion in older versions + -Wno-enum-constexpr-conversion # for Boost.Test + > $<$: -Wextra -wd161 diff --git a/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/test/axpy.cpp b/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/test/axpy.cpp index 809464dbe5..b2bc041baa 100644 --- a/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/test/axpy.cpp +++ b/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/test/axpy.cpp @@ -2,189 +2,231 @@ // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt -#include +#include // for axpy, operator- +#include // for context +#include // for imag, real +// #include // for complex, operator* +#include // for array, implicit_cast -#include -#include -#include +#include -#include - -#include +#include // for complex, operator+ namespace multi = boost::multi; namespace blas = multi::blas; -using complex = multi::complex; // test internal implementation of complex (partially formed complex) - -BOOST_AUTO_TEST_CASE(multi_blas_axpy_real) { - multi::array arr = { - {1.0, 2.0, 3.0, 4.0}, - {5.0, 6.0, 7.0, 8.0}, - {9.0, 10.0, 11.0, 12.0}, - }; - - auto const AC = arr; - - multi::array const b = arr[2]; // NOLINT(readability-identifier-length) BLAS naming - - blas::axpy(2.0, b, arr[1]); // daxpy - BOOST_REQUIRE( arr[1][2] == 2.0*b[2] + AC[1][2] ); -} - -BOOST_AUTO_TEST_CASE(blas_axpy_repeat) { - multi::array a1D = multi::iextension(3); - BOOST_REQUIRE( a1D[0] == 0.0 ); - BOOST_REQUIRE( a1D[1] == 1.0 ); - BOOST_REQUIRE( a1D[2] == 2.0 ); - - multi::array const b1D = {3.0, 3.0, 3.0}; +// using complex = multi::complex; // test internal implementation of complex (partially formed complex) +using complex = std::complex; // test internal implementation of complex (partially formed complex) - blas::axpy(1.0, b1D, a1D); - BOOST_REQUIRE( a1D[0] == 3.0 ); - BOOST_REQUIRE( a1D[1] == 4.0 ); - BOOST_REQUIRE( a1D[2] == 5.0 ); +#define BOOST_AUTO_TEST_CASE(CasenamE) /**/ - // BOOST_REQUIRE(( multi::array(3.0).broadcasted().size() != 0 )); +void zero_stride() { + multi::array y = {1.0, 2.0, 3.0}; // NOLINT(readability-identifier-length) blas naming - blas::axpy_n(1.0, multi::array(3.0).broadcasted().begin(), 3, a1D.begin()); - BOOST_REQUIRE( a1D[0] == 6.0 ); - BOOST_REQUIRE( a1D[1] == 7.0 ); - BOOST_REQUIRE( a1D[2] == 8.0 ); + // regular arrays, stride != 0 + multi::array const x = {1.0, 1.0, 1.0}; // NOLINT(readability-identifier-length) blas naming - // blas::axpy(1.0, multi::array(3.0).broadcasted(), a1D); - // BOOST_REQUIRE( a1D[0] == 6.0 ); - // BOOST_REQUIRE( a1D[1] == 7.0 ); - // BOOST_REQUIRE( a1D[2] == 8.0 ); - - // blas::axpy(2.0, b, arr[1]); // daxpy - // BOOST_REQUIRE( arr[1][2] == 2.0*b[2] + AC[1][2] ); -} + multi::blas::axpy(1.0, x.begin(), y); -BOOST_AUTO_TEST_CASE(multi_blas_axpy_double) { - multi::array const const_arr = { - {1.0, 2.0, 3.0, 4.0}, - {5.0, 6.0, 7.0, 8.0}, - {9.0, 10.0, 11.0, 12.0}, - }; - multi::array arr = const_arr; - multi::array const b = const_arr[2]; // NOLINT(readability-identifier-length) conventional name in BLAS + BOOST_TEST(y[0] == 2.0); + BOOST_TEST(y[1] == 3.0); + BOOST_TEST(y[2] == 4.0); - blas::axpy(2.0, b, arr[1]); // A[1] = 2*b + A[1], A[1]+= a*A[1] - BOOST_REQUIRE( arr[1][2] == 2.0*b[2] + const_arr[1][2] ); + // broadcasted array of 0D into 1D, stride == 0 + multi::array const x0(1.0); - auto const I = complex{0, 1}; // NOLINT(readability-identifier-length) imaginary unit + // x0.broadcasted() is {..., 1.0, 1.0, ...} and has zero stride - multi::array AC = {1.0 + 2.0 * I, 3.0 + 4.0 * I, 4.0 - 8.0 * I}; - multi::array BC(extensions(AC), complex{0.0, 0.0}); - - blas::axpy(+1.0, blas::real(AC), blas::real(BC)); - blas::axpy(-1.0, blas::imag(AC), blas::imag(BC)); - - // BOOST_REQUIRE( BC[2] == std::conj(AC[2]) ); - BOOST_REQUIRE( BC[2] == conj(AC[2]) ); -} - -BOOST_AUTO_TEST_CASE(multi_blas_axpy_complex) { - multi::array arr = { - {{1.0, 0.0}, {2.0, 0.0}, {3.0, 0.0}, {4.0, 0.0}}, - {{5.0, 0.0}, {6.0, 0.0}, {7.0, 0.0}, {8.0, 0.0}}, - {{9.0, 0.0}, {10.0, 0.0}, {11.0, 0.0}, {12.0, 0.0}}, - }; - auto const const_arr = arr; - - multi::array const x = arr[2]; // NOLINT(readability-identifier-length) BLAS naming - blas::axpy(complex{2.0, 0.0}, x, arr[1]); // zaxpy (2. is promoted to 2+I*0 internally and automatically) - BOOST_REQUIRE( arr[1][2] == 2.0*x[2] + const_arr[1][2] ); -} - -BOOST_AUTO_TEST_CASE(multi_blas_axpy_complex_as_operator_plus_equal) { - using complex = std::complex; - - multi::array arr = { - {{1.0, 0.0}, {2.0, 0.0}, {3.0, 0.0}, {4.0, 0.0}}, - {{5.0, 0.0}, {6.0, 0.0}, {7.0, 0.0}, {8.0, 0.0}}, - {{9.0, 0.0}, {10.0, 0.0}, {11.0, 0.0}, {12.0, 0.0}}, - }; - auto const carr = arr; - multi::array const y = arr[2]; // NOLINT(readability-identifier-length) BLAS naming - arr[1] += blas::axpy(2.0, y); // zaxpy (2. is promoted to 2+I*0 internally and automatically) - BOOST_REQUIRE( arr[1][2] == 2.0*y[2] + carr[1][2] ); -} - -BOOST_AUTO_TEST_CASE(multi_blas_axpy_complex_as_operator_minus_equal) { - multi::array arr = { - {{1.0, 0.0}, {2.0, 0.0}, {3.0, 0.0}, {4.0, 0.0}}, - {{5.0, 0.0}, {6.0, 0.0}, {7.0, 0.0}, {8.0, 0.0}}, - {{9.0, 0.0}, {10.0, 0.0}, {11.0, 0.0}, {12.0, 0.0}}, - }; - auto const AC = arr; - multi::array const x = arr[2]; // NOLINT(readability-identifier-length) BLAS naming - arr[1] -= blas::axpy(complex{2.0, 0.0}, x); // zaxpy (2. is promoted to 2+I*0 internally and automatically) - BOOST_REQUIRE( arr[1][2] == -2.0*x[2] + AC[1][2] ); -} + multi::blas::axpy(1.0, x0.broadcasted().begin(), y); -BOOST_AUTO_TEST_CASE(multi_blas_axpy_complex_context) { - multi::array arr = { - {{1.0, 0.0}, {2.0, 0.0}, {3.0, 0.0}, {4.0, 0.0}}, - {{5.0, 0.0}, {6.0, 0.0}, {7.0, 0.0}, {8.0, 0.0}}, - {{9.0, 0.0}, {10.0, 0.0}, {11.0, 0.0}, {12.0, 0.0}}, - }; - auto const arr_copy = arr; - multi::array const arr2 = arr[2]; - blas::context ctxt{}; - blas::axpy(&ctxt, complex{2.0, 0.0}, arr2, arr[1]); // zaxpy (2. is promoted to 2+I*0 internally and automatically) - BOOST_REQUIRE( arr[1][2] == 2.0*arr2[2] + arr_copy[1][2] ); + BOOST_TEST(y[0] == 3.0); + BOOST_TEST(y[1] == 4.0); + BOOST_TEST(y[2] == 5.0); } -BOOST_AUTO_TEST_CASE(multi_blas_axpy_operator_minus) { - // NOLINTNEXTLINE(readability-identifier-length) BLAS naming - multi::array x = { - {10.0, 0.0}, - {11.0, 0.0}, - {12.0, 0.0}, - {13.0, 0.0}, - }; - multi::array const y = x; // NOLINT(readability-identifier-length) BLAS naming - - using blas::operators::operator-; - - BOOST_REQUIRE( (x - y)[0] == complex{} ); - BOOST_REQUIRE( (y - x)[0] == complex{} ); - - using blas::operators::operator+; - - BOOST_REQUIRE( (x - (y+y))[0] == -x[0] ); - BOOST_REQUIRE( ((x+x) - y)[0] == +x[0] ); - - multi::array arr = { - {{1.0, 0.0}, {2.0, 0.0}}, - {{3.0, 0.0}, {4.0, 0.0}}, - }; - multi::array const arr2 = { - {1.0, 0.0}, - {2.0, 0.0}, - }; - BOOST_REQUIRE( (arr[0] - arr2)[0] == complex{} ); - BOOST_REQUIRE( (arr[0] - arr2)[1] == complex{} ); - - // NOLINTNEXTLINE(readability-identifier-length) BLAS naming - multi::array X = { - {10.0, 0.0}, - {11.0, 0.0}, - {12.0, 0.0}, - {13.0, 0.0}, - }; - - // NOLINTNEXTLINE(readability-identifier-length) BLAS naming - multi::array const Y = { - {10.0, 0.0}, - {11.0, 0.0}, - {12.0, 0.0}, - {13.0, 0.0}, - }; - - using blas::operators::operator-=; - X -= Y; - BOOST_REQUIRE( X[0] == complex{} ); +auto main() -> int { // NOLINT(readability-function-cognitive-complexity,bugprone-exception-escape) + BOOST_AUTO_TEST_CASE(multi_blas_axpy_real) { + multi::array arr = { + {1.0, 2.0, 3.0, 4.0}, + {5.0, 6.0, 7.0, 8.0}, + {9.0, 10.0, 11.0, 12.0}, + }; + + auto const AC = arr; + + multi::array const b = arr[2]; // NOLINT(readability-identifier-length) BLAS naming + + blas::axpy(2.0, b, arr[1]); // daxpy + BOOST_TEST( arr[1][2] == 2.0*b[2] + AC[1][2] ); + } + + BOOST_AUTO_TEST_CASE(blas_axpy_repeat) { + multi::array a1D = multi::iextension(3); + BOOST_TEST( a1D[0] == 0.0 ); + BOOST_TEST( a1D[1] == 1.0 ); + BOOST_TEST( a1D[2] == 2.0 ); + + multi::array const b1D = {3.0, 3.0, 3.0}; + + blas::axpy(1.0, b1D, a1D); + BOOST_TEST( a1D[0] == 3.0 ); + BOOST_TEST( a1D[1] == 4.0 ); + BOOST_TEST( a1D[2] == 5.0 ); + + // BOOST_TEST(( multi::array(3.0).broadcasted().size() != 0 )); + + blas::axpy_n(1.0, multi::array(3.0).broadcasted().begin(), 3, a1D.begin()); + BOOST_TEST( a1D[0] == 6.0 ); + BOOST_TEST( a1D[1] == 7.0 ); + BOOST_TEST( a1D[2] == 8.0 ); + + // blas::axpy(1.0, multi::array(3.0).broadcasted(), a1D); + // BOOST_TEST( a1D[0] == 6.0 ); + // BOOST_TEST( a1D[1] == 7.0 ); + // BOOST_TEST( a1D[2] == 8.0 ); + + // blas::axpy(2.0, b, arr[1]); // daxpy + // BOOST_TEST( arr[1][2] == 2.0*b[2] + AC[1][2] ); + } + + BOOST_AUTO_TEST_CASE(multi_blas_axpy_double) { + multi::array const const_arr = { + {1.0, 2.0, 3.0, 4.0}, + {5.0, 6.0, 7.0, 8.0}, + {9.0, 10.0, 11.0, 12.0}, + }; + multi::array arr = const_arr; + multi::array const b{const_arr[2]}; // NOLINT(readability-identifier-length) conventional name in BLAS + + blas::axpy(2.0, b, arr[1]); // A[1] = 2*b + A[1], A[1]+= a*A[1] + BOOST_TEST( arr[1][2] == 2.0*b[2] + const_arr[1][2] ); + + auto const I = complex{0, 1}; // NOLINT(readability-identifier-length) imaginary unit + + multi::array AC = {1.0 + 2.0 * I, 3.0 + 4.0 * I, 4.0 - 8.0 * I}; + multi::array BC(extensions(AC), complex{0.0, 0.0}); + + blas::axpy(+1.0, blas::real(AC), blas::real(BC)); + blas::axpy(-1.0, blas::imag(AC), blas::imag(BC)); + + // BOOST_TEST( BC[2] == std::conj(AC[2]) ); + BOOST_TEST( BC[2] == conj(AC[2]) ); + } + + BOOST_AUTO_TEST_CASE(multi_blas_axpy_complex) { + multi::array arr = { + {{1.0, 0.0}, {2.0, 0.0}, {3.0, 0.0}, {4.0, 0.0}}, + {{5.0, 0.0}, {6.0, 0.0}, {7.0, 0.0}, {8.0, 0.0}}, + {{9.0, 0.0}, {10.0, 0.0}, {11.0, 0.0}, {12.0, 0.0}}, + }; + auto const const_arr = arr; + + multi::array const x = arr[2]; // NOLINT(readability-identifier-length) BLAS naming + blas::axpy(complex{2.0, 0.0}, x, arr[1]); // zaxpy (2. is promoted to 2+I*0 internally and automatically) + BOOST_TEST( arr[1][2] == 2.0*x[2] + const_arr[1][2] ); + } + + BOOST_AUTO_TEST_CASE(multi_blas_axpy_complex_as_operator_plus_equal) { + using complex = std::complex; + + multi::array arr = { + {{1.0, 0.0}, {2.0, 0.0}, {3.0, 0.0}, {4.0, 0.0}}, + {{5.0, 0.0}, {6.0, 0.0}, {7.0, 0.0}, {8.0, 0.0}}, + {{9.0, 0.0}, {10.0, 0.0}, {11.0, 0.0}, {12.0, 0.0}}, + }; + auto const carr = arr; + multi::array const y = arr[2]; // NOLINT(readability-identifier-length) BLAS naming + arr[1] += blas::axpy(2.0, y); // zaxpy (2. is promoted to 2+I*0 internally and automatically) + BOOST_TEST( arr[1][2] == 2.0*y[2] + carr[1][2] ); + } + + BOOST_AUTO_TEST_CASE(axpy_assignment) { + multi::array const xx = {1.0, 1.0, 1.0}; + multi::array yy = {2.0, 2.0, 2.0}; + + yy += blas::axpy(3.0, xx); + + BOOST_TEST( yy[0] == 5.0 ); + } + + BOOST_AUTO_TEST_CASE(multi_blas_axpy_complex_as_operator_minus_equal) { + multi::array arr = { + {{1.0, 0.0}, {2.0, 0.0}, {3.0, 0.0}, {4.0, 0.0}}, + {{5.0, 0.0}, {6.0, 0.0}, {7.0, 0.0}, {8.0, 0.0}}, + {{9.0, 0.0}, {10.0, 0.0}, {11.0, 0.0}, {12.0, 0.0}}, + }; + auto const AC = arr; + multi::array const x = arr[2]; // NOLINT(readability-identifier-length) BLAS naming + arr[1] -= blas::axpy(complex{2.0, 0.0}, x); // zaxpy (2. is promoted to 2+I*0 internally and automatically) + BOOST_TEST( arr[1][2] == -2.0*x[2] + AC[1][2] ); + } + + BOOST_AUTO_TEST_CASE(multi_blas_axpy_complex_context) { + multi::array arr = { + {{1.0, 0.0}, {2.0, 0.0}, {3.0, 0.0}, {4.0, 0.0}}, + {{5.0, 0.0}, {6.0, 0.0}, {7.0, 0.0}, {8.0, 0.0}}, + {{9.0, 0.0}, {10.0, 0.0}, {11.0, 0.0}, {12.0, 0.0}}, + }; + auto const arr_copy = arr; + multi::array const arr2 = arr[2]; + blas::context ctxt{}; + blas::axpy(&ctxt, complex{2.0, 0.0}, arr2, arr[1]); // zaxpy (2. is promoted to 2+I*0 internally and automatically) + BOOST_TEST( arr[1][2] == 2.0*arr2[2] + arr_copy[1][2] ); + } + + BOOST_AUTO_TEST_CASE(multi_blas_axpy_operator_minus) { + // NOLINTNEXTLINE(readability-identifier-length) BLAS naming + multi::array x = { + {10.0, 0.0}, + {11.0, 0.0}, + {12.0, 0.0}, + {13.0, 0.0}, + }; + multi::array const y = x; // NOLINT(readability-identifier-length) BLAS naming + + using blas::operators::operator-; + + BOOST_TEST( (x - y)[0] == complex(0.0, 0.0) ); + BOOST_TEST( (y - x)[0] == complex(0.0, 0.0) ); + + using blas::operators::operator+; + + BOOST_TEST( (x - (y+y))[0] == -x[0] ); + BOOST_TEST( ((x+x) - y)[0] == +x[0] ); + + multi::array arr = { + {{1.0, 0.0}, {2.0, 0.0}}, + {{3.0, 0.0}, {4.0, 0.0}}, + }; + multi::array const arr2 = { + {1.0, 0.0}, + {2.0, 0.0}, + }; + BOOST_TEST( (arr[0] - arr2)[0] == complex(0.0, 0.0) ); + BOOST_TEST( (arr[0] - arr2)[1] == complex(0.0, 0.0) ); + + // NOLINTNEXTLINE(readability-identifier-length) BLAS naming + multi::array X = { + {10.0, 0.0}, + {11.0, 0.0}, + {12.0, 0.0}, + {13.0, 0.0}, + }; + + // NOLINTNEXTLINE(readability-identifier-length) BLAS naming + multi::array const Y = { + {10.0, 0.0}, + {11.0, 0.0}, + {12.0, 0.0}, + {13.0, 0.0}, + }; + + using blas::operators::operator-=; + X -= Y; + BOOST_TEST( X[0] == complex(0.0, 0.0) ); + } + + zero_stride(); + + return boost::report_errors(); } diff --git a/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/test/copy.cpp b/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/test/copy.cpp index f49f39e19c..09159e385d 100644 --- a/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/test/copy.cpp +++ b/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/test/copy.cpp @@ -1,79 +1,205 @@ // Copyright 2019-2024 Alfredo A. Correa +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt -#include +#include // for copy, copy_n +#include // for array, layout_t, subarray -#include "../../../array.hpp" +#if defined(NDEBUG) // && !defined(__NVCC__) && !(defined(__clang__) && defined(__CUDA__)) + #include // for transform + #include // NOLINT(build/c++11) for duration, high_resolution... + #if __has_include() && !defined(__NVCC__) && !defined(__NVCOMPILER) + #if !((defined(__clang__) && !defined(__apple_build_version__)) && defined(__CUDA__)) + #if (!defined(__INTEL_LLVM_COMPILER) || (__INTEL_LLVM_COMPILER > 20240000)) + #include // for execution_policy + #endif + #endif + #endif + #include // for invoke // IWYU pragma: keep + #include // for basic_ostream, endl, cout +#endif -#include "../../blas/copy.hpp" - -#include +#include // for operator*, operator+ +#include // for size namespace multi = boost::multi; namespace blas = multi::blas; -BOOST_AUTO_TEST_CASE(multi_blas_copy_n) { - multi::array const x = {1.0, 2.0, 3.0, 4.0}; // NOLINT(readability-identifier-length) BLAS naming - multi::array y = {5.0, 6.0, 7.0, 8.0}; // NOLINT(readability-identifier-length) BLAS naming - blas::copy_n(x.begin(), x.size(), y.begin()); - BOOST_REQUIRE( y == x ); -} +#include +#define BOOST_AUTO_TEST_CASE(CasenamE) -BOOST_AUTO_TEST_CASE(multi_blas_copy) { - multi::array const x = {1.0, 2.0, 3.0, 4.0}; // NOLINT(readability-identifier-length) BLAS naming - { - multi::array y = {5.0, 6.0, 7.0, 8.0}; // NOLINT(readability-identifier-length) BLAS naming - blas::copy(x, y); // segmentation fault in clang-11 - BOOST_REQUIRE( y == x ); +auto main() -> int { // NOLINT(readability-function-cognitive-complexity,bugprone-exception-escape) + BOOST_AUTO_TEST_CASE(multi_blas_copy_n) { + multi::array const x = {1.0, 2.0, 3.0, 4.0}; // NOLINT(readability-identifier-length) BLAS naming + multi::array y = {5.0, 6.0, 7.0, 8.0}; // NOLINT(readability-identifier-length) BLAS naming + blas::copy_n(x.begin(), x.size(), y.begin()); + BOOST_TEST( y == x ); } - { - multi::array y = {5.0, 6.0, 7.0, 8.0}; // NOLINT(readability-identifier-length) BLAS naming - BOOST_REQUIRE( size(y) == size(x) ); - y() = blas::copy(x); - BOOST_REQUIRE( y == x ); + + BOOST_AUTO_TEST_CASE(multi_blas_copy) { + multi::array const x = {1.0, 2.0, 3.0, 4.0}; // NOLINT(readability-identifier-length) BLAS naming + { + multi::array y = {5.0, 6.0, 7.0, 8.0}; // NOLINT(readability-identifier-length) BLAS naming + blas::copy(x, y); // segmentation fault in clang-11 + BOOST_TEST( y == x ); + } + { + multi::array y = {5.0, 6.0, 7.0, 8.0}; // NOLINT(readability-identifier-length) BLAS naming + BOOST_TEST( size(y) == size(x) ); + y() = blas::copy(x); + BOOST_TEST( y == x ); + } } -} -BOOST_AUTO_TEST_CASE(multi_adaptors_blas_test_copy_real) { - namespace blas = multi::blas; - multi::array arr = { - {1.0, 2.0, 3.0, 4.0}, - {5.0, 6.0, 7.0, 8.0}, - {9.0, 10.0, 11.0, 12.0}, - }; - BOOST_REQUIRE( arr[0][2] == 3.0 ); - BOOST_REQUIRE( arr[2][2] == 11.0 ); - - blas::copy(arr[0], arr[2]); - BOOST_REQUIRE( arr[0][2] == 3.0 ); - BOOST_REQUIRE( arr[2][2] == 3.0 ); - - blas::copy(arr[1]({0, size(arr[1])}), arr[2]({0, size(arr[1])})); - BOOST_REQUIRE( arr[1][3] == 8.0 ); - BOOST_REQUIRE( arr[2][3] == 8.0 ); - - multi::array AR3 = blas::copy(rotated(arr)[3]); // dcopy - BOOST_REQUIRE( AR3[1] == arr[1][3] ); -} + BOOST_AUTO_TEST_CASE(multi_adaptors_blas_test_copy_real) { + namespace blas = multi::blas; -BOOST_AUTO_TEST_CASE(multi_blas_copy_row) { - multi::array const arr = { - {1.0, 2.0, 3.0}, - {4.0, 5.0, 6.0}, - {7.0, 8.0, 9.0}, - }; - multi::array y(multi::extensions_t<1>{multi::iextension{3}}); // NOLINT(readability-identifier-length) BLAS naming - blas::copy(rotated(arr)[0], y); - BOOST_REQUIRE( y == rotated(arr)[0] ); -} + multi::array arr = { + {1.0, 2.0, 3.0, 4.0}, + {5.0, 6.0, 7.0, 8.0}, + {9.0, 10.0, 11.0, 12.0}, + }; + + BOOST_TEST( arr[0][2] == 3.0 ); + BOOST_TEST( arr[2][2] == 11.0 ); + + blas::copy(arr[0], arr[2]); + BOOST_TEST( arr[0][2] == 3.0 ); + BOOST_TEST( arr[2][2] == 3.0 ); + + blas::copy(arr[1]({0, size(arr[1])}), arr[2]({0, size(arr[1])})); + BOOST_TEST( arr[1][3] == 8.0 ); + BOOST_TEST( arr[2][3] == 8.0 ); + + multi::array AR3 = blas::copy(arr.rotated()[3]); // dcopy + BOOST_TEST( AR3[1] == arr[1][3] ); + } + + BOOST_AUTO_TEST_CASE(multi_blas_copy_row) { + multi::array const arr = { + {1.0, 2.0, 3.0}, + {4.0, 5.0, 6.0}, + {7.0, 8.0, 9.0}, + }; + multi::array y(multi::extensions_t<1>{multi::iextension{3}}); // NOLINT(readability-identifier-length) BLAS naming + blas::copy(arr.rotated()[0], y); + BOOST_TEST( y == arr.rotated()[0] ); + } + + BOOST_AUTO_TEST_CASE(multi_adaptors_blas_test_copy_complex) { + using complex = std::complex; + + auto const I = complex{0.0, 1.0}; // NOLINT(readability-identifier-length) imag unit + + multi::array arr = { + {1.0 + 3.0 * I, 2.0 + 4.0 * I, 3.0 + 5.0 * I, 4.0 + 6.0 * I}, + {5.0 + 0.0 * I, 6.0 + 0.0 * I, 7.0 + 0.0 * I, 8.0 + 0.0 * I}, + {9.0 + 0.0 * I, 10.0 + 0.0 * I, 11.0 + 0.0 * I, 12.0 + 0.0 * I}, + }; + blas::copy(arr[0], arr[2]); + BOOST_TEST( arr[0][2] == 3.0 + 5.0*I ); + } + +#if defined(__INTEL_LLVM_COMPILER) + std::cout << __INTEL_LLVM_COMPILER << std::endl; +#endif + +#if defined(NDEBUG) + /* transform copy */ { + multi::array A2D({10000, 10000}, 55.5); + auto&& A2D_block = A2D({1000, 9000}, {1000, 5000}); + + multi::array B2D({10000, 10000}, 66.6); + auto&& B2D_block = ~(~B2D({1000, 9000}, {1000, 9000})).strided(2); + + using std::chrono::high_resolution_clock; + using std::chrono::duration; + + std::cout + << "MULTI assignment\n" + << std::invoke([&, start_time = high_resolution_clock::now()] { + B2D_block = A2D_block; + return duration{high_resolution_clock::now() - start_time}; + }).count() + << '\n'; + + BOOST_TEST( A2D_block == B2D_block ); + + std::cout << "std::transform BLAS\n" + << std::invoke([&, start_time = high_resolution_clock::now()] { + std::transform(A2D_block.begin(), A2D_block.end(), B2D_block.begin(), [](auto const& row) { return multi::blas::copy(row); }); + return duration{high_resolution_clock::now() - start_time}; + }).count() + << '\n'; + + BOOST_TEST( A2D_block == B2D_block ); + + #if __has_include() && !defined(__NVCC__) && !defined(__NVCOMPILER) + #if !((defined(__clang__) ) && defined(__CUDA__)) && (!defined(__INTEL_LLVM_COMPILER) || (__INTEL_LLVM_COMPILER > 20240000)) + #if(__cplusplus >= 202002L) + #if !defined(__apple_build_version__) + std::cout << "std::transform par BLAS\n" + << std::invoke([&, start_time = high_resolution_clock::now()] { + std::transform(std::execution::par, A2D_block.begin(), A2D_block.end(), B2D_block.begin(), [](auto& row) { return multi::blas::copy(row); }); + return duration{high_resolution_clock::now() - start_time}; + }).count() + << '\n'; + + BOOST_TEST( A2D_block == B2D_block ); + #endif + std::cout << "std::copy par\n" + << std::invoke([&, start_time = high_resolution_clock::now()] { + std::copy(std::execution::par, A2D_block.begin(), A2D_block.end(), B2D_block.begin()); + return duration{high_resolution_clock::now() - start_time}; + }).count() + << '\n'; + + std::cout << "std::copy par 2\n" + << std::invoke([&, start_time = high_resolution_clock::now()] { + std::transform( + std::execution::par, A2D_block.begin(), A2D_block.end(), B2D_block.begin(), B2D_block.begin(), + [](auto const& row_a, auto&& row_b) -> auto&& { + std::copy(std::execution::par_unseq, row_a.begin(), row_a.end(), row_b.begin()); + return std::forward(row_b); + } + ); + return duration{high_resolution_clock::now() - start_time}; + }).count() + << '\n'; + + BOOST_TEST( A2D_block == B2D_block ); + + std::cout << "std::copy elements par\n" + << std::invoke([&, start_time = high_resolution_clock::now()] { + std::copy(std::execution::par_unseq, A2D_block.elements().begin(), A2D_block.elements().end(), B2D_block.elements().begin()); + return duration{high_resolution_clock::now() - start_time}; + }).count() + << '\n'; + + BOOST_TEST( A2D_block == B2D_block ); + #endif + #endif + #endif + + std::cout << "std::copy\n" + << std::invoke([&, start_time = high_resolution_clock::now()] { + std::copy(A2D_block.begin(), A2D_block.end(), B2D_block.begin()); + return duration{high_resolution_clock::now() - start_time}; + }).count() + << '\n'; + + BOOST_TEST( A2D_block == B2D_block ); + + std::cout << "Multi element assignment\n" + << std::invoke([&, start_time = high_resolution_clock::now()] { + B2D_block.elements() = A2D_block.elements(); + return duration{high_resolution_clock::now() - start_time}; + }).count() + << '\n'; + + BOOST_TEST( A2D_block == B2D_block ); + } +#endif -BOOST_AUTO_TEST_CASE(multi_adaptors_blas_test_copy_complex) { - using complex = std::complex; - auto const I = complex{0.0, 1.0}; // NOLINT(readability-identifier-length) imag unit - multi::array arr = { - {1.0 + 3.0 * I, 2.0 + 4.0 * I, 3.0 + 5.0 * I, 4.0 + 6.0 * I}, - {5.0 + 0.0 * I, 6.0 + 0.0 * I, 7.0 + 0.0 * I, 8.0 + 0.0 * I}, - {9.0 + 0.0 * I, 10.0 + 0.0 * I, 11.0 + 0.0 * I, 12.0 + 0.0 * I}, - }; - blas::copy(arr[0], arr[2]); - BOOST_REQUIRE( arr[0][2] == 3.0 + 5.0*I ); + return boost::report_errors(); } diff --git a/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/test/dot.cpp b/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/test/dot.cpp index ebbadab64b..507acc18bb 100644 --- a/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/test/dot.cpp +++ b/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/test/dot.cpp @@ -2,491 +2,619 @@ // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt -#include - -#include -#include - -#include -#include -#include +#include + +#include // for context, dot +#include // for dot_ref, dot, dot_n +#include // for involuter, conj +#include // for C, hermitized +#include // for array, static_array + +#include // for for_each, transform +#include +#include // for complex, operator* +#include // for plus // IWYU pragma: keep +#include // for begin, end +#include // for numeric_limits +#include // for allocator +#include // for inner_product +// IWYU pragma: no_include // for tuple_element<>:... +// IWYU pragma: no_include +#include // for is_same +#include // for forward namespace multi = boost::multi; namespace blas = multi::blas; -BOOST_AUTO_TEST_CASE(blas_dot_context_double) { - multi::array const x = {1.0, 2.0, 3.0}; // NOLINT(readability-identifier-length) BLAS naming - multi::array const y = {1.0, 2.0, 3.0}; // NOLINT(readability-identifier-length) BLAS naming - - blas::context const ctxt; - - auto res1 = +blas::dot(&ctxt, x, y); - BOOST_TEST( res1 == std::inner_product(begin(x), end(x), begin(y), 0.0) ); - - auto const res2 = +blas::dot(&ctxt, x, y); - BOOST_TEST( res2 == std::inner_product(begin(x), end(x), begin(y), 0.0) ); -} - -BOOST_AUTO_TEST_CASE(blas_dot_no_context_double) { - multi::array const x = {1.0, 2.0, 3.0}; // NOLINT(readability-identifier-length) BLAS naming - multi::array const y = {1.0, 2.0, 3.0}; // NOLINT(readability-identifier-length) BLAS naming - - auto res = +blas::dot(x, y); - - BOOST_TEST( res == std::inner_product(begin(x), end(x), begin(y), 0.0) ); -} - -BOOST_AUTO_TEST_CASE(blas_dot_no_context_out_param_double) { - multi::array const x = {1.0, 2.0, 3.0}; // NOLINT(readability-identifier-length) BLAS naming - multi::array const y = {1.0, 2.0, 3.0}; // NOLINT(readability-identifier-length) BLAS naming - - double res = NAN; - - blas::dot(x, y, multi::array_ref(res)); - BOOST_TEST( res == std::inner_product(begin(x), end(x), begin(y), 0.0) ); -} - -// float uses of dot are disabled because of a bug in Apple Accelerate BLAS, https://fortran-lang.discourse.group/t/how-many-blas-libraries-have-this-error/4454/23, https://forums.developer.apple.com/forums/thread/717757 -BOOST_AUTO_TEST_CASE(blas_dot_context_float, *boost::unit_test::disabled()) { - multi::array const x = {1.0F, 2.0F, 3.0F}; // NOLINT(readability-identifier-length) BLAS naming - multi::array const y = {1.0F, 2.0F, 3.0F}; // NOLINT(readability-identifier-length) BLAS naming - - blas::context const ctxt; - - auto res1 = +blas::dot(&ctxt, x, y); - BOOST_TEST( res1 == std::inner_product(begin(x), end(x), begin(y), 0.0F) ); - - auto const res2 = +blas::dot(&ctxt, x, y); - BOOST_TEST( res2 == std::inner_product(begin(x), end(x), begin(y), 0.0F) ); -} - -BOOST_AUTO_TEST_CASE(blas_dot_no_context_float, *boost::unit_test::disabled()) { - multi::array const x = {1.0F, 2.0F, 3.0F}; // NOLINT(readability-identifier-length) BLAS naming - multi::array const y = {1.0F, 2.0F, 3.0F}; // NOLINT(readability-identifier-length) BLAS naming - - auto res = +blas::dot(x, y); - - BOOST_TEST( res == std::inner_product(begin(x), end(x), begin(y), 0.0F) ); -} - -BOOST_AUTO_TEST_CASE(blas_dot_no_context_out_param_float, *boost::unit_test::disabled()) { - multi::array const x = {1.0F, 2.0F, 3.0F}; // NOLINT(readability-identifier-length) BLAS naming - multi::array const y = {1.0F, 2.0F, 3.0F}; // NOLINT(readability-identifier-length) BLAS naming - float res = NAN; - blas::dot(x, y, multi::array_ref(res)); - BOOST_TEST( res == std::inner_product(begin(x), end(x), begin(y), 0.0F) ); -} - -BOOST_AUTO_TEST_CASE(blas_dot_no_context_out_param_complex_double) { // if you get a segfaut here, your system may require -DRETURN_BY_STACK - using complex = std::complex; - // NOLINTNEXTLINE(readability-identifier-length) BLAS naming - multi::array const x = { - {1.0, 0.0}, - {2.0, 0.0}, - {3.0, 0.0}, - }; - // NOLINTNEXTLINE(readability-identifier-length) BLAS naming - multi::array const y = { - {1.0, 0.0}, - {2.0, 0.0}, - {3.0, 0.0}, - }; // NOLINT(readability-identifier-length) BLAS naming - complex res{0.0, 0.0}; - blas::dot(x, y, res); - // an isolated error here might mean that the dot and nrm2 interface for the BLAS library is not detected properly - BOOST_REQUIRE_EQUAL(real(res), real(std::inner_product(begin(x), end(x), begin(y), complex{0.0, 0.0}, std::plus<>{}, [](auto const& alpha, auto const& omega) { return alpha * std::conj(omega); }))); - BOOST_REQUIRE_EQUAL(imag(res), imag(std::inner_product(begin(x), end(x), begin(y), complex{0.0, 0.0}, std::plus<>{}, [](auto const& alpha, auto const& omega) { return alpha * std::conj(omega); }))); -} - -BOOST_AUTO_TEST_CASE(blas_dot_no_context_out_param_complex_float) { // if you get a segfaut here, your system may require -DRETURN_BY_STACK - using complex = std::complex; - // NOLINTNEXTLINE(readability-identifier-length) BLAS naming - multi::array const x = { - {1.0F, 0.0F}, - {2.0F, 0.0F}, - {3.0F, 0.0F}, - }; - // NOLINTNEXTLINE(readability-identifier-length) BLAS naming - multi::array const y = { - {1.0F, 0.0F}, - {2.0F, 0.0F}, - {3.0F, 0.0F}, - }; // NOLINT(readability-identifier-length) BLAS naming - complex res{0.0F, 0.0F}; - blas::dot(x, y, res); - - // // an isolated error here might mean that the dot and nrm2 interface for the BLAS library is not detected properly - BOOST_REQUIRE_EQUAL(real(res), real(std::inner_product(begin(x), end(x), begin(y), complex{0.0F, 0.0F}, std::plus<>{}, [](auto const& alpha, auto const& omega) { return alpha * std::conj(omega); }))); - BOOST_REQUIRE_EQUAL(imag(res), imag(std::inner_product(begin(x), end(x), begin(y), complex{0.0F, 0.0F}, std::plus<>{}, [](auto const& alpha, auto const& omega) { return alpha * std::conj(omega); }))); -} - -BOOST_AUTO_TEST_CASE(blas_dot_no_context_out_param_complex_C) { - using complex = std::complex; - auto const I = complex{0.0, 1.0}; // NOLINT(readability-identifier-length) imag unit - - multi::array const x = {1.0 + 0.0 * I, 2.0 + 0.0 * I, 3.0 + 0.0 * I}; // NOLINT(readability-identifier-length) BLAS naming - multi::array const y = {1.0 + 0.0 * I, 2.0 + 2.0 * I, 3.0 + 0.0 * I}; // NOLINT(readability-identifier-length) BLAS naming - - complex res{0.0, 0.0}; - blas::dot(blas::C(x), y, res); - BOOST_REQUIRE( res == std::inner_product(begin(x), end(x), begin(y), complex{0.0, 0.0}, std::plus<>{}, [](auto const& alpha, auto const& omega) { return conj(alpha) * omega;}) ); -} - -BOOST_AUTO_TEST_CASE(blas_dot_no_context_out_param_complex_C_float) { - using complex = std::complex; - auto const I = complex{0.0F, 1.0F}; // NOLINT(readability-identifier-length) imag unit +#define BOOST_AUTO_TEST_CASE(CasenamE) /**/ - multi::array const x = {1.0F + 0.0F * I, 2.0F + 0.0F * I, 3.0F + 0.0F * I}; // NOLINT(readability-identifier-length) BLAS naming - multi::array const y = {1.0F + 0.0F * I, 2.0F + 2.0F * I, 3.0F + 0.0F * I}; // NOLINT(readability-identifier-length) BLAS naming +auto main() -> int { // NOLINT(readability-function-cognitive-complexity,bugprone-exception-escape) + BOOST_AUTO_TEST_CASE(blas_dot_context_double) { + multi::array const x = {1.0, 2.0, 3.0}; // NOLINT(readability-identifier-length) BLAS naming + multi::array const y = {1.0, 2.0, 3.0}; // NOLINT(readability-identifier-length) BLAS naming - complex res{0.0F, 0.0F}; - blas::dot(blas::C(x), y, res); - BOOST_REQUIRE( res == std::inner_product(begin(x), end(x), begin(y), complex{0.0F, 0.0F}, std::plus<>{}, [](auto const& alpha, auto const& omega) { return conj(alpha) * omega;}) ); -} - -#if defined(CUDA_FOUND) and CUDA_FOUND -#include -BOOST_AUTO_TEST_CASE(blas_dot_no_context_out_param_complex_C_thrust) { - using complex = thrust::complex; - auto const I = complex{0.0, 1.0}; + blas::context const ctxt; - multi::array const A = {1.0 + 0. * I, 2.0 + 0.0 * I, 3.0 + 0.0 * I}; - multi::array const B = {1.0 + 0. * I, 2.0 + 2.0 * I, 3.0 + 0.0 * I}; + auto res1 = +blas::dot(&ctxt, x, y); + BOOST_TEST( res1 == std::inner_product(begin(x), end(x), begin(y), 0.0) ); + + auto const res2 = +blas::dot(&ctxt, x, y); + BOOST_TEST( res2 == std::inner_product(begin(x), end(x), begin(y), 0.0) ); + } + + BOOST_AUTO_TEST_CASE(blas_dot_no_context_double) { + multi::array const x = {1.0, 2.0, 3.0}; // NOLINT(readability-identifier-length) BLAS naming + multi::array const y = {1.0, 2.0, 3.0}; // NOLINT(readability-identifier-length) BLAS naming + + auto res = +blas::dot(x, y); + + BOOST_TEST( res == std::inner_product(begin(x), end(x), begin(y), 0.0) ); + } + + BOOST_AUTO_TEST_CASE(blas_dot_no_context_out_param_double) { + multi::array const x = {1.0, 2.0, 3.0}; // NOLINT(readability-identifier-length) BLAS naming + multi::array const y = {1.0, 2.0, 3.0}; // NOLINT(readability-identifier-length) BLAS naming + + double res = std::numeric_limits::quiet_NaN(); + + blas::dot(x, y, multi::array_ref(res)); + BOOST_TEST( res == std::inner_product(begin(x), end(x), begin(y), 0.0) ); + } + + BOOST_AUTO_TEST_CASE(blas_dot_context_double) { + using T = double; + multi::array const x = {1.0, 2.0, 3.0}; // NOLINT(readability-identifier-length) BLAS naming + multi::array const y = {1.0, 2.0, 3.0}; // NOLINT(readability-identifier-length) BLAS naming + + blas::context const ctxt; + + auto const res1 = +blas::dot(&ctxt, x, y); + BOOST_TEST( std::abs(res1 - std::inner_product(begin(x), end(x), begin(y), 0.0)) < 1.0e-8F ); + + auto const res2 = +blas::dot(&ctxt, x, y); + BOOST_TEST( res2 == std::inner_product(begin(x), end(x), begin(y), 0.0) ); + } + + BOOST_AUTO_TEST_CASE(blas_dot_context_float) { + using T = float; + multi::array const x = {1.0F, 2.0F, 3.0F}; // NOLINT(readability-identifier-length) BLAS naming + multi::array const y = {1.0F, 2.0F, 3.0F}; // NOLINT(readability-identifier-length) BLAS naming + + blas::context const ctxt; + + auto const res1 = +blas::dot(x, y); + BOOST_TEST( std::abs(res1 - std::inner_product(begin(x), end(x), begin(y), 0.0F)) < 1.0e-8F ); + + auto const res2 = +blas::dot(&ctxt, x, y); + BOOST_TEST( res2 == std::inner_product(begin(x), end(x), begin(y), 0.0F) ); + } + + // Apple Accelerate BLAS has bugs with dot for floats, https://fortran-lang.discourse.group/t/how-many-blas-libraries-have-this-error/4454/23, https://forums.developer.apple.com/forums/thread/717757 + + BOOST_AUTO_TEST_CASE(blas_dot_no_context_float) { + multi::array const x = {1.0F, 2.0F, 3.0F}; // NOLINT(readability-identifier-length) BLAS naming + multi::array const y = {1.0F, 2.0F, 3.0F}; // NOLINT(readability-identifier-length) BLAS naming + + auto res = +blas::dot(x, y); + + BOOST_TEST( res == std::inner_product(begin(x), end(x), begin(y), 0.0F) ); + } + + BOOST_AUTO_TEST_CASE(blas_dot_no_context_out_param_float) { + multi::array const x = {1.0F, 2.0F, 3.0F}; // NOLINT(readability-identifier-length) BLAS naming + multi::array const y = {1.0F, 2.0F, 3.0F}; // NOLINT(readability-identifier-length) BLAS naming + float res = std::numeric_limits::quiet_NaN(); + blas::dot(x, y, multi::array_ref(res)); + BOOST_TEST( res == std::inner_product(begin(x), end(x), begin(y), 0.0F) ); + } + + BOOST_AUTO_TEST_CASE(blas_dot_no_context_out_param_complex_double) { // if you get a segfaut here, your system may require -DRETURN_BY_STACK + using complex = std::complex; + // NOLINTNEXTLINE(readability-identifier-length) BLAS naming + multi::array const x = { + {1.0, 0.0}, + {2.0, 0.0}, + {3.0, 0.0}, + }; + // NOLINTNEXTLINE(readability-identifier-length) BLAS naming + multi::array const y = { + {1.0, 0.0}, + {2.0, 0.0}, + {3.0, 0.0}, + }; // NOLINT(readability-identifier-length) BLAS naming + complex res{0.0, 0.0}; + blas::dot(x, y, res); + + auto hermitian_product = [](auto alpha, auto omega) { + return alpha * std::conj(omega); + }; + + // an isolated error here might mean that the dot and nrm2 interface for the BLAS library is not detected properly + BOOST_TEST_EQ( + real(res), + real(std::inner_product(begin(x), end(x), begin(y), complex{}, std::plus<>{}, hermitian_product)) // NOLINT(fuchsia-default-arguments-calls) + ); + BOOST_TEST_EQ( + imag(res), + imag(std::inner_product(begin(x), end(x), begin(y), complex{}, std::plus<>{}, hermitian_product)) // NOLINT(fuchsia-default-arguments-calls) + ); + } + + BOOST_AUTO_TEST_CASE(blas_dot_no_context_out_param_complex_float) { // if you get a segfaut here, your system may require -DRETURN_BY_STACK + using complex = std::complex; + // NOLINTNEXTLINE(readability-identifier-length) BLAS naming + multi::array const x = { + {1.0F, 0.0F}, + {2.0F, 0.0F}, + {3.0F, 0.0F}, + }; + // NOLINTNEXTLINE(readability-identifier-length) BLAS naming + multi::array const y = { + {1.0F, 0.0F}, + {2.0F, 0.0F}, + {3.0F, 0.0F}, + }; // NOLINT(readability-identifier-length) BLAS naming + complex res{0.0F, 0.0F}; + blas::dot(x, y, res); + + BOOST_TEST( std::abs(real(res)) > 1.0e-6 ); + + // // an isolated error here might mean that the dot and nrm2 interface for the BLAS library is not detected properly + BOOST_TEST_EQ( + real(res), + real(std::inner_product( + begin(x), end(x), begin(y), complex{}, std::plus<>{}, // NOLINT(fuchsia-default-arguments-calls) + [](auto alpha, auto omega) { return alpha * std::conj(omega); } + )) + ); + BOOST_TEST_EQ( + imag(res), + imag( + std::inner_product(begin(x), end(x), begin(y), complex{}, std::plus{}, // NOLINT(fuchsia-default-arguments-calls) + [](auto alpha, auto omega) { return alpha * std::conj(omega); }) + ) + ); + } + + BOOST_AUTO_TEST_CASE(blas_dot_no_context_out_param_complex_C) { + using complex = std::complex; + auto const I = complex{0.0, 1.0}; // NOLINT(readability-identifier-length) imag unit + + multi::array const x = {1.0 + 0.0 * I, 2.0 + 0.0 * I, 3.0 + 0.0 * I}; // NOLINT(readability-identifier-length) BLAS naming + multi::array const y = {1.0 + 0.0 * I, 2.0 + 2.0 * I, 3.0 + 0.0 * I}; // NOLINT(readability-identifier-length) BLAS naming + + complex res{-999.0, 666.0}; + blas::dot(blas::C(x), y, res); + BOOST_TEST( + res == std::inner_product(begin(x), end(x), begin(y), complex{}, std::plus{}, // NOLINT(fuchsia-default-arguments-calls) + [](auto alpha, auto omega) { return conj(alpha) * omega;} + ) + ); + } + + BOOST_AUTO_TEST_CASE(blas_dot_no_context_out_param_complex_C_float) { + using complex = std::complex; + auto const I = complex{0.0F, 1.0F}; // NOLINT(readability-identifier-length) imag unit + + multi::array const x = {1.0F + 0.0F * I, 2.0F + 0.0F * I, 3.0F + 0.0F * I}; // NOLINT(readability-identifier-length) BLAS naming + multi::array const y = {1.0F + 0.0F * I, 2.0F + 2.0F * I, 3.0F + 0.0F * I}; // NOLINT(readability-identifier-length) BLAS naming + + complex res{0.0F, 0.0F}; + blas::dot(blas::C(x), y, res); + + + BOOST_TEST( + res == std::inner_product( + begin(x), end(x), begin(y), complex{}, std::plus<>{}, // NOLINT(fuchsia-default-arguments-calls) + [](auto const& alpha, auto const& omega) { + return conj(alpha) * omega; + } + ) + ); + } + +// #if defined(CUDA_FOUND) and CUDA_FOUND +// #include +// BOOST_AUTO_TEST_CASE(blas_dot_no_context_out_param_complex_C_thrust) { +// using complex = thrust::complex; +// auto const I = complex{0.0, 1.0}; + +// multi::array const A = {1.0 + 0. * I, 2.0 + 0.0 * I, 3.0 + 0.0 * I}; +// multi::array const B = {1.0 + 0. * I, 2.0 + 2.0 * I, 3.0 + 0.0 * I}; + +// complex C; +// blas::dot(blas::C(A), B, C); +// BOOST_TEST( C == std::inner_product(begin(A), end(A), begin(B), complex{0.0, 0.0}, std::plus<>{}, [](auto& a, auto& b){ +// return conj(a) * b;}) ); +// } +// #endif + + BOOST_AUTO_TEST_CASE(multi_blas_dot_strided_double) { + multi::array const CA = { + {1.0, 2.0, 3.0, 4.0}, + {5.0, 6.0, 7.0, 8.0}, + {9.0, 10.0, 11.0, 12.0}, + }; + double res = std::numeric_limits::quiet_NaN(); + blas::dot_n(begin(CA[1]), size(CA[1]), begin(CA[2]), &res); + BOOST_TEST( res == std::inner_product(begin(CA[1]), begin(CA[2]), end(CA[1]), 0.0) ); + + double const res2 = blas::dot(CA[1], CA[2]); + BOOST_TEST( res == res2 ); + } + + BOOST_AUTO_TEST_CASE(multi_blas_dot_strided_float) { + multi::array const CA = { + {1.0F, 2.0F, 3.0F, 4.0F}, + {5.0F, 6.0F, 7.0F, 8.0F}, + {9.0F, 10.0F, 11.0F, 12.0F}, + }; + auto res = std::numeric_limits::quiet_NaN(); + blas::dot_n(begin(CA[1]), size(CA[1]), begin(CA[2]), &res); + BOOST_TEST( res == std::inner_product(begin(CA[1]), begin(CA[2]), end(CA[1]), 0.0F) ); + + double const res2 = blas::dot(CA[1], CA[2]); + BOOST_TEST( res == res2 ); + } + + BOOST_AUTO_TEST_CASE(multi_blas_dot_strided_context) { + multi::array const CA = { + {1.0, 2.0, 3.0, 4.0}, + {5.0, 6.0, 7.0, 8.0}, + {9.0, 10.0, 11.0, 12.0}, + }; + + double res = std::numeric_limits::quiet_NaN(); + + blas::context ctxt; + blas::dot_n(&ctxt, begin(CA[1]), size(CA[1]), begin(CA[2]), &res); + BOOST_TEST( res == std::inner_product(begin(CA[1]), begin(CA[2]), end(CA[1]), 0.0) ); + + double const res2 = blas::dot(CA[1], CA[2]); + BOOST_TEST( res == res2 ); + } + +// #ifndef __APPLE__ +// BOOST_AUTO_TEST_CASE(multi_blas_dot_strided_context_float) { +// multi::array const CA = { +// {1.0F, 2.0F, 3.0F, 4.0F}, +// {5.0F, 6.0F, 7.0F, 8.0F}, +// {9.0F, 10.0F, 11.0F, 12.0F}, +// }; +// auto res = std::numeric_limits::quiet_NaN(); + +// blas::context ctxt; +// blas::dot_n(&ctxt, begin(CA[1]), size(CA[1]), begin(CA[2]), &res); + +// BOOST_TEST( res == std::inner_product(begin(CA[1]), begin(CA[2]), end(CA[1]), 0.0) ); + +// float const res2 = blas::dot(CA[1], CA[2]); +// BOOST_TEST( res == res2 ); +// } +// #endif + + BOOST_AUTO_TEST_CASE(multi_blas_dot_1d_real_double) { + multi::array const x = {1.0, 2.0, 3.0}; // NOLINT(readability-identifier-length) BLAS naming + multi::array const y = {1.0, 2.0, 3.0}; // NOLINT(readability-identifier-length) BLAS naming + + using blas::dot; + + BOOST_TEST( dot(x, y) == 14.0F ); + BOOST_TEST( 14.0 == dot(x, y) ); + } + + BOOST_AUTO_TEST_CASE(multi_blas_dot_1d_real_double_equal) { + multi::array const x = {1.0, 2.0, 3.0}; // NOLINT(readability-identifier-length) BLAS naming + multi::array const y = {1.0, 2.0, 3.0}; // NOLINT(readability-identifier-length) BLAS naming + + using blas::dot; + BOOST_TEST( dot(x, y) == dot(x, y) ); + } + +// #ifndef __APPLE__ +// BOOST_AUTO_TEST_CASE(multi_blas_dot_1d_real_float) { +// multi::array const x = {1.0F, 2.0F, 3.0F}; // NOLINT(readability-identifier-length) BLAS naming +// multi::array const y = {1.0F, 2.0F, 3.0F}; // NOLINT(readability-identifier-length) BLAS naming + +// using blas::dot; +// BOOST_TEST( 14.0F == dot(x, y) ); +// BOOST_TEST( 14.0F == +dot(x, y) ); +// BOOST_TEST( dot(x, y) == 14.0F ); +// } +// #endif + + BOOST_AUTO_TEST_CASE(multi_blas_dot_impl_real_double) { + multi::array const cA = { + {1.0, 2.0, 3.0, 4.0}, + {5.0, 6.0, 7.0, 8.0}, + {9.0, 10.0, 11.0, 12.0}, + }; + + double const res1 = blas::dot(cA[1], cA[2]); + BOOST_TEST( res1 == std::inner_product(begin(cA[1]), begin(cA[2]), end(cA[1]), 0.0) ); + + auto res2 = std::numeric_limits::quiet_NaN(); + blas::dot(cA[1], cA[2], res2); + BOOST_TEST( res2 == std::inner_product(begin(cA[1]), begin(cA[2]), end(cA[1]), 0.0) ); + + auto res_nan = std::numeric_limits::quiet_NaN(); + double const res3 = blas::dot(cA[1], cA[2], res_nan); + BOOST_TEST( res3 == res2 ); + + double const res4 = blas::dot(cA[1], cA[2]); + BOOST_TEST( res4 == std::inner_product(begin(cA[1]), begin(cA[2]), end(cA[1]), 0.0) ); + BOOST_TEST( blas::dot(cA[1], cA[2]) == blas::dot(cA[2], cA[1]) ); + } + +// #ifndef __APPLE__ +// BOOST_AUTO_TEST_CASE(multi_blas_dot_impl_real_float) { +// multi::array const cA = { +// {1.0F, 2.0F, 3.0F, 4.0F}, +// {5.0F, 6.0F, 7.0F, 8.0F}, +// {9.0F, 10.0F, 11.0F, 12.0F}, +// }; + +// float const res1 = blas::dot(cA[1], cA[2]); +// BOOST_TEST( res1 == std::inner_product(begin(cA[1]), begin(cA[2]), end(cA[1]), 0.0F) ); + +// auto res2 = std::numeric_limits::quiet_NaN(); +// blas::dot(cA[1], cA[2], res2); +// BOOST_TEST( res2 == std::inner_product(begin(cA[1]), begin(cA[2]), end(cA[1]), 0.0F) ); + +// auto res_nan = std::numeric_limits::quiet_NaN(); +// float const res3 = blas::dot(cA[1], cA[2], res_nan); + +// BOOST_TEST( res3 == res2 ); + +// float const res4 = blas::dot(cA[1], cA[2]); +// BOOST_TEST( res4 == std::inner_product(begin(cA[1]), begin(cA[2]), end(cA[1]), 0.0F) ); +// BOOST_TEST( blas::dot(cA[1], cA[2]) == blas::dot(cA[2], cA[1]) ); +// } +// #endif + + BOOST_AUTO_TEST_CASE(inq_case) { + multi::array const x(multi::extensions_t<1>{multi::iextension{10}}, +1.0); // NOLINT(readability-identifier-length) BLAS naming + multi::array const y(multi::extensions_t<1>{multi::iextension{10}}, -1.0); // NOLINT(readability-identifier-length) BLAS naming + + using blas::conj; + using blas::dot; + using blas::hermitized; - complex C; - blas::dot(blas::C(A), B, C); - BOOST_REQUIRE( C == std::inner_product(begin(A), end(A), begin(B), complex{0.0, 0.0}, std::plus<>{}, [](auto& a, auto& b){ return conj(a) * b;}) ); -} -#endif - -BOOST_AUTO_TEST_CASE(multi_blas_dot_strided_double) { - multi::array const CA = { - {1.0, 2.0, 3.0, 4.0}, - {5.0, 6.0, 7.0, 8.0}, - {9.0, 10.0, 11.0, 12.0}, - }; - double res = std::numeric_limits::quiet_NaN(); - blas::dot_n(begin(CA[1]), size(CA[1]), begin(CA[2]), &res); - BOOST_REQUIRE( res == std::inner_product(begin(CA[1]), begin(CA[2]), end(CA[1]), 0.0) ); - - double const res2 = blas::dot(CA[1], CA[2]); - BOOST_REQUIRE( res == res2 ); -} + auto res = dot(x, y); + auto res2 = dot(hermitized(x), y); -BOOST_AUTO_TEST_CASE(multi_blas_dot_strided_float, *boost::unit_test::disabled()) { - multi::array const CA = { - {1.0F, 2.0F, 3.0F, 4.0F}, - {5.0F, 6.0F, 7.0F, 8.0F}, - {9.0F, 10.0F, 11.0F, 12.0F}, - }; - auto res = std::numeric_limits::quiet_NaN(); - blas::dot_n(begin(CA[1]), size(CA[1]), begin(CA[2]), &res); - BOOST_REQUIRE( res == std::inner_product(begin(CA[1]), begin(CA[2]), end(CA[1]), 0.0F) ); - - double const res2 = blas::dot(CA[1], CA[2]); - BOOST_REQUIRE( res == res2 ); -} - -BOOST_AUTO_TEST_CASE(multi_blas_dot_strided_context) { - multi::array const CA = { - {1.0, 2.0, 3.0, 4.0}, - {5.0, 6.0, 7.0, 8.0}, - {9.0, 10.0, 11.0, 12.0}, - }; - double res = std::numeric_limits::quiet_NaN(); - blas::context ctxt; - blas::dot_n(&ctxt, begin(CA[1]), size(CA[1]), begin(CA[2]), &res); - BOOST_REQUIRE( res == std::inner_product(begin(CA[1]), begin(CA[2]), end(CA[1]), 0.0) ); - - double const res2 = blas::dot(CA[1], CA[2]); - BOOST_REQUIRE( res == res2 ); -} + BOOST_TEST(+res == +res2); -BOOST_AUTO_TEST_CASE(multi_blas_dot_strided_context_float, *boost::unit_test::disabled()) { - multi::array const CA = { - {1.0F, 2.0F, 3.0F, 4.0F}, - {5.0F, 6.0F, 7.0F, 8.0F}, - {9.0F, 10.0F, 11.0F, 12.0F}, - }; - float res = std::numeric_limits::quiet_NaN(); + auto res3 = dot(blas::conj(x), y); // conjugation doesn't do anything for real array + BOOST_TEST(res3 == res); + + auto d_arr = dot(blas::C(x), y); + BOOST_TEST(d_arr == res); + + static_assert(!std::is_same_v); + + using blas::C; + double const d_doub = dot(C(x), y); + + BOOST_TEST( d_doub == d_arr ); + } + + BOOST_AUTO_TEST_CASE(multi_blas_dot_impl_complex_double) { + namespace blas = multi::blas; + + using complex = std::complex; + + complex const I{0.0, 1.0}; // NOLINT(readability-identifier-length) imag unit + + // NOLINTNEXTLINE(readability-identifier-length) BLAS naming + multi::array const A = { + { 1.0 + I, 2.0 + 3.0 * I, 3.0 + 2.0 * I, 4.0 - 9.0 * I}, + {5.0 + 2.0 * I, 6.0 + 6.0 * I, 7.0 + 2.0 * I, 8.0 - 3.0 * I}, + {9.0 + 1.0 * I, 10.0 + 9.0 * I, 11.0 + 1.0 * I, 12.0 + 2.0 * I}, + }; + + auto c1 = complex{0.0, 0.0}; + blas::dot(A[1], A[2], c1); + BOOST_TEST( c1 == std::inner_product(begin(A[1]), end(A[1]), begin(A[2]), complex{0.0, 0.0}) ); + + auto const c2 = +blas::dot(A[1], A[2]); + BOOST_TEST( c2 == std::inner_product(begin(A[1]), end(A[1]), begin(A[2]), complex{0.0, 0.0}) ); + + complex const c3 = blas::dot(A[1], A[2]); + BOOST_TEST( c3 == std::inner_product(begin(A[1]), end(A[1]), begin(A[2]), complex{0.0, 0.0}) ); + + complex const c4 = blas::dot(A[1], blas::C(A[2])); + BOOST_TEST( + c4 == std::inner_product(begin(A[1]), end(A[1]), begin(A[2]), complex{0.0, 0.0}, std::plus<>{}, [](auto alpha, auto omega) { + return alpha * conj(omega);}) + ); - blas::context ctxt; - blas::dot_n(&ctxt, begin(CA[1]), size(CA[1]), begin(CA[2]), &res); + complex const c5 = blas::dot(blas::C(A[1]), A[2]); + BOOST_TEST( + c5 == inner_product(begin(A[1]), end(A[1]), begin(A[2]), complex{0.0, 0.0}, std::plus<>{}, [](auto alpha, auto omega) { + return conj(alpha) * omega;}) + ); + + complex const c6 = blas::dot(blas::conj(A[1]), A[2]); + BOOST_TEST( + c6 + == inner_product( + begin(A[1]), end(A[1]), begin(A[2]), complex{0.0, 0.0}, std::plus<>{}, + [](auto alpha, auto omega) { return conj(alpha) * omega; } + ) + ); + + complex const c7 = blas::dot(blas::C(A[1]), A[2]); + BOOST_TEST( + c7 + == std::inner_product( + begin(A[1]), end(A[1]), begin(A[2]), complex{0.0, 0.0}, std::plus<>{}, + [](auto alpha, auto omega) { return conj(alpha) * omega; } + ) + ); + } - BOOST_REQUIRE( res == std::inner_product(begin(CA[1]), begin(CA[2]), end(CA[1]), 0.0) ); + BOOST_AUTO_TEST_CASE(multi_blas_dot_impl_complex_float) { + namespace blas = multi::blas; - float const res2 = blas::dot(CA[1], CA[2]); - BOOST_REQUIRE( res == res2 ); -} - -BOOST_AUTO_TEST_CASE(multi_blas_dot_1d_real_double) { - multi::array const x = {1.0, 2.0, 3.0}; // NOLINT(readability-identifier-length) BLAS naming - multi::array const y = {1.0, 2.0, 3.0}; // NOLINT(readability-identifier-length) BLAS naming - - using blas::dot; - BOOST_TEST( 14.0 == dot(x, y) ); - BOOST_TEST( dot(x, y) == 14.0F ); -} - -BOOST_AUTO_TEST_CASE(multi_blas_dot_1d_real_float, *boost::unit_test::disabled()) { - multi::array const x = {1.0F, 2.0F, 3.0F}; // NOLINT(readability-identifier-length) BLAS naming - multi::array const y = {1.0F, 2.0F, 3.0F}; // NOLINT(readability-identifier-length) BLAS naming - - using blas::dot; - BOOST_TEST( 14.0F == dot(x, y) ); - BOOST_TEST( dot(x, y) == 14.0F ); -} - -BOOST_AUTO_TEST_CASE(multi_blas_dot_impl_real_double) { - multi::array const cA = { - {1.0, 2.0, 3.0, 4.0}, - {5.0, 6.0, 7.0, 8.0}, - {9.0, 10.0, 11.0, 12.0}, - }; - - double const res1 = blas::dot(cA[1], cA[2]); - BOOST_REQUIRE( res1 == std::inner_product(begin(cA[1]), begin(cA[2]), end(cA[1]), 0.0) ); - - double res2 = NAN; - blas::dot(cA[1], cA[2], res2); - BOOST_REQUIRE( res2 == std::inner_product(begin(cA[1]), begin(cA[2]), end(cA[1]), 0.0) ); - - double res_nan = NAN; - double const res3 = blas::dot(cA[1], cA[2], res_nan); - BOOST_REQUIRE( res3 == res2 ); - - double const res4 = blas::dot(cA[1], cA[2]); - BOOST_REQUIRE( res4 == std::inner_product(begin(cA[1]), begin(cA[2]), end(cA[1]), 0.0) ); - BOOST_REQUIRE( blas::dot(cA[1], cA[2]) == blas::dot(cA[2], cA[1]) ); -} + using complex = std::complex; + + complex const I{0.0, 1.0}; // NOLINT(readability-identifier-length) imag unit -BOOST_AUTO_TEST_CASE(multi_blas_dot_impl_real_float, *boost::unit_test::disabled()) { - multi::array const cA = { - {1.0F, 2.0F, 3.0F, 4.0F}, - {5.0F, 6.0F, 7.0F, 8.0F}, - {9.0F, 10.0F, 11.0F, 12.0F}, - }; - - float const res1 = blas::dot(cA[1], cA[2]); - BOOST_REQUIRE( res1 == std::inner_product(begin(cA[1]), begin(cA[2]), end(cA[1]), 0.0F) ); - - float res2 = NAN; - blas::dot(cA[1], cA[2], res2); - BOOST_REQUIRE( res2 == std::inner_product(begin(cA[1]), begin(cA[2]), end(cA[1]), 0.0F) ); - - float res_nan = NAN; - float const res3 = blas::dot(cA[1], cA[2], res_nan); - - BOOST_REQUIRE( res3 == res2 ); - - float const res4 = blas::dot(cA[1], cA[2]); - BOOST_REQUIRE( res4 == std::inner_product(begin(cA[1]), begin(cA[2]), end(cA[1]), 0.0F) ); - BOOST_REQUIRE( blas::dot(cA[1], cA[2]) == blas::dot(cA[2], cA[1]) ); -} - -BOOST_AUTO_TEST_CASE(inq_case) { - multi::array const x(multi::extensions_t<1>{multi::iextension{10}}, +1.0); // NOLINT(readability-identifier-length) BLAS naming - multi::array const y(multi::extensions_t<1>{multi::iextension{10}}, -1.0); // NOLINT(readability-identifier-length) BLAS naming - - using blas::conj; - using blas::dot; - using blas::hermitized; - - auto res = dot(x, y); - auto res2 = dot(hermitized(x), y); - - BOOST_REQUIRE(res == res2); - - auto res3 = dot(blas::conj(x), y); // conjugation doesn't do anything for real array - BOOST_REQUIRE(res3 == res); - - auto d_arr = dot(blas::C(x), y); - BOOST_REQUIRE(d_arr == res); - - static_assert(!std::is_same{}); - - using blas::C; - double const d_doub = dot(C(x), y); - - BOOST_REQUIRE( d_doub == d_arr ); -} - -BOOST_AUTO_TEST_CASE(multi_blas_dot_impl_complex_double) { - namespace blas = multi::blas; - - using complex = std::complex; - - complex const I{0.0, 1.0}; // NOLINT(readability-identifier-length) imag unit - - // NOLINTNEXTLINE(readability-identifier-length) BLAS naming - multi::array const A = { - { 1.0 + I, 2.0 + 3.0 * I, 3.0 + 2.0 * I, 4.0 - 9.0 * I}, - {5.0 + 2.0 * I, 6.0 + 6.0 * I, 7.0 + 2.0 * I, 8.0 - 3.0 * I}, - {9.0 + 1.0 * I, 10.0 + 9.0 * I, 11.0 + 1.0 * I, 12.0 + 2.0 * I}, - }; - - auto c1 = complex{0.0, 0.0}; - blas::dot(A[1], A[2], c1); - BOOST_TEST_REQUIRE( c1 == std::inner_product(begin(A[1]), end(A[1]), begin(A[2]), complex{0.0, 0.0}) ); - - auto const c2 = +blas::dot(A[1], A[2]); - BOOST_TEST_REQUIRE( c2 == std::inner_product(begin(A[1]), end(A[1]), begin(A[2]), complex{0.0, 0.0}) ); - - complex const c3 = blas::dot(A[1], A[2]); - BOOST_TEST_REQUIRE( c3 == std::inner_product(begin(A[1]), end(A[1]), begin(A[2]), complex{0.0, 0.0}) ); - - complex const c4 = blas::dot(A[1], blas::C(A[2])); - BOOST_TEST_REQUIRE( c4 == std::inner_product(begin(A[1]), end(A[1]), begin(A[2]), complex{0.0, 0.0}, std::plus<>{}, [](auto alpha, auto omega) { return alpha * conj(omega);}) ); - - complex const c5 = blas::dot(blas::C(A[1]), A[2]); - BOOST_TEST_REQUIRE( c5 == inner_product(begin(A[1]), end(A[1]), begin(A[2]), complex{0.0, 0.0}, std::plus<>{}, [](auto alpha, auto omega) { return conj(alpha) * omega;}) ); - - complex const c6 = blas::dot(blas::conj(A[1]), A[2]); - BOOST_TEST_REQUIRE( c6 == inner_product(begin(A[1]), end(A[1]), begin(A[2]), complex{0.0, 0.0}, std::plus<>{}, [](auto alpha, auto omega) { return conj(alpha) * omega;}) ); - - complex const c7 = blas::dot(blas::C(A[1]), A[2]); - BOOST_TEST_REQUIRE( c7 == std::inner_product(begin(A[1]), end(A[1]), begin(A[2]), complex{0.0, 0.0}, std::plus<>{}, [](auto alpha, auto omega) { return conj(alpha) * omega;}) ); -} - -BOOST_AUTO_TEST_CASE(multi_blas_dot_impl_complex_float) { - namespace blas = multi::blas; - - using complex = std::complex; - - complex const I{0.0, 1.0}; // NOLINT(readability-identifier-length) imag unit - - // NOLINTNEXTLINE(readability-identifier-length) BLAS naming - multi::array const A = { - {1.0F + 1.0F * I, 2.0F + 3.0F * I, 3.0F + 2.0F * I, 4.0F - 9.0F * I}, - {5.0F + 2.0F * I, 6.0F + 6.0F * I, 7.0F + 2.0F * I, 8.0F - 3.0F * I}, - {9.0F + 1.0F * I, 10.0F + 9.0F * I, 11.0F + 1.0F * I, 12.0F + 2.0F * I}, - }; - - auto c1 = complex{0.0F, 0.0F}; - blas::dot(A[1], A[2], c1); - BOOST_TEST_REQUIRE( c1 == std::inner_product(begin(A[1]), end(A[1]), begin(A[2]), complex{0.0F, 0.0F}) ); - - auto const c2 = +blas::dot(A[1], A[2]); - BOOST_TEST_REQUIRE( c2 == std::inner_product(begin(A[1]), end(A[1]), begin(A[2]), complex{0.0F, 0.0F}) ); - - complex const c3 = blas::dot(A[1], A[2]); - BOOST_TEST_REQUIRE( c3 == std::inner_product(begin(A[1]), end(A[1]), begin(A[2]), complex{0.0F, 0.0F}) ); - - complex const c4 = blas::dot(A[1], blas::C(A[2])); - BOOST_TEST_REQUIRE( c4 == std::inner_product(begin(A[1]), end(A[1]), begin(A[2]), complex{0.0F, 0.0F}, std::plus<>{}, [](auto alpha, auto omega) { return alpha * conj(omega);}) ); - - complex const c5 = blas::dot(blas::C(A[1]), A[2]); - BOOST_TEST_REQUIRE( c5 == inner_product(begin(A[1]), end(A[1]), begin(A[2]), complex{0.0F, 0.0F}, std::plus<>{}, [](auto alpha, auto omega) { return conj(alpha) * omega;}) ); - - complex const c6 = blas::dot(blas::conj(A[1]), A[2]); - BOOST_TEST_REQUIRE( c6 == inner_product(begin(A[1]), end(A[1]), begin(A[2]), complex{0.0F, 0.0F}, std::plus<>{}, [](auto alpha, auto omega) { return conj(alpha) * omega;}) ); - - complex const c7 = blas::dot(blas::C(A[1]), A[2]); - BOOST_TEST_REQUIRE( c7 == std::inner_product(begin(A[1]), end(A[1]), begin(A[2]), complex{0.0F, 0.0F}, std::plus<>{}, [](auto alpha, auto omega) { return conj(alpha) * omega;}) ); -} - -BOOST_AUTO_TEST_CASE(cublas_one_gemm_complex_conj_second_double) { - namespace blas = multi::blas; - - using complex = std::complex; - using Alloc = std::allocator; // thrust::cuda::allocator; - - auto const I = complex{0.0, 1.0}; // NOLINT(readability-identifier-length) - - // NOLINTNEXTLINE(readability-identifier-length) BLAS naming - multi::array const A = { - {1.0 - 2.0 * I, 9.0 - 1.0 * I}, - {2.0 + 3.0 * I, 1.0 - 2.0 * I}, - }; - - // NOLINTNEXTLINE(readability-identifier-length) BLAS naming - multi::array const B = { - {3.0 - 4.0 * I, 19.0 - 1.0 * I}, - {1.0 + 5.0 * I, 8.0 - 8.0 * I}, - }; - - multi::array C({2, 2}, {3.0, 0.0}); // NOLINT(readability-identifier-length) conventional BLAS naming + // NOLINTNEXTLINE(readability-identifier-length) BLAS naming + multi::array const A = { + {1.0F + 1.0F * I, 2.0F + 3.0F * I, 3.0F + 2.0F * I, 4.0F - 9.0F * I}, + {5.0F + 2.0F * I, 6.0F + 6.0F * I, 7.0F + 2.0F * I, 8.0F - 3.0F * I}, + {9.0F + 1.0F * I, 10.0F + 9.0F * I, 11.0F + 1.0F * I, 12.0F + 2.0F * I}, + }; + + auto c1 = complex{0.0F, 0.0F}; + blas::dot(A[1], A[2], c1); + BOOST_TEST( c1 == std::inner_product(begin(A[1]), end(A[1]), begin(A[2]), complex{0.0F, 0.0F}) ); + + auto const c2 = +blas::dot(A[1], A[2]); + BOOST_TEST( c2 == std::inner_product(begin(A[1]), end(A[1]), begin(A[2]), complex{0.0F, 0.0F}) ); + + complex const c3 = blas::dot(A[1], A[2]); + BOOST_TEST( c3 == std::inner_product(begin(A[1]), end(A[1]), begin(A[2]), complex{0.0F, 0.0F}) ); + + complex const c4 = blas::dot(A[1], blas::C(A[2])); + + BOOST_TEST( + c4 + == std::inner_product(A[1].begin(), A[1].end(), A[2].begin(), complex{0.0F, 0.0F}, std::plus<>{}, [](auto al, auto om) { return al * conj(om); }) + ); + + complex const c5 = blas::dot(blas::C(A[1]), A[2]); + BOOST_TEST( + c5 + == std::inner_product(A[1].begin(), A[1].end(), A[2].begin(), complex{0.0F, 0.0F}, std::plus<>{}, [](auto al, auto om) { return conj(al) * om; }) + ); + + complex const c6 = blas::dot(blas::conj(A[1]), A[2]); + BOOST_TEST( + c6 + == std::inner_product(A[1].begin(), A[1].end(), A[2].begin(), complex{0.0F, 0.0F}, std::plus<>{}, [](auto al, auto om) { return conj(al) * om; }) + ); + + complex const c7 = blas::dot(blas::C(A[1]), A[2]); + BOOST_TEST( + c7 + == std::inner_product(A[1].begin(), A[1].end(), A[2].begin(), complex{0.0F, 0.0F}, std::plus<>{}, [](auto al, auto om) { return conj(al) * om; }) + ); + } + + BOOST_AUTO_TEST_CASE(cublas_one_gemm_complex_conj_second_double) { + namespace blas = multi::blas; + + using complex = std::complex; + using Alloc = std::allocator; // thrust::cuda::allocator; + + auto const I = complex{0.0, 1.0}; // NOLINT(readability-identifier-length) + + // NOLINTNEXTLINE(readability-identifier-length) BLAS naming + multi::array const A = { + {1.0 - 2.0 * I, 9.0 - 1.0 * I}, + {2.0 + 3.0 * I, 1.0 - 2.0 * I}, + }; + + // NOLINTNEXTLINE(readability-identifier-length) BLAS naming + multi::array const B = { + {3.0 - 4.0 * I, 19.0 - 1.0 * I}, + {1.0 + 5.0 * I, 8.0 - 8.0 * I}, + }; + + multi::array C({2, 2}, {3.0, 0.0}); // NOLINT(readability-identifier-length) conventional BLAS naming + + auto CC = C; + + auto const [is, js] = C.extensions(); + std::for_each(is.begin(), is.end(), [&, js = js](auto ii) { + std::for_each(js.begin(), js.end(), [&](auto jj) { + C[ii][jj] *= 0.0; + std::for_each(B.extension().begin(), B.extension().end(), [&](auto kk) { + C[ii][jj] += A[ii][kk] * conj(B[kk][jj]); + }); + }); + }); - auto CC = C; + // TODO(correaa) MKL gives an error here + // unknown location(0): fatal error: in "cublas_one_gemv_complex_conjtrans_zero": memory access violation at address: 0x00000007: no mapping at fault address - auto const [is, js] = C.extensions(); - std::for_each(is.begin(), is.end(), [&, js = js](auto ii) { - std::for_each(js.begin(), js.end(), [&](auto jj) { - C[ii][jj] *= 0.0; - std::for_each(B.extension().begin(), B.extension().end(), [&](auto kk) { - C[ii][jj] += A[ii][kk] * conj(B[kk][jj]); - }); + std::transform(begin(A), end(A), begin(CC), begin(CC), [BT = B.transposed()](auto const& Ar, auto&& Cr) { + return std::transform( + begin(BT), end(BT), begin(Cr), begin(Cr), [&Ar](auto const& Bc, auto const& Ce) { + return std::complex{1.0, 0.0} * blas::dot(Ar, blas::C(Bc)) + 0.0 * Ce; + } + ), + std::forward(Cr); }); - }); - // TODO(correaa) MKL gives an error here - // unknown location(0): fatal error: in "cublas_one_gemv_complex_conjtrans_zero": memory access violation at address: 0x00000007: no mapping at fault address + BOOST_TEST( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); + BOOST_TEST( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); - std::transform(begin(A), end(A), begin(CC), begin(CC), [BT = transposed(B)](auto const& Ar, auto&& Cr) { - return std::transform( - begin(BT), end(BT), begin(Cr), begin(Cr), [&Ar](auto const& Bc, auto const& Ce) { - return std::complex{1.0, 0.0} * blas::dot(Ar, blas::C(Bc)) + 0.0 * Ce; - } - ), - std::forward(Cr); - }); + BOOST_TEST( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); + BOOST_TEST( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); + } - BOOST_TEST_REQUIRE( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); - BOOST_TEST_REQUIRE( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); + // BOOST_AUTO_TEST_CASE(cublas_one_gemm_complex_conj_second_float) { + // namespace blas = multi::blas; - BOOST_TEST_REQUIRE( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); - BOOST_TEST_REQUIRE( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); -} + // using complex = std::complex; + // using Alloc = std::allocator; // thrust::cuda::allocator; -BOOST_AUTO_TEST_CASE(cublas_one_gemm_complex_conj_second_float) { - namespace blas = multi::blas; + // auto const I = complex{0.0F, 1.0F}; // NOLINT(readability-identifier-length) - using complex = std::complex; - using Alloc = std::allocator; // thrust::cuda::allocator; + // // NOLINTNEXTLINE(readability-identifier-length) BLAS naming + // multi::array const A = { + // {1.0F - 2.0F * I, 9.0F - 1.0F * I}, + // {2.0F + 3.0F * I, 1.0F - 2.0F * I}, + // }; - auto const I = complex{0.0F, 1.0F}; // NOLINT(readability-identifier-length) + // // NOLINTNEXTLINE(readability-identifier-length) BLAS naming + // multi::array const B = { + // {3.0F - 4.0F * I, 19.0F - 1.0F * I}, + // {1.0F + 5.0F * I, 8.0F - 8.0F * I}, + // }; - // NOLINTNEXTLINE(readability-identifier-length) BLAS naming - multi::array const A = { - {1.0F - 2.0F * I, 9.0F - 1.0F * I}, - {2.0F + 3.0F * I, 1.0F - 2.0F * I}, - }; + // multi::array C({2, 2}, {3.0F, 0.0F}); // NOLINT(readability-identifier-length) conventional BLAS naming - // NOLINTNEXTLINE(readability-identifier-length) BLAS naming - multi::array const B = { - {3.0F - 4.0F * I, 19.0F - 1.0F * I}, - {1.0F + 5.0F * I, 8.0F - 8.0F * I}, - }; + // auto CC = C; - multi::array C({2, 2}, {3.0F, 0.0F}); // NOLINT(readability-identifier-length) conventional BLAS naming + // auto const [is, js] = C.extensions(); + // std::for_each(is.begin(), is.end(), [&, js = js](auto ii) { + // std::for_each(js.begin(), js.end(), [&](auto jj) { + // C[ii][jj] *= 0.0F; + // std::for_each(B.extension().begin(), B.extension().end(), [&](auto kk) { + // C[ii][jj] += A[ii][kk] * conj(B[kk][jj]); + // }); + // }); + // }); - auto CC = C; + // // TODO(correaa) MKL gives an error here + // // unknown location(0): fatal error: in "cublas_one_gemv_complex_conjtrans_zero": + // // memory access violation at address: 0x00000007: no mapping at fault address - auto const [is, js] = C.extensions(); - std::for_each(is.begin(), is.end(), [&, js = js](auto ii) { - std::for_each(js.begin(), js.end(), [&](auto jj) { - C[ii][jj] *= 0.0F; - std::for_each(B.extension().begin(), B.extension().end(), [&](auto kk) { - C[ii][jj] += A[ii][kk] * conj(B[kk][jj]); - }); - }); - }); + // std::transform(begin(A), end(A), begin(CC), begin(CC), [BT = B.transposed()](auto const& Ar, auto&& Cr) { + // std::transform( + // begin(BT), end(BT), begin(Cr), begin(Cr), + // [&Ar](auto const& Bc, auto const& Ce) { return complex{1.0F, 0.0F} * blas::dot(Ar, blas::C(Bc)) + 0.0F * Ce; } + // ); + // return std::forward(Cr); + // }); + + // std::cerr << "CC[1][0] = " << static_cast(CC[1][0]) << '\n'; + // std::cerr << "C [1][0] = " << static_cast(C [1][0]) << '\n'; - // TODO(correaa) MKL gives an error here - // unknown location(0): fatal error: in "cublas_one_gemv_complex_conjtrans_zero": memory access violation at address: 0x00000007: no mapping at fault address + // BOOST_TEST( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); + // BOOST_TEST( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); - std::transform(begin(A), end(A), begin(CC), begin(CC), [BT = transposed(B)](auto const& Ar, auto&& Cr) { - return std::transform( - begin(BT), end(BT), begin(Cr), begin(Cr), [&Ar](auto const& Bc, auto const& Ce) { - return complex{1.0F, 0.0F} * blas::dot(Ar, blas::C(Bc)) + 0.0F * Ce; - } - ), - std::forward(Cr); - }); + // std::cerr << "CC[0][1] = " << static_cast(CC[0][1]) << '\n'; + // std::cerr << "C [0][1] = " << static_cast(C [0][1]) << '\n'; - BOOST_TEST_REQUIRE( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); - BOOST_TEST_REQUIRE( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); + // BOOST_TEST( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); + // BOOST_TEST( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); + // } - BOOST_TEST_REQUIRE( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); - BOOST_TEST_REQUIRE( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); + return boost::report_errors(); } diff --git a/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/test/gemm.cpp b/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/test/gemm.cpp index b200c7abbd..9d9d0aba98 100644 --- a/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/test/gemm.cpp +++ b/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/test/gemm.cpp @@ -2,1920 +2,1962 @@ // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt -#include +#include -#include "../../../adaptors/blas/gemm.hpp" -#include "../../../adaptors/blas/operations.hpp" +#include // for context +#include // for gemm, gemm_range +// IWYU pragma: no_include "boost/multi/adaptors/blas/numeric.hpp" // for involuter, conju... +#include // for H, T, (anonymous) -#include +#include // for layout_t, array -#include +#include // for abs // IWYU pragma: keep +#include // for complex, operator* +#include // for begin, size +// IWYU pragma: no_include namespace multi = boost::multi; namespace blas = multi::blas; -BOOST_AUTO_TEST_CASE(adaptor_blas_double_100x1_1x1_T_sub) { - namespace blas = multi::blas; +#define BOOST_AUTO_TEST_CASE(CasenamE) /**/ +#define BOOST_REQUIRE_CLOSE(X, Y, ToL) BOOST_TEST( std::abs( (X) - (Y) ) < (ToL) ) +// #define BOOST_REQUIRE_SMALL(X, ToL) BOOST_TEST( std::abs( X ) < (ToL) ) - multi::array A({100, 4}, 1.0); // NOLINT(readability-identifier-length) BLAS naming - multi::array B({4, 4}, 1.0); // NOLINT(readability-identifier-length) BLAS naming +auto main() -> int { // NOLINT(readability-function-cognitive-complexity,bugprone-exception-escape) + BOOST_AUTO_TEST_CASE(adaptor_blas_double_100x1_1x1_T_sub) { + namespace blas = multi::blas; - multi::array C({100, 1}, 0.0); // NOLINT(readability-identifier-length) BLAS naming + multi::array A({100, 4}, 1.0); // NOLINT(readability-identifier-length) BLAS naming + multi::array B({4, 4}, 1.0); // NOLINT(readability-identifier-length) BLAS naming - blas::gemm(1.0, A({0, 100}, {1, 2}), blas::T(B)({0, 1}, {0, 1}), 0.0, C); // c=ab, c⸆=b⸆a⸆ - BOOST_REQUIRE(C[99][0] == 1.0); -} + multi::array C({100, 1}, 0.0); // NOLINT(readability-identifier-length) BLAS naming -BOOST_AUTO_TEST_CASE(adaptor_blas_double_100x1_1x1_H_sub) { - multi::array A({100, 4}, 1.0); // NOLINT(readability-identifier-length) BLAS naming - multi::array B({4, 4}, 1.0); // NOLINT(readability-identifier-length) BLAS naming + blas::gemm(1.0, A({0, 100}, {1, 2}), blas::T(B)({0, 1}, {0, 1}), 0.0, C); // c=ab, c⸆=b⸆a⸆ + BOOST_TEST(C[99][0] == 1.0); + } + + BOOST_AUTO_TEST_CASE(adaptor_blas_double_100x1_1x1_H_sub) { + multi::array A({100, 4}, 1.0); // NOLINT(readability-identifier-length) BLAS naming + multi::array B({4, 4}, 1.0); // NOLINT(readability-identifier-length) BLAS naming + + multi::array C({100, 1}, 0.0); // NOLINT(readability-identifier-length) BLAS naming + + blas::gemm(1., A({0, 100}, {1, 2}), blas::H(B)({0, 1}, {0, 1}), 0.0, C); // c=ab, c⸆=b⸆a⸆ + BOOST_TEST(C[99][0] == 1.0); + } + + BOOST_AUTO_TEST_CASE(adaptor_blas_double_100x1_1x1_H_sub_6) { + multi::array A({100, 4}, 2.0); // NOLINT(readability-identifier-length) BLAS naming + multi::array B({4, 4}, 3.0); // NOLINT(readability-identifier-length) BLAS naming + + multi::array C({100, 1}, 0.0); // NOLINT(readability-identifier-length) BLAS naming + + blas::gemm(1., A({0, 100}, {1, 2}), blas::H(B)({0, 1}, {0, 1}), 0.0, C); // c=ab, c⸆=b⸆a⸆ + BOOST_TEST(C[99][0] == 6.0); + } + + BOOST_AUTO_TEST_CASE(adaptor_blas_double_100x1_1x1_H_copy) { + multi::array A({100, 4}, 1.0); // NOLINT(readability-identifier-length) BLAS naming + multi::array B({4, 4}, 1.0); // NOLINT(readability-identifier-length) BLAS naming + + auto C = +blas::gemm(1., A({0, 100}, {1, 2}), blas::H(B)({2, 3}, {2, 3})); // c=ab, c⸆=b⸆a⸆ // NOLINT(readability-identifier-length) BLAS naming + BOOST_TEST(C[99][0] == 1.0); + } + + BOOST_AUTO_TEST_CASE(adaptor_blas_complex_100x1_1x1) { + using complex = std::complex; + multi::array const A({100, 1}, {1.0, 0.0}); // NOLINT(readability-identifier-length) BLAS naming + multi::array const B({1, 1}, {1.0, 0.0}); // NOLINT(readability-identifier-length) BLAS naming + + multi::array C({100, 1}, {0.0, 0.0}); // NOLINT(readability-identifier-length) BLAS naming + + blas::gemm({1.0, 0.0}, A, B, {0.0, 0.0}, C); // c=ab, c⸆=b⸆a⸆ + BOOST_TEST(C[99][0] == 1.0); + } + + BOOST_AUTO_TEST_CASE(adaptor_blas_complex_100x1_1x1_T) { + using complex = std::complex; + multi::array const A({100, 1}, complex{1.0, 0.0}); // NOLINT(readability-identifier-length) BLAS naming + multi::array const B({1, 1}, complex{1.0, 0.0}); // NOLINT(readability-identifier-length) BLAS naming + + multi::array C({100, 1}, complex{0.0, 0.0}); // NOLINT(readability-identifier-length) BLAS naming + + blas::gemm(complex{1.0, 0.0}, A, blas::T(B), complex{0.0, 0.0}, C); // c=ab, c⸆=b⸆a⸆ + BOOST_TEST( C[99][0] == 1.0 ); + } + + BOOST_AUTO_TEST_CASE(adaptor_blas_complex_100x1_1x1_H) { + using complex = std::complex; // complex const I{0, 1}; + multi::array const A({100, 1}, {1.0, 0.0}); // NOLINT(readability-identifier-length) BLAS naming + multi::array const B({1, 1}, {1.0, 0.0}); // NOLINT(readability-identifier-length) BLAS naming + + multi::array C({100, 1}, {0.0, 0.0}); // NOLINT(readability-identifier-length) BLAS naming - multi::array C({100, 1}, 0.0); // NOLINT(readability-identifier-length) BLAS naming + blas::gemm({1.0, 0.0}, A, blas::H(B), {0.0, 0.0}, C); // c=ab, c⸆=b⸆a⸆ + BOOST_TEST( C[99][0] == 1.0 ); + } + + BOOST_AUTO_TEST_CASE(adaptor_blas_double_100x1_1x1) { + using complex = std::complex; + multi::array const A({100, 1}, {1.0, 0.0}); // NOLINT(readability-identifier-length) BLAS naming + multi::array const B({1, 1}, {1.0, 0.0}); // NOLINT(readability-identifier-length) BLAS naming + + multi::array C({100, 1}, {0.0, 0.0}); // NOLINT(readability-identifier-length) BLAS naming - blas::gemm(1., A({0, 100}, {1, 2}), blas::H(B)({0, 1}, {0, 1}), 0.0, C); // c=ab, c⸆=b⸆a⸆ - BOOST_REQUIRE(C[99][0] == 1.0); -} + blas::gemm({1.0, 0.0}, A, B, {0.0, 0.0}, C); // c=ab, c⸆=b⸆a⸆ + BOOST_TEST(C[99][0] == 1.0); + } -BOOST_AUTO_TEST_CASE(adaptor_blas_double_100x1_1x1_H_sub_6) { - multi::array A({100, 4}, 2.0); // NOLINT(readability-identifier-length) BLAS naming - multi::array B({4, 4}, 3.0); // NOLINT(readability-identifier-length) BLAS naming + BOOST_AUTO_TEST_CASE(adaptor_blas_double_100x1_1x1_T) { + multi::array const A({100, 1}, 1.0); // NOLINT(readability-identifier-length) BLAS naming + multi::array const B({1, 1}, 1.0); // NOLINT(readability-identifier-length) BLAS naming - multi::array C({100, 1}, 0.0); // NOLINT(readability-identifier-length) BLAS naming + multi::array C({100, 1}, 0.0); // NOLINT(readability-identifier-length) BLAS naming - blas::gemm(1., A({0, 100}, {1, 2}), blas::H(B)({0, 1}, {0, 1}), 0.0, C); // c=ab, c⸆=b⸆a⸆ - BOOST_REQUIRE(C[99][0] == 6.0); -} + blas::gemm(1.0, A, blas::T(B), 0.0, C); // c=ab, c⸆=b⸆a⸆ + BOOST_TEST(C[99][0] == 1.0); + } -BOOST_AUTO_TEST_CASE(adaptor_blas_double_100x1_1x1_H_copy) { - multi::array A({100, 4}, 1.0); // NOLINT(readability-identifier-length) BLAS naming - multi::array B({4, 4}, 1.0); // NOLINT(readability-identifier-length) BLAS naming + BOOST_AUTO_TEST_CASE(adaptor_blas_double_100x1_1x1_H) { + multi::array const A({100, 1}, 1.0); // NOLINT(readability-identifier-length) BLAS naming + multi::array const B({1, 1}, 1.0); // NOLINT(readability-identifier-length) BLAS naming - auto C = +blas::gemm(1., A({0, 100}, {1, 2}), blas::H(B)({2, 3}, {2, 3})); // c=ab, c⸆=b⸆a⸆ // NOLINT(readability-identifier-length) BLAS naming - BOOST_REQUIRE(C[99][0] == 1.0); -} + multi::array C({100, 1}, 0.0); // NOLINT(readability-identifier-length) BLAS naming -BOOST_AUTO_TEST_CASE(adaptor_blas_complex_100x1_1x1) { - using complex = std::complex; - multi::array const A({100, 1}, {1.0, 0.0}); // NOLINT(readability-identifier-length) BLAS naming - multi::array const B({1, 1}, {1.0, 0.0}); // NOLINT(readability-identifier-length) BLAS naming + blas::gemm(1.0, A, blas::H(B), 0.0, C); // c=ab, c⸆=b⸆a⸆ + BOOST_TEST(C[99][0] == 1.0); + } + + BOOST_AUTO_TEST_CASE(multi_blas_gemm_square_real) { + // NOLINTNEXTLINE(readability-identifier-length) BLAS naming + multi::array const a = { + {1.0, 3.0, 4.0}, + {9.0, 7.0, 1.0}, + {1.0, 2.0, 3.0}, + }; + // NOLINTNEXTLINE(readability-identifier-length) BLAS naming + multi::array const b = { + {11.0, 12.0, 4.0}, + { 7.0, 19.0, 1.0}, + {11.0, 12.0, 4.0}, + }; + { + multi::array c({size(a), size(~b)}, 9999.0); // NOLINT(readability-identifier-length) conventional BLAS naming + blas::gemm(1.0, a, b, 0.0, c); + BOOST_TEST( c[2][1] == 86.0 ); + } + { + multi::array c({size(a), size(~b)}, 9999.0); // NOLINT(readability-identifier-length) conventional BLAS naming + BOOST_TEST( size( a) == size( c) ); + BOOST_TEST( size(~b) == size(~c) ); + blas::gemm_n(1.0, begin(a), size(a), begin(b), 0.0, begin(c)); + BOOST_TEST( c[2][1] == 86.0 ); + } + { + multi::array c({size(a), size(~b)}, 9999.0); // NOLINT(readability-identifier-length) conventional BLAS naming + blas::gemm(1.0, a, blas::T(b), 0.0, c); + BOOST_TEST( c[2][1] == 48.0 ); + } + { + multi::array c({size(a), size(~b)}, 9999.0); // NOLINT(readability-identifier-length) conventional BLAS naming + blas::gemm_n(1., a.begin(), a.size(), blas::T(b).begin(), 0.0, c.begin()); + BOOST_TEST( c[2][1] == 48.0 ); + } + { + multi::array c({size(a), size(~b)}, 9999.0); // NOLINT(readability-identifier-length) conventional BLAS naming + blas::gemm(1.0, blas::T(a), b, 0.0, c); + BOOST_TEST( c[2][1] == 103.0 ); + } + { + multi::array c({size(a), size(~b)}, 9999.0); // NOLINT(readability-identifier-length) conventional BLAS naming + blas::gemm_n(1.0, begin(blas::T(a)), size(blas::T(a)), begin(b), 0.0, begin(c)); + BOOST_TEST( c[2][1] == 103.0 ); + } + { + multi::array c({size(a), size(~b)}, 9999.0); // NOLINT(readability-identifier-length) conventional BLAS naming + blas::gemm(1.0, blas::T(a), blas::T(b), 0.0, c); + BOOST_TEST( c[2][1] == 50.0 ); + } + { + multi::array c({size(a), size(~b)}, 9999.0); // NOLINT(readability-identifier-length) conventional BLAS naming + blas::gemm_n(1.0, begin(blas::T(a)), size(blas::T(a)), begin(blas::T(b)), 0.0, begin(c)); + BOOST_TEST( c[2][1] == 50.0 ); + } + { + multi::array c({size(a), size(~b)}, 9999.0); // NOLINT(readability-identifier-length) conventional BLAS naming + blas::gemm(1.0, a, blas::T(b), 0.0, c); + BOOST_TEST( c[2][1] == 48.0 ); + } + { + multi::array c({size(a), size(~b)}, 9999.0); // NOLINT(readability-identifier-length) conventional BLAS naming + blas::gemm_n(1.0, begin(a), size(a), begin(blas::T(b)), 0.0, begin(c)); + BOOST_TEST( c[2][1] == 48.0 ); + } + { + multi::array c({size(a), size(~b)}, 9999.0); // NOLINT(readability-identifier-length) conventional BLAS naming + blas::gemm(1.0, blas::T(a), b, 0.0, c); + BOOST_TEST( c[2][1] == 103.0 ); + } + { + multi::array c({size(a), size(~b)}, 9999.0); // NOLINT(readability-identifier-length) conventional BLAS naming + blas::gemm_n(1.0, begin(blas::T(a)), size(blas::T(a)), begin(b), 0.0, begin(c)); + BOOST_TEST( c[2][1] == 103.0 ); + } + { + multi::array c({a.size(), b.rotated().size()}, 9999.0); // NOLINT(readability-identifier-length) BLAS naming + blas::gemm(2.0, blas::H(a), blas::H(b), 0.0, c); + BOOST_TEST( c[2][1] == 100.0 ); + } + { + multi::array c = blas::gemm(2.0, blas::H(a), blas::H(b)); // NOLINT(readability-identifier-length) BLAS naming + BOOST_TEST( c[2][1] == 100.0 ); + } + { + multi::array const c = blas::gemm(2.0, blas::H(a), blas::H(b)); // NOLINT(readability-identifier-length) BLAS naming + BOOST_TEST( c[2][1] == 100.0 ); + } + { + multi::array c({a.size(), b.rotated().size()}, 9999.0); // NOLINT(readability-identifier-length) BLAS naming + c = blas::gemm(2.0, blas::H(a), blas::H(b)); + BOOST_TEST( c[2][1] == 100.0 ); + } + { + multi::array c; // NOLINT(readability-identifier-length) BLAS naming + c = blas::gemm(2.0, blas::H(a), blas::H(b)); + BOOST_TEST( c[2][1] == 100.0 ); + } + { + multi::array c({a.size(), b.rotated().size()}, 9999.0); // NOLINT(readability-identifier-length) BLAS naming + blas::gemm_n(2.0, begin(blas::H(a)), size(blas::H(a)), begin(blas::H(b)), 0.0, begin(c)); + BOOST_TEST( c[2][1] == 100.0 ); + } + } + + BOOST_AUTO_TEST_CASE(multi_adaptors_blas_gemm_real_square) { + // NOLINTNEXTLINE(readability-identifier-length) BLAS naming + multi::array const a = { + {1.0, 3.0}, + {9.0, 7.0}, + }; + // NOLINTNEXTLINE(readability-identifier-length) BLAS naming + multi::array const b = { + {11.0, 12.0}, + { 7.0, 19.0}, + }; + { + multi::array c({2, 2}); // NOLINT(readability-identifier-length) conventional BLAS naming + blas::gemm(1.0, a, b, 0.0, c); // c=ab, c⸆=b⸆a⸆ + BOOST_TEST( c[1][0] == 148.0 ); + } + { + multi::array c({2, 2}); // NOLINT(readability-identifier-length) conventional BLAS naming + + blas::context const ctxt; + blas::gemm_n(&ctxt, 1.0, begin(a), size(a), begin(b), 0.0, begin(c)); + BOOST_TEST( c[1][0] == 148.0 ); + } + { + multi::array c({2, 2}); // NOLINT(readability-identifier-length) conventional BLAS naming + blas::gemm(1.0, ~a, b, 0.0, c); // c=a⸆b, c⸆=b⸆a + BOOST_TEST(( c[1][1] == 169.0 && c[1][0] == 82.0 )); + } + { + multi::array c({2, 2}); // NOLINT(readability-identifier-length) conventional BLAS naming + + blas::context const ctxt; + blas::gemm_n(&ctxt, 1.0, begin(~a), size(~a), begin(b), 0.0, begin(c)); + BOOST_TEST(( c[1][1] == 169 && c[1][0] == 82 )); + } + { + multi::array const c({2, 2}); // NOLINT(readability-identifier-length) conventional BLAS naming + + blas::context const ctxt; + blas::gemm_n(&ctxt, 1.0, begin(~a), size(~a), begin(b), 0.0, begin(~c)); + BOOST_TEST( (~c)[1][1] == 169 ); + BOOST_TEST( (~c)[1][0] == 82 ); + } + { + multi::array c({2, 2}); // NOLINT(readability-identifier-length) conventional BLAS naming + blas::gemm(1.0, a, ~b, 0.0, c); // c=ab⸆, c⸆=ba⸆ + BOOST_TEST( c[1][0] == 183.0 ); + } + { + // TODO(correaa) fix sfinae of const c + multi::array c({2, 2}); // NOLINT(readability-identifier-length) conventional BLAS naming + + blas::context const ctxt; + blas::gemm_n(&ctxt, 1.0, begin(a), size(a), begin(~b), 0.0, begin(c)); // c=ab⸆, c⸆=ba⸆ + BOOST_TEST( c[1][0] == 183.0 ); + } + { + // NOLINTNEXTLINE(misc-const-correctness) TODO(correaa) fix sfinae of const c + multi::array c({2, 2}); // NOLINT(readability-identifier-length) conventional BLAS naming + blas::gemm(1.0, a, ~b, 0.0, ~c); // c=ab⸆, c⸆=ba⸆ + BOOST_TEST( (~c)[1][0] == 183.0 ); + } + { + // NOLINTNEXTLINE(misc-const-correctness) TODO(correaa) fix sfinae of const c + multi::array c({2, 2}); // NOLINT(readability-identifier-length) conventional BLAS naming + blas::gemm_n(1.0, begin(a), size(a), begin(~b), 0.0, begin(~c)); // c=ab⸆, c⸆=ba⸆ + BOOST_TEST( (~c)[1][0] == 183.0 ); + } + { + multi::array c({2, 2}); // NOLINT(readability-identifier-length) conventional BLAS naming + blas::gemm(1.0, ~a, ~b, 0.0, c); // c=a⸆b⸆, c⸆=ba + BOOST_TEST( c[1][0] == 117.0 ); + } + { + multi::array c({2, 2}); // NOLINT(readability-identifier-length) conventional BLAS naming + blas::gemm_n(1.0, begin(~a), size(~a), begin(~b), 0.0, begin(c)); // c=a⸆b⸆, c⸆=ba + BOOST_TEST( c[1][0] == 117.0 ); + } + { + multi::array c({2, 2}); // NOLINT(readability-identifier-length) conventional BLAS naming + blas::gemm(1.0, ~a, ~b, 0.0, ~c); // c⸆=a⸆b⸆, c=ba + BOOST_TEST( c[0][1] == 117.0 ); + } + { + multi::array c({2, 2}); // NOLINT(readability-identifier-length) conventional BLAS naming + blas::gemm_n(1.0, begin(~a), size(~a), begin(~b), 0.0, begin(~c)); // c⸆=a⸆b⸆, c=ba + BOOST_TEST( c[0][1] == 117.0 ); + } + } + + BOOST_AUTO_TEST_CASE(multi_adaptors_blas_gemm_real_nonsquare) { + // NOLINTNEXTLINE(readability-identifier-length) BLAS naming + multi::array const a = { + {1.0, 3.0, 1.0}, + {9.0, 7.0, 1.0}, + }; - multi::array C({100, 1}, {0.0, 0.0}); // NOLINT(readability-identifier-length) BLAS naming - - blas::gemm({1.0, 0.0}, A, B, {0.0, 0.0}, C); // c=ab, c⸆=b⸆a⸆ - BOOST_REQUIRE(C[99][0] == 1.0); -} - -BOOST_AUTO_TEST_CASE(adaptor_blas_complex_100x1_1x1_T) { - using complex = std::complex; - multi::array const A({100, 1}, complex{1.0, 0.0}); // NOLINT(readability-identifier-length) BLAS naming - multi::array const B({1, 1}, complex{1.0, 0.0}); // NOLINT(readability-identifier-length) BLAS naming - - multi::array C({100, 1}, complex{0.0, 0.0}); // NOLINT(readability-identifier-length) BLAS naming - - blas::gemm(complex{1.0, 0.0}, A, blas::T(B), complex{0.0, 0.0}, C); // c=ab, c⸆=b⸆a⸆ - BOOST_REQUIRE( C[99][0] == 1.0 ); -} - -BOOST_AUTO_TEST_CASE(adaptor_blas_complex_100x1_1x1_H) { - using complex = std::complex; // complex const I{0, 1}; - multi::array const A({100, 1}, {1.0, 0.0}); // NOLINT(readability-identifier-length) BLAS naming - multi::array const B({1, 1}, {1.0, 0.0}); // NOLINT(readability-identifier-length) BLAS naming - - multi::array C({100, 1}, {0.0, 0.0}); // NOLINT(readability-identifier-length) BLAS naming - - blas::gemm({1.0, 0.0}, A, blas::H(B), {0.0, 0.0}, C); // c=ab, c⸆=b⸆a⸆ - BOOST_REQUIRE( C[99][0] == 1.0 ); -} - -BOOST_AUTO_TEST_CASE(adaptor_blas_double_100x1_1x1) { - using complex = std::complex; - multi::array const A({100, 1}, {1.0, 0.0}); // NOLINT(readability-identifier-length) BLAS naming - multi::array const B({1, 1}, {1.0, 0.0}); // NOLINT(readability-identifier-length) BLAS naming - - multi::array C({100, 1}, {0.0, 0.0}); // NOLINT(readability-identifier-length) BLAS naming - - blas::gemm({1.0, 0.0}, A, B, {0.0, 0.0}, C); // c=ab, c⸆=b⸆a⸆ - BOOST_REQUIRE(C[99][0] == 1.0); -} - -BOOST_AUTO_TEST_CASE(adaptor_blas_double_100x1_1x1_T) { - multi::array const A({100, 1}, 1.0); // NOLINT(readability-identifier-length) BLAS naming - multi::array const B({1, 1}, 1.0); // NOLINT(readability-identifier-length) BLAS naming - - multi::array C({100, 1}, 0.0); // NOLINT(readability-identifier-length) BLAS naming - - blas::gemm(1.0, A, blas::T(B), 0.0, C); // c=ab, c⸆=b⸆a⸆ - BOOST_REQUIRE(C[99][0] == 1.0); -} - -BOOST_AUTO_TEST_CASE(adaptor_blas_double_100x1_1x1_H) { - multi::array const A({100, 1}, 1.0); // NOLINT(readability-identifier-length) BLAS naming - multi::array const B({1, 1}, 1.0); // NOLINT(readability-identifier-length) BLAS naming - - multi::array C({100, 1}, 0.0); // NOLINT(readability-identifier-length) BLAS naming - - blas::gemm(1.0, A, blas::H(B), 0.0, C); // c=ab, c⸆=b⸆a⸆ - BOOST_REQUIRE(C[99][0] == 1.0); -} - -BOOST_AUTO_TEST_CASE(multi_blas_gemm_square_real) { - // NOLINTNEXTLINE(readability-identifier-length) BLAS naming - multi::array const a = { - {1.0, 3.0, 4.0}, - {9.0, 7.0, 1.0}, - {1.0, 2.0, 3.0}, - }; - // NOLINTNEXTLINE(readability-identifier-length) BLAS naming - multi::array const b = { - {11.0, 12.0, 4.0}, - { 7.0, 19.0, 1.0}, - {11.0, 12.0, 4.0}, - }; - { - multi::array c({size(a), size(~b)}, 9999.0); // NOLINT(readability-identifier-length) conventional BLAS naming - blas::gemm(1.0, a, b, 0.0, c); - BOOST_REQUIRE( c[2][1] == 86.0 ); - } - { - multi::array c({size(a), size(~b)}, 9999.0); // NOLINT(readability-identifier-length) conventional BLAS naming - BOOST_REQUIRE( size( a) == size( c) ); - BOOST_REQUIRE( size(~b) == size(~c) ); - blas::gemm_n(1.0, begin(a), size(a), begin(b), 0.0, begin(c)); - BOOST_REQUIRE( c[2][1] == 86.0 ); - } - { - multi::array c({size(a), size(~b)}, 9999.0); // NOLINT(readability-identifier-length) conventional BLAS naming - blas::gemm(1.0, a, blas::T(b), 0.0, c); - BOOST_REQUIRE( c[2][1] == 48.0 ); - } - { - multi::array c({size(a), size(~b)}, 9999.0); // NOLINT(readability-identifier-length) conventional BLAS naming - blas::gemm_n(1., a.begin(), a.size(), blas::T(b).begin(), 0.0, c.begin()); - BOOST_REQUIRE( c[2][1] == 48.0 ); - } - { - multi::array c({size(a), size(~b)}, 9999.0); // NOLINT(readability-identifier-length) conventional BLAS naming - blas::gemm(1.0, blas::T(a), b, 0.0, c); - BOOST_REQUIRE( c[2][1] == 103.0 ); - } - { - multi::array c({size(a), size(~b)}, 9999.0); // NOLINT(readability-identifier-length) conventional BLAS naming - blas::gemm_n(1.0, begin(blas::T(a)), size(blas::T(a)), begin(b), 0.0, begin(c)); - BOOST_REQUIRE( c[2][1] == 103.0 ); - } - { - multi::array c({size(a), size(~b)}, 9999.0); // NOLINT(readability-identifier-length) conventional BLAS naming - blas::gemm(1.0, blas::T(a), blas::T(b), 0.0, c); - BOOST_REQUIRE( c[2][1] == 50.0 ); - } - { - multi::array c({size(a), size(~b)}, 9999.0); // NOLINT(readability-identifier-length) conventional BLAS naming - blas::gemm_n(1.0, begin(blas::T(a)), size(blas::T(a)), begin(blas::T(b)), 0.0, begin(c)); - BOOST_REQUIRE( c[2][1] == 50.0 ); - } - { - multi::array c({size(a), size(~b)}, 9999.0); // NOLINT(readability-identifier-length) conventional BLAS naming - blas::gemm(1.0, a, blas::T(b), 0.0, c); - BOOST_REQUIRE( c[2][1] == 48.0 ); - } - { - multi::array c({size(a), size(~b)}, 9999.0); // NOLINT(readability-identifier-length) conventional BLAS naming - blas::gemm_n(1.0, begin(a), size(a), begin(blas::T(b)), 0.0, begin(c)); - BOOST_REQUIRE( c[2][1] == 48.0 ); - } - { - multi::array c({size(a), size(~b)}, 9999.0); // NOLINT(readability-identifier-length) conventional BLAS naming - blas::gemm(1.0, blas::T(a), b, 0.0, c); - BOOST_REQUIRE( c[2][1] == 103.0 ); - } - { - multi::array c({size(a), size(~b)}, 9999.0); // NOLINT(readability-identifier-length) conventional BLAS naming - blas::gemm_n(1.0, begin(blas::T(a)), size(blas::T(a)), begin(b), 0.0, begin(c)); - BOOST_REQUIRE( c[2][1] == 103.0 ); - } - { - multi::array c({size(a), size(rotated(b))}, 9999.0); // NOLINT(readability-identifier-length) BLAS naming - blas::gemm(2.0, blas::H(a), blas::H(b), 0.0, c); - BOOST_REQUIRE( c[2][1] == 100.0 ); - } - { - multi::array c = blas::gemm(2.0, blas::H(a), blas::H(b)); // NOLINT(readability-identifier-length) BLAS naming - BOOST_REQUIRE( c[2][1] == 100.0 ); - } - { - multi::array const c = blas::gemm(2.0, blas::H(a), blas::H(b)); // NOLINT(readability-identifier-length) BLAS naming - BOOST_REQUIRE( c[2][1] == 100.0 ); - } - { - multi::array c({size(a), size(rotated(b))}, 9999.0); // NOLINT(readability-identifier-length) BLAS naming - c = blas::gemm(2.0, blas::H(a), blas::H(b)); - BOOST_REQUIRE( c[2][1] == 100.0 ); - } - { - multi::array c; // NOLINT(readability-identifier-length) BLAS naming - c = blas::gemm(2.0, blas::H(a), blas::H(b)); - BOOST_REQUIRE( c[2][1] == 100.0 ); - } - { - multi::array c({size(a), size(rotated(b))}, 9999.0); // NOLINT(readability-identifier-length) BLAS naming - blas::gemm_n(2.0, begin(blas::H(a)), size(blas::H(a)), begin(blas::H(b)), 0.0, begin(c)); - BOOST_REQUIRE( c[2][1] == 100.0 ); - } -} - -BOOST_AUTO_TEST_CASE(multi_adaptors_blas_gemm_real_square) { - // NOLINTNEXTLINE(readability-identifier-length) BLAS naming - multi::array const a = { - {1.0, 3.0}, - {9.0, 7.0}, - }; - // NOLINTNEXTLINE(readability-identifier-length) BLAS naming - multi::array const b = { - {11.0, 12.0}, - { 7.0, 19.0}, - }; - { - multi::array c({2, 2}); // NOLINT(readability-identifier-length) conventional BLAS naming - blas::gemm(1.0, a, b, 0.0, c); // c=ab, c⸆=b⸆a⸆ - BOOST_REQUIRE( c[1][0] == 148.0 ); - } - { - multi::array c({2, 2}); // NOLINT(readability-identifier-length) conventional BLAS naming - - blas::context const ctxt; - blas::gemm_n(&ctxt, 1.0, begin(a), size(a), begin(b), 0.0, begin(c)); - BOOST_REQUIRE( c[1][0] == 148.0 ); - } - { - multi::array c({2, 2}); // NOLINT(readability-identifier-length) conventional BLAS naming - blas::gemm(1.0, ~a, b, 0.0, c); // c=a⸆b, c⸆=b⸆a - BOOST_REQUIRE(( c[1][1] == 169.0 && c[1][0] == 82.0 )); - } - { - multi::array c({2, 2}); // NOLINT(readability-identifier-length) conventional BLAS naming - - blas::context const ctxt; - blas::gemm_n(&ctxt, 1.0, begin(~a), size(~a), begin(b), 0.0, begin(c)); - BOOST_REQUIRE(( c[1][1] == 169 && c[1][0] == 82 )); - } - { - multi::array const c({2, 2}); // NOLINT(readability-identifier-length) conventional BLAS naming - - blas::context const ctxt; - blas::gemm_n(&ctxt, 1.0, begin(~a), size(~a), begin(b), 0.0, begin(~c)); - BOOST_REQUIRE( (~c)[1][1] == 169 ); - BOOST_REQUIRE( (~c)[1][0] == 82 ); - } - { - multi::array c({2, 2}); // NOLINT(readability-identifier-length) conventional BLAS naming - blas::gemm(1.0, a, ~b, 0.0, c); // c=ab⸆, c⸆=ba⸆ - BOOST_REQUIRE( c[1][0] == 183.0 ); - } - { - // TODO(correaa) fix sfinae of const c - multi::array c({2, 2}); // NOLINT(readability-identifier-length) conventional BLAS naming - - blas::context const ctxt; - blas::gemm_n(&ctxt, 1.0, begin(a), size(a), begin(~b), 0.0, begin(c)); // c=ab⸆, c⸆=ba⸆ - BOOST_REQUIRE( c[1][0] == 183.0 ); - } - { - // NOLINTNEXTLINE(misc-const-correctness) TODO(correaa) fix sfinae of const c - multi::array c({2, 2}); // NOLINT(readability-identifier-length) conventional BLAS naming - blas::gemm(1.0, a, ~b, 0.0, ~c); // c=ab⸆, c⸆=ba⸆ - BOOST_REQUIRE( (~c)[1][0] == 183.0 ); - } - { - // NOLINTNEXTLINE(misc-const-correctness) TODO(correaa) fix sfinae of const c - multi::array c({2, 2}); // NOLINT(readability-identifier-length) conventional BLAS naming - blas::gemm_n(1.0, begin(a), size(a), begin(~b), 0.0, begin(~c)); // c=ab⸆, c⸆=ba⸆ - BOOST_REQUIRE( (~c)[1][0] == 183.0 ); - } - { - multi::array c({2, 2}); // NOLINT(readability-identifier-length) conventional BLAS naming - blas::gemm(1.0, ~a, ~b, 0.0, c); // c=a⸆b⸆, c⸆=ba - BOOST_REQUIRE( c[1][0] == 117.0 ); - } - { - multi::array c({2, 2}); // NOLINT(readability-identifier-length) conventional BLAS naming - blas::gemm_n(1.0, begin(~a), size(~a), begin(~b), 0.0, begin(c)); // c=a⸆b⸆, c⸆=ba - BOOST_REQUIRE( c[1][0] == 117.0 ); - } - { - multi::array c({2, 2}); // NOLINT(readability-identifier-length) conventional BLAS naming - blas::gemm(1.0, ~a, ~b, 0.0, ~c); // c⸆=a⸆b⸆, c=ba - BOOST_REQUIRE( c[0][1] == 117.0 ); - } - { - multi::array c({2, 2}); // NOLINT(readability-identifier-length) conventional BLAS naming - blas::gemm_n(1.0, begin(~a), size(~a), begin(~b), 0.0, begin(~c)); // c⸆=a⸆b⸆, c=ba - BOOST_REQUIRE( c[0][1] == 117.0 ); - } -} - -BOOST_AUTO_TEST_CASE(multi_adaptors_blas_gemm_real_nonsquare) { - // NOLINTNEXTLINE(readability-identifier-length) BLAS naming - multi::array const a = { - {1.0, 3.0, 1.0}, - {9.0, 7.0, 1.0}, - }; - // NOLINTNEXTLINE(readability-identifier-length) BLAS naming - multi::array const b = { - {11.0, 12.0, 1.0}, - { 7.0, 19.0, 1.0}, - { 1.0, 1.0, 1.0}, - }; - { - multi::array c({2, 3}); // NOLINT(readability-identifier-length) BLAS naming - blas::gemm(1.0, a, b, 0.0, c); // c=ab, c⸆=b⸆a⸆ - BOOST_REQUIRE( c[1][2] == 17 ); - } - { - multi::array c({2, 3}); // NOLINT(readability-identifier-length) BLAS naming - blas::gemm_n(1.0, begin(a), size(a), begin(b), 0.0, begin(c)); // c=ab, c⸆=b⸆a⸆ - BOOST_REQUIRE( c[1][2] == 17.0 ); - } -} - -BOOST_AUTO_TEST_CASE(multi_adaptors_blas_gemm_real_nonsquare_automatic) { - namespace blas = multi::blas; - // NOLINTNEXTLINE(readability-identifier-length) BLAS naming - multi::array const a = { - {1.0, 3.0, 1.0}, - {9.0, 7.0, 1.0}, - }; - // NOLINTNEXTLINE(readability-identifier-length) BLAS naming - multi::array const b = { - {11.0, 12.0, 4.0, 8.0}, - { 7.0, 19.0, 2.0, 7.0}, - { 5.0, 3.0, 3.0, 1.0}, - }; - { - multi::array c({size(a), size(~b)}); // NOLINT(readability-identifier-length) conventional BLAS naming - blas::gemm(1.0, a, b, 0.0, c); // c=ab, c⸆=b⸆a⸆ - BOOST_REQUIRE( c[1][2] == 53.0 ); - } - { - multi::array c({size(a), size(~b)}); // NOLINT(readability-identifier-length) conventional BLAS naming - blas::gemm_n(1.0, begin(a), size(a), begin(b), 0.0, begin(c)); // c=ab, c⸆=b⸆a⸆ - BOOST_REQUIRE( c[1][2] == 53.0 ); - } - { - multi::array c({2, 4}); // NOLINT(readability-identifier-length) conventional BLAS naming - blas::gemm(0.1, a, b, 0.0, c); // c=ab, c⸆=b⸆a⸆ - BOOST_REQUIRE_CLOSE(c[1][2], 5.3, 0.00001); - } - { - multi::array c({2, 4}); // NOLINT(readability-identifier-length) conventional BLAS naming - blas::gemm_n(0.1, begin(a), size(a), begin(b), 0., begin(c)); // c=ab, c⸆=b⸆a⸆ - BOOST_REQUIRE_CLOSE(c[1][2], 5.3, 0.00001); - } - { - auto c = +blas::gemm(0.1, a, b); // c=ab, c⸆=b⸆a⸆ // NOLINT(readability-identifier-length) conventional BLAS naming - BOOST_REQUIRE_CLOSE(c[1][2], 5.3, 0.00001); - } - { - multi::array c = blas::gemm(0.1, a, b); // NOLINT(readability-identifier-length) conventional BLAS naming - BOOST_REQUIRE_CLOSE(c[1][2], 5.3, 0.00001); - } -} - -BOOST_AUTO_TEST_CASE(multi_blas_gemm_nh) { - using complex = std::complex; - complex const I{0.0, 1.0}; // NOLINT(readability-identifier-length) imaginary unit - - // NOLINTNEXTLINE(readability-identifier-length) BLAS naming - multi::array const a = { - {1.0 - 2.0 * I, 9.0 - 1.0 * I}, - {2.0 + 3.0 * I, 1.0 - 2.0 * I}, - }; - { - auto c = +blas::gemm(1.0, a, blas::H(a)); // c=aa†, c†=aa† // NOLINT(readability-identifier-length) BLAS naming - BOOST_REQUIRE( c[1][0] == 7.0 - 10.0*I ); - BOOST_REQUIRE( c[0][1] == 7.0 + 10.0*I ); - } - { - multi::array c = blas::gemm(1.0, a, blas::H(a)); // c=aa†, c†=aa† // NOLINT(readability-identifier-length) BLAS naming - BOOST_REQUIRE( c[1][0] == 7.-10.*I ); - BOOST_REQUIRE( c[0][1] == 7.+10.*I ); - } - { - multi::array c = blas::gemm(1.0, a, blas::H(a)); // c=aa†, c†=aa† // NOLINT(readability-identifier-length) conventional BLAS naming - BOOST_REQUIRE( c[1][0] == 7.0 - 10.0*I ); - BOOST_REQUIRE( c[0][1] == 7.0 + 10.0*I ); - } - { - multi::array c({2, 2}, {9999.0, 0.0}); // NOLINT(readability-identifier-length) conventional BLAS naming - c = blas::gemm(1.0, a, blas::H(a)); // c=aa†, c†=aa† - BOOST_REQUIRE( c[1][0] == 7.0 - 10.0*I ); - BOOST_REQUIRE( c[0][1] == 7.0 + 10.0*I ); - } - { - multi::array c({2, 2}, {9999.0, 0.0}); // NOLINT(readability-identifier-length) conventional BLAS naming - c() = blas::gemm(1.0, a, blas::H(a)); // c=aa†, c†=aa† - BOOST_REQUIRE( c[1][0] == 7.0 - 10.*I ); - BOOST_REQUIRE( c[0][1] == 7.0 + 10.*I ); - } - { - multi::array c({2, 2}, {9999.0, 0.0}); // NOLINT(readability-identifier-length) conventional BLAS naming - blas::gemm({1.0, 0.0}, a, blas::H(a), {0.0, 0.0}, c); // c=aa†, c†=aa† - BOOST_REQUIRE( c[1][0] == 7.0 - 10.0*I ); - BOOST_REQUIRE( c[0][1] == 7.0 + 10.0*I ); - } - { - multi::array c({2, 2}, {9999.0, 0.0}); // NOLINT(readability-identifier-length) conventional BLAS naming - blas::gemm_n({1.0, 0.0}, begin(a), size(a), begin(blas::H(a)), {0.0, 0.0}, begin(c)); // c=aa†, c†=aa† - BOOST_REQUIRE( c[1][0] == 7. - 10.*I ); - BOOST_REQUIRE( c[0][1] == 7. + 10.*I ); - } -} + // NOLINTNEXTLINE(readability-identifier-length) BLAS naming + multi::array const b = { + {11.0, 12.0, 1.0}, + { 7.0, 19.0, 1.0}, + { 1.0, 1.0, 1.0}, + }; + { + multi::array c({2, 3}); // NOLINT(readability-identifier-length) BLAS naming + blas::gemm(1.0, a, b, 0.0, c); // c=ab, c⸆=b⸆a⸆ + BOOST_TEST( c[1][2] == 17 ); + } + { + multi::array c({2, 3}); // NOLINT(readability-identifier-length) BLAS naming + blas::gemm_n(1.0, begin(a), size(a), begin(b), 0.0, begin(c)); // c=ab, c⸆=b⸆a⸆ + BOOST_TEST( c[1][2] == 17.0 ); + } + } + + BOOST_AUTO_TEST_CASE(multi_adaptors_blas_gemm_real_nonsquare_automatic) { + namespace blas = multi::blas; + // NOLINTNEXTLINE(readability-identifier-length) BLAS naming + multi::array const a = { + {1.0, 3.0, 1.0}, + {9.0, 7.0, 1.0}, + }; + // NOLINTNEXTLINE(readability-identifier-length) BLAS naming + multi::array const b = { + {11.0, 12.0, 4.0, 8.0}, + { 7.0, 19.0, 2.0, 7.0}, + { 5.0, 3.0, 3.0, 1.0}, + }; + { + multi::array c({size(a), size(~b)}); // NOLINT(readability-identifier-length) conventional BLAS naming + blas::gemm(1.0, a, b, 0.0, c); // c=ab, c⸆=b⸆a⸆ + BOOST_TEST( c[1][2] == 53.0 ); + } + { + multi::array c({size(a), size(~b)}); // NOLINT(readability-identifier-length) conventional BLAS naming + blas::gemm_n(1.0, begin(a), size(a), begin(b), 0.0, begin(c)); // c=ab, c⸆=b⸆a⸆ + BOOST_TEST( c[1][2] == 53.0 ); + } + { + multi::array c({2, 4}); // NOLINT(readability-identifier-length) conventional BLAS naming + blas::gemm(0.1, a, b, 0.0, c); // c=ab, c⸆=b⸆a⸆ + BOOST_REQUIRE_CLOSE(c[1][2], 5.3, 0.00001); + } + { + multi::array c({2, 4}); // NOLINT(readability-identifier-length) conventional BLAS naming + blas::gemm_n(0.1, begin(a), size(a), begin(b), 0., begin(c)); // c=ab, c⸆=b⸆a⸆ + BOOST_REQUIRE_CLOSE(c[1][2], 5.3, 0.00001); + } + { + auto c = +blas::gemm(0.1, a, b); // c=ab, c⸆=b⸆a⸆ // NOLINT(readability-identifier-length) conventional BLAS naming + BOOST_REQUIRE_CLOSE(c[1][2], 5.3, 0.00001); + } + { + multi::array c = blas::gemm(0.1, a, b); // NOLINT(readability-identifier-length) conventional BLAS naming + BOOST_REQUIRE_CLOSE(c[1][2], 5.3, 0.00001); + } + } + + BOOST_AUTO_TEST_CASE(multi_blas_gemm_nh) { + using complex = std::complex; + complex const I{0.0, 1.0}; // NOLINT(readability-identifier-length) imaginary unit + + // NOLINTNEXTLINE(readability-identifier-length) BLAS naming + multi::array const a = { + {1.0 - 2.0 * I, 9.0 - 1.0 * I}, + {2.0 + 3.0 * I, 1.0 - 2.0 * I}, + }; + { + auto c = +blas::gemm(1.0, a, blas::H(a)); // c=aa†, c†=aa† // NOLINT(readability-identifier-length) BLAS naming + BOOST_TEST( c[1][0] == 7.0 - 10.0*I ); + BOOST_TEST( c[0][1] == 7.0 + 10.0*I ); + } + { + multi::array c = blas::gemm(1.0, a, blas::H(a)); // c=aa†, c†=aa† // NOLINT(readability-identifier-length) BLAS naming + BOOST_TEST( c[1][0] == 7.-10.*I ); + BOOST_TEST( c[0][1] == 7.+10.*I ); + } + { + multi::array c = blas::gemm(1.0, a, blas::H(a)); // c=aa†, c†=aa† // NOLINT(readability-identifier-length) conventional BLAS naming + BOOST_TEST( c[1][0] == 7.0 - 10.0*I ); + BOOST_TEST( c[0][1] == 7.0 + 10.0*I ); + } + { + multi::array c({2, 2}, {9999.0, 0.0}); // NOLINT(readability-identifier-length) conventional BLAS naming + c = blas::gemm(1.0, a, blas::H(a)); // c=aa†, c†=aa† + BOOST_TEST( c[1][0] == 7.0 - 10.0*I ); + BOOST_TEST( c[0][1] == 7.0 + 10.0*I ); + } + { + multi::array c({2, 2}, {9999.0, 0.0}); // NOLINT(readability-identifier-length) conventional BLAS naming + c() = blas::gemm(1.0, a, blas::H(a)); // c=aa†, c†=aa† + BOOST_TEST( c[1][0] == 7.0 - 10.*I ); + BOOST_TEST( c[0][1] == 7.0 + 10.*I ); + } + { + multi::array c({2, 2}, {9999.0, 0.0}); // NOLINT(readability-identifier-length) conventional BLAS naming + blas::gemm({1.0, 0.0}, a, blas::H(a), {0.0, 0.0}, c); // c=aa†, c†=aa† + BOOST_TEST( c[1][0] == 7.0 - 10.0*I ); + BOOST_TEST( c[0][1] == 7.0 + 10.0*I ); + } + { + multi::array c({2, 2}, {9999.0, 0.0}); // NOLINT(readability-identifier-length) conventional BLAS naming + blas::gemm_n({1.0, 0.0}, begin(a), size(a), begin(blas::H(a)), {0.0, 0.0}, begin(c)); // c=aa†, c†=aa† + BOOST_TEST( c[1][0] == 7. - 10.*I ); + BOOST_TEST( c[0][1] == 7. + 10.*I ); + } + } #if defined(CUDA_FOUND) -#include -BOOST_AUTO_TEST_CASE(multi_blas_gemm_nh_thrust) { - using complex = thrust::complex; - complex const I{0.0, 1.0}; - multi::array const a = { - {1.0 - 2.0 * I, 9.0 - 1.0 * I}, - {2.0 + 3.0 * I, 1.0 - 2.0 * I} - }; - { - auto c = +blas::gemm(1.0, a, blas::hermitized(a)); // c=aa†, c†=aa† - BOOST_REQUIRE( c[1][0] == 7.0 - 10.0*I ); - BOOST_REQUIRE( c[0][1] == 7.0 + 10.0*I ); - } - { - multi::array c = blas::gemm(1.0, a, blas::hermitized(a)); // c=aa†, c†=aa† - BOOST_REQUIRE( c[1][0] == 7.0 - 10.0*I ); - BOOST_REQUIRE( c[0][1] == 7.0 + 10.0*I ); - } - { - multi::array c = blas::gemm(1.0, a, blas::hermitized(a)); // c=aa†, c†=aa† - BOOST_REQUIRE( c[1][0] == 7.0 - 10.0*I ); - BOOST_REQUIRE( c[0][1] == 7.0 + 10.0*I ); - } - { - multi::array c({2, 2}); - c = blas::gemm(1.0, a, blas::hermitized(a)); // c=aa†, c†=aa† - BOOST_REQUIRE( c[1][0] == 7.0 - 10.0*I ); - BOOST_REQUIRE( c[0][1] == 7.0 + 10.0*I ); - } - { - multi::array c({2, 2}); - blas::gemm(1., a, blas::hermitized(a), 0.0, c); // c=aa†, c†=aa† - BOOST_REQUIRE( c[1][0] == 7.0 - 10.0*I ); - BOOST_REQUIRE( c[0][1] == 7.0 + 10.0*I ); - } - { - multi::array c({2, 2}); - blas::gemm_n(1.0, begin(a), size(a), begin(blas::H(a)), 0.0, begin(c)); // c=aa†, c†=aa† - BOOST_REQUIRE( c[1][0] == 7.0 - 10.0*I ); - BOOST_REQUIRE( c[0][1] == 7.0 + 10.0*I ); - } -} - -BOOST_AUTO_TEST_CASE(multi_blas_gemm_elongated) { - using complex = std::complex; - complex const I{0.0, 1.0}; - multi::array const a = { - {1.0 - 2.0 * I, 9.0 - 1.0 * I} - }; - { - multi::array c({1, 1}); - blas::gemm(1.0, a, blas::H(a), 0.0, c); // c=aa†, c†=aa† - BOOST_REQUIRE( c[0][0] == 87.0 + 0.0*I ); - } - { - multi::array c({1, 1}); - blas::gemm_n(1.0, begin(a), size(a), begin(blas::H(a)), 0.0, begin(c)); // c=aa†, c†=aa† - BOOST_REQUIRE( c[0][0] == 87.0 + 0.0*I ); - } -} - -BOOST_AUTO_TEST_CASE(multi_adaptors_blas_gemm_complex_3x1_3x1_bisbis) { - using complex = std::complex; - complex const I{0.0, 1.0}; - multi::array const a = { - {1.0 + 2.0 * I}, - {9.0 - 1.0 * I}, - {1.0 + 1.0 * I}}; - multi::array const b = { - {11.0 - 2.0 * I, 7.0 - 3.0 * I, 8.0 - 1.0 * I} - }; - { - multi::array c({1, 1}); - - BOOST_REQUIRE( size(blas::H(a)) == 1 ); - BOOST_REQUIRE( size(blas::H(b)[0]) == 1 ); - - blas::gemm(1.0, blas::H(a), blas::H(b), 0.0, c); // c=ab, c⸆=b⸆a⸆ - BOOST_REQUIRE( c[0][0] == 84.0 + 7.0*I ); - } - { - multi::array c({1, 1}); - blas::gemm_n(1.0, begin(blas::H(a)), size(blas::H(a)), begin(blas::H(b)), 0.0, begin(c)); // c=ab, c⸆=b⸆a⸆ - BOOST_REQUIRE( c[0][0] == 84.0 + 7.0*I ); - } -} - -BOOST_AUTO_TEST_CASE(multi_adaptors_blas_gemm_real_empty) { - multi::array const a({0, 5}); - BOOST_REQUIRE( size( a) == 0 ); - BOOST_REQUIRE( size(~a) == 5 ); - BOOST_REQUIRE( a.is_empty() ); - - multi::array const b({5, 0}); - BOOST_REQUIRE( size( b) == 0 ); - BOOST_REQUIRE( size(~b) == 0 ); - BOOST_REQUIRE( b.is_empty() ); - { - multi::array c; - blas::gemm(1.0, a, b, 0.0, c); // c=ab, c⸆=b⸆a⸆ - } - { - multi::array c; - blas::gemm_n(1.0, begin(a), size(a), begin(b), 0.0, begin(c)); // c=ab, c⸆=b⸆a⸆ - } -} - -BOOST_AUTO_TEST_CASE(multi_adaptors_blas_gemm_real_nonsquare2) { - multi::array const a = { - {1.0, 3.0}, - {9.0, 7.0}, - {1.0, 1.0}, - }; - multi::array const b = { - {11.0, 12.0}, - { 7.0, 19.0}, - }; - { - multi::array c({size(a), size(~b)}); - blas::gemm(1.0, a, b, 0.0, c); // c=ab, c⸆=b⸆a⸆ - BOOST_REQUIRE( c[2][1] == 31.0 ); - } - { - multi::array c({size(a), size(~b)}); - blas::gemm_n(1.0, begin(a), size(a), begin(b), 0.0, begin(c)); // c=ab, c⸆=b⸆a⸆ - BOOST_REQUIRE( c[2][1] == 31.0 ); - } - { - multi::array c({size(~b), size(a)}); - blas::gemm(1.0, a, b, 0.0, ~c); // c=ab, c⸆=b⸆a⸆ - BOOST_REQUIRE( c[1][2] == 31.0 ); - } - { - multi::array c({size(~b), size(a)}); - blas::gemm_n(1.0, begin(a), size(a), begin(b), 0.0, begin(~c)); // c=ab, c⸆=b⸆a⸆ - BOOST_REQUIRE( c[1][2] == 31.0 ); - } - { - auto ar = +~a; - multi::array c({3, 2}); - blas::gemm(1.0, ~ar, b, 0.0, c); // c=ab, c⸆=b⸆a⸆ - BOOST_REQUIRE( c[2][1] == 31.0 ); - } - { - auto ar = +~a; - multi::array c({3, 2}); - blas::gemm_n(1.0, begin(~ar), size(~ar), begin(b), 0.0, begin(c)); // c=ab, c⸆=b⸆a⸆ - BOOST_REQUIRE( c[2][1] == 31.0 ); - } - { - auto ar = +~a; - multi::array c({2, 3}); - blas::gemm(1.0, ~ar, b, 0.0, ~c); // c=ab, c⸆=b⸆a⸆ - BOOST_REQUIRE( c[1][2] == 31.0 ); - } - { - auto ar = +~a; - multi::array c({2, 3}); - blas::gemm_n(1.0, begin(~ar), size(~ar), begin(b), 0.0, begin(~c)); // c=ab, c⸆=b⸆a⸆ - BOOST_REQUIRE( c[1][2] == 31.0 ); - } -} - -BOOST_AUTO_TEST_CASE(multi_adaptors_blas_gemm_real_2x2_2x2) { - multi::array const a = { - {1.0, 3.0}, - {9.0, 4.0}, - }; - multi::array const b = { - {11.0, 12.0}, - { 7.0, 19.0}, - }; - { - multi::array c({2, 2}); - blas::gemm(1.0, ~a, b, 0.0, c); // c=a⸆b, c⸆=b⸆a - BOOST_REQUIRE( c[1][0] == 61.0 ); - - blas::gemm(1.0, ~a, b, 0.0, ~c); // c⸆=a⸆b, c=b⸆a - BOOST_REQUIRE( c[0][1] == 61.0 ); - } - { - multi::array c({2, 2}); - blas::gemm_n(1.0, begin(~a), size(~a), begin(b), 0.0, begin(c)); // c=a⸆b, c⸆=b⸆a - BOOST_REQUIRE( c[1][0] == 61.0 ); - - blas::gemm_n(1.0, begin(~a), size(~a), begin(b), 0.0, begin(~c)); // c⸆=a⸆b, c=b⸆a - BOOST_REQUIRE( c[0][1] == 61.0 ); - } -} - -BOOST_AUTO_TEST_CASE(multi_adaptors_blas_gemm_real_2x3_3x2) { - multi::array const a = { - {1.0, 3.0}, - {9.0, 4.0}, - {1.0, 5.0}, - }; - multi::array const b = { - {11.0, 12.0}, - { 7.0, 19.0}, - { 8.0, 1.0}, - }; - { - multi::array c({2, 2}); - blas::gemm(1.0, ~a, b, 0.0, c); // c=a⸆b, c⸆=b⸆a - BOOST_REQUIRE( c[1][0] == 101.0 ); - - blas::gemm(1., ~a, b, 0., ~c); // c⸆=a⸆b, c=b⸆a - BOOST_REQUIRE( c[0][1] == 101 ); - } - { - multi::array c({2, 2}); - blas::gemm_n(1.0, begin(~a), size(~a), begin(b), 0.0, begin(c)); // c=a⸆b, c⸆=b⸆a - BOOST_REQUIRE( c[1][0] == 101.0 ); - - blas::gemm_n(1.0, begin(~a), size(~a), begin(b), 0.0, begin(~c)); // c⸆=a⸆b, c=b⸆a - BOOST_REQUIRE( c[0][1] == 101.0 ); - } -} - -BOOST_AUTO_TEST_CASE(multi_adaptors_blas_gemm_real_1x3_3x2) { - multi::array const a = { - {1.0, 9.0, 1.0} - }; - BOOST_REQUIRE( stride(~a) == 1 ); - BOOST_REQUIRE( stride( a) == 3 ); - multi::array const b = { - {11.0, 12.0}, - { 7.0, 19.0}, - { 8.0, 1.0}, - }; - { - multi::array c({size(a), size(~b)}); - blas::gemm(1.0, a, b, 0.0, c); // c=ab, c⸆=b⸆a⸆ - BOOST_REQUIRE( c[0][1] == 184.0 ); - } - { - multi::array c({size(a), size(~b)}); - blas::gemm_n(1.0, begin(a), size(a), begin(b), 0.0, begin(c)); // c=ab, c⸆=b⸆a⸆ - BOOST_REQUIRE( c[0][1] == 184.0 ); - } - { - auto ar = +~a; - multi::array c({size(~b), size(~ar)}); - blas::gemm(1.0, ~ar, b, 0.0, ~c); // c⸆=a⸆b, c=b⸆a - BOOST_REQUIRE( c[1][0] == 184.0 ); - } - { - auto ar = +~a; - BOOST_REQUIRE( size(~ar) == 1 ); - BOOST_REQUIRE( begin(~ar).stride() == 1 ); - BOOST_REQUIRE( begin(~ar)->stride() == 1 ); - BOOST_REQUIRE( begin( ar)->stride() == 1 ); - - multi::array c({size(~b), size(~ar)}); - BOOST_REQUIRE( begin( c).stride() == 1 ); - BOOST_REQUIRE( begin(~c).stride() == 1 ); - BOOST_REQUIRE( begin(c)->stride() == 1 ); - - BOOST_REQUIRE( begin(b) ); - blas::gemm_n(1.0, begin(~ar), size(~ar), begin(b), 0.0, begin(~c)); // c⸆=a⸆b, c=b⸆a - BOOST_REQUIRE( c[1][0] == 184.0 ); - } -} - -BOOST_AUTO_TEST_CASE(multi_adaptors_blas_gemm_complexreal_1x3_3x2) { - using complex = std::complex; - multi::array const a = { - {1.0, 9.0, 1.0} - }; - BOOST_REQUIRE( stride(~a) == 1 ); - BOOST_REQUIRE( stride( a) == 3 ); - multi::array const b = { - {11.0, 12.0}, - { 7.0, 19.0}, - { 8.0, 1.0}, - }; - { - multi::array c({size(a), size(~b)}); - blas::gemm(1.0, a, b, 0.0, c); // c=ab, c⸆=b⸆a⸆ - BOOST_REQUIRE( c[0][1] == 184.0 ); - } - { - multi::array c({size(a), size(~b)}); - blas::gemm_n(1.0, begin(a), size(a), begin(b), 0.0, begin(c)); // c=ab, c⸆=b⸆a⸆ - BOOST_REQUIRE( c[0][1] == 184.0 ); - } - { - auto ar = +~a; - multi::array c({size(~b), size(~ar)}); - blas::gemm(1.0, ~ar, b, 0.0, ~c); // c⸆=a⸆b, c=b⸆a - BOOST_REQUIRE( c[1][0] == 184.0 ); - } - { - auto ar = +~a; - multi::array c({size(~b), size(~ar)}); - blas::gemm_n(1.0, begin(~ar), size(~ar), begin(b), 0.0, begin(~c)); // c⸆=a⸆b, c=b⸆a - BOOST_REQUIRE( c[1][0] == 184.0 ); - } -} - -BOOST_AUTO_TEST_CASE(multi_adaptors_blas_gemm_real_1x3_part_3x2) { - multi::array const a = { - {1.0, 9.0, 1.0}, - {3.0, 3.0, 3.0}, - }; - BOOST_REQUIRE( stride(~a) == 1 ); - BOOST_REQUIRE( stride( a) == 3 ); - multi::array const b = { - {11.0, 12.0}, - { 7.0, 19.0}, - { 8.0, 1.0}, - }; - { - multi::array c({size(a({0, 1})), size(~b)}); - blas::gemm(1.0, a({0, 1}), b, 0.0, c); // c=a⸆b, c⸆=b⸆a - BOOST_REQUIRE( c[0][1] == 184.0 ); - } - { - multi::array c({size(a({0, 1})), size(~b)}); - blas::gemm_n(1.0, begin(a({0, 1})), size(a({0, 1})), begin(b), 0.0, begin(c)); // c=a⸆b, c⸆=b⸆a - BOOST_REQUIRE( c[0][1] == 184.0 ); - } - { - auto ar = +~a; - multi::array c({size(~b), size(~ar(extension(ar), {0, 1}))}); - blas::gemm(1.0, ~(ar(extension(ar), {0, 1})), b, 0.0, ~c); // c=a⸆b, c⸆=b⸆a - BOOST_REQUIRE( c[1][0] == 184.0 ); - } - { - auto ar = +~a; - multi::array c({size(~b), size(~ar(extension(ar), {0, 1}))}); - blas::gemm_n(1.0, begin(~(ar(extension(ar), {0, 1}))), size(~(ar(extension(ar), {0, 1}))), begin(b), 0., begin(~c)); // c=a⸆b, c⸆=b⸆a - BOOST_REQUIRE( c[1][0] == 184.0 ); - } -} - -BOOST_AUTO_TEST_CASE(multi_adaptors_blas_gemm_complexreal_1x3_part_3x2) { - using complex = std::complex; - multi::array const a = { - {1.0, 9.0, 1.0}, - {3.0, 3.0, 3.0}, - }; - BOOST_REQUIRE( stride(~a) == 1 ); - BOOST_REQUIRE( stride( a) == 3 ); - multi::array const b = { - {11.0, 12.0}, - { 7.0, 19.0}, - { 8.0, 1.0} - }; - { - multi::array c({size(a({0, 1})), size(~b)}); - blas::gemm(1.0, a({0, 1}), b, 0.0, c); - BOOST_REQUIRE( c[0][1] == 184.0 ); - } - { - multi::array c({size(a({0, 1})), size(~b)}); - blas::gemm_n(1.0, begin(a({0, 1})), size(a({0, 1})), begin(b), 0.0, begin(c)); - BOOST_REQUIRE( c[0][1] == 184.0 ); - } - { - auto ar = +~a; - multi::array c({size(~b), size(~ar(extension(ar), {0, 1}))}); - blas::gemm(1.0, ~(ar(extension(ar), {0, 1})), b, 0.0, ~c); - BOOST_REQUIRE( c[1][0] == 184.0 ); - } - { - auto ar = +~a; - multi::array c({size(~b), size(~ar(extension(ar), {0, 1}))}); - blas::gemm_n(1.0, begin(~(ar(extension(ar), {0, 1}))), size(~(ar(extension(ar), {0, 1}))), begin(b), 0.0, begin(~c)); - BOOST_REQUIRE( c[1][0] == 184.0 ); - } -} - -BOOST_AUTO_TEST_CASE(multi_adaptors_blas_gemm_real_2x3_3x1) { - multi::array const a = { - {1.0, 9.0, 1.0}, - {3.0, 3.0, 3.0}, - }; - BOOST_REQUIRE( stride(~a) == 1 ); - BOOST_REQUIRE( stride( a) == 3 ); - multi::array const b = { - {11.0}, - {7.0}, - {8.0}}; - { - multi::array c({size(a), size(~b)}); - blas::gemm(1.0, a, b, 0.0, c); // c=ab, c⸆=b⸆a⸆ - BOOST_REQUIRE( c[0][0] == 82.0 ); - BOOST_REQUIRE( c[1][0] == 78.0 ); - } - { - multi::array c({size(a), size(~b)}); - blas::gemm_n(1.0, begin(a), size(a), begin(b), 0.0, begin(c)); // c=a⸆b, c⸆=b⸆a - BOOST_REQUIRE( c[0][0] == 82.0 ); - BOOST_REQUIRE( c[1][0] == 78.0 ); - } - { - auto ar = +~a; - multi::array c({size(~b), size(~ar(extension(ar), {0, 1}))}); - blas::gemm(1.0, ~(ar(extension(ar), {0, 1})), b, 0.0, ~c); // c=a⸆b, c⸆=b⸆a - BOOST_REQUIRE( c[0][0] == 82.0 ); - } - { - auto ar = +~a; - multi::array c({size(~b), size(~ar(extension(ar), {0, 1}))}); - blas::gemm_n(1., begin(~(ar(extension(ar), {0, 1}))), size(~(ar(extension(ar), {0, 1}))), begin(b), 0., begin(~c)); // c=a⸆b, c⸆=b⸆a - BOOST_REQUIRE( c[0][0] == 82.0 ); - } -} - -BOOST_AUTO_TEST_CASE(multi_adaptors_blas_gemm_real_2x3_3x1_bis) { - multi::array const a = { - {1.0, 9.0, 1.0}, - {3.0, 4.0, 5.0}, - }; - multi::array const b = { - {11.0}, - {7.0}, - {8.0}}; - - { - multi::array c({1, 2}); - blas::gemm(1.0, a, b, 0.0, ~c); // c⸆=ab, c=b⸆a⸆ - BOOST_REQUIRE( (~c)[0][0] == 82.0 ); - BOOST_REQUIRE( (~c)[1][0] == 101.0 ); - } - { - multi::array c({1, 2}); - blas::gemm_n(1.0, begin(a), size(a), begin(b), 0.0, begin(~c)); // c⸆=ab, c=b⸆a⸆ - BOOST_REQUIRE( (~c)[0][0] == 82.0 ); - BOOST_REQUIRE( (~c)[1][0] == 101.0 ); - } - { - multi::array c({2, 1}); - blas::gemm(1.0, a, b, 0.0, c); // c⸆=ab, c=b⸆a⸆ - BOOST_REQUIRE( (~c)[0][1] == 101.0 ); - BOOST_REQUIRE( c[1][0] == 101.0 ); - } - { - multi::array c({2, 1}); - blas::gemm_n(1., begin(a), size(a), begin(b), 0., begin(c)); // c⸆=ab, c=b⸆a⸆ - BOOST_REQUIRE( (~c)[0][1] == 101.0 ); - BOOST_REQUIRE( c[1][0] == 101.0 ); - } - { - multi::array c({1, 2}); - auto ar = +~a; - blas::gemm(1., ~ar, b, 0., ~c); // c⸆=ab, c⸆=b⸆a⸆ - BOOST_REQUIRE( c[0][1] == 101.0 ); - } - { - multi::array c({1, 2}); - auto ar = +~a; - blas::gemm_n(1., begin(~ar), size(~ar), begin(b), 0., begin(~c)); // c⸆=ab, c⸆=b⸆a⸆ - BOOST_REQUIRE( c[0][1] == 101.0 ); - } -} - -BOOST_AUTO_TEST_CASE(multi_adaptors_blas_gemm_real_1x3_3x1) { - multi::array const a = { - {1.0, 9.0, 1.0}, - }; - multi::array const b = { - {11.0}, - {7.0}, - {8.0}}; - { - multi::array c({1, 1}); - blas::gemm(1.0, a, b, 0.0, c); // c=ab, c⸆=b⸆a⸆ - BOOST_REQUIRE( c[0][0] == 82.0 ); - } - { - multi::array c({1, 1}); - blas::gemm_n(1., begin(a), size(a), begin(b), 0., begin(c)); - BOOST_REQUIRE( c[0][0] == 82.0 ); - } - { - multi::array c({1, 1}); - auto ar = +~a; - blas::gemm(1.0, ~ar, b, 0.0, c); - BOOST_REQUIRE( c[0][0] == 82.0 ); - } - { - multi::array c({1, 1}); - auto ar = +~a; - blas::gemm_n(1.0, begin(~ar), size(~ar), begin(b), 0.0, begin(c)); - BOOST_REQUIRE( c[0][0] == 82.0 ); - } - { - multi::array c({1, 1}); - auto br = +~b; - blas::gemm(1.0, a, ~br, 0.0, c); - BOOST_REQUIRE( c[0][0] == 82.0 ); - } - { - multi::array c({1, 1}); - BOOST_REQUIRE( begin(c). stride() == 1 ); - BOOST_REQUIRE( begin(c)->stride() == 1 ); - - auto br = +~b; - // BOOST_REQUIRE( begin(br). stride() == 1 ); - BOOST_REQUIRE( begin( br)->stride() == 1 ); - - BOOST_REQUIRE(begin(a)->stride() == 1); - BOOST_REQUIRE( begin(~br). stride() == 1 ); - // BOOST_REQUIRE( begin(~br)->stride() == 1 ); - BOOST_REQUIRE(begin(c)->stride() == 1); - BOOST_REQUIRE(begin(c).stride() == 1); - BOOST_REQUIRE(size(a) == 1); - - blas::gemm_n(1.0, begin(a), size(a), begin(~br), 0.0, begin(c)); - BOOST_REQUIRE( c[0][0] == 82.0 ); - } - { - multi::array c({1, 1}); - auto br = +~b; - blas::gemm(1.0, a, blas::H(br), 0.0, c); - BOOST_REQUIRE( c[0][0] == 82.0 ); - } - { - multi::array c({1, 1}); - auto br = +~b; - blas::gemm_n(1.0, begin(a), size(a), begin(blas::H(br)), 0.0, begin(c)); - BOOST_REQUIRE( c[0][0] == 82.0 ); - } -} - -BOOST_AUTO_TEST_CASE(multi_adaptors_blas_gemm_complex_square) { - using complex = std::complex; - constexpr complex I{0.0, 1.0}; - multi::array const a = { - {1.0 + 3.0 * I, 3.0 + 2.0 * I}, - {9.0 + 1.0 * I, 7.0 + 1.0 * I}, - }; - multi::array const b = { - {11.0 + 2.0 * I, 12.0 + 4.0 * I}, - { 7.0 + 1.0 * I, 19.0 - 9.0 * I}, - }; - { - multi::array c({2, 2}); - blas::gemm(1.0, a, b, 0.0, c); // c=ab, c⸆=b⸆a⸆ - BOOST_REQUIRE( c[1][0] == 145.0 + 43.0*I ); - } - { - multi::array c({2, 2}); - blas::gemm_n(1., begin(a), size(a), begin(b), 0., begin(c)); // c=ab, c⸆=b⸆a⸆ - BOOST_REQUIRE( c[1][0] == 145. + 43.*I ); - } - { - multi::array c({2, 2}); - blas::gemm(1., ~a, b, 0., c); // c=a⸆b, c⸆=b⸆a - BOOST_REQUIRE(( c[1][1] == 170.-8.*I && c[1][0] == 77.+42.*I )); - } - { - multi::array c({2, 2}); - blas::gemm_n(1., begin(~a), size(~a), begin(b), 0., begin(c)); // c=a⸆b, c⸆=b⸆a - BOOST_REQUIRE(( c[1][1] == 170.-8.*I && c[1][0] == 77.+42.*I )); - } - { - multi::array c({2, 2}); - blas::gemm(1., a, ~b, 0., c); // c=ab⸆, c⸆=ba⸆ - BOOST_REQUIRE( c[1][0] == 177.+69.*I ); - } - { - multi::array c({2, 2}); - blas::gemm_n(1., begin(a), size(a), begin(~b), 0., begin(c)); // c=ab⸆, c⸆=ba⸆ - BOOST_REQUIRE( c[1][0] == 177.+69.*I ); - } - { - multi::array c({2, 2}); - blas::gemm(1., blas::T(a), blas::T(b), 0., c); // c=a⸆b⸆, c⸆=ba - BOOST_REQUIRE( c[1][0] == 109. + 68.*I ); - } - { - multi::array c({2, 2}); - blas::gemm_n(1., begin(blas::T(a)), size(blas::T(a)), begin(blas::T(b)), 0., begin(c)); // c=a⸆b⸆, c⸆=ba - BOOST_REQUIRE( c[1][0] == 109. + 68.*I ); - } - { - multi::array c({2, 2}); - blas::gemm(1., blas::T(a), blas::T(b), 0., blas::T(c)); // c⸆=a⸆b⸆, c=ba - BOOST_REQUIRE( c[0][1] == 109.+68.*I ); - } - { - multi::array c({2, 2}); - blas::gemm_n(1., begin(blas::T(a)), size(blas::T(a)), begin(blas::T(b)), 0., begin(blas::T(c))); // c⸆=a⸆b⸆, c=ba - BOOST_REQUIRE( c[0][1] == 109.+68.*I ); - } -} - -BOOST_AUTO_TEST_CASE(multi_adaptors_blas_gemm_complex_1x3_3x1) { - using complex = std::complex; - complex const I{0, 1}; - multi::array const a = { - {1. + 2. * I, 9. - 1. * I, 1. + 1. * I}, - }; - multi::array const b = { - {11. - 2. * I}, - {7. - 3. * I}, - {8. - 1. * I}}; - { - multi::array c({1, 1}); - blas::gemm(1., a, b, 0., c); // c=ab, c⸆=b⸆a⸆ - BOOST_REQUIRE( c[0][0] == 84.-7.*I ); - } - { - multi::array c({1, 1}); - blas::gemm_n(1., begin(a), size(a), begin(b), 0., begin(c)); // c=ab, c⸆=b⸆a⸆ - BOOST_REQUIRE( c[0][0] == 84.-7.*I ); - } - { - multi::array c({1, 1}); - auto ar = +~a; - blas::gemm(1., ~ar, b, 0., c); // c=ab, c⸆=ba - BOOST_REQUIRE( c[0][0] == 84.-7.*I ); - } - { - multi::array c({1, 1}); - auto ar = +~a; - blas::gemm_n(1., begin(~ar), size(~ar), begin(b), 0., begin(c)); // c=ab, c⸆=ba - BOOST_REQUIRE( c[0][0] == 84.-7.*I ); - } - { - multi::array c({1, 1}); - auto br = +~b; - blas::gemm(1., a, ~br, 0., c); - BOOST_REQUIRE( c[0][0] == 84.-7.*I ); - } - { - multi::array c({1, 1}); - auto br = +~b; - blas::context ctxt; - blas::gemm_n(ctxt, 1., begin(a), size(a), begin(~br), 0., begin(c)); - BOOST_REQUIRE( c[0][0] == 84.-7.*I ); - } - { - multi::array c({1, 1}); - auto br = +~b; - blas::gemm(1., a, blas::H(br), 0., ~c); - BOOST_REQUIRE( c[0][0] == 80. + 53.*I ); - } - { - multi::array c({1, 1}); - auto br = +~b; - blas::gemm_n(1., begin(a), size(a), begin(blas::H(br)), 0., begin(~c)); - BOOST_REQUIRE( c[0][0] == 80. + 53.*I ); - } -} - -BOOST_AUTO_TEST_CASE(multi_adaptors_blas_gemm_complex_hermitized_square) { - using complex = std::complex; - constexpr complex I{0, 1}; - multi::array const a = { - {1. + 3. * I, 3. + 2. * I}, - {9. + 1. * I, 7. + 1. * I}, - }; - multi::array const b = { - {11. + 2. * I, 12. + 4. * I}, - { 7. + 1. * I, 19. - 9. * I}, - }; - { - multi::array c({2, 2}); - blas::gemm(1., a, b, 0., c); // c=ab, c†=b†a† - BOOST_REQUIRE( c[1][0] == 145. + 43.*I ); - } - { - multi::array c({2, 2}); - blas::gemm_n(1., begin(a), size(a), begin(b), 0., begin(c)); // c=ab, c†=b†a† - BOOST_REQUIRE( c[1][0] == 145. + 43.*I ); - } - { - multi::array c({2, 2}); - blas::gemm(1., blas::H(a), blas::H(b), 0., c); // c=a†b†, c†=ba - BOOST_REQUIRE( c[1][0] == 109. - 68.*I ); - } - { - multi::array c({2, 2}); - blas::gemm_n(1., begin(blas::H(a)), size(blas::H(a)), begin(blas::H(b)), 0., begin(c)); // c=a†b†, c†=ba - BOOST_REQUIRE( c[1][0] == 109. - 68.*I ); - } - { - multi::array c({2, 2}); - blas::gemm(1., blas::H(a), blas::H(b), 0., blas::H(c)); // c†=a†b†, c=ba - BOOST_REQUIRE( c[1][0] == 184. - 40.*I ); - } - { - multi::array c({2, 2}); - blas::gemm(1., blas::H(a), b, 0., c); // c=a†b, c†=b†a - BOOST_REQUIRE( c[1][0] == 87. - 16.*I ); - } - { - multi::array c({2, 2}); - blas::gemm_n(1., begin(blas::H(a)), size(blas::H(a)), begin(b), 0., begin(c)); // c=a†b, c†=b†a - BOOST_REQUIRE( c[1][0] == 87. - 16.*I ); - } - { - multi::array c({2, 2}); - blas::gemm(1., a, blas::H(b), 0., c); // c=ab†, c†=ba† - BOOST_REQUIRE( c[1][0] == 189. - 23.*I ); - } - { - multi::array c({2, 2}); - c = blas::gemm(1., a, blas::H(b)); // c=ab†, c†=ba† - BOOST_REQUIRE( c[1][0] == 189. - 23.*I ); - } - { - multi::array c = blas::gemm(1., a, blas::H(b)); // c=ab†, c†=ba† - BOOST_REQUIRE( size(c) == 2 ); - BOOST_REQUIRE( c[1][0] == 189. - 23.*I ); - } - { - auto c = multi::array(blas::gemm(1., a, blas::H(b))); // c=ab†, c†=ba† - BOOST_REQUIRE( size(c) == 2 ); - BOOST_REQUIRE( c[1][0] == 189. - 23.*I ); - } - { - multi::array c({2, 2}); - blas::gemm_n(1., begin(a), size(a), begin(blas::H(b)), 0., begin(c)); // c=ab†, c†=ba† - BOOST_REQUIRE( c[1][0] == 189. - 23.*I ); - } - { - multi::array c({2, 2}); - blas::gemm(1., blas::H(a), blas::H(b), 0., c); // c=a†b†, c†=ba - BOOST_REQUIRE( c[1][0] == 109. - 68.*I); - } - { - multi::array c({2, 2}); - blas::gemm_n(1., begin(blas::H(a)), size(blas::H(a)), begin(blas::H(b)), 0., begin(c)); // c=a†b†, c†=ba - BOOST_REQUIRE( c[1][0] == 109. - 68.*I); - } -} - -BOOST_AUTO_TEST_CASE(multi_adaptors_blas_gemm_complex_3x1_3x1) { - using complex = std::complex; - complex const I{0, 1}; - multi::array const a = { - {1. + 2. * I}, - {9. - 1. * I}, - {1. + 1. * I}}; - multi::array const b = { - {11. - 2. * I}, - {7. - 3. * I}, - {8. - 1. * I}}; - { - multi::array c({1, 1}); - blas::gemm(1., blas::H(a), b, 0., c); // c=ab, c⸆=b⸆a⸆ - BOOST_REQUIRE( c[0][0] == 80.-53.*I ); - } - { - multi::array c({1, 1}); - blas::gemm_n(1., begin(blas::H(a)), size(blas::H(a)), begin(b), 0., begin(c)); // c=ab, c⸆=b⸆a⸆ - BOOST_REQUIRE( c[0][0] == 80.-53.*I ); - } - { - multi::array c({1, 1}); - blas::gemm(1., blas::H(a), b, 0., c); // c=a†b, c†=b†a - BOOST_REQUIRE( c[0][0] == 80.-53.*I ); - } - { - multi::array c({1, 1}); - blas::gemm_n(1., begin(blas::H(a)), size(blas::H(a)), begin(b), 0., begin(c)); // c=a†b, c†=b†a - BOOST_REQUIRE( c[0][0] == 80.-53.*I ); - } - { - multi::array c({1, 1}); - auto ha = +blas::hermitized(a); - blas::gemm(1., ha, b, 0., c); - BOOST_REQUIRE( c[0][0] == 80.-53.*I ); - - blas::gemm(1., blas::H(b), a, 0., c); - BOOST_REQUIRE( c[0][0] == 80.+53.*I ); - } - { - multi::array c({1, 1}); - auto ha = +blas::hermitized(a); - blas::gemm_n(1., begin(ha), size(ha), begin(b), 0., begin(c)); - BOOST_REQUIRE( c[0][0] == 80.-53.*I ); - - blas::gemm_n(1., begin(blas::H(b)), size(blas::H(b)), begin(a), 0., begin(c)); - BOOST_REQUIRE( c[0][0] == 80.+53.*I ); - } -} - -BOOST_AUTO_TEST_CASE(multi_adaptors_blas_gemm_complex_1x3_3x2) { - using complex = std::complex; - constexpr complex I{0, 1}; - multi::array const a = { - {1. + 2. * I, 9. - 1. * I, 1. + 1. * I} - }; - multi::array const b = { - {11. - 2. * I, 5. + 2. * I}, - { 7. - 3. * I, 2. + 1. * I}, - { 8. - 1. * I, 1. + 1. * I} - }; - { - multi::array c({1, 2}); - blas::gemm(1., a, b, 0., c); // c=ab, c⸆=b⸆a⸆ - BOOST_REQUIRE( c[0][1] == 20.+21.*I ); - } - { - multi::array c({1, 2}); - blas::gemm_n(1., begin(a), size(a), begin(b), 0., begin(c)); // c=ab, c⸆=b⸆a⸆ - BOOST_REQUIRE( c[0][1] == 20.+21.*I ); - } - { - auto ar = +~a; - multi::array c({1, 2}); - blas::gemm(1., blas::H(ar), b, 0., c); // c=ab, c⸆=b⸆a⸆ - BOOST_REQUIRE( c[0][1] == 28.+3.*I ); - } - { - auto ar = +~a; - multi::array c({1, 2}); - blas::gemm_n(1., begin(blas::H(ar)), size(blas::H(ar)), begin(b), 0., begin(c)); // c=ab, c⸆=b⸆a⸆ - BOOST_REQUIRE( c[0][1] == 28.+3.*I ); - } -} - -BOOST_AUTO_TEST_CASE(multi_adaptors_blas_gemm_complex_3x1_3x2) { - using complex = std::complex; - complex const I{0, 1}; - multi::array const a = { - {1. + 2. * I}, - {9. - 1. * I}, - {1. + 1. * I}}; - multi::array const b = { - {11. - 2. * I, 5. + 2. * I}, - { 7. - 3. * I, 2. + 1. * I}, - { 8. - 1. * I, 1. + 1. * I} - }; - { - multi::array c({1, 2}); - blas::gemm(1., blas::H(a), b, 0., c); // c=ab, c⸆=b⸆a⸆ - BOOST_REQUIRE( c[0][1] == 28.+3.*I ); - } - { - multi::array c({1, 2}); - blas::gemm_n(1., begin(blas::H(a)), size(blas::H(a)), begin(b), 0., begin(c)); // c=ab, c⸆=b⸆a⸆ - BOOST_REQUIRE( c[0][1] == 28.+3.*I ); - } -} - -BOOST_AUTO_TEST_CASE(multi_adaptors_blas_gemm_complex_3x2_3x2) { - using complex = std::complex; - complex const I{0, 1}; - multi::array const a = { - {1. + 2. * I, 5. + 2. * I}, - {9. - 1. * I, 9. + 1. * I}, - {1. + 1. * I, 2. + 2. * I} - }; - multi::array const b = { - {11. - 2. * I, 5. + 2. * I}, - { 7. - 3. * I, 2. + 1. * I}, - { 8. - 1. * I, 1. + 1. * I} - }; - { - multi::array c({2, 2}); - blas::gemm(1., blas::H(a), b, 0., c); // c=ab, c⸆=b⸆a⸆ - BOOST_REQUIRE( c[1][0] == 125.-84.*I ); - } - { - multi::array c({2, 2}); - blas::gemm_n(1., begin(blas::H(a)), size(blas::H(a)), begin(b), 0., begin(c)); // c=ab, c⸆=b⸆a⸆ - BOOST_REQUIRE( c[1][0] == 125.-84.*I ); - } -} - -BOOST_AUTO_TEST_CASE(multi_adaptors_blas_gemm_complex_3x2_3x1) { - using complex = std::complex; - complex const I{0, 1}; - multi::array const a = { - {1. + 2. * I, 5. + 2. * I}, - {9. - 1. * I, 9. + 1. * I}, - {1. + 1. * I, 2. + 2. * I} - }; - multi::array const b = { - {11. - 2. * I}, - {7. - 3. * I}, - {8. - 1. * I}}; - { - multi::array c({2, 1}); - blas::gemm(1., blas::H(a), b, 0., c); // c=ab, c⸆=b⸆a⸆ - BOOST_REQUIRE( c[1][0] == 125.-84.*I ); - } - { - multi::array c({2, 1}); - blas::gemm_n(1., begin(blas::H(a)), size(blas::H(a)), begin(b), 0., begin(c)); // c=ab, c⸆=b⸆a⸆ - BOOST_REQUIRE( c[1][0] == 125.-84.*I ); - } -} - -BOOST_AUTO_TEST_CASE(multi_adaptors_blas_gemm_complex_3x1_3x1_bis) { - using complex = std::complex; - complex const I{0, 1}; - multi::array const a = { - {1. + 2. * I}, - {9. - 1. * I}, - {1. + 1. * I}}; - multi::array const b = { - {11. - 2. * I}, - {7. - 3. * I}, - {8. - 1. * I}}; - { - multi::array c({1, 1}); - blas::gemm(1., blas::H(a), b, 0., c); // c=ab, c⸆=b⸆a⸆ - BOOST_REQUIRE( c[0][0] == 80. - 53.*I ); - } - { - multi::array c({1, 1}); - blas::gemm_n(1., begin(blas::H(a)), size(blas::H(a)), begin(b), 0., begin(c)); // c=ab, c⸆=b⸆a⸆ - BOOST_REQUIRE( c[0][0] == 80. - 53.*I ); - } -} - -BOOST_AUTO_TEST_CASE(multi_adaptors_blas_gemm_real_square_automatic) { - multi::array const a = { - {1., 3.}, - {9., 7.}, - }; - multi::array const b = { - {11., 12.}, - { 7., 19.}, - }; - { - multi::array c({2, 2}); - blas::gemm(1., a, b, 0., c); // c=ab, c⸆=b⸆a⸆ - BOOST_REQUIRE( c[1][0] == 148 && c[1][1] == 241 ); - } - { - multi::array c({2, 2}); - blas::gemm_n(1., begin(a), size(a), begin(b), 0., begin(c)); // c=ab, c⸆=b⸆a⸆ - BOOST_REQUIRE( c[1][0] == 148 && c[1][1] == 241 ); - } - { - multi::array c({2, 2}); - blas::gemm(1., a, blas::T(b), 0., c); // c=ab, c⸆=b⸆a⸆ - BOOST_REQUIRE( c[1][1] == 196. ); - } - { - multi::array c({2, 2}); - blas::gemm(1., blas::T(a), b, 0., c); // c=ab, c⸆=b⸆a⸆ - BOOST_REQUIRE( c[1][1] == 169. ); - BOOST_REQUIRE( c[1][0] == 82. ); - } - { - multi::array c({2, 2}); - blas::gemm(1., blas::T(a), blas::T(b), 0., c); // c=ab, c⸆=b⸆a⸆ - BOOST_REQUIRE( c[1][1] == 154. ); - } -} - -BOOST_AUTO_TEST_CASE(multi_adaptors_blas_gemm_complex_square_automatic) { - using complex = std::complex; - complex const I{0, 1}; - multi::array const a = { - {1. + 2. * I, 3. - 3. * I}, - {9. + 1. * I, 7. + 4. * I}, - }; - multi::array const b = { - {11. + 1. * I, 12. + 1. * I}, - { 7. + 8. * I, 19. - 2. * I}, - }; - namespace blas = multi::blas; - { - multi::array c({2, 2}); - blas::gemm(1., a, b, 0., c); // c=ab, c⸆=b⸆a⸆ - BOOST_REQUIRE( c[1][0] == complex(115, 104) ); - } - { - multi::array c({2, 2}); - blas::gemm_n(1., begin(a), size(a), begin(b), 0., begin(c)); // c=ab, c⸆=b⸆a⸆ - BOOST_REQUIRE( c[1][0] == complex(115, 104) ); - } - { - multi::array c({2, 2}); - blas::gemm(1., a, blas::T(b), 0., c); // c=ab⸆, c⸆=ba⸆ - BOOST_REQUIRE( c[1][0] == complex(178, 75) ); - } - { - multi::array c({2, 2}); - blas::gemm_n(1., begin(a), size(a), begin(blas::T(b)), 0., begin(c)); // c=ab⸆, c⸆=ba⸆ - BOOST_REQUIRE( c[1][0] == complex(178, 75) ); - } -} - -BOOST_AUTO_TEST_CASE(multi_adaptors_blas_gemm_complex_square_automatic_part2) { - using complex = std::complex; - complex const I{0, 1}; - multi::array const a = { - {1. + 2. * I, 3. - 3. * I}, - {9. + 1. * I, 7. + 4. * I}, - }; - multi::array const b = { - {11. + 1. * I, 12. + 1. * I}, - { 7. + 8. * I, 19. - 2. * I}, - }; - namespace blas = multi::blas; - { - multi::array c({2, 2}); - blas::gemm(1., blas::T(a), b, 0., c); // c=a⸆b, c⸆=b⸆a - BOOST_REQUIRE(( c[1][1] == complex(180, 29) && c[1][0] == complex(53, 54) )); - } - { - multi::array c({2, 2}); - blas::gemm_n(1., begin(blas::T(a)), size(blas::T(a)), begin(b), 0., begin(c)); // c=a⸆b, c⸆=b⸆a - BOOST_REQUIRE(( c[1][1] == complex(180, 29) && c[1][0] == complex(53, 54) )); - } - { - multi::array c({2, 2}); - blas::gemm(1., blas::T(a), blas::T(b), 0., c); // c=ab, c⸆=b⸆a⸆ - BOOST_REQUIRE(( c[1][1] == complex(186, 65) && c[1][0] == complex(116, 25) )); - } - { - multi::array c({2, 2}); - blas::gemm_n(1., begin(blas::T(a)), size(blas::T(a)), begin(blas::T(b)), 0., begin(c)); // c=ab, c⸆=b⸆a⸆ - BOOST_REQUIRE(( c[1][1] == complex(186, 65) && c[1][0] == complex(116, 25) )); - } - { - multi::array c({2, 2}); - blas::gemm(1., a, b, 0., c); // c=ab, c⸆=b⸆a⸆ - BOOST_REQUIRE( c[1][0] == complex(115, 104) ); - } - { - multi::array c({2, 2}); - blas::gemm_n(1., begin(a), size(a), begin(b), 0.0, begin(c)); // c=ab, c⸆=b⸆a⸆ - BOOST_REQUIRE( c[1][0] == complex(115, 104) ); - } - { - multi::array c({2, 2}); - blas::gemm(1., blas::H(a), b, 0., c); // c=a†b, c†=b†a - BOOST_REQUIRE( c[1][0] == complex(111, 64) && c[1][1] == complex(158, -51) ); - } -} - -BOOST_AUTO_TEST_CASE(multi_adaptors_blas_gemm_complex_square_automatic_part3) { - using complex = std::complex; - complex const I{0, 1}; - multi::array const a = { - {1. + 2. * I, 3. - 3. * I}, - {9. + 1. * I, 7. + 4. * I}, - }; - multi::array const b = { - {11. + 1. * I, 12. + 1. * I}, - { 7. + 8. * I, 19. - 2. * I}, - }; - namespace blas = multi::blas; - { - multi::array c({2, 2}); - blas::gemm_n(1., begin(blas::H(a)), size(blas::H(a)), begin(b), 0., begin(c)); // c=a†b, c†=b†a - BOOST_REQUIRE( c[1][0] == complex(111, 64) && c[1][1] == complex(158, -51) ); - } - { - multi::array c({2, 2}); - blas::gemm(1., a, blas::H(b), 0., c); // c=ab†, c†=ba† - BOOST_REQUIRE( c[1][0] == complex(188, 43) && c[1][1] == complex(196, 25) ); - auto c2 = +blas::gemm(1., a, blas::H(b)); - BOOST_REQUIRE( c2 == c ); - } - { - multi::array c({2, 2}); - blas::gemm(0.1, a, blas::H(b), 0., c); // c=ab†, c†=ba† - auto const c2 = +blas::gemm(0.1, a, blas::H(b)); - BOOST_REQUIRE( c2 == c ); - } - { - multi::array c({2, 2}); - blas::gemm(1., blas::H(a), blas::H(b), 0., c); // c=a†b†, c†=ba - BOOST_REQUIRE( c[1][0] == complex(116, -25) && c[1][1] == complex(186, -65) ); - } - { - multi::array c({2, 2}); - blas::gemm_n(1., begin(blas::H(a)), size(blas::H(a)), begin(blas::H(b)), 0., begin(c)); // c=a†b†, c†=ba - BOOST_REQUIRE( c[1][0] == complex(116, -25) && c[1][1] == complex(186, -65) ); - } - { - multi::array c({2, 2}); - blas::gemm(1., blas::T(a), blas::H(b), 0., c); // c=a⸆b†, c†=ba⸆† - BOOST_REQUIRE( c[1][0] == complex(118, 5) && c[1][1] == complex(122, 45) ); - } - { - multi::array c({2, 2}); - blas::gemm_n(1., begin(blas::T(a)), size(blas::T(a)), begin(blas::H(b)), 0., begin(c)); // c=a⸆b†, c†=ba⸆† - BOOST_REQUIRE( c[1][0] == complex(118, 5) && c[1][1] == complex(122, 45) ); - } - { - multi::array c({2, 2}); - blas::gemm(1., blas::T(a), blas::T(b), 0., c); // c=a⸆b⸆, c⸆=ba - BOOST_REQUIRE( c[1][0] == complex(116, 25) && c[1][1] == complex(186, 65) ); - } - { - multi::array c({2, 2}); - blas::gemm_n(1., begin(blas::T(a)), size(blas::T(a)), begin(blas::T(b)), 0., begin(c)); // c=a⸆b⸆, c⸆=ba - BOOST_REQUIRE( c[1][0] == complex(116, 25) && c[1][1] == complex(186, 65) ); - } -} - -BOOST_AUTO_TEST_CASE(multi_adaptors_blas_gemm_complex_nonsquare_automatic) { - using complex = std::complex; - complex const I{0, 1}; - multi::array const a = { - {1. + 2. * I, 3. - 3. * I, 1. - 9. * I}, - {9. + 1. * I, 7. + 4. * I, 1. - 8. * I}, - }; - multi::array const b = { - {11. + 1. * I, 12. + 1. * I, 4. + 1. * I, 8. - 2. * I}, - { 7. + 8. * I, 19. - 2. * I, 2. + 1. * I, 7. + 1. * I}, - { 5. + 1. * I, 3. - 1. * I, 3. + 8. * I, 1. + 1. * I} - }; - { - multi::array c({2, 4}); - blas::gemm(1., a, b, 0., c); // c=ab, c⸆=b⸆a⸆ - BOOST_REQUIRE( c[1][2] == complex(112, 12) ); - } - { - multi::array c({2, 4}); - blas::gemm_n(1., begin(a), size(a), begin(b), 0., begin(c)); // c=ab, c⸆=b⸆a⸆ - BOOST_REQUIRE( c[1][2] == complex(112, 12) ); - } -} - -BOOST_AUTO_TEST_CASE(multi_adaptors_blas_gemm_realcomplex_complex_nonsquare_automatic) { - using complex = std::complex; - complex const I{0, 1}; - multi::array const a = { - {1., 3., 1.}, - {9., 7., 1.}, - }; - multi::array const b = { - {11. + 1. * I, 12. + 1. * I, 4. + 1. * I, 8. - 2. * I}, - { 7. + 8. * I, 19. - 2. * I, 2. + 1. * I, 7. + 1. * I}, - { 5. + 1. * I, 3. - 1. * I, 3. + 8. * I, 1. + 1. * I} - }; - { - multi::array c = blas::gemm(1., a, b); // c=ab, c⸆=b⸆a⸆ - BOOST_REQUIRE( c[1][2] == complex(53, 24) ); - } - { - multi::array c({2, 4}); - c = blas::gemm(1., a, b); // c=ab, c⸆=b⸆a⸆ - BOOST_REQUIRE( c[1][2] == complex(53, 24) ); - } - { - multi::array c({2, 4}); - blas::gemm(1., a, b, 0., c); // c=ab, c⸆=b⸆a⸆ - BOOST_REQUIRE( c[1][2] == complex(53, 24) ); - } - { - multi::array c({2, 4}); - blas::gemm_n(1., begin(a), size(a), begin(b), 0., begin(c)); // c=ab, c⸆=b⸆a⸆ - BOOST_REQUIRE( c[1][2] == complex(53, 24) ); - } - { - multi::array const a_real = { - {1., 3., 1.}, - {9., 7., 1.}, + #include + BOOST_AUTO_TEST_CASE(multi_blas_gemm_nh_thrust) { + using complex = thrust::complex; + complex const I{0.0, 1.0}; + multi::array const a = { + {1.0 - 2.0 * I, 9.0 - 1.0 * I}, + {2.0 + 3.0 * I, 1.0 - 2.0 * I} + }; + { + auto c = +blas::gemm(1.0, a, blas::hermitized(a)); // c=aa†, c†=aa† + BOOST_TEST( c[1][0] == 7.0 - 10.0*I ); + BOOST_TEST( c[0][1] == 7.0 + 10.0*I ); + } + { + multi::array c = blas::gemm(1.0, a, blas::hermitized(a)); // c=aa†, c†=aa† + BOOST_TEST( c[1][0] == 7.0 - 10.0*I ); + BOOST_TEST( c[0][1] == 7.0 + 10.0*I ); + } + { + multi::array c = blas::gemm(1.0, a, blas::hermitized(a)); // c=aa†, c†=aa† + BOOST_TEST( c[1][0] == 7.0 - 10.0*I ); + BOOST_TEST( c[0][1] == 7.0 + 10.0*I ); + } + { + multi::array c({2, 2}); + c = blas::gemm(1.0, a, blas::hermitized(a)); // c=aa†, c†=aa† + BOOST_TEST( c[1][0] == 7.0 - 10.0*I ); + BOOST_TEST( c[0][1] == 7.0 + 10.0*I ); + } + { + multi::array c({2, 2}); + blas::gemm(1., a, blas::hermitized(a), 0.0, c); // c=aa†, c†=aa† + BOOST_TEST( c[1][0] == 7.0 - 10.0*I ); + BOOST_TEST( c[0][1] == 7.0 + 10.0*I ); + } + { + multi::array c({2, 2}); + blas::gemm_n(1.0, begin(a), size(a), begin(blas::H(a)), 0.0, begin(c)); // c=aa†, c†=aa† + BOOST_TEST( c[1][0] == 7.0 - 10.0*I ); + BOOST_TEST( c[0][1] == 7.0 + 10.0*I ); + } + } + + BOOST_AUTO_TEST_CASE(multi_blas_gemm_elongated) { + using complex = std::complex; + complex const I{0.0, 1.0}; + multi::array const a = { + {1.0 - 2.0 * I, 9.0 - 1.0 * I} + }; + { + multi::array c({1, 1}); + blas::gemm(1.0, a, blas::H(a), 0.0, c); // c=aa†, c†=aa† + BOOST_TEST( c[0][0] == 87.0 + 0.0*I ); + } + { + multi::array c({1, 1}); + blas::gemm_n(1.0, begin(a), size(a), begin(blas::H(a)), 0.0, begin(c)); // c=aa†, c†=aa† + BOOST_TEST( c[0][0] == 87.0 + 0.0*I ); + } + } + + BOOST_AUTO_TEST_CASE(multi_adaptors_blas_gemm_complex_3x1_3x1_bisbis) { + using complex = std::complex; + complex const I{0.0, 1.0}; + multi::array const a = { + {1.0 + 2.0 * I}, + {9.0 - 1.0 * I}, + {1.0 + 1.0 * I} + }; + multi::array const b = { + {11.0 - 2.0 * I, 7.0 - 3.0 * I, 8.0 - 1.0 * I} + }; + { + multi::array c({1, 1}); + + BOOST_TEST( size(blas::H(a)) == 1 ); + BOOST_TEST( size(blas::H(b)[0]) == 1 ); + + blas::gemm(1.0, blas::H(a), blas::H(b), 0.0, c); // c=ab, c⸆=b⸆a⸆ + BOOST_TEST( c[0][0] == 84.0 + 7.0*I ); + } + { + multi::array c({1, 1}); + blas::gemm_n(1.0, begin(blas::H(a)), size(blas::H(a)), begin(blas::H(b)), 0.0, begin(c)); // c=ab, c⸆=b⸆a⸆ + BOOST_TEST( c[0][0] == 84.0 + 7.0*I ); + } + } + + BOOST_AUTO_TEST_CASE(multi_adaptors_blas_gemm_real_empty) { + multi::array const a({0, 5}); + BOOST_TEST( size( a) == 0 ); + BOOST_TEST( size(~a) == 5 ); + BOOST_TEST( a.is_empty() ); + + multi::array const b({5, 0}); + BOOST_TEST( size( b) == 0 ); + BOOST_TEST( size(~b) == 0 ); + BOOST_TEST( b.is_empty() ); + { + multi::array c; + blas::gemm(1.0, a, b, 0.0, c); // c=ab, c⸆=b⸆a⸆ + } + { + multi::array c; + blas::gemm_n(1.0, begin(a), size(a), begin(b), 0.0, begin(c)); // c=ab, c⸆=b⸆a⸆ + } + } + + BOOST_AUTO_TEST_CASE(multi_adaptors_blas_gemm_real_nonsquare2) { + multi::array const a = { + {1.0, 3.0}, + {9.0, 7.0}, + {1.0, 1.0}, + }; + multi::array const b = { + {11.0, 12.0}, + { 7.0, 19.0}, + }; + { + multi::array c({size(a), size(~b)}); + blas::gemm(1.0, a, b, 0.0, c); // c=ab, c⸆=b⸆a⸆ + BOOST_TEST( c[2][1] == 31.0 ); + } + { + multi::array c({size(a), size(~b)}); + blas::gemm_n(1.0, begin(a), size(a), begin(b), 0.0, begin(c)); // c=ab, c⸆=b⸆a⸆ + BOOST_TEST( c[2][1] == 31.0 ); + } + { + multi::array c({size(~b), size(a)}); + blas::gemm(1.0, a, b, 0.0, ~c); // c=ab, c⸆=b⸆a⸆ + BOOST_TEST( c[1][2] == 31.0 ); + } + { + multi::array c({size(~b), size(a)}); + blas::gemm_n(1.0, begin(a), size(a), begin(b), 0.0, begin(~c)); // c=ab, c⸆=b⸆a⸆ + BOOST_TEST( c[1][2] == 31.0 ); + } + { + auto ar = +~a; + multi::array c({3, 2}); + blas::gemm(1.0, ~ar, b, 0.0, c); // c=ab, c⸆=b⸆a⸆ + BOOST_TEST( c[2][1] == 31.0 ); + } + { + auto ar = +~a; + multi::array c({3, 2}); + blas::gemm_n(1.0, begin(~ar), size(~ar), begin(b), 0.0, begin(c)); // c=ab, c⸆=b⸆a⸆ + BOOST_TEST( c[2][1] == 31.0 ); + } + { + auto ar = +~a; + multi::array c({2, 3}); + blas::gemm(1.0, ~ar, b, 0.0, ~c); // c=ab, c⸆=b⸆a⸆ + BOOST_TEST( c[1][2] == 31.0 ); + } + { + auto ar = +~a; + multi::array c({2, 3}); + blas::gemm_n(1.0, begin(~ar), size(~ar), begin(b), 0.0, begin(~c)); // c=ab, c⸆=b⸆a⸆ + BOOST_TEST( c[1][2] == 31.0 ); + } + } + + BOOST_AUTO_TEST_CASE(multi_adaptors_blas_gemm_real_2x2_2x2) { + multi::array const a = { + {1.0, 3.0}, + {9.0, 4.0}, + }; + multi::array const b = { + {11.0, 12.0}, + { 7.0, 19.0}, + }; + { + multi::array c({2, 2}); + blas::gemm(1.0, ~a, b, 0.0, c); // c=a⸆b, c⸆=b⸆a + BOOST_TEST( c[1][0] == 61.0 ); + + blas::gemm(1.0, ~a, b, 0.0, ~c); // c⸆=a⸆b, c=b⸆a + BOOST_TEST( c[0][1] == 61.0 ); + } + { + multi::array c({2, 2}); + blas::gemm_n(1.0, begin(~a), size(~a), begin(b), 0.0, begin(c)); // c=a⸆b, c⸆=b⸆a + BOOST_TEST( c[1][0] == 61.0 ); + + blas::gemm_n(1.0, begin(~a), size(~a), begin(b), 0.0, begin(~c)); // c⸆=a⸆b, c=b⸆a + BOOST_TEST( c[0][1] == 61.0 ); + } + } + + BOOST_AUTO_TEST_CASE(multi_adaptors_blas_gemm_real_2x3_3x2) { + multi::array const a = { + {1.0, 3.0}, + {9.0, 4.0}, + {1.0, 5.0}, + }; + multi::array const b = { + {11.0, 12.0}, + { 7.0, 19.0}, + { 8.0, 1.0}, }; - multi::array c({2, 4}); - blas::real_doubled(c) = blas::gemm(1., a_real, blas::real_doubled(b)); - - BOOST_REQUIRE( c[1][2] == complex(53, 24) ); - } -} - -BOOST_AUTO_TEST_CASE(submatrix_result_issue_97) { - using complex = std::complex; - constexpr complex I{0, 1}; - multi::array M = { - {2. + 3. * I, 2. + 1. * I, 1. + 2. * I}, - {4. + 2. * I, 2. + 4. * I, 3. + 1. * I}, - {7. + 1. * I, 1. + 5. * I, 0. + 3. * I}, - }; - auto M2 = +M({0, 3}, {0, 1}); - BOOST_REQUIRE( M2 == M({0, 3}, {0, 1}) ); -} - -BOOST_AUTO_TEST_CASE(blas_context_gemm) { - using complex = std::complex; - static constexpr complex I{0, 1}; - auto rand = [d = std::normal_distribution<>{}, g = std::mt19937{}]() mutable { return d(g) + d(g) * I; }; // NOLINT(cert-msc32-c, cert-msc51-cpp): test purposes - - multi::array A({30, 40}); - multi::array B({40, 50}); - - std::generate(A.elements().begin(), A.elements().end(), rand); - std::generate(B.elements().begin(), B.elements().end(), rand); -} - -BOOST_AUTO_TEST_CASE(multi_adaptors_blas_gemm_real_nonsquare_hermitized_second_gemm_range) { - multi::array const a({2, 3}, 0.); - multi::array const b({4, 3}, 0.); - { - multi::array c({2, 4}); - c() = blas::gemm(0.1, a, blas::H(b)); - BOOST_REQUIRE_CLOSE(c[1][2], 0., 0.00001); - } - { - multi::array c = blas::gemm(0.1, a, blas::H(b)); // c=ab⸆, c⸆=ba⸆ - BOOST_REQUIRE( c[1][2] == 0. ); - } - { + { + multi::array c({2, 2}); + blas::gemm(1.0, ~a, b, 0.0, c); // c=a⸆b, c⸆=b⸆a + BOOST_TEST( c[1][0] == 101.0 ); + + blas::gemm(1., ~a, b, 0., ~c); // c⸆=a⸆b, c=b⸆a + BOOST_TEST( c[0][1] == 101 ); + } + { + multi::array c({2, 2}); + blas::gemm_n(1.0, begin(~a), size(~a), begin(b), 0.0, begin(c)); // c=a⸆b, c⸆=b⸆a + BOOST_TEST( c[1][0] == 101.0 ); + + blas::gemm_n(1.0, begin(~a), size(~a), begin(b), 0.0, begin(~c)); // c⸆=a⸆b, c=b⸆a + BOOST_TEST( c[0][1] == 101.0 ); + } + } + + BOOST_AUTO_TEST_CASE(multi_adaptors_blas_gemm_real_1x3_3x2) { + multi::array const a = { + {1.0, 9.0, 1.0} + }; + BOOST_TEST( stride(~a) == 1 ); + BOOST_TEST( stride( a) == 3 ); + multi::array const b = { + {11.0, 12.0}, + { 7.0, 19.0}, + { 8.0, 1.0}, + }; + { + multi::array c({size(a), size(~b)}); + blas::gemm(1.0, a, b, 0.0, c); // c=ab, c⸆=b⸆a⸆ + BOOST_TEST( c[0][1] == 184.0 ); + } + { + multi::array c({size(a), size(~b)}); + blas::gemm_n(1.0, begin(a), size(a), begin(b), 0.0, begin(c)); // c=ab, c⸆=b⸆a⸆ + BOOST_TEST( c[0][1] == 184.0 ); + } + { + auto ar = +~a; + multi::array c({size(~b), size(~ar)}); + blas::gemm(1.0, ~ar, b, 0.0, ~c); // c⸆=a⸆b, c=b⸆a + BOOST_TEST( c[1][0] == 184.0 ); + } + { + auto ar = +~a; + BOOST_TEST( size(~ar) == 1 ); + BOOST_TEST( begin(~ar).stride() == 1 ); + BOOST_TEST( begin(~ar)->stride() == 1 ); + BOOST_TEST( begin( ar)->stride() == 1 ); + + multi::array c({size(~b), size(~ar)}); + BOOST_TEST( begin( c).stride() == 1 ); + BOOST_TEST( begin(~c).stride() == 1 ); + BOOST_TEST( begin(c)->stride() == 1 ); + + BOOST_TEST( begin(b) ); + blas::gemm_n(1.0, begin(~ar), size(~ar), begin(b), 0.0, begin(~c)); // c⸆=a⸆b, c=b⸆a + BOOST_TEST( c[1][0] == 184.0 ); + } + } + + BOOST_AUTO_TEST_CASE(multi_adaptors_blas_gemm_complexreal_1x3_3x2) { + using complex = std::complex; + multi::array const a = { + {1.0, 9.0, 1.0} + }; + BOOST_TEST( stride(~a) == 1 ); + BOOST_TEST( stride( a) == 3 ); + multi::array const b = { + {11.0, 12.0}, + { 7.0, 19.0}, + { 8.0, 1.0}, + }; + { + multi::array c({size(a), size(~b)}); + blas::gemm(1.0, a, b, 0.0, c); // c=ab, c⸆=b⸆a⸆ + BOOST_TEST( c[0][1] == 184.0 ); + } + { + multi::array c({size(a), size(~b)}); + blas::gemm_n(1.0, begin(a), size(a), begin(b), 0.0, begin(c)); // c=ab, c⸆=b⸆a⸆ + BOOST_TEST( c[0][1] == 184.0 ); + } + { + auto ar = +~a; + multi::array c({size(~b), size(~ar)}); + blas::gemm(1.0, ~ar, b, 0.0, ~c); // c⸆=a⸆b, c=b⸆a + BOOST_TEST( c[1][0] == 184.0 ); + } + { + auto ar = +~a; + multi::array c({size(~b), size(~ar)}); + blas::gemm_n(1.0, begin(~ar), size(~ar), begin(b), 0.0, begin(~c)); // c⸆=a⸆b, c=b⸆a + BOOST_TEST( c[1][0] == 184.0 ); + } + } + + BOOST_AUTO_TEST_CASE(multi_adaptors_blas_gemm_real_1x3_part_3x2) { + multi::array const a = { + {1.0, 9.0, 1.0}, + {3.0, 3.0, 3.0}, + }; + BOOST_TEST( stride(~a) == 1 ); + BOOST_TEST( stride( a) == 3 ); + multi::array const b = { + {11.0, 12.0}, + { 7.0, 19.0}, + { 8.0, 1.0}, + }; + { + multi::array c({size(a({0, 1})), size(~b)}); + blas::gemm(1.0, a({0, 1}), b, 0.0, c); // c=a⸆b, c⸆=b⸆a + BOOST_TEST( c[0][1] == 184.0 ); + } + { + multi::array c({size(a({0, 1})), size(~b)}); + blas::gemm_n(1.0, begin(a({0, 1})), size(a({0, 1})), begin(b), 0.0, begin(c)); // c=a⸆b, c⸆=b⸆a + BOOST_TEST( c[0][1] == 184.0 ); + } + { + auto ar = +~a; + multi::array c({size(~b), size(~ar(extension(ar), {0, 1}))}); + blas::gemm(1.0, ~(ar(extension(ar), {0, 1})), b, 0.0, ~c); // c=a⸆b, c⸆=b⸆a + BOOST_TEST( c[1][0] == 184.0 ); + } + { + auto ar = +~a; + multi::array c({size(~b), size(~ar(extension(ar), {0, 1}))}); + blas::gemm_n(1.0, begin(~(ar(extension(ar), {0, 1}))), size(~(ar(extension(ar), {0, 1}))), begin(b), 0., begin(~c)); // c=a⸆b, c⸆=b⸆a + BOOST_TEST( c[1][0] == 184.0 ); + } + } + + BOOST_AUTO_TEST_CASE(multi_adaptors_blas_gemm_complexreal_1x3_part_3x2) { + using complex = std::complex; + multi::array const a = { + {1.0, 9.0, 1.0}, + {3.0, 3.0, 3.0}, + }; + BOOST_TEST( stride(~a) == 1 ); + BOOST_TEST( stride( a) == 3 ); + multi::array const b = { + {11.0, 12.0}, + { 7.0, 19.0}, + { 8.0, 1.0} + }; + { + multi::array c({size(a({0, 1})), size(~b)}); + blas::gemm(1.0, a({0, 1}), b, 0.0, c); + BOOST_TEST( c[0][1] == 184.0 ); + } + { + multi::array c({size(a({0, 1})), size(~b)}); + blas::gemm_n(1.0, begin(a({0, 1})), size(a({0, 1})), begin(b), 0.0, begin(c)); + BOOST_TEST( c[0][1] == 184.0 ); + } + { + auto ar = +~a; + multi::array c({size(~b), size(~ar(extension(ar), {0, 1}))}); + blas::gemm(1.0, ~(ar(extension(ar), {0, 1})), b, 0.0, ~c); + BOOST_TEST( c[1][0] == 184.0 ); + } + { + auto ar = +~a; + multi::array c({size(~b), size(~ar(extension(ar), {0, 1}))}); + blas::gemm_n(1.0, begin(~(ar(extension(ar), {0, 1}))), size(~(ar(extension(ar), {0, 1}))), begin(b), 0.0, begin(~c)); + BOOST_TEST( c[1][0] == 184.0 ); + } + } + + BOOST_AUTO_TEST_CASE(multi_adaptors_blas_gemm_real_2x3_3x1) { + multi::array const a = { + {1.0, 9.0, 1.0}, + {3.0, 3.0, 3.0}, + }; + BOOST_TEST( stride(~a) == 1 ); + BOOST_TEST( stride( a) == 3 ); + multi::array const b = { + {11.0}, + {7.0}, + {8.0} + }; + { + multi::array c({size(a), size(~b)}); + blas::gemm(1.0, a, b, 0.0, c); // c=ab, c⸆=b⸆a⸆ + BOOST_TEST( c[0][0] == 82.0 ); + BOOST_TEST( c[1][0] == 78.0 ); + } + { + multi::array c({size(a), size(~b)}); + blas::gemm_n(1.0, begin(a), size(a), begin(b), 0.0, begin(c)); // c=a⸆b, c⸆=b⸆a + BOOST_TEST( c[0][0] == 82.0 ); + BOOST_TEST( c[1][0] == 78.0 ); + } + { + auto ar = +~a; + multi::array c({size(~b), size(~ar(extension(ar), {0, 1}))}); + blas::gemm(1.0, ~(ar(extension(ar), {0, 1})), b, 0.0, ~c); // c=a⸆b, c⸆=b⸆a + BOOST_TEST( c[0][0] == 82.0 ); + } + { + auto ar = +~a; + multi::array c({size(~b), size(~ar(extension(ar), {0, 1}))}); + blas::gemm_n(1., begin(~(ar(extension(ar), {0, 1}))), size(~(ar(extension(ar), {0, 1}))), begin(b), 0., begin(~c)); // c=a⸆b, c⸆=b⸆a + BOOST_TEST( c[0][0] == 82.0 ); + } + } + + BOOST_AUTO_TEST_CASE(multi_adaptors_blas_gemm_real_2x3_3x1_bis) { + multi::array const a = { + {1.0, 9.0, 1.0}, + {3.0, 4.0, 5.0}, + }; + multi::array const b = { + {11.0}, + {7.0}, + {8.0} + }; + + { + multi::array c({1, 2}); + blas::gemm(1.0, a, b, 0.0, ~c); // c⸆=ab, c=b⸆a⸆ + BOOST_TEST( (~c)[0][0] == 82.0 ); + BOOST_TEST( (~c)[1][0] == 101.0 ); + } + { + multi::array c({1, 2}); + blas::gemm_n(1.0, begin(a), size(a), begin(b), 0.0, begin(~c)); // c⸆=ab, c=b⸆a⸆ + BOOST_TEST( (~c)[0][0] == 82.0 ); + BOOST_TEST( (~c)[1][0] == 101.0 ); + } + { + multi::array c({2, 1}); + blas::gemm(1.0, a, b, 0.0, c); // c⸆=ab, c=b⸆a⸆ + BOOST_TEST( (~c)[0][1] == 101.0 ); + BOOST_TEST( c[1][0] == 101.0 ); + } + { + multi::array c({2, 1}); + blas::gemm_n(1., begin(a), size(a), begin(b), 0., begin(c)); // c⸆=ab, c=b⸆a⸆ + BOOST_TEST( (~c)[0][1] == 101.0 ); + BOOST_TEST( c[1][0] == 101.0 ); + } + { + multi::array c({1, 2}); + auto ar = +~a; + blas::gemm(1., ~ar, b, 0., ~c); // c⸆=ab, c⸆=b⸆a⸆ + BOOST_TEST( c[0][1] == 101.0 ); + } + { + multi::array c({1, 2}); + auto ar = +~a; + blas::gemm_n(1., begin(~ar), size(~ar), begin(b), 0., begin(~c)); // c⸆=ab, c⸆=b⸆a⸆ + BOOST_TEST( c[0][1] == 101.0 ); + } + } + + BOOST_AUTO_TEST_CASE(multi_adaptors_blas_gemm_real_1x3_3x1) { + multi::array const a = { + {1.0, 9.0, 1.0}, + }; + multi::array const b = { + {11.0}, + {7.0}, + {8.0} + }; + { + multi::array c({1, 1}); + blas::gemm(1.0, a, b, 0.0, c); // c=ab, c⸆=b⸆a⸆ + BOOST_TEST( c[0][0] == 82.0 ); + } + { + multi::array c({1, 1}); + blas::gemm_n(1., begin(a), size(a), begin(b), 0., begin(c)); + BOOST_TEST( c[0][0] == 82.0 ); + } + { + multi::array c({1, 1}); + auto ar = +~a; + blas::gemm(1.0, ~ar, b, 0.0, c); + BOOST_TEST( c[0][0] == 82.0 ); + } + { + multi::array c({1, 1}); + auto ar = +~a; + blas::gemm_n(1.0, begin(~ar), size(~ar), begin(b), 0.0, begin(c)); + BOOST_TEST( c[0][0] == 82.0 ); + } + { + multi::array c({1, 1}); + auto br = +~b; + blas::gemm(1.0, a, ~br, 0.0, c); + BOOST_TEST( c[0][0] == 82.0 ); + } + { + multi::array c({1, 1}); + BOOST_TEST( begin(c). stride() == 1 ); + BOOST_TEST( begin(c)->stride() == 1 ); + + auto br = +~b; + // BOOST_TEST( begin(br). stride() == 1 ); + BOOST_TEST( begin( br)->stride() == 1 ); + + BOOST_TEST(begin(a)->stride() == 1); + BOOST_TEST( begin(~br). stride() == 1 ); + // BOOST_TEST( begin(~br)->stride() == 1 ); + BOOST_TEST(begin(c)->stride() == 1); + BOOST_TEST(begin(c).stride() == 1); + BOOST_TEST(size(a) == 1); + + blas::gemm_n(1.0, begin(a), size(a), begin(~br), 0.0, begin(c)); + BOOST_TEST( c[0][0] == 82.0 ); + } + { + multi::array c({1, 1}); + auto br = +~b; + blas::gemm(1.0, a, blas::H(br), 0.0, c); + BOOST_TEST( c[0][0] == 82.0 ); + } + { + multi::array c({1, 1}); + auto br = +~b; + blas::gemm_n(1.0, begin(a), size(a), begin(blas::H(br)), 0.0, begin(c)); + BOOST_TEST( c[0][0] == 82.0 ); + } + } + + BOOST_AUTO_TEST_CASE(multi_adaptors_blas_gemm_complex_square) { + using complex = std::complex; + constexpr complex I{0.0, 1.0}; + multi::array const a = { + {1.0 + 3.0 * I, 3.0 + 2.0 * I}, + {9.0 + 1.0 * I, 7.0 + 1.0 * I}, + }; + multi::array const b = { + {11.0 + 2.0 * I, 12.0 + 4.0 * I}, + { 7.0 + 1.0 * I, 19.0 - 9.0 * I}, + }; + { + multi::array c({2, 2}); + blas::gemm(1.0, a, b, 0.0, c); // c=ab, c⸆=b⸆a⸆ + BOOST_TEST( c[1][0] == 145.0 + 43.0*I ); + } + { + multi::array c({2, 2}); + blas::gemm_n(1., begin(a), size(a), begin(b), 0., begin(c)); // c=ab, c⸆=b⸆a⸆ + BOOST_TEST( c[1][0] == 145. + 43.*I ); + } + { + multi::array c({2, 2}); + blas::gemm(1., ~a, b, 0., c); // c=a⸆b, c⸆=b⸆a + BOOST_TEST(( c[1][1] == 170.-8.*I && c[1][0] == 77.+42.*I )); + } + { + multi::array c({2, 2}); + blas::gemm_n(1., begin(~a), size(~a), begin(b), 0., begin(c)); // c=a⸆b, c⸆=b⸆a + BOOST_TEST(( c[1][1] == 170.-8.*I && c[1][0] == 77.+42.*I )); + } + { + multi::array c({2, 2}); + blas::gemm(1., a, ~b, 0., c); // c=ab⸆, c⸆=ba⸆ + BOOST_TEST( c[1][0] == 177.+69.*I ); + } + { + multi::array c({2, 2}); + blas::gemm_n(1., begin(a), size(a), begin(~b), 0., begin(c)); // c=ab⸆, c⸆=ba⸆ + BOOST_TEST( c[1][0] == 177.+69.*I ); + } + { + multi::array c({2, 2}); + blas::gemm(1., blas::T(a), blas::T(b), 0., c); // c=a⸆b⸆, c⸆=ba + BOOST_TEST( c[1][0] == 109. + 68.*I ); + } + { + multi::array c({2, 2}); + blas::gemm_n(1., begin(blas::T(a)), size(blas::T(a)), begin(blas::T(b)), 0., begin(c)); // c=a⸆b⸆, c⸆=ba + BOOST_TEST( c[1][0] == 109. + 68.*I ); + } + { + multi::array c({2, 2}); + blas::gemm(1., blas::T(a), blas::T(b), 0., blas::T(c)); // c⸆=a⸆b⸆, c=ba + BOOST_TEST( c[0][1] == 109.+68.*I ); + } + { + multi::array c({2, 2}); + blas::gemm_n(1., begin(blas::T(a)), size(blas::T(a)), begin(blas::T(b)), 0., begin(blas::T(c))); // c⸆=a⸆b⸆, c=ba + BOOST_TEST( c[0][1] == 109.+68.*I ); + } + } + + BOOST_AUTO_TEST_CASE(multi_adaptors_blas_gemm_complex_1x3_3x1) { + using complex = std::complex; + complex const I{0, 1}; + multi::array const a = { + {1. + 2. * I, 9. - 1. * I, 1. + 1. * I}, + }; + multi::array const b = { + {11. - 2. * I}, + {7. - 3. * I}, + {8. - 1. * I} + }; + { + multi::array c({1, 1}); + blas::gemm(1., a, b, 0., c); // c=ab, c⸆=b⸆a⸆ + BOOST_TEST( c[0][0] == 84.-7.*I ); + } + { + multi::array c({1, 1}); + blas::gemm_n(1., begin(a), size(a), begin(b), 0., begin(c)); // c=ab, c⸆=b⸆a⸆ + BOOST_TEST( c[0][0] == 84.-7.*I ); + } + { + multi::array c({1, 1}); + auto ar = +~a; + blas::gemm(1., ~ar, b, 0., c); // c=ab, c⸆=ba + BOOST_TEST( c[0][0] == 84.-7.*I ); + } + { + multi::array c({1, 1}); + auto ar = +~a; + blas::gemm_n(1., begin(~ar), size(~ar), begin(b), 0., begin(c)); // c=ab, c⸆=ba + BOOST_TEST( c[0][0] == 84.-7.*I ); + } + { + multi::array c({1, 1}); + auto br = +~b; + blas::gemm(1., a, ~br, 0., c); + BOOST_TEST( c[0][0] == 84.-7.*I ); + } + { + multi::array c({1, 1}); + auto br = +~b; + blas::context ctxt; + blas::gemm_n(ctxt, 1., begin(a), size(a), begin(~br), 0., begin(c)); + BOOST_TEST( c[0][0] == 84.-7.*I ); + } + { + multi::array c({1, 1}); + auto br = +~b; + blas::gemm(1., a, blas::H(br), 0., ~c); + BOOST_TEST( c[0][0] == 80. + 53.*I ); + } + { + multi::array c({1, 1}); + auto br = +~b; + blas::gemm_n(1., begin(a), size(a), begin(blas::H(br)), 0., begin(~c)); + BOOST_TEST( c[0][0] == 80. + 53.*I ); + } + } + + BOOST_AUTO_TEST_CASE(multi_adaptors_blas_gemm_complex_hermitized_square) { + using complex = std::complex; + constexpr complex I{0, 1}; + multi::array const a = { + {1. + 3. * I, 3. + 2. * I}, + {9. + 1. * I, 7. + 1. * I}, + }; + multi::array const b = { + {11. + 2. * I, 12. + 4. * I}, + { 7. + 1. * I, 19. - 9. * I}, + }; + { + multi::array c({2, 2}); + blas::gemm(1., a, b, 0., c); // c=ab, c†=b†a† + BOOST_TEST( c[1][0] == 145. + 43.*I ); + } + { + multi::array c({2, 2}); + blas::gemm_n(1., begin(a), size(a), begin(b), 0., begin(c)); // c=ab, c†=b†a† + BOOST_TEST( c[1][0] == 145. + 43.*I ); + } + { + multi::array c({2, 2}); + blas::gemm(1., blas::H(a), blas::H(b), 0., c); // c=a†b†, c†=ba + BOOST_TEST( c[1][0] == 109.0 - 68.0*I ); + } + { + multi::array c({2, 2}); + blas::gemm_n(1., begin(blas::H(a)), size(blas::H(a)), begin(blas::H(b)), 0., begin(c)); // c=a†b†, c†=ba + BOOST_TEST( c[1][0] == 109.0 - 68.0*I ); + } + { + multi::array c({2, 2}); + blas::gemm(1., blas::H(a), blas::H(b), 0., blas::H(c)); // c†=a†b†, c=ba + BOOST_TEST( c[1][0] == 184.0 - 40.*I ); + } + { + multi::array c({2, 2}); + blas::gemm(1., blas::H(a), b, 0., c); // c=a†b, c†=b†a + BOOST_TEST( c[1][0] == 87.0 - 16.0*I ); + } + { + multi::array c({2, 2}); + blas::gemm_n(1., begin(blas::H(a)), size(blas::H(a)), begin(b), 0., begin(c)); // c=a†b, c†=b†a + BOOST_TEST( c[1][0] == 87.0 - 16.*I ); + } + { + multi::array c({2, 2}); + blas::gemm(1., a, blas::H(b), 0., c); // c=ab†, c†=ba† + BOOST_TEST( c[1][0] == 189.0 - 23.0*I ); + } + { + multi::array c({2, 2}); + c = blas::gemm(1., a, blas::H(b)); // c=ab†, c†=ba† + BOOST_TEST( c[1][0] == 189.0 - 23.0*I ); + } + { + multi::array c = blas::gemm(1., a, blas::H(b)); // c=ab†, c†=ba† + BOOST_TEST( size(c) == 2 ); + BOOST_TEST( c[1][0] == 189.0 - 23.0*I ); + } + { + auto c = multi::array(blas::gemm(1., a, blas::H(b))); // c=ab†, c†=ba† + BOOST_TEST( size(c) == 2 ); + BOOST_TEST( c[1][0] == 189.0 - 23.0*I ); + } + { + multi::array c({2, 2}); + blas::gemm_n(1., begin(a), size(a), begin(blas::H(b)), 0., begin(c)); // c=ab†, c†=ba† + BOOST_TEST( c[1][0] == 189. - 23.*I ); + } + { + multi::array c({2, 2}); + blas::gemm(1., blas::H(a), blas::H(b), 0., c); // c=a†b†, c†=ba + BOOST_TEST( c[1][0] == 109. - 68.*I); + } + { + multi::array c({2, 2}); + blas::gemm_n(1., begin(blas::H(a)), size(blas::H(a)), begin(blas::H(b)), 0., begin(c)); // c=a†b†, c†=ba + BOOST_TEST( c[1][0] == 109. - 68.*I); + } + } + + BOOST_AUTO_TEST_CASE(multi_adaptors_blas_gemm_complex_3x1_3x1) { + using complex = std::complex; + complex const I{0, 1}; + multi::array const a = { + {1. + 2. * I}, + {9. - 1. * I}, + {1. + 1. * I} + }; + multi::array const b = { + {11. - 2. * I}, + {7. - 3. * I}, + {8. - 1. * I} + }; + { + multi::array c({1, 1}); + blas::gemm(1., blas::H(a), b, 0., c); // c=ab, c⸆=b⸆a⸆ + BOOST_TEST( c[0][0] == 80.-53.*I ); + } + { + multi::array c({1, 1}); + blas::gemm_n(1., begin(blas::H(a)), size(blas::H(a)), begin(b), 0., begin(c)); // c=ab, c⸆=b⸆a⸆ + BOOST_TEST( c[0][0] == 80.-53.*I ); + } + { + multi::array c({1, 1}); + blas::gemm(1., blas::H(a), b, 0., c); // c=a†b, c†=b†a + BOOST_TEST( c[0][0] == 80.-53.*I ); + } + { + multi::array c({1, 1}); + blas::gemm_n(1., begin(blas::H(a)), size(blas::H(a)), begin(b), 0., begin(c)); // c=a†b, c†=b†a + BOOST_TEST( c[0][0] == 80.-53.*I ); + } + { + multi::array c({1, 1}); + auto ha = +blas::hermitized(a); + blas::gemm(1., ha, b, 0., c); + BOOST_TEST( c[0][0] == 80.-53.*I ); + + blas::gemm(1., blas::H(b), a, 0., c); + BOOST_TEST( c[0][0] == 80.+53.*I ); + } + { + multi::array c({1, 1}); + auto ha = +blas::hermitized(a); + blas::gemm_n(1., begin(ha), size(ha), begin(b), 0., begin(c)); + BOOST_TEST( c[0][0] == 80.-53.*I ); + + blas::gemm_n(1., begin(blas::H(b)), size(blas::H(b)), begin(a), 0., begin(c)); + BOOST_TEST( c[0][0] == 80.+53.*I ); + } + } + + BOOST_AUTO_TEST_CASE(multi_adaptors_blas_gemm_complex_1x3_3x2) { + using complex = std::complex; + constexpr complex I{0, 1}; + multi::array const a = { + {1. + 2. * I, 9. - 1. * I, 1. + 1. * I} + }; + multi::array const b = { + {11. - 2. * I, 5. + 2. * I}, + { 7. - 3. * I, 2. + 1. * I}, + { 8. - 1. * I, 1. + 1. * I} + }; + { + multi::array c({1, 2}); + blas::gemm(1., a, b, 0., c); // c=ab, c⸆=b⸆a⸆ + BOOST_TEST( c[0][1] == 20.+21.*I ); + } + { + multi::array c({1, 2}); + blas::gemm_n(1., begin(a), size(a), begin(b), 0., begin(c)); // c=ab, c⸆=b⸆a⸆ + BOOST_TEST( c[0][1] == 20.+21.*I ); + } + { + auto ar = +~a; + multi::array c({1, 2}); + blas::gemm(1., blas::H(ar), b, 0., c); // c=ab, c⸆=b⸆a⸆ + BOOST_TEST( c[0][1] == 28.+3.*I ); + } + { + auto ar = +~a; + multi::array c({1, 2}); + blas::gemm_n(1., begin(blas::H(ar)), size(blas::H(ar)), begin(b), 0., begin(c)); // c=ab, c⸆=b⸆a⸆ + BOOST_TEST( c[0][1] == 28.+3.*I ); + } + } + + BOOST_AUTO_TEST_CASE(multi_adaptors_blas_gemm_complex_3x1_3x2) { + using complex = std::complex; + complex const I{0, 1}; + multi::array const a = { + {1. + 2. * I}, + {9. - 1. * I}, + {1. + 1. * I} + }; + multi::array const b = { + {11. - 2. * I, 5. + 2. * I}, + { 7. - 3. * I, 2. + 1. * I}, + { 8. - 1. * I, 1. + 1. * I} + }; + { + multi::array c({1, 2}); + blas::gemm(1., blas::H(a), b, 0., c); // c=ab, c⸆=b⸆a⸆ + BOOST_TEST( c[0][1] == 28.+3.*I ); + } + { + multi::array c({1, 2}); + blas::gemm_n(1., begin(blas::H(a)), size(blas::H(a)), begin(b), 0., begin(c)); // c=ab, c⸆=b⸆a⸆ + BOOST_TEST( c[0][1] == 28.+3.*I ); + } + } + + BOOST_AUTO_TEST_CASE(multi_adaptors_blas_gemm_complex_3x2_3x2) { + using complex = std::complex; + complex const I{0, 1}; + multi::array const a = { + {1. + 2. * I, 5. + 2. * I}, + {9. - 1. * I, 9. + 1. * I}, + {1. + 1. * I, 2. + 2. * I} + }; + multi::array const b = { + {11. - 2. * I, 5. + 2. * I}, + { 7. - 3. * I, 2. + 1. * I}, + { 8. - 1. * I, 1. + 1. * I} + }; + { + multi::array c({2, 2}); + blas::gemm(1., blas::H(a), b, 0., c); // c=ab, c⸆=b⸆a⸆ + BOOST_TEST( c[1][0] == 125.-84.*I ); + } + { + multi::array c({2, 2}); + blas::gemm_n(1., begin(blas::H(a)), size(blas::H(a)), begin(b), 0., begin(c)); // c=ab, c⸆=b⸆a⸆ + BOOST_TEST( c[1][0] == 125.-84.*I ); + } + } + + BOOST_AUTO_TEST_CASE(multi_adaptors_blas_gemm_complex_3x2_3x1) { + using complex = std::complex; + complex const I{0, 1}; + multi::array const a = { + {1. + 2. * I, 5. + 2. * I}, + {9. - 1. * I, 9. + 1. * I}, + {1. + 1. * I, 2. + 2. * I} + }; + multi::array const b = { + {11. - 2. * I}, + {7. - 3. * I}, + {8. - 1. * I} + }; + { + multi::array c({2, 1}); + blas::gemm(1., blas::H(a), b, 0., c); // c=ab, c⸆=b⸆a⸆ + BOOST_TEST( c[1][0] == 125.-84.*I ); + } + { + multi::array c({2, 1}); + blas::gemm_n(1., begin(blas::H(a)), size(blas::H(a)), begin(b), 0., begin(c)); // c=ab, c⸆=b⸆a⸆ + BOOST_TEST( c[1][0] == 125.-84.*I ); + } + } + + BOOST_AUTO_TEST_CASE(multi_adaptors_blas_gemm_complex_3x1_3x1_bis) { + using complex = std::complex; + complex const I{0, 1}; + multi::array const a = { + {1. + 2. * I}, + {9. - 1. * I}, + {1. + 1. * I} + }; + multi::array const b = { + {11. - 2. * I}, + {7. - 3. * I}, + {8. - 1. * I} + }; + { + multi::array c({1, 1}); + blas::gemm(1., blas::H(a), b, 0., c); // c=ab, c⸆=b⸆a⸆ + BOOST_TEST( c[0][0] == 80. - 53.*I ); + } + { + multi::array c({1, 1}); + blas::gemm_n(1., begin(blas::H(a)), size(blas::H(a)), begin(b), 0., begin(c)); // c=ab, c⸆=b⸆a⸆ + BOOST_TEST( c[0][0] == 80. - 53.*I ); + } + } + + BOOST_AUTO_TEST_CASE(multi_adaptors_blas_gemm_real_square_automatic) { + multi::array const a = { + {1., 3.}, + {9., 7.}, + }; + multi::array const b = { + {11., 12.}, + { 7., 19.}, + }; + { + multi::array c({2, 2}); + blas::gemm(1., a, b, 0., c); // c=ab, c⸆=b⸆a⸆ + BOOST_TEST( c[1][0] == 148 && c[1][1] == 241 ); + } + { + multi::array c({2, 2}); + blas::gemm_n(1., begin(a), size(a), begin(b), 0., begin(c)); // c=ab, c⸆=b⸆a⸆ + BOOST_TEST( c[1][0] == 148 && c[1][1] == 241 ); + } + { + multi::array c({2, 2}); + blas::gemm(1., a, blas::T(b), 0., c); // c=ab, c⸆=b⸆a⸆ + BOOST_TEST( c[1][1] == 196. ); + } + { + multi::array c({2, 2}); + blas::gemm(1., blas::T(a), b, 0., c); // c=ab, c⸆=b⸆a⸆ + BOOST_TEST( c[1][1] == 169. ); + BOOST_TEST( c[1][0] == 82. ); + } + { + multi::array c({2, 2}); + blas::gemm(1., blas::T(a), blas::T(b), 0., c); // c=ab, c⸆=b⸆a⸆ + BOOST_TEST( c[1][1] == 154. ); + } + } + + BOOST_AUTO_TEST_CASE(multi_adaptors_blas_gemm_complex_square_automatic) { + using complex = std::complex; + complex const I{0, 1}; + multi::array const a = { + {1. + 2. * I, 3. - 3. * I}, + {9. + 1. * I, 7. + 4. * I}, + }; + multi::array const b = { + {11. + 1. * I, 12. + 1. * I}, + { 7. + 8. * I, 19. - 2. * I}, + }; + namespace blas = multi::blas; + { + multi::array c({2, 2}); + blas::gemm(1., a, b, 0., c); // c=ab, c⸆=b⸆a⸆ + BOOST_TEST( c[1][0] == complex(115, 104) ); + } + { + multi::array c({2, 2}); + blas::gemm_n(1., begin(a), size(a), begin(b), 0., begin(c)); // c=ab, c⸆=b⸆a⸆ + BOOST_TEST( c[1][0] == complex(115, 104) ); + } + { + multi::array c({2, 2}); + blas::gemm(1., a, blas::T(b), 0., c); // c=ab⸆, c⸆=ba⸆ + BOOST_TEST( c[1][0] == complex(178, 75) ); + } + { + multi::array c({2, 2}); + blas::gemm_n(1., begin(a), size(a), begin(blas::T(b)), 0., begin(c)); // c=ab⸆, c⸆=ba⸆ + BOOST_TEST( c[1][0] == complex(178.0, 75.0) ); + } + } + + BOOST_AUTO_TEST_CASE(multi_adaptors_blas_gemm_complex_square_automatic_part2) { + using complex = std::complex; + complex const I{0.0, 1.0}; + + multi::array const a = { + {1.0 + 2.0 * I, 3.0 - 3.0 * I}, + {9.0 + 1.0 * I, 7.0 + 4.0 * I}, + }; + multi::array const b = { + {11.0 + 1.0 * I, 12.0 + 1.0 * I}, + { 7.0 + 8.0 * I, 19.0 - 2.0 * I}, + }; + namespace blas = multi::blas; + { + multi::array c({2, 2}); + blas::gemm(1., blas::T(a), b, 0., c); // c=a⸆b, c⸆=b⸆a + BOOST_TEST(( c[1][1] == complex(180, 29) && c[1][0] == complex(53, 54) )); + } + { + multi::array c({2, 2}); + blas::gemm_n(1., begin(blas::T(a)), size(blas::T(a)), begin(b), 0., begin(c)); // c=a⸆b, c⸆=b⸆a + BOOST_TEST(( c[1][1] == complex(180, 29) && c[1][0] == complex(53, 54) )); + } + { + multi::array c({2, 2}); + blas::gemm(1., blas::T(a), blas::T(b), 0., c); // c=ab, c⸆=b⸆a⸆ + BOOST_TEST( c[1][1] == complex(186.0, 65.0) ); + BOOST_TEST( c[1][0] == complex(116, 25) ); + } + { + multi::array c({2, 2}); + blas::gemm_n(1., begin(blas::T(a)), size(blas::T(a)), begin(blas::T(b)), 0., begin(c)); // c=ab, c⸆=b⸆a⸆ + BOOST_TEST(( c[1][1] == complex(186, 65) && c[1][0] == complex(116.0, 25.0) )); + } + { + multi::array c({2, 2}); + blas::gemm(1., a, b, 0., c); // c=ab, c⸆=b⸆a⸆ + BOOST_TEST( c[1][0] == complex(115, 104) ); + } + { + multi::array c({2, 2}); + blas::gemm_n(1.0, begin(a), size(a), begin(b), 0.0, begin(c)); // c=ab, c⸆=b⸆a⸆ + BOOST_TEST( c[1][0] == complex(115, 104) ); + } + { + multi::array c({2, 2}); + blas::gemm(1., blas::H(a), b, 0., c); // c=a†b, c†=b†a + BOOST_TEST( c[1][0] == complex(111, 64) && c[1][1] == complex(158.0, -51.0) ); + } + } + + BOOST_AUTO_TEST_CASE(multi_adaptors_blas_gemm_complex_square_automatic_part3) { + using complex = std::complex; + complex const I{0.0, 1.0}; + + multi::array const a = { + {1.0 + 2.0 * I, 3.0 - 3.0 * I}, + {9.0 + 1.0 * I, 7.0 + 4.0 * I}, + }; + multi::array const b = { + {11.0 + 1.0 * I, 12.0 + 1.0 * I}, + { 7.0 + 8.0 * I, 19.0 - 2.0 * I}, + }; + namespace blas = multi::blas; + { + multi::array c({2, 2}); + blas::gemm_n(1., begin(blas::H(a)), size(blas::H(a)), begin(b), 0., begin(c)); // c=a†b, c†=b†a + BOOST_TEST( c[1][0] == complex(111, 64) && c[1][1] == complex(158, -51) ); + } + { + multi::array c({2, 2}); + blas::gemm(1., a, blas::H(b), 0.0, c); // c=ab†, c†=ba† + BOOST_TEST( c[1][0] == complex(188, 43) && c[1][1] == complex(196, 25) ); + auto c2 = +blas::gemm(1., a, blas::H(b)); + BOOST_TEST( c2 == c ); + } + { + multi::array c({2, 2}); + blas::gemm(0.1, a, blas::H(b), 0.0, c); // c=ab†, c†=ba† + auto const c2 = +blas::gemm(0.1, a, blas::H(b)); + BOOST_TEST( c2 == c ); + } + { + multi::array c({2, 2}); + blas::gemm(1., blas::H(a), blas::H(b), 0.0, c); // c=a†b†, c†=ba + BOOST_TEST( c[1][0] == complex(116, -25) && c[1][1] == complex(186, -65) ); + } + { + multi::array c({2, 2}); + blas::gemm_n(1., begin(blas::H(a)), size(blas::H(a)), begin(blas::H(b)), 0., begin(c)); // c=a†b†, c†=ba + BOOST_TEST( c[1][0] == complex(116, -25) && c[1][1] == complex(186, -65) ); + } + { + multi::array c({2, 2}); + blas::gemm(1., blas::T(a), blas::H(b), 0.0, c); // c=a⸆b†, c†=ba⸆† + BOOST_TEST( c[1][0] == complex(118, 5) && c[1][1] == complex(122, 45) ); + } + { + multi::array c({2, 2}); + blas::gemm_n(1., begin(blas::T(a)), size(blas::T(a)), begin(blas::H(b)), 0., begin(c)); // c=a⸆b†, c†=ba⸆† + BOOST_TEST( c[1][0] == complex(118, 5) && c[1][1] == complex(122, 45) ); + } + { + multi::array c({2, 2}); + blas::gemm(1.0, blas::T(a), blas::T(b), 0.0, c); // c=a⸆b⸆, c⸆=ba + BOOST_TEST( c[1][0] == complex(116, 25) && c[1][1] == complex(186, 65) ); + } + { + multi::array c({2, 2}); + blas::gemm_n(1.0, begin(blas::T(a)), size(blas::T(a)), begin(blas::T(b)), 0., begin(c)); // c=a⸆b⸆, c⸆=ba + BOOST_TEST( c[1][0] == complex(116, 25) && c[1][1] == complex(186, 65) ); + } + } + + BOOST_AUTO_TEST_CASE(multi_adaptors_blas_gemm_complex_nonsquare_automatic) { + using complex = std::complex; + complex const I{0.0, 1.0}; + + multi::array const a = { + {1.0 + 2.0 * I, 3.0 - 3.0 * I, 1.0 - 9.0 * I}, + {9.0 + 1.0 * I, 7.0 + 4.0 * I, 1.0 - 8.0 * I}, + }; + multi::array const b = { + {11.0 + 1.0 * I, 12.0 + 1.0 * I, 4.0 + 1.0 * I, 8.0 - 2.0 * I}, + { 7.0 + 8.0 * I, 19.0 - 2.0 * I, 2.0 + 1.0 * I, 7.0 + 1.0 * I}, + { 5.0 + 1.0 * I, 3.0 - 1.0 * I, 3.0 + 8.0 * I, 1.0 + 1.0 * I} + }; + { + multi::array c({2, 4}); + blas::gemm(1., a, b, 0., c); // c=ab, c⸆=b⸆a⸆ + BOOST_TEST( c[1][2] == complex(112, 12) ); + } + { + multi::array c({2, 4}); + blas::gemm_n(1., begin(a), size(a), begin(b), 0., begin(c)); // c=ab, c⸆=b⸆a⸆ + BOOST_TEST( c[1][2] == complex(112, 12) ); + } + } + + BOOST_AUTO_TEST_CASE(multi_adaptors_blas_gemm_realcomplex_complex_nonsquare_automatic) { + using complex = std::complex; + + complex const I{0.0, 1.0}; + + multi::array const a = { + {1.0, 3.0, 1.0}, + {9.0, 7.0, 1.0}, + }; + multi::array const b = { + {11. + 1. * I, 12. + 1. * I, 4. + 1. * I, 8. - 2. * I}, + { 7. + 8. * I, 19. - 2. * I, 2. + 1. * I, 7. + 1. * I}, + { 5. + 1. * I, 3. - 1. * I, 3. + 8. * I, 1. + 1. * I} + }; + { + multi::array c = blas::gemm(1., a, b); // c=ab, c⸆=b⸆a⸆ + BOOST_TEST( c[1][2] == complex(53, 24) ); + } + { + multi::array c({2, 4}); + c = blas::gemm(1., a, b); // c=ab, c⸆=b⸆a⸆ + BOOST_TEST( c[1][2] == complex(53, 24) ); + } + { + multi::array c({2, 4}); + blas::gemm(1., a, b, 0., c); // c=ab, c⸆=b⸆a⸆ + BOOST_TEST( c[1][2] == complex(53, 24) ); + } + { + multi::array c({2, 4}); + blas::gemm_n(1., begin(a), size(a), begin(b), 0., begin(c)); // c=ab, c⸆=b⸆a⸆ + BOOST_TEST( c[1][2] == complex(53, 24) ); + } + { + multi::array const a_real = { + {1., 3., 1.}, + {9., 7., 1.}, + }; + multi::array c({2, 4}); + blas::real_doubled(c) = blas::gemm(1., a_real, blas::real_doubled(b)); + + BOOST_TEST( c[1][2] == complex(53, 24) ); + } + } + + BOOST_AUTO_TEST_CASE(submatrix_result_issue_97) { + using complex = std::complex; + + constexpr complex I{0.0, 1.0}; + + multi::array M = { + {2.0 + 3.0 * I, 2.0 + 1.0 * I, 1.0 + 2.0 * I}, + {4.0 + 2.0 * I, 2.0 + 4.0 * I, 3.0 + 1.0 * I}, + {7.0 + 1.0 * I, 1.0 + 5.0 * I, 0.0 + 3.0 * I}, + }; + auto M2 = +M({0, 3}, {0, 1}); + BOOST_TEST( M2 == M({0, 3}, {0, 1}) ); + } + + BOOST_AUTO_TEST_CASE(blas_context_gemm) { + using complex = std::complex; + + static constexpr complex I{0, 1}; + + auto rand = [d = std::normal_distribution<>{}, g = std::mt19937{}]() mutable { // NOLINT(cert-msc32-c, cert-msc51-cpp) for test purposes + return d(g) + d(g) * I; + }; + + multi::array A({30, 40}); + multi::array B({40, 50}); + + std::generate(A.elements().begin(), A.elements().end(), rand); + std::generate(B.elements().begin(), B.elements().end(), rand); + } + + BOOST_AUTO_TEST_CASE(multi_adaptors_blas_gemm_real_nonsquare_hermitized_second_gemm_range) { + multi::array const a({2, 3}, 0.); + multi::array const b({4, 3}, 0.); + { + multi::array c({2, 4}); + c() = blas::gemm(0.1, a, blas::H(b)); + BOOST_REQUIRE_CLOSE(c[1][2], 0., 0.00001); + } + { + multi::array c = blas::gemm(0.1, a, blas::H(b)); // c=ab⸆, c⸆=ba⸆ + BOOST_TEST( c[1][2] == 0. ); + } + { + multi::array const a = { + {1, 3, 1}, + {9, 7, 1}, + }; + (void)a; + } + } + + BOOST_AUTO_TEST_CASE(multi_adaptors_blas_gemm_complex_nonsquare_hermitized_second_gemm_range) { + using complex = std::complex; + + multi::array const a({2, 3}, 0.); + multi::array const b({4, 3}, 0.); + { + multi::array c({2, 4}, 999.); + blas::gemm_n(1., begin(a), size(a), begin(blas::H(b)), 0., begin(c)); + BOOST_TEST( c[1][2] != 999. ); + } + { + multi::array c = blas::gemm(1., a, blas::H(b)); // c=ab⸆, c⸆=ba⸆ + BOOST_TEST( c[1][2] == 0. ); + } + } + + BOOST_AUTO_TEST_CASE(multi_adaptors_blas_gemm_real_nonsquare_hermitized_second) { + namespace blas = multi::blas; + multi::array const a = { {1, 3, 1}, {9, 7, 1}, }; - (void)a; + multi::array const b = { + {11, 7, 5}, + {12, 19, 3}, + { 4, 2, 3}, + { 8, 7, 1} + }; + { + multi::array c({2, 4}); + blas::gemm(1., a, blas::H(b), 0., c); // c=ab, c⸆=b⸆a⸆ + BOOST_TEST( c[1][2] == 53. ); + } + { + multi::array c({2, 4}); + blas::gemm_n(1., begin(a), size(a), begin(blas::H(b)), 0., begin(c)); // c=ab, c⸆=b⸆a⸆ + BOOST_TEST( c[1][2] == 53. ); + } + { + multi::array c({2, 4}); + blas::gemm(0.1, a, blas::H(b), 0., c); // c=ab, c⸆=b⸆a⸆ + BOOST_REQUIRE_CLOSE(c[1][2], 5.3, 0.00001); + } + { + multi::array c({2, 4}); + blas::gemm_n(0.1, begin(a), size(a), begin(blas::H(b)), 0., begin(c)); // c=ab, c⸆=b⸆a⸆ + BOOST_REQUIRE_CLOSE(c[1][2], 5.3, 0.00001); + } + { + multi::array c({2, 4}); + c() = blas::gemm(0.1, a, blas::H(b)); + } + { + multi::array c = blas::gemm(0.1, a, blas::H(b)); // c=ab⸆, c⸆=ba⸆ + BOOST_REQUIRE_CLOSE(c[1][2], 5.3, 0.00001); + } + } + + BOOST_AUTO_TEST_CASE(multi_adaptors_blas_gemm_complex_real_nonsquare_hermitized_second) { + namespace blas = multi::blas; + using complex = std::complex; + + multi::array const a = { + {1., 3., 1.}, + {9., 7., 1.}, + }; + multi::array const b = { + {11., 7., 5.}, + {12., 19., 3.}, + { 4., 2., 3.}, + { 8., 7., 1.} + }; + { + multi::array c({2, 4}); + blas::gemm(1., a, blas::H(b), 0., c); // c=ab, c⸆=b⸆a⸆ + BOOST_TEST( c[1][2] == 53. ); + } + { + multi::array c({2, 4}); + blas::gemm_n(1., begin(a), size(a), begin(blas::H(b)), 0., begin(c)); // c=ab, c⸆=b⸆a⸆ + BOOST_REQUIRE_CLOSE(c[1][2], 53.0, 1E-6); + } + { + multi::array c({2, 4}); + blas::gemm(0.1, a, blas::H(b), 0., c); // c=ab, c⸆=b⸆a⸆ + BOOST_REQUIRE_CLOSE(real(c[1][2]), 5.3, 0.00001); + } + { + multi::array c({2, 4}); + blas::gemm_n(0.1, begin(a), size(a), begin(blas::H(b)), 0., begin(c)); // c=ab, c⸆=b⸆a⸆ + BOOST_REQUIRE_CLOSE(real(c[1][2]), 5.3, 0.00001); + } + { + multi::array c({2, 4}); + c() = blas::gemm(0.1, a, blas::H(b)); + } + { + multi::array c = blas::gemm(0.1, a, blas::H(b)); // c=ab⸆, c⸆=ba⸆ + BOOST_REQUIRE_CLOSE(real(c[1][2]), 5.3, 0.00001); + } + } + + BOOST_AUTO_TEST_CASE(blas_gemm_1xn_complex) { + using complex = std::complex; + multi::array const a({1, 100}, 1.); + multi::array const b({1, 100}, 1.); + + multi::array c({1, 1}, 999.); + blas::gemm_n(1., begin(a), size(a), begin(blas::H(b)), 0., begin(c)); + BOOST_TEST( c[0][0] == 100. ); } -} -BOOST_AUTO_TEST_CASE(multi_adaptors_blas_gemm_complex_nonsquare_hermitized_second_gemm_range) { - using complex = std::complex; - multi::array const a({2, 3}, 0.); - multi::array const b({4, 3}, 0.); - { - multi::array c({2, 4}, 999.); + BOOST_AUTO_TEST_CASE(blas_gemm_nx1_times_1x1_complex_inq_hydrogen_case) { + using complex = std::complex; + complex const I{0, 1}; + + multi::array const a({3, 1}, 2. + 1. * I); + multi::array const b({1, 1}, 3. + 4. * I); + + multi::array c({3, 1}, 999.); blas::gemm_n(1., begin(a), size(a), begin(blas::H(b)), 0., begin(c)); - BOOST_REQUIRE( c[1][2] != 999. ); - } - { - multi::array c = blas::gemm(1., a, blas::H(b)); // c=ab⸆, c⸆=ba⸆ - BOOST_REQUIRE( c[1][2] == 0. ); - } -} - -BOOST_AUTO_TEST_CASE(multi_adaptors_blas_gemm_real_nonsquare_hermitized_second) { - namespace blas = multi::blas; - multi::array const a = { - {1, 3, 1}, - {9, 7, 1}, - }; - multi::array const b = { - {11, 7, 5}, - {12, 19, 3}, - { 4, 2, 3}, - { 8, 7, 1} - }; - { - multi::array c({2, 4}); - blas::gemm(1., a, blas::H(b), 0., c); // c=ab, c⸆=b⸆a⸆ - BOOST_REQUIRE( c[1][2] == 53. ); - } - { - multi::array c({2, 4}); - blas::gemm_n(1., begin(a), size(a), begin(blas::H(b)), 0., begin(c)); // c=ab, c⸆=b⸆a⸆ - BOOST_REQUIRE( c[1][2] == 53. ); - } - { - multi::array c({2, 4}); - blas::gemm(0.1, a, blas::H(b), 0., c); // c=ab, c⸆=b⸆a⸆ - BOOST_REQUIRE_CLOSE(c[1][2], 5.3, 0.00001); - } - { - multi::array c({2, 4}); - blas::gemm_n(0.1, begin(a), size(a), begin(blas::H(b)), 0., begin(c)); // c=ab, c⸆=b⸆a⸆ - BOOST_REQUIRE_CLOSE(c[1][2], 5.3, 0.00001); - } - { - multi::array c({2, 4}); - c() = blas::gemm(0.1, a, blas::H(b)); - } - { - multi::array c = blas::gemm(0.1, a, blas::H(b)); // c=ab⸆, c⸆=ba⸆ - BOOST_REQUIRE_CLOSE(c[1][2], 5.3, 0.00001); - } -} - -BOOST_AUTO_TEST_CASE(multi_adaptors_blas_gemm_complex_real_nonsquare_hermitized_second) { - namespace blas = multi::blas; - using complex = std::complex; - multi::array const a = { - {1., 3., 1.}, - {9., 7., 1.}, - }; - multi::array const b = { - {11., 7., 5.}, - {12., 19., 3.}, - { 4., 2., 3.}, - { 8., 7., 1.} - }; - { - multi::array c({2, 4}); - blas::gemm(1., a, blas::H(b), 0., c); // c=ab, c⸆=b⸆a⸆ - BOOST_REQUIRE( c[1][2] == 53. ); - } - { - multi::array c({2, 4}); - blas::gemm_n(1., begin(a), size(a), begin(blas::H(b)), 0., begin(c)); // c=ab, c⸆=b⸆a⸆ - BOOST_REQUIRE( c[1][2] == 53. ); - } - { - multi::array c({2, 4}); - blas::gemm(0.1, a, blas::H(b), 0., c); // c=ab, c⸆=b⸆a⸆ - BOOST_REQUIRE_CLOSE(real(c[1][2]), 5.3, 0.00001); - } - { - multi::array c({2, 4}); - blas::gemm_n(0.1, begin(a), size(a), begin(blas::H(b)), 0., begin(c)); // c=ab, c⸆=b⸆a⸆ - BOOST_REQUIRE_CLOSE(real(c[1][2]), 5.3, 0.00001); - } - { - multi::array c({2, 4}); - c() = blas::gemm(0.1, a, blas::H(b)); - } - { - multi::array c = blas::gemm(0.1, a, blas::H(b)); // c=ab⸆, c⸆=ba⸆ - BOOST_REQUIRE_CLOSE(real(c[1][2]), 5.3, 0.00001); - } -} - -BOOST_AUTO_TEST_CASE(blas_gemm_1xn_complex) { - using complex = std::complex; - multi::array const a({1, 100}, 1.); - multi::array const b({1, 100}, 1.); - - multi::array c({1, 1}, 999.); - blas::gemm_n(1., begin(a), size(a), begin(blas::H(b)), 0., begin(c)); - BOOST_REQUIRE( c[0][0] == 100. ); -} - -BOOST_AUTO_TEST_CASE(blas_gemm_nx1_times_1x1_complex_inq_hydrogen_case) { - using complex = std::complex; - complex const I{0, 1}; - multi::array const a({3, 1}, 2. + 1. * I); - multi::array const b({1, 1}, 3. + 4. * I); - - multi::array c({3, 1}, 999.); - blas::gemm_n(1., begin(a), size(a), begin(blas::H(b)), 0., begin(c)); - BOOST_TEST_REQUIRE( c[0][0] == (2. + 1.*I)*std::conj(3. + 4.*I) ); - BOOST_TEST_REQUIRE( c[1][0] == (2. + 1.*I)*std::conj(3. + 4.*I) ); - BOOST_TEST_REQUIRE( c[2][0] == (2. + 1.*I)*std::conj(3. + 4.*I) ); -} - -BOOST_AUTO_TEST_CASE(blas_gemm_nx1_times_1x1_complex_inq_hydrogen_case_no_n_interface) { - using complex = std::complex; - complex const I{0, 1}; - multi::array const a({3, 1}, 2. + 1. * I); - multi::array const b({10, 1}, 3. + 4. * I); - - multi::array c({3, 10}, 999.); - blas::gemm(1., a, blas::H(b), 0., c); - BOOST_TEST_REQUIRE( c[0][0] == (2. + 1.*I)*std::conj(3. + 4.*I) ); - BOOST_TEST_REQUIRE( c[1][0] == (2. + 1.*I)*std::conj(3. + 4.*I) ); - BOOST_TEST_REQUIRE( c[0][1] == (2. + 1.*I)*std::conj(3. + 4.*I) ); -} - -BOOST_AUTO_TEST_CASE(blas_gemm_nx1_times_1x1_1x1_complex_inq_hydrogen_case_complex_value_hermitized) { - using complex = std::complex; - complex const I{0, 1}; - multi::array const a({1, 1}, 2. + 1. * I); - multi::array const b({1, 1}, 3. + 4. * I); - - multi::array c({1, 1}, 999.); - c = blas::gemm(1., a, blas::H(b)); - BOOST_REQUIRE( c[0][0] == (2. + 1.*I)*std::conj(3. + 4.*I) ); -} - -BOOST_AUTO_TEST_CASE(blas_gemm_nx1_times_1x1_1x1_complex_inq_hydrogen_case_complex_value) { - using complex = std::complex; - complex const I{0, 1}; - multi::array const a({1, 1}, 2. + 1. * I); - multi::array const b({1, 1}, 3. + 4. * I); - - multi::array c({1, 1}, 999.); - c = blas::gemm(1., a, b); - BOOST_REQUIRE( c[0][0] == (2. + 1.*I)*(3. + 4.*I) ); -} - -BOOST_AUTO_TEST_CASE(blas_gemm_nx1_times_1x1_1x1_complex_inq_hydrogen_case) { - using complex = std::complex; - multi::array const a({1, 1}, 2.); - multi::array const b({1, 1}, 3.); - - multi::array c({1, 1}, 999.); - c = blas::gemm(1., a, b); - BOOST_REQUIRE( c[0][0] == 6. ); -} - -BOOST_AUTO_TEST_CASE(blas_gemm_inq_case) { // https://gitlab.com/correaa/boost-multi/-/issues/97 - using complex = std::complex; - complex const I{0, 1}; - multi::array mat({10, 2}, 1.0 + 3. * I); - multi::array vec({10, 1}, -2.0 + 4. * I); - - mat({0, 10}, {1, 2}) = vec; - - namespace blas = multi::blas; - - { - auto olap1 = +blas::gemm(1., blas::H(mat), vec); - auto olap2 = +blas::gemm(1., blas::H(mat({0, 10}, {0, 1})), vec); - - BOOST_REQUIRE( blas::H(mat)[1].size() == (~vec)[0].size() ); - BOOST_REQUIRE( blas::dot(blas::H(mat)[0], (~vec)[0]) == olap1[0][0] ); - BOOST_REQUIRE( std::inner_product(blas::H(mat)[0].begin(), blas::H(mat)[0].end(), (~vec)[0].begin(), complex{0}) == olap1[0][0] ); - - multi::array mat2 = mat({0, 10}, {0, 1}); - auto olap3 = +blas::gemm(1., blas::H(mat2), vec); - - BOOST_REQUIRE(olap1[0][0] == olap2[0][0]); - BOOST_REQUIRE(olap3[0][0] == olap2[0][0]); - } - { - multi::array mat2 = mat({0, 3}, {0, 1}); - auto olap3 = +blas::gemm(1., blas::H(mat({0, 3}, {0, 1})), vec); - BOOST_REQUIRE( (+blas::gemm(1., blas::H(mat2), vec))[0][0] == (+blas::gemm(1., blas::H(mat({0, 3}, {0, 1})), vec))[0][0] ); - } -} - -BOOST_AUTO_TEST_CASE(blas_issue_109_part2) { - multi::array const A({3, 4}, 5.); // NOLINT(readability-identifier-length) BLAS naming - multi::array const B({2, 3}, 7.); // NOLINT(readability-identifier-length) BLAS naming - - multi::array C({2, 4}, 999.0); // NOLINT(readability-identifier-length) BLAS naming - blas::gemm(1.0, ~A, ~B, 0.0, ~C); - - BOOST_TEST_REQUIRE( C[0][0] == 105.0 ); - BOOST_TEST_REQUIRE( C[0][1] == 105.0 ); - BOOST_TEST_REQUIRE( C[1][0] == 105.0 ); -} - -BOOST_AUTO_TEST_CASE(blas_issue_109) { - multi::array const A({3, 4}, 5.0); // NOLINT(readability-identifier-length) BLAS naming - multi::array const B({2, 3}, 7.0); // NOLINT(readability-identifier-length) BLAS naming - - multi::array C({4, 2}, 999.0); // NOLINT(readability-identifier-length) BLAS naming - blas::gemm(1., ~A, ~B, 0., C); - - BOOST_TEST_REQUIRE( C[0][0] == 105.0 ); - BOOST_TEST_REQUIRE( C[0][1] == 105.0 ); - BOOST_TEST_REQUIRE( C[1][0] == 105.0 ); -} - -BOOST_AUTO_TEST_CASE(blas_issue_109_part2_complex) { - multi::array, 2> const A({3, 4}, {5.0, 0.0}); // NOLINT(readability-identifier-length) BLAS naming - multi::array, 2> const B({2, 3}, {7.0, 0.0}); // NOLINT(readability-identifier-length) BLAS naming - - multi::array, 2> C({2, 4}, {999.0, 0.0}); // NOLINT(readability-identifier-length) BLAS naming - blas::gemm({1.0, 0.0}, ~A, ~B, {0.0, 0.0}, ~C); - - BOOST_TEST_REQUIRE( C[0][0] == 105.0 ); - BOOST_TEST_REQUIRE( C[0][1] == 105.0 ); - BOOST_TEST_REQUIRE( C[1][0] == 105.0 ); -} - -BOOST_AUTO_TEST_CASE(blas_issue_109_complex) { - multi::array, 2> const A({3, 4}, {5.0, 0.0}); // NOLINT(readability-identifier-length) BLAS naming - multi::array, 2> const B({2, 3}, {7.0, 0.0}); // NOLINT(readability-identifier-length) BLAS naming - - multi::array, 2> C({4, 2}, {999.0, 0.0}); // NOLINT(readability-identifier-length) BLAS naming - blas::gemm({1.0, 0.0}, ~A, ~B, {0.0, 0.0}, C); + BOOST_TEST_REQUIRE( c[0][0] == (2. + 1.*I)*std::conj(3. + 4.*I) ); + BOOST_TEST_REQUIRE( c[1][0] == (2. + 1.*I)*std::conj(3. + 4.*I) ); + BOOST_TEST_REQUIRE( c[2][0] == (2. + 1.*I)*std::conj(3. + 4.*I) ); + } + + BOOST_AUTO_TEST_CASE(blas_gemm_nx1_times_1x1_complex_inq_hydrogen_case_no_n_interface) { + using complex = std::complex; + complex const I{0, 1}; + multi::array const a({3, 1}, 2. + 1. * I); + multi::array const b({10, 1}, 3. + 4. * I); + + multi::array c({3, 10}, 999.); + blas::gemm(1., a, blas::H(b), 0., c); + BOOST_TEST_REQUIRE( c[0][0] == (2. + 1.*I)*std::conj(3. + 4.*I) ); + BOOST_TEST_REQUIRE( c[1][0] == (2. + 1.*I)*std::conj(3. + 4.*I) ); + BOOST_TEST_REQUIRE( c[0][1] == (2. + 1.*I)*std::conj(3. + 4.*I) ); + } + + BOOST_AUTO_TEST_CASE(blas_gemm_nx1_times_1x1_1x1_complex_inq_hydrogen_case_complex_value_hermitized) { + using complex = std::complex; + complex const I{0, 1}; + multi::array const a({1, 1}, 2. + 1. * I); + multi::array const b({1, 1}, 3. + 4. * I); + + multi::array c({1, 1}, 999.); + c = blas::gemm(1., a, blas::H(b)); + BOOST_TEST( c[0][0] == (2. + 1.*I)*std::conj(3. + 4.*I) ); + } + + BOOST_AUTO_TEST_CASE(blas_gemm_nx1_times_1x1_1x1_complex_inq_hydrogen_case_complex_value) { + using complex = std::complex; + complex const I{0, 1}; + multi::array const a({1, 1}, 2. + 1. * I); + multi::array const b({1, 1}, 3. + 4. * I); + + multi::array c({1, 1}, 999.); + c = blas::gemm(1., a, b); + BOOST_TEST( c[0][0] == (2. + 1.*I)*(3. + 4.*I) ); + } + + BOOST_AUTO_TEST_CASE(blas_gemm_nx1_times_1x1_1x1_complex_inq_hydrogen_case) { + using complex = std::complex; + multi::array const a({1, 1}, 2.); + multi::array const b({1, 1}, 3.); + + multi::array c({1, 1}, 999.); + c = blas::gemm(1., a, b); + BOOST_TEST( c[0][0] == 6. ); + } + + BOOST_AUTO_TEST_CASE(blas_gemm_inq_case) { // https://gitlab.com/correaa/boost-multi/-/issues/97 + using complex = std::complex; + complex const I{0, 1}; + + multi::array mat({10, 2}, 1.0 + 3. * I); + multi::array vec({10, 1}, -2.0 + 4. * I); + + mat({0, 10}, {1, 2}) = vec; + + namespace blas = multi::blas; + + { + auto olap1 = +blas::gemm(1., blas::H(mat), vec); + auto olap2 = +blas::gemm(1., blas::H(mat({0, 10}, {0, 1})), vec); + + BOOST_TEST( blas::H(mat)[1].size() == (~vec)[0].size() ); + BOOST_TEST( blas::dot(blas::H(mat)[0], (~vec)[0]) == olap1[0][0] ); + BOOST_TEST( std::inner_product(blas::H(mat)[0].begin(), blas::H(mat)[0].end(), (~vec)[0].begin(), complex{0}) == olap1[0][0] ); + + multi::array mat2 = mat({0, 10}, {0, 1}); + auto olap3 = +blas::gemm(1., blas::H(mat2), vec); - BOOST_TEST_REQUIRE( C[0][0] == 105.0 ); - BOOST_TEST_REQUIRE( C[0][1] == 105.0 ); - BOOST_TEST_REQUIRE( C[1][0] == 105.0 ); -} + BOOST_TEST(olap1[0][0] == olap2[0][0]); + BOOST_TEST(olap3[0][0] == olap2[0][0]); + } + { + multi::array mat2 = mat({0, 3}, {0, 1}); + auto olap3 = +blas::gemm(1., blas::H(mat({0, 3}, {0, 1})), vec); + BOOST_TEST( (+blas::gemm(1., blas::H(mat2), vec))[0][0] == (+blas::gemm(1., blas::H(mat({0, 3}, {0, 1})), vec))[0][0] ); + } + } + + BOOST_AUTO_TEST_CASE(blas_issue_109_part2) { + multi::array const A({3, 4}, 5.); // NOLINT(readability-identifier-length) BLAS naming + multi::array const B({2, 3}, 7.); // NOLINT(readability-identifier-length) BLAS naming + + multi::array C({2, 4}, 999.0); // NOLINT(readability-identifier-length) BLAS naming + blas::gemm(1.0, ~A, ~B, 0.0, ~C); + + BOOST_TEST_REQUIRE( C[0][0] == 105.0 ); + BOOST_TEST_REQUIRE( C[0][1] == 105.0 ); + BOOST_TEST_REQUIRE( C[1][0] == 105.0 ); + } + + BOOST_AUTO_TEST_CASE(blas_issue_109) { + multi::array const A({3, 4}, 5.0); // NOLINT(readability-identifier-length) BLAS naming + multi::array const B({2, 3}, 7.0); // NOLINT(readability-identifier-length) BLAS naming + + multi::array C({4, 2}, 999.0); // NOLINT(readability-identifier-length) BLAS naming + blas::gemm(1., ~A, ~B, 0., C); + + BOOST_TEST_REQUIRE( C[0][0] == 105.0 ); + BOOST_TEST_REQUIRE( C[0][1] == 105.0 ); + BOOST_TEST_REQUIRE( C[1][0] == 105.0 ); + } + + BOOST_AUTO_TEST_CASE(blas_issue_109_part2_complex) { + multi::array, 2> const A({3, 4}, {5.0, 0.0}); // NOLINT(readability-identifier-length) BLAS naming + multi::array, 2> const B({2, 3}, {7.0, 0.0}); // NOLINT(readability-identifier-length) BLAS naming + + multi::array, 2> C({2, 4}, {999.0, 0.0}); // NOLINT(readability-identifier-length) BLAS naming + blas::gemm({1.0, 0.0}, ~A, ~B, {0.0, 0.0}, ~C); + + BOOST_TEST_REQUIRE( C[0][0] == 105.0 ); + BOOST_TEST_REQUIRE( C[0][1] == 105.0 ); + BOOST_TEST_REQUIRE( C[1][0] == 105.0 ); + } + + BOOST_AUTO_TEST_CASE(blas_issue_109_complex) { + multi::array, 2> const A({3, 4}, {5.0, 0.0}); // NOLINT(readability-identifier-length) BLAS naming + multi::array, 2> const B({2, 3}, {7.0, 0.0}); // NOLINT(readability-identifier-length) BLAS naming + + multi::array, 2> C({4, 2}, {999.0, 0.0}); // NOLINT(readability-identifier-length) BLAS naming + blas::gemm({1.0, 0.0}, ~A, ~B, {0.0, 0.0}, C); + + BOOST_TEST( C[0][0] == 105.0 ); + BOOST_TEST( C[0][1] == 105.0 ); + BOOST_TEST( C[1][0] == 105.0 ); + } #endif -BOOST_AUTO_TEST_CASE(blas_issue_109_complex_mx2) { - multi::array, 2> const A({3, 4}, {5.0, 0.0}); // NOLINT(readability-identifier-length) BLAS naming - multi::array, 2> const B({2, 3}, {7.0, 0.0}); // NOLINT(readability-identifier-length) BLAS naming + BOOST_AUTO_TEST_CASE(blas_issue_109_complex_mx2) { + multi::array, 2> const A({3, 4}, {5.0, 0.0}); // NOLINT(readability-identifier-length) BLAS naming + multi::array, 2> const B({2, 3}, {7.0, 0.0}); // NOLINT(readability-identifier-length) BLAS naming - multi::array, 2> C({4, 2}, {999.0, 0.0}); // NOLINT(readability-identifier-length) BLAS naming - blas::gemm({1.0, 0.0}, ~A, ~B, {0.0, 0.0}, C); + multi::array, 2> C({4, 2}, {999.0, 0.0}); // NOLINT(readability-identifier-length) BLAS naming + blas::gemm({1.0, 0.0}, ~A, ~B, {0.0, 0.0}, C); - BOOST_TEST_REQUIRE( C[0][0] == 105.0 ); - BOOST_TEST_REQUIRE( C[1][0] == 105.0 ); -} + BOOST_TEST( C[0][0] == 105.0 ); + BOOST_TEST( C[1][0] == 105.0 ); + } -BOOST_AUTO_TEST_CASE(blas_issue_109_complex_mx1) { - multi::array, 2> const A({3, 4}, {5.0, 0.0}); // NOLINT(readability-identifier-length) BLAS naming - multi::array, 2> const B({1, 3}, {7.0, 0.0}); // NOLINT(readability-identifier-length) BLAS naming + BOOST_AUTO_TEST_CASE(blas_issue_109_complex_mx1) { + multi::array, 2> const A({3, 4}, {5.0, 0.0}); // NOLINT(readability-identifier-length) BLAS naming + multi::array, 2> const B({1, 3}, {7.0, 0.0}); // NOLINT(readability-identifier-length) BLAS naming - multi::array, 2> C({4, 1}, {999.0, 0.0}); // NOLINT(readability-identifier-length) BLAS naming - blas::gemm(std::complex{1.0, 0.0}, ~A, ~B, std::complex{0.0, 0.0}, C); + multi::array, 2> C({4, 1}, {999.0, 0.0}); // NOLINT(readability-identifier-length) BLAS naming + blas::gemm(std::complex{1.0, 0.0}, ~A, ~B, std::complex{0.0, 0.0}, C); - BOOST_TEST_REQUIRE( C[0][0] == 105.0 ); - BOOST_TEST_REQUIRE( C[1][0] == 105.0 ); -} + BOOST_TEST( C[0][0] == 105.0 ); + BOOST_TEST( C[1][0] == 105.0 ); + } -BOOST_AUTO_TEST_CASE(blas_issue_109_double_mx1) { - multi::array const A({3, 4}, 5.0); // NOLINT(readability-identifier-length) BLAS naming - multi::array const B({1, 3}, 7.0); // NOLINT(readability-identifier-length) BLAS naming + BOOST_AUTO_TEST_CASE(blas_issue_109_double_mx1) { + multi::array const A({3, 4}, 5.0); // NOLINT(readability-identifier-length) BLAS naming + multi::array const B({1, 3}, 7.0); // NOLINT(readability-identifier-length) BLAS naming - multi::array C({4, 1}, 999.0); // NOLINT(readability-identifier-length) BLAS naming - blas::gemm(1.0, ~A, ~B, 0.0, C); + multi::array C({4, 1}, 999.0); // NOLINT(readability-identifier-length) BLAS naming + blas::gemm(1.0, ~A, ~B, 0.0, C); + + BOOST_TEST( C[0][0] == 105.0 ); + BOOST_TEST( C[1][0] == 105.0 ); + } - BOOST_TEST_REQUIRE( C[0][0] == 105.0 ); - BOOST_TEST_REQUIRE( C[1][0] == 105.0 ); -} + return boost::report_errors(); +} // NOLINT(readability/fn_size) diff --git a/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/test/gemv.cpp b/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/test/gemv.cpp index 2f43dd1b1b..8229fe4db5 100644 --- a/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/test/gemv.cpp +++ b/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/test/gemv.cpp @@ -1,25 +1,34 @@ // Copyright 2020-2024 Alfredo A. Correa - -#include - -#include - -#include "../../../adaptors/blas/gemv.hpp" -#include "../../../array.hpp" - -#include "../../../utility.hpp" - -#include "../../blas/axpy.hpp" -#include "../../blas/dot.hpp" -#include "../../blas/gemm.hpp" -#include "../../blas/nrm2.hpp" - -#include +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include // for operator- +#include // for gemv, context, dot, nrm2 +#include // for dot, dot_ref +#include // for gemv_range, gemv, oper... +#include // for operator^ +#include // for array, layout_t, array... + +#include + +// #include // for list + +#include // for generate, transform +#include // for abs +#include // for complex, operator* +#include // for char_traits, basic_ost... +#include // for size, begin +// IWYU pragma: no_include // for allocator +#include // for inner_product +#include // for normal_distribution +#include // for is_same_v +#include // for move, forward +// IWYU pragma: no_include // for abs namespace multi = boost::multi; namespace blas = multi::blas; -using fp_types = boost::mpl::list; // old versions of Boost.Test need MPL Type lists explicitly +// using fp_types = boost::mpl::list; // old versions of Boost.Test need MPL Type lists explicitly template auto MV(M const& a, VI const& x, VO&& y) -> VO&& { // NOLINT(readability-identifier-naming,readability-identifier-length) BLAS naming @@ -30,262 +39,482 @@ auto MV(M const& a, VI const& x, VO&& y) -> VO&& { // NOLINT(readability-identi return std::forward(y); } -// #ifdef _MULTI_USING_BLAS_MKL -// #include // for mkl_free_buffers -// struct Fixture { -// Fixture() {mkl_disable_fast_mm(); } // this is reported to solve memory leaks, but it doesn't with BLA_VENDOR=Intel10_64ilp (non seq) and INTEL_MKL_VERSION 20200004 -// ~Fixture() { mkl_free_buffers(); } // this is reported to solve memory leaks, but it doesn't with BLA_VENDOR=Intel10_64ilp (non seq) and INTEL_MKL_VERSION 20200004 -// }; - -// BOOST_GLOBAL_FIXTURE(Fixture); -// #endif - -BOOST_AUTO_TEST_CASE_TEMPLATE(multi_blas_gemv, T, fp_types) { - // NOLINTNEXTLINE(readability-identifier-length) BLAS naming - multi::array const a = { - { 9.0, 24.0, 30.0, 9.0}, - { 4.0, 10.0, 12.0, 7.0}, - {14.0, 16.0, 36.0, 1.0}, +#define BOOST_AUTO_TEST_CASE(CasenamE) /**/ +#define BOOST_REQUIRE_CLOSE(X, Y, ToL) BOOST_TEST( std::abs( (X) - (Y) ) < (ToL) ) +#define BOOST_REQUIRE_SMALL(X, ToL) BOOST_TEST( std::abs( X ) < (ToL) ) + +void gemv_broadcast() { + // NOLINTNEXTLINE(readability-identifier-length) + multi::array const a = { + {1.0, 2.0, 3.0}, + {4.0, 5.0, 6.0} }; - multi::array const x = {1.1, 2.1, 3.1, 4.1}; // NOLINT(readability-identifier-length) BLAS naming - { - multi::array y(multi::extensions_t<1>{multi::iextension{size(a)}}); // NOLINT(readability-identifier-length) BLAS naming - blas::gemv_n(1.0, begin(a), size(a), begin(x), 0.0, begin(y)); - BOOST_REQUIRE_CLOSE(y[1], 91.3, 0.0001); - if(!std::is_same_v) { // workaround Apple Accelerate BLAS bug in dot - BOOST_REQUIRE_CLOSE(y[2], +blas::dot(a[2], x), 0.0001); - } - } - { - multi::array y(multi::extensions_t<1>{multi::iextension{size(a)}}); // NOLINT(readability-identifier-length) BLAS naming - multi::array const aT = ~a; - blas::gemv_n(1.0, begin(~aT), size(~aT), begin(x), 0.0, begin(y)); - BOOST_REQUIRE_CLOSE(y[1], 91.3, 0.0001); - if(!std::is_same_v) { // workaround Apple Accelerate BLAS bug in dot - BOOST_REQUIRE_CLOSE(y[2], +blas::dot(a[2], x), 0.0001); - } - } - { - multi::array y(multi::extensions_t<1>{multi::iextension{size(a)}}); // NOLINT(readability-identifier-length) BLAS naming - auto mv = blas::gemv(1.0, a, x); - copy_n(mv.begin(), mv.size(), y.begin()); - BOOST_REQUIRE_CLOSE(y[1], 91.3, 0.00001); - - multi::array w2(multi::extensions_t<1>{multi::iextension{size(a)}}); - MV(a, x, w2); - BOOST_REQUIRE_CLOSE(w2[0], y[0], 0.00001); - } - { - multi::array y(multi::extensions_t<1>{multi::iextension{size(a)}}); // NOLINT(readability-identifier-length) BLAS naming - y = blas::gemv(1.0, a, x); - BOOST_REQUIRE_CLOSE(y[1], 91.3, 0.00001); - } - { - multi::array y = blas::gemv(1.0, a, x); // NOLINT(readability-identifier-length) BLAS naming - BOOST_REQUIRE_CLOSE(y[1], 91.3, 0.00001); - } { - multi::array y(multi::extensions_t<1>{multi::iextension{size(a)}}, 0.); // NOLINT(readability-identifier-length) BLAS naming - y += blas::gemv(1.0, a, x); - BOOST_REQUIRE_CLOSE(y[1], 91.3, 0.00001); - } - { - multi::array y = {4.0, 5.0, 6.0}; // NOLINT(readability-identifier-length) BLAS naming - blas::gemv(1.1, a, x, 1.0, y); // y = a*M*x + b*y - BOOST_REQUIRE_CLOSE(y[1], 105.43, 0.00001); - } -} + multi::array const ones({3}, 1.0); -BOOST_AUTO_TEST_CASE_TEMPLATE(multi_blas_gemv_real, T, fp_types) { - namespace blas = multi::blas; + BOOST_TEST( ones.stride() == 1 ); - using std::abs; - // NOLINTNEXTLINE(readability-identifier-length) BLAS naming - multi::array const a = { - { 9.0, 24.0, 30.0, 9.0}, - { 4.0, 10.0, 12.0, 7.0}, - {14.0, 16.0, 36.0, 1.0}, - }; - multi::array const x = {1.1, 2.1, 3.1, 4.1}; // NOLINT(readability-identifier-length) BLAS naming - { - multi::array y = {4.0, 5.0, 6.0}; // NOLINT(readability-identifier-length) BLAS naming - T const alpha = 1.1; - T const beta = 1.2; - blas::gemv(alpha, a, x, beta, y); // y = a*M*x + b*y + BOOST_TEST( ones[0] == 1.0 ); + BOOST_TEST( ones[1] == 1.0 ); + BOOST_TEST( ones[2] == 1.0 ); - multi::array const y3 = {214.02, 106.43, 188.37}; - BOOST_REQUIRE( abs(y[1] - y3[1]) < 2e-14 ); - } - if constexpr(!std::is_same_v) { - auto Y = +blas::gemv(1.0, a, x); // NOLINT(readability-identifier-length) BLAS naming - BOOST_REQUIRE_CLOSE(Y[0], +blas::dot(a[0], x), 0.00001); - BOOST_REQUIRE_CLOSE(Y[1], +blas::dot(a[1], x), 0.00001); - BOOST_REQUIRE_CLOSE(Y[2], +blas::dot(a[2], x), 0.00001); + multi::array sum_by_rows({2}, 0.0); + blas::gemv_n(1.0, a.begin(), 2, ones.begin(), 0.0, sum_by_rows.begin()); + + std::cout << sum_by_rows[0] << " " << sum_by_rows[1] << "\n"; + BOOST_TEST( std::abs( sum_by_rows[0] - (1.0 + 2.0 + 3.0)) < 1.0e-8 ); + BOOST_TEST( std::abs( sum_by_rows[1] - (4.0 + 5.0 + 6.0)) < 1.0e-8 ); } - { - multi::array const x = {1.0, 2.0, 3.0}; // NOLINT(readability-identifier-length) BLAS naming - multi::array const y = {4.0, 5.0, 6.0}; // NOLINT(readability-identifier-length) BLAS naming - multi::array const dot = blas::gemv(1., multi::array({x}), y); - if(!std::is_same_v) { // workaround Apple Accelerate BLAS bug in dot - BOOST_REQUIRE( dot[0] == blas::dot(x, y) ); + // BLAS GEMV doesn't work with stride zero + // { + // multi::array const one(1.0); + // auto const& ones = one.broadcasted(); + + // BOOST_TEST( ones.stride() == 0 ); + + // BOOST_TEST( ones[0] == 1.0 ); + // BOOST_TEST( ones[1] == 1.0 ); + // BOOST_TEST( ones[2] == 1.0 ); + + // multi::array sum_by_rows({2}, 0.0); + // blas::gemv_n(1.0, a.begin(), 2, ones.begin(), 0.0, sum_by_rows.begin()); + + // std::cout << sum_by_rows[0] << " " << sum_by_rows[1] << "\n"; + // BOOST_TEST( std::abs( sum_by_rows[0] - (1.0 + 2.0 + 3.0)) < 1.0e-8 ); + // BOOST_TEST( std::abs( sum_by_rows[1] - (4.0 + 5.0 + 6.0)) < 1.0e-8 ); + // } +} + +auto main() -> int { // NOLINT(readability-function-cognitive-complexity,bugprone-exception-escape) + BOOST_AUTO_TEST_CASE(multi_blas_gemv_double) { + using T = double; + // NOLINTNEXTLINE(readability-identifier-length) BLAS naming + multi::array const a = { + { 9.0, 24.0, 30.0, 9.0}, + { 4.0, 10.0, 12.0, 7.0}, + {14.0, 16.0, 36.0, 1.0}, + }; + multi::array const x = {1.1, 2.1, 3.1, 4.1}; // NOLINT(readability-identifier-length) BLAS naming + { + multi::array y(multi::extensions_t<1>{multi::iextension{size(a)}}); // NOLINT(readability-identifier-length) BLAS naming + blas::gemv_n(1.0, a.begin(), a.size(), x.begin(), 0.0, y.begin()); + BOOST_TEST( std::abs( y[1] - 91.3 ) < 0.0001); + if(!std::is_same_v) { // workaround Apple Accelerate BLAS bug in dot + BOOST_TEST( std::abs( y[2] - +blas::dot(a[2], x)) < 0.0001); + } + } + { + multi::array y(multi::extensions_t<1>{multi::iextension{size(a)}}); // NOLINT(readability-identifier-length) BLAS naming + multi::array const aT{~a}; + blas::gemv_n(1.0, (~aT).begin(), (~aT).size(), x.begin(), 0.0, y.begin()); + BOOST_TEST( std::abs( y[1] - 91.3 ) < 0.0001); + + if(!std::is_same_v) { // workaround Apple Accelerate BLAS bug in dot + BOOST_TEST( std::abs( y[2] - +blas::dot(a[2], x)) < 0.0001); + } + } + { + multi::array y(multi::extensions_t<1>{multi::iextension{size(a)}}); // NOLINT(readability-identifier-length) BLAS naming + auto mv = blas::gemv(1.0, a, x); + copy_n(mv.begin(), mv.size(), y.begin()); + BOOST_TEST( std::abs( y[1] - 91.3) < 0.00001); + + multi::array w2(multi::extensions_t<1>{multi::iextension{size(a)}}); + MV(a, x, w2); + BOOST_TEST( std::abs(w2[0] - y[0]) < 0.00001); + } + { + multi::array y(multi::extensions_t<1>{multi::iextension{size(a)}}); // NOLINT(readability-identifier-length) BLAS naming + y = blas::gemv(1.0, a, x); + BOOST_REQUIRE_CLOSE(y[1], 91.3, 0.00001); + } + { + multi::array y = blas::gemv(1.0, a, x); // NOLINT(readability-identifier-length) BLAS naming + BOOST_REQUIRE_CLOSE(y[1], 91.3, 0.00001); + } + { + multi::array y(multi::extensions_t<1>{multi::iextension{size(a)}}, 0.); // NOLINT(readability-identifier-length) BLAS naming + y += blas::gemv(1.0, a, x); + BOOST_REQUIRE_CLOSE(y[1], 91.3, 0.00001); + } + { + multi::array y = {4.0, 5.0, 6.0}; // NOLINT(readability-identifier-length) BLAS naming + blas::gemv(1.1, a, x, 1.0, y); // y = a*M*x + b*y + BOOST_REQUIRE_CLOSE(y[1], 105.43, 0.00001); } } - { - using blas::operators::operator%; - using blas::operators::operator-; - using blas::operators::operator^; - BOOST_REQUIRE_SMALL(((~+~a) % x - a % x) ^ 2, 1e-9); - } -} -BOOST_AUTO_TEST_CASE_TEMPLATE(multi_blas_gemv_real_complex, T, fp_types) { - namespace blas = multi::blas; - using complex = std::complex; - using std::abs; + BOOST_AUTO_TEST_CASE(multi_blas_gemv_float) { + using T = float; + // NOLINTNEXTLINE(readability-identifier-length) BLAS naming + multi::array const a = { + { 9.0, 24.0, 30.0, 9.0}, + { 4.0, 10.0, 12.0, 7.0}, + {14.0, 16.0, 36.0, 1.0}, + }; + multi::array const x = {1.1, 2.1, 3.1, 4.1}; // NOLINT(readability-identifier-length) BLAS naming + { + multi::array y(multi::extensions_t<1>{multi::iextension{size(a)}}); // NOLINT(readability-identifier-length) BLAS naming + blas::gemv_n(1.0, a.begin(), a.size(), x.begin(), 0.0, y.begin()); + BOOST_TEST( std::abs( y[1] - 91.3 ) < 0.0001); + if(!std::is_same_v) { // workaround Apple Accelerate BLAS bug in dot + BOOST_TEST( std::abs( y[2] - +blas::dot(a[2], x)) < 0.0001); + } + } + { + multi::array y(multi::extensions_t<1>{multi::iextension{size(a)}}); // NOLINT(readability-identifier-length) BLAS naming + multi::array const aT{~a}; + blas::gemv_n(1.0, (~aT).begin(), (~aT).size(), x.begin(), 0.0, y.begin()); + BOOST_TEST( std::abs( y[1] - 91.3 ) < 0.0001); + + if(!std::is_same_v) { // workaround Apple Accelerate BLAS bug in dot + BOOST_TEST( std::abs( y[2] - +blas::dot(a[2], x)) < 0.0001); + } + } + { + multi::array y(multi::extensions_t<1>{multi::iextension{size(a)}}); // NOLINT(readability-identifier-length) BLAS naming + auto mv = blas::gemv(1.0, a, x); + copy_n(mv.begin(), mv.size(), y.begin()); + BOOST_TEST( std::abs( y[1] - 91.3) < 0.00001); + + multi::array w2(multi::extensions_t<1>{multi::iextension{size(a)}}); + MV(a, x, w2); + BOOST_TEST_LT(std::abs(w2[0] - y[0]), 0.0001); + } + { + multi::array y(multi::extensions_t<1>{multi::iextension{size(a)}}); // NOLINT(readability-identifier-length) BLAS naming + y = blas::gemv(1.0, a, x); + BOOST_REQUIRE_CLOSE(y[1], 91.3, 0.00001); + } + { + multi::array y = blas::gemv(1.0, a, x); // NOLINT(readability-identifier-length) BLAS naming + BOOST_REQUIRE_CLOSE(y[1], 91.3, 0.00001); + } + { + multi::array y(multi::extensions_t<1>{multi::iextension{size(a)}}, 0.); // NOLINT(readability-identifier-length) BLAS naming + y += blas::gemv(1.0, a, x); + BOOST_REQUIRE_CLOSE(y[1], 91.3, 0.00001); + } + { + multi::array y = {4.0, 5.0, 6.0}; // NOLINT(readability-identifier-length) BLAS naming + blas::gemv(1.1, a, x, 1.0, y); // y = a*M*x + b*y + BOOST_REQUIRE_CLOSE(y[1], 105.43, 0.00001); + } + } - // NOLINTNEXTLINE(readability-identifier-length) BLAS naming - multi::array const M = { - { {9.0, 0.0}, {24.0, 0.0}, {30.0, 0.0}, {9.0, 0.0}}, - { {4.0, 0.0}, {10.0, 0.0}, {12.0, 0.0}, {7.0, 0.0}}, - {{14.0, 0.0}, {16.0, 0.0}, {36.0, 0.0}, {1.0, 0.0}}, - }; + BOOST_AUTO_TEST_CASE(multi_blas_gemv_real_double) { + using T = double; + namespace blas = multi::blas; - // NOLINTNEXTLINE(readability-identifier-length) BLAS naming - multi::array const X = { - {1.1, 0.0}, - {2.1, 0.0}, - {3.1, 0.0}, - {4.1, 0.0}, - }; - { + using std::abs; // NOLINTNEXTLINE(readability-identifier-length) BLAS naming - multi::array Y = { - {4.0, 0.0}, - {5.0, 0.0}, - {6.0, 0.0}, + multi::array const a = { + { 9.0, 24.0, 30.0, 9.0}, + { 4.0, 10.0, 12.0, 7.0}, + {14.0, 16.0, 36.0, 1.0}, }; + multi::array const x = {1.1, 2.1, 3.1, 4.1}; // NOLINT(readability-identifier-length) BLAS naming + { + multi::array y = {4.0, 5.0, 6.0}; // NOLINT(readability-identifier-length) BLAS naming + T const alpha = 1.1; + T const beta = 1.2; + blas::gemv(alpha, a, x, beta, y); // y = a*M*x + b*y + + multi::array const y3 = {214.02, 106.43, 188.37}; + BOOST_TEST( std::abs(y[1] - y3[1]) < 2e-14 ); + } + if constexpr(!std::is_same_v) { + auto Y = +blas::gemv(1.0, a, x); // NOLINT(readability-identifier-length) BLAS naming + BOOST_REQUIRE_CLOSE(Y[0], +blas::dot(a[0], x), 0.00001); + BOOST_REQUIRE_CLOSE(Y[1], +blas::dot(a[1], x), 0.00001); + BOOST_REQUIRE_CLOSE(Y[2], +blas::dot(a[2], x), 0.00001); + } + { + multi::array const x = {1.0, 2.0, 3.0}; // NOLINT(readability-identifier-length) BLAS naming + multi::array const y = {4.0, 5.0, 6.0}; // NOLINT(readability-identifier-length) BLAS naming + multi::array const dot = blas::gemv(1., multi::array({x}), y); + if(!std::is_same_v) { // workaround Apple Accelerate BLAS bug in dot + BOOST_TEST( dot[0] == blas::dot(x, y) ); + } + } + { + using blas::operators::operator%; + using blas::operators::operator-; + using blas::operators::operator^; + BOOST_REQUIRE_SMALL(((~+~a) % x - a % x) ^ 2, 1e-9); + } + } - auto const alpha = T{1.1}; - auto const beta = T{1.2}; + BOOST_AUTO_TEST_CASE(multi_blas_gemv_real_float) { + using T = float; + namespace blas = multi::blas; + + using std::abs; + // NOLINTNEXTLINE(readability-identifier-length) BLAS naming + multi::array const a = { + { 9.0, 24.0, 30.0, 9.0}, + { 4.0, 10.0, 12.0, 7.0}, + {14.0, 16.0, 36.0, 1.0}, + }; + multi::array const x = {1.1, 2.1, 3.1, 4.1}; // NOLINT(readability-identifier-length) BLAS naming + { + multi::array y = {4.0, 5.0, 6.0}; // NOLINT(readability-identifier-length) BLAS naming + T const alpha = 1.1; + T const beta = 1.2; + blas::gemv(alpha, a, x, beta, y); // y = a*M*x + b*y + + multi::array const y3 = {214.02, 106.43, 188.37}; + BOOST_TEST( abs(y[1] - y3[1]) < 2e-14 ); + } + if constexpr(!std::is_same_v) { + auto Y = +blas::gemv(1.0, a, x); // NOLINT(readability-identifier-length) BLAS naming + BOOST_REQUIRE_CLOSE(Y[0], +blas::dot(a[0], x), 0.00001); + BOOST_REQUIRE_CLOSE(Y[1], +blas::dot(a[1], x), 0.00001); + BOOST_REQUIRE_CLOSE(Y[2], +blas::dot(a[2], x), 0.00001); + } + { + multi::array const x = {1.0, 2.0, 3.0}; // NOLINT(readability-identifier-length) BLAS naming + multi::array const y = {4.0, 5.0, 6.0}; // NOLINT(readability-identifier-length) BLAS naming + multi::array const dot = blas::gemv(1., multi::array({x}), y); + if(!std::is_same_v) { // workaround Apple Accelerate BLAS bug in dot + BOOST_TEST( dot[0] == blas::dot(x, y) ); + } + } + { + using blas::operators::operator%; + using blas::operators::operator-; + using blas::operators::operator^; + BOOST_REQUIRE_SMALL(((~+~a) % x - a % x) ^ 2, 1e-9); + } + } - blas::gemv(alpha, M, X, beta, Y); // y = a*M*x + b*y + BOOST_AUTO_TEST_CASE(multi_blas_gemv_real_complex_double) { + using T = double; + namespace blas = multi::blas; + using complex = std::complex; + using std::abs; - multi::array const Y3 = { - {214.02, 0.0}, - {106.43, 0.0}, - {188.37, 0.0}, + // NOLINTNEXTLINE(readability-identifier-length) BLAS naming + multi::array const M = { + { {9.0, 0.0}, {24.0, 0.0}, {30.0, 0.0}, {9.0, 0.0}}, + { {4.0, 0.0}, {10.0, 0.0}, {12.0, 0.0}, {7.0, 0.0}}, + {{14.0, 0.0}, {16.0, 0.0}, {36.0, 0.0}, {1.0, 0.0}}, }; - using blas::operators::operator-; - T const n2{blas::nrm2(Y - Y3)}; - BOOST_REQUIRE_SMALL(n2, T{1.0e-4}); + // NOLINTNEXTLINE(readability-identifier-length) BLAS naming + multi::array const X = { + {1.1, 0.0}, + {2.1, 0.0}, + {3.1, 0.0}, + {4.1, 0.0}, + }; + { + // NOLINTNEXTLINE(readability-identifier-length) BLAS naming + multi::array Y = { + {4.0, 0.0}, + {5.0, 0.0}, + {6.0, 0.0}, + }; + + auto const alpha = T{1.1}; + auto const beta = T{1.2}; + + blas::gemv(alpha, M, X, beta, Y); // y = a*M*x + b*y + + multi::array const Y3 = { + {214.02, 0.0}, + {106.43, 0.0}, + {188.37, 0.0}, + }; + + using blas::operators::operator-; + T const n2{blas::nrm2(Y - Y3)}; + BOOST_REQUIRE_SMALL(n2, T{1.0e-4}); + } } -} -BOOST_AUTO_TEST_CASE(multi_blas_gemv_complex) { - namespace blas = multi::blas; - using complex = std::complex; - auto const I = complex{0.0, 1.0}; // NOLINT(readability-identifier-length) imag unit + BOOST_AUTO_TEST_CASE(blas_gemv_complex_float_mimic_cdot) { + multi::array, 2> const v1 = { + {std::complex{1.0F, 2.0F}, std::complex{3.0F, 4.0F}, std::complex{ 5.0F, 6.0F}} + }; + BOOST_TEST( v1.size() == 1 ); + BOOST_TEST( v1.num_elements() == 3 ); - using std::abs; + multi::array, 1> const v2 = {std::complex{7.0F, 8.0F}, std::complex{9.0F, 10.0F}, std::complex{11.0F, 12.0F}}; + BOOST_TEST( v2.size() == 3 ); - // NOLINTNEXTLINE(readability-identifier-length) BLAS naming - multi::array const a = { - {2.0 + 3.0 * I, 2.0 + 1.0 * I, 1.0 + 2.0 * I}, - {4.0 + 2.0 * I, 2.0 + 4.0 * I, 3.0 + 1.0 * I}, - {7.0 + 1.0 * I, 1.0 + 5.0 * I, 0.0 + 3.0 * I}, - }; - multi::array const x = {1.0 + 2.0 * I, 2.0 + 1.0 * I, 9.0 + 2.0 * I}; // NOLINT(readability-identifier-length) BLAS naming - BOOST_REQUIRE(( +blas::gemv(1., a, x) == multi::array{4.0 + 31.*I, 25.0 + 35.0*I, -4.0 + 53.0*I} )); + multi::array, 1> res({1}, std::complex{}); // NOLINT(fuchsia-default-arguments-calls) + BOOST_TEST( res.size() == 1 ); - auto aT = +~a; - BOOST_REQUIRE(( +blas::gemv(1., ~aT, x) == multi::array{4.0 + 31.0*I, 25.0 + 35.0*I, -4.0 + 53.0*I} )); + blas::gemv(1.0, v1, v2, 0.0, res); - BOOST_REQUIRE( +blas::gemv(1., ~a, x) == (multi::array{63.0 + 38.0*I, -1.0 + 62.0*I, -4.0 + 36.0*I}) ); - BOOST_REQUIRE( +blas::gemv(1., ~a, x) == + blas::gemv(1.0, aT, x) ); -} + BOOST_TEST( std::abs(res[0] - (v1[0][0]*v2[0] + v1[0][1]*v2[1] + v1[0][2]*v2[2])) < 1.0e-8 ); -BOOST_AUTO_TEST_CASE(multi_blas_gemv_temporary) { - using complex = std::complex; + std::complex res_dot; // NOLINT(fuchsia-default-arguments-calls) - // NOLINTNEXTLINE(readability-identifier-length) BLAS naming - multi::array const A = { - {{1.0, 0.0}, {0.0, 0.0}, {0.0, 0.0}}, - {{0.0, 0.0}, {1.0, 0.0}, {0.0, 0.0}}, - {{0.0, 0.0}, {0.0, 0.0}, {1.0, 0.0}}, - }; + blas::dot(v1[0], v2, res_dot); - auto const B = [](auto array) { // NOLINT(readability-identifier-length) BLAS naming - auto rand = [gauss = std::normal_distribution<>{}, gen = std::mt19937{1}]() mutable { return complex{gauss(gen), gauss(gen)}; }; // NOLINT(cert-msc32-c,cert-msc51-cpp) test purposes - std::generate(array.elements().begin(), array.elements().end(), rand); - return array; - }(multi::array({3, 3})); - - using blas::operators::operator*; - using blas::operators::operator-; - using blas::operators::operator^; - BOOST_REQUIRE( (((+(A*B))[0] - B[0])^2) == 0.0 ); - BOOST_REQUIRE( (((+(A*B))[1] - B[1])^2) == 0.0 ); - BOOST_REQUIRE( (((+(A*B))[2] - B[2])^2) == 0.0 ); -} + BOOST_TEST( std::abs(res[0] - res_dot) < 1.0e-8 ); + } -BOOST_AUTO_TEST_CASE(multi_blas_gemv_context) { - // NOLINTNEXTLINE(readability-identifier-length) BLAS naming - multi::array const a = { - { 9.0, 24.0, 30.0, 9.0}, - { 4.0, 10.0, 12.0, 7.0}, - {14.0, 16.0, 36.0, 1.0}, - }; - multi::array const x = {1.1, 2.1, 3.1, 4.1}; // NOLINT(readability-identifier-length) conventional name in BLAS + BOOST_AUTO_TEST_CASE(multi_blas_gemv_real_complex_float) { + using T = float; + namespace blas = multi::blas; + using complex = std::complex; + using std::abs; - blas::context ctxt; - { - multi::array y(multi::extensions_t<1>{multi::iextension{size(a)}}); // NOLINT(readability-identifier-length) conventional name in BLAS - blas::gemv_n(&ctxt, 1.0, begin(a), size(a), begin(x), 0.0, begin(y)); - BOOST_REQUIRE_CLOSE(y[1], 91.3, 0.0001); - BOOST_REQUIRE_CLOSE(y[2], +blas::dot(a[2], x), 0.0001); - } - { - multi::array y(multi::extensions_t<1>{multi::iextension{size(a)}}); // NOLINT(readability-identifier-length) conventional name in BLAS - multi::array const aT = ~a; - blas::gemv_n(&ctxt, 1.0, begin(~aT), size(~aT), begin(x), 0.0, begin(y)); - BOOST_REQUIRE_CLOSE(y[1], 91.3, 0.00001); - BOOST_REQUIRE_CLOSE(y[2], +blas::dot(a[2], x), 0.00001); - } - { - multi::array y(multi::extensions_t<1>{multi::iextension{size(a)}}); // NOLINT(readability-identifier-length) conventional name in BLAS - auto&& mv = blas::gemv(&ctxt, 1.0, a, x); - copy_n(mv.begin(), mv.size(), y.begin()); - BOOST_REQUIRE_CLOSE(y[1], 91.3, 0.00001); - } - { - multi::array y(multi::extensions_t<1>{multi::iextension{size(a)}}); // NOLINT(readability-identifier-length) conventional name in BLAS - y = blas::gemv(&ctxt, 1.0, a, x); - BOOST_REQUIRE_CLOSE(y[1], 91.3, 0.00001); - } - { - multi::array y(multi::extensions_t<1>{multi::iextension{size(a)}}); // NOLINT(readability-identifier-length) conventional name in BLAS - y = blas::gemv(1.0, a, x); - BOOST_REQUIRE_CLOSE(y[1], 91.3, 0.00001); - } - { - multi::array y(multi::extensions_t<1>{multi::iextension{size(a)}}); // NOLINT(readability-identifier-length) conventional name in BLAS - y() = blas::gemv(1.0, a, x); - BOOST_REQUIRE_CLOSE(y[1], 91.3, 0.00001); + // NOLINTNEXTLINE(readability-identifier-length) BLAS naming + multi::array const M = { + { {9.0, 0.0}, {24.0, 0.0}, {30.0, 0.0}, {9.0, 0.0}}, + { {4.0, 0.0}, {10.0, 0.0}, {12.0, 0.0}, {7.0, 0.0}}, + {{14.0, 0.0}, {16.0, 0.0}, {36.0, 0.0}, {1.0, 0.0}}, + }; + + // NOLINTNEXTLINE(readability-identifier-length) BLAS naming + multi::array const X = { + {1.1, 0.0}, + {2.1, 0.0}, + {3.1, 0.0}, + {4.1, 0.0}, + }; + { + // NOLINTNEXTLINE(readability-identifier-length) BLAS naming + multi::array Y = { + {4.0, 0.0}, + {5.0, 0.0}, + {6.0, 0.0}, + }; + + auto const alpha = T{1.1}; + auto const beta = T{1.2}; + + blas::gemv(alpha, M, X, beta, Y); // y = a*M*x + b*y + + multi::array const Y3 = { + {214.02, 0.0}, + {106.43, 0.0}, + {188.37, 0.0}, + }; + + using blas::operators::operator-; + T const n2{blas::nrm2(Y - Y3)}; + BOOST_REQUIRE_SMALL(n2, T{1.0e-4}); + } } - { - multi::array y = blas::gemv(&ctxt, 1.0, a, x); // NOLINT(readability-identifier-length) conventional name in BLAS - BOOST_REQUIRE_CLOSE(y[1], 91.3, 0.00001); + + BOOST_AUTO_TEST_CASE(multi_blas_gemv_complex) { + namespace blas = multi::blas; + using complex = std::complex; + auto const I = complex{0.0, 1.0}; // NOLINT(readability-identifier-length) imag unit + + using std::abs; + + // NOLINTNEXTLINE(readability-identifier-length) BLAS naming + multi::array const a = { + {2.0 + 3.0 * I, 2.0 + 1.0 * I, 1.0 + 2.0 * I}, + {4.0 + 2.0 * I, 2.0 + 4.0 * I, 3.0 + 1.0 * I}, + {7.0 + 1.0 * I, 1.0 + 5.0 * I, 0.0 + 3.0 * I}, + }; + multi::array const x = {1.0 + 2.0 * I, 2.0 + 1.0 * I, 9.0 + 2.0 * I}; // NOLINT(readability-identifier-length) BLAS naming + BOOST_TEST(( +blas::gemv(1., a, x) == multi::array{4.0 + 31.*I, 25.0 + 35.0*I, -4.0 + 53.0*I} )); + + auto aT = +~a; + BOOST_TEST(( +blas::gemv(1., ~aT, x) == multi::array{4.0 + 31.0*I, 25.0 + 35.0*I, -4.0 + 53.0*I} )); + + BOOST_TEST( +blas::gemv(1., ~a, x) == (multi::array{63.0 + 38.0*I, -1.0 + 62.0*I, -4.0 + 36.0*I}) ); + BOOST_TEST( +blas::gemv(1., ~a, x) == + blas::gemv(1.0, aT, x) ); } - { - multi::array y(multi::extensions_t<1>{multi::iextension{size(a)}}, 0.0); // NOLINT(readability-identifier-length) conventional name in BLAS - y += blas::gemv(&ctxt, 1.0, a, x); - BOOST_REQUIRE_CLOSE(y[1], 91.3, 0.00001); + + BOOST_AUTO_TEST_CASE(multi_blas_gemv_temporary) { + using complex = std::complex; + + // NOLINTNEXTLINE(readability-identifier-length) BLAS naming + multi::array const A = { + {{1.0, 0.0}, {0.0, 0.0}, {0.0, 0.0}}, + {{0.0, 0.0}, {1.0, 0.0}, {0.0, 0.0}}, + {{0.0, 0.0}, {0.0, 0.0}, {1.0, 0.0}}, + }; + + // NOLINTNEXTLINE(readability-identifier-length) BLAS naming + auto const B = [](auto array) { + // NOLINTNEXTLINE(cert-msc32-c,cert-msc51-cpp) test purposes + auto rand = [gauss = std::normal_distribution<>{}, gen = std::mt19937{}]() mutable { + return complex{gauss(gen), gauss(gen)}; + }; + std::generate(array.elements().begin(), array.elements().end(), rand); + return array; + }(multi::array({3, 3})); + + // using blas::operators::operator*; + // using blas::operators::operator-; + // using blas::operators::operator^; + // BOOST_TEST( (((+(A*B))[0] - B[0])^2) == 0.0 ); + // BOOST_TEST( (((+(A*B))[1] - B[1])^2) == 0.0 ); + // BOOST_TEST( (((+(A*B))[2] - B[2])^2) == 0.0 ); } - { - multi::array y = {4.0, 5.0, 6.0}; // NOLINT(readability-identifier-length) conventional name in BLAS - y += blas::gemv(&ctxt, 1.1, a, x); - BOOST_REQUIRE_CLOSE(y[1], 105.43, 0.00001); + + BOOST_AUTO_TEST_CASE(multi_blas_gemv_context) { + // NOLINTNEXTLINE(readability-identifier-length) BLAS naming + multi::array const a = { + { 9.0, 24.0, 30.0, 9.0}, + { 4.0, 10.0, 12.0, 7.0}, + {14.0, 16.0, 36.0, 1.0}, + }; + multi::array const x = {1.1, 2.1, 3.1, 4.1}; // NOLINT(readability-identifier-length) conventional name in BLAS + + blas::context ctxt; + { + multi::array y(multi::extensions_t<1>{multi::iextension{size(a)}}); // NOLINT(readability-identifier-length) conventional name in BLAS + blas::gemv_n(&ctxt, 1.0, begin(a), size(a), begin(x), 0.0, begin(y)); + BOOST_REQUIRE_CLOSE(y[1], 91.3, 0.0001); + BOOST_REQUIRE_CLOSE(y[2], +blas::dot(a[2], x), 0.0001); + } + { + multi::array y(multi::extensions_t<1>{multi::iextension{size(a)}}); // NOLINT(readability-identifier-length) conventional name in BLAS + multi::array const aT{~a}; + blas::gemv_n(&ctxt, 1.0, begin(~aT), size(~aT), begin(x), 0.0, begin(y)); + BOOST_REQUIRE_CLOSE(y[1], 91.3, 0.00001); + BOOST_REQUIRE_CLOSE(y[2], +blas::dot(a[2], x), 0.00001); + } + { + multi::array y(multi::extensions_t<1>{multi::iextension{size(a)}}); // NOLINT(readability-identifier-length) conventional name in BLAS + auto&& mv = blas::gemv(&ctxt, 1.0, a, x); + copy_n(mv.begin(), mv.size(), y.begin()); + BOOST_REQUIRE_CLOSE(y[1], 91.3, 0.00001); + } + { + multi::array y(multi::extensions_t<1>{multi::iextension{size(a)}}); // NOLINT(readability-identifier-length) conventional name in BLAS + y = blas::gemv(&ctxt, 1.0, a, x); + BOOST_REQUIRE_CLOSE(y[1], 91.3, 0.00001); + } + { + multi::array y(multi::extensions_t<1>{multi::iextension{size(a)}}); // NOLINT(readability-identifier-length) conventional name in BLAS + y = blas::gemv(1.0, a, x); + BOOST_REQUIRE_CLOSE(y[1], 91.3, 0.00001); + } + { + multi::array y(multi::extensions_t<1>{multi::iextension{size(a)}}); // NOLINT(readability-identifier-length) conventional name in BLAS + y() = blas::gemv(1.0, a, x); + BOOST_REQUIRE_CLOSE(y[1], 91.3, 0.00001); + } + { + multi::array y = blas::gemv(&ctxt, 1.0, a, x); // NOLINT(readability-identifier-length) conventional name in BLAS + BOOST_REQUIRE_CLOSE(y[1], 91.3, 0.00001); + } + { + multi::array y(multi::extensions_t<1>{multi::iextension{size(a)}}, 0.0); // NOLINT(readability-identifier-length) conventional name in BLAS + y += blas::gemv(&ctxt, 1.0, a, x); + BOOST_REQUIRE_CLOSE(y[1], 91.3, 0.00001); + } + { + multi::array y = {4.0, 5.0, 6.0}; // NOLINT(readability-identifier-length) conventional name in BLAS + y += blas::gemv(&ctxt, 1.1, a, x); + BOOST_REQUIRE_CLOSE(y[1], 105.43, 0.00001); + } } + + gemv_broadcast(); + + return boost::report_errors(); } diff --git a/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/test/herk.cpp b/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/test/herk.cpp index 02b3e6d44c..c097f027c4 100644 --- a/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/test/herk.cpp +++ b/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/test/herk.cpp @@ -2,21 +2,35 @@ // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt -#include - -#include -#include -#include - -#include +#include + +#include // for filling +#include // for gemm, gemm_range +#include // for herk +#include // for nrm2_ref, nrm2 +#include // for involuted, under... +#include // for H, T, (anonymous) +// IWYU pragma: no_include "boost/multi/adaptors/blas/traits.hpp" // for blas // needed for iwyu-clang-macos + +#include // for array, layout_t + +#include // for sqrt +// IWYU pragma: no_include +#include // for operator*, opera... +#include // for operator<<, basi... +#include // for size +#include // for numeric_limits +#include // for char_traits, bas... +#include // for is_same namespace multi = boost::multi; -template auto print(M const& mat, std::string const& msg = "") -> decltype(auto) { // NOLINT(fuchsia-default-arguments-declarations,fuchsia-default-arguments-calls) +// NOLINTNEXTLINE(fuchsia-default-arguments-declarations,fuchsia-default-arguments-calls) +template auto print(M const& mat, std::string const& msg = "") -> decltype(auto) { using multi::size; using std::cout; cout << msg << "\n" - << '{'; + << '{'; for(int i = 0; i != size(mat); ++i) { cout << '{'; for(auto j : mat[i].extension()) { // NOLINT(altera-unroll-loops) @@ -33,262 +47,283 @@ template auto print(M const& mat, std::string const& msg = "") -> declt return cout << '}' << '\n'; } -BOOST_AUTO_TEST_CASE(multi_blas_herk) { - namespace blas = multi::blas; - using complex = std::complex; - auto const I = complex{0.0, 1.0}; // NOLINT(readability-identifier-length) imag unit - - // NOLINTNEXTLINE(readability-identifier-length) conventional name in BLAS - multi::array const a = { - {1.0 + 3.0 * I, 3.0 - 2.0 * I, 4.0 + 1.0 * I}, - {9.0 + 1.0 * I, 7.0 - 8.0 * I, 1.0 - 3.0 * I}, - }; - { - multi::array c({2, 2}, {9999.0, 0.0}); // NOLINT(readability-identifier-length) conventional name in BLAS - blas::herk(a, c); - BOOST_REQUIRE( c[1][0] == complex(50.0, -49.0) ); - BOOST_REQUIRE( c[0][1] == complex(50.0, +49.0) ); - - multi::array const c_copy = blas::herk(1., a); - BOOST_REQUIRE( c == c_copy ); - - BOOST_REQUIRE( +blas::gemm(1.0, a, blas::H(a)) == blas::herk(a) ); +#define BOOST_AUTO_TEST_CASE(CasenamE) /**/ + +auto main() -> int { // NOLINT(readability-function-cognitive-complexity,bugprone-exception-escape) + BOOST_AUTO_TEST_CASE(multi_blas_herk) { + namespace blas = multi::blas; + using complex = std::complex; + auto const I = complex{0.0, 1.0}; // NOLINT(readability-identifier-length) imag unit + + // NOLINTNEXTLINE(readability-identifier-length) conventional name in BLAS + multi::array const a = { + {1.0 + 3.0 * I, 3.0 - 2.0 * I, 4.0 + 1.0 * I}, + {9.0 + 1.0 * I, 7.0 - 8.0 * I, 1.0 - 3.0 * I}, + }; + { + multi::array c({2, 2}, {9999.0, 0.0}); // NOLINT(readability-identifier-length) conventional name in BLAS + blas::herk(a, c); + BOOST_TEST( c[1][0] == complex(50.0, -49.0) ); + BOOST_TEST( c[0][1] == complex(50.0, +49.0) ); + + multi::array const c_copy = blas::herk(1.0, a); + BOOST_TEST( c == c_copy ); + + BOOST_TEST( +blas::gemm(1.0, a, blas::H(a)) == blas::herk(a) ); + } } -} -BOOST_AUTO_TEST_CASE(inq_case) { - namespace blas = multi::blas; - // NOLINTNEXTLINE(readability-identifier-length) conventional name in BLAS - multi::array const a = { - {0.0, 1.0, 2.0}, - {3.0, 4.0, 5.0}, - {6.0, 7.0, 8.0}, - {9.0, 10.0, 11.0}, - }; - BOOST_REQUIRE( (+blas::gemm(1.0, a, blas::T(a)))[1][2] == 86.0 ); - { - multi::array c({4, 4}); // NOLINT(readability-identifier-length) conventional name in BLAS - blas::herk(1.0, a, c); - BOOST_REQUIRE( c[1][2] == (+blas::gemm(1.0, a, blas::T(a)))[1][2] ); - // BOOST_REQUIRE( c[2][1] == (+blas::gemm(1., a, blas::T(a)))[2][1] ); - } - { - multi::array const c = blas::herk(1.0, a); // NOLINT(readability-identifier-length) conventional name in BLAS - BOOST_REQUIRE( c == +blas::gemm(1., a, blas::T(a)) ); - BOOST_REQUIRE( blas::herk(a) == +blas::gemm(1.0, a, blas::T(a)) ); - BOOST_REQUIRE( blas::herk(2.0, a) == +blas::gemm(2.0, a, blas::T(a)) ); + BOOST_AUTO_TEST_CASE(inq_case) { + namespace blas = multi::blas; + // NOLINTNEXTLINE(readability-identifier-length) conventional name in BLAS + multi::array const a = { + {0.0, 1.0, 2.0}, + {3.0, 4.0, 5.0}, + {6.0, 7.0, 8.0}, + {9.0, 10.0, 11.0}, + }; + + BOOST_TEST( (+blas::gemm(1.0, a, blas::T(a)))[1][2] == 86.0 ); + { + multi::array c({4, 4}); // NOLINT(readability-identifier-length) conventional name in BLAS + blas::herk(1.0, a, c); + BOOST_TEST( c[1][2] == (+blas::gemm(1.0, a, blas::T(a)))[1][2] ); + // BOOST_TEST( c[2][1] == (+blas::gemm(1., a, blas::T(a)))[2][1] ); + } + { + multi::array const c = blas::herk(1.0, a); // NOLINT(readability-identifier-length) conventional name in BLAS + BOOST_TEST( c == +blas::gemm(1., a, blas::T(a)) ); + BOOST_TEST( blas::herk(a) == +blas::gemm(1.0, a, blas::T(a)) ); + BOOST_TEST( blas::herk(2.0, a) == +blas::gemm(2.0, a, blas::T(a)) ); + } } -} -BOOST_AUTO_TEST_CASE(multi_blas_herk_real) { - namespace blas = multi::blas; - // NOLINTNEXTLINE(readability-identifier-length) conventional name in BLAS - multi::array const a = { - {1.0, 3.0, 4.0}, - {9.0, 7.0, 1.0}, - }; - { - multi::array c({2, 2}, 9999.0); // NOLINT(readability-identifier-length) BLAS naming - blas::herk(1.0, a, c); - BOOST_REQUIRE( c[0][1] == 34.0 ); + BOOST_AUTO_TEST_CASE(multi_blas_herk_real) { + namespace blas = multi::blas; + // NOLINTNEXTLINE(readability-identifier-length) conventional name in BLAS + multi::array const a = { + {1.0, 3.0, 4.0}, + {9.0, 7.0, 1.0}, + }; + { + multi::array c({2, 2}, 9999.0); // NOLINT(readability-identifier-length) BLAS naming + blas::herk(1.0, a, c); + BOOST_TEST( c[0][1] == 34.0 ); + } } -} - -BOOST_AUTO_TEST_CASE(multi_blas_herk1x1_case) { - namespace blas = multi::blas; - // NOLINTNEXTLINE(readability-identifier-length) conventional name in BLAS - multi::array const a = { - {1.0, 2.0, 3.0}, - }; - multi::array b = blas::herk(a); // NOLINT(readability-identifier-length) BLAS naming - BOOST_REQUIRE( size(b) == 1 ); - BOOST_REQUIRE( b[0][0] == 1.0*1.0 + 2.0*2.0 + 3.0*3.0 ); -} + BOOST_AUTO_TEST_CASE(multi_blas_herk1x1_case) { + namespace blas = multi::blas; + // NOLINTNEXTLINE(readability-identifier-length) conventional name in BLAS + multi::array const a = { + {1.0, 2.0, 3.0}, + }; + multi::array b = blas::herk(a); // NOLINT(readability-identifier-length) BLAS naming -BOOST_AUTO_TEST_CASE(multi_blas_herk1x1_case_scale, *boost::unit_test::tolerance(0.00001)) { - namespace blas = multi::blas; - // NOLINTNEXTLINE(readability-identifier-length) conventional name in BLAS - multi::array const a = { - {1.0, 2.0, 3.0}, - }; + BOOST_TEST( size(b) == 1 ); + BOOST_TEST( b[0][0] == 1.0*1.0 + 2.0*2.0 + 3.0*3.0 ); + } - multi::array b = blas::herk(0.1, a); // NOLINT(readability-identifier-length) BLAS naming + BOOST_AUTO_TEST_CASE(multi_blas_herk1x1_case_scale) { + namespace blas = multi::blas; + // NOLINTNEXTLINE(readability-identifier-length) conventional name in BLAS + multi::array const a = { + {1.0, 2.0, 3.0}, + }; - BOOST_REQUIRE( size(b) == 1 ); - BOOST_TEST( b[0][0] == (1.0*1.0 + 2.0*2.0 + 3.0*3.0)*0.1 ); -} + multi::array b = blas::herk(0.1, a); // NOLINT(readability-identifier-length) BLAS naming -BOOST_AUTO_TEST_CASE(multi_blas_herk1x1_complex_real_case) { - namespace blas = multi::blas; - - using complex = std::complex; - // NOLINTNEXTLINE(readability-identifier-length) BLAS naming - multi::array const a = { - {{1.0, 0.0}, {2.0, 0.0}, {3.0, 0.0}}, - }; - multi::array b = blas::herk(1.0, a); // NOLINT(readability-identifier-length) BLAS naming - BOOST_REQUIRE( size(b) == 1 ); - BOOST_REQUIRE( b[0][0] == 1.0*1.0 + 2.0*2.0 + 3.0*3.0 ); -} + BOOST_TEST( size(b) == 1 ); + BOOST_TEST( std::abs( b[0][0] - (1.0*1.0 + 2.0*2.0 + 3.0*3.0)*0.1 ) < 1E-6 ); + } -BOOST_AUTO_TEST_CASE(multi_blas_herk1x1_complex_real_case_scale, *boost::unit_test::tolerance(0.00001)) { - namespace blas = multi::blas; - - using complex = std::complex; - // NOLINTNEXTLINE(readability-identifier-length) BLAS naming - multi::array const a = { - {{1.0, 0.0}, {2.0, 0.0}, {3.0, 0.0}}, - }; - multi::array b = blas::herk(0.1, a); // NOLINT(readability-identifier-length) BLAS naming - BOOST_REQUIRE( size(b) == 1 ); - BOOST_TEST( real( b[0][0]/0.1 ) == 1.0*1.0 + 2.0*2.0 + 3.0*3.0 ); -} + BOOST_AUTO_TEST_CASE(multi_blas_herk1x1_complex_real_case) { + namespace blas = multi::blas; + + using complex = std::complex; + // NOLINTNEXTLINE(readability-identifier-length) BLAS naming + multi::array const a = { + {{1.0, 0.0}, {2.0, 0.0}, {3.0, 0.0}}, + }; + multi::array b = blas::herk(1.0, a); // NOLINT(readability-identifier-length) BLAS naming + BOOST_TEST( size(b) == 1 ); + BOOST_TEST( b[0][0] == 1.0*1.0 + 2.0*2.0 + 3.0*3.0 ); + } -BOOST_AUTO_TEST_CASE(multi_blas_herk1x1_complex_case) { - namespace blas = multi::blas; + BOOST_AUTO_TEST_CASE(multi_blas_herk1x1_complex_real_case_scale) { + namespace blas = multi::blas; + + using complex = std::complex; + // NOLINTNEXTLINE(readability-identifier-length) BLAS naming + multi::array const a = { + {{1.0, 0.0}, {2.0, 0.0}, {3.0, 0.0}}, + }; + multi::array b = blas::herk(0.1, a); // NOLINT(readability-identifier-length) BLAS naming + BOOST_TEST( size(b) == 1 ); + BOOST_TEST( std::abs( real( b[0][0]/0.1 ) - (1.0*1.0 + 2.0*2.0 + 3.0*3.0) ) < 1E-6 ); + } - using complex = std::complex; - auto const I = complex{0.0, 1.0}; // NOLINT(readability-identifier-length) imag unit - // NOLINTNEXTLINE(readability-identifier-length) conventional name in BLAS - multi::array const a = { - {1.0 + 2.0 * I, 2.0 + 3.0 * I, 3.0 + 4.0 * I}, - }; - multi::array b = blas::herk(a); // NOLINT(readability-identifier-length) BLAS naming - BOOST_REQUIRE( size(b) == 1 ); - BOOST_REQUIRE( b[0][0] == std::norm(1.0 + 2.0*I) + std::norm(2.0 + 3.0*I) + std::norm(3.0 + 4.0*I) ); + BOOST_AUTO_TEST_CASE(multi_blas_herk1x1_complex_case) { + namespace blas = multi::blas; - BOOST_TEST( std::sqrt(real(blas::herk(a)[0][0])) == blas::nrm2(a[0]) ); -} + using complex = std::complex; + auto const I = complex{0.0, 1.0}; // NOLINT(readability-identifier-length) imag unit + // NOLINTNEXTLINE(readability-identifier-length) conventional name in BLAS + multi::array const a = { + {1.0 + 2.0 * I, 2.0 + 3.0 * I, 3.0 + 4.0 * I}, + }; + multi::array b = blas::herk(a); // NOLINT(readability-identifier-length) BLAS naming + BOOST_TEST( size(b) == 1 ); + BOOST_TEST( b[0][0] == std::norm(1.0 + 2.0*I) + std::norm(2.0 + 3.0*I) + std::norm(3.0 + 4.0*I) ); -BOOST_AUTO_TEST_CASE(multi_blas_herk1x1_complex_case_hermitized_out_param) { - namespace blas = multi::blas; - using complex = std::complex; - auto const I = complex{0.0, 1.0}; // NOLINT(readability-identifier-length) imag unit + BOOST_TEST( std::sqrt(real(blas::herk(a)[0][0])) == blas::nrm2(a[0]) ); + } - multi::array const a = {{1.0 + 2.0 * I}, {2.0 + 3.0 * I}, {3.0 + 4.0 * I}}; // NOLINT(readability-identifier-length) BLAS naming - multi::array b({1, 1}); // NOLINT(readability-identifier-length) BLAS naming - BOOST_REQUIRE( size(b) == 1 ); + BOOST_AUTO_TEST_CASE(multi_blas_herk1x1_complex_case_hermitized_out_param) { + namespace blas = multi::blas; + using complex = std::complex; + auto const I = complex{0.0, 1.0}; // NOLINT(readability-identifier-length) imag unit - blas::herk(blas::filling::upper, 1.0, blas::H(a), 0.0, b); + multi::array const a = {{1.0 + 2.0 * I}, {2.0 + 3.0 * I}, {3.0 + 4.0 * I}}; // NOLINT(readability-identifier-length) BLAS naming + multi::array b({1, 1}); // NOLINT(readability-identifier-length) BLAS naming + BOOST_TEST( size(b) == 1 ); - BOOST_REQUIRE( b[0][0] == std::norm(1.0 + 2.0*I) + std::norm(2.0 + 3.0*I) + std::norm(3.0 + 4.0*I) ); + blas::herk(blas::filling::upper, 1.0, blas::H(a), 0.0, b); - // BOOST_TEST( std::sqrt(real(b[0][0])) == blas::nrm2(blas::T(a)[0])() ); -} + BOOST_TEST( b[0][0] == std::norm(1.0 + 2.0*I) + std::norm(2.0 + 3.0*I) + std::norm(3.0 + 4.0*I) ); -BOOST_AUTO_TEST_CASE(multi_blas_herk1x1_complex_case_hermitized) { - using complex = std::complex; - auto const I = complex{0.0, 1.0}; // NOLINT(readability-identifier-length) conventional name in BLAS + // BOOST_TEST( std::sqrt(real(b[0][0])) == blas::nrm2(blas::T(a)[0])() ); + } - // NOLINTNEXTLINE(readability-identifier-length) conventional name in BLAS - multi::array const a = { - {1.0 + 2.0 * I}, - {2.0 + 3.0 * I}, - {3.0 + 4.0 * I}, - }; + BOOST_AUTO_TEST_CASE(multi_blas_herk1x1_complex_case_hermitized) { + using complex = std::complex; + auto const I = complex{0.0, 1.0}; // NOLINT(readability-identifier-length) conventional name in BLAS - namespace blas = multi::blas; + // NOLINTNEXTLINE(readability-identifier-length) conventional name in BLAS + multi::array const a = { + {1.0 + 2.0 * I}, + {2.0 + 3.0 * I}, + {3.0 + 4.0 * I}, + }; - multi::array b = blas::herk(blas::H(a)); // NOLINT(readability-identifier-length) BLAS naming + namespace blas = multi::blas; - BOOST_REQUIRE( size(b) == 1 ); - BOOST_REQUIRE( b[0][0] == std::norm(1.0 + 2.0*I) + std::norm(2.0 + 3.0*I) + std::norm(3.0 + 4.0*I) ); + multi::array b = blas::herk(blas::H(a)); // NOLINT(readability-identifier-length) BLAS naming - BOOST_TEST( std::sqrt(real(blas::herk(blas::H(a))[0][0])) == blas::nrm2(rotated(a)[0]) ); -} + BOOST_TEST( size(b) == 1 ); + BOOST_TEST( b[0][0] == std::norm(1.0 + 2.0*I) + std::norm(2.0 + 3.0*I) + std::norm(3.0 + 4.0*I) ); -BOOST_AUTO_TEST_CASE(multi_blas_herk1x1_complex_case_hermitized_auto) { - namespace blas = multi::blas; - using complex = std::complex; - auto const I = complex{0.0, 1.0}; // NOLINT(readability-identifier-length) imag unit - - multi::array const arr = { - {1.0 + 2.0 * I}, - {2.0 + 3.0 * I}, - {3.0 + 4.0 * I}, - }; - auto arr2 = blas::herk(1.0, blas::hermitized(arr)); - static_assert(std::is_same>{}); - BOOST_REQUIRE( size(arr2) == 1 ); - BOOST_REQUIRE( arr2[0][0] == std::norm(1.0 + 2.0*I) + std::norm(2.0 + 3.0*I) + std::norm(3.0 + 4.0*I) ); - - BOOST_TEST( std::sqrt(real(blas::herk(blas::H(arr))[0][0])) == blas::nrm2(rotated(arr)[0]) ); -} + BOOST_TEST( std::sqrt(real(blas::herk(blas::H(a))[0][0])) == blas::nrm2(a.rotated()[0]) ); + } -BOOST_AUTO_TEST_CASE(multi_blas_herk_complex_identity) { - namespace blas = multi::blas; - using complex = std::complex; - auto const I = complex{0.0, 1.0}; // NOLINT(readability-identifier-length) imag unit - - multi::array const arr = { - {1.0 + 3.0 * I, 3.0 - 2.0 * I, 4.0 + 1.0 * I}, - {9.0 + 1.0 * I, 7.0 - 8.0 * I, 1.0 - 3.0 * I}, - }; - - { - multi::array arr2({2, 2}, {9999.0, 0.0}); // NOLINT(readability-identifier-length) conventional one-letter operation BLASs - blas::herk(blas::filling::lower, 1.0, arr, 0.0, arr2); // c†=c=aa†=(aa†)†, `c` in lower triangular - BOOST_REQUIRE(( arr2[1][0] == complex{50.0, -49.0} )); - BOOST_REQUIRE( arr2[0][1] == 9999.0 ); + BOOST_AUTO_TEST_CASE(multi_blas_herk1x1_complex_case_hermitized_auto) { + namespace blas = multi::blas; + using complex = std::complex; + auto const I = complex{0.0, 1.0}; // NOLINT(readability-identifier-length) imag unit + + multi::array const arr = { + {1.0 + 2.0 * I}, + {2.0 + 3.0 * I}, + {3.0 + 4.0 * I}, + }; + auto arr2 = blas::herk(1.0, blas::hermitized(arr)); + static_assert(std::is_same>{}); + BOOST_TEST( size(arr2) == 1 ); + BOOST_TEST( arr2[0][0] == std::norm(1.0 + 2.0*I) + std::norm(2.0 + 3.0*I) + std::norm(3.0 + 4.0*I) ); + + BOOST_TEST( std::sqrt(real(blas::herk(blas::H(arr))[0][0])) == blas::nrm2(arr.rotated()[0]) ); } - { - multi::array c({2, 2}, {9999.0, 0.0}); // NOLINT(readability-identifier-length) conventional one-letter operation BLASs - static_assert(blas::is_conjugated{}); - blas::herk(blas::filling::lower, 1.0, arr, 0.0, blas::H(c)); // c†=c=aa†=(aa†)†, `c` in upper triangular + BOOST_AUTO_TEST_CASE(multi_blas_herk_complex_identity) { + namespace blas = multi::blas; + using complex = std::complex; + auto const I = complex{0.0, 1.0}; // NOLINT(readability-identifier-length) imag unit + + multi::array const arr = { + {1.0 + 3.0 * I, 3.0 - 2.0 * I, 4.0 + 1.0 * I}, + {9.0 + 1.0 * I, 7.0 - 8.0 * I, 1.0 - 3.0 * I}, + }; + + { + multi::array arr2({2, 2}, {9999.0, 0.0}); // NOLINT(readability-identifier-length) conventional one-letter operation BLAS + blas::herk(blas::filling::lower, 1.0, arr, 0.0, arr2); // c^dagger = c = a a^dagger = (a a^dagger)^dagger, `c` is lower triangular + BOOST_TEST(( arr2[1][0] == complex{50.0, -49.0} )); + BOOST_TEST( arr2[0][1] == 9999.0 ); + } + { + multi::array c({2, 2}, {9999.0, 0.0}); // NOLINT(readability-identifier-length) conventional one-letter operation BLAS + static_assert(blas::is_conjugated::value); - BOOST_REQUIRE(( blas::H(c)[1][0] == complex{50.0, -49.0} )); - BOOST_REQUIRE( blas::H(c)[0][1] == 9999.0 ); - } - { - multi::array c({3, 3}, {9999.0, 0.0}); // NOLINT(readability-identifier-length) : conventional one-letter operation BLASs - herk(blas::filling::lower, 1.0, blas::T(arr), 0.0, blas::T(c)); // c†=c=aT(aT)† not supported - BOOST_REQUIRE(( transposed(c)[1][0] == complex{52.0, -90.0} )); - BOOST_REQUIRE( transposed(c)[0][1] == 9999.0 ); - } - { - multi::array c({3, 3}, {9999.0, 0.0}); // NOLINT(readability-identifier-length) : conventional one-letter operation BLASs - blas::herk(blas::filling::lower, 1.0, blas::T(arr), 0.0, blas::H(blas::T(c))); // c†=c=aT(aT)† not supported - BOOST_REQUIRE(( blas::H(blas::T(c))[1][0] == complex{52.0, -90.0} )); - BOOST_REQUIRE( blas::H(blas::T(c))[0][1] == 9999.0 ); - } - { - multi::array c({2, 2}, {9999.0, 0.0}); // NOLINT(readability-identifier-length) : conventional one-letter operation BLAS - blas::herk(blas::filling::upper, 1.0, arr, 0.0, c); // c†=c=aa†=(aa†)†, `c` in upper triangular - BOOST_REQUIRE(( c[0][1] == complex{50.0, +49.0} )); - BOOST_REQUIRE( c[1][0] == 9999.0 ); - } - { - multi::array c({2, 2}, {9999.0, 0.0}); // NOLINT(readability-identifier-length) : conventional one-letter operation BLAS - blas::herk(1., arr, c); // c†=c=aa†=(aa†)† - BOOST_REQUIRE(( c[0][1] == complex{50.0, +49.0} )); - BOOST_REQUIRE(( c[1][0] == complex{50.0, -49.0} )); - } - { - multi::array c({3, 3}, {9999.0, 0.0}); // NOLINT(readability-identifier-length) : conventional one-letter operation BLAS - blas::herk(blas::filling::lower, 1.0, blas::H(arr), 0.0, c); // c†=c=aa†=(aa†)†, `c` in lower triangular - BOOST_REQUIRE(( c[1][0] == complex{52.0, 90.0} )); - BOOST_REQUIRE( c[0][1] == 9999.0 ); + blas::herk(blas::filling::lower, 1.0, arr, 0.0, blas::H(c)); // c^dagger = c = a a^dagger = (aa^dagger)^daggerr, `c` in upper triangular + + BOOST_TEST(( blas::H(c)[1][0] == complex{50.0, -49.0} )); + BOOST_TEST( blas::H(c)[0][1] == 9999.0 ); + } + { + // NOLINTNEXTLINE(readability-identifier-length) : conventional one-letter operation BLASs + multi::array c({3, 3}, {9999.0, 0.0}); + herk(blas::filling::lower, 1.0, blas::T(arr), 0.0, blas::T(c)); // c†=c=aT(aT)† not supported + BOOST_TEST(( c.transposed()[1][0] == complex{52.0, -90.0} )); + BOOST_TEST( c.transposed()[0][1] == 9999.0 ); + } + { + // NOLINTNEXTLINE(readability-identifier-length) : conventional one-letter operation BLASs + multi::array c({3, 3}, {9999.0, 0.0}); + blas::herk(blas::filling::lower, 1.0, blas::T(arr), 0.0, blas::H(blas::T(c))); // c†=c=aT(aT)† not supported + BOOST_TEST(( blas::H(blas::T(c))[1][0] == complex{52.0, -90.0} )); + BOOST_TEST( blas::H(blas::T(c))[0][1] == 9999.0 ); + } + { + multi::array c({2, 2}, {9999.0, 0.0}); // NOLINT(readability-identifier-length) : conventional one-letter operation BLAS + blas::herk(blas::filling::upper, 1.0, arr, 0.0, c); // c†=c=aa†=(aa†)†, `c` in upper triangular + BOOST_TEST(( c[0][1] == complex{50.0, +49.0} )); + BOOST_TEST( c[1][0] == 9999.0 ); + } + { + multi::array c({2, 2}, {9999.0, 0.0}); // NOLINT(readability-identifier-length) : conventional one-letter operation BLAS + blas::herk_nm(blas::filling::upper, 1.0, arr.home(), arr.size(), (~arr).size(), 0.0, c.home()); + BOOST_TEST(( c[0][1] == complex{50.0, +49.0} )); + BOOST_TEST( c[1][0] == 9999.0 ); + } + // { + // multi::array c({2, 2}, {9999.0, 0.0}); // NOLINT(readability-identifier-length) : conventional one-letter operation BLAS + // c() = blas::herk(blas::filling::upper, 1.0, arr); + // BOOST_TEST(( c[0][1] == complex{50.0, +49.0} )); + // // BOOST_TEST( c[1][0] == 9999.0 ); + // } + { + multi::array c({2, 2}, {9999.0, 0.0}); // NOLINT(readability-identifier-length) : conventional one-letter operation BLAS + blas::herk(1.0, arr, c); // c†=c=aa†=(aa†)† + BOOST_TEST(( c[0][1] == complex{50.0, +49.0} )); + BOOST_TEST(( c[1][0] == complex{50.0, -49.0} )); + } + { + multi::array c({3, 3}, {9999.0, 0.0}); // NOLINT(readability-identifier-length) : conventional one-letter operation BLAS + blas::herk(blas::filling::lower, 1.0, blas::H(arr), 0.0, c); // c†=c=aa†=(aa†)†, `c` in lower triangular + BOOST_TEST(( c[1][0] == complex{52.0, 90.0} )); + BOOST_TEST( c[0][1] == 9999.0 ); + } } -} -BOOST_AUTO_TEST_CASE(multi_blas_herk_complex_square) { - namespace blas = multi::blas; + BOOST_AUTO_TEST_CASE(multi_blas_herk_complex_square) { + namespace blas = multi::blas; - using complex = std::complex; - auto const I = complex{0.0, 1.0}; // NOLINT(readability-identifier-length) imag unit - auto const nan = std::numeric_limits::quiet_NaN(); + using complex = std::complex; + auto const I = complex{0.0, 1.0}; // NOLINT(readability-identifier-length) imag unit + auto const nan = std::numeric_limits::quiet_NaN(); - // NOLINTNEXTLINE(readability-identifier-length) lapack conventional name - multi::array const A = { - {12.9388 + I * 0.0, 9.80028 + I * -0.00011091, 9.66966 + I * -0.0114817}, - { nan + I * nan, 8.44604 + I * 0.0, 3.78646 + I * 0.0170734}, - { nan + I * nan, nan + I * nan, 7.70655 + I * 0.0}, - }; + // NOLINTNEXTLINE(readability-identifier-length) lapack conventional name + multi::array const A = { + {12.9388 + I * 0.0, 9.80028 + I * -0.00011091, 9.66966 + I * -0.0114817}, + { nan + I * nan, 8.44604 + I * 0.0, 3.78646 + I * 0.0170734}, + { nan + I * nan, nan + I * nan, 7.70655 + I * 0.0}, + }; - // NOLINTNEXTLINE(readability-identifier-length) lapack conventional name - multi::array C({3, 3}, complex{0.0, 0.0}); + // NOLINTNEXTLINE(readability-identifier-length) lapack conventional name + multi::array C({3, 3}, complex{0.0, 0.0}); + + blas::herk(boost::multi::blas::filling::upper, complex{1.0, 0.0}, A, complex{0.0, 0.0}, C); + } - blas::herk(boost::multi::blas::filling::upper, complex{1.0, 0.0}, A, complex{0.0, 0.0}, C); + return boost::report_errors(); } diff --git a/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/test/nrm2.cpp b/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/test/nrm2.cpp index d4ae33f7d3..e84ac2baee 100644 --- a/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/test/nrm2.cpp +++ b/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/test/nrm2.cpp @@ -2,140 +2,184 @@ // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt -#include +#include -#include -#include +// IWYU pragma: no_include "boost/multi/adaptors/blas/core.hpp" // for context +// IWYU pragma: no_include "boost/multi/adaptors/blas/traits.hpp" // for blas, multi +#include // for context +#include // for dot, dot_ref, operator== +#include // for nrm2, nrm2_ref -#include +#include // for array, layout_t, impli... +#include // for sqrt, NAN #include +#include namespace multi = boost::multi; -using complex = multi::complex; -constexpr complex I{0.0, 1.0}; // NOLINT(readability-identifier-length) imaginary unit - -BOOST_AUTO_TEST_CASE(multi_blas_nrm2) { - namespace blas = multi::blas; - - // NOLINTNEXTLINE(readability-identifier-length) blas conventional name - multi::array const A = { - {1.0, 2.0, 3.0, 4.0}, - {5.0, 6.0, 7.0, 8.0}, - {9.0, 10.0, 11.0, 12.0}, - }; - BOOST_REQUIRE( blas::nrm2(A[1]) == std::sqrt(blas::dot(A[1], A[1])) ); - - { - multi::array const x = {1.0 + 1.0 * I, 3.0 + 2.0 * I, 3.0 + 4.0 * I}; // NOLINT(readability-identifier-length) blas conventional name - BOOST_REQUIRE( blas::dot(x, x) == (1.0 + 1.0*I)*(1.0 + 1.0*I) + (3.0 + 2.0*I)*(3.0 + 2.0*I) + (3.0 + 4.0*I)*(3.0 + 4.0*I) ); - using std::sqrt; - BOOST_REQUIRE( blas::nrm2(x) == sqrt(norm(1.0 + 1.0*I) + norm(3.0 + 2.0*I) + norm(3.0 + 4.0*I)) ); +using complex = std::complex; + +#define BOOST_AUTO_TEST_CASE(CasenamE) /**/ + +auto main() -> int { // NOLINT(readability-function-cognitive-complexity,bugprone-exception-escape) + complex const I{0.0, 1.0}; // NOLINT(readability-identifier-length) imaginary unit + + BOOST_AUTO_TEST_CASE(multi_blas_nrm2) { + namespace blas = multi::blas; + + // NOLINTNEXTLINE(readability-identifier-length) blas conventional name + multi::array const A = { + {1.0, 2.0, 3.0, 4.0}, + {5.0, 6.0, 7.0, 8.0}, + {9.0, 10.0, 11.0, 12.0}, + }; + BOOST_TEST( blas::nrm2(A[1]) == std::sqrt(blas::dot(A[1], A[1])) ); + + { + multi::array const x = {1.0 + 1.0 * I, 3.0 + 2.0 * I, 3.0 + 4.0 * I}; // NOLINT(readability-identifier-length) blas conventional name + + BOOST_TEST( std::abs(+blas::dot(x, x) - ((1.0 + 1.0*I)*(1.0 + 1.0*I) + (3.0 + 2.0*I)*(3.0 + 2.0*I) + (3.0 + 4.0*I)*(3.0 + 4.0*I))) < 1.0e-8 ); + + std::cout << "nrm2 "<< blas::nrm2(x) << " " << std::sqrt(norm(1.0 + 1.0*I) + norm(3.0 + 2.0*I) + norm(3.0 + 4.0*I)) << '\n'; + BOOST_TEST( std::abs( blas::nrm2(x) - std::sqrt(norm(1.0 + 1.0*I) + norm(3.0 + 2.0*I) + norm(3.0 + 4.0*I)) ) < 1.0e-8 ); + } } -} -BOOST_AUTO_TEST_CASE(multi_adaptor_multi_nrm2_real) { - namespace blas = multi::blas; - multi::array const cA = { - {1.0, 2.0, 3.0, 4.0}, - {5.0, 6.0, 7.0, 8.0}, - {9.0, 10.0, 11.0, 12.0}, - }; + BOOST_AUTO_TEST_CASE(multi_adaptor_multi_nrm2_real) { + namespace blas = multi::blas; - double n = NAN; // NOLINT(readability-identifier-length) BLAS naming - blas::nrm2(rotated(cA)[1], n); + multi::array const cA = { + {1.0, 2.0, 3.0, 4.0}, + {5.0, 6.0, 7.0, 8.0}, + {9.0, 10.0, 11.0, 12.0}, + }; - // BOOST_REQUIRE( blas::nrm2(rotated(cA)[1], n) == std::sqrt( 2.0*2.0 + 6.0*6.0 + 10.0*10.0) ); // TODO(correaa) nrm2 is returning a pointer? - BOOST_REQUIRE( n == std::sqrt( 2.0*2.0 + 6.0*6.0 + 10.0*10.0) ); - // BOOST_REQUIRE( blas::nrm2(rotated(cA)[1]) == std::sqrt( 2.*2. + 6.*6 + 10.*10.) ); + double n = NAN; // NOLINT(readability-identifier-length) BLAS naming + blas::nrm2(cA.rotated()[1], n); - // double n2 = blas::nrm2(rotated(cA)[1]); - // BOOST_REQUIRE( n == n2 ); + // BOOST_TEST( blas::nrm2(rotated(cA)[1], n) == std::sqrt( 2.0*2.0 + 6.0*6.0 + 10.0*10.0) ); // TODO(correaa) nrm2 is returning a pointer? + BOOST_TEST( n == std::sqrt( 2.0*2.0 + 6.0*6.0 + 10.0*10.0) ); - // multi::array R(4); - // blas::nrm2( rotated(cA)[1], R[2]); - // BOOST_REQUIRE( R[2] == std::sqrt( 2.*2. + 6.*6 + 10.*10.) ); + // BOOST_TEST( blas::nrm2(rotated(cA)[1]) == std::sqrt( 2.*2. + 6.*6 + 10.*10.) ); - // multi::array R0; - // blas::nrm2( rotated(cA)[1], R0); - // BOOST_REQUIRE( R0 == std::sqrt( 2.*2. + 6.*6 + 10.*10.) ); + // double n2 = blas::nrm2(rotated(cA)[1]); + // BOOST_TEST( n == n2 ); - // BOOST_REQUIRE( blas::nrm2(rotated(cA)[1]) == std::sqrt( 2.*2. + 6.*6 + 10.*10.) ); -} + // multi::array R(4); + // blas::nrm2( rotated(cA)[1], R[2]); + // BOOST_TEST( R[2] == std::sqrt( 2.*2. + 6.*6 + 10.*10.) ); + + // multi::array R0; + // blas::nrm2( rotated(cA)[1], R0); + // BOOST_TEST( R0 == std::sqrt( 2.*2. + 6.*6 + 10.*10.) ); -BOOST_AUTO_TEST_CASE(multi_adaptor_blas_nrm2_operators) { - multi::array const X = {1.1, 2.1, 3.1, 4.1}; // NOLINT(readability-identifier-length) BLAS naming + // BOOST_TEST( blas::nrm2(rotated(cA)[1]) == std::sqrt( 2.*2. + 6.*6 + 10.*10.) ); + } - double n = NAN; // NOLINT(readability-identifier-length) BLAS naming + BOOST_AUTO_TEST_CASE(multi_adaptor_blas_nrm2_operators) { + multi::array const X = {1.1, 2.1, 3.1, 4.1}; // NOLINT(readability-identifier-length) BLAS naming + + { + double n = NAN; // NOLINT(readability-identifier-length) BLAS naming + + multi::blas::nrm2(X, n); + BOOST_TEST( n == multi::blas::nrm2(X) ); + } + { + double n = NAN; // NOLINT(readability-identifier-length) BLAS naming + + n = multi::blas::nrm2(X); + BOOST_TEST( n == multi::blas::nrm2(X) ); + } + { + double const n = multi::blas::nrm2(X); // NOLINT(readability-identifier-length) BLAS naming + BOOST_TEST( n == multi::blas::nrm2(X) ); + } + { + multi::array res{0.0}; + multi::array const xx = {1.0, 2.0, 3.0}; + + // multi::blas::dot(xx, xx, res); + // multi::blas::nrm2(xx, res); + multi::blas::context ctx; + multi::blas::dot_n(&ctx, xx.begin(), xx.size(), xx.begin(), res.base()); + // multi::blas::nrm2_n(&ctx, xx.begin(), xx.size(), res.base()); + + // BOOST_TEST( *res.base() == 1.0*1.0 + 2.0*2.0 + 3.0*3.0 ); + + // multi::blas::nrm2(xx, res); + + // BOOST_TEST( *res.base() == 1.0*1.0 + 2.0*2.0 + 3.0*3.0 ); + } + } - multi::blas::nrm2(X, n); - BOOST_REQUIRE( n == multi::blas::nrm2(X) ); + // BOOST_AUTO_TEST_CASE(multi_adaptor_multi_nrm2_complex_real_case){ + // using complex = std::complex; + // multi::array const cA = { + // {1.0, 2.0, 3.0, 4.0}, + // {5.0, 6.0, 7.0, 8.0}, + // {9.0, 10.0, 11.0, 12.0} + // }; + // } + + // using multi::blas::nrm2; + // double n; + // BOOST_TEST( nrm2(rotated(cA)[1], n) == std::sqrt( 2.*2. + 6.*6 + 10.*10.) ); + // BOOST_TEST( nrm2(rotated(cA)[1]) == n ); + //} + + // #if 0 + // BOOST_AUTO_TEST_CASE(multi_adaptor_multi_nrm2_complex_real_case_thrust){ + // using complex = thrust::complex; + // multi::array const cA = { + // {1., 2., 3., 4.}, + // {5., 6., 7., 8.}, + // {9., 10., 11., 12.} + // }; + + // using multi::blas::nrm2; + // double n; + // BOOST_TEST( nrm2(rotated(cA)[1], n) == std::sqrt( 2.*2. + 6.*6 + 10.*10.) ); + // BOOST_TEST( nrm2(rotated(cA)[1]) == n ); + //} + + // BOOST_AUTO_TEST_CASE(multi_adaptor_multi_nrm2_complex_real_case_types){ + // boost::mpl::for_each, + // thrust::complex//, + // // boost::multi::complex // TODO make this work + // >>([](auto cplx){ + // multi::array const cA = { + // {1., 2., 3., 4.}, + // {5., 6., 7., 8.}, + // {9., 10., 11., 12.} + // }; + + // using multi::blas::nrm2; + // double n; + // BOOST_TEST( nrm2(rotated(cA)[1], n) == std::sqrt( 2.*2. + 6.*6 + 10.*10.) ); + // BOOST_TEST( nrm2(rotated(cA)[1]) == n ); + // }); + //} + // #endif + + // BOOST_AUTO_TEST_CASE(multi_adaptor_multi_nrm2_complex){ + // using complex = std::complex; complex const I{0,1}; + // multi::array const cA = { + // {1., 2. + 1.*I, 3., 4.}, + // {5., 6. + 4.*I, 7., 8.}, + // {9., 10. - 3.*I, 11., 12.} + // }; + + // using multi::blas::nrm2; + // double n; + // BOOST_TEST( nrm2(rotated(cA)[1], n) == std::sqrt( norm(cA[0][1]) + norm(cA[1][1]) + norm(cA[2][1]) ) ); + // BOOST_TEST( nrm2(rotated(cA)[1]) == std::sqrt( norm(cA[0][1]) + norm(cA[1][1]) + norm(cA[2][1]) ) ); + + // using namespace multi::blas::operators; + // BOOST_TEST_REQUIRE( (rotated(cA)[1]^-1) == 1/std::sqrt(norm(cA[0][1]) + norm(cA[1][1]) + norm(cA[2][1])) , boost::test_tools::tolerance(1e-15) ); + // BOOST_TEST_REQUIRE( (rotated(cA)[1]^2) == norm(cA[0][1]) + norm(cA[1][1]) + norm(cA[2][1]) , boost::test_tools::tolerance(1e-15) ); + //} + return boost::report_errors(); } - -// BOOST_AUTO_TEST_CASE(multi_adaptor_multi_nrm2_complex_real_case){ -// using complex = std::complex; -// multi::array const cA = { -// {1., 2., 3., 4.}, -// {5., 6., 7., 8.}, -// {9., 10., 11., 12.} -// }; - -// using multi::blas::nrm2; -// double n; -// BOOST_REQUIRE( nrm2(rotated(cA)[1], n) == std::sqrt( 2.*2. + 6.*6 + 10.*10.) ); -// BOOST_REQUIRE( nrm2(rotated(cA)[1]) == n ); -//} - -// #if 0 -// BOOST_AUTO_TEST_CASE(multi_adaptor_multi_nrm2_complex_real_case_thrust){ -// using complex = thrust::complex; -// multi::array const cA = { -// {1., 2., 3., 4.}, -// {5., 6., 7., 8.}, -// {9., 10., 11., 12.} -// }; - -// using multi::blas::nrm2; -// double n; -// BOOST_REQUIRE( nrm2(rotated(cA)[1], n) == std::sqrt( 2.*2. + 6.*6 + 10.*10.) ); -// BOOST_REQUIRE( nrm2(rotated(cA)[1]) == n ); -//} - -// BOOST_AUTO_TEST_CASE(multi_adaptor_multi_nrm2_complex_real_case_types){ -// boost::mpl::for_each, -// thrust::complex//, -// // boost::multi::complex // TODO make this work -// >>([](auto cplx){ -// multi::array const cA = { -// {1., 2., 3., 4.}, -// {5., 6., 7., 8.}, -// {9., 10., 11., 12.} -// }; - -// using multi::blas::nrm2; -// double n; -// BOOST_REQUIRE( nrm2(rotated(cA)[1], n) == std::sqrt( 2.*2. + 6.*6 + 10.*10.) ); -// BOOST_REQUIRE( nrm2(rotated(cA)[1]) == n ); -// }); -//} -// #endif - -// BOOST_AUTO_TEST_CASE(multi_adaptor_multi_nrm2_complex){ -// using complex = std::complex; complex const I{0,1}; -// multi::array const cA = { -// {1., 2. + 1.*I, 3., 4.}, -// {5., 6. + 4.*I, 7., 8.}, -// {9., 10. - 3.*I, 11., 12.} -// }; - -// using multi::blas::nrm2; -// double n; -// BOOST_REQUIRE( nrm2(rotated(cA)[1], n) == std::sqrt( norm(cA[0][1]) + norm(cA[1][1]) + norm(cA[2][1]) ) ); -// BOOST_REQUIRE( nrm2(rotated(cA)[1]) == std::sqrt( norm(cA[0][1]) + norm(cA[1][1]) + norm(cA[2][1]) ) ); - -// using namespace multi::blas::operators; -// BOOST_TEST_REQUIRE( (rotated(cA)[1]^-1) == 1/std::sqrt(norm(cA[0][1]) + norm(cA[1][1]) + norm(cA[2][1])) , boost::test_tools::tolerance(1e-15) ); -// BOOST_TEST_REQUIRE( (rotated(cA)[1]^2) == norm(cA[0][1]) + norm(cA[1][1]) + norm(cA[2][1]) , boost::test_tools::tolerance(1e-15) ); -//} diff --git a/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/test/numeric.cpp b/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/test/numeric.cpp index 5097798bac..fcb02acce7 100644 --- a/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/test/numeric.cpp +++ b/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/test/numeric.cpp @@ -2,170 +2,180 @@ // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt -#include - #include #include +// IWYU pragma: no_include "boost/multi/adaptors/blas/complex_traits.hpp" // for blas // needed by iwyu-clang-macos #include -#include +#include namespace multi = boost::multi; -BOOST_AUTO_TEST_CASE(multi_adaptors_blas_test_numeric_imag) { - using complex = std::complex; auto const I = complex{0.0, 1.0}; // NOLINT(readability-identifier-length) imag unit +#include +#define BOOST_AUTO_TEST_CASE(CasenamE) /**/ - namespace blas = multi::blas; - multi::array const array = { 1.0 + 2.0*I, 3.0 + 5.0*I, 9.0 + 2.0*I }; - BOOST_REQUIRE( blas::imag(array)[2] == 2.0 ); - BOOST_REQUIRE( blas::real(array)[2] == 9.0 ); -} +auto main() -> int { // NOLINT(readability-function-cognitive-complexity,bugprone-exception-escape) + BOOST_AUTO_TEST_CASE(multi_adaptors_blas_test_numeric_imag) { + using complex = std::complex; + auto const I = complex{0.0, 1.0}; // NOLINT(readability-identifier-length) imag unit -BOOST_AUTO_TEST_CASE(multi_blas_numeric_real_conjugated) { - using complex = std::complex; complex const I{0.0, 1.0}; // NOLINT(readability-identifier-length) imag unit + namespace blas = multi::blas; + multi::array const array = {1.0 + 2.0 * I, 3.0 + 5.0 * I, 9.0 + 2.0 * I}; + BOOST_TEST( blas::imag(array)[2] == 2.0 ); + BOOST_TEST( blas::real(array)[2] == 9.0 ); + } - multi::array array = { - {1.0 - 3.0*I, 6.0 + 2.0*I}, - {8.0 + 2.0*I, 2.0 + 4.0*I}, - {2.0 - 1.0*I, 1.0 + 1.0*I} - }; - BOOST_REQUIRE( array[0][0] == 1.0 - 3.0*I ); + BOOST_AUTO_TEST_CASE(multi_blas_numeric_real_conjugated) { + using complex = std::complex; + complex const I{0.0, 1.0}; // NOLINT(readability-identifier-length) imag unit - multi::array const carray = { - {1.0 - 3.0*I, 6.0 + 2.0*I}, - {8.0 + 2.0*I, 2.0 + 4.0*I}, - {2.0 - 1.0*I, 1.0 + 1.0*I} - }; - BOOST_REQUIRE( carray[0][0] == 1.0 - 3.0*I ); + multi::array array = { + {1.0 - 3.0 * I, 6.0 + 2.0 * I}, + {8.0 + 2.0 * I, 2.0 + 4.0 * I}, + {2.0 - 1.0 * I, 1.0 + 1.0 * I} + }; + BOOST_TEST( array[0][0] == 1.0 - 3.0*I ); - namespace blas = multi::blas; - auto conjr = blas::make_conjugater(array.data_elements()); + multi::array const carray = { + {1.0 - 3.0 * I, 6.0 + 2.0 * I}, + {8.0 + 2.0 * I, 2.0 + 4.0 * I}, + {2.0 - 1.0 * I, 1.0 + 1.0 * I} + }; + BOOST_TEST( carray[0][0] == 1.0 - 3.0*I ); - decltype(blas::make_conjugater(carray.data_elements())) ppp; // = BdataC; - ppp = conjr; + namespace blas = multi::blas; + auto conjr = blas::make_conjugater(array.data_elements()); - BOOST_REQUIRE( *ppp == 1.0 + 3.0*I ); + decltype(blas::make_conjugater(carray.data_elements())) ppp; // = BdataC; + ppp = conjr; -// static_assert( multi::blas::is_complex_array, 2>>{}, "!"); - static_assert( blas::is_complex_array{} ); - static_assert(! blas::is_conjugated{} ); + BOOST_TEST( *ppp == 1.0 + 3.0*I ); - auto&& conjd_array = blas::conj(array); - static_assert( blas::is_conjugated{} ); + // static_assert( multi::blas::is_complex_array, 2>>{}, "!"); + static_assert(blas::is_complex_array{}); + static_assert(!blas::is_conjugated{}); - BOOST_REQUIRE( conjd_array[0][0] == 1.0 + 3.0*I ); - BOOST_REQUIRE( imag(*base(conjd_array)) == +3.0 ); + auto&& conjd_array = blas::conj(array); + static_assert(blas::is_conjugated{}); -// BOOST_TEST_REQUIRE( base(Bconj)->imag() == +3 ); - BOOST_REQUIRE( conjd_array[0][1] == rotated(conjd_array)[1][0] ); - BOOST_REQUIRE( rotated(conjd_array)[1][0] == conjd_array[0][1] ); + BOOST_TEST( conjd_array[0][0] == 1.0 + 3.0*I ); + BOOST_TEST( imag(*conjd_array.base()) == +3.0 ); -// BOOST_REQUIRE( base(Bconj) == -3.0*I ); - static_assert( blas::is_complex_array{} ); + // BOOST_TEST_REQUIRE( base(Bconj)->imag() == +3 ); + BOOST_TEST( conjd_array[0][1] == conjd_array.rotated()[1][0] ); + BOOST_TEST( conjd_array.rotated()[1][0] == conjd_array[0][1] ); - BOOST_REQUIRE( blas::conj(conjd_array) == array ); + // BOOST_TEST( base(Bconj) == -3.0*I ); + static_assert(blas::is_complex_array{}); - BOOST_REQUIRE( blas::conj(array)[1][0] == std::conj(array[1][0]) ); -} + BOOST_TEST( blas::conj(conjd_array) == array ); -BOOST_AUTO_TEST_CASE(multi_blas_numeric_decay) { - using complex = std::complex; complex const I{0.0, 1.0}; // NOLINT(readability-identifier-length) imag unit + BOOST_TEST( blas::conj(array)[1][0] == std::conj(array[1][0]) ); + } - multi::array arr = { - { 1.0 - 3.0*I, 6.0 + 2.0*I, 9.0 + 3.0*I}, - { 8.0 + 2.0*I, 2.0 + 4.0*I, 9.0 + 3.0*I}, - { 2.0 - 1.0*I, 1.0 + 1.0*I, 9.0 + 3.0*I}, - { 9.0 + 3.0*I, 9.0 + 3.0*I, 9.0 + 3.0*I} - }; + BOOST_AUTO_TEST_CASE(multi_blas_numeric_decay) { + using complex = std::complex; + complex const I{0.0, 1.0}; // NOLINT(readability-identifier-length) imag unit - namespace blas = multi::blas; - multi::array conj_arr{blas::conj(arr)}; - multi::array const conj_arr2 = blas::conj(arr); + multi::array arr = { + {1.0 - 3.0 * I, 6.0 + 2.0 * I, 9.0 + 3.0 * I}, + {8.0 + 2.0 * I, 2.0 + 4.0 * I, 9.0 + 3.0 * I}, + {2.0 - 1.0 * I, 1.0 + 1.0 * I, 9.0 + 3.0 * I}, + {9.0 + 3.0 * I, 9.0 + 3.0 * I, 9.0 + 3.0 * I} + }; - BOOST_REQUIRE( conj_arr[2][1] == std::conj(arr[2][1]) ); - BOOST_REQUIRE( blas::conj(arr)[2][1] == std::conj(arr[2][1]) ); + namespace blas = multi::blas; + multi::array conj_arr{blas::conj(arr)}; + multi::array const conj_arr2{blas::conj(arr)}; - BOOST_REQUIRE( blas::transposed(arr)[1][2] == arr[2][1] ); - BOOST_REQUIRE( blas::transposed(arr) == ~arr ); + BOOST_TEST( conj_arr[2][1] == std::conj(arr[2][1]) ); + BOOST_TEST( blas::conj(arr)[2][1] == std::conj(arr[2][1]) ); - BOOST_REQUIRE( blas::conj(arr)[1][2] == blas::hermitized(arr)[2][1] ); - BOOST_REQUIRE( blas::conj(blas::transposed(arr)) == blas::hermitized(arr) ); + BOOST_TEST( blas::T(arr)[1][2] == arr[2][1] ); + BOOST_TEST( blas::T(arr) == ~arr ); - BOOST_REQUIRE( blas::hermitized(arr)[2][1] == blas::conj(arr)[1][2] ); - BOOST_REQUIRE( blas::hermitized(arr) == blas::conj(blas::transposed(arr)) ); + BOOST_TEST( blas::conj(arr)[1][2] == blas::hermitized(arr)[2][1] ); + BOOST_TEST( blas::conj(blas::T(arr)) == blas::hermitized(arr) ); - BOOST_REQUIRE( blas::real(arr)[2][1] == std::real(arr[2][1]) ); - BOOST_REQUIRE( blas::imag(arr)[2][1] == std::imag(arr[2][1]) ); + BOOST_TEST( blas::hermitized(arr)[2][1] == blas::conj(arr)[1][2] ); + BOOST_TEST( blas::hermitized(arr) == blas::conj(blas::T(arr)) ); - multi::array const B_real_doubled = { - { 1.0, -3.0, 6.0, 2.0, 9.0, 3.0}, - { 8.0, 2.0, 2.0, 4.0, 9.0, 3.0}, - { 2.0, -1.0, 1.0, 1.0, 9.0, 3.0}, - { 9.0, 3.0, 9.0, 3.0, 9.0, 3.0} - }; - BOOST_REQUIRE( sizes(blas::real_doubled(arr)) == sizes(B_real_doubled) ); - BOOST_REQUIRE( blas::real_doubled(arr) == B_real_doubled ); -} + BOOST_TEST( blas::real(arr)[2][1] == std::real(arr[2][1]) ); + BOOST_TEST( blas::imag(arr)[2][1] == std::imag(arr[2][1]) ); -#if defined(CUDA_FOUND) and CUDA_FOUND -#include + multi::array const B_real_doubled = { + {1.0, -3.0, 6.0, 2.0, 9.0, 3.0}, + {8.0, 2.0, 2.0, 4.0, 9.0, 3.0}, + {2.0, -1.0, 1.0, 1.0, 9.0, 3.0}, + {9.0, 3.0, 9.0, 3.0, 9.0, 3.0} + }; + BOOST_TEST( blas::real_doubled(arr).sizes() == B_real_doubled.sizes() ); + BOOST_TEST( blas::real_doubled(arr) == B_real_doubled ); + } -BOOST_AUTO_TEST_CASE(multi_blas_numeric_decay_thrust) { - using complex = thrust::complex; complex const I{0.0, 1.0}; - - multi::array B = { - {1.0 - 3.0*I, 6.0 + 2.0*I}, - {8.0 + 2.0*I, 2.0 + 4.0*I}, - {2.0 - 1.0*I, 1.0 + 1.0*I}, - }; - - namespace blas = multi::blas; - multi::array conjB = blas::conj(B); - BOOST_REQUIRE( conjB[1][2] == conj(B[1][2]) ); -} +#if defined(CUDA_FOUND) and CUDA_FOUND + #include + + BOOST_AUTO_TEST_CASE(multi_blas_numeric_decay_thrust) { + using complex = thrust::complex; + complex const I{0.0, 1.0}; + + multi::array B = { + {1.0 - 3.0 * I, 6.0 + 2.0 * I}, + {8.0 + 2.0 * I, 2.0 + 4.0 * I}, + {2.0 - 1.0 * I, 1.0 + 1.0 * I}, + }; + + namespace blas = multi::blas; + multi::array conjB = blas::conj(B); + BOOST_TEST( conjB[1][2] == conj(B[1][2]) ); + } #endif -BOOST_AUTO_TEST_CASE(multi_blas_numeric_real_imag_part) { - using complex = std::complex; complex const I{0.0, 1.0}; // NOLINT(readability-identifier-length) imag unit - - multi::array arr = { - {1.0, 3.0, 4.0}, - {9.0, 7.0, 1.0} - }; - multi::array complex_arr = arr; - BOOST_REQUIRE( complex_arr[1][1] == arr[1][1] ); - - multi::array arr2 = { - {1.0 - 3.0*I, 6.0 + 2.0*I}, - {8.0 + 2.0*I, 2.0 + 4.0*I}, - {2.0 - 1.0*I, 1.0 + 1.0*I} - }; - - multi::array const arr2_real = { - {1.0, 6.0}, - {8.0, 2.0}, - {2.0, 1.0}, - }; - multi::array const arr2_imag = { - {-3.0, +2.0}, - {+2.0, +4.0}, - {-1.0, +1.0}, - }; - - using multi::blas::real; - using multi::blas::imag; - - BOOST_REQUIRE( arr2_real == real(arr2) ); - BOOST_REQUIRE( real(arr2) == arr2_real ); - BOOST_REQUIRE( imag(arr2) == arr2_imag ); - - BOOST_REQUIRE( arr2[1][0] == 8.0 + 2.0*I ); - BOOST_REQUIRE( arr2[1][0].imag() == 2.0 ); - - namespace blas = multi::blas; - BOOST_REQUIRE( blas::hermitized(arr2)[1][2] == std::conj( arr2[2][1] ) ); - - blas::hermitized(arr2)[1][2] = 20.0 + 30.0*I; - BOOST_REQUIRE( arr2[2][1] == 20.0 - 30.0*I ); + BOOST_AUTO_TEST_CASE(multi_blas_numeric_real_imag_part) { + using complex = std::complex; + complex const I{0.0, 1.0}; // NOLINT(readability-identifier-length) imag unit + + multi::array arr = { + {1.0, 3.0, 4.0}, + {9.0, 7.0, 1.0} + }; + multi::array complex_arr = arr; + BOOST_TEST( complex_arr[1][1] == arr[1][1] ); + + multi::array arr2 = { + {1.0 - 3.0 * I, 6.0 + 2.0 * I}, + {8.0 + 2.0 * I, 2.0 + 4.0 * I}, + {2.0 - 1.0 * I, 1.0 + 1.0 * I} + }; + + multi::array const arr2_real = { + {1.0, 6.0}, + {8.0, 2.0}, + {2.0, 1.0}, + }; + multi::array const arr2_imag = { + {-3.0, +2.0}, + {+2.0, +4.0}, + {-1.0, +1.0}, + }; + + using multi::blas::imag; + using multi::blas::real; + + BOOST_TEST( arr2_real == real(arr2) ); + BOOST_TEST( real(arr2) == arr2_real ); + BOOST_TEST( imag(arr2) == arr2_imag ); + + BOOST_TEST( arr2[1][0] == 8.0 + 2.0*I ); + BOOST_TEST( arr2[1][0].imag() == 2.0 ); + + namespace blas = multi::blas; + BOOST_TEST( blas::hermitized(arr2)[1][2] == std::conj( arr2[2][1] ) ); + + blas::hermitized(arr2)[1][2] = 20.0 + 30.0 * I; + BOOST_TEST( arr2[2][1] == 20.0 - 30.0*I ); + } + return boost::report_errors(); } diff --git a/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/test/scal.cpp b/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/test/scal.cpp index b517e232cc..132ae0c27c 100644 --- a/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/test/scal.cpp +++ b/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/test/scal.cpp @@ -2,87 +2,96 @@ // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt -#include - #include +// IWYU pragma: no_include "boost/multi/adaptors/blas/traits.hpp" // for blas, multi #include +#include // for complex, operator* + namespace multi = boost::multi; namespace blas = multi::blas; +#include +#define BOOST_AUTO_TEST_CASE(CasenamE) /**/ +#define BOOST_REQUIRE_CLOSE(X, Y, ToL) BOOST_TEST( std::abs( (X) - (Y) ) < (ToL) ) +// #define BOOST_REQUIRE_SMALL(X, ToL) BOOST_TEST( std::abs( X ) < (ToL) ) + +auto main() -> int { // NOLINT(readability-function-cognitive-complexity,bugprone-exception-escape) BOOST_AUTO_TEST_CASE(multi_adaptors_blas_test_scal_n) { multi::array arr = { - {1.0, 2.0, 3.0, 4.0}, - {5.0, 6.0, 7.0, 8.0}, - {9.0, 10.0, 11.0, 12.0}, + { 1.0, 2.0, 3.0, 4.0 }, + { 5.0, 6.0, 7.0, 8.0 }, + { 9.0, 10.0, 11.0, 12.0 }, }; - BOOST_REQUIRE( (arr[0][2] == 3.0) && (arr[2][2] == 11.0) ); + BOOST_TEST( (arr[0][2] == 3.0) && (arr[2][2] == 11.0) ); blas::scal_n(2.0, arr[2].begin(), arr[2].size()); - BOOST_REQUIRE( arr[0][2] == 3. && arr[2][2] == 11.0*2.0 ); + BOOST_TEST( arr[0][2] == 3. && arr[2][2] == 11.0*2.0 ); } BOOST_AUTO_TEST_CASE(multi_adaptors_blas_test_scal_it) { multi::array arr = { - {1.0, 2.0, 3.0, 4.0}, - {5.0, 6.0, 7.0, 8.0}, - {9.0, 10.0, 11.0, 12.0}, + { 1.0, 2.0, 3.0, 4.0 }, + { 5.0, 6.0, 7.0, 8.0 }, + { 9.0, 10.0, 11.0, 12.0 }, }; - BOOST_REQUIRE( arr[0][2] == 3.0 ); - BOOST_REQUIRE( arr[2][2] == 11.0 ); + BOOST_TEST( arr[0][2] == 3.0 ); + BOOST_TEST( arr[2][2] == 11.0 ); blas::scal(2.0, arr[2].begin(), arr[2].end()); - BOOST_REQUIRE( arr[0][2] == 3.0 ); - BOOST_REQUIRE(arr[2][2] == 11.0*2.0 ); + BOOST_TEST( arr[0][2] == 3.0 ); + BOOST_TEST(arr[2][2] == 11.0*2.0 ); } BOOST_AUTO_TEST_CASE(multi_adaptors_blas_test_scal_real) { multi::array arr = { - {1.0, 2.0, 3.0, 4.0}, - {5.0, 6.0, 7.0, 8.0}, - {9.0, 10.0, 11.0, 12.0}, + { 1.0, 2.0, 3.0, 4.0 }, + { 5.0, 6.0, 7.0, 8.0 }, + { 9.0, 10.0, 11.0, 12.0 }, }; - BOOST_REQUIRE( arr[0][2] == 3.0 ); - BOOST_REQUIRE( arr[2][2] == 11.0 ); + BOOST_TEST( arr[0][2] == 3.0 ); + BOOST_TEST( arr[2][2] == 11.0 ); - BOOST_REQUIRE( blas::scal(1.0, arr[2]) == arr[2] ); - BOOST_REQUIRE( &blas::scal(1.0, arr[2]) == &arr[2] ); - BOOST_REQUIRE( +blas::scal(1.0, arr[2]) == arr[2] ); + BOOST_TEST( blas::scal(1.0, arr[2]) == arr[2] ); + BOOST_TEST( &blas::scal(1.0, arr[2]) == &arr[2] ); + BOOST_TEST( +blas::scal(1.0, arr[2]) == arr[2] ); blas::scal(2.0, arr[2]); - BOOST_REQUIRE( arr[0][2] == 3.0 && arr[2][2] == 11.0*2.0 ); + BOOST_TEST( arr[0][2] == 3.0 && arr[2][2] == 11.0*2.0 ); - BOOST_REQUIRE( &blas::scal(1.0, arr[2]) == &arr[2] ); + BOOST_TEST( &blas::scal(1.0, arr[2]) == &arr[2] ); } BOOST_AUTO_TEST_CASE(multi_adaptors_blas_test_scal_real_2D) { multi::array arr = { - {1.0, 2.0, 3.0, 4.0}, - {5.0, 6.0, 7.0, 8.0}, - {9.0, 10.0, 11.0, 12.0}, + { 1.0, 2.0, 3.0, 4.0 }, + { 5.0, 6.0, 7.0, 8.0 }, + { 9.0, 10.0, 11.0, 12.0 }, }; - BOOST_REQUIRE( arr[0][2] == 3.0 ); - BOOST_REQUIRE( arr[2][2] == 11.0 ); + BOOST_TEST( arr[0][2] == 3.0 ); + BOOST_TEST( arr[2][2] == 11.0 ); blas::scal(2.0, arr.elements()); - BOOST_REQUIRE( arr[0][2] == 6.0 ); - BOOST_REQUIRE( arr[2][2] == 22.0 ); + BOOST_TEST( arr[0][2] == 6.0 ); + BOOST_TEST( arr[2][2] == 22.0 ); } BOOST_AUTO_TEST_CASE(multi_adaptors_blas_test_scal_complex_2D) { auto const I = std::complex(0.0, 1.0); // NOLINT(readability-identifier-length) blas conventional name + multi::array, 2> arr = { - {1.0 + 0.0*I, 2.0 + 0.0*I, 3.0 + 0.0*I, 4.0 + 0.0*I}, - {5.0 + 0.0*I, 6.0 + 0.0*I, 7.0 + 0.0*I, 8.0 + 0.0*I}, - {9.0 + 0.0*I, 10.0 + 0.0*I, 11.0 + 0.0*I, 12.0 + 0.0*I}, + { 1.0 + 0.0 * I, 2.0 + 0.0 * I, 3.0 + 0.0 * I, 4.0 + 0.0 * I }, + { 5.0 + 0.0 * I, 6.0 + 0.0 * I, 7.0 + 0.0 * I, 8.0 + 0.0 * I }, + { 9.0 + 0.0 * I, 10.0 + 0.0 * I, 11.0 + 0.0 * I, 12.0 + 0.0 * I }, }; - BOOST_REQUIRE( arr[0][2] == 3.0 ); - BOOST_REQUIRE( arr[2][2] == 11.0 ); + BOOST_TEST( arr[0][2] == 3.0 ); + BOOST_TEST( arr[2][2] == 11.0 ); blas::scal(2.0, arr.elements()); - BOOST_REQUIRE( arr[0][2] == 6.0 ); - BOOST_REQUIRE( arr[2][2] == 22.0 ); + BOOST_TEST( arr[0][2] == 6.0 ); + BOOST_TEST( arr[2][2] == 22.0 ); } +return boost::report_errors();} diff --git a/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/test/swap.cpp b/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/test/swap.cpp index d87c8c6dc2..9f41e8a856 100644 --- a/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/test/swap.cpp +++ b/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/test/swap.cpp @@ -1,5 +1,4 @@ -// -*-indent-tabs-mode:t;c-basic-offset:4;tab-width:4;autowrap:nil;-*- -// Copyright 2019-2023 Alfredo A. Correa +// Copyright 2019-2024 Alfredo A. Correa #define BOOST_TEST_MODULE "C++ Unit Tests for Multi BLAS swap" #include @@ -50,7 +49,7 @@ BOOST_AUTO_TEST_CASE(lapack_potrf, *boost::unit_test::tolerance(0.00001)) { } { using complex = std::complex; - complex const I{0, 1}; + complex const I{0, 1}; multi::array A = { {1.0 + 2. * I, 2.0, 3.0, 4.0 + 3.0 * I}, { 5.0, 6.0, 7.0, 8.0}, diff --git a/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/test/syrk.cpp b/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/test/syrk.cpp index 329ebf7564..ffeb0c9fd6 100644 --- a/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/test/syrk.cpp +++ b/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/test/syrk.cpp @@ -2,314 +2,314 @@ // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt -#include +#include // for filling +#include // for transposed, T +#include // for syrk +// IWYU pragma: no_include "boost/multi/adaptors/blas/traits.hpp" // for blas, multi -#include -#include +#include // for array, layout_t -#include +#include // for operator*, complex namespace multi = boost::multi; -BOOST_AUTO_TEST_CASE(multi_blas_syrk_real) { - // NOLINTNEXTLINE(readability-identifier-length) - multi::array const a = { - {1.0, 3.0, 4.0}, - {9.0, 7.0, 1.0}, - }; - { - multi::array c({3, 3}, 9999.0); // NOLINT(readability-identifier-length) - namespace blas = multi::blas; +#include +#define BOOST_AUTO_TEST_CASE(CasenamE) /**/ - using blas::filling; - using blas::transposed; +auto main() -> int { // NOLINT(readability-function-cognitive-complexity,bugprone-exception-escape) + BOOST_AUTO_TEST_CASE(multi_blas_syrk_real) { + // NOLINTNEXTLINE(readability-identifier-length) + multi::array const a = { + {1.0, 3.0, 4.0}, + {9.0, 7.0, 1.0}, + }; + { + multi::array c({3, 3}, 9999.0); // NOLINT(readability-identifier-length) + namespace blas = multi::blas; - syrk(filling::lower, 1.0, transposed(a), 0.0, c); // c⸆=c=a⸆a=(a⸆a)⸆, `c` in lower triangular + using blas::filling; - BOOST_REQUIRE( c[2][1] == 19.0 ); - BOOST_REQUIRE( c[1][2] == 9999.0 ); - } - { - multi::array c({3, 3}, 9999.0); // NOLINT(readability-identifier-length) - namespace blas = multi::blas; + syrk(filling::lower, 1.0, blas::T(a), 0.0, c); // c⸆=c=a⸆a=(a⸆a)⸆, `c` in lower triangular - using blas::filling; - using blas::transposed; + BOOST_TEST( c[2][1] == 19.0 ); + BOOST_TEST( c[1][2] == 9999.0 ); + } + { + multi::array c({3, 3}, 9999.0); // NOLINT(readability-identifier-length) + namespace blas = multi::blas; - syrk(filling::upper, 1.0, transposed(a), 0.0, c); // c⸆=c=a⸆a=(a⸆a)⸆, `c` in lower triangular + using blas::filling; - BOOST_REQUIRE( c[1][2] == 19.0 ); - BOOST_REQUIRE( c[2][1] == 9999.0 ); - } - { - multi::array c({2, 2}, 9999.0); // NOLINT(readability-identifier-length) - namespace blas = multi::blas; + syrk(filling::upper, 1.0, blas::T(a), 0.0, c); // c⸆=c=a⸆a=(a⸆a)⸆, `c` in lower triangular - using blas::filling; - using blas::syrk; + BOOST_TEST( c[1][2] == 19.0 ); + BOOST_TEST( c[2][1] == 9999.0 ); + } + { + multi::array c({2, 2}, 9999.0); // NOLINT(readability-identifier-length) + namespace blas = multi::blas; - syrk(filling::lower, 1.0, a, 0.0, c); // c⸆=c=a⸆a=(a⸆a)⸆, `c` in lower triangular + using blas::filling; + using blas::syrk; - BOOST_REQUIRE( c[1][0] == 34.0 ); - BOOST_REQUIRE( c[0][1] == 9999.0 ); - } - { - multi::array c({2, 2}, 9999.0); // NOLINT(readability-identifier-length) + syrk(filling::lower, 1.0, a, 0.0, c); // c⸆=c=a⸆a=(a⸆a)⸆, `c` in lower triangular - namespace blas = multi::blas; + BOOST_TEST( c[1][0] == 34.0 ); + BOOST_TEST( c[0][1] == 9999.0 ); + } + { + multi::array c({2, 2}, 9999.0); // NOLINT(readability-identifier-length) - using blas::filling; + namespace blas = multi::blas; - syrk(filling::upper, 1.0, a, 0.0, c); // c⸆=c=a⸆a=(a⸆a)⸆, a⸆a, `c` in lower triangular + using blas::filling; - BOOST_REQUIRE( c[0][1] == 34.0 ); - BOOST_REQUIRE( c[1][0] == 9999.0 ); - } - { - multi::array c({2, 2}, 9999.0); // NOLINT(readability-identifier-length) + syrk(filling::upper, 1.0, a, 0.0, c); // c⸆=c=a⸆a=(a⸆a)⸆, a⸆a, `c` in lower triangular + + BOOST_TEST( c[0][1] == 34.0 ); + BOOST_TEST( c[1][0] == 9999.0 ); + } + { + multi::array c({2, 2}, 9999.0); // NOLINT(readability-identifier-length) - namespace blas = multi::blas; + namespace blas = multi::blas; - using blas::filling; + using blas::filling; - syrk(filling::upper, 1.0, a, 0.0, c); // c⸆=c=a⸆a=(a⸆a)⸆, a⸆a, `c` in lower triangular + syrk(filling::upper, 1.0, a, 0.0, c); // c⸆=c=a⸆a=(a⸆a)⸆, a⸆a, `c` in lower triangular - BOOST_REQUIRE( c[0][1] == 34.0 ); - BOOST_REQUIRE( c[1][0] == 9999.0 ); + BOOST_TEST( c[0][1] == 34.0 ); + BOOST_TEST( c[1][0] == 9999.0 ); + } } -} -BOOST_AUTO_TEST_CASE(multi_blas_syrk_real_special_case) { - // NOLINTNEXTLINE(readability-identifier-length) - multi::array const a = { - {1.0, 3.0, 4.0}, - }; - { - multi::array c({1, 1}, 9999.0); // NOLINT(readability-identifier-length) + BOOST_AUTO_TEST_CASE(multi_blas_syrk_real_special_case) { + // NOLINTNEXTLINE(readability-identifier-length) + multi::array const a = { + {1.0, 3.0, 4.0}, + }; + { + multi::array c({1, 1}, 9999.0); // NOLINT(readability-identifier-length) - namespace blas = multi::blas; - using blas::filling; + namespace blas = multi::blas; + using blas::filling; - syrk(filling::lower, 1.0, a, 0.0, c); // c⸆=c=a⸆a=(a⸆a)⸆, `c` in lower triangular + syrk(filling::lower, 1.0, a, 0.0, c); // c⸆=c=a⸆a=(a⸆a)⸆, `c` in lower triangular - BOOST_TEST( c[0][0] == 1.0*1.0 + 3.0*3.0 + 4.0*4.0 ); - } - { - multi::array c({1, 1}, 9999.0); // NOLINT(readability-identifier-length) + BOOST_TEST( c[0][0] == 1.0*1.0 + 3.0*3.0 + 4.0*4.0 ); + } + { + multi::array c({1, 1}, 9999.0); // NOLINT(readability-identifier-length) - namespace blas = multi::blas; - using blas::filling; + namespace blas = multi::blas; + using blas::filling; - syrk(filling::upper, 1.0, a, 0.0, c); // c⸆=c=a⸆a=(a⸆a)⸆, `c` in lower triangular + syrk(filling::upper, 1.0, a, 0.0, c); // c⸆=c=a⸆a=(a⸆a)⸆, `c` in lower triangular - BOOST_TEST( c[0][0] == 1.0*1.0 + 3.0*3.0 + 4.0*4.0 ); + BOOST_TEST( c[0][0] == 1.0*1.0 + 3.0*3.0 + 4.0*4.0 ); + } } -} -BOOST_AUTO_TEST_CASE(multi_blas_syrk_complex_real_case) { - using complex = std::complex; - auto const I = complex{0.0, 1.0}; // NOLINT(readability-identifier-length) imag unit + BOOST_AUTO_TEST_CASE(multi_blas_syrk_complex_real_case) { + using complex = std::complex; + auto const I = complex{0.0, 1.0}; // NOLINT(readability-identifier-length) imag unit - // NOLINTNEXTLINE(readability-identifier-length) - multi::array const a = { - {1.0 + I * 0.0, 3.0 + I * 0.0, 4.0 + I * 0.0}, - {9.0 + I * 0.0, 7.0 + I * 0.0, 1.0 + I * 0.0}, - }; - { - multi::array c({3, 3}, 9999.0 + I * 0.0); // NOLINT(readability-identifier-length) + // NOLINTNEXTLINE(readability-identifier-length) + multi::array const a = { + {1.0 + I * 0.0, 3.0 + I * 0.0, 4.0 + I * 0.0}, + {9.0 + I * 0.0, 7.0 + I * 0.0, 1.0 + I * 0.0}, + }; + { + multi::array c({3, 3}, 9999.0 + I * 0.0); // NOLINT(readability-identifier-length) - namespace blas = multi::blas; + namespace blas = multi::blas; - using blas::filling; - using blas::transposed; + using blas::filling; - syrk(filling::lower, 1.0, transposed(a), 0.0, c); // c⸆=c=a⸆a=(a⸆a)⸆, `c` in lower triangular // NOLINT(fuchsia-default-arguments-calls) + syrk(filling::lower, 1.0, blas::T(a), 0.0, c); // c⸆=c=a⸆a=(a⸆a)⸆, `c` in lower triangular // NOLINT(fuchsia-default-arguments-calls) - BOOST_REQUIRE( real(c[2][1]) == 19.0 ); - BOOST_REQUIRE( real(c[1][2]) == 9999.0 ); + BOOST_TEST( real(c[2][1]) == 19.0 ); + BOOST_TEST( real(c[1][2]) == 9999.0 ); + } } -} -BOOST_AUTO_TEST_CASE(multi_blas_syrk_complex) { - using complex = std::complex; + BOOST_AUTO_TEST_CASE(multi_blas_syrk_complex) { + using complex = std::complex; - auto const I = complex{0.0, 1.0}; // NOLINT(readability-identifier-length) + auto const I = complex{0.0, 1.0}; // NOLINT(readability-identifier-length) - // NOLINTNEXTLINE(readability-identifier-length) - multi::array const a = { - {1.0 + 3.0 * I, 3.0 - 2.0 * I, 4.0 + 1.0 * I}, - {9.0 + 1.0 * I, 7.0 - 8.0 * I, 1.0 - 3.0 * I}, - }; - { - multi::array c({3, 3}, 9999.0 + I * 0.0); // NOLINT(readability-identifier-length) + // NOLINTNEXTLINE(readability-identifier-length) + multi::array const a = { + {1.0 + 3.0 * I, 3.0 - 2.0 * I, 4.0 + 1.0 * I}, + {9.0 + 1.0 * I, 7.0 - 8.0 * I, 1.0 - 3.0 * I}, + }; + { + multi::array c({3, 3}, 9999.0 + I * 0.0); // NOLINT(readability-identifier-length) - namespace blas = multi::blas; + namespace blas = multi::blas; - syrk(blas::filling::lower, 1.0, blas::T(a), 0.0, c); // c⸆=c=a⸆a=(a⸆a)⸆, `c` in lower triangular // NOLINT(fuchsia-default-arguments-calls) + syrk(blas::filling::lower, 1.0, blas::T(a), 0.0, c); // c⸆=c=a⸆a=(a⸆a)⸆, `c` in lower triangular // NOLINT(fuchsia-default-arguments-calls) - BOOST_TEST( real(c[2][1]) == - 3.0 ); - BOOST_TEST( imag(c[2][1]) == -34.0 ); - } - { - multi::array c({2, 2}, 9999.0 + I * 0.0); // NOLINT(readability-identifier-length) + BOOST_TEST( real(c[2][1]) == - 3.0 ); + BOOST_TEST( imag(c[2][1]) == -34.0 ); + } + { + multi::array c({2, 2}, 9999.0 + I * 0.0); // NOLINT(readability-identifier-length) - namespace blas = multi::blas; + namespace blas = multi::blas; - syrk(blas::filling::lower, 1.0, a, 0.0, c); // c⸆=c=aa⸆=(aa⸆)⸆, `c` in lower triangular // NOLINT(fuchsia-default-arguments-calls) + syrk(blas::filling::lower, 1.0, a, 0.0, c); // c⸆=c=aa⸆=(aa⸆)⸆, `c` in lower triangular // NOLINT(fuchsia-default-arguments-calls) - BOOST_REQUIRE( c[1][0] == complex(18.0, -21.0) ); - BOOST_REQUIRE( c[0][1] == 9999.0 ); - } - { - multi::array c({2, 2}, 9999.0 + I * 0.0); // NOLINT(readability-identifier-length) + BOOST_TEST( c[1][0] == complex(18.0, -21.0) ); + BOOST_TEST( c[0][1] == 9999.0 ); + } + { + multi::array c({2, 2}, 9999.0 + I * 0.0); // NOLINT(readability-identifier-length) - namespace blas = multi::blas; + namespace blas = multi::blas; - syrk(blas::filling::upper, 1.0, a, 0.0, c); // c⸆=c=aa⸆=(aa⸆)⸆, `c` in upper triangular // NOLINT(fuchsia-default-arguments-calls) + syrk(blas::filling::upper, 1.0, a, 0.0, c); // c⸆=c=aa⸆=(aa⸆)⸆, `c` in upper triangular // NOLINT(fuchsia-default-arguments-calls) - BOOST_REQUIRE( c[0][1] == complex(18.0, -21.0) ); - BOOST_REQUIRE( c[1][0] == 9999.0 ); + BOOST_TEST( c[0][1] == complex(18.0, -21.0) ); + BOOST_TEST( c[1][0] == 9999.0 ); + } } -} -BOOST_AUTO_TEST_CASE(multi_blas_syrk_automatic_operation_complex) { - using complex = std::complex; + BOOST_AUTO_TEST_CASE(multi_blas_syrk_automatic_operation_complex) { + using complex = std::complex; - auto const I = complex{0.0, 1.0}; // NOLINT(readability-identifier-length) + auto const I = complex{0.0, 1.0}; // NOLINT(readability-identifier-length) - // NOLINTNEXTLINE(readability-identifier-length) - multi::array const a = { - {1.0 + 3.0 * I, 3.0 - 2.0 * I, 4.0 + 1.0 * I}, - {9.0 + 1.0 * I, 7.0 - 8.0 * I, 1.0 - 3.0 * I}, - }; + // NOLINTNEXTLINE(readability-identifier-length) + multi::array const a = { + {1.0 + 3.0 * I, 3.0 - 2.0 * I, 4.0 + 1.0 * I}, + {9.0 + 1.0 * I, 7.0 - 8.0 * I, 1.0 - 3.0 * I}, + }; - { - multi::array c({2, 2}, 9999.0 + I * 0.0); // NOLINT(readability-identifier-length) + { + multi::array c({2, 2}, 9999.0 + I * 0.0); // NOLINT(readability-identifier-length) - using multi::blas::filling; + using multi::blas::filling; - syrk(filling::lower, 1.0, a, 0.0, c); // c⸆=c=aa⸆=(aa⸆)⸆, `c` in lower triangular // NOLINT(fuchsia-default-arguments-calls) + syrk(filling::lower, 1.0, a, 0.0, c); // c⸆=c=aa⸆=(aa⸆)⸆, `c` in lower triangular // NOLINT(fuchsia-default-arguments-calls) - BOOST_REQUIRE( c[1][0]==complex(18.0, -21.0) ); - BOOST_REQUIRE( c[0][1]==9999.0 ); - } - { - multi::array c({3, 3}, 9999.0); // NOLINT(readability-identifier-length) // NOLINT(fuchsia-default-arguments-calls) + BOOST_TEST( c[1][0] == complex(18.0, -21.0) ); + BOOST_TEST( c[0][1] == 9999.0 ); + } + { + multi::array c({3, 3}, 9999.0); // NOLINT(readability-identifier-length) // NOLINT(fuchsia-default-arguments-calls) - namespace blas = multi::blas; + namespace blas = multi::blas; - using blas::filling; - using blas::transposed; + using blas::filling; - syrk(filling::lower, 1.0, transposed(a), 0.0, c); // c⸆=c=a⸆a=(aa⸆)⸆, `c` in lower triangular // NOLINT(fuchsia-default-arguments-calls) + syrk(filling::lower, 1.0, blas::T(a), 0.0, c); // c⸆=c=a⸆a=(aa⸆)⸆, `c` in lower triangular // NOLINT(fuchsia-default-arguments-calls) - BOOST_REQUIRE( c[2][1] == complex(-3.0, -34.0) ); - BOOST_REQUIRE( c[1][2] == 9999.0 ); - } - { - multi::array c({3, 3}, 9999.0); // NOLINT(readability-identifier-length) // NOLINT(fuchsia-default-arguments-calls) + BOOST_TEST( c[2][1] == complex(-3.0, -34.0) ); + BOOST_TEST( c[1][2] == 9999.0 ); + } + { + multi::array c({3, 3}, 9999.0); // NOLINT(readability-identifier-length) // NOLINT(fuchsia-default-arguments-calls) - namespace blas = multi::blas; + namespace blas = multi::blas; - using blas::filling; - using blas::transposed; + using blas::filling; - syrk(filling::lower, 1.0, rotated(a), 0.0, c); // c⸆=c=a⸆a=(aa⸆)⸆, `c` in lower triangular // NOLINT(fuchsia-default-arguments-calls) + syrk(filling::lower, 1.0, a.rotated(), 0.0, c); // c⸆=c=a⸆a=(aa⸆)⸆, `c` in lower triangular // NOLINT(fuchsia-default-arguments-calls) - BOOST_REQUIRE( c[2][1] == complex(-3.0, -34.0) ); - BOOST_REQUIRE( c[1][2] == 9999.0 ); + BOOST_TEST( c[2][1] == complex(-3.0, -34.0) ); + BOOST_TEST( c[1][2] == 9999.0 ); + } } -} -BOOST_AUTO_TEST_CASE(multi_blas_syrk_automatic_operation_real) { - // NOLINTNEXTLINE(readability-identifier-length) - multi::array const a = { - {1.0, 3.0, 4.0}, - {9.0, 7.0, 1.0}, - }; - { - multi::array c({2, 2}, 9999.0); // NOLINT(readability-identifier-length) + BOOST_AUTO_TEST_CASE(multi_blas_syrk_automatic_operation_real) { + // NOLINTNEXTLINE(readability-identifier-length) + multi::array const a = { + {1.0, 3.0, 4.0}, + {9.0, 7.0, 1.0}, + }; + { + multi::array c({2, 2}, 9999.0); // NOLINT(readability-identifier-length) - using multi::blas::filling; + using multi::blas::filling; - syrk(filling::lower, 1.0, a, 0.0, c); // c⸆=c=aa⸆=(aa⸆)⸆, `c` in lower triangular + syrk(filling::lower, 1.0, a, 0.0, c); // c⸆=c=aa⸆=(aa⸆)⸆, `c` in lower triangular - BOOST_REQUIRE( c[1][0] == 34.0 ); - BOOST_REQUIRE( c[0][1] == 9999.0 ); - } - { - multi::array c({2, 2}, 9999.0); // NOLINT(readability-identifier-length) + BOOST_TEST( c[1][0] == 34.0 ); + BOOST_TEST( c[0][1] == 9999.0 ); + } + { + multi::array c({2, 2}, 9999.0); // NOLINT(readability-identifier-length) - using multi::blas::filling; + using multi::blas::filling; - syrk(filling::upper, 1.0, a, 0.0, c); // c⸆=c=aa⸆=(aa⸆)⸆, `c` in upper triangular + syrk(filling::upper, 1.0, a, 0.0, c); // c⸆=c=aa⸆=(aa⸆)⸆, `c` in upper triangular - BOOST_REQUIRE( c[0][1] == 34.0 ); - BOOST_REQUIRE( c[1][0] == 9999.0 ); - } - { - multi::array c({3, 3}, 9999.0); // NOLINT(readability-identifier-length) + BOOST_TEST( c[0][1] == 34.0 ); + BOOST_TEST( c[1][0] == 9999.0 ); + } + { + multi::array c({3, 3}, 9999.0); // NOLINT(readability-identifier-length) - using multi::blas::filling; + using multi::blas::filling; - syrk(filling::lower, 1.0, rotated(a), 0.0, c); // c⸆=c=a⸆a=(a⸆a)⸆, `c` in lower triangular + syrk(filling::lower, 1.0, a.rotated(), 0.0, c); // c⸆=c=a⸆a=(a⸆a)⸆, `c` in lower triangular - BOOST_REQUIRE( c[2][1] == 19.0 ); - BOOST_REQUIRE( c[1][2] == 9999.0 ); - } - { - multi::array c({3, 3}, 9999.0); // NOLINT(readability-identifier-length) + BOOST_TEST( c[2][1] == 19.0 ); + BOOST_TEST( c[1][2] == 9999.0 ); + } + { + multi::array c({3, 3}, 9999.0); // NOLINT(readability-identifier-length) - namespace blas = multi::blas; + namespace blas = multi::blas; - using blas::filling; - using blas::transposed; + using blas::filling; - syrk(filling::lower, 1.0, transposed(a), 0.0, c); // c⸆=c=a⸆a=(a⸆a)⸆, `c` in lower triangular + syrk(filling::lower, 1.0, blas::T(a), 0.0, c); // c⸆=c=a⸆a=(a⸆a)⸆, `c` in lower triangular - BOOST_REQUIRE( c[2][1] == 19.0 ); - BOOST_REQUIRE( c[1][2] == 9999.0 ); - } - { - multi::array c({3, 3}, 9999.0); // NOLINT(readability-identifier-length) + BOOST_TEST( c[2][1] == 19.0 ); + BOOST_TEST( c[1][2] == 9999.0 ); + } + { + multi::array c({3, 3}, 9999.0); // NOLINT(readability-identifier-length) - namespace blas = multi::blas; + namespace blas = multi::blas; - using blas::filling; - using blas::transposed; + using blas::filling; - syrk(filling::upper, 1.0, transposed(a), 0.0, c); // c⸆=c=a⸆a=(a⸆a)⸆, `c` in upper triangular + syrk(filling::upper, 1.0, blas::T(a), 0.0, c); // c⸆=c=a⸆a=(a⸆a)⸆, `c` in upper triangular - BOOST_REQUIRE( c[1][2] == 19.0 ); - BOOST_REQUIRE( c[2][1] == 9999.0 ); - } - { - multi::array c({2, 2}, 9999.0); // NOLINT(readability-identifier-length) + BOOST_TEST( c[1][2] == 19.0 ); + BOOST_TEST( c[2][1] == 9999.0 ); + } + { + multi::array c({2, 2}, 9999.0); // NOLINT(readability-identifier-length) - using multi::blas::filling; - using multi::blas::transposed; + namespace blas = multi::blas; - syrk(filling::upper, 1.0, a, 0.0, transposed(c)); // c⸆=c=aa⸆=(aa⸆)⸆, `c` in upper triangular + syrk(blas::filling::upper, 1.0, a, 0.0, blas::T(c)); // c⸆=c=aa⸆=(aa⸆)⸆, `c` in upper triangular - BOOST_REQUIRE( c[0][1] == 9999.0 ); - BOOST_REQUIRE( c[1][0] == 34.0 ); + BOOST_TEST( c[0][1] == 9999.0 ); + BOOST_TEST( c[1][0] == 34.0 ); + } } -} -BOOST_AUTO_TEST_CASE(multi_blas_syrk_automatic_implicit_zero) { - // NOLINTNEXTLINE(readability-identifier-length) - multi::array const a = { - {1.0, 3.0, 4.0}, - {9.0, 7.0, 1.0}, - }; - { - multi::array c({2, 2}, 9999.0); // NOLINT(readability-identifier-length) + BOOST_AUTO_TEST_CASE(multi_blas_syrk_automatic_implicit_zero) { + // NOLINTNEXTLINE(readability-identifier-length) + multi::array const a = { + {1.0, 3.0, 4.0}, + {9.0, 7.0, 1.0}, + }; + { + multi::array c({2, 2}, 9999.0); // NOLINT(readability-identifier-length) - using multi::blas::filling; + using multi::blas::filling; - syrk(filling::lower, 1.0, a, c); // c⸆=c=aa⸆=(aa⸆)⸆, `c` in lower triangular + syrk(filling::lower, 1.0, a, c); // c⸆=c=aa⸆=(aa⸆)⸆, `c` in lower triangular - BOOST_REQUIRE( c[1][0] == 34.0 ); - BOOST_REQUIRE( c[0][1] == 9999.0 ); + BOOST_TEST( c[1][0] == 34.0 ); + BOOST_TEST( c[0][1] == 9999.0 ); + } } + return boost::report_errors(); } diff --git a/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/test/traits.cpp b/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/test/traits.cpp index db419b19ce..78fc56d814 100644 --- a/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/test/traits.cpp +++ b/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/test/traits.cpp @@ -1,19 +1,30 @@ // Copyright 2019-2024 Alfredo A. Correa +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt -// #define BOOST_TEST_MODULE "C++ Unit Tests for Multi BLAS traits" -#include +#include +#include -#include "../../blas/traits.hpp" - -#include +#include namespace multi = boost::multi; -namespace blas = multi::blas; +namespace blas = multi::blas; + +#include +#define BOOST_AUTO_TEST_CASE(CasenamE) /**/ + +auto main() -> int { // NOLINT(readability-function-cognitive-complexity,bugprone-exception-escape) + BOOST_AUTO_TEST_CASE(multi_adaptors_blas_traits_simple_array) { + multi::array const arr; + BOOST_TEST( arr.empty() ); + } -BOOST_AUTO_TEST_CASE(multi_adaptors_blas_traits) { - static_assert( blas::is_d{} ); - static_assert( blas::is_s{} ); + BOOST_AUTO_TEST_CASE(multi_adaptors_blas_traits) { + static_assert(blas::is_d{}); + static_assert(blas::is_s{}); - static_assert( blas::is_c>{} ); - static_assert( blas::is_z>{} ); + static_assert(blas::is_c>{}); + static_assert(blas::is_z>{}); + } + return boost::report_errors(); } diff --git a/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/test/trsm.cpp b/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/test/trsm.cpp index 21d742dc43..b3acc2a250 100644 --- a/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/test/trsm.cpp +++ b/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/test/trsm.cpp @@ -2,365 +2,457 @@ // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt -#include +#include // for filling +#include // for gemm, gemm_range +// IWYU pragma: no_include "boost/multi/adaptors/blas/numeric.hpp" // for underlying +#include // for T, H, (anonymous) +#include // for side +#include // for trsm, diagonal +// IWYU pragma: no_include "boost/multi/adaptors/blas/traits.hpp" // for blas -#include -#include +#include // for array, subarray -#include - -#include +// IWYU pragma: no_include // for min +#include // for NAN +#include // for operator*, opera... +#include // for NAN, abs +// IWYU pragma: no_include // for allocator namespace multi = boost::multi; -BOOST_AUTO_TEST_CASE(multi_blas_trsm_double_0x0) { - namespace blas = multi::blas; - multi::array const A; // NOLINT(readability-identifier-length) BLAS naming +#include +#define BOOST_AUTO_TEST_CASE(CasenamE) /**/ +#define BOOST_REQUIRE_CLOSE(X, Y, ToL) BOOST_TEST( std::abs( (X) - (Y) ) < (ToL) ) - { - multi::array B; // NOLINT(readability-identifier-length) BLAS naming - // B=Solve(A.X=alpha*B, X) B=A⁻¹B, B⊤=B⊤.(A⊤)⁻¹, A upper triangular (implicit zeros below) - blas::trsm(blas::side::left, blas::filling::upper, blas::diagonal::general, 1.0, A, B); - } -} +auto main() -> int { // NOLINT(readability-function-cognitive-complexity,bugprone-exception-escape) + BOOST_AUTO_TEST_CASE(multi_blas_trsm_double_0x0) { + namespace blas = multi::blas; + multi::array const A; // NOLINT(readability-identifier-length) BLAS naming -BOOST_AUTO_TEST_CASE(multi_blas_trsm_double_1x1) { - namespace blas = multi::blas; - multi::array const A = { // NOLINT(readability-identifier-length) BLAS naming - {10.0, }, - }; - { - multi::array B = { // NOLINT(readability-identifier-length) BLAS naming - {3.0, }, - }; - auto const B_cpy = B; - blas::trsm(blas::side::left, blas::filling::upper, blas::diagonal::general, 1.0, A, B); - // B=Solve(A.X=alpha*B, X) B=A⁻¹B, B⊤=B⊤.(A⊤)⁻¹, A upper triangular (implicit zeros below) - BOOST_REQUIRE_CLOSE( B[0][0] , 3.0/10.0 , 0.00001 ); - BOOST_REQUIRE_CLOSE( (+blas::gemm(1.0, A, B))[0][0] , B_cpy[0][0] , 0.00001 ); + { + multi::array B; // NOLINT(readability-identifier-length) BLAS naming + // B=Solve(A.X=alpha*B, X) B=A⁻¹B, B⊤=B⊤.(A⊤)⁻¹, A upper triangular (implicit zeros below) + blas::trsm(blas::side::left, blas::filling::upper, blas::diagonal::general, 1.0, A, B); + } } - { - multi::array B = { // NOLINT(readability-identifier-length) BLAS naming - {3.0, }, - }; + + BOOST_AUTO_TEST_CASE(multi_blas_trsm_double_1x1) { + namespace blas = multi::blas; + + // clang-format off + // NOLINTNEXTLINE(readability-identifier-length) BLAS naming + multi::array const A = { {10.0, }, }; + // clang-format on + { + // clang-format off + // NOLINTNEXTLINE(readability-identifier-length) BLAS naming + multi::array B = {{3.0, }, }; + // clang-format on + + auto const B_cpy = B; + blas::trsm(blas::side::left, blas::filling::upper, blas::diagonal::general, 1.0, A, B); + // B=Solve(A.X=alpha*B, X) B=A⁻¹B, B⊤=B⊤.(A⊤)⁻¹, A upper triangular (implicit zeros below) + BOOST_REQUIRE_CLOSE(B[0][0], 3.0 / 10.0, 0.00001); + BOOST_REQUIRE_CLOSE((+blas::gemm(1.0, A, B))[0][0], B_cpy[0][0], 0.00001); + } + { + // clang-format off + // NOLINTNEXTLINE(readability-identifier-length) BLAS naming + multi::array B = {{3.0, }, }; + auto const B_cpy = B; // B=Solve(A.X=alpha*B, X) B=A⁻¹B, B⊤=B⊤.(A⊤)⁻¹, A upper triangular (implicit zeros below) blas::trsm(blas::side::left, blas::filling::upper, blas::diagonal::general, 2.0, A, B); - BOOST_REQUIRE_CLOSE( B[0][0] , 2.0*3.0/10.0 , 0.00001 ); - BOOST_REQUIRE_CLOSE( (+blas::gemm(1.0, A, B))[0][0] , 2.*B_cpy[0][0] , 0.00001 ); + BOOST_REQUIRE_CLOSE(B[0][0], 2.0 * 3.0 / 10.0, 0.00001); + BOOST_REQUIRE_CLOSE((+blas::gemm(1.0, A, B))[0][0], 2. * B_cpy[0][0], 0.00001); } { - multi::array B = { // NOLINT(readability-identifier-length) BLAS naming - {3.0, 4.0, 5.0}, + // NOLINTNEXTLINE(readability-identifier-length) BLAS naming + multi::array B = { + { 3.0, 4.0, 5.0 }, }; auto const B_cpy = B; // B=Solve(A.X=alpha*B, X) B=A⁻¹B, B⊤=B⊤.(A⊤)⁻¹, A upper triangular (implicit zeros below) blas::trsm(blas::side::left, blas::filling::upper, blas::diagonal::general, 1.0, A, B); - BOOST_REQUIRE_CLOSE( B[0][0] , 3./10. , 0.00001 ); - BOOST_REQUIRE_CLOSE( B[0][1] , 4./10. , 0.00001 ); - BOOST_REQUIRE_CLOSE( B[0][2] , 5./10. , 0.00001 ); - BOOST_REQUIRE_CLOSE( (+blas::gemm(1., A, B))[0][1] , B_cpy[0][1] , 0.00001 ); + BOOST_REQUIRE_CLOSE(B[0][0], 3. / 10., 0.00001); + BOOST_REQUIRE_CLOSE(B[0][1], 4. / 10., 0.00001); + BOOST_REQUIRE_CLOSE(B[0][2], 5. / 10., 0.00001); + BOOST_REQUIRE_CLOSE((+blas::gemm(1., A, B))[0][1], B_cpy[0][1], 0.00001); } } BOOST_AUTO_TEST_CASE(multi_blas_trsm_real_square) { namespace blas = multi::blas; - multi::array const A = { // NOLINT(readability-identifier-length) BLAS naming - {1.0, 3.0, 4.0}, - {NAN, 7.0, 1.0}, - {NAN, NAN, 8.0} + + // NOLINTNEXTLINE(readability-identifier-length) BLAS naming + multi::array const A = { + { 1.0, 3.0, 4.0 }, + { NAN, 7.0, 1.0 }, + { NAN, NAN, 8.0 } }; auto const A_cpy = triangular(blas::filling::upper, A); { - multi::array B = { // NOLINT(readability-identifier-length) BLAS naming - {1.0, 3.0, 4.0}, - {2.0, 7.0, 1.0}, - {3.0, 4.0, 2.0} + // NOLINTNEXTLINE(readability-identifier-length) BLAS naming + multi::array B = { + { 1.0, 3.0, 4.0 }, + { 2.0, 7.0, 1.0 }, + { 3.0, 4.0, 2.0 } }; auto const B_cpy = B; blas::trsm(blas::side::left, blas::filling::upper, 1.0, A, B); // B=Solve(A.X=alpha*B, X) B=A⁻¹B, B⊤=B⊤.(A⊤)⁻¹, A upper triangular (implicit zeros below) - BOOST_REQUIRE_CLOSE( B[1][2] , 0.107143 , 0.001 ); - BOOST_REQUIRE( (+blas::gemm(1., A_cpy, B))[1][2] == B_cpy[1][2] ); + + BOOST_REQUIRE_CLOSE(B[1][2], 0.107143, 0.001); + BOOST_TEST( (+blas::gemm(1., A_cpy, B))[1][2] == B_cpy[1][2] ); } { - auto const AT =+ ~A; + auto const AT = +~A; auto const AT_cpy = triangular(blas::filling::lower, AT); - multi::array B = { // NOLINT(readability-identifier-length) BLAS naming - {1.0, 3.0, 4.0}, - {2.0, 7.0, 1.0}, - {3.0, 4.0, 2.0} + + // NOLINTNEXTLINE(readability-identifier-length) BLAS naming + multi::array B = { + { 1.0, 3.0, 4.0 }, + { 2.0, 7.0, 1.0 }, + { 3.0, 4.0, 2.0 } }; auto const B_cpy = B; blas::trsm(blas::side::left, blas::filling::upper, 1., blas::T(AT), B); - BOOST_REQUIRE_CLOSE( B[1][2] , 0.107143 , 0.001 ); - BOOST_REQUIRE( (+blas::gemm(1., blas::T(AT_cpy), B))[1][2] == B_cpy[1][2] ); + BOOST_REQUIRE_CLOSE(B[1][2], 0.107143, 0.001); + BOOST_TEST( (+blas::gemm(1., blas::T(AT_cpy), B))[1][2] == B_cpy[1][2] ); } { - auto const AT =+ ~A; + auto const AT = +~A; auto const AT_cpy = triangular(blas::filling::lower, AT); - multi::array const B = { // NOLINT(readability-identifier-length) BLAS naming - {1.0, 3.0, 4.0}, - {2.0, 7.0, 1.0}, - {3.0, 4.0, 2.0} + + // NOLINTNEXTLINE(readability-identifier-length) BLAS naming + multi::array const B = { + { 1.0, 3.0, 4.0 }, + { 2.0, 7.0, 1.0 }, + { 3.0, 4.0, 2.0 } }; - auto BT =+ ~B; + auto BT = +~B; blas::trsm(blas::side::left, blas::filling::upper, 1., blas::T(AT), blas::T(BT)); - BOOST_REQUIRE_CLOSE( blas::T(BT)[1][2] , 0.107143 , 0.001 ); - BOOST_REQUIRE( (+blas::gemm(1., blas::T(AT_cpy), blas::T(BT)))[1][2] == B[1][2] ); + BOOST_REQUIRE_CLOSE(blas::T(BT)[1][2], 0.107143, 0.001); + BOOST_TEST( (+blas::gemm(1., blas::T(AT_cpy), blas::T(BT)))[1][2] == B[1][2] ); } { - multi::array const B = { // NOLINT(readability-identifier-length) BLAS naming - {1.0, 3.0, 4.0}, - {2.0, 7.0, 1.0}, - {3.0, 4.0, 2.0} + // NOLINTNEXTLINE(readability-identifier-length) BLAS naming + multi::array const B = { + { 1.0, 3.0, 4.0 }, + { 2.0, 7.0, 1.0 }, + { 3.0, 4.0, 2.0 } }; - auto BT =+ ~B; + auto BT = +~B; blas::trsm(blas::side::left, blas::filling::upper, 1.0, A, blas::T(BT)); - BOOST_REQUIRE_CLOSE( (~BT)[1][2] , 0.107143 , 0.001 ); + BOOST_REQUIRE_CLOSE((~BT)[1][2], 0.107143, 0.001); } } BOOST_AUTO_TEST_CASE(multi_blas_trsm_complex) { namespace blas = multi::blas; - using complex = std::complex; auto const I = complex{0.0, 1.0}; // NOLINT(readability-identifier-length) imag unit - multi::array const A = { // NOLINT(readability-identifier-length) BLAS naming - {1.0 + 2.0*I, 3.0 - 1.0*I, 4.0 + 9.0*I}, - {NAN , 7.0 + 4.0*I, 1.0 + 8.0*I}, - {NAN , NAN , 8.0 + 2.0*I} + + using complex = std::complex; + + auto const I = complex{ 0.0, 1.0 }; // NOLINT(readability-identifier-length) imag unit + + // NOLINTNEXTLINE(readability-identifier-length) BLAS naming + multi::array const A = { + { 1.0 + 2.0 * I, 3.0 - 1.0 * I, 4.0 + 9.0 * I }, + { NAN, 7.0 + 4.0 * I, 1.0 + 8.0 * I }, + { NAN, NAN, 8.0 + 2.0 * I } }; - multi::array B = { // NOLINT(readability-identifier-length) BLAS naming - {1.0 - 9.0*I, 3.0 + 2.0*I, 4.0 + 3.0*I}, - {2.0 - 2.0*I, 7.0 - 2.0*I, 1.0 - 1.0*I}, - {3.0 + 1.0*I, 4.0 + 8.0*I, 2.0 + 7.0*I} + + // NOLINTNEXTLINE(readability-identifier-length) BLAS naming + multi::array B = { + { 1.0 - 9.0 * I, 3.0 + 2.0 * I, 4.0 + 3.0 * I }, + { 2.0 - 2.0 * I, 7.0 - 2.0 * I, 1.0 - 1.0 * I }, + { 3.0 + 1.0 * I, 4.0 + 8.0 * I, 2.0 + 7.0 * I } }; - blas::trsm(blas::side::left, blas::filling::lower, 2.+1.*I, blas::H(A), B); // B=alpha Inv[A†].B, B†=B†.Inv[A], Solve(A†.X=B, X), Solve(X†.A=B†, X), A is upper triangular (with implicit zeros below) - BOOST_REQUIRE_CLOSE( real(B[1][2]) , 2.33846 , 0.0001 ); - BOOST_REQUIRE_CLOSE( imag(B[1][2]) , -0.0923077 , 0.0001 ); + + // B=alpha Inv[A†].B, B†=B†.Inv[A], Solve(A†.X=B, X), Solve(X†.A=B†, X), A is upper triangular (with implicit zeros below) + blas::trsm(blas::side::left, blas::filling::lower, 2. + 1. * I, blas::H(A), B); + BOOST_REQUIRE_CLOSE(real(B[1][2]), 2.33846, 0.0001); + BOOST_REQUIRE_CLOSE(imag(B[1][2]), -0.0923077, 0.0001); } BOOST_AUTO_TEST_CASE(multi_blas_trsm_complex_rectangular) { namespace blas = multi::blas; - using complex = std::complex; complex const I{0, 1}; // NOLINT(readability-identifier-length) imag unit - multi::array const A = { // NOLINT(readability-identifier-length) BLAS naming - { 1.0 + 2.0*I, 3.0 - 1.0*I, 4.0 + 9.0*I}, - {NAN , 7.0 + 4.0*I, 1.0 + 8.0*I}, - {NAN , NAN , 8.0 + 2.0*I} + using complex = std::complex; + complex const I{ 0, 1 }; // NOLINT(readability-identifier-length) imag unit + + // NOLINTNEXTLINE(readability-identifier-length) BLAS naming + multi::array const A = { + { 1.0 + 2.0 * I, 3.0 - 1.0 * I, 4.0 + 9.0 * I }, + { NAN, 7.0 + 4.0 * I, 1.0 + 8.0 * I }, + { NAN, NAN, 8.0 + 2.0 * I } }; - multi::array B = { // NOLINT(readability-identifier-length) BLAS naming - {1. - 9.*I, 3. + 2.*I}, - {2. - 2.*I, 7. - 2.*I}, - {3. + 1.*I, 4. + 8.*I} + + // NOLINTNEXTLINE(readability-identifier-length) BLAS naming + multi::array B = { + { 1.0 - 9.0 * I, 3.0 + 2.0 * I }, + { 2.0 - 2.0 * I, 7.0 - 2.0 * I }, + { 3.0 + 1.0 * I, 4.0 + 8.0 * I } }; - blas::trsm(blas::side::left, blas::filling::lower, 2.0 + 1.0*I, blas::H(A), B); // B=alpha Inv[A†].B, B†=B†.Inv[A], Solve(A†.X=B, X), Solve(X†.A=B†, X), A is upper triangular (with implicit zeros below) - BOOST_REQUIRE_CLOSE( real(B[2][0]) , -4.16471 , 0.0001 ); - BOOST_REQUIRE_CLOSE( imag(B[2][0]) , 8.25882 , 0.0001 ); + + // B=alpha Inv[A†].B, B†=B†.Inv[A], Solve(A†.X=B, X), Solve(X†.A=B†, X), A is upper triangular (with implicit zeros below) + blas::trsm(blas::side::left, blas::filling::lower, 2.0 + 1.0 * I, blas::H(A), B); + + BOOST_REQUIRE_CLOSE(real(B[2][0]), -4.16471, 0.0001); + BOOST_REQUIRE_CLOSE(imag(B[2][0]), 8.25882, 0.0001); } BOOST_AUTO_TEST_CASE(multi_blas_trsm_complex_column) { namespace blas = multi::blas; - using complex = std::complex; complex const I{0, 1}; // NOLINT(readability-identifier-length) imag unit - multi::array const A = { // NOLINT(readability-identifier-length) BLAS naming - {1.0 + 2.0*I, 3.0 - 1.0*I, 4.0 + 9.0*I}, - {NAN , 7.0 + 4.0*I, 1.0 + 8.0*I}, - {NAN , NAN , 8.0 + 2.0*I} + using complex = std::complex; + complex const I{ 0, 1 }; // NOLINT(readability-identifier-length) imag unit + + // NOLINTNEXTLINE(readability-identifier-length) BLAS naming + multi::array const A = { + { 1.0 + 2.0 * I, 3.0 - 1.0 * I, 4.0 + 9.0 * I }, + { NAN, 7.0 + 4.0 * I, 1.0 + 8.0 * I }, + { NAN, NAN, 8.0 + 2.0 * I } }; - multi::array B = { // NOLINT(readability-identifier-length) BLAS naming - {1. - 9.*I}, - {2. - 2.*I}, - {3. + 1.*I} + + // NOLINTNEXTLINE(readability-identifier-length) BLAS naming + multi::array B = { + { 1. - 9. * I }, + { 2. - 2. * I }, + { 3. + 1. * I } }; - blas::trsm(blas::side::left, blas::filling::lower, 2.0 + 1.0*I, blas::H(A), B); // B=alpha Inv[A†].B, B†=B†.Inv[A], Solve(A†.X=B, X), Solve(X†.A=B†, X), A is upper triangular (with implicit zeros below) - BOOST_REQUIRE_CLOSE( real(B[2][0]) , -4.16471 , 0.0001); - BOOST_REQUIRE_CLOSE( imag(B[2][0]) , 8.25882 , 0.0001); + + // B=alpha Inv[A†].B, B†=B†.Inv[A], Solve(A†.X=B, X), Solve(X†.A=B†, X), A is upper triangular (with implicit zeros below) + blas::trsm(blas::side::left, blas::filling::lower, 2.0 + 1.0 * I, blas::H(A), B); + + BOOST_REQUIRE_CLOSE(real(B[2][0]), -4.16471, 0.0001); + BOOST_REQUIRE_CLOSE(imag(B[2][0]), 8.25882, 0.0001); } BOOST_AUTO_TEST_CASE(multi_blas_trsm_complex_column_cpu) { namespace blas = multi::blas; - using complex = std::complex; complex const I{0, 1}; // NOLINT(readability-identifier-length) imaginary unit - multi::array const A = { // NOLINT(readability-identifier-length) BLAS naming - { 1.0 + 2.0*I, 3.0 - 1.0*I, 4.0 + 9.0*I}, - {NAN , 7.0 + 4.0*I, 1.0 + 8.0*I}, - {NAN , NAN , 8.0 + 2.0*I} + using complex = std::complex; + complex const I{ 0, 1 }; // NOLINT(readability-identifier-length) imaginary unit + + // NOLINTNEXTLINE(readability-identifier-length) BLAS naming + multi::array const A = { + { 1.0 + 2.0 * I, 3.0 - 1.0 * I, 4.0 + 9.0 * I }, + { NAN, 7.0 + 4.0 * I, 1.0 + 8.0 * I }, + { NAN, NAN, 8.0 + 2.0 * I } }; - multi::array B = { // NOLINT(readability-identifier-length) BLAS naming - {1.0 - 9.0*I}, - {2.0 - 2.0*I}, - {3.0 + 1.0*I} + + // NOLINTNEXTLINE(readability-identifier-length) BLAS naming + multi::array B = { + { 1.0 - 9.0 * I }, + { 2.0 - 2.0 * I }, + { 3.0 + 1.0 * I } }; - blas::trsm(blas::side::left, blas::filling::lower, 2.0 + 1.0*I, blas::H(A), B); // B=alpha Inv[A†].B, B†=B†.Inv[A], Solve(A†.X=B, X), Solve(X†.A=B†, X), A is upper triangular (with implicit zeros below) - BOOST_REQUIRE_CLOSE( real(B[2][0]) , -4.16471 , 0.0001 ); - BOOST_REQUIRE_CLOSE( imag(B[2][0]) , 8.25882 , 0.0001 ); + + // B=alpha Inv[A†].B, B†=B†.Inv[A], Solve(A†.X=B, X), Solve(X†.A=B†, X), A is upper triangular (with implicit zeros below) + blas::trsm(blas::side::left, blas::filling::lower, 2.0 + 1.0 * I, blas::H(A), B); + BOOST_REQUIRE_CLOSE(real(B[2][0]), -4.16471, 0.0001); + BOOST_REQUIRE_CLOSE(imag(B[2][0]), 8.25882, 0.0001); } BOOST_AUTO_TEST_CASE(multi_blas_trsm_hydrogen_inq_case_real) { namespace blas = multi::blas; - multi::array const A = {{2.0, }, }; // NOLINT(readability-identifier-length) BLAS naming - { - multi::array B = {{1.0, 2.0, 3.0}, }; // NOLINT(readability-identifier-length) BLAS naming - BOOST_REQUIRE( B.size() == 1 ); - auto const B_cpy = B; - blas::trsm(blas::side::left, blas::filling::lower, 1.0, A, B); - BOOST_REQUIRE( B[0][1] == B_cpy[0][1]/A[0][0] ); - } - { - multi::array B = { // NOLINT(readability-identifier-length) BLAS naming - {1.0}, - {2.0}, - {3.0}, - }; - auto const B_cpy = B; - blas::trsm(blas::side::left, blas::filling::lower, 1.0, A, blas::T(B)); - BOOST_REQUIRE( blas::T(B)[0][1] == blas::T(B_cpy)[0][1]/A[0][0] ); + + // clang-format off + // NOLINTNEXTLINE(readability-identifier-length) BLAS naming + multi::array const A = {{2.0, }, }; + // clang-format on + { + // NOLINTNEXTLINE(readability-identifier-length) BLAS naming + multi::array B = { + {1.0, 2.0, 3.0}, + }; + BOOST_TEST( B.size() == 1 ); + auto const B_cpy = B; + blas::trsm(blas::side::left, blas::filling::lower, 1.0, A, B); + BOOST_TEST( B[0][1] == B_cpy[0][1]/A[0][0] ); + } + { + // NOLINTNEXTLINE(readability-identifier-length) BLAS naming + multi::array B = { + {1.0}, + {2.0}, + {3.0}, + }; + auto const B_cpy = B; + blas::trsm(blas::side::left, blas::filling::lower, 1.0, A, blas::T(B)); + BOOST_TEST( blas::T(B)[0][1] == blas::T(B_cpy)[0][1]/A[0][0] ); + } } -} -BOOST_AUTO_TEST_CASE(multi_blas_trsm_hydrogen_inq_case_complex) { - namespace blas = multi::blas; - using complex = std::complex; - multi::array const A = { // NOLINT(readability-identifier-length) BLAS naming - { {2.0, 0.0}, }, - }; + BOOST_AUTO_TEST_CASE(multi_blas_trsm_hydrogen_inq_case_complex) { + namespace blas = multi::blas; + using complex = std::complex; + + // clang-format off + // NOLINTNEXTLINE(readability-identifier-length) BLAS naming + multi::array const A = {{{ 2.0, 0.0 }, }, }; + // clang-format on - { - multi::array B = { // NOLINT(readability-identifier-length) BLAS naming - { {1.0, 0.0}, {2.0, 0.0}, {3.0, 0.0} }, + { + // NOLINTNEXTLINE(readability-identifier-length) BLAS naming + multi::array B = { + {{1.0, 0.0}, {2.0, 0.0}, {3.0, 0.0}}, + }; + auto const B_cpy = B; + blas::trsm(blas::side::left, blas::filling::lower, {1.0, 0.0}, A, B); + BOOST_TEST( B[0][1] == B_cpy[0][1]/A[0][0] ); + } + multi::array B1 = { + {{1.0, 0.0}}, + {{2.0, 0.0}}, + {{3.0, 0.0}}, + }; + multi::array B2 = { + {{1.0, 0.0}}, + {{2.0, 0.0}}, + {{3.0, 0.0}}, }; - auto const B_cpy = B; - blas::trsm(blas::side::left, blas::filling::lower, {1.0, 0.0}, A, B); - BOOST_REQUIRE( B[0][1] == B_cpy[0][1]/A[0][0] ); - } - multi::array B1 = { - { {1.0, 0.0} }, - { {2.0, 0.0} }, - { {3.0, 0.0} }, - }; - multi::array B2 = { - { {1.0, 0.0} }, - { {2.0, 0.0} }, - { {3.0, 0.0} }, - }; - blas::trsm(blas::side::left, blas::filling::lower, {1.0, 0.0}, A, blas::H(B1)); + blas::trsm(blas::side::left, blas::filling::lower, {1.0, 0.0}, A, blas::H(B1)); - { - auto const B_cpy = B2; - blas::trsm(blas::side::right, blas::filling::upper, {1.0, 0.0}, blas::H(A), B2); - // BOOST_REQUIRE( (+blas::gemm(1., A, blas::H(B)))[0][1] == blas::H(B_cpy)[0][1] ); - BOOST_REQUIRE( (+blas::gemm(1., B2, blas::H(A)))[1][0] == B_cpy[1][0] ); + { + auto const B_cpy = B2; + blas::trsm(blas::side::right, blas::filling::upper, {1.0, 0.0}, blas::H(A), B2); + // BOOST_TEST( (+blas::gemm(1., A, blas::H(B)))[0][1] == blas::H(B_cpy)[0][1] ); + BOOST_TEST( (+blas::gemm(1., B2, blas::H(A)))[1][0] == B_cpy[1][0] ); + } + BOOST_TEST( B1 == B2 ); } - BOOST_REQUIRE( B1 == B2 ); -} -BOOST_AUTO_TEST_CASE(multi_blas_trsm_real_nonsquare) { - namespace blas = multi::blas; - multi::array const A = { // NOLINT(readability-identifier-length) BLAS naming - {1.0, 3.0, 40.0}, - {NAN, 7.0, 1.0}, - {NAN, NAN, 8.0} - }; - auto const A_cpy = triangular(blas::filling::upper, A); - { - multi::array B = { // NOLINT(readability-identifier-length) BLAS naming - {1.0, 3.0, 4.0, 8.0}, - {2.0, 7.0, 1.0, 9.0}, - {3.0, 4.0, 2.0, 1.0}, + BOOST_AUTO_TEST_CASE(multi_blas_trsm_real_nonsquare) { + namespace blas = multi::blas; + + // NOLINTNEXTLINE(readability-identifier-length) BLAS naming + multi::array const A = { + {1.0, 3.0, 40.0}, + {NAN, 7.0, 1.0}, + {NAN, NAN, 8.0} }; - auto const B_cpy =+ B; - multi::array BT =+ ~B; - BOOST_REQUIRE( BT == ~B ); - blas::trsm(blas::side::left, blas::filling::upper, 1.0, A, B); // B=Solve(A.X=alpha*B, X) B=A⁻¹B, B⊤=B⊤.(A⊤)⁻¹, A upper triangular (implicit zeros below) - BOOST_REQUIRE_CLOSE( B[1][2] , 0.107143 , 0.001); - BOOST_REQUIRE_CLOSE( (+blas::gemm(1., A_cpy, B))[1][2] , B_cpy[1][2] , 0.001); + auto const A_cpy = triangular(blas::filling::upper, A); + { + // NOLINTNEXTLINE(readability-identifier-length) BLAS naming + multi::array B = { + {1.0, 3.0, 4.0, 8.0}, + {2.0, 7.0, 1.0, 9.0}, + {3.0, 4.0, 2.0, 1.0}, + }; + auto const B_cpy = +B; + multi::array BT = +~B; + BOOST_TEST( BT == ~B ); - auto const BT_cpy = BT; - blas::trsm(blas::side::left, blas::filling::upper, 1.0, A, blas::T(BT)); - BOOST_REQUIRE_CLOSE( blas::T(BT)[1][2], 0.107143, 0.001 ); + blas::trsm(blas::side::left, blas::filling::upper, 1.0, A, B); // B=Solve(A.X=alpha*B, X) B=A⁻¹B, B⊤=B⊤.(A⊤)⁻¹, A upper triangular (implicit zeros below) + BOOST_REQUIRE_CLOSE(B[1][2], 0.107143, 0.001); + BOOST_REQUIRE_CLOSE((+blas::gemm(1., A_cpy, B))[1][2], B_cpy[1][2], 0.001); - BOOST_REQUIRE_CLOSE( (+blas::gemm(1., A_cpy, blas::T(BT)))[1][2] , blas::T(BT_cpy)[1][2] , 0.00001 ); - } - { - multi::array B = { // NOLINT(readability-identifier-length) BLAS naming - {1.0, 3.0, 4.0, 8.0}, - {2.0, 7.0, 1.0, 9.0}, - {3.0, 4.0, 2.0, 1.0}, - }; - multi::array AT = ~A; - multi::array BT = ~B; - blas::trsm(blas::side::left, blas::filling::upper, 1.0, blas::T(AT), B); // B=Solve(A.X=alpha*B, X) B=A⁻¹B, B⊤=B⊤.(A⊤)⁻¹, A upper triangular (implicit zeros below) - BOOST_REQUIRE_CLOSE( B[1][2] , 0.107143 , 0.001 ); + auto const BT_cpy = BT; + blas::trsm(blas::side::left, blas::filling::upper, 1.0, A, blas::T(BT)); + BOOST_REQUIRE_CLOSE(blas::T(BT)[1][2], 0.107143, 0.001); - blas::trsm(blas::side::left, blas::filling::upper, 1.0, blas::T(AT), blas::T(BT)); - BOOST_REQUIRE_CLOSE( (~BT)[1][2] , 0.107143, 0.001 ); - } - { - multi::array B = { // NOLINT(readability-identifier-length) BLAS naming - {1.0}, - {2.0}, - {3.0}, - }; - auto const B_cpy =+ B; - blas::trsm(blas::side::left, blas::filling::upper, 1.0, A, B); // B=Solve(A.X=alpha*B, X) B=A⁻¹B, B⊤=B⊤.(A⊤)⁻¹, A upper triangular (implicit zeros below) - BOOST_REQUIRE_CLOSE( B[2][0] , 0.375 , 0.00001 ); - BOOST_REQUIRE_CLOSE( (+blas::gemm(1., A_cpy, B))[1][0] , B_cpy[1][0] , 0.00001 ); + BOOST_REQUIRE_CLOSE((+blas::gemm(1., A_cpy, blas::T(BT)))[1][2], blas::T(BT_cpy)[1][2], 0.00001); + } + { + // NOLINTNEXTLINE(readability-identifier-length) BLAS naming + multi::array B = { + {1.0, 3.0, 4.0, 8.0}, + {2.0, 7.0, 1.0, 9.0}, + {3.0, 4.0, 2.0, 1.0}, + }; + multi::array AT{~A}; + multi::array BT{~B}; + + // B=Solve(A.X=alpha*B, X) B=A⁻¹B, B⊤=B⊤.(A⊤)⁻¹, A upper triangular (implicit zeros below) + blas::trsm(blas::side::left, blas::filling::upper, 1.0, blas::T(AT), B); + BOOST_REQUIRE_CLOSE(B[1][2], 0.107143, 0.001); + + blas::trsm(blas::side::left, blas::filling::upper, 1.0, blas::T(AT), blas::T(BT)); + BOOST_REQUIRE_CLOSE((~BT)[1][2], 0.107143, 0.001); + } + { + // NOLINTNEXTLINE(readability-identifier-length) BLAS naming + multi::array B = { + {1.0}, + {2.0}, + {3.0}, + }; + auto const B_cpy = +B; + blas::trsm(blas::side::left, blas::filling::upper, 1.0, A, B); // B=Solve(A.X=alpha*B, X) B=A⁻¹B, B⊤=B⊤.(A⊤)⁻¹, A upper triangular (implicit zeros below) + BOOST_REQUIRE_CLOSE(B[2][0], 0.375, 0.00001); + BOOST_REQUIRE_CLOSE((+blas::gemm(1., A_cpy, B))[1][0], B_cpy[1][0], 0.00001); + } + { + // NOLINTNEXTLINE(readability-identifier-length) BLAS naming + multi::array B = { + {1.0}, + {2.0}, + {3.0}, + }; + auto const B_cpy = +B; + blas::trsm(blas::side::left, blas::filling::upper, 1.2, A, B); + BOOST_REQUIRE_CLOSE((+blas::gemm(1.0, A_cpy, B))[1][0], 1.2 * B_cpy[1][0], 0.00001); + BOOST_REQUIRE_CLOSE((+blas::gemm(1.0 / 1.2, A_cpy, B))[1][0], B_cpy[1][0], 0.00001); + } + { + // NOLINTNEXTLINE(readability-identifier-length) BLAS naming + multi::array B = { + {1.0}, + {2.0}, + {3.0}, + }; + multi::array BT{B.rotated()}; + blas::trsm(blas::side::left, blas::filling::upper, 1.0, A, blas::T(BT)); + BOOST_REQUIRE_CLOSE((~BT)[2][0], 0.375, 0.00001); + } } - { - multi::array B = { // NOLINT(readability-identifier-length) BLAS naming - {1.0}, - {2.0}, - {3.0}, + + BOOST_AUTO_TEST_CASE(multi_blas_trsm_complex_nonsquare_default_diagonal_hermitized_gemm_check_no_const) { + namespace blas = multi::blas; + using complex = std::complex; + complex const I{0.0, 1.0}; // NOLINT(readability-identifier-length) imag unit + + // NOLINTNEXTLINE(readability-identifier-length) BLAS naming + multi::array const A = { + {1.0 + 4.0 * I, 3.0 + 0.0 * I, 4.0 - 10.0 * I}, + {0.0 + 0.0 * I, 7.0 - 3.0 * I, 1.0 + 0.0 * I}, + {0.0 + 0.0 * I, 0.0 + 0.0 * I, 8.0 - 2.0 * I}, }; - auto const B_cpy =+ B; - blas::trsm(blas::side::left, blas::filling::upper, 1.2, A, B); - BOOST_REQUIRE_CLOSE( (+blas::gemm(1.0, A_cpy, B))[1][0] , 1.2*B_cpy[1][0] , 0.00001 ); - BOOST_REQUIRE_CLOSE( (+blas::gemm(1.0/1.2, A_cpy, B))[1][0] , B_cpy[1][0] , 0.00001 ); - } - { - multi::array B = { // NOLINT(readability-identifier-length) BLAS naming - {1.0}, - {2.0}, - {3.0}, + + // NOLINTNEXTLINE(readability-identifier-length) BLAS naming + multi::array B = { + {1.0 + 1.0 * I, 2.0 + 1.0 * I, 3.0 + 1.0 * I}, + {5.0 + 3.0 * I, 9.0 + 3.0 * I, 1.0 - 1.0 * I}, }; - multi::array BT = rotated(B); - blas::trsm(blas::side::left, blas::filling::upper, 1.0, A, blas::T(BT)); - BOOST_REQUIRE_CLOSE( (~BT)[2][0] , 0.375 , 0.00001); + + using multi::blas::filling; + using multi::blas::hermitized; + using multi::blas::trsm; + blas::trsm(blas::side::left, blas::filling::upper, {1.0, 0.0}, A, blas::H(B)); // B†←A⁻¹.B†, B←B.A⁻¹†, B←(A⁻¹.B†)† + BOOST_REQUIRE_CLOSE(imag(B[1][2]), -0.147059, 0.001); } -} -BOOST_AUTO_TEST_CASE(multi_blas_trsm_complex_nonsquare_default_diagonal_hermitized_gemm_check_no_const) { - namespace blas = multi::blas; - using complex = std::complex; complex const I{0.0, 1.0}; // NOLINT(readability-identifier-length) imag unit - multi::array const A = { // NOLINT(readability-identifier-length) BLAS naming - { 1.0 + 4.0*I, 3.0 + 0.0*I, 4.0 - 10.0*I}, - { 0.0 + 0.0*I, 7.0 - 3.0*I, 1.0 + 0.0*I}, - { 0.0 + 0.0*I, 0.0 + 0.0*I, 8.0 - 2.0*I}, - }; - multi::array B = { // NOLINT(readability-identifier-length) BLAS naming - {1.0 + 1.0*I, 2.0 + 1.0*I, 3.0 + 1.0*I}, - {5.0 + 3.0*I, 9.0 + 3.0*I, 1.0 - 1.0*I}, - }; + BOOST_AUTO_TEST_CASE(UTA_blas_trsm_complex_nonsquare_default_diagonal_hermitized_gemm_check_no_const) { + namespace blas = multi::blas; + using complex = std::complex; + complex const I{0.0, 1.0}; // NOLINT(readability-identifier-length) imag unit - using multi::blas::trsm; - using multi::blas::filling; - using multi::blas::hermitized; - blas::trsm(blas::side::left, blas::filling::upper, {1.0, 0.0}, A, blas::H(B)); // B†←A⁻¹.B†, B←B.A⁻¹†, B←(A⁻¹.B†)† - BOOST_REQUIRE_CLOSE( imag(B[1][2]) , -0.147059 , 0.001); -} + // NOLINTNEXTLINE(readability-identifier-length) BLAS naming + multi::array const A = { + {1.0 + 4.0 * I, 3.0 + 0.0 * I, 4.0 - 10.0 * I}, + {0.0 + 0.0 * I, 7.0 - 3.0 * I, 1.0 + 0.0 * I}, + {0.0 + 0.0 * I, 0.0 + 0.0 * I, 8.0 - 2.0 * I}, + }; -BOOST_AUTO_TEST_CASE(UTA_blas_trsm_complex_nonsquare_default_diagonal_hermitized_gemm_check_no_const) { - namespace blas = multi::blas; - using complex = std::complex; complex const I{0.0, 1.0}; // NOLINT(readability-identifier-length) imag unit - multi::array const A = { // NOLINT(readability-identifier-length) BLAS naming - { 1.0 + 4.0*I, 3.0 + 0.0*I, 4.0 - 10.0*I}, - { 0.0 + 0.0*I, 7.0 - 3.0*I, 1.0 + 0.0*I}, - { 0.0 + 0.0*I, 0.0 + 0.0*I, 8.0 - 2.0*I}, - }; - multi::array B = { // NOLINT(readability-identifier-length) BLAS naming - {1.0 + 1.0*I, 2.0 + 1.0*I, 3.0 + 1.0*I}, - {5.0 + 3.0*I, 9.0 + 3.0*I, 1.0 - 1.0*I}, - }; + // NOLINTNEXTLINE(readability-identifier-length) BLAS naming + multi::array B = { + {1.0 + 1.0 * I, 2.0 + 1.0 * I, 3.0 + 1.0 * I}, + {5.0 + 3.0 * I, 9.0 + 3.0 * I, 1.0 - 1.0 * I}, + }; - using multi::blas::trsm; + using multi::blas::trsm; - blas::trsm(blas::side::left, {1.0, 0.0}, blas::U(A), blas::H(B)); // B†←A⁻¹.B†, B←B.A⁻¹†, B←(A⁻¹.B†)† - BOOST_REQUIRE_CLOSE( imag(B[1][2]) , -0.147059 , 0.001); + blas::trsm(blas::side::left, {1.0, 0.0}, blas::U(A), blas::H(B)); // B†←A⁻¹.B†, B←B.A⁻¹†, B←(A⁻¹.B†)† + BOOST_REQUIRE_CLOSE(imag(B[1][2]), -0.147059, 0.001); + } + return boost::report_errors(); } diff --git a/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/test/trsv.cpp b/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/test/trsv.cpp index c963c4705d..db6567cce4 100644 --- a/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/test/trsv.cpp +++ b/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/test/trsv.cpp @@ -1,7 +1,6 @@ -#ifdef COMPILATION// -*-indent-tabs-mode:t;c-basic-offset:4;tab-width:4;-*- -$CXX $0 -o $0x -lcudart -lcublas -lboost_unit_test_framework `pkg-config --libs blas`&&$0x&&rm $0x;exit -#endif -// © Alfredo A. Correa 2019-2024 +// Copyright 2019-2024 Alfredo A. Correa +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt #define BOOST_TEST_MODULE "C++ Unit Tests for Multi cuBLAS trsv" #define BOOST_TEST_DYN_LINK diff --git a/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/traits.hpp b/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/traits.hpp index 45acab04ad..66172580e7 100644 --- a/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/traits.hpp +++ b/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/traits.hpp @@ -6,10 +6,11 @@ #define BOOST_MULTI_ADAPTORS_BLAS_TRAITS_HPP #pragma once -#include -#include +#include +#include // for enable_if_t, false_type, is_convertible, true... +#include // for declval // IWYU pragma: keep -namespace boost::multi::blas { +namespace boost::multi::blas { // TODO(correaa) include in blas/detail? // TODO(correaa) : create a BinaryDouble concept? diff --git a/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/trsm.hpp b/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/trsm.hpp index 8128bba97d..cb90d7c19c 100644 --- a/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/trsm.hpp +++ b/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/trsm.hpp @@ -5,10 +5,10 @@ #ifndef BOOST_MULTI_ADAPTORS_BLAS_TRSM_HPP #define BOOST_MULTI_ADAPTORS_BLAS_TRSM_HPP -#include "../blas/core.hpp" -#include "../blas/filling.hpp" -#include "../blas/operations.hpp" // uplo -#include "../blas/side.hpp" +#include +#include +#include +#include namespace boost::multi::blas { @@ -18,18 +18,19 @@ enum class diagonal : char { }; template -auto triangular_parted(Array const& arr) { - class triangular_part { - Array const& ref_; // NOLINT(cppcoreguidelines-avoid-const-or-ref-data-members) - - public: - explicit triangular_part(Array const& ref) : ref_{ref} {} - static constexpr auto filling() { return Fill; } - using underlying_type __attribute__((unused)) = Array; - auto underlying() const -> Array const& { return ref_;} - }; +class triangular_part { + Array const& ref_; // NOLINT(cppcoreguidelines-avoid-const-or-ref-data-members) + + public: + explicit triangular_part(Array const& ref) : ref_{ref} {} + static constexpr auto filling() { return Fill; } + using underlying_type = Array; + auto underlying() const -> Array const& { return ref_;} +}; - return triangular_part{arr}; +template +auto triangular_parted(Array const& arr) { + return triangular_part{arr}; } template @@ -79,22 +80,22 @@ auto trsm(Context&& ctxt, blas::side a_side, blas::filling a_fill, blas::diagona if(size(b) != 0) { #define CTXT std::forward(ctxt) if constexpr(! is_conjugated{} && ! is_conjugated{}) { - if (stride( a)==1 && stride( b)==1) {CTXT->trsm(static_cast( (a_side)), static_cast(-a_fill), 'N', static_cast(a_diag), size( b), size(~b), alpha , base(a) , stride(~a), base(b) , stride(~b));} - else if(stride(~a)==1 && stride(~b)==1) {CTXT->trsm(static_cast(swap(a_side)), static_cast(+a_fill), 'N', static_cast(a_diag), size(~b), size( b), alpha , base(a) , stride( a), base(b) , stride( b));} - else if(stride( a)==1 && stride(~b)==1) {CTXT->trsm(static_cast(swap(a_side)), static_cast(-a_fill), 'T', static_cast(a_diag), size(~b), size( b), alpha , base(a) , stride(~a), base(b) , stride( b));} - else if(stride(~a)==1 && stride( b)==1) {CTXT->trsm(static_cast( (a_side)), static_cast(+a_fill), 'T', static_cast(a_diag), size( b), size(~b), alpha , base(a) , stride( a), base(b) , stride(~b));} + if (stride( a)==1 && stride( b)==1) {CTXT->trsm(static_cast( (a_side)), static_cast(-a_fill), 'N', static_cast(a_diag), size( b), size(~b), alpha , a.base() , stride(~a), b.base() , stride(~b));} + else if(stride(~a)==1 && stride(~b)==1) {CTXT->trsm(static_cast(swap(a_side)), static_cast(+a_fill), 'N', static_cast(a_diag), size(~b), size( b), alpha , a.base() , stride( a), b.base() , stride( b));} + else if(stride( a)==1 && stride(~b)==1) {CTXT->trsm(static_cast(swap(a_side)), static_cast(-a_fill), 'T', static_cast(a_diag), size(~b), size( b), alpha , a.base() , stride(~a), b.base() , stride( b));} + else if(stride(~a)==1 && stride( b)==1) {CTXT->trsm(static_cast( (a_side)), static_cast(+a_fill), 'T', static_cast(a_diag), size( b), size(~b), alpha , a.base() , stride( a), b.base() , stride(~b));} else {assert(0 && "not implemented in blas");} // LCOV_EXCL_LINE } else if constexpr( is_conjugated{} && ! is_conjugated{}) { - if (stride( a)==1 && stride(~b)==1) {CTXT->trsm(static_cast(swap(a_side)), static_cast(-a_fill), 'C', static_cast(a_diag), size(~b), size( b), alpha , underlying(base(a)), stride(~a), base(b) , stride( b));} - else if(stride(~a)==1 && stride( b)==1) {CTXT->trsm(static_cast( (a_side)), static_cast(+a_fill), 'C', static_cast(a_diag), size( b), size(~b), alpha , underlying(base(a)), stride( a), base(b) , stride(~b));} + if (stride( a)==1 && stride(~b)==1) {CTXT->trsm(static_cast(swap(a_side)), static_cast(-a_fill), 'C', static_cast(a_diag), size(~b), size( b), alpha , underlying(a.base()), stride(~a), b.base() , stride( b));} + else if(stride(~a)==1 && stride( b)==1) {CTXT->trsm(static_cast( (a_side)), static_cast(+a_fill), 'C', static_cast(a_diag), size( b), size(~b), alpha , underlying(a.base()), stride( a), b.base() , stride(~b));} else {assert(0 && "not implemented in blas");} // LCOV_EXCL_LINE } else if constexpr(! is_conjugated{} && is_conjugated{}) { - if (stride(~a)==1 && stride( b)==1) {CTXT->trsm(static_cast( (a_side)), static_cast(+a_fill), 'C', static_cast(a_diag), size( b), size(~b), conj(alpha), base(a) , stride( a), underlying(base(b)), stride(~b));} + if (stride(~a)==1 && stride( b)==1) {CTXT->trsm(static_cast( (a_side)), static_cast(+a_fill), 'C', static_cast(a_diag), size( b), size(~b), conj(alpha), a.base() , stride( a), underlying(b.base()), stride(~b));} // else if(stride( a)==1 && stride(~b)==1) {assert(0 && "not implemented in blas");} // LCOV_EXCL_LINE else {assert(0 && "not implemented in blas");} // LCOV_EXCL_LINE } else if constexpr( is_conjugated{} && is_conjugated{}) { - if (stride( a)==1 && stride(~b)==1) {CTXT->trsm(static_cast(swap(a_side)), static_cast(-a_fill), 'T', static_cast(a_diag), size(~b), size( b), conj(alpha), underlying(base(a)), stride(~a), underlying(base(b)), stride( b));} - else if(stride(~a)==1 && stride( b)==1) {CTXT->trsm(static_cast( (a_side)), static_cast(+a_fill), 'T', static_cast(a_diag), size( b), size(~b), conj(alpha), underlying(base(a)), stride( a), underlying(base(b)), stride(~b));} + if (stride( a)==1 && stride(~b)==1) {CTXT->trsm(static_cast(swap(a_side)), static_cast(-a_fill), 'T', static_cast(a_diag), size(~b), size( b), conj(alpha), underlying(a.base()), stride(~a), underlying(b.base()), stride( b));} + else if(stride(~a)==1 && stride( b)==1) {CTXT->trsm(static_cast( (a_side)), static_cast(+a_fill), 'T', static_cast(a_diag), size( b), size(~b), conj(alpha), underlying(a.base()), stride( a), underlying(bbase(b)), stride(~b));} else {assert(0 && "not implemented in blas");} // LCOV_EXCL_LINE } #undef CTXT diff --git a/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/trsv.hpp b/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/trsv.hpp index 462b434a8e..9b5bf5104f 100644 --- a/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/trsv.hpp +++ b/external_codes/boost_multi/multi/include/boost/multi/adaptors/blas/trsv.hpp @@ -29,7 +29,7 @@ template auto trsv(filling a_nonzero_side, diagonal a_diag, A2D const& a, X1D&& x) ->decltype(trsv(static_cast(flip(a_nonzero_side)), 'N', static_cast(a_diag), size(x), trsv_base(a), stride(rotated(a)), trsv_base(x), stride(x)), std::forward(x)) { -// if(is_conjugated(x)) trsv(a_nonzero_side, a_diag, conjugated(a), conjugated(std::forward(x))); +// if(is_conjugated(x)) trsv(a_nonzero_side, a_diag, conjugated(a), conjugated(std::forward(x))); { auto base_a = trsv_base(a); auto base_x = trsv_base(x); @@ -52,9 +52,6 @@ auto trsv(filling a_nonzero_side, A2D const& a, X1D&& x) return trsv(a_nonzero_side, diagonal::general, a, std::forward(x)); } #if 0 - - -#if 1 template Ret trsv(filling a_nonzero_side, diagonal a_diag, A2D const& a, X1D const& x, void* = 0){ return trsv(a_nonzero_side, a_diag, a, Ret{x});} @@ -63,7 +60,6 @@ template Ret trsv(filling a_nonzero_side, A2D const& a, X1D const& x, void* = 0){ return trsv(a_nonzero_side, a, Ret{x});} #endif -#endif } // end namespace boost::multi::blas @@ -82,20 +78,20 @@ Ret trsv(filling a_nonzero_side, A2D const& a, X1D const& x, void* = 0){ //namespace multi = boost::multi; //template decltype(auto) print_1D(M const& C){ -// using boost::multi::size; using std::cout; -// for(int i = 0; i != size(C); ++i) -// cout<< C[i] <<' '; -// cout< decltype(auto) print(M const& C){ -// using boost::multi::size; using std::cout; -// for(int i = 0; i != size(C); ++i){ -// for(int j = 0; j != size(C[i]); ++j) -// cout<< C[i][j] <<' '; -// cout< const A = { -// { 1., 3., 4.}, -// { NAN, 7., 1.}, -// { NAN, NAN, 8.} -// }; -// multi::array b = {1., 3., 4.}; -// blas::trsv(blas::filling::upper, blas::diagonal::general, A, b); // B<-Solve(A.X==B), B<-A⁻¹.B, B⊤<-(A⁻¹.B)⊤, B<-B⊤.A⁻¹⊤ -// BOOST_TEST( b[0] == -2.07143 ); -// BOOST_TEST( b[1] == 0.357143 ); -// BOOST_TEST( b[2] == 0.5 ); -// } -// { -// multi::array const A = { -// { 1., 3., 4.}, -// { NAN, 7., 1.}, -// { NAN, NAN, 8.} -// }; -// multi::array b = {1., 3., 4.}; -// blas::trsv(blas::filling::lower, blas::diagonal::general, blas::T(A), b); // B<-Solve(A.X==B), B<-A⊤⁻¹.B, B⊤<-(A⊤⁻¹.B)⊤, B<-B⊤.A⁻¹ -// BOOST_TEST( b[0] == 1. ); -// BOOST_TEST( b[1] == 0. ); -// BOOST_TEST( b[2] == 0. ); -// } +// { +// multi::array const A = { +// { 1., 3., 4.}, +// { NAN, 7., 1.}, +// { NAN, NAN, 8.} +// }; +// multi::array b = {1., 3., 4.}; +// blas::trsv(blas::filling::upper, blas::diagonal::general, A, b); // B<-Solve(A.X==B), B<-A⁻¹.B, B⊤<-(A⁻¹.B)⊤, B<-B⊤.A⁻¹⊤ +// BOOST_TEST( b[0] == -2.07143 ); +// BOOST_TEST( b[1] == 0.357143 ); +// BOOST_TEST( b[2] == 0.5 ); +// } +// { +// multi::array const A = { +// { 1., 3., 4.}, +// { NAN, 7., 1.}, +// { NAN, NAN, 8.} +// }; +// multi::array b = {1., 3., 4.}; +// blas::trsv(blas::filling::lower, blas::diagonal::general, blas::T(A), b); // B<-Solve(A.X==B), B<-A⊤⁻¹.B, B⊤<-(A⊤⁻¹.B)⊤, B<-B⊤.A⁻¹ +// BOOST_TEST( b[0] == 1. ); +// BOOST_TEST( b[1] == 0. ); +// BOOST_TEST( b[2] == 0. ); +// } //#if 0 -// { -// multi::array b = {3., 3., 1.}; -// // trsv(filling::lower, diagonal::general, hermitized(A), b); // B<-Solve(A.X==B), B<-A⊤⁻¹.B, B⊤<-(A⊤⁻¹.B)⊤, B<-B⊤.A⁻¹ -// // BOOST_TEST( b[0] == 3. ); -// // BOOST_TEST( b[1] == -0.857143 ); -// // BOOST_TEST( b[2] == -1.26786 ); -// } +// { +// multi::array b = {3., 3., 1.}; +// // trsv(filling::lower, diagonal::general, hermitized(A), b); // B<-Solve(A.X==B), B<-A⊤⁻¹.B, B⊤<-(A⊤⁻¹.B)⊤, B<-B⊤.A⁻¹ +// // BOOST_TEST( b[0] == 3. ); +// // BOOST_TEST( b[1] == -0.857143 ); +// // BOOST_TEST( b[2] == -1.26786 ); +// } //#endif //} @@ -143,455 +139,455 @@ Ret trsv(filling a_nonzero_side, A2D const& a, X1D const& x, void* = 0){ //using complex = std::complex; //BOOST_AUTO_TEST_CASE(multi_blas_trsv_complex_real_case_square, *utf::tolerance(0.00001)){ -// multi::array const A = { -// { 1., 3., 4.}, -// {NAN, 7., 1.}, -// {NAN, NAN, 8.} -// }; -// using blas::filling; -// using blas::diagonal; -// using blas::transposed; -// using blas::hermitized; -// using blas::conjugated; -// using blas::trsv; -// { -// multi::array b = {1., 3., 4.}; -// blas::trsv(filling::upper, diagonal::general, A, b); // B<-Solve(A.X==B), B<-A⁻¹.B, B⊤<-(A⁻¹.B)⊤, B<-B⊤.A⁻¹⊤ -// BOOST_TEST( real(b[0]) == -2.07143 ); -// BOOST_TEST( real(b[1]) == 0.357143 ); -// BOOST_TEST( real(b[2]) == 0.5 ); -// } -// { -// multi::array const b = {1., 3., 4.}; -// auto b_copy = blas::trsv(filling::upper, A, b); // B<-Solve(A.X==B), B<-A⁻¹.B, B⊤<-(A⁻¹.B)⊤, B<-B⊤.A⁻¹⊤ -// BOOST_TEST( real(b[0]) == 1. ); -// BOOST_TEST( real(b_copy[0]) == -2.07143 ); -// BOOST_TEST( real(b_copy[1]) == 0.357143 ); -// BOOST_TEST( real(b_copy[2]) == 0.5 ); -// } -// { -// multi::array const b = {1., 3., 4.}; -// auto b_copy = blas::trsv(filling::upper, diagonal::general, A, b); // B<-Solve(A.X==B), B<-A⁻¹.B, B⊤<-(A⁻¹.B)⊤, B<-B⊤.A⁻¹⊤ -// BOOST_TEST( real(b[0]) == 1. ); -// BOOST_TEST( real(b_copy[0]) == -2.07143 ); -// BOOST_TEST( real(b_copy[1]) == 0.357143 ); -// BOOST_TEST( real(b_copy[2]) == 0.5 ); -// } -// { -// multi::array b = {3., 3., 1.}; -// trsv(filling::lower, diagonal::general, transposed(A), b); // B<-Solve(A.X==B), B<-A⊤⁻¹.B, B⊤<-(A⊤⁻¹.B)⊤, B<-B⊤.A⁻¹ -// BOOST_TEST( real(b[0]) == 3. ); -// BOOST_TEST( real(b[1]) == -0.857143 ); -// BOOST_TEST( real(b[2]) == -1.26786 ); -// } -// { -// multi::array b = {3., 3., 1.}; -// // trsv(filling::lower, diagonal::general, hermitized(A), b); // B<-Solve(A.X==B), B<-A⊤⁻¹.B, B⊤<-(A⊤⁻¹.B)⊤, B<-B⊤.A⁻¹ -// // BOOST_TEST( real(b[0]) == 3. ); -// // BOOST_TEST( real(b[1]) == -0.857143 ); -// // BOOST_TEST( real(b[2]) == -1.26786 ); -// } -// { -// multi::array b = {3., 3., 1.}; -//// trsv(filling::lower, diagonal::general, hermitized(A), conjugated(b)); // B<-Solve(A.X==B), B<-A⊤⁻¹.B, B⊤<-(A⊤⁻¹.B)⊤, B<-B⊤.A⁻¹ -//// BOOST_TEST( real(b[0]) == 3. ); -//// BOOST_TEST( real(b[1]) == -0.857143 ); -//// BOOST_TEST( real(b[2]) == -1.26786 ); -// } +// multi::array const A = { +// { 1., 3., 4.}, +// {NAN, 7., 1.}, +// {NAN, NAN, 8.} +// }; +// using blas::filling; +// using blas::diagonal; +// using blas::transposed; +// using blas::hermitized; +// using blas::conjugated; +// using blas::trsv; +// { +// multi::array b = {1., 3., 4.}; +// blas::trsv(filling::upper, diagonal::general, A, b); // B<-Solve(A.X==B), B<-A⁻¹.B, B⊤<-(A⁻¹.B)⊤, B<-B⊤.A⁻¹⊤ +// BOOST_TEST( real(b[0]) == -2.07143 ); +// BOOST_TEST( real(b[1]) == 0.357143 ); +// BOOST_TEST( real(b[2]) == 0.5 ); +// } +// { +// multi::array const b = {1., 3., 4.}; +// auto b_copy = blas::trsv(filling::upper, A, b); // B<-Solve(A.X==B), B<-A⁻¹.B, B⊤<-(A⁻¹.B)⊤, B<-B⊤.A⁻¹⊤ +// BOOST_TEST( real(b[0]) == 1. ); +// BOOST_TEST( real(b_copy[0]) == -2.07143 ); +// BOOST_TEST( real(b_copy[1]) == 0.357143 ); +// BOOST_TEST( real(b_copy[2]) == 0.5 ); +// } +// { +// multi::array const b = {1., 3., 4.}; +// auto b_copy = blas::trsv(filling::upper, diagonal::general, A, b); // B<-Solve(A.X==B), B<-A⁻¹.B, B⊤<-(A⁻¹.B)⊤, B<-B⊤.A⁻¹⊤ +// BOOST_TEST( real(b[0]) == 1. ); +// BOOST_TEST( real(b_copy[0]) == -2.07143 ); +// BOOST_TEST( real(b_copy[1]) == 0.357143 ); +// BOOST_TEST( real(b_copy[2]) == 0.5 ); +// } +// { +// multi::array b = {3., 3., 1.}; +// trsv(filling::lower, diagonal::general, transposed(A), b); // B<-Solve(A.X==B), B<-A⊤⁻¹.B, B⊤<-(A⊤⁻¹.B)⊤, B<-B⊤.A⁻¹ +// BOOST_TEST( real(b[0]) == 3. ); +// BOOST_TEST( real(b[1]) == -0.857143 ); +// BOOST_TEST( real(b[2]) == -1.26786 ); +// } +// { +// multi::array b = {3., 3., 1.}; +// // trsv(filling::lower, diagonal::general, hermitized(A), b); // B<-Solve(A.X==B), B<-A⊤⁻¹.B, B⊤<-(A⊤⁻¹.B)⊤, B<-B⊤.A⁻¹ +// // BOOST_TEST( real(b[0]) == 3. ); +// // BOOST_TEST( real(b[1]) == -0.857143 ); +// // BOOST_TEST( real(b[2]) == -1.26786 ); +// } +// { +// multi::array b = {3., 3., 1.}; +//// trsv(filling::lower, diagonal::general, hermitized(A), conjugated(b)); // B<-Solve(A.X==B), B<-A⊤⁻¹.B, B⊤<-(A⊤⁻¹.B)⊤, B<-B⊤.A⁻¹ +//// BOOST_TEST( real(b[0]) == 3. ); +//// BOOST_TEST( real(b[1]) == -0.857143 ); +//// BOOST_TEST( real(b[2]) == -1.26786 ); +// } //} //BOOST_AUTO_TEST_CASE(multi_blas_trsv_complex_square, *utf::tolerance(0.00001)){ -// namespace blas = multi::blas; - -// multi::array const A = { -// { 1. + 1.*I, 3. - 2.*I, 4. + 1.*I}, -// {NAN , 7. - 10.*I, 1. + 2.*I}, -// {NAN , NAN , 8. + 1.*I} -// }; -// using blas::filling; -// using blas::diagonal; -// using blas::transposed; -// using blas::hermitized; -// using blas::conjugated; -// using blas::trsv; -// { -// multi::array b = {1. + 2.*I, 3. + 1.*I, 4. + 5.*I}; -// blas::trsv(filling::upper, diagonal::general, A, b); // B<-Solve(A.X==B), B<-A⁻¹.B, B⊤<-(A⁻¹.B)⊤, B<-B⊤.A⁻¹⊤ -// BOOST_TEST( real(b[0]) == -1.37259 ); -// BOOST_TEST( real(b[1]) == 0.2127 ); -// BOOST_TEST( real(b[2]) == 0.569231 ); -// } -// { -// multi::array b = {1. + 2.*I, 3. + 1.*I, 4. + 5.*I}; -// trsv(filling::lower, diagonal::general, transposed(A), b); // B<-Solve(A.X==B), B<-A⊤⁻¹.B, B⊤<-(A⊤⁻¹.B)⊤, B<-B⊤.A⁻¹ -// BOOST_TEST( real(b[0]) == 1.5 ); BOOST_TEST( imag(b[0]) == 0.5 ); -// BOOST_TEST( real(b[1]) == -0.285235 ); BOOST_TEST( imag(b[1]) == -0.0503356 ); -// BOOST_TEST( real(b[2]) == -0.129272 ); BOOST_TEST( imag(b[2]) == 0.28126 ); -// } -// { -// multi::array b = {1. + 2.*I, 3. + 1.*I, 4. + 5.*I}; -// trsv(filling::upper, diagonal::general, blas::H(A), b); // B<-Solve(A.X==B), B<-A⊤⁻¹.B, B⊤<-(A⊤⁻¹.B)⊤, B<-B⊤.A⁻¹ -// print_1D(b); -// BOOST_TEST( real(b[0]) == -0.661693 ); BOOST_TEST( imag(b[0]) == -1.13934 ); -// BOOST_TEST( real(b[1]) == 0.135261 ); BOOST_TEST( imag(b[1]) == -0.0283944 ); -// BOOST_TEST( real(b[2]) == 0.415385 ); BOOST_TEST( imag(b[2]) == 0.676923 ); -// } -// { -// multi::array b = {1. - 2.*I, 3. - 1.*I, 4. - 5.*I}; -// trsv(filling::upper, diagonal::general, blas::H(A), blas::conj(b)); // B<-Solve(A.X==B), B<-A⊤⁻¹.B, B⊤<-(A⊤⁻¹.B)⊤, B<-B⊤.A⁻¹ -//// print_1D(b); -//// BOOST_TEST( real(conjugated(b)[0]) == -0.661693 ); BOOST_TEST( imag(conjugated(b)[0]) == -1.13934 ); -//// BOOST_TEST( real(conjugated(b)[1]) == 0.135261 ); BOOST_TEST( imag(conjugated(b)[1]) == -0.0283944 ); -//// BOOST_TEST( real(conjugated(b)[2]) == 0.415385 ); BOOST_TEST( imag(conjugated(b)[2]) == 0.676923 ); -// } -// { -// multi::array b = {1. + 2.*I, 3. + 1.*I, 4. + 5.*I}; -// // trsv(filling::lower, diagonal::general, hermitized(A), b); // B<-Solve(A.X==B), B<-A⊤⁻¹.B, B⊤<-(A⊤⁻¹.B)⊤, B<-B⊤.A⁻¹ -// // BOOST_TEST( real(b[0]) == -0.5 ); BOOST_TEST( imag(b[0]) == 1.5 ); -// // BOOST_TEST( real(b[1]) == 0.184564 ); BOOST_TEST( imag(b[1]) == -0.620805 ); -// // BOOST_TEST( real(b[2]) == 0.691791 ); BOOST_TEST( imag(b[2]) == 0.0227155 ); -// } +// namespace blas = multi::blas; + +// multi::array const A = { +// { 1. + 1.*I, 3. - 2.*I, 4. + 1.*I}, +// {NAN , 7. - 10.*I, 1. + 2.*I}, +// {NAN , NAN , 8. + 1.*I} +// }; +// using blas::filling; +// using blas::diagonal; +// using blas::transposed; +// using blas::hermitized; +// using blas::conjugated; +// using blas::trsv; +// { +// multi::array b = {1. + 2.*I, 3. + 1.*I, 4. + 5.*I}; +// blas::trsv(filling::upper, diagonal::general, A, b); // B<-Solve(A.X==B), B<-A⁻¹.B, B⊤<-(A⁻¹.B)⊤, B<-B⊤.A⁻¹⊤ +// BOOST_TEST( real(b[0]) == -1.37259 ); +// BOOST_TEST( real(b[1]) == 0.2127 ); +// BOOST_TEST( real(b[2]) == 0.569231 ); +// } +// { +// multi::array b = {1. + 2.*I, 3. + 1.*I, 4. + 5.*I}; +// trsv(filling::lower, diagonal::general, transposed(A), b); // B<-Solve(A.X==B), B<-A⊤⁻¹.B, B⊤<-(A⊤⁻¹.B)⊤, B<-B⊤.A⁻¹ +// BOOST_TEST( real(b[0]) == 1.5 ); BOOST_TEST( imag(b[0]) == 0.5 ); +// BOOST_TEST( real(b[1]) == -0.285235 ); BOOST_TEST( imag(b[1]) == -0.0503356 ); +// BOOST_TEST( real(b[2]) == -0.129272 ); BOOST_TEST( imag(b[2]) == 0.28126 ); +// } +// { +// multi::array b = {1. + 2.*I, 3. + 1.*I, 4. + 5.*I}; +// trsv(filling::upper, diagonal::general, blas::H(A), b); // B<-Solve(A.X==B), B<-A⊤⁻¹.B, B⊤<-(A⊤⁻¹.B)⊤, B<-B⊤.A⁻¹ +// print_1D(b); +// BOOST_TEST( real(b[0]) == -0.661693 ); BOOST_TEST( imag(b[0]) == -1.13934 ); +// BOOST_TEST( real(b[1]) == 0.135261 ); BOOST_TEST( imag(b[1]) == -0.0283944 ); +// BOOST_TEST( real(b[2]) == 0.415385 ); BOOST_TEST( imag(b[2]) == 0.676923 ); +// } +// { +// multi::array b = {1. - 2.*I, 3. - 1.*I, 4. - 5.*I}; +// trsv(filling::upper, diagonal::general, blas::H(A), blas::conj(b)); // B<-Solve(A.X==B), B<-A⊤⁻¹.B, B⊤<-(A⊤⁻¹.B)⊤, B<-B⊤.A⁻¹ +//// print_1D(b); +//// BOOST_TEST( real(conjugated(b)[0]) == -0.661693 ); BOOST_TEST( imag(conjugated(b)[0]) == -1.13934 ); +//// BOOST_TEST( real(conjugated(b)[1]) == 0.135261 ); BOOST_TEST( imag(conjugated(b)[1]) == -0.0283944 ); +//// BOOST_TEST( real(conjugated(b)[2]) == 0.415385 ); BOOST_TEST( imag(conjugated(b)[2]) == 0.676923 ); +// } +// { +// multi::array b = {1. + 2.*I, 3. + 1.*I, 4. + 5.*I}; +// // trsv(filling::lower, diagonal::general, hermitized(A), b); // B<-Solve(A.X==B), B<-A⊤⁻¹.B, B⊤<-(A⊤⁻¹.B)⊤, B<-B⊤.A⁻¹ +// // BOOST_TEST( real(b[0]) == -0.5 ); BOOST_TEST( imag(b[0]) == 1.5 ); +// // BOOST_TEST( real(b[1]) == 0.184564 ); BOOST_TEST( imag(b[1]) == -0.620805 ); +// // BOOST_TEST( real(b[2]) == 0.691791 ); BOOST_TEST( imag(b[2]) == 0.0227155 ); +// } //} //#if 0 //BOOST_AUTO_TEST_CASE(multi_blas_trsm_double_1x1, *utf::tolerance(0.00001)){ -// multi::array const A = { -// {10.,}, -// }; -// using multi::blas::side; -// using multi::blas::filling; -// using multi::blas::diagonal; -// { -// multi::array B = { -// {3.,}, -// }; -// trsm(filling::upper, diagonal::general, 1., A, B); // B=Solve(A.X=alpha*B, X) B=A⁻¹B, B⊤=B⊤.(A⊤)⁻¹, A upper triangular (implicit zeros below) -// BOOST_TEST( B[0][0] == 3./10. ); -// } -// { -// multi::array B = { -// {3.,}, -// }; -// trsm(filling::upper, diagonal::general, 2., A, B); // B=Solve(A.X=alpha*B, X) B=A⁻¹B, B⊤=B⊤.(A⊤)⁻¹, A upper triangular (implicit zeros below) -// BOOST_TEST( B[0][0] == 2.*3./10. ); -// } -// { -// multi::array B = { -// {3., 4., 5.}, -// }; -// trsm(filling::upper, diagonal::general, 1., A, B); // B=Solve(A.X=alpha*B, X) B=A⁻¹B, B⊤=B⊤.(A⊤)⁻¹, A upper triangular (implicit zeros below) -// BOOST_TEST( B[0][1] == 4./10. ); -// } +// multi::array const A = { +// {10.,}, +// }; +// using multi::blas::side; +// using multi::blas::filling; +// using multi::blas::diagonal; +// { +// multi::array B = { +// {3.,}, +// }; +// trsm(filling::upper, diagonal::general, 1., A, B); // B=Solve(A.X=alpha*B, X) B=A⁻¹B, B⊤=B⊤.(A⊤)⁻¹, A upper triangular (implicit zeros below) +// BOOST_TEST( B[0][0] == 3./10. ); +// } +// { +// multi::array B = { +// {3.,}, +// }; +// trsm(filling::upper, diagonal::general, 2., A, B); // B=Solve(A.X=alpha*B, X) B=A⁻¹B, B⊤=B⊤.(A⊤)⁻¹, A upper triangular (implicit zeros below) +// BOOST_TEST( B[0][0] == 2.*3./10. ); +// } +// { +// multi::array B = { +// {3., 4., 5.}, +// }; +// trsm(filling::upper, diagonal::general, 1., A, B); // B=Solve(A.X=alpha*B, X) B=A⁻¹B, B⊤=B⊤.(A⊤)⁻¹, A upper triangular (implicit zeros below) +// BOOST_TEST( B[0][1] == 4./10. ); +// } //} //BOOST_AUTO_TEST_CASE(multi_blas_trsm_double_0x0, *utf::tolerance(0.00001)){ -// multi::array const A; -// using multi::blas::side; -// using multi::blas::filling; -// using multi::blas::diagonal; -// { -// multi::array B; -// trsm(filling::upper, diagonal::general, 1., A, B); // B=Solve(A.X=alpha*B, X) B=A⁻¹B, B⊤=B⊤.(A⊤)⁻¹, A upper triangular (implicit zeros below) -// } +// multi::array const A; +// using multi::blas::side; +// using multi::blas::filling; +// using multi::blas::diagonal; +// { +// multi::array B; +// trsm(filling::upper, diagonal::general, 1., A, B); // B=Solve(A.X=alpha*B, X) B=A⁻¹B, B⊤=B⊤.(A⊤)⁻¹, A upper triangular (implicit zeros below) +// } //} //BOOST_AUTO_TEST_CASE(multi_blas_trsm_real_nonsquare, *utf::tolerance(0.00001)){ -// multi::array const A = { -// { 1., 3., 4.}, -// { 0., 7., 1.}, -// { 0., 0., 8.} -// }; -// using multi::blas::side; -// using multi::blas::filling; -// using multi::blas::diagonal; -// { -// multi::array B = { -// {1., 3., 4., 8.}, -// {2., 7., 1., 9.}, -// {3., 4., 2., 1.}, -// }; -// multi::array BT = rotated(B); -// trsm(filling::upper, diagonal::general, 1., A, B); // B=Solve(A.X=alpha*B, X) B=A⁻¹B, B⊤=B⊤.(A⊤)⁻¹, A upper triangular (implicit zeros below) -// BOOST_TEST( B[1][2] == 0.107143 ); - -// trsm(filling::upper, diagonal::general, 1., A, rotated(BT)); -// BOOST_TEST( rotated(BT)[1][2] == 0.107143 ); -// } -// { -// multi::array B = { -// {1., 3., 4., 8.}, -// {2., 7., 1., 9.}, -// {3., 4., 2., 1.}, -// }; -// multi::array AT = rotated(A); -// multi::array BT = rotated(B); -// trsm(filling::upper, diagonal::general, 1., rotated(AT), B); // B=Solve(A.X=alpha*B, X) B=A⁻¹B, B⊤=B⊤.(A⊤)⁻¹, A upper triangular (implicit zeros below) -// BOOST_TEST( B[1][2] == 0.107143 ); - -// trsm(filling::upper, diagonal::general, 1., rotated(AT), rotated(BT)); -// print(rotated(BT)); -// BOOST_TEST( rotated(BT)[1][2] == 0.107143 ); -// } -// { -// multi::array B = { -// {1.}, -// {2.}, -// {3.}, -// }; -// trsm(filling::upper, diagonal::general, 1., A, B); // B=Solve(A.X=alpha*B, X) B=A⁻¹B, B⊤=B⊤.(A⊤)⁻¹, A upper triangular (implicit zeros below) -// BOOST_TEST( B[2][0] == 0.375 ); -// } -// { -// multi::array B = { -// {1.}, -// {2.}, -// {3.}, -// }; -// multi::array BT = rotated(B); -// trsm(filling::upper, diagonal::general, 1., A, rotated(BT)); -// BOOST_TEST( rotated(BT)[2][0] == 0.375 ); -// } +// multi::array const A = { +// { 1., 3., 4.}, +// { 0., 7., 1.}, +// { 0., 0., 8.} +// }; +// using multi::blas::side; +// using multi::blas::filling; +// using multi::blas::diagonal; +// { +// multi::array B = { +// {1., 3., 4., 8.}, +// {2., 7., 1., 9.}, +// {3., 4., 2., 1.}, +// }; +// multi::array BT = rotated(B); +// trsm(filling::upper, diagonal::general, 1., A, B); // B=Solve(A.X=alpha*B, X) B=A⁻¹B, B⊤=B⊤.(A⊤)⁻¹, A upper triangular (implicit zeros below) +// BOOST_TEST( B[1][2] == 0.107143 ); + +// trsm(filling::upper, diagonal::general, 1., A, rotated(BT)); +// BOOST_TEST( rotated(BT)[1][2] == 0.107143 ); +// } +// { +// multi::array B = { +// {1., 3., 4., 8.}, +// {2., 7., 1., 9.}, +// {3., 4., 2., 1.}, +// }; +// multi::array AT = rotated(A); +// multi::array BT = rotated(B); +// trsm(filling::upper, diagonal::general, 1., rotated(AT), B); // B=Solve(A.X=alpha*B, X) B=A⁻¹B, B⊤=B⊤.(A⊤)⁻¹, A upper triangular (implicit zeros below) +// BOOST_TEST( B[1][2] == 0.107143 ); + +// trsm(filling::upper, diagonal::general, 1., rotated(AT), rotated(BT)); +// print(rotated(BT)); +// BOOST_TEST( rotated(BT)[1][2] == 0.107143 ); +// } +// { +// multi::array B = { +// {1.}, +// {2.}, +// {3.}, +// }; +// trsm(filling::upper, diagonal::general, 1., A, B); // B=Solve(A.X=alpha*B, X) B=A⁻¹B, B⊤=B⊤.(A⊤)⁻¹, A upper triangular (implicit zeros below) +// BOOST_TEST( B[2][0] == 0.375 ); +// } +// { +// multi::array B = { +// {1.}, +// {2.}, +// {3.}, +// }; +// multi::array BT = rotated(B); +// trsm(filling::upper, diagonal::general, 1., A, rotated(BT)); +// BOOST_TEST( rotated(BT)[2][0] == 0.375 ); +// } //} //BOOST_AUTO_TEST_CASE(multi_blas_trsm_real_nonsquare_default_diagonal_gemm_check, *utf::tolerance(0.00001)){ -// multi::array const A = { -// { 1., 3., 4.}, -// { 0., 7., 1.}, -// { 0., 0., 8.} -// }; -// using multi::blas::side; -// using multi::blas::filling; -// using multi::blas::diagonal; -// { -// multi::array const B = { -// {1.},// 3., 4.}, -// {2.},// 7., 1.}, -// {3.},// 4., 2.}, -// }; -// using multi::blas::gemm; -// { -// auto S = trsm(filling::upper, diagonal::general, 1., A, B); -// BOOST_REQUIRE( S[2][0] == 0.375 ); -// auto Bck=gemm(1., A, S); -// BOOST_REQUIRE( Bck[2][0] == 3. ); -// for(int i{};i<3;++i)for(int j{};j const BT = rotated(B); -// auto Bck=gemm(1., A, trsm(filling::upper, diagonal::general, 1., A, rotated(BT))); -// for(int i{};i<3;++i)for(int j{};j const A = { +// { 1., 3., 4.}, +// { 0., 7., 1.}, +// { 0., 0., 8.} +// }; +// using multi::blas::side; +// using multi::blas::filling; +// using multi::blas::diagonal; +// { +// multi::array const B = { +// {1.},// 3., 4.}, +// {2.},// 7., 1.}, +// {3.},// 4., 2.}, +// }; +// using multi::blas::gemm; +// { +// auto S = trsm(filling::upper, diagonal::general, 1., A, B); +// BOOST_REQUIRE( S[2][0] == 0.375 ); +// auto Bck=gemm(1., A, S); +// BOOST_REQUIRE( Bck[2][0] == 3. ); +// for(int i{};i<3;++i)for(int j{};j const BT = rotated(B); +// auto Bck=gemm(1., A, trsm(filling::upper, diagonal::general, 1., A, rotated(BT))); +// for(int i{};i<3;++i)for(int j{};j const A = { -// { 4.}, -// }; -// using multi::blas::side; -// using multi::blas::filling; -// using multi::blas::diagonal; -// { -// multi::array const B = { -// {5.}, -// }; -// { -// auto S = trsm(filling::upper, diagonal::general, 3., A, B); -// BOOST_REQUIRE( S[0][0] == 3.*5./4. ); -// } -// { -// auto S = trsm(filling::upper, 1., A, B); -// BOOST_REQUIRE( S[0][0] == 1.*5./4. ); -// } -// { -// auto S = trsm(filling::upper, A, B); -// BOOST_REQUIRE( S[0][0] == 1.*5./4. ); -// } -// } +// multi::array const A = { +// { 4.}, +// }; +// using multi::blas::side; +// using multi::blas::filling; +// using multi::blas::diagonal; +// { +// multi::array const B = { +// {5.}, +// }; +// { +// auto S = trsm(filling::upper, diagonal::general, 3., A, B); +// BOOST_REQUIRE( S[0][0] == 3.*5./4. ); +// } +// { +// auto S = trsm(filling::upper, 1., A, B); +// BOOST_REQUIRE( S[0][0] == 1.*5./4. ); +// } +// { +// auto S = trsm(filling::upper, A, B); +// BOOST_REQUIRE( S[0][0] == 1.*5./4. ); +// } +// } //} //BOOST_AUTO_TEST_CASE(multi_blas_trsm_complex_1x1_check, *utf::tolerance(0.00001)){ -// using complex = std::complex; complex const I = complex{0, 1}; -// multi::array const A = { -// { 4. + 2.*I}, -// }; -// using multi::blas::side; -// using multi::blas::filling; -// using multi::blas::diagonal; -// { -// multi::array const B = { -// {5. + 1.*I}, -// }; -// using multi::blas::gemm; -// { -// auto S = trsm(filling::upper, diagonal::general, 3.+5.*I, A, B); -// BOOST_TEST( real(S[0][0]) == real((3.+5.*I)*B[0][0]/A[0][0]) ); -// BOOST_TEST( imag(S[0][0]) == imag((3.+5.*I)*B[0][0]/A[0][0]) ); -// } -// } +// using complex = std::complex; complex const I = complex{0, 1}; +// multi::array const A = { +// { 4. + 2.*I}, +// }; +// using multi::blas::side; +// using multi::blas::filling; +// using multi::blas::diagonal; +// { +// multi::array const B = { +// {5. + 1.*I}, +// }; +// using multi::blas::gemm; +// { +// auto S = trsm(filling::upper, diagonal::general, 3.+5.*I, A, B); +// BOOST_TEST( real(S[0][0]) == real((3.+5.*I)*B[0][0]/A[0][0]) ); +// BOOST_TEST( imag(S[0][0]) == imag((3.+5.*I)*B[0][0]/A[0][0]) ); +// } +// } //} //BOOST_AUTO_TEST_CASE(multi_blas_trsm_complex_nonsquare_default_diagonal_one_check, *utf::tolerance(0.00001)){ -// using complex = std::complex; complex const I{0, 1}; -// multi::array const A = { -// { 1. + 4.*I, 3., 4.- 10.*I}, -// { 0., 7.- 3.*I, 1.}, -// { 0., 0., 8.- 2.*I} -// }; -// using multi::blas::side; -// using multi::blas::filling; -// using multi::blas::diagonal; -// { -// multi::array const B = { -// {1. + 1.*I}, -// {2. + 1.*I}, -// {3. + 1.*I}, -// }; -// using multi::blas::gemm; -// { -// auto S = trsm(filling::upper, diagonal::general, 1., A, B); -// BOOST_TEST( real(S[2][0]) == 0.323529 ); -// } -// { -// auto const BT = +rotated(B); -// auto S = trsm(filling::upper, diagonal::general, 1., A, rotated(BT)); -// BOOST_TEST( real(S[2][0]) == 0.323529 ); -// } -// { -// auto const AT = +rotated(A); -// auto S = trsm(filling::upper, diagonal::general, 1., rotated(AT), B); -// BOOST_TEST( real(S[2][0]) == 0.323529 ); -// } -// { -// auto const AT = +rotated(A); -// auto const BT = +rotated(B); -// auto S = trsm(filling::upper, diagonal::general, 1., rotated(AT), rotated(BT)); -// BOOST_TEST( real(S[2][0]) == 0.323529 ); -// } -// } +// using complex = std::complex; complex const I{0, 1}; +// multi::array const A = { +// { 1. + 4.*I, 3., 4.- 10.*I}, +// { 0., 7.- 3.*I, 1.}, +// { 0., 0., 8.- 2.*I} +// }; +// using multi::blas::side; +// using multi::blas::filling; +// using multi::blas::diagonal; +// { +// multi::array const B = { +// {1. + 1.*I}, +// {2. + 1.*I}, +// {3. + 1.*I}, +// }; +// using multi::blas::gemm; +// { +// auto S = trsm(filling::upper, diagonal::general, 1., A, B); +// BOOST_TEST( real(S[2][0]) == 0.323529 ); +// } +// { +// auto const BT = +rotated(B); +// auto S = trsm(filling::upper, diagonal::general, 1., A, rotated(BT)); +// BOOST_TEST( real(S[2][0]) == 0.323529 ); +// } +// { +// auto const AT = +rotated(A); +// auto S = trsm(filling::upper, diagonal::general, 1., rotated(AT), B); +// BOOST_TEST( real(S[2][0]) == 0.323529 ); +// } +// { +// auto const AT = +rotated(A); +// auto const BT = +rotated(B); +// auto S = trsm(filling::upper, diagonal::general, 1., rotated(AT), rotated(BT)); +// BOOST_TEST( real(S[2][0]) == 0.323529 ); +// } +// } //} //BOOST_AUTO_TEST_CASE(multi_blas_trsm_complex_nonsquare_default_diagonal_gemm_check, *utf::tolerance(0.00001)){ -// using complex = std::complex; complex const I{0, 1}; -// multi::array const A = { -// { 1. + 4.*I, 3., 4.- 10.*I}, -// { 0., 7.- 3.*I, 1.}, -// { 0., 0., 8.- 2.*I} -// }; -// using multi::blas::side; -// using multi::blas::filling; -// using multi::blas::diagonal; -// { -// multi::array const B = { -// {1. + 1.*I, 5. + 3.*I}, -// {2. + 1.*I, 9. + 3.*I}, -// {3. + 1.*I, 1. - 1.*I}, -// }; -// using multi::blas::gemm; -// { -// auto S = trsm(filling::upper, diagonal::general, 1., A, B); // S = Ainv.B -// BOOST_TEST( real(S[2][1]) == 0.147059 ); -// } -// { -// auto const BT = +rotated(B); -// auto S = trsm(filling::upper, diagonal::general, 1., A, rotated(BT)); -// BOOST_TEST( real(S[2][1]) == 0.147059 ); -// } -// { -// auto const AT = +rotated(A); -// auto S = trsm(filling::upper, diagonal::general, 1., rotated(AT), B); -// BOOST_TEST( real(S[2][1]) == 0.147059 ); -// } -// { -// auto const AT = +rotated(A); -// auto const BT = +rotated(B); -// auto S = trsm(filling::upper, diagonal::general, 1., rotated(AT), rotated(BT)); -// BOOST_TEST( real(S[2][1]) == 0.147059 ); -// } -// } +// using complex = std::complex; complex const I{0, 1}; +// multi::array const A = { +// { 1. + 4.*I, 3., 4.- 10.*I}, +// { 0., 7.- 3.*I, 1.}, +// { 0., 0., 8.- 2.*I} +// }; +// using multi::blas::side; +// using multi::blas::filling; +// using multi::blas::diagonal; +// { +// multi::array const B = { +// {1. + 1.*I, 5. + 3.*I}, +// {2. + 1.*I, 9. + 3.*I}, +// {3. + 1.*I, 1. - 1.*I}, +// }; +// using multi::blas::gemm; +// { +// auto S = trsm(filling::upper, diagonal::general, 1., A, B); // S = Ainv.B +// BOOST_TEST( real(S[2][1]) == 0.147059 ); +// } +// { +// auto const BT = +rotated(B); +// auto S = trsm(filling::upper, diagonal::general, 1., A, rotated(BT)); +// BOOST_TEST( real(S[2][1]) == 0.147059 ); +// } +// { +// auto const AT = +rotated(A); +// auto S = trsm(filling::upper, diagonal::general, 1., rotated(AT), B); +// BOOST_TEST( real(S[2][1]) == 0.147059 ); +// } +// { +// auto const AT = +rotated(A); +// auto const BT = +rotated(B); +// auto S = trsm(filling::upper, diagonal::general, 1., rotated(AT), rotated(BT)); +// BOOST_TEST( real(S[2][1]) == 0.147059 ); +// } +// } //} //BOOST_AUTO_TEST_CASE(multi_blas_trsm_complex_nonsquare_default_diagonal_hermitized_gemm_check, *utf::tolerance(0.00001)){ -// using complex = std::complex; complex const I{0, 1}; -// multi::array const A = { -// { 1. + 4.*I, 3., 4.- 10.*I}, -// { 0., 7.- 3.*I, 1.}, -// { 0., 0., 8.- 2.*I} -// }; -// using multi::blas::filling; -// using multi::blas::diagonal; -// { -// multi::array const B = { -// {1. + 1.*I, 5. + 3.*I}, -// {2. + 1.*I, 9. + 3.*I}, -// {3. + 1.*I, 1. - 1.*I}, -// }; -// using multi::blas::hermitized; -// { -// auto S = trsm(filling::lower, diagonal::general, 1., hermitized(A), B); // S = A⁻¹†.B, S† = B†.A⁻¹ -// BOOST_TEST( real(S[2][1]) == 1.71608 ); -// } -// { -// multi::array const B = { -// {1. + 1.*I, 2. + 1.*I, 3. + 1.*I}, -// {5. + 3.*I, 9. + 3.*I, 1. - 1.*I} -// }; -// auto S =* trsm(filling::upper, 1., A, hermitized(B)); // S = A⁻¹B†, S†=B.A⁻¹†, S=(B.A⁻¹)†, B <- S†, B <- B.A⁻¹† -// BOOST_TEST( imag(S[2][1]) == +0.147059 ); -// BOOST_TEST( imag(B[1][2]) == -0.147059 ); -// } -// { -// multi::array const B = { -// {1. + 1.*I, 2. + 1.*I, 3. + 1.*I}, -// {5. + 3.*I, 9. + 3.*I, 1. - 1.*I} -// }; -// auto S =* trsm(filling::upper, 2., A, hermitized(B)); // S = A⁻¹B†, S†=B.A⁻¹†, S=(B.A⁻¹)†, B <- S†, B <- B.A⁻¹† -// BOOST_TEST( imag(S[2][1]) == +0.147059*2. ); -// BOOST_TEST( imag(B[1][2]) == -0.147059*2. ); -// } -// } +// using complex = std::complex; complex const I{0, 1}; +// multi::array const A = { +// { 1. + 4.*I, 3., 4.- 10.*I}, +// { 0., 7.- 3.*I, 1.}, +// { 0., 0., 8.- 2.*I} +// }; +// using multi::blas::filling; +// using multi::blas::diagonal; +// { +// multi::array const B = { +// {1. + 1.*I, 5. + 3.*I}, +// {2. + 1.*I, 9. + 3.*I}, +// {3. + 1.*I, 1. - 1.*I}, +// }; +// using multi::blas::hermitized; +// { +// auto S = trsm(filling::lower, diagonal::general, 1., hermitized(A), B); // S = A⁻¹†.B, S† = B†.A⁻¹ +// BOOST_TEST( real(S[2][1]) == 1.71608 ); +// } +// { +// multi::array const B = { +// {1. + 1.*I, 2. + 1.*I, 3. + 1.*I}, +// {5. + 3.*I, 9. + 3.*I, 1. - 1.*I} +// }; +// auto S =* trsm(filling::upper, 1., A, hermitized(B)); // S = A⁻¹B†, S†=B.A⁻¹†, S=(B.A⁻¹)†, B <- S†, B <- B.A⁻¹† +// BOOST_TEST( imag(S[2][1]) == +0.147059 ); +// BOOST_TEST( imag(B[1][2]) == -0.147059 ); +// } +// { +// multi::array const B = { +// {1. + 1.*I, 2. + 1.*I, 3. + 1.*I}, +// {5. + 3.*I, 9. + 3.*I, 1. - 1.*I} +// }; +// auto S =* trsm(filling::upper, 2., A, hermitized(B)); // S = A⁻¹B†, S†=B.A⁻¹†, S=(B.A⁻¹)†, B <- S†, B <- B.A⁻¹† +// BOOST_TEST( imag(S[2][1]) == +0.147059*2. ); +// BOOST_TEST( imag(B[1][2]) == -0.147059*2. ); +// } +// } //} //BOOST_AUTO_TEST_CASE(multi_blas_trsm_complex_nonsquare_default_diagonal_hermitized_gemm_check_no_const, *utf::tolerance(0.00001)){ -// using complex = std::complex; complex const I{0, 1}; -// multi::array const A = { -// { 1. + 4.*I, 3., 4.- 10.*I}, -// { 0., 7.- 3.*I, 1.}, -// { 0., 0., 8.- 2.*I} -// }; -// multi::array B = { -// {1. + 1.*I, 2. + 1.*I, 3. + 1.*I}, -// {5. + 3.*I, 9. + 3.*I, 1. - 1.*I} -// }; -// using multi::blas::trsm; -// using multi::blas::filling; -// using multi::blas::hermitized; -// trsm(filling::upper, A, hermitized(B)); // B†←A⁻¹.B†, B←B.A⁻¹†, B←(A⁻¹.B†)† -// BOOST_TEST( imag(B[1][2]) == -0.147059 ); +// using complex = std::complex; complex const I{0, 1}; +// multi::array const A = { +// { 1. + 4.*I, 3., 4.- 10.*I}, +// { 0., 7.- 3.*I, 1.}, +// { 0., 0., 8.- 2.*I} +// }; +// multi::array B = { +// {1. + 1.*I, 2. + 1.*I, 3. + 1.*I}, +// {5. + 3.*I, 9. + 3.*I, 1. - 1.*I} +// }; +// using multi::blas::trsm; +// using multi::blas::filling; +// using multi::blas::hermitized; +// trsm(filling::upper, A, hermitized(B)); // B†←A⁻¹.B†, B←B.A⁻¹†, B←(A⁻¹.B†)† +// BOOST_TEST( imag(B[1][2]) == -0.147059 ); //} //#endif //#endif diff --git a/external_codes/boost_multi/multi/include/boost/multi/adaptors/complex/adl.hpp b/external_codes/boost_multi/multi/include/boost/multi/adaptors/complex/adl.hpp index ef2e85bbfd..8c0c771e1b 100644 --- a/external_codes/boost_multi/multi/include/boost/multi/adaptors/complex/adl.hpp +++ b/external_codes/boost_multi/multi/include/boost/multi/adaptors/complex/adl.hpp @@ -21,29 +21,35 @@ namespace boost { // NOLINT(modernize-concat-nested-namespaces) keep c++14 compat namespace multi { -inline constexpr class /*adl_conj_t*/ { +class adl_conj_t { template constexpr auto _(priority<1> /**/, As&&... args) const BOOST_MULTI_JUSTRETURN(std::conj(std::forward(args)...)) template constexpr auto _(priority<2> /**/, As&&... args) const BOOST_MULTI_DECLRETURN(conj(std::forward(args)...)) template constexpr auto _(priority<3> /**/, T&& arg, As&&... args) const BOOST_MULTI_DECLRETURN(std::forward(arg).conj(std::forward(args)...)) public : template constexpr auto operator()(As&&... args) const BOOST_MULTI_DECLRETURN(_(priority<3>{}, std::forward(args)...)) -} adl_conj; +}; + +inline constexpr adl_conj_t adl_conj; -inline constexpr class /*adl_real_t*/ { +class adl_real_t { template constexpr auto _(priority<1> /**/, As&&... args) const BOOST_MULTI_DECLRETURN(std::real(std::forward(args)...)) template constexpr auto _(priority<2> /**/, As&&... args) const BOOST_MULTI_DECLRETURN(real(std::forward(args)...)) template constexpr auto _(priority<3> /**/, T&& arg, As&&... args) const BOOST_MULTI_DECLRETURN(std::forward(arg).real(std::forward(args)...)) public : template constexpr auto operator()(As&&... args) const BOOST_MULTI_DECLRETURN(_(priority<3>{}, std::forward(args)...)) -} adl_real; +}; -inline constexpr class /*adl_imag_t*/ { +inline constexpr adl_real_t adl_real; + +class adl_imag_t { template constexpr auto _(priority<1> /**/, As&&... args) const BOOST_MULTI_DECLRETURN(std::imag(std::forward(args)...)) template constexpr auto _(priority<2> /**/, As&&... args) const BOOST_MULTI_DECLRETURN(imag(std::forward(args)...)) template constexpr auto _(priority<3> /**/, T&& arg, As&&... args) const BOOST_MULTI_DECLRETURN(std::forward(arg).imag(std::forward(args)...)) public : template constexpr auto operator()(As&&... args) const BOOST_MULTI_DECLRETURN(_(priority<3>{}, std::forward(args)...)) -} adl_imag; +}; + +inline constexpr adl_imag_t adl_imag; struct real_t; struct imag_t; @@ -67,19 +73,19 @@ struct _complex { // NOLINT(readability-identifier-naming) deprecating this template< class T, - std::enable_if_t< + std::enable_if_t< // NOLINT(modernize-use-constraints) TODO(correaa) for C++20 sizeof(T) == 2 * sizeof(value_type) && std::is_assignable().real())>{} && std::is_assignable().imag())>{}, - int> = 0> + int> =0> constexpr explicit operator T const&() const& { return reinterpret_cast(*this); // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast) } template< class T, - std::enable_if_t< + std::enable_if_t< // NOLINT(modernize-use-constraints) TODO(correaa) for C++20 sizeof(T) == 2 * sizeof(value_type) && - std::is_assignable().real())>{} && - std::is_assignable().imag())>{}, + std::is_assignable_v().real())> && + std::is_assignable_v().imag())>, int> = 0> constexpr explicit operator T&() & { return reinterpret_cast(*this); } // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast) @@ -116,17 +122,17 @@ struct real_t { return std::forward(array).template reinterpret_array_cast<_complex>().template member_cast(&_complex::real); } template::value_type, - std::enable_if_t< + std::enable_if_t< // NOLINT(modernize-use-constraints) TODO(correaa) for C++20 sizeof(T) == 2 * sizeof(ValueType) && - std::is_assignable()))>{} && - std::is_assignable()))>{}, + std::is_assignable_v()))> && + std::is_assignable_v()))>, int> = 0> constexpr auto operator()(T& value) const -> ValueType& { return reinterpret_cast&>(value).real; } // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast) : TODO(correaa) : t[0] template::value_type, - std::enable_if_t< + std::enable_if_t< // NOLINT(modernize-use-constraints) TODO(correaa) for C++20 sizeof(T) == 2 * sizeof(ValueType) && - std::is_assignable()))>{} && - std::is_assignable()))>{}, + std::is_assignable_v()))> && + std::is_assignable_v()))>, int> = 0> auto operator()(T const& value) const -> ValueType const& { return reinterpret_cast const&>(value).real; // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast) : TODO(correaa) : t[0] @@ -140,7 +146,7 @@ struct imag_t { return std::forward(array).template reinterpret_array_cast<_complex>().template member_cast(&_complex::imag); } template::value_type, - std::enable_if_t< + std::enable_if_t< // NOLINT(modernize-use-constraints) TODO(correaa) for C++20 sizeof(T) == 2 * sizeof(ValueType) && std::is_assignable()))>{} && std::is_assignable()))>{}, @@ -149,7 +155,7 @@ struct imag_t { return reinterpret_cast&>(value).imag; // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast) : TODO(correaa) : t[1] } template::value_type, - std::enable_if_t< + std::enable_if_t< // NOLINT(modernize-use-constraints) TODO(correaa) for C++20 sizeof(T) == 2 * sizeof(ValueType) && std::is_assignable()))>{} && std::is_assignable()))>{}, diff --git a/external_codes/boost_multi/multi/include/boost/multi/adaptors/complex/test/CMakeLists.txt b/external_codes/boost_multi/multi/include/boost/multi/adaptors/complex/test/CMakeLists.txt index d17b35fd89..9dfebf37a7 100644 --- a/external_codes/boost_multi/multi/include/boost/multi/adaptors/complex/test/CMakeLists.txt +++ b/external_codes/boost_multi/multi/include/boost/multi/adaptors/complex/test/CMakeLists.txt @@ -3,31 +3,6 @@ cmake_minimum_required(VERSION 3.16) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) -# if((NOT -# CMAKE_CXX_COMPILER_ID -# STREQUAL -# "PGI" -# ) -# AND (NOT -# DART_COMPILER_NAME -# STREQUAL -# "nvcc" -# ) -# AND (NOT -# DART_COMPILER_NAME -# STREQUAL -# "icpc" -# ) -# ) -# find_package(Boost REQUIRED COMPONENTS unit_test_framework) -# link_libraries("-lboost_unit_test_framework") -# else() -# find_package(Boost REQUIRED) # cmake cannot detect this component with pgi compiler -# link_libraries("-lboost_unit_test_framework") - -# link_libraries("-lblas") # cmake cannot detect BLAS with pgi/nvc++ but it ships with its own version -# endif() - if(CMAKE_CXX_COMPILER_ID STREQUAL "PGI") add_definitions(-DRETURN_BY_STACK) endif() diff --git a/external_codes/boost_multi/multi/include/boost/multi/adaptors/complex.hpp b/external_codes/boost_multi/multi/include/boost/multi/adaptors/complex_.hpp similarity index 92% rename from external_codes/boost_multi/multi/include/boost/multi/adaptors/complex.hpp rename to external_codes/boost_multi/multi/include/boost/multi/adaptors/complex_.hpp index af5cf121cc..9a8f3209c6 100644 --- a/external_codes/boost_multi/multi/include/boost/multi/adaptors/complex.hpp +++ b/external_codes/boost_multi/multi/include/boost/multi/adaptors/complex_.hpp @@ -47,22 +47,22 @@ struct [[nodiscard]] imaginary { [[nodiscard]] constexpr auto operator/(imaginary other) const { return T{1} / other._value; } }; -constexpr imaginary I{}; // NOLINT(readability-identifier-length) imaginary unit +inline constexpr imaginary I{}; // NOLINT(readability-identifier-length) imaginary unit namespace literals { // constexpr imaginary operator""_i(unsigned long long d) { // return imaginary{static_cast(d)}; // } -constexpr auto operator"" _i(long double value) { return imaginary{static_cast(value)}; } +constexpr auto operator""_i(long double value) { return imaginary{static_cast(value)}; } // constexpr auto operator"" i(long double value) {return imaginary{static_cast(value)};} -constexpr auto operator"" _I(long double value) { return imaginary{static_cast(value)}; } +constexpr auto operator""_I(long double value) { return imaginary{static_cast(value)}; } // constexpr auto operator"" f_i(long double value) {return imaginary{static_cast(value)};} constexpr auto operator""_f_i(long double value) { return imaginary{static_cast(value)}; } -constexpr auto operator"" _if(long double value) { return imaginary{static_cast(value)}; } +constexpr auto operator""_if(long double value) { return imaginary{static_cast(value)}; } constexpr auto operator""_F_I(long double value) { return imaginary{static_cast(value)}; } -constexpr auto operator"" _IF(long double value) { return imaginary{static_cast(value)}; } +constexpr auto operator""_IF(long double value) { return imaginary{static_cast(value)}; } // template // constexpr auto operator""_FI() noexcept {} diff --git a/external_codes/boost_multi/multi/include/boost/multi/adaptors/cuda/CMakeLists.txt b/external_codes/boost_multi/multi/include/boost/multi/adaptors/cuda/CMakeLists.txt index f4d6090a5c..fd73056da2 100644 --- a/external_codes/boost_multi/multi/include/boost/multi/adaptors/cuda/CMakeLists.txt +++ b/external_codes/boost_multi/multi/include/boost/multi/adaptors/cuda/CMakeLists.txt @@ -5,13 +5,11 @@ cmake_minimum_required(VERSION 3.11) # LANGUAGES CXX #) -set(CMAKE_VERBOSE_MAKEFILE ON) - -set(CMAKE_CXX_STANDARD 17) +# set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) -find_package(Boost REQUIRED COMPONENTS unit_test_framework) +find_package(Boost REQUIRED COMPONENTS) # unit_test_framework) if(ENABLE_HIP) enable_language(HIP) # may need `module load rocm` diff --git a/external_codes/boost_multi/multi/include/boost/multi/adaptors/cuda/cublas/call.hpp b/external_codes/boost_multi/multi/include/boost/multi/adaptors/cuda/cublas/call.hpp index fb50aaa38d..020d99aa28 100644 --- a/external_codes/boost_multi/multi/include/boost/multi/adaptors/cuda/cublas/call.hpp +++ b/external_codes/boost_multi/multi/include/boost/multi/adaptors/cuda/cublas/call.hpp @@ -8,13 +8,13 @@ #include "../cublas/error.hpp" -#if not defined(MULTI_USE_HIP) +#if !defined(MULTI_USE_HIP) #include // cudaDeviceSynchronize #else #include // cudaDeviceSynchronize #endif -#if not defined(MULTI_USE_HIP) +#if !defined(MULTI_USE_HIP) #define hicup(name) cuda##name #define HICUP(name) CU##name #else diff --git a/external_codes/boost_multi/multi/include/boost/multi/adaptors/cuda/cublas/context.hpp b/external_codes/boost_multi/multi/include/boost/multi/adaptors/cuda/cublas/context.hpp index 2ad055f783..03b1192b65 100644 --- a/external_codes/boost_multi/multi/include/boost/multi/adaptors/cuda/cublas/context.hpp +++ b/external_codes/boost_multi/multi/include/boost/multi/adaptors/cuda/cublas/context.hpp @@ -10,7 +10,7 @@ #include #include -#if not defined(MULTI_USE_HIP) +#if !defined(MULTI_USE_HIP) #include // for thrust::cuda::pointer #else #include // for thrust::cuda::pointer @@ -309,22 +309,51 @@ class context : private std::unique_ptr::element_type, - class RRP, class RR = typename std::pointer_traits::element_type, + class RRP, class RR = typename std::pointer_traits::element_type + , std::enable_if_t< - is_z{} and is_d{} and is_assignable{} and - is_convertible_v> and (is_convertible_v> or is_convertible_v) + is_z::value + , int> =0 + // , + // std::enable_if_t< + // is_z{} && is_d{} && is_assignable{} && + // is_convertible_v> && (is_convertible_v> or is_convertible_v) + // , int> =0 + > + void nrm2(int n, XXP xx, int incx, RRP rr) { + if(is_convertible_v>) {hicu(blasSetPointerMode)(get(), HICU(BLAS_POINTER_MODE_DEVICE));} + if constexpr(is_convertible_v>) { + sync_call(n, reinterpret_cast(::thrust::raw_pointer_cast(xx)), incx, reinterpret_cast(::thrust::raw_pointer_cast(rr)) ); + } else { + sync_call(n, reinterpret_cast(::thrust::raw_pointer_cast(xx)), incx, reinterpret_cast( rr ) ); + } + if(is_convertible_v>) {hicu(blasSetPointerMode)(get(), HICU(BLAS_POINTER_MODE_HOST));} + } + + template< + class XXP, class XX = typename std::pointer_traits::element_type, + class RRP, class RR = typename std::pointer_traits::element_type + , + std::enable_if_t< + is_d::value , int> =0 + // , + // std::enable_if_t< + // is_z{} && is_d{} && is_assignable{} && + // is_convertible_v> && (is_convertible_v> or is_convertible_v) + // , int> =0 > void nrm2(int n, XXP xx, int incx, RRP rr) { if(is_convertible_v>) {hicu(blasSetPointerMode)(get(), HICU(BLAS_POINTER_MODE_DEVICE));} if constexpr(is_convertible_v>) { - sync_call(n, (DoubleComplex const*)::thrust::raw_pointer_cast(xx), incx, (double*)::thrust::raw_pointer_cast(rr) ); + sync_call(n, ::thrust::raw_pointer_cast(xx), incx, reinterpret_cast(::thrust::raw_pointer_cast(rr)) ); } else { - sync_call(n, (DoubleComplex const*)::thrust::raw_pointer_cast(xx), incx, (double*) rr ); + sync_call(n, ::thrust::raw_pointer_cast(xx), incx, reinterpret_cast( rr ) ); } if(is_convertible_v>) {hicu(blasSetPointerMode)(get(), HICU(BLAS_POINTER_MODE_HOST));} } + template< class XXP, class XX = typename std::pointer_traits::element_type, class YYP, class YY = typename std::pointer_traits::element_type, diff --git a/external_codes/boost_multi/multi/include/boost/multi/adaptors/cuda/cublas/test/CMakeLists.txt b/external_codes/boost_multi/multi/include/boost/multi/adaptors/cuda/cublas/test/CMakeLists.txt index c66046fb99..4c68461e8f 100644 --- a/external_codes/boost_multi/multi/include/boost/multi/adaptors/cuda/cublas/test/CMakeLists.txt +++ b/external_codes/boost_multi/multi/include/boost/multi/adaptors/cuda/cublas/test/CMakeLists.txt @@ -1,8 +1,6 @@ cmake_minimum_required(VERSION 3.17) # for CUDAToolkit -set(CMAKE_VERBOSE_MAKEFILE ON) - -find_package(Boost REQUIRED COMPONENTS unit_test_framework) +find_package(Boost REQUIRED COMPONENTS) # unit_test_framework) if((NOT CMAKE_CXX_COMPILER_ID @@ -65,8 +63,8 @@ include_directories(${CMAKE_BINARY_DIR}) if(ENABLE_HIP) add_executable(all.hip.x all.hip) #set_source_files_properties(${TEST_FILE} PROPERTIES LANGUAGE HIP) - target_link_libraries(all.hip.x PRIVATE multi roc::hipblas Boost::unit_test_framework) - target_compile_definitions(all.hip.x PRIVATE BOOST_TEST_DYN_LINK=1) + target_link_libraries(all.hip.x PRIVATE multi roc::hipblas Boost::boost) + # target_compile_definitions(all.hip.x PRIVATE BOOST_TEST_DYN_LINK=1) add_test(NAME all.hip.x COMMAND ./all.hip.x) endif() @@ -84,6 +82,7 @@ set(TEST_SRCS gemm.cu gemv.cu # herk.cu + nrm2.cu scal.cu trsm.cu ) @@ -102,11 +101,11 @@ foreach(TEST_FILE ${TEST_SRCS}) #target_compile_options(${TEST_EXE} PRIVATE --expt-relaxed-constexpr) - target_link_libraries(${TEST_EXE} PRIVATE Boost::unit_test_framework) + # target_link_libraries(${TEST_EXE} PRIVATE Boost::unit_test_framework) target_link_libraries(${TEST_EXE} PRIVATE ${CUDA_LIBRARIES}) target_link_libraries(${TEST_EXE} PRIVATE CUDA::cublas) - target_link_libraries(${TEST_EXE} PRIVATE multi Boost::unit_test_framework) + target_link_libraries(${TEST_EXE} PRIVATE multi) # Boost::unit_test_framework) # target_include_directories(${TEST_EXE} PRIVATE /opt/nvidia/hpc_sdk/Linux_x86_64/22.3/math_libs/include) diff --git a/external_codes/boost_multi/multi/include/boost/multi/adaptors/cuda/cublas/test/all.cu b/external_codes/boost_multi/multi/include/boost/multi/adaptors/cuda/cublas/test/all.cu index b1ebb0f215..44824e315c 100644 --- a/external_codes/boost_multi/multi/include/boost/multi/adaptors/cuda/cublas/test/all.cu +++ b/external_codes/boost_multi/multi/include/boost/multi/adaptors/cuda/cublas/test/all.cu @@ -3,7 +3,7 @@ // https://www.boost.org/LICENSE_1_0.txt #define BOOST_TEST_MODULE "C++ Unit Tests for Multi CUBLAS all" -#include +// #include #include @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -18,9 +19,9 @@ #include -#include +#include -#include +#include #include #include @@ -30,293 +31,301 @@ using complex = thrust::complex; template> auto generate_ABx() { - complex const I{0.0, 1.0}; - multi::array x = { 1.0 + I*0.0, 2.0 + I*0.0, 3.0 + I*0.0, 4.0 + I*0.0}; + complex const I{ 0.0, 1.0 }; + multi::array x = { 1.0 + I * 0.0, 2.0 + I * 0.0, 3.0 + I * 0.0, 4.0 + I * 0.0 }; multi::array A = { - { 1.0 + I*0.0, 2.0 + I*0.0, 3.0 + I*0.0, 4.0 + I*0.0}, - { 5.0 + I*0.0, 6.0 + I*0.0, 7.0 + I*0.0, 8.0 + I*0.0}, - { 9.0 + I*0.0, 10.0 + I*0.0, 11.0 + I*0.0, 12.0 + I*0.0}, - {13.0 + I*0.0, 14.0 + I*0.0, 15.0 + I*0.0, 16.0 + I*0.0}, + { 1.0 + I * 0.0, 2.0 + I * 0.0, 3.0 + I * 0.0, 4.0 + I * 0.0}, + { 5.0 + I * 0.0, 6.0 + I * 0.0, 7.0 + I * 0.0, 8.0 + I * 0.0}, + { 9.0 + I * 0.0, 10.0 + I * 0.0, 11.0 + I * 0.0, 12.0 + I * 0.0}, + {13.0 + I * 0.0, 14.0 + I * 0.0, 15.0 + I * 0.0, 16.0 + I * 0.0}, }; multi::array B = { - { 1.0 + I*0.0, 2.0 + I*0.0, 3.0 + I*0.0, 4.0 + I*0.0}, - { 5.0 + I*0.0, 6.0 + I*0.0, 7.0 + I*0.0, 8.0 + I*0.0}, - { 9.0 + I*0.0, 10.0 + I*0.0, 11.0 + I*0.0, 12.0 + I*0.0}, - {13.0 + I*0.0, 14.0 + I*0.0, 15.0 + I*0.0, 16.0 + I*0.0}, + { 1.0 + I * 0.0, 2.0 + I * 0.0, 3.0 + I * 0.0, 4.0 + I * 0.0}, + { 5.0 + I * 0.0, 6.0 + I * 0.0, 7.0 + I * 0.0, 8.0 + I * 0.0}, + { 9.0 + I * 0.0, 10.0 + I * 0.0, 11.0 + I * 0.0, 12.0 + I * 0.0}, + {13.0 + I * 0.0, 14.0 + I * 0.0, 15.0 + I * 0.0, 16.0 + I * 0.0}, }; return std::make_tuple(std::move(x), std::move(A), std::move(B)); } +#include +#define BOOST_AUTO_TEST_CASE(CasenamE) /**/ + +#define BOOST_REQUIRE_CLOSE(X, Y, ToL) BOOST_TEST( std::abs( (X) - (Y) ) < (ToL) ) + +int main() { BOOST_AUTO_TEST_CASE(cublas_scal_complex_column) { namespace blas = multi::blas; - complex const I{0.0, 1.0}; + complex const I{ 0.0, 1.0 }; { - using T = complex; - auto [x, A, B] = generate_ABx >(); - auto const s = 2.0 + I*3.0; + using T = complex; + auto [x, A, B] = generate_ABx>(); + auto const s = 2.0 + I * 3.0; blas::scal(s, x); // x_i <- s*x_i { - auto [x2, A2, B2] = generate_ABx >(); - auto xx = +x2; + auto [x2, A2, B2] = generate_ABx>(); + auto xx = +x2; blas::scal(s, xx); - BOOST_REQUIRE(xx == x); + BOOST_TEST(xx == x); } { - auto [x2, A2, B2] = generate_ABx >(); + auto [x2, A2, B2] = generate_ABx>(); using blas::operators::operator*=; x2 *= s; - BOOST_REQUIRE(x == x2); + BOOST_TEST(x == x2); } { - auto [x2, A2, B2] = generate_ABx >(); - thrust::transform(x2.begin(), x2.end(), x2.begin(), [s] __device__ (T& e) {return s*e;}); + auto [x2, A2, B2] = generate_ABx>(); + thrust::transform(x2.begin(), x2.end(), x2.begin(), [s] __device__(T & e) { return s * e; }); - BOOST_REQUIRE(x == x2); + BOOST_TEST(x == x2); } { - auto [x2, A2, B2] = generate_ABx >(); - thrust::for_each(x2.begin(), x2.end(), [s] __device__ (T& e) {return e*=s;}); + auto [x2, A2, B2] = generate_ABx>(); + thrust::for_each(x2.begin(), x2.end(), [s] __device__(T & e) { return e *= s; }); - BOOST_REQUIRE(x == x2); + BOOST_TEST(x == x2); } } } BOOST_AUTO_TEST_CASE(cublas_copy_complex) { namespace blas = multi::blas; - complex const I{0.0, 1.0}; + complex const I{ 0.0, 1.0 }; - using T = complex; - using Alloc = thrust::cuda::allocator; + using T = complex; + using Alloc = thrust::cuda::allocator; - multi::array const x = { 1.0 + I*8.0, 2.0 + I*6.0, 3.0 + I*5.0, 4.0 + I*3.0}; - multi::array y = { 1.0 + I*9.0, 2.0 + I*6.0, 3.0 + I*5.0, 4.0 + I*3.0}; + multi::array const x = { 1.0 + I * 8.0, 2.0 + I * 6.0, 3.0 + I * 5.0, 4.0 + I * 3.0 }; + multi::array y = { 1.0 + I * 9.0, 2.0 + I * 6.0, 3.0 + I * 5.0, 4.0 + I * 3.0 }; blas::copy(x, y); - BOOST_REQUIRE( static_cast(y[0]) == 1.0 + I*8.0 ); + BOOST_TEST( static_cast(y[0]) == 1.0 + I*8.0 ); { thrust::copy(begin(x), end(x), begin(y)); - BOOST_REQUIRE( static_cast(y[0]) == 1.0 + I*8.0 ); + BOOST_TEST( static_cast(y[0]) == 1.0 + I*8.0 ); } { blas::copy_n(x.begin(), x.size(), y.begin()); - BOOST_REQUIRE( static_cast(y[0]) == 1.0 + I*8.0 ); + BOOST_TEST( static_cast(y[0]) == 1.0 + I*8.0 ); } { y() = blas::copy(x); - BOOST_REQUIRE( static_cast(y[0]) == 1.0 + I*8.0 ); + BOOST_TEST( static_cast(y[0]) == 1.0 + I*8.0 ); } { multi::array yy = blas::copy(x); - BOOST_REQUIRE( static_cast(yy[0]) == 1.0 + I*8.0 ); + BOOST_TEST( static_cast(yy[0]) == 1.0 + I*8.0 ); } { y = blas::copy(x); - BOOST_REQUIRE( static_cast(y[0]) == 1.0 + I*8.0 ); + BOOST_TEST( static_cast(y[0]) == 1.0 + I*8.0 ); } { { using blas::operators::operator<<; y << x; - // BOOST_REQUIRE(( static_cast(y[0]) == 1.0 + I*8.0 )); // this can't be used with a free operator<< + // BOOST_TEST(( static_cast(y[0]) == 1.0 + I*8.0 )); // this can't be used with a free operator<< } - BOOST_REQUIRE(( static_cast(y[0]) == 1.0 + I*8.0 )); // this can't be used with a free operator<< + BOOST_TEST(( static_cast(y[0]) == 1.0 + I*8.0 )); // this can't be used with a free operator<< } } #if 1 BOOST_AUTO_TEST_CASE(cublas_swap_complex) { namespace blas = multi::blas; - complex const I{0.0, 1.0}; + complex const I{ 0.0, 1.0 }; - using T = complex; - using Alloc = thrust::cuda::allocator; + using T = complex; + using Alloc = thrust::cuda::allocator; - multi::array x = { 1.0 + I*8.0, 2.0 + I*6.0, 3.0 + I*5.0, 4.0 + I*3.0}; - multi::array y = { 1.0 + I*9.0, 2.0 + I*6.0, 3.0 + I*5.0, 4.0 + I*3.0}; + multi::array x = { 1.0 + I * 8.0, 2.0 + I * 6.0, 3.0 + I * 5.0, 4.0 + I * 3.0 }; + multi::array y = { 1.0 + I * 9.0, 2.0 + I * 6.0, 3.0 + I * 5.0, 4.0 + I * 3.0 }; blas::swap(x, y); - BOOST_REQUIRE( static_cast(x[0]) == 1.0 + I*9.0 ); + BOOST_TEST( static_cast(x[0]) == 1.0 + I*9.0 ); { thrust::swap_ranges(begin(x), end(x), begin(y)); thrust::swap_ranges(begin(x), end(x), begin(y)); - BOOST_REQUIRE( static_cast(x[0]) == 1.0 + I*9.0 ); + BOOST_TEST( static_cast(x[0]) == 1.0 + I*9.0 ); } { using blas::operator^; - (x^y); - (x^y); - BOOST_REQUIRE( static_cast(x[0]) == 1.0 + I*9.0 ); + (x ^ y); + (x ^ y); + BOOST_TEST( static_cast(x[0]) == 1.0 + I*9.0 ); } } BOOST_AUTO_TEST_CASE(cublas_asum_complex_column) { namespace blas = multi::blas; - complex const I{0.0, 1.0}; + complex const I{ 0.0, 1.0 }; - using T = complex; + using T = complex; using Alloc = thrust::cuda::allocator; - multi::array const x = { 1.0 + I*8.0, 2.0 + I*6.0, 3.0 + I*5.0, 4.0 + I*3.0}; + multi::array const x = { 1.0 + I * 8.0, 2.0 + I * 6.0, 3.0 + I * 5.0, 4.0 + I * 3.0 }; double res; blas::asum_n(x.begin(), x.size(), &res); { double res2; res2 = blas::asum(x); - BOOST_REQUIRE( res == res2 ); + BOOST_TEST( res == res2 ); } { double res2 = blas::asum(x); - BOOST_REQUIRE( res == res2 ); + BOOST_TEST( res == res2 ); } { auto res2 = std::transform_reduce( - x.begin(), x.end(), double{}, std::plus<>{}, [](T const& e) {return std::abs(e.real()) + std::abs(e.imag());} + x.begin(), x.end(), double{}, std::plus<>{}, [](T const& e) { return std::abs(e.real()) + std::abs(e.imag()); } ); - BOOST_REQUIRE( res == res2 ); + BOOST_TEST( res == res2 ); } { auto res2 = thrust::transform_reduce( - x.begin(), x.end(), [] __device__ (T const& e) {return std::abs(e.real()) + std::abs(e.imag());}, + x.begin(), x.end(), + [] __host__ __device__(T const& e) { return std::abs(e.real()) + std::abs(e.imag()); }, double{}, thrust::plus<>{} ); - BOOST_REQUIRE( res == res2 ); + BOOST_TEST( res == res2 ); } { multi::static_array> res2({}, 0.0); - res2.assign( &blas::asum(x) ); + res2.assign(&blas::asum(x)); res2 = blas::asum(x); - BOOST_REQUIRE(( res == static_cast>::element_ref>(res2) )); - BOOST_REQUIRE(( res == static_cast(res2) )); - // BOOST_REQUIRE( res == res2 ); + BOOST_TEST(( res == static_cast>::element_ref>(res2) )); + BOOST_TEST(( res == static_cast(res2) )); + // BOOST_TEST( res == res2 ); } { multi::array> res2 = blas::asum(x); - BOOST_REQUIRE(( res == static_cast>::element_ref>(res2) )); - BOOST_REQUIRE(( res == static_cast(res2) )); - // BOOST_REQUIRE( res == res2 ); + BOOST_TEST(( res == static_cast>::element_ref>(res2) )); + BOOST_TEST(( res == static_cast(res2) )); + // BOOST_TEST( res == res2 ); } { using blas::operators::operator==; using blas::operators::operator!=; - BOOST_REQUIRE( x != 0 ); - BOOST_REQUIRE( not (x == 0) ); + BOOST_TEST( x != 0 ); + BOOST_TEST( not (x == 0) ); } { using blas::operators::contains_nan; - BOOST_REQUIRE( not contains_nan(x) ); + BOOST_TEST( not contains_nan(x) ); } { using blas::operators::isfinite; using blas::operators::isinf; - BOOST_REQUIRE( isfinite(x) ); - BOOST_REQUIRE( not isinf(x) ); + BOOST_TEST( isfinite(x) ); + BOOST_TEST( not isinf(x) ); } } BOOST_AUTO_TEST_CASE(cublas_asum_complex_nans) { namespace blas = multi::blas; - complex const I{0.0, 1.0}; + complex const I{ 0.0, 1.0 }; - using T = complex; + using T = complex; using Alloc = thrust::cuda::allocator; - multi::array const x = { 1.0 + I*8.0, std::numeric_limits::quiet_NaN() + I*6.0, 3.0 + I*5.0, 4.0 + I*3.0}; + multi::array const x = { 1.0 + I * 8.0, std::numeric_limits::quiet_NaN() + I * 6.0, 3.0 + I * 5.0, 4.0 + I * 3.0 }; { using blas::operators::contains_nan; - BOOST_REQUIRE( contains_nan(x) ); + BOOST_TEST( contains_nan(x) ); } { using blas::operators::operator==; using blas::operators::operator!=; - BOOST_REQUIRE( not (x != 0) ); - BOOST_REQUIRE( not (x == 0) ); + BOOST_TEST( not (x != 0) ); + BOOST_TEST( not (x == 0) ); } { using blas::operators::isfinite; using blas::operators::isinf; - BOOST_REQUIRE( not isfinite(x) ); - BOOST_REQUIRE( not isinf(x) ); + BOOST_TEST( not isfinite(x) ); + BOOST_TEST( not isinf(x) ); } } BOOST_AUTO_TEST_CASE(cublas_asum_complex_inf) { namespace blas = multi::blas; - complex const I{0.0, 1.0}; + complex const I{ 0.0, 1.0 }; - using T = complex; + using T = complex; using Alloc = thrust::cuda::allocator; - multi::array const x = { 1.0 + I*8.0, std::numeric_limits::infinity() + I*6.0, 3.0 + I*5.0, 4.0 + I*3.0}; + multi::array const x = { 1.0 + I * 8.0, std::numeric_limits::infinity() + I * 6.0, 3.0 + I * 5.0, 4.0 + I * 3.0 }; // double res; { using blas::operators::contains_nan; - BOOST_REQUIRE( not contains_nan(x) ); + BOOST_TEST( not contains_nan(x) ); } { using blas::operators::operator==; using blas::operators::operator!=; - BOOST_REQUIRE( (x != 0) ); - BOOST_REQUIRE( not (x == 0) ); + BOOST_TEST( (x != 0) ); + BOOST_TEST( not (x == 0) ); } { using blas::operators::isfinite; using blas::operators::isinf; - BOOST_REQUIRE( not isfinite(x) ); - BOOST_REQUIRE( isinf(x) ); + BOOST_TEST( not isfinite(x) ); + BOOST_TEST( isinf(x) ); } } BOOST_AUTO_TEST_CASE(cublas_nrm2_complex_column) { namespace blas = multi::blas; - complex const I{0.0, 1.0}; + complex const I{ 0.0, 1.0 }; - using T = complex; - using Alloc = thrust::cuda::allocator; + using T = complex; + using Alloc = thrust::cuda::allocator; - multi::array const x = { 1.0 + I*8.0, 2.0 + I*6.0, 3.0 + I*5.0, 4.0 + I*3.0}; + multi::array const x = { 1.0 + I * 8.0, 2.0 + I * 6.0, 3.0 + I * 5.0, 4.0 + I * 3.0 }; double res; blas::nrm2(x, res); { double res2; res2 = blas::nrm2(x); - BOOST_REQUIRE( res == res2 ); + BOOST_TEST( res == res2 ); } { auto res2 = +blas::nrm2(x); - BOOST_REQUIRE( res == res2 ); + BOOST_TEST( res == res2 ); } { auto res2 = sqrt(thrust::transform_reduce( - x.begin(), x.end(), [] __device__ (T const& e) {return thrust::norm(e);}, + x.begin(), x.end(), + [] __host__ __device__(T const& e) { return thrust::norm(e); }, double{}, thrust::plus<>{} )); - BOOST_REQUIRE( res == res2 ); + BOOST_TEST( res == res2 ); } { multi::array> res2 = blas::nrm2(x); - BOOST_REQUIRE(( res == static_cast(res2) )); + BOOST_TEST(( res == static_cast(res2) )); } } BOOST_AUTO_TEST_CASE(cublas_dot_complex_column) { namespace blas = multi::blas; - complex const I{0.0, 1.0}; + complex const I{ 0.0, 1.0 }; - using T = complex; - using Alloc = thrust::cuda::allocator; + using T = complex; + using Alloc = thrust::cuda::allocator; - multi::array const x = { 1.0 + I*8.0, 2.0 + I*6.0, 3.0 + I*5.0, 4.0 + I*3.0}; - multi::array const y = { 1.0 + I*2.0, 2.0 + I*3.0, 3.0 + I*5.0, 4.0 + I*7.0}; + multi::array const x = { 1.0 + I * 8.0, 2.0 + I * 6.0, 3.0 + I * 5.0, 4.0 + I * 3.0 }; + multi::array const y = { 1.0 + I * 2.0, 2.0 + I * 3.0, 3.0 + I * 5.0, 4.0 + I * 7.0 }; { T res; @@ -324,111 +333,111 @@ BOOST_AUTO_TEST_CASE(cublas_dot_complex_column) { { complex res2; res2 = blas::dot(x, y); - BOOST_REQUIRE(res == res2); + BOOST_TEST(res == res2); } { - multi::array res2(complex{1.0, 0.0}); + multi::array res2(complex{ 1.0, 0.0 }); res2 = blas::dot(x, y); - BOOST_REQUIRE( static_cast(res2) == res ); + BOOST_TEST( static_cast(res2) == res ); } { - using blas::operators::operator,; + using blas::operators::operator, ; auto res2 = +(x, y); - BOOST_REQUIRE(res == res2); + BOOST_TEST(res == res2); } { auto res2 = +blas::dot(x, y); - BOOST_REQUIRE(res == res2); + BOOST_TEST(res == res2); } { - // auto [x2, A2, B2] = generate_ABx >(); - // thrust::for_each(x2.begin(), x2.end(), [s] __device__ (T& e) {return e*=s;}); + // auto [x2, A2, B2] = generate_ABx >(); + // thrust::for_each(x2.begin(), x2.end(), [s] __device__ (T& e) {return e*=s;}); auto res2 = thrust::inner_product(x.begin(), x.end(), y.begin(), T{}); - BOOST_REQUIRE(res == res2); + BOOST_TEST(res == res2); } } { T res; blas::dot(blas::C(x), y, res); { - using blas::operators::operator,; + using blas::operators::operator, ; using blas::operators::operator*; auto res2 = +(*x, y); - BOOST_REQUIRE(res == res2); + BOOST_TEST(res == res2); } { auto res2 = +blas::dot(blas::C(x), y); - BOOST_REQUIRE(res == res2); + BOOST_TEST(res == res2); } { - // auto [x2, A2, B2] = generate_ABx >(); - // thrust::for_each(x2.begin(), x2.end(), [s] __device__ (T& e) {return e*=s;}); - auto res2 = thrust::inner_product(x.begin(), x.end(), y.begin(), T{}, thrust::plus<>{}, [] __device__ (T const& t1, T const& t2) {return conj(t1)*t2;}); - BOOST_REQUIRE(res == res2); + // auto [x2, A2, B2] = generate_ABx >(); + // thrust::for_each(x2.begin(), x2.end(), [s] __device__ (T& e) {return e*=s;}); + auto res2 = thrust::inner_product(x.begin(), x.end(), y.begin(), T{}, thrust::plus<>{}, [] __device__(T const& t1, T const& t2) { return conj(t1) * t2; }); + BOOST_TEST(res == res2); } } { T res; blas::dot(x, blas::C(y), res); { - using blas::operators::operator,; + using blas::operators::operator, ; auto res2 = +(x, blas::C(y)); - BOOST_REQUIRE(res == res2); + BOOST_TEST(res == res2); } { auto res2 = +blas::dot(x, blas::C(y)); - BOOST_REQUIRE(res == res2); + BOOST_TEST(res == res2); } { - // auto [x2, A2, B2] = generate_ABx >(); - // thrust::for_each(x2.begin(), x2.end(), [s] __device__ (T& e) {return e*=s;}); - auto res2 = thrust::inner_product(x.begin(), x.end(), y.begin(), T{}, thrust::plus<>{}, [] __device__ (T const& t1, T const& t2) {return t1*conj(t2);}); - BOOST_REQUIRE(res == res2); + // auto [x2, A2, B2] = generate_ABx >(); + // thrust::for_each(x2.begin(), x2.end(), [s] __device__ (T& e) {return e*=s;}); + auto res2 = thrust::inner_product(x.begin(), x.end(), y.begin(), T{}, thrust::plus<>{}, [] __device__(T const& t1, T const& t2) { return t1 * conj(t2); }); + BOOST_TEST(res == res2); } { - BOOST_REQUIRE( blas::dot(blas::C(x), x) == pow(blas::nrm2(x), 2.0) ); - BOOST_REQUIRE( blas::dot(x, blas::C(x)) == pow(blas::nrm2(x), 2.0) ); + BOOST_TEST( blas::dot(blas::C(x), x) == pow(blas::nrm2(x), 2.0) ); + BOOST_TEST( blas::dot(x, blas::C(x)) == pow(blas::nrm2(x), 2.0) ); - using blas::operators::operator,; + using blas::operators::operator, ; using blas::operators::operator*; using blas::operators::abs; using blas::operators::norm; using blas::operators::operator^; - BOOST_REQUIRE( (*x, x) == pow(abs(x), 2.0) ); - BOOST_REQUIRE( (*x, x) == pow(abs(x), 2) ); - BOOST_REQUIRE( (*x, x) == norm(x) ); + BOOST_TEST( (*x, x) == pow(abs(x), 2.0) ); + BOOST_TEST( (*x, x) == pow(abs(x), 2) ); + BOOST_TEST( (*x, x) == norm(x) ); - BOOST_REQUIRE( (x, *x) == pow(abs(x), 2.0) ); - BOOST_REQUIRE( (x, *x) == pow(abs(x), 2) ); - BOOST_REQUIRE( (x, *x) == norm(x) ); + BOOST_TEST( (x, *x) == pow(abs(x), 2.0) ); + BOOST_TEST( (x, *x) == pow(abs(x), 2) ); + BOOST_TEST( (x, *x) == norm(x) ); - BOOST_REQUIRE( (*x, x) == (x^2) ); + BOOST_TEST( (*x, x) == (x^2) ); } } { // T res; // blas::dot(blas::C(x), blas::C(y), res); - multi::array res({1, 1}, 0.0); - auto rr = blas::gemm( 1.0, x.partitioned(1), blas::H(y.partitioned(1)), 0.0, res)[0][0]; + multi::array res({ 1, 1 }, 0.0); + auto rr = blas::gemm(1.0, x.partitioned(1), blas::H(y.partitioned(1)), 0.0, res)[0][0]; // { // using blas::operators::operator,; // auto res2 = +(x, blas::C(y)); - // BOOST_REQUIRE(res == res2); + // BOOST_TEST(res == res2); // } // { // auto res2 = +blas::dot(x, blas::C(y)); - // BOOST_REQUIRE(res == res2); + // BOOST_TEST(res == res2); // } // { // // auto [x2, A2, B2] = generate_ABx >(); // // thrust::for_each(x2.begin(), x2.end(), [s] __device__ (T& e) {return e*=s;}); // auto res2 = thrust::inner_product(x.begin(), x.end(), y.begin(), T{}, thrust::plus<>{}, [] __device__ (T const& t1, T const& t2) {return t1*conj(t2);}); - // BOOST_REQUIRE(res == res2); + // BOOST_TEST(res == res2); // } // { - // BOOST_REQUIRE( blas::dot(blas::C(x), x) == pow(blas::nrm2(x), 2.0) ); - // BOOST_REQUIRE( blas::dot(x, blas::C(x)) == pow(blas::nrm2(x), 2.0) ); + // BOOST_TEST( blas::dot(blas::C(x), x) == pow(blas::nrm2(x), 2.0) ); + // BOOST_TEST( blas::dot(x, blas::C(x)) == pow(blas::nrm2(x), 2.0) ); // using blas::operators::operator,; // using blas::operators::operator*; @@ -436,280 +445,387 @@ BOOST_AUTO_TEST_CASE(cublas_dot_complex_column) { // using blas::operators::norm; // using blas::operators::operator^; - // BOOST_REQUIRE( (*x, x) == pow(abs(x), 2.0) ); - // BOOST_REQUIRE( (*x, x) == pow(abs(x), 2) ); - // BOOST_REQUIRE( (*x, x) == norm(x) ); + // BOOST_TEST( (*x, x) == pow(abs(x), 2.0) ); + // BOOST_TEST( (*x, x) == pow(abs(x), 2) ); + // BOOST_TEST( (*x, x) == norm(x) ); - // BOOST_REQUIRE( (x, *x) == pow(abs(x), 2.0) ); - // BOOST_REQUIRE( (x, *x) == pow(abs(x), 2) ); - // BOOST_REQUIRE( (x, *x) == norm(x) ); + // BOOST_TEST( (x, *x) == pow(abs(x), 2.0) ); + // BOOST_TEST( (x, *x) == pow(abs(x), 2) ); + // BOOST_TEST( (x, *x) == norm(x) ); - // BOOST_REQUIRE( (*x, x) == (x^2) ); + // BOOST_TEST( (*x, x) == (x^2) ); // } } } BOOST_AUTO_TEST_CASE(cublas_axpy_complex_one) { namespace blas = multi::blas; - complex const I{0.0, 1.0}; + complex const I{ 0.0, 1.0 }; - using T = complex; - using Alloc = thrust::cuda::allocator; + using T = complex; + using Alloc = thrust::cuda::allocator; - multi::array const x = { {1.1, 0.0}, {2.1, 0.0}, {3.1, 0.0}, {4.1, 0.0} }; // NOLINT(readability-identifier-length) BLAS naming - multi::array y = { {2.1, 0.0}, {4.1, 0.0}, {6.1, 0.0}, {11.0, 0.0} }; // NOLINT(readability-identifier-length) BLAS naming + multi::array const x = { + {1.1, 0.0}, + {2.1, 0.0}, + {3.1, 0.0}, + {4.1, 0.0} + }; // NOLINT(readability-identifier-length) BLAS naming + multi::array y = { + { 2.1, 0.0}, + { 4.1, 0.0}, + { 6.1, 0.0}, + {11.0, 0.0} + }; // NOLINT(readability-identifier-length) BLAS naming blas::axpy(1.0, x, y); std::cout << y[0] << std::endl; - BOOST_REQUIRE( static_cast(y[0]) == 3.2 + I*0.0 ); + BOOST_TEST( static_cast(y[0]) == 3.2 + I*0.0 ); { - multi::array yy = { {2.1, 0.0}, {4.1, 0.0}, {6.1, 0.0}, {11.0, 0.0} }; // NOLINT(readability-identifier-length) BLAS naming - thrust::transform(x.begin(), x.end(), yy.begin(), yy.begin(), [] __device__ (auto const& ex, auto const& ey) {return ex + ey;}); - BOOST_TEST( yy == y , boost::test_tools::per_element() ); + multi::array yy = { + { 2.1, 0.0}, + { 4.1, 0.0}, + { 6.1, 0.0}, + {11.0, 0.0} + }; + + thrust::transform(x.begin(), x.end(), yy.begin(), yy.begin(), [] __device__(auto const& ex, auto const& ey) { return ex + ey; }); + BOOST_TEST( yy == y ); // , boost::test_tools::per_element() ); } { - multi::array yy = { {2.1, 0.0}, {4.1, 0.0}, {6.1, 0.0}, {11.0, 0.0} }; + multi::array yy = { + { 2.1, 0.0}, + { 4.1, 0.0}, + { 6.1, 0.0}, + {11.0, 0.0} + }; using blas::operators::operator+=; yy += x; - BOOST_REQUIRE( yy == y ); + BOOST_TEST( yy == y ); } } BOOST_AUTO_TEST_CASE(cublas_axpy_complex_mone) { namespace blas = multi::blas; - complex const I{0.0, 1.0}; + complex const I{ 0.0, 1.0 }; - using T = complex; - using Alloc = thrust::cuda::allocator; + using T = complex; + using Alloc = thrust::cuda::allocator; - multi::array const x = { {1.1, 0.0}, {2.1, 0.0}, {3.1, 0.0}, {4.1, 0.0} }; // NOLINT(readability-identifier-length) BLAS naming - multi::array y = { {2.1, 0.0}, {4.1, 0.0}, {6.1, 0.0}, {11.0, 0.0} }; // NOLINT(readability-identifier-length) BLAS naming + multi::array const x = { + {1.1, 0.0}, + {2.1, 0.0}, + {3.1, 0.0}, + {4.1, 0.0} + }; // NOLINT(readability-identifier-length) BLAS naming + multi::array y = { + { 2.1, 0.0}, + { 4.1, 0.0}, + { 6.1, 0.0}, + {11.0, 0.0} + }; // NOLINT(readability-identifier-length) BLAS naming blas::axpy(-1.0, x, y); std::cout << y[0] << std::endl; - BOOST_REQUIRE( static_cast(y[0]) == 1.0 + I*0.0 ); - { - multi::array yy = { {2.1, 0.0}, {4.1, 0.0}, {6.1, 0.0}, {11.0, 0.0} }; // NOLINT(readability-identifier-length) BLAS naming - thrust::transform(x.begin(), x.end(), yy.begin(), yy.begin(), [] __host__ __device__ (T ex, T ey) {return -1.0*ex + ey;}); - BOOST_TEST( yy == y , boost::test_tools::per_element() ); - } - { - multi::array yy = { {2.1, 0.0}, {4.1, 0.0}, {6.1, 0.0}, {11.0, 0.0} }; + BOOST_TEST( static_cast(y[0]) == 1.0 + I*0.0 ); + { + multi::array yy = { + { 2.1, 0.0}, + { 4.1, 0.0}, + { 6.1, 0.0}, + {11.0, 0.0} + }; // NOLINT(readability-identifier-length) BLAS naming + thrust::transform(x.begin(), x.end(), yy.begin(), yy.begin(), [] __host__ __device__(T ex, T ey) { return -1.0 * ex + ey; }); + BOOST_TEST( yy == y ); // boost::test_tools::per_element() ); + } + { + multi::array yy = { + { 2.1, 0.0}, + { 4.1, 0.0}, + { 6.1, 0.0}, + {11.0, 0.0} + }; using blas::operators::operator-=; yy -= x; - BOOST_REQUIRE( yy == y ); + BOOST_TEST( yy == y ); } { - multi::array yy = { {2.1, 0.0}, {4.1, 0.0}, {6.1, 0.0}, {11.0, 0.0} }; + multi::array yy = { + { 2.1, 0.0}, + { 4.1, 0.0}, + { 6.1, 0.0}, + {11.0, 0.0} + }; using blas::operators::operator-=; yy -= x; yy -= y; using blas::operators::norm; - BOOST_REQUIRE( norm(yy) == 0 ); + BOOST_TEST( norm(yy) == 0 ); using blas::operators::operator==; - BOOST_REQUIRE( operator==(yy, 0) ); - BOOST_REQUIRE( yy == 0 ); + BOOST_TEST( operator==(yy, 0) ); + BOOST_TEST( yy == 0 ); } } BOOST_AUTO_TEST_CASE(cublas_axpy_complex_alpha) { namespace blas = multi::blas; - complex const I{0.0, 1.0}; + complex const I{ 0.0, 1.0 }; - using T = complex; - using Alloc = thrust::cuda::allocator; + using T = complex; + using Alloc = thrust::cuda::allocator; - multi::array const x = { {1.1, 0.0}, {2.1, 0.0}, {3.1, 0.0}, {4.1, 0.0} }; // NOLINT(readability-identifier-length) BLAS naming - multi::array y = { {2.1, 0.0}, {4.1, 0.0}, {6.1, 0.0}, {11.0, 0.0} }; // NOLINT(readability-identifier-length) BLAS naming + multi::array const x = { + {1.1, 0.0}, + {2.1, 0.0}, + {3.1, 0.0}, + {4.1, 0.0} + }; // NOLINT(readability-identifier-length) BLAS naming + multi::array y = { + { 2.1, 0.0}, + { 4.1, 0.0}, + { 6.1, 0.0}, + {11.0, 0.0} + }; // NOLINT(readability-identifier-length) BLAS naming blas::axpy(3.0, x, y); std::cout << y[0] << std::endl; - BOOST_REQUIRE( static_cast(y[0]) == 5.4 + I*0.0 ); - { - multi::array yy = { {2.1, 0.0}, {4.1, 0.0}, {6.1, 0.0}, {11.0, 0.0} }; // NOLINT(readability-identifier-length) BLAS naming - thrust::transform(x.begin(), x.end(), yy.begin(), yy.begin(), [aa=3.0] __device__ (T ex, T ey) {return aa*ex + ey;}); - BOOST_TEST( yy == y , boost::test_tools::per_element() ); - } + BOOST_TEST( static_cast(y[0]) == 5.4 + I*0.0 ); + // { + // multi::array yy = { + // { 2.1, 0.0}, + // { 4.1, 0.0}, + // { 6.1, 0.0}, + // {11.0, 0.0} + // }; // NOLINT(readability-identifier-length) BLAS naming + // thrust::transform(x.begin(), x.end(), yy.begin(), yy.begin(), [aa = 3.0] __device__(T ex, T ey) { return aa * ex + ey; }); + // BOOST_TEST( yy == y , boost::test_tools::per_element() ); + // } { - multi::array yy = { {2.1, 0.0}, {4.1, 0.0}, {6.1, 0.0}, {11.0, 0.0} }; + multi::array yy = { + { 2.1, 0.0}, + { 4.1, 0.0}, + { 6.1, 0.0}, + {11.0, 0.0} + }; using blas::operators::operator+=; using blas::operators::operator*; - yy += 3.0*x; - BOOST_REQUIRE( yy == y ); + yy += 3.0 * x; + BOOST_TEST( yy == y ); } } BOOST_AUTO_TEST_CASE(cublas_one_gemv_conj_complex_zero) { namespace blas = multi::blas; - using T = complex; - complex const I{0.0, 1.0}; - using Alloc = thrust::cuda::allocator; + using T = complex; + complex const I{ 0.0, 1.0 }; + using Alloc = thrust::cuda::allocator; // NOLINT(readability-identifier-length) BLAS naming multi::array const A = { - { { 9.0, 0.0}, {24.0, 0.0}, {30.0, 0.0}, {9.0, 0.0} }, - { { 4.0, 0.0}, {10.0, 0.0}, {12.0, 0.0}, {7.0, 0.0} }, - { {14.0, 0.0}, {16.0, 0.0}, {36.0, 0.0}, {1.0, 0.0} }, + { { 9.0, 0.0 }, { 24.0, 0.0 }, { 30.0, 0.0 }, { 9.0, 0.0 }}, + { { 4.0, 0.0 }, { 10.0, 0.0 }, { 12.0, 0.0 }, { 7.0, 0.0 }}, + {{ 14.0, 0.0 }, { 16.0, 0.0 }, { 36.0, 0.0 }, { 1.0, 0.0 }}, }; - multi::array const x = { {1.1, 0.0}, {2.1, 0.0}, {3.1, 0.0}, {4.1, 0.0} }; // NOLINT(readability-identifier-length) BLAS naming - multi::array y = { {1.1, 0.0}, {2.1, 0.0}, {3.1, 0.0} }; // NOLINT(readability-identifier-length) BLAS naming + multi::array const x = { + {1.1, 0.0}, + {2.1, 0.0}, + {3.1, 0.0}, + {4.1, 0.0} + }; // NOLINT(readability-identifier-length) BLAS naming + multi::array y = { + {1.1, 0.0}, + {2.1, 0.0}, + {3.1, 0.0} + }; // NOLINT(readability-identifier-length) BLAS naming blas::gemv(1.0, A, x, 0.0, y); { - multi::array yy = { {1.1, 0.0}, {2.1, 0.0}, {3.1, 0.0} }; // NOLINT(readability-identifier-length) BLAS naming - std::transform(begin(A), end(A), begin(yy), [&x] (auto const& Ac) {return blas::dot(Ac, x);}); + multi::array yy = { + {1.1, 0.0}, + {2.1, 0.0}, + {3.1, 0.0} + }; // NOLINT(readability-identifier-length) BLAS naming + std::transform(begin(A), end(A), begin(yy), [&x](auto const& Ac) { return blas::dot(Ac, x); }); - BOOST_REQUIRE( static_cast(y[0]) == static_cast(yy[0]) ); - BOOST_REQUIRE( static_cast(y[1]) == static_cast(yy[1]) ); - BOOST_REQUIRE( static_cast(y[2]) == static_cast(yy[2]) ); + BOOST_TEST( std::abs(static_cast(y[0]).real() - static_cast(yy[0]).real()) < 1e-10 ); + BOOST_TEST( std::abs(static_cast(y[1]).imag() - static_cast(yy[1]).imag()) < 1e-10 ); + BOOST_TEST( std::abs(static_cast(y[2]).real() - static_cast(yy[2]).real()) < 1e-10 ); } { - multi::array yy = { {1.1, 0.0}, {2.1, 0.0}, {3.1, 0.0} }; // NOLINT(readability-identifier-length) BLAS naming + multi::array yy = { + {1.1, 0.0}, + {2.1, 0.0}, + {3.1, 0.0} + }; // NOLINT(readability-identifier-length) BLAS naming yy = blas::gemv(1.0, A, x); - BOOST_REQUIRE( static_cast(y[0]) == static_cast(yy[0]) ); - BOOST_REQUIRE( static_cast(y[1]) == static_cast(yy[1]) ); - BOOST_REQUIRE( static_cast(y[2]) == static_cast(yy[2]) ); + BOOST_TEST( static_cast(y[0]) == static_cast(yy[0]) ); + BOOST_TEST( static_cast(y[1]) == static_cast(yy[1]) ); + BOOST_TEST( static_cast(y[2]) == static_cast(yy[2]) ); } { multi::array yy = blas::gemv(1.0, A, x); - BOOST_REQUIRE( static_cast(y[0]) == static_cast(yy[0]) ); - BOOST_REQUIRE( static_cast(y[1]) == static_cast(yy[1]) ); - BOOST_REQUIRE( static_cast(y[2]) == static_cast(yy[2]) ); - + BOOST_TEST( static_cast(y[0]) == static_cast(yy[0]) ); + BOOST_TEST( static_cast(y[1]) == static_cast(yy[1]) ); + BOOST_TEST( static_cast(y[2]) == static_cast(yy[2]) ); } { using blas::operators::operator%; - multi::array yy = { {1.1, 0.0}, {2.1, 0.0}, {3.1, 0.0} }; // NOLINT(readability-identifier-length) BLAS naming + multi::array yy = { + {1.1, 0.0}, + {2.1, 0.0}, + {3.1, 0.0} + }; // NOLINT(readability-identifier-length) BLAS naming yy = A % x; - BOOST_REQUIRE( static_cast(y[0]) == static_cast(yy[0]) ); - BOOST_REQUIRE( static_cast(y[1]) == static_cast(yy[1]) ); - BOOST_REQUIRE( static_cast(y[2]) == static_cast(yy[2]) ); + BOOST_TEST( static_cast(y[0]) == static_cast(yy[0]) ); + BOOST_TEST( static_cast(y[1]) == static_cast(yy[1]) ); + BOOST_TEST( static_cast(y[2]) == static_cast(yy[2]) ); } } BOOST_AUTO_TEST_CASE(cublas_one_gemv_complex_conj_zero) { namespace blas = multi::blas; - using T = complex; - using Alloc = thrust::cuda::allocator; - complex const I{0.0, 1.0}; + using T = complex; + using Alloc = thrust::cuda::allocator; + complex const I{ 0.0, 1.0 }; // NOLINT(readability-identifier-length) BLAS naming multi::array const A = { - { 9.0 + I*0.0, 24.0 + I* 0.0, 30.0 + I* 0.0, 9.0 + I* 0.0 }, - { 4.0 + I*0.0, 10.0 + I* 0.0, 12.0 + I* 0.0, 7.0 + I* 0.0 }, - { 14.0 + I*0.0, 16.0 + I* 0.0, 36.0 + I* 0.0, 1.0 + I* 0.0 }, + { 9.0 + I * 0.0, 24.0 + I * 0.0, 30.0 + I * 0.0, 9.0 + I * 0.0}, + { 4.0 + I * 0.0, 10.0 + I * 0.0, 12.0 + I * 0.0, 7.0 + I * 0.0}, + {14.0 + I * 0.0, 16.0 + I * 0.0, 36.0 + I * 0.0, 1.0 + I * 0.0}, }; - multi::array const x = { 1.1 + I* 0.0, 2.1 + I* 0.0, 3.1 + I* 0.0}; // NOLINT(readability-identifier-length) BLAS naming - multi::array y = { 1.1 + I* 0.0, 2.1 +I* 0.0, 3.1 + I* 0.0, 6.7 + I*0.0 }; // NOLINT(readability-identifier-length) BLAS naming + multi::array const x = { 1.1 + I * 0.0, 2.1 + I * 0.0, 3.1 + I * 0.0 }; // NOLINT(readability-identifier-length) BLAS naming + multi::array y = { 1.1 + I * 0.0, 2.1 + I * 0.0, 3.1 + I * 0.0, 6.7 + I * 0.0 }; // NOLINT(readability-identifier-length) BLAS naming blas::gemv(1.0, blas::T(A), x, 0.0, y); { - multi::array yy = { 1.1 + I* 0.0, 2.1 +I* 0.0, 3.1 + I* 0.0, 6.7 + I*0.0 }; // NOLINT(readability-identifier-length) BLAS naming + multi::array yy = { 1.1 + I * 0.0, 2.1 + I * 0.0, 3.1 + I * 0.0, 6.7 + I * 0.0 }; // NOLINT(readability-identifier-length) BLAS naming using blas::operators::operator*; - std::transform(begin(transposed(A)), end(transposed(A)), begin(yy), [&x] (auto const& Ac) {return blas::dot(Ac, x);}); + + std::transform(begin(A.transposed()), end(A.transposed()), begin(yy), [&x](auto const& Ac) { return blas::dot(Ac, x); }); - BOOST_REQUIRE_CLOSE( static_cast(y[0]).real(), static_cast(yy[0]).real(), 1e-7 ); - BOOST_REQUIRE( static_cast(y[1]) == static_cast(yy[1]) ); - BOOST_REQUIRE( static_cast(y[2]) == static_cast(yy[2]) ); + BOOST_REQUIRE_CLOSE(static_cast(y[0]).real(), static_cast(yy[0]).real(), 1e-7); + BOOST_TEST( static_cast(y[1]) == static_cast(yy[1]) ); + BOOST_TEST( static_cast(y[2]) == static_cast(yy[2]) ); } { - multi::array yy = { 1.1 + I* 0.0, 2.1 +I* 0.0, 3.1 + I* 0.0, 6.7 + I*0.0 }; // NOLINT(readability-identifier-length) BLAS naming - yy = blas::gemv(1.0, blas::T(A), x); - BOOST_REQUIRE( static_cast(y[0]) == static_cast(yy[0]) ); - BOOST_REQUIRE( static_cast(y[1]) == static_cast(yy[1]) ); - BOOST_REQUIRE( static_cast(y[2]) == static_cast(yy[2]) ); + multi::array yy = { 1.1 + I * 0.0, 2.1 + I * 0.0, 3.1 + I * 0.0, 6.7 + I * 0.0 }; // NOLINT(readability-identifier-length) BLAS naming + yy = blas::gemv(1.0, blas::T(A), x); + BOOST_TEST( static_cast(y[0]) == static_cast(yy[0]) ); + BOOST_TEST( static_cast(y[1]) == static_cast(yy[1]) ); + BOOST_TEST( static_cast(y[2]) == static_cast(yy[2]) ); } { multi::array yy = blas::gemv(1.0, blas::T(A), x); - BOOST_REQUIRE( static_cast(y[0]) == static_cast(yy[0]) ); - BOOST_REQUIRE( static_cast(y[1]) == static_cast(yy[1]) ); - BOOST_REQUIRE( static_cast(y[2]) == static_cast(yy[2]) ); + BOOST_TEST( static_cast(y[0]) == static_cast(yy[0]) ); + BOOST_TEST( static_cast(y[1]) == static_cast(yy[1]) ); + BOOST_TEST( static_cast(y[2]) == static_cast(yy[2]) ); } { using blas::operators::operator%; - multi::array yy = { 1.1 + I* 0.0, 2.1 +I* 0.0, 3.1 + I* 0.0, 6.7 + I*0.0 }; // NOLINT(readability-identifier-length) BLAS naming - yy = ~A % x; - BOOST_REQUIRE( static_cast(y[0]) == static_cast(yy[0]) ); - BOOST_REQUIRE( static_cast(y[1]) == static_cast(yy[1]) ); - BOOST_REQUIRE( static_cast(y[2]) == static_cast(yy[2]) ); + multi::array yy = { 1.1 + I * 0.0, 2.1 + I * 0.0, 3.1 + I * 0.0, 6.7 + I * 0.0 }; // NOLINT(readability-identifier-length) BLAS naming + yy = ~A % x; + BOOST_TEST( static_cast(y[0]) == static_cast(yy[0]) ); + BOOST_TEST( static_cast(y[1]) == static_cast(yy[1]) ); + BOOST_TEST( static_cast(y[2]) == static_cast(yy[2]) ); } } -template void what(T&&) = delete; - BOOST_AUTO_TEST_CASE(cublas_one_gemv_complex_zero) { namespace blas = multi::blas; - using T = complex; - complex const I{0.0, 1.0}; - using Alloc = thrust::cuda::allocator; + using T = complex; + complex const I{ 0.0, 1.0 }; + using Alloc = thrust::cuda::allocator; // NOLINT(readability-identifier-length) BLAS naming multi::array const A = { - { { 9.0, 0.0}, {24.0, 0.0}, {30.0, 0.0}, {9.0, 0.0} }, - { { 4.0, 0.0}, {10.0, 0.0}, {12.0, 0.0}, {7.0, 0.0} }, - { {14.0, 0.0}, {16.0, 0.0}, {36.0, 0.0}, {1.0, 0.0} }, + { { 9.0, 0.0 }, { 24.0, 0.0 }, { 30.0, 0.0 }, { 9.0, 0.0 }}, + { { 4.0, 0.0 }, { 10.0, 0.0 }, { 12.0, 0.0 }, { 7.0, 0.0 }}, + {{ 14.0, 0.0 }, { 16.0, 0.0 }, { 36.0, 0.0 }, { 1.0, 0.0 }}, + }; + multi::array const x = { + {1.1, 0.0}, + {2.1, 0.0}, + {3.1, 0.0}, + {4.1, 0.0} + }; + + // NOLINTNEXTLINE(readability-identifier-length) BLAS naming + multi::array y = { + {1.1, 0.0}, + {2.1, 0.0}, + {3.1, 0.0} }; - multi::array const x = { {1.1, 0.0}, {2.1, 0.0}, {3.1, 0.0}, {4.1, 0.0} }; // NOLINT(readability-identifier-length) BLAS naming - multi::array y = { {1.1, 0.0}, {2.1, 0.0}, {3.1, 0.0} }; // NOLINT(readability-identifier-length) BLAS naming blas::gemv(1.0, blas::J(A), x, 0.0, y); { - multi::array yy = { {1.1, 0.0}, {2.1, 0.0}, {3.1, 0.0} }; // NOLINT(readability-identifier-length) BLAS naming - std::transform(begin(A), end(A), begin(yy), [&x] (auto const& Ac) { + multi::array yy = { + {1.1, 0.0}, + {2.1, 0.0}, + {3.1, 0.0} + }; + std::transform(begin(A), end(A), begin(yy), [&x](auto const& Ac) { using blas::operators::operator*; // nvcc 11.8 needs this to be inside lambda - return blas::dot(*Ac, x);} + return blas::dot(*Ac, x); } ); - BOOST_REQUIRE( static_cast(y[0]) == static_cast(yy[0]) ); - BOOST_REQUIRE( static_cast(y[1]) == static_cast(yy[1]) ); - BOOST_REQUIRE( static_cast(y[2]) == static_cast(yy[2]) ); + BOOST_TEST( abs( static_cast(y[0]) - static_cast(yy[0])) < 1e-7 ); + BOOST_TEST( abs( static_cast(y[1]) - static_cast(yy[1])) < 1e-7 ); + BOOST_TEST( abs( static_cast(y[2]) - static_cast(yy[2])) < 1e-7 ); } { - multi::array yy = { {1.1, 0.0}, {2.1, 0.0}, {3.1, 0.0} }; // NOLINT(readability-identifier-length) BLAS naming + multi::array yy = { + {1.1, 0.0}, + {2.1, 0.0}, + {3.1, 0.0} + }; yy = blas::gemv(1.0, blas::J(A), x); - BOOST_REQUIRE( static_cast(y[0]) == static_cast(yy[0]) ); - BOOST_REQUIRE( static_cast(y[1]) == static_cast(yy[1]) ); - BOOST_REQUIRE( static_cast(y[2]) == static_cast(yy[2]) ); + BOOST_TEST( static_cast(y[0]) == static_cast(yy[0]) ); + BOOST_TEST( static_cast(y[1]) == static_cast(yy[1]) ); + BOOST_TEST( static_cast(y[2]) == static_cast(yy[2]) ); } { multi::array yy = blas::gemv(1.0, blas::J(A), x); - BOOST_REQUIRE( static_cast(y[0]) == static_cast(yy[0]) ); - BOOST_REQUIRE( static_cast(y[1]) == static_cast(yy[1]) ); - BOOST_REQUIRE( static_cast(y[2]) == static_cast(yy[2]) ); - + BOOST_TEST( static_cast(y[0]) == static_cast(yy[0]) ); + BOOST_TEST( static_cast(y[1]) == static_cast(yy[1]) ); + BOOST_TEST( static_cast(y[2]) == static_cast(yy[2]) ); } { using blas::operators::operator%; using blas::operators::operator*; - multi::array yy = { {1.1, 0.0}, {2.1, 0.0}, {3.1, 0.0} }; // NOLINT(readability-identifier-length) BLAS naming + multi::array yy = { + {1.1, 0.0}, + {2.1, 0.0}, + {3.1, 0.0} + }; // NOLINT(readability-identifier-length) BLAS naming yy = *A % x; - BOOST_REQUIRE( static_cast(y[0]) == static_cast(yy[0]) ); - BOOST_REQUIRE( static_cast(y[1]) == static_cast(yy[1]) ); - BOOST_REQUIRE( static_cast(y[2]) == static_cast(yy[2]) ); + BOOST_TEST( static_cast(y[0]) == static_cast(yy[0]) ); + BOOST_TEST( static_cast(y[1]) == static_cast(yy[1]) ); + BOOST_TEST( static_cast(y[2]) == static_cast(yy[2]) ); } } BOOST_AUTO_TEST_CASE(cublas_one_gemv_complex_conjtrans_zero) { namespace blas = multi::blas; - using T = complex; - using Alloc = std::allocator; // thrust::cuda::allocator; - complex const I{0.0, 1.0}; + using T = complex; + using Alloc = std::allocator; // thrust::cuda::allocator; + complex const I{ 0.0, 1.0 }; // NOLINT(readability-identifier-length) BLAS naming multi::array const A = { - { 9.0 + I*0.0, 24.0 + I* 0.0, 30.0 + I* 0.0, 9.0 + I* 0.0 }, - { 4.0 + I*0.0, 10.0 + I* 0.0, 12.0 + I* 0.0, 7.0 + I* 0.0 }, - { 14.0 + I*0.0, 16.0 + I* 0.0, 36.0 + I* 0.0, 1.0 + I* 0.0 }, + { 9.0 + I * 0.0, 24.0 + I * 0.0, 30.0 + I * 0.0, 9.0 + I * 0.0}, + { 4.0 + I * 0.0, 10.0 + I * 0.0, 12.0 + I * 0.0, 7.0 + I * 0.0}, + {14.0 + I * 0.0, 16.0 + I * 0.0, 36.0 + I * 0.0, 1.0 + I * 0.0}, }; - multi::array const x = { 1.1 + I* 0.0, 2.1 + I* 0.0, 3.1 + I* 0.0}; // NOLINT(readability-identifier-length) BLAS naming - multi::array y = { 1.1 + I* 0.0, 2.1 +I* 0.0, 3.1 + I* 0.0, 6.7 + I*0.0 }; // NOLINT(readability-identifier-length) BLAS naming + multi::array const x = { 1.1 + I * 0.0, 2.1 + I * 0.0, 3.1 + I * 0.0 }; // NOLINT(readability-identifier-length) BLAS naming + multi::array y = { 1.1 + I * 0.0, 2.1 + I * 0.0, 3.1 + I * 0.0, 6.7 + I * 0.0 }; // NOLINT(readability-identifier-length) BLAS naming // blas::gemv(1.0, blas::H(A), x, 0.0, y); { - // TODO(correaa) MKL gives an error here - #if 0 + // TODO(correaa) MKL gives an error here + #if 0 multi::array yy = { 1.1 + I* 0.0, 2.1 +I* 0.0, 3.1 + I* 0.0, 6.7 + I*0.0 }; // NOLINT(readability-identifier-length) BLAS naming std::transform(begin(transposed(A)), end(transposed(A)), begin(yy), [&x] (auto const& Ac) { using blas::operators::operator*; // nvcc 11.8 needs this to be inside lambda @@ -724,58 +840,58 @@ BOOST_AUTO_TEST_CASE(cublas_one_gemv_complex_conjtrans_zero) { using blas::operators::operator*; BOOST_REQUIRE_CLOSE( static_cast(yy[0]).real() , (+blas::dot(*(~A)[0], x)).real() , 1.e-7 ); BOOST_REQUIRE_CLOSE( static_cast(yy[1]).real() , (+blas::dot(*(~A)[1], x)).real() , 1.e-7 ); - #endif + #endif } } BOOST_AUTO_TEST_CASE(cublas_one_gemv_complex_trans_one) { namespace blas = multi::blas; - using T = complex; - using Alloc = thrust::cuda::allocator; - complex const I{0.0, 1.0}; + using T = complex; + using Alloc = thrust::cuda::allocator; + complex const I{ 0.0, 1.0 }; // NOLINT(readability-identifier-length) BLAS naming multi::array const A = { - { 9.0 + I*0.0, 24.0 + I* 0.0, 30.0 + I* 0.0, 9.0 + I* 0.0 }, - { 4.0 + I*0.0, 10.0 + I* 0.0, 12.0 + I* 0.0, 7.0 + I* 0.0 }, - { 14.0 + I*0.0, 16.0 + I* 0.0, 36.0 + I* 0.0, 1.0 + I* 0.0 }, + { 9.0 + I * 0.0, 24.0 + I * 0.0, 30.0 + I * 0.0, 9.0 + I * 0.0}, + { 4.0 + I * 0.0, 10.0 + I * 0.0, 12.0 + I * 0.0, 7.0 + I * 0.0}, + {14.0 + I * 0.0, 16.0 + I * 0.0, 36.0 + I * 0.0, 1.0 + I * 0.0}, }; - multi::array const x = { 1.1 + I* 0.0, 2.1 + I* 0.0, 3.1 + I* 0.0}; // NOLINT(readability-identifier-length) BLAS naming - multi::array y = { 1.1 + I* 0.0, 2.1 +I* 0.0, 3.1 + I* 0.0, 6.7 + I*0.0 }; // NOLINT(readability-identifier-length) BLAS naming - blas::gemv(3.0 + I*4.0, blas::T(A), x, 1.0, y); + multi::array const x = { 1.1 + I * 0.0, 2.1 + I * 0.0, 3.1 + I * 0.0 }; // NOLINT(readability-identifier-length) BLAS naming + multi::array y = { 1.1 + I * 0.0, 2.1 + I * 0.0, 3.1 + I * 0.0, 6.7 + I * 0.0 }; // NOLINT(readability-identifier-length) BLAS naming + blas::gemv(3.0 + I * 4.0, blas::T(A), x, 1.0, y); { - multi::array yy = { 1.1 + I* 0.0, 2.1 +I* 0.0, 3.1 + I* 0.0, 6.7 + I*0.0 }; // NOLINT(readability-identifier-length) BLAS naming + multi::array yy = { 1.1 + I * 0.0, 2.1 + I * 0.0, 3.1 + I * 0.0, 6.7 + I * 0.0 }; // NOLINT(readability-identifier-length) BLAS naming // using blas::operators::operator*; - std::transform(begin(transposed(A)), end(transposed(A)), begin(yy), begin(yy), [&x,aa=3.0 + I*4.0,bb=1.0] (auto const& Ac, complex e) {return aa*blas::dot(Ac, x) + bb*e;}); + std::transform(begin(transposed(A)), end(transposed(A)), begin(yy), begin(yy), [&x, aa = 3.0 + I * 4.0, bb = 1.0](auto const& Ac, complex e) { return aa * blas::dot(Ac, x) + bb * e; }); - BOOST_REQUIRE_CLOSE( static_cast(y[0]).real(), static_cast(yy[0]).real(), 1e-7 ); - BOOST_REQUIRE( static_cast(y[1]) == static_cast(yy[1]) ); - BOOST_REQUIRE( static_cast(y[2]) == static_cast(yy[2]) ); + BOOST_REQUIRE_CLOSE(static_cast(y[0]).real(), static_cast(yy[0]).real(), 1e-7); + BOOST_TEST( static_cast(y[1]) == static_cast(yy[1]) ); + BOOST_TEST( static_cast(y[2]) == static_cast(yy[2]) ); } { - multi::array yy = { 1.1 + I* 0.0, 2.1 +I* 0.0, 3.1 + I* 0.0, 6.7 + I*0.0 }; // NOLINT(readability-identifier-length) BLAS naming - yy += blas::gemv(3.0 + I*4.0, blas::T(A), x); + multi::array yy = { 1.1 + I * 0.0, 2.1 + I * 0.0, 3.1 + I * 0.0, 6.7 + I * 0.0 }; // NOLINT(readability-identifier-length) BLAS naming + yy += blas::gemv(3.0 + I * 4.0, blas::T(A), x); - BOOST_REQUIRE_CLOSE( static_cast(y[0]).real(), static_cast(yy[0]).real(), 1e-7 ); - BOOST_REQUIRE( static_cast(y[1]) == static_cast(yy[1]) ); - BOOST_REQUIRE( static_cast(y[2]) == static_cast(yy[2]) ); + BOOST_REQUIRE_CLOSE(static_cast(y[0]).real(), static_cast(yy[0]).real(), 1e-7); + BOOST_TEST( static_cast(y[1]) == static_cast(yy[1]) ); + BOOST_TEST( static_cast(y[2]) == static_cast(yy[2]) ); } { - multi::array yy = { 1.1 + I* 0.0, 2.1 +I* 0.0, 3.1 + I* 0.0, 6.7 + I*0.0 }; // NOLINT(readability-identifier-length) BLAS naming + multi::array yy = { 1.1 + I * 0.0, 2.1 + I * 0.0, 3.1 + I * 0.0, 6.7 + I * 0.0 }; // NOLINT(readability-identifier-length) BLAS naming using blas::operators::operator*; - yy += (3.0 + I*4.0)* ~A % x; + yy += (3.0 + I * 4.0) * ~A % x; - BOOST_REQUIRE_CLOSE( static_cast(y[0]).real(), static_cast(yy[0]).real(), 1e-7 ); - BOOST_REQUIRE( static_cast(y[1]) == static_cast(yy[1]) ); - BOOST_REQUIRE( static_cast(y[2]) == static_cast(yy[2]) ); + BOOST_REQUIRE_CLOSE(static_cast(y[0]).real(), static_cast(yy[0]).real(), 1e-7); + BOOST_TEST( static_cast(y[1]) == static_cast(yy[1]) ); + BOOST_TEST( static_cast(y[2]) == static_cast(yy[2]) ); } } BOOST_AUTO_TEST_CASE(cublas_one_gemm_complex_trans_none) { namespace blas = multi::blas; - using T = complex; - using Alloc = thrust::cuda::allocator; - complex const I{0.0, 1.0}; + using T = complex; + using Alloc = thrust::cuda::allocator; + complex const I{ 0.0, 1.0 }; // NOLINT(readability-identifier-length) BLAS naming multi::array const A = { @@ -787,70 +903,68 @@ BOOST_AUTO_TEST_CASE(cublas_one_gemm_complex_trans_none) { {1.0 + 5.0 * I, 8.0 - 8.0 * I}, }; { - multi::array C({2, 2}, {3.0, 0.0}); // NOLINT(readability-identifier-length) conventional BLAS naming - auto C_copy = C; - blas::gemm({1.0, 0.0}, A, B, {0.0, 0.0}, C); + multi::array C({ 2, 2 }, { 3.0, 0.0 }); // NOLINT(readability-identifier-length) conventional BLAS naming + auto C_copy = C; + blas::gemm({ 1.0, 0.0 }, A, B, { 0.0, 0.0 }, C); // std::transform(begin(transposed(B)), end(transposed(B)), begin(transposed(C_copy)), begin(transposed(C_copy)), // [&A, aa=1.0, bb=0.0] (auto const& Bc, auto&& Cc) {return blas::gemv(aa, A, Bc, bb, std::move(Cc));} // ); std::transform(begin(A), end(A), begin(C_copy), end(C_copy), - [&B, aa=1.0, bb=0] (auto const& Ar, auto&& Cr) {return blas::gemv(aa, blas::T(B), Ar, bb, std::move(Cr));} + [&B, aa = 1.0, bb = 0](auto const& Ar, auto&& Cr) { return blas::gemv(aa, blas::T(B), Ar, bb, std::move(Cr)); } ); - BOOST_REQUIRE( static_cast(C_copy[1][0]) == static_cast(C[1][0]) ); - BOOST_REQUIRE( static_cast(C_copy[0][1]) == static_cast(C[0][1]) ); + BOOST_TEST( static_cast(C_copy[1][0]) == static_cast(C[1][0]) ); + BOOST_TEST( static_cast(C_copy[0][1]) == static_cast(C[0][1]) ); } { - multi::array C({2, 2}, {3.0, 0.0}); // NOLINT(readability-identifier-length) conventional BLAS naming - auto C_copy = C; - C = blas::gemm(1.0 + I*0.0, A, B); + multi::array C({ 2, 2 }, { 3.0, 0.0 }); // NOLINT(readability-identifier-length) conventional BLAS naming + auto C_copy = C; + C = blas::gemm(1.0 + I * 0.0, A, B); // std::transform(begin(transposed(B)), end(transposed(B)), begin(transposed(C_copy)), begin(transposed(C_copy)), // [&A, aa=1.0, bb=0.0] (auto const& Bc, auto&& Cc) {return blas::gemv(aa, A, Bc, bb, std::move(Cc));} // ); - std::transform(begin(A), end(A), begin(C_copy), begin(C_copy), [&B, aa=1.0, bb=0.0] (auto const& Ar, auto&& Cr) { + std::transform(begin(A), end(A), begin(C_copy), begin(C_copy), [&B, aa = 1.0, bb = 0.0](auto const& Ar, auto&& Cr) { return blas::gemv(aa, blas::T(B), Ar, bb, std::move(Cr)); - } - ); + }); - BOOST_REQUIRE( static_cast(C_copy[1][0]) == static_cast(C[1][0]) ); - BOOST_REQUIRE( static_cast(C_copy[0][1]) == static_cast(C[0][1]) ); + BOOST_TEST( static_cast(C_copy[1][0]) == static_cast(C[1][0]) ); + BOOST_TEST( static_cast(C_copy[0][1]) == static_cast(C[0][1]) ); } { - multi::array C({2, 2}, {3.0, 0.0}); // NOLINT(readability-identifier-length) conventional BLAS naming - auto C_copy = C; - C += blas::gemm(1.0 + I*0.0, A, B); + multi::array C({ 2, 2 }, { 3.0, 0.0 }); // NOLINT(readability-identifier-length) conventional BLAS naming + auto C_copy = C; + C += blas::gemm(1.0 + I * 0.0, A, B); std::transform(begin(transposed(B)), end(transposed(B)), begin(transposed(C_copy)), begin(transposed(C_copy)), - [&A, aa=1.0, bb=1.0] (auto const& Bc, auto&& Cc) {return blas::gemv(aa, A, Bc, bb, std::move(Cc));} + [&A, aa = 1.0, bb = 1.0](auto const& Bc, auto&& Cc) { return blas::gemv(aa, A, Bc, bb, std::move(Cc)); } ); - BOOST_REQUIRE( static_cast(C_copy[1][0]) == static_cast(C[1][0]) ); - BOOST_REQUIRE( static_cast(C_copy[0][1]) == static_cast(C[0][1]) ); + BOOST_TEST( static_cast(C_copy[1][0]) == static_cast(C[1][0]) ); + BOOST_TEST( static_cast(C_copy[0][1]) == static_cast(C[0][1]) ); } { - multi::array C({2, 2}, {3.0, 0.0}); // NOLINT(readability-identifier-length) conventional BLAS naming - auto C_copy = C; + multi::array C({ 2, 2 }, { 3.0, 0.0 }); // NOLINT(readability-identifier-length) conventional BLAS naming + auto C_copy = C; using blas::operators::operator*; using blas::operators::operator+=; - C += A*B; + C += A * B; - std::transform(begin(A), end(A), begin(C_copy), begin(C_copy), [&B, aa=1.0, bb=1.0] (auto const& Ar, auto&& Cr) { + std::transform(begin(A), end(A), begin(C_copy), begin(C_copy), [&B, aa = 1.0, bb = 1.0](auto const& Ar, auto&& Cr) { return blas::gemv(aa, blas::T(B), Ar, bb, std::move(Cr)); - } - ); + }); - BOOST_REQUIRE( static_cast(C_copy[1][0]) == static_cast(C[1][0]) ); - BOOST_REQUIRE( static_cast(C_copy[0][1]) == static_cast(C[0][1]) ); + BOOST_TEST( static_cast(C_copy[1][0]) == static_cast(C[1][0]) ); + BOOST_TEST( static_cast(C_copy[0][1]) == static_cast(C[0][1]) ); } } BOOST_AUTO_TEST_CASE(cublas_one_gemm_complex_trans_second) { namespace blas = multi::blas; - using T = complex; - using Alloc = thrust::cuda::allocator; - complex const I{0.0, 1.0}; + using T = complex; + using Alloc = thrust::cuda::allocator; + complex const I{ 0.0, 1.0 }; // NOLINT(readability-identifier-length) BLAS naming multi::array const A = { @@ -862,81 +976,79 @@ BOOST_AUTO_TEST_CASE(cublas_one_gemm_complex_trans_second) { {1.0 + 5.0 * I, 8.0 - 8.0 * I}, }; { - multi::array C({2, 2}, {3.0, 0.0}); // NOLINT(readability-identifier-length) conventional BLAS naming - auto C_copy = C; - blas::gemm({1.0, 0.0}, A, blas::T(B), {0.0, 0.0}, C); + multi::array C({ 2, 2 }, { 3.0, 0.0 }); // NOLINT(readability-identifier-length) conventional BLAS naming + auto C_copy = C; + blas::gemm({ 1.0, 0.0 }, A, blas::T(B), { 0.0, 0.0 }, C); std::transform(begin(B), end(B), begin(transposed(C_copy)), begin(transposed(C_copy)), - [&A, aa=1.0, bb=0.0] (auto const& Bc, auto&& Cc) {return blas::gemv(aa, A, Bc, bb, std::move(Cc));} + [&A, aa = 1.0, bb = 0.0](auto const& Bc, auto&& Cc) { return blas::gemv(aa, A, Bc, bb, std::move(Cc)); } ); - BOOST_REQUIRE( static_cast(C_copy[1][0]) == static_cast(C[1][0]) ); - BOOST_REQUIRE( static_cast(C_copy[0][1]) == static_cast(C[0][1]) ); + BOOST_TEST( static_cast(C_copy[1][0]) == static_cast(C[1][0]) ); + BOOST_TEST( static_cast(C_copy[0][1]) == static_cast(C[0][1]) ); } { - multi::array C({2, 2}, {3.0, 0.0}); // NOLINT(readability-identifier-length) conventional BLAS naming - auto C_copy = C; - C = blas::gemm(1.0 + I*0.0, A, blas::T(B)); + multi::array C({ 2, 2 }, { 3.0, 0.0 }); // NOLINT(readability-identifier-length) conventional BLAS naming + auto C_copy = C; + C = blas::gemm(1.0 + I * 0.0, A, blas::T(B)); // std::transform(begin(transposed(B)), end(transposed(B)), begin(transposed(C_copy)), begin(transposed(C_copy)), // [&A, aa=1.0, bb=0.0] (auto const& Bc, auto&& Cc) {return blas::gemv(aa, A, Bc, bb, std::move(Cc));} // ); - std::transform(begin(A), end(A), begin(C_copy), begin(C_copy), [&B, aa=1.0, bb=0.0] (auto const& Ac, auto&& Cr) { + std::transform(begin(A), end(A), begin(C_copy), begin(C_copy), [&B, aa = 1.0, bb = 0.0](auto const& Ac, auto&& Cr) { return blas::gemv(aa, B, Ac, bb, std::move(Cr)); }); - BOOST_REQUIRE( static_cast(C_copy[1][0]) == static_cast(C[1][0]) ); - BOOST_REQUIRE( static_cast(C_copy[0][1]) == static_cast(C[0][1]) ); + BOOST_TEST( static_cast(C_copy[1][0]) == static_cast(C[1][0]) ); + BOOST_TEST( static_cast(C_copy[0][1]) == static_cast(C[0][1]) ); } { - multi::array C({2, 2}, {3.0, 0.0}); // NOLINT(readability-identifier-length) conventional BLAS naming - auto C_copy = C; - C += blas::gemm(1.0 + I*0.0, A, blas::T(B)); + multi::array C({ 2, 2 }, { 3.0, 0.0 }); // NOLINT(readability-identifier-length) conventional BLAS naming + auto C_copy = C; + C += blas::gemm(1.0 + I * 0.0, A, blas::T(B)); std::transform(begin(B), end(B), begin(transposed(C_copy)), begin(transposed(C_copy)), - [&A, aa=1.0, bb=1.0] (auto const& Bc, auto&& Cc) {return blas::gemv(aa, A, Bc, bb, std::move(Cc));} + [&A, aa = 1.0, bb = 1.0](auto const& Bc, auto&& Cc) { return blas::gemv(aa, A, Bc, bb, std::move(Cc)); } ); - BOOST_REQUIRE( static_cast(C_copy[1][0]) == static_cast(C[1][0]) ); - BOOST_REQUIRE( static_cast(C_copy[0][1]) == static_cast(C[0][1]) ); + BOOST_TEST( static_cast(C_copy[1][0]) == static_cast(C[1][0]) ); + BOOST_TEST( static_cast(C_copy[0][1]) == static_cast(C[0][1]) ); } { - multi::array C({2, 2}, {3.0, 0.0}); // NOLINT(readability-identifier-length) conventional BLAS naming - auto C_copy = C; + multi::array C({ 2, 2 }, { 3.0, 0.0 }); // NOLINT(readability-identifier-length) conventional BLAS naming + auto C_copy = C; using blas::operators::operator*; using blas::operators::operator+=; C += A * ~B; - std::transform(begin(A), end(A), begin(C_copy), begin(C_copy), [&B, aa=1.0, bb=1.0] (auto const& Ar, auto&& Cr) { + std::transform(begin(A), end(A), begin(C_copy), begin(C_copy), [&B, aa = 1.0, bb = 1.0](auto const& Ar, auto&& Cr) { return blas::gemv(aa, B, Ar, bb, std::move(Cr)); - } - ); + }); - BOOST_REQUIRE( static_cast(C_copy[1][0]) == static_cast(C[1][0]) ); - BOOST_REQUIRE( static_cast(C_copy[0][1]) == static_cast(C[0][1]) ); + BOOST_TEST( static_cast(C_copy[1][0]) == static_cast(C[1][0]) ); + BOOST_TEST( static_cast(C_copy[0][1]) == static_cast(C[0][1]) ); } { - multi::array C({2, 2}, {3.0, 0.0}); // NOLINT(readability-identifier-length) conventional BLAS naming - auto C_copy = C; + multi::array C({ 2, 2 }, { 3.0, 0.0 }); // NOLINT(readability-identifier-length) conventional BLAS naming + auto C_copy = C; using blas::operators::operator*; using blas::operators::operator+=; - C += 2.0*(A * ~B); + C += 2.0 * (A * ~B); - std::transform(begin(A), end(A), begin(C_copy), begin(C_copy), [&B, aa=2.0, bb=1.0] (auto const& Ar, auto&& Cr) { + std::transform(begin(A), end(A), begin(C_copy), begin(C_copy), [&B, aa = 2.0, bb = 1.0](auto const& Ar, auto&& Cr) { return blas::gemv(aa, B, Ar, bb, std::move(Cr)); - } - ); + }); - BOOST_REQUIRE( static_cast(C_copy[1][0]) == static_cast(C[1][0]) ); - BOOST_REQUIRE( static_cast(C_copy[0][1]) == static_cast(C[0][1]) ); + BOOST_TEST( static_cast(C_copy[1][0]) == static_cast(C[1][0]) ); + BOOST_TEST( static_cast(C_copy[0][1]) == static_cast(C[0][1]) ); } } BOOST_AUTO_TEST_CASE(cublas_one_gemm_complex_trans_first) { namespace blas = multi::blas; - using T = complex; - using Alloc = thrust::cuda::allocator; - complex const I{0.0, 1.0}; + using T = complex; + using Alloc = thrust::cuda::allocator; + complex const I{ 0.0, 1.0 }; // NOLINT(readability-identifier-length) BLAS naming multi::array const A = { @@ -948,81 +1060,79 @@ BOOST_AUTO_TEST_CASE(cublas_one_gemm_complex_trans_first) { {1.0 + 5.0 * I, 8.0 - 8.0 * I}, }; { - multi::array C({2, 2}, {3.0, 0.0}); // NOLINT(readability-identifier-length) conventional BLAS naming - auto C_copy = C; - blas::gemm({1.0, 0.0}, blas::T(A), B, {0.0, 0.0}, C); + multi::array C({ 2, 2 }, { 3.0, 0.0 }); // NOLINT(readability-identifier-length) conventional BLAS naming + auto C_copy = C; + blas::gemm({ 1.0, 0.0 }, blas::T(A), B, { 0.0, 0.0 }, C); std::transform(begin(transposed(B)), end(transposed(B)), begin(transposed(C_copy)), begin(transposed(C_copy)), - [&A, aa=1.0, bb=0.0] (auto const& Bc, auto&& Cc) {return blas::gemv(aa, blas::T(A), Bc, bb, std::move(Cc));} + [&A, aa = 1.0, bb = 0.0](auto const& Bc, auto&& Cc) { return blas::gemv(aa, blas::T(A), Bc, bb, std::move(Cc)); } ); - BOOST_REQUIRE( static_cast(C_copy[1][0]) == static_cast(C[1][0]) ); - BOOST_REQUIRE( static_cast(C_copy[0][1]) == static_cast(C[0][1]) ); + BOOST_TEST( static_cast(C_copy[1][0]) == static_cast(C[1][0]) ); + BOOST_TEST( static_cast(C_copy[0][1]) == static_cast(C[0][1]) ); } { - multi::array C({2, 2}, {3.0, 0.0}); // NOLINT(readability-identifier-length) conventional BLAS naming - auto C_copy = C; - C = blas::gemm(1.0 + I*0.0, blas::T(A), B); + multi::array C({ 2, 2 }, { 3.0, 0.0 }); // NOLINT(readability-identifier-length) conventional BLAS naming + auto C_copy = C; + C = blas::gemm(1.0 + I * 0.0, blas::T(A), B); // std::transform(begin(transposed(B)), end(transposed(B)), begin(transposed(C_copy)), begin(transposed(C_copy)), // [&A, aa=1.0, bb=0.0] (auto const& Bc, auto&& Cc) {return blas::gemv(aa, A, Bc, bb, std::move(Cc));} // ); - std::transform(begin(transposed(A)), end(transposed(A)), begin(C_copy), begin(C_copy), [&B, aa=1.0, bb=0.0] (auto const& Ac, auto&& Cr) { + std::transform(begin(transposed(A)), end(transposed(A)), begin(C_copy), begin(C_copy), [&B, aa = 1.0, bb = 0.0](auto const& Ac, auto&& Cr) { return blas::gemv(aa, blas::T(B), Ac, bb, std::move(Cr)); }); - BOOST_REQUIRE( static_cast(C_copy[1][0]) == static_cast(C[1][0]) ); - BOOST_REQUIRE( static_cast(C_copy[0][1]) == static_cast(C[0][1]) ); + BOOST_TEST( static_cast(C_copy[1][0]) == static_cast(C[1][0]) ); + BOOST_TEST( static_cast(C_copy[0][1]) == static_cast(C[0][1]) ); } { - multi::array C({2, 2}, {3.0, 0.0}); // NOLINT(readability-identifier-length) conventional BLAS naming - auto C_copy = C; - C += blas::gemm(1.0 + I*0.0, blas::T(A), B); + multi::array C({ 2, 2 }, { 3.0, 0.0 }); // NOLINT(readability-identifier-length) conventional BLAS naming + auto C_copy = C; + C += blas::gemm(1.0 + I * 0.0, blas::T(A), B); std::transform(begin(transposed(B)), end(transposed(B)), begin(transposed(C_copy)), begin(transposed(C_copy)), - [&A, aa=1.0, bb=1.0] (auto const& Bc, auto&& Cc) {return blas::gemv(aa, blas::T(A), Bc, bb, std::move(Cc));} + [&A, aa = 1.0, bb = 1.0](auto const& Bc, auto&& Cc) { return blas::gemv(aa, blas::T(A), Bc, bb, std::move(Cc)); } ); - BOOST_REQUIRE( static_cast(C_copy[1][0]) == static_cast(C[1][0]) ); - BOOST_REQUIRE( static_cast(C_copy[0][1]) == static_cast(C[0][1]) ); + BOOST_TEST( static_cast(C_copy[1][0]) == static_cast(C[1][0]) ); + BOOST_TEST( static_cast(C_copy[0][1]) == static_cast(C[0][1]) ); } { - multi::array C({2, 2}, {3.0, 0.0}); // NOLINT(readability-identifier-length) conventional BLAS naming - auto C_copy = C; + multi::array C({ 2, 2 }, { 3.0, 0.0 }); // NOLINT(readability-identifier-length) conventional BLAS naming + auto C_copy = C; using blas::operators::operator*; using blas::operators::operator+=; C += ~A * B; - std::transform(begin(transposed(A)), end(transposed(A)), begin(C_copy), begin(C_copy), [&B, aa=1.0, bb=1.0] (auto const& Ar, auto&& Cr) { + std::transform(begin(transposed(A)), end(transposed(A)), begin(C_copy), begin(C_copy), [&B, aa = 1.0, bb = 1.0](auto const& Ar, auto&& Cr) { return blas::gemv(aa, blas::T(B), Ar, bb, std::move(Cr)); - } - ); + }); - BOOST_REQUIRE( static_cast(C_copy[1][0]) == static_cast(C[1][0]) ); - BOOST_REQUIRE( static_cast(C_copy[0][1]) == static_cast(C[0][1]) ); + BOOST_TEST( static_cast(C_copy[1][0]) == static_cast(C[1][0]) ); + BOOST_TEST( static_cast(C_copy[0][1]) == static_cast(C[0][1]) ); } { - multi::array C({2, 2}, {3.0, 0.0}); // NOLINT(readability-identifier-length) conventional BLAS naming - auto C_copy = C; + multi::array C({ 2, 2 }, { 3.0, 0.0 }); // NOLINT(readability-identifier-length) conventional BLAS naming + auto C_copy = C; using blas::operators::operator*; using blas::operators::operator+=; - C += 2.0*(~A * B); + C += 2.0 * (~A * B); - std::transform(begin(transposed(A)), end(transposed(A)), begin(C_copy), begin(C_copy), [&B, aa=2.0, bb=1.0] (auto const& Ar, auto&& Cr) { + std::transform(begin(A.transposed()), end(A.transposed()), begin(C_copy), begin(C_copy), [&B, aa = 2.0, bb = 1.0](auto const& Ar, auto&& Cr) { return blas::gemv(aa, blas::T(B), Ar, bb, std::move(Cr)); - } - ); + }); - BOOST_REQUIRE( static_cast(C_copy[1][0]) == static_cast(C[1][0]) ); - BOOST_REQUIRE( static_cast(C_copy[0][1]) == static_cast(C[0][1]) ); + BOOST_TEST( static_cast(C_copy[1][0]) == static_cast(C[1][0]) ); + BOOST_TEST( static_cast(C_copy[0][1]) == static_cast(C[0][1]) ); } } BOOST_AUTO_TEST_CASE(cublas_one_gemm_complex_trans_both) { namespace blas = multi::blas; - using T = complex; - using Alloc = thrust::cuda::allocator; - complex const I{0.0, 1.0}; + using T = complex; + using Alloc = thrust::cuda::allocator; + complex const I{ 0.0, 1.0 }; // NOLINT(readability-identifier-length) BLAS naming multi::array const A = { @@ -1034,81 +1144,79 @@ BOOST_AUTO_TEST_CASE(cublas_one_gemm_complex_trans_both) { {1.0 + 5.0 * I, 8.0 - 8.0 * I}, }; { - multi::array C({2, 2}, {3.0, 0.0}); // NOLINT(readability-identifier-length) conventional BLAS naming - auto C_copy = C; - blas::gemm({1.0, 0.0}, blas::T(A), blas::T(B), {0.0, 0.0}, C); + multi::array C({ 2, 2 }, { 3.0, 0.0 }); // NOLINT(readability-identifier-length) conventional BLAS naming + auto C_copy = C; + blas::gemm({ 1.0, 0.0 }, blas::T(A), blas::T(B), { 0.0, 0.0 }, C); - std::transform(begin(B), end(B), begin(transposed(C_copy)), begin(transposed(C_copy)), - [&A, aa=1.0, bb=0.0] (auto const& Br, auto&& Cc) {return blas::gemv(aa, blas::T(A), Br, bb, std::move(Cc));} + std::transform(B.begin(), B.end(), C_copy.transposed().begin(), C_copy.transposed().begin(), + [&A, aa = 1.0, bb = 0.0](auto const& Br, auto&& Cc) { return blas::gemv(aa, blas::T(A), Br, bb, std::move(Cc)); } ); - BOOST_REQUIRE( static_cast(C_copy[1][0]) == static_cast(C[1][0]) ); - BOOST_REQUIRE( static_cast(C_copy[0][1]) == static_cast(C[0][1]) ); + BOOST_TEST( static_cast(C_copy[1][0]) == static_cast(C[1][0]) ); + BOOST_TEST( static_cast(C_copy[0][1]) == static_cast(C[0][1]) ); } { - multi::array C({2, 2}, {3.0, 0.0}); // NOLINT(readability-identifier-length) conventional BLAS naming - auto C_copy = C; - C = blas::gemm(1.0 + I*0.0, blas::T(A), blas::T(B)); + multi::array C({ 2, 2 }, { 3.0, 0.0 }); // NOLINT(readability-identifier-length) conventional BLAS naming + auto C_copy = C; + C = blas::gemm(1.0 + I * 0.0, blas::T(A), blas::T(B)); // std::transform(begin(transposed(B)), end(transposed(B)), begin(transposed(C_copy)), begin(transposed(C_copy)), // [&A, aa=1.0, bb=0.0] (auto const& Bc, auto&& Cc) {return blas::gemv(aa, A, Bc, bb, std::move(Cc));} // ); - std::transform(begin(transposed(A)), end(transposed(A)), begin(C_copy), begin(C_copy), [&B, aa=1.0, bb=0.0] (auto const& Ac, auto&& Cr) { + std::transform(A.transposed().begin(), A.transposed().end(), C_copy.begin(), C_copy.begin(), [&B, aa = 1.0, bb = 0.0](auto const& Ac, auto&& Cr) { return blas::gemv(aa, B, Ac, bb, std::move(Cr)); }); - BOOST_REQUIRE( static_cast(C_copy[1][0]) == static_cast(C[1][0]) ); - BOOST_REQUIRE( static_cast(C_copy[0][1]) == static_cast(C[0][1]) ); + BOOST_TEST( static_cast(C_copy[1][0]) == static_cast(C[1][0]) ); + BOOST_TEST( static_cast(C_copy[0][1]) == static_cast(C[0][1]) ); } { - multi::array C({2, 2}, {3.0, 0.0}); // NOLINT(readability-identifier-length) conventional BLAS naming - auto C_copy = C; - C += blas::gemm(1.0 + I*0.0, blas::T(A), blas::T(B)); + multi::array C({ 2, 2 }, { 3.0, 0.0 }); // NOLINT(readability-identifier-length) conventional BLAS naming + auto C_copy = C; + C += blas::gemm(1.0 + I * 0.0, blas::T(A), blas::T(B)); - std::transform(begin(B), end(B), begin(transposed(C_copy)), begin(transposed(C_copy)), - [&A, aa=1.0, bb=1.0] (auto const& Br, auto&& Cc) {return blas::gemv(aa, blas::T(A), Br, bb, std::move(Cc));} + std::transform(begin(B), end(B), C_copy.transposed().begin(), C_copy.transposed().begin(), + [&A, aa = 1.0, bb = 1.0](auto const& Br, auto&& Cc) { return blas::gemv(aa, blas::T(A), Br, bb, std::move(Cc)); } ); - BOOST_REQUIRE( static_cast(C_copy[1][0]) == static_cast(C[1][0]) ); - BOOST_REQUIRE( static_cast(C_copy[0][1]) == static_cast(C[0][1]) ); + BOOST_TEST( static_cast(C_copy[1][0]) == static_cast(C[1][0]) ); + BOOST_TEST( static_cast(C_copy[0][1]) == static_cast(C[0][1]) ); } { - multi::array C({2, 2}, {3.0, 0.0}); // NOLINT(readability-identifier-length) conventional BLAS naming - auto C_copy = C; + multi::array C({ 2, 2 }, { 3.0, 0.0 }); // NOLINT(readability-identifier-length) conventional BLAS naming + auto C_copy = C; using blas::operators::operator*; using blas::operators::operator+=; C += ~A * ~B; - std::transform(begin(transposed(A)), end(transposed(A)), begin(C_copy), begin(C_copy), [&B, aa=1.0, bb=1.0] (auto const& Ar, auto&& Cr) { + std::transform(A.transposed().begin(), A.transposed().end(), C_copy.begin(), C_copy.begin(), [&B, aa = 1.0, bb = 1.0](auto const& Ar, auto&& Cr) { return blas::gemv(aa, B, Ar, bb, std::move(Cr)); - } - ); + }); - BOOST_REQUIRE( static_cast(C_copy[1][0]) == static_cast(C[1][0]) ); - BOOST_REQUIRE( static_cast(C_copy[0][1]) == static_cast(C[0][1]) ); + BOOST_TEST( static_cast(C_copy[1][0]) == static_cast(C[1][0]) ); + BOOST_TEST( static_cast(C_copy[0][1]) == static_cast(C[0][1]) ); } { - multi::array C({2, 2}, {3.0, 0.0}); // NOLINT(readability-identifier-length) conventional BLAS naming - auto C_copy = C; + multi::array C({ 2, 2 }, { 3.0, 0.0 }); // NOLINT(readability-identifier-length) conventional BLAS naming + auto C_copy = C; using blas::operators::operator*; using blas::operators::operator+=; - C += 2.0*(~A * ~B); + C += 2.0 * (~A * ~B); - std::transform(begin(transposed(A)), end(transposed(A)), begin(C_copy), begin(C_copy), [&B, aa=2.0, bb=1.0] (auto const& Ar, auto&& Cr) { + std::transform(A.transposed().begin(), A.transposed().end(), begin(C_copy), begin(C_copy), [&B, aa = 2.0, bb = 1.0](auto const& Ar, auto&& Cr) { return blas::gemv(aa, B, Ar, bb, std::move(Cr)); - } - ); + }); - BOOST_REQUIRE( static_cast(C_copy[1][0]) == static_cast(C[1][0]) ); - BOOST_REQUIRE( static_cast(C_copy[0][1]) == static_cast(C[0][1]) ); + BOOST_TEST( static_cast(C_copy[1][0]) == static_cast(C[1][0]) ); + BOOST_TEST( static_cast(C_copy[0][1]) == static_cast(C[0][1]) ); } } BOOST_AUTO_TEST_CASE(cublas_one_gemm_complex_conj_second) { namespace blas = multi::blas; - using T = complex; - using Alloc = std::allocator; // thrust::cuda::allocator; - complex const I{0.0, 1.0}; + using T = complex; + using Alloc = std::allocator; // thrust::cuda::allocator; + complex const I{ 0.0, 1.0 }; // NOLINT(readability-identifier-length) BLAS naming multi::array const A = { @@ -1120,25 +1228,25 @@ BOOST_AUTO_TEST_CASE(cublas_one_gemm_complex_conj_second) { {1.0 + 5.0 * I, 8.0 - 8.0 * I}, }; { - multi::array C({2, 2}, {3.0, 0.0}); // NOLINT(readability-identifier-length) conventional BLAS naming - auto CC = C; - auto C_copy = CC; + multi::array C({ 2, 2 }, { 3.0, 0.0 }); // NOLINT(readability-identifier-length) conventional BLAS naming + auto CC = C; + auto C_copy = CC; // blas::gemm({1.0, 0.0}, A, blas::J(B), {0.0, 0.0}, C); - blas::gemm({1.0, 0.0}, blas::T(B), blas::H(A), {0.0, 0.0}, C_copy); + blas::gemm({ 1.0, 0.0 }, blas::T(B), blas::H(A), { 0.0, 0.0 }, C_copy); { auto const [is, js] = C.extensions(); for(auto i : is) { for(auto j : js) { C[i][j] *= 0.0; for(auto k : B.extension()) { - C[i][j] += A[i][k]*conj(B[k][j]); + C[i][j] += A[i][k] * conj(B[k][j]); } } } } - // TODO(correaa) MKL gives an error here - // unknown location(0): fatal error: in "cublas_one_gemv_complex_conjtrans_zero": memory access violation at address: 0x00000007: no mapping at fault address - #if 0 + // TODO(correaa) MKL gives an error here + // unknown location(0): fatal error: in "cublas_one_gemv_complex_conjtrans_zero": memory access violation at address: 0x00000007: no mapping at fault address + #if 0 { std::transform(begin(A), end(A), begin(CC), begin(CC), [BT = transposed(B)](auto const& Ar, auto&& Cr) { return std::transform( @@ -1148,23 +1256,23 @@ BOOST_AUTO_TEST_CASE(cublas_one_gemm_complex_conj_second) { ), std::move(Cr); }); } - BOOST_TEST_REQUIRE( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); - BOOST_TEST_REQUIRE( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); + BOOST_TEST( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); + BOOST_TEST( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); - BOOST_TEST_REQUIRE( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); - BOOST_TEST_REQUIRE( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); + BOOST_TEST( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); + BOOST_TEST( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); - BOOST_TEST_REQUIRE( static_cast(C_copy[1][0]).real() == +static_cast(C[0][1]).real() ); - BOOST_TEST_REQUIRE( static_cast(C_copy[1][0]).imag() == -static_cast(C[0][1]).imag() ); - #endif + BOOST_TEST( static_cast(C_copy[1][0]).real() == +static_cast(C[0][1]).real() ); + BOOST_TEST( static_cast(C_copy[1][0]).imag() == -static_cast(C[0][1]).imag() ); + #endif } } BOOST_AUTO_TEST_CASE(cublas_one_gemm_complex_conj_first) { namespace blas = multi::blas; - using T = complex; - using Alloc = std::allocator; // thrust::cuda::allocator; - complex const I{0.0, 1.0}; + using T = complex; + using Alloc = std::allocator; // thrust::cuda::allocator; + complex const I{ 0.0, 1.0 }; // NOLINT(readability-identifier-length) BLAS naming multi::array const A = { @@ -1176,9 +1284,9 @@ BOOST_AUTO_TEST_CASE(cublas_one_gemm_complex_conj_first) { {1.0 + 5.0 * I, 8.0 - 8.0 * I}, }; { - multi::array C({2, 2}, {3.0, 0.0}); // NOLINT(readability-identifier-length) conventional BLAS naming - auto CC = C; - auto C_copy = CC; + multi::array C({ 2, 2 }, { 3.0, 0.0 }); // NOLINT(readability-identifier-length) conventional BLAS naming + auto CC = C; + auto C_copy = CC; // blas::gemm({1.0, 0.0}, blas::J(A), B, {0.0, 0.0}, C); // blas::gemm({1.0, 0.0}, blas::T(B), blas::H(A), {0.0, 0.0}, C_copy); // { @@ -1201,22 +1309,22 @@ BOOST_AUTO_TEST_CASE(cublas_one_gemm_complex_conj_first) { // ), std::move(Cr); // }); // } - // BOOST_TEST_REQUIRE( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); - // BOOST_TEST_REQUIRE( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); + // BOOST_TEST( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); + // BOOST_TEST( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); - // BOOST_TEST_REQUIRE( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); - // BOOST_TEST_REQUIRE( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); + // BOOST_TEST( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); + // BOOST_TEST( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); - // BOOST_TEST_REQUIRE( static_cast(C_copy[1][0]).real() == +static_cast(C[0][1]).real() ); - // BOOST_TEST_REQUIRE( static_cast(C_copy[1][0]).imag() == -static_cast(C[0][1]).imag() ); + // BOOST_TEST( static_cast(C_copy[1][0]).real() == +static_cast(C[0][1]).real() ); + // BOOST_TEST( static_cast(C_copy[1][0]).imag() == -static_cast(C[0][1]).imag() ); } } BOOST_AUTO_TEST_CASE(cublas_one_gemm_complex_conj_both) { namespace blas = multi::blas; - using T = complex; - using Alloc = std::allocator; // thrust::cuda::allocator; - complex const I{0.0, 1.0}; + using T = complex; + using Alloc = std::allocator; // thrust::cuda::allocator; + complex const I{ 0.0, 1.0 }; // NOLINT(readability-identifier-length) BLAS naming multi::array const A = { @@ -1228,18 +1336,18 @@ BOOST_AUTO_TEST_CASE(cublas_one_gemm_complex_conj_both) { {1.0 + 5.0 * I, 8.0 - 8.0 * I}, }; { - multi::array C({2, 2}, {3.0, 0.0}); // NOLINT(readability-identifier-length) conventional BLAS naming - auto CC = C; - auto C_copy = CC; - // blas::gemm({1.0, 0.0}, blas::J(A), blas::J(B), {0.0, 0.0}, C); + multi::array C({ 2, 2 }, { 3.0, 0.0 }); // NOLINT(readability-identifier-length) conventional BLAS naming + auto CC = C; + auto C_copy = CC; + // blas::gemm({1.0, 0.0}, blas::J(A), blas::J(B), {0.0, 0.0}, C); } } BOOST_AUTO_TEST_CASE(cublas_one_gemm_complex_herm_second) { namespace blas = multi::blas; - using T = complex; - using Alloc = thrust::cuda::allocator; - complex const I{0.0, 1.0}; + using T = complex; + using Alloc = thrust::cuda::allocator; + complex const I{ 0.0, 1.0 }; // NOLINT(readability-identifier-length) BLAS naming multi::array const A = { @@ -1250,54 +1358,53 @@ BOOST_AUTO_TEST_CASE(cublas_one_gemm_complex_herm_second) { {3.0 - 4.0 * I, 19.0 - 1.0 * I}, {1.0 + 5.0 * I, 8.0 - 8.0 * I}, }; - multi::array C({2, 2}, {3.0, 0.0}); // NOLINT(readability-identifier-length) conventional BLAS naming - blas::gemm({1.0, 0.0}, A, blas::H(B), {0.0, 0.0}, C); + multi::array C({ 2, 2 }, { 3.0, 0.0 }); // NOLINT(readability-identifier-length) conventional BLAS naming + blas::gemm({ 1.0, 0.0 }, A, blas::H(B), { 0.0, 0.0 }, C); { - multi::array CC({2, 2}, {3.0, 0.0}); + multi::array CC({ 2, 2 }, { 3.0, 0.0 }); std::transform( begin(A), end(A), begin(CC), begin(CC), - [&B, aa = 1.0, bb = 0.0] (auto const& Ar, auto&& Cr) { + [&B, aa = 1.0, bb = 0.0](auto const& Ar, auto&& Cr) { return blas::gemv(aa, blas::J(B), Ar, bb, std::move(Cr)); } ); - BOOST_TEST_REQUIRE( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); - BOOST_TEST_REQUIRE( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); + BOOST_TEST( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); + BOOST_TEST( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); - BOOST_TEST_REQUIRE( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); - BOOST_TEST_REQUIRE( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); + BOOST_TEST( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); + BOOST_TEST( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); } { - multi::array CC({2, 2}, {3.0, 0.0}); - CC = blas::gemm({1.0, 0.0}, A, blas::H(B)); + multi::array CC({ 2, 2 }, { 3.0, 0.0 }); + CC = blas::gemm({ 1.0, 0.0 }, A, blas::H(B)); - BOOST_TEST_REQUIRE( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); - BOOST_TEST_REQUIRE( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); + BOOST_TEST( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); + BOOST_TEST( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); - BOOST_TEST_REQUIRE( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); - BOOST_TEST_REQUIRE( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); + BOOST_TEST( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); + BOOST_TEST( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); } { - multi::array CC({2, 2}, {3.0, 0.0}); + multi::array CC({ 2, 2 }, { 3.0, 0.0 }); using blas::operators::operator*; using blas::operators::operator~; - CC = A* ~*B; + CC = A * ~*B; - BOOST_TEST_REQUIRE( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); - BOOST_TEST_REQUIRE( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); + BOOST_TEST( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); + BOOST_TEST( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); - BOOST_TEST_REQUIRE( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); - BOOST_TEST_REQUIRE( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); + BOOST_TEST( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); + BOOST_TEST( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); } - } BOOST_AUTO_TEST_CASE(cublas_one_gemm_complex_herm_second_plus) { namespace blas = multi::blas; - using T = complex; - using Alloc = thrust::cuda::allocator; - complex const I{0.0, 1.0}; + using T = complex; + using Alloc = thrust::cuda::allocator; + complex const I{ 0.0, 1.0 }; // NOLINT(readability-identifier-length) BLAS naming multi::array const A = { @@ -1308,53 +1415,53 @@ BOOST_AUTO_TEST_CASE(cublas_one_gemm_complex_herm_second_plus) { {3.0 - 4.0 * I, 19.0 - 1.0 * I}, {1.0 + 5.0 * I, 8.0 - 8.0 * I}, }; - multi::array C({2, 2}, {3.0, 0.0}); // NOLINT(readability-identifier-length) conventional BLAS naming - blas::gemm({1.0, 0.0}, A, blas::H(B), {1.0, 0.0}, C); + multi::array C({ 2, 2 }, { 3.0, 0.0 }); // NOLINT(readability-identifier-length) conventional BLAS naming + blas::gemm({ 1.0, 0.0 }, A, blas::H(B), { 1.0, 0.0 }, C); { - multi::array CC({2, 2}, {3.0, 0.0}); + multi::array CC({ 2, 2 }, { 3.0, 0.0 }); std::transform( begin(A), end(A), begin(CC), begin(CC), - [&B, aa = 1.0, bb = 1.0] (auto const& Ar, auto&& Cr) { + [&B, aa = 1.0, bb = 1.0](auto const& Ar, auto&& Cr) { return blas::gemv(aa, blas::J(B), Ar, bb, std::move(Cr)); } ); - BOOST_TEST_REQUIRE( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); - BOOST_TEST_REQUIRE( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); + BOOST_TEST( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); + BOOST_TEST( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); - BOOST_TEST_REQUIRE( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); - BOOST_TEST_REQUIRE( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); + BOOST_TEST( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); + BOOST_TEST( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); } { - multi::array CC({2, 2}, {3.0, 0.0}); - CC += blas::gemm({1.0, 0.0}, A, blas::H(B)); + multi::array CC({ 2, 2 }, { 3.0, 0.0 }); + CC += blas::gemm({ 1.0, 0.0 }, A, blas::H(B)); - BOOST_TEST_REQUIRE( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); - BOOST_TEST_REQUIRE( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); + BOOST_TEST( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); + BOOST_TEST( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); - BOOST_TEST_REQUIRE( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); - BOOST_TEST_REQUIRE( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); + BOOST_TEST( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); + BOOST_TEST( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); } { - multi::array CC({2, 2}, {3.0, 0.0}); + multi::array CC({ 2, 2 }, { 3.0, 0.0 }); using blas::operators::operator*; using blas::operators::operator~; - CC += A* ~*B; + CC += A * ~*B; - BOOST_TEST_REQUIRE( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); - BOOST_TEST_REQUIRE( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); + BOOST_TEST( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); + BOOST_TEST( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); - BOOST_TEST_REQUIRE( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); - BOOST_TEST_REQUIRE( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); + BOOST_TEST( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); + BOOST_TEST( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); } } BOOST_AUTO_TEST_CASE(cublas_one_gemm_complex_herm_first) { namespace blas = multi::blas; - using T = complex; - using Alloc = thrust::cuda::allocator; - complex const I{0.0, 1.0}; + using T = complex; + using Alloc = thrust::cuda::allocator; + complex const I{ 0.0, 1.0 }; // NOLINT(readability-identifier-length) BLAS naming multi::array const A = { @@ -1365,8 +1472,8 @@ BOOST_AUTO_TEST_CASE(cublas_one_gemm_complex_herm_first) { {3.0 - 4.0 * I, 19.0 - 1.0 * I}, {1.0 + 5.0 * I, 8.0 - 8.0 * I}, }; - multi::array C({2, 2}, {3.0, 0.0}); // NOLINT(readability-identifier-length) conventional BLAS naming - blas::gemm({1.0, 0.0}, blas::H(A), B, {0.0, 0.0}, C); + multi::array C({ 2, 2 }, { 3.0, 0.0 }); // NOLINT(readability-identifier-length) conventional BLAS naming + blas::gemm({ 1.0, 0.0 }, blas::H(A), B, { 0.0, 0.0 }, C); // { // multi::array CC({2, 2}, {3.0, 0.0}); // auto const [is, js] = CC.extensions(); @@ -1378,56 +1485,56 @@ BOOST_AUTO_TEST_CASE(cublas_one_gemm_complex_herm_first) { // } // } // } - // BOOST_TEST_REQUIRE( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); - // BOOST_TEST_REQUIRE( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); + // BOOST_TEST( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); + // BOOST_TEST( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); - // BOOST_TEST_REQUIRE( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); - // BOOST_TEST_REQUIRE( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); + // BOOST_TEST( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); + // BOOST_TEST( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); // } { - multi::array CC({2, 2}, {3.0, 0.0}); + multi::array CC({ 2, 2 }, { 3.0, 0.0 }); - std::transform(begin(transposed(A)), end(transposed(A)), begin(CC), begin(CC), [BT=transposed(B)](auto const& Ac, auto&& Cr) { + std::transform(begin(transposed(A)), end(transposed(A)), begin(CC), begin(CC), [BT = transposed(B)](auto const& Ac, auto&& Cr) { std::transform(begin(BT), end(BT), begin(Cr), begin(Cr), [&Ac](auto const& Bc, auto&& c) { return blas::dot(blas::C(Ac), Bc, std::move(c)); }); return std::move(Cr); }); - BOOST_TEST_REQUIRE( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); - BOOST_TEST_REQUIRE( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); + BOOST_TEST( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); + BOOST_TEST( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); - BOOST_TEST_REQUIRE( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); - BOOST_TEST_REQUIRE( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); + BOOST_TEST( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); + BOOST_TEST( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); } { - multi::array CC({2, 2}, {3.0, 0.0}); - CC = blas::gemm({1.0, 0.0}, blas::H(A), B); + multi::array CC({ 2, 2 }, { 3.0, 0.0 }); + CC = blas::gemm({ 1.0, 0.0 }, blas::H(A), B); - BOOST_TEST_REQUIRE( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); - BOOST_TEST_REQUIRE( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); + BOOST_TEST( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); + BOOST_TEST( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); - BOOST_TEST_REQUIRE( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); - BOOST_TEST_REQUIRE( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); + BOOST_TEST( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); + BOOST_TEST( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); } { - multi::array CC({2, 2}, {3.0, 0.0}); + multi::array CC({ 2, 2 }, { 3.0, 0.0 }); using blas::operators::operator*; using blas::operators::operator~; - CC = ~*A *B; + CC = ~*A * B; - BOOST_TEST_REQUIRE( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); - BOOST_TEST_REQUIRE( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); + BOOST_TEST( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); + BOOST_TEST( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); - BOOST_TEST_REQUIRE( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); - BOOST_TEST_REQUIRE( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); + BOOST_TEST( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); + BOOST_TEST( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); } } BOOST_AUTO_TEST_CASE(cublas_one_gemm_complex_herm_both) { namespace blas = multi::blas; - using T = complex; - using Alloc = thrust::cuda::allocator; - complex const I{0.0, 1.0}; + using T = complex; + using Alloc = thrust::cuda::allocator; + complex const I{ 0.0, 1.0 }; // NOLINT(readability-identifier-length) BLAS naming multi::array const A = { @@ -1438,8 +1545,8 @@ BOOST_AUTO_TEST_CASE(cublas_one_gemm_complex_herm_both) { {3.0 - 4.0 * I, 19.0 - 1.0 * I}, {1.0 + 5.0 * I, 8.0 - 8.0 * I}, }; - multi::array C({2, 2}, {3.0, 0.0}); // NOLINT(readability-identifier-length) conventional BLAS naming - blas::gemm({1.0, 0.0}, blas::H(A), blas::H(B), {0.0, 0.0}, C); + multi::array C({ 2, 2 }, { 3.0, 0.0 }); // NOLINT(readability-identifier-length) conventional BLAS naming + blas::gemm({ 1.0, 0.0 }, blas::H(A), blas::H(B), { 0.0, 0.0 }, C); // { // multi::array CC({2, 2}, {3.0, 0.0}); // auto const [is, js] = CC.extensions(); @@ -1451,11 +1558,11 @@ BOOST_AUTO_TEST_CASE(cublas_one_gemm_complex_herm_both) { // } // } // } - // BOOST_TEST_REQUIRE( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); - // BOOST_TEST_REQUIRE( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); + // BOOST_TEST( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); + // BOOST_TEST( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); - // BOOST_TEST_REQUIRE( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); - // BOOST_TEST_REQUIRE( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); + // BOOST_TEST( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); + // BOOST_TEST( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); // } // { // multi::array CC({2, 2}, {3.0, 0.0}); @@ -1467,42 +1574,42 @@ BOOST_AUTO_TEST_CASE(cublas_one_gemm_complex_herm_both) { // }); // return std::move(Cr); // }); - // BOOST_TEST_REQUIRE( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); - // BOOST_TEST_REQUIRE( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); + // BOOST_TEST( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); + // BOOST_TEST( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); - // BOOST_TEST_REQUIRE( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); - // BOOST_TEST_REQUIRE( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); + // BOOST_TEST( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); + // BOOST_TEST( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); // } { - multi::array CC({2, 2}, {3.0, 0.0}); + multi::array CC({ 2, 2 }, { 3.0, 0.0 }); - CC = blas::gemm({1.0, 0.0}, blas::H(A), blas::H(B)); + CC = blas::gemm({ 1.0, 0.0 }, blas::H(A), blas::H(B)); - BOOST_TEST_REQUIRE( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); - BOOST_TEST_REQUIRE( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); + BOOST_TEST( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); + BOOST_TEST( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); - BOOST_TEST_REQUIRE( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); - BOOST_TEST_REQUIRE( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); + BOOST_TEST( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); + BOOST_TEST( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); } { - multi::array CC({2, 2}, {3.0, 0.0}); + multi::array CC({ 2, 2 }, { 3.0, 0.0 }); using blas::operators::operator*; using blas::operators::operator~; CC = ~*A * ~*B; - BOOST_TEST_REQUIRE( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); - BOOST_TEST_REQUIRE( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); + BOOST_TEST( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); + BOOST_TEST( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); - BOOST_TEST_REQUIRE( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); - BOOST_TEST_REQUIRE( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); + BOOST_TEST( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); + BOOST_TEST( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); } } BOOST_AUTO_TEST_CASE(cublas_one_gemm_complex_trans_herm) { namespace blas = multi::blas; - using T = complex; - using Alloc = thrust::cuda::allocator; - complex const I{0.0, 1.0}; + using T = complex; + using Alloc = thrust::cuda::allocator; + complex const I{ 0.0, 1.0 }; // NOLINT(readability-identifier-length) BLAS naming multi::array const A = { @@ -1513,8 +1620,8 @@ BOOST_AUTO_TEST_CASE(cublas_one_gemm_complex_trans_herm) { {3.0 - 4.0 * I, 19.0 - 1.0 * I}, {1.0 + 5.0 * I, 8.0 - 8.0 * I}, }; - multi::array C({2, 2}, {3.0, 0.0}); // NOLINT(readability-identifier-length) conventional BLAS naming - blas::gemm({1.0, 0.0}, blas::T(A), blas::H(B), {0.0, 0.0}, C); + multi::array C({ 2, 2 }, { 3.0, 0.0 }); // NOLINT(readability-identifier-length) conventional BLAS naming + blas::gemm({ 1.0, 0.0 }, blas::T(A), blas::H(B), { 0.0, 0.0 }, C); // { // multi::array CC({2, 2}, {3.0, 0.0}); // auto const [is, js] = CC.extensions(); @@ -1526,11 +1633,11 @@ BOOST_AUTO_TEST_CASE(cublas_one_gemm_complex_trans_herm) { // } // } // } - // BOOST_TEST_REQUIRE( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); - // BOOST_TEST_REQUIRE( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); + // BOOST_TEST( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); + // BOOST_TEST( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); - // BOOST_TEST_REQUIRE( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); - // BOOST_TEST_REQUIRE( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); + // BOOST_TEST( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); + // BOOST_TEST( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); // } // { // multi::array CC({2, 2}, {3.0, 0.0}); @@ -1542,42 +1649,42 @@ BOOST_AUTO_TEST_CASE(cublas_one_gemm_complex_trans_herm) { // }); // return std::move(Cr); // }); - // BOOST_TEST_REQUIRE( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); - // BOOST_TEST_REQUIRE( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); + // BOOST_TEST( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); + // BOOST_TEST( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); - // BOOST_TEST_REQUIRE( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); - // BOOST_TEST_REQUIRE( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); + // BOOST_TEST( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); + // BOOST_TEST( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); // } { - multi::array CC({2, 2}, {3.0, 0.0}); + multi::array CC({ 2, 2 }, { 3.0, 0.0 }); - CC = blas::gemm({1.0, 0.0}, blas::T(A), blas::H(B)); + CC = blas::gemm({ 1.0, 0.0 }, blas::T(A), blas::H(B)); - BOOST_TEST_REQUIRE( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); - BOOST_TEST_REQUIRE( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); + BOOST_TEST( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); + BOOST_TEST( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); - BOOST_TEST_REQUIRE( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); - BOOST_TEST_REQUIRE( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); + BOOST_TEST( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); + BOOST_TEST( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); } { - multi::array CC({2, 2}, {3.0, 0.0}); + multi::array CC({ 2, 2 }, { 3.0, 0.0 }); using blas::operators::operator*; using blas::operators::operator~; CC = ~A * ~*B; - BOOST_TEST_REQUIRE( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); - BOOST_TEST_REQUIRE( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); + BOOST_TEST( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); + BOOST_TEST( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); - BOOST_TEST_REQUIRE( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); - BOOST_TEST_REQUIRE( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); + BOOST_TEST( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); + BOOST_TEST( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); } } BOOST_AUTO_TEST_CASE(cublas_one_gemm_complex_herm_trans) { namespace blas = multi::blas; - using T = complex; - using Alloc = thrust::cuda::allocator; - complex const I{0.0, 1.0}; + using T = complex; + using Alloc = thrust::cuda::allocator; + complex const I{ 0.0, 1.0 }; // NOLINT(readability-identifier-length) BLAS naming multi::array const A = { @@ -1588,24 +1695,25 @@ BOOST_AUTO_TEST_CASE(cublas_one_gemm_complex_herm_trans) { {3.0 - 4.0 * I, 19.0 - 1.0 * I}, {1.0 + 5.0 * I, 8.0 - 8.0 * I}, }; - multi::array C({2, 2}, {3.0, 0.0}); // NOLINT(readability-identifier-length) conventional BLAS naming - //blas::gemm({1.0, 0.0}, blas::H(A), blas::T(B), {0.0, 0.0}, C); - // { - // multi::array CC({2, 2}, {3.0, 0.0}); - // auto const [is, js] = CC.extensions(); - // for(auto i : is) { - // for(auto j : js) { - // CC[i][j] = 0.0; - // for(auto k : A.extension()) { - // CC[i][j] += 1.0*conj(A[k][i])*conj(B[j][k]) ; - // } - // } - // } - // BOOST_TEST_REQUIRE( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); - // BOOST_TEST_REQUIRE( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); - - // BOOST_TEST_REQUIRE( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); - // BOOST_TEST_REQUIRE( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); + multi::array C({ 2, 2 }, { 3.0, 0.0 }); // NOLINT(readability-identifier-length) conventional BLAS naming + + // blas::gemm({1.0, 0.0}, blas::H(A), blas::T(B), {0.0, 0.0}, C); + // { + // multi::array CC({2, 2}, {3.0, 0.0}); + // auto const [is, js] = CC.extensions(); + // for(auto i : is) { + // for(auto j : js) { + // CC[i][j] = 0.0; + // for(auto k : A.extension()) { + // CC[i][j] += 1.0*conj(A[k][i])*conj(B[j][k]) ; + // } + // } + // } + // BOOST_TEST( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); + // BOOST_TEST( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); + + // BOOST_TEST( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); + // BOOST_TEST( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); // } // { // multi::array CC({2, 2}, {3.0, 0.0}); @@ -1617,22 +1725,22 @@ BOOST_AUTO_TEST_CASE(cublas_one_gemm_complex_herm_trans) { // }); // return std::move(Cr); // }); - // BOOST_TEST_REQUIRE( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); - // BOOST_TEST_REQUIRE( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); + // BOOST_TEST( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); + // BOOST_TEST( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); - // BOOST_TEST_REQUIRE( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); - // BOOST_TEST_REQUIRE( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); + // BOOST_TEST( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); + // BOOST_TEST( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); // } // { // multi::array CC({2, 2}, {3.0, 0.0}); // CC = blas::gemm({1.0, 0.0}, blas::H(A), blas::T(B)); - // BOOST_TEST_REQUIRE( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); - // BOOST_TEST_REQUIRE( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); + // BOOST_TEST( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); + // BOOST_TEST( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); - // BOOST_TEST_REQUIRE( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); - // BOOST_TEST_REQUIRE( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); + // BOOST_TEST( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); + // BOOST_TEST( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); // } // { // multi::array CC({2, 2}, {3.0, 0.0}); @@ -1640,19 +1748,19 @@ BOOST_AUTO_TEST_CASE(cublas_one_gemm_complex_herm_trans) { // using blas::operators::operator~; // CC = ~*A * ~B; - // BOOST_TEST_REQUIRE( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); - // BOOST_TEST_REQUIRE( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); + // BOOST_TEST( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); + // BOOST_TEST( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); - // BOOST_TEST_REQUIRE( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); - // BOOST_TEST_REQUIRE( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); + // BOOST_TEST( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); + // BOOST_TEST( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); // } } BOOST_AUTO_TEST_CASE(cublas_one_gemm_complex_conj_herm) { namespace blas = multi::blas; - using T = complex; - using Alloc = thrust::cuda::allocator; - complex const I{0.0, 1.0}; + using T = complex; + using Alloc = thrust::cuda::allocator; + complex const I{ 0.0, 1.0 }; // NOLINT(readability-identifier-length) BLAS naming multi::array const A = { @@ -1663,7 +1771,8 @@ BOOST_AUTO_TEST_CASE(cublas_one_gemm_complex_conj_herm) { {3.0 - 4.0 * I, 19.0 - 1.0 * I}, {1.0 + 5.0 * I, 8.0 - 8.0 * I}, }; - multi::array C({2, 2}, {3.0, 0.0}); // NOLINT(readability-identifier-length) conventional BLAS naming + multi::array C({ 2, 2 }, { 3.0, 0.0 }); // NOLINT(readability-identifier-length) conventional BLAS naming + // blas::gemm({1.0, 0.0}, blas::J(A), blas::H(B), {0.0, 0.0}, C); // { // multi::array CC({2, 2}, {3.0, 0.0}); @@ -1676,11 +1785,11 @@ BOOST_AUTO_TEST_CASE(cublas_one_gemm_complex_conj_herm) { // } // } // } - // BOOST_TEST_REQUIRE( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); - // BOOST_TEST_REQUIRE( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); + // BOOST_TEST( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); + // BOOST_TEST( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); - // BOOST_TEST_REQUIRE( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); - // BOOST_TEST_REQUIRE( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); + // BOOST_TEST( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); + // BOOST_TEST( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); // } // { // multi::array CC({2, 2}, {3.0, 0.0}); @@ -1692,22 +1801,22 @@ BOOST_AUTO_TEST_CASE(cublas_one_gemm_complex_conj_herm) { // }); // return std::move(Cr); // }); - // BOOST_TEST_REQUIRE( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); - // BOOST_TEST_REQUIRE( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); + // BOOST_TEST( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); + // BOOST_TEST( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); - // BOOST_TEST_REQUIRE( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); - // BOOST_TEST_REQUIRE( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); + // BOOST_TEST( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); + // BOOST_TEST( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); // } // { // multi::array CC({2, 2}, {3.0, 0.0}); // CC = blas::gemm({1.0, 0.0}, blas::T(A), blas::H(B)); - // BOOST_TEST_REQUIRE( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); - // BOOST_TEST_REQUIRE( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); + // BOOST_TEST( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); + // BOOST_TEST( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); - // BOOST_TEST_REQUIRE( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); - // BOOST_TEST_REQUIRE( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); + // BOOST_TEST( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); + // BOOST_TEST( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); // } // { // multi::array CC({2, 2}, {3.0, 0.0}); @@ -1715,19 +1824,19 @@ BOOST_AUTO_TEST_CASE(cublas_one_gemm_complex_conj_herm) { // using blas::operators::operator~; // CC = ~A * ~*B; - // BOOST_TEST_REQUIRE( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); - // BOOST_TEST_REQUIRE( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); + // BOOST_TEST( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); + // BOOST_TEST( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); - // BOOST_TEST_REQUIRE( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); - // BOOST_TEST_REQUIRE( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); + // BOOST_TEST( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); + // BOOST_TEST( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); // } } BOOST_AUTO_TEST_CASE(cublas_one_gemm_complex_herm_conj) { namespace blas = multi::blas; - using T = complex; - using Alloc = thrust::cuda::allocator; - complex const I{0.0, 1.0}; + using T = complex; + using Alloc = thrust::cuda::allocator; + complex const I{ 0.0, 1.0 }; // NOLINT(readability-identifier-length) BLAS naming multi::array const A = { @@ -1739,24 +1848,24 @@ BOOST_AUTO_TEST_CASE(cublas_one_gemm_complex_herm_conj) { {3.0 - 4.0 * I, 19.0 - 1.0 * I}, {1.0 + 5.0 * I, 8.0 - 8.0 * I}, }; - multi::array C({2, 2}, {3.0, 0.0}); // NOLINT(readability-identifier-length) conventional BLAS naming - //blas::gemm({1.0, 0.0}, blas::H(A), blas::J(B), {0.0, 0.0}, C); - // { - // multi::array CC({2, 2}, {3.0, 0.0}); - // auto const [is, js] = CC.extensions(); - // for(auto i : is) { - // for(auto j : js) { - // CC[i][j] = 0.0; - // for(auto k : A.extension()) { - // CC[i][j] += 1.0*conj(A[k][i])*conj(B[j][k]) ; - // } - // } - // } - // BOOST_TEST_REQUIRE( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); - // BOOST_TEST_REQUIRE( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); - - // BOOST_TEST_REQUIRE( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); - // BOOST_TEST_REQUIRE( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); + multi::array C({ 2, 2 }, { 3.0, 0.0 }); // NOLINT(readability-identifier-length) conventional BLAS naming + // blas::gemm({1.0, 0.0}, blas::H(A), blas::J(B), {0.0, 0.0}, C); + // { + // multi::array CC({2, 2}, {3.0, 0.0}); + // auto const [is, js] = CC.extensions(); + // for(auto i : is) { + // for(auto j : js) { + // CC[i][j] = 0.0; + // for(auto k : A.extension()) { + // CC[i][j] += 1.0*conj(A[k][i])*conj(B[j][k]) ; + // } + // } + // } + // BOOST_TEST( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); + // BOOST_TEST( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); + + // BOOST_TEST( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); + // BOOST_TEST( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); // } // { // multi::array CC({2, 2}, {3.0, 0.0}); @@ -1768,22 +1877,22 @@ BOOST_AUTO_TEST_CASE(cublas_one_gemm_complex_herm_conj) { // }); // return std::move(Cr); // }); - // BOOST_TEST_REQUIRE( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); - // BOOST_TEST_REQUIRE( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); + // BOOST_TEST( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); + // BOOST_TEST( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); - // BOOST_TEST_REQUIRE( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); - // BOOST_TEST_REQUIRE( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); + // BOOST_TEST( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); + // BOOST_TEST( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); // } // { // multi::array CC({2, 2}, {3.0, 0.0}); // CC = blas::gemm({1.0, 0.0}, blas::T(A), blas::H(B)); - // BOOST_TEST_REQUIRE( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); - // BOOST_TEST_REQUIRE( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); + // BOOST_TEST( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); + // BOOST_TEST( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); - // BOOST_TEST_REQUIRE( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); - // BOOST_TEST_REQUIRE( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); + // BOOST_TEST( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); + // BOOST_TEST( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); // } // { // multi::array CC({2, 2}, {3.0, 0.0}); @@ -1791,84 +1900,89 @@ BOOST_AUTO_TEST_CASE(cublas_one_gemm_complex_herm_conj) { // using blas::operators::operator~; // CC = ~A * ~*B; - // BOOST_TEST_REQUIRE( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); - // BOOST_TEST_REQUIRE( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); + // BOOST_TEST( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); + // BOOST_TEST( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); - // BOOST_TEST_REQUIRE( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); - // BOOST_TEST_REQUIRE( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); + // BOOST_TEST( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); + // BOOST_TEST( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); // } } BOOST_AUTO_TEST_CASE(UTA_blas_trsm_complex_nonsquare_default_diagonal_hermitized_gemm_check_no_const) { namespace blas = multi::blas; - using complex = thrust::complex; complex const I{0.0, 1.0}; // NOLINT(readability-identifier-length) imag unit + using complex = thrust::complex; + complex const I{ 0.0, 1.0 }; // NOLINT(readability-identifier-length) imag unit using Alloc = thrust::cuda::allocator; - multi::array const A = { // NOLINT(readability-identifier-length) BLAS naming - { 1.0 + 4.0*I, 3.0 + 0.0*I, 4.0 - 10.0*I}, - { 0.0 + 0.0*I, 7.0 - 3.0*I, 1.0 + 0.0*I}, - { 0.0 + 0.0*I, 0.0 + 0.0*I, 8.0 - 2.0*I}, + multi::array const A = { + // NOLINT(readability-identifier-length) BLAS naming + {1.0 + 4.0 * I, 3.0 + 0.0 * I, 4.0 - 10.0 * I}, + {0.0 + 0.0 * I, 7.0 - 3.0 * I, 1.0 + 0.0 * I}, + {0.0 + 0.0 * I, 0.0 + 0.0 * I, 8.0 - 2.0 * I}, }; - multi::array B = { // NOLINT(readability-identifier-length) BLAS naming - {1.0 + 1.0*I, 2.0 + 1.0*I, 3.0 + 1.0*I}, - {5.0 + 3.0*I, 9.0 + 3.0*I, 1.0 - 1.0*I}, + multi::array B = { + // NOLINT(readability-identifier-length) BLAS naming + {1.0 + 1.0 * I, 2.0 + 1.0 * I, 3.0 + 1.0 * I}, + {5.0 + 3.0 * I, 9.0 + 3.0 * I, 1.0 - 1.0 * I}, }; using multi::blas::trsm; - blas::trsm(blas::side::left, {1.0, 0.0}, blas::U(A), blas::H(B)); // B†←A⁻¹.B†, B←B.A⁻¹†, B←(A⁻¹.B†)† - BOOST_REQUIRE_CLOSE( static_cast(B[1][2]).imag() , -0.147059 , 0.001); + blas::trsm(blas::side::left, { 1.0, 0.0 }, blas::U(A), blas::H(B)); // B†←A⁻¹.B†, B←B.A⁻¹†, B←(A⁻¹.B†)† + BOOST_REQUIRE_CLOSE(static_cast(B[1][2]).imag(), -0.147059, 0.001); } BOOST_AUTO_TEST_CASE(UTA_blas_trsm_complex_nonsquare_default_diagonal_hermitized_gemm_check_no_const_UTH) { namespace blas = multi::blas; - using complex = thrust::complex; complex const I{0.0, 1.0}; // NOLINT(readability-identifier-length) imag unit + using complex = thrust::complex; + complex const I{ 0.0, 1.0 }; // NOLINT(readability-identifier-length) imag unit using Alloc = thrust::cuda::allocator; // NOLINTNEXTLINE(readability-identifier-length) BLAS naming multi::array const A = { - { 1.0 + 4.0*I, 0.0 + 0.0*I, 0.0 - 0.0*I}, - { 3.0 + 0.0*I, 7.0 - 3.0*I, 0.0 + 0.0*I}, - { 4.0 - 10.0*I, 1.0 + 0.0*I, 8.0 - 2.0*I}, + { 1.0 + 4.0 * I, 0.0 + 0.0 * I, 0.0 - 0.0 * I}, + { 3.0 + 0.0 * I, 7.0 - 3.0 * I, 0.0 + 0.0 * I}, + {4.0 - 10.0 * I, 1.0 + 0.0 * I, 8.0 - 2.0 * I}, }; // NOLINTNEXTLINE(readability-identifier-length) BLAS naming multi::array B = { - {1.0 + 1.0*I, 2.0 + 1.0*I}, - {5.0 + 3.0*I, 9.0 + 3.0*I}, - {3.0 + 1.0*I, 1.0 - 1.0*I}, + {1.0 + 1.0 * I, 2.0 + 1.0 * I}, + {5.0 + 3.0 * I, 9.0 + 3.0 * I}, + {3.0 + 1.0 * I, 1.0 - 1.0 * I}, }; using multi::blas::trsm; - blas::trsm(blas::side::left, {1.0, 0.0}, blas::U(blas::H(A)), B); - BOOST_REQUIRE_CLOSE( static_cast(B[1][1]).imag(), -0.0811359, 0.001); - BOOST_REQUIRE_CLOSE( static_cast(B[2][1]).imag(), -0.147059, 0.001); + blas::trsm(blas::side::left, { 1.0, 0.0 }, blas::U(blas::H(A)), B); + BOOST_REQUIRE_CLOSE(static_cast(B[1][1]).imag(), -0.0811359, 0.001); + BOOST_REQUIRE_CLOSE(static_cast(B[2][1]).imag(), -0.147059, 0.001); } BOOST_AUTO_TEST_CASE(UTA_blas_trsm_complex_nonsquare_default_diagonal_gemm_check_no_const) { namespace blas = multi::blas; - using complex = thrust::complex; complex const I{0.0, 1.0}; // NOLINT(readability-identifier-length) imag unit + using complex = thrust::complex; + complex const I{ 0.0, 1.0 }; // NOLINT(readability-identifier-length) imag unit using Alloc = thrust::cuda::allocator; // NOLINTNEXTLINE(readability-identifier-length) BLAS naming multi::array const A = { - { 1.0 + 4.0*I, 3.0 + 0.0*I, 4.0 - 10.0*I}, - { 0.0 + 0.0*I, 7.0 - 3.0*I, 1.0 + 0.0*I}, - { 0.0 + 0.0*I, 0.0 + 0.0*I, 8.0 - 2.0*I}, + {1.0 + 4.0 * I, 3.0 + 0.0 * I, 4.0 - 10.0 * I}, + {0.0 + 0.0 * I, 7.0 - 3.0 * I, 1.0 + 0.0 * I}, + {0.0 + 0.0 * I, 0.0 + 0.0 * I, 8.0 - 2.0 * I}, }; // NOLINTNEXTLINE(readability-identifier-length) BLAS naming multi::array B = { - {1.0 + 1.0*I, 2.0 + 1.0*I}, - {5.0 + 3.0*I, 9.0 + 3.0*I}, - {3.0 + 1.0*I, 1.0 - 1.0*I}, + {1.0 + 1.0 * I, 2.0 + 1.0 * I}, + {5.0 + 3.0 * I, 9.0 + 3.0 * I}, + {3.0 + 1.0 * I, 1.0 - 1.0 * I}, }; using multi::blas::trsm; - blas::trsm(blas::side::left, {1.0, 0.0}, blas::U(A), B); // B←A⁻¹.B, B†←A⁻¹.B† - BOOST_REQUIRE_CLOSE( static_cast(B[2][1]).imag() , -0.0882353, 0.001); + blas::trsm(blas::side::left, { 1.0, 0.0 }, blas::U(A), B); // B←A⁻¹.B, B†←A⁻¹.B† + BOOST_REQUIRE_CLOSE(static_cast(B[2][1]).imag(), -0.0882353, 0.001); } // BOOST_AUTO_TEST_CASE(UTA_blas_trsm_complex_nonsquare_default_diagonal_gemm_check_no_const_conj_second) { @@ -1898,70 +2012,77 @@ BOOST_AUTO_TEST_CASE(UTA_blas_trsm_complex_nonsquare_default_diagonal_gemm_check BOOST_AUTO_TEST_CASE(UTA_blas_trsm_complex_nonsquare_default_diagonal_gemm_check_no_const_operator) { namespace blas = multi::blas; - using complex = thrust::complex; complex const I{0.0, 1.0}; // NOLINT(readability-identifier-length) imag unit + using complex = thrust::complex; + complex const I{ 0.0, 1.0 }; // NOLINT(readability-identifier-length) imag unit using Alloc = thrust::cuda::universal_allocator; - multi::array const A = { // NOLINT(readability-identifier-length) BLAS naming - { 1.0 + 4.0*I, 3.0 + 0.0*I, 4.0 - 10.0*I}, - { 0.0 + 0.0*I, 7.0 - 3.0*I, 1.0 + 0.0*I}, - { 0.0 + 0.0*I, 0.0 + 0.0*I, 8.0 - 2.0*I}, + multi::array const A = { + // NOLINT(readability-identifier-length) BLAS naming + {1.0 + 4.0 * I, 3.0 + 0.0 * I, 4.0 - 10.0 * I}, + {0.0 + 0.0 * I, 7.0 - 3.0 * I, 1.0 + 0.0 * I}, + {0.0 + 0.0 * I, 0.0 + 0.0 * I, 8.0 - 2.0 * I}, }; - multi::array B = { // NOLINT(readability-identifier-length) BLAS naming - {1.0 + 1.0*I, 2.0 + 1.0*I}, - {5.0 + 3.0*I, 9.0 + 3.0*I}, - {3.0 + 1.0*I, 1.0 - 1.0*I}, + multi::array B = { + // NOLINT(readability-identifier-length) BLAS naming + {1.0 + 1.0 * I, 2.0 + 1.0 * I}, + {5.0 + 3.0 * I, 9.0 + 3.0 * I}, + {3.0 + 1.0 * I, 1.0 - 1.0 * I}, }; using blas::operators::operator|=; using blas::operators::U; B |= U(A); // B←A⁻¹.B, B†←A⁻¹.B† - BOOST_REQUIRE_CLOSE( static_cast(B[2][1]).imag() , -0.0882353, 0.001); + BOOST_REQUIRE_CLOSE(static_cast(B[2][1]).imag(), -0.0882353, 0.001); } BOOST_AUTO_TEST_CASE(UTA_blas_trsm_complex_nonsquare_default_diagonal_gemm_check_no_const_right) { namespace blas = multi::blas; - using complex = thrust::complex; complex const I{0.0, 1.0}; // NOLINT(readability-identifier-length) imag unit + using complex = thrust::complex; + complex const I{ 0.0, 1.0 }; // NOLINT(readability-identifier-length) imag unit using Alloc = thrust::cuda::allocator; - multi::array const A = { // NOLINT(readability-identifier-length) BLAS naming - { 1.0 + 4.0*I, 3.0 + 0.0*I, 4.0 - 10.0*I}, - { 0.0 + 0.0*I, 7.0 - 3.0*I, 1.0 + 0.0*I}, - { 0.0 + 0.0*I, 0.0 + 0.0*I, 8.0 - 2.0*I}, + multi::array const A = { + // NOLINT(readability-identifier-length) BLAS naming + {1.0 + 4.0 * I, 3.0 + 0.0 * I, 4.0 - 10.0 * I}, + {0.0 + 0.0 * I, 7.0 - 3.0 * I, 1.0 + 0.0 * I}, + {0.0 + 0.0 * I, 0.0 + 0.0 * I, 8.0 - 2.0 * I}, }; - multi::array B = { // NOLINT(readability-identifier-length) BLAS naming - {1.0 + 1.0*I, 2.0 + 1.0*I, 3.0 + 1.0*I}, - {5.0 + 3.0*I, 9.0 + 3.0*I, 1.0 - 1.0*I}, + multi::array B = { + // NOLINT(readability-identifier-length) BLAS naming + {1.0 + 1.0 * I, 2.0 + 1.0 * I, 3.0 + 1.0 * I}, + {5.0 + 3.0 * I, 9.0 + 3.0 * I, 1.0 - 1.0 * I}, }; using multi::blas::trsm; - blas::trsm(blas::side::right, {1.0, 0.0}, blas::U(A), B); // B←B.A⁻¹, B←B/A, B†←A⁻¹†.B† - BOOST_REQUIRE_CLOSE( static_cast(B[1][2]).imag(), 1.60142, 0.001); + blas::trsm(blas::side::right, { 1.0, 0.0 }, blas::U(A), B); // B←B.A⁻¹, B←B/A, B†←A⁻¹†.B† + BOOST_REQUIRE_CLOSE(static_cast(B[1][2]).imag(), 1.60142, 0.001); } BOOST_AUTO_TEST_CASE(UTA_blas_trsm_complex_nonsquare_default_diagonal_gemm_check_no_const_right_LT) { namespace blas = multi::blas; - using complex = thrust::complex; complex const I{0.0, 1.0}; // NOLINT(readability-identifier-length) imag unit + using complex = thrust::complex; + complex const I{ 0.0, 1.0 }; // NOLINT(readability-identifier-length) imag unit using Alloc = thrust::cuda::allocator; // NOLINTNEXTLINE(readability-identifier-length) BLAS naming multi::array const A = { - { 1.0 + 4.0*I, 3.0 + 0.0*I, 4.0 - 10.0*I}, - { 0.0 + 0.0*I, 7.0 - 3.0*I, 1.0 + 0.0*I}, - { 0.0 + 0.0*I, 0.0 + 0.0*I, 8.0 - 2.0*I}, + {1.0 + 4.0 * I, 3.0 + 0.0 * I, 4.0 - 10.0 * I}, + {0.0 + 0.0 * I, 7.0 - 3.0 * I, 1.0 + 0.0 * I}, + {0.0 + 0.0 * I, 0.0 + 0.0 * I, 8.0 - 2.0 * I}, }; // NOLINTNEXTLINE(readability-identifier-length) BLAS naming multi::array B = { - { 1.0 + 1.0*I, 2.0 + 1.0*I, 3.0 + 1.0*I}, - { 5.0 + 3.0*I, 9.0 + 3.0*I, 1.0 - 1.0*I}, + {1.0 + 1.0 * I, 2.0 + 1.0 * I, 3.0 + 1.0 * I}, + {5.0 + 3.0 * I, 9.0 + 3.0 * I, 1.0 - 1.0 * I}, }; using multi::blas::trsm; - blas::trsm(blas::side::right, {1.0, 0.0}, blas::L(blas::T(A)), B); // B←B.Aᵀ⁻¹, B←B/Aᵀ, B†←Aᵀ⁻¹†.B†, Bᵀ←A⁻¹.Bᵀ, Bᵀ←Bᵀ\A - BOOST_REQUIRE_CLOSE( static_cast(B[1][2]).imag(), -0.0882353, 0.001); + blas::trsm(blas::side::right, { 1.0, 0.0 }, blas::L(blas::T(A)), B); // B←B.Aᵀ⁻¹, B←B/Aᵀ, B†←Aᵀ⁻¹†.B†, Bᵀ←A⁻¹.Bᵀ, Bᵀ←Bᵀ\A + BOOST_REQUIRE_CLOSE(static_cast(B[1][2]).imag(), -0.0882353, 0.001); } // BOOST_AUTO_TEST_CASE(UTA_blas_trsm_complex_nonsquare_default_diagonal_gemm_check_no_const_right_LH) { @@ -1990,24 +2111,29 @@ BOOST_AUTO_TEST_CASE(UTA_blas_trsm_complex_nonsquare_default_diagonal_gemm_check BOOST_AUTO_TEST_CASE(UTA_blas_trsm_complex_nonsquare_default_diagonal_gemm_check_no_const_right_operator) { namespace blas = multi::blas; - using complex = thrust::complex; complex const I{0.0, 1.0}; // NOLINT(readability-identifier-length) imag unit + using complex = thrust::complex; + complex const I{ 0.0, 1.0 }; // NOLINT(readability-identifier-length) imag unit using Alloc = thrust::cuda::allocator; - multi::array const A = { // NOLINT(readability-identifier-length) BLAS naming - { 1.0 + 4.0*I, 3.0 + 0.0*I, 4.0 - 10.0*I}, - { 0.0 + 0.0*I, 7.0 - 3.0*I, 1.0 + 0.0*I}, - { 0.0 + 0.0*I, 0.0 + 0.0*I, 8.0 - 2.0*I}, + multi::array const A = { + // NOLINT(readability-identifier-length) BLAS naming + {1.0 + 4.0 * I, 3.0 + 0.0 * I, 4.0 - 10.0 * I}, + {0.0 + 0.0 * I, 7.0 - 3.0 * I, 1.0 + 0.0 * I}, + {0.0 + 0.0 * I, 0.0 + 0.0 * I, 8.0 - 2.0 * I}, }; - multi::array B = { // NOLINT(readability-identifier-length) BLAS naming - {1.0 + 1.0*I, 2.0 + 1.0*I, 3.0 + 1.0*I}, - {5.0 + 3.0*I, 9.0 + 3.0*I, 1.0 - 1.0*I}, + multi::array B = { + // NOLINT(readability-identifier-length) BLAS naming + {1.0 + 1.0 * I, 2.0 + 1.0 * I, 3.0 + 1.0 * I}, + {5.0 + 3.0 * I, 9.0 + 3.0 * I, 1.0 - 1.0 * I}, }; using multi::blas::trsm; using blas::operators::operator/=; B /= blas::U(A); - BOOST_REQUIRE_CLOSE( static_cast(B[1][2]).imag(), 1.60142, 0.001); + BOOST_REQUIRE_CLOSE(static_cast(B[1][2]).imag(), 1.60142, 0.001); } #endif + +return boost::report_errors();} diff --git a/external_codes/boost_multi/multi/include/boost/multi/adaptors/cuda/cublas/test/all.hip b/external_codes/boost_multi/multi/include/boost/multi/adaptors/cuda/cublas/test/all.hip index f76986a42d..4439206ac6 100644 --- a/external_codes/boost_multi/multi/include/boost/multi/adaptors/cuda/cublas/test/all.hip +++ b/external_codes/boost_multi/multi/include/boost/multi/adaptors/cuda/cublas/test/all.hip @@ -3,14 +3,16 @@ // https://www.boost.org/LICENSE_1_0.txt #define BOOST_TEST_MODULE "C++ Unit Tests for Multi CUBLAS all" -#include +// #include #include #include #include #include +#include #include +#include #include #include #include @@ -50,6 +52,12 @@ auto generate_ABx() { return std::make_tuple(std::move(x), std::move(A), std::move(B)); } +#include +#define BOOST_AUTO_TEST_CASE(CasenamE) /**/ + +#define BOOST_REQUIRE_CLOSE(X, Y, ToL) BOOST_TEST( std::abs( (X) - (Y) ) < (ToL) ) + +int main() { BOOST_AUTO_TEST_CASE(cublas_scal_complex_column) { namespace blas = multi::blas; complex const I{0.0, 1.0}; @@ -64,25 +72,25 @@ BOOST_AUTO_TEST_CASE(cublas_scal_complex_column) { auto [x2, A2, B2] = generate_ABx >(); auto xx = +x2; blas::scal(s, xx); - BOOST_REQUIRE(xx == x); + BOOST_TEST(xx == x); } { auto [x2, A2, B2] = generate_ABx >(); using blas::operators::operator*=; x2 *= s; - BOOST_REQUIRE(x == x2); + BOOST_TEST(x == x2); } { auto [x2, A2, B2] = generate_ABx >(); thrust::transform(x2.begin(), x2.end(), x2.begin(), [s] __device__ (T& e) {return s*e;}); - BOOST_REQUIRE(x == x2); + BOOST_TEST(x == x2); } { auto [x2, A2, B2] = generate_ABx >(); thrust::for_each(x2.begin(), x2.end(), [s] __device__ (T& e) {return e*=s;}); - BOOST_REQUIRE(x == x2); + BOOST_TEST(x == x2); } } } @@ -99,34 +107,34 @@ BOOST_AUTO_TEST_CASE(cublas_copy_complex_device) { multi::array y = { 1.0 + I*9.0, 2.0 + I*6.0, 3.0 + I*5.0, 4.0 + I*3.0}; blas::copy(x, y); - BOOST_REQUIRE( static_cast(y[0]) == 1.0 + I*8.0 ); + BOOST_TEST( static_cast(y[0]) == 1.0 + I*8.0 ); { thrust::copy(begin(x), end(x), begin(y)); - BOOST_REQUIRE( static_cast(y[0]) == 1.0 + I*8.0 ); + BOOST_TEST( static_cast(y[0]) == 1.0 + I*8.0 ); } { blas::copy_n(x.begin(), x.size(), y.begin()); - BOOST_REQUIRE( static_cast(y[0]) == 1.0 + I*8.0 ); + BOOST_TEST( static_cast(y[0]) == 1.0 + I*8.0 ); } { y() = blas::copy(x); - BOOST_REQUIRE( static_cast(y[0]) == 1.0 + I*8.0 ); + BOOST_TEST( static_cast(y[0]) == 1.0 + I*8.0 ); } { multi::array yy = blas::copy(x); - BOOST_REQUIRE( static_cast(yy[0]) == 1.0 + I*8.0 ); + BOOST_TEST( static_cast(yy[0]) == 1.0 + I*8.0 ); } { y = blas::copy(x); - BOOST_REQUIRE( static_cast(y[0]) == 1.0 + I*8.0 ); + BOOST_TEST( static_cast(y[0]) == 1.0 + I*8.0 ); } { { using blas::operators::operator<<; y << x; - // BOOST_REQUIRE(( static_cast(y[0]) == 1.0 + I*8.0 )); // this can't be used with a free operator<< + // BOOST_TEST(( static_cast(y[0]) == 1.0 + I*8.0 )); // this can't be used with a free operator<< } - BOOST_REQUIRE(( static_cast(y[0]) == 1.0 + I*8.0 )); // this can't be used with a free operator<< + BOOST_TEST(( static_cast(y[0]) == 1.0 + I*8.0 )); // this can't be used with a free operator<< } } @@ -142,34 +150,34 @@ BOOST_AUTO_TEST_CASE(cublas_copy_complex) { multi::array y = { 1.0 + I*9.0, 2.0 + I*6.0, 3.0 + I*5.0, 4.0 + I*3.0}; blas::copy(x, y); - BOOST_REQUIRE( static_cast(y[0]) == 1.0 + I*8.0 ); + BOOST_TEST( static_cast(y[0]) == 1.0 + I*8.0 ); { thrust::copy(begin(x), end(x), begin(y)); - BOOST_REQUIRE( static_cast(y[0]) == 1.0 + I*8.0 ); + BOOST_TEST( static_cast(y[0]) == 1.0 + I*8.0 ); } { blas::copy_n(x.begin(), x.size(), y.begin()); - BOOST_REQUIRE( static_cast(y[0]) == 1.0 + I*8.0 ); + BOOST_TEST( static_cast(y[0]) == 1.0 + I*8.0 ); } { y() = blas::copy(x); - BOOST_REQUIRE( static_cast(y[0]) == 1.0 + I*8.0 ); + BOOST_TEST( static_cast(y[0]) == 1.0 + I*8.0 ); } { multi::array yy = blas::copy(x); - BOOST_REQUIRE( static_cast(yy[0]) == 1.0 + I*8.0 ); + BOOST_TEST( static_cast(yy[0]) == 1.0 + I*8.0 ); } { y = blas::copy(x); - BOOST_REQUIRE( static_cast(y[0]) == 1.0 + I*8.0 ); + BOOST_TEST( static_cast(y[0]) == 1.0 + I*8.0 ); } { { using blas::operators::operator<<; y << x; - // BOOST_REQUIRE(( static_cast(y[0]) == 1.0 + I*8.0 )); // this can't be used with a free operator<< + // BOOST_TEST(( static_cast(y[0]) == 1.0 + I*8.0 )); // this can't be used with a free operator<< } - BOOST_REQUIRE(( static_cast(y[0]) == 1.0 + I*8.0 )); // this can't be used with a free operator<< + BOOST_TEST(( static_cast(y[0]) == 1.0 + I*8.0 )); // this can't be used with a free operator<< } } @@ -185,17 +193,17 @@ BOOST_AUTO_TEST_CASE(cublas_swap_complex) { multi::array y = { 1.0 + I*9.0, 2.0 + I*6.0, 3.0 + I*5.0, 4.0 + I*3.0}; blas::swap(x, y); - BOOST_REQUIRE( static_cast(x[0]) == 1.0 + I*9.0 ); + BOOST_TEST( static_cast(x[0]) == 1.0 + I*9.0 ); { thrust::swap_ranges(begin(x), end(x), begin(y)); thrust::swap_ranges(begin(x), end(x), begin(y)); - BOOST_REQUIRE( static_cast(x[0]) == 1.0 + I*9.0 ); + BOOST_TEST( static_cast(x[0]) == 1.0 + I*9.0 ); } { using blas::operator^; (x^y); (x^y); - BOOST_REQUIRE( static_cast(x[0]) == 1.0 + I*9.0 ); + BOOST_TEST( static_cast(x[0]) == 1.0 + I*9.0 ); } } @@ -213,54 +221,54 @@ BOOST_AUTO_TEST_CASE(cublas_asum_complex_column) { { double res2; res2 = blas::asum(x); - BOOST_REQUIRE( res == res2 ); + BOOST_TEST( res == res2 ); } { double res2 = blas::asum(x); - BOOST_REQUIRE( res == res2 ); + BOOST_TEST( res == res2 ); } { auto res2 = std::transform_reduce( x.begin(), x.end(), double{}, std::plus<>{}, [](T const& e) {return std::abs(e.real()) + std::abs(e.imag());} ); - BOOST_REQUIRE( res == res2 ); + BOOST_TEST( res == res2 ); } { auto res2 = thrust::transform_reduce( x.begin(), x.end(), [] __device__ (T const& e) {return std::abs(e.real()) + std::abs(e.imag());}, double{}, thrust::plus<>{} ); - BOOST_REQUIRE( res == res2 ); + BOOST_TEST( res == res2 ); } { multi::static_array> res2({}, 0.0); res2.assign( &blas::asum(x) ); res2 = blas::asum(x); - BOOST_REQUIRE(( res == static_cast>::element_ref>(res2) )); - BOOST_REQUIRE(( res == static_cast(res2) )); - // BOOST_REQUIRE( res == res2 ); + BOOST_TEST(( res == static_cast>::element_ref>(res2) )); + BOOST_TEST(( res == static_cast(res2) )); + // BOOST_TEST( res == res2 ); } { multi::array> res2 = blas::asum(x); - BOOST_REQUIRE(( res == static_cast>::element_ref>(res2) )); - BOOST_REQUIRE(( res == static_cast(res2) )); - // BOOST_REQUIRE( res == res2 ); + BOOST_TEST(( res == static_cast>::element_ref>(res2) )); + BOOST_TEST(( res == static_cast(res2) )); + // BOOST_TEST( res == res2 ); } { using blas::operators::operator==; using blas::operators::operator!=; - BOOST_REQUIRE( x != 0 ); - BOOST_REQUIRE( not (x == 0) ); + BOOST_TEST( x != 0 ); + BOOST_TEST( not (x == 0) ); } { using blas::operators::contains_nan; - BOOST_REQUIRE( not contains_nan(x) ); + BOOST_TEST( not contains_nan(x) ); } { using blas::operators::isfinite; using blas::operators::isinf; - BOOST_REQUIRE( isfinite(x) ); - BOOST_REQUIRE( not isinf(x) ); + BOOST_TEST( isfinite(x) ); + BOOST_TEST( not isinf(x) ); } } @@ -275,19 +283,19 @@ BOOST_AUTO_TEST_CASE(cublas_asum_complex_nans) { { using blas::operators::contains_nan; - BOOST_REQUIRE( contains_nan(x) ); + BOOST_TEST( contains_nan(x) ); } { using blas::operators::operator==; using blas::operators::operator!=; - BOOST_REQUIRE( not (x != 0) ); - BOOST_REQUIRE( not (x == 0) ); + BOOST_TEST( not (x != 0) ); + BOOST_TEST( not (x == 0) ); } { using blas::operators::isfinite; using blas::operators::isinf; - BOOST_REQUIRE( not isfinite(x) ); - BOOST_REQUIRE( not isinf(x) ); + BOOST_TEST( not isfinite(x) ); + BOOST_TEST( not isinf(x) ); } } @@ -303,19 +311,19 @@ BOOST_AUTO_TEST_CASE(cublas_asum_complex_inf) { // double res; { using blas::operators::contains_nan; - BOOST_REQUIRE( not contains_nan(x) ); + BOOST_TEST( not contains_nan(x) ); } { using blas::operators::operator==; using blas::operators::operator!=; - BOOST_REQUIRE( (x != 0) ); - BOOST_REQUIRE( not (x == 0) ); + BOOST_TEST( (x != 0) ); + BOOST_TEST( not (x == 0) ); } { using blas::operators::isfinite; using blas::operators::isinf; - BOOST_REQUIRE( not isfinite(x) ); - BOOST_REQUIRE( isinf(x) ); + BOOST_TEST( not isfinite(x) ); + BOOST_TEST( isinf(x) ); } } @@ -333,22 +341,22 @@ BOOST_AUTO_TEST_CASE(cublas_nrm2_complex_column) { { double res2; res2 = blas::nrm2(x); - BOOST_REQUIRE( res == res2 ); + BOOST_TEST( res == res2 ); } { auto res2 = +blas::nrm2(x); - BOOST_REQUIRE( res == res2 ); + BOOST_TEST( res == res2 ); } { auto res2 = sqrt(thrust::transform_reduce( x.begin(), x.end(), [] __device__ (T const& e) {return thrust::norm(e);}, double{}, thrust::plus<>{} )); - BOOST_REQUIRE( res == res2 ); + BOOST_TEST( res == res2 ); } { multi::array> res2 = blas::nrm2(x); - BOOST_REQUIRE(( res == static_cast(res2) )); + BOOST_TEST(( res == static_cast(res2) )); } } @@ -368,27 +376,27 @@ BOOST_AUTO_TEST_CASE(cublas_dot_complex_column) { { complex res2; res2 = blas::dot(x, y); - BOOST_REQUIRE(res == res2); + BOOST_TEST(res == res2); } { multi::array res2(complex{1.0, 0.0}); res2 = blas::dot(x, y); - BOOST_REQUIRE( static_cast(res2) == res ); + BOOST_TEST( static_cast(res2) == res ); } { using blas::operators::operator,; auto res2 = +(x, y); - BOOST_REQUIRE(res == res2); + BOOST_TEST(res == res2); } { auto res2 = +blas::dot(x, y); - BOOST_REQUIRE(res == res2); + BOOST_TEST(res == res2); } { // auto [x2, A2, B2] = generate_ABx >(); // thrust::for_each(x2.begin(), x2.end(), [s] __device__ (T& e) {return e*=s;}); auto res2 = thrust::inner_product(x.begin(), x.end(), y.begin(), T{}); - BOOST_REQUIRE(res == res2); + BOOST_TEST(res == res2); } } { @@ -398,17 +406,17 @@ BOOST_AUTO_TEST_CASE(cublas_dot_complex_column) { using blas::operators::operator,; using blas::operators::operator*; auto res2 = +(*x, y); - BOOST_REQUIRE(res == res2); + BOOST_TEST(res == res2); } { auto res2 = +blas::dot(blas::C(x), y); - BOOST_REQUIRE(res == res2); + BOOST_TEST(res == res2); } { // auto [x2, A2, B2] = generate_ABx >(); // thrust::for_each(x2.begin(), x2.end(), [s] __device__ (T& e) {return e*=s;}); auto res2 = thrust::inner_product(x.begin(), x.end(), y.begin(), T{}, thrust::plus<>{}, [] __device__ (T const& t1, T const& t2) {return conj(t1)*t2;}); - BOOST_REQUIRE(res == res2); + BOOST_TEST(res == res2); } } { @@ -417,21 +425,21 @@ BOOST_AUTO_TEST_CASE(cublas_dot_complex_column) { { using blas::operators::operator,; auto res2 = +(x, blas::C(y)); - BOOST_REQUIRE(res == res2); + BOOST_TEST(res == res2); } { auto res2 = +blas::dot(x, blas::C(y)); - BOOST_REQUIRE(res == res2); + BOOST_TEST(res == res2); } { // auto [x2, A2, B2] = generate_ABx >(); // thrust::for_each(x2.begin(), x2.end(), [s] __device__ (T& e) {return e*=s;}); auto res2 = thrust::inner_product(x.begin(), x.end(), y.begin(), T{}, thrust::plus<>{}, [] __device__ (T const& t1, T const& t2) {return t1*conj(t2);}); - BOOST_REQUIRE(res == res2); + BOOST_TEST(res == res2); } { - BOOST_REQUIRE( blas::dot(blas::C(x), x) == pow(blas::nrm2(x), 2.0) ); - BOOST_REQUIRE( blas::dot(x, blas::C(x)) == pow(blas::nrm2(x), 2.0) ); + BOOST_TEST( blas::dot(blas::C(x), x) == pow(blas::nrm2(x), 2.0) ); + BOOST_TEST( blas::dot(x, blas::C(x)) == pow(blas::nrm2(x), 2.0) ); using blas::operators::operator,; using blas::operators::operator*; @@ -439,15 +447,15 @@ BOOST_AUTO_TEST_CASE(cublas_dot_complex_column) { using blas::operators::norm; using blas::operators::operator^; - BOOST_REQUIRE( (*x, x) == pow(abs(x), 2.0) ); - BOOST_REQUIRE( (*x, x) == pow(abs(x), 2) ); - BOOST_REQUIRE( (*x, x) == norm(x) ); + BOOST_TEST( (*x, x) == pow(abs(x), 2.0) ); + BOOST_TEST( (*x, x) == pow(abs(x), 2) ); + BOOST_TEST( (*x, x) == norm(x) ); - BOOST_REQUIRE( (x, *x) == pow(abs(x), 2.0) ); - BOOST_REQUIRE( (x, *x) == pow(abs(x), 2) ); - BOOST_REQUIRE( (x, *x) == norm(x) ); + BOOST_TEST( (x, *x) == pow(abs(x), 2.0) ); + BOOST_TEST( (x, *x) == pow(abs(x), 2) ); + BOOST_TEST( (x, *x) == norm(x) ); - BOOST_REQUIRE( (*x, x) == (x^2) ); + BOOST_TEST( (*x, x) == (x^2) ); } } { @@ -458,21 +466,21 @@ BOOST_AUTO_TEST_CASE(cublas_dot_complex_column) { // { // using blas::operators::operator,; // auto res2 = +(x, blas::C(y)); - // BOOST_REQUIRE(res == res2); + // BOOST_TEST(res == res2); // } // { // auto res2 = +blas::dot(x, blas::C(y)); - // BOOST_REQUIRE(res == res2); + // BOOST_TEST(res == res2); // } // { // // auto [x2, A2, B2] = generate_ABx >(); // // thrust::for_each(x2.begin(), x2.end(), [s] __device__ (T& e) {return e*=s;}); // auto res2 = thrust::inner_product(x.begin(), x.end(), y.begin(), T{}, thrust::plus<>{}, [] __device__ (T const& t1, T const& t2) {return t1*conj(t2);}); - // BOOST_REQUIRE(res == res2); + // BOOST_TEST(res == res2); // } // { - // BOOST_REQUIRE( blas::dot(blas::C(x), x) == pow(blas::nrm2(x), 2.0) ); - // BOOST_REQUIRE( blas::dot(x, blas::C(x)) == pow(blas::nrm2(x), 2.0) ); + // BOOST_TEST( blas::dot(blas::C(x), x) == pow(blas::nrm2(x), 2.0) ); + // BOOST_TEST( blas::dot(x, blas::C(x)) == pow(blas::nrm2(x), 2.0) ); // using blas::operators::operator,; // using blas::operators::operator*; @@ -480,15 +488,15 @@ BOOST_AUTO_TEST_CASE(cublas_dot_complex_column) { // using blas::operators::norm; // using blas::operators::operator^; - // BOOST_REQUIRE( (*x, x) == pow(abs(x), 2.0) ); - // BOOST_REQUIRE( (*x, x) == pow(abs(x), 2) ); - // BOOST_REQUIRE( (*x, x) == norm(x) ); + // BOOST_TEST( (*x, x) == pow(abs(x), 2.0) ); + // BOOST_TEST( (*x, x) == pow(abs(x), 2) ); + // BOOST_TEST( (*x, x) == norm(x) ); - // BOOST_REQUIRE( (x, *x) == pow(abs(x), 2.0) ); - // BOOST_REQUIRE( (x, *x) == pow(abs(x), 2) ); - // BOOST_REQUIRE( (x, *x) == norm(x) ); + // BOOST_TEST( (x, *x) == pow(abs(x), 2.0) ); + // BOOST_TEST( (x, *x) == pow(abs(x), 2) ); + // BOOST_TEST( (x, *x) == norm(x) ); - // BOOST_REQUIRE( (*x, x) == (x^2) ); + // BOOST_TEST( (*x, x) == (x^2) ); // } } } @@ -505,17 +513,17 @@ BOOST_AUTO_TEST_CASE(cublas_axpy_complex_one) { blas::axpy(1.0, x, y); std::cout << y[0] << std::endl; - BOOST_REQUIRE( static_cast(y[0]) == 3.2 + I*0.0 ); + BOOST_TEST( static_cast(y[0]) == 3.2 + I*0.0 ); { multi::array yy = { {2.1, 0.0}, {4.1, 0.0}, {6.1, 0.0}, {11.0, 0.0} }; // NOLINT(readability-identifier-length) BLAS naming thrust::transform(x.begin(), x.end(), yy.begin(), yy.begin(), [] __device__ (auto const& ex, auto const& ey) {return ex + ey;}); - BOOST_TEST( yy == y , boost::test_tools::per_element() ); + BOOST_TEST( yy == y ); } { multi::array yy = { {2.1, 0.0}, {4.1, 0.0}, {6.1, 0.0}, {11.0, 0.0} }; using blas::operators::operator+=; yy += x; - BOOST_REQUIRE( yy == y ); + BOOST_TEST( yy == y ); } } @@ -531,17 +539,17 @@ BOOST_AUTO_TEST_CASE(cublas_axpy_complex_mone) { blas::axpy(-1.0, x, y); std::cout << y[0] << std::endl; - BOOST_REQUIRE( static_cast(y[0]) == 1.0 + I*0.0 ); + BOOST_TEST( static_cast(y[0]) == 1.0 + I*0.0 ); { multi::array yy = { {2.1, 0.0}, {4.1, 0.0}, {6.1, 0.0}, {11.0, 0.0} }; // NOLINT(readability-identifier-length) BLAS naming thrust::transform(x.begin(), x.end(), yy.begin(), yy.begin(), [] __host__ __device__ (T ex, T ey) {return -1.0*ex + ey;}); - BOOST_TEST( yy == y , boost::test_tools::per_element() ); + BOOST_TEST( yy == y ); } { multi::array yy = { {2.1, 0.0}, {4.1, 0.0}, {6.1, 0.0}, {11.0, 0.0} }; using blas::operators::operator-=; yy -= x; - BOOST_REQUIRE( yy == y ); + BOOST_TEST( yy == y ); } { multi::array yy = { {2.1, 0.0}, {4.1, 0.0}, {6.1, 0.0}, {11.0, 0.0} }; @@ -549,10 +557,10 @@ BOOST_AUTO_TEST_CASE(cublas_axpy_complex_mone) { yy -= x; yy -= y; using blas::operators::norm; - BOOST_REQUIRE( norm(yy) == 0 ); + BOOST_TEST( norm(yy) == 0 ); using blas::operators::operator==; - BOOST_REQUIRE( operator==(yy, 0) ); - BOOST_REQUIRE( yy == 0 ); + BOOST_TEST( operator==(yy, 0) ); + BOOST_TEST( yy == 0 ); } } @@ -568,18 +576,18 @@ BOOST_AUTO_TEST_CASE(cublas_axpy_complex_alpha) { blas::axpy(3.0, x, y); std::cout << y[0] << std::endl; - BOOST_REQUIRE( static_cast(y[0]) == 5.4 + I*0.0 ); + BOOST_TEST( static_cast(y[0]) == 5.4 + I*0.0 ); { multi::array yy = { {2.1, 0.0}, {4.1, 0.0}, {6.1, 0.0}, {11.0, 0.0} }; // NOLINT(readability-identifier-length) BLAS naming thrust::transform(x.begin(), x.end(), yy.begin(), yy.begin(), [aa=3.0] __device__ (T ex, T ey) {return aa*ex + ey;}); - BOOST_TEST( yy == y , boost::test_tools::per_element() ); + BOOST_TEST( yy == y ); } { multi::array yy = { {2.1, 0.0}, {4.1, 0.0}, {6.1, 0.0}, {11.0, 0.0} }; using blas::operators::operator+=; using blas::operators::operator*; yy += 3.0*x; - BOOST_REQUIRE( yy == y ); + BOOST_TEST( yy == y ); } } @@ -603,22 +611,22 @@ BOOST_AUTO_TEST_CASE(cublas_one_gemv_conj_complex_zero) { multi::array yy = { {1.1, 0.0}, {2.1, 0.0}, {3.1, 0.0} }; // NOLINT(readability-identifier-length) BLAS naming std::transform(begin(A), end(A), begin(yy), [&x] (auto const& Ac) {return blas::dot(Ac, x);}); - BOOST_REQUIRE( static_cast(y[0]) == static_cast(yy[0]) ); - BOOST_REQUIRE( static_cast(y[1]) == static_cast(yy[1]) ); - BOOST_REQUIRE( static_cast(y[2]) == static_cast(yy[2]) ); + BOOST_TEST( static_cast(y[0]) == static_cast(yy[0]) ); + BOOST_TEST( static_cast(y[1]) == static_cast(yy[1]) ); + BOOST_TEST( static_cast(y[2]) == static_cast(yy[2]) ); } { multi::array yy = { {1.1, 0.0}, {2.1, 0.0}, {3.1, 0.0} }; // NOLINT(readability-identifier-length) BLAS naming yy = blas::gemv(1.0, A, x); - BOOST_REQUIRE( static_cast(y[0]) == static_cast(yy[0]) ); - BOOST_REQUIRE( static_cast(y[1]) == static_cast(yy[1]) ); - BOOST_REQUIRE( static_cast(y[2]) == static_cast(yy[2]) ); + BOOST_TEST( static_cast(y[0]) == static_cast(yy[0]) ); + BOOST_TEST( static_cast(y[1]) == static_cast(yy[1]) ); + BOOST_TEST( static_cast(y[2]) == static_cast(yy[2]) ); } { multi::array yy = blas::gemv(1.0, A, x); - BOOST_REQUIRE( static_cast(y[0]) == static_cast(yy[0]) ); - BOOST_REQUIRE( static_cast(y[1]) == static_cast(yy[1]) ); - BOOST_REQUIRE( static_cast(y[2]) == static_cast(yy[2]) ); + BOOST_TEST( static_cast(y[0]) == static_cast(yy[0]) ); + BOOST_TEST( static_cast(y[1]) == static_cast(yy[1]) ); + BOOST_TEST( static_cast(y[2]) == static_cast(yy[2]) ); } { @@ -626,9 +634,9 @@ BOOST_AUTO_TEST_CASE(cublas_one_gemv_conj_complex_zero) { multi::array yy = { {1.1, 0.0}, {2.1, 0.0}, {3.1, 0.0} }; // NOLINT(readability-identifier-length) BLAS naming yy = A % x; - BOOST_REQUIRE( static_cast(y[0]) == static_cast(yy[0]) ); - BOOST_REQUIRE( static_cast(y[1]) == static_cast(yy[1]) ); - BOOST_REQUIRE( static_cast(y[2]) == static_cast(yy[2]) ); + BOOST_TEST( static_cast(y[0]) == static_cast(yy[0]) ); + BOOST_TEST( static_cast(y[1]) == static_cast(yy[1]) ); + BOOST_TEST( static_cast(y[2]) == static_cast(yy[2]) ); } } @@ -653,35 +661,33 @@ BOOST_AUTO_TEST_CASE(cublas_one_gemv_complex_conj_zero) { std::transform(begin(transposed(A)), end(transposed(A)), begin(yy), [&x] (auto const& Ac) {return blas::dot(Ac, x);}); BOOST_REQUIRE_CLOSE( static_cast(y[0]).real(), static_cast(yy[0]).real(), 1e-7 ); - BOOST_REQUIRE( static_cast(y[1]) == static_cast(yy[1]) ); - BOOST_REQUIRE( static_cast(y[2]) == static_cast(yy[2]) ); + BOOST_TEST( static_cast(y[1]) == static_cast(yy[1]) ); + BOOST_TEST( static_cast(y[2]) == static_cast(yy[2]) ); } { multi::array yy = { 1.1 + I* 0.0, 2.1 +I* 0.0, 3.1 + I* 0.0, 6.7 + I*0.0 }; // NOLINT(readability-identifier-length) BLAS naming yy = blas::gemv(1.0, blas::T(A), x); - BOOST_REQUIRE( static_cast(y[0]) == static_cast(yy[0]) ); - BOOST_REQUIRE( static_cast(y[1]) == static_cast(yy[1]) ); - BOOST_REQUIRE( static_cast(y[2]) == static_cast(yy[2]) ); + BOOST_TEST( static_cast(y[0]) == static_cast(yy[0]) ); + BOOST_TEST( static_cast(y[1]) == static_cast(yy[1]) ); + BOOST_TEST( static_cast(y[2]) == static_cast(yy[2]) ); } { multi::array yy = blas::gemv(1.0, blas::T(A), x); - BOOST_REQUIRE( static_cast(y[0]) == static_cast(yy[0]) ); - BOOST_REQUIRE( static_cast(y[1]) == static_cast(yy[1]) ); - BOOST_REQUIRE( static_cast(y[2]) == static_cast(yy[2]) ); + BOOST_TEST( static_cast(y[0]) == static_cast(yy[0]) ); + BOOST_TEST( static_cast(y[1]) == static_cast(yy[1]) ); + BOOST_TEST( static_cast(y[2]) == static_cast(yy[2]) ); } { using blas::operators::operator%; multi::array yy = { 1.1 + I* 0.0, 2.1 +I* 0.0, 3.1 + I* 0.0, 6.7 + I*0.0 }; // NOLINT(readability-identifier-length) BLAS naming yy = ~A % x; - BOOST_REQUIRE( static_cast(y[0]) == static_cast(yy[0]) ); - BOOST_REQUIRE( static_cast(y[1]) == static_cast(yy[1]) ); - BOOST_REQUIRE( static_cast(y[2]) == static_cast(yy[2]) ); + BOOST_TEST( static_cast(y[0]) == static_cast(yy[0]) ); + BOOST_TEST( static_cast(y[1]) == static_cast(yy[1]) ); + BOOST_TEST( static_cast(y[2]) == static_cast(yy[2]) ); } } -template void what(T&&) = delete; - BOOST_AUTO_TEST_CASE(cublas_one_gemv_complex_zero) { namespace blas = multi::blas; using T = complex; @@ -704,22 +710,22 @@ BOOST_AUTO_TEST_CASE(cublas_one_gemv_complex_zero) { return blas::dot(*Ac, x);} ); - BOOST_REQUIRE( static_cast(y[0]) == static_cast(yy[0]) ); - BOOST_REQUIRE( static_cast(y[1]) == static_cast(yy[1]) ); - BOOST_REQUIRE( static_cast(y[2]) == static_cast(yy[2]) ); + BOOST_TEST( static_cast(y[0]) == static_cast(yy[0]) ); + BOOST_TEST( static_cast(y[1]) == static_cast(yy[1]) ); + BOOST_TEST( static_cast(y[2]) == static_cast(yy[2]) ); } { multi::array yy = { {1.1, 0.0}, {2.1, 0.0}, {3.1, 0.0} }; // NOLINT(readability-identifier-length) BLAS naming yy = blas::gemv(1.0, blas::J(A), x); - BOOST_REQUIRE( static_cast(y[0]) == static_cast(yy[0]) ); - BOOST_REQUIRE( static_cast(y[1]) == static_cast(yy[1]) ); - BOOST_REQUIRE( static_cast(y[2]) == static_cast(yy[2]) ); + BOOST_TEST( static_cast(y[0]) == static_cast(yy[0]) ); + BOOST_TEST( static_cast(y[1]) == static_cast(yy[1]) ); + BOOST_TEST( static_cast(y[2]) == static_cast(yy[2]) ); } { multi::array yy = blas::gemv(1.0, blas::J(A), x); - BOOST_REQUIRE( static_cast(y[0]) == static_cast(yy[0]) ); - BOOST_REQUIRE( static_cast(y[1]) == static_cast(yy[1]) ); - BOOST_REQUIRE( static_cast(y[2]) == static_cast(yy[2]) ); + BOOST_TEST( static_cast(y[0]) == static_cast(yy[0]) ); + BOOST_TEST( static_cast(y[1]) == static_cast(yy[1]) ); + BOOST_TEST( static_cast(y[2]) == static_cast(yy[2]) ); } { @@ -728,9 +734,9 @@ BOOST_AUTO_TEST_CASE(cublas_one_gemv_complex_zero) { multi::array yy = { {1.1, 0.0}, {2.1, 0.0}, {3.1, 0.0} }; // NOLINT(readability-identifier-length) BLAS naming yy = *A % x; - BOOST_REQUIRE( static_cast(y[0]) == static_cast(yy[0]) ); - BOOST_REQUIRE( static_cast(y[1]) == static_cast(yy[1]) ); - BOOST_REQUIRE( static_cast(y[2]) == static_cast(yy[2]) ); + BOOST_TEST( static_cast(y[0]) == static_cast(yy[0]) ); + BOOST_TEST( static_cast(y[1]) == static_cast(yy[1]) ); + BOOST_TEST( static_cast(y[2]) == static_cast(yy[2]) ); } } @@ -791,16 +797,16 @@ BOOST_AUTO_TEST_CASE(cublas_one_gemv_complex_trans_one) { std::transform(begin(transposed(A)), end(transposed(A)), begin(yy), begin(yy), [&x,aa=3.0 + I*4.0,bb=1.0] (auto const& Ac, complex e) {return aa*blas::dot(Ac, x) + bb*e;}); BOOST_REQUIRE_CLOSE( static_cast(y[0]).real(), static_cast(yy[0]).real(), 1e-7 ); - BOOST_REQUIRE( static_cast(y[1]) == static_cast(yy[1]) ); - BOOST_REQUIRE( static_cast(y[2]) == static_cast(yy[2]) ); + BOOST_TEST( static_cast(y[1]) == static_cast(yy[1]) ); + BOOST_TEST( static_cast(y[2]) == static_cast(yy[2]) ); } { multi::array yy = { 1.1 + I* 0.0, 2.1 +I* 0.0, 3.1 + I* 0.0, 6.7 + I*0.0 }; // NOLINT(readability-identifier-length) BLAS naming yy += blas::gemv(3.0 + I*4.0, blas::T(A), x); BOOST_REQUIRE_CLOSE( static_cast(y[0]).real(), static_cast(yy[0]).real(), 1e-7 ); - BOOST_REQUIRE( static_cast(y[1]) == static_cast(yy[1]) ); - BOOST_REQUIRE( static_cast(y[2]) == static_cast(yy[2]) ); + BOOST_TEST( static_cast(y[1]) == static_cast(yy[1]) ); + BOOST_TEST( static_cast(y[2]) == static_cast(yy[2]) ); } { multi::array yy = { 1.1 + I* 0.0, 2.1 +I* 0.0, 3.1 + I* 0.0, 6.7 + I*0.0 }; // NOLINT(readability-identifier-length) BLAS naming @@ -808,8 +814,8 @@ BOOST_AUTO_TEST_CASE(cublas_one_gemv_complex_trans_one) { yy += (3.0 + I*4.0)* ~A % x; BOOST_REQUIRE_CLOSE( static_cast(y[0]).real(), static_cast(yy[0]).real(), 1e-7 ); - BOOST_REQUIRE( static_cast(y[1]) == static_cast(yy[1]) ); - BOOST_REQUIRE( static_cast(y[2]) == static_cast(yy[2]) ); + BOOST_TEST( static_cast(y[1]) == static_cast(yy[1]) ); + BOOST_TEST( static_cast(y[2]) == static_cast(yy[2]) ); } } @@ -840,8 +846,8 @@ BOOST_AUTO_TEST_CASE(cublas_one_gemm_complex_trans_none) { [&B, aa=1.0, bb=0] (auto const& Ar, auto&& Cr) {return blas::gemv(aa, blas::T(B), Ar, bb, std::move(Cr));} ); - BOOST_REQUIRE( static_cast(C_copy[1][0]) == static_cast(C[1][0]) ); - BOOST_REQUIRE( static_cast(C_copy[0][1]) == static_cast(C[0][1]) ); + BOOST_TEST( static_cast(C_copy[1][0]) == static_cast(C[1][0]) ); + BOOST_TEST( static_cast(C_copy[0][1]) == static_cast(C[0][1]) ); } { multi::array C({2, 2}, {3.0, 0.0}); // NOLINT(readability-identifier-length) conventional BLAS naming @@ -856,8 +862,8 @@ BOOST_AUTO_TEST_CASE(cublas_one_gemm_complex_trans_none) { } ); - BOOST_REQUIRE( static_cast(C_copy[1][0]) == static_cast(C[1][0]) ); - BOOST_REQUIRE( static_cast(C_copy[0][1]) == static_cast(C[0][1]) ); + BOOST_TEST( static_cast(C_copy[1][0]) == static_cast(C[1][0]) ); + BOOST_TEST( static_cast(C_copy[0][1]) == static_cast(C[0][1]) ); } { multi::array C({2, 2}, {3.0, 0.0}); // NOLINT(readability-identifier-length) conventional BLAS naming @@ -868,8 +874,8 @@ BOOST_AUTO_TEST_CASE(cublas_one_gemm_complex_trans_none) { [&A, aa=1.0, bb=1.0] (auto const& Bc, auto&& Cc) {return blas::gemv(aa, A, Bc, bb, std::move(Cc));} ); - BOOST_REQUIRE( static_cast(C_copy[1][0]) == static_cast(C[1][0]) ); - BOOST_REQUIRE( static_cast(C_copy[0][1]) == static_cast(C[0][1]) ); + BOOST_TEST( static_cast(C_copy[1][0]) == static_cast(C[1][0]) ); + BOOST_TEST( static_cast(C_copy[0][1]) == static_cast(C[0][1]) ); } { multi::array C({2, 2}, {3.0, 0.0}); // NOLINT(readability-identifier-length) conventional BLAS naming @@ -883,8 +889,8 @@ BOOST_AUTO_TEST_CASE(cublas_one_gemm_complex_trans_none) { } ); - BOOST_REQUIRE( static_cast(C_copy[1][0]) == static_cast(C[1][0]) ); - BOOST_REQUIRE( static_cast(C_copy[0][1]) == static_cast(C[0][1]) ); + BOOST_TEST( static_cast(C_copy[1][0]) == static_cast(C[1][0]) ); + BOOST_TEST( static_cast(C_copy[0][1]) == static_cast(C[0][1]) ); } } @@ -912,8 +918,8 @@ BOOST_AUTO_TEST_CASE(cublas_one_gemm_complex_trans_second) { [&A, aa=1.0, bb=0.0] (auto const& Bc, auto&& Cc) {return blas::gemv(aa, A, Bc, bb, std::move(Cc));} ); - BOOST_REQUIRE( static_cast(C_copy[1][0]) == static_cast(C[1][0]) ); - BOOST_REQUIRE( static_cast(C_copy[0][1]) == static_cast(C[0][1]) ); + BOOST_TEST( static_cast(C_copy[1][0]) == static_cast(C[1][0]) ); + BOOST_TEST( static_cast(C_copy[0][1]) == static_cast(C[0][1]) ); } { multi::array C({2, 2}, {3.0, 0.0}); // NOLINT(readability-identifier-length) conventional BLAS naming @@ -927,8 +933,8 @@ BOOST_AUTO_TEST_CASE(cublas_one_gemm_complex_trans_second) { return blas::gemv(aa, B, Ac, bb, std::move(Cr)); }); - BOOST_REQUIRE( static_cast(C_copy[1][0]) == static_cast(C[1][0]) ); - BOOST_REQUIRE( static_cast(C_copy[0][1]) == static_cast(C[0][1]) ); + BOOST_TEST( static_cast(C_copy[1][0]) == static_cast(C[1][0]) ); + BOOST_TEST( static_cast(C_copy[0][1]) == static_cast(C[0][1]) ); } { multi::array C({2, 2}, {3.0, 0.0}); // NOLINT(readability-identifier-length) conventional BLAS naming @@ -939,8 +945,8 @@ BOOST_AUTO_TEST_CASE(cublas_one_gemm_complex_trans_second) { [&A, aa=1.0, bb=1.0] (auto const& Bc, auto&& Cc) {return blas::gemv(aa, A, Bc, bb, std::move(Cc));} ); - BOOST_REQUIRE( static_cast(C_copy[1][0]) == static_cast(C[1][0]) ); - BOOST_REQUIRE( static_cast(C_copy[0][1]) == static_cast(C[0][1]) ); + BOOST_TEST( static_cast(C_copy[1][0]) == static_cast(C[1][0]) ); + BOOST_TEST( static_cast(C_copy[0][1]) == static_cast(C[0][1]) ); } { multi::array C({2, 2}, {3.0, 0.0}); // NOLINT(readability-identifier-length) conventional BLAS naming @@ -954,8 +960,8 @@ BOOST_AUTO_TEST_CASE(cublas_one_gemm_complex_trans_second) { } ); - BOOST_REQUIRE( static_cast(C_copy[1][0]) == static_cast(C[1][0]) ); - BOOST_REQUIRE( static_cast(C_copy[0][1]) == static_cast(C[0][1]) ); + BOOST_TEST( static_cast(C_copy[1][0]) == static_cast(C[1][0]) ); + BOOST_TEST( static_cast(C_copy[0][1]) == static_cast(C[0][1]) ); } { multi::array C({2, 2}, {3.0, 0.0}); // NOLINT(readability-identifier-length) conventional BLAS naming @@ -969,8 +975,8 @@ BOOST_AUTO_TEST_CASE(cublas_one_gemm_complex_trans_second) { } ); - BOOST_REQUIRE( static_cast(C_copy[1][0]) == static_cast(C[1][0]) ); - BOOST_REQUIRE( static_cast(C_copy[0][1]) == static_cast(C[0][1]) ); + BOOST_TEST( static_cast(C_copy[1][0]) == static_cast(C[1][0]) ); + BOOST_TEST( static_cast(C_copy[0][1]) == static_cast(C[0][1]) ); } } @@ -998,8 +1004,8 @@ BOOST_AUTO_TEST_CASE(cublas_one_gemm_complex_trans_first) { [&A, aa=1.0, bb=0.0] (auto const& Bc, auto&& Cc) {return blas::gemv(aa, blas::T(A), Bc, bb, std::move(Cc));} ); - BOOST_REQUIRE( static_cast(C_copy[1][0]) == static_cast(C[1][0]) ); - BOOST_REQUIRE( static_cast(C_copy[0][1]) == static_cast(C[0][1]) ); + BOOST_TEST( static_cast(C_copy[1][0]) == static_cast(C[1][0]) ); + BOOST_TEST( static_cast(C_copy[0][1]) == static_cast(C[0][1]) ); } { multi::array C({2, 2}, {3.0, 0.0}); // NOLINT(readability-identifier-length) conventional BLAS naming @@ -1013,8 +1019,8 @@ BOOST_AUTO_TEST_CASE(cublas_one_gemm_complex_trans_first) { return blas::gemv(aa, blas::T(B), Ac, bb, std::move(Cr)); }); - BOOST_REQUIRE( static_cast(C_copy[1][0]) == static_cast(C[1][0]) ); - BOOST_REQUIRE( static_cast(C_copy[0][1]) == static_cast(C[0][1]) ); + BOOST_TEST( static_cast(C_copy[1][0]) == static_cast(C[1][0]) ); + BOOST_TEST( static_cast(C_copy[0][1]) == static_cast(C[0][1]) ); } { multi::array C({2, 2}, {3.0, 0.0}); // NOLINT(readability-identifier-length) conventional BLAS naming @@ -1025,8 +1031,8 @@ BOOST_AUTO_TEST_CASE(cublas_one_gemm_complex_trans_first) { [&A, aa=1.0, bb=1.0] (auto const& Bc, auto&& Cc) {return blas::gemv(aa, blas::T(A), Bc, bb, std::move(Cc));} ); - BOOST_REQUIRE( static_cast(C_copy[1][0]) == static_cast(C[1][0]) ); - BOOST_REQUIRE( static_cast(C_copy[0][1]) == static_cast(C[0][1]) ); + BOOST_TEST( static_cast(C_copy[1][0]) == static_cast(C[1][0]) ); + BOOST_TEST( static_cast(C_copy[0][1]) == static_cast(C[0][1]) ); } { multi::array C({2, 2}, {3.0, 0.0}); // NOLINT(readability-identifier-length) conventional BLAS naming @@ -1040,8 +1046,8 @@ BOOST_AUTO_TEST_CASE(cublas_one_gemm_complex_trans_first) { } ); - BOOST_REQUIRE( static_cast(C_copy[1][0]) == static_cast(C[1][0]) ); - BOOST_REQUIRE( static_cast(C_copy[0][1]) == static_cast(C[0][1]) ); + BOOST_TEST( static_cast(C_copy[1][0]) == static_cast(C[1][0]) ); + BOOST_TEST( static_cast(C_copy[0][1]) == static_cast(C[0][1]) ); } { multi::array C({2, 2}, {3.0, 0.0}); // NOLINT(readability-identifier-length) conventional BLAS naming @@ -1055,8 +1061,8 @@ BOOST_AUTO_TEST_CASE(cublas_one_gemm_complex_trans_first) { } ); - BOOST_REQUIRE( static_cast(C_copy[1][0]) == static_cast(C[1][0]) ); - BOOST_REQUIRE( static_cast(C_copy[0][1]) == static_cast(C[0][1]) ); + BOOST_TEST( static_cast(C_copy[1][0]) == static_cast(C[1][0]) ); + BOOST_TEST( static_cast(C_copy[0][1]) == static_cast(C[0][1]) ); } } @@ -1084,8 +1090,8 @@ BOOST_AUTO_TEST_CASE(cublas_one_gemm_complex_trans_both) { [&A, aa=1.0, bb=0.0] (auto const& Br, auto&& Cc) {return blas::gemv(aa, blas::T(A), Br, bb, std::move(Cc));} ); - BOOST_REQUIRE( static_cast(C_copy[1][0]) == static_cast(C[1][0]) ); - BOOST_REQUIRE( static_cast(C_copy[0][1]) == static_cast(C[0][1]) ); + BOOST_TEST( static_cast(C_copy[1][0]) == static_cast(C[1][0]) ); + BOOST_TEST( static_cast(C_copy[0][1]) == static_cast(C[0][1]) ); } { multi::array C({2, 2}, {3.0, 0.0}); // NOLINT(readability-identifier-length) conventional BLAS naming @@ -1099,8 +1105,8 @@ BOOST_AUTO_TEST_CASE(cublas_one_gemm_complex_trans_both) { return blas::gemv(aa, B, Ac, bb, std::move(Cr)); }); - BOOST_REQUIRE( static_cast(C_copy[1][0]) == static_cast(C[1][0]) ); - BOOST_REQUIRE( static_cast(C_copy[0][1]) == static_cast(C[0][1]) ); + BOOST_TEST( static_cast(C_copy[1][0]) == static_cast(C[1][0]) ); + BOOST_TEST( static_cast(C_copy[0][1]) == static_cast(C[0][1]) ); } { multi::array C({2, 2}, {3.0, 0.0}); // NOLINT(readability-identifier-length) conventional BLAS naming @@ -1111,8 +1117,8 @@ BOOST_AUTO_TEST_CASE(cublas_one_gemm_complex_trans_both) { [&A, aa=1.0, bb=1.0] (auto const& Br, auto&& Cc) {return blas::gemv(aa, blas::T(A), Br, bb, std::move(Cc));} ); - BOOST_REQUIRE( static_cast(C_copy[1][0]) == static_cast(C[1][0]) ); - BOOST_REQUIRE( static_cast(C_copy[0][1]) == static_cast(C[0][1]) ); + BOOST_TEST( static_cast(C_copy[1][0]) == static_cast(C[1][0]) ); + BOOST_TEST( static_cast(C_copy[0][1]) == static_cast(C[0][1]) ); } { multi::array C({2, 2}, {3.0, 0.0}); // NOLINT(readability-identifier-length) conventional BLAS naming @@ -1126,8 +1132,8 @@ BOOST_AUTO_TEST_CASE(cublas_one_gemm_complex_trans_both) { } ); - BOOST_REQUIRE( static_cast(C_copy[1][0]) == static_cast(C[1][0]) ); - BOOST_REQUIRE( static_cast(C_copy[0][1]) == static_cast(C[0][1]) ); + BOOST_TEST( static_cast(C_copy[1][0]) == static_cast(C[1][0]) ); + BOOST_TEST( static_cast(C_copy[0][1]) == static_cast(C[0][1]) ); } { multi::array C({2, 2}, {3.0, 0.0}); // NOLINT(readability-identifier-length) conventional BLAS naming @@ -1141,8 +1147,8 @@ BOOST_AUTO_TEST_CASE(cublas_one_gemm_complex_trans_both) { } ); - BOOST_REQUIRE( static_cast(C_copy[1][0]) == static_cast(C[1][0]) ); - BOOST_REQUIRE( static_cast(C_copy[0][1]) == static_cast(C[0][1]) ); + BOOST_TEST( static_cast(C_copy[1][0]) == static_cast(C[1][0]) ); + BOOST_TEST( static_cast(C_copy[0][1]) == static_cast(C[0][1]) ); } } @@ -1187,14 +1193,14 @@ BOOST_AUTO_TEST_CASE(cublas_one_gemm_complex_conj_second) { ), std::move(Cr); }); } - BOOST_TEST_REQUIRE( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); - BOOST_TEST_REQUIRE( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); + BOOST_TEST( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); + BOOST_TEST( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); - BOOST_TEST_REQUIRE( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); - BOOST_TEST_REQUIRE( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); + BOOST_TEST( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); + BOOST_TEST( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); - BOOST_TEST_REQUIRE( static_cast(C_copy[1][0]).real() == +static_cast(C[0][1]).real() ); - BOOST_TEST_REQUIRE( static_cast(C_copy[1][0]).imag() == -static_cast(C[0][1]).imag() ); + BOOST_TEST( static_cast(C_copy[1][0]).real() == +static_cast(C[0][1]).real() ); + BOOST_TEST( static_cast(C_copy[1][0]).imag() == -static_cast(C[0][1]).imag() ); } } @@ -1239,14 +1245,14 @@ BOOST_AUTO_TEST_CASE(cublas_one_gemm_complex_conj_first) { // ), std::move(Cr); // }); // } - // BOOST_TEST_REQUIRE( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); - // BOOST_TEST_REQUIRE( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); + // BOOST_TEST( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); + // BOOST_TEST( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); - // BOOST_TEST_REQUIRE( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); - // BOOST_TEST_REQUIRE( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); + // BOOST_TEST( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); + // BOOST_TEST( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); - // BOOST_TEST_REQUIRE( static_cast(C_copy[1][0]).real() == +static_cast(C[0][1]).real() ); - // BOOST_TEST_REQUIRE( static_cast(C_copy[1][0]).imag() == -static_cast(C[0][1]).imag() ); + // BOOST_TEST( static_cast(C_copy[1][0]).real() == +static_cast(C[0][1]).real() ); + // BOOST_TEST( static_cast(C_copy[1][0]).imag() == -static_cast(C[0][1]).imag() ); } } @@ -1300,21 +1306,21 @@ BOOST_AUTO_TEST_CASE(cublas_one_gemm_complex_herm_second) { } ); - BOOST_TEST_REQUIRE( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); - BOOST_TEST_REQUIRE( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); + BOOST_TEST( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); + BOOST_TEST( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); - BOOST_TEST_REQUIRE( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); - BOOST_TEST_REQUIRE( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); + BOOST_TEST( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); + BOOST_TEST( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); } { multi::array CC({2, 2}, {3.0, 0.0}); CC = blas::gemm({1.0, 0.0}, A, blas::H(B)); - BOOST_TEST_REQUIRE( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); - BOOST_TEST_REQUIRE( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); + BOOST_TEST( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); + BOOST_TEST( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); - BOOST_TEST_REQUIRE( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); - BOOST_TEST_REQUIRE( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); + BOOST_TEST( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); + BOOST_TEST( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); } { multi::array CC({2, 2}, {3.0, 0.0}); @@ -1322,11 +1328,11 @@ BOOST_AUTO_TEST_CASE(cublas_one_gemm_complex_herm_second) { using blas::operators::operator~; CC = A* ~*B; - BOOST_TEST_REQUIRE( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); - BOOST_TEST_REQUIRE( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); + BOOST_TEST( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); + BOOST_TEST( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); - BOOST_TEST_REQUIRE( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); - BOOST_TEST_REQUIRE( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); + BOOST_TEST( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); + BOOST_TEST( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); } } @@ -1358,21 +1364,21 @@ BOOST_AUTO_TEST_CASE(cublas_one_gemm_complex_herm_second_plus) { } ); - BOOST_TEST_REQUIRE( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); - BOOST_TEST_REQUIRE( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); + BOOST_TEST( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); + BOOST_TEST( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); - BOOST_TEST_REQUIRE( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); - BOOST_TEST_REQUIRE( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); + BOOST_TEST( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); + BOOST_TEST( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); } { multi::array CC({2, 2}, {3.0, 0.0}); CC += blas::gemm({1.0, 0.0}, A, blas::H(B)); - BOOST_TEST_REQUIRE( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); - BOOST_TEST_REQUIRE( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); + BOOST_TEST( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); + BOOST_TEST( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); - BOOST_TEST_REQUIRE( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); - BOOST_TEST_REQUIRE( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); + BOOST_TEST( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); + BOOST_TEST( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); } { multi::array CC({2, 2}, {3.0, 0.0}); @@ -1380,11 +1386,11 @@ BOOST_AUTO_TEST_CASE(cublas_one_gemm_complex_herm_second_plus) { using blas::operators::operator~; CC += A* ~*B; - BOOST_TEST_REQUIRE( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); - BOOST_TEST_REQUIRE( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); + BOOST_TEST( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); + BOOST_TEST( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); - BOOST_TEST_REQUIRE( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); - BOOST_TEST_REQUIRE( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); + BOOST_TEST( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); + BOOST_TEST( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); } } @@ -1416,11 +1422,11 @@ BOOST_AUTO_TEST_CASE(cublas_one_gemm_complex_herm_first) { // } // } // } - // BOOST_TEST_REQUIRE( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); - // BOOST_TEST_REQUIRE( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); + // BOOST_TEST( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); + // BOOST_TEST( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); - // BOOST_TEST_REQUIRE( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); - // BOOST_TEST_REQUIRE( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); + // BOOST_TEST( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); + // BOOST_TEST( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); // } { multi::array CC({2, 2}, {3.0, 0.0}); @@ -1431,21 +1437,21 @@ BOOST_AUTO_TEST_CASE(cublas_one_gemm_complex_herm_first) { }); return std::move(Cr); }); - BOOST_TEST_REQUIRE( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); - BOOST_TEST_REQUIRE( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); + BOOST_TEST( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); + BOOST_TEST( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); - BOOST_TEST_REQUIRE( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); - BOOST_TEST_REQUIRE( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); + BOOST_TEST( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); + BOOST_TEST( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); } { multi::array CC({2, 2}, {3.0, 0.0}); CC = blas::gemm({1.0, 0.0}, blas::H(A), B); - BOOST_TEST_REQUIRE( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); - BOOST_TEST_REQUIRE( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); + BOOST_TEST( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); + BOOST_TEST( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); - BOOST_TEST_REQUIRE( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); - BOOST_TEST_REQUIRE( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); + BOOST_TEST( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); + BOOST_TEST( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); } { multi::array CC({2, 2}, {3.0, 0.0}); @@ -1453,11 +1459,11 @@ BOOST_AUTO_TEST_CASE(cublas_one_gemm_complex_herm_first) { using blas::operators::operator~; CC = ~*A *B; - BOOST_TEST_REQUIRE( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); - BOOST_TEST_REQUIRE( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); + BOOST_TEST( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); + BOOST_TEST( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); - BOOST_TEST_REQUIRE( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); - BOOST_TEST_REQUIRE( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); + BOOST_TEST( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); + BOOST_TEST( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); } } @@ -1489,11 +1495,11 @@ BOOST_AUTO_TEST_CASE(cublas_one_gemm_complex_herm_both) { // } // } // } - // BOOST_TEST_REQUIRE( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); - // BOOST_TEST_REQUIRE( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); + // BOOST_TEST( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); + // BOOST_TEST( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); - // BOOST_TEST_REQUIRE( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); - // BOOST_TEST_REQUIRE( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); + // BOOST_TEST( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); + // BOOST_TEST( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); // } // { // multi::array CC({2, 2}, {3.0, 0.0}); @@ -1505,22 +1511,22 @@ BOOST_AUTO_TEST_CASE(cublas_one_gemm_complex_herm_both) { // }); // return std::move(Cr); // }); - // BOOST_TEST_REQUIRE( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); - // BOOST_TEST_REQUIRE( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); + // BOOST_TEST( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); + // BOOST_TEST( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); - // BOOST_TEST_REQUIRE( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); - // BOOST_TEST_REQUIRE( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); + // BOOST_TEST( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); + // BOOST_TEST( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); // } { multi::array CC({2, 2}, {3.0, 0.0}); CC = blas::gemm({1.0, 0.0}, blas::H(A), blas::H(B)); - BOOST_TEST_REQUIRE( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); - BOOST_TEST_REQUIRE( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); + BOOST_TEST( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); + BOOST_TEST( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); - BOOST_TEST_REQUIRE( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); - BOOST_TEST_REQUIRE( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); + BOOST_TEST( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); + BOOST_TEST( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); } { multi::array CC({2, 2}, {3.0, 0.0}); @@ -1528,11 +1534,11 @@ BOOST_AUTO_TEST_CASE(cublas_one_gemm_complex_herm_both) { using blas::operators::operator~; CC = ~*A * ~*B; - BOOST_TEST_REQUIRE( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); - BOOST_TEST_REQUIRE( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); + BOOST_TEST( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); + BOOST_TEST( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); - BOOST_TEST_REQUIRE( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); - BOOST_TEST_REQUIRE( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); + BOOST_TEST( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); + BOOST_TEST( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); } } @@ -1564,11 +1570,11 @@ BOOST_AUTO_TEST_CASE(cublas_one_gemm_complex_trans_herm) { // } // } // } - // BOOST_TEST_REQUIRE( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); - // BOOST_TEST_REQUIRE( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); + // BOOST_TEST( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); + // BOOST_TEST( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); - // BOOST_TEST_REQUIRE( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); - // BOOST_TEST_REQUIRE( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); + // BOOST_TEST( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); + // BOOST_TEST( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); // } // { // multi::array CC({2, 2}, {3.0, 0.0}); @@ -1580,22 +1586,22 @@ BOOST_AUTO_TEST_CASE(cublas_one_gemm_complex_trans_herm) { // }); // return std::move(Cr); // }); - // BOOST_TEST_REQUIRE( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); - // BOOST_TEST_REQUIRE( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); + // BOOST_TEST( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); + // BOOST_TEST( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); - // BOOST_TEST_REQUIRE( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); - // BOOST_TEST_REQUIRE( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); + // BOOST_TEST( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); + // BOOST_TEST( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); // } { multi::array CC({2, 2}, {3.0, 0.0}); CC = blas::gemm({1.0, 0.0}, blas::T(A), blas::H(B)); - BOOST_TEST_REQUIRE( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); - BOOST_TEST_REQUIRE( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); + BOOST_TEST( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); + BOOST_TEST( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); - BOOST_TEST_REQUIRE( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); - BOOST_TEST_REQUIRE( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); + BOOST_TEST( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); + BOOST_TEST( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); } { multi::array CC({2, 2}, {3.0, 0.0}); @@ -1603,11 +1609,11 @@ BOOST_AUTO_TEST_CASE(cublas_one_gemm_complex_trans_herm) { using blas::operators::operator~; CC = ~A * ~*B; - BOOST_TEST_REQUIRE( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); - BOOST_TEST_REQUIRE( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); + BOOST_TEST( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); + BOOST_TEST( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); - BOOST_TEST_REQUIRE( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); - BOOST_TEST_REQUIRE( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); + BOOST_TEST( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); + BOOST_TEST( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); } } @@ -1639,11 +1645,11 @@ BOOST_AUTO_TEST_CASE(cublas_one_gemm_complex_herm_trans) { // } // } // } - // BOOST_TEST_REQUIRE( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); - // BOOST_TEST_REQUIRE( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); + // BOOST_TEST( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); + // BOOST_TEST( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); - // BOOST_TEST_REQUIRE( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); - // BOOST_TEST_REQUIRE( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); + // BOOST_TEST( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); + // BOOST_TEST( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); // } // { // multi::array CC({2, 2}, {3.0, 0.0}); @@ -1655,22 +1661,22 @@ BOOST_AUTO_TEST_CASE(cublas_one_gemm_complex_herm_trans) { // }); // return std::move(Cr); // }); - // BOOST_TEST_REQUIRE( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); - // BOOST_TEST_REQUIRE( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); + // BOOST_TEST( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); + // BOOST_TEST( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); - // BOOST_TEST_REQUIRE( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); - // BOOST_TEST_REQUIRE( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); + // BOOST_TEST( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); + // BOOST_TEST( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); // } // { // multi::array CC({2, 2}, {3.0, 0.0}); // CC = blas::gemm({1.0, 0.0}, blas::H(A), blas::T(B)); - // BOOST_TEST_REQUIRE( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); - // BOOST_TEST_REQUIRE( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); + // BOOST_TEST( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); + // BOOST_TEST( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); - // BOOST_TEST_REQUIRE( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); - // BOOST_TEST_REQUIRE( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); + // BOOST_TEST( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); + // BOOST_TEST( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); // } // { // multi::array CC({2, 2}, {3.0, 0.0}); @@ -1678,11 +1684,11 @@ BOOST_AUTO_TEST_CASE(cublas_one_gemm_complex_herm_trans) { // using blas::operators::operator~; // CC = ~*A * ~B; - // BOOST_TEST_REQUIRE( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); - // BOOST_TEST_REQUIRE( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); + // BOOST_TEST( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); + // BOOST_TEST( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); - // BOOST_TEST_REQUIRE( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); - // BOOST_TEST_REQUIRE( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); + // BOOST_TEST( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); + // BOOST_TEST( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); // } } @@ -1714,11 +1720,11 @@ BOOST_AUTO_TEST_CASE(cublas_one_gemm_complex_conj_herm) { // } // } // } - // BOOST_TEST_REQUIRE( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); - // BOOST_TEST_REQUIRE( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); + // BOOST_TEST( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); + // BOOST_TEST( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); - // BOOST_TEST_REQUIRE( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); - // BOOST_TEST_REQUIRE( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); + // BOOST_TEST( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); + // BOOST_TEST( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); // } // { // multi::array CC({2, 2}, {3.0, 0.0}); @@ -1730,22 +1736,22 @@ BOOST_AUTO_TEST_CASE(cublas_one_gemm_complex_conj_herm) { // }); // return std::move(Cr); // }); - // BOOST_TEST_REQUIRE( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); - // BOOST_TEST_REQUIRE( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); + // BOOST_TEST( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); + // BOOST_TEST( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); - // BOOST_TEST_REQUIRE( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); - // BOOST_TEST_REQUIRE( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); + // BOOST_TEST( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); + // BOOST_TEST( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); // } // { // multi::array CC({2, 2}, {3.0, 0.0}); // CC = blas::gemm({1.0, 0.0}, blas::T(A), blas::H(B)); - // BOOST_TEST_REQUIRE( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); - // BOOST_TEST_REQUIRE( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); + // BOOST_TEST( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); + // BOOST_TEST( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); - // BOOST_TEST_REQUIRE( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); - // BOOST_TEST_REQUIRE( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); + // BOOST_TEST( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); + // BOOST_TEST( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); // } // { // multi::array CC({2, 2}, {3.0, 0.0}); @@ -1753,11 +1759,11 @@ BOOST_AUTO_TEST_CASE(cublas_one_gemm_complex_conj_herm) { // using blas::operators::operator~; // CC = ~A * ~*B; - // BOOST_TEST_REQUIRE( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); - // BOOST_TEST_REQUIRE( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); + // BOOST_TEST( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); + // BOOST_TEST( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); - // BOOST_TEST_REQUIRE( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); - // BOOST_TEST_REQUIRE( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); + // BOOST_TEST( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); + // BOOST_TEST( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); // } } @@ -1790,11 +1796,11 @@ BOOST_AUTO_TEST_CASE(cublas_one_gemm_complex_herm_conj) { // } // } // } - // BOOST_TEST_REQUIRE( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); - // BOOST_TEST_REQUIRE( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); + // BOOST_TEST( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); + // BOOST_TEST( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); - // BOOST_TEST_REQUIRE( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); - // BOOST_TEST_REQUIRE( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); + // BOOST_TEST( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); + // BOOST_TEST( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); // } // { // multi::array CC({2, 2}, {3.0, 0.0}); @@ -1806,22 +1812,22 @@ BOOST_AUTO_TEST_CASE(cublas_one_gemm_complex_herm_conj) { // }); // return std::move(Cr); // }); - // BOOST_TEST_REQUIRE( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); - // BOOST_TEST_REQUIRE( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); + // BOOST_TEST( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); + // BOOST_TEST( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); - // BOOST_TEST_REQUIRE( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); - // BOOST_TEST_REQUIRE( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); + // BOOST_TEST( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); + // BOOST_TEST( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); // } // { // multi::array CC({2, 2}, {3.0, 0.0}); // CC = blas::gemm({1.0, 0.0}, blas::T(A), blas::H(B)); - // BOOST_TEST_REQUIRE( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); - // BOOST_TEST_REQUIRE( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); + // BOOST_TEST( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); + // BOOST_TEST( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); - // BOOST_TEST_REQUIRE( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); - // BOOST_TEST_REQUIRE( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); + // BOOST_TEST( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); + // BOOST_TEST( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); // } // { // multi::array CC({2, 2}, {3.0, 0.0}); @@ -1829,11 +1835,11 @@ BOOST_AUTO_TEST_CASE(cublas_one_gemm_complex_herm_conj) { // using blas::operators::operator~; // CC = ~A * ~*B; - // BOOST_TEST_REQUIRE( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); - // BOOST_TEST_REQUIRE( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); + // BOOST_TEST( static_cast(CC[1][0]).real() == static_cast(C[1][0]).real() ); + // BOOST_TEST( static_cast(CC[1][0]).imag() == static_cast(C[1][0]).imag() ); - // BOOST_TEST_REQUIRE( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); - // BOOST_TEST_REQUIRE( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); + // BOOST_TEST( static_cast(CC[0][1]).real() == static_cast(C[0][1]).real() ); + // BOOST_TEST( static_cast(CC[0][1]).imag() == static_cast(C[0][1]).imag() ); // } } @@ -2049,3 +2055,5 @@ BOOST_AUTO_TEST_CASE(UTA_blas_trsm_complex_nonsquare_default_diagonal_gemm_check } #endif #endif + +return boost::report_errors();} diff --git a/external_codes/boost_multi/multi/include/boost/multi/adaptors/cuda/cublas/test/axpy.cu b/external_codes/boost_multi/multi/include/boost/multi/adaptors/cuda/cublas/test/axpy.cu index e8b5b71b3c..b2bb020795 100644 --- a/external_codes/boost_multi/multi/include/boost/multi/adaptors/cuda/cublas/test/axpy.cu +++ b/external_codes/boost_multi/multi/include/boost/multi/adaptors/cuda/cublas/test/axpy.cu @@ -3,7 +3,7 @@ // https://www.boost.org/LICENSE_1_0.txt #define BOOST_TEST_MODULE "C++ Unit Tests for Multi CUBLAS gemv" -#include +// #include #include @@ -16,6 +16,12 @@ namespace multi = boost::multi; +#include +#define BOOST_AUTO_TEST_CASE(CasenamE) /**/ + +#define BOOST_REQUIRE_CLOSE(X, Y, ToL) BOOST_TEST( std::abs( (X) - (Y) ) < (ToL) ) + +int main() { BOOST_AUTO_TEST_CASE(blas_axpy_complex) { namespace blas = multi::blas; using complex = thrust::complex; @@ -32,7 +38,7 @@ BOOST_AUTO_TEST_CASE(blas_axpy_complex) { blas::axpy(complex{2.0, 0.0}, x, arr[1]); // arr can't be const multi::array arr_copy = arr; - BOOST_REQUIRE(( arr_copy[1][0] == complex{23.0, 0.0} )); + BOOST_TEST(( arr_copy[1][0] == complex{23.0, 0.0} )); } { multi::thrust::cuda::array arr = { @@ -46,7 +52,7 @@ BOOST_AUTO_TEST_CASE(blas_axpy_complex) { arr[1] += blas::axpy(complex{2.0, 0.0}, x); multi::array arr_copy = arr; - BOOST_REQUIRE(( arr_copy[1][0] == complex{23.0, 0.0} )); + BOOST_TEST(( arr_copy[1][0] == complex{23.0, 0.0} )); } { multi::thrust::cuda::array arr = { @@ -61,6 +67,8 @@ BOOST_AUTO_TEST_CASE(blas_axpy_complex) { multi::array arr_copy = arr; std::cout << arr_copy[1][0] << std::endl; - BOOST_REQUIRE(( arr_copy[1][0] == complex{23.0, 0.0} )); + BOOST_TEST(( arr_copy[1][0] == complex{23.0, 0.0} )); } } + +return boost::report_errors();} diff --git a/external_codes/boost_multi/multi/include/boost/multi/adaptors/cuda/cublas/test/dot.cu b/external_codes/boost_multi/multi/include/boost/multi/adaptors/cuda/cublas/test/dot.cu index 1d6a4bd68d..b0a9b0ffb5 100644 --- a/external_codes/boost_multi/multi/include/boost/multi/adaptors/cuda/cublas/test/dot.cu +++ b/external_codes/boost_multi/multi/include/boost/multi/adaptors/cuda/cublas/test/dot.cu @@ -2,8 +2,7 @@ // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt -#define BOOST_TEST_MODULE "C++ Unit Tests for Multi CUBLAS dot" -#include +#include #include @@ -21,6 +20,9 @@ namespace multi = boost::multi; +#define BOOST_AUTO_TEST_CASE(CasenamE) /**/ + +int main() { // BOOST_AUTO_TEST_CASE(cublas_dot_out_param_complex_C) { // namespace blas = multi::blas; // using complex = thrust::complex; @@ -31,8 +33,16 @@ namespace multi = boost::multi; // complex res{0.0, 0.0}; // blas::dot(blas::C(x), y, res); -// // BOOST_REQUIRE( res == std::inner_product(begin(x), end(x), begin(y), complex{0.0, 0.0}, std::plus<>{}, [](auto const& alpha, auto const& omega) {return conj(alpha)*omega;}) ); +// // BOOST_TEST( res == std::inner_product(begin(x), end(x), begin(y), complex{0.0, 0.0}, std::plus<>{}, [](auto const& alpha, auto const& omega) {return conj(alpha)*omega;}) ); // } + // range for test + { + multi::thrust::universal::array const x = {1, 2, 3}; + for(auto const& elem : x) { + int ee = elem; + BOOST_TEST(ee < 10); + } + } BOOST_AUTO_TEST_CASE(cublas_dot_out_array0D_complex_C) { namespace blas = multi::blas; @@ -48,11 +58,11 @@ BOOST_AUTO_TEST_CASE(cublas_dot_out_array0D_complex_C) { { multi::array res_copy{complex{0.0, 0.0}}; res_copy = res; - BOOST_REQUIRE(( *res_copy.base() == complex{14.0, 4.0} )); + BOOST_TEST(( *res_copy.base() == complex{14.0, 4.0} )); } { multi::array res_copy{res}; - BOOST_REQUIRE(( *res_copy.base() == complex{14.0, 4.0} )); + BOOST_TEST(( *res_copy.base() == complex{14.0, 4.0} )); } } @@ -65,7 +75,7 @@ BOOST_AUTO_TEST_CASE(cublas_dot_out_array0D_complex_C) { // multi::thrust::cuda::array const y = {1.0 + 0.0*I, 2.0 + 2.0*I, 3.0 + 0.0*I}; // NOLINT(readability-identifier-length) BLAS naming // complex res = blas::dot(blas::C(x), y); -// BOOST_REQUIRE( res == std::inner_product(begin(x), end(x), begin(y), complex{0.0, 0.0}, std::plus<>{}, [](auto const& alpha, auto const& omega) {return conj(alpha)*omega;}) ); +// BOOST_TEST( res == std::inner_product(begin(x), end(x), begin(y), complex{0.0, 0.0}, std::plus<>{}, [](auto const& alpha, auto const& omega) {return conj(alpha)*omega;}) ); // } // BOOST_AUTO_TEST_CASE(blas_dot_functional_mutate_complex_C) { @@ -78,5 +88,7 @@ BOOST_AUTO_TEST_CASE(cublas_dot_out_array0D_complex_C) { // complex res; // res = blas::dot(blas::C(x), y); -// BOOST_REQUIRE( res == std::inner_product(begin(x), end(x), begin(y), complex{0.0, 0.0}, std::plus<>{}, [](auto const& alpha, auto const& omega) {return conj(alpha)*omega;}) ); +// BOOST_TEST( res == std::inner_product(begin(x), end(x), begin(y), complex{0.0, 0.0}, std::plus<>{}, [](auto const& alpha, auto const& omega) {return conj(alpha)*omega;}) ); // } + +return boost::report_errors();} diff --git a/external_codes/boost_multi/multi/include/boost/multi/adaptors/cuda/cublas/test/gemm.cu b/external_codes/boost_multi/multi/include/boost/multi/adaptors/cuda/cublas/test/gemm.cu index 70f0216da0..9ffaeb3614 100644 --- a/external_codes/boost_multi/multi/include/boost/multi/adaptors/cuda/cublas/test/gemm.cu +++ b/external_codes/boost_multi/multi/include/boost/multi/adaptors/cuda/cublas/test/gemm.cu @@ -3,19 +3,27 @@ // https://www.boost.org/LICENSE_1_0.txt #define BOOST_TEST_MODULE "C++ Unit Tests for Multi CUBLAS gemm" -#include +// #include #include -#include #include +#include +#include #include + #include #include namespace multi = boost::multi; +#include +#define BOOST_AUTO_TEST_CASE(CasenamE) /**/ + +#define BOOST_REQUIRE_CLOSE(X, Y, ToL) BOOST_TEST( std::abs( (X) - (Y) ) < (ToL) ) + +int main() { BOOST_AUTO_TEST_CASE(multi_blas_gemv_complex) { namespace blas = multi::blas; using complex = thrust::complex; @@ -35,7 +43,7 @@ BOOST_AUTO_TEST_CASE(multi_blas_gemv_complex) { multi::array const Y_copy = Y_gpu; using blas::operators::operator-; - BOOST_REQUIRE_SMALL( +blas::nrm2(Y_copy - multi::array{ {214.02, 0.0}, {106.43, 0.0}, {188.37, 0.0} }) , 1e-13); + BOOST_REQUIRE_CLOSE( +blas::nrm2(Y_copy - multi::array{ {214.02, 0.0}, {106.43, 0.0}, {188.37, 0.0} }) , 0.0, 1e-13); } BOOST_AUTO_TEST_CASE(cublas_gemv_real) { @@ -57,7 +65,7 @@ BOOST_AUTO_TEST_CASE(cublas_gemv_real) { multi::array const Y_copy = Y_gpu; using blas::operators::operator-; - BOOST_REQUIRE_SMALL( +blas::nrm2(Y_copy - multi::array{ 214.02, 106.43, 188.37 }) , 1e-13); + BOOST_REQUIRE_CLOSE( +blas::nrm2(Y_copy - multi::array{ 214.02, 106.43, 188.37 }) , 0.0, 1e-13); } BOOST_AUTO_TEST_CASE(cublas_gemm_nh) { @@ -76,22 +84,24 @@ BOOST_AUTO_TEST_CASE(cublas_gemm_nh) { blas::gemm({1.0, 0.0}, a, a, {0.0, 0.0}, c); // c=aa†, c†=aa† multi::array const c_copy = c; - BOOST_REQUIRE( c_copy[1][0] == 16.0 - 2.0*I ); - BOOST_REQUIRE( c_copy[0][1] == 14.0 - 38.0*I ); + BOOST_TEST( c_copy[1][0] == 16.0 - 2.0*I ); + BOOST_TEST( c_copy[0][1] == 14.0 - 38.0*I ); } { auto const c = +blas::gemm(complex{1.0, 0.0}, a, a); // c=aa†, c†=aa† multi::array const c_copy = c; - BOOST_REQUIRE( c_copy[1][0] == 16.0 - 2.0*I ); - BOOST_REQUIRE( c_copy[0][1] == 14.0 - 38.0*I ); + BOOST_TEST( c_copy[1][0] == 16.0 - 2.0*I ); + BOOST_TEST( c_copy[0][1] == 14.0 - 38.0*I ); } { multi::thrust::cuda::array c({2, 2}, {0.0, 0.0}); c += blas::gemm(complex{1.0, 0.0}, a, a); // c=aa†, c†=aa† multi::array const c_copy = c; - BOOST_REQUIRE( c_copy[1][0] == 16.0 - 2.0*I ); - BOOST_REQUIRE( c_copy[0][1] == 14.0 - 38.0*I ); + BOOST_TEST( c_copy[1][0] == 16.0 - 2.0*I ); + BOOST_TEST( c_copy[0][1] == 14.0 - 38.0*I ); } -} \ No newline at end of file +} + +return boost::report_errors();} diff --git a/external_codes/boost_multi/multi/include/boost/multi/adaptors/cuda/cublas/test/gemv.cu b/external_codes/boost_multi/multi/include/boost/multi/adaptors/cuda/cublas/test/gemv.cu index aef3158bc4..dbc1278a44 100644 --- a/external_codes/boost_multi/multi/include/boost/multi/adaptors/cuda/cublas/test/gemv.cu +++ b/external_codes/boost_multi/multi/include/boost/multi/adaptors/cuda/cublas/test/gemv.cu @@ -1,12 +1,11 @@ // -*-indent-tabs-mode:t;c-basic-offset:4;tab-width:4;autowrap:nil;-*- -// Copyright 2023 Alfredo A. Correa +// Copyright 2023-2024 Alfredo A. Correa -#define BOOST_TEST_MODULE "C++ Unit Tests for Multi CUBLAS gemv" -#include +#include #include -#include +#include #include #include #include @@ -15,6 +14,11 @@ namespace multi = boost::multi; +#define BOOST_AUTO_TEST_CASE(CasenamE) /**/ + +#define BOOST_REQUIRE_CLOSE(X, Y, ToL) BOOST_TEST( std::abs( (X) - (Y) ) < (ToL) ) + +int main() { BOOST_AUTO_TEST_CASE(multi_blas_gemv_complex) { namespace blas = multi::blas; using complex = thrust::complex; @@ -34,7 +38,7 @@ BOOST_AUTO_TEST_CASE(multi_blas_gemv_complex) { multi::array const Y_copy = Y_gpu; using blas::operators::operator-; - BOOST_REQUIRE_SMALL( +blas::nrm2(Y_copy - multi::array{ {214.02, 0.0}, {106.43, 0.0}, {188.37, 0.0} }) , 1e-13); + BOOST_REQUIRE_CLOSE( +blas::nrm2(Y_copy - multi::array{ {214.02, 0.0}, {106.43, 0.0}, {188.37, 0.0} }) , 0.0, 1e-13); } BOOST_AUTO_TEST_CASE(multi_blas_gemv_complex_value) { @@ -54,7 +58,7 @@ BOOST_AUTO_TEST_CASE(multi_blas_gemv_complex_value) { multi::array const Y_copy = Y_gpu; using blas::operators::operator-; - BOOST_REQUIRE_SMALL( +blas::nrm2(Y_copy - multi::array{ {209.22, 0.0}, {100.43, 0.0}, {181.17, 0.0} }) , 1e-13); + BOOST_REQUIRE_CLOSE( +blas::nrm2(Y_copy - multi::array{ {209.22, 0.0}, {100.43, 0.0}, {181.17, 0.0} }) , 0.0, 1e-13); } BOOST_AUTO_TEST_CASE(cublas_gemv_real) { @@ -76,5 +80,7 @@ BOOST_AUTO_TEST_CASE(cublas_gemv_real) { multi::array const Y_copy = Y_gpu; using blas::operators::operator-; - BOOST_REQUIRE_SMALL( +blas::nrm2(Y_copy - multi::array{ 214.02, 106.43, 188.37 }) , 1e-13); + BOOST_REQUIRE_CLOSE( +blas::nrm2(Y_copy - multi::array{ 214.02, 106.43, 188.37 }) , 0.0, 1e-13); } + +return boost::report_errors();} diff --git a/external_codes/boost_multi/multi/include/boost/multi/adaptors/cuda/cublas/test/nrm2.cu b/external_codes/boost_multi/multi/include/boost/multi/adaptors/cuda/cublas/test/nrm2.cu new file mode 100644 index 0000000000..ab08243e96 --- /dev/null +++ b/external_codes/boost_multi/multi/include/boost/multi/adaptors/cuda/cublas/test/nrm2.cu @@ -0,0 +1,189 @@ +// Copyright 2024 Alfredo A. Correa +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include + +#include +#include +#include +#include +#include + +#include + +#include + +#include + +namespace multi = boost::multi; + +#include +#define BOOST_AUTO_TEST_CASE(CasenamE) /**/ + +int main() { +// BOOST_AUTO_TEST_CASE(cublas_dot_out_param_complex_C) { +// namespace blas = multi::blas; +// using complex = thrust::complex; +// complex const I{0.0, 1.0}; + +// multi::thrust::cuda::array const x = {1.0 + 0.0*I, 2.0 + 0.0*I, 3.0 + 0.0*I}; // NOLINT(readability-identifier-length) BLAS naming +// multi::thrust::cuda::array const y = {1.0 + 0.0*I, 2.0 + 2.0*I, 3.0 + 0.0*I}; // NOLINT(readability-identifier-length) BLAS naming + +// complex res{0.0, 0.0}; +// blas::dot(blas::C(x), y, res); +// // BOOST_TEST( res == std::inner_product(begin(x), end(x), begin(y), complex{0.0, 0.0}, std::plus<>{}, [](auto const& alpha, auto const& omega) {return conj(alpha)*omega;}) ); +// } + +BOOST_AUTO_TEST_CASE(cublas_dot_out_array0D_complex_C) { + namespace blas = multi::blas; + using complex = thrust::complex; + complex const I{0.0, 1.0}; + + multi::thrust::cuda::array const x = {1.0 + 0.0*I, 2.0 + 0.0*I, 3.0 + 0.0*I}; // NOLINT(readability-identifier-length) BLAS naming + multi::thrust::cuda::array const y = {1.0 + 0.0*I, 2.0 + 2.0*I, 3.0 + 0.0*I}; // NOLINT(readability-identifier-length) BLAS naming + + multi::thrust::cuda::array res{complex{0.0, 0.0}}; + blas::dot(blas::C(x), y, res); + + { + multi::array res_copy{complex{0.0, 0.0}}; + res_copy = res; + BOOST_TEST(( *res_copy.base() == complex{14.0, 4.0} )); + } + { + multi::array res_copy{res}; + BOOST_TEST(( *res_copy.base() == complex{14.0, 4.0} )); + } +} + +BOOST_AUTO_TEST_CASE(cublas_dot_out_array0D_complex_C) { + namespace blas = multi::blas; + using complex = thrust::complex; + complex const I{0.0, 1.0}; + + multi::thrust::cuda::array const x = {1.0 + 0.0*I, 2.0 + 0.0*I, 3.0 + 0.0*I}; // NOLINT(readability-identifier-length) BLAS naming + multi::thrust::cuda::array const y = {1.0 + 0.0*I, 2.0 + 2.0*I, 3.0 + 0.0*I}; // NOLINT(readability-identifier-length) BLAS naming + + multi::thrust::cuda::array res{complex{0.0, 0.0}}; + + { + double res{0.0}; + multi::array const xx = {1.0, 2.0, 3.0}; + + res = blas::nrm2(xx); + BOOST_TEST( std::abs( res - std::sqrt(1.0*1.0 + 2.0*2.0 + 3.0*3.0) ) < 1e-7 ); + } + { + double res{0.0}; + multi::array const xx = {1.0, 2.0, 3.0}; + + blas::nrm2(xx, res); + BOOST_TEST( std::abs( res - std::sqrt(1.0*1.0 + 2.0*2.0 + 3.0*3.0) ) < 1e-7 ); + } + { + multi::array res{0.0}; + multi::array const xx = {1.0, 2.0, 3.0}; + + blas::nrm2(xx, res); + BOOST_TEST( std::abs( *res.base() - std::sqrt(1.0*1.0 + 2.0*2.0 + 3.0*3.0) ) < 1e-7 ); + } + { + multi::array res{0.0}; + multi::array, 1> const xx = {std::complex{1.0, 2.0}, std::complex{3.0, 4.0}, std::complex{5.0, 6.0}}; + + blas::nrm2(xx, res); + BOOST_TEST( std::abs( *res.base() - std::sqrt(std::norm(std::complex{1.0, 2.0}) + std::norm(std::complex{3.0, 4.0}) + std::norm(std::complex{5.0, 6.0})) ) < 1e-7 ); + } + { + multi::thrust::cuda::array res{0.0}; + multi::thrust::cuda::array const xx = {1.0, 2.0, 3.0}; + + blas::nrm2(xx, res); + BOOST_TEST( *res.base() == std::sqrt(1.0*1.0 + 2.0*2.0 + 3.0*3.0) ); + } + { + multi::thrust::cuda::array res{0.0}; + multi::thrust::cuda::array const xx = {1.0, 2.0, 3.0}; + + res = blas::nrm2(xx); + BOOST_TEST( *res.base() == std::sqrt(1.0*1.0 + 2.0*2.0 + 3.0*3.0) ); + + double res2 = blas::nrm2(xx); + BOOST_TEST( res2 == std::sqrt(1.0*1.0 + 2.0*2.0 + 3.0*3.0) ); + } + { + multi::thrust::cuda::array res{0.0}; + multi::thrust::cuda::array, 1> const xx = {thrust::complex(1.0, 2.0), thrust::complex(3.0, 4.0), thrust::complex(4.0, 5.0)}; + + res = blas::nrm2(xx); + BOOST_TEST( *res.base() == std::sqrt(std::norm(std::complex(1.0, 2.0)) + std::norm(std::complex(3.0, 4.0)) + std::norm(std::complex(4.0, 5.0))) ); + + double res2 = blas::nrm2(xx); + BOOST_TEST( res2 == *res.base() ); + + auto res3 = blas::nrm2(xx); + } + { + multi::thrust::cuda::array res{0.0}; + multi::thrust::cuda::array, 1> const xx = {thrust::complex(1.0, 2.0), thrust::complex(3.0, 4.0), thrust::complex(4.0, 5.0)}; + + blas::nrm2_n(xx.begin(), xx.size(), res.base()); + BOOST_TEST( *res.base() == std::sqrt(std::norm(std::complex(1.0, 2.0)) + std::norm(std::complex(3.0, 4.0)) + std::norm(std::complex(4.0, 5.0))) ); + } + { + multi::thrust::cuda::array res{0.0}; + multi::thrust::cuda::array const xx = {1.0, 2.0, 3.0, 4.0, 5.0, 6.0}; + + blas::nrm2_n(xx.begin(), 3, res.base()); + BOOST_TEST( *res.base() == std::sqrt(1.0*1.0 + 2.0*2.0 + 3.0*3.0) ); + } + + // { + // multi::thrust::cuda::array res{0.0}; + // multi::thrust::cuda::array const xx = {1.0, 2.0, 3.0}; + + // blas::nrm2(xx, res); + // BOOST_TEST( *res.base() == std::sqrt(1.0*1.0 + 2.0*2.0 + 3.0*3.0) ); + // } + + // multi::thrust::cuda::array res{complex{0.0, 0.0}}; + // blas::dot(blas::C(x), y, res); + + // { + // multi::array res_copy{complex{0.0, 0.0}}; + // res_copy = res; + // BOOST_TEST(( *res_copy.base() == complex{14.0, 4.0} )); + // } + // { + // multi::array res_copy{res}; + // BOOST_TEST(( *res_copy.base() == complex{14.0, 4.0} )); + // } +} + +// BOOST_AUTO_TEST_CASE(blas_dot_functional_complex_C) { +// namespace blas = multi::blas; +// using complex = thrust::complex; +// complex const I{0.0, 1.0}; + +// multi::thrust::cuda::array const x = {1.0 + 0.0*I, 2.0 + 0.0*I, 3.0 + 0.0*I}; // NOLINT(readability-identifier-length) BLAS naming +// multi::thrust::cuda::array const y = {1.0 + 0.0*I, 2.0 + 2.0*I, 3.0 + 0.0*I}; // NOLINT(readability-identifier-length) BLAS naming + +// complex res = blas::dot(blas::C(x), y); +// BOOST_TEST( res == std::inner_product(begin(x), end(x), begin(y), complex{0.0, 0.0}, std::plus<>{}, [](auto const& alpha, auto const& omega) {return conj(alpha)*omega;}) ); +// } + +// BOOST_AUTO_TEST_CASE(blas_dot_functional_mutate_complex_C) { +// namespace blas = multi::blas; +// using complex = thrust::complex; +// complex const I{0.0, 1.0}; + +// multi::thrust::cuda::array const x = {1.0 + 0.0*I, 2.0 + 0.0*I, 3.0 + 0.0*I}; // NOLINT(readability-identifier-length) BLAS naming +// multi::thrust::cuda::array const y = {1.0 + 0.0*I, 2.0 + 2.0*I, 3.0 + 0.0*I}; // NOLINT(readability-identifier-length) BLAS naming + +// complex res; +// res = blas::dot(blas::C(x), y); +// BOOST_TEST( res == std::inner_product(begin(x), end(x), begin(y), complex{0.0, 0.0}, std::plus<>{}, [](auto const& alpha, auto const& omega) {return conj(alpha)*omega;}) ); +// } + +return boost::report_errors();} diff --git a/external_codes/boost_multi/multi/include/boost/multi/adaptors/cuda/cublas/test/scal.cu b/external_codes/boost_multi/multi/include/boost/multi/adaptors/cuda/cublas/test/scal.cu index a35c9dc0a2..0d0bcf6b6e 100644 --- a/external_codes/boost_multi/multi/include/boost/multi/adaptors/cuda/cublas/test/scal.cu +++ b/external_codes/boost_multi/multi/include/boost/multi/adaptors/cuda/cublas/test/scal.cu @@ -3,7 +3,7 @@ // https://www.boost.org/LICENSE_1_0.txt #define BOOST_TEST_MODULE "C++ Unit Tests for Multi CUBLAS gemv" -#include +// #include #include @@ -18,6 +18,12 @@ namespace multi = boost::multi; +#include +#define BOOST_AUTO_TEST_CASE(CasenamE) /**/ + +// #define BOOST_REQUIRE_CLOSE(X, Y, ToL) BOOST_TEST( std::abs( (X) - (Y) ) < (ToL) ) + +int main() { BOOST_AUTO_TEST_CASE(cublas_scal_complex_column) { namespace blas = multi::blas; @@ -33,7 +39,7 @@ BOOST_AUTO_TEST_CASE(cublas_scal_complex_column) { multi::array arr_copy = arr; - BOOST_REQUIRE(( (~arr_copy)[1][2] == complex{20.0, 0.0} )); + BOOST_TEST(( (~arr_copy)[1][2] == complex{20.0, 0.0} )); } BOOST_AUTO_TEST_CASE(cublas_scal_complex) { @@ -47,5 +53,7 @@ BOOST_AUTO_TEST_CASE(cublas_scal_complex) { auto const alpha = complex{2.0, 3.0}; blas::scal(alpha, x); // x <- alpha*x - BOOST_REQUIRE(( x[1] == alpha*x_copy[1] )); -} \ No newline at end of file + BOOST_TEST(( x[1] == alpha*x_copy[1] )); +} + +return boost::report_errors();} diff --git a/external_codes/boost_multi/multi/include/boost/multi/adaptors/cuda/cublas/test/trsm.cu b/external_codes/boost_multi/multi/include/boost/multi/adaptors/cuda/cublas/test/trsm.cu index 3b0259e61c..30ba775621 100644 --- a/external_codes/boost_multi/multi/include/boost/multi/adaptors/cuda/cublas/test/trsm.cu +++ b/external_codes/boost_multi/multi/include/boost/multi/adaptors/cuda/cublas/test/trsm.cu @@ -3,7 +3,7 @@ // https://www.boost.org/LICENSE_1_0.txt #define BOOST_TEST_MODULE "C++ Unit Tests for Multi CUBLAS trsm" -#include +// #include #include #include @@ -14,6 +14,12 @@ namespace multi = boost::multi; +#include +#define BOOST_AUTO_TEST_CASE(CasenamE) /**/ + +#define BOOST_REQUIRE_CLOSE(X, Y, ToL) BOOST_TEST( std::abs( (X) - (Y) ) < (ToL) ) + +int main() { BOOST_AUTO_TEST_CASE(unit_trsm_multi_blas_trsm_complex_nonsquare_default_diagonal_hermitized_gemm_check_no_const) { namespace blas = multi::blas; using complex = thrust::complex; complex const I{0.0, 1.0}; // NOLINT(readability-identifier-length) imag unit @@ -124,3 +130,4 @@ BOOST_AUTO_TEST_CASE(default_param_unit_trsm_multi_blas_trsm_complex_nonsquare_d BOOST_REQUIRE_CLOSE( B_cpy[1][0].real() , -0.72562939983295538 , 0.001); BOOST_REQUIRE_CLOSE( B_cpy[1][0].imag() , 0.046772461520104877, 0.001); } +return boost::report_errors();} diff --git a/external_codes/boost_multi/multi/include/boost/multi/adaptors/fftw.hpp b/external_codes/boost_multi/multi/include/boost/multi/adaptors/fftw.hpp index 210e01eec5..48df23bd97 100644 --- a/external_codes/boost_multi/multi/include/boost/multi/adaptors/fftw.hpp +++ b/external_codes/boost_multi/multi/include/boost/multi/adaptors/fftw.hpp @@ -8,7 +8,7 @@ #include -#include +#include // IWYU pragma: export #include // sort #include diff --git a/external_codes/boost_multi/multi/include/boost/multi/adaptors/fftw/CMakeLists.txt b/external_codes/boost_multi/multi/include/boost/multi/adaptors/fftw/CMakeLists.txt index 761c767430..05bb66cb9b 100644 --- a/external_codes/boost_multi/multi/include/boost/multi/adaptors/fftw/CMakeLists.txt +++ b/external_codes/boost_multi/multi/include/boost/multi/adaptors/fftw/CMakeLists.txt @@ -27,7 +27,8 @@ if(PKG_CONFIG_FOUND) else() message(WARNING "Cannot find FFTW, FFTW-adaptor will not be tested. If you want this feature install FFTW, for example please run:" "\n sudo apt install pkg-config libfftw3-dev" - "\n sudo dnf install fftw-devel # in Fedora") + "\n sudo dnf install fftw-devel # in Fedora" + "\n brew install fftw pkg-config") endif() else() message(WARNING "Cannot find PkgConfig and/or FFTW, FFTW-adaptor will not be tested. If you want this feature install PkgConfig and FFTW, for example please run:" diff --git a/external_codes/boost_multi/multi/include/boost/multi/adaptors/fftw/memory.hpp b/external_codes/boost_multi/multi/include/boost/multi/adaptors/fftw/memory.hpp index b19568ca52..690a4689d2 100644 --- a/external_codes/boost_multi/multi/include/boost/multi/adaptors/fftw/memory.hpp +++ b/external_codes/boost_multi/multi/include/boost/multi/adaptors/fftw/memory.hpp @@ -36,8 +36,10 @@ struct allocator { } } - constexpr auto operator==(allocator const& /*other*/) const -> bool { return true; } - constexpr auto operator!=(allocator const& /*other*/) const -> bool { return false; } + // constexpr auto operator==(allocator const& /*other*/) const -> bool { return true; } + // constexpr auto operator!=(allocator const& /*other*/) const -> bool { return false; } + constexpr friend auto operator==(allocator const& /*lhs*/, allocator const& /*rhs*/) { return true; } + constexpr friend auto operator!=(allocator const& /*lhs*/, allocator const& /*rhs*/) { return false; } static constexpr auto max_size() noexcept { return std::numeric_limits::max() / sizeof(T); } }; diff --git a/external_codes/boost_multi/multi/include/boost/multi/adaptors/fftw/test/CMakeLists.txt b/external_codes/boost_multi/multi/include/boost/multi/adaptors/fftw/test/CMakeLists.txt index e4d19acf75..3f4f53da7f 100644 --- a/external_codes/boost_multi/multi/include/boost/multi/adaptors/fftw/test/CMakeLists.txt +++ b/external_codes/boost_multi/multi/include/boost/multi/adaptors/fftw/test/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.18) +cmake_minimum_required(VERSION 3.10) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake") @@ -85,12 +85,6 @@ foreach(TEST_FILE ${TEST_SRCS}) # set_property(TARGET ${TEST_EXE} PROPERTY "${CUDA_ARCH_LIST}") target_compile_options(${TEST_EXE} PRIVATE -std=c++17) endif() - # target_compile_features (${TEST_EXE} PUBLIC cxx_std_17) - - target_compile_definitions(${TEST_EXE} PRIVATE "BOOST_PP_VARIADICS") - target_compile_definitions(${TEST_EXE} PRIVATE ${Boost_DEFINITIONS}) - target_compile_definitions(${TEST_EXE} PRIVATE BOOST_TEST_DYN_LINK=1) - target_compile_definitions(${TEST_EXE} PRIVATE BOOST_TEST_MODULE="C++ Unit Tests for Multi FFTW") target_include_directories(${TEST_EXE} PRIVATE ${PROJECT_SOURCE_DIR}/include) target_include_directories(${TEST_EXE} SYSTEM PRIVATE ${Boost_INCLUDE_DIRS}) @@ -114,6 +108,7 @@ foreach(TEST_FILE ${TEST_SRCS}) -fno-common -Wpedantic -Wformat-truncation + -Wparentheses -fstack-usage> # -Wconversion $<$,$>: -fno-common diff --git a/external_codes/boost_multi/multi/include/boost/multi/adaptors/fftw/test/combinations.cpp b/external_codes/boost_multi/multi/include/boost/multi/adaptors/fftw/test/combinations.cpp index 1ceabe45c2..f6e7373b29 100644 --- a/external_codes/boost_multi/multi/include/boost/multi/adaptors/fftw/test/combinations.cpp +++ b/external_codes/boost_multi/multi/include/boost/multi/adaptors/fftw/test/combinations.cpp @@ -2,25 +2,29 @@ // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt -#include +// #include // TODO(correaa) use lightweight +// #include #include -#include // NOLINT(build/c++11) -#include -#include -#include +#include + +#include // for generate, for_each +#include // for array +#include // for operator-, duration // NOLINT(build/c++11) +#include // for complex, operator== +#include // for operator<<, basic_os... +#include // for iota +#include // for linear_congruential_... +#include // for operator""s, operator+ +#include // for move +#include // for vector namespace multi = boost::multi; template<> inline constexpr bool multi::force_element_trivial_default_construction> = true; -namespace utf = boost::unit_test::framework; - -using fftw_fixture = multi::fftw::environment; -BOOST_TEST_GLOBAL_FIXTURE(fftw_fixture); - class watch : private std::chrono::high_resolution_clock { // NOSONAR(cpp:S4963) this class will report timing on destruction std::string label_; time_point start_ = now(); @@ -41,7 +45,13 @@ class watch : private std::chrono::high_resolution_clock { // NOSONAR(cpp:S4963 template using marray = multi::array; constexpr auto exts = multi::extensions_t<4>({6, 12, 24, 12}); -BOOST_AUTO_TEST_CASE(fft_combinations, *boost::unit_test::tolerance(0.00001)) { +#include +#define BOOST_AUTO_TEST_CASE(CasenamE) /**/ + +auto main() -> int { // NOLINT(readability-function-cognitive-complexity,bugprone-exception-escape) +multi::fftw::environment const env; + +BOOST_AUTO_TEST_CASE(fft_combinations) { // , *boost::unit_test::tolerance(0.00001)) { using complex = std::complex; auto const in = [] { @@ -71,23 +81,27 @@ BOOST_AUTO_TEST_CASE(fft_combinations, *boost::unit_test::tolerance(0.00001)) { for(auto which : which_cases) { // NOLINT(altera-unroll-loops) cout << "case "; - copy(begin(which), end(which), std::ostream_iterator{cout, ", "}); + std::for_each(which.begin(), which.end(), [](auto elem) { cout << elem << ", "; }); + // copy(which.begin(), which.end(), std::ostream_iterator{cout, ", "}); cout << "\n"; marray out = in; { auto const pln = multi::fftw::plan::forward(which, in.base(), in.layout(), out.base(), out.layout()); - watch const unnamed{"cpu_oplac planned %ws wall, CPU (%p%)\n"s}; + watch const unnamed("cpu_oplac planned %ws wall, CPU (%p%)\n"s); // NOLINT(misc-include-cleaner) bug in clang-tidy 18 pln.execute(in.base(), out.base()); } { - auto in_rw = in; + auto in_rw = in; + watch const unnamed{"cpu_iplac %ws wall, CPU (%p%)\n"s}; multi::fftw::dft_forward(which, in_rw, in_rw); } { - auto in_rw = in; - auto const pln = multi::fftw::plan::forward(which, in_rw.base(), in_rw.layout(), in_rw.base(), in_rw.layout()); + auto in_rw = in; + + auto const pln = multi::fftw::plan::forward(which, in_rw.base(), in_rw.layout(), in_rw.base(), in_rw.layout()); + watch const unnamed{"cpu_iplac planned %ws wall, CPU (%p%)\n"s}; pln.execute(in_rw.base(), in_rw.base()); } @@ -100,7 +114,7 @@ BOOST_AUTO_TEST_CASE(fft_combinations, *boost::unit_test::tolerance(0.00001)) { } } -BOOST_AUTO_TEST_CASE(fftw_4D_power_benchmark, *boost::unit_test::enabled()) { +BOOST_AUTO_TEST_CASE(fftw_4D_power_benchmark) { //, *boost::unit_test::enabled()) { using namespace std::string_literals; // NOLINT(build/namespaces) for ""s using complex = std::complex; @@ -109,36 +123,36 @@ BOOST_AUTO_TEST_CASE(fftw_4D_power_benchmark, *boost::unit_test::enabled()) { marray in(exts); std::iota(in.data_elements(), in.data_elements() + in.num_elements(), 1.2); - BOOST_REQUIRE(in[0][0][0][0] == 1.2); + BOOST_TEST(in[0][0][0][0] == 1.2); std::array which = {false, true, true, true}; - [&, unnamed = watch{utf::current_test_case().full_name() + " inplace FTTT"s}] { + [&, unnamed = watch{"fftw_4D_power_benchmark inplace FTTT"s}] { fftw::dft(which, in, fftw::forward); }(); - [&, unnamed = watch{utf::current_test_case().full_name() + " inplace FTTT"s}] { + [&, unnamed = watch{"fftw_4D_power_benchmark inplace FTTT"s}] { fftw::dft(which, in, fftw::forward); }(); auto in0000 = in[0][0][0][0]; - BOOST_REQUIRE(in0000 != 1.2); + BOOST_TEST(in0000 != 1.2); marray out(exts); - [&, unnamed = watch{utf::current_test_case().full_name() + " outofplace FTTT"s}] { + [&, unnamed = watch{"fftw_4D_power_benchmark outofplace FTTT"s}] { fftw::dft(which, in, out, fftw::forward); }(); - [&, unnamed = watch{utf::current_test_case().full_name() + " outofplace FTTT"s}] { + [&, unnamed = watch{"fftw_4D_power_benchmark outofplace FTTT"s}] { fftw::dft(which, in, out, fftw::forward); }(); - [&, unnamed = watch{utf::current_test_case().full_name() + " outofplace FTTT"s}] { + [&, unnamed = watch{"fftw_4D_power_benchmark outofplace FTTT"s}] { fftw::dft(which, in, out, fftw::forward); }(); - [&, unnamed = watch{utf::current_test_case().full_name() + " outofplace+alloc FTTT"s}] { + [&, unnamed = watch{"fftw_4D_power_benchmark outofplace+alloc FTTT"s}] { marray out2(exts); fftw::dft(which, in, out2, fftw::forward); }(); - [&, unnamed = watch{utf::current_test_case().full_name() + " outofplace+alloc FTTT"s}] { + [&, unnamed = watch{"fftw_4D_power_benchmark outofplace+alloc FTTT"s}] { marray out2(exts); fftw::dft(which, in, out2, fftw::forward); }(); - BOOST_REQUIRE(in0000 == in[0][0][0][0]); + BOOST_TEST(in0000 == in[0][0][0][0]); } BOOST_AUTO_TEST_CASE(fftw_4D_power_benchmark_syntax) { @@ -155,15 +169,16 @@ BOOST_AUTO_TEST_CASE(fftw_4D_power_benchmark_syntax) { auto const in = [] { marray ret(exts); - std::generate(ret.data_elements(), ret.data_elements() + ret.num_elements(), - [eng = std::default_random_engine{std::random_device{}()}, - uniform_01 = std::uniform_real_distribution<>{}]() mutable { - return complex{uniform_01(eng), uniform_01(eng)}; - }); + std::generate( + ret.data_elements(), ret.data_elements() + ret.num_elements(), + [eng = std::default_random_engine{std::random_device{}()}, + uniform_01 = std::uniform_real_distribution<>{}]() mutable { + return complex{uniform_01(eng), uniform_01(eng)}; + } + ); return ret; }(); +} - auto io = in; - (void)io; - BOOST_REQUIRE( io.extensions() == in.extensions() ); +return boost::report_errors(); } diff --git a/external_codes/boost_multi/multi/include/boost/multi/adaptors/fftw/test/core.cpp b/external_codes/boost_multi/multi/include/boost/multi/adaptors/fftw/test/core.cpp index 0a83028d77..fc6aa30bc1 100644 --- a/external_codes/boost_multi/multi/include/boost/multi/adaptors/fftw/test/core.cpp +++ b/external_codes/boost_multi/multi/include/boost/multi/adaptors/fftw/test/core.cpp @@ -2,16 +2,17 @@ // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt -#include - #include #include -#include // NOLINT(build/c++11) bug in cpplint -#include -#include - -#include +#include // for for_each, tra... +#include // for operator* +#include // for begin, end +#include // for accumulate, iota +#include // std::mt19937_64 +#include // for operator""s +#include // for decay_t, enab... +#include // for forward namespace { @@ -61,212 +62,218 @@ template class randomizer> { } }; -using fftw_fixture = fftw::environment; -BOOST_TEST_GLOBAL_FIXTURE(fftw_fixture); +#include +#define BOOST_AUTO_TEST_CASE(CasenamE) /**/ -BOOST_AUTO_TEST_CASE(fftw_2D_identity_2, *boost::unit_test::tolerance(0.0001)) { - using complex = std::complex; +auto main() -> int { // NOLINT(readability-function-cognitive-complexity,bugprone-exception-escape) + fftw::environment const env; - [[maybe_unused]] auto const I = complex{0.0, 1.0}; // NOLINT(readability-identifier-length) imag unit + BOOST_AUTO_TEST_CASE(fftw_2D_identity_2) { //, *boost::unit_test::tolerance(0.0001)) { + using complex = std::complex; - multi::array const in = { - { 1.0 + 2.0 * I, 9.0 - 1.0 * I, 2.0 + 4.0 * I}, - { 3.0 + 3.0 * I, 7.0 - 4.0 * I, 1.0 + 9.0 * I}, - { 4.0 + 1.0 * I, 5.0 + 3.0 * I, 2.0 + 4.0 * I}, - { 3.0 - 1.0 * I, 8.0 + 7.0 * I, 2.0 + 1.0 * I}, - {31.0 - 1.0 * I, 18.0 + 7.0 * I, 2.0 + 10.0 * I}, - }; - multi::array out(extensions(in)); + [[maybe_unused]] auto const I = complex{0.0, 1.0}; // NOLINT(readability-identifier-length) imag unit - multi::fftw::dft_forward({false, false}, in, out); // out = in; + multi::array const in = { + { 1.0 + 2.0 * I, 9.0 - 1.0 * I, 2.0 + 4.0 * I}, + { 3.0 + 3.0 * I, 7.0 - 4.0 * I, 1.0 + 9.0 * I}, + { 4.0 + 1.0 * I, 5.0 + 3.0 * I, 2.0 + 4.0 * I}, + { 3.0 - 1.0 * I, 8.0 + 7.0 * I, 2.0 + 1.0 * I}, + {31.0 - 1.0 * I, 18.0 + 7.0 * I, 2.0 + 10.0 * I}, + }; + multi::array out(extensions(in)); - BOOST_TEST_REQUIRE( in[2][3].real() == out[2][3].real() ); - BOOST_TEST_REQUIRE( in[2][3].imag() == out[2][3].imag() ); + multi::fftw::dft_forward({false, false}, in, out); // out = in; - BOOST_REQUIRE( out == in ); -} + BOOST_TEST( in[2][3].real() == out[2][3].real() ); + BOOST_TEST( in[2][3].imag() == out[2][3].imag() ); -BOOST_AUTO_TEST_CASE(fftw_2D_many, *boost::unit_test::tolerance(0.0001)) { - using complex = std::complex; + BOOST_TEST( out == in ); + } - auto const I = complex{0.0, 1.0}; // NOLINT(readability-identifier-length) imag unit + BOOST_AUTO_TEST_CASE(fftw_2D_many) { // , *boost::unit_test::tolerance(0.0001)) { + using complex = std::complex; - multi::array const in = { - { 1.0 + 2.0 * I, 9.0 - 1.0 * I, 2.0 + 4.0 * I}, - { 3.0 + 3.0 * I, 7.0 - 4.0 * I, 1.0 + 9.0 * I}, - { 4.0 + 1.0 * I, 5.0 + 3.0 * I, 2.0 + 4.0 * I}, - { 3.0 - 1.0 * I, 8.0 + 7.0 * I, 2.0 + 1.0 * I}, - {31.0 - 1.0 * I, 18.0 + 7.0 * I, 2.0 + 10.0 * I}, - }; - multi::array out(extensions(in)); + auto const I = complex{0.0, 1.0}; // NOLINT(readability-identifier-length) imag unit - using multi::fftw::dft_forward; + multi::array const in = { + { 1.0 + 2.0 * I, 9.0 - 1.0 * I, 2.0 + 4.0 * I}, + { 3.0 + 3.0 * I, 7.0 - 4.0 * I, 1.0 + 9.0 * I}, + { 4.0 + 1.0 * I, 5.0 + 3.0 * I, 2.0 + 4.0 * I}, + { 3.0 - 1.0 * I, 8.0 + 7.0 * I, 2.0 + 1.0 * I}, + {31.0 - 1.0 * I, 18.0 + 7.0 * I, 2.0 + 10.0 * I}, + }; + multi::array out(extensions(in)); - multi::fftw::dft_forward({false, false}, rotated(in), rotated(out)); - BOOST_REQUIRE( in == out ); -} + using multi::fftw::dft_forward; -BOOST_AUTO_TEST_CASE(fftw_many1_from_2) { - using complex = std::complex; + multi::fftw::dft_forward({false, false}, in.rotated(), out.rotated()); + BOOST_TEST( in == out ); + } - [[maybe_unused]] auto const I = complex{0.0, 1.0}; // NOLINT(readability-identifier-length) imag unit + BOOST_AUTO_TEST_CASE(fftw_many1_from_2) { + using complex = std::complex; - std::random_device dev; - multi::array in({3, 10}); - randomizer{dev()}(in); - multi::array out({3, 10}); - fftw::dft_forward({false, true}, in, out); + [[maybe_unused]] auto const I = complex{0.0, 1.0}; // NOLINT(readability-identifier-length) imag unit - multi::array out2({3, 10}); - std::transform(in.begin(), in.end(), out2.begin(), out2.begin(), [](auto const& in_elem, auto&& out2_elem) { - fftw::dft_forward({true}, in_elem, out2_elem); - return std::forward(out2_elem); - }); + std::random_device dev; + multi::array in({3, 10}); + randomizer{dev()}(in); + multi::array out({3, 10}); + fftw::dft_forward({false, true}, in, out); - BOOST_REQUIRE(out2 == out); -} + multi::array out2({3, 10}); + std::transform(in.begin(), in.end(), out2.begin(), out2.begin(), [](auto const& in_elem, auto&& out2_elem) { + fftw::dft_forward({true}, in_elem, out2_elem); + return std::forward(out2_elem); + }); -BOOST_AUTO_TEST_CASE(fftw_many2_from_3) { - using complex = std::complex; + BOOST_TEST(out2 == out); + } - [[maybe_unused]] auto const I = complex{0.0, 1.0}; // NOLINT(readability-identifier-length) imag unit + BOOST_AUTO_TEST_CASE(fftw_many2_from_3) { + using complex = std::complex; - std::random_device dev; - multi::array in({3, 5, 6}); - randomizer{dev()}(in); - multi::array out({3, 5, 6}); - fftw::dft_forward({false, true, true}, in, out); + [[maybe_unused]] auto const I = complex{0.0, 1.0}; // NOLINT(readability-identifier-length) imag unit - multi::array out2({3, 5, 6}); - std::transform(in.begin(), in.end(), out2.begin(), out2.begin(), [](auto const& in_elem, auto&& out2_elem) { - fftw::dft_forward({true, true}, in_elem, out2_elem); - return std::forward(out2_elem); - }); + std::random_device dev; + multi::array in({3, 5, 6}); + randomizer{dev()}(in); + multi::array out({3, 5, 6}); + fftw::dft_forward({false, true, true}, in, out); - BOOST_REQUIRE(out2 == out); -} + multi::array out2({3, 5, 6}); + std::transform(in.begin(), in.end(), out2.begin(), out2.begin(), [](auto const& in_elem, auto&& out2_elem) { + fftw::dft_forward({true, true}, in_elem, out2_elem); + return std::forward(out2_elem); + }); -BOOST_AUTO_TEST_CASE(fftw_2D_power_plan) { - using complex = std::complex; + BOOST_TEST(out2 == out); + } - [[maybe_unused]] auto const I = complex{0.0, 1.0}; // NOLINT(readability-identifier-length) imag unit + BOOST_AUTO_TEST_CASE(fftw_2D_power_plan) { + using complex = std::complex; - multi::array in({16, 16}); - std::iota(data_elements(in), data_elements(in) + num_elements(in), 1.2); // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic): test code - multi::array out(extensions(in)); - auto const pln = multi::fftw::plan::forward({true, true}, in.base(), in.layout(), out.base(), out.layout()); - pln.execute(in.base(), out.base()); - BOOST_REQUIRE( power(in) - power(out)/num_elements(out) < 1e-7 ); -} + [[maybe_unused]] auto const I = complex{0.0, 1.0}; // NOLINT(readability-identifier-length) imag unit -BOOST_AUTO_TEST_CASE(fftw_2D_power_plan_modern) { - using complex = std::complex; + multi::array in({16, 16}); + std::iota(data_elements(in), data_elements(in) + num_elements(in), 1.2); // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic): test code + multi::array out(extensions(in)); + auto const pln = multi::fftw::plan::forward({true, true}, in.base(), in.layout(), out.base(), out.layout()); + pln.execute(in.base(), out.base()); + BOOST_TEST( power(in) - power(out)/num_elements(out) < 1e-7 ); + } - [[maybe_unused]] auto const I = complex{0.0, 1.0}; // NOLINT(readability-identifier-length) imag unit + BOOST_AUTO_TEST_CASE(fftw_2D_power_plan_modern) { + using complex = std::complex; - multi::array in({16, 16}); - std::iota(data_elements(in), data_elements(in) + num_elements(in), 1.2); // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic): test code - multi::array out(extensions(in)); - auto const pln = multi::fftw::plan::forward({true, true}, in.base(), in.layout(), out.base(), out.layout()); - pln.execute(in.base(), out.base()); - BOOST_REQUIRE( power(in) - power(out)/num_elements(out) < 1e-8 ); -} + [[maybe_unused]] auto const I = complex{0.0, 1.0}; // NOLINT(readability-identifier-length) imag unit -BOOST_AUTO_TEST_CASE(fftw_2D_power_plan_modern_measure) { - using complex = std::complex; + multi::array in({16, 16}); + std::iota(data_elements(in), data_elements(in) + num_elements(in), 1.2); // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic): test code + multi::array out(extensions(in)); + auto const pln = multi::fftw::plan::forward({true, true}, in.base(), in.layout(), out.base(), out.layout()); + pln.execute(in.base(), out.base()); + BOOST_TEST( power(in) - power(out)/num_elements(out) < 1e-8 ); + } - [[maybe_unused]] auto const I = complex{0.0, 1.0}; // NOLINT(readability-identifier-length) imag unit + BOOST_AUTO_TEST_CASE(fftw_2D_power_plan_modern_measure) { + using complex = std::complex; - multi::array in({16, 16}); - std::iota(data_elements(in), data_elements(in) + num_elements(in), 1.2); // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic): test code - multi::array out(extensions(in)); - auto const pln = multi::fftw::plan::forward({true, true}, in.base(), in.layout(), out.base(), out.layout()); - pln.execute(in.base(), out.base()); - BOOST_REQUIRE( power(in) - power(out)/num_elements(out) < 1e-8 ); -} + [[maybe_unused]] auto const I = complex{0.0, 1.0}; // NOLINT(readability-identifier-length) imag unit -BOOST_AUTO_TEST_CASE(fftw_2D_power_dft) { - using complex = std::complex; - [[maybe_unused]] auto const I = complex{0.0, 1.0}; // NOLINT(readability-identifier-length) imag unit + multi::array in({16, 16}); + std::iota(data_elements(in), data_elements(in) + num_elements(in), 1.2); // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic): test code + multi::array out(extensions(in)); + auto const pln = multi::fftw::plan::forward({true, true}, in.base(), in.layout(), out.base(), out.layout()); + pln.execute(in.base(), out.base()); + BOOST_TEST( power(in) - power(out)/num_elements(out) < 1e-8 ); + } - multi::array in({16, 16}); - std::iota(data_elements(in), data_elements(in) + num_elements(in), 1.2); // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic): test code - multi::array out(extensions(in)); - multi::fftw::dft_forward({true, true}, in, out); - BOOST_REQUIRE( power(in) - power(out)/num_elements(out) < 1e-8 ); -} + BOOST_AUTO_TEST_CASE(fftw_2D_power_dft) { + using complex = std::complex; + [[maybe_unused]] auto const I = complex{0.0, 1.0}; // NOLINT(readability-identifier-length) imag unit -BOOST_AUTO_TEST_CASE(fftw_3D_power_in_place_over_ref_inplace) { - using complex = std::complex; + multi::array in({16, 16}); + std::iota(data_elements(in), data_elements(in) + num_elements(in), 1.2); // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic): test code + multi::array out(extensions(in)); + multi::fftw::dft_forward({true, true}, in, out); + BOOST_TEST( power(in) - power(out)/num_elements(out) < 1e-8 ); + } - [[maybe_unused]] auto const I = complex{0.0, 1.0}; // NOLINT(readability-identifier-length) imag unit + BOOST_AUTO_TEST_CASE(fftw_3D_power_in_place_over_ref_inplace) { + using complex = std::complex; - multi::array io({4, 4, 4}); - std::iota(io.data_elements(), io.data_elements() + io.num_elements(), 1.2); // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic): test code - auto const powerin = power(io); + [[maybe_unused]] auto const I = complex{0.0, 1.0}; // NOLINT(readability-identifier-length) imag unit - // fftw::dft_inplace(multi::array_ref(io.data(), io.extensions()), fftw::forward); + multi::array io({4, 4, 4}); + std::iota(io.data_elements(), io.data_elements() + io.num_elements(), 1.2); // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic): test code + auto const powerin = power(io); - fftw::dft_forward( - {true, true, true}, - multi::array_ref(data_elements(io), extensions(io)), - multi::array_ref(data_elements(io), extensions(io)) - ); - BOOST_REQUIRE( powerin - power(io)/num_elements(io) < 1e-10 ); -} + // fftw::dft_inplace(multi::array_ref(io.data(), io.extensions()), fftw::forward); -BOOST_AUTO_TEST_CASE(fftw_2D_const_range_ref) { - using complex = std::complex; + fftw::dft_forward( + {true, true, true}, + multi::array_ref(data_elements(io), extensions(io)), + multi::array_ref(data_elements(io), extensions(io)) + ); + BOOST_TEST( powerin - power(io)/num_elements(io) < 1e-10 ); + } - [[maybe_unused]] auto const I = complex{0.0, 1.0}; // NOLINT(readability-identifier-length) imag unit + BOOST_AUTO_TEST_CASE(fftw_2D_const_range_ref) { + using complex = std::complex; - multi::array const in = { - {100.0 + 2.0 * I, 9.0 - 1.0 * I, 2.0 + 4.0 * I}, - { 3.0 + 3.0 * I, 7.0 - 4.0 * I, 1.0 + 9.0 * I}, - { 4.0 + 1.0 * I, 5.0 + 3.0 * I, 2.0 + 4.0 * I}, - { 3.0 - 1.0 * I, 8.0 + 7.0 * I, 2.0 + 1.0 * I}, - { 31.0 - 1.0 * I, 18.0 + 7.0 * I, 2.0 + 10.0 * I}, - }; -} + [[maybe_unused]] auto const I = complex{0.0, 1.0}; // NOLINT(readability-identifier-length) imag unit + + multi::array const in = { + {100.0 + 2.0 * I, 9.0 - 1.0 * I, 2.0 + 4.0 * I}, + { 3.0 + 3.0 * I, 7.0 - 4.0 * I, 1.0 + 9.0 * I}, + { 4.0 + 1.0 * I, 5.0 + 3.0 * I, 2.0 + 4.0 * I}, + { 3.0 - 1.0 * I, 8.0 + 7.0 * I, 2.0 + 1.0 * I}, + { 31.0 - 1.0 * I, 18.0 + 7.0 * I, 2.0 + 10.0 * I}, + }; + } -BOOST_AUTO_TEST_CASE(fftw_2D_const_range_ref_transposed_naive_square) { - using complex = std::complex; + BOOST_AUTO_TEST_CASE(fftw_2D_const_range_ref_transposed_naive_square) { + using complex = std::complex; - [[maybe_unused]] auto const I = complex{0.0, 1.0}; // NOLINT(readability-identifier-length) imag unit + [[maybe_unused]] auto const I = complex{0.0, 1.0}; // NOLINT(readability-identifier-length) imag unit - multi::array in = { - {100.0 + 2.0 * I, 9.0 - 1.0 * I, 2.0 + 4.0 * I}, - { 3.0 + 3.0 * I, 7.0 - 4.0 * I, 1.0 + 9.0 * I}, - { 4.0 + 1.0 * I, 5.0 + 3.0 * I, 2.0 + 4.0 * I}, - }; - multi::array const in_transpose = in.transposed(); - in = in.transposed(); - BOOST_REQUIRE( in != in_transpose ); -} + multi::array in = { + {100.0 + 2.0 * I, 9.0 - 1.0 * I, 2.0 + 4.0 * I}, + { 3.0 + 3.0 * I, 7.0 - 4.0 * I, 1.0 + 9.0 * I}, + { 4.0 + 1.0 * I, 5.0 + 3.0 * I, 2.0 + 4.0 * I}, + }; + multi::array const in_transpose = in.transposed(); + in = in.transposed(); + BOOST_TEST( in != in_transpose ); + } -BOOST_AUTO_TEST_CASE(fftw_2D_const_range_ref_transposed_nonpod) { - using namespace std::string_literals; // NOLINT(build/namespaces) for ""s - multi::array in = { - {"100.0 + 2.0*I"s, "9.0 - 1.0*I"s, "2.0 + 4.0*I"s}, - { "3.0 + 3.0*I"s, "7.0 - 4.0*I"s, "1.0 + 9.0*I"s}, - { "4.0 + 1.0*I"s, "5.0 + 3.0*I"s, "2.0 + 4.0*I"s}, - { "3.0 - 1.0*I"s, "8.0 + 7.0*I"s, "2.0 + 1.0*I"s}, - { "31.0 - 1.0*I"s, "18.0 + 7.0*I"s, "2.0 + 10.0*I"s}, - }; - multi::array const in_transpose = in.transposed(); - in = in.transposed(); - BOOST_REQUIRE( in != in_transpose ); -} + BOOST_AUTO_TEST_CASE(fftw_2D_const_range_ref_transposed_nonpod) { + using namespace std::string_literals; // NOLINT(build/namespaces) for ""s + multi::array in = { + {"100.0 + 2.0*I"s, "9.0 - 1.0*I"s, "2.0 + 4.0*I"s}, // NOLINT(misc-include-cleaner) bug in clang-tidy 18 + { "3.0 + 3.0*I"s, "7.0 - 4.0*I"s, "1.0 + 9.0*I"s}, + { "4.0 + 1.0*I"s, "5.0 + 3.0*I"s, "2.0 + 4.0*I"s}, + { "3.0 - 1.0*I"s, "8.0 + 7.0*I"s, "2.0 + 1.0*I"s}, + { "31.0 - 1.0*I"s, "18.0 + 7.0*I"s, "2.0 + 10.0*I"s}, + }; + multi::array const in_transpose = in.transposed(); + in = in.transposed(); + BOOST_TEST( in != in_transpose ); + } + + BOOST_AUTO_TEST_CASE(fftw_2D_const_range_ref_transposed_nonpod_square) { + using namespace std::string_literals; // NOLINT(build/namespaces) for ""s + + multi::array in = { + {"100.0 + 2.0*I"s, "9.0 - 1.0*I"s, "2.0 + 4.0*I"s}, + { "3.0 + 3.0*I"s, "7.0 - 4.0*I"s, "1.0 + 9.0*I"s}, + { "4.0 + 1.0*I"s, "5.0 + 3.0*I"s, "2.0 + 4.0*I"s}, + }; + multi::array const in_transpose = in.transposed(); + in = in.transposed(); + BOOST_TEST( in != in_transpose ); + } -BOOST_AUTO_TEST_CASE(fftw_2D_const_range_ref_transposed_nonpod_square) { - using namespace std::string_literals; // NOLINT(build/namespaces) for ""s - - multi::array in = { - {"100.0 + 2.0*I"s, "9.0 - 1.0*I"s, "2.0 + 4.0*I"s}, - { "3.0 + 3.0*I"s, "7.0 - 4.0*I"s, "1.0 + 9.0*I"s}, - { "4.0 + 1.0*I"s, "5.0 + 3.0*I"s, "2.0 + 4.0*I"s}, - }; - multi::array const in_transpose = in.transposed(); - in = in.transposed(); - BOOST_REQUIRE( in != in_transpose ); + return boost::report_errors(); } diff --git a/external_codes/boost_multi/multi/include/boost/multi/adaptors/fftw/test/moved.cpp b/external_codes/boost_multi/multi/include/boost/multi/adaptors/fftw/test/moved.cpp index 206f266766..c40f0da47c 100644 --- a/external_codes/boost_multi/multi/include/boost/multi/adaptors/fftw/test/moved.cpp +++ b/external_codes/boost_multi/multi/include/boost/multi/adaptors/fftw/test/moved.cpp @@ -1,301 +1,261 @@ // Copyright 2020-2024 Alfredo A. Correa -#include - #include #include +#include #include // for std::transform_reduce namespace multi = boost::multi; template auto power(M const& array) { - return std::accumulate(array.elements().begin(), array.elements().end(), 0.0, [](auto e1, auto e2) {return std::move(e1) + std::norm(e2);}); -// return std::transform_reduce(array.elements().begin(), array.elements().end(), 0.0, std::plus<>{}, [](auto zee) { return std::norm(zee); }); + return std::accumulate(array.elements().begin(), array.elements().end(), 0.0, [](auto e1, auto e2) { return std::move(e1) + std::norm(e2); }); + // return std::transform_reduce(array.elements().begin(), array.elements().end(), 0.0, std::plus<>{}, [](auto zee) { return std::norm(zee); }); } -using fftw_fixture = multi::fftw::environment; -BOOST_TEST_GLOBAL_FIXTURE(fftw_fixture); - -// BOOST_AUTO_TEST_CASE(fftw_2D_const_range_fft_move) { -// using complex = std::complex; [[maybe_unused]] auto const I = complex{0.0, 1.0}; // NOLINT(readability-identifier-length) imag unit - -// multi::array in = { -// {100.0 + 2.0 * I, 9. - 1.0 * I, 2.0 + 4.0 * I}, -// { 3.0 + 3.0 * I, 7. - 4.0 * I, 1.0 + 9.0 * I}, -// { 4.0 + 1.0 * I, 5. + 3.0 * I, 2.0 + 4.0 * I}, -// { 3.0 - 1.0 * I, 8. + 7.0 * I, 2.0 + 1.0 * I}, -// { 31.0 - 1.0 * I, 18. + 7.0 * I, 2.0 + 10.0 * I}, -// }; - -// auto const in_copy = in; -// // auto* const in_base = in.base(); - -// // multi::array in2(in.extensions()); - -// // in2 = multi::fftw::fft(std::move(in)); - -// // BOOST_REQUIRE( power(in2)/num_elements(in2) - power(in_copy) < 1e-8 ); -// // BOOST_REQUIRE( in2.base() == in_base ); -// // BOOST_REQUIRE( in.is_empty() ); // NOLINT(bugprone-use-after-move,hicpp-invalid-access-moved) for testing -// } - -BOOST_AUTO_TEST_CASE(fftw_2D_const_range_move) { - using complex = std::complex; [[maybe_unused]] auto const I = complex{0.0, 1.0}; // NOLINT(readability-identifier-length) imag unit - - multi::array in = { - {100.0 + 2.0 * I, 9.0 - 1.0 * I, 2.0 + 4.0 * I}, - { 3.0 + 3.0 * I, 7.0 - 4.0 * I, 1.0 + 9.0 * I}, - { 4.0 + 1.0 * I, 5.0 + 3.0 * I, 2.0 + 4.0 * I}, - { 3.0 - 1.0 * I, 8.0 + 7.0 * I, 2.0 + 1.0 * I}, - { 31.0 - 1.0 * I, 18.0 + 7.0 * I, 2.0 + 10.0 * I}, - }; - BOOST_REQUIRE( in[1][1] == 7.0 - 4.0*I ); - - auto const in_copy = in; - auto* const in_base = in.base(); - BOOST_REQUIRE( in_base == in.base() ); - - // in = multi::fftw::ref(in); - - // BOOST_REQUIRE( in == in_copy ); - // BOOST_REQUIRE( in_base == in.base() ); // prove no allocation +#include +#define BOOST_AUTO_TEST_CASE(CasenamE) /**/ + +auto main() -> int { // NOLINT(readability-function-cognitive-complexity,bugprone-exception-escape) + multi::fftw::environment const env; + + BOOST_AUTO_TEST_CASE(fftw_2D_const_range_move) { + using complex = std::complex; + [[maybe_unused]] auto const I = complex{0.0, 1.0}; // NOLINT(readability-identifier-length) imag unit + + multi::array in = { + {100.0 + 2.0 * I, 9.0 - 1.0 * I, 2.0 + 4.0 * I}, + { 3.0 + 3.0 * I, 7.0 - 4.0 * I, 1.0 + 9.0 * I}, + { 4.0 + 1.0 * I, 5.0 + 3.0 * I, 2.0 + 4.0 * I}, + { 3.0 - 1.0 * I, 8.0 + 7.0 * I, 2.0 + 1.0 * I}, + { 31.0 - 1.0 * I, 18.0 + 7.0 * I, 2.0 + 10.0 * I}, + }; + BOOST_TEST( in[1][1] == 7.0 - 4.0*I ); + + auto const in_copy = in; + auto* const in_base = in.base(); + BOOST_TEST( in_base == in.base() ); + + // in = multi::fftw::ref(in); + + // BOOST_TEST( in == in_copy ); + // BOOST_TEST( in_base == in.base() ); // prove no allocation + } + + BOOST_AUTO_TEST_CASE(fftw_2D_const_range_transposed) { + using complex = std::complex; + [[maybe_unused]] auto const I = complex{0.0, 1.0}; // NOLINT(readability-identifier-length) imag unit + + multi::array in = { + {100.0 + 2.0 * I, 9.0 - 1.0 * I, 2.0 + 4.0 * I}, + { 3.0 + 3.0 * I, 7.0 - 4.0 * I, 1.0 + 9.0 * I}, + { 4.0 + 1.0 * I, 5.0 + 3.0 * I, 2.0 + 4.0 * I}, + { 3.0 - 1.0 * I, 8.0 + 7.0 * I, 2.0 + 1.0 * I}, + { 31.0 - 1.0 * I, 18.0 + 7.0 * I, 2.0 + 10.0 * I}, + }; + BOOST_TEST( in[1][1] == 7.0 - 4.0*I ); + + auto const in_copy = in; + auto* const in_base = in.base(); + BOOST_TEST( in_base == in.base() ); + BOOST_TEST( in.size() == 5 ); + + // in = multi::fftw::ref(in).transposed(); + + // BOOST_TEST( in.size() == 3 ); + // BOOST_TEST( in == in_copy.transposed() ); // prove correctness + // BOOST_TEST( in_base == in.base() ); // prove no allocation + } + + BOOST_AUTO_TEST_CASE(fftw_2D_const_range_transposed_naive) { + using complex = std::complex; + [[maybe_unused]] auto const I = complex{0.0, 1.0}; // NOLINT(readability-identifier-length) imag unit + + multi::array in = { + {100.0 + 2.0 * I, 9.0 - 1.0 * I, 2.0 + 4.0 * I}, + { 3.0 + 3.0 * I, 7.0 - 4.0 * I, 1.0 + 9.0 * I}, + { 4.0 + 1.0 * I, 5.0 + 3.0 * I, 2.0 + 4.0 * I}, + { 3.0 - 1.0 * I, 8.0 + 7.0 * I, 2.0 + 1.0 * I}, + { 31.0 - 1.0 * I, 18.0 + 7.0 * I, 2.0 + 10.0 * I}, + }; + BOOST_TEST( in[1][1] == 7.0 - 4.0*I ); + + auto const in_copy = in; + auto* const in_base = in.base(); + BOOST_TEST( in_base == in.base() ); + BOOST_TEST( in.size() == 5 ); + + in = in.transposed(); // this is UB + + BOOST_TEST( in.size() == 3 ); + // BOOST_TEST( in != in_copy.transposed() ); // prove it is incorrect + BOOST_TEST( in_base == in.base() ); // prove no allocation + } + + BOOST_AUTO_TEST_CASE(fftw_2D_const_range_transposed_naive_copy) { + using complex = std::complex; + [[maybe_unused]] auto const I = complex{0.0, 1.0}; // NOLINT(readability-identifier-length) imag unit + + multi::array in = { + {100.0 + 2.0 * I, 9.0 - 1.0 * I, 2.0 + 4.0 * I}, + { 3.0 + 3.0 * I, 7.0 - 4.0 * I, 1.0 + 9.0 * I}, + { 4.0 + 1.0 * I, 5.0 + 3.0 * I, 2.0 + 4.0 * I}, + { 3.0 - 1.0 * I, 8.0 + 7.0 * I, 2.0 + 1.0 * I}, + { 31.0 - 1.0 * I, 18.0 + 7.0 * I, 2.0 + 10.0 * I}, + }; + BOOST_TEST( in[1][1] == 7.0 - 4.0*I ); + + auto const in_copy = in; + auto* const in_base = in.base(); + BOOST_TEST( in_base == in.base() ); + BOOST_TEST( in.size() == 5 ); + + in = +in.transposed(); + + BOOST_TEST( in.size() == 3 ); + BOOST_TEST( in == in_copy.transposed() ); // prove correctness + BOOST_TEST( in_base != in.base() ); // prove no allocation + } + + // BOOST_AUTO_TEST_CASE(fftw_2D_const_range_fft_copy) { + // using complex = std::complex; [[maybe_unused]] auto const I = complex{0.0, 1.0}; // NOLINT(readability-identifier-length) imag unit + + // multi::array in = { + // {100.0 + 2.0 * I, 9.0 - 1.0 * I, 2.0 + 4.0 * I}, + // { 3.0 + 3.0 * I, 7.0 - 4.0 * I, 1.0 + 9.0 * I}, + // { 4.0 + 1.0 * I, 5.0 + 3.0 * I, 2.0 + 4.0 * I}, + // { 3.0 - 1.0 * I, 8.0 + 7.0 * I, 2.0 + 1.0 * I}, + // { 31.0 - 1.0 * I, 18.0 + 7.0 * I, 2.0 + 10.0 * I}, + // }; + + // auto const in_copy = in; + // auto* const in_base = in.base(); + + // multi::array in2 = multi::fftw::fft(in); + + // BOOST_TEST( power(in2)/num_elements(in2) - power(in_copy) < 1e-8 ); + // BOOST_TEST( in2.base() != in_base ); + // BOOST_TEST( not in.is_empty() ); // NOLINT(bugprone-use-after-move,hicpp-invalid-access-moved) for testing + // } + + // BOOST_AUTO_TEST_CASE(fftw_2D_const_range_transposed_copyconstruct) { + // using complex = std::complex; [[maybe_unused]] auto const I = complex{0.0, 1.0}; // NOLINT(readability-identifier-length) imag unit + + // multi::array in = { + // {100.0 + 2.0 * I, 9.0 - 1.0 * I, 2.0 + 4.0 * I}, + // { 3.0 + 3.0 * I, 7.0 - 4.0 * I, 1.0 + 9.0 * I}, + // { 4.0 + 1.0 * I, 5.0 + 3.0 * I, 2.0 + 4.0 * I}, + // { 3.0 - 1.0 * I, 8.0 + 7.0 * I, 2.0 + 1.0 * I}, + // { 31.0 - 1.0 * I, 18.0 + 7.0 * I, 2.0 + 10.0 * I}, + // }; + + // auto const in_copy = in; + // auto* const in_base = in.base(); + + // multi::array in2 = multi::fftw::ref(in).transposed(); + + // BOOST_TEST( in2 == in_copy.transposed() ); + // BOOST_TEST( in2.base() != in_base ); + // BOOST_TEST( in .base() == in_base ); // NOLINT(bugprone-use-after-move,hicpp-invalid-access-moved) for testing + // } + + // BOOST_AUTO_TEST_CASE(fftw_2D_const_range_transposed_moveconstruct) { + // using complex = std::complex; [[maybe_unused]] auto const I = complex{0.0, 1.0}; // NOLINT(readability-identifier-length) imag unit + + // multi::array in = { + // {100.0 + 2.0 * I, 9.0 - 1.0 * I, 2.0 + 4.0 * I}, + // { 3.0 + 3.0 * I, 7.0 - 4.0 * I, 1.0 + 9.0 * I}, + // { 4.0 + 1.0 * I, 5.0 + 3.0 * I, 2.0 + 4.0 * I}, + // { 3.0 - 1.0 * I, 8.0 + 7.0 * I, 2.0 + 1.0 * I}, + // { 31.0 - 1.0 * I, 18.0 + 7.0 * I, 2.0 + 10.0 * I}, + // }; + + // auto const in_copy = in; + // auto* const in_base = in.base(); + + // multi::array in2 = multi::fftw::ref(std::move(in)).transposed(); + + // BOOST_TEST( in2 == in_copy.transposed() ); + // BOOST_TEST( in2.base() == in_base ); + // BOOST_TEST( in.is_empty() ); // NOLINT(bugprone-use-after-move,hicpp-invalid-access-moved) for testing + // } + + // BOOST_AUTO_TEST_CASE(fftw_2D_const_range_transposed_moveconstruct_implicit) { + // using complex = std::complex; [[maybe_unused]] auto const I = complex{0.0, 1.0}; // NOLINT(readability-identifier-length) imag unit + + // #if not defined(__INTEL_COMPILER) // TODO(correaa) problem with icpc 2022.3.0.8751 + // multi::array in = { + // {100.0 + 2.0 * I, 9.0 - 1.0 * I, 2.0 + 4.0 * I}, + // { 3.0 + 3.0 * I, 7.0 - 4.0 * I, 1.0 + 9.0 * I}, + // { 4.0 + 1.0 * I, 5.0 + 3.0 * I, 2.0 + 4.0 * I}, + // { 3.0 - 1.0 * I, 8.0 + 7.0 * I, 2.0 + 1.0 * I}, + // { 31.0 - 1.0 * I, 18.0 + 7.0 * I, 2.0 + 10.0 * I}, + // }; + + // auto const in_copy = in; + // auto* const in_base = in.base(); + + // auto in2 = +multi::fftw::ref(std::move(in)).transposed(); + + // BOOST_TEST( in2 == in_copy.transposed() ); + // #if not defined(__NVCOMPILER) // these tests fail with nvc++ 22.9, 23.1 + // BOOST_TEST( in2.base() == in_base ); + // BOOST_TEST( in.is_empty() ); // NOLINT(bugprone-use-after-move,hicpp-invalid-access-moved) for testing + // #endif + // #endif + // } + + // BOOST_AUTO_TEST_CASE(fftw_2D_const_range_transposed_moveassign_from_temp) { + // using complex = std::complex; [[maybe_unused]] auto const I = complex{0.0, 1.0}; // NOLINT(readability-identifier-length) imag unit + + // #if not defined(__INTEL_COMPILER) // TODO(correaa) problem with icpc 2022.3.0.8751 + // multi::array in = { + // {100.0 + 2.0 * I, 9.0 - 1.0 * I, 2.0 + 4.0 * I}, + // { 3.0 + 3.0 * I, 7.0 - 4.0 * I, 1.0 + 9.0 * I}, + // { 4.0 + 1.0 * I, 5.0 + 3.0 * I, 2.0 + 4.0 * I}, + // { 3.0 - 1.0 * I, 8.0 + 7.0 * I, 2.0 + 1.0 * I}, + // { 31.0 - 1.0 * I, 18.0 + 7.0 * I, 2.0 + 10.0 * I}, + // }; + + // auto const in_copy = in; + // auto* const in_base = in.base(); + + // multi::array in2; + // in2 = static_cast>(multi::fftw::ref(std::move(in)).transposed()); + + // BOOST_TEST( in2 == in_copy.transposed() ); + // #if not defined(__NVCOMPILER) // these tests fail with nvc++ 22.9, 23.1 + // BOOST_TEST( in2.base() == in_base ); + // BOOST_TEST( in.is_empty() ); // NOLINT(bugprone-use-after-move,hicpp-invalid-access-moved) for testing + // #endif + // #endif + // } + + // BOOST_AUTO_TEST_CASE(fftw_2D_const_range_transposed_moveassign) { + // using complex = std::complex; [[maybe_unused]] auto const I = complex{0.0, 1.0}; // NOLINT(readability-identifier-length) imag unit + + // #if not defined(__INTEL_COMPILER) // TODO(correaa) problem with icpc 2022.3.0.8751 + // multi::array in = { + // {100.0 + 2.0 * I, 9.0 - 1.0 * I, 2.0 + 4.0 * I}, + // { 3.0 + 3.0 * I, 7.0 - 4.0 * I, 1.0 + 9.0 * I}, + // { 4.0 + 1.0 * I, 5.0 + 3.0 * I, 2.0 + 4.0 * I}, + // { 3.0 - 1.0 * I, 8.0 + 7.0 * I, 2.0 + 1.0 * I}, + // { 31.0 - 1.0 * I, 18.0 + 7.0 * I, 2.0 + 10.0 * I}, + // }; + + // auto const in_copy = in; + // auto* const in_base = in.base(); + + // multi::array in2; + // in2 = multi::fftw::ref(std::move(in)).transposed(); + + // BOOST_TEST( in2 == in_copy.transposed() ); + // #if not defined(__NVCOMPILER) // these tests fail with nvc++ 22.9, 23.1 + // BOOST_TEST( in2.base() == in_base ); + // BOOST_TEST( in.is_empty() ); // NOLINT(bugprone-use-after-move,hicpp-invalid-access-moved) for testing + // #endif + // #endif + // } + + return boost::report_errors(); } - -BOOST_AUTO_TEST_CASE(fftw_2D_const_range_transposed) { - using complex = std::complex; [[maybe_unused]] auto const I = complex{0.0, 1.0}; // NOLINT(readability-identifier-length) imag unit - - multi::array in = { - {100.0 + 2.0 * I, 9.0 - 1.0 * I, 2.0 + 4.0 * I}, - { 3.0 + 3.0 * I, 7.0 - 4.0 * I, 1.0 + 9.0 * I}, - { 4.0 + 1.0 * I, 5.0 + 3.0 * I, 2.0 + 4.0 * I}, - { 3.0 - 1.0 * I, 8.0 + 7.0 * I, 2.0 + 1.0 * I}, - { 31.0 - 1.0 * I, 18.0 + 7.0 * I, 2.0 + 10.0 * I}, - }; - BOOST_REQUIRE( in[1][1] == 7.0 - 4.0*I ); - - auto const in_copy = in; - auto* const in_base = in.base(); - BOOST_REQUIRE( in_base == in.base() ); - BOOST_REQUIRE( in.size() == 5 ); - -// in = multi::fftw::ref(in).transposed(); - -// BOOST_REQUIRE( in.size() == 3 ); -// BOOST_REQUIRE( in == in_copy.transposed() ); // prove correctness -// BOOST_REQUIRE( in_base == in.base() ); // prove no allocation -} - -BOOST_AUTO_TEST_CASE(fftw_2D_const_range_transposed_naive) { - using complex = std::complex; [[maybe_unused]] auto const I = complex{0.0, 1.0}; // NOLINT(readability-identifier-length) imag unit - - multi::array in = { - {100.0 + 2.0 * I, 9.0 - 1.0 * I, 2.0 + 4.0 * I}, - { 3.0 + 3.0 * I, 7.0 - 4.0 * I, 1.0 + 9.0 * I}, - { 4.0 + 1.0 * I, 5.0 + 3.0 * I, 2.0 + 4.0 * I}, - { 3.0 - 1.0 * I, 8.0 + 7.0 * I, 2.0 + 1.0 * I}, - { 31.0 - 1.0 * I, 18.0 + 7.0 * I, 2.0 + 10.0 * I}, - }; - BOOST_REQUIRE( in[1][1] == 7.0 - 4.0*I ); - - auto const in_copy = in; - auto* const in_base = in.base(); - BOOST_REQUIRE( in_base == in.base() ); - BOOST_REQUIRE( in.size() == 5 ); - - in = in.transposed(); // this is UB - - BOOST_REQUIRE( in.size() == 3 ); - // BOOST_REQUIRE( in != in_copy.transposed() ); // prove it is incorrect - BOOST_REQUIRE( in_base == in.base() ); // prove no allocation -} - -BOOST_AUTO_TEST_CASE(fftw_2D_const_range_transposed_naive_copy) { - using complex = std::complex; [[maybe_unused]] auto const I = complex{0.0, 1.0}; // NOLINT(readability-identifier-length) imag unit - - multi::array in = { - {100.0 + 2.0 * I, 9.0 - 1.0 * I, 2.0 + 4.0 * I}, - { 3.0 + 3.0 * I, 7.0 - 4.0 * I, 1.0 + 9.0 * I}, - { 4.0 + 1.0 * I, 5.0 + 3.0 * I, 2.0 + 4.0 * I}, - { 3.0 - 1.0 * I, 8.0 + 7.0 * I, 2.0 + 1.0 * I}, - { 31.0 - 1.0 * I, 18.0 + 7.0 * I, 2.0 + 10.0 * I}, - }; - BOOST_REQUIRE( in[1][1] == 7.0 - 4.0*I ); - - auto const in_copy = in; - auto* const in_base = in.base(); - BOOST_REQUIRE( in_base == in.base() ); - BOOST_REQUIRE( in.size() == 5 ); - - in = +in.transposed(); - - BOOST_REQUIRE( in.size() == 3 ); - BOOST_REQUIRE( in == in_copy.transposed() ); // prove correctness - BOOST_REQUIRE( in_base != in.base() ); // prove no allocation -} - -// BOOST_AUTO_TEST_CASE(fftw_2D_const_range_fft_copy) { -// using complex = std::complex; [[maybe_unused]] auto const I = complex{0.0, 1.0}; // NOLINT(readability-identifier-length) imag unit - -// multi::array in = { -// {100.0 + 2.0 * I, 9.0 - 1.0 * I, 2.0 + 4.0 * I}, -// { 3.0 + 3.0 * I, 7.0 - 4.0 * I, 1.0 + 9.0 * I}, -// { 4.0 + 1.0 * I, 5.0 + 3.0 * I, 2.0 + 4.0 * I}, -// { 3.0 - 1.0 * I, 8.0 + 7.0 * I, 2.0 + 1.0 * I}, -// { 31.0 - 1.0 * I, 18.0 + 7.0 * I, 2.0 + 10.0 * I}, -// }; - -// auto const in_copy = in; -// auto* const in_base = in.base(); - -// multi::array in2 = multi::fftw::fft(in); - -// BOOST_REQUIRE( power(in2)/num_elements(in2) - power(in_copy) < 1e-8 ); -// BOOST_REQUIRE( in2.base() != in_base ); -// BOOST_REQUIRE( not in.is_empty() ); // NOLINT(bugprone-use-after-move,hicpp-invalid-access-moved) for testing -// } - -// BOOST_AUTO_TEST_CASE(fftw_2D_const_range_transposed_copyconstruct) { -// using complex = std::complex; [[maybe_unused]] auto const I = complex{0.0, 1.0}; // NOLINT(readability-identifier-length) imag unit - -// multi::array in = { -// {100.0 + 2.0 * I, 9.0 - 1.0 * I, 2.0 + 4.0 * I}, -// { 3.0 + 3.0 * I, 7.0 - 4.0 * I, 1.0 + 9.0 * I}, -// { 4.0 + 1.0 * I, 5.0 + 3.0 * I, 2.0 + 4.0 * I}, -// { 3.0 - 1.0 * I, 8.0 + 7.0 * I, 2.0 + 1.0 * I}, -// { 31.0 - 1.0 * I, 18.0 + 7.0 * I, 2.0 + 10.0 * I}, -// }; - -// auto const in_copy = in; -// auto* const in_base = in.base(); - -// multi::array in2 = multi::fftw::ref(in).transposed(); - -// BOOST_REQUIRE( in2 == in_copy.transposed() ); -// BOOST_REQUIRE( in2.base() != in_base ); -// BOOST_REQUIRE( in .base() == in_base ); // NOLINT(bugprone-use-after-move,hicpp-invalid-access-moved) for testing -// } - -// BOOST_AUTO_TEST_CASE(fftw_2D_const_range_transposed_moveconstruct) { -// using complex = std::complex; [[maybe_unused]] auto const I = complex{0.0, 1.0}; // NOLINT(readability-identifier-length) imag unit - -// multi::array in = { -// {100.0 + 2.0 * I, 9.0 - 1.0 * I, 2.0 + 4.0 * I}, -// { 3.0 + 3.0 * I, 7.0 - 4.0 * I, 1.0 + 9.0 * I}, -// { 4.0 + 1.0 * I, 5.0 + 3.0 * I, 2.0 + 4.0 * I}, -// { 3.0 - 1.0 * I, 8.0 + 7.0 * I, 2.0 + 1.0 * I}, -// { 31.0 - 1.0 * I, 18.0 + 7.0 * I, 2.0 + 10.0 * I}, -// }; - -// auto const in_copy = in; -// auto* const in_base = in.base(); - -// multi::array in2 = multi::fftw::ref(std::move(in)).transposed(); - -// BOOST_REQUIRE( in2 == in_copy.transposed() ); -// BOOST_REQUIRE( in2.base() == in_base ); -// BOOST_REQUIRE( in.is_empty() ); // NOLINT(bugprone-use-after-move,hicpp-invalid-access-moved) for testing -// } - -// BOOST_AUTO_TEST_CASE(fftw_2D_const_range_transposed_moveconstruct_implicit) { -// using complex = std::complex; [[maybe_unused]] auto const I = complex{0.0, 1.0}; // NOLINT(readability-identifier-length) imag unit - -// #if not defined(__INTEL_COMPILER) // TODO(correaa) problem with icpc 2022.3.0.8751 -// multi::array in = { -// {100.0 + 2.0 * I, 9.0 - 1.0 * I, 2.0 + 4.0 * I}, -// { 3.0 + 3.0 * I, 7.0 - 4.0 * I, 1.0 + 9.0 * I}, -// { 4.0 + 1.0 * I, 5.0 + 3.0 * I, 2.0 + 4.0 * I}, -// { 3.0 - 1.0 * I, 8.0 + 7.0 * I, 2.0 + 1.0 * I}, -// { 31.0 - 1.0 * I, 18.0 + 7.0 * I, 2.0 + 10.0 * I}, -// }; - -// auto const in_copy = in; -// auto* const in_base = in.base(); - -// auto in2 = +multi::fftw::ref(std::move(in)).transposed(); - -// BOOST_REQUIRE( in2 == in_copy.transposed() ); -// #if not defined(__NVCOMPILER) // these tests fail with nvc++ 22.9, 23.1 -// BOOST_REQUIRE( in2.base() == in_base ); -// BOOST_REQUIRE( in.is_empty() ); // NOLINT(bugprone-use-after-move,hicpp-invalid-access-moved) for testing -// #endif -// #endif -// } - -// BOOST_AUTO_TEST_CASE(fftw_2D_const_range_transposed_moveassign_from_temp) { -// using complex = std::complex; [[maybe_unused]] auto const I = complex{0.0, 1.0}; // NOLINT(readability-identifier-length) imag unit - -// #if not defined(__INTEL_COMPILER) // TODO(correaa) problem with icpc 2022.3.0.8751 -// multi::array in = { -// {100.0 + 2.0 * I, 9.0 - 1.0 * I, 2.0 + 4.0 * I}, -// { 3.0 + 3.0 * I, 7.0 - 4.0 * I, 1.0 + 9.0 * I}, -// { 4.0 + 1.0 * I, 5.0 + 3.0 * I, 2.0 + 4.0 * I}, -// { 3.0 - 1.0 * I, 8.0 + 7.0 * I, 2.0 + 1.0 * I}, -// { 31.0 - 1.0 * I, 18.0 + 7.0 * I, 2.0 + 10.0 * I}, -// }; - -// auto const in_copy = in; -// auto* const in_base = in.base(); - -// multi::array in2; -// in2 = static_cast>(multi::fftw::ref(std::move(in)).transposed()); - -// BOOST_REQUIRE( in2 == in_copy.transposed() ); -// #if not defined(__NVCOMPILER) // these tests fail with nvc++ 22.9, 23.1 -// BOOST_REQUIRE( in2.base() == in_base ); -// BOOST_REQUIRE( in.is_empty() ); // NOLINT(bugprone-use-after-move,hicpp-invalid-access-moved) for testing -// #endif -// #endif -// } - -// BOOST_AUTO_TEST_CASE(fftw_2D_const_range_transposed_moveassign) { -// using complex = std::complex; [[maybe_unused]] auto const I = complex{0.0, 1.0}; // NOLINT(readability-identifier-length) imag unit - -// #if not defined(__INTEL_COMPILER) // TODO(correaa) problem with icpc 2022.3.0.8751 -// multi::array in = { -// {100.0 + 2.0 * I, 9.0 - 1.0 * I, 2.0 + 4.0 * I}, -// { 3.0 + 3.0 * I, 7.0 - 4.0 * I, 1.0 + 9.0 * I}, -// { 4.0 + 1.0 * I, 5.0 + 3.0 * I, 2.0 + 4.0 * I}, -// { 3.0 - 1.0 * I, 8.0 + 7.0 * I, 2.0 + 1.0 * I}, -// { 31.0 - 1.0 * I, 18.0 + 7.0 * I, 2.0 + 10.0 * I}, -// }; - -// auto const in_copy = in; -// auto* const in_base = in.base(); - -// multi::array in2; -// in2 = multi::fftw::ref(std::move(in)).transposed(); - -// BOOST_REQUIRE( in2 == in_copy.transposed() ); -// #if not defined(__NVCOMPILER) // these tests fail with nvc++ 22.9, 23.1 -// BOOST_REQUIRE( in2.base() == in_base ); -// BOOST_REQUIRE( in.is_empty() ); // NOLINT(bugprone-use-after-move,hicpp-invalid-access-moved) for testing -// #endif -// #endif -// } - -// BOOST_AUTO_TEST_CASE(fftw_2D_const_range_transposed_fftwmove) { -// using complex = std::complex; [[maybe_unused]] auto const I = complex{0.0, 1.0}; // NOLINT(readability-identifier-length) imag unit - -// #if not defined(__INTEL_COMPILER) // TODO(correaa) problem with icpc 2022.3.0.8751 -// multi::array in = { -// {100.0 + 2.0 * I, 9.0 - 1.0 * I, 2.0 + 4.0 * I}, -// { 3.0 + 3.0 * I, 7.0 - 4.0 * I, 1.0 + 9.0 * I}, -// { 4.0 + 1.0 * I, 5.0 + 3.0 * I, 2.0 + 4.0 * I}, -// { 3.0 - 1.0 * I, 8.0 + 7.0 * I, 2.0 + 1.0 * I}, -// { 31.0 - 1.0 * I, 18.0 + 7.0 * I, 2.0 + 10.0 * I}, -// }; - -// auto const in_copy = in; -// auto* const in_base = in.base(); - -// multi::array in2; -// in2 = multi::fftw::move(in).transposed(); - -// BOOST_REQUIRE( in2 == in_copy.transposed() ); -// #if not defined(__NVCOMPILER) // these tests fail with nvc++ 22.9, 23.1 -// BOOST_REQUIRE( in2.base() == in_base ); -// BOOST_REQUIRE( in.is_empty() ); // NOLINT(bugprone-use-after-move,hicpp-invalid-access-moved) for testing -// #endif -// #endif -// } diff --git a/external_codes/boost_multi/multi/include/boost/multi/adaptors/fftw/test/shift.cpp b/external_codes/boost_multi/multi/include/boost/multi/adaptors/fftw/test/shift.cpp index fa3ff6d05b..d73f4f7bb6 100644 --- a/external_codes/boost_multi/multi/include/boost/multi/adaptors/fftw/test/shift.cpp +++ b/external_codes/boost_multi/multi/include/boost/multi/adaptors/fftw/test/shift.cpp @@ -1,20 +1,28 @@ // Copyright 2022-2024 Alfredo A. Correa +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt -#include +#include +#include -#include "../../fftw.hpp" - -#include // NOLINT(build/c++11) +#include // for for_each, rotate +#include // NOLINT(build/c++11) +#include // for complex +#include // for size_t, ptrdiff_t +#include // for char_traits, basic_ostream #include template class n_random_complex { // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions) - std::size_t n_ = 0; + std::size_t n_ = 0; + mutable std::mt19937 gen_{std::random_device{}()}; // NOLINT(whitespace/braces) cpplint 1.6 bug mutable std::uniform_real_distribution<> dist_{-1.0, 1.0}; public: n_random_complex(n_random_complex const&) = delete; + auto operator=(n_random_complex const&) -> n_random_complex& = delete; + explicit n_random_complex(std::size_t n) : n_{n} {} class iterator : public boost::multi::random_access_iterator, std::complex, void> { @@ -30,8 +38,8 @@ class n_random_complex { // NOLINT(cppcoreguidelines-special-member-functions,h return *this; } - friend auto operator==(iterator const& self, iterator const& other) { return self.n_ == other.n_; } - friend auto operator!=(iterator const& self, iterator const& other) { return self.n_ != other.n_; } + auto operator==(iterator const& other) const { return n_ == other.n_; } + auto operator!=(iterator const& other) const { return n_ != other.n_; } auto operator-(iterator const& other) const { return n_ - other.n_; } @@ -47,33 +55,37 @@ class n_random_complex { // NOLINT(cppcoreguidelines-special-member-functions,h namespace multi = boost::multi; namespace fftw = multi::fftw; -using fftw_fixture = fftw::environment; -BOOST_TEST_GLOBAL_FIXTURE(fftw_fixture); - -BOOST_AUTO_TEST_CASE(fftw_shift) { - class watch : std::chrono::steady_clock { - time_point start_ = now(); - - public: // NOLINT(whitespace/indent) cpplint 1.6 bug - auto elapsed_sec() const { return std::chrono::duration(now() - start_).count(); } - }; - - multi::array, 1> const arr = n_random_complex(19586); - BOOST_REQUIRE(arr.size() == 19586); - multi::array, 1> res(arr.extensions()); - BOOST_REQUIRE(res.size() == 19586); - - auto fdft = fftw::plan::forward({true}, arr.base(), arr.layout(), res.base(), res.layout()); - // fftw::plan fdft({true}, arr.layout(), res.layout(), multi::fftw::forward); - - [&, unnamed = watch{}] { - auto const repeat = 40; - std::for_each( - multi::extension_t{0, repeat}.begin(), multi::extension_t{0, repeat}.end(), [&fdft, &arr, &res](auto /*idx*/) { - fdft.execute(arr.base(), res.base()); - std::rotate(res.begin(), res.begin() + res.size() / 2, res.end()); - } - ); - BOOST_TEST_MESSAGE("FFTW shift " << unnamed.elapsed_sec() / repeat << " sec"); // prints 0.000882224 sec - }(); +#include +#define BOOST_AUTO_TEST_CASE(CasenamE) /**/ + +auto main() -> int { // NOLINT(readability-function-cognitive-complexity,bugprone-exception-escape) + fftw::environment const env; + BOOST_AUTO_TEST_CASE(fftw_shift) { + class watch : std::chrono::steady_clock { + time_point start_ = now(); + + public: // NOLINT(whitespace/indent) cpplint 1.6 bug + auto elapsed_sec() const { return std::chrono::duration(now() - start_).count(); } + }; + + multi::array, 1> const arr = n_random_complex(19586); + BOOST_TEST(arr.size() == 19586); + multi::array, 1> res(arr.extensions()); + BOOST_TEST(res.size() == 19586); + + auto fdft = fftw::plan::forward({true}, arr.base(), arr.layout(), res.base(), res.layout()); + // fftw::plan fdft({true}, arr.layout(), res.layout(), multi::fftw::forward); + + [&, unnamed = watch{}] { + auto const repeat = 40; + std::for_each( + multi::extension_t{0, repeat}.begin(), multi::extension_t{0, repeat}.end(), [&fdft, &arr, &res](auto /*idx*/) { + fdft.execute(arr.base(), res.base()); + std::rotate(res.begin(), res.begin() + res.size() / 2, res.end()); + } + ); + std::cout << "FFTW shift " << unnamed.elapsed_sec() / repeat << " sec\n"; // prints 0.000882224 sec + }(); + } + return boost::report_errors(); } diff --git a/external_codes/boost_multi/multi/include/boost/multi/adaptors/fftw/test/so_shift.cpp b/external_codes/boost_multi/multi/include/boost/multi/adaptors/fftw/test/so_shift.cpp index 55babc7663..b2f209f091 100644 --- a/external_codes/boost_multi/multi/include/boost/multi/adaptors/fftw/test/so_shift.cpp +++ b/external_codes/boost_multi/multi/include/boost/multi/adaptors/fftw/test/so_shift.cpp @@ -4,11 +4,10 @@ #include -#include // includes fftw3.hpp +// #include // includes fftw3.hpp -#include // for std::rotate #include -#include +#include #include // for std::iota namespace multi = boost::multi; diff --git a/external_codes/boost_multi/multi/include/boost/multi/adaptors/fftw/test/transpose.cpp b/external_codes/boost_multi/multi/include/boost/multi/adaptors/fftw/test/transpose.cpp index d40d8a15b2..e7702d2cf9 100644 --- a/external_codes/boost_multi/multi/include/boost/multi/adaptors/fftw/test/transpose.cpp +++ b/external_codes/boost_multi/multi/include/boost/multi/adaptors/fftw/test/transpose.cpp @@ -2,14 +2,19 @@ // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt -#include +#include #include +#include -#include // NOLINT(build/c++11) -#include -#include -#include +#include // for generate +#include // for operator-, duration, system... // NOLINT(build/c++11) +#include // for operator==, complex +#include // for invoke // IWYU pragma: keep +#include // for operator<<, basic_os... +#include // for linear_congruential_... +#include // for operator<<, operator""s +#include // for move namespace multi = boost::multi; @@ -29,10 +34,11 @@ class watch // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special- ~watch() { std::cerr << label_ << ": " << elapsed_sec() << " sec" << '\n'; } // NOLINT(cpp:S4963) }; -using fftw_fixture = multi::fftw::environment; -BOOST_TEST_GLOBAL_FIXTURE(fftw_fixture); +#define BOOST_AUTO_TEST_CASE(CasenamE) /**/ + +auto main() -> int { // NOLINT(readability-function-cognitive-complexity,bugprone-exception-escape) + multi::fftw::environment const env; -BOOST_AUTO_TEST_CASE(fftw_transpose) { using namespace std::string_literals; // NOLINT(build/namespaces) for ""s using complex = std::complex; @@ -50,10 +56,12 @@ BOOST_AUTO_TEST_CASE(fftw_transpose) { multi::array out = in; - watch const unnamed{"transposition with aux %ws wall, CPU (%p%)\n"s}; + watch const unnamed{"transposition with aux %ws wall, CPU (%p%)\n"s}; // NOLINT(misc-include-cleaner) bug in clang-tidy 18 - multi::array aux = ~out; + multi::array aux{~out}; out = std::move(aux); - BOOST_REQUIRE( out[35][79] == in[79][35] ); + BOOST_TEST( out[35][79] == in[79][35] ); + + return boost::report_errors(); } diff --git a/external_codes/boost_multi/multi/include/boost/multi/adaptors/fftw/test/transpose_square.cpp b/external_codes/boost_multi/multi/include/boost/multi/adaptors/fftw/test/transpose_square.cpp index cf445534c8..2c59e8638c 100644 --- a/external_codes/boost_multi/multi/include/boost/multi/adaptors/fftw/test/transpose_square.cpp +++ b/external_codes/boost_multi/multi/include/boost/multi/adaptors/fftw/test/transpose_square.cpp @@ -2,21 +2,20 @@ // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt -#include -#include +#include // for initialize_threads, environ... +#include // for array, subarray, layout_t -#include - -#include // NOLINT(build/c++11) -#include -#include -#include +#include // for for_each, generate +#include // for duration, operator-, high_r... // NOLINT(build/c++11) +#include // for operator==, complex +#include // for invoke // IWYU pragma: keep +#include // for basic_ostream, operator<< +#include // for uniform_real_distribution +#include // for char_traits, operator""s +#include // for move, swap namespace multi = boost::multi; -using fftw_fixture = multi::fftw::environment; -BOOST_TEST_GLOBAL_FIXTURE(fftw_fixture); - using complex = std::complex; class watch : private std::chrono::high_resolution_clock { // NOSONAR(cpp:S4963) this class will report timing on destruction @@ -24,7 +23,7 @@ class watch : private std::chrono::high_resolution_clock { // NOSONAR(cpp:S4963 time_point start_ = now(); public: - explicit watch(std::string label) : label_{std::move(label)} {} + explicit watch(std::string label) : label_{ std::move(label) } {} watch(watch const&) = delete; watch(watch&&) = delete; @@ -36,62 +35,67 @@ class watch : private std::chrono::high_resolution_clock { // NOSONAR(cpp:S4963 ~watch() { std::cerr << label_ << ": " << elapsed_sec() << " sec" << '\n'; } }; +#include +#define BOOST_AUTO_TEST_CASE(CasenamE) /**/ + +auto main() -> int { // NOLINT(readability-function-cognitive-complexity,bugprone-exception-escape) +multi::fftw::environment const env; BOOST_AUTO_TEST_CASE(fftw_transpose) { using namespace std::string_literals; // NOLINT(build/namespaces) for ""s multi::fftw::initialize_threads(); { - auto const in = [] { + auto const in = std::invoke([] { // multi::array ret({819, 819}); - multi::array ret({81, 81}); + multi::array ret({ 81, 81 }); std::generate( ret.data_elements(), ret.data_elements() + ret.num_elements(), - [eng = std::default_random_engine{std::random_device{}()}, + [eng = std::default_random_engine{ std::random_device{}() }, uniform_01 = std::uniform_real_distribution<>{}]() mutable { - return complex{uniform_01(eng), uniform_01(eng)}; + return complex{ uniform_01(eng), uniform_01(eng) }; } ); - // std::cout<<"memory size "<< ret.num_elements()*sizeof(complex)/1e6 <<" MB\n"; return ret; - }(); + }); { multi::array out = in; - multi::array aux(extensions(out)); + multi::array aux(out.extensions()); { - watch const unnamed{"auxiliary copy %ws wall, CPU (%p%)\n"s}; + watch const unnamed("auxiliary copy %ws wall, CPU (%p%)\n"s); // NOLINT(misc-include-cleaner) bug in clang-tidy 18 aux = ~out; out = std::move(aux); - BOOST_REQUIRE( out[35][79] == in[79][35] ); + BOOST_TEST( out[35][79] == in[79][35] ); } - BOOST_REQUIRE( out == ~in ); + BOOST_TEST( out == ~in ); } { multi::array out = in; { - watch const unnamed{"transposition with loop %ws wall, CPU (%p%)\n"s}; + watch const unnamed{ "transposition with loop %ws wall, CPU (%p%)\n"s }; std::for_each(extension(out).begin(), extension(out).end(), [&out](auto idx) { auto ext = multi::extension_t(0L, idx); std::for_each(ext.begin(), ext.end(), [&out, idx](auto jdx) { std::swap(out[idx][jdx], out[jdx][idx]); }); }); - BOOST_REQUIRE( out[35][79] == in[79][35] ); + BOOST_TEST( out[35][79] == in[79][35] ); } - BOOST_REQUIRE( out == ~in ); + BOOST_TEST( out == ~in ); } { multi::array out = in; { - watch const unnamed{"transposition with loop 2 %ws wall, CPU (%p%)\n"s}; + watch const unnamed{ "transposition with loop 2 %ws wall, CPU (%p%)\n"s }; std::for_each(extension(out).begin(), extension(out).end(), [&out](auto idx) { auto ext = multi::extension_t(idx + 1, out.size()); std::for_each(ext.begin(), ext.end(), [&out, idx](auto jdx) { std::swap(out[idx][jdx], out[jdx][idx]); }); }); - BOOST_REQUIRE( out[35][79] == in[79][35] ); + BOOST_TEST( out[35][79] == in[79][35] ); } - BOOST_REQUIRE( out == ~in ); + BOOST_TEST( out == ~in ); } } } +return boost::report_errors();} diff --git a/external_codes/boost_multi/multi/include/boost/multi/adaptors/hipfft/test/CMakeLists.txt b/external_codes/boost_multi/multi/include/boost/multi/adaptors/hipfft/test/CMakeLists.txt index 15185d7076..bb082a8398 100644 --- a/external_codes/boost_multi/multi/include/boost/multi/adaptors/hipfft/test/CMakeLists.txt +++ b/external_codes/boost_multi/multi/include/boost/multi/adaptors/hipfft/test/CMakeLists.txt @@ -31,7 +31,7 @@ add_executable(hipfft.cpp.x hipfft.cpp) set_source_files_properties(hipfft.cpp PROPERTIES LANGUAGE HIP) # target_link_libraries(${TEST_EXE} PRIVATE multi) -target_link_libraries(hipfft.cpp.x PRIVATE hip::hipfft Boost::unit_test_framework) +target_link_libraries(hipfft.cpp.x PRIVATE hip::hipfft Boost::unit_test_framework multi) add_test(NAME hipfft.cpp.x COMMAND $) diff --git a/external_codes/boost_multi/multi/include/boost/multi/adaptors/lapack/CMakeLists.txt b/external_codes/boost_multi/multi/include/boost/multi/adaptors/lapack/CMakeLists.txt index ed205cdea1..05895bcaa4 100644 --- a/external_codes/boost_multi/multi/include/boost/multi/adaptors/lapack/CMakeLists.txt +++ b/external_codes/boost_multi/multi/include/boost/multi/adaptors/lapack/CMakeLists.txt @@ -8,8 +8,12 @@ project( add_library(multi-lapack INTERFACE) -find_package(LAPACK REQUIRED) +if(NOT DEFINED ENABLE_CIRCLE) -target_link_libraries(multi-lapack INTERFACE multi LAPACK::LAPACK) + find_package(LAPACK REQUIRED) -add_subdirectory(./test) + target_link_libraries(multi-lapack INTERFACE multi LAPACK::LAPACK) + + add_subdirectory(./test) + +endif() \ No newline at end of file diff --git a/external_codes/boost_multi/multi/include/boost/multi/adaptors/lapack/getrf.hpp b/external_codes/boost_multi/multi/include/boost/multi/adaptors/lapack/getrf.hpp index 96475fdd4f..d1743103d2 100644 --- a/external_codes/boost_multi/multi/include/boost/multi/adaptors/lapack/getrf.hpp +++ b/external_codes/boost_multi/multi/include/boost/multi/adaptors/lapack/getrf.hpp @@ -1,15 +1,12 @@ -#ifdef COMPILATION// -*-indent-tabs-mode:t;c-basic-offset:4;tab-width:4;-*- -$CXXX $CXXFLAGS $0 -o $0x$OXX `pkg-config --libs blas lapack` -lboost_unit_test_framework&&$0x$OXX -x 0&&rm $0x$OXX;exit -#endif -// © Alfredo A. Correa 2020 +// Copyright 2020-2024 Alfredo A. Correa -#ifndef MULTI_ADAPTORS_LAPACK_GEQRF_HPP -#define MULTI_ADAPTORS_LAPACK_GEQRF_HPP +#ifndef BOOST_MULTI_ADAPTORS_LAPACK_GEQRF_HPP +#define BOOST_MULTI_ADAPTORS_LAPACK_GEQRF_HPP -#include "../lapack/core.hpp" -#include "../blas/filling.hpp" +#include +#include -#include "../../config/NODISCARD.hpp" +#include @@ -25,7 +22,7 @@ template auto getrf(Context&& ctxt, A&& a, IPIV&& ipiv){ assert( ipiv.size() == std::min(size(a), size(~a)) ); assert( stride(a) == 1 ); -// assert( stride(ipiv) == 1 ); +// assert( stride(ipiv) == 1 ); multi::index i = std::forward(ctxt).getrf(size(~a), size(a), base(a), stride(~a), ipiv.data() ); if(i == 0) return a(); else return a({0, i - 1}, {0, i - 1}); @@ -36,7 +33,7 @@ void getrs(Context&& ctxt, LU const& lu, IPIV const& ipiv, B&& b){ assert( size(lu) == size(~lu) ); assert( stride(lu) == 1 ); assert( size(ipiv) >= size(lu) ); -// assert( stride(ipiv) == 1 ); +// assert( stride(ipiv) == 1 ); assert( stride(b) == 1 ); std::forward(ctxt).getrs('N', size(lu), size(~b), base(lu), stride(~lu), ipiv.data(), base(b), stride(~b)); } @@ -45,7 +42,7 @@ template void getrs_one(Context&& ctxt, LU const& lu, IPIV const& ipiv, V&& b){ assert( size(lu) == size(~lu) ); assert( stride(lu) == 1 ); -// assert( stride(ipiv) == 1 ); +// assert( stride(ipiv) == 1 ); assert( stride(b) == 1 ); std::forward(ctxt).getrs('N', size(lu), 1, base(lu), stride(~lu), ipiv.data(), base(b), size(lu)); } diff --git a/external_codes/boost_multi/multi/include/boost/multi/adaptors/lapack/potrf.hpp b/external_codes/boost_multi/multi/include/boost/multi/adaptors/lapack/potrf.hpp index 7d26df73d3..afa96b8ebf 100644 --- a/external_codes/boost_multi/multi/include/boost/multi/adaptors/lapack/potrf.hpp +++ b/external_codes/boost_multi/multi/include/boost/multi/adaptors/lapack/potrf.hpp @@ -25,14 +25,14 @@ using ::core::potrf; template BOOST_MULTI_NODISCARD("result has information of order of minor through .size() member") auto potrf(filling uplo, Iterator first, Iterator last) -->decltype(potrf(static_cast(uplo), typename std::iterator_traits::difference_type{}, base(first), stride(first), std::declval()), Iterator{}) +->decltype(potrf(static_cast(uplo), typename std::iterator_traits::difference_type{}, first.base(), stride(first), std::declval()), Iterator{}) { assert( stride(first) == stride(last) ); assert( first->stride() == 1 ); // auto lda = stride(first); int info; // NOLINT(cppcoreguidelines-init-variables) - potrf(static_cast(uplo), std::distance(first, last), base(first), stride(first), info); + potrf(static_cast(uplo), std::distance(first, last), first.base(), stride(first), info); assert( info >= 0 ); // if(info > 0) {std::cerr << "warning minor of order " << info << " is not possitive\n";} @@ -47,9 +47,9 @@ auto potrf(filling uplo, A2D&& A) // NOLINT(readability-identifier-length) conv using lapack::flip; if(stride(A) == 1) { - auto last = potrf(flip(uplo), begin(rotated(A)), end(rotated(A))); + auto last = potrf(flip(uplo), A.rotated().begin(), A.rotated().end()); using std::distance; - return A({0, distance(begin(rotated(A)), last)}, {0, distance(begin(rotated(A)), last)}); + return A({0, distance(A.rotated().begin(), last)}, {0, distance(A.rotated().begin(), last)}); } auto last = potrf(uplo, begin(A), end(A)); diff --git a/external_codes/boost_multi/multi/include/boost/multi/adaptors/lapack/test/CMakeLists.txt b/external_codes/boost_multi/multi/include/boost/multi/adaptors/lapack/test/CMakeLists.txt index 63adb43334..0776005a76 100644 --- a/external_codes/boost_multi/multi/include/boost/multi/adaptors/lapack/test/CMakeLists.txt +++ b/external_codes/boost_multi/multi/include/boost/multi/adaptors/lapack/test/CMakeLists.txt @@ -1,15 +1,19 @@ -cmake_minimum_required(VERSION 3.18) +cmake_minimum_required(VERSION 3.5) -project( - boost-multi-adaptors-lapack-test - VERSION 0.1 - LANGUAGES CXX -) +if(ENABLE_CUDA) + enable_language(CUDA) +endif() -set(CMAKE_CXX_STANDARD_REQUIRED ON) -set(CMAKE_CXX_EXTENSIONS OFF) +# project( +# boost-multi-adaptors-lapack-test +# VERSION 0.1 +# LANGUAGES CXX +# ) + +# set(CMAKE_CXX_STANDARD_REQUIRED ON) +# set(CMAKE_CXX_EXTENSIONS OFF) -find_package(Boost REQUIRED COMPONENTS unit_test_framework) +find_package(Boost REQUIRED) # add_compile_definitions(${TEST_EXE} PRIVATE ${Boost_DEFINITIONS}) # include_directories(SYSTEM ${Boost_INCLUDE_DIRS}) # link_libraries(${Boost_LIBRARIES}) @@ -52,6 +56,7 @@ find_package(Boost REQUIRED COMPONENTS unit_test_framework) # # -Wpointer-sign -Wreorder -Wno-return-type -Wsign-compare -Wsequence-point -Wtrigraphs -Wunused-function -Wunused-but-set-variable -Wunused-variable -Wwrite-strings -Werror -diag-error:3846 > $<$: /W4 > # ) + enable_testing() include(CTest) @@ -62,6 +67,11 @@ include(CTest) # add_test(NAME geqrf.cpp.x COMMAND ./geqrf.cpp.x) add_executable(potrf.cpp.x potrf.cpp) -target_link_libraries(potrf.cpp.x PRIVATE multi-lapack Boost::unit_test_framework) + +if(ENABLE_CUDA) + set_source_files_properties(potrf.cpp PROPERTIES LANGUAGE CUDA) +endif() + +target_link_libraries(potrf.cpp.x PRIVATE multi-lapack Boost::boost) add_test(NAME potrf.cpp.x COMMAND $) diff --git a/external_codes/boost_multi/multi/include/boost/multi/adaptors/lapack/test/potrf.cpp b/external_codes/boost_multi/multi/include/boost/multi/adaptors/lapack/test/potrf.cpp index b78ad81ca4..1897844830 100644 --- a/external_codes/boost_multi/multi/include/boost/multi/adaptors/lapack/test/potrf.cpp +++ b/external_codes/boost_multi/multi/include/boost/multi/adaptors/lapack/test/potrf.cpp @@ -1,15 +1,26 @@ // Copyright 2019-2024 Alfredo A. Correa -#define BOOST_TEST_MODULE "C++ Unit Tests for Multi cuSolver potrf" -#include - -#include "../../blas/gemm.hpp" -#include "../../blas/herk.hpp" - -#include "../../lapack/potrf.hpp" - -#include -#include +#include // for filling, filling... +#include // for potrf + +// IWYU pragma: no_include "boost/multi/adaptors/blas/complex_traits.hpp" // for blas +#include // for gemm +#include // for herk +// IWYU pragma: no_include "boost/multi/adaptors/blas/numeric.hpp" // for underlying +#include // for H, (anonymous) + +#include // for array, subarray + +#include // for for_each, generate // IWYU pragma: keep +#include // for operator*, complex +#include // for abs +#include // for operator<<, ostream +#include // for numeric_limits +#include // for uniform_real_dis... +#include // for allocator, opera... +// IWYU pragma: no_include +// IWYU pragma: no_include // for add_const<>::type +#include // for forward namespace multi = boost::multi; // namespace lapack = multi::lapack; @@ -26,7 +37,7 @@ template auto print(M const& arr, std::string const& msg) -> decltype(a using multi::size; using std::cout; cout << msg << "\n" - << '{'; + << '{'; for(int i = 0; i != size(arr); ++i) { cout << '{'; for(auto j : arr[i].extension()) { // NOLINT(altera-unroll-loops) @@ -42,7 +53,11 @@ template auto print(M const& arr, std::string const& msg) -> decltype(a } return cout << '}' << '\n'; } -template auto print(M const& arr, char const* msg) -> decltype(auto) { return print(arr, std::string{msg}); } // NOLINT(fuchsia-default-arguments-calls) + +template +auto print(M const& arr, char const* msg) -> decltype(auto) { + return print(arr, std::string{msg}); // NOLINT(fuchsia-default-arguments-calls) +} template auto randomize(M&& arr) -> M&& { @@ -58,263 +73,281 @@ auto randomize(M&& arr) -> M&& { return std::forward(arr); } -/* -BOOST_AUTO_TEST_CASE(orthogonalization_over_rows, *boost::unit_test::tolerance(0.00001)){ - auto A = randomize(multi::array({3, 10})); - lapack::onrm(A); - - using blas::herk; - using blas::hermitized; - using blas::filling; - auto id = herk(filling::upper, A); - BOOST_TEST( real(id[1][1]) == 1.0 ); BOOST_TEST( imag(id[1][1]) == 0.0 ); - BOOST_TEST( real(id[1][2]) == 0.0 ); BOOST_TEST( imag(id[1][2]) == 0.0 ); -} -*/ +#include +#define BOOST_AUTO_TEST_CASE(CasenamE) /**/ +#define BOOST_TEST_CLOSE(X, Y, ToL) BOOST_TEST(std::abs((X) - (Y)) < (ToL)) + +auto main() -> int { // NOLINT(readability-function-cognitive-complexity,bugprone-exception-escape) + /* + BOOST_AUTO_TEST_CASE(orthogonalization_over_rows, *boost::unit_test::tolerance(0.00001)){ + auto A = randomize(multi::array({3, 10})); + lapack::onrm(A); + + using blas::herk; + using blas::hermitized; + using blas::filling; + auto id = herk(filling::upper, A); + BOOST_TEST( real(id[1][1]) == 1.0 ); BOOST_TEST( imag(id[1][1]) == 0.0 ); + BOOST_TEST( real(id[1][2]) == 0.0 ); BOOST_TEST( imag(id[1][2]) == 0.0 ); + } + */ -// BOOST_AUTO_TEST_CASE(orthogonalization_over_rows_cuda, *boost::unit_test::tolerance(0.00001)) { -// auto Acpu = randomize(multi::array({3, 10})); + // BOOST_AUTO_TEST_CASE(orthogonalization_over_rows_cuda, *boost::unit_test::tolerance(0.00001)) { + // auto Acpu = randomize(multi::array({3, 10})); -// multi::cuda::array A = Acpu; + // multi::cuda::array A = Acpu; -// using namespace blas; -// using namespace lapack; + // using namespace blas; + // using namespace lapack; -// trsm(filling::lower, hermitized(potrf(filling::upper, herk(filling::upper, A))), A); + // trsm(filling::lower, hermitized(potrf(filling::upper, herk(filling::upper, A))), A); -// Acpu = A; -// auto id = herk(filling::upper, Acpu); -// BOOST_TEST( real(id[1][1]) == 1.0 ); -// BOOST_TEST( imag(id[1][1]) == 0.0 ); -// BOOST_TEST( real(id[1][2]) == 0.0 ); -// BOOST_TEST( imag(id[1][2]) == 0.0 ); -// } + // Acpu = A; + // auto id = herk(filling::upper, Acpu); + // BOOST_TEST( real(id[1][1]) == 1.0 ); + // BOOST_TEST( imag(id[1][1]) == 0.0 ); + // BOOST_TEST( real(id[1][2]) == 0.0 ); + // BOOST_TEST( imag(id[1][2]) == 0.0 ); + // } -/* -BOOST_AUTO_TEST_CASE(orthogonalization_over_columns, *boost::unit_test::tolerance(0.00001)){ + /* + BOOST_AUTO_TEST_CASE(orthogonalization_over_columns, *boost::unit_test::tolerance(0.00001)){ - auto A = randomize( multi::array({10, 3}) ); - using blas::hermitized; - lapack::onrm(hermitized(A)); + auto A = randomize( multi::array({10, 3}) ); + using blas::hermitized; + lapack::onrm(hermitized(A)); - using blas::filling; - auto id = herk(filling::upper, hermitized(A)); - BOOST_TEST( real(id[1][1]) == 1. ); BOOST_TEST( imag(id[1][1]) == 0. ); - BOOST_TEST( real(id[1][2]) == 0. ); BOOST_TEST( imag(id[1][2]) == 0. ); -}*/ + using blas::filling; + auto id = herk(filling::upper, hermitized(A)); + BOOST_TEST( real(id[1][1]) == 1. ); BOOST_TEST( imag(id[1][1]) == 0. ); + BOOST_TEST( real(id[1][2]) == 0. ); BOOST_TEST( imag(id[1][2]) == 0. ); + }*/ -BOOST_AUTO_TEST_CASE(numericalalgorithmsgroup_define_both_sides, *boost::unit_test::tolerance(0.0000001)) { - double const nan = std::numeric_limits::quiet_NaN(); - auto const I = complex{0.0, 1.0}; // NOLINT(readability-identifier-length) + BOOST_AUTO_TEST_CASE(numericalalgorithmsgroup_define_both_sides) { // }, *boost::unit_test::tolerance(0.0000001)) { + auto const I = complex{0.0, 1.0}; // NOLINT(readability-identifier-length) - multi::array const A_gold = { - {3.23 + 0.00 * I, 1.51 - 1.92 * I, 1.90 + 0.84 * I, 0.42 + 2.50 * I}, - {1.51 + 1.92 * I, 3.58 + 0.00 * I, -0.23 + 1.11 * I, -1.18 + 1.37 * I}, - {1.90 - 0.84 * I, -0.23 - 1.11 * I, 4.09 + 0.00 * I, 2.33 - 0.14 * I}, - {0.42 - 2.50 * I, -1.18 - 1.37 * I, 2.33 + 0.14 * I, 4.29 + 0.00 * I}, - }; + multi::array const A_gold = { + {3.23 + 0.00 * I, 1.51 - 1.92 * I, 1.90 + 0.84 * I, 0.42 + 2.50 * I}, + {1.51 + 1.92 * I, 3.58 + 0.00 * I, -0.23 + 1.11 * I, -1.18 + 1.37 * I}, + {1.90 - 0.84 * I, -0.23 - 1.11 * I, 4.09 + 0.00 * I, 2.33 - 0.14 * I}, + {0.42 - 2.50 * I, -1.18 - 1.37 * I, 2.33 + 0.14 * I, 4.29 + 0.00 * I}, + }; - auto A = A_gold; // NOLINT(readability-identifier-length) lapack conventional name + auto A = A_gold; // NOLINT(readability-identifier-length) lapack conventional name - auto const As = multi::lapack::potrf(multi::lapack::filling::upper, A).size(); - BOOST_REQUIRE( As == A.size() ); + auto const As = multi::lapack::potrf(multi::lapack::filling::upper, A).size(); + BOOST_TEST( As == A.size() ); - auto AA = A; + auto AA = A; - for(auto i = 0; i != 4; ++i) { - for(auto j = 0; j != i; ++j) { // NOLINT(altera-unroll-loops) - AA[i][j] = 0.0; + for(auto i = 0; i != 4; ++i) { + for(auto j = 0; j != i; ++j) { // NOLINT(altera-unroll-loops) + AA[i][j] = 0.0; + } } - } - auto const C = +blas::herk(1.0, blas::H(AA)); // +blas::gemm(1.0, blas::H(AA), AA); // NOLINT(readability-identifier-length) conventional lapack name + auto const C = +blas::herk(1.0, blas::H(AA)); // +blas::gemm(1.0, blas::H(AA), AA); // NOLINT(readability-identifier-length) conventional lapack name - for(auto i = 0; i != 4; ++i) { - for(auto j = 0; j != 4; ++j) { - BOOST_TEST( real(A_gold[i][j]) == real(C[i][j]) ); - BOOST_TEST( imag(A_gold[i][j]) == imag(C[i][j]) ); + for(auto i = 0; i != 4; ++i) { + for(auto j = 0; j != 4; ++j) { // NOLINT(altera-unroll-loops) + BOOST_TEST_CLOSE(real(A_gold[i][j]), real(C[i][j]), 0.0000001); + BOOST_TEST_CLOSE(imag(A_gold[i][j]), imag(C[i][j]), 0.0000001); + } } } -} -BOOST_AUTO_TEST_CASE(numericalalgorithmsgroup_define_upper, *boost::unit_test::tolerance(0.0000001)) { - double const nan = std::numeric_limits::quiet_NaN(); - auto const I = complex{0.0, 1.0}; // NOLINT(readability-identifier-length) + BOOST_AUTO_TEST_CASE(numericalalgorithmsgroup_define_upper) { + double const nan = std::numeric_limits::quiet_NaN(); + auto const I = complex{0.0, 1.0}; // NOLINT(readability-identifier-length) - multi::array const A_gold = { - {3.23 + 0.00 * I, 1.51 - 1.92 * I, 1.90 + 0.84 * I, 0.42 + 2.50 * I}, - { nan + nan * I, 3.58 + 0.00 * I, -0.23 + 1.11 * I, -1.18 + 1.37 * I}, - { nan - nan * I, nan - nan * I, 4.09 + 0.00 * I, 2.33 - 0.14 * I}, - { nan - nan * I, nan - nan * I, nan + nan * I, 4.29 + 0.00 * I}, - }; + multi::array const A_gold = { + {3.23 + 0.00 * I, 1.51 - 1.92 * I, 1.90 + 0.84 * I, 0.42 + 2.50 * I}, + { nan + nan * I, 3.58 + 0.00 * I, -0.23 + 1.11 * I, -1.18 + 1.37 * I}, + { nan - nan * I, nan - nan * I, 4.09 + 0.00 * I, 2.33 - 0.14 * I}, + { nan - nan * I, nan - nan * I, nan + nan * I, 4.29 + 0.00 * I}, + }; - auto A = A_gold; // NOLINT(readability-identifier-length) lapack conventional name + auto A = A_gold; // NOLINT(readability-identifier-length) lapack conventional name - auto const As = multi::lapack::potrf(multi::lapack::filling::upper, A).size(); + auto const As = multi::lapack::potrf(multi::lapack::filling::upper, A).size(); - BOOST_REQUIRE( As == A.size() ); + BOOST_TEST( As == A.size() ); - auto AA = A; + auto AA = A; - for(auto i = 0; i != 4; ++i) { - for(auto j = 0; j != i; ++j) { // NOLINT(altera-unroll-loops) - AA[i][j] = 0.0; + for(auto i = 0; i != 4; ++i) { + for(auto j = 0; j != i; ++j) { // NOLINT(altera-unroll-loops) + AA[i][j] = 0.0; + } } - } - auto const C = +blas::herk(1.0, blas::H(AA)); // +blas::gemm(1.0, blas::H(AA), AA); // NOLINT(readability-identifier-length) conventional lapack name + auto const C = +blas::herk(1.0, blas::H(AA)); // +blas::gemm(1.0, blas::H(AA), AA); // NOLINT(readability-identifier-length) conventional lapack name - print(A_gold, "A gold"); // NOLINT(fuchsia-default-arguments-calls) - print(C, "recover"); // NOLINT(fuchsia-default-arguments-calls) + print(A_gold, "A gold"); // NOLINT(fuchsia-default-arguments-calls) + print(C, "recover"); // NOLINT(fuchsia-default-arguments-calls) - for(auto i = 0; i != 4; ++i) { - for(auto j = i; j != 4; ++j) { // NOLINT(altera-id-dependent-backward-branch) // only compare upper part of the reference array (the other half is garbage) - BOOST_TEST( real(A_gold[i][j]) == real(C[i][j]) ); - BOOST_TEST( imag(A_gold[i][j]) == imag(C[i][j]) ); + for(auto i = 0; i != 4; ++i) { + // only compare upper part of the reference array (the other half is garbage) + for(auto j = i; j != 4; ++j) { // NOLINT(altera-unroll-loops,altera-id-dependent-backward-branch) + BOOST_TEST_CLOSE(real(A_gold[i][j]), real(C[i][j]), 0.0000001); + // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-array-to-pointer-decay,readability-simplify-boolean-expr) bug in clang-tidy 14 + BOOST_TEST_CLOSE(imag(A_gold[i][j]), imag(C[i][j]), 0.0000001); + } } } -} -BOOST_AUTO_TEST_CASE(numericalalgorithmsgroup_trivial_imperfect, *boost::unit_test::tolerance(0.0000001)) { // NOLINT(fuchsia-default-arguments-calls) - double const nan = std::numeric_limits::quiet_NaN(); - auto const I = complex{0.0, 1.0}; // NOLINT(readability-identifier-length) + BOOST_AUTO_TEST_CASE(numericalalgorithmsgroup_trivial_imperfect) { + double const nan = std::numeric_limits::quiet_NaN(); + auto const I = complex{0.0, 1.0}; // NOLINT(readability-identifier-length) - multi::array const A_gold = { - {3.23 + 0.00 * I, 1.51 - 1.92 * I, 1.90 + 0.84 * I, 0.42 + 2.50 * I}, - { nan + nan * I, 3.58 + 0.00 * I, -0.23 + 1.11 * I, -1.18 + 1.37 * I}, - { nan - nan * I, nan - nan * I, -10000.00 + 0.00 * I, 0.00 - 0.00 * I}, - { nan - nan * I, nan - nan * I, nan + nan * I, -1000.00 + 0.00 * I}, - }; + multi::array const A_gold = { + {3.23 + 0.00 * I, 1.51 - 1.92 * I, 1.90 + 0.84 * I, 0.42 + 2.50 * I}, + { nan + nan * I, 3.58 + 0.00 * I, -0.23 + 1.11 * I, -1.18 + 1.37 * I}, + { nan - nan * I, nan - nan * I, -10000.00 + 0.00 * I, 0.00 - 0.00 * I}, + { nan - nan * I, nan - nan * I, nan + nan * I, -1000.00 + 0.00 * I}, + }; - auto A = A_gold; // NOLINT(readability-identifier-length) lapack conventional name + auto A = A_gold; // NOLINT(readability-identifier-length) lapack conventional name - auto const& Adec = multi::lapack::potrf(multi::lapack::filling::upper, A); + auto const& Adec = multi::lapack::potrf(multi::lapack::filling::upper, A); - print(A, "A"); - print(Adec, "A dec"); + print(A, "A"); + print(Adec, "A dec"); - auto AA = +Adec; + auto AA = +Adec; - for(auto i = 0; i != AA.size(); ++i) { // NOLINT(altera-id-dependent-backward-branch) - for(auto j = 0; j != i; ++j) { // NOLINT(altera-unroll-loops) - AA[i][j] = 0.0; + // NOLINTNEXTLINE(altera-id-dependent-backward-branch) + for(auto i = 0; i != AA.size(); ++i) { + for(auto j = 0; j != i; ++j) { // NOLINT(altera-unroll-loops) + AA[i][j] = 0.0; + } } - } - auto const C = +blas::herk(1.0, blas::H(AA)); // +blas::gemm(1.0, blas::H(AA), AA); // NOLINT(readability-identifier-length) conventional lapack name + auto const C = +blas::herk(1.0, blas::H(AA)); // +blas::gemm(1.0, blas::H(AA), AA); // NOLINT(readability-identifier-length) conventional lapack name + + print(A_gold, "A gold"); // NOLINT(fuchsia-default-arguments-calls) + print(C, "recover"); // NOLINT(fuchsia-default-arguments-calls) - print(A_gold, "A gold"); // NOLINT(fuchsia-default-arguments-calls) - print(C, "recover"); // NOLINT(fuchsia-default-arguments-calls) + using std::get; - for(auto i = 0; i != AA.size(); ++i) { // NOLINT(altera-id-dependent-backward-branch) - for(auto j = i; j != std::get<1>(C.sizes()); ++j) { // only compare upper part of the reference array (the other half is garbage) // NOLINT(altera-id-dependent-backward-branch) - BOOST_TEST( real(A_gold[i][j]) == real(C[i][j]) ); - BOOST_TEST( imag(A_gold[i][j]) == imag(C[i][j]) ); + for(auto i = 0; i != AA.size(); ++i) { // NOLINT(altera-id-dependent-backward-branch) + for(auto j = i; j != get<1>(C.sizes()); ++j) { // NOLINT(altera-unroll-loops,altera-id-dependent-backward-branch) + BOOST_TEST_CLOSE(real(A_gold[i][j]), real(C[i][j]), 0.0000001); + // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-array-to-pointer-decay,readability-simplify-boolean-exp) bug in clang-tidy 14 + BOOST_TEST_CLOSE(imag(A_gold[i][j]), imag(C[i][j]), 0.0000001); + } } } -} -BOOST_AUTO_TEST_CASE(numericalalgorithmsgroup_nontrivial_imperfect, *boost::unit_test::tolerance(0.0000001)) { // NOLINT(fuchsia-default-arguments-calls) - double const nan = std::numeric_limits::quiet_NaN(); - auto const I = complex{0.0, 1.0}; // NOLINT(readability-identifier-length) + BOOST_AUTO_TEST_CASE(numericalalgorithmsgroup_nontrivial_imperfect) { + double const nan = std::numeric_limits::quiet_NaN(); + auto const I = complex{0.0, 1.0}; // NOLINT(readability-identifier-length) - multi::array const A_gold = { - {1.00 + 0.00 * I, 0.00 - 0.00 * I, 0.00 + 0.00 * I, 0.00 + 0.00 * I}, - { nan + nan * I, 1.00 + 0.00 * I, 0.00 + 0.00 * I, 0.00 + 0.00 * I}, - { nan - nan * I, nan - nan * I, -1.00 + 0.00 * I, 0.00 - 0.00 * I}, - { nan - nan * I, nan - nan * I, nan + nan * I, -1.00 + 0.00 * I}, - }; + multi::array const A_gold = { + {1.00 + 0.00 * I, 0.00 - 0.00 * I, 0.00 + 0.00 * I, 0.00 + 0.00 * I}, + { nan + nan * I, 1.00 + 0.00 * I, 0.00 + 0.00 * I, 0.00 + 0.00 * I}, + { nan - nan * I, nan - nan * I, -1.00 + 0.00 * I, 0.00 - 0.00 * I}, + { nan - nan * I, nan - nan * I, nan + nan * I, -1.00 + 0.00 * I}, + }; - auto A = A_gold; // NOLINT(readability-identifier-length) lapack conventional name + auto A = A_gold; // NOLINT(readability-identifier-length) lapack conventional name - auto const& Adec = multi::lapack::potrf(multi::lapack::filling::upper, A); + auto const& Adec = multi::lapack::potrf(multi::lapack::filling::upper, A); - print(A, "A"); - print(Adec, "A dec"); + print(A, "A"); + print(Adec, "A dec"); - auto AA = +Adec; + auto AA = +Adec; // NOLINT(altera-id-dependent-backward-branch) bug in clang-tidy 14 - for(auto i = 0; i != AA.size(); ++i) { // NOLINT(altera-id-dependent-backward-branch) - for(auto j = 0; j != i; ++j) { // NOLINT(altera-unroll-loops) - AA[i][j] = 0.0; + // NOLINTNEXTLINE(altera-id-dependent-backward-branch) + for(auto i = 0; i != AA.size(); ++i) { + for(auto j = 0; j != i; ++j) { // NOLINT(altera-unroll-loops) + AA[i][j] = 0.0; + } } - } - auto const C = +blas::herk(1.0, blas::H(AA)); // +blas::gemm(1.0, blas::H(AA), AA); // NOLINT(readability-identifier-length) conventional lapack name + auto const C = +blas::herk(1.0, blas::H(AA)); // +blas::gemm(1.0, blas::H(AA), AA); // NOLINT(readability-identifier-length) conventional lapack name + + print(A_gold, "A gold"); // NOLINT(fuchsia-default-arguments-calls) + print(C, "recover"); // NOLINT(fuchsia-default-arguments-calls) - print(A_gold, "A gold"); // NOLINT(fuchsia-default-arguments-calls) - print(C, "recover"); // NOLINT(fuchsia-default-arguments-calls) + using std::get; // workaround use of function template name with no prior declaration in function call with explicit template arguments is a C++20 extension [-Wc++20-extensions] - for(auto i = 0; i != AA.size(); ++i) { // NOLINT(altera-id-dependent-backward-branch) - for(auto j = i; j != std::get<1>(C.sizes()); ++j) { // only compare upper part of the reference array (the other half is garbage) // NOLINT(altera-id-dependent-backward-branch) - BOOST_TEST( real(A_gold[i][j]) == real(C[i][j]) ); - BOOST_TEST( imag(A_gold[i][j]) == imag(C[i][j]) ); + // NOLINTNEXTLINE(altera-id-dependent-backward-branch) + for(auto i = 0; i != AA.size(); ++i) { + // NOLINTNEXTLINE(altera-unroll-loops,altera-id-dependent-backward-branch) + for(auto j = i; j != get<1>(C.sizes()); ++j) { // only compare upper part of the reference array (the other half is garbage) + BOOST_TEST_CLOSE(real(A_gold[i][j]), real(C[i][j]), 0.0000001); + BOOST_TEST_CLOSE(imag(A_gold[i][j]), imag(C[i][j]), 0.0000001); + } } } -} -BOOST_AUTO_TEST_CASE(lapack_potrf, *boost::unit_test::tolerance(0.00001)) { - double const nan = std::numeric_limits::quiet_NaN(); - auto const I = complex{0.0, 1.0}; // NOLINT(readability-identifier-length) + BOOST_AUTO_TEST_CASE(lapack_potrf) { // , *boost::unit_test::tolerance(0.00001)) { + double const nan = std::numeric_limits::quiet_NaN(); + auto const I = complex{0.0, 1.0}; // NOLINT(readability-identifier-length) - { - // NOLINTNEXTLINE(readability-identifier-length) - multi::array A = { - {167.413 + 0.0 * I, 126.804 - 0.00143505 * I, 125.114 - 0.1485590 * I}, - { nan + nan * I, 167.381 + 0.0 * I, 126.746 + 0.0327519 * I}, - { nan + nan * I, nan + nan * I, 167.231 + 0.0 * I}, - }; + { + // NOLINTNEXTLINE(readability-identifier-length) + multi::array A = { + {167.413 + 0.0 * I, 126.804 - 0.00143505 * I, 125.114 - 0.1485590 * I}, + { nan + nan * I, 167.381 + 0.0 * I, 126.746 + 0.0327519 * I}, + { nan + nan * I, nan + nan * I, 167.231 + 0.0 * I}, + }; - print(A, "original A"); - using boost::multi::lapack::filling; - using boost::multi::lapack::potrf; + print(A, "original A"); + using boost::multi::lapack::filling; + using boost::multi::lapack::potrf; - auto const As = potrf(filling::upper, A).size(); // A is hermitic in upper triangular (implicit below) - BOOST_REQUIRE( As == A.size() ); + auto const As = potrf(filling::upper, A).size(); // A is hermitic in upper triangular (implicit below) + BOOST_TEST( As == A.size() ); - BOOST_TEST( real(A[1][2]) == 3.78646 ); - BOOST_TEST( imag(A[1][2]) == 0.0170734 ); - // BOOST_TEST( A[2][1] != A[2][1] ); - print(A, "decomposition"); + BOOST_TEST_CLOSE(real(A[1][2]), 3.78646, 0.00001); + BOOST_TEST_CLOSE(imag(A[1][2]), 0.0170734, 0.00001); + // BOOST_TEST( A[2][1] != A[2][1] ); + print(A, "decomposition"); - multi::array C(A.extensions(), complex{0.0, 0.0}); // NOLINT(readability-identifier-length) conventional lapack name + multi::array C(A.extensions(), complex{0.0, 0.0}); // NOLINT(readability-identifier-length) conventional lapack name - multi::array AA = A; + multi::array AA = A; - auto const [is, js] = AA.extensions(); - for(auto i : is) { - for(auto j = 0; j != i; ++j) { // NOLINT(altera-unroll-loops,altera-id-dependent-backward-branch) - AA[i][j] = std::conj(A[j][i]); + auto const [is, js] = AA.extensions(); + for(auto i : is) { + for(auto j = 0; j != i; ++j) { // NOLINT(altera-unroll-loops,altera-id-dependent-backward-branch) + AA[i][j] = std::conj(A[j][i]); + } } - } - blas::gemm(complex{1.0, 0.0}, blas::H(AA), AA, complex{0.0, 0.0}, C); + blas::gemm(complex{1.0, 0.0}, blas::H(AA), AA, complex{0.0, 0.0}, C); - print(C, "recovery"); + print(C, "recovery"); + } + // { + // multi::cuda::managed::array A = { + // {167.413, 126.804 - 0.00143505 * I, 125.114 - 0.1485590 * I}, + // { NAN, 167.381, 126.746 + 0.0327519 * I}, + // { NAN, NAN, 167.231}, + // }; + // using lapack::filling; + // using lapack::potrf; + // potrf(filling::upper, A); // A is hermitic in upper triangular (implicit below) + // BOOST_TEST( real(A[1][2]) == 3.78646 ); + // BOOST_TEST( imag(A[1][2]) == 0.0170734 ); + // // BOOST_TEST( A[2][1] != A[2][1] ); + // } + // { + // multi::cuda::array A = { + // {167.413, 126.804 - 0.00143505 * I, 125.114 - 0.1485590 * I}, + // { NAN, 167.381, 126.746 + 0.0327519 * I}, + // { NAN, NAN, 167.231}, + // }; + // using lapack::filling; + // using lapack::potrf; + // potrf(filling::upper, A); // A is hermitic in upper triangular (implicit below) + // multi::array A_copy = A; + // print(A_copy); + // } } - // { - // multi::cuda::managed::array A = { - // {167.413, 126.804 - 0.00143505 * I, 125.114 - 0.1485590 * I}, - // { NAN, 167.381, 126.746 + 0.0327519 * I}, - // { NAN, NAN, 167.231}, - // }; - // using lapack::filling; - // using lapack::potrf; - // potrf(filling::upper, A); // A is hermitic in upper triangular (implicit below) - // BOOST_TEST( real(A[1][2]) == 3.78646 ); - // BOOST_TEST( imag(A[1][2]) == 0.0170734 ); - // // BOOST_TEST( A[2][1] != A[2][1] ); - // } - // { - // multi::cuda::array A = { - // {167.413, 126.804 - 0.00143505 * I, 125.114 - 0.1485590 * I}, - // { NAN, 167.381, 126.746 + 0.0327519 * I}, - // { NAN, NAN, 167.231}, - // }; - // using lapack::filling; - // using lapack::potrf; - // potrf(filling::upper, A); // A is hermitic in upper triangular (implicit below) - // multi::array A_copy = A; - // print(A_copy); - // } + + return boost::report_errors(); } diff --git a/external_codes/boost_multi/multi/include/boost/multi/adaptors/mpi.hpp b/external_codes/boost_multi/multi/include/boost/multi/adaptors/mpi.hpp new file mode 100644 index 0000000000..d990fd9177 --- /dev/null +++ b/external_codes/boost_multi/multi/include/boost/multi/adaptors/mpi.hpp @@ -0,0 +1,258 @@ +// Copyright 2024 Alfredo A. Correa +// Distributed under the Boost Software License, Version 10. +// https://www.boost.org/LICENSE_1_0.txt + +#ifndef BOOST_MULTI_ADAPTORS_MPI_HPP_ +#define BOOST_MULTI_ADAPTORS_MPI_HPP_ +#pragma once + +#include + +#define OMPI_SKIP_MPICXX 1 +#include + +#include // for assert +#include // for numeric_limits NOLINT(misc-include-cleaner) +#include // for exchange, move + +namespace boost::multi::mpi { + +using const_MPI_Datatype = MPI_Datatype const; + +template static const_MPI_Datatype datatype = std::conditional_t(sizeof(T*)), void, int>{}; + +// template<> MPI_Datatype const datatype = MPI_CHAR; +// template<> MPI_Datatype const datatype = MPI_UNSIGNED_CHAR; + +// #if(__cplusplus >= 201703L) +// MPI3_DECLARE_DATATYPE(byte , MPI_BYTE); +// #endif +// MPI3_DECLARE_DATATYPE(wchar , MPI_WCHAR); + +// MPI3_DECLARE_DATATYPE(short , MPI_SHORT); +// MPI3_DECLARE_DATATYPE(unsigned short , MPI_UNSIGNED_SHORT); + +template<> const_MPI_Datatype datatype = MPI_INT; // NOLINT(misc-misplaced-const,misc-definitions-in-headers) + +// MPI3_DECLARE_DATATYPE(unsigned int , MPI_UNSIGNED); +// MPI3_DECLARE_DATATYPE(long , MPI_LONG); +// MPI3_DECLARE_DATATYPE(unsigned long , MPI_UNSIGNED_LONG); +// MPI3_DECLARE_DATATYPE(float , MPI_FLOAT); + +template<> const_MPI_Datatype datatype = MPI_FLOAT; // NOLINT(misc-definitions-in-headers) +template<> const_MPI_Datatype datatype = MPI_DOUBLE; // NOLINT(misc-definitions-in-headers) + +// MPI3_DECLARE_DATATYPE(long double , MPI_LONG_DOUBLE); +// MPI3_DECLARE_DATATYPE(long long int , MPI_LONG_LONG_INT); + +// MPI3_DECLARE_DATATYPE(bool , MPI_C_BOOL); // C++ binding not used MPI_CXX_BOOL); + +class data { + void* buf_; + MPI_Datatype datatype_; + + public: + template + explicit data(It first) // NOLINT(cppcoreguidelines-pro-type-member-init,hicpp-member-init) + : buf_{const_cast(static_cast(first.base()))} // NOLINT(cppcoreguidelines-pro-type-const-cast) + { + MPI_Type_vector( + 1, 1, + first.stride(), + mpi::datatype, + &datatype_ + ); + + MPI_Type_commit(&datatype_); // type cannot be used until committed, in communication operations at least + } + + data(data const&) = delete; + data(data&&) = delete; + + auto operator=(data const&) = delete; + auto operator=(data&&) = delete; + + ~data() { MPI_Type_free(&datatype_); } + + auto buffer() const { return buf_; } + auto datatype() const { return datatype_; } +}; + +template +auto create_subarray_aux( + Layout lyt, + int subcount, + MPI_Datatype old_datatype, + MPI_Datatype* new_datatype +) -> int { + MPI_Datatype sub_type; // NOLINT(cppcoreguidelines-init-variables) + + if constexpr(Layout::dimensionality == 1) { + MPI_Type_dup(old_datatype, &sub_type); + } else { + create_subarray_aux(lyt.sub(), lyt.sub().size(), old_datatype, &sub_type); + } + + int dt_size; // NOLINT(cppcoreguidelines-init-variables) + MPI_Type_size(old_datatype, &dt_size); + + assert(lyt.stride() * dt_size <= std::numeric_limits::max()); + { + MPI_Datatype vector_datatype; // NOLINT(cppcoreguidelines-init-variables) + MPI_Type_create_hvector( + subcount, 1, + lyt.stride() * dt_size, + sub_type, &vector_datatype + ); + + MPI_Type_create_resized(vector_datatype, 0, lyt.stride() * dt_size, new_datatype); + MPI_Type_free(&vector_datatype); + } + MPI_Type_free(&sub_type); + return MPI_SUCCESS; +} + +template +class skeleton { + Size count_; + MPI_Datatype datatype_; + + skeleton() : datatype_{MPI_DATATYPE_NULL} {} + + auto operator=(skeleton&& other) & noexcept -> skeleton& { + count_ = other.count_; + datatype_ = std::exchange(other.datatype_, MPI_DATATYPE_NULL); + return *this; + } + + template + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init,hicpp-member-init,fuchsia-default-arguments-declarations) + skeleton(Layout const& lyt, MPI_Datatype dt, Size subcount) : count_{static_cast(lyt.size())} { + assert(lyt.size() <= std::numeric_limits::max()); + + MPI_Datatype sub_type; // NOLINT(cppcoreguidelines-init-variables) + [[maybe_unused]] skeleton sk; // NOLINT(misc-const-correctness) + if constexpr(Layout::dimensionality == 1) { + sub_type = dt; + } else { + sk = skeleton(lyt.sub(), dt, lyt.sub().size()); + sub_type = sk.datatype(); + } + + int dt_size; // NOLINT(cppcoreguidelines-init-variables) + MPI_Type_size(dt, &dt_size); + + { + MPI_Datatype vector_datatype; // NOLINT(cppcoreguidelines-init-variables) + MPI_Type_create_hvector( + subcount, 1, + lyt.stride() * dt_size, + sub_type, &vector_datatype + ); + + MPI_Type_create_resized(vector_datatype, 0, lyt.stride() * dt_size, &datatype_); + MPI_Type_free(&vector_datatype); + } + } + + public: + skeleton(skeleton&& other) noexcept + : count_{other.count_}, datatype_{std::exchange(other.datatype_, MPI_DATATYPE_NULL)} {} + + template + skeleton(Layout const& lyt, MPI_Datatype dt) + : skeleton{lyt, dt, 1} { + MPI_Type_commit(&datatype_); + } + + template + explicit skeleton(Layout const& lyt) : skeleton{lyt, mpi::datatype} {} + + skeleton(skeleton const&) = delete; + + auto operator=(skeleton const&) = delete; + + ~skeleton() { + if(datatype_ != MPI_DATATYPE_NULL) { + MPI_Type_free(&datatype_); + } + } + + auto count() const { return count_; } + auto datatype() const& { return datatype_; } + auto datatype() && { return std::exchange(datatype_, MPI_DATATYPE_NULL); } +}; + +template +auto create_subarray(Layout const& lyt, MPI_Datatype old_datatype, MPI_Datatype* new_datatype) -> int { + int old_datatype_size; // NOLINT(cppcoreguidelines-init-variables) + MPI_Type_size(old_datatype, &old_datatype_size); + + // return create_subarray_aux(lyt, 1, old_datatype, new_datatype); + skeleton const sk(lyt, old_datatype); + // new_datatype = std::move(sk).type(); + { + MPI_Datatype vector_datatype; // NOLINT(cppcoreguidelines-init-variables) + MPI_Type_create_hvector( + lyt.size(), 1, + lyt.stride() * old_datatype_size, + sk.datatype(), &vector_datatype + ); + + MPI_Type_create_resized(vector_datatype, 0, lyt.stride() * old_datatype_size, new_datatype); + MPI_Type_free(&vector_datatype); + } + return MPI_SUCCESS; +} + +template +class message : skeleton { + void* buf_; + + using skeleton_type = skeleton; + + public: + message(void* buf, skeleton_type&& sk) : skeleton_type{std::move(sk)}, buf_{buf} {} + + template + message(void* buf, Layout const& lyt, MPI_Datatype dt) : skeleton_type(lyt, dt), buf_{buf} {} + + // template + // message(TT* buf, Layout const& lyt) : message(buf, lyt, mpi::datatype) {} + + template + explicit message(ArrayElements const& arrelems) + : message{ + const_cast(static_cast(arrelems.base())), // NOLINT(cppcoreguidelines-pro-type-const-cast) + arrelems.layout(), + mpi::datatype + } {} + + message(message const& other) = delete; + message(message&&) = delete; + + auto operator=(message const&) = delete; + auto operator=(message&&) = delete; + + ~message() = default; + + auto buffer() const { return buf_; } + using skeleton_type::count; + // auto count() const { return this->count_; } + using skeleton_type::datatype; + // auto datatype() const { return this->datatype_; } + + // template + // std::tuple_element_t> const& get() const& { + // if constexpr(Index == 0) + // return buf_; + // if constexpr(Index == 1) + // return this->count_; + // if constexpr(Index == 2) + // return this->datatype_; + // } +}; + +} // namespace boost::multi::mpi + +#endif \ No newline at end of file diff --git a/external_codes/boost_multi/multi/include/boost/multi/adaptors/mpi/CMakeLists.txt b/external_codes/boost_multi/multi/include/boost/multi/adaptors/mpi/CMakeLists.txt new file mode 100644 index 0000000000..41a705feda --- /dev/null +++ b/external_codes/boost_multi/multi/include/boost/multi/adaptors/mpi/CMakeLists.txt @@ -0,0 +1,6 @@ +cmake_minimum_required(VERSION 3.5) +# project(boost-multi-mpi VERSION 0.1) + +find_package(MPI REQUIRED) + +add_subdirectory(../mpi/test) diff --git a/external_codes/boost_multi/multi/include/boost/multi/adaptors/mpi/README.md b/external_codes/boost_multi/multi/include/boost/multi/adaptors/mpi/README.md new file mode 100644 index 0000000000..cee3623818 --- /dev/null +++ b/external_codes/boost_multi/multi/include/boost/multi/adaptors/mpi/README.md @@ -0,0 +1,250 @@ + +# Multi MPI Adaptor + +_© Alfredo A. Correa, 2024_ + +(documentation in progress) + +MPI libraries are a standard for parallel computing in C and C++. +The Multi MPI Adaptor provides ways to interface arrays with MPI library implementations. +This feature helps use arrays in MPI-based programs by streamlining the communication of array contents between different MPI processes. + +The functions in the adaptor do not access the array data, which ensures that it is compatible with GPU-aware implementations of MPI. + +## Contents +[[_TOC_]] + +## Interfaces + +The message-passing interface of MPI generally works with messages to communicate data. +An MPI message is described in 3 parts: a buffer, a count, and a datatype. + +For example, the function to send data from one process to another (destination) via a communicator is: + +```cpp +int MPI_Send(const void* buffer, int count, MPI_Datatype datatype, int destination, int tag, MPI_Comm communicator); +``` + +MPI library implementations provide dozens of functions like this to send, receive, and process data between MPI processes. +This adaptor doesn't try to replace these functions; +instead, it works by providing a function that generates messages, explicitly calculating the datatypes to describe the arrays. + +The MPI user-defined datatypes are generated from the Multi arrays, including their type information and layout information (strides). + +The basic usage consists of creating a `multi::mpi::message` object from the array elements. +A message is created by passing a reference to the elements of an array, `multi::mpi::message(my_array.elements())`. +(Elements are not copied in the process.) + +The message can then be later decomposed into a buffer, a count, and a datatype for use in the MPI functions. + +In this example, which runs in 2 processes, creates an array that is communicated from process 0 to process 1: + +```cpp +// compile with `mpic++ -std=c++17 example.cpp -o example.x` +// run with `mpirun -n 2 example.x` +#include + +int main() { + int rank; + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + + auto const A = multi::array({ + {1, 2, 3}, + {4, 5, 6} + }); + + if(world_rank == 0) { + auto const& A_msg = multi::mpi::message(A.elements()); + MPI_Send(A_msg.buffer(), A_msg.count(), A_msg.datatype(), 1, 0, MPI_COMM_WORLD); + } else if(world_rank == 1) { + multi::array B({2, 3}); + + auto&& B_msg = multi::mpi::message(B.elements()); + MPI_Recv(B_msg.buffer(), B_msg.count(), B_msg.datatype(), 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE); + + assert(B == A); + } +} +``` + +The examples in this documentation are two-dimensional for simplicity and illustration purposes. +The usage is general to an arbitrary number of dimensions. + +## Advanced usage + +### Subarrays + +A subarray can also be communicated, for example, a small 2x2 block of the original array. +Replacing `message(AA.elements())` with `message(A({0, 2}, {0, 2}).elements())` and `message(B.elements())` with `message(B({0, 2}, {0, 2}).elements())` will result in a communication of a subset of elements. + +```cpp + ... + if(world_rank == 0) { + auto const& msg = multi::mpi::message(A({0, 2}, {0, 2}).elements()); + MPI_Send(msg.buffer(), msg.count(), msg.datatype(), 1, 0, MPI_COMM_WORLD); + } else if(world_rank == 1) { + multi::array B({2, 3}); + + auto&& msg = multi::mpi::message(B({0, 2}, {0, 2}).elements()); + MPI_Recv(msg.buffer(), msg.count(), msg.datatype(), 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE); + + assert(B({0, 2}, {0, 2}) == A({0, 2}, {0, 2})); // only the 2x2 block is communicated + } +``` + +### Rearrangement of elements + +It is essential to understand that, due to the way MPI works, the array's value is not what is communicated but only its fundamental elements (in a canonical order). +We emphasize this detail by passing the `.elements()` range for message construction, not the array per se. + +A consequence of this is that the user has to ensure consistency in the shape of the receiving end, as in the previous example. +Communicating a 2x3 array and receiving a 2x2 array will be an error because they have different numbers of elements. + +Similarly, a 2x3 array can be communicated into a 3x2 array, although the elements will be rearranged, which is typically not desired. + +Still, a reasonable use of rearrangement of elements could involve transposition of the array during communication. +The key to rearranging the elements is that the layouts can be different in different processes. + +```cpp +int main() { + int rank; + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + + auto const A = multi::array({ + {1, 2, 3}, + {4, 5, 6} + }); + + if(world_rank == 0) { + auto const& A_msg = multi::mpi::message(A.elements()); + MPI_Send(A_msg.buffer(), A_msg.count(), A_msg.datatype(), 1, 0, MPI_COMM_WORLD); + } else if(world_rank == 1) { + multi::array B({3, 2}); + + auto&& BT_msg = multi::mpi::message(B.tranposed().elements()); + MPI_Recv(BT_msg.buffer(), BT_msg.count(), BT_msg.datatype(), 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE); + + assert(B == multi::array{ + {1, 4}, + {2, 5}, + {3, 6} + }); + } +} +``` + +In this example, the layouts of `A` and the transpose of `B` are different since the elements are arranged differently in memory. +However, they will be equal because the logical element arrangement is the same. +The result is that `B` is the transposed version of `A`. + +### Reduction and other operations + +Since the message represents a set of elements, reductions and other MPI computations can be used directly element-wise. + +```cpp +int main() { + int rank; + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + + auto const A = multi::array({ + {1, 2, 3}, + {4, 5, 6} + }); + + auto const& A_msg = multi::mpi::message(A.elements()); + MPI_Reduce(MPI_SUM, A_msg.buffer(), A_msg.count(), A_msg.datatype(), MPI_COMM_WORLD); +} +``` + +### Iteration and skeletons + +If subelements of an array need to be communicated repeatedly, it is wasteful to produce a new message for each type. +The key is that all subarrays of a larger array have the same layout. + +Suppose we want to communicate the rows of an array in random order. + +```cpp +int main() { + int rank; + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + + multi::array A({ + {1, 2, 3, 4}, + {5, 6, 7, 8}, + {9, 10, 11, 12} + }); + + if(rank == 0) { + std::vector perm(A.size()); std::iota(perm.begin(), perm.end(), 0); + for(auto&& row_index: perm) { + auto const& msg = multi::mpi::message(A[row_index].elements()); + MPI_Send(msg.buffer(), msg.count(), msg.datatype(), 1, 0, MPI_COMM_WORLD); + } + } else if(rank == 1) { + multi::array B({3, 4}); + for(auto&& row: B) { + auto&& msg = multi::mpi::message(row.elements()); + MPI_Recv(msg.buffer(), msg.count(), msg.datatype(), 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE); + } +} +``` + +The MPI datatype computation is unfortunately repeated for each message inside both loops. +The alternative is to use MPI skeletons, which only contain datatype information. +The loops can be replaced with this code: + +```cpp + ... + auto sk = multi::mpi::skeleton(A.front().layout()); + for(auto&& row_index: perm) { + MPI_Send(A[row_index].base(), sk.count(), sk.datatype(), 1, 0, MPI_COMM_WORLD); + } + ... +``` + +## GPU-aware MPI + +Messages and skeletons can be generated for arrays on the GPU. +If the MPI implementation is GPU-aware (e.g., Spectrum MPI), it can communicate the GPU array elements with the same interface. + +In the examples above, the arrays can be replaced with `multi::array >`, and the communication will automatically use GPU hardware. + +## Serialization + +The advantage of using datatypes and messages is that data doesn't need to be copied explicitly into a local buffer. +However, in certain cases it is possible that communication using datatypes is slower than compacting the array data into a contiguous buffer. + +A completely alternative to the use of message and datatypes is to use serialization. + +```cpp +#include + +int main() { + int rank; + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + + auto const A = multi::array({ + {1, 2, 3}, + {4, 5, 6} + }); + + if(world_rank == 0) { + std::ostringstream oss; + boost::archive:::binary_oarchive oa(oss); + oa << A(); + + MPI_Send(A_msg.str().data(), A_msg.str().data(), MPI_CHAR, 1, 0, MPI_COMM_WORLD); + } else if(world_rank == 1) { + multi::array B({2, 3}); + std::istringstream iss; + + MPI_Recv(B_msg.buffer(), B_msg.count(), B_msg.datatype(), 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE); + + assert(B == A); + } +} +``` + + diff --git a/external_codes/boost_multi/multi/include/boost/multi/adaptors/mpi/test/CMakeLists.txt b/external_codes/boost_multi/multi/include/boost/multi/adaptors/mpi/test/CMakeLists.txt new file mode 100644 index 0000000000..52dbfb1fb3 --- /dev/null +++ b/external_codes/boost_multi/multi/include/boost/multi/adaptors/mpi/test/CMakeLists.txt @@ -0,0 +1,29 @@ +cmake_minimum_required(VERSION 3.15) + +if(ENABLE_CUDA) + enable_language(CUDA) +endif() + +enable_testing() +include(CTest) + +find_package(Boost REQUIRED COMPONENTS) + +add_executable(mpi.cpp.x mpi.cpp) + +if(ENABLE_CUDA) + set_source_files_properties(${TEST_FILE} PROPERTIES LANGUAGE CUDA) +endif() + +if(APPLE) + # https://apple.stackexchange.com/a/121010 + # add_custom_command (TARGET mpi.cpp.x POST_BUILD COMMAND codesign --force --deep -s ACTMPI ${CMAKE_CURRENT_BINARY_DIR}/mpi.cpp.x) +endif() + +target_link_libraries(mpi.cpp.x PRIVATE multi MPI::MPI_CXX Boost::boost) + +if(APPLE) + add_test(NAME mpi.cpp.x COMMAND ${MPIEXEC_EXECUTABLE} --mca btl ^tcp ${MPIEXEC_NUMPROC_FLAG} 2 ${MPIEXEC_PREFLAGS} $ ${MPIEXEC_POSTFLAGS}) +else() + add_test(NAME mpi.cpp.x COMMAND ${MPIEXEC_EXECUTABLE} ${MPIEXEC_NUMPROC_FLAG} 2 ${MPIEXEC_PREFLAGS} $ ${MPIEXEC_POSTFLAGS}) +endif() \ No newline at end of file diff --git a/external_codes/boost_multi/multi/include/boost/multi/adaptors/mpi/test/mpi.cpp b/external_codes/boost_multi/multi/include/boost/multi/adaptors/mpi/test/mpi.cpp new file mode 100644 index 0000000000..a27dd6e5d0 --- /dev/null +++ b/external_codes/boost_multi/multi/include/boost/multi/adaptors/mpi/test/mpi.cpp @@ -0,0 +1,325 @@ +// Copyright 2024 Alfredo A. Correa +// Distributed under the Boost Software License, Version 10. +// https://www.boost.org/LICENSE_1_0.txt + +#include + +#include + +#define OMPI_SKIP_MPICXX 1 +#include + +#include + +#include // for std::cout +#include + +namespace multi = boost::multi; + +namespace { +void test_single_number(MPI_Comm comm) { + int world_rank; // NOLINT(cppcoreguidelines-init-variables) + MPI_Comm_rank(comm, &world_rank); + int world_size; // NOLINT(cppcoreguidelines-init-variables) + MPI_Comm_size(comm, &world_size); + + BOOST_TEST(world_size > 1); + + int number = 0; + if(world_rank == 0) { + number = -1; + MPI_Send(&number, 1, MPI_INT, 1, 0, comm); + } else if(world_rank == 1) { + MPI_Recv(&number, 1, MPI_INT, 0, 0, comm, MPI_STATUS_IGNORE); + BOOST_TEST(number == -1); + } + { + std::vector vv(3, 99); // NOLINT(fuchsia-default-arguments-calls) + if(world_rank == 0) { + vv = {1, 2, 3}; + MPI_Send(vv.data(), static_cast(vv.size()), MPI_INT, 1, 0, comm); + } else if(world_rank == 1) { + MPI_Recv(vv.data(), static_cast(vv.size()), MPI_INT, 0, 0, comm, MPI_STATUS_IGNORE); + BOOST_TEST( vv == std::vector({1, 2, 3}) ); // NOLINT(fuchsia-default-arguments-calls) + } + } +} + +void test_1d(MPI_Comm comm) { + int world_rank; // NOLINT(cppcoreguidelines-init-variables) + MPI_Comm_rank(comm, &world_rank); + int world_size; // NOLINT(cppcoreguidelines-init-variables) + MPI_Comm_size(comm, &world_size); + { + if(world_rank == 0) { + multi::array const AA = multi::array({1, 2, 3, 4, 5, 6}); + auto const&& BB = AA.strided(2); + BOOST_TEST(( BB == multi::array({1, 3, 5}) )); + + auto const B_data = multi::mpi::data(BB.begin()); + + MPI_Send(B_data.buffer(), static_cast(BB.size()), B_data.datatype(), 1, 0, comm); + } else if(world_rank == 1) { + multi::array CC(3, 99); // NOLINT(misc-const-correctness) + + auto const& C_msg = multi::mpi::message(CC.elements()); + + MPI_Recv(C_msg.buffer(), C_msg.count(), C_msg.datatype(), 0, 0, comm, MPI_STATUS_IGNORE); + BOOST_TEST(( CC == multi::array({1, 2, 3}) )); + } + } + std::cout << world_rank << '\n'; + { + if(world_rank == 0) { + auto const AA = multi::array({1, 2, 3, 4, 5, 6}); + auto const& BB = AA.strided(2); + BOOST_TEST(( BB == multi::array({1, 3, 5}) )); + + auto const B_data = multi::mpi::data(BB.begin()); + + MPI_Send(B_data.buffer(), static_cast(BB.size()), B_data.datatype(), 1, 0, comm); + } else if(world_rank == 1) { + multi::array CC(3, 99); // NOLINT(misc-const-correctness) + + auto const C_msg = multi::mpi::message(CC); + + MPI_Recv(C_msg.buffer(), C_msg.count(), C_msg.datatype(), 0, 0, comm, MPI_STATUS_IGNORE); + BOOST_TEST(( CC == multi::array({1, 2, 3}) )); + } + } + std::cout << world_rank << '\n'; + { + if(world_rank == 0) { + auto const AA = multi::array({1, 2, 3, 4, 5, 6}); + auto const& BB = AA.strided(2); + BOOST_TEST(( BB == multi::array({1, 3, 5}) )); + + MPI_Datatype B_type; // NOLINT(cppcoreguidelines-init-variables) + multi::mpi::create_subarray(BB.layout(), MPI_INT, &B_type); + MPI_Type_commit(&B_type); + MPI_Send(BB.base(), 1, B_type, 1, 0, comm); + MPI_Type_free(&B_type); + + } else if(world_rank == 1) { + multi::array CC(3, 99); // NOLINT(misc-const-correctness) + + auto const C_msg = multi::mpi::message{CC.base(), CC.layout(), MPI_INT}; + + MPI_Recv(C_msg.buffer(), C_msg.count(), C_msg.datatype(), 0, 0, comm, MPI_STATUS_IGNORE); + BOOST_TEST(( CC == multi::array({1, 3, 5}) )); + } + } +} + +void test_2d(MPI_Comm comm) { + int world_rank; // NOLINT(cppcoreguidelines-init-variables) + MPI_Comm_rank(comm, &world_rank); + int world_size; // NOLINT(cppcoreguidelines-init-variables) + MPI_Comm_size(comm, &world_size); + + { + if(world_rank == 0) { + auto const AA = multi::array({ + {1, 2, 3}, + {4, 5, 6} + }); + + auto const& BB = AA({0, 2}, {1, 3}); + BOOST_TEST(( BB == multi::array({{2, 3}, {5, 6}}) )); + + auto const B_msg = multi::mpi::message(BB.elements()); + + MPI_Send(B_msg.buffer(), B_msg.count(), B_msg.datatype(), 1, 0, comm); + } else if(world_rank == 1) { + multi::array CC({2, 2}, 99); + + auto const C_sk = multi::mpi::skeleton(CC.elements().layout(), MPI_INT); + + MPI_Recv(CC.base(), C_sk.count(), C_sk.datatype(), 0, 0, comm, MPI_STATUS_IGNORE); + std::cout << CC[0][0] << ' ' << CC[0][1] << '\n' + << CC[1][0] << ' ' << CC[1][1] << '\n'; + + BOOST_TEST(( CC == multi::array({{2, 3}, {5, 6}}) )); + } + } + { + if(world_rank == 0) { + auto const AA = multi::array({ + {1, 2, 3}, + {4, 5, 6} + }); + + auto const& BB = AA({0, 2}, {1, 3}); + BOOST_TEST(( BB == multi::array({{2, 3}, {5, 6}}) )); + + auto const B_msg = multi::mpi::message(BB.elements()); + + MPI_Send(B_msg.buffer(), B_msg.count(), B_msg.datatype(), 1, 0, comm); + } else if(world_rank == 1) { + multi::array CC({2, 2}, 99); + + auto const C_sk = multi::mpi::skeleton(CC.elements().layout(), MPI_INT); + + MPI_Recv(CC.base(), C_sk.count(), C_sk.datatype(), 0, 0, comm, MPI_STATUS_IGNORE); + std::cout << CC[0][0] << ' ' << CC[0][1] << '\n' + << CC[1][0] << ' ' << CC[1][1] << '\n'; + + BOOST_TEST(( CC == multi::array({{2, 3}, {5, 6}}) )); + } + } + { + if(world_rank == 0) { + auto const AA = multi::array( + { + {1, 2, 3}, + {4, 5, 6} + } + ); + auto const& BB = AA({0, 2}, {1, 3}); + BOOST_TEST(( BB == multi::array({{2, 3}, {5, 6}}) )); + + MPI_Datatype B_type; // NOLINT(cppcoreguidelines-init-variables) + multi::mpi::create_subarray(BB.layout(), MPI_INT, &B_type); + MPI_Type_commit(&B_type); + MPI_Send(BB.base(), 1, B_type, 1, 0, comm); + MPI_Type_free(&B_type); + } else if(world_rank == 1) { + multi::array CC({2, 2}, 99); + + auto const C_sk = multi::mpi::skeleton(CC.layout(), MPI_INT); + + MPI_Recv(CC.base(), C_sk.count(), C_sk.datatype(), 0, 0, comm, MPI_STATUS_IGNORE); + std::cout << CC[0][0] << ' ' << CC[0][1] << '\n' + << CC[1][0] << ' ' << CC[1][1] << '\n'; + + BOOST_TEST(( CC == multi::array({{2, 3}, {5, 6}}) )); + } + } +} + +void test_2d_int(MPI_Comm comm) { + int world_rank; // NOLINT(cppcoreguidelines-init-variables) + MPI_Comm_rank(comm, &world_rank); + int world_size; // NOLINT(cppcoreguidelines-init-variables) + MPI_Comm_size(comm, &world_size); + + { + if(world_rank == 0) { + auto const AA = multi::array({ + {1, 2, 3}, + {4, 5, 6} + }); + + auto const& BB = AA({0, 2}, {1, 3}); + BOOST_TEST(( BB == multi::array({{2, 3}, {5, 6}}) )); + + auto const B_msg = multi::mpi::message(BB.elements()); + + MPI_Send(B_msg.buffer(), B_msg.count(), B_msg.datatype(), 1, 0, comm); + } else if(world_rank == 1) { + multi::array CC({2, 2}, 99); + + auto const C_sk = multi::mpi::skeleton(CC.layout()); + + MPI_Recv(CC.base(), C_sk.count(), C_sk.datatype(), 0, 0, comm, MPI_STATUS_IGNORE); + std::cout << CC[0][0] << ' ' << CC[0][1] << '\n' + << CC[1][0] << ' ' << CC[1][1] << '\n'; + + BOOST_TEST(( CC == multi::array({{2, 3}, {5, 6}}) )); + } + } +} + +void test_2d_double(MPI_Comm comm) { + int world_rank; // NOLINT(cppcoreguidelines-init-variables) + MPI_Comm_rank(comm, &world_rank); + int world_size; // NOLINT(cppcoreguidelines-init-variables) + MPI_Comm_size(comm, &world_size); + + { + if(world_rank == 0) { + auto const AA = multi::array({ + {1, 2, 3}, + {4, 5, 6} + }); + + auto const& BB = AA({0, 2}, {1, 3}); + BOOST_TEST(( BB == multi::array({{2, 3}, {5, 6}}) )); + + auto const& B_msg = multi::mpi::message(BB.elements()); + + MPI_Send(B_msg.buffer(), B_msg.count(), B_msg.datatype(), 1, 0, comm); + } else if(world_rank == 1) { + multi::array CC({2, 2}, 99.0); + + auto const C_sk = multi::mpi::skeleton(CC.layout()); + + MPI_Recv(CC.base(), C_sk.count(), C_sk.datatype(), 0, 0, comm, MPI_STATUS_IGNORE); + std::cout << CC[0][0] << ' ' << CC[0][1] << '\n' + << CC[1][0] << ' ' << CC[1][1] << '\n'; + + BOOST_TEST(( CC == multi::array({{2.0, 3.0}, {5.0, 6.0}}) )); + } + } +} + +} // namespace + +auto main() -> int { // NOLINT(bugprone-exception-escape) + MPI_Init(nullptr, nullptr); + + int world_rank; // NOLINT(cppcoreguidelines-init-variables) + MPI_Comm_rank(MPI_COMM_WORLD, &world_rank); + + int world_size; // NOLINT(cppcoreguidelines-init-variables) + MPI_Comm_size(MPI_COMM_WORLD, &world_size); + + std::cout << "size " << world_size << '\n'; + // int world_rank; MPI_Comm_rank(MPI_COMM_WORLD, &world_rank); // NOLINT(cppcoreguidelines-init-variables) + // int world_size; MPI_Comm_size(MPI_COMM_WORLD, &world_size); // NOLINT(cppcoreguidelines-init-variables) + + test_single_number(MPI_COMM_WORLD); + test_1d(MPI_COMM_WORLD); + + { + multi::array AA({3}, 99); + if(world_rank == 0) { + AA = multi::array({1, 2, 3}); + MPI_Send(AA.base(), static_cast(AA.size()), MPI_INT, 1, 0, MPI_COMM_WORLD); + } else if(world_rank == 1) { + MPI_Recv(AA.base(), static_cast(AA.size()), MPI_INT, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE); + BOOST_TEST(( AA == boost::multi::array({1, 2, 3}) )); + } + } + { + if(world_rank == 0) { + auto const AA = multi::array({ + {1, 2, 3}, + {4, 5, 6} + }); + + auto const& BB = AA({0, 2}, {1, 3}); + BOOST_TEST(( BB == multi::array({{2, 3}, {5, 6}}) )); + + auto const B_sk = multi::mpi::skeleton(BB.layout(), MPI_INT); + + MPI_Send(BB.base(), B_sk.count(), B_sk.datatype(), 1, 0, MPI_COMM_WORLD); + } else if(world_rank == 1) { + multi::array CC({2, 2}, 99); + + auto const C_sk = multi::mpi::skeleton(CC.elements().layout(), MPI_INT); + + MPI_Recv(CC.base(), C_sk.count(), C_sk.datatype(), 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE); + BOOST_TEST(( CC == multi::array({{2, 3}, {5, 6}}) )); + } + } + MPI_Barrier(MPI_COMM_WORLD); + + test_2d(MPI_COMM_WORLD); + test_2d_int(MPI_COMM_WORLD); + test_2d_double(MPI_COMM_WORLD); + + MPI_Finalize(); + + return boost::report_errors(); +} diff --git a/external_codes/boost_multi/multi/include/boost/multi/adaptors/rangev3_.hpp b/external_codes/boost_multi/multi/include/boost/multi/adaptors/rangev3_.hpp deleted file mode 100644 index df5b7c65d9..0000000000 --- a/external_codes/boost_multi/multi/include/boost/multi/adaptors/rangev3_.hpp +++ /dev/null @@ -1,50 +0,0 @@ -#ifdef COMPILATION_INSTRUCTIONS -(echo '#include"'$0'"'>$0.cpp)&&c++ -D_TEST_MULTI_ADAPTORS_RANGEV3 -Wall -Wfatal-errors $0.cpp -o$0x &&$0x&&rm $0x $0.cpp;exit -#endif -// © Alfredo A. Correa 2019 - -// This header is to make some exotic cases of Multi iterators with Ranges v3 -#include "../array.hpp" - -#include - -#ifndef BOOST_MULTI_ADAPTORS_RANGEV3_HPP -#define BOOST_MULTI_ADAPTORS_RANGEV3_HPP - -namespace ranges{namespace v3{ -namespace concepts{ // needed for later version of rangesv3 -// this allows to recognize const_iterator as RandomAccessIterator -#if 0 - template - struct common_reference< - boost::multi::subarray&&, - MA& - >{ - using type = boost::multi::subarray&&; - }; - template - struct common_reference< - MA&, - boost::multi::subarray&& - >{ - using type = boost::multi::subarray&&; - }; -#endif -} -}} - -#ifdef _TEST_MULTI_ADAPTORS_RANGEV3 - -#include - -namespace multi = boost::multi; - -int main(){ - - using I = multi::array::const_iterator; - static_assert( ranges::RandomAccessIterator{}, "!"); - -} -#endif - -#endif // BOOST_MULTI_ADAPTORS_RANGEV3_HPP \ No newline at end of file diff --git a/external_codes/boost_multi/multi/include/boost/multi/adaptors/thrust.hpp b/external_codes/boost_multi/multi/include/boost/multi/adaptors/thrust.hpp index e6482df433..3edc646edb 100644 --- a/external_codes/boost_multi/multi/include/boost/multi/adaptors/thrust.hpp +++ b/external_codes/boost_multi/multi/include/boost/multi/adaptors/thrust.hpp @@ -6,16 +6,13 @@ #define BOOST_MULTI_ADAPTORS_THRUST_HPP_ #pragma once -#include "../array.hpp" - -#include "./thrust/reference.hpp" +#include #include #include -#include -#if not defined(MULTI_USE_HIP) +#if !defined(MULTI_USE_HIP) #include // for ::thrust::cuda::allocator #else #include // for ::thrust::hip::allocator @@ -24,10 +21,37 @@ // #include -#include // std::copy +// #include // std::copy + +#include // for pointer + +#include // for allocator (ptr only), stateless_resource_allocator +#include // for memory_resource + +#if !defined(MULTI_USE_HIP) +#include // for tag +#include // for universal_memory_resource +#include // for universal_pointer + +#include // for cudaGetDevice, cudaMemPrefetchAsync, cudaPointerGetAttributes +#include // for cudaErrorInvalidValue, cudaPointerAttributes, cudaSuccess, cudaErrorInvalidDevice, cudaMemoryTypeManaged +#else +// #include // for tag +// #include // for universal_memory_resource +// #include // for universal_pointer + +// #include // for cudaGetDevice, cudaMemPrefetchAsync, cudaPointerGetAttributes +#endif #include -#include + +#include +#include // for iterator_traits +#include // for allocator_traits, allocator, pointer_traits +// #include // for iterator_system +#include // for decay_t + +// #include // // begin of nvcc trhust 11.5 workaround : https://github.com/NVIDIA/thrust/issues/1629 // namespace thrust { @@ -48,7 +72,7 @@ // } // end namespace std // // end of nvcc thrust 11.5 workaround -#if not defined(MULTI_USE_HIP) +#if !defined(MULTI_USE_HIP) #define HICUP cuda #define HICUP_(NAME) cuda ## NAME #else @@ -56,6 +80,8 @@ #define HICUP_(NAME) hip ## NAME #endif +namespace boost::multi { template struct allocator_traits; } + namespace boost::multi { template @@ -132,16 +158,16 @@ struct allocator_traits<::thrust::mr::stateless_resource_allocator struct iterator_system; +// template struct iterator_system; // not needed in cuda 12.0, doesn't work on cuda 12.5 -template -struct iterator_system>{ - using type = typename ::thrust::iterator_system::element_ptr>::type; +template +struct iterator_system<::boost::multi::array_iterator>{ + using type = typename ::thrust::iterator_system::element_ptr>::type; }; template -struct iterator_system> { - using type = typename ::thrust::iterator_system::pointer>::type; +struct iterator_system<::boost::multi::elements_iterator_t> { // TODO(correaa) might need changes for IsConst templating + using type = typename ::thrust::iterator_system::pointer>::type; }; // namespace detail { diff --git a/external_codes/boost_multi/multi/include/boost/multi/adaptors/thrust/CMakeLists.txt b/external_codes/boost_multi/multi/include/boost/multi/adaptors/thrust/CMakeLists.txt index a732d26d9a..dda9b1742a 100644 --- a/external_codes/boost_multi/multi/include/boost/multi/adaptors/thrust/CMakeLists.txt +++ b/external_codes/boost_multi/multi/include/boost/multi/adaptors/thrust/CMakeLists.txt @@ -5,7 +5,7 @@ project( LANGUAGES CXX ) -find_package(Boost REQUIRED COMPONENTS unit_test_framework) +find_package(Boost REQUIRED) # REQUIRED COMPONENTS unit_test_framework) if(ENABLE_CUDA OR DEFINED CXXCUDA) enable_language(CUDA) diff --git a/external_codes/boost_multi/multi/include/boost/multi/adaptors/thrust/fix_pointer_traits.hpp b/external_codes/boost_multi/multi/include/boost/multi/adaptors/thrust/fix_pointer_traits.hpp index 59981db301..e8afd59ad4 100644 --- a/external_codes/boost_multi/multi/include/boost/multi/adaptors/thrust/fix_pointer_traits.hpp +++ b/external_codes/boost_multi/multi/include/boost/multi/adaptors/thrust/fix_pointer_traits.hpp @@ -8,13 +8,14 @@ #include // for std::pointer_traits -// #include +#include -// begin of nvcc trhust 11.5 workaround : https://github.com/NVIDIA/thrust/issues/1629 +// #if(__CUDACC_VER_MAJOR__ * 10000 + __CUDACC_VER_MINOR__ * 100 + __CUDACC_VER_BUILD__ < 120500) +// begin of nvcc thrust 11.5 workaround : https://github.com/NVIDIA/thrust/issues/1629 namespace thrust { -template class pointer; -template struct pointer_traits; +// template class pointer; +// template struct pointer_traits; } // end namespace thrust @@ -24,6 +25,7 @@ struct std::pointer_traits<::thrust::pointer> // NOLINT(cert-dcl58-cpp) template using rebind = typename ::thrust::detail::pointer_traits<::thrust::pointer>::template rebind::other; }; - // end of nvcc thrust 11.5 workaround +// #endif + #endif diff --git a/external_codes/boost_multi/multi/include/boost/multi/adaptors/thrust/test/CMakeLists.txt b/external_codes/boost_multi/multi/include/boost/multi/adaptors/thrust/test/CMakeLists.txt index f550c43dca..4f618ea5a4 100644 --- a/external_codes/boost_multi/multi/include/boost/multi/adaptors/thrust/test/CMakeLists.txt +++ b/external_codes/boost_multi/multi/include/boost/multi/adaptors/thrust/test/CMakeLists.txt @@ -9,28 +9,29 @@ if(NOT DEFINED CMAKE_CUDA_ARCHITECTURES) set(CMAKE_CUDA_ARCHITECTURES native) endif() -set(CMAKE_CXX_STANDARD 17) +# set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) # set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} --expt-relaxed-constexpr --extended-lambda --Werror=cross-execution-space-call -Xcudafe \"--display_error_number\"") -find_package(Boost REQUIRED COMPONENTS unit_test_framework) +find_package(Boost) # COMPONENTS boost unit_test_framework) # tests require Boost.Core LightweightTest +include(CTest) enable_testing() -find_program(MEMORYCHECK_COMMAND valgrind) -set(MEMORYCHECK_COMMAND_OPTIONS "--leak-check=full --error-exitcode=1") -include(CTest) +# find_program(MEMORYCHECK_COMMAND valgrind) +# set(MEMORYCHECK_COMMAND_OPTIONS "--leak-check=full --error-exitcode=1") -find_package(Boost COMPONENTS unit_test_framework timer) +find_package(Boost COMPONENTS timer) if(NOT Boost_FOUND) - message(ERROR " Cannot find Boost.Timer. Try\n sudo apt install libboost-timer-dev # in Debian/Ubuntu") + message(ERROR " Cannot find Boost.Timer. Try\n sudo apt install libboost-timer-dev # in Debian/Ubuntu") endif() set(TEST_SRCS array.cu memory_resource.cu + run_reduce.cu set_identity_kernel.cu speed.cu speed_algo.cu diff --git a/external_codes/boost_multi/multi/include/boost/multi/adaptors/thrust/test/array.cu b/external_codes/boost_multi/multi/include/boost/multi/adaptors/thrust/test/array.cu index 1d61708b71..04c4ad77c6 100644 --- a/external_codes/boost_multi/multi/include/boost/multi/adaptors/thrust/test/array.cu +++ b/external_codes/boost_multi/multi/include/boost/multi/adaptors/thrust/test/array.cu @@ -2,20 +2,20 @@ // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt -#define BOOST_TEST_MODULE "C++ Unit Tests for Multi CUDA thrust" +#include -#include -#include -#include - -#include #include #include +#include #include +#include #include #include #include +#include + +#include #include @@ -40,411 +40,807 @@ inline constexpr bool ::boost::multi::force_element_trivial_default_construction namespace { template using test_allocator = -// multi ::memory::cuda::allocator -// multi ::memory::cuda::managed::allocator//, std::integral_constant > -// multi ::memory::cuda::cached::allocator > -// multi::thrust::cuda::managed_allocator - thrust::cuda::allocator -; - + // multi::thrust::cuda::managed_allocator + thrust::cuda::allocator; } -using types_list = boost::mpl::list< - // char, - double, - // std::complex, - thrust::complex ->; - -BOOST_AUTO_TEST_CASE(dummy_test) {} - -BOOST_AUTO_TEST_CASE(cuda_universal_empty) { - using complex = std::complex; - multi::array> A; - multi::array> B = A; - BOOST_REQUIRE( A.is_empty() ); - BOOST_REQUIRE( B.is_empty() ); - BOOST_REQUIRE( A == B ); -} +// using types_list = boost::mpl::list< +// // char, +// double, +// // std::complex, +// thrust::complex +// >; -BOOST_AUTO_TEST_CASE(cuda_allocators) { +#define BOOST_AUTO_TEST_CASE(CasenamE) /**/ - multi::array > A1(200, 0.0); +auto main() -> int { // NOLINT(readability-function-cognitive-complexity,bugprone-exception-escape) - BOOST_REQUIRE( size(A1) == 200 ); - A1[100] = 1.0; + BOOST_AUTO_TEST_CASE(cuda_universal_empty) { + using complex = thrust::complex; + multi::array> A; + multi::array> B = A; + BOOST_TEST( A.is_empty() ); + BOOST_TEST( B.is_empty() ); + BOOST_TEST( A == B ); + } - multi::array> const B1(200, 2.0); - BOOST_REQUIRE( B1[10] == 2.0 ); + BOOST_AUTO_TEST_CASE(cuda_allocators) { - A1[10] = B1[10]; - BOOST_REQUIRE( A1[10] == 2.0 ); -} + multi::array> A1(200, 0.0); + BOOST_TEST( size(A1) == 200 ); + A1[100] = 1.0; -BOOST_AUTO_TEST_CASE(test_univ_alloc) { - multi::array > Dev({128, 128}); - *raw_pointer_cast(Dev.base()) = 99.0; -} + multi::array> const B1(200, 2.0); + BOOST_TEST( B1[10] == 2.0 ); -BOOST_AUTO_TEST_CASE(mtc_universal_array) { - multi::thrust::cuda::universal_array Dev({128, 128}); - *raw_pointer_cast(Dev.base()) = 99.0; -} + A1[10] = B1[10]; + BOOST_TEST( A1[10] == 2.0 ); + } -BOOST_AUTO_TEST_CASE(mtc_universal_coloncolon_array) { - multi::thrust::cuda::universal::array Dev({128, 128}); - *raw_pointer_cast(Dev.base()) = 99.0; -} + BOOST_AUTO_TEST_CASE(cuda_1d_initlist) { -BOOST_AUTO_TEST_CASE(test_alloc) { - multi::array > Dev({128, 128}); - // *raw_pointer_cast(Dev.base()) = 99.0; // segmentation fault (correct behavior) -} + multi::array> A1 = {1.0, 2.0, 3.0}; + BOOST_TEST( A1.size() == 3 ); -#ifdef NDEBUG -BOOST_AUTO_TEST_CASE_TEMPLATE(thrust_copy_1D_issue123, T, types_list) { // BOOST_AUTO_TEST_CASE(fdfdfdsfds) { using T = char; - static_assert( multi::is_trivially_default_constructible{}, "!"); - static_assert( std::is_trivially_copy_constructible{} , "!"); - static_assert( std::is_trivially_assignable{} , "!"); + // BOOST_TEST( size(A1) == 200 ); + // A1[100] = 1.0; + // multi::array> const B1(200, 2.0); + // BOOST_TEST( B1[10] == 2.0 ); - multi::array> Devc(multi::extensions_t<1>{10240*10240}); - multi::array> Dev2(multi::extensions_t<1>{10240*10240}); - multi::array Host(multi::extensions_t<1>{10240*10240}); std::iota(Host.elements().begin(), Host.elements().end(), 12.); - multi::array Hos2(multi::extensions_t<1>{10240*10240}); + // A1[10] = B1[10]; + // BOOST_TEST( A1[10] == 2.0 ); - std::cout<<"| 1D `"<< typeid(T).name() <<"` total data size: "<< Host.num_elements()*sizeof(T) / 1073741824. <<" GB | speed |\n|---|---|"< devc | "<< Host.num_elements()*sizeof(T) / (t.elapsed().wall/1e9) / 1073741824. << "GB/sec |"< devc | "<< Host.sliced(0, 10240*10240/2).num_elements()*sizeof(T) / (t.elapsed().wall/1e9) / 1073741824. << "GB/sec |"< devc | "<< Host.strided(2).num_elements()*sizeof(T) / (t.elapsed().wall/1e9) / 1073741824. << "GB/sec |"< host | "<< Host.num_elements()*sizeof(T) / (t.elapsed().wall/1e9) / 1073741824. << "GB/sec |"< host | "<< Host.sliced(0, 10240*10240/2).num_elements()*sizeof(T) / (t.elapsed().wall/1e9) / 1073741824. << "GB/sec |"< host | "<< Host.strided(2).num_elements()*sizeof(T) / (t.elapsed().wall/1e9) / 1073741824. << "GB/sec |"< devc | "<< Dev2.num_elements()*sizeof(T) / (t.elapsed().wall/1e9) / 1073741824. << "GB/sec |"< devc | "<< Devc.num_elements()*sizeof(T) / (t.elapsed().wall/1e9) / 1073741824. << "GB/sec |"< devc | "<< Dev2.num_elements()*sizeof(T) / (t.elapsed().wall/1e9) / 1073741824. << "GB/sec |"< devc | "<< Dev2.num_elements()*sizeof(T) / (t.elapsed().wall/1e9) / 1073741824. << "GB/sec |"< devc | "<< Dev2.sliced(0, 10240*10240/2).num_elements()*sizeof(T) / (t.elapsed().wall/1e9) / 1073741824. << "GB/sec |"< devc | "<< Dev2.strided(2).num_elements()*sizeof(T) / (t.elapsed().wall/1e9) / 1073741824. << "GB/sec |"< host | "<< Hos2.num_elements()*sizeof(T) / (t.elapsed().wall/1e9) / 1073741824. << "GB/sec |"< host | "<< Hos2.sliced(0, 10240*10240/2).num_elements()*sizeof(T) / (t.elapsed().wall/1e9) / 1073741824. << "GB/sec |"< host | "<< Hos2.strided(2).num_elements()*sizeof(T) / (t.elapsed().wall/1e9) / 1073741824. << "GB/sec |"<> A = {1, 2, 3}; + multi::array> B(3, 0); -BOOST_AUTO_TEST_CASE_TEMPLATE(thrust_cpugpu_2D_issue123, T, types_list) { -// BOOST_AUTO_TEST_CASE(thrust_cpugpu_2D_issue123) { using T = double; + BOOST_TEST( A[1] == 2 ); - auto const exts = multi::extensions_t<2>({10240, 10240}); + thrust::transform( + A.begin(), A.end(), + B.begin(), + [] __host__ __device__(int elem) { + return elem * 2; + } // *2.0;} + ); - std::cout<<"| 2D `"<< typeid(T).name() <<"` max data size "<< exts.num_elements()*sizeof(T) / 1073741824. <<" GB | speed |\n|---|---|"<> Devc(exts); - multi::array> Dev2(exts); + { + multi::array> A = {1.0, 2.0, 3.0}; + multi::array> B(3); - multi::array Host(exts); std::iota(Host.elements().begin(), Host.elements().end(), 12.); - multi::array Hos2(exts); + // // for(int i = 0; i != A.size(); ++i) { B[i] = A[i]*2.0; } + // // for(auto i : A.extension()) { B[i] = A[i]*2.0; } - { - Devc({0, 5120},{0, 5120}) = Host({0, 5120},{0, 5120}); // 0.002859s - } - { - boost::timer::auto_cpu_timer t{""}; - Devc = Host; - std::cout<<"| contiguous host to devc | "<< Host.num_elements()*sizeof(T) / (t.elapsed().wall/1e9) / 1073741824. << "GB/sec |"< devc | "<< Devc.num_elements()*sizeof(T) / (t.elapsed().wall/1e9) / 1073741824. << "GB/sec |"<({1024, 1024, 100}); - - std::cout<<"| 3D `"<< typeid(T).name() <<"` max data size "<< exts.num_elements()*sizeof(T) / 1073741824. <<" GB | speed |\n|---|---|"<> Devc(exts); - multi::array> Dev2(exts); - multi::array Host(exts); std::iota(Host.elements().begin(), Host.elements().end(), 12.); - multi::array Hos2(exts); - - { - Devc({0, 512}, {0, 512}, {0, 512}) = Host({0, 512}, {0, 512}, {0, 512}); // 0.002859s - } - { - boost::timer::auto_cpu_timer t{""}; - Devc = Host; - std::cout<<"| contiguous host to devc | "<< Host.num_elements()*sizeof(T) / (t.elapsed().wall/1e9) / 1073741824. << " GB/sec |"< devc | "<< Devc.num_elements()*sizeof(T) / (t.elapsed().wall/1e9) / 1073741824. << "GB/sec |"< devc | "<< Dev2.num_elements()*sizeof(T) / (t.elapsed().wall/1e9) / 1073741824. << "GB/sec |"< devc | "<< Dev2.num_elements()*sizeof(T) / (t.elapsed().wall/1e9) / 1073741824. << "GB/sec |"<> Dev({128, 128}); + *raw_pointer_cast(Dev.base()) = 99.0; } - { - boost::timer::auto_cpu_timer t{""}; - Dev2({0, 512}, {0, 512}, {0, 512}) = Devc({0, 512}, {0, 512}, {0, 512}); // 0.002859s - cudaDeviceSynchronize(); - std::cout<<"| strided devc to devc | "<< Dev2({0, 512},{0, 512}, {0, 512}).num_elements()*sizeof(T) / (t.elapsed().wall/1e9) / 1073741824. << "GB/sec |"< Dev({128, 128}); + *raw_pointer_cast(Dev.base()) = 99.0; } - { - boost::timer::auto_cpu_timer t{""}; - Hos2 = Host; - std::cout<<"| contiguous host to host | "<< Hos2.num_elements()*sizeof(T) / (t.elapsed().wall/1e9) / 1073741824. << "GB/sec |"< Dev({128, 128}); + *raw_pointer_cast(Dev.base()) = 99.0; } - { - boost::timer::auto_cpu_timer t{""}; - Hos2.sliced(0, 512) = Host.sliced(0, 512); // 0.005292s - std::cout<<"| sliced host to host | "<< Hos2.sliced(0, 512).num_elements()*sizeof(T) / (t.elapsed().wall/1e9) / 1073741824. << "GB/sec |"<> Dev({128, 128}); + // *raw_pointer_cast(Dev.base()) = 99.0; // segmentation fault (correct behavior) } - { - boost::timer::auto_cpu_timer t{""}; - Hos2({0, 512}, {0, 512}, {0, 512}) = Host({0, 512}, {0, 512}, {0, 512}); // 0.002859s - std::cout<<"| strided host to host | "<< Hos2({0, 512},{0, 512}, {0, 512}).num_elements()*sizeof(T) / (t.elapsed().wall/1e9) / 1073741824. << "GB/sec |"<{}); + static_assert(std::is_trivially_copy_constructible{}); + static_assert(std::is_trivially_assignable{}); + + multi::array> Devc(multi::extensions_t<1>{10240 * 10240}); + multi::array> Dev2(multi::extensions_t<1>{10240 * 10240}); + multi::array Host(multi::extensions_t<1>{10240 * 10240}); + std::iota(Host.elements().begin(), Host.elements().end(), 12.); + multi::array Hos2(multi::extensions_t<1>{10240 * 10240}); + + std::cout << "| 1D `" << typeid(T).name() << "` total data size: " << Host.num_elements() * sizeof(T) / 1073741824. << " GB | speed |\n|---|---|" << std::endl; + { + Devc = Host; + } + { + boost::timer::auto_cpu_timer t{""}; + Devc = Host; + cudaDeviceSynchronize(); + std::cout << "| contiguous host -> devc | " << Host.num_elements() * sizeof(T) / (t.elapsed().wall / 1e9) / 1073741824. << "GB/sec |" << std::endl; + } + { + boost::timer::auto_cpu_timer t{""}; + Devc.sliced(0, 10240 * 10240 / 2) = Host.sliced(0, 10240 * 10240 / 2); + cudaDeviceSynchronize(); + std::cout << "| sliced host -> devc | " << Host.sliced(0, 10240 * 10240 / 2).num_elements() * sizeof(T) / (t.elapsed().wall / 1e9) / 1073741824. << "GB/sec |" << std::endl; + } + { + boost::timer::auto_cpu_timer t{""}; + Devc.strided(2) = Host.strided(2); + cudaDeviceSynchronize(); + std::cout << "| strided host -> devc | " << Host.strided(2).num_elements() * sizeof(T) / (t.elapsed().wall / 1e9) / 1073741824. << "GB/sec |" << std::endl; + } + { + boost::timer::auto_cpu_timer t{""}; + Hos2 = Devc; + cudaDeviceSynchronize(); + std::cout << "| contiguous devc -> host | " << Host.num_elements() * sizeof(T) / (t.elapsed().wall / 1e9) / 1073741824. << "GB/sec |" << std::endl; + // BOOST_TEST( Hos2 == Host ); + } + { + boost::timer::auto_cpu_timer t{""}; + Hos2.sliced(0, 10240 * 10240 / 2) = Devc.sliced(0, 10240 * 10240 / 2); + cudaDeviceSynchronize(); + std::cout << "| sliced devc -> host | " << Host.sliced(0, 10240 * 10240 / 2).num_elements() * sizeof(T) / (t.elapsed().wall / 1e9) / 1073741824. << "GB/sec |" << std::endl; + // BOOST_TEST( Hos2 == Host ); + } + { + boost::timer::auto_cpu_timer t{""}; + Hos2.strided(2) = Devc.strided(2); + cudaDeviceSynchronize(); + std::cout << "| strided devc -> host | " << Host.strided(2).num_elements() * sizeof(T) / (t.elapsed().wall / 1e9) / 1073741824. << "GB/sec |" << std::endl; + // BOOST_TEST( Hos2 == Host ); + } + { + boost::timer::auto_cpu_timer t{""}; + Dev2 = Devc; + cudaDeviceSynchronize(); + std::cout << "| contiguous devc -> devc | " << Dev2.num_elements() * sizeof(T) / (t.elapsed().wall / 1e9) / 1073741824. << "GB/sec |" << std::endl; + // BOOST_TEST( Dev2 == Devc ); + } + { + boost::timer::auto_cpu_timer t{""}; + auto Dev3 = Devc; + cudaDeviceSynchronize(); + std::cout << "| copy_ctr devc -> devc | " << Devc.num_elements() * sizeof(T) / (t.elapsed().wall / 1e9) / 1073741824. << "GB/sec |" << std::endl; + // BOOST_TEST( Dev3 == Devc ); + } + { + boost::timer::auto_cpu_timer t{""}; + cudaMemcpy(raw_pointer_cast(Dev2.data_elements()), raw_pointer_cast(Devc.data_elements()), Devc.num_elements() * sizeof(T), cudaMemcpyDeviceToDevice); + cudaDeviceSynchronize(); + std::cout << "| cudaMemcpy devc -> devc | " << Dev2.num_elements() * sizeof(T) / (t.elapsed().wall / 1e9) / 1073741824. << "GB/sec |" << std::endl; + // BOOST_TEST( Dev2 == Devc ); + } + { + boost::timer::auto_cpu_timer t{""}; + cudaMemcpy(raw_pointer_cast(Dev2.data_elements()), raw_pointer_cast(Devc.data_elements()), Devc.num_elements() * sizeof(T), cudaMemcpyDeviceToDevice); + cudaDeviceSynchronize(); + std::cout << "| cudaMemcpy devc -> devc | " << Dev2.num_elements() * sizeof(T) / (t.elapsed().wall / 1e9) / 1073741824. << "GB/sec |" << std::endl; + // BOOST_TEST( Dev2 == Devc ); + } + { + boost::timer::auto_cpu_timer t{""}; + Dev2.sliced(0, 10240 * 10240 / 2) = Devc.sliced(0, 10240 * 10240 / 2); // 0.005292s + cudaDeviceSynchronize(); + std::cout << "| sliced devc -> devc | " << Dev2.sliced(0, 10240 * 10240 / 2).num_elements() * sizeof(T) / (t.elapsed().wall / 1e9) / 1073741824. << "GB/sec |" << std::endl; + // BOOST_TEST( Dev2 == Devc ); + } + { + boost::timer::auto_cpu_timer t{""}; + Dev2.strided(2) = Devc.strided(2); // 0.005292s + cudaDeviceSynchronize(); + std::cout << "| strided devc -> devc | " << Dev2.strided(2).num_elements() * sizeof(T) / (t.elapsed().wall / 1e9) / 1073741824. << "GB/sec |" << std::endl; + // BOOST_TEST( Dev2 == Devc ); + } + { + boost::timer::auto_cpu_timer t{""}; + Hos2 = Host; + cudaDeviceSynchronize(); + std::cout << "| contiguous host -> host | " << Hos2.num_elements() * sizeof(T) / (t.elapsed().wall / 1e9) / 1073741824. << "GB/sec |" << std::endl; + } + { + boost::timer::auto_cpu_timer t{""}; + Hos2.sliced(0, 10240 * 10240 / 2) = Host.sliced(0, 10240 * 10240 / 2); // 0.005292s + cudaDeviceSynchronize(); + std::cout << "| sliced host -> host | " << Hos2.sliced(0, 10240 * 10240 / 2).num_elements() * sizeof(T) / (t.elapsed().wall / 1e9) / 1073741824. << "GB/sec |" << std::endl; + } + { + boost::timer::auto_cpu_timer t{""}; + Hos2.strided(2) = Host.strided(2); // 0.005292s + cudaDeviceSynchronize(); + std::cout << "| strided host -> host | " << Hos2.strided(2).num_elements() * sizeof(T) / (t.elapsed().wall / 1e9) / 1073741824. << "GB/sec |" << std::endl; + } + std::cout << " " << std::endl; + } + + BOOST_AUTO_TEST_CASE(thrust_copy_1D_issue123_complex) { // BOOST_AUTO_TEST_CASE(fdfdfdsfds) { using T = char; + using T = thrust::complex; + + static_assert(multi::is_trivially_default_constructible{}, "!"); + static_assert(std::is_trivially_copy_constructible{}, "!"); + static_assert(std::is_trivially_assignable{}, "!"); + + multi::array> Devc(multi::extensions_t<1>{10240 * 10240}); + multi::array> Dev2(multi::extensions_t<1>{10240 * 10240}); + multi::array Host(multi::extensions_t<1>{10240 * 10240}); + std::iota(Host.elements().begin(), Host.elements().end(), 12.); + multi::array Hos2(multi::extensions_t<1>{10240 * 10240}); + + std::cout << "| 1D `" << typeid(T).name() << "` total data size: " << Host.num_elements() * sizeof(T) / 1073741824. << " GB | speed |\n|---|---|" << std::endl; + { + Devc = Host; + } + { + boost::timer::auto_cpu_timer t{""}; + Devc = Host; + cudaDeviceSynchronize(); + std::cout << "| contiguous host -> devc | " << Host.num_elements() * sizeof(T) / (t.elapsed().wall / 1e9) / 1073741824. << "GB/sec |" << std::endl; + } + { + boost::timer::auto_cpu_timer t{""}; + Devc.sliced(0, 10240 * 10240 / 2) = Host.sliced(0, 10240 * 10240 / 2); + cudaDeviceSynchronize(); + std::cout << "| sliced host -> devc | " << Host.sliced(0, 10240 * 10240 / 2).num_elements() * sizeof(T) / (t.elapsed().wall / 1e9) / 1073741824. << "GB/sec |" << std::endl; + } + { + boost::timer::auto_cpu_timer t{""}; + Devc.strided(2) = Host.strided(2); + cudaDeviceSynchronize(); + std::cout << "| strided host -> devc | " << Host.strided(2).num_elements() * sizeof(T) / (t.elapsed().wall / 1e9) / 1073741824. << "GB/sec |" << std::endl; + } + { + boost::timer::auto_cpu_timer t{""}; + Hos2 = Devc; + cudaDeviceSynchronize(); + std::cout << "| contiguous devc -> host | " << Host.num_elements() * sizeof(T) / (t.elapsed().wall / 1e9) / 1073741824. << "GB/sec |" << std::endl; + // BOOST_TEST( Hos2 == Host ); + } + { + boost::timer::auto_cpu_timer t{""}; + Hos2.sliced(0, 10240 * 10240 / 2) = Devc.sliced(0, 10240 * 10240 / 2); + cudaDeviceSynchronize(); + std::cout << "| sliced devc -> host | " << Host.sliced(0, 10240 * 10240 / 2).num_elements() * sizeof(T) / (t.elapsed().wall / 1e9) / 1073741824. << "GB/sec |" << std::endl; + // BOOST_TEST( Hos2 == Host ); + } + { + boost::timer::auto_cpu_timer t{""}; + Hos2.strided(2) = Devc.strided(2); + cudaDeviceSynchronize(); + std::cout << "| strided devc -> host | " << Host.strided(2).num_elements() * sizeof(T) / (t.elapsed().wall / 1e9) / 1073741824. << "GB/sec |" << std::endl; + // BOOST_TEST( Hos2 == Host ); + } + { + boost::timer::auto_cpu_timer t{""}; + Dev2 = Devc; + cudaDeviceSynchronize(); + std::cout << "| contiguous devc -> devc | " << Dev2.num_elements() * sizeof(T) / (t.elapsed().wall / 1e9) / 1073741824. << "GB/sec |" << std::endl; + // BOOST_TEST( Dev2 == Devc ); + } + { + boost::timer::auto_cpu_timer t{""}; + auto Dev3 = Devc; + cudaDeviceSynchronize(); + std::cout << "| copy_ctr devc -> devc | " << Devc.num_elements() * sizeof(T) / (t.elapsed().wall / 1e9) / 1073741824. << "GB/sec |" << std::endl; + // BOOST_TEST( Dev3 == Devc ); + } + { + boost::timer::auto_cpu_timer t{""}; + cudaMemcpy(raw_pointer_cast(Dev2.data_elements()), raw_pointer_cast(Devc.data_elements()), Devc.num_elements() * sizeof(T), cudaMemcpyDeviceToDevice); + cudaDeviceSynchronize(); + std::cout << "| cudaMemcpy devc -> devc | " << Dev2.num_elements() * sizeof(T) / (t.elapsed().wall / 1e9) / 1073741824. << "GB/sec |" << std::endl; + // BOOST_TEST( Dev2 == Devc ); + } + { + boost::timer::auto_cpu_timer t{""}; + cudaMemcpy(raw_pointer_cast(Dev2.data_elements()), raw_pointer_cast(Devc.data_elements()), Devc.num_elements() * sizeof(T), cudaMemcpyDeviceToDevice); + cudaDeviceSynchronize(); + std::cout << "| cudaMemcpy devc -> devc | " << Dev2.num_elements() * sizeof(T) / (t.elapsed().wall / 1e9) / 1073741824. << "GB/sec |" << std::endl; + // BOOST_TEST( Dev2 == Devc ); + } + { + boost::timer::auto_cpu_timer t{""}; + Dev2.sliced(0, 10240 * 10240 / 2) = Devc.sliced(0, 10240 * 10240 / 2); // 0.005292s + cudaDeviceSynchronize(); + std::cout << "| sliced devc -> devc | " << Dev2.sliced(0, 10240 * 10240 / 2).num_elements() * sizeof(T) / (t.elapsed().wall / 1e9) / 1073741824. << "GB/sec |" << std::endl; + // BOOST_TEST( Dev2 == Devc ); + } + { + boost::timer::auto_cpu_timer t{""}; + Dev2.strided(2) = Devc.strided(2); // 0.005292s + cudaDeviceSynchronize(); + std::cout << "| strided devc -> devc | " << Dev2.strided(2).num_elements() * sizeof(T) / (t.elapsed().wall / 1e9) / 1073741824. << "GB/sec |" << std::endl; + // BOOST_TEST( Dev2 == Devc ); + } + { + boost::timer::auto_cpu_timer t{""}; + Hos2 = Host; + cudaDeviceSynchronize(); + std::cout << "| contiguous host -> host | " << Hos2.num_elements() * sizeof(T) / (t.elapsed().wall / 1e9) / 1073741824. << "GB/sec |" << std::endl; + } + { + boost::timer::auto_cpu_timer t{""}; + Hos2.sliced(0, 10240 * 10240 / 2) = Host.sliced(0, 10240 * 10240 / 2); // 0.005292s + cudaDeviceSynchronize(); + std::cout << "| sliced host -> host | " << Hos2.sliced(0, 10240 * 10240 / 2).num_elements() * sizeof(T) / (t.elapsed().wall / 1e9) / 1073741824. << "GB/sec |" << std::endl; + } + { + boost::timer::auto_cpu_timer t{""}; + Hos2.strided(2) = Host.strided(2); // 0.005292s + cudaDeviceSynchronize(); + std::cout << "| strided host -> host | " << Hos2.strided(2).num_elements() * sizeof(T) / (t.elapsed().wall / 1e9) / 1073741824. << "GB/sec |" << std::endl; + } + std::cout << " " << std::endl; + } + + BOOST_AUTO_TEST_CASE(thrust_cpugpu_2D_issue123_double) { + using T = double; + + auto const exts = multi::extensions_t<2>({10240, 10240}); + + std::cout << "| 2D `" << typeid(T).name() << "` max data size " << exts.num_elements() * sizeof(T) / 1073741824. << " GB | speed |\n|---|---|" << std::endl; + + multi::array> Devc(exts); + multi::array> Dev2(exts); + + multi::array Host(exts); + std::iota(Host.elements().begin(), Host.elements().end(), 12.); + multi::array Hos2(exts); + + { + Devc({0, 5120}, {0, 5120}) = Host({0, 5120}, {0, 5120}); // 0.002859s + } + { + boost::timer::auto_cpu_timer t{""}; + Devc = Host; + std::cout << "| contiguous host to devc | " << Host.num_elements() * sizeof(T) / (t.elapsed().wall / 1e9) / 1073741824. << "GB/sec |" << std::endl; + } + { + boost::timer::auto_cpu_timer t{""}; + Devc.sliced(0, 5120) = Host.sliced(0, 5120); // 0.005292s + std::cout << "| sliced host to devc | " << Host.sliced(0, 5120).num_elements() * sizeof(T) / (t.elapsed().wall / 1e9) / 1073741824. << "GB/sec |" << std::endl; + } + { + boost::timer::auto_cpu_timer t{""}; + Devc({0, 5120}, {0, 5120}) = Host({0, 5120}, {0, 5120}); // 0.002859s + std::cout << "| strided host to devc | " << Host({0, 5120}, {0, 5120}).num_elements() * sizeof(T) / (t.elapsed().wall / 1e9) / 1073741824. << "GB/sec |" << std::endl; + } + { + boost::timer::auto_cpu_timer t{""}; + Hos2 = Devc; + std::cout << "| contiguous devc to host | " << Host.num_elements() * sizeof(T) / (t.elapsed().wall / 1e9) / 1073741824. << "GB/sec |" << std::endl; + // BOOST_TEST(Hos2 == Host); + } + { + boost::timer::auto_cpu_timer t{""}; + Hos2.sliced(0, 5120) = Devc.sliced(0, 5120); // 0.005292s + std::cout << "| sliced devc to host | " << Host.sliced(0, 5120).num_elements() * sizeof(T) / (t.elapsed().wall / 1e9) / 1073741824. << "GB/sec |" << std::endl; + // BOOST_TEST(Hos2 == Host); + } + { + boost::timer::auto_cpu_timer t{""}; + Hos2({0, 5120}, {0, 5120}) = Devc({0, 5120}, {0, 5120}); // 0.002859s + std::cout << "| strided devc to host | " << Host({0, 5120}, {0, 5120}).num_elements() * sizeof(T) / (t.elapsed().wall / 1e9) / 1073741824. << "GB/sec |" << std::endl; + // BOOST_TEST(Hos2 == Host); + } + { + boost::timer::auto_cpu_timer t{""}; + Dev2 = Devc; + cudaDeviceSynchronize(); + std::cout << "| contiguous devc to devc | " << Host.num_elements() * sizeof(T) / (t.elapsed().wall / 1e9) / 1073741824. << "GB/sec |" << std::endl; + // BOOST_TEST( Dev2 == Devc ); + } + { + boost::timer::auto_cpu_timer t{""}; + auto Dev3 = Devc; + cudaDeviceSynchronize(); + std::cout << "| copy_ctr devc -> devc | " << Devc.num_elements() * sizeof(T) / (t.elapsed().wall / 1e9) / 1073741824. << "GB/sec |" << std::endl; + // BOOST_TEST( Dev3 == Devc ); + } + { + boost::timer::auto_cpu_timer t{""}; + cudaMemcpy(raw_pointer_cast(Dev2.data_elements()), raw_pointer_cast(Devc.data_elements()), Devc.num_elements() * sizeof(T), cudaMemcpyDeviceToDevice); + cudaDeviceSynchronize(); + std::cout << "| cudaMemcpy devc to devc | " << Host.num_elements() * sizeof(T) / (t.elapsed().wall / 1e9) / 1073741824. << "GB/sec |" << std::endl; + // BOOST_TEST( Dev2 == Devc ); + } + { + boost::timer::auto_cpu_timer t{""}; + cudaMemcpy(raw_pointer_cast(Dev2.data_elements()), raw_pointer_cast(Devc.data_elements()), Devc.num_elements() * sizeof(T), cudaMemcpyDeviceToDevice); + cudaDeviceSynchronize(); + std::cout << "| cudaMemcpy devc to devc | " << Host.num_elements() * sizeof(T) / (t.elapsed().wall / 1e9) / 1073741824. << "GB/sec |" << std::endl; + // BOOST_TEST( Dev2 == Devc ); + } + { + boost::timer::auto_cpu_timer t{""}; + auto Dev3 = Devc; + cudaDeviceSynchronize(); + std::cout << "| copy_ctr devc to devc | " << Host.num_elements() * sizeof(T) / (t.elapsed().wall / 1e9) / 1073741824. << "GB/sec |" << std::endl; + // BOOST_TEST( Dev2 == Devc ); + } + { + boost::timer::auto_cpu_timer t{""}; + Dev2.sliced(0, 5120) = Devc.sliced(0, 5120); // 0.005292s + cudaDeviceSynchronize(); + std::cout << "| sliced devc to devc | " << Host.sliced(0, 5120).num_elements() * sizeof(T) / (t.elapsed().wall / 1e9) / 1073741824. << "GB/sec |" << std::endl; + // BOOST_TEST( Dev2 == Devc ); + } + { + boost::timer::auto_cpu_timer t{""}; + Dev2({0, 5120}, {0, 5120}) = Devc({0, 5120}, {0, 5120}); // 0.002859s + cudaDeviceSynchronize(); + std::cout << "| strided devc to devc | " << Host({0, 5120}, {0, 5120}).num_elements() * sizeof(T) / (t.elapsed().wall / 1e9) / 1073741824. << "GB/sec |" << std::endl; + // BOOST_TEST( Dev2 == Devc ); + } + { + boost::timer::auto_cpu_timer t{""}; + Hos2 = Host; + std::cout << "| contiguous host to host | " << Host.num_elements() * sizeof(T) / (t.elapsed().wall / 1e9) / 1073741824. << "GB/sec |" << std::endl; + } + { + boost::timer::auto_cpu_timer t{""}; + Hos2.sliced(0, 5120) = Host.sliced(0, 5120); // 0.005292s + std::cout << "| sliced host to host | " << Host.sliced(0, 5120).num_elements() * sizeof(T) / (t.elapsed().wall / 1e9) / 1073741824. << "GB/sec |" << std::endl; + } + { + boost::timer::auto_cpu_timer t{""}; + Hos2({0, 5120}, {0, 5120}) = Host({0, 5120}, {0, 5120}); // 0.002859s + std::cout << "| strided host to host | " << Host({0, 5120}, {0, 5120}).num_elements() * sizeof(T) / (t.elapsed().wall / 1e9) / 1073741824. << "GB/sec |" << std::endl; + } + std::cout << " " << std::endl; + } + + BOOST_AUTO_TEST_CASE(thrust_cpugpu_2D_issue123_complex) { + using T = thrust::complex; + + auto const exts = multi::extensions_t<2>({10240, 10240}); + + std::cout << "| 2D `" << typeid(T).name() << "` max data size " << exts.num_elements() * sizeof(T) / 1073741824. << " GB | speed |\n|---|---|" << std::endl; + + multi::array> Devc(exts); + multi::array> Dev2(exts); + + multi::array Host(exts); + std::iota(Host.elements().begin(), Host.elements().end(), 12.); + multi::array Hos2(exts); + + { + Devc({0, 5120}, {0, 5120}) = Host({0, 5120}, {0, 5120}); // 0.002859s + } + { + boost::timer::auto_cpu_timer t{""}; + Devc = Host; + std::cout << "| contiguous host to devc | " << Host.num_elements() * sizeof(T) / (t.elapsed().wall / 1e9) / 1073741824. << "GB/sec |" << std::endl; + } + { + boost::timer::auto_cpu_timer t{""}; + Devc.sliced(0, 5120) = Host.sliced(0, 5120); // 0.005292s + std::cout << "| sliced host to devc | " << Host.sliced(0, 5120).num_elements() * sizeof(T) / (t.elapsed().wall / 1e9) / 1073741824. << "GB/sec |" << std::endl; + } + { + boost::timer::auto_cpu_timer t{""}; + Devc({0, 5120}, {0, 5120}) = Host({0, 5120}, {0, 5120}); // 0.002859s + std::cout << "| strided host to devc | " << Host({0, 5120}, {0, 5120}).num_elements() * sizeof(T) / (t.elapsed().wall / 1e9) / 1073741824. << "GB/sec |" << std::endl; + } + { + boost::timer::auto_cpu_timer t{""}; + Hos2 = Devc; + std::cout << "| contiguous devc to host | " << Host.num_elements() * sizeof(T) / (t.elapsed().wall / 1e9) / 1073741824. << "GB/sec |" << std::endl; + // BOOST_TEST(Hos2 == Host); + } + { + boost::timer::auto_cpu_timer t{""}; + Hos2.sliced(0, 5120) = Devc.sliced(0, 5120); // 0.005292s + std::cout << "| sliced devc to host | " << Host.sliced(0, 5120).num_elements() * sizeof(T) / (t.elapsed().wall / 1e9) / 1073741824. << "GB/sec |" << std::endl; + // BOOST_TEST(Hos2 == Host); + } + { + boost::timer::auto_cpu_timer t{""}; + Hos2({0, 5120}, {0, 5120}) = Devc({0, 5120}, {0, 5120}); // 0.002859s + std::cout << "| strided devc to host | " << Host({0, 5120}, {0, 5120}).num_elements() * sizeof(T) / (t.elapsed().wall / 1e9) / 1073741824. << "GB/sec |" << std::endl; + // BOOST_TEST(Hos2 == Host); + } + { + boost::timer::auto_cpu_timer t{""}; + Dev2 = Devc; + cudaDeviceSynchronize(); + std::cout << "| contiguous devc to devc | " << Host.num_elements() * sizeof(T) / (t.elapsed().wall / 1e9) / 1073741824. << "GB/sec |" << std::endl; + // BOOST_TEST( Dev2 == Devc ); + } + { + boost::timer::auto_cpu_timer t{""}; + auto Dev3 = Devc; + cudaDeviceSynchronize(); + std::cout << "| copy_ctr devc -> devc | " << Devc.num_elements() * sizeof(T) / (t.elapsed().wall / 1e9) / 1073741824. << "GB/sec |" << std::endl; + // BOOST_TEST( Dev3 == Devc ); + } + { + boost::timer::auto_cpu_timer t{""}; + cudaMemcpy(raw_pointer_cast(Dev2.data_elements()), raw_pointer_cast(Devc.data_elements()), Devc.num_elements() * sizeof(T), cudaMemcpyDeviceToDevice); + cudaDeviceSynchronize(); + std::cout << "| cudaMemcpy devc to devc | " << Host.num_elements() * sizeof(T) / (t.elapsed().wall / 1e9) / 1073741824. << "GB/sec |" << std::endl; + // BOOST_TEST( Dev2 == Devc ); + } + { + boost::timer::auto_cpu_timer t{""}; + cudaMemcpy(raw_pointer_cast(Dev2.data_elements()), raw_pointer_cast(Devc.data_elements()), Devc.num_elements() * sizeof(T), cudaMemcpyDeviceToDevice); + cudaDeviceSynchronize(); + std::cout << "| cudaMemcpy devc to devc | " << Host.num_elements() * sizeof(T) / (t.elapsed().wall / 1e9) / 1073741824. << "GB/sec |" << std::endl; + // BOOST_TEST( Dev2 == Devc ); + } + { + boost::timer::auto_cpu_timer t{""}; + auto Dev3 = Devc; + cudaDeviceSynchronize(); + std::cout << "| copy_ctr devc to devc | " << Host.num_elements() * sizeof(T) / (t.elapsed().wall / 1e9) / 1073741824. << "GB/sec |" << std::endl; + // BOOST_TEST( Dev2 == Devc ); + } + { + boost::timer::auto_cpu_timer t{""}; + Dev2.sliced(0, 5120) = Devc.sliced(0, 5120); // 0.005292s + cudaDeviceSynchronize(); + std::cout << "| sliced devc to devc | " << Host.sliced(0, 5120).num_elements() * sizeof(T) / (t.elapsed().wall / 1e9) / 1073741824. << "GB/sec |" << std::endl; + // BOOST_TEST( Dev2 == Devc ); + } + { + boost::timer::auto_cpu_timer t{""}; + Dev2({0, 5120}, {0, 5120}) = Devc({0, 5120}, {0, 5120}); // 0.002859s + cudaDeviceSynchronize(); + std::cout << "| strided devc to devc | " << Host({0, 5120}, {0, 5120}).num_elements() * sizeof(T) / (t.elapsed().wall / 1e9) / 1073741824. << "GB/sec |" << std::endl; + // BOOST_TEST( Dev2 == Devc ); + } + { + boost::timer::auto_cpu_timer t{""}; + Hos2 = Host; + std::cout << "| contiguous host to host | " << Host.num_elements() * sizeof(T) / (t.elapsed().wall / 1e9) / 1073741824. << "GB/sec |" << std::endl; + } + { + boost::timer::auto_cpu_timer t{""}; + Hos2.sliced(0, 5120) = Host.sliced(0, 5120); // 0.005292s + std::cout << "| sliced host to host | " << Host.sliced(0, 5120).num_elements() * sizeof(T) / (t.elapsed().wall / 1e9) / 1073741824. << "GB/sec |" << std::endl; + } + { + boost::timer::auto_cpu_timer t{""}; + Hos2({0, 5120}, {0, 5120}) = Host({0, 5120}, {0, 5120}); // 0.002859s + std::cout << "| strided host to host | " << Host({0, 5120}, {0, 5120}).num_elements() * sizeof(T) / (t.elapsed().wall / 1e9) / 1073741824. << "GB/sec |" << std::endl; + } + std::cout << " " << std::endl; + } + + BOOST_AUTO_TEST_CASE(thrust_cpugpu_issue123_3D_double) { + using T = double; + auto const exts = multi::extensions_t<3>({1024, 1024, 100}); + + std::cout << "| 3D `" << typeid(T).name() << "` max data size " << exts.num_elements() * sizeof(T) / 1073741824. << " GB | speed |\n|---|---|" << std::endl; + + multi::array> Devc(exts); + multi::array> Dev2(exts); + multi::array Host(exts); + std::iota(Host.elements().begin(), Host.elements().end(), 12.); + multi::array Hos2(exts); + + { + Devc({0, 512}, {0, 512}, {0, 512}) = Host({0, 512}, {0, 512}, {0, 512}); // 0.002859s + } + { + boost::timer::auto_cpu_timer t{""}; + Devc = Host; + std::cout << "| contiguous host to devc | " << Host.num_elements() * sizeof(T) / (t.elapsed().wall / 1e9) / 1073741824. << " GB/sec |" << std::endl; + } + { + boost::timer::auto_cpu_timer t{""}; + Devc.sliced(0, 512) = Host.sliced(0, 512); // 0.005292s + std::cout << "| sliced host to devc | " << Host.sliced(0, 512).num_elements() * sizeof(T) / (t.elapsed().wall / 1e9) / 1073741824. << " GB/sec |" << std::endl; + } + { + boost::timer::auto_cpu_timer t{""}; + Devc({0, 512}, {0, 512}, {0, 512}) = Host({0, 512}, {0, 512}, {0, 512}); // 0.002859s + std::cout << "| strided host to devc | " << Host({0, 512}, {0, 512}, {0, 512}).num_elements() * sizeof(T) / (t.elapsed().wall / 1e9) / 1073741824. << "GB/sec |" << std::endl; + } + { + boost::timer::auto_cpu_timer t{""}; + Hos2 = Devc; + std::cout << "| contiguous devc to host | " << Host.num_elements() * sizeof(T) / (t.elapsed().wall / 1e9) / 1073741824. << "GB/sec |" << std::endl; + // BOOST_TEST(Hos2 == Host); + } + { + boost::timer::auto_cpu_timer t{""}; + Hos2.sliced(0, 512) = Devc.sliced(0, 512); // 0.005292s + std::cout << "| sliced devc to host | " << Host.sliced(0, 512).num_elements() * sizeof(T) / (t.elapsed().wall / 1e9) / 1073741824. << "GB/sec |" << std::endl; + // BOOST_TEST(Hos2 == Host); + } + { + boost::timer::auto_cpu_timer t{""}; + Hos2({0, 512}, {0, 512}, {0, 512}) = Devc({0, 512}, {0, 512}, {0, 512}); // 0.002859s + std::cout << "| strided devc to host | " << Host({0, 512}, {0, 512}, {0, 512}).num_elements() * sizeof(T) / (t.elapsed().wall / 1e9) / 1073741824. << "GB/sec |" << std::endl; + // BOOST_TEST(Hos2 == Host); + } + { + boost::timer::auto_cpu_timer t{""}; + Dev2 = Devc; + cudaDeviceSynchronize(); + std::cout << "| contiguous devc to devc | " << Dev2.num_elements() * sizeof(T) / (t.elapsed().wall / 1e9) / 1073741824. << "GB/sec |" << std::endl; + // BOOST_TEST(Dev2 == Devc); + } + { + boost::timer::auto_cpu_timer t{""}; + auto Dev3 = Devc; + cudaDeviceSynchronize(); + std::cout << "| copy_ctr devc -> devc | " << Devc.num_elements() * sizeof(T) / (t.elapsed().wall / 1e9) / 1073741824. << "GB/sec |" << std::endl; + // BOOST_TEST( Dev3 == Devc ); + } + { + boost::timer::auto_cpu_timer t{""}; + cudaMemcpy(raw_pointer_cast(Dev2.data_elements()), raw_pointer_cast(Devc.data_elements()), Devc.num_elements() * sizeof(T), cudaMemcpyDeviceToDevice); + cudaDeviceSynchronize(); + std::cout << "| cudaMemcpy devc -> devc | " << Dev2.num_elements() * sizeof(T) / (t.elapsed().wall / 1e9) / 1073741824. << "GB/sec |" << std::endl; + // BOOST_TEST( Dev2 == Devc ); + } + { + boost::timer::auto_cpu_timer t{""}; + cudaMemcpy(raw_pointer_cast(Dev2.data_elements()), raw_pointer_cast(Devc.data_elements()), Devc.num_elements() * sizeof(T), cudaMemcpyDeviceToDevice); + cudaDeviceSynchronize(); + std::cout << "| cudaMemcpy devc -> devc | " << Dev2.num_elements() * sizeof(T) / (t.elapsed().wall / 1e9) / 1073741824. << "GB/sec |" << std::endl; + // BOOST_TEST( Dev2 == Devc ); + } + { + boost::timer::auto_cpu_timer t{""}; + Dev2.sliced(0, 512) = Devc.sliced(0, 512); // 0.005292s + cudaDeviceSynchronize(); + std::cout << "| sliced devc to devc | " << Dev2.sliced(0, 512).num_elements() * sizeof(T) / (t.elapsed().wall / 1e9) / 1073741824. << "GB/sec |" << std::endl; + // BOOST_TEST(Dev2 == Devc); + } + { + boost::timer::auto_cpu_timer t{""}; + Dev2({0, 512}, {0, 512}, {0, 512}) = Devc({0, 512}, {0, 512}, {0, 512}); // 0.002859s + cudaDeviceSynchronize(); + std::cout << "| strided devc to devc | " << Dev2({0, 512}, {0, 512}, {0, 512}).num_elements() * sizeof(T) / (t.elapsed().wall / 1e9) / 1073741824. << "GB/sec |" << std::endl; + // BOOST_TEST(Dev2 == Devc); + } + { + boost::timer::auto_cpu_timer t{""}; + Hos2 = Host; + std::cout << "| contiguous host to host | " << Hos2.num_elements() * sizeof(T) / (t.elapsed().wall / 1e9) / 1073741824. << "GB/sec |" << std::endl; + } + { + boost::timer::auto_cpu_timer t{""}; + Hos2.sliced(0, 512) = Host.sliced(0, 512); // 0.005292s + std::cout << "| sliced host to host | " << Hos2.sliced(0, 512).num_elements() * sizeof(T) / (t.elapsed().wall / 1e9) / 1073741824. << "GB/sec |" << std::endl; + } + { + boost::timer::auto_cpu_timer t{""}; + Hos2({0, 512}, {0, 512}, {0, 512}) = Host({0, 512}, {0, 512}, {0, 512}); // 0.002859s + std::cout << "| strided host to host | " << Hos2({0, 512}, {0, 512}, {0, 512}).num_elements() * sizeof(T) / (t.elapsed().wall / 1e9) / 1073741824. << "GB/sec |" << std::endl; + } + std::cout << " " << std::endl; + } + + BOOST_AUTO_TEST_CASE(thrust_cpugpu_issue123_3D_complex) { + using T = thrust::complex; + auto const exts = multi::extensions_t<3>({1024, 1024, 100}); + + std::cout << "| 3D `" << typeid(T).name() << "` max data size " << exts.num_elements() * sizeof(T) / 1073741824. << " GB | speed |\n|---|---|" << std::endl; + + multi::array> Devc(exts); + multi::array> Dev2(exts); + multi::array Host(exts); + std::iota(Host.elements().begin(), Host.elements().end(), 12.); + multi::array Hos2(exts); + + { + Devc({0, 512}, {0, 512}, {0, 512}) = Host({0, 512}, {0, 512}, {0, 512}); // 0.002859s + } + { + boost::timer::auto_cpu_timer t{""}; + Devc = Host; + std::cout << "| contiguous host to devc | " << Host.num_elements() * sizeof(T) / (t.elapsed().wall / 1e9) / 1073741824. << " GB/sec |" << std::endl; + } + { + boost::timer::auto_cpu_timer t{""}; + Devc.sliced(0, 512) = Host.sliced(0, 512); // 0.005292s + std::cout << "| sliced host to devc | " << Host.sliced(0, 512).num_elements() * sizeof(T) / (t.elapsed().wall / 1e9) / 1073741824. << " GB/sec |" << std::endl; + } + { + boost::timer::auto_cpu_timer t{""}; + Devc({0, 512}, {0, 512}, {0, 512}) = Host({0, 512}, {0, 512}, {0, 512}); // 0.002859s + std::cout << "| strided host to devc | " << Host({0, 512}, {0, 512}, {0, 512}).num_elements() * sizeof(T) / (t.elapsed().wall / 1e9) / 1073741824. << "GB/sec |" << std::endl; + } + { + boost::timer::auto_cpu_timer t{""}; + Hos2 = Devc; + std::cout << "| contiguous devc to host | " << Host.num_elements() * sizeof(T) / (t.elapsed().wall / 1e9) / 1073741824. << "GB/sec |" << std::endl; + // BOOST_TEST(Hos2 == Host); + } + { + boost::timer::auto_cpu_timer t{""}; + Hos2.sliced(0, 512) = Devc.sliced(0, 512); // 0.005292s + std::cout << "| sliced devc to host | " << Host.sliced(0, 512).num_elements() * sizeof(T) / (t.elapsed().wall / 1e9) / 1073741824. << "GB/sec |" << std::endl; + // BOOST_TEST(Hos2 == Host); + } + { + boost::timer::auto_cpu_timer t{""}; + Hos2({0, 512}, {0, 512}, {0, 512}) = Devc({0, 512}, {0, 512}, {0, 512}); // 0.002859s + std::cout << "| strided devc to host | " << Host({0, 512}, {0, 512}, {0, 512}).num_elements() * sizeof(T) / (t.elapsed().wall / 1e9) / 1073741824. << "GB/sec |" << std::endl; + // BOOST_TEST(Hos2 == Host); + } + { + boost::timer::auto_cpu_timer t{""}; + Dev2 = Devc; + cudaDeviceSynchronize(); + std::cout << "| contiguous devc to devc | " << Dev2.num_elements() * sizeof(T) / (t.elapsed().wall / 1e9) / 1073741824. << "GB/sec |" << std::endl; + // BOOST_TEST(Dev2 == Devc); + } + { + boost::timer::auto_cpu_timer t{""}; + auto Dev3 = Devc; + cudaDeviceSynchronize(); + std::cout << "| copy_ctr devc -> devc | " << Devc.num_elements() * sizeof(T) / (t.elapsed().wall / 1e9) / 1073741824. << "GB/sec |" << std::endl; + // BOOST_TEST( Dev3 == Devc ); + } + { + boost::timer::auto_cpu_timer t{""}; + cudaMemcpy(raw_pointer_cast(Dev2.data_elements()), raw_pointer_cast(Devc.data_elements()), Devc.num_elements() * sizeof(T), cudaMemcpyDeviceToDevice); + cudaDeviceSynchronize(); + std::cout << "| cudaMemcpy devc -> devc | " << Dev2.num_elements() * sizeof(T) / (t.elapsed().wall / 1e9) / 1073741824. << "GB/sec |" << std::endl; + // BOOST_TEST( Dev2 == Devc ); + } + { + boost::timer::auto_cpu_timer t{""}; + cudaMemcpy(raw_pointer_cast(Dev2.data_elements()), raw_pointer_cast(Devc.data_elements()), Devc.num_elements() * sizeof(T), cudaMemcpyDeviceToDevice); + cudaDeviceSynchronize(); + std::cout << "| cudaMemcpy devc -> devc | " << Dev2.num_elements() * sizeof(T) / (t.elapsed().wall / 1e9) / 1073741824. << "GB/sec |" << std::endl; + // BOOST_TEST( Dev2 == Devc ); + } + { + boost::timer::auto_cpu_timer t{""}; + Dev2.sliced(0, 512) = Devc.sliced(0, 512); // 0.005292s + cudaDeviceSynchronize(); + std::cout << "| sliced devc to devc | " << Dev2.sliced(0, 512).num_elements() * sizeof(T) / (t.elapsed().wall / 1e9) / 1073741824. << "GB/sec |" << std::endl; + // BOOST_TEST(Dev2 == Devc); + } + { + boost::timer::auto_cpu_timer t{""}; + Dev2({0, 512}, {0, 512}, {0, 512}) = Devc({0, 512}, {0, 512}, {0, 512}); // 0.002859s + cudaDeviceSynchronize(); + std::cout << "| strided devc to devc | " << Dev2({0, 512}, {0, 512}, {0, 512}).num_elements() * sizeof(T) / (t.elapsed().wall / 1e9) / 1073741824. << "GB/sec |" << std::endl; + // BOOST_TEST(Dev2 == Devc); + } + { + boost::timer::auto_cpu_timer t{""}; + Hos2 = Host; + std::cout << "| contiguous host to host | " << Hos2.num_elements() * sizeof(T) / (t.elapsed().wall / 1e9) / 1073741824. << "GB/sec |" << std::endl; + } + { + boost::timer::auto_cpu_timer t{""}; + Hos2.sliced(0, 512) = Host.sliced(0, 512); // 0.005292s + std::cout << "| sliced host to host | " << Hos2.sliced(0, 512).num_elements() * sizeof(T) / (t.elapsed().wall / 1e9) / 1073741824. << "GB/sec |" << std::endl; + } + { + boost::timer::auto_cpu_timer t{""}; + Hos2({0, 512}, {0, 512}, {0, 512}) = Host({0, 512}, {0, 512}, {0, 512}); // 0.002859s + std::cout << "| strided host to host | " << Hos2({0, 512}, {0, 512}, {0, 512}).num_elements() * sizeof(T) / (t.elapsed().wall / 1e9) / 1073741824. << "GB/sec |" << std::endl; + } + std::cout << " " << std::endl; } - std::cout<<" "<> Devc(multi::extensions_t<1>{10240*10240}); multi::array> Dev2(multi::extensions_t<1>{10240*10240}); @@ -459,25 +855,25 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(thrust_equality_1D_issue123, T, types_list) { Hos2 = Host; { boost::timer::auto_cpu_timer t{""}; - BOOST_REQUIRE( Devc == Dev2 ); + BOOST_TEST( Devc == Dev2 ); std::cout<<"| contiguous devc == devc | "<< Devc.num_elements()*sizeof(T) / (t.elapsed().wall/1e9) / 1073741824. << "GB/sec |\n"; } { boost::timer::auto_cpu_timer t{""}; - // BOOST_REQUIRE( Devc.sliced(0, Devc.size()/2) == Dev2.sliced(0, Devc.size()/2) ); - BOOST_REQUIRE( thrust::equal( Devc.sliced(0, Devc.size()/2).elements().begin(), Devc.sliced(0, Devc.size()/2).elements().end(), Dev2.sliced(0, Devc.size()/2).elements().begin() ) ); + // BOOST_TEST( Devc.sliced(0, Devc.size()/2) == Dev2.sliced(0, Devc.size()/2) ); + BOOST_TEST( thrust::equal( Devc.sliced(0, Devc.size()/2).elements().begin(), Devc.sliced(0, Devc.size()/2).elements().end(), Dev2.sliced(0, Devc.size()/2).elements().begin() ) ); std::cout<<"| sliced devc == devc | "<< Devc.num_elements()*sizeof(T) / (t.elapsed().wall/1e9) / 1073741824. << "GB/sec |\n"; } { boost::timer::auto_cpu_timer t{""}; - // BOOST_REQUIRE(Host == Hos2); - BOOST_REQUIRE( std::equal( Host.elements().begin(), Host.elements().end(), Hos2.elements().begin() ) ); + // BOOST_TEST(Host == Hos2); + BOOST_TEST( std::equal( Host.elements().begin(), Host.elements().end(), Hos2.elements().begin() ) ); std::cout<<"| contiguous host == host | "<< Hos2.num_elements()*sizeof(T) / (t.elapsed().wall/1e9) / 1073741824. << "GB/sec |\n"; } { boost::timer::auto_cpu_timer t{""}; - // BOOST_REQUIRE(Host.sliced(0, Devc.size()/2) == Hos2.sliced(0, Devc.size()/2) ); - BOOST_REQUIRE( std::equal( Host.sliced(0, Host.size()/2).elements().begin(), Host.sliced(0, Host.size()/2).elements().end(), Hos2.sliced(0, Devc.size()/2).elements().begin() ) ); + // BOOST_TEST(Host.sliced(0, Devc.size()/2) == Hos2.sliced(0, Devc.size()/2) ); + BOOST_TEST( std::equal( Host.sliced(0, Host.size()/2).elements().begin(), Host.sliced(0, Host.size()/2).elements().end(), Hos2.sliced(0, Devc.size()/2).elements().begin() ) ); std::cout<<"| sliced host == host | "<< Hos2.num_elements()*sizeof(T) / (t.elapsed().wall/1e9) / 1073741824. << "GB/sec |\n"; } @@ -488,25 +884,25 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(thrust_equality_1D_issue123, T, types_list) { BOOST_AUTO_TEST_CASE(thrust_equality_2D_small_host_issue123) { multi::array Host = {{1, 2, 3}, {4, 5, 6}}; multi::array Hos2 = {{1, 2, 3}, {4, 5, 6}}; - BOOST_REQUIRE( Host.size() == 2 ); + BOOST_TEST( Host.size() == 2 ); - BOOST_REQUIRE( *Host().elements().begin() == *Hos2().elements().begin() ); + BOOST_TEST( *Host().elements().begin() == *Hos2().elements().begin() ); - BOOST_REQUIRE( Host().elements().begin()[0] == Hos2().elements().begin()[0] ); - BOOST_REQUIRE( Host().elements().begin()[1] == Hos2().elements().begin()[1] ); - BOOST_REQUIRE( Host().elements().begin()[2] == Hos2().elements().begin()[2] ); - BOOST_REQUIRE( Host().elements().begin()[3] == Hos2().elements().begin()[3] ); - BOOST_REQUIRE( Host().elements().begin()[4] == Hos2().elements().begin()[4] ); - BOOST_REQUIRE( Host().elements().begin()[5] == Hos2().elements().begin()[5] ); + BOOST_TEST( Host().elements().begin()[0] == Hos2().elements().begin()[0] ); + BOOST_TEST( Host().elements().begin()[1] == Hos2().elements().begin()[1] ); + BOOST_TEST( Host().elements().begin()[2] == Hos2().elements().begin()[2] ); + BOOST_TEST( Host().elements().begin()[3] == Hos2().elements().begin()[3] ); + BOOST_TEST( Host().elements().begin()[4] == Hos2().elements().begin()[4] ); + BOOST_TEST( Host().elements().begin()[5] == Hos2().elements().begin()[5] ); - BOOST_REQUIRE( *(Host().elements().end() - 1) == *(Hos2().elements().end() - 1) ); - BOOST_REQUIRE( *(Host().elements().end() - 2) == *(Hos2().elements().end() - 2) ); - BOOST_REQUIRE( *(Host().elements().end() - 3) == *(Hos2().elements().end() - 3) ); + BOOST_TEST( *(Host().elements().end() - 1) == *(Hos2().elements().end() - 1) ); + BOOST_TEST( *(Host().elements().end() - 2) == *(Hos2().elements().end() - 2) ); + BOOST_TEST( *(Host().elements().end() - 3) == *(Hos2().elements().end() - 3) ); - BOOST_REQUIRE( std::equal(Host().elements().begin(), Host().elements().end(), Hos2().elements().begin()) ); - BOOST_REQUIRE( thrust::equal(Host().elements().begin(), Host().elements().end(), Hos2().elements().begin()) ); + BOOST_TEST( std::equal(Host().elements().begin(), Host().elements().end(), Hos2().elements().begin()) ); + BOOST_TEST( thrust::equal(Host().elements().begin(), Host().elements().end(), Hos2().elements().begin()) ); -// BOOST_REQUIRE( Host() == Hos2() ); +// BOOST_TEST( Host() == Hos2() ); } BOOST_AUTO_TEST_CASE(thrust_equality_2D_small_gpu_issue123) { @@ -514,31 +910,31 @@ BOOST_AUTO_TEST_CASE(thrust_equality_2D_small_gpu_issue123) { multi::array> Devc(Host.extensions()); Devc = Host; multi::array> Dev2(Host.extensions()); Dev2 = Host; - BOOST_REQUIRE( Dev2.size() == 2 ); + BOOST_TEST( Dev2.size() == 2 ); - BOOST_REQUIRE( thrust::equal( + BOOST_TEST( thrust::equal( Devc().elements().begin(), Devc().elements().end() , Dev2().elements().begin() )); - BOOST_REQUIRE( thrust::equal( + BOOST_TEST( thrust::equal( thrust::cuda::par, Devc().elements().begin(), Devc().elements().end() , Dev2().elements().begin() )); - BOOST_REQUIRE( thrust::equal( + BOOST_TEST( thrust::equal( Devc.rotated().elements().begin(), Devc.rotated().elements().end() , Dev2.rotated().elements().begin() )); - BOOST_REQUIRE( thrust::equal( + BOOST_TEST( thrust::equal( thrust::cuda::par, Devc.rotated().elements().begin(), Devc.rotated().elements().end() , Dev2.rotated().elements().begin() )); - BOOST_REQUIRE( multi::adl_equal( + BOOST_TEST( multi::adl_equal( Devc.rotated().elements().begin(), Devc.rotated().elements().end() , Dev2.rotated().elements().begin() )); @@ -558,40 +954,40 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(thrust_equality_2D_issue123, T, types_list) { Hos2 = Host; { boost::timer::auto_cpu_timer t{""}; - BOOST_REQUIRE(Host == Hos2); + BOOST_TEST(Host == Hos2); std::cout<<"| contiguous host == host | "<< Hos2.num_elements()*sizeof(T) / (t.elapsed().wall/1e9) / 1073741824. << "GB/sec |\n"; } { boost::timer::auto_cpu_timer t{""}; - BOOST_REQUIRE(Host.sliced(0, Host.size()/2) == Hos2.sliced(0, Host.size()/2)); - // BOOST_REQUIRE( std::equal(Host.sliced(0, 5120).elements().begin(), Host.sliced(0, 5120).elements().end(), Hos2.sliced(0, 5120).elements().begin()) ); + BOOST_TEST(Host.sliced(0, Host.size()/2) == Hos2.sliced(0, Host.size()/2)); + // BOOST_TEST( std::equal(Host.sliced(0, 5120).elements().begin(), Host.sliced(0, 5120).elements().end(), Hos2.sliced(0, 5120).elements().begin()) ); std::cout<<"| sliced host == host | "<< Hos2.num_elements()*sizeof(T) / (t.elapsed().wall/1e9) / 1073741824. << "GB/sec |\n"; } { boost::timer::auto_cpu_timer t{""}; - BOOST_REQUIRE(Host({0, Host.size()/2},{0, Host.size()/2}) == Hos2({0, Hos2.size()/2},{0, Hos2.size()/2})); - // BOOST_REQUIRE( std::equal(Host({0, 5120},{0, 5120}).elements().begin(), Host({0, 5120},{0, 5120}).elements().end(), Hos2({0, 5120},{0, 5120}).elements().begin()) ); + BOOST_TEST(Host({0, Host.size()/2},{0, Host.size()/2}) == Hos2({0, Hos2.size()/2},{0, Hos2.size()/2})); + // BOOST_TEST( std::equal(Host({0, 5120},{0, 5120}).elements().begin(), Host({0, 5120},{0, 5120}).elements().end(), Hos2({0, 5120},{0, 5120}).elements().begin()) ); std::cout<<"| strided host == host | "<< Hos2({0, Host.size()/2},{0, Host.size()/2}).num_elements()*sizeof(T) / (t.elapsed().wall/1e9) / 1073741824. << "GB/sec |\n"; } { boost::timer::auto_cpu_timer t{""}; - BOOST_REQUIRE(Devc == Dev2); + BOOST_TEST(Devc == Dev2); std::cout<<"| contiguous devc == devc | "<< Devc.num_elements()*sizeof(T) / (t.elapsed().wall/1e9) / 1073741824. << "GB/sec |\n"; } { boost::timer::auto_cpu_timer t{""}; - BOOST_REQUIRE(Devc.sliced(0, Devc.size()/2) == Dev2.sliced(0, Dev2.size()/2)); + BOOST_TEST(Devc.sliced(0, Devc.size()/2) == Dev2.sliced(0, Dev2.size()/2)); std::cout<<"| sliced devc == devc | "<< Devc.sliced(0, Devc.size()/2).num_elements()*sizeof(T) / (t.elapsed().wall/1e9) / 1073741824. << "GB/sec |\n"; } { boost::timer::auto_cpu_timer t{""}; - BOOST_REQUIRE(Devc({0, Devc.size()/2},{0, Devc.size()/2}) == Dev2({0, Dev2.size()/2},{0, Dev2.size()/2})); + BOOST_TEST(Devc({0, Devc.size()/2},{0, Devc.size()/2}) == Dev2({0, Dev2.size()/2},{0, Dev2.size()/2})); std::cout<<"| strided devc == devc | "<< Devc({0, Devc.size()/2},{0, Devc.size()/2}).num_elements()*sizeof(T) / (t.elapsed().wall/1e9) / 1073741824. << "GB/sec |\n"; } std::cout<<" "<> Devc({1024, 1024, 100}); multi::array> Dev2({1024, 1024, 100}); @@ -605,42 +1001,42 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(thrust_equality_issue123_3D, T, types_list) { Hos2 = Host; { boost::timer::auto_cpu_timer t{""}; - BOOST_REQUIRE( Devc == Dev2 ); + BOOST_TEST( Devc == Dev2 ); std::cout<<"| contiguous devc == devc | "<< Devc.num_elements()*sizeof(T) / (t.elapsed().wall/1e9) / 1073741824. << " GB/sec |\n"; } { boost::timer::auto_cpu_timer t{""}; - BOOST_REQUIRE( Devc.sliced(0, 512) == Dev2.sliced(0, 512) ); + BOOST_TEST( Devc.sliced(0, 512) == Dev2.sliced(0, 512) ); std::cout<<"| sliced devc == devc | "<< Dev2.sliced(0, 512).num_elements()*sizeof(T) / (t.elapsed().wall/1e9) / 1073741824. << " GB/sec |\n"; } { boost::timer::auto_cpu_timer t{""}; - BOOST_REQUIRE( Devc({0, 512}, {0, 512}, {0, 512}) == Dev2({0, 512}, {0, 512}, {0, 512}) ); + BOOST_TEST( Devc({0, 512}, {0, 512}, {0, 512}) == Dev2({0, 512}, {0, 512}, {0, 512}) ); std::cout<<"| strided devc == devc | "<< Dev2({0, 512},{0, 512}, {0, 512}).num_elements()*sizeof(T) / (t.elapsed().wall/1e9) / 1073741824. << "GB/sec |\n"; } { boost::timer::auto_cpu_timer t{""}; - BOOST_REQUIRE( Host == Hos2 ); + BOOST_TEST( Host == Hos2 ); std::cout<<"| contiguous host == host | "<< Hos2.num_elements()*sizeof(T) / (t.elapsed().wall/1e9) / 1073741824. << " GB/sec |\n"; } { boost::timer::auto_cpu_timer t{""}; - // BOOST_REQUIRE( Host.sliced(0, 512) == Hos2.sliced(0, 512) ); - BOOST_REQUIRE( std::equal( Host.sliced(0, 512).elements().begin(), Host.sliced(0, 512).elements().end(), Hos2.sliced(0, 512).elements().begin() ) ); + // BOOST_TEST( Host.sliced(0, 512) == Hos2.sliced(0, 512) ); + BOOST_TEST( std::equal( Host.sliced(0, 512).elements().begin(), Host.sliced(0, 512).elements().end(), Hos2.sliced(0, 512).elements().begin() ) ); std::cout<<"| sliced host == host | "<< Hos2.sliced(0, 512).num_elements()*sizeof(T) / (t.elapsed().wall/1e9) / 1073741824. << " GB/sec |\n"; } { boost::timer::auto_cpu_timer t{""}; - // BOOST_REQUIRE( Host({0, 512}, {0, 512}, {0, 512}) == Hos2({0, 512}, {0, 512}, {0, 512}) ); - BOOST_REQUIRE( std::equal( Host({0, 512}, {0, 512}, {0, 512}).elements().begin(), Host({0, 512}, {0, 512}, {0, 512}).elements().end(), Hos2({0, 512}, {0, 512}, {0, 512}).elements().begin() ) ); + // BOOST_TEST( Host({0, 512}, {0, 512}, {0, 512}) == Hos2({0, 512}, {0, 512}, {0, 512}) ); + BOOST_TEST( std::equal( Host({0, 512}, {0, 512}, {0, 512}).elements().begin(), Host({0, 512}, {0, 512}, {0, 512}).elements().end(), Hos2({0, 512}, {0, 512}, {0, 512}).elements().begin() ) ); std::cout<<"| strided host == host | "<< Hos2({0, 512},{0, 512}, {0, 512}).num_elements()*sizeof(T) / (t.elapsed().wall/1e9) / 1073741824. << "GB/sec |\n"; } std::cout<<" "<; } @@ -652,19 +1048,19 @@ BOOST_AUTO_TEST_CASE(thrust_complex_cached_1D) { bb = aa; - BOOST_REQUIRE(( bb[0] == T{1., 1.} )); + BOOST_TEST(( bb[0] == T{1., 1.} )); } BOOST_AUTO_TEST_CASE(thrust_complex_cached_without_values_1D) { using T = inq::complex; multi::array > aa(10); multi::array > bb(10); - BOOST_REQUIRE( aa.size() == 10 ); - BOOST_REQUIRE( bb.size() == 10 ); + BOOST_TEST( aa.size() == 10 ); + BOOST_TEST( bb.size() == 10 ); bb = aa; - BOOST_REQUIRE(( bb[0] == aa[0] )); + BOOST_TEST(( bb[0] == aa[0] )); } BOOST_AUTO_TEST_CASE(thrust_complex_cached_2D) { @@ -674,19 +1070,19 @@ BOOST_AUTO_TEST_CASE(thrust_complex_cached_2D) { bb = aa; - BOOST_REQUIRE(( bb[0][0] == T{1., 1.} )); + BOOST_TEST(( bb[0][0] == T{1., 1.} )); } BOOST_AUTO_TEST_CASE(thrust_complex_cached_without_values_2D) { using T = inq::complex; multi::array > aa({10, 20}); multi::array > bb({10, 20}); - BOOST_REQUIRE( aa.size() == 10 ); - BOOST_REQUIRE( bb.size() == 10 ); + BOOST_TEST( aa.size() == 10 ); + BOOST_TEST( bb.size() == 10 ); bb = aa; - BOOST_REQUIRE(( bb[0][0] == aa[0][0] )); + BOOST_TEST(( bb[0][0] == aa[0][0] )); } BOOST_AUTO_TEST_CASE(array) { @@ -709,58 +1105,62 @@ BOOST_AUTO_TEST_CASE(array) { // { // multi::thrust::cuda::array C(H.extensions()); -// BOOST_REQUIRE( C.num_elements() == H.num_elements() ); +// BOOST_TEST( C.num_elements() == H.num_elements() ); // thrust::copy_n(H.data_elements(), H.num_elements(), C.data_elements()); // BOOST_TEST_REQUIRE( C[1][1] == 11. ); -// BOOST_REQUIRE( C == H ); +// BOOST_TEST( C == H ); // } // { // multi::thrust::cuda::array C(H.extensions()); -// BOOST_REQUIRE( C.num_elements() == H.num_elements() ); +// BOOST_TEST( C.num_elements() == H.num_elements() ); // std::copy_n(H.data_elements(), H.num_elements(), C.data_elements()); // BOOST_TEST_REQUIRE( C[1][1] == 11. ); -// BOOST_REQUIRE( C == H ); +// BOOST_TEST( C == H ); // } // { // multi::thrust::cuda::array C(H.extensions()); -// BOOST_REQUIRE( C.num_elements() == H.num_elements() ); +// BOOST_TEST( C.num_elements() == H.num_elements() ); // std::uninitialized_copy_n(H.data_elements(), H.num_elements(), C.data_elements()); // BOOST_TEST_REQUIRE( C[1][1] == 11. ); -// BOOST_REQUIRE( C == H ); +// BOOST_TEST( C == H ); // } // { // multi::thrust::cuda::array C(H.extensions()); -// BOOST_REQUIRE( C.num_elements() == H.num_elements() ); +// BOOST_TEST( C.num_elements() == H.num_elements() ); // thrust::uninitialized_copy_n(H.data_elements(), H.num_elements(), C.data_elements()); // BOOST_TEST_REQUIRE( C[1][1] == 11. ); -// BOOST_REQUIRE( C == H ); +// BOOST_TEST( C == H ); // } // { // multi::thrust::cuda::array C(H.extensions()); -// BOOST_REQUIRE( C.extensions() == H.extensions() ); +// BOOST_TEST( C.extensions() == H.extensions() ); // thrust::copy_n(H.begin(), H.size(), C.begin()); -// BOOST_REQUIRE( C == H ); +// BOOST_TEST( C == H ); // } // { // multi::thrust::cuda::array C(H.extensions()); -// BOOST_REQUIRE( C.extensions() == H.extensions() ); +// BOOST_TEST( C.extensions() == H.extensions() ); // std::copy_n(H.begin(), H.size(), C.begin()); -// BOOST_REQUIRE( C == H ); +// BOOST_TEST( C == H ); // } // { // multi::thrust::cuda::array C(H.extensions()); // C = H; -// BOOST_REQUIRE( C == H ); +// BOOST_TEST( C == H ); // } // { // multi::thrust::cuda::array C = H; -// BOOST_REQUIRE( C == H ); +// BOOST_TEST( C == H ); // } //} } -#endif + +return boost::report_errors();} + + #endif +#endif \ No newline at end of file diff --git a/external_codes/boost_multi/multi/include/boost/multi/adaptors/thrust/test/device_vector.cu b/external_codes/boost_multi/multi/include/boost/multi/adaptors/thrust/test/device_vector.cu index 6c24222454..8cf38843b8 100644 --- a/external_codes/boost_multi/multi/include/boost/multi/adaptors/thrust/test/device_vector.cu +++ b/external_codes/boost_multi/multi/include/boost/multi/adaptors/thrust/test/device_vector.cu @@ -1,10 +1,10 @@ #include int main(){ -// thrust::device_vector D(5); -// assert( D.size() == 5 ); - -// cudaDeviceSynchronize(); +// thrust::device_vector D(5); +// assert( D.size() == 5 ); +sasa; +// cudaDeviceSynchronize(); std::allocator alloc; int* p = alloc.allocate(10); p[0] = 2; diff --git a/external_codes/boost_multi/multi/include/boost/multi/adaptors/thrust/test/memory_resource.cu b/external_codes/boost_multi/multi/include/boost/multi/adaptors/thrust/test/memory_resource.cu index b58159e817..c996ee383f 100644 --- a/external_codes/boost_multi/multi/include/boost/multi/adaptors/thrust/test/memory_resource.cu +++ b/external_codes/boost_multi/multi/include/boost/multi/adaptors/thrust/test/memory_resource.cu @@ -3,7 +3,6 @@ // https://www.boost.org/LICENSE_1_0.txt #define BOOST_TEST_MODULE "C++ Unit Tests for Multi CUDA thrust memory resource" -#include #include #include @@ -15,7 +14,7 @@ #include // for thrust::mr::tls_disjoint_pool #include // for thrust::mr::unsynchronized_pool_resource -#include +// #include #include #include @@ -39,6 +38,12 @@ void do_stuff_with_array(typename MultiArray::allocator_type alloc) { BOOST_REQUIRE(arr1.num_elements() == 600); } +#include +#define BOOST_AUTO_TEST_CASE(CasenamE) /**/ + +auto main() -> int { // NOLINT(readability-function-cognitive-complexity,bugprone-exception-escape) + +#if 0 BOOST_AUTO_TEST_CASE(thrust_host_memory_resource) { thrust::mr::new_delete_resource memres; @@ -71,8 +76,6 @@ BOOST_AUTO_TEST_CASE(thrust_host_memory_resource) { } } -template void what(T&&) = delete; - BOOST_AUTO_TEST_CASE(thrust_device_memory_resource) { { // use the global device_ptr-flavored device memory resource @@ -325,3 +328,8 @@ BOOST_AUTO_TEST_CASE(thrust_benchmark_contd) { } } #endif + +#endif +return boost::report_errors(); + +} \ No newline at end of file diff --git a/external_codes/boost_multi/multi/include/boost/multi/adaptors/thrust/test/run_reduce.cu b/external_codes/boost_multi/multi/include/boost/multi/adaptors/thrust/test/run_reduce.cu new file mode 100644 index 0000000000..51e094024b --- /dev/null +++ b/external_codes/boost_multi/multi/include/boost/multi/adaptors/thrust/test/run_reduce.cu @@ -0,0 +1,185 @@ + +// #define ENABLE_GPU 1 + +#include + +#include + +#include + +#include + +template +__global__ void reduce_kernel_vr(long sizex, long sizey, kernel_type kernel, array_type odata) { + + extern __shared__ char shared_mem[]; + auto reduction_buffer = (typename array_type::element*)shared_mem; // {blockDim.x, blockDim.y} + + // each thread loads one element from global to shared mem + unsigned int ix = blockIdx.x * blockDim.x + threadIdx.x; + unsigned int tid = threadIdx.y; + unsigned int iy = blockIdx.y * blockDim.y + threadIdx.y; + + if(ix >= sizex) + return; + + if(iy < sizey) { + reduction_buffer[threadIdx.x + blockDim.x * tid] = kernel(ix, iy); + } else { + reduction_buffer[threadIdx.x + blockDim.x * tid] = (typename array_type::element)0.0; + } + + __syncthreads(); + + // do reduction in shared mem + for(unsigned int s = blockDim.y / 2; s > 0; s >>= 1) { + if(tid < s) { + reduction_buffer[threadIdx.x + blockDim.x * tid] += reduction_buffer[threadIdx.x + blockDim.x * (tid + s)]; + } + __syncthreads(); + } + + // write result for this block to global mem + if(tid == 0) + odata[blockIdx.y][ix] = reduction_buffer[threadIdx.x]; +} + +namespace gpu { +template> +using array = boost::multi::array; + +struct reduce { + explicit reduce(long arg_size) : size(arg_size) { + } + long size; +}; + +template +struct array_access { + array_type array; + + __host__ __device__ auto operator()(long ii) const { + return array[ii]; + } + + __host__ __device__ auto operator()(long ix, long iy) const { + return array[ix][iy]; + } +}; + +template +auto run(long sizex, reduce const& redy, kernel_type kernel) /*-> gpu::array*/ { + + auto const sizey = redy.size; + + // using type = decltype(kernel(0, 0)); + +#ifndef ENABLE_GPU + + gpu::array accumulator(sizex, 0.0); + + for(long iy = 0; iy < sizey; iy++) { + for(long ix = 0; ix < sizex; ix++) { + accumulator[ix] += kernel(ix, iy); + } + } + + // thrust::transform( + // boost::multi::extension_t({0, sizey}).begin(), + // boost::multi::extension_t({0, sizey}).end(), + // accumulator.begin(), + // [](auto e) {return 0.0;} + // ); + + return accumulator; + +#else + + gpu::array result; + + auto blocksize = 256; // max_blocksize(reduce_kernel_vr); + + unsigned bsizex = 4; // this seems to be the optimal value + if(sizex <= 2) + bsizex = sizex; + unsigned bsizey = blocksize / bsizex; + + assert(bsizey > 1); + + unsigned nblockx = (sizex + bsizex - 1) / bsizex; + unsigned nblocky = (sizey + bsizey - 1) / bsizey; + + result.reextent({nblocky, sizex}); + + gpu::array result2({nblocky, sizex}); + + struct dim3 dg { + nblockx, nblocky + }; + struct dim3 db { + bsizex, bsizey + }; + + auto shared_mem_size = blocksize * sizeof(type); + + assert(shared_mem_size <= 48 * 1024); + + reduce_kernel_vr<<>>(sizex, sizey, kernel, begin(result)); + // check_error(last_error()); + + boost::multi::extensions_t<2> xs = {sizex, sizey}; + assert( xs.size() == sizex ); + + // thrust::transform_reduce( + // xs. + // ); + + if(nblocky == 1) { + cudaDeviceSynchronize(); + // gpu::sync(); + + assert(result[0].size() == sizex); + + return gpu::array(result[0]); + } else { + return run(sizex, reduce(nblocky), array_access{begin(result.transposed())}); + } + +#endif +} + +} // namespace gpu + +struct prod { + /*__host__*/ __device__ auto operator()(long ix, long iy) const { + return double(ix) * double(iy); + } +}; + +auto main() -> int { + + long const maxsize = 390; // 390625; + long const nmax = 100; // 10000; + + auto start = std::chrono::high_resolution_clock::now(); + + int rank = 0; + for(long nx = 1; nx <= nmax; nx *= 10) { + for(long ny = 1; ny <= maxsize; ny *= 5) { + + auto pp = [] __host__ __device__(long ix, long iy) -> double { return double(ix) * double(iy); }; + + auto res = gpu::run(nx, gpu::reduce(ny), pp); + + BOOST_TEST(typeid(decltype(res)) == typeid(gpu::array)); + BOOST_TEST(res.size() == nx); + + for(long ix = 0; ix < nx; ix++) + BOOST_TEST(res[ix] == double(ix) * ny * (ny - 1.0) / 2.0); + rank++; + } + } + std::cout << std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - start).count() << "ms\n"; + + return boost::report_errors(); +} diff --git a/external_codes/boost_multi/multi/include/boost/multi/adaptors/thrust/test/speed.cu b/external_codes/boost_multi/multi/include/boost/multi/adaptors/thrust/test/speed.cu index c00ab46cbc..9396de38b4 100644 --- a/external_codes/boost_multi/multi/include/boost/multi/adaptors/thrust/test/speed.cu +++ b/external_codes/boost_multi/multi/include/boost/multi/adaptors/thrust/test/speed.cu @@ -3,7 +3,6 @@ // https://www.boost.org/LICENSE_1_0.txt #define BOOST_TEST_MODULE "C++ Unit Tests for Multi CUDA thrust universal copy and assignment" -#include #include @@ -27,12 +26,17 @@ inline constexpr bool multi::force_element_trivial_default_construction // inline constexpr bool multi::force_element_trivial_default_construction> = true; -using test_types = boost::mpl::list< - char, unsigned, int, - ::thrust::complex, // std::complex, - ::thrust::complex, // std::complex, - double, float ->; +// using test_types = boost::mpl::list< +// char, unsigned, int, +// ::thrust::complex, // std::complex, +// ::thrust::complex, // std::complex, +// double, float +// >; + +#include +#define BOOST_AUTO_TEST_CASE(CasenamE) /**/ + +auto main() -> int { // NOLINT(readability-function-cognitive-complexity,bugprone-exception-escape) BOOST_AUTO_TEST_CASE(warmup) { using T = double; @@ -107,7 +111,8 @@ BOOST_AUTO_TEST_CASE(warmup) { } } -BOOST_AUTO_TEST_CASE_TEMPLATE(thrust_nonuniversal_speed, T, test_types) { +BOOST_AUTO_TEST_CASE(thrust_nonuniversal_speed) { + using T = ::thrust::complex; std::cout << typeid(T).name() << " ******************************************\n"; auto const n = 8000; @@ -178,7 +183,8 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(thrust_nonuniversal_speed, T, test_types) { } } -BOOST_AUTO_TEST_CASE_TEMPLATE(thrust_universal_speed, T, test_types) { +BOOST_AUTO_TEST_CASE(thrust_universal_speed) { + using T = ::thrust::complex; std::cout << typeid(T).name() << " ******************************************\n"; auto const n = 8000; @@ -222,7 +228,7 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(thrust_universal_speed, T, test_types) { double ratio = rate / memcpy_rate; std::cout << "cctor rate = " << rate << " GB/s (ratio = " << ratio << ")\n"; - BOOST_WARN(ratio >= threshold); + // BOOST_WARN(ratio >= threshold); } { // assign auto tick = std::chrono::high_resolution_clock::now(); @@ -248,3 +254,6 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(thrust_universal_speed, T, test_types) { BOOST_TEST(ratio >= threshold); } } + +return boost::report_errors(); +} diff --git a/external_codes/boost_multi/multi/include/boost/multi/adaptors/thrust/test/speed_algo.cu b/external_codes/boost_multi/multi/include/boost/multi/adaptors/thrust/test/speed_algo.cu index 3b47f47e8a..a9cbefd93f 100644 --- a/external_codes/boost_multi/multi/include/boost/multi/adaptors/thrust/test/speed_algo.cu +++ b/external_codes/boost_multi/multi/include/boost/multi/adaptors/thrust/test/speed_algo.cu @@ -3,7 +3,7 @@ // https://www.boost.org/LICENSE_1_0.txt #define BOOST_TEST_MODULE "C++ Unit Tests for Multi CUDA thrust universal copy and assignment" -#include +// #include #include //#include @@ -23,6 +23,13 @@ void doNotOptimize(T const& val) { asm volatile("" : : "g"(val) : "memory"); } + +#include +#define BOOST_AUTO_TEST_CASE(CasenamE) /**/ + +// #define BOOST_REQUIRE_CLOSE(X, Y, ToL) BOOST_TEST( std::abs( (X) - (Y) ) < (ToL) ) + +int main() { BOOST_AUTO_TEST_CASE(thrust_universal_speed_algo) { auto const n = 8000; @@ -107,4 +114,8 @@ BOOST_AUTO_TEST_CASE(thrust_universal_speed_algo) { BOOST_AUTO_TEST_CASE(thrust_run) { multi::array> A(100); +} + +return boost::report_errors(); + } \ No newline at end of file diff --git a/external_codes/boost_multi/multi/include/boost/multi/adaptors/thrust/test/universal.cu b/external_codes/boost_multi/multi/include/boost/multi/adaptors/thrust/test/universal.cu index ad2402752d..d9178a4aa7 100644 --- a/external_codes/boost_multi/multi/include/boost/multi/adaptors/thrust/test/universal.cu +++ b/external_codes/boost_multi/multi/include/boost/multi/adaptors/thrust/test/universal.cu @@ -2,7 +2,7 @@ // Copyright 2023 Alfredo A. Correa #define BOOST_TEST_MODULE "C++ Unit Tests for Multi CUDA thrust universal" -#include +// #include #include @@ -17,6 +17,11 @@ namespace multi = boost::multi; +#include +#define BOOST_AUTO_TEST_CASE(CasenamE) /**/ + +auto main() -> int { // NOLINT(readability-function-cognitive-complexity,bugprone-exception-escape) + BOOST_AUTO_TEST_CASE(thrust_universal_ptr) { multi::array Host({1024, 1024}); std::iota(Host.data_elements(), Host.data_elements() + Host.num_elements(), 12.0); @@ -28,12 +33,12 @@ BOOST_AUTO_TEST_CASE(thrust_universal_ptr) { multi::array Hos2({1024, 1024}); Hos2({0, 10}, {0, 20}) = Univ({0, 10}, {0, 20}); - BOOST_REQUIRE( Hos2[0][0] == 12.0 ); + BOOST_TEST( Hos2[0][0] == 12.0 ); } BOOST_AUTO_TEST_CASE(thrust_universal_ptr_initializer_list) { multi::array Host = {1.0, 2.0, 3.0}; - BOOST_REQUIRE( Host.size() == 3 ); + BOOST_TEST( Host.size() == 3 ); { multi::array> Univ(multi::extensions_t<1>{3}); Univ[0] = 3.0; @@ -42,7 +47,7 @@ BOOST_AUTO_TEST_CASE(thrust_universal_ptr_initializer_list) { Host() = Univ(); - BOOST_REQUIRE( Host[0] == 3.0 ); + BOOST_TEST( Host[0] == 3.0 ); } { multi::array tmp = {3.0, 2.0, 1.0,}; @@ -51,7 +56,7 @@ BOOST_AUTO_TEST_CASE(thrust_universal_ptr_initializer_list) { Host() = Univ(); - BOOST_REQUIRE( Host[0] == 3.0 ); + BOOST_TEST( Host[0] == 3.0 ); } { multi::array tmp = {3.0, 2.0, 1.0,}; @@ -59,14 +64,14 @@ BOOST_AUTO_TEST_CASE(thrust_universal_ptr_initializer_list) { Host() = Univ(); - BOOST_REQUIRE( Host[0] == 3.0 ); + BOOST_TEST( Host[0] == 3.0 ); } { multi::array> Univ = {3.0, 2.0, 1.0,}; Host() = Univ(); - BOOST_REQUIRE( Host[0] == 3.0 ); + BOOST_TEST( Host[0] == 3.0 ); } // what( thrust::cuda::universal_allocator{} ); // { @@ -74,7 +79,10 @@ BOOST_AUTO_TEST_CASE(thrust_universal_ptr_initializer_list) { // Host() = Univ(); -// BOOST_REQUIRE( Host[0] == 3. ); +// BOOST_TEST( Host[0] == 3. ); // } } +return boost::report_errors(); + +} \ No newline at end of file diff --git a/external_codes/boost_multi/multi/include/boost/multi/adaptors/thrust/test/vector.cu b/external_codes/boost_multi/multi/include/boost/multi/adaptors/thrust/test/vector.cu index aab63e4197..dfd2d2d145 100644 --- a/external_codes/boost_multi/multi/include/boost/multi/adaptors/thrust/test/vector.cu +++ b/external_codes/boost_multi/multi/include/boost/multi/adaptors/thrust/test/vector.cu @@ -1,9 +1,13 @@ #define BOOST_TEST_MODULE "C++ Unit Tests for Multi CUDA thrust" -#include #include #include +#include +#define BOOST_AUTO_TEST_CASE(CasenamE) /**/ + +auto main() -> int { // NOLINT(readability-function-cognitive-complexity,bugprone-exception-escape) + BOOST_AUTO_TEST_CASE(vector){ // H has storage for 4 integers thrust::host_vector H(4); @@ -15,15 +19,15 @@ BOOST_AUTO_TEST_CASE(vector){ H[3] = 46; // H.size() returns the size of vector H - BOOST_TEST_REQUIRE( H.size() == 4 ); + BOOST_TEST( H.size() == 4 ); // print contents of H - BOOST_TEST_REQUIRE( H[2] == 38 ); + BOOST_TEST( H[2] == 38 ); // resize H H.resize(2); - BOOST_REQUIRE( H.size() == 2 ); + BOOST_TEST( H.size() == 2 ); // Copy host_vector H to device_vector D thrust::device_vector D = H; @@ -36,7 +40,11 @@ BOOST_AUTO_TEST_CASE(vector){ // thurst::device_ptr p = D.data(); // doesn't work with CUDA 11.8 thrust::cuda::pointer p = D.data(); // this works with thrust from CUDA 12.1 - BOOST_REQUIRE( p[0] == 99 ); + BOOST_TEST( p[0] == 99 ); + + BOOST_TEST( D[1] == 88 ); +} + +return boost::report_errors(); - BOOST_TEST_REQUIRE( D[1] == 88 ); } diff --git a/external_codes/boost_multi/multi/include/boost/multi/algorithms/gemm.hpp b/external_codes/boost_multi/multi/include/boost/multi/algorithms/gemm.hpp index 460ca467e9..a3e762859b 100644 --- a/external_codes/boost_multi/multi/include/boost/multi/algorithms/gemm.hpp +++ b/external_codes/boost_multi/multi/include/boost/multi/algorithms/gemm.hpp @@ -4,7 +4,7 @@ // this header contains a generic gemm algorithm (not the blas one) // it is ~3 times slower than blas::gemm but it is more generic in the type and in the operations -// when compiled using -DCMAKE_CXX_FLAGS_RELEASE="-Ofast -DNDEBUG -mfpmath=sse -march=native -funroll-loops -fargument-noalias" +// when compiled using -DCMAKE_CXX_FLAGS_RELEASE="-Ofast -DNDEBUG -mfpmath=sse -march=native -funroll-loops" #ifndef BOOST_MULTI_ALGORITHM_GEMM_HPP #define BOOST_MULTI_ALGORITHM_GEMM_HPP diff --git a/external_codes/boost_multi/multi/include/boost/multi/algorithms/redux.hpp b/external_codes/boost_multi/multi/include/boost/multi/algorithms/redux.hpp new file mode 100644 index 0000000000..ec2b20436f --- /dev/null +++ b/external_codes/boost_multi/multi/include/boost/multi/algorithms/redux.hpp @@ -0,0 +1,16 @@ +// Copyright 2024 Alfredo A. Correa +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#ifndef BOOST_MULTI_ALGORITHM_REDUX_HPP +#define BOOST_MULTI_ALGORITHM_REDUX_HPP + +// #include // for par // needs linking to TBB library +// #include // for inner_product and transform_reduce + +namespace boost::multi { + + +} // end namespace boost::multi + +#endif // BOOST_MULTI_ALGORITHM_GEMM_HPP diff --git a/external_codes/boost_multi/multi/include/boost/multi/array.hpp b/external_codes/boost_multi/multi/include/boost/multi/array.hpp index 626f3bc1a5..cf13c2ab20 100644 --- a/external_codes/boost_multi/multi/include/boost/multi/array.hpp +++ b/external_codes/boost_multi/multi/include/boost/multi/array.hpp @@ -5,13 +5,13 @@ #ifndef BOOST_MULTI_ARRAY_HPP_ #define BOOST_MULTI_ARRAY_HPP_ -#include +#include // IWYU pragma: export #include #include +#include #include -#include #include // for std::allocator_traits #include // needed by a deprecated function @@ -50,7 +50,7 @@ struct array_allocator { using pointer_ = typename allocator_traits::pointer; protected: - constexpr auto alloc() & -> allocator_type& { return alloc_; } + constexpr auto alloc() & -> auto& { return alloc_; } constexpr auto alloc() const& -> allocator_type const& { return alloc_; } constexpr explicit array_allocator(allocator_type const& alloc) : alloc_{alloc} {} // NOLINT(modernize-pass-by-value) @@ -65,6 +65,7 @@ struct array_allocator { constexpr auto uninitialized_fill_n(pointer_ first, size_type_ count, typename allocator_traits::value_type const& value) { return adl_alloc_uninitialized_fill_n(alloc_, first, count, value); } + template auto uninitialized_copy_n(It first, size_type count, pointer_ d_first) { #if defined(__clang__) && defined(__CUDACC__) @@ -77,6 +78,18 @@ struct array_allocator { #endif } + template + auto uninitialized_move_n(It first, size_type count, pointer_ d_first) { + #if defined(__clang__) && defined(__CUDACC__) + if constexpr(! std::is_trivially_default_constructible_v::element_type> && ! multi::force_element_trivial_default_construction::element_type> ) { + adl_alloc_uninitialized_default_construct_n(alloc_, d_first, count); + } + return adl_copy_n( std::make_move_iterator(first), count, d_first); + #else + return adl_alloc_uninitialized_move_n(alloc_, first , count, d_first); + #endif + } + template auto uninitialized_copy_n(EP&& ep, It first, size_type count, pointer_ d_first) { // #if defined(__clang__) && defined(__CUDACC__) @@ -108,7 +121,7 @@ struct static_array // NOLINT(fuchsia-multiple-inheritance) : multiple inherita static_assert( std::is_same_v< std::remove_const_t::value_type>, - typename static_array::element + typename static_array::element_type > || std::is_same_v< @@ -148,8 +161,8 @@ struct static_array // NOLINT(fuchsia-multiple-inheritance) : multiple inherita return adl_alloc_uninitialized_value_construct_n(static_array::alloc(), this->base_, this->num_elements()); } - auto uninitialized_default_construct() { - if constexpr(!std::is_trivially_default_constructible_v && ! multi::force_element_trivial_default_construction) { + constexpr auto uninitialized_default_construct() { + if constexpr(!std::is_trivially_default_constructible_v && ! multi::force_element_trivial_default_construction) { return adl_alloc_uninitialized_default_construct_n(static_array::alloc(), this->base_, this->num_elements()); } } @@ -158,12 +171,16 @@ struct static_array // NOLINT(fuchsia-multiple-inheritance) : multiple inherita return array_alloc::uninitialized_copy_n(first, this->num_elements(), this->data_elements()); } + template auto uninitialized_move_elements(It first) { + return array_alloc::uninitialized_move_n(first, this->num_elements(), this->data_elements()); + } + template auto uninitialized_copy_elements(EP&& ep, It first) { return array_alloc::uninitialized_copy_n(std::forward(ep), first, this->num_elements(), this->data_elements()); } constexpr void destroy() { - if constexpr(!(std::is_trivially_destructible_v || multi::force_element_trivial_destruction)) { + if constexpr(!(std::is_trivially_destructible_v || multi::force_element_trivial_destruction)) { array_alloc::destroy_n(this->data_elements(), this->num_elements()); } } @@ -175,8 +192,8 @@ struct static_array // NOLINT(fuchsia-multiple-inheritance) : multiple inherita public: using value_type = typename std::conditional_t< (D > 1), // this parenthesis is needed - array, - typename static_array::element>; + array, + typename static_array::element_type>; using typename ref::difference_type; using typename ref::size_type; @@ -191,11 +208,19 @@ struct static_array // NOLINT(fuchsia-multiple-inheritance) : multiple inherita using ref::dropped; constexpr auto dropped(difference_type n) && -> decltype(auto) { return ref::dropped(n).element_moved(); } - static_array(static_array&& other) noexcept : static_array{other.element_moved()} {} + static_array(static_array&& other) noexcept : + array_alloc{other.alloc()}, + ref{ + array_alloc::allocate(static_cast::size_type>(other.num_elements())), + other.extensions() + } + { + uninitialized_move_elements(other.data_elements()); + } constexpr static_array(decay_type&& other, allocator_type const& alloc) noexcept - : array_alloc{alloc}, ref{std::exchange(other.base_, nullptr), other.extensions()} { - std::move(other).layout_mutable() = {}; + : array_alloc{alloc}, ref(std::exchange(other.base_, nullptr), other.extensions()) { + std::move(other).layout_mutable() = typename static_array::layout_type(typename static_array::extensions_type{}); // = {}; careful! this is the place where layout can become invalid } constexpr explicit static_array(decay_type&& other) noexcept @@ -204,9 +229,8 @@ struct static_array // NOLINT(fuchsia-multiple-inheritance) : multiple inherita template>::difference_type> constexpr explicit static_array(It first, It last, allocator_type const& alloc) : array_alloc{alloc}, ref{ - array_alloc::allocate(static_cast::size_type>(layout_type{index_extension{adl_distance(first, last)} * multi::extensions(*first)}.num_elements())), - index_extension{adl_distance(first, last)} * multi::extensions(*first)} { - if(adl_distance(first, last) == 0) {return;} + array_alloc::allocate(static_cast::size_type>(layout_type{index_extension(adl_distance(first, last)) * multi::extensions(*first)}.num_elements())), + index_extension(adl_distance(first, last)) * multi::extensions(*first)} { #if defined(__clang__) && defined(__CUDACC__) // TODO(correaa) add workaround for non-default constructible type and use adl_alloc_uninitialized_default_construct_n if constexpr(! std::is_trivially_default_constructible_v && ! multi::force_element_trivial_default_construction ) { @@ -224,7 +248,7 @@ struct static_array // NOLINT(fuchsia-multiple-inheritance) : multiple inherita template< class Range, class = std::enable_if_t>{}>, class = decltype(/*static_array*/ (std::declval().begin() - std::declval().end())), // instantiation of static_array here gives a compiler error in 11.0, partially defined type? - class = std::enable_if_t::value> + class = std::enable_if_t::value> // NOLINT(modernize-use-constraints) TODO(correaa) in C++20 > // cppcheck-suppress noExplicitConstructor ; because I want to use equal for lazy assigments form range-expressions // NOLINTNEXTLINE(runtime/explicit) static_array(Range const& rng) // NOLINT(google-explicit-constructor,hicpp-explicit-conversions) : to allow terse syntax @@ -251,7 +275,7 @@ struct static_array // NOLINT(fuchsia-multiple-inheritance) : multiple inherita #endif } - static_array(typename static_array::extensions_type extensions, typename static_array::element const& elem, allocator_type const& alloc) // 2 + static_array(typename static_array::extensions_type extensions, typename static_array::element_type const& elem, allocator_type const& alloc) // 2 : array_alloc{alloc}, ref{array_alloc::allocate(static_cast::size_type>(typename static_array::layout_t{extensions}.num_elements()), nullptr), extensions} { array_alloc::uninitialized_fill_n(this->data_elements(), static_cast::size_type>(this->num_elements()), elem); } @@ -266,11 +290,11 @@ struct static_array // NOLINT(fuchsia-multiple-inheritance) : multiple inherita template explicit static_array( Element const& elem, allocator_type const& alloc, - std::enable_if_t && (D == 0), int> /*dummy*/ = 0 // NOLINT(fuchsia-default-arguments-declarations) for classic sfinae, needed by MSVC? + std::enable_if_t && (D == 0), int> /*dummy*/ = 0 // NOLINT(fuchsia-default-arguments-declarations) for classic sfinae, needed by MSVC? ) : static_array(typename static_array::extensions_type{}, elem, alloc) {} - constexpr static_array(typename static_array::extensions_type exts, typename static_array::element const& elem) + constexpr static_array(typename static_array::extensions_type exts, typename static_array::element_type const& elem) : array_alloc{}, array_ref::template rebind_alloc>::pointer>( @@ -279,12 +303,16 @@ struct static_array // NOLINT(fuchsia-multiple-inheritance) : multiple inherita static_cast::size_type>(typename static_array::layout_t(exts).num_elements()) , nullptr ) - ) - { - array_alloc::uninitialized_fill_n(this->base(), static_cast::size_type>(this->num_elements()), elem); + ) { + if constexpr(! std::is_trivially_default_constructible_v) { + array_alloc::uninitialized_fill_n(this->base(), static_cast::size_type>(this->num_elements()), elem); + } else { // this workaround allows constexpr arrays for simple types + adl_fill_n(this->base(), static_cast::size_type>(this->num_elements()), elem); + } } - template().extensions()), std::enable_if_t, int> =0> + template().extensions()), + std::enable_if_t, int> =0> // NOLINT(modernize-use-constraints) TODO(correaa) for C++20 explicit static_array(typename static_array::index_extension const& extension, ValueType const& value, allocator_type const& alloc) // fill constructor : array_alloc{alloc}, ref(array_alloc::allocate(static_cast::size_type>(typename static_array::layout_t(extension*value.extensions()).num_elements())), extension*value.extensions()) { @@ -292,117 +320,159 @@ struct static_array // NOLINT(fuchsia-multiple-inheritance) : multiple inherita adl_fill_n(this->begin(), this->size(), value); // TODO(correaa) implement via .elements()? substitute with uninitialized version of fill, uninitialized_fill_n? } - template().extensions()), std::enable_if_t, int> =0> + template().extensions()), + std::enable_if_t, int> =0> // NOLINT(modernize-use-constraints) TODO(correaa) for C++20 explicit static_array(typename static_array::index_extension const& extension, ValueType const& value) // fill constructor : static_array(extension, value, allocator_type{}) {} - explicit static_array(typename static_array::extensions_type extensions, allocator_type const& alloc) + constexpr explicit static_array(typename static_array::extensions_type extensions, allocator_type const& alloc) : array_alloc{alloc}, ref(array_alloc::allocate(static_cast::size_type>(typename static_array::layout_t{extensions}.num_elements())), extensions) { uninitialized_default_construct(); + assert(this->stride() != 0); } - explicit static_array(typename static_array::extensions_type extensions) + constexpr explicit static_array(typename static_array::extensions_type extensions) : static_array(extensions, allocator_type{}) {} - template::element>{}>, - class = decltype(adl_copy(std::declval const&>().begin(), std::declval const&>().end(), std::declval()))> - constexpr static_array(multi::subarray const& other, allocator_type const& alloc) - : array_alloc{alloc}, ref(array_alloc::allocate(static_cast::size_type>(typename static_array::layout_t{other.extensions()}.num_elements())), other.extensions()) { - #if defined(__clang__) && defined(__CUDACC__) - if constexpr(! std::is_trivially_default_constructible_v && ! multi::force_element_trivial_default_construction ) { - adl_alloc_uninitialized_default_construct_n(static_array::alloc(), this->data_elements(), this->num_elements()); - } - adl_copy (other.begin(), other.end(), this->begin()); // TODO(correaa) implement via .elements() - #else - adl_uninitialized_copy(/*static_array::alloc()*/ other.begin(), other.end(), this->begin()); // TODO(correaa) implement via .elements() - #endif + template::element_type>{}>, + class = decltype(adl_copy(std::declval const&>().begin(), std::declval const&>().end(), std::declval()))> + constexpr static_array(multi::const_subarray const& other, allocator_type const& alloc) + : array_alloc{alloc}, + ref( + array_alloc::allocate(static_cast::size_type>(typename static_array::layout_t{other.extensions()}.num_elements())), + other.extensions() + ) { + // #if (defined(__clang__) && defined(__CUDACC__)) + // if constexpr(! std::is_trivially_default_constructible_v && ! multi::force_element_trivial_default_construction ) { + // adl_alloc_uninitialized_default_construct_n(static_array::alloc(), this->data_elements(), this->num_elements()); + // } + // adl_copy_n ( other.elements().begin(), this->num_elements(), this->data_elements()); + // #else + adl_alloc_uninitialized_copy_n(static_array::alloc(), other.elements().begin(), this->num_elements(), this->data_elements()); + // #endif } - template const&>().base()), T>, int> = 0, - class = decltype(adl_copy(std::declval const&>().begin(), std::declval const&>().end(), std::declval()))> - // cppcheck-suppress noExplicitConstructor // NOLINTNEXTLINE(runtime/explicit) - constexpr /*mplct*/ static_array(multi::subarray const& other) // NOLINT(google-explicit-constructor,hicpp-explicit-conversions) + template::element_type>{}>, + class = decltype(adl_copy(std::declval const&>().begin(), std::declval const&>().end(), std::declval()))> + constexpr static_array(multi::subarray&& other, allocator_type const& alloc) + : array_alloc{alloc}, + ref( + array_alloc::allocate(static_cast::size_type>(typename static_array::layout_t{other.extensions()}.num_elements())), + other.extensions() + ) { + adl_alloc_uninitialized_copy_n(static_array::alloc(), std::move(other).elements().begin(), this->num_elements(), this->data_elements()); + } + + template< + class TT, class EElementPtr, class LLayout, + std::enable_if_t< ! multi::detail::is_implicitly_convertible_v&>().base()), T>, int> = 0, + class = decltype(adl_copy(std::declval const&>().begin(), std::declval const&>().end(), std::declval())) + > + explicit static_array(multi::const_subarray const& other) : static_array(other, allocator_type{}) {} - template const&>().base()), T>, int> = 0, - class = decltype(adl_copy(std::declval const&>().begin(), std::declval const&>().end(), std::declval()))> - explicit static_array(multi::subarray const& other) + template< + class TT, class EElementPtr, class LLayout, + std::enable_if_t< multi::detail::is_implicitly_convertible_v const&>().base()), T>, int> = 0, + class = decltype(adl_copy(std::declval const&>().begin(), std::declval const&>().end(), std::declval())) + > + // cppcheck-suppress noExplicitConstructor // NOLINTNEXTLINE(runtime/explicit) + constexpr /*implicit*/ static_array(multi::const_subarray const& other) // NOLINT(google-explicit-constructor,hicpp-explicit-conversions) : static_array(other, allocator_type{}) {} - template&>().base()), T>, int> = 0, - class = decltype(adl_copy(std::declval&>().begin(), std::declval const&>().end(), std::declval()))> - // cppcheck-suppress noExplicitConstructor ; // NOLINTNEXTLINE(runtime/explicit) - /*mplct*/ static_array(multi::subarray& other) // NOLINT(google-explicit-constructor,hicpp-explicit-conversions) + template< + class TT, class EElementPtr, class LLayout, + std::enable_if_t< multi::detail::is_implicitly_convertible_v const&>().base()), T>, int> = 0, + class = decltype(adl_copy(std::declval const&>().begin(), std::declval const&>().end(), std::declval())) + > + // cppcheck-suppress noExplicitConstructor // NOLINTNEXTLINE(runtime/explicit) + constexpr /*implicit*/ static_array(multi::subarray&& other) // NOLINT(google-explicit-constructor,hicpp-explicit-conversions) + : static_array(std::move(other), allocator_type{}) {} + + constexpr static_array(multi::subarray const&& other) // NOLINT(google-explicit-constructor,hicpp-explicit-conversions) : static_array(other, allocator_type{}) {} - template&>().base()), T>, int> = 0, - class = decltype(adl_copy(std::declval&>().begin(), std::declval const&>().end(), std::declval()))> - explicit static_array(multi::subarray& other) + constexpr static_array(multi::const_subarray const&& other) // NOLINT(google-explicit-constructor,hicpp-explicit-conversions) : static_array(other, allocator_type{}) {} - template&&>().base()), T>, int> = 0, - class = decltype(adl_copy(std::declval&&>().begin(), std::declval const&>().end(), std::declval()))> - // cppcheck-suppress noExplicitConstructor ; // NOLINTNEXTLINE(runtime/explicit) - /*mplct*/ static_array(multi::subarray&& other) // NOLINT(google-explicit-constructor,hicpp-explicit-conversions) + constexpr static_array(multi::subarray&& other) // NOLINT(google-explicit-constructor,hicpp-explicit-conversions) : static_array(std::move(other), allocator_type{}) {} - template&&>().base()), T>, int> = 0, - class = decltype(adl_copy(std::declval&&>().begin(), std::declval const&>().end(), std::declval()))> - explicit static_array(multi::subarray&& other) - : static_array(std::move(other), allocator_type{}) {} + // template const&>().base()), T>, int> = 0, + // class = decltype(adl_copy(std::declval const&>().begin(), std::declval const&>().end(), std::declval()))> + // explicit static_array(multi::const_subarray const& other) + // : static_array(other, allocator_type{}) {} + + + + // template&&>().base()), T>, int> = 0, + // class = decltype(adl_copy(std::declval&&>().begin(), std::declval const&>().end(), std::declval()))> + // // cppcheck-suppress noExplicitConstructor ; // NOLINTNEXTLINE(runtime/explicit) + // /*mplct*/ static_array(multi::subarray&& other) // NOLINT(google-explicit-constructor,hicpp-explicit-conversions) + // : static_array(std::move(other), allocator_type{}) {} + + // template&&>().base()), T>, int> = 0, + // class = decltype(adl_copy(std::declval&&>().begin(), std::declval const&>().end(), std::declval()))> + // explicit static_array(multi::const_subarray&& other) + // : static_array(std::move(other), allocator_type{}) {} template&>().base()), T>, int> = 0> + std::enable_if_t&>().base()), T>, int> =0> // NOLINT(modernize-use-constraints) TODO(correaa) for C++20 // cppcheck-suppress noExplicitConstructor ; to allow terse syntax /*mplct*/ static_array(array_ref& other) // NOLINT(google-explicit-constructor,hicpp-explicit-conversions) : array_alloc{}, ref{array_alloc::allocate(static_cast::size_type>(other.num_elements())), other.extensions()} { static_array::uninitialized_copy_elements(other.data_elements()); } - template&>().base()), T>, int> = 0> + template&>().base()), T>, int> =0> // NOLINT(modernize-use-constraints) TODO(correaa) for C++20 explicit static_array(array_ref& other) // NOLINT(fuchsia-default-arguments-declarations) : array_alloc{}, ref{array_alloc::allocate(static_cast::size_type>(other.num_elements())), other.extensions()} { + assert(this->stride() != 0); static_array::uninitialized_copy_elements(other.data_elements()); } - template&&>().base()), T>, int> = 0> + template&&>().base()), T>, int> =0> // NOLINT(modernize-use-constraints) TODO(correaa) for C++20 // cppcheck-suppress noExplicitConstructor ; to allow terse syntax /*mplct*/ static_array(array_ref&& other) // NOLINT(google-explicit-constructor,hicpp-explicit-conversions) : array_alloc{}, ref{array_alloc::allocate(static_cast::size_type>(other.num_elements())), other.extensions()} { + assert(this->stride() != 0); static_array::uninitialized_copy_elements(std::move(other).data_elements()); } template&&>().base()), T>, int> = 0> + std::enable_if_t&&>().base()), T>, int> =0> // NOLINT(modernize-use-constraints) TODO(correaa) for C++20 explicit static_array(array_ref&& other) // NOLINT(fuchsia-default-arguments-declarations) : array_alloc{}, ref{array_alloc::allocate(static_cast::size_type>(other.num_elements())), other.extensions()} { + assert(this->stride() != 0); static_array::uninitialized_copy_elements(std::move(other).data_elements()); } template const&>().base()), T>, int> = 0> + std::enable_if_t const&>().base()), T>, int> =0> // NOLINT(modernize-use-constraints) TODO(correaa) for C++20 // cppcheck-suppress noExplicitConstructor ; to allow terse syntax /*mplct*/ static_array(array_ref const& other) // NOLINT(google-explicit-constructor,hicpp-explicit-conversions) : array_alloc{}, ref{array_alloc::allocate(static_cast::size_type>(other.num_elements())), other.extensions()} { + assert(this->stride() != 0); static_array::uninitialized_copy_elements(other.data_elements()); } template const&>().base()), T>, int> = 0> + std::enable_if_t const&>().base()), T>, int> =0> // NOLINT(modernize-use-constraints) TODO(correaa) for C++20 explicit static_array(array_ref const& other) // NOLINT(fuchsia-default-arguments-declarations) : array_alloc{}, - ref{ + ref( array_alloc::allocate(static_cast::size_type>(other.num_elements())), other.extensions() - } { + ) { + assert(this->stride() != 0); static_array::uninitialized_copy_elements(std::move(other).data_elements()); } @@ -419,54 +489,59 @@ struct static_array // NOLINT(fuchsia-multiple-inheritance) : multiple inherita other.extensions() } { + assert(this->stride() != 0); uninitialized_copy_elements(other.data_elements()); } - template, int> =0> + template, int> =0> // NOLINT(modernize-use-constraints) TODO(correaa) static_array(ExecutionPolicy&& policy, static_array const& other) : array_alloc{multi::allocator_traits::select_on_container_copy_construction(other.alloc())}, ref{array_alloc::allocate(static_cast::size_type>(other.num_elements()), other.data_elements()), extensions(other)} { + assert(this->stride() != 0); uninitialized_copy_elements(std::forward(policy), other.data_elements()); } // cppcheck-suppress noExplicitConstructor ; to allow assignment-like construction of nested arrays - static_array(std::initializer_list::value_type> values) + constexpr static_array(std::initializer_list::value_type> values) : static_array{array(values.begin(), values.end())} {} // construct all with default constructor and copy to special memory at the end static_array( std::initializer_list::value_type> values, allocator_type const& alloc ) - : static_array{static_array(values.begin(), values.end()), alloc} {} + : static_array{static_array(values.begin(), values.end()), alloc} { + assert(this->stride() != 0); + } template constexpr explicit static_array(TT (&array)[N]) // @SuppressWarnings(cpp:S5945) NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) : for backward compatibility // NOSONAR - : static_array(std::begin(array), std::end(array)) {} + : static_array(std::begin(array), std::end(array)) { + assert(this->stride() != 0); + } constexpr auto begin() const& -> typename static_array::const_iterator { return ref::begin(); } constexpr auto end() const& -> typename static_array::const_iterator { return ref::end(); } - constexpr auto begin() && -> typename static_array::iterator { return ref::begin(); } - constexpr auto end() && -> typename static_array::iterator { return ref::end(); } + constexpr auto begin() && -> typename static_array::move_iterator { return ref::begin(); } + constexpr auto end() && -> typename static_array::move_iterator { return ref::end(); } constexpr auto begin() & -> typename static_array::iterator { return ref::begin(); } constexpr auto end() & -> typename static_array::iterator { return ref::end(); } using ref::operator[]; - - BOOST_MULTI_HD constexpr auto operator[](index idx) const& -> typename static_array::const_reference { return ref::operator[](idx); } BOOST_MULTI_HD constexpr auto operator[](index idx) && -> decltype(auto) { - if constexpr(D == 1) { - return std::move(ref::operator[](idx)); - } else { - return ref::operator[](idx).moved(); - } // NOLINT(readability/braces) + return multi::move(ref::operator[](idx)); + // if constexpr(D == 1) { + // return std::move(ref::operator[](idx)); + // } else { + // return ref::operator[](idx).element_moved(); + // } // NOLINT(readability/braces) } - BOOST_MULTI_HD constexpr auto operator[](index idx) & -> typename static_array::reference { return ref::operator[](idx); } constexpr auto max_size() const noexcept { return static_cast(multi::allocator_traits::max_size(this->alloc())); } // TODO(correaa) divide by nelements in under-dimensions? protected: constexpr void deallocate() { + assert(this->stride() != 0); if(this->num_elements()) { multi::allocator_traits::deallocate(this->alloc(), this->base_, static_cast::size_type>(this->num_elements())); } @@ -474,7 +549,8 @@ struct static_array // NOLINT(fuchsia-multiple-inheritance) : multiple inherita void clear() noexcept { this->destroy(); deallocate(); - this->layout_mutable() = {}; + this->layout_mutable() = typename static_array::layout_type(typename static_array::extensions_type{}); + assert(this->stride() != 0); } template constexpr auto reindex(Indices... idxs) & -> static_array& { @@ -488,40 +564,46 @@ struct static_array // NOLINT(fuchsia-multiple-inheritance) : multiple inherita } public: - constexpr static_array() noexcept // decay_type&& other, allocator_type const& alloc) noexcept - : array_alloc{}, ref{nullptr, {}} { // other.extensions()} { - // std::move(other).layout_mutable() = {}; + constexpr static_array() noexcept + : array_alloc{}, ref(nullptr, typename static_array::extensions_type{}) { + assert(this->stride() != 0); + assert(this->size() == 0); } - // static_array() = default; #if __cplusplus >= 202002L || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L) constexpr #endif - ~static_array() /*noexcept*/ { + ~static_array() /*noexcept*/ { + assert(this->stride() != 0); destroy(); + assert(this->stride() != 0); deallocate(); } - using element_const_ptr = typename std::pointer_traits::template rebind; + using element_const_ptr = typename std::pointer_traits::template rebind; using element_move_ptr = multi::move_ptr; using reference = std::conditional_t< (D > 1), - subarray, + subarray, std::conditional_t< D == 1, typename std::iterator_traits::reference, - void>>; + void + > + >; using const_reference = std::conditional_t< (D > 1), - subarray, // TODO(correaa) should be const_reference, but doesn't work witn rangev3? + const_subarray, // TODO(correaa) should be const_reference, but doesn't work witn rangev3? std::conditional_t< D == 1, decltype(*std::declval()), - void>>; + void + > + >; using iterator = multi::array_iterator; - using const_iterator = multi::array_iterator; + using const_iterator = multi::array_iterator; friend auto get_allocator(static_array const& self) -> allocator_type { return self.get_allocator(); } @@ -536,8 +618,8 @@ struct static_array // NOLINT(fuchsia-multiple-inheritance) : multiple inherita constexpr auto base() & -> typename static_array::element_ptr { return ref::base(); } constexpr auto base() const& -> typename static_array::element_const_ptr { return typename static_array::element_const_ptr{ref::base()}; } - BOOST_MULTI_FRIEND_CONSTEXPR auto base(static_array& self) -> typename static_array::element_ptr { return self.base(); } - BOOST_MULTI_FRIEND_CONSTEXPR auto base(static_array const& self) -> typename static_array::element_const_ptr { return self.base(); } + // BOOST_MULTI_FRIEND_CONSTEXPR auto base(static_array& self) -> typename static_array::element_ptr { return self.base(); } + // BOOST_MULTI_FRIEND_CONSTEXPR auto base(static_array const& self) -> typename static_array::element_const_ptr { return self.base(); } constexpr auto origin() & -> typename static_array::element_ptr { return ref::origin(); } constexpr auto origin() const& -> typename static_array::element_const_ptr { return ref::origin(); } @@ -573,9 +655,10 @@ struct static_array // NOLINT(fuchsia-multiple-inheritance) : multiple inherita // friend constexpr auto unrotated(static_array & self) -> decltype(auto) {return self.unrotated();} // friend constexpr auto unrotated(static_array const& self) -> decltype(auto) {return self.unrotated();} - template - auto operator=(multi::subarray const& other) -> static_array& { + template + auto operator=(multi::const_subarray const& other) -> static_array& { ref::operator=(other); // TODO(correaa) : protect for self assigment + assert(this->stride() != 0); return *this; } auto operator=(static_array const& other) & -> static_array& { @@ -584,13 +667,27 @@ struct static_array // NOLINT(fuchsia-multiple-inheritance) : multiple inherita } // cert-oop54-cpp assert(other.extensions() == this->extensions()); adl_copy_n(other.data_elements(), other.num_elements(), this->data_elements()); + assert(this->stride() != 0); return *this; } + + #if defined(__clang__) + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wunknown-warning-option" + #pragma clang diagnostic ignored "-Wunsafe-buffer-usage" // TODO(correaa) use checked span + #endif + constexpr auto operator=(static_array&& other) noexcept -> static_array& { // lints (cppcoreguidelines-special-member-functions,hicpp-special-member-functions) assert(extensions(other) == static_array::extensions()); // NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay) : allow a constexpr-friendly assert adl_move(other.data_elements(), other.data_elements() + other.num_elements(), this->data_elements()); // there is no std::move_n algorithm + assert(this->stride() != 0); return *this; } + + #if defined(__clang__) + #pragma clang diagnostic pop + #endif + template auto operator=(static_array const& other) & -> static_array& { assert(extensions(other) == static_array::extensions()); @@ -608,7 +705,7 @@ struct static_array // NOLINT(fuchsia-multiple-inheritance) : multiple inherita } private: - void swap_(static_array& other) noexcept { operator()().swap(other()); } + void swap_(static_array& other) noexcept { operator()().swap(other()); assert(this->stride() != 0);} public: friend void swap(static_array& lhs, static_array& rhs) noexcept { @@ -620,7 +717,7 @@ template struct static_array // NOLINT(fuchsia-multiple-inheritance) : design : protected detail::array_allocator , public array_ref::allocator_type>::pointer> { - static_assert(std::is_same_v::value_type, typename static_array::element>, + static_assert(std::is_same_v::value_type, typename static_array::element_type>, "allocator value type must match array value type"); private: @@ -659,7 +756,7 @@ struct static_array // NOLINT using ref = array_ref::template rebind_alloc>::pointer>; auto uninitialized_value_construct() { - if constexpr(! std::is_trivially_default_constructible_v && ! multi::force_element_trivial_default_construction) { + if constexpr(! std::is_trivially_default_constructible_v && ! multi::force_element_trivial_default_construction) { return adl_alloc_uninitialized_value_construct_n(static_array::alloc(), this->base_, this->num_elements()); } } @@ -680,7 +777,7 @@ struct static_array // NOLINT } constexpr void destroy() { - if constexpr(!(std::is_trivially_destructible_v || multi::force_element_trivial_destruction)) { + if constexpr(!(std::is_trivially_destructible_v || multi::force_element_trivial_destruction)) { array_alloc::destroy_n(this->data_elements(), this->num_elements()); } } @@ -703,16 +800,27 @@ struct static_array // NOLINT using ref::operator==; using ref::operator!=; - static_array(typename static_array::extensions_type extensions, typename static_array::element const& elem, allocator_type const& alloc) // 2 - : array_alloc{alloc}, ref(static_array::allocate(typename static_array::layout_t{extensions}.num_elements()), extensions) { + static_array( + typename static_array::extensions_type const& extensions, + typename static_array::element const& elem, allocator_type const& alloc + ) + : array_alloc{ alloc }, + ref( + static_array::allocate( + static_cast::size_type>( + typename static_array::layout_t{ extensions }.num_elements() + ) + ), + extensions + ) { uninitialized_fill(elem); } static_array(typename static_array::element_type const& elem, allocator_type const& alloc) : static_array(typename static_array::extensions_type{}, elem, alloc) {} - template - explicit static_array(multi::subarray const& other, allocator_type const& alloc) + template + explicit static_array(multi::const_subarray const& other, allocator_type const& alloc) : array_alloc{alloc}, ref(static_array::allocate(other.num_elements()), extensions(other)) { assert(other.num_elements() <= 1); if(other.num_elements()) { @@ -744,7 +852,7 @@ struct static_array // NOLINT explicit static_array(multi::static_array const& other) : static_array(other, allocator_type{}) {} - auto uninitialized_fill(typename static_array::element const& elem) { + auto uninitialized_fill(typename static_array::element_type const& elem) { array_alloc::uninitialized_fill_n( this->base_, static_cast::size_type>(this->num_elements()), @@ -753,22 +861,22 @@ struct static_array // NOLINT } template - auto operator=(multi::subarray const& other) -> static_array& { + auto operator=(multi::const_subarray const& other) -> static_array& { adl_copy_n(other.base(), 1, this->base()); return *this; } static_array( typename static_array::extensions_type const& extensions, - typename static_array::element const& elem + typename static_array::element_type const& elem ) // 2 : array_alloc{}, ref(static_array::allocate(static_cast::size_type>(typename static_array::layout_t{extensions}.num_elements()), nullptr), extensions) { uninitialized_fill(elem); } - static_array() : static_array(multi::iextensions<0>{}) {} + static_array() : static_array(multi::iextensions<0>{}) {} // TODO(correaa) a noexcept will force a partially formed state for zero dimensional arrays - explicit static_array(typename static_array::element const& elem) + explicit static_array(typename static_array::element_type const& elem) : static_array(multi::iextensions<0>{}, elem) {} template // NOLINT #endif } - template{}>> + template> > // NOLINT(modernize-use-constraints) TODO(correaa) for C++20 explicit static_array(typename static_array::index_extension const& extension, ValueType const& value, allocator_type const& alloc) // 3 : static_array(extension * extensions(value), alloc) { + assert(this->stride() != 0); using std::fill; fill(this->begin(), this->end(), value); } - template{}>> + template >> // NOLINT(modernize-use-constraints) TODO(correaa) for C++20 explicit static_array(typename static_array::index_extension const& extension, ValueType const& value) // 3 // TODO(correaa) : call other constructor (above) : static_array(extension * extensions(value)) { + assert(this->stride() != 0); using std::fill; fill(this->begin(), this->end(), value); } explicit static_array(typename static_array::extensions_type const& extensions, allocator_type const& alloc) // 3 - : array_alloc{alloc}, ref{static_array::allocate(typename static_array::layout_t{extensions}.num_elements()), extensions} { + : array_alloc{alloc}, ref(static_array::allocate(typename static_array::layout_t{extensions}.num_elements()), extensions) { + assert(this->stride() != 0); uninitialized_value_construct(); } explicit static_array(typename static_array::extensions_type const& extensions) // 3 - : static_array(extensions, allocator_type{}) {} + : static_array(extensions, allocator_type{}) { + assert(this->stride() != 0); + } static_array(static_array const& other, allocator_type const& alloc) // 5b - : array_alloc{alloc}, ref{static_array::allocate(other.num_elements()), extensions(other)} { + : array_alloc{alloc}, ref(static_array::allocate(other.num_elements()), extensions(other)) { + assert(this->stride() != 0); uninitialized_copy_(other.data_elements()); } static_array(static_array const& other) // 5b : array_alloc{other.get_allocator()}, ref{static_array::allocate(other.num_elements(), other.data_elements()), {}} { + assert(this->stride() != 0); uninitialized_copy(other.data_elements()); } static_array(static_array&& other) noexcept // it is private because it is a valid operation for derived classes //5b : array_alloc{other.get_allocator()}, ref{static_array::allocate(static_cast::size_type>(other.num_elements()), other.data_elements()), other.extensions()} { + assert(this->stride() != 0); uninitialized_move(std::move(other).data_elements()); } // template static auto distance(It a, It b) {using std::distance; return distance(a, b);} @@ -840,7 +958,7 @@ struct static_array // NOLINT this->destroy(); deallocate(); } - using element_const_ptr = typename std::pointer_traits::template rebind; + using element_const_ptr = typename std::pointer_traits::template rebind; BOOST_MULTI_FRIEND_CONSTEXPR auto get_allocator(static_array const& self) -> allocator_type { return self.get_allocator(); } @@ -869,19 +987,19 @@ struct static_array // NOLINT } constexpr auto rotated() const& { - typename static_array::layout_t new_layout = *this; + typename static_array::layout_t new_layout = this->layout(); new_layout.rotate(); return subarray{new_layout, this->base_}; } constexpr auto rotated() & { - typename static_array::layout_t new_layout = *this; + typename static_array::layout_t new_layout = this->layout(); new_layout.rotate(); return subarray{new_layout, this->base_}; } constexpr auto rotated() && { - typename static_array::layout_t new_layout = *this; + typename static_array::layout_t new_layout = this->layout(); new_layout.rotate(); return subarray{new_layout, this->base_}; } @@ -923,13 +1041,24 @@ struct static_array // NOLINT constexpr auto equal_extensions_if_(std::false_type /*false*/, static_array const& /*other*/) { return true; } public: + #if defined(__clang__) + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wunknown-warning-option" + #pragma clang diagnostic ignored "-Wunsafe-buffer-usage" + #endif + constexpr auto operator=(static_array&& other) noexcept -> static_array& { assert(equal_extensions_if_(std::integral_constant{}, other)); // NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay) : allow a constexpr-friendly assert adl_move(other.data_elements(), other.data_elements() + other.num_elements(), this->data_elements()); // there is no std::move_n algorithm return *this; } - template{}>> + #if defined(__clang__) + #pragma clang diagnostic pop + #endif + + template{}>> // NOLINT(modernize-use-constraints) TODO(correaa) for C++20 auto operator=(static_array const& other) & -> static_array& { assert(extensions(other) == static_array::extensions()); adl_copy_n(other.data_elements(), other.num_elements(), this->data_elements()); @@ -973,11 +1102,12 @@ struct array : static_array { } #endif - template>{}, int> /*dummy*/ = 0> + template>{}, int> =0> // NOLINT(modernize-use-constraints) TODO(correaa) for C++20 auto operator=(Other const& other) -> array& { this->assign(&other); return *this; - } // NOLINT(google-runtime-operator) allow assigment from other ranges + } auto reextent(typename array::extensions_type const& /*empty_extensions*/) -> array& { return *this; @@ -991,6 +1121,7 @@ struct array : static_array { template struct array : static_array { + ~array() = default; using static_ = static_array; static_assert( std::is_same_v< @@ -1012,7 +1143,7 @@ struct array : static_array { // NOLINTNEXTLINE(runtime/operator) BOOST_MULTI_HD constexpr auto operator&() const& -> array const* { return this; } // NOLINT(google-runtime-operator) //NOSONAR delete operator&& defined in base class to avoid taking address of temporary - friend auto sizes(array const& self) -> typename array::sizes_type { return self.sizes(); } + // friend auto sizes(array const& self) -> typename array::sizes_type { return self.sizes(); } template> void serialize(Archive& arxiv, unsigned int const version) { @@ -1037,16 +1168,16 @@ struct array : static_array { class = decltype(Range{std::declval(), std::declval()}) > constexpr explicit operator Range() const { - // vvv Range{...} needed by Windows GCC? - return Range{this->begin(), this->end()}; // NOLINT(fuchsia-default-arguments-calls) e.g. std::vector(it, it, alloc = {}) + // vvv Range{...} needed by Windows GCC? + return Range{this->begin(), this->end()}; // NOLINT(fuchsia-default-arguments-calls) e.g. std::vector(it, it, alloc = {}) } // move this to static_array - template, int> = 0> + template, int> =0> // NOLINT(modernize-use-constraints) TODO(correaa) for C++20 constexpr explicit operator TTN const&() const& { return this->template to_carray_(); } - template, int> = 0> + template, int> =0> // NOLINT(modernize-use-constraints) TODO(correaa) for C++20 constexpr explicit operator TTN&() && { return this->template to_carray_(); } - template, int> = 0> + template, int> =0> // NOLINT(modernize-use-constraints) TODO(correaa) for C++20 constexpr explicit operator TTN&() & { return this->template to_carray_(); } // NOLINTNEXTLINE(cppcoreguidelines-rvalue-reference-param-not-moved) false positive in clang-tidy 17 ? @@ -1055,18 +1186,24 @@ struct array : static_array { #ifdef _MSC_VER array(typename array::extensions_type exts, typename array::allocator_type const& alloc) - : static_array(exts, alloc) {} + : static_array(exts, alloc) {assert(this->stride() != 0);} + array(typename array::extensions_type exts) - : static_array(exts) {} + : static_array(exts) {assert(this->stride() != 0);} #endif // cppcheck-suppress noExplicitConstructor ; to allow assignment-like construction of nested arrays constexpr array(std::initializer_list::value_type> ilv) - : static_{array(ilv.begin(), ilv.end())} {} + : static_{array(ilv.begin(), ilv.end())} { + assert(this->stride() != 0); + } - template::value_type, OtherT> && !std::is_convertible_v::value_type> && (D == 1)>> + template::value_type, OtherT> && !std::is_convertible_v::value_type> && (D == 1)>> // NOLINT(modernize-use-constraints) TODO(correaa) for C++20 constexpr explicit array(std::initializer_list ilv) // NOLINT(google-explicit-constructor,hicpp-explicit-conversions) inherit explicitness of conversion from the elements - : static_{array(ilv.begin(), ilv.end()).element_transformed([](auto const& elem) noexcept { return static_cast(elem); })} {} // TODO(correaa) investigate why noexcept is necessary + : static_{array(ilv.begin(), ilv.end()).element_transformed([](auto const& elem) noexcept { return static_cast(elem); })} { + assert(this->stride() != 0); + } // TODO(correaa) investigate why noexcept is necessary array() = default; array(array const&) = default; @@ -1075,11 +1212,13 @@ struct array : static_array { typename array::layout_t const new_layout{extensions}; // TODO(correaa) implement move-reextent in terms of reshape assert(new_layout.num_elements() == this->num_elements()); this->layout_mutable() = new_layout; + assert(this->stride() != 0); return *this; } auto clear() noexcept -> array& { static_::clear(); + assert(this->stride() != 0); return *this; } friend auto clear(array& self) noexcept -> array& { return self.clear(); } @@ -1088,19 +1227,29 @@ struct array : static_array { BOOST_MULTI_FRIEND_CONSTEXPR auto data_elements(array& self) { return self.data_elements(); } BOOST_MULTI_FRIEND_CONSTEXPR auto data_elements(array&& self) { return std::move(self).data_elements(); } - auto move() & -> subarray> { - subarray> - ret = multi::static_array_cast>(*this); - layout_t:: operator=({}); - return ret; + // auto move() & -> subarray> { + // subarray> + // ret = multi::static_array_cast>(*this); + + // layout_t::operator=({}); + + // assert(this->stride() != 0); + // return ret; + // } + // friend auto move(array& self) -> subarray> { + // return self.move(); + // } + + friend BOOST_MULTI_HD constexpr auto move(array& self) -> decltype(auto) { return std::move(self); } + friend BOOST_MULTI_HD constexpr auto move(array&& self) -> decltype(auto) { return std::move(self); } + + array(array&& other, typename array::allocator_type const& alloc) noexcept : static_array{std::move(other), alloc} { + assert(this->stride() != 0); } - friend auto move(array& self) -> subarray> { - return self.move(); + array(array&& other) noexcept : array{std::move(other), other.get_allocator()} { + assert(this->stride() != 0); } - array(array&& other, typename array::allocator_type const& alloc) noexcept : static_array{std::move(other), alloc} {} - array(array&& other) noexcept : array{std::move(other), other.get_allocator()} {} - friend auto get_allocator(array const& self) -> typename array::allocator_type { return self.get_allocator(); } void swap(array& other) noexcept { @@ -1113,6 +1262,7 @@ struct array : static_array { this->layout_mutable(), other.layout_mutable() ); + assert(this->stride() != 0); } #ifndef NOEXCEPT_ASSIGNMENT @@ -1125,7 +1275,9 @@ struct array : static_array { if constexpr(multi::allocator_traits::propagate_on_container_move_assignment::value) { this->alloc() = std::move(other.alloc()); } - this->layout_mutable() = std::exchange(other.layout_mutable(), {}); + this->layout_mutable() = std::exchange(other.layout_mutable(), typename array::layout_type(typename array::extensions_type{})); + assert(this->stride() != 0); + assert(other.stride() != 0); return *this; } @@ -1147,14 +1299,15 @@ struct array : static_array { array::allocate(); array::uninitialized_copy_elements(other.data_elements()); } + assert(this->stride() != 0); return *this; } #else auto operator=(array o) noexcept -> array& { return swap(o), *this; } #endif - template - auto operator=(multi::subarray const& other) -> array& { + template + auto operator=(multi::const_subarray const& other) -> array& { if(array::extensions() == other.extensions()) { static_::operator=(other); // TODO(correaa) : protect for self assigment } else { @@ -1175,6 +1328,7 @@ struct array : static_array { } else { operator=(static_cast(other)); } + assert(this->stride() != 0); return *this; } @@ -1182,15 +1336,16 @@ struct array : static_array { class Range, class = decltype(std::declval().operator=(std::declval())), std::enable_if_t>::value, int> = 0, - std::enable_if_t>{}, int> = 0> + std::enable_if_t>::value, int> = 0, + std::enable_if_t>{}, int> = 0> // NOLINT(modernize-use-constraints) TODO(correaa) auto operator=(Range&& other) -> array& { // TODO(correaa) : check that LHS is not read-only? if(array::extensions() == other.extensions()) { - this->operator()() = other; + this->operator()() = std::forward(other); // static_::operator=(other); } else if(this->num_elements() == other.extensions().num_elements()) { reshape(other.extensions()); // static_::operator=(other); - this->operator()() = other; + this->operator()() = std::forward(other); } else { operator=(static_cast(std::forward(other))); } @@ -1200,7 +1355,7 @@ struct array : static_array { template< class Range, class = decltype(std::declval().operator=(std::declval())), - std::enable_if_t>{}, int> = 0> + std::enable_if_t>{}, int> =0> // NOLINT(modernize-use-constraints) TODO(correaa) for C++20 auto from(Range&& other) -> array& { // TODO(correaa) : check that LHS is not read-only? if(array::extensions() == other.extensions()) { this->operator()() = other; @@ -1217,7 +1372,7 @@ struct array : static_array { friend void swap(array& self, array& other) noexcept(true /*noexcept(self.swap(other))*/) { self.swap(other); } - void assign(typename array::extensions_type extensions, typename array::element const& elem) { + void assign(typename array::extensions_type extensions, typename array::element_type const& elem) { if(array::extensions() == extensions) { adl_fill_n(this->base_, this->num_elements(), elem); } else { @@ -1266,12 +1421,12 @@ struct array : static_array { this->deallocate(); this->layout_mutable() = typename array::layout_t{extensions}; this->base_ = this->static_::array_alloc::allocate( - static_cast::size_type>( - typename array::layout_t{extensions}.num_elements() - ), - this->data_elements() // used as hint - ); - if constexpr(!(std::is_trivially_default_constructible_v || multi::force_element_trivial_default_construction)) { + static_cast::size_type>( + typename array::layout_t{extensions}.num_elements() + ), + this->data_elements() // used as hint + ); + if constexpr(!(std::is_trivially_default_constructible_v || multi::force_element_trivial_default_construction)) { adl_alloc_uninitialized_value_construct_n(this->alloc(), this->base_, this->num_elements()); } return std::move(*this); @@ -1290,7 +1445,7 @@ struct array : static_array { ), extensions ); - if constexpr(!(std::is_trivially_default_constructible_v || multi::force_element_trivial_default_construction)) { + if constexpr(!(std::is_trivially_default_constructible_v || multi::force_element_trivial_default_construction)) { adl_alloc_uninitialized_value_construct_n(this->alloc(), tmp.data_elements(), tmp.num_elements()); } auto const is = intersection(this->extensions(), extensions); @@ -1302,26 +1457,10 @@ struct array : static_array { return *this; } - constexpr auto operator+() const& { return array{*this}; } - constexpr auto operator+() && { return array{std::move(*this)}; } - - // auto reextent(typename array::extensions_type const& extensions, typename array::element const& elem) && -> array&& { - // if(extensions == this->extensions()) {return std::move(*this);} - // this->destroy(); - // this->deallocate(); - // this->layout_mutable() = typename array::layout_t{extensions}; - // this->base_ = this->static_::array_alloc::allocate( - // static_cast::size_type>( - // typename array::layout_t{extensions}.num_elements() - // ), - // this->data_elements() // used as hint - // ); - // this->uninitialized_fill_n(this->base_, static_cast::size_type>(this->num_elements()), elem); + [[nodiscard]] constexpr auto operator+() const& { return array{*this}; } + [[nodiscard]] constexpr auto operator+() && { return array{*this}; } - // return std::move(*this); - // } - - auto reextent(typename array::extensions_type const& exs, typename array::element const& elem) & -> array& { + auto reextent(typename array::extensions_type const& exs, typename array::element_type const& elem) & -> array& { if(exs == this->extensions()) { return *this; } @@ -1359,7 +1498,9 @@ struct array : static_array { return *this; } - ~array() = default; + // ~array() { + // assert(this->stride() != 0); + // } }; #if defined(__cpp_deduction_guides) @@ -1396,11 +1537,24 @@ template>> array(iex template>> array(iextensions, T) -> array; -template +template array(MatrixRef) -> array; template array(subarray) -> array; +template< + class Range, + std::enable_if_t::value, int> = 0, + typename V = decltype(*::std::begin(std::declval())) + // typename V = typename std::iterator_traits()))>::value_type +> +array(Range) -> array; + +template +auto operator+(Reference&& ref) +->decltype(array(std::forward(ref))) { + return array(std::forward(ref)); } + #endif // ends defined(__cpp_deduction_guides) template @@ -1434,20 +1588,24 @@ struct [[deprecated("no PMR allocator")]] array; // your version of C++ doesn't // common_reference for compatibility with ranges #if defined(__cpp_lib_common_reference) || defined(__cpp_lib_ranges) // TODO(correaa) achieve this by normal inheritance -template struct std::common_reference::basic_const_array &&, ::boost::multi::array &> { using type = typename ::boost::multi::array::basic_const_array &&; }; -template struct std::common_reference::basic_const_array &&, ::boost::multi::array const&> { using type = typename ::boost::multi::array::basic_const_array &&; }; -template struct std::common_reference< ::boost::multi::array &, typename ::boost::multi::array::basic_const_array &&> { using type = typename ::boost::multi::array::basic_const_array &&; }; -template struct std::common_reference< ::boost::multi::array const&, typename ::boost::multi::array::basic_const_array &&> { using type = typename ::boost::multi::array::basic_const_array &&; }; -template struct std::common_reference::basic_const_array , ::boost::multi::array &> { using type = typename ::boost::multi::array::basic_const_array ; }; -template struct std::common_reference< ::boost::multi::array const&, typename ::boost::multi::array::basic_const_array const&> { using type = typename ::boost::multi::array::basic_const_array const&; }; -template struct std::common_reference::basic_const_array const&, ::boost::multi::array const&> { using type = typename ::boost::multi::array::basic_const_array const&; }; - -template struct std::common_reference::basic_const_array &, ::boost::multi::array &> { using type = typename ::boost::multi::array::basic_const_array &; }; -template struct std::common_reference< ::boost::multi::array &, typename ::boost::multi::array::basic_const_array &> { using type = typename ::boost::multi::array::basic_const_array &; }; +// NOLINTBEGIN(cert-dcl58-cpp) +// template struct std::common_reference::basic_const_array &&, ::boost::multi::array &> { using type = typename ::boost::multi::array::basic_const_array &&; }; +// template struct std::common_reference::basic_const_array &&, ::boost::multi::array const&> { using type = typename ::boost::multi::array::basic_const_array &&; }; +// template struct std::common_reference< ::boost::multi::array &, typename ::boost::multi::array::basic_const_array &&> { using type = typename ::boost::multi::array::basic_const_array &&; }; +// template struct std::common_reference< ::boost::multi::array const&, typename ::boost::multi::array::basic_const_array &&> { using type = typename ::boost::multi::array::basic_const_array &&; }; +// template struct std::common_reference::basic_const_array , ::boost::multi::array &> { using type = typename ::boost::multi::array::basic_const_array ; }; +// template struct std::common_reference< ::boost::multi::array const&, typename ::boost::multi::array::basic_const_array const&> { using type = typename ::boost::multi::array::basic_const_array const&; }; +// template struct std::common_reference::basic_const_array const&, ::boost::multi::array const&> { using type = typename ::boost::multi::array::basic_const_array const&; }; + +// template struct std::common_reference::basic_const_array &, ::boost::multi::array &> { using type = typename ::boost::multi::array::basic_const_array &; }; +// template struct std::common_reference< ::boost::multi::array &, typename ::boost::multi::array::basic_const_array &> { using type = typename ::boost::multi::array::basic_const_array &; }; +// NOLINTEND(cert-dcl58-cpp) #endif namespace boost::serialization { +template struct version; // in case serialization was not included before + template struct version> { using type = std::integral_constant; // TODO(correaa) use constexpr variable here, not macro diff --git a/external_codes/boost_multi/multi/include/boost/multi/array_ref.hpp b/external_codes/boost_multi/multi/include/boost/multi/array_ref.hpp index 6806b94442..26be6c7f28 100644 --- a/external_codes/boost_multi/multi/include/boost/multi/array_ref.hpp +++ b/external_codes/boost_multi/multi/include/boost/multi/array_ref.hpp @@ -6,15 +6,50 @@ #define BOOST_MULTI_ARRAY_REF_HPP_ #pragma once -#include -#include +#include +#include // IWYU pragma: export -#include -#include -#include // for pointer_traits -#include // for random_iterable +namespace boost::multi { + +template +inline constexpr bool force_element_trivial = false; + +template +inline constexpr bool force_element_trivial_destruction = force_element_trivial; + +template +inline constexpr bool force_element_trivial_default_construction = force_element_trivial; + +#ifdef _MULTI_FORCE_TRIVIAL_STD_COMPLEX +template +inline constexpr bool force_element_trivial> = std::is_trivial_v; + +template +inline constexpr bool force_element_trivial_destruction> = std::is_trivially_default_constructible_v; + +template +inline constexpr bool force_element_trivial_default_construction> = std::is_trivially_destructible_v; + +template<> inline constexpr bool force_element_trivial > = true; +template<> inline constexpr bool force_element_trivial_default_construction> = true; +template<> inline constexpr bool force_element_trivial_destruction > = true; + +template<> inline constexpr bool force_element_trivial > = true; +template<> inline constexpr bool force_element_trivial_default_construction> = true; +template<> inline constexpr bool force_element_trivial_destruction > = true; +#endif + +} // end namespace boost::multi + +#include // TODO(correaa) remove instantiation of force_element_trivial in this header +#include // IWYU pragma: export +#include // for pointer_traits +#include // for random_iterable +#include // IWYU pragma: export #include -#include // for dimensionality_type +#include // for dimensionality_type // IWYU pragma: export + +#include #include // fpr copy_n #include @@ -36,9 +71,9 @@ #include // for forward #if !defined(__NVCC__) - #define BOOST_MULTI_FRIEND_CONSTEXPR friend constexpr // this generates a problem with intel compiler 19 and v2021 "a constexpr function cannot have a nonliteral return type" + #define BOOST_MULTI_FRIEND_CONSTEXPR friend constexpr // this generates a problem with intel compiler 19 and v2021 "a constexpr function cannot have a nonliteral return type" #else - #define BOOST_MULTI_FRIEND_CONSTEXPR friend /*constexpr*/ + #define BOOST_MULTI_FRIEND_CONSTEXPR template friend constexpr // workaround nvcc #endif #if defined(__NVCC__) @@ -47,34 +82,59 @@ #define BOOST_MULTI_HD #endif +// #if defined(__APPLE__) && !defined(__clang__) /*&& defined(__aarch64__)*/ && defined(BOOST_UNIT_TEST_FRAMEWORK_DYN_LINK) +// #include +// #include +// #include +// auto boost::test_tools::tt_detail::print_log_value::operator()(std::ostream&, char) -> void {} +// auto boost::unit_test::test_unit::full_name() const -> std::string { return std::string{}; } +// auto boost::unit_test::ut_detail::normalize_test_case_name(boost::unit_test::basic_cstring name) -> std::string { +// return std::string(name.begin(), name.end()); +// } +// namespace boost::unit_test { +// // void make_test_case(boost::function const& f, boost::unit_test::basic_cstring, boost::unit_test::basic_cstring, unsigned long) { +// // f(); +// // } +// } +// #endif + namespace boost::multi { template> -struct subarray; +struct const_subarray; -template -constexpr auto is_subarray_aux(subarray const&) -> std::true_type; -constexpr auto is_subarray_aux(... ) -> std::false_type; +// template> +// using subarray = const_subarray; + +template::difference_type>> +class subarray; + +template::difference_type>> +class move_subarray; + +template +constexpr auto is_subarray_aux(const_subarray const&) -> std::true_type; +constexpr auto is_subarray_aux(... ) -> std::false_type; template struct is_subarray: decltype(is_subarray_aux(std::declval())) {}; // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg) template struct of_dim { -template -static constexpr auto is_subarray_of_dim_aux(subarray const&) -> std::true_type; -static constexpr auto is_subarray_of_dim_aux(... ) -> std::false_type; +template +static constexpr auto is_subarray_of_dim_aux(subarray const&) -> std::true_type; +static constexpr auto is_subarray_of_dim_aux(... ) -> std::false_type; template struct is_subarray_of_dim: decltype(is_subarray_of_dim_aux(std::declval())) {}; // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg) }; -template -constexpr auto home(Array&& arr) -->decltype(std::forward(arr).home()) { - return std::forward(arr).home(); } - template> struct array; -template> +template< + typename T, + dimensionality_type D, + typename ElementPtr = T*, + class Layout = layout_t::size_type> > +> struct array_types : private Layout { // cppcheck-suppress syntaxError ; false positive in cppcheck using element = T; using element_type = element; // this follows more closely https://en.cppreference.com/w/cpp/memory/pointer_traits @@ -89,19 +149,10 @@ struct array_types : private Layout { // cppcheck-suppress syntaxError ; false using rank = typename layout_t::rank; - using layout_t::rank_v; - - // using typename layout_t::dimensionality_type; // needed by MSVC - using dimensionality_type = typename layout_t::dimensionality_type; // needed by MSVC + using layout_t::rank_v; - using Layout::dimensionality; -// #else -// static constexpr auto dimensionality = layout_t::dimensionality; -// #endif - - // using layout_t::num_dimensions; - - [[deprecated("this is from BMA")]] static constexpr auto num_dimensions() {return dimensionality;} + using dimensionality_type = typename layout_t::dimensionality_type; + using layout_t::dimensionality; using typename layout_t::stride_type; using layout_t::stride ; @@ -116,10 +167,8 @@ struct array_types : private Layout { // cppcheck-suppress syntaxError ; false using typename layout_t::index_extension; using typename layout_t::strides_type; - // using layout_t::strides ; - auto strides() const { return convertible_tuple(layout_t::strides()); } - [[deprecated("BMA backward compatible")]] auto index_bases() const -> std::ptrdiff_t const*; // = delete; + auto strides() const { return detail::convertible_tuple(layout_t::strides()); } using typename layout_t::difference_type; @@ -144,7 +193,14 @@ struct array_types : private Layout { // cppcheck-suppress syntaxError ; false using typename layout_t::sizes_type; using layout_t::sizes; - [[deprecated("from BMA")]] constexpr auto shape() const {return convertible_tuple(this->sizes());} + [[deprecated("This is for compatiblity with Boost.MultiArray, you can use `rank` member type or `dimensionality` static member variable")]] + static constexpr auto num_dimensions() { return dimensionality; } + + [[deprecated("This is for compatiblity with Boost.MultiArray, you can use `offsets` member function")]] + auto index_bases() const -> std::ptrdiff_t const*; // = delete; this function is not implemented, it can give a linker error + + [[deprecated("This is for compatiblity with Boost.MultiArray, you can use `offsets` member function")]] + constexpr auto shape() const { return detail::convertible_tuple(this->sizes()); } using layout_t::is_compact; @@ -182,20 +238,23 @@ struct array_types : private Layout { // cppcheck-suppress syntaxError ; false using const_reference = typename std::conditional_t< (D > 1), - subarray, + const_subarray, typename std::iterator_traits::reference >; - BOOST_MULTI_HD constexpr auto base() & -> element_ptr {return base_;} - BOOST_MULTI_HD constexpr auto base() && -> element_ptr {return base_;} - BOOST_MULTI_HD constexpr auto base() const& -> element_const_ptr {return base_;} + // BOOST_MULTI_HD constexpr auto base() & -> element_ptr {return base_;} + // BOOST_MULTI_HD constexpr auto base() && -> element_ptr {return base_;} + // BOOST_MULTI_HD constexpr auto base() const& -> element_const_ptr {return base_;} + BOOST_MULTI_HD constexpr auto base() const -> element_const_ptr { return base_; } + + BOOST_MULTI_HD constexpr auto mutable_base() const -> element_ptr {return base_;} BOOST_MULTI_HD constexpr auto cbase() const -> element_const_ptr {return base_;} BOOST_MULTI_HD constexpr auto mbase() const& -> element_ptr& {return base_;} - friend /*constexpr*/ auto base(array_types & self) -> element_ptr {return self.base();} - friend /*constexpr*/ auto base(array_types && self) -> element_ptr {return std::move(self).base();} - friend /*constexpr*/ auto base(array_types const& self) -> element_const_ptr {return self.base();} + // friend /*constexpr*/ auto base(array_types & self) -> element_ptr {return self.base_;} + // friend /*constexpr*/ auto base(array_types && self) -> element_ptr {return std::move(self).base_;} + // friend /*constexpr*/ auto base(array_types const& self) -> element_const_ptr {return self.base_;} BOOST_MULTI_HD constexpr auto layout() const -> layout_t const& {return *this;} friend constexpr auto layout(array_types const& self) -> layout_t const& {return self.layout();} @@ -204,8 +263,10 @@ struct array_types : private Layout { // cppcheck-suppress syntaxError ; false friend constexpr auto origin(array_types const& self) -> decltype(auto) {return self.origin();} protected: + BOOST_MULTI_NO_UNIQUE_ADDRESS element_ptr base_; // NOLINT(cppcoreguidelines-non-private-member-variables-in-classes,misc-non-private-member-variables-in-classes) : TODO(correaa) try to make it private, [static_]array needs mutation - template friend struct array_iterator; + + template friend struct array_iterator; using derived = subarray; BOOST_MULTI_HD constexpr explicit array_types(std::nullptr_t) : Layout{}, base_(nullptr) {} @@ -228,7 +289,7 @@ struct array_types : private Layout { // cppcheck-suppress syntaxError ; false template< class ArrayTypes, - typename = std::enable_if_t>{}>, + typename = std::enable_if_t>{}>, decltype(multi::detail::implicit_cast(std::declval().base_))* = nullptr > // cppcheck-suppress noExplicitConstructor ; because underlying pointers are implicitly convertible @@ -246,134 +307,166 @@ struct array_types : private Layout { // cppcheck-suppress syntaxError ; false template friend struct array_types; }; -template +template +struct subarray_ptr; + +template > +using const_subarray_ptr = subarray_ptr; + +template, bool IsConst> struct subarray_ptr // NOLINT(fuchsia-multiple-inheritance) : to allow mixin CRTP -//: private Ref // TODO(correaa) : remove inheritance from Ref?? : boost::multi::iterator_facade< - subarray_ptr, void, std::random_access_iterator_tag, - Ref const&, typename Layout::difference_type -> { //, boost::multi::totally_ordered2, void> -private: - mutable Ref ref_; + subarray_ptr, void, std::random_access_iterator_tag, + subarray const&, typename Layout::difference_type +> { + private: + Layout layout_; + ElementPtr base_; + typename std::iterator_traits::difference_type offset_; + + public: + template friend struct subarray_ptr; + template friend struct array_iterator; -public: ~subarray_ptr() = default; // lints(cppcoreguidelines-special-member-functions,hicpp-special-member-functions) - using pointer = Ref const*; - using element_type = typename Ref::decay_type; + using pointer = subarray*; + using element_type = typename subarray::decay_type; using difference_type = typename Layout::difference_type; using value_type = element_type; - using reference = Ref; + + using reference = std::conditional_t< + IsConst, + const_subarray, + subarray>; + using iterator_category = std::random_access_iterator_tag; // cppcheck-suppress noExplicitConstructor - BOOST_MULTI_HD constexpr subarray_ptr(std::nullptr_t nil) : ref_{nil} {} // NOLINT(google-explicit-constructor,hicpp-explicit-conversions) terse syntax and functionality by default - BOOST_MULTI_HD constexpr subarray_ptr() : subarray_ptr{nullptr} {} // TODO(correaa) consider uninitialized ptr + BOOST_MULTI_HD constexpr subarray_ptr(std::nullptr_t nil) : layout_{}, base_{nil}, offset_{0} {} // NOLINT(google-explicit-constructor,hicpp-explicit-conversions) terse syntax and functionality by default + + subarray_ptr() = default; + + template friend struct subarray_ptr; - template friend struct subarray_ptr; + BOOST_MULTI_HD constexpr subarray_ptr(typename reference::element_ptr base, layout_t lyt) : layout_{lyt}, base_{base}, offset_{0} {} - BOOST_MULTI_HD constexpr subarray_ptr(typename Ref::element_ptr base, layout_t lyt) : ref_{lyt, base} {} - BOOST_MULTI_HD constexpr subarray_ptr(typename Ref::element_ptr base, index_extensions exts) : ref_{base, exts} {} + template = 0> // NOLINT(modernize-use-constraints) TODO(correaa) + BOOST_MULTI_HD constexpr/*mplct*/ subarray_ptr(subarray_ptr const& other) // NOLINT(google-explicit-constructor,hicpp-explicit-conversions) : propagate implicitness of pointer + : layout_{other.layout_}, base_{other.base_}, offset_{other.offset_} {} - template(std::declval()))* = nullptr + template< + typename OtherT, multi::dimensionality_type OtherD, typename OtherEPtr, class OtherLayout, bool OtherIsConst, + decltype(multi::detail::implicit_cast(std::declval()))* = nullptr > // cppcheck-suppress noExplicitConstructor ; because underlying pointer is implicitly convertible - BOOST_MULTI_HD constexpr/*mplct*/ subarray_ptr(subarray_ptr const& other) // NOLINT(google-explicit-constructor,hicpp-explicit-conversions) : propagate implicitness of pointer - : ref_(other->layout(), other->base()) {} + BOOST_MULTI_HD constexpr/*mplct*/ subarray_ptr(subarray_ptr const& other) // NOLINT(google-explicit-constructor,hicpp-explicit-conversions) : propagate implicitness of pointer + : layout_{other.layout_}, base_{other.base_} {} + + template< + class ElementPtr2, + std::enable_if_t && (D==0), int> =0 // NOLINT(modernize-use-constraints) TODO(correaa) for C++20 + > + BOOST_MULTI_HD constexpr explicit subarray_ptr(ElementPtr2 const& other) : layout_{}, base_{other} {} - template - // cppcheck-suppress noExplicitConstructor ; no information loss, allows comparisons - BOOST_MULTI_HD constexpr subarray_ptr(Array* other) // NOLINT(google-explicit-constructor,hicpp-explicit-conversions) - : subarray_ptr(other->data_elements(), other->layout()) {} + // template + // // cppcheck-suppress noExplicitConstructor ; no information loss, allows comparisons + // BOOST_MULTI_HD constexpr subarray_ptr(Array* other) // NOLINT(google-explicit-constructor,hicpp-explicit-conversions) + // : subarray_ptr(other->data_elements(), other->layout()) {} + // BOOST_MULTI_HD constexpr explicit subarray_ptr(subarray_ptr* other) + // : subarray_ptr(other->base(), other->layout()) {} - subarray_ptr(subarray_ptr const&) noexcept = default; + subarray_ptr(subarray_ptr const&) = default; subarray_ptr(subarray_ptr &&) noexcept = default; // TODO(correaa) remove inheritnace from reference to remove this move ctor - BOOST_MULTI_HD constexpr auto operator=(subarray_ptr const& other) noexcept -> subarray_ptr& { - if(this == std::addressof(other)) { // lints(cert-oop54-cpp) - return *this; - } - this->ref_.base_ = other.ref_.base_; - this->ref_.layout_mutable() = other.ref_.layout(); - return *this; - } + auto operator=(subarray_ptr const&) -> subarray_ptr& = default; + auto operator=(subarray_ptr &&) noexcept -> subarray_ptr& = default; - BOOST_MULTI_HD constexpr auto operator=(subarray_ptr&& other) noexcept // TODO(correaa) remove move constructor to remove this move assignment - -> subarray_ptr& { - if(this == std::addressof(other)) { // lints(cert-oop54-cpp) - return *this; - } - operator=(other); - return *this; - } + BOOST_MULTI_HD constexpr explicit operator bool() const { return static_cast(base()); } - BOOST_MULTI_HD constexpr explicit operator bool() const {return base();} + BOOST_MULTI_HD constexpr auto operator*() const -> reference { return reference(layout_, base_); } - BOOST_MULTI_HD constexpr auto dereference() const -> Ref {return Ref{this->layout(), this->base_};} + // [[deprecated("->() is experimental on msvc")]] + BOOST_MULTI_HD constexpr auto operator->() const { + // static_assert( sizeof(*this) == sizeof(reference) ); + class proxy { + reference ref_; - BOOST_MULTI_HD constexpr auto operator* () const -> Ref {return Ref{ref_};} + public: + BOOST_MULTI_HD constexpr explicit proxy(reference&& ref) : ref_{std::move(ref)} {} + BOOST_MULTI_HD constexpr auto operator->() && -> reference* {return std::addressof(this->ref_);} + }; + return proxy{operator*()}; + } - BOOST_MULTI_HD constexpr auto operator->() const -> Ref* {return std::addressof(ref_);} - // BOOST_MULTI_HD constexpr auto operator->() const -> Ref* {return const_cast(this);} // NOLINT(cppcoreguidelines-pro-type-const-cast) : TODO(correaa) find a better way without const_cast - // BOOST_MULTI_HD constexpr auto operator->() -> Ref* {return this;} + // BOOST_MULTI_HD constexpr auto operator->() -> reference* { + // return std::addressof(reinterpret_cast(*this)); + // } - BOOST_MULTI_HD constexpr auto operator[](difference_type n) const -> Ref {return *(*this + n);} + BOOST_MULTI_HD constexpr auto operator[](difference_type n) const -> reference { return *(*this + n); } - BOOST_MULTI_HD constexpr auto operator<(subarray_ptr const& other) const -> bool {return distance_to(other) > 0;} + BOOST_MULTI_HD constexpr auto operator<(subarray_ptr const& other) const -> bool { return distance_to(other) > 0; } - BOOST_MULTI_HD constexpr subarray_ptr(typename Ref::element_ptr base, Layout const& lyt) : ref_{lyt, base} {} + BOOST_MULTI_HD constexpr subarray_ptr(typename reference::element_ptr base, Layout const& lyt) : layout_{lyt}, base_{base} {} - template - friend struct subarray; + template friend struct const_subarray; - BOOST_MULTI_HD constexpr auto base() const -> typename Ref::element_ptr {return ref_.base();} + BOOST_MULTI_HD constexpr auto base() const -> typename reference::element_ptr {return base_;} friend BOOST_MULTI_HD constexpr auto base(subarray_ptr const& self) {return self.base();} + template, int> =0> // NOLINT(modernize-use-constraints) TODO(correaa) for C++20 + constexpr auto operator==(OtherSubarrayPtr const& other) const + ->decltype((base_ == other.base_) && (layout_ == other.layout_)) { + return (base_ == other.base_) && (layout_ == other.layout_); } + constexpr auto operator==(subarray_ptr const& other) const -> bool { - return (this->ref_.base_ == other.ref_.base_) && (this->ref_.layout() == other.ref_.layout()); + return (base_ == other.base_) && (layout_ == other.layout_); } - template>, int> =0> // TODO(correaa) improve this - friend BOOST_MULTI_HD constexpr auto operator==(subarray_ptr const& self, subarray_ptr const& other) -> bool { - return self.base() == other->base() && self->layout() == other->layout(); + constexpr auto operator!=(subarray_ptr const& other) const -> bool { + return (base_ != other.base_) || (layout_ != other.layout_); } - template>, int> =0> - friend BOOST_MULTI_HD constexpr auto operator!=(subarray_ptr const& self, subarray_ptr const& other) -> bool { - return self.base() == other->base() && self->layout() == other->layout(); + + template< + typename OtherT, multi::dimensionality_type OtherD, typename OtherEPtr, class OtherL, bool OtherIsConst, + std::enable_if_t>, int> =0 // NOLINT(modernize-use-constraints) TODO(correaa) for C++20 + > + friend BOOST_MULTI_HD constexpr auto operator!=(subarray_ptr const& self, subarray_ptr const& other) -> bool { + return self.base_ != other.base_ || self.layout_ != other.layout_; } protected: - BOOST_MULTI_HD constexpr void increment() {ref_.base_ += Ref::nelems();} - BOOST_MULTI_HD constexpr void decrement() {ref_.base_ -= Ref::nelems();} + BOOST_MULTI_HD constexpr void increment() { base_ += layout_.nelems(); } + BOOST_MULTI_HD constexpr void decrement() { base_ -= layout_.nelems(); } - BOOST_MULTI_HD constexpr void advance(difference_type n) {ref_.base_ += ref_.nelems()*n;} + BOOST_MULTI_HD constexpr void advance(difference_type n) { base_ += layout_.nelems()*n; } BOOST_MULTI_HD constexpr auto distance_to(subarray_ptr const& other) const -> difference_type { - assert( Ref::nelems() == other.Ref::nelems() && Ref::nelems() != 0 ); - assert( (other.base() - base())%Ref::nelems() == 0); - assert( ref_.layout() == other.ref_.layout() ); - return (other.base() - base())/Ref::nelems(); + assert( layout_.nelems() == other.layout_.nelems() ); + // assert( Ref::nelems() == other.Ref::nelems() && Ref::nelems() != 0 ); + // assert( (other.base() - base())%Ref::nelems() == 0); + assert( layout_ == other.layout_ ); + return (other.base_ - base_)/layout_.nelems(); } public: - BOOST_MULTI_HD constexpr auto operator+=(difference_type n) -> subarray_ptr& {advance(n); return *this;} + BOOST_MULTI_HD constexpr auto operator+=(difference_type n) -> subarray_ptr& { advance(n); return *this; } }; -template +template struct array_iterator; -template +template struct array_iterator // NOLINT(fuchsia-multiple-inheritance) : boost::multi::iterator_facade< - array_iterator, void, std::random_access_iterator_tag, + array_iterator, void, std::random_access_iterator_tag, subarray const&, typename layout_t::difference_type > -, multi::decrementable> -, multi::incrementable> -, multi::affine, multi::difference_type> -, multi::totally_ordered2, void> { +, multi::decrementable> +, multi::incrementable> +, multi::affine, multi::difference_type> +, multi::totally_ordered2, void> { ~array_iterator() = default; // lints(cppcoreguidelines-special-member-functions,hicpp-special-member-functions) constexpr auto operator=(array_iterator&&) // lints(cppcoreguidelines-special-member-functions,hicpp-special-member-functions) @@ -389,24 +482,29 @@ struct array_iterator // NOLINT(fuchsia-multiple-inheritance) using element_const_ptr = typename std::pointer_traits::template rebind; using value_type = typename subarray::decay_type; - using pointer = subarray*; - using reference = subarray; - using const_reference [[deprecated("not friendly with std::ranges concepts")]] = subarray; // TODO(correaa) should be const_subarray (base of subarray) + using pointer = subarray*; + using reference = std::conditional_t< + IsConst, + const_subarray, + subarray + >; + using const_reference = const_subarray; // TODO(correaa) should be const_subarray (base of subarray) using iterator_category = std::random_access_iterator_tag; constexpr static dimensionality_type rank_v = D; using rank = std::integral_constant; // TODO(correaa) make rank a function for compat with mdspan? - using ptr_type = subarray_ptr, layout_t>; + using ptr_type = subarray_ptr>; using stride_type = index; - using layout_type = typename reference::layout_type; + using layout_type = typename reference::layout_type; // layout_t - BOOST_MULTI_HD constexpr explicit array_iterator(std::nullptr_t nil) : ptr_{nil} {} - BOOST_MULTI_HD constexpr array_iterator() : array_iterator{nullptr} {} + // BOOST_MULTI_HD constexpr explicit array_iterator(std::nullptr_t nil) : ptr_{nil} {} + // BOOST_MULTI_HD constexpr array_iterator() : array_iterator{nullptr} {} + BOOST_MULTI_HD constexpr array_iterator() : ptr_{}, stride_{} {} // = default; // TODO(correaa) make = default, now it is not compiling - template friend struct array_iterator; + template friend struct array_iterator; template< class EElement, typename PPtr, @@ -420,35 +518,53 @@ struct array_iterator // NOLINT(fuchsia-multiple-inheritance) > // cppcheck-suppress noExplicitConstructor ; because underlying pointer is implicitly convertible BOOST_MULTI_HD constexpr/*mplct*/ array_iterator(array_iterator const& other) // NOLINT(google-explicit-constructor,hicpp-explicit-conversions) : propagate implicitness of pointer - : ptr_{element_ptr{other.ptr_->base()}, other.ptr_->layout()}, stride_{other.stride_} {} + : ptr_(other.ptr_), stride_{other.stride_} {} array_iterator(array_iterator const&) = default; auto operator=(array_iterator const&) -> array_iterator& = default; BOOST_MULTI_HD constexpr explicit operator bool() const {return ptr_->base();} // TODO(correaa) implement bool conversion for subarray_ptr - BOOST_MULTI_HD constexpr auto operator*() const -> subarray {return {*ptr_};} + BOOST_MULTI_HD constexpr auto operator*() const -> reference {return *ptr_;} BOOST_MULTI_HD constexpr auto operator->() const -> decltype(auto) {return ptr_;} BOOST_MULTI_HD constexpr auto operator+ (difference_type n) const -> array_iterator {array_iterator ret{*this}; ret += n; return ret;} BOOST_MULTI_HD constexpr auto operator[](difference_type n) const -> subarray {return *((*this) + n);} - friend BOOST_MULTI_HD constexpr auto operator==(array_iterator const& self, array_iterator const& other) -> bool { - return self.ptr_ == other.ptr_ && self.stride_== other.stride_ && self.ptr_->layout() == other.ptr_->layout(); + template =0> // NOLINT(modernize-use-constraints) TODO(correaa) for C++20 + BOOST_MULTI_HD constexpr auto operator==(array_iterator const& other) const -> bool { + // assert( this->stride_ == other.stride_ ); + // assert( this->ptr_->layout() == other.ptr_->layout() ); + return (this->ptr_ == other.ptr_) && (this->stride_ == other.stride_) && ( (*(this->ptr_)).layout() == (*(other.ptr_)).layout() ); + } + + BOOST_MULTI_HD constexpr auto operator==(array_iterator const& other) const -> bool { + // assert( this->stride_ == other.stride_ ); + // assert( this->ptr_->layout() == other.ptr_->layout() ); + return (this->ptr_ == other.ptr_) && (this->stride_ == other.stride_) && ( (*(this->ptr_)).layout() == (*(other.ptr_)).layout() ); + } + + BOOST_MULTI_HD constexpr auto operator!=(array_iterator const& other) const -> bool { + return !operator==(other); } + // BOOST_MULTI_HD constexpr auto operator==(array_iterator const& other) const -> bool { + // return this->ptr_ == other.ptr_ && this->stride_== other.stride_ && this->ptr_->layout() == other.ptr_->layout(); + // } + BOOST_MULTI_HD constexpr auto operator< (array_iterator const& other) const -> bool { - assert(ptr_->layout() == other.ptr_->layout()); + assert((*ptr_).layout() == (*(other.ptr_)).layout()); assert(stride_ != 0); return ((0 < stride_) && (ptr_.base() - other.ptr_.base() < 0)) || ((stride_ < 0) && (0 < ptr_.base() - other.ptr_.base())); // TODO(correaa) consider the case where stride_ is negative } - BOOST_MULTI_HD constexpr explicit array_iterator(typename subarray::element_ptr base, layout_t lyt, index stride) + BOOST_MULTI_HD constexpr explicit array_iterator(typename subarray::element_ptr base, layout_t const& lyt, index stride) : ptr_{base, lyt}, stride_{stride} {} - template friend struct subarray; + template friend struct const_subarray; template BOOST_MULTI_HD constexpr auto operator()(index idx, As... args) const -> decltype(auto) {return this->operator[](idx)(args...); } @@ -457,28 +573,38 @@ struct array_iterator // NOLINT(fuchsia-multiple-inheritance) private: template static BOOST_MULTI_HD constexpr auto apply_impl_(Self&& self, Tuple const& tuple, std::index_sequence/*012*/) -> decltype(auto) { - return std::forward(self)(std::get(tuple)...); + using std::get; + return std::forward(self)(get(tuple)...); } public: - template BOOST_MULTI_HD constexpr auto apply(Tuple const& tpl) const& -> decltype(auto) { return apply_impl_( *this , tpl, std::make_index_sequence::value>()); } - template BOOST_MULTI_HD constexpr auto apply(Tuple const& tpl) && -> decltype(auto) { return apply_impl_(std::move(*this), tpl, std::make_index_sequence::value>()); } - template BOOST_MULTI_HD constexpr auto apply(Tuple const& tpl) & -> decltype(auto) { return apply_impl_( *this , tpl, std::make_index_sequence::value>()); } + template BOOST_MULTI_HD constexpr auto apply(Tuple const& tpl) const -> decltype(auto) { return apply_impl_( *this , tpl, std::make_index_sequence::value>()); } + // template BOOST_MULTI_HD constexpr auto apply(Tuple const& tpl) && -> decltype(auto) { return apply_impl_(std::move(*this), tpl, std::make_index_sequence::value>()); } + // template BOOST_MULTI_HD constexpr auto apply(Tuple const& tpl) & -> decltype(auto) { return apply_impl_( *this , tpl, std::make_index_sequence::value>()); } private: ptr_type ptr_; - stride_type stride_ = {1}; // nice non-zero default // TODO(correaa) use INT_MAX? + stride_type stride_; // = {1}; // nice non-zero default // TODO(correaa) use INT_MAX? // TODO(correaa) remove to make type trivial - BOOST_MULTI_HD constexpr void decrement_() {ptr_->base_ -= stride_;} - BOOST_MULTI_HD constexpr void advance_(difference_type n) {ptr_->base_ += stride_*n;} + #if defined(__clang__) + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wunknown-warning-option" + #pragma clang diagnostic ignored "-Wunsafe-buffer-usage" // TODO(correaa) use checked span + #endif - public: - BOOST_MULTI_HD constexpr auto base() const& -> element_ptr {return ptr_.base();} - friend /*constexpr*/ auto base(array_iterator const& self) -> element_ptr {return self.base();} + BOOST_MULTI_HD constexpr void decrement_() { ptr_.base_ -= stride_; } + BOOST_MULTI_HD constexpr void advance_(difference_type n) { ptr_.base_ += stride_*n; } + + #if defined(__clang__) + #pragma clang diagnostic pop + #endif - BOOST_MULTI_HD constexpr auto stride() const& -> stride_type {return stride_;} - friend constexpr auto stride(array_iterator const& self) -> stride_type {return self.stride_;} + public: + BOOST_MULTI_HD constexpr auto base() const -> element_ptr {return ptr_.base_;} + BOOST_MULTI_HD constexpr auto stride() const -> stride_type {return stride_;} + friend /*constexpr*/ auto base(array_iterator const& self) -> element_ptr {return self.base();} // TODO(correaa) remove + friend constexpr auto stride(array_iterator const& self) -> stride_type {return self.stride_;} // TODO(correaa) remove #if defined(__clang__) #pragma clang diagnostic push @@ -486,8 +612,8 @@ struct array_iterator // NOLINT(fuchsia-multiple-inheritance) #pragma clang diagnostic ignored "-Wunsafe-buffer-usage" // TODO(correaa) use checked span #endif - constexpr auto operator++() -> array_iterator& {ptr_->base_ += stride_; return *this;} - constexpr auto operator--() -> array_iterator& {decrement_(); return *this;} + constexpr auto operator++() -> array_iterator& { ptr_.base_ += stride_; return *this; } + constexpr auto operator--() -> array_iterator& { ptr_.base_ -= stride_; return *this; } #if defined(__clang__) #pragma clang diagnostic pop @@ -495,12 +621,12 @@ struct array_iterator // NOLINT(fuchsia-multiple-inheritance) friend constexpr auto operator-(array_iterator const& self, array_iterator const& other) -> difference_type { assert(self.stride_ == other.stride_); // NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay) normal in a constexpr function - assert(self.stride_ != 0); // NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay) normal in a constexpr function + assert(self.stride_ != 0); return (self.ptr_.base() - other.ptr_.base())/self.stride_; } - constexpr auto operator+=(difference_type n) -> array_iterator& {advance_(+n); return *this;} - constexpr auto operator-=(difference_type n) -> array_iterator& {advance_(-n); return *this;} + constexpr auto operator+=(difference_type n) -> array_iterator& { advance_(+n); return *this; } + constexpr auto operator-=(difference_type n) -> array_iterator& { advance_(-n); return *this; } }; template @@ -517,17 +643,26 @@ struct cursor_t { using indices_type = typename extensions_t::indices_type; + cursor_t() = default; + private: strides_type strides_; element_ptr base_; - template friend struct subarray; + template friend struct const_subarray; template friend struct cursor_t; BOOST_MULTI_HD constexpr cursor_t(element_ptr base, strides_type const& strides) : strides_{strides}, base_{base} {} + template(std::declval().base()))> + // cppcheck-suppress noExplicitConstructor + BOOST_MULTI_HD constexpr cursor_t(OtherCursor const& other) : strides_{other.strides()}, base_{other.base()} {} // NOLINT(google-explicit-constructor,hicpp-explicit-conversions) + template + BOOST_MULTI_HD constexpr explicit cursor_t(OtherCursor const& other) : strides_{other.strides()}, base_{other.base()} {} + public: BOOST_MULTI_HD constexpr auto operator[](difference_type n) const -> decltype(auto) { + using std::get; if constexpr(D != 1) { return cursor_t< ElementPtr, @@ -535,13 +670,14 @@ struct cursor_t { std::decay_t >{ base_ - + std::get<0>(strides_)*n, + + get<0>(strides_)*n, strides_.tail() }; } else { - return base_[std::get<0>(strides_)*n]; + return base_[get<0>(strides_)*n]; } } + BOOST_MULTI_HD constexpr auto operator()(difference_type n) const -> decltype(auto) { return operator[](n); } @@ -553,7 +689,8 @@ struct cursor_t { private: template BOOST_MULTI_HD constexpr auto apply_impl_(Tuple const& tup, std::index_sequence /*012*/) const -> decltype(auto) { - return ((std::get(tup)*std::get(strides_)) + ...); + using std::get; + return ((get(tup)*get(strides_)) + ...); } public: @@ -564,6 +701,11 @@ struct cursor_t { } BOOST_MULTI_HD constexpr auto operator* () const -> reference {return *base_;} BOOST_MULTI_HD constexpr auto operator->() const -> pointer {return base_;} + + BOOST_MULTI_HD constexpr auto base() const -> pointer { return base_; } + BOOST_MULTI_HD constexpr auto strides() const -> strides_type { return strides_; } + template + BOOST_MULTI_HD constexpr auto stride() const { using std::get; return get

(strides_); } }; template @@ -592,12 +734,15 @@ struct elements_iterator_t // NOLINT(cppcoreguidelines-special-member-functions template friend struct elements_iterator_t; template friend struct elements_range_t; - constexpr elements_iterator_t(pointer base, layout_type lyt, difference_type n) + constexpr elements_iterator_t(pointer base, layout_type const& lyt, difference_type n) : base_{base}, l_{lyt}, n_{n}, xs_{l_.extensions()}, ns_{lyt.is_empty()?indices_type{}:xs_.from_linear(n)} {} public: - constexpr auto base() -> pointer {return base_;} - constexpr auto base() const -> const_pointer {return base_;} + elements_iterator_t() = default; + + BOOST_MULTI_HD constexpr auto base() -> pointer {return base_;} + BOOST_MULTI_HD constexpr auto base() const -> const_pointer {return base_;} + BOOST_MULTI_HD constexpr auto layout() const -> layout_type {return l_;} template(std::declval().base_))* = nullptr> @@ -698,6 +843,8 @@ struct elements_range_t { using iterator = elements_iterator_t; using const_iterator = elements_iterator_t; + // using element = value_type; + private: pointer base_; layout_type l_; @@ -709,14 +856,30 @@ struct elements_range_t { template(std::declval().base_))* = nullptr> constexpr explicit elements_range_t(OtherRange const& other) : elements_range_t{other} {} - constexpr elements_range_t(pointer base, layout_type lyt) : base_{base}, l_{lyt} {} + constexpr elements_range_t(pointer base, layout_type const& lyt) : base_{base}, l_{lyt} {} + + constexpr auto base() -> pointer {return base_;} + constexpr auto base() const -> const_pointer {return base_;} + + constexpr auto layout() const -> layout_type {return l_;} private: + + #if defined(__clang__) + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wunknown-warning-option" + #pragma clang diagnostic ignored "-Wunsafe-buffer-usage" // TODO(correaa) use checked span + #endif + constexpr auto at_aux_(difference_type n) const -> reference { assert( ! is_empty() ); return base_[std::apply(l_, l_.extensions().from_linear(n))]; } + #if defined(__clang__) + #pragma clang diagnostic pop + #endif + public: BOOST_MULTI_HD constexpr auto operator[](difference_type n) const& -> const_reference {return at_aux_(n);} BOOST_MULTI_HD constexpr auto operator[](difference_type n) && -> reference {return at_aux_(n);} @@ -773,7 +936,7 @@ struct elements_range_t { auto operator=(elements_range_t const&) -> elements_range_t& = delete; auto operator=(elements_range_t && other) noexcept -> elements_range_t& { // cannot be =delete in NVCC? - if(! is_empty()) {adl_copy(std::begin(std::move(other)), std::end(std::move(other)), begin());} + if(! is_empty()) {adl_copy(other.begin(), other.end(), this->begin());} return *this; } @@ -798,7 +961,7 @@ struct elements_range_t { }; template -BOOST_MULTI_HD constexpr auto ref(It begin, It end) +[[deprecated("remove")]] BOOST_MULTI_HD constexpr auto ref(It begin, It end) ->multi::subarray { return multi::subarray{begin, end}; } @@ -806,68 +969,45 @@ BOOST_MULTI_HD constexpr auto ref(It begin, It end) template struct static_array; // this might be needed by MSVC 14.3 in c++17 mode template -struct subarray : array_types { +struct const_subarray : array_types { using types = array_types; - using ref_ = subarray; + using ref_ = const_subarray; using array_types::rank_v; - friend struct subarray; + friend struct const_subarray; using types::layout; using typename types::element_type; using layout_type = Layout; - BOOST_MULTI_HD constexpr auto layout() const -> layout_type {return array_types::layout();} + BOOST_MULTI_HD constexpr auto layout() const -> decltype(auto) {return array_types::layout();} using basic_const_array = subarray::template rebind, Layout>; - subarray() = default; + const_subarray() = default; + auto operator=(const_subarray const&) -> const_subarray& = delete; + auto operator=(const_subarray &&) -> const_subarray& = delete; - BOOST_MULTI_HD constexpr subarray(layout_type const& layout, ElementPtr const& base) + BOOST_MULTI_HD constexpr const_subarray(layout_type const& layout, ElementPtr const& base) : array_types{layout, base} {} - auto operator=(subarray&& other) & noexcept(std::is_nothrow_copy_assignable_v) -> subarray& { // allows assigment in temporaries // NOLINT(cppcoreguidelines-noexcept-move-operations,hicpp-noexcept-move,performance-noexcept-move-constructor) //NOSONAR - operator=(other); return *this; - } - - auto operator=(subarray&& other) && noexcept(std::is_nothrow_copy_assignable_v) -> subarray& { // allows assigment in temporaries // NOLINT(cppcoreguidelines-noexcept-move-operations,hicpp-noexcept-move,performance-noexcept-move-constructor) //NOSONAR - operator=(std::move(other)); return *this; - } - -#if defined(__NVCOMPILER) -#pragma diagnostic push -#pragma diag_suppress = conversion_function_not_usable -#elif defined(__NVCC__) -#pragma nv_diagnostic push -#pragma nv_diag_suppress = conversion_function_not_usable -#endif - BOOST_MULTI_HD constexpr operator subarray const& () const { // NOLINT(google-explicit-constructor,hicpp-explicit-conversions) this is needed by std::ranges, TODO(correaa) think if this can be solved by inheritance from subarray - return reinterpret_cast const&>(*this); // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast,cppcoreguidelines-pro-type-reinterpret-cast) think if this can be solved by inheritance from subarray - } -#ifdef __NVCOMPILER -#pragma diagnostic pop -#elif defined(__NVCC__) -#pragma nv_diagnostic pop -#endif - protected: // using types::types; - BOOST_MULTI_HD constexpr explicit subarray(std::nullptr_t nil) : types{nil} {} + BOOST_MULTI_HD constexpr explicit const_subarray(std::nullptr_t nil) : types{nil} {} template friend struct static_array; // TODO(correaa) vvv consider making it explicit (seems that in C++23 it can prevent auto s = a[0];) - subarray(subarray const&) = default; // NOTE: reference type cannot be copied. perhaps you want to return by std::move or std::forward if you got the object from a universal reference argument + const_subarray(const_subarray const&) = default; // NOTE: reference type cannot be copied. perhaps you want to return by std::move or std::forward if you got the object from a universal reference argument - template friend struct subarray_ptr; + template friend struct subarray_ptr; public: using element = typename types::element; using element_ptr = typename types::element_ptr; using element_const_ptr = typename types::element_const_ptr; - using element_move_ptr = multi::move_ptr; using element_ref = typename types::element_ref; using element_cref = typename std::iterator_traits::reference; @@ -885,7 +1025,7 @@ struct subarray : array_types { constexpr auto elements_aux_() const {return elements_range(this->base_, this->layout());} public: - subarray(subarray&&) noexcept = default; // lints(readability-redundant-access-specifiers) + const_subarray(const_subarray&&) noexcept = default; // lints(readability-redundant-access-specifiers) constexpr auto elements() & -> elements_range { return elements_aux_(); } constexpr auto elements() && -> elements_range { return elements_aux_(); } @@ -896,30 +1036,30 @@ struct subarray : array_types { return {this->base(), std::abs(this->hull_size())}; } - ~subarray() = default; // this lints(cppcoreguidelines-special-member-functions,hicpp-special-member-functions) + ~const_subarray() = default; // this lints(cppcoreguidelines-special-member-functions,hicpp-special-member-functions) - BOOST_MULTI_FRIEND_CONSTEXPR auto sizes(subarray const& self) noexcept -> typename subarray::sizes_type {return self.sizes();} // needed by nvcc - BOOST_MULTI_FRIEND_CONSTEXPR auto size (subarray const& self) noexcept -> typename subarray::size_type {return self.size ();} // needed by nvcc + BOOST_MULTI_FRIEND_CONSTEXPR auto sizes(const_subarray const& self) noexcept -> typename const_subarray::sizes_type {return self.sizes();} // needed by nvcc + BOOST_MULTI_FRIEND_CONSTEXPR auto size (const_subarray const& self) noexcept -> typename const_subarray::size_type {return self.size ();} // needed by nvcc - template friend constexpr auto reinterpret_array_cast(subarray && self) {return std::move(self).template reinterpret_array_cast::template rebind>();} - template friend constexpr auto reinterpret_array_cast(subarray const& self) {return self .template reinterpret_array_cast::template rebind>();} + // template friend constexpr auto reinterpret_array_cast(const_subarray && self) {return std::move(self).template reinterpret_array_cast::template rebind>();} + // template friend constexpr auto reinterpret_array_cast(const_subarray const& self) {return self .template reinterpret_array_cast::template rebind>();} - friend constexpr auto dimensionality(subarray const& /*self*/) {return D;} + friend constexpr auto dimensionality(const_subarray const& /*self*/) {return D;} using typename types::reference; - using default_allocator_type = typename multi::pointer_traits::default_allocator_type; + using default_allocator_type = typename multi::pointer_traits::default_allocator_type; constexpr auto get_allocator() const -> default_allocator_type { using multi::get_allocator; return get_allocator(this->base()); } - BOOST_MULTI_FRIEND_CONSTEXPR auto get_allocator(subarray const& self) -> default_allocator_type {return self.get_allocator();} + BOOST_MULTI_FRIEND_CONSTEXPR auto get_allocator(const_subarray const& self) -> default_allocator_type {return self.get_allocator();} - using decay_type = array::default_allocator_type>; + using decay_type = array::default_allocator_type>; - friend constexpr auto decay(subarray const& self) -> decay_type {return self.decay();} + friend constexpr auto decay(const_subarray const& self) -> decay_type {return self.decay();} constexpr auto decay() const& -> decay_type { decay_type ret{*this}; return ret; @@ -929,58 +1069,80 @@ struct subarray : array_types { using typename types::const_reference; private: + template friend class subarray; + BOOST_MULTI_HD constexpr auto at_aux_(index idx) const { #if defined(__clang__) #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wunknown-warning-option" #pragma clang diagnostic ignored "-Wunsafe-buffer-usage" // TODO(correaa) use checked span #endif - return reference { + return const_reference( this->layout().sub(), this->base_ + (idx*this->layout().stride() - this->layout().offset()) - }; // cppcheck-suppress syntaxError ; bug in cppcheck 2.5 + ); // cppcheck-suppress syntaxError ; bug in cppcheck 2.5 #if defined(__clang__) #pragma clang diagnostic pop #endif } public: - BOOST_MULTI_HD constexpr auto operator[](index idx) const& { return static_cast(at_aux_(idx)); } // TODO(correaa) use return type to cast - BOOST_MULTI_HD constexpr auto operator[](index idx) && -> reference { return at_aux_(idx) ; } - BOOST_MULTI_HD constexpr auto operator[](index idx) & -> reference { return at_aux_(idx) ; } - template(D)>, typename = std::enable_if_t<(std::tuple_size::value > 1)> > + #if defined(__clang__) + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wunknown-warning-option" + #pragma clang diagnostic ignored "-Wunsafe-buffer-usage" // TODO(correaa) use checked span + #endif + + BOOST_MULTI_HD constexpr auto operator[](index idx) const& -> const_reference { + return const_reference( + this->layout().sub(), + this->base_ + (idx*this->layout().stride() - this->layout().offset()) + ); // cppcheck-suppress syntaxError ; bug in cppcheck 2.5 + // return at_aux_(idx); + } // TODO(correaa) use return type to cast + + #if defined(__clang__) + #pragma clang diagnostic pop + #endif + + // BOOST_MULTI_HD constexpr auto operator[](index idx) && -> reference { return at_aux_(idx) ; } + // BOOST_MULTI_HD constexpr auto operator[](index idx) & -> reference { return at_aux_(idx) ; } + + template(D)>, + typename = std::enable_if_t<(std::tuple_size::value > 1)> // NOLINT(modernize-use-constraints) TODO(correaa) for C++20 + > BOOST_MULTI_HD constexpr auto operator[](Tuple const& tup) const - ->decltype(operator[](std::get<0>(tup))[detail::tuple_tail(tup)]) { - return operator[](std::get<0>(tup))[detail::tuple_tail(tup)]; } + ->decltype(operator[](detail::head(tup))[detail::tuple_tail(tup)]) { + return operator[](detail::head(tup))[detail::tuple_tail(tup)]; } - template::value == 1)> > + template::value == 1)> > // NOLINT(modernize-use-constraints) TODO(correaa) BOOST_MULTI_HD constexpr auto operator[](Tuple const& tup) const - ->decltype(operator[](std::get<0>(tup))) { - return operator[](std::get<0>(tup)); } + ->decltype(operator[](detail::head(tup))) { + return operator[](detail::head(tup)); } - constexpr auto front() const& -> const_reference {return *begin();} - constexpr auto back() const& -> const_reference {return *std::prev(end(), 1);} + constexpr auto front() const& -> const_reference { return *begin(); } + constexpr auto back() const& -> const_reference { return *(end() - 1); } // std::prev(end(), 1);} - constexpr auto front() && -> reference {return *begin();} - constexpr auto back() && -> reference {return *std::prev(end(), 1);} + constexpr auto front() && -> reference { return *begin(); } + constexpr auto back() && -> reference { return *(end() - 1); } // std::prev(end(), 1);} constexpr auto front() & -> reference {return *begin();} - constexpr auto back() & -> reference {return *std::prev(end(), 1);} + constexpr auto back() & -> reference {return *(end() - 1);} // std::prev(end(), 1);} using typename types::index; constexpr auto reindexed(index first) const& { typename types::layout_t new_layout = this->layout(); new_layout.reindex(first); - return basic_const_array(new_layout, types::base_); + return const_subarray(new_layout, types::base_); } constexpr auto reindexed(index first)& { typename types::layout_t new_layout = this->layout(); new_layout.reindex(first); - return subarray(new_layout, types::base_); + return const_subarray(new_layout, types::base_); } - constexpr auto reindexed(index first)&& -> subarray { + constexpr auto reindexed(index first)&& -> const_subarray { typename types::layout_t new_layout = this->layout(); new_layout.reindex(first); return {new_layout, types::base_}; @@ -988,17 +1150,9 @@ struct subarray : array_types { // TODO(correaa) : implement reindexed_aux template - constexpr auto reindexed(index first, Indexes... idxs) const& -> basic_const_array { - return ((reindexed(first).rotated()).reindexed(idxs...)).unrotated(); - } - template - constexpr auto reindexed(index first, Indexes... idxs) & -> subarray { + constexpr auto reindexed(index first, Indexes... idxs) const& -> const_subarray { return ((reindexed(first).rotated()).reindexed(idxs...)).unrotated(); } - template - constexpr auto reindexed(index first, Indexes... idxs)&& -> subarray { - return ((std::move(*this).reindexed(first).rotated()).reindexed(idxs...)).unrotated(); - } private: constexpr auto taked_aux_(difference_type n) const { @@ -1009,13 +1163,13 @@ struct subarray : array_types { this->layout().offset(), this->stride()*n ); - return subarray(new_layout, this->base_); + return const_subarray(new_layout, this->base_); } public: - constexpr auto taked(difference_type n) const& -> basic_const_array {return taked_aux_(n);} - constexpr auto taked(difference_type n) && -> subarray {return taked_aux_(n);} - constexpr auto taked(difference_type n) & -> subarray {return taked_aux_(n);} + constexpr auto taked(difference_type n) const& -> basic_const_array { return taked_aux_(n); } + // constexpr auto taked(difference_type n) && -> const_subarray { return taked_aux_(n); } + // constexpr auto taked(difference_type n) & -> const_subarray { return taked_aux_(n); } private: constexpr auto dropped_aux_(difference_type n) const { @@ -1026,15 +1180,33 @@ struct subarray : array_types { this->layout().offset(), this->stride()*(this->size() - n) }; - return subarray(new_layout, this->base_ + n*this->layout().stride() - this->layout().offset()); + + #if defined(__clang__) + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wunknown-warning-option" + #pragma clang diagnostic ignored "-Wunsafe-buffer-usage" + #endif + + return const_subarray(new_layout, this->base_ + n*this->layout().stride() - this->layout().offset()); + + #if defined(__clang__) + #pragma clang diagnostic pop + #endif } public: constexpr auto dropped(difference_type n) const& -> basic_const_array { return dropped_aux_(n); } - constexpr auto dropped(difference_type n) && -> subarray { return dropped_aux_(n); } - constexpr auto dropped(difference_type n) & -> subarray { return dropped_aux_(n); } + constexpr auto dropped(difference_type n) && -> const_subarray { return dropped_aux_(n); } + constexpr auto dropped(difference_type n) & -> const_subarray { return dropped_aux_(n); } private: + + #if defined(__clang__) + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wunknown-warning-option" + #pragma clang diagnostic ignored "-Wunsafe-buffer-usage" // TODO(correaa) use checked span + #endif + BOOST_MULTI_HD constexpr auto sliced_aux_(index first, index last) const { // TODO(correaa) remove first == last condition BOOST_MULTI_ACCESS_ASSERT(((first==last) || this->extension().contains(first ))&&"sliced first out of bounds"); // NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay) : normal in a constexpr function @@ -1042,32 +1214,34 @@ struct subarray : array_types { typename types::layout_t new_layout = this->layout(); new_layout.nelems() = this->stride()*(last - first); // TODO(correaa) : reconstruct layout instead of mutating it BOOST_MULTI_ACCESS_ASSERT(this->base_ || ((first*this->layout().stride() - this->layout().offset()) == 0) ); // it is UB to offset a nullptr - return subarray{new_layout, this->base_ + (first*this->layout().stride() - this->layout().offset())}; + return const_subarray{new_layout, this->base_ + (first*this->layout().stride() - this->layout().offset())}; } + #if defined(__clang__) + #pragma clang diagnostic pop + #endif + public: - BOOST_MULTI_HD constexpr auto sliced(index first, index last) const& -> basic_const_array { return sliced_aux_(first, last); } - BOOST_MULTI_HD constexpr auto sliced(index first, index last) & -> subarray { return sliced_aux_(first, last); } - BOOST_MULTI_HD constexpr auto sliced(index first, index last) && -> subarray { return sliced_aux_(first, last); } + BOOST_MULTI_HD constexpr auto sliced(index first, index last) const& -> const_subarray { return sliced_aux_(first, last); } constexpr auto blocked(index first, index last) const& -> basic_const_array { return sliced(first, last).reindexed(first); } - constexpr auto blocked(index first, index last) & -> subarray { return sliced(first, last).reindexed(first); } + constexpr auto blocked(index first, index last) & -> const_subarray { return sliced(first, last).reindexed(first); } - using iextension = typename subarray::index_extension; + using iextension = typename const_subarray::index_extension; - constexpr auto stenciled(iextension iex) & -> subarray { return blocked(iex.first(), iex.last()); } - constexpr auto stenciled(iextension iex, iextension iex1) & -> subarray { return ((stenciled(iex).rotated()).stenciled(iex1)).unrotated(); } - constexpr auto stenciled(iextension iex, iextension iex1, iextension iex2) & -> subarray { return ((stenciled(iex).rotated()).stenciled(iex1, iex2)).unrotated(); } - constexpr auto stenciled(iextension iex, iextension iex1, iextension iex2, iextension iex3) & -> subarray { return ((stenciled(iex).rotated()).stenciled(iex1, iex2, iex3)).unrotated(); } + constexpr auto stenciled(iextension iex) & -> const_subarray { return blocked(iex.first(), iex.last()); } + constexpr auto stenciled(iextension iex, iextension iex1) & -> const_subarray { return ((stenciled(iex).rotated()).stenciled(iex1)).unrotated(); } + constexpr auto stenciled(iextension iex, iextension iex1, iextension iex2) & -> const_subarray { return ((stenciled(iex).rotated()).stenciled(iex1, iex2)).unrotated(); } + constexpr auto stenciled(iextension iex, iextension iex1, iextension iex2, iextension iex3) & -> const_subarray { return ((stenciled(iex).rotated()).stenciled(iex1, iex2, iex3)).unrotated(); } template - constexpr auto stenciled(iextension iex, iextension iex1, iextension iex2, iextension iex3, Xs... iexs) & -> subarray{return ((stenciled(iex).rotated()).stenciled(iex1, iex2, iex3, iexs...)).unrotated(); } + constexpr auto stenciled(iextension iex, iextension iex1, iextension iex2, iextension iex3, Xs... iexs) & -> const_subarray { return ((stenciled(iex).rotated()).stenciled(iex1, iex2, iex3, iexs...)).unrotated(); } - constexpr auto stenciled(iextension iex) && -> subarray { return blocked(iex.first(), iex.last()); } - constexpr auto stenciled(iextension iex, iextension iex1) && -> subarray { return ((stenciled(iex).rotated()).stenciled(iex1)).unrotated(); } - constexpr auto stenciled(iextension iex, iextension iex1, iextension iex2) && -> subarray { return ((stenciled(iex).rotated()).stenciled(iex1, iex2)).unrotated(); } - constexpr auto stenciled(iextension iex, iextension iex1, iextension iex2, iextension iex3) && -> subarray { return ((stenciled(iex).rotated()).stenciled(iex1, iex2, iex3)).unrotated(); } + constexpr auto stenciled(iextension iex) && -> const_subarray { return blocked(iex.first(), iex.last()); } + constexpr auto stenciled(iextension iex, iextension iex1) && -> const_subarray { return ((stenciled(iex).rotated()).stenciled(iex1)).unrotated(); } + constexpr auto stenciled(iextension iex, iextension iex1, iextension iex2) && -> const_subarray { return ((stenciled(iex).rotated()).stenciled(iex1, iex2)).unrotated(); } + constexpr auto stenciled(iextension iex, iextension iex1, iextension iex2, iextension iex3) && -> const_subarray { return ((stenciled(iex).rotated()).stenciled(iex1, iex2, iex3)).unrotated(); } template - constexpr auto stenciled(iextension iex, iextension iex1, iextension iex2, iextension iex3, Xs... iexs) && -> subarray{ return ((stenciled(iex).rotated()).stenciled(iex1, iex2, iex3, iexs...)).unrotated(); } + constexpr auto stenciled(iextension iex, iextension iex1, iextension iex2, iextension iex3, Xs... iexs) && -> const_subarray{ return ((stenciled(iex).rotated()).stenciled(iex1, iex2, iex3, iexs...)).unrotated(); } constexpr auto stenciled(iextension iex) const& -> basic_const_array { return blocked(iex.first(), iex.last()); } constexpr auto stenciled(iextension iex, iextension iex1) const& -> basic_const_array { return ((stenciled(iex).rotated()).stenciled(iex1)).unrotated(); } @@ -1098,25 +1272,25 @@ struct subarray : array_types { private: constexpr auto strided_aux_(difference_type diff) const { typename types::layout_t const new_layout{this->layout().sub(), this->layout().stride()*diff, this->layout().offset(), this->layout().nelems()}; - return subarray(new_layout, types::base_); + return const_subarray(new_layout, types::base_); } public: constexpr auto strided(difference_type diff) const& -> basic_const_array { return strided_aux_(diff); } - constexpr auto strided(difference_type diff) && -> subarray { return strided_aux_(diff); } - constexpr auto strided(difference_type diff) & -> subarray { return strided_aux_(diff); } + constexpr auto strided(difference_type diff) && -> const_subarray { return strided_aux_(diff); } + constexpr auto strided(difference_type diff) & -> const_subarray { return strided_aux_(diff); } constexpr auto sliced( typename types::index first, typename types::index last, typename types::index stride_ - ) const -> subarray { + ) const& -> const_subarray { return sliced(first, last).strided(stride_); } - using index_range = typename subarray::index_range; + using index_range = typename const_subarray::index_range; - constexpr auto range(index_range irng) const& -> decltype(auto) {return sliced(irng.front(), irng.front() + irng.size());} - constexpr auto range(index_range irng) && -> decltype(auto) {return std::move(*this).sliced(irng.front(), irng.front() + irng.size());} - constexpr auto range(index_range irng) & -> decltype(auto) {return sliced(irng.front(), irng.front() + irng.size());} + BOOST_MULTI_HD constexpr auto range(index_range irng) const& -> decltype(auto) {return sliced(irng.front(), irng.front() + irng.size());} + // constexpr auto range(index_range irng) && -> decltype(auto) {return std::move(*this).sliced(irng.front(), irng.front() + irng.size());} + // constexpr auto range(index_range irng) & -> decltype(auto) {return sliced(irng.front(), irng.front() + irng.size());} [[deprecated("is_flattable will be a property of the layout soon")]] constexpr auto is_flattable() const -> bool{ @@ -1126,12 +1300,12 @@ struct subarray : array_types { ; } - friend constexpr auto flatted(subarray const& self) {return self.flatted();} - constexpr auto flatted() const& { + // friend constexpr auto flatted(const_subarray const& self) {return self.flatted();} + constexpr auto flatted() const& { // assert(is_flattable() && "flatted doesn't work for all layouts!"); // NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay) : normal in a constexpr function multi::layout_t new_layout{this->layout().sub()}; new_layout.nelems() *= this->size(); // TODO(correaa) : use immutable layout - return subarray{new_layout, types::base_}; + return const_subarray{new_layout, types::base_}; } void flattened() const = delete; @@ -1141,71 +1315,82 @@ struct subarray : array_types { // } constexpr auto broadcasted() const& { - multi::layout_t const new_layout{layout(), 0, 0, std::numeric_limits::max()}; - return subarray{new_layout, types::base_}; + multi::layout_t const new_layout{layout(), 0, 0, (std::numeric_limits::max)()}; // paren for MSVC macros + return const_subarray{new_layout, types::base_}; } // TODO(correaa) : define a diagonal_aux constexpr auto diagonal() && {return this->diagonal();} - constexpr auto diagonal() & -> subarray { + constexpr auto diagonal() & -> const_subarray { using boost::multi::detail::get; - auto square_size = std::min(get<0>(this->sizes()), get<1>(this->sizes())); + auto square_size = (std::min)(get<0>(this->sizes()), get<1>(this->sizes())); // paren for MSVC macros multi::layout_t new_layout{(*this)({0, square_size}, {0, square_size}).layout().sub()}; new_layout.nelems() += (*this)({0, square_size}, {0, square_size}).layout().nelems(); // TODO(correaa) : don't use mutation new_layout.stride() += (*this)({0, square_size}, {0, square_size}).layout().stride(); // TODO(correaa) : don't use mutation return {new_layout, types::base_}; } - template 1) && sizeof(Dummy*), int> =0> - constexpr auto diagonal() const& -> subarray { - auto square_size = std::min(std::get<0>(this->sizes()), std::get<1>(this->sizes())); + template 1) && sizeof(Dummy*), int> =0> // NOLINT(modernize-use-constraints) TODO(correaa) + constexpr auto diagonal() const& -> const_subarray { + using std::get; + auto const square_size = (std::min)(get<0>(this->sizes()), get<1>(this->sizes())); // parenthesis min for MSVC macros multi::layout_t new_layout{(*this)({0, square_size}, {0, square_size}).layout().sub()}; new_layout.nelems() += (*this)({0, square_size}, {0, square_size}).layout().nelems(); new_layout.stride() += (*this)({0, square_size}, {0, square_size}).layout().stride(); // cppcheck-suppress arithOperationsOnVoidPointer ; false positive D == 1 doesn't happen here return {new_layout, types::base_}; } - friend constexpr auto diagonal(subarray const& self) {return self .diagonal();} - friend constexpr auto diagonal(subarray& self) {return self .diagonal();} - friend constexpr auto diagonal(subarray&& self) {return std::move(self).diagonal();} + friend constexpr auto diagonal(const_subarray const& self) {return self .diagonal();} + friend constexpr auto diagonal(const_subarray& self) {return self .diagonal();} + friend constexpr auto diagonal(const_subarray&& self) {return std::move(self).diagonal();} - using partitioned_type = subarray; - using partitioned_const_type = subarray; + // using partitioned_type = const_subarray; + // using partitioned_const_type = const_subarray; private: - BOOST_MULTI_HD constexpr auto partitioned_aux_(size_type n) const -> partitioned_type { + BOOST_MULTI_HD constexpr auto partitioned_aux_(size_type n) const { assert(n != 0); // NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay) : normal in a constexpr function // vvv TODO(correaa) should be size() here? // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay) normal in a constexpr function assert( (this->layout().nelems() % n) == 0); // if you get an assertion here it means that you are partitioning an array with an incommunsurate partition multi::layout_t new_layout{this->layout(), this->layout().nelems()/n, 0, this->layout().nelems()}; new_layout.sub().nelems() /= n; - return {new_layout, types::base_}; + return subarray(new_layout, types::base_); } public: - BOOST_MULTI_HD constexpr auto partitioned(size_type n) const& -> partitioned_const_type {return partitioned_aux_(n);} - BOOST_MULTI_HD constexpr auto partitioned(size_type n) & -> partitioned_type {return partitioned_aux_(n);} - BOOST_MULTI_HD constexpr auto partitioned(size_type n) && -> partitioned_type {return partitioned_aux_(n);} + BOOST_MULTI_HD constexpr auto partitioned(size_type n) const& -> const_subarray {return partitioned_aux_(n);} - friend BOOST_MULTI_HD constexpr auto partitioned(subarray const& self, size_type n) -> partitioned_const_type {return self .partitioned(n);} - friend BOOST_MULTI_HD constexpr auto partitioned(subarray & self, size_type n) -> partitioned_type {return self .partitioned(n);} - friend BOOST_MULTI_HD constexpr auto partitioned(subarray && self, size_type n) -> partitioned_type {return std::move(self).partitioned(n);} + // friend BOOST_MULTI_HD constexpr auto partitioned(const_subarray const& self, size_type n) -> partitioned_const_type {return self .partitioned(n);} + // friend BOOST_MULTI_HD constexpr auto partitioned(const_subarray & self, size_type n) -> partitioned_type {return self .partitioned(n);} + // friend BOOST_MULTI_HD constexpr auto partitioned(const_subarray && self, size_type n) -> partitioned_type {return std::move(self).partitioned(n);} private: - BOOST_MULTI_HD constexpr auto chunked_aux_(size_type count) const -> partitioned_type { + BOOST_MULTI_HD constexpr auto chunked_aux_(size_type count) const { assert( this->size() % count == 0 ); return partitioned_aux_(this->size()/count); } public: // in Mathematica this is called Partition https://reference.wolfram.com/language/ref/Partition.html in RangesV3 it is called chunk - BOOST_MULTI_HD constexpr auto chunked(size_type count) const& -> partitioned_const_type {return chunked_aux_(count);} - BOOST_MULTI_HD constexpr auto chunked(size_type count) & -> partitioned_type {return chunked_aux_(count);} - BOOST_MULTI_HD constexpr auto chunked(size_type count) && -> partitioned_type {return chunked_aux_(count);} + BOOST_MULTI_HD constexpr auto chunked(size_type count) const& -> const_subarray {return chunked_aux_(count);} + // BOOST_MULTI_HD constexpr auto chunked(size_type count) & -> partitioned_type {return chunked_aux_(count);} + // BOOST_MULTI_HD constexpr auto chunked(size_type count) && -> partitioned_type {return chunked_aux_(count);} + + constexpr auto tiled(size_type count) const & { + assert(count != 0); + struct divided_type { + const_subarray quotient; + const_subarray remainder; + }; + return divided_type{ + this->taked(this->size() - (this->size() % count)).chunked(count), + this->dropped(this->size() - (this->size() % count)) + }; + } private: - constexpr auto reversed_aux_() const -> subarray { + constexpr auto reversed_aux_() const -> const_subarray { auto new_layout = this->layout(); new_layout.reverse(); return {new_layout, types::base_}; @@ -1213,164 +1398,122 @@ struct subarray : array_types { public: constexpr auto reversed() const& -> basic_const_array { return reversed_aux_(); } - constexpr auto reversed() & -> subarray { return reversed_aux_(); } - constexpr auto reversed() && -> subarray { return reversed_aux_(); } - friend constexpr auto reversed(subarray const& self) -> basic_const_array { return self .reversed(); } - friend constexpr auto reversed(subarray & self) -> subarray { return self .reversed(); } - friend constexpr auto reversed(subarray && self) -> subarray { return std::move(self).reversed(); } + constexpr auto reversed() & -> const_subarray { return reversed_aux_(); } + constexpr auto reversed() && -> const_subarray { return reversed_aux_(); } + friend constexpr auto reversed(const_subarray const& self) -> basic_const_array { return self .reversed(); } + friend constexpr auto reversed(const_subarray & self) -> const_subarray { return self .reversed(); } + friend constexpr auto reversed(const_subarray && self) -> const_subarray { return std::move(self).reversed(); } private: BOOST_MULTI_HD constexpr auto transposed_aux_() const { auto new_layout = this->layout(); new_layout.transpose(); - return subarray(new_layout, types::base_); + return const_subarray(new_layout, types::base_); } public: - BOOST_MULTI_HD constexpr auto transposed() const& -> basic_const_array { return transposed_aux_(); } - BOOST_MULTI_HD constexpr auto transposed() & -> subarray { return transposed_aux_(); } - BOOST_MULTI_HD constexpr auto transposed() && -> subarray { return transposed_aux_(); } + BOOST_MULTI_HD constexpr auto transposed() const& -> const_subarray { return transposed_aux_(); } + // BOOST_MULTI_HD constexpr auto transposed() & -> const_subarray { return transposed_aux_(); } + // BOOST_MULTI_HD constexpr auto transposed() && -> const_subarray { return transposed_aux_(); } - friend BOOST_MULTI_HD /*constexpr*/ auto transposed(subarray const& self) -> basic_const_array { return self .transposed(); } - friend BOOST_MULTI_HD /*constexpr*/ auto transposed(subarray & self) -> subarray { return self .transposed(); } - friend BOOST_MULTI_HD /*constexpr*/ auto transposed(subarray && self) -> subarray { return std::move(self).transposed(); } + // friend BOOST_MULTI_HD /*constexpr*/ auto transposed(const_subarray const& self) -> basic_const_array { return self .transposed(); } + // friend BOOST_MULTI_HD /*constexpr*/ auto transposed(const_subarray & self) -> const_subarray { return self .transposed(); } + // friend BOOST_MULTI_HD /*constexpr*/ auto transposed(const_subarray && self) -> const_subarray { return std::move(self).transposed(); } BOOST_MULTI_FRIEND_CONSTEXPR BOOST_MULTI_HD - auto operator~ (subarray const& self) -> basic_const_array {return self.transposed();} - BOOST_MULTI_FRIEND_CONSTEXPR BOOST_MULTI_HD - auto operator~ (subarray& self) -> subarray {return self.transposed();} - BOOST_MULTI_FRIEND_CONSTEXPR BOOST_MULTI_HD - auto operator~ (subarray&& self) -> subarray {return std::move(self).transposed();} + auto operator~ (const_subarray const& self) -> const_subarray {return self.transposed();} + // BOOST_MULTI_FRIEND_CONSTEXPR BOOST_MULTI_HD + // auto operator~ (const_subarray& self) -> const_subarray {return self.transposed();} + // BOOST_MULTI_FRIEND_CONSTEXPR BOOST_MULTI_HD + // auto operator~ (const_subarray&& self) -> const_subarray {return std::move(self).transposed();} private: BOOST_MULTI_HD constexpr auto rotated_aux_() const { typename types::layout_t new_layout = this->layout(); new_layout.rotate(); - return subarray(new_layout, types::base_); + return const_subarray(new_layout, types::base_); } - - public: - BOOST_MULTI_HD constexpr auto rotated() && -> subarray { return rotated_aux_(); } - BOOST_MULTI_HD constexpr auto rotated() & -> subarray { return rotated_aux_(); } - BOOST_MULTI_HD constexpr auto rotated() const& -> basic_const_array { return rotated_aux_(); } - - BOOST_MULTI_FRIEND_CONSTEXPR auto rotated(subarray const& self) { return self .rotated(); } - BOOST_MULTI_FRIEND_CONSTEXPR auto rotated(subarray & self) { return self .rotated(); } - BOOST_MULTI_FRIEND_CONSTEXPR auto rotated(subarray && self) { return std::move(self).rotated(); } - - private: BOOST_MULTI_HD constexpr auto unrotated_aux_() const { typename types::layout_t new_layout = this->layout(); new_layout.unrotate(); - return subarray(new_layout, types::base_); + return const_subarray(new_layout, types::base_); } public: - BOOST_MULTI_HD constexpr auto unrotated() & -> subarray { return unrotated_aux_(); } - BOOST_MULTI_HD constexpr auto unrotated() && -> subarray { return unrotated_aux_(); } - BOOST_MULTI_HD constexpr auto unrotated() const& -> basic_const_array /*const*/ { return unrotated_aux_(); } // NOLINT(readability-const-return-type) + BOOST_MULTI_HD constexpr auto rotated() const& -> const_subarray { return rotated_aux_(); } + BOOST_MULTI_HD constexpr auto unrotated() const& -> const_subarray { return unrotated_aux_(); } - BOOST_MULTI_FRIEND_CONSTEXPR auto unrotated(subarray const& self) { return self .unrotated(); } - BOOST_MULTI_FRIEND_CONSTEXPR auto unrotated(subarray & self) { return self .unrotated(); } - BOOST_MULTI_FRIEND_CONSTEXPR auto unrotated(subarray && self) { return std::move(self).unrotated(); } + // BOOST_MULTI_FRIEND_CONSTEXPR auto unrotated(const_subarray const& self) { return self .unrotated(); } + // BOOST_MULTI_FRIEND_CONSTEXPR auto unrotated(const_subarray & self) { return self .unrotated(); } + // BOOST_MULTI_FRIEND_CONSTEXPR auto unrotated(const_subarray && self) { return std::move(self).unrotated(); } - constexpr auto operator|(typename subarray::size_type n) & -> decltype(auto) { return partitioned(n); } - constexpr auto operator|(typename subarray::size_type n) && -> decltype(auto) { return std::move(*this).partitioned(n); } - constexpr auto operator|(typename subarray::size_type n) const& -> decltype(auto) { return partitioned(n); } + // constexpr auto operator|(typename const_subarray::size_type n) & -> decltype(auto) { return partitioned(n); } + // constexpr auto operator|(typename const_subarray::size_type n) && -> decltype(auto) { return std::move(*this).partitioned(n); } + // constexpr auto operator|(typename const_subarray::size_type n) const& -> decltype(auto) { return partitioned(n); } private: - template friend struct subarray; + template friend struct const_subarray; - // BOOST_MULTI_HD constexpr auto paren_aux() & -> subarray {return *this;} - // BOOST_MULTI_HD constexpr auto paren_aux() && -> subarray {return this->operator()();} - BOOST_MULTI_HD constexpr auto paren_aux_() const {return subarray{this->layout(), this->base_};} + BOOST_MULTI_HD constexpr auto paren_aux_() const& {return const_subarray(this->layout(), this->base_);} public: - BOOST_MULTI_HD constexpr auto operator()() & -> subarray {return paren_aux_();} - BOOST_MULTI_HD constexpr auto operator()() && -> subarray {return paren_aux_();} - BOOST_MULTI_HD constexpr auto operator()() const& -> basic_const_array /*const*/ {return paren_aux_();} // NOLINT(readability-redundant-access-specifiers,readability-const-return-type) + BOOST_MULTI_HD constexpr auto operator()() const& -> const_subarray {return paren_aux_();} // NOLINT(readability-redundant-access-specifiers,readability-const-return-type) private: - template - constexpr auto paren_aux_(index_range irng, As... args) & { - // TODO(correaa) investigate how to make it BOOST_MULTI_HD - // return range(a).rotated().paren_aux(as...).unrotated(); // TODO(correaa) compact - // auto&& tmp = range(irng); - // auto&& tmp2 = - // std::move(tmp). - // rotated(); - // auto&& tmp3 = std::move(tmp2).paren_aux(args...); - // auto&& ret = std::move(tmp3).unrotated(); - // return std::move(tmp3).unrotated(); // std::move(ret); - return range(irng).rotated().paren_aux_(args...).unrotated(); - } - template - constexpr auto paren_aux_(index_range irng, As... args) && { - // TODO(correaa) investigate how to make it BOOST_MULTI_HD - // auto&& tmp = std::move(*this).range(irng); - // auto&& tmp2 = std::move(tmp).rotated().paren_aux(args...); - // return std::move(tmp2).unrotated(); - return std::move(*this).range(irng).rotated().paren_aux_(args...).unrotated(); - } - template constexpr auto paren_aux_(index_range rng, As... args) const& {return range(rng).rotated().paren_aux_(args...).unrotated();} + template BOOST_MULTI_HD constexpr auto paren_aux_(index_range rng, As... args) const& {return range(rng).rotated().paren_aux_(args...).unrotated();} - template constexpr auto paren_aux_(intersecting_range inr, As... args) & -> decltype(auto) {return paren_aux_(intersection(this->extension(), inr), args...);} - template constexpr auto paren_aux_(intersecting_range inr, As... args) && -> decltype(auto) {return paren_aux_(intersection(this->extension(), inr), args...);} - template constexpr auto paren_aux_(intersecting_range inr, As... args) const& -> decltype(auto) {return paren_aux_(intersection(this->extension(), inr), args...);} + // template constexpr auto paren_aux_(intersecting_range inr, As... args) & -> decltype(auto) {return paren_aux_(intersection(this->extension(), inr), args...);} + // template constexpr auto paren_aux_(intersecting_range inr, As... args) && -> decltype(auto) {return paren_aux_(intersection(this->extension(), inr), args...);} + template BOOST_MULTI_HD constexpr auto paren_aux_(intersecting_range inr, As... args) const& -> decltype(auto) {return paren_aux_(intersection(this->extension(), inr), args...);} - template BOOST_MULTI_HD constexpr auto paren_aux_(index idx, As... args) & -> decltype(auto) {return operator[](idx).paren_aux_(args...);} - template BOOST_MULTI_HD constexpr auto paren_aux_(index idx, As... args) && -> decltype(auto) {return operator[](idx).paren_aux_(args...);} + // template BOOST_MULTI_HD constexpr auto paren_aux_(index idx, As... args) & -> decltype(auto) {return operator[](idx).paren_aux_(args...);} + // template BOOST_MULTI_HD constexpr auto paren_aux_(index idx, As... args) && -> decltype(auto) {return operator[](idx).paren_aux_(args...);} template BOOST_MULTI_HD constexpr auto paren_aux_(index idx, As... args) const& -> decltype(auto) {return operator[](idx).paren_aux_(args...);} public: // vvv DO NOT remove default parameter `= irange` : the default template parameters below help interpret the expression `{first, last}` syntax as index ranges - template constexpr auto operator()(A1 arg1) const& -> decltype(auto) {return paren_aux_(arg1);} // NOLINT(whitespace/line_length) pattern line - template constexpr auto operator()(A1 arg1, A2 arg2) const& -> decltype(auto) {return paren_aux_(arg1, arg2);} // NOLINT(whitespace/line_length) pattern line - template constexpr auto operator()(A1 arg1, A2 arg2, A3 arg3) const& -> decltype(auto) {return paren_aux_(arg1, arg2, arg3);} // NOLINT(whitespace/line_length) pattern line - template constexpr auto operator()(A1 arg1, A2 arg2, A3 arg3, A4 arg4, As... args) const& -> decltype(auto) {return paren_aux_(arg1, arg2, arg3, arg4, args...);} // NOLINT(whitespace/line_length) pattern line - - template constexpr auto operator()(A1 arg1) & -> decltype(auto) {return paren_aux_(arg1);} // NOLINT(whitespace/line_length) pattern line - template constexpr auto operator()(A1 arg1, A2 arg2) & -> decltype(auto) {return paren_aux_(arg1, arg2);} // NOLINT(whitespace/line_length) pattern line - template /*[[gnu::pure]]*/ constexpr auto operator()(A1 arg1, A2 arg2, A3 arg3) & -> decltype(auto) {return paren_aux_(arg1, arg2, arg3);} // NOLINT(whitespace/line_length) pattern line - template constexpr auto operator()(A1 arg1, A2 arg2, A3 arg3, A4 arg4, As... args) & -> decltype(auto) {return paren_aux_(arg1, arg2, arg3, arg4, args...);} // NOLINT(whitespace/line_length) pattern line - - template constexpr auto operator()(A1 arg1) && -> decltype(auto) {return std::move(*this).paren_aux_(arg1);} // NOLINT(whitespace/line_length) pattern line - template BOOST_MULTI_HD constexpr auto operator()(A1 arg1, A2 arg2) && -> decltype(auto) {return std::move(*this).paren_aux_(arg1, arg2);} // NOLINT(whitespace/line_length) pattern line - template constexpr auto operator()(A1 arg1, A2 arg2, A3 arg3) && -> decltype(auto) {return std::move(*this).paren_aux_(arg1, arg2, arg3);} // NOLINT(whitespace/line_length) pattern line - template constexpr auto operator()(A1 arg1, A2 arg2, A3 arg3, A4 arg4, As... args) && -> decltype(auto) {return std::move(*this).paren_aux_(arg1, arg2, arg3, arg4, args...);} // NOLINT(whitespace/line_length) pattern line + template BOOST_MULTI_HD constexpr auto operator()(A1 arg1) const& -> decltype(auto) {return paren_aux_(arg1);} // NOLINT(whitespace/line_length) pattern line + template BOOST_MULTI_HD constexpr auto operator()(A1 arg1, A2 arg2) const& -> decltype(auto) {return paren_aux_(arg1, arg2);} // NOLINT(whitespace/line_length) pattern line + template BOOST_MULTI_HD constexpr auto operator()(A1 arg1, A2 arg2, A3 arg3) const& -> decltype(auto) {return paren_aux_(arg1, arg2, arg3);} // NOLINT(whitespace/line_length) pattern line + template BOOST_MULTI_HD constexpr auto operator()(A1 arg1, A2 arg2, A3 arg3, A4 arg4, As... args) const& -> decltype(auto) {return paren_aux_(arg1, arg2, arg3, arg4, args...);} private: - template constexpr auto apply_impl_(Tuple const& tuple, std::index_sequence/*012*/) const& -> decltype(auto) {return this->operator()(std::get(tuple)...);} - template constexpr auto apply_impl_(Tuple const& tuple, std::index_sequence/*012*/) & -> decltype(auto) {return this->operator()(std::get(tuple)...);} - template constexpr auto apply_impl_(Tuple const& tuple, std::index_sequence/*012*/) && -> decltype(auto) {return std::move(*this).operator()(std::get(tuple)...);} + template BOOST_MULTI_HD constexpr auto apply_impl_(Tuple const& tuple, std::index_sequence/*012*/) const& -> decltype(auto) {return this->operator()(std::get(tuple)...);} public: template constexpr auto apply(Tuple const& tuple) const& -> decltype(auto) {return apply_impl_(tuple, std::make_index_sequence::value>());} - template constexpr auto apply(Tuple const& tuple) && -> decltype(auto) {return apply_impl_(tuple, std::make_index_sequence::value>());} - template constexpr auto apply(Tuple const& tuple) & -> decltype(auto) {return apply_impl_(tuple, std::make_index_sequence::value>());} + // template constexpr auto apply(Tuple const& tuple) && -> decltype(auto) {return apply_impl_(tuple, std::make_index_sequence::value>());} + // template constexpr auto apply(Tuple const& tuple) & -> decltype(auto) {return apply_impl_(tuple, std::make_index_sequence::value>());} using iterator = array_iterator; - using const_iterator = array_iterator; - using move_iterator = array_iterator; + using const_iterator = array_iterator; + using move_iterator = array_iterator; + + // using move_iterator = array_iterator; // using reverse_iterator [[deprecated]] = std::reverse_iterator< iterator>; // using const_reverse_iterator [[deprecated]] = std::reverse_iterator; - private: - BOOST_MULTI_HD constexpr explicit subarray(iterator begin, iterator end) - : subarray( - layout_type{begin->layout(), begin.stride(), 0, begin.stride() * (end - begin)}, - begin.base() - ) { - assert(begin.stride() == end.stride()); // NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay) : normal in a constexpr function - assert(begin->layout() == end->layout()); // NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay) : normal in a constexpr function + const_subarray(iterator first, iterator last) + : const_subarray(layout_type(first->layout(), first.stride(), 0, (last - first)*first->size()), first.base()) { + assert(first->layout() == last->layout()); } + private: + // [[deprecated("remove")]] BOOST_MULTI_HD constexpr explicit const_subarray(iterator begin, iterator end) + // : const_subarray( + // layout_type{begin->layout(), begin.stride(), 0, begin.stride() * (end - begin)}, + // begin.base() + // ) { + // assert(begin.stride() == end.stride()); // NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay) : normal in a constexpr function + // assert(begin->layout() == end->layout()); // NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay) : normal in a constexpr function + // } + friend BOOST_MULTI_HD constexpr auto ref(iterator begin, iterator end) -> multi::subarray; public: - using ptr = subarray_ptr; - using const_ptr = subarray_ptr; + using ptr = subarray_ptr; + using const_ptr = const_subarray_ptr; // TODO(correaa) add const_subarray_ptr using pointer = ptr; using const_pointer = const_ptr; @@ -1383,166 +1526,87 @@ struct subarray : array_types { constexpr auto addressof() & -> ptr { return addressof_aux_(); } constexpr auto addressof() const& -> const_ptr { return addressof_aux_(); } - // NOLINTNEXTLINE(runtime/operator) //NOSONAR - constexpr auto operator&() && {return addressof();} // NOLINT(google-runtime-operator) //NOSONAR - // NOLINTNEXTLINE(runtime/operator) //NOSONAR - [[deprecated("controversial")]] constexpr auto operator&() & {return addressof();} // NOLINT(google-runtime-operator) //NOSONAR - // NOLINTNEXTLINE(runtime/operator) //NOSONAR - [[deprecated("controversial")]] constexpr auto operator&() const& {return addressof();} // NOLINT(google-runtime-operator) //NOSONAR + // NOLINTBEGIN(google-runtime-operator) //NOSONAR + // operator& is not defined for r-values anyway + constexpr auto operator&() && { return addressof(); } // NOLINT(runtime/operator) //NOSONAR + // [[deprecated("controversial")]] + constexpr auto operator&() & { return addressof(); } // NOLINT(runtime/operator) //NOSONAR + // [[deprecated("controversial")]] + constexpr auto operator&() const& { return addressof(); } // NOLINT(runtime/operator) //NOSONAR + // NOLINTEND(google-runtime-operator) private: + #if defined(__clang__) + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wunknown-warning-option" + #pragma clang diagnostic ignored "-Wunsafe-buffer-usage" // TODO(correaa) use checked span + #endif + BOOST_MULTI_HD constexpr auto begin_aux_() const {return iterator(types::base_ , this->sub(), this->stride());} constexpr auto end_aux_ () const {return iterator(types::base_ + this->nelems(), this->sub(), this->stride());} + #if defined(__clang__) + #pragma clang diagnostic pop + #endif + public: BOOST_MULTI_HD constexpr auto begin() & {return begin_aux_();} constexpr auto end () & {return end_aux_() ;} - friend BOOST_MULTI_HD /*constexpr*/ auto begin(subarray& self) {return self.begin();} - friend constexpr auto end (subarray& self) {return self.end ();} + friend BOOST_MULTI_HD /*constexpr*/ auto begin(const_subarray& self) {return self.begin();} + friend constexpr auto end (const_subarray& self) {return self.end ();} constexpr auto begin() && {return begin();} constexpr auto end () && {return end() ;} - friend /*constexpr*/ auto begin(subarray&& self) {return std::move(self).begin();} - friend /*constexpr*/ auto end (subarray&& self) {return std::move(self).end() ;} + friend /*constexpr*/ auto begin(const_subarray&& self) {return std::move(self).begin();} + friend /*constexpr*/ auto end (const_subarray&& self) {return std::move(self).end() ;} constexpr auto begin() const& -> const_iterator { return begin_aux_(); } constexpr auto end () const& -> const_iterator { return end_aux_() ; } - friend /*constexpr*/ auto begin(subarray const& self) -> const_iterator { return self.begin(); } // NOLINT(whitespace/indent) constexpr doesn't work with nvcc friend - friend /*constexpr*/ auto end (subarray const& self) -> const_iterator { return self.end() ; } // NOLINT(whitespace/indent) constexpr doesn't work with nvcc friend + friend /*constexpr*/ auto begin(const_subarray const& self) -> const_iterator { return self.begin(); } // NOLINT(whitespace/indent) constexpr doesn't work with nvcc friend + friend /*constexpr*/ auto end (const_subarray const& self) -> const_iterator { return self.end() ; } // NOLINT(whitespace/indent) constexpr doesn't work with nvcc friend BOOST_MULTI_HD constexpr auto cbegin() const& {return begin();} /*fd*/ constexpr auto cend() const& {return end() ;} - friend constexpr auto cbegin(subarray const& self) {return self.cbegin();} - friend constexpr auto cend (subarray const& self) {return self.cend() ;} - - constexpr auto mbegin() & { return move_iterator{begin()}; } - constexpr auto mend() & { return move_iterator{end() }; } - friend constexpr auto mbegin(subarray & self) { return self.mbegin(); } - friend constexpr auto mend (subarray & self) { return self.mend() ; } - - constexpr auto mbegin() && {return mbegin();} - constexpr auto mend() && {return mend() ;} - friend constexpr auto mbegin(subarray && self) {return std::move(self).mbegin();} - friend constexpr auto mend (subarray && self) {return std::move(self).mend() ;} - - constexpr auto mbegin() const& -> const_iterator {return begin();} - constexpr auto mend() const& -> const_iterator {return end() ;} - friend constexpr auto mbegin(subarray const& self) {return self.mbegin();} - friend constexpr auto mend (subarray const& self) {return self.mend() ;} - - using cursor = cursor_t; + friend constexpr auto cbegin(const_subarray const& self) {return self.cbegin();} + friend constexpr auto cend (const_subarray const& self) {return self.cend() ;} + using cursor = cursor_t; + using const_cursor = cursor_t; private: constexpr auto home_aux_() const {return cursor(this->base_, this->strides());} public: - using const_cursor = cursor_t; - constexpr auto home() const& -> const_cursor { return home_aux_(); } - constexpr auto home() && -> cursor { return home_aux_(); } - constexpr auto home() & -> cursor { return home_aux_(); } + + // const_subarray(cursor home, typename const_subarray::sizes_type szs) {} template constexpr auto assign(It first) & -> It { adl_copy_n(first, this->size(), begin()); std::advance(first, this->size()); return first; } template constexpr auto assign(It first)&& -> It { return assign(first);} - template< - class Range, - class = std::enable_if_t>, - class = std::enable_if_t::value>, - class = decltype(adl_copy_n(adl_begin(std::declval()), std::declval(), std::declval())) - > - constexpr auto operator=(Range const& rng) & // check that you LHS is not read-only - -> subarray& { // lints(cppcoreguidelines-c-copy-assignment-signature,misc-unconventional-assign-operator) - assert(this->size() == rng.size()); // NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay) : normal in a constexpr function - // MULTI_MARK_SCOPE(std::string{"multi::operator= D="}+std::to_string(D)+" from range to "+typeid(T).name() ); - // adl_copy_n(adl_begin(r), this->size(), begin()); - adl_copy(adl_begin(rng), adl_end(rng), begin()); - return *this; - } - template>> - constexpr auto operator=(Range const& rng) && -> subarray& {operator=(rng); return *this;} - - template - constexpr auto operator=(subarray const& other) && -> subarray& {operator=(other); return *this;} - - template - constexpr - auto operator=(subarray const& other) & -> subarray& { - assert(this->extension() == other.extension()); // NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay) : normal in a constexpr function - // MULTI_MARK_SCOPE( std::string{"multi::operator= (D="}+std::to_string(D)+") from "+typeid(TT).name()+" to "+typeid(T).name() ); - this->elements() = other.elements(); -// if(this->is_empty()) {return *this;} -// if(this->num_elements() == this->nelems() and o.num_elements() == this->nelems() and this->layout() == o.layout()) { -// this->elements() = o.elements(); -//// adl_copy_n(o.base(), o.num_elements(), this->base()); -// } else if(o.stride() < (~o).stride()) { -// (~(*this)).elements() = o.elements(); -//// adl_copy_n( (~o).begin(), (~o).size(), (~(*this)).begin() ); -// } else { -// assign(o.begin()); -// } - return *this; - } - - constexpr - auto operator=(subarray const& other) & -> subarray& { - if(this == std::addressof(other)) {return *this;} // lints(cert-oop54-cpp) - assert(this->extension() == other.extension()); // NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay) : normal in a constexpr function - // MULTI_MARK_SCOPE("multi::operator= [D="+std::to_string(D)+"] from "+typeid(T).name()+" to "+typeid(T).name() ); - elements() = other.elements(); -// if(this->num_elements() == this->nelems() and o.num_elements() == this->nelems() and this->layout() == o.layout()) { -// adl_copy_n(o.base(), o.num_elements(), this->base()); -// } else if(o.stride() < (~o).stride()) { -// adl_copy_n( (~o).begin(), (~o).size(), (~(*this)).begin() ); -// } else { -// assign(o.begin()); -// } - return *this; - } - - constexpr auto operator=(subarray const& other) && - -> subarray& { // lints(cppcoreguidelines-c-copy-assignment-signature,misc-unconventional-assign-operator) - if(this == std::addressof(other)) {return *this;} // lints(cert-oop54-cpp) - operator=(other); - return *this; // lints(cppcoreguidelines-c-copy-assignment-signature,misc-unconventional-assign-operator) - } - template< class Range, std::enable_if_t>::value, int> = 0, // std::enable_if_t, int> =0, - class = decltype(Range(std::declval(), std::declval()))> + class = decltype(Range(std::declval(), std::declval()))> constexpr explicit operator Range() const { return Range(begin(), end()); } // NOLINT(fuchsia-default-arguments-calls) for example std::vector(it, ti, alloc = {}) - template constexpr void swap(Array&& other) && noexcept { - assert( std::move(*this).extension() == std::forward(other).extension() ); // NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay) : normal in a constexpr function - elements().swap(other.elements()); - // adl_swap_ranges(this->begin(), this->end(), adl_begin(std::forward(o))); - } - template constexpr void swap(A&& other) & noexcept {return swap(std::forward(other));} - - friend constexpr void swap(subarray&& self, subarray&& other) noexcept {std::move(self).swap(std::move(other));} - - template constexpr void swap(subarray const& self, Array&& other) noexcept {self.swap(std::forward(other));} // TODO(correaa) remove - template constexpr void swap(Array&& other, subarray const& self) noexcept {self.swap(std::forward(other));} - template - friend constexpr auto operator==(subarray const& self, subarray const& other) -> bool { + friend constexpr auto operator==(const_subarray const& self, const_subarray const& other) -> bool { return (self.extension() == other.extension()) && (self.elements() == other.elements()); } template - friend constexpr auto operator!=(subarray const& self, subarray const& other) -> bool { + friend constexpr auto operator!=(const_subarray const& self, const_subarray const& other) -> bool { return (self.extension() != other.extension()) || (self.elements() != other.elements()); } - constexpr auto operator==(subarray const& other) const -> bool { + constexpr auto operator==(const_subarray const& other) const -> bool { return (this->extension() == other.extension()) && (this->elements() == other.elements()); } - constexpr auto operator!=(subarray const& other) const -> bool { + constexpr auto operator!=(const_subarray const& other) const -> bool { return (this->extension() != other.extension()) || (this->elements() != other.elements()); } - friend constexpr auto lexicographical_compare(subarray const& self, subarray const& other) -> bool { + friend constexpr auto lexicographical_compare(const_subarray const& self, const_subarray const& other) -> bool { if(self.extension().first() > other.extension().first()) {return true ;} if(self.extension().first() < other.extension().first()) {return false;} return adl_lexicographical_compare( @@ -1551,16 +1615,20 @@ struct subarray : array_types { ); } - constexpr auto operator< (subarray const& other) const& -> bool {return lexicographical_compare(*this, other);} - constexpr auto operator<=(subarray const& other) const& -> bool {return *this == other || lexicographical_compare(*this, other);} - constexpr auto operator> (subarray const& other) const& -> bool {return other < *this;} + constexpr auto operator< (const_subarray const& other) const& -> bool {return lexicographical_compare(*this, other);} + constexpr auto operator<=(const_subarray const& other) const& -> bool {return *this == other || lexicographical_compare(*this, other);} + constexpr auto operator> (const_subarray const& other) const& -> bool {return other < *this;} - template::template rebind, std::enable_if_t< std::is_const_v::element_type>,int> =0> + template::template rebind, + std::enable_if_t< std::is_const_v::element_type>,int> =0 // NOLINT(modernize-use-constraints) TODO(correaa) + > constexpr auto static_array_cast() const & { // name taken from std::static_pointer_cast return subarray(this->layout(), static_cast(this->base_)); // TODO(correaa) might violate constness } - template::template rebind, std::enable_if_t::element_type>,int> =0> + template::template rebind, + std::enable_if_t::element_type>,int> =0 // NOLINT(modernize-use-constraints) TODO(correaa) for C++20 + > [[deprecated("violates constness")]] constexpr auto static_array_cast() const & { // name taken from std::static_pointer_cast return subarray(this->layout(), static_cast(this->base_)); // TODO(correaa) might violate constness @@ -1568,12 +1636,12 @@ struct subarray : array_types { template::template rebind> constexpr auto static_array_cast() && { // name taken from std::static_pointer_cast - return subarray(this->layout(), static_cast(this->base())); + return subarray(this->layout(), static_cast(this->base_)); } template::template rebind> constexpr auto static_array_cast() & { // name taken from std::static_pointer_cast - return subarray(this->layout(), static_cast(this->base())); + return subarray(this->layout(), static_cast(this->base_)); } private: @@ -1609,8 +1677,8 @@ struct subarray : array_types { constexpr auto element_transformed(UF&& fun) && {return element_transformed(std::forward(fun));} template< - class T2, class P2 = typename std::pointer_traits::template rebind, - class Element = typename subarray::element, + class T2, class P2 = typename std::pointer_traits::template rebind, + class Element = typename const_subarray::element, class PM = T2 Element::* > constexpr auto member_cast(PM member) const& -> subarray { @@ -1623,8 +1691,8 @@ struct subarray : array_types { } template< - class T2, class P2 = typename std::pointer_traits::template rebind, - class Element = typename subarray::element, + class T2, class P2 = typename std::pointer_traits::template rebind, + class Element = typename const_subarray::element, class PM = T2 Element::* > constexpr auto member_cast(PM member) & -> subarray { @@ -1637,21 +1705,21 @@ struct subarray : array_types { } template< - class T2, class P2 = typename std::pointer_traits::template rebind, - class Element = typename subarray::element, + class T2, class P2 = typename std::pointer_traits::template rebind, + class Element = typename const_subarray::element, class PM = T2 Element::* > constexpr auto member_cast(PM member) && -> subarray { return this->member_cast(member); } - template::template rebind> + template::template rebind> using rebind = subarray, D, P2>; template< class T2 = std::remove_const_t, class P2 = typename std::pointer_traits::template rebind, - std::enable_if_t< + std::enable_if_t< // NOLINT(modernize-use-constraints) TODO(correaa) for C++20 std::is_same_v< // check that pointer family is not changed typename std::pointer_traits::template rebind, typename std::pointer_traits::template rebind @@ -1659,7 +1727,7 @@ struct subarray : array_types { && std::is_same_v< // check that only constness is changed std::remove_const_t::element_type>, - std::remove_const_t + std::remove_const_t > , int> =0 > @@ -1675,9 +1743,6 @@ struct subarray : array_types { return rebind{this->layout(), this->base()}; } - constexpr auto element_moved() & {return rebind{this->layout(), element_move_ptr{this->base()}};} - constexpr auto element_moved() && {return element_moved();} - private: template constexpr auto reinterpret_array_cast_aux_() const -> rebind { @@ -1694,38 +1759,36 @@ struct subarray : array_types { template::template rebind> constexpr auto reinterpret_array_cast() const& {return reinterpret_array_cast_aux_().as_const();} - template::template rebind> - constexpr auto reinterpret_array_cast() & {return reinterpret_array_cast_aux_();} - - template::template rebind> - constexpr auto reinterpret_array_cast() && {return reinterpret_array_cast_aux_();} - - template::template rebind > - constexpr auto reinterpret_array_cast(multi::size_type count) & -> subarray, D + 1, P2> { - // static_assert( sizeof(T)%sizeof(T2) == 0, - // "error: reinterpret_array_cast is limited to integral stride values"); - - assert( count > 0 ); - assert( sizeof(T) == sizeof(T2)*static_cast(count) ); // NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay) : normal in a constexpr function - return subarray, D + 1, P2>( - layout_t(this->layout().scale(sizeof(T), sizeof(T2)), 1, 0, count).rotate(), // NOLINT(bugprone-sizeof-expression) T and T2 are size compatible (see static_assert above) - reinterpret_pointer_cast(this->base()) // if ADL gets confused here (e.g. multi:: and thrust::) then adl_reinterpret_pointer_cast will be necessary - ); - } - - template::template rebind > - constexpr auto reinterpret_array_cast(multi::size_type count) && -> subarray, D + 1, P2> {return reinterpret_array_cast(count);} - - template::template rebind > - constexpr auto reinterpret_array_cast(size_type count) const& -> subarray, D + 1, P2> { - static_assert( sizeof(T)%sizeof(T2) == 0, - "error: reinterpret_array_cast is limited to integral stride values"); - - assert( sizeof(T) == sizeof(T2)*static_cast(count) ); // NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay) : checck implicit size compatibility - return subarray, D + 1, P2>( - layout_t(this->layout().scale(sizeof(T), sizeof(T2)), 1, 0, count).rotate(), - static_cast(static_cast(this->base_)) // NOLINT(bugprone-casting-through-void) direct reinterepret_cast doesn't work here - ); + template< + class T2, + class P2 = + std::conditional_t< + std::is_const_v::element_type>, + typename std::pointer_traits::template rebind, + typename std::pointer_traits::template rebind + > + > + constexpr auto reinterpret_array_cast(size_type count) const& { + static_assert(sizeof(T) % sizeof(T2) == 0, "error: reinterpret_array_cast is limited to integral stride values"); + + assert(sizeof(T) == sizeof(T2) * static_cast(count)); // NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay) : checck implicit size compatibility + + if constexpr(std::is_pointer_v) { + using void_ptr_like = std::conditional_t< + std::is_const_vbase_)>::element_type>, + typename std::pointer_traits::template rebind, + typename std::pointer_traits::template rebind + >; + return const_subarray( + layout_t(this->layout().scale(sizeof(T), sizeof(T2)), 1, 0, count).rotate(), + static_cast(static_cast(this->base_)) // NOLINT(bugprone-casting-through-void) direct reinterepret_cast doesn't work here for some exotic pointers (e.g. thrust::pointer) + ); + } else { // TODO(correaa) try to unify both if-branches + return const_subarray( + layout_t(this->layout().scale(sizeof(T), sizeof(T2)), 1, 0, count).rotate(), + reinterpret_cast(this->base_) // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast,bugprone-casting-through-void) direct reinterepret_cast doesn't work here + ); + } } template @@ -1741,26 +1804,510 @@ struct subarray : array_types { } }; +template +BOOST_MULTI_HD constexpr auto move(T&& val) noexcept -> decltype(auto) { + if constexpr(has_member_move::value) { + return std::forward(val).move(); + } else { + return std::move(std::forward(val)); + } +} + +template +class move_subarray : public subarray { + BOOST_MULTI_HD constexpr move_subarray(subarray& other) // NOLINT(google-explicit-constructor,hicpp-explicit-conversions) TODO(correa) check if this is necessary + : subarray(other.layout(), other.mutable_base()) {} + + friend class subarray; + + public: + using subarray::operator[]; + BOOST_MULTI_HD constexpr auto operator[](index idx) && -> decltype(auto) { + return multi::move(subarray::operator[](idx)); + } + + using subarray::begin; + using subarray::end; + + auto begin() && { return this->mbegin(); } + auto end () && { return this->mend (); } +}; + +template +class subarray : public const_subarray { + BOOST_MULTI_HD constexpr subarray(const_subarray const& other) // NOLINT(google-explicit-constructor,hicpp-explicit-conversions) TODO(correa) check if this is necessary + : subarray(other.layout(), other.mutable_base()) {} + + template friend class subarray; + template friend struct subarray_ptr; + + template friend struct array_iterator; + + subarray(subarray const&) = default; + + public: + BOOST_MULTI_HD constexpr auto move() {return move_subarray(*this);} + friend BOOST_MULTI_HD constexpr auto move(subarray& self) { return self.move(); } + friend BOOST_MULTI_HD constexpr auto move(subarray&& self) { return std::move(self).move(); } + + using move_iterator = array_iterator; + + subarray(subarray&&) noexcept = default; + ~subarray() = default; + + using ptr = subarray_ptr; + + // NOLINTNEXTLINE(runtime/operator) + BOOST_MULTI_HD constexpr auto operator&() && { return subarray_ptr(this->base_, this->layout()); } // NOLINT(google-runtime-operator) : taking address of a reference-like object should be allowed //NOSONAR + // NOLINTNEXTLINE(runtime/operator) + BOOST_MULTI_HD constexpr auto operator&() & { return subarray_ptr(this->base_, this->layout()); } // NOLINT(google-runtime-operator) : taking address of a reference-like object should be allowed //NOSONAR + + using const_subarray::operator&; + // NOLINTNEXTLINE(runtime/operator) + // BOOST_MULTI_HD constexpr auto operator&() const& {return subarray_ptr{this->base_, this->layout()};} // NOLINT(google-runtime-operator) extend semantics //NOSONAR + + using const_subarray::const_subarray; + + constexpr auto mbegin() { return move_iterator{this->begin()}; } + constexpr auto mend() { return move_iterator{this->end() }; } + + using const_subarray::home; + constexpr auto home() && { return this->home_aux_(); } + constexpr auto home() & { return this->home_aux_(); } + + using const_subarray::strided; + constexpr auto strided(difference_type diff) && -> subarray { return this->strided_aux_(diff);} + constexpr auto strided(difference_type diff) & -> subarray { return this->strided_aux_(diff);} + + using const_subarray::taked; + constexpr auto taked(difference_type count) && -> subarray {return this->taked_aux_(count);} + constexpr auto taked(difference_type count) & -> subarray {return this->taked_aux_(count);} + + using const_subarray::dropped; + constexpr auto dropped(difference_type count) && -> subarray { return this->dropped_aux_(count); } + constexpr auto dropped(difference_type count) & -> subarray { return this->dropped_aux_(count); } + + using const_subarray::rotated; + BOOST_MULTI_HD constexpr auto rotated() && -> subarray { return const_subarray::rotated(); } + BOOST_MULTI_HD constexpr auto rotated() & -> subarray { return const_subarray::rotated(); } + + using const_subarray::unrotated; + BOOST_MULTI_HD constexpr auto unrotated() && -> subarray { return const_subarray::unrotated(); } + BOOST_MULTI_HD constexpr auto unrotated() & -> subarray { return const_subarray::unrotated(); } + + using const_subarray::transposed; + BOOST_MULTI_HD constexpr auto transposed() && -> subarray { return const_subarray::transposed(); } + BOOST_MULTI_HD constexpr auto transposed() & -> subarray { return const_subarray::transposed(); } + + // BOOST_MULTI_FRIEND_CONSTEXPR BOOST_MULTI_HD + // auto operator~ (subarray const& self) { return self.transposed(); } + BOOST_MULTI_FRIEND_CONSTEXPR BOOST_MULTI_HD + auto operator~ (subarray& self) { return self.transposed(); } + BOOST_MULTI_FRIEND_CONSTEXPR BOOST_MULTI_HD + auto operator~ (subarray&& self) { return std::move(self).transposed(); } + + using const_subarray::reindexed; + + template + constexpr auto reindexed(index first, Indexes... idxs) & -> subarray { + return const_subarray::reindexed(first, idxs...); + // return ((this->reindexed(first).rotated()).reindexed(idxs...)).unrotated(); + } + template + constexpr auto reindexed(index first, Indexes... idxs)&& -> subarray { + return const_subarray::reindexed(first, idxs...); + // return ((std::move(*this).reindexed(first).rotated()).reindexed(idxs...)).unrotated(); + } + + BOOST_MULTI_HD constexpr auto base() const& -> typename subarray::element_const_ptr { return this->base_; } + BOOST_MULTI_HD constexpr auto base() & -> ElementPtr { return this->base_; } + BOOST_MULTI_HD constexpr auto base() && -> ElementPtr { return this->base_; } + // BOOST_MULTI_HD constexpr auto base() const& -> element_const_ptr {return base_;} + + constexpr auto operator=(const_subarray const& other) & -> subarray& { + if(this == std::addressof(other)) {return *this;} + assert(this->extension() == other.extension()); + this->elements() = other.elements(); + return *this; + } + + constexpr void swap(subarray&& other) && noexcept { + assert(this->extension() == other.extension()); + adl_swap_ranges(this->elements().begin(), this->elements().end(), std::move(other).elements().begin()); + } + friend constexpr void swap(subarray&& self, subarray&& other) noexcept { std::move(self).swap(std::move(other)); } + + // template>>> friend constexpr void swap(subarray&& self, A&& other) noexcept { std::move(self).swap(std::forward(other)); } + // template>>> friend constexpr void swap(A&& other, subarray&& self) noexcept { std::move(self).swap(std::forward(other)); } + + // template constexpr void swap(Array&& other) && noexcept { + // assert( std::move(*this).extension() == other.extension() ); // NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay) : normal in a constexpr function + // this->elements().swap(std::forward(other).elements()); + // // adl_swap_ranges(this->begin(), this->end(), adl_begin(std::forward(o))); + // } + // template constexpr void swap(A&& other) & noexcept {return swap(std::forward(other));} + + // friend constexpr void swap(subarray&& self, subarray&& other) noexcept {std::move(self).swap(std::move(other));} + + // template constexpr void swap(subarray& self, Array&& other) noexcept {self.swap(std::forward(other));} // TODO(correaa) remove + // template constexpr void swap(Array&& other, subarray& self) noexcept {self.swap(std::forward(other));} + + // fix mutation + // template constexpr auto operator=(const_subarray const& other) && -> decltype(auto) {operator=( other ); return *this;} + template constexpr auto operator=(const_subarray const& other) & -> subarray& { + assert(other.extensions() == this->extensions()); + this->elements() = other.elements(); + return *this; + } + + // fix mutation + template constexpr auto operator=(const_subarray && other) && -> subarray& {operator=(std::move(other)); return *this;} + template constexpr auto operator=(const_subarray && other) & -> subarray& { + assert(this->extensions() == other.extensions()); + this->elements() = std::move(other).elements(); + return *this; + } + + template< + class Range, + class = std::enable_if_t >, + class = std::enable_if_t::value> // NOLINT(modernize-use-constraints) TODO(correaa) for C++20 + > + constexpr auto operator=(Range const& rng) & // TODO(correaa) check that you LHS is not read-only? + -> subarray& { // lints(cppcoreguidelines-c-copy-assignment-signature,misc-unconventional-assign-operator) + assert(this->size() == static_cast(adl_size(rng))); // TODO(correaa) or use std::cmp_equal? + adl_copy_n(adl_begin(rng), adl_size(rng), this->begin()); + return *this; + } + + template< + class Range, + class = std::enable_if_t >, // NOLINT(modernize-use-constraints) TODO(correaa) in C++20 + class = std::enable_if_t::value > // NOLINT(modernize-use-constraints) TODO(correaa) in C++20 + > + constexpr auto operator=(Range const& rng) && -> subarray& {operator=(rng); return *this;} + + // template + // constexpr auto operator=(const_subarray const& other) && -> subarray& {operator=(other); return *this;} + + // template + // constexpr auto operator=(subarray&& other) && -> subarray& {operator=(std::move(other)); return *this;} + + // template + // constexpr + // auto operator=(const_subarray const& other) & -> subarray& { + // assert(this->extension() == other.extension()); // NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay) : normal in a constexpr function + // this->elements() = other.elements(); + // return *this; + // } + + template + constexpr + auto operator=(const_subarray const& other) && -> subarray& { + assert(this->extension() == other.extension()); // NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay) : normal in a constexpr function + this->elements() = other.elements(); + return *this; + } + + template + constexpr + auto operator=(subarray&& other) & -> subarray& { + assert(this->extension() == other.extension()); // NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay) : normal in a constexpr function + this->elements() = std::move(other).elements(); + return *this; + } + + // template + // constexpr + // auto operator=(array&& other) & -> subarray& { + // operator=(static_cast&&>(std::move(other))); + // other.clear(); // TODO(correaa) is this a good idea? + // return *this; + // } + + constexpr auto operator=(const_subarray const& other) const&& -> subarray&; // for std::indirectly_writable + // { + // assert(this->extension() == other.extension()); + // this->elements() = other.elements(); + // return std::move(*this); + // } + + constexpr auto operator=(subarray const& other) & -> subarray& { + if(this == std::addressof(other)) { return *this; } + assert(this->extension() == other.extension()); + this->elements() = other.elements(); + return *this; + } + constexpr auto operator=(subarray&& other) & noexcept -> subarray& { // TODO(correaa) make conditionally noexcept + if(this == std::addressof(other)) { return *this; } + assert(this->extension() == other.extension()); + this->elements() = other.elements(); + return *this; + } + + auto operator=(std::initializer_list values) && -> subarray& {operator=(values); return *this; } + auto operator=(std::initializer_list values) & -> subarray& { + assert( static_cast(values.size()) == this->size() ); + adl_copy_n(values.begin(), values.size(), this->begin()); + return *this; + } + +// constexpr +// auto operator=(const_subarray const& other) & -> const_subarray& { +// if(this == std::addressof(other)) {return *this;} // lints(cert-oop54-cpp) +// assert(this->extension() == other.extension()); // NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay) : normal in a constexpr function +// // MULTI_MARK_SCOPE("multi::operator= [D="+std::to_string(D)+"] from "+typeid(T).name()+" to "+typeid(T).name() ); +// elements() = other.elements(); +// // if(this->num_elements() == this->nelems() and o.num_elements() == this->nelems() and this->layout() == o.layout()) { +// // adl_copy_n(o.base(), o.num_elements(), this->base()); +// // } else if(o.stride() < (~o).stride()) { +// // adl_copy_n( (~o).begin(), (~o).size(), (~(*this)).begin() ); +// // } else { +// // assign(o.begin()); +// // } +// return *this; +// } + + // constexpr auto operator=(const_subarray const& other) && + // -> const_subarray& { // lints(cppcoreguidelines-c-copy-assignment-signature,misc-unconventional-assign-operator) + // if(this == std::addressof(other)) {return *this;} // lints(cert-oop54-cpp) + // operator=(other); + // return *this; // lints(cppcoreguidelines-c-copy-assignment-signature,misc-unconventional-assign-operator) + // } + + // template< + // class Range, + // class = decltype( static_cast(std::declval const&>()) ) + // > + // constexpr explicit operator Range() const { + // return static_cast const&>(*this).operator Range(); + // } + + // BOOST_MULTI_HD constexpr auto operator()() const& -> const_subarray /*const*/ {return this->paren_aux_();} // NOLINT(readability-redundant-access-specifiers,readability-const-return-type) + + // using reference = typename std::conditional_t< + // (D > 1), + // subarray, + // typename std::iterator_traits::reference + // >; + + // using const_reference = typename std::conditional_t< + // (D > 1), + // const_subarray, + // typename std::iterator_traits::reference + // >; + + // BOOST_MULTI_HD constexpr auto operator[](index idx) const& { return static_cast(this->at_aux_(idx)); } // TODO(correaa) use return type to cast + using const_subarray::operator[]; + // BOOST_MULTI_HD constexpr auto operator[](index idx) const& { return const_subarray::operator[](idx); } + BOOST_MULTI_HD constexpr auto operator[](index idx) && -> typename subarray::reference { return this->at_aux_(idx) ; } + BOOST_MULTI_HD constexpr auto operator[](index idx) & -> typename subarray::reference { return this->at_aux_(idx) ; } + + using const_subarray::sliced; + BOOST_MULTI_HD constexpr auto sliced(index first, index last) && -> subarray { return const_subarray::sliced(first, last) ; } + BOOST_MULTI_HD constexpr auto sliced(index first, index last) & -> subarray { return const_subarray::sliced(first, last) ; } + + using const_subarray::range; + BOOST_MULTI_HD constexpr auto range(index_range irng) && -> decltype(auto) {return std::move(*this).sliced(irng.front(), irng.front() + irng.size());} + BOOST_MULTI_HD constexpr auto range(index_range irng) & -> decltype(auto) {return sliced(irng.front(), irng.front() + irng.size());} + + private: + using const_subarray::paren_aux_; + + BOOST_MULTI_HD constexpr auto paren_aux_() & {return subarray(this->layout(), this->base_);} + BOOST_MULTI_HD constexpr auto paren_aux_() && {return subarray(this->layout(), this->base_);} + + template BOOST_MULTI_HD constexpr auto paren_aux_(index idx) & -> decltype(auto) { return operator[](idx); } + template BOOST_MULTI_HD constexpr auto paren_aux_(index idx) && -> decltype(auto) { return operator[](idx); } + + template BOOST_MULTI_HD constexpr auto paren_aux_(index idx, As... args) & -> decltype(auto) {return operator[](idx).paren_aux_(args...);} + template BOOST_MULTI_HD constexpr auto paren_aux_(index idx, As... args) && -> decltype(auto) {return operator[](idx).paren_aux_(args...);} + + template + BOOST_MULTI_HD constexpr auto paren_aux_(index_range irng, As... args) & { + return this->range(irng).rotated().paren_aux_(args...).unrotated(); + } + template + BOOST_MULTI_HD constexpr auto paren_aux_(index_range irng, As... args) && { + return std::move(*this).range(irng).rotated().paren_aux_(args...).unrotated(); + } + + template BOOST_MULTI_HD constexpr auto paren_aux_(intersecting_range inr, As... args) & -> decltype(auto) {return paren_aux_(intersection(this->extension(), inr), args...);} + template BOOST_MULTI_HD constexpr auto paren_aux_(intersecting_range inr, As... args) && -> decltype(auto) {return paren_aux_(intersection(this->extension(), inr), args...);} + + public: + using const_subarray::operator(); + + BOOST_MULTI_HD constexpr auto operator()() & -> subarray {return this->paren_aux_();} + BOOST_MULTI_HD constexpr auto operator()() && -> subarray {return this->paren_aux_();} + + template BOOST_MULTI_HD constexpr auto operator()(A1 arg1) & -> decltype(auto) {return this->paren_aux_(arg1);} // NOLINT(whitespace/line_length) pattern line + template BOOST_MULTI_HD constexpr auto operator()(A1 arg1, A2 arg2) & -> decltype(auto) {return this->paren_aux_(arg1, arg2);} + template BOOST_MULTI_HD constexpr auto operator()(A1 arg1, A2 arg2, A3 arg3) & -> decltype(auto) {return this->paren_aux_(arg1, arg2, arg3);} // NOLINT(whitespace/line_length) pattern line + template BOOST_MULTI_HD constexpr auto operator()(A1 arg1, A2 arg2, A3 arg3, A4 arg4, As... args) & -> decltype(auto) {return this->paren_aux_(arg1, arg2, arg3, arg4, args...);} // NOLINT(whitespace/line_length) pattern line + + template BOOST_MULTI_HD constexpr auto operator()(A1 arg1) && -> decltype(auto) {return std::move(*this).paren_aux_(arg1);} // NOLINT(whitespace/line_length) pattern line + template BOOST_MULTI_HD constexpr auto operator()(A1 arg1, A2 arg2) && -> decltype(auto) {return std::move(*this).paren_aux_(arg1, arg2);} // NOLINT(whitespace/line_length) pattern line + template BOOST_MULTI_HD constexpr auto operator()(A1 arg1, A2 arg2, A3 arg3) && -> decltype(auto) {return std::move(*this).paren_aux_(arg1, arg2, arg3);} // NOLINT(whitespace/line_length) pattern line + template BOOST_MULTI_HD constexpr auto operator()(A1 arg1, A2 arg2, A3 arg3, A4 arg4, As... args) && -> decltype(auto) {return std::move(*this).paren_aux_(arg1, arg2, arg3, arg4, args...);} // NOLINT(whitespace/line_length) pattern line + + + private: + template + static BOOST_MULTI_HD constexpr auto apply_impl_(Self&& self, Tuple const& tuple, std::index_sequence/*012*/) -> decltype(auto) { + using std::get; + return std::forward(self)(get(tuple)...); + } + + public: + using const_subarray::apply; + template BOOST_MULTI_HD constexpr auto apply(Tuple const& tpl) && -> decltype(auto) { return apply_impl_(std::move(*this), tpl, std::make_index_sequence::value>()); } + template BOOST_MULTI_HD constexpr auto apply(Tuple const& tpl) & -> decltype(auto) { return apply_impl_( *this , tpl, std::make_index_sequence::value>()); } + + using const_subarray::partitioned; + BOOST_MULTI_HD constexpr auto partitioned(size_type size) & -> subarray { return this->partitioned_aux_(size); } + BOOST_MULTI_HD constexpr auto partitioned(size_type size) && -> subarray { return this->partitioned_aux_(size); } + + using const_subarray::flatted; + constexpr auto flatted() & { + // assert(is_flattable() && "flatted doesn't work for all layouts!"); // NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay) : normal in a constexpr function + multi::layout_t new_layout{this->layout().sub()}; + new_layout.nelems() *= this->size(); // TODO(correaa) : use immutable layout + return subarray(new_layout, this->base_); + } + constexpr auto flatted() && {return this->flatted();} + + using const_subarray::reinterpret_array_cast; + // template::template rebind> + // constexpr auto reinterpret_array_cast() & { + // assert(this->layout().stride() * static_cast(sizeof(T)) % static_cast(sizeof(T2)) == 0); + + // return subarray{ + // typename subarray::layout_type{this->layout().sub(), this->layout().stride() * static_cast(sizeof(T)) / static_cast(sizeof(T2)), this->layout().offset() * static_cast(sizeof(T)) / static_cast(sizeof(T2)), this->layout().nelems() * static_cast(sizeof(T)) / static_cast(sizeof(T2))}, + // reinterpret_pointer_cast(this->base_) + // }; + // } + + // template::template rebind> + // constexpr auto reinterpret_array_cast() && { return this->reinterpret_array_cast(); } + + template::template rebind> + constexpr auto reinterpret_array_cast() & { + // static_assert( sizeof(T)%sizeof(T2) == 0, + // "error: reinterpret_array_cast is limited to integral stride values, therefore the element target size must be multiple of the source element size. Use custom pointers to allow reintrepreation of array elements in other cases" ); + + return subarray( + this->layout().scale(sizeof(T), sizeof(T2)), // NOLINT(bugprone-sizeof-expression) : sizes are compatible according to static assert above + reinterpret_pointer_cast(this->base_) // if ADL gets confused here (e.g. multi:: and thrust::) then adl_reinterpret_pointer_cast will be necessary + ); + } + + template::template rebind> + constexpr auto reinterpret_array_cast() && { + // static_assert( sizeof(T)%sizeof(T2) == 0, + // "error: reinterpret_array_cast is limited to integral stride values, therefore the element target size must be multiple of the source element size. Use custom pointers to allow reintrepreation of array elements in other cases" ); + + return subarray( + this->layout().scale(sizeof(T), sizeof(T2)), // NOLINT(bugprone-sizeof-expression) : sizes are compatible according to static assert above + reinterpret_pointer_cast(this->base_) // if ADL gets confused here (e.g. multi:: and thrust::) then adl_reinterpret_pointer_cast will be necessary + ); + } + + template::template rebind > + constexpr auto reinterpret_array_cast(size_type count) & { + static_assert( sizeof(T)%sizeof(T2) == 0, + "error: reinterpret_array_cast is limited to integral stride values"); + + assert( sizeof(T) == sizeof(T2)*static_cast(count) ); // NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay) : checck implicit size compatibility + if constexpr(std::is_pointer_v) { + return subarray( + layout_t(this->layout().scale(sizeof(T), sizeof(T2)), 1, 0, count).rotate(), + static_cast(static_cast(this->base_)) // NOLINT(bugprone-casting-through-void) direct reinterepret_cast doesn't work here + ); + } else { + return subarray( + layout_t(this->layout().scale(sizeof(T), sizeof(T2)), 1, 0, count).rotate(), + reinterpret_cast(this->base_) // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast,bugprone-casting-through-void) direct reinterepret_cast doesn't work here + ); + } + } + + template::template rebind > + constexpr auto reinterpret_array_cast(size_type count) && { + static_assert( sizeof(T)%sizeof(T2) == 0, + "error: reinterpret_array_cast is limited to integral stride values"); + + assert( sizeof(T) == sizeof(T2)*static_cast(count) ); // NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay) : checck implicit size compatibility + if constexpr(std::is_pointer_v) { + return subarray( + layout_t(this->layout().scale(sizeof(T), sizeof(T2)), 1, 0, count).rotate(), + static_cast(static_cast(this->base_)) // NOLINT(bugprone-casting-through-void) direct reinterepret_cast doesn't work here + ); + } else { + return subarray( + layout_t(this->layout().scale(sizeof(T), sizeof(T2)), 1, 0, count).rotate(), + reinterpret_cast(this->base_) // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast,bugprone-casting-through-void) direct reinterepret_cast doesn't work here + ); + } + } + + using element_move_ptr = multi::move_ptr; + + constexpr auto element_moved() & {return subarray(this->layout(), element_move_ptr{this->base_});} + constexpr auto element_moved() && {return element_moved();} +}; + template struct array_iterator{}; -template -struct array_iterator // NOLINT(fuchsia-multiple-inheritance) -: boost::multi::iterator_facade< - array_iterator, - Element, std::random_access_iterator_tag, - typename std::iterator_traits::reference, multi::difference_type -> -, multi::affine , multi::difference_type> -, multi::decrementable > -, multi::incrementable > -, multi::totally_ordered2, void> -{ - using affine = multi::affine, multi::difference_type>; +template +struct array_iterator // NOLINT(fuchsia-multiple-inheritance,cppcoreguidelines-pro-type-member-init,hicpp-member-init) stride_ is not initialized in some constructors + : boost::multi::iterator_facade< + array_iterator, + Element, std::random_access_iterator_tag, + std::conditional_t< + IsConst, + typename std::iterator_traits::template rebind >::reference, + typename std::iterator_traits::reference + >, multi::difference_type + > + , multi::affine , multi::difference_type> + , multi::decrementable > + , multi::incrementable > + , multi::totally_ordered2, void> { + using affine = multi::affine, multi::difference_type>; + + using pointer = std::conditional_t< + IsConst, + typename std::pointer_traits::template rebind, + Ptr + >; + + private: + using reference_aux = std::conditional_t< + IsConst, + typename std::iterator_traits::template rebind >::reference, + typename std::iterator_traits::reference + >; + + public: + using reference = std::conditional_t< + IsMove, + std::add_rvalue_reference_t, + reference_aux + >; + using difference_type = typename affine::difference_type; + static constexpr dimensionality_type dimensionality = 1; array_iterator() = default; // NOLINT(cppcoreguidelines-pro-type-member-init,hicpp-member-init) using layout_type = multi::layout_t<0>; + template< + bool OtherIsConst, std::enable_if_t< ! OtherIsConst, int> =0 // NOLINT(modernize-use-constraints) TODO(correaa) for C++20 + > + BOOST_MULTI_HD constexpr explicit array_iterator(array_iterator const& other) + : ptr_{other.base()}, stride_{other.stride()} {} + template< class Other, decltype(multi::detail::implicit_cast(typename Other::pointer{}))* = nullptr, @@ -1768,7 +2315,7 @@ struct array_iterator // NOLINT(fuchsia-multiple-inheritance) > // cppcheck-suppress noExplicitConstructor ; because underlying pointer is implicitly convertible BOOST_MULTI_HD constexpr/*mplct*/ array_iterator(Other const& other) // NOLINT(google-explicit-constructor,hicpp-explicit-conversions) : to reproduce the implicitness of the argument - : data_{other.base()}, stride_{other.stride()} {} + : ptr_{other.base()}, stride_{other.stride()} {} template< class Other, @@ -1776,66 +2323,68 @@ struct array_iterator // NOLINT(fuchsia-multiple-inheritance) decltype(std::declval().data_)* = nullptr > constexpr explicit array_iterator(Other const& other) - : data_{other.data_}, stride_{other.stride_} {} + : ptr_{other.data_}, stride_{other.stride_} {} - template friend struct array_iterator; - - constexpr explicit array_iterator(std::nullptr_t nil) : data_{nil} {} - constexpr explicit array_iterator(Ptr const& ptr) : data_{ptr} {} + template friend struct array_iterator; template< class EElement, typename PPtr, typename = decltype(multi::detail::implicit_cast(std::declval>().data_)) > BOOST_MULTI_HD constexpr /*impl*/ array_iterator(array_iterator const& other) // NOLINT(google-explicit-constructor,hicpp-explicit-conversions) : to reproduce the implicitness of original pointer - : data_{other.data_}, stride_{other.stride_} {} + : ptr_{other.base()}, stride_{other.stride_} {} - constexpr explicit operator bool() const {return static_cast(this->data_);} + constexpr explicit operator bool() const {return static_cast(this->ptr_);} - BOOST_MULTI_HD constexpr auto operator[](typename array_iterator::difference_type n) const -> typename std::iterator_traits::reference { + BOOST_MULTI_HD constexpr auto operator[](typename array_iterator::difference_type n) const -> decltype(auto) { return *((*this) + n); } - constexpr auto operator->() const -> Ptr {return data_;} + constexpr auto operator->() const {return static_cast(ptr_);} using element = Element; using element_ptr = Ptr; - using pointer = element_ptr; + // using pointer = element_ptr; using stride_type = multi::index; static constexpr dimensionality_type rank_v = 1; using rank = std::integral_constant; - constexpr auto operator<(array_iterator const& other) const -> bool {return distance_to_(other) > 0;} + constexpr auto operator<(array_iterator const& other) const -> bool { + assert(other.stride_ == stride_); + assert((ptr_ - other.ptr_)%stride_ == 0); + return (ptr_ - other.ptr_)/stride_ < 0; + // return distance_to_(other) > 0; + } - BOOST_MULTI_HD explicit constexpr array_iterator(Ptr ptr, typename subarray::index stride) - : data_{ptr}, stride_{stride} {} + BOOST_MULTI_HD explicit constexpr array_iterator(Ptr ptr, typename const_subarray::index stride) + : ptr_{ptr}, stride_{stride} {} private: - friend struct subarray; + friend struct const_subarray; - element_ptr data_; // {nullptr}; // TODO(correaa) : consider uninitialized pointer - stride_type stride_ = {1}; + element_ptr ptr_; // {nullptr}; // TODO(correaa) : consider uninitialized pointer + stride_type stride_; // = {1}; // = {0}; // TODO(correaa) change to make it trivially default constructible - constexpr auto distance_to_(array_iterator const& other) const -> difference_type { - assert(stride_==other.stride_ && (other.data_-data_)%stride_ == 0); // NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay) : normal in a constexpr function - return (other.data_ - data_)/stride_; // with struct-overflow=3 error: assuming signed overflow does not occur when simplifying `X - Y > 0` to `X > Y` [-Werror=strict-overflow] - } + // constexpr auto distance_to_(array_iterator const& other) const -> difference_type { + // assert(stride_==other.stride_ && (other.data_-data_)%stride_ == 0); // NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay) : normal in a constexpr function + // return (other.data_ - data_)/stride_; // with struct-overflow=3 error: assuming signed overflow does not occur when simplifying `X - Y > 0` to `X > Y` [-Werror=strict-overflow] + // } public: - BOOST_MULTI_HD constexpr auto operator+(difference_type n) const -> array_iterator {array_iterator ret{*this}; ret+=n; return ret;} - BOOST_MULTI_HD constexpr auto operator-(difference_type n) const -> array_iterator {array_iterator ret{*this}; ret-=n; return ret;} + BOOST_MULTI_HD constexpr auto operator+(difference_type n) const -> array_iterator { array_iterator ret{*this}; ret+=n; return ret; } + BOOST_MULTI_HD constexpr auto operator-(difference_type n) const -> array_iterator { array_iterator ret{*this}; ret-=n; return ret; } - [[deprecated("use base() for iterator")]] - constexpr auto data() const -> element_ptr {return data_;} + BOOST_MULTI_HD constexpr auto base() const {return static_cast(ptr_);} - constexpr auto base() const& -> element_ptr {return data_;} + [[deprecated("use base() for iterator")]] + BOOST_MULTI_HD constexpr auto data() const {return base();} BOOST_MULTI_FRIEND_CONSTEXPR - auto base(array_iterator const& self) -> element_ptr {return self.base();} + auto base(array_iterator const& self) { return self.base(); } - BOOST_MULTI_HD constexpr auto stride() const -> stride_type {return stride_;} - friend constexpr auto stride(array_iterator const& self) -> stride_type {return self.stride_;} + BOOST_MULTI_HD constexpr auto stride() const -> stride_type {return stride_;} + friend constexpr auto stride(array_iterator const& self) -> stride_type { return self.stride_; } #if defined(__clang__) #pragma clang diagnostic push @@ -1843,43 +2392,72 @@ struct array_iterator // NOLINT(fuchsia-multiple-inheritance) #pragma clang diagnostic ignored "-Wunsafe-buffer-usage" // TODO(correaa) use checked span #endif - constexpr auto operator++() -> array_iterator& {data_ += stride_; return *this;} - constexpr auto operator--() -> array_iterator& {data_ -= stride_; return *this;} + constexpr auto operator++() -> array_iterator& {ptr_ += stride_; return *this;} + constexpr auto operator--() -> array_iterator& {ptr_ -= stride_; return *this;} - constexpr auto operator+=(difference_type n) -> array_iterator& {data_ += stride_*n; return *this;} - constexpr auto operator-=(difference_type n) -> array_iterator& {data_ -= stride_*n; return *this;} + constexpr auto operator+=(difference_type n) -> array_iterator& {assert(stride_ != 0); ptr_ += stride_*n; return *this;} + constexpr auto operator-=(difference_type n) -> array_iterator& {assert(stride_ != 0); ptr_ -= stride_*n; return *this;} #if defined(__clang__) #pragma clang diagnostic pop #endif - constexpr auto operator-(array_iterator const& other) const -> difference_type {return -distance_to_(other);} + constexpr auto operator-(array_iterator const& other) const -> difference_type { + assert(stride_==other.stride_ && (ptr_ - other.ptr_)%stride_ == 0); + return (ptr_ - other.ptr_)/stride_; // with struct-overflow=3 error: assuming signed overflow does not occur when simplifying `X - Y > 0` to `X > Y` [-Werror=strict-overflow] + // return -distance_to_(other); + } - friend constexpr auto operator==(array_iterator const& self, array_iterator const& other) -> bool {return self.data_ == other.data_;} + constexpr auto operator==(array_iterator const& other) const -> bool { + assert(this->stride_ == other.stride_); + return this->ptr_ == other.ptr_; + } + + template =0> // NOLINT(modernize-use-constraints) TODO(correaa) for C++20 + constexpr auto operator==(array_iterator const& other) const -> bool { + assert(this->stride_ == other.stride_); + return this->ptr_ == other.ptr_; + } - BOOST_MULTI_HD constexpr auto operator*() const -> typename std::iterator_traits::reference { return *data_; } // NOLINT(readability-const-return-type) + // constexpr auto operator!=(array_iterator const& other) const -> bool { + // assert(this->stride_ == other.stride_); + // return this->ptr_ != other.ptr_; + // } + +// friend constexpr auto operator==(array_iterator const& self, array_iterator const& other) -> bool {return self.ptr_ == other.ptr_;} + + BOOST_MULTI_HD constexpr auto operator*() const -> decltype(auto) { + if constexpr(IsMove) { + return multi::move(*ptr_); + } else { + return static_cast(*ptr_); + } + } }; template using iterator = array_iterator; template -struct subarray -: array_types { +class const_subarray +: public array_types { + public: using types = array_types; using types::types; using element = typename types::element; - using element_ref = typename std::iterator_traits::reference; - using element_cref = typename std::iterator_traits::reference; + using element_ref = typename std::iterator_traits::reference; + using element_cref = typename std::iterator_traits::reference; using iterator = array_iterator; - constexpr auto operator= (element const& elem) & -> subarray& { + using layout_type = Layout; + + constexpr auto operator= (element const& elem) & -> const_subarray& { // MULTI_MARK_SCOPE(std::string{"multi::operator= D=0 from "}+typeid(T).name()+" to "+typeid(T).name() ); adl_copy_n(&elem, 1, this->base_); return *this; } - constexpr auto operator= (element const& elem) && -> subarray& { + constexpr auto operator= (element const& elem) && -> const_subarray& { operator=(elem); return *this; // lints(cppcoreguidelines-c-copy-assignment-signature,misc-unconventional-assign-operator) } @@ -1892,7 +2470,7 @@ struct subarray template constexpr - auto operator=(Range0 const& rng) & -> subarray& { + auto operator=(Range0 const& rng) & -> const_subarray& { adl_copy_n(&rng, 1, this->base_); return *this; } @@ -1901,22 +2479,77 @@ struct subarray constexpr auto elements_at(size_type idx [[maybe_unused]]) && -> element_ref {assert(idx < this->num_elements()); return *(this->base_);} constexpr auto elements_at(size_type idx [[maybe_unused]]) & -> element_ref {assert(idx < this->num_elements()); return *(this->base_);} - constexpr auto operator!=(subarray const& other) const {return ! adl_equal(other.base_, other.base_ + 1, this->base_);} - constexpr auto operator==(subarray const& other) const {return adl_equal(other.base_, other.base_ + 1, this->base_);} + constexpr auto operator!=(const_subarray const& other) const {return ! adl_equal(other.base_, other.base_ + 1, this->base_);} + constexpr auto operator==(const_subarray const& other) const {return adl_equal(other.base_, other.base_ + 1, this->base_);} - constexpr auto operator<(subarray const& other) const {return adl_lexicographical_compare(this->base_, this->base_ + this->num_elements(), other.base_);} + constexpr auto operator<(const_subarray const& other) const { + return adl_lexicographical_compare( + this->base_, this->base_ + this->num_elements(), + other.base_, other.base_ + other.num_elements() + ); + } using decay_type = typename types::element; - constexpr auto operator()() const -> element_ref {return *(this->base_);} + BOOST_MULTI_HD constexpr auto operator()() const& -> element_ref {return *(this->base_);} // NOLINT(hicpp-explicit-conversions) + + constexpr operator element_ref () && noexcept {return *(this->base_);} // NOLINT(google-explicit-constructor,hicpp-explicit-conversions) : to allow terse syntax + constexpr operator element_ref () & noexcept {return *(this->base_);} // NOLINT(google-explicit-constructor,hicpp-explicit-conversions) : to allow terse syntax + constexpr operator element_cref() const& noexcept {return *(this->base_);} // NOLINT(google-explicit-constructor,hicpp-explicit-conversions) : to allow terse syntax + + template + constexpr auto operator[](IndexType const&) const& = delete; + constexpr auto sliced() const& = delete; + constexpr auto partitioned() const& = delete; + + constexpr auto strided(difference_type) const& = delete; + + constexpr auto taked(difference_type) const& = delete; + constexpr auto dropped(difference_type) const& = delete; + + BOOST_MULTI_HD constexpr auto reindexed() const& { return operator()(); } + BOOST_MULTI_HD constexpr auto rotated() const& { return operator()(); } + BOOST_MULTI_HD constexpr auto unrotated() const& { return operator()(); } - constexpr operator element_ref () && {return *(this->base_);} // NOLINT(google-explicit-constructor,hicpp-explicit-conversions) : to allow terse syntax - constexpr operator element_ref () & {return *(this->base_);} // NOLINT(google-explicit-constructor,hicpp-explicit-conversions) : to allow terse syntax - constexpr operator element_cref() const& {return *(this->base_);} // NOLINT(google-explicit-constructor,hicpp-explicit-conversions) : to allow terse syntax + auto transposed() const& = delete; + auto flatted() const& = delete; + auto range() const& -> const_subarray = delete; + + using cursor = cursor_t; + using const_cursor = cursor_t; + private: + constexpr auto home_aux_() const {return cursor(this->base_, this->strides());} + + public: + constexpr auto home() const& -> const_cursor {return home_aux_();} + + private: + template friend class subarray; + + auto paren_aux_() const& {return operator()();} + + public: + template + BOOST_MULTI_HD constexpr auto apply(Tuple const& /*unused*/) const { + static_assert(std::tuple_size_v == 0); + return operator()(); + } + + BOOST_MULTI_HD constexpr auto operator&() const& { // NOLINT(google-runtime-operator) + return /*TODO(correaa) add const*/ subarray_ptr(this->base_, this->layout()); + } // NOLINT(google-runtime-operator) extend semantics //NOSONAR + + template::template rebind> + constexpr auto reinterpret_array_cast() const& { + return const_subarray{ + typename const_subarray::layout_type{this->layout()}, + reinterpret_pointer_cast(this->base_) + }; + } constexpr auto broadcasted() const& { - multi::layout_t<1> const new_layout{this->layout(), 0, 0, std::numeric_limits::max()}; - return subarray{new_layout, types::base_}; + multi::layout_t<1> const new_layout{this->layout(), 0, 0, (std::numeric_limits::max)()}; // paren for MSVC macros + return subarray{new_layout, types::base_}; } template @@ -1930,14 +2563,14 @@ struct subarray }; template -struct subarray // NOLINT(fuchsia-multiple-inheritance) : to define operators via CRTP -: multi::random_iterable > -, array_types { - ~subarray() = default; // lints(cppcoreguidelines-special-member-functions,hicpp-special-member-functions) +struct const_subarray // NOLINT(fuchsia-multiple-inheritance) : to define operators via CRTP + : multi::random_iterable > // paren for msvc 19.14? + , array_types { // paren for msvc 19.14? + ~const_subarray() = default; // lints(cppcoreguidelines-special-member-functions,hicpp-special-member-functions) - // boost serialization needs `delete`. void boost::serialization::extended_type_info_typeid::destroy(const void*) const [with T = boost::multi::subarray >]’ + // boost serialization needs `delete`. void boost::serialization::extended_type_info_typeid::destroy(const void*) const [with T = boost::multi::subarray >] // void operator delete(void* ptr) noexcept = delete; - // void operator delete(void* ptr, void* place ) noexcept = delete; // NOLINT(bugprone-easily-swappable-parameters) + // void operator delete(void* ptr, void* place ) noexcept = doperator=(elete; // NOLINT(bugprone-easily-swappable-parameters) static constexpr dimensionality_type rank_v = 1; using rank = std::integral_constant; @@ -1945,7 +2578,7 @@ struct subarray using types = array_types; using types::types; using layout_type = Layout; - using ref_ = subarray; + using ref_ = const_subarray; using element_type = T; @@ -1960,20 +2593,20 @@ struct subarray using const_reference = typename array_types::const_reference; using reference = typename array_types:: reference; - using default_allocator_type = typename multi::pointer_traits::default_allocator_type; + using default_allocator_type = typename multi::pointer_traits::default_allocator_type; - constexpr auto get_allocator() const -> default_allocator_type {return default_allocator_of(subarray::base());} + constexpr auto get_allocator() const -> default_allocator_type {return default_allocator_of(const_subarray::base());} BOOST_MULTI_FRIEND_CONSTEXPR - auto get_allocator(subarray const& self) -> default_allocator_type {return self.get_allocator();} + auto get_allocator(const_subarray const& self) -> default_allocator_type {return self.get_allocator();} - using decay_type = array::default_allocator_type>; + using decay_type = array::default_allocator_type>; constexpr auto decay() const -> decay_type {return decay_type{*this};} - BOOST_MULTI_FRIEND_CONSTEXPR auto decay(subarray const& self) -> decay_type {return self.decay();} + BOOST_MULTI_FRIEND_CONSTEXPR auto decay(const_subarray const& self) -> decay_type {return self.decay();} - using basic_const_array = subarray< + using basic_const_array = const_subarray< T, 1, - typename std::pointer_traits::template rebind, + typename std::pointer_traits::template rebind, Layout >; @@ -1987,54 +2620,47 @@ struct subarray ); } - subarray(subarray const&) = default; + const_subarray(const_subarray const&) = default; - template friend struct subarray; + template friend struct const_subarray; template friend struct static_array; // TODO(correaa) check if this is necessary template friend constexpr auto static_array_cast(subarray const&) -> decltype(auto); - template - friend constexpr auto reinterpret_array_cast(subarray&& self) { - return std::move(self).template reinterpret_array_cast::template rebind>(); - } - template - friend constexpr auto reinterpret_array_cast(subarray const& self) { - return self.template reinterpret_array_cast::template rebind>(); - } + // template + // friend constexpr auto reinterpret_array_cast(const_subarray&& self) { + // return std::move(self).template reinterpret_array_cast::template rebind>(); + // } + // template + // friend constexpr auto reinterpret_array_cast(const_subarray const& self) { + // return self.template reinterpret_array_cast::template rebind>(); + // } public: - friend constexpr auto sizes(subarray const& self) noexcept -> typename subarray::sizes_type {return self.sizes();} // needed by nvcc - friend constexpr auto size (subarray const& self) noexcept -> typename subarray::size_type {return self.size ();} // needed by nvcc + friend constexpr auto sizes(const_subarray const& self) noexcept -> typename const_subarray::sizes_type {return self.sizes();} // needed by nvcc + friend constexpr auto size (const_subarray const& self) noexcept -> typename const_subarray::size_type {return self.size ();} // needed by nvcc - constexpr auto operator+() const -> decay_type {return decay();} + constexpr auto operator+() const { return decay(); } - subarray(subarray&&) noexcept = default; // in C++ 14 this is necessary to return array references from functions -// in c++17 things changed and non-moveable non-copyable types can be returned from functions and captured by auto + const_subarray(const_subarray&&) noexcept = default; // in C++ 14 this is necessary to return array references from functions + // in c++17 things changed and non-moveable non-copyable types can be returned from functions and captured by auto protected: - template friend struct subarray_ptr; - template friend struct array_iterator; + template friend struct subarray_ptr; + template friend struct array_iterator; public: - friend constexpr auto dimensionality(subarray const& /*self*/) -> dimensionality_type {return 1;} - - auto operator=(std::initializer_list values) && -> subarray& {operator=(values); return *this;} - auto operator=(std::initializer_list values) & -> subarray& { - assert( static_cast(values.size()) == this->size() ); - adl_copy_n(values.begin(), values.size(), begin()); - return *this; - } + friend constexpr auto dimensionality(const_subarray const& /*self*/) -> dimensionality_type {return 1;} + // // NOLINTNEXTLINE(runtime/operator) + // BOOST_MULTI_HD constexpr auto operator&() && { return subarray_ptr{this->base_, this->layout()}; } // NOLINT(google-runtime-operator) : taking address of a reference-like object should be allowed //NOSONAR + // // NOLINTNEXTLINE(runtime/operator) + // BOOST_MULTI_HD constexpr auto operator&() & { return subarray_ptr{this->base_, this->layout()}; } // NOLINT(google-runtime-operator) : taking address of a reference-like object should be allowed //NOSONAR // NOLINTNEXTLINE(runtime/operator) - BOOST_MULTI_HD constexpr auto operator&() && { return subarray_ptr{this->base_, this->layout()}; } // NOLINT(google-runtime-operator) : taking address of a reference-like object should be allowed //NOSONAR - // NOLINTNEXTLINE(runtime/operator) - BOOST_MULTI_HD constexpr auto operator&() & { return subarray_ptr{this->base_, this->layout()}; } // NOLINT(google-runtime-operator) : taking address of a reference-like object should be allowed //NOSONAR - // NOLINTNEXTLINE(runtime/operator) - BOOST_MULTI_HD constexpr auto operator&() const& {return subarray_ptr{this->base_, this->layout()};} // NOLINT(google-runtime-operator) extend semantics //NOSONAR + BOOST_MULTI_HD constexpr auto operator&() const& {return const_subarray_ptr{this->base_, this->layout()};} // NOLINT(google-runtime-operator) extend semantics //NOSONAR - BOOST_MULTI_HD constexpr void assign(std::initializer_list values) const {assert( values.size() == static_cast(this->size()) ); + BOOST_MULTI_HD constexpr void assign(std::initializer_list values) const {assert( values.size() == static_cast(this->size()) ); assign(values.begin(), values.end()); } template @@ -2049,35 +2675,45 @@ struct subarray template constexpr void assign(It first, It last)&& {assign(first, last);} - constexpr auto operator=(subarray&& other) & noexcept(std::is_nothrow_copy_assignable_v) // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor,cppcoreguidelines-noexcept-move-operations) //NOSONAR - -> subarray& { // lints(cppcoreguidelines-special-member-functions,hicpp-special-member-functions) - operator=(other); - return *this; // lints([cppcoreguidelines-c-copy-assignment-signature,misc-unconventional-assign-operator) - } + // constexpr auto operator=(const_subarray&& other) & noexcept(std::is_nothrow_copy_assignable_v) // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor,cppcoreguidelines-noexcept-move-operations) //NOSONAR + // -> const_subarray& { // lints(cppcoreguidelines-special-member-functions,hicpp-special-member-functions) + // operator=(other); + // return *this; // lints([cppcoreguidelines-c-copy-assignment-signature,misc-unconventional-assign-operator) + // } - constexpr auto operator=(subarray const& other) const& -> subarray const& = delete; - constexpr auto operator=(subarray const& other) & -> subarray& { - static_assert(std::is_copy_assignable_v, "assignment requires element-wise assignment"); // TODO(correaa) : make sfinae friendly - if(this == std::addressof(other)) {return *this;} - assert(this->extension() == other.extension()); - elements() = other.elements(); - return *this; - } + constexpr auto operator=(const_subarray const&) const& -> const_subarray const& = delete; + constexpr auto operator=(const_subarray &&) const& -> const_subarray const& = delete; - constexpr auto operator=(subarray const& other) && -> subarray& { - if(this == std::addressof(other)) {return *this;} // lints cert-oop54-cpp - operator=(other); return *this; - } + // constexpr auto operator=(const_subarray const& other) && -> const_subarray& { + // if(this == std::addressof(other)) {return *this;} // lints cert-oop54-cpp + // operator=(other); return *this; + // } - [[deprecated("for compatibility with ranges")]] constexpr auto operator=(subarray const& other) const&& -> subarray const&&; // NOLINT(cppcoreguidelines-c-copy-assignment-signature,misc-unconventional-assign-operator) //NOSONAR this is needed to satify the std::indirectly_writable concept + // [[deprecated("for compatibility with ranges")]] constexpr auto operator=(const_subarray const& other) const&& -> const_subarray const&&; // NOLINT(cppcoreguidelines-c-copy-assignment-signature,misc-unconventional-assign-operator) //NOSONAR this is needed to satify the std::indirectly_writable concept // { // something like this will fail // if(this == std::addressof(other)) {return static_cast(*this);} // lints cert-oop54-cpp // const_cast(*this).operator=(other); // return static_cast(*this); // } + template< + class ECPtr, + class = std::enable_if_t< std::is_same_v && !std::is_same_v > // NOLINT(modernize-use-constraints) TODO(correaa) for C++20 + > + constexpr auto operator=(const_subarray const& other) const && -> const_subarray& {assert(0); operator=( other ); return *this;} // required by https://en.cppreference.com/w/cpp/iterator/indirectly_writable for std::ranges::copy_n + + using cursor = cursor_t; + using const_cursor = cursor_t; + private: + constexpr auto home_aux_() const {return cursor(this->base_, this->strides());} + + public: + constexpr auto home() const& -> const_cursor {return home_aux_();} + private: - BOOST_MULTI_HD constexpr auto at_aux_(index idx) const -> typename subarray::reference { // NOLINT(readability-const-return-type) fancy pointers can deref into const values to avoid assignment + template friend class subarray; + + BOOST_MULTI_HD constexpr auto at_aux_(index idx) const -> typename const_subarray::reference { // NOLINT(readability-const-return-type) fancy pointers can deref into const values to avoid assignment // MULTI_ACCESS_ASSERT(this->extension().contains(i)&&"out of bounds"); // NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay) : normal in a constexpr function #if defined(__clang__) #pragma clang diagnostic push @@ -2096,13 +2732,13 @@ struct subarray public: constexpr auto broadcasted() const& { - multi::layout_t<2> const new_layout{this->layout(), 0, 0, std::numeric_limits::max()}; - return subarray{new_layout, types::base_}; + multi::layout_t<2> const new_layout{this->layout(), 0, 0, (std::numeric_limits::max)()}; + return const_subarray{new_layout, types::base_}; } - BOOST_MULTI_HD constexpr auto operator[](index idx) const& -> typename subarray::const_reference { return at_aux_(idx); } // NOLINT(readability-const-return-type) fancy pointers can deref into const values to avoid assignment - BOOST_MULTI_HD constexpr auto operator[](index idx) & -> typename subarray:: reference { return at_aux_(idx); } // NOLINT(readability-const-return-type) fancy pointers can deref into const values to avoid assignment - BOOST_MULTI_HD constexpr auto operator[](index idx) && -> typename subarray:: reference { return at_aux_(idx); } // NOLINT(readability-const-return-type) fancy pointers can deref into const values to avoid assignment + BOOST_MULTI_HD constexpr auto operator[](index idx) const& -> typename const_subarray::const_reference { return at_aux_(idx); } // NOLINT(readability-const-return-type) fancy pointers can deref into const values to avoid assignment + // BOOST_MULTI_HD constexpr auto operator[](index idx) & -> typename const_subarray:: reference { return at_aux_(idx); } // NOLINT(readability-const-return-type) fancy pointers can deref into const values to avoid assignment + // BOOST_MULTI_HD constexpr auto operator[](index idx) && -> typename const_subarray:: reference { return at_aux_(idx); } // NOLINT(readability-const-return-type) fancy pointers can deref into const values to avoid assignment constexpr auto front() const& -> const_reference {return *begin();} constexpr auto back() const& -> const_reference {return *std::prev(end(), 1);} @@ -2113,27 +2749,27 @@ struct subarray constexpr auto front() & -> reference {return *begin();} constexpr auto back() & -> reference {return *std::prev(end(), 1);} - template, int> = 0 - > - constexpr operator subarray&& () const & { // NOLINT(google-explicit-constructor,hicpp-explicit-conversions) this is needed by std::ranges, TODO(correaa) think if this can be solved by inheritance from subarray - return std::move(reinterpret_cast const&>(*this)); // NOLINT([ppcoreguidelines-pro-type-reinterpret-cast,cppcoreguidelines-pro-type-reinterpret-cast) think if this can be solved by inheritance from subarray - } + // template, int> = 0 + // > + // constexpr operator subarray&& () const & { // NOLINT(google-explicit-constructor,hicpp-explicit-conversions) this is needed by std::ranges, TODO(correaa) think if this can be solved by inheritance from subarray + // return std::move(reinterpret_cast const&>(*this)); // NOLINT([ppcoreguidelines-pro-type-reinterpret-cast,cppcoreguidelines-pro-type-reinterpret-cast) think if this can be solved by inheritance from subarray + // } - private: - template + private: + template static constexpr auto apply_impl_(Self&& self, Tuple const& tuple, std::index_sequence /*012*/) -> decltype(auto) { return std::forward(self)(std::get(tuple)...); } public: template BOOST_MULTI_HD constexpr auto apply(Tuple const& tuple) const& -> decltype(auto) {return apply_impl_( *this , tuple, std::make_index_sequence>());} - template BOOST_MULTI_HD constexpr auto apply(Tuple const& tuple) && -> decltype(auto) {return apply_impl_(std::move(*this), tuple, std::make_index_sequence>());} - template constexpr auto apply(Tuple const& tuple) & -> decltype(auto) {return apply_impl_( *this , tuple, std::make_index_sequence>());} + // template BOOST_MULTI_HD constexpr auto apply(Tuple const& tuple) && -> decltype(auto) {return apply_impl_(std::move(*this), tuple, std::make_index_sequence>());} + // template constexpr auto apply(Tuple const& tuple) & -> decltype(auto) {return apply_impl_( *this , tuple, std::make_index_sequence>());} - template::value == 0), int> = 0> BOOST_MULTI_HD constexpr auto operator[](Tuple const& /*empty*/) const& -> decltype(auto) {return *this;} - template::value == 1), int> = 0> BOOST_MULTI_HD constexpr auto operator[](Tuple const& indices ) const& -> decltype(auto) {return operator[](std::get<0>(indices));} - template::value > 1), int> = 0> BOOST_MULTI_HD constexpr auto operator[](Tuple const& indices ) const& + template::value == 0), int> = 0> BOOST_MULTI_HD constexpr auto operator[](Tuple const& /*empty*/) const& -> decltype(auto) { return *this; } // NOLINT(modernize-use-constraints) TODO(correaa) + template::value == 1), int> = 0> BOOST_MULTI_HD constexpr auto operator[](Tuple const& indices ) const& -> decltype(auto) { return operator[](std::get<0>(indices)); } // NOLINT(modernize-use-constraints) TODO(correaa) + template::value > 1), int> = 0> BOOST_MULTI_HD constexpr auto operator[](Tuple const& indices ) const& // NOLINT(modernize-use-constraints) TODO(correaa) ->decltype(operator[](std::get<0>(indices))[detail::tuple_tail(indices)]) { return operator[](std::get<0>(indices))[detail::tuple_tail(indices)]; } @@ -2157,7 +2793,7 @@ struct subarray constexpr auto reindexed(index first) & { typename types::layout_t new_layout = this->layout(); new_layout.reindex(first); - return subarray{new_layout, types::base_}; + return const_subarray{new_layout, types::base_}; } private: @@ -2169,16 +2805,14 @@ struct subarray this->layout().offset(), this->stride()*count }; - return subarray{new_layout, this->base_}; + return const_subarray{new_layout, this->base_}; } public: - constexpr auto taked(difference_type count) const& -> basic_const_array {return taked_aux_(count);} - constexpr auto taked(difference_type count) && -> subarray {return taked_aux_(count);} - constexpr auto taked(difference_type count) & -> subarray {return taked_aux_(count);} + constexpr auto taked(difference_type count) const& -> const_subarray {return taked_aux_(count);} private: - BOOST_MULTI_HD constexpr auto dropped_aux_(difference_type count) const -> subarray { + BOOST_MULTI_HD constexpr auto dropped_aux_(difference_type count) const -> const_subarray { assert( count <= this->size() ); typename types::layout_t const new_layout{ this->layout().sub(), @@ -2186,15 +2820,31 @@ struct subarray this->layout().offset(), this->stride()*(this->size() - count) }; - return subarray{new_layout, this->base_ + (count*this->layout().stride() - this->layout().offset())}; + + #if defined(__clang__) + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wunknown-warning-option" + #pragma clang diagnostic ignored "-Wunsafe-buffer-usage" // TODO(correaa) use checked span + #endif + + return const_subarray{new_layout, this->base_ + (count*this->layout().stride() - this->layout().offset())}; + + #if defined(__clang__) + #pragma clang diagnostic pop + #endif } public: - constexpr auto dropped(difference_type count) const& -> basic_const_array { return dropped_aux_(count); } - constexpr auto dropped(difference_type count) && -> subarray { return dropped_aux_(count); } - constexpr auto dropped(difference_type count) & -> subarray { return dropped_aux_(count); } + constexpr auto dropped(difference_type count) const& -> const_subarray { return dropped_aux_(count); } private: + + #if defined(__clang__) + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wunknown-warning-option" + #pragma clang diagnostic ignored "-Wunsafe-buffer-usage" // TODO(correaa) use checked span + #endif + BOOST_MULTI_HD constexpr auto sliced_aux_(index first, index last) const { typename types::layout_t new_layout = this->layout(); if(this->is_empty()) { @@ -2204,13 +2854,17 @@ struct subarray (new_layout.nelems() /= this->size())*=(last - first); } - return subarray{new_layout, this->base_ + (first*this->layout().stride() - this->layout().offset())}; + return const_subarray{new_layout, this->base_ + (first*this->layout().stride() - this->layout().offset())}; } + #if defined(__clang__) + #pragma clang diagnostic pop + #endif + public: BOOST_MULTI_HD constexpr auto sliced(index first, index last) const& -> basic_const_array /*const*/ { return basic_const_array{sliced_aux_(first, last)};} // NOLINT(readability-const-return-type) - BOOST_MULTI_HD constexpr auto sliced(index first, index last) & -> subarray { return sliced_aux_(first, last) ;} - BOOST_MULTI_HD constexpr auto sliced(index first, index last) && -> subarray { return sliced_aux_(first, last) ;} + BOOST_MULTI_HD constexpr auto sliced(index first, index last) & -> const_subarray { return sliced_aux_(first, last) ;} + BOOST_MULTI_HD constexpr auto sliced(index first, index last) && -> const_subarray { return sliced_aux_(first, last) ;} using elements_iterator = elements_iterator_t; using celements_iterator = elements_iterator_t; @@ -2229,114 +2883,119 @@ struct subarray constexpr auto celements() const -> const_elements_range {return elements_aux_();} constexpr auto hull() const -> std::pair { - return {std::min(this->base(), this->base() + this->hull_size()), std::abs(this->hull_size())}; + return {(std::min)(this->base(), this->base() + this->hull_size()), std::abs(this->hull_size())}; // paren for MSVC macros } - /*[[gnu::pure]]*/ constexpr auto blocked(index first, index last)& -> subarray { + /*[[gnu::pure]]*/ constexpr auto blocked(index first, index last)& -> const_subarray { return sliced(first, last).reindexed(first); } - /*[[gnu::pure]]*/ constexpr auto stenciled(typename subarray::index_extension ext) -> subarray { + /*[[gnu::pure]]*/ constexpr auto stenciled(typename const_subarray::index_extension ext) -> const_subarray { return blocked(ext.first(), ext.last()); } private: - constexpr auto strided_aux_(difference_type diff) const -> subarray { + constexpr auto strided_aux_(difference_type diff) const -> const_subarray { auto const new_layout = typename types::layout_t{this->layout().sub(), this->layout().stride()*diff, this->layout().offset(), this->layout().nelems()}; return {new_layout, types::base_}; } public: constexpr auto strided(difference_type diff) const& -> basic_const_array { return strided_aux_(diff);} - constexpr auto strided(difference_type diff) && -> subarray { return strided_aux_(diff);} - constexpr auto strided(difference_type diff) & -> subarray { return strided_aux_(diff);} BOOST_MULTI_HD constexpr auto sliced(index first, index last, difference_type stride) const& -> basic_const_array { return sliced(first, last).strided(stride); } - BOOST_MULTI_HD constexpr auto sliced(index first, index last, difference_type stride) && -> subarray { return sliced(first, last).strided(stride); } - BOOST_MULTI_HD constexpr auto sliced(index first, index last, difference_type stride) & -> subarray { return sliced(first, last).strided(stride); } + // BOOST_MULTI_HD constexpr auto sliced(index first, index last, difference_type stride) && -> const_subarray { return sliced(first, last).strided(stride); } + // BOOST_MULTI_HD constexpr auto sliced(index first, index last, difference_type stride) & -> const_subarray { return sliced(first, last).strided(stride); } - BOOST_MULTI_HD constexpr auto range(index_range const& rng) & {return sliced(rng.front(), rng.last());} - BOOST_MULTI_HD constexpr auto range(index_range const& rng) && {return std::move(*this).sliced(rng.front(), rng.last());} + // BOOST_MULTI_HD constexpr auto range(index_range const& rng) & {return sliced(rng.front(), rng.last());} + // BOOST_MULTI_HD constexpr auto range(index_range const& rng) && {return std::move(*this).sliced(rng.front(), rng.last());} BOOST_MULTI_HD constexpr auto range(index_range const& rng) const& {return sliced(rng.front(), rng.last());} - BOOST_MULTI_HD constexpr auto operator()() const& -> basic_const_array {return {this->layout(), this->base()};} - BOOST_MULTI_HD constexpr auto operator()() && -> subarray {return *this;} - BOOST_MULTI_HD constexpr auto operator()() & -> subarray {return *this;} + BOOST_MULTI_HD constexpr auto operator()() const& -> const_subarray {return *this;} // const_subarray(this->base(), this->layout());} + // BOOST_MULTI_HD constexpr auto operator()() && -> const_subarray {return *this;} + // BOOST_MULTI_HD constexpr auto operator()() & -> const_subarray {return *this;} - BOOST_MULTI_HD constexpr auto operator()(index_range const& rng) & {return range(rng);} - BOOST_MULTI_HD constexpr auto operator()(index_range const& rng) && {return std::move(*this).range(rng);} + // BOOST_MULTI_HD constexpr auto operator()(index_range const& rng) & {return range(rng);} + // BOOST_MULTI_HD constexpr auto operator()(index_range const& rng) && {return std::move(*this).range(rng);} BOOST_MULTI_HD constexpr auto operator()(index_range const& rng) const& {return range(rng);} - BOOST_MULTI_HD constexpr auto operator()(index idx) & -> decltype(auto) {return operator[](idx);} - BOOST_MULTI_HD constexpr auto operator()(index idx) && -> decltype(auto) {return std::move(*this).operator[](idx);} - BOOST_MULTI_HD constexpr auto operator()(index idx) const& -> decltype(auto) {return operator[](idx);} + // BOOST_MULTI_HD constexpr auto operator()(index idx) & -> decltype(auto) {return operator[](idx);} + // BOOST_MULTI_HD constexpr auto operator()(index idx) && -> decltype(auto) {return std::move(*this).operator[](idx);} + BOOST_MULTI_HD constexpr auto operator()(index idx) const -> decltype(auto) {return operator[](idx);} private: - BOOST_MULTI_HD constexpr auto paren_aux_() & {return operator()();} - BOOST_MULTI_HD constexpr auto paren_aux_() && {return operator()();} + // BOOST_MULTI_HD constexpr auto paren_aux_() & {return operator()();} + // BOOST_MULTI_HD constexpr auto paren_aux_() && {return operator()();} BOOST_MULTI_HD constexpr auto paren_aux_() const& {return operator()();} - BOOST_MULTI_HD constexpr auto paren_aux_(index_range const& rng) & {return range(rng);} - BOOST_MULTI_HD constexpr auto paren_aux_(index_range const& rng) && {return range(rng);} + // BOOST_MULTI_HD constexpr auto paren_aux_(index_range const& rng) & {return range(rng);} + // BOOST_MULTI_HD constexpr auto paren_aux_(index_range const& rng) && {return range(rng);} BOOST_MULTI_HD constexpr auto paren_aux_(index_range const& rng) const& {return range(rng);} - BOOST_MULTI_HD constexpr auto paren_aux_(index idx) & -> decltype(auto) {return operator[](idx);} - BOOST_MULTI_HD constexpr auto paren_aux_(index idx) && -> decltype(auto) {return operator[](idx);} + // BOOST_MULTI_HD constexpr auto paren_aux_(index idx) & -> decltype(auto) {return operator[](idx);} + // BOOST_MULTI_HD constexpr auto paren_aux_(index idx) && -> decltype(auto) {return operator[](idx);} BOOST_MULTI_HD constexpr auto paren_aux_(index idx) const& -> decltype(auto) {return operator[](idx);} - constexpr auto paren_aux_(intersecting_range const& rng) & -> decltype(auto) {return paren_aux_(intersection(this->extension(), rng));} - constexpr auto paren_aux_(intersecting_range const& rng) && -> decltype(auto) {return std::move(*this).paren_aux_(intersection(this->extension(), rng));} + // constexpr auto paren_aux_(intersecting_range const& rng) & -> decltype(auto) {return paren_aux_(intersection(this->extension(), rng));} + // constexpr auto paren_aux_(intersecting_range const& rng) && -> decltype(auto) {return std::move(*this).paren_aux_(intersection(this->extension(), rng));} constexpr auto paren_aux_(intersecting_range const& rng) const& -> decltype(auto) {return paren_aux_(intersection(this->extension(), rng));} public: - constexpr auto operator()(intersecting_range const& isrange) & -> decltype(auto) {return paren_aux_(isrange);} - constexpr auto operator()(intersecting_range const& isrange) && -> decltype(auto) {return std::move(*this).paren_aux_(isrange);} - constexpr auto operator()(intersecting_range const& isrange) const& -> decltype(auto) {return paren_aux_(isrange);} + // constexpr auto operator()(intersecting_range const& isrange) & -> decltype(auto) {return paren_aux_(isrange);} + // constexpr auto operator()(intersecting_range const& isrange) && -> decltype(auto) {return std::move(*this).paren_aux_(isrange);} + BOOST_MULTI_HD constexpr auto operator()(intersecting_range const& isrange) const& -> decltype(auto) {return paren_aux_(isrange);} - template - constexpr auto operator()(Args&&... args) & - ->decltype(paren_(*this, std::forward(args)...)) { - return paren_(*this, std::forward(args)...); } + // template + // constexpr auto operator()(Args&&... args) & + // ->decltype(paren_(*this, std::forward(args)...)) { + // return paren_(*this, std::forward(args)...); } - template - constexpr auto operator()(Args&&... args) && - ->decltype(paren_(std::move(*this), std::forward(args)...)) { - return paren_(std::move(*this), std::forward(args)...); } + // template + // constexpr auto operator()(Args&&... args) && + // ->decltype(paren_(std::move(*this), std::forward(args)...)) { + // return paren_(std::move(*this), std::forward(args)...); } template - constexpr auto operator()(Args&&... args) const& + BOOST_MULTI_HD constexpr auto operator()(Args&&... args) const& ->decltype(paren_(*this, std::forward(args)...)) { return paren_(*this, std::forward(args)...); } - using partitioned_type = subarray; - using partitioned_const_type = subarray; - private: - BOOST_MULTI_HD constexpr auto partitioned_aux_(size_type size) const -> partitioned_type { - assert( size != 0 ); // NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay) : normal in a constexpr function + BOOST_MULTI_HD constexpr auto partitioned_aux_(size_type size) const { + assert( size != 0 ); assert( (this->layout().nelems() % size) == 0 ); // TODO(correaa) remove assert? truncate left over? (like mathematica) // NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay) : normal in a constexpr function multi::layout_t<2> new_layout{this->layout(), this->layout().nelems()/size, 0, this->layout().nelems()}; new_layout.sub().nelems() /= size; // TODO(correaa) : don't use mutation - return {new_layout, types::base_}; + return subarray(new_layout, types::base_); } public: - BOOST_MULTI_HD constexpr auto partitioned(size_type size) const& -> partitioned_const_type {return partitioned_aux_(size);} - BOOST_MULTI_HD constexpr auto partitioned(size_type size) & -> partitioned_type {return partitioned_aux_(size);} - BOOST_MULTI_HD constexpr auto partitioned(size_type size) && -> partitioned_type {return partitioned_aux_(size);} + BOOST_MULTI_HD constexpr auto partitioned(size_type size) const& -> const_subarray {return partitioned_aux_(size);} private: - BOOST_MULTI_HD constexpr auto chunked_aux_(size_type size) const -> partitioned_type { + BOOST_MULTI_HD constexpr auto chunked_aux_(size_type size) const { assert( this->size() % size == 0 ); return partitioned_aux_(this->size()/size); } public: // in Mathematica this is called Partition https://reference.wolfram.com/language/ref/Partition.html in RangesV3 it is called chunk - BOOST_MULTI_HD constexpr auto chunked(size_type size) const& -> partitioned_const_type {return chunked_aux_(size);} - BOOST_MULTI_HD constexpr auto chunked(size_type size) & -> partitioned_type {return chunked_aux_(size);} - BOOST_MULTI_HD constexpr auto chunked(size_type size) && -> partitioned_type {return chunked_aux_(size);} + BOOST_MULTI_HD constexpr auto chunked(size_type size) const& -> const_subarray {return chunked_aux_(size);} + // BOOST_MULTI_HD constexpr auto chunked(size_type size) & -> partitioned_type {return chunked_aux_(size);} + // BOOST_MULTI_HD constexpr auto chunked(size_type size) && -> partitioned_type {return chunked_aux_(size);} + + constexpr auto tiled(size_type count) const & { + assert(count != 0); + struct divided_type { + const_subarray quotient; + const_subarray remainder; + }; + return divided_type{ + this->taked(this->size() - (this->size() % count)).chunked(count), + this->dropped(this->size() - (this->size() % count)) + }; + } private: - constexpr auto reversed_aux_() const -> subarray { + constexpr auto reversed_aux_() const -> const_subarray { auto new_layout = this->layout(); new_layout.reverse(); return {new_layout, types::base_}; @@ -2344,27 +3003,27 @@ struct subarray public: constexpr auto reversed() const& -> basic_const_array {return reversed_aux_();} - constexpr auto reversed() & -> subarray {return reversed_aux_();} - constexpr auto reversed() && -> subarray {return reversed_aux_();} + constexpr auto reversed() & -> const_subarray {return reversed_aux_();} + constexpr auto reversed() && -> const_subarray {return reversed_aux_();} - friend constexpr auto reversed(subarray const& self) -> basic_const_array {return self .reversed();} - friend constexpr auto reversed(subarray & self) -> subarray {return self .reversed();} - friend constexpr auto reversed(subarray && self) -> subarray {return std::move(self).reversed();} + friend constexpr auto reversed(const_subarray const& self) -> basic_const_array {return self .reversed();} + friend constexpr auto reversed(const_subarray & self) -> const_subarray {return self .reversed();} + friend constexpr auto reversed(const_subarray && self) -> const_subarray {return std::move(self).reversed();} - friend constexpr auto rotated(subarray const& self) -> decltype(auto) {return self. rotated();} - friend constexpr auto unrotated(subarray const& self) -> decltype(auto) {return self.unrotated();} + // friend constexpr auto rotated(const_subarray const& self) -> decltype(auto) {return self. rotated();} + // friend constexpr auto unrotated(const_subarray const& self) -> decltype(auto) {return self.unrotated();} - constexpr auto rotated() & -> decltype(auto) {return operator()();} - constexpr auto rotated() && -> decltype(auto) {return operator()();} - constexpr auto rotated() const& -> decltype(auto) {return operator()();} + // constexpr auto rotated() & -> decltype(auto) {return operator()();} + // constexpr auto rotated() && -> decltype(auto) {return operator()();} + BOOST_MULTI_HD constexpr auto rotated() const& { return operator()(); } + BOOST_MULTI_HD constexpr auto unrotated() const& { return operator()(); } - BOOST_MULTI_HD constexpr auto unrotated() const& -> decltype(auto) {return operator()();} - BOOST_MULTI_HD constexpr auto unrotated() && -> decltype(auto) {return operator()();} - BOOST_MULTI_HD constexpr auto unrotated() & -> decltype(auto) {return operator()();} + auto transposed() const& = delete; + auto flatted() const& = delete; using iterator = typename multi::array_iterator; - using const_iterator = typename multi::array_iterator; - using move_iterator = array_iterator; + using const_iterator = typename multi::array_iterator; + using move_iterator = typename multi::array_iterator; using reverse_iterator [[deprecated]] = std::reverse_iterator< iterator>; using const_reverse_iterator [[deprecated]] = std::reverse_iterator; @@ -2376,7 +3035,9 @@ struct subarray template< class Range, std::enable_if_t>::value, int> =0, - class = decltype(Range{std::declval(), std::declval()}) + std::enable_if_t>::value, int> =0, + class = decltype((void)std::declval().begin(), std::declval().end() ), + class = decltype(Range{std::declval(), std::declval()}) > constexpr explicit operator Range() const { // vvv Range{...} needed by Windows GCC? @@ -2384,29 +3045,39 @@ struct subarray } private: - BOOST_MULTI_HD constexpr explicit subarray(iterator begin, iterator end) - : subarray { - layout_type{ {}/*begin->layout()*/, begin.stride(), 0, begin.stride()*(end - begin)}, - begin.base() - } { - assert(begin.stride() == end.stride() ); // NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay) : normal in a constexpr function - // assert(begin->layout() == end->layout()); // NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay) : normal in a constexpr function - } - friend constexpr auto ref(iterator begin, iterator end) -> multi::subarray; + // [[deprecated("remove")]] BOOST_MULTI_HD constexpr explicit const_subarray(iterator begin, iterator end) + // : const_subarray { + // layout_type{ {}/*begin->layout()*/, begin.stride(), 0, begin.stride()*(end - begin)}, + // begin.base() + // } { + // assert(begin.stride() == end.stride() ); // NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay) : normal in a constexpr function + // // assert(begin->layout() == end->layout()); // NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay) : normal in a constexpr function + // } + // friend constexpr auto ref(iterator begin, iterator end) -> multi::subarray; + + #if defined(__clang__) + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wunknown-warning-option" + #pragma clang diagnostic ignored "-Wunsafe-buffer-usage" // TODO(correaa) use checked span + #endif constexpr BOOST_MULTI_HD auto begin_aux_() const {return iterator{this->base_ , this->stride()};} constexpr auto end_aux_ () const {return iterator{this->base_ + types::nelems(), this->stride()};} + #if defined(__clang__) + #pragma clang diagnostic pop + #endif + public: BOOST_MULTI_HD constexpr auto begin() const& -> const_iterator {return begin_aux_();} constexpr auto begin() & -> iterator {return begin_aux_();} constexpr auto begin() && -> iterator {return begin_aux_();} - constexpr auto mbegin() & {return move_iterator{begin()};} - constexpr auto mend () & {return move_iterator{end ()};} + // constexpr auto mbegin() & {return move_iterator{begin()};} + // constexpr auto mend () & {return move_iterator{end ()};} - constexpr auto mbegin() && {return move_iterator{begin()};} - constexpr auto mend () && {return move_iterator{end ()};} + // constexpr auto mbegin() && {return move_iterator{begin()};} + // constexpr auto mend () && {return move_iterator{end ()};} constexpr auto end () const& -> const_iterator {return end_aux_();} constexpr auto end () & -> iterator {return end_aux_();} @@ -2415,72 +3086,74 @@ struct subarray [[deprecated("implement as negative stride")]] constexpr auto rbegin() const& {return const_reverse_iterator(end ());} // TODO(correaa) implement as negative stride? [[deprecated("implement as negative stride")]] constexpr auto rend () const& {return const_reverse_iterator(begin());} // TODO(correaa) implement as negative stride? - BOOST_MULTI_FRIEND_CONSTEXPR auto begin(subarray const& self) -> const_iterator {return self .begin();} - BOOST_MULTI_FRIEND_CONSTEXPR auto begin(subarray & self) -> iterator {return self .begin();} - BOOST_MULTI_FRIEND_CONSTEXPR auto begin(subarray && self) -> iterator {return std::move(self).begin();} + BOOST_MULTI_FRIEND_CONSTEXPR auto begin(const_subarray const& self) -> const_iterator {return self .begin();} + BOOST_MULTI_FRIEND_CONSTEXPR auto begin(const_subarray & self) -> iterator {return self .begin();} + BOOST_MULTI_FRIEND_CONSTEXPR auto begin(const_subarray && self) -> iterator {return std::move(self).begin();} - BOOST_MULTI_FRIEND_CONSTEXPR auto end (subarray const& self) -> const_iterator {return self .end() ;} - BOOST_MULTI_FRIEND_CONSTEXPR auto end (subarray & self) -> iterator {return self .end() ;} - BOOST_MULTI_FRIEND_CONSTEXPR auto end (subarray && self) -> iterator {return std::move(self).end() ;} + BOOST_MULTI_FRIEND_CONSTEXPR auto end (const_subarray const& self) -> const_iterator {return self .end() ;} + BOOST_MULTI_FRIEND_CONSTEXPR auto end (const_subarray & self) -> iterator {return self .end() ;} + BOOST_MULTI_FRIEND_CONSTEXPR auto end (const_subarray && self) -> iterator {return std::move(self).end() ;} BOOST_MULTI_HD constexpr auto cbegin() const& -> const_iterator {return begin();} constexpr auto cend () const& -> const_iterator {return end() ;} - friend BOOST_MULTI_HD /*constexpr*/ auto cbegin(subarray const& self) {return self.cbegin();} - BOOST_MULTI_FRIEND_CONSTEXPR auto cend (subarray const& self) {return self.cend() ;} + friend BOOST_MULTI_HD /*constexpr*/ auto cbegin(const_subarray const& self) {return self.cbegin();} + BOOST_MULTI_FRIEND_CONSTEXPR auto cend (const_subarray const& self) {return self.cend() ;} - template constexpr auto operator=(subarray const& other) && -> subarray& {operator=( other ); return *this;} - template constexpr auto operator=(subarray const& other) & -> subarray& { - assert(other.extensions() == this->extensions()); - elements() = other.elements(); - return *this; - } + // // fix mutation + // template constexpr auto operator=(const_subarray const& other) && -> const_subarray& {operator=( other ); return *this;} + // template constexpr auto operator=(const_subarray const& other) & -> const_subarray& { + // assert(other.extensions() == this->extensions()); + // elements() = other.elements(); + // return *this; + // } - template constexpr auto operator=(subarray && other) && -> subarray& {operator=(std::move(other)); return *this;} - template constexpr auto operator=(subarray && other) & -> subarray& { - assert(this->extensions() == other.extensions()); - elements() = std::move(other).elements(); - return *this; - } + // // fix mutation + // template constexpr auto operator=(const_subarray && other) && -> const_subarray& {operator=(std::move(other)); return *this;} + // template constexpr auto operator=(const_subarray && other) & -> const_subarray& { + // assert(this->extensions() == other.extensions()); + // elements() = std::move(other).elements(); + // return *this; + // } - template< - class Range, - class = std::enable_if_t >, - class = std::enable_if_t::value> - > - constexpr auto operator=(Range const& rng) & // TODO(correaa) check that you LHS is not read-only? - -> subarray& { // lints(cppcoreguidelines-c-copy-assignment-signature,misc-unconventional-assign-operator) - assert(this->size() == static_cast(adl_size(rng))); // TODO(correaa) or use std::cmp_equal? - adl_copy_n(adl_begin(rng), adl_size(rng), begin()); - return *this; - } - template< - class Range, - class = std::enable_if_t>, - class = std::enable_if_t::value> - > - constexpr auto operator=(Range const& rng) && -> subarray& {operator=(rng); return *this;} + // template< + // class Range, + // class = std::enable_if_t >, + // class = std::enable_if_t::value> // NOLINT(modernize-use-constraints) TODO(correaa) for C++20 + // > + // constexpr auto operator=(Range const& rng) & // TODO(correaa) check that you LHS is not read-only? + // -> const_subarray& { // lints(cppcoreguidelines-c-copy-assignment-signature,misc-unconventional-assign-operator) + // assert(this->size() == static_cast(adl_size(rng))); // TODO(correaa) or use std::cmp_equal? + // adl_copy_n(adl_begin(rng), adl_size(rng), begin()); + // return *this; + // } + // template< + // class Range, + // class = std::enable_if_t>, + // class = std::enable_if_t::value> // NOLINT(modernize-use-constraints) TODO(correaa) for C++20 + // > + // constexpr auto operator=(Range const& rng) && -> const_subarray& {operator=(rng); return *this;} template constexpr auto assign(It first) && ->decltype(adl_copy_n(first, std::declval(), std::declval()), void()) { return adl_copy_n(first, this-> size() , std::move(*this).begin()), void(); } - friend constexpr auto operator==(subarray const& self, subarray const& other) -> bool { + friend constexpr auto operator==(const_subarray const& self, const_subarray const& other) -> bool { return self.extension() == other.extension() && self.elements() == other.elements() ; } - friend constexpr auto operator!=(subarray const& self, subarray const& other) -> bool { + friend constexpr auto operator!=(const_subarray const& self, const_subarray const& other) -> bool { return self.extension() != other.extension() || self.elements() != other.elements() ; } - template - friend constexpr auto operator==(subarray const& self, subarray const& other) -> bool { + template + friend constexpr auto operator==(const_subarray const& self, const_subarray const& other) -> bool { return self.extension() == other.extension() && self.elements() == other.elements() @@ -2488,27 +3161,18 @@ struct subarray } template - friend constexpr auto operator!=(subarray const& self, subarray const& other) -> bool { + friend constexpr auto operator!=(const_subarray const& self, const_subarray const& other) -> bool { return self.extension() != other.extension() || self.elements() != other.elements() ; } - friend constexpr auto operator<(subarray const& self, subarray const& other) -> bool { return lexicographical_compare_(self, other); } - friend constexpr auto operator>(subarray const& self, subarray const& other) -> bool { return lexicographical_compare_(other, self); } // NOLINT(readability-suspicious-call-argument) + friend constexpr auto operator<(const_subarray const& self, const_subarray const& other) -> bool { return lexicographical_compare_(self, other); } + friend constexpr auto operator>(const_subarray const& self, const_subarray const& other) -> bool { return lexicographical_compare_(other, self); } // NOLINT(readability-suspicious-call-argument) - friend constexpr auto operator<=(subarray const& self, subarray const& other) -> bool { return lexicographical_compare_(self, other) || self == other; } - friend constexpr auto operator>=(subarray const& self, subarray const& other) -> bool { return lexicographical_compare_(other, self) || self == other; } // NOLINT(readability-suspicious-call-argument) - - constexpr void swap(subarray&& other) && noexcept { - assert(this->extension() == other.extension()); - adl_swap_ranges(this->elements().begin(), this->elements().end(), std::move(other).elements().begin()); - } - friend constexpr void swap(subarray&& self, subarray&& other) noexcept { std::move(self).swap(std::move(other)); } - - template>>> friend constexpr void swap(subarray&& self, A&& other) noexcept { std::move(self).swap(std::forward(other)); } - template>>> friend constexpr void swap(A&& other, subarray&& self) noexcept { std::move(self).swap(std::forward(other)); } + friend constexpr auto operator<=(const_subarray const& self, const_subarray const& other) -> bool { return lexicographical_compare_(self, other) || self == other; } + friend constexpr auto operator>=(const_subarray const& self, const_subarray const& other) -> bool { return lexicographical_compare_(other, self) || self == other; } // NOLINT(readability-suspicious-call-argument) private: template @@ -2559,7 +3223,7 @@ struct subarray template< class T2, class P2 = typename std::pointer_traits::template rebind, - class Element = typename subarray::element, + class Element = typename const_subarray::element, class PM = T2 std::decay_t::* > constexpr auto member_cast(PM member) const { @@ -2570,7 +3234,7 @@ struct subarray #if defined(__GNUC__) && !defined(__INTEL_COMPILER) // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) reinterpret is what the function does. alternative for GCC/NVCC - auto&& r1 = (*(reinterpret_cast(subarray::base_))).*member; // ->*pm; + auto&& r1 = (*(reinterpret_cast(const_subarray::base_))).*member; // ->*pm; // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) TODO(correaa) find a better way auto* p1 = &r1; P2 p2 = reinterpret_cast(p1); //NOSONAR #else @@ -2579,39 +3243,19 @@ struct subarray return subarray(this->layout().scale(sizeof(T), sizeof(T2)), p2); } - constexpr auto element_moved() & {return subarray{this->layout(), element_move_ptr{this->base()}};} - constexpr auto element_moved() && {return element_moved();} + // constexpr auto element_moved() & {return subarray(this->layout(), element_move_ptr{this->base_});} + // constexpr auto element_moved() && {return element_moved();} template::template rebind> constexpr auto reinterpret_array_cast() const& { assert( this->layout().stride()*static_cast(sizeof(T)) % static_cast(sizeof(T2)) == 0 ); - return subarray, 1, P2>{ + return const_subarray{ layout_type{this->layout().sub(), this->layout().stride()*static_cast(sizeof(T))/static_cast(sizeof(T2)), this->layout().offset()*static_cast(sizeof(T))/static_cast(sizeof(T2)), this->layout().nelems()*static_cast(sizeof(T))/static_cast(sizeof(T2))}, reinterpret_pointer_cast(this->base_) }; } - template::template rebind> - constexpr auto reinterpret_array_cast() & { - assert( this->layout().stride()*static_cast(sizeof(T)) % static_cast(sizeof(T2)) == 0 ); - - return subarray, 1, P2>{ - layout_type{this->layout().sub(), this->layout().stride()*static_cast(sizeof(T))/static_cast(sizeof(T2)), this->layout().offset()*static_cast(sizeof(T))/static_cast(sizeof(T2)), this->layout().nelems()*static_cast(sizeof(T))/static_cast(sizeof(T2))}, - reinterpret_pointer_cast(this->base()) - }; - } - - template::template rebind> - constexpr auto reinterpret_array_cast() && { - assert( this->layout().stride()*static_cast(sizeof(T)) % static_cast(sizeof(T2)) == 0 ); - - return subarray, 1, P2>{ - layout_type{this->layout().sub(), this->layout().stride()*static_cast(sizeof(T))/static_cast(sizeof(T2)), this->layout().offset()*static_cast(sizeof(T))/static_cast(sizeof(T2)), this->layout().nelems()*static_cast(sizeof(T))/static_cast(sizeof(T2))}, - reinterpret_pointer_cast(this->base()) - }; - } - template::template rebind > constexpr auto reinterpret_array_cast(size_type n) const& -> subarray, 2, P2> { // TODO(correaa) : use rebind for return type static_assert( sizeof(T)%sizeof(T2)== 0, @@ -2623,32 +3267,32 @@ struct subarray }.rotated(); } - // TODO(correaa) : rename to reinterpret_pointer_cast? - template::template rebind > - constexpr auto reinterpret_array_cast(size_type n)& -> subarray, 2, P2> { - // static_assert( sizeof(T)%sizeof(T2)== 0, - // "error: reinterpret_array_cast is limited to integral stride values, therefore the element target size must be multiple of the source element size. Use custom pointers to allow reintrepreation of array elements in other cases"); + // // TODO(correaa) : rename to reinterpret_pointer_cast? + // template::template rebind > + // constexpr auto reinterpret_array_cast(size_type n)& { // -> subarray, 2, P2> { + // // static_assert( sizeof(T)%sizeof(T2)== 0, + // // "error: reinterpret_array_cast is limited to integral stride values, therefore the element target size must be multiple of the source element size. Use custom pointers to allow reintrepreation of array elements in other cases"); - return subarray, 2, P2>( - layout_t<2>(this->layout().scale(sizeof(T), sizeof(T2)), 1, 0, n), - reinterpret_pointer_cast(this->base()) - ).rotated(); - } - template::template rebind > - constexpr auto reinterpret_array_cast(size_type n)&& -> subarray, 2, P2> { - return this->reinterpret_array_cast(n); - } + // return subarray, 2, P2>( + // layout_t<2>(this->layout().scale(sizeof(T), sizeof(T2)), 1, 0, n), + // reinterpret_pointer_cast(this->base()) + // ).rotated(); + // } + // template::template rebind > + // constexpr auto reinterpret_array_cast(size_type n)&& -> subarray, 2, P2> { + // return this->reinterpret_array_cast(n); + // } - template + template constexpr auto fill(TT const& value) & -> decltype(auto) { return adl_fill_n(this->begin(), this->size(), value), *this; } - constexpr auto fill()& -> decltype(auto) {return fill(typename subarray::element_type{});} + constexpr auto fill()& -> decltype(auto) {return fill(typename const_subarray::element_type{});} - template - constexpr auto fill(TT const& value) && -> decltype(auto) {return std::move(this->fill(value));} - constexpr auto fill() && -> decltype(auto) { - return std::move(*this).fill(typename subarray::element_type{}); + template + [[deprecated]] constexpr auto fill(TT const& value) && -> decltype(auto) {return std::move(this->fill(value));} + [[deprecated]] constexpr auto fill() && -> decltype(auto) { + return std::move(*this).fill(typename const_subarray::element_type{}); } template @@ -2685,11 +3329,9 @@ struct array_ref // TODO(correaa) : inheredit from multi::partially_ordered2 typename array_ref::sizes_type*/ {return self.sizes();} // needed by nvcc friend constexpr auto size (array_ref const& self) noexcept /*-> typename array_ref::size_type*/ {return self.size ();} // needed by nvcc - protected: [[deprecated("references are not copyable, use auto&&")]] array_ref(array_ref const&) = default; // don't try to use `auto` for references, use `auto&&` or explicit value type - public: #if defined(__NVCC__) array_ref(array_ref&&) noexcept = default; // this needs to be public in nvcc c++17 #else @@ -2697,13 +3339,15 @@ struct array_ref // TODO(correaa) : inheredit from multi::partially_ordered2 and D == 1, int> = 0> + template && (D == 1), int> = 0 // NOLINT(modernize-use-constraints) TODO(correaa) + > constexpr explicit operator std::span() const& {return std::span(this->data_elements(), this->size());} #endif template{}>, decltype(multi::detail::explicit_cast(std::declval()))* = nullptr> constexpr explicit array_ref(array_ref&& other) - : subarray{other.layout(), ElementPtr{std::move(other).base()}} {} + : subarray{other.layout(), ElementPtr{std::move(other).base()}} {} // cppcheck-suppress internalAstError ; bug in cppcheck 2.13.0 template{}>, decltype(multi::detail::implicit_cast(std::declval()))* = nullptr> // cppcheck-suppress noExplicitConstructor ; to allow terse syntax @@ -2723,7 +3367,7 @@ struct array_ref // TODO(correaa) : inheredit from multi::partially_ordered2 > =0, std::enable_if_t>, int> =0, - std::enable_if_t())), ElementPtr>, int> =0 // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) support legacy c-arrays + std::enable_if_t())), ElementPtr>, int> =0 // NOLINT(modernize-use-constraints,ppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) support legacy c-arrays > // cppcheck-suppress noExplicitConstructor ; to allow terse syntax and because a reference to c-array can be represented as an array_ref constexpr array_ref( // NOLINT(google-explicit-constructor,hicpp-explicit-conversions) : to allow terse syntax and because a reference to c-array can be represented as an array_ref @@ -2734,7 +3378,7 @@ struct array_ref // TODO(correaa) : inheredit from multi::partially_ordered2 =0> + template =0> // NOLINT(modernize-use-constraints) TODO(correaa) for C++20 // cppcheck-suppress noExplicitConstructor ; to allow terse syntax and because a reference to c-array can be represented as an array_ref constexpr array_ref( // NOLINT(google-explicit-constructor,hicpp-explicit-conversions) : to allow terse syntax and because a reference to c-array can be represented as an array_ref T& elem // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) : backwards compatibility @@ -2757,7 +3401,7 @@ struct array_ref // TODO(correaa) : inheredit from multi::partially_ordered2& arr) : array_ref(::boost::multi::extensions(arr), ::boost::multi::data_elements(arr)) {} // NOLINT(google-explicit-constructor,hicpp-explicit-conversions,cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) array_ptr is more general than pointer c-array support legacy c-arrays // NOSONAR // this ctor makes memcheck complain about memmory used after scope - template, int> =0> + template, int> =0> // NOLINT(modernize-use-constraints) TODO(correaa) for C++20 // cppcheck-suppress noExplicitConstructor array_ref(std::initializer_list il) : array_ref(il.begin(), typename array_ref::extensions_type{static_cast(il.size())}) {} @@ -2772,9 +3416,9 @@ struct array_ref // TODO(correaa) : inheredit from multi::partially_ordered2 typename array_ref::element_const_ptr {return array_ref::base_;} + BOOST_MULTI_HD constexpr auto data_elements() const& -> typename array_ref::element_const_ptr { return array_ref::base_; } - template> ,int> =0> + template> ,int> =0> // NOLINT(modernize-use-constraints) TODO(correaa) for C++20 constexpr auto operator=(array_ref const& other) && -> array_ref& { assert(this->extensions() == other.extensions()); array_ref::copy_elements_(other.data_elements()); @@ -2866,6 +3510,13 @@ struct array_ref // TODO(correaa) : inheredit from multi::partially_ordered2 friend constexpr auto operator!=(array_ref const& self, array_ref const& other) -> bool { if(self.extensions() != other.extensions()) { return true; } @@ -2876,21 +3527,26 @@ struct array_ref // TODO(correaa) : inheredit from multi::partially_ordered2 typename array_ref::element_ptr {return array_ref::base_;} - BOOST_MULTI_HD constexpr auto data_elements() && -> typename array_ref::element_ptr {return array_ref::base_;} - // BOOST_MULTI_HD constexpr auto data_elements() const& -> typename array_ref::element_const_ptr {return array_ref::base_;} + #if defined(__clang__) + #pragma clang diagnostic pop + #endif + + + BOOST_MULTI_HD constexpr auto data_elements() & -> typename array_ref::element_ptr { return array_ref::base_; } + BOOST_MULTI_HD constexpr auto data_elements() && -> typename array_ref::element_ptr { return array_ref::base_; } + // BOOST_MULTI_HD constexpr auto data_elements() const& -> typename array_ref::element_const_ptr { return array_ref::base_; } friend constexpr auto data_elements(array_ref&& self) -> typename array_ref::element_ptr {return std::move(self).data_elements();} // data() is here for compatibility with std::vector - template = 0> constexpr auto data() const& {return data_elements();} - template = 0> constexpr auto data() && {return data_elements();} - template = 0> constexpr auto data() & {return data_elements();} + template = 0> constexpr auto data() const& { return data_elements(); } // NOLINT(modernize-use-constraints) TODO(correaa) + template = 0> constexpr auto data() && { return data_elements(); } // NOLINT(modernize-use-constraints) TODO(correaa) + template = 0> constexpr auto data() & { return data_elements(); } // NOLINT(modernize-use-constraints) TODO(correaa) // TODO(correaa) : find a way to use [[deprecated("use data_elements()")]] for friend functions - friend constexpr auto data(array_ref const& self) -> typename array_ref::element_ptr {return self .data_elements();} - friend constexpr auto data(array_ref & self) -> typename array_ref::element_ptr {return self .data_elements();} - friend constexpr auto data(array_ref && self) -> typename array_ref::element_ptr {return std::move(self).data_elements();} + friend constexpr auto data(array_ref const& self) -> typename array_ref::element_ptr { return self .data_elements(); } + friend constexpr auto data(array_ref & self) -> typename array_ref::element_ptr { return self .data_elements(); } + friend constexpr auto data(array_ref && self) -> typename array_ref::element_ptr { return std::move(self).data_elements(); } using decay_type = typename array_ref::decay_type; @@ -2900,7 +3556,8 @@ struct array_ref // TODO(correaa) : inheredit from multi::partially_ordered2 void check_sizes_() const { - if(size_type{std::get
(this->sizes())} != size_type{std::extent::value}) { + using std::get; + if(size_type{get
(this->sizes())} != size_type{std::extent::value}) { throw std::bad_cast{}; } if constexpr(DD + 1 != D) { @@ -2916,7 +3573,8 @@ struct array_ref // TODO(correaa) : inheredit from multi::partially_ordered2 friend struct array; + template constexpr auto to_carray_()& -> TTN& { check_sizes_(); @@ -2930,11 +3588,11 @@ struct array_ref // TODO(correaa) : inheredit from multi::partially_ordered2, int> = 0> + template, int> = 0> // NOLINT(modernize-use-constraints) TODO(correaa) for C++20 constexpr explicit operator TTN const&() const& { return to_carray_(); } // NOLINT(google-explicit-constructor,hicpp-explicit-conversions) - template, int> = 0> + template, int> = 0> // NOLINT(modernize-use-constraints) TODO(correaa) for C++20 constexpr explicit operator TTN&() && { return to_carray_(); } // NOLINT(google-explicit-constructor,hicpp-explicit-conversions) - template, int> = 0> + template, int> = 0> // NOLINT(modernize-use-constraints) TODO(correaa) for C++20 constexpr explicit operator TTN&() & { return to_carray_(); } // NOLINT(google-explicit-constructor,hicpp-explicit-conversions) private: @@ -2991,9 +3649,8 @@ constexpr auto ref( template struct array_ptr -: subarray_ptr -, typename array_ref::layout_t> { - using basic_ptr = subarray_ptr, typename array_ref::layout_t>; +: subarray_ptr::layout_t> { + using basic_ptr = subarray_ptr::layout_t>; constexpr array_ptr(Ptr data, multi::extensions_t extensions) : basic_ptr{data, multi::layout_t{extensions}} {} @@ -3006,27 +3663,34 @@ struct array_ptr template< class TT, std::size_t N, - std::enable_if_t())), Ptr>,int> =0 // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) support legacy c-arrays + std::enable_if_t())), Ptr>,int> =0 // NOLINT(modernize-use-constraints,cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) support legacy c-arrays TODO(correaa) for C++20 > // cppcheck-suppress noExplicitConstructor ; // NOLINTNEXTLINE(runtime/explicit) - constexpr array_ptr(TT(*array)[N]) : array_ptr{data_elements(*array), extensions(*array)} {} // NOLINT(google-explicit-constructor,hicpp-explicit-conversions,cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) array_ptr is more general than pointer c-array support legacy c-arrays // NOSONAR + constexpr array_ptr(TT(*array)[N]) : array_ptr{data_elements(*array), extensions(*array)} {} // NOLINT(modernize-use-constraints,google-explicit-constructor,hicpp-explicit-conversions,cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) array_ptr is more general than pointer c-array support legacy c-arrays TODO(correaa) for C++20 // NOSONAR - constexpr auto operator*() const { - return array_ref((*this)->extensions(), this->base()); + constexpr auto operator*() const -> array_ref { + return array_ref((*static_cast::layout_t> const&>(*this)).extensions(), this->base()); } }; template -class array_ptr { // TODO(correaa) make it private mutable member - mutable multi::array_ref ref_; +class [[deprecated("no good uses found")]] array_ptr { // TODO(correaa) make it private mutable member + mutable multi::array_ref ref_; // TODO(correaa) implement array_ptr like other cases public: + ~array_ptr() = default; + constexpr array_ptr(array_ptr const&) = default; + constexpr array_ptr(array_ptr&&) noexcept = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor) TODO(correaa) change the implementation like the other cases + constexpr explicit array_ptr(Ptr dat, typename multi::array_ref::extensions_type extensions) : ref_(dat, extensions) {} constexpr explicit array_ptr(Ptr dat) : array_ptr(dat, typename multi::array_ref::extensions_type{}) {} constexpr explicit operator bool() const {return ref_.base();} constexpr explicit operator Ptr () const {return ref_.base();} + auto operator=(array_ptr const&) -> array_ptr& = default; + auto operator=(array_ptr &&) noexcept -> array_ptr& = default; + friend constexpr auto operator==(array_ptr const& self, array_ptr const& other) -> bool {return self.ref_.base() == other.ref_.base();} friend constexpr auto operator!=(array_ptr const& self, array_ptr const& other) -> bool {return self.ref_.base() != other.ref_.base();} @@ -3111,11 +3775,23 @@ template1 (this is important because it forces calling placement new on the pointer (In first, In last, multi::array_iterator dest) { + + #if defined(__clang__) + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wunknown-warning-option" + #pragma clang diagnostic ignored "-Wunsafe-buffer-usage" // TODO(correaa) use checked span + #endif + while(first != last) { // NOLINT(altera-unroll-loops) TODO(correaa) consider using an algorithm adl_uninitialized_copy(adl_begin(*first), adl_end(*first), adl_begin(*dest)); ++first; ++dest; } + + #if defined(__clang__) + #pragma clang diagnostic pop + #endif + return dest; } diff --git a/external_codes/boost_multi/multi/include/boost/multi/detail/adl.hpp b/external_codes/boost_multi/multi/include/boost/multi/detail/adl.hpp index 5709458f8d..d220ec189f 100644 --- a/external_codes/boost_multi/multi/include/boost/multi/detail/adl.hpp +++ b/external_codes/boost_multi/multi/include/boost/multi/detail/adl.hpp @@ -14,12 +14,13 @@ #include #endif -#include // for std::copy, std::copy_n, std::equal, etc -#include // std::size_t -#include // for begin, end -#include // for uninitialized_copy, etc -#include // std::conditional_t -#include +#include // for for_each, copy_n, fill, fill_n, lexicographical_compare, swap_ranges // IWYU pragma: keep // bug in iwyu 0.18 +#include // for size_t +#include // for equal_to +#include // for iterator_traits, distance, size +#include // for allocator_traits, allocator, pointer_traits +#include // for decay_t, enable_if_t, conditional_t, declval, is_pointer, true_type +#include // for forward, addressof #ifdef _MULTI_FORCE_TRIVIAL_STD_COMPLEX #include @@ -43,38 +44,6 @@ namespace adl { \ } /* end namespace multi */ \ } /* end namespace boost */ -namespace boost::multi { - -template -inline constexpr bool force_element_trivial = false; - -template -inline constexpr bool force_element_trivial_destruction = force_element_trivial; - -template -inline constexpr bool force_element_trivial_default_construction = force_element_trivial; - -#ifdef _MULTI_FORCE_TRIVIAL_STD_COMPLEX -template -inline constexpr bool force_element_trivial> = std::is_trivial_v; - -template -inline constexpr bool force_element_trivial_destruction> = std::is_trivially_default_constructible_v; - -template -inline constexpr bool force_element_trivial_default_construction> = std::is_trivially_destructible_v; - -template<> inline constexpr bool force_element_trivial > = true; -template<> inline constexpr bool force_element_trivial_default_construction> = true; -template<> inline constexpr bool force_element_trivial_destruction > = true; - -template<> inline constexpr bool force_element_trivial > = true; -template<> inline constexpr bool force_element_trivial_default_construction> = true; -template<> inline constexpr bool force_element_trivial_destruction > = true; -#endif - -} // end namespace boost::multi - #define BOOST_MULTI_DECLRETURN(ExpR) -> decltype(ExpR) {return ExpR;} // NOLINT(cppcoreguidelines-macro-usage) saves a lot of typing #define BOOST_MULTI_JUSTRETURN(ExpR) {return ExpR;} // NOLINT(cppcoreguidelines-macro-usage) saves a lot of typing @@ -96,6 +65,8 @@ class adl_copy_n_t { }; inline constexpr adl_copy_n_t adl_copy_n; +// there is no move_n (std::move_n), use copy_n(std::make_move_iterator(first), count) instead + class adl_move_t { template constexpr auto _(priority<0>/**/, As&&... args) const BOOST_MULTI_DECLRETURN( std:: move( std::forward(args)...)) #if defined(__NVCC__) || defined(__HIP_PLATFORM_NVIDIA__) || defined(__HIP_PLATFORM_AMD__) || defined(__HIPCC__) // there is no thrust::move algorithm @@ -124,6 +95,20 @@ class adl_fill_n_t { }; inline constexpr adl_fill_n_t adl_fill_n; +class adl_fill_t { + template< class... As> constexpr auto _(priority<0>/**/, As&&... args) const BOOST_MULTI_DECLRETURN( std:: fill (std::forward(args)...)) +#if defined(__NVCC__) || defined(__HIP_PLATFORM_NVIDIA__) || defined(__HIP_PLATFORM_AMD__) || defined(__HIPCC__) + template< class... As> constexpr auto _(priority<1>/**/, As&&... args) const BOOST_MULTI_DECLRETURN( thrust:: fill (std::forward(args)...)) +#endif + template< class... As> constexpr auto _(priority<2>/**/, As&&... args) const BOOST_MULTI_DECLRETURN( fill (std::forward(args)...)) + template constexpr auto _(priority<3>/**/, T&& arg, As&&... args) const BOOST_MULTI_DECLRETURN(std::decay_t:: fill(std::forward(arg), std::forward(args)...)) + template constexpr auto _(priority<4>/**/, T&& arg, As&&... args) const BOOST_MULTI_DECLRETURN(std::forward(arg).fill (std::forward(args)...)) + + public: + template constexpr auto operator()(As&&... args) const BOOST_MULTI_DECLRETURN(_(priority<4>{}, std::forward(args)...)) +}; +inline constexpr adl_fill_t adl_fill; + class adl_equal_t { template< class...As> constexpr auto _(priority<1>/**/, As&&...args) const BOOST_MULTI_DECLRETURN( std:: equal( std::forward(args)...)) #if defined(__NVCC__) || defined(__HIP_PLATFORM_NVIDIA__) || defined(__HIP_PLATFORM_AMD__) || defined(__HIPCC__) @@ -139,15 +124,13 @@ class adl_equal_t { }; inline constexpr adl_equal_t adl_equal; -template struct adl_custom_copy; - #ifndef _MSC_VER -template > void copy(As...) = delete; +template > void copy(As...) = delete; // NOLINT(modernize-use-constraints) TODO(correaa) #endif class adl_copy_t { template::reference, typename std::iterator_traits::reference>> + class=std::enable_if_t::reference, typename std::iterator_traits::reference>> // NOLINT(modernize-use-constraints) TODO(correaa) > constexpr auto _(priority<1>/**/, InputIt first, InputIt last, OutputIt d_first) const BOOST_MULTI_DECLRETURN(std::copy(first, last, d_first)) #if defined(__NVCC__) || defined(__HIP_PLATFORM_NVIDIA__) || defined(__HIP_PLATFORM_AMD__) || defined(__HIPCC__) @@ -164,12 +147,12 @@ class adl_copy_t { inline constexpr adl_copy_t adl_copy; namespace adl { - namespace custom {template struct fill_t;} + // namespace custom {template struct fill_t;} class fill_t { template auto _(priority<1>/**/, As&&... args) const BOOST_MULTI_DECLRETURN( std:: fill (std::forward(args)...)) template auto _(priority<2>/**/, As&&... args) const BOOST_MULTI_DECLRETURN( fill (std::forward(args)...)) template auto _(priority<3>/**/, T&& arg, As&&... args) const BOOST_MULTI_DECLRETURN(std::forward(arg).fill (std::forward(args)...)) - template auto _(priority<4>/**/, As&&... args) const BOOST_MULTI_DECLRETURN(custom:: fill_t::_(std::forward(args)...)) + // template auto _(priority<4>/**/, As&&... args) const BOOST_MULTI_DECLRETURN(custom:: fill_t::_(std::forward(args)...)) public: template auto operator()(As&&... args) const BOOST_MULTI_DECLRETURN(_(priority<5>{}, std::forward(args)...)) @@ -202,7 +185,7 @@ constexpr auto me_to_address(priority<1> /**/, T const& ptr) noexcept return std::pointer_traits::to_address(ptr); } -template{}, int> =0> +template{}, int> =0> // NOLINT(modernize-use-constraints) TODO(correaa) constexpr auto me_to_address(priority<2>/**/, T const& ptr) noexcept -> T { static_assert(! std::is_function_v); return ptr; @@ -315,22 +298,26 @@ class adl_uninitialized_copy_t { #if __cplusplus >= 202002L using ValueType = typename std::iterator_traits::value_type; if( - std::is_constant_evaluated() + std::is_constant_evaluated() && (std::is_trivially_default_constructible_v || multi::force_element_trivial_default_construction) ) { return std:: copy(first, last, d_first); - } else - #endif - { - return std::uninitialized_copy(first, last, d_first); } + #endif + return std::uninitialized_copy(first, last, d_first); } -// #if defined(__CUDACC__) || defined(__CUDA__) || defined(__NVCC__) || defined(__HIP_PLATFORM_NVIDIA__) || defined(__HIP_PLATFORM_AMD__) || defined(__HIPCC__) #if defined(__CUDACC__) || defined(__HIPCC__) - template constexpr auto _(priority<2>/**/, As&&... args) const BOOST_MULTI_DECLRETURN( ::thrust::uninitialized_copy( std::forward(args)...)) // doesn't work with culang 17, cuda 12 ? + template::value_type> + constexpr auto _(priority<2>/**/, InIt first, InIt last, FwdIt d_first) const -> decltype(::thrust::uninitialized_copy(first, last, d_first)) // doesn't work with culang 17, cuda 12 ? + { + if(std::is_trivially_default_constructible_v || multi::force_element_trivial_default_construction) { + return ::thrust::copy(first, last, d_first); + } + return ::thrust::uninitialized_copy(first, last, d_first); + } #endif - template constexpr auto _(priority<3>/**/, TB first, As&&... args ) const BOOST_MULTI_DECLRETURN( uninitialized_copy( first , std::forward(args)...)) - template constexpr auto _(priority<4>/**/, TB first, TE last, DB d_first) const BOOST_MULTI_DECLRETURN(std::decay_t ::uninitialized_copy( first , last, d_first )) + template constexpr auto _(priority<3>/**/, TB&& first, As&&... args ) const BOOST_MULTI_DECLRETURN( uninitialized_copy( std::forward(first) , std::forward(args)...)) + template constexpr auto _(priority<4>/**/, TB&& first, TE&& last, DB&& d_first) const BOOST_MULTI_DECLRETURN(std::decay_t ::uninitialized_copy( std::forward(first) , std::forward(last), std::forward(d_first) )) template constexpr auto _(priority<5>/**/, TB&& first, As&&... args ) const BOOST_MULTI_DECLRETURN(std::decay_t ::uninitialized_copy(std::forward(first), std::forward(args)...)) template constexpr auto _(priority<6>/**/, TB&& first, As&&... args ) const BOOST_MULTI_DECLRETURN(std::forward(first).uninitialized_copy( std::forward(args)...)) @@ -343,19 +330,23 @@ class adl_uninitialized_copy_n_t { template constexpr auto _(priority<1>/**/, As&&... args) const BOOST_MULTI_DECLRETURN( std::uninitialized_copy_n(std::forward(args)...)) template constexpr auto _(priority<2>/**/, As&&... args) const BOOST_MULTI_DECLRETURN( uninitialized_copy_n(std::forward(args)...)) #if defined(__NVCC__) || defined(__HIP_PLATFORM_NVIDIA__) || defined(__HIP_PLATFORM_AMD__) || defined(__HIPCC__) - template constexpr auto _(priority<3>/**/, As&&... args) const BOOST_MULTI_DECLRETURN( ::thrust::uninitialized_copy_n(std::forward(args)...)) - template(), ...))>, - std::enable_if_t< - std::is_trivially_default_constructible_v::value_type> - || multi::force_element_trivial_default_construction::value_type> - , int> =0 - > constexpr auto _(priority<4>/**/, As&&... args) const BOOST_MULTI_DECLRETURN( ::thrust::copy_n(std::forward(args)...)) + template< + class It, class Size, class ItFwd, + class ValueType = typename std::iterator_traits::value_type, + class = std::enable_if_t::reference> > + > + constexpr auto _(priority<3>/**/, It first, Size count, ItFwd d_first) const -> decltype(::thrust::uninitialized_copy_n(first, count, d_first)) { + if(std::is_trivially_default_constructible_v || multi::force_element_trivial_default_construction) { + return ::thrust::copy_n(first, count, d_first); + } + return ::thrust::uninitialized_copy_n(first, count, d_first); + } #endif - template constexpr auto _(priority<5>/**/, T&& arg, As&&... args) const BOOST_MULTI_DECLRETURN(std::decay_t:: uninitialized_copy_n(std::forward(arg), std::forward(args)...)) - template constexpr auto _(priority<6>/**/, T&& arg, As&&... args) const BOOST_MULTI_DECLRETURN(std::forward(arg).uninitialized_copy_n(std::forward(args)...)) + template constexpr auto _(priority<4>/**/, T&& arg, As&&... args) const BOOST_MULTI_DECLRETURN(std::decay_t:: uninitialized_copy_n(std::forward(arg), std::forward(args)...)) + template constexpr auto _(priority<5>/**/, T&& arg, As&&... args) const BOOST_MULTI_DECLRETURN(std::forward(arg).uninitialized_copy_n(std::forward(args)...)) public: - template constexpr auto operator()(As&&... args) const BOOST_MULTI_DECLRETURN(_(priority<7>{}, std::forward(args)...)) // TODO(correaa) this might trigger a compiler crash with g++ 7.5 because of operator&() && overloads + template constexpr auto operator()(As&&... args) const BOOST_MULTI_DECLRETURN(_(priority<5>{}, std::forward(args)...)) // TODO(correaa) this might trigger a compiler crash with g++ 7.5 because of operator&() && overloads }; inline constexpr adl_uninitialized_copy_n_t adl_uninitialized_copy_n; @@ -399,17 +390,25 @@ auto alloc_uninitialized_copy_n(Alloc& alloc, InputIt first, Size count, Forward template auto alloc_uninitialized_move_n(Alloc& alloc, InputIt first, Size count, ForwardIt d_first) { ForwardIt current = d_first; + #if defined(__clang__) + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wunknown-warning-option" + #pragma clang diagnostic ignored "-Wunsafe-buffer-usage" // TODO(correaa) use checked span + #endif try { for(; count > 0; ++first, ++current, --count) { // NOLINT(altera-unroll-loops) TODO(correaa) consider using an algorithm std::allocator_traits::construct(alloc, std::addressof(*current), std::move(*first)); } return current; } catch(...) { - for(; d_first != current; ++d_first) { // NOLINT(altera-unroll-loops) TODO(correaa) consider using an algorithm + for(; d_first != current; ++d_first) { // NOLINT(altera-unroll-loops,altera-id-dependent-backward-branch) TODO(correaa) consider using an algorithm std::allocator_traits::destroy(alloc, std::addressof(*d_first)); } throw; } + #if defined(__clang__) + #pragma clang diagnostic pop + #endif } template @@ -417,7 +416,9 @@ constexpr auto alloc_uninitialized_copy(std::allocator&/*allocator*/, InputIt return adl_uninitialized_copy(first, last, d_first); } -template())), class=std::enable_if_t::value_type, typename std::iterator_traits::reference>>> +template())), + class=std::enable_if_t::value_type, typename std::iterator_traits::reference>> // NOLINT(modernize-use-constraints) TODO(correaa) +> #if __cplusplus >= 202002L constexpr #endif @@ -458,13 +459,14 @@ auto alloc_uninitialized_fill_n(Alloc& alloc, ForwardIt first, Size n, T const& } // end namespace xtd class adl_distance_t { - template constexpr auto _(priority<1>/**/, As&&... args) const BOOST_MULTI_DECLRETURN( std:: distance(std::forward(args)...)) - template constexpr auto _(priority<2>/**/, As&&... args) const BOOST_MULTI_DECLRETURN( distance(std::forward(args)...)) - template constexpr auto _(priority<3>/**/, T&& arg, As&&... args) const BOOST_MULTI_DECLRETURN( std::decay_t:: distance(std::forward(arg), std::forward(args)...)) - template constexpr auto _(priority<4>/**/, T&& arg, As&&... args) const BOOST_MULTI_DECLRETURN(std::forward(arg).distance(std::forward(args)...)) + template constexpr auto _(priority<1>/**/, As&&... args) const BOOST_MULTI_DECLRETURN( std:: distance(std::forward(args)...)) + template constexpr auto _(priority<2>/**/, As&&... args) const BOOST_MULTI_DECLRETURN( distance(std::forward(args)...)) + template constexpr auto _(priority<3>/**/, It1 it1, It2 it2 ) const BOOST_MULTI_DECLRETURN(it2 - it1) + template constexpr auto _(priority<4>/**/, T&& arg, As&&... args) const BOOST_MULTI_DECLRETURN( std::decay_t:: distance(std::forward(arg), std::forward(args)...)) + template constexpr auto _(priority<5>/**/, T&& arg, As&&... args) const BOOST_MULTI_DECLRETURN(std::forward(arg).distance(std::forward(args)...)) public: - template constexpr auto operator()(As&&... args) const BOOST_MULTI_DECLRETURN(_(priority<4>{}, std::forward(args)...)) + template constexpr auto operator()(As&&... args) const BOOST_MULTI_DECLRETURN(_(priority<5>{}, std::forward(args)...)) }; inline constexpr adl_distance_t adl_distance; @@ -519,13 +521,13 @@ class adl_swap_ranges_t { inline constexpr adl_swap_ranges_t adl_swap_ranges; class adl_lexicographical_compare_t { - template /*[[gnu::pure]]*/ constexpr auto _(priority<1>/**/, As&&... args) const BOOST_MULTI_DECLRETURN( std:: lexicographical_compare(std::forward(args)...)) + template constexpr auto _(priority<1>/**/, As&&... args) const BOOST_MULTI_DECLRETURN( std:: lexicographical_compare(std::forward(args)...)) template constexpr auto _(priority<2>/**/, As&&... args) const BOOST_MULTI_DECLRETURN( lexicographical_compare(std::forward(args)...)) template constexpr auto _(priority<3>/**/, T&& arg, As&&... args) const BOOST_MULTI_DECLRETURN( std::decay_t:: lexicographical_compare(std::forward(arg), std::forward(args)...)) template constexpr auto _(priority<4>/**/, T&& arg, As&&... args) const BOOST_MULTI_DECLRETURN(std::forward(arg).lexicographical_compare(std::forward(args)...)) public: - template /*[[gnu::pure]]*/ constexpr auto operator()(As&&... args) const BOOST_MULTI_DECLRETURN(_(priority<4>{}, std::forward(args)...)) + template constexpr auto operator()(As&&... args) const BOOST_MULTI_DECLRETURN(_(priority<4>{}, std::forward(args)...)) }; inline constexpr adl_lexicographical_compare_t adl_lexicographical_compare; @@ -620,14 +622,14 @@ class adl_alloc_uninitialized_copy_t { inline constexpr adl_alloc_uninitialized_copy_t adl_alloc_uninitialized_copy; class adl_alloc_uninitialized_copy_n_t { - template constexpr auto _(priority<1>/**/, Alloc&& /*alloc*/, As&&... args) const BOOST_MULTI_DECLRETURN( adl_uninitialized_copy_n(std::forward(args)...) ) // NOLINT(cppcoreguidelines-missing-std-forward) - template constexpr auto _(priority<2>/**/, As&&... args) const BOOST_MULTI_DECLRETURN( alloc_uninitialized_copy_n(std::forward(args)...)) -// template constexpr auto _(priority<3>/**/, As&&... args) const BOOST_MULTI_DECLRETURN( xtd::alloc_uninitialized_copy_n(std::forward(args)...)) + template constexpr auto _(priority<1>/**/, Alloc&& /*alloc*/, As&&... args) const BOOST_MULTI_DECLRETURN( adl_uninitialized_copy_n(std::forward(args)...)) // NOLINT(cppcoreguidelines-missing-std-forward) + template constexpr auto _(priority<2>/**/, As&&... args) const BOOST_MULTI_DECLRETURN( alloc_uninitialized_copy_n(std::forward(args)...)) +// template constexpr auto _(priority<3>/**/, As&&... args) const BOOST_MULTI_DECLRETURN( xtd::alloc_uninitialized_copy_n(std::forward(args)...)) // #if defined(__NVCC__) // there is no thrust alloc uninitialized copy // #endif - template constexpr auto _(priority<5>/**/, T&& arg, As&&... args) const BOOST_MULTI_DECLRETURN( std::decay_t::alloc_uninitialized_copy_n(std::forward(arg), std::forward(args)...)) - template constexpr auto _(priority<6>/**/, T&& arg, As&&... args) const BOOST_MULTI_DECLRETURN(std::forward(arg).alloc_uninitialized_copy_n(std::forward(args)...)) + template constexpr auto _(priority<5>/**/, T&& arg, As&&... args) const BOOST_MULTI_DECLRETURN( std::decay_t::alloc_uninitialized_copy_n(std::forward(arg), std::forward(args)...)) + template constexpr auto _(priority<6>/**/, T&& arg, As&&... args) const BOOST_MULTI_DECLRETURN(std::forward(arg).alloc_uninitialized_copy_n(std::forward(args)...)) public: template constexpr auto operator()(As&&... args) const {return _(priority<6>{}, std::forward(args)...);} @@ -636,7 +638,7 @@ inline constexpr adl_alloc_uninitialized_copy_n_t adl_alloc_uninitialized_copy_n class alloc_uninitialized_move_n_t { // TODO(correaa) : fallback to no alloc version - template constexpr auto _(priority<1>/**/, As&&... args) const {return( xtd:: alloc_uninitialized_move_n(std::forward(args)...));} + template constexpr auto _(priority<1>/**/, As&&... args) const {return( xtd:: alloc_uninitialized_move_n(std::forward(args)...));} template constexpr auto _(priority<2>/**/, As&&... args) const BOOST_MULTI_DECLRETURN( alloc_uninitialized_move_n(std::forward(args)...)) template constexpr auto _(priority<3>/**/, T&& arg, As&&... args) const BOOST_MULTI_DECLRETURN(std::forward(arg).alloc_uninitialized_move_n(std::forward(args)...)) diff --git a/external_codes/boost_multi/multi/include/boost/multi/detail/config/NODISCARD.hpp b/external_codes/boost_multi/multi/include/boost/multi/detail/config/NODISCARD.hpp index 07760a41e5..c753c3ae50 100644 --- a/external_codes/boost_multi/multi/include/boost/multi/detail/config/NODISCARD.hpp +++ b/external_codes/boost_multi/multi/include/boost/multi/detail/config/NODISCARD.hpp @@ -7,12 +7,13 @@ #define BOOST_MULTI_DETAIL_CONFIG_NODISCARD_HPP // clang-format off + #ifdef __has_cpp_attribute // No discard first # ifdef __NVCC__ # define BOOST_MULTI_NODISCARD(MsG) -# elif __has_cpp_attribute(nodiscard) && (__cplusplus >= 201703L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L)) +# elif __has_cpp_attribute(nodiscard) # if (__has_cpp_attribute(nodiscard) >= 201907L) && (__cplusplus >= 202002L || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L)) # define BOOST_MULTI_NODISCARD(MsG) [[nodiscard]] // [[nodiscard(MsG)]] in c++20 empty message is not allowed with paren # else @@ -23,7 +24,7 @@ # endif // No discard class -# if(__has_cpp_attribute(nodiscard) && !defined(__NVCC__) && (!defined(__clang__) || (defined(__clang__) && (__cplusplus >= 202002L)))) && (__cplusplus >= 201703L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L)) +# if(__has_cpp_attribute(nodiscard) && !defined(__NVCC__) && (!defined(__clang__) || (defined(__clang__) && (__cplusplus >= 202002L)))) # if (__has_cpp_attribute(nodiscard) >= 201907L) && (__cplusplus >= 202002L || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L)) # define BOOST_MULTI_NODISCARD_CLASS(MsG) [[nodiscard_(MsG)]] # else diff --git a/external_codes/boost_multi/multi/include/boost/multi/detail/config/NO_UNIQUE_ADDRESS.hpp b/external_codes/boost_multi/multi/include/boost/multi/detail/config/NO_UNIQUE_ADDRESS.hpp index fe92fb5392..eac13d4094 100644 --- a/external_codes/boost_multi/multi/include/boost/multi/detail/config/NO_UNIQUE_ADDRESS.hpp +++ b/external_codes/boost_multi/multi/include/boost/multi/detail/config/NO_UNIQUE_ADDRESS.hpp @@ -6,17 +6,21 @@ #ifndef BOOST_MULTI_DETAIL_CONFIG_NO_UNIQUE_ADDRESS_HPP #define BOOST_MULTI_DETAIL_CONFIG_NO_UNIQUE_ADDRESS_HPP -// clang-format off +// klang-format off #ifdef __has_cpp_attribute -# if __has_cpp_attribute(no_unique_address) >= 201803L && ! defined(__NVCC__) && ! defined(__PGI) && (__cplusplus >= 202002L || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L)) - // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) this macro will be needed until C++20 -# define BOOST_MULTI_NO_UNIQUE_ADDRESS [[no_unique_address]] -# endif + #if __has_cpp_attribute(no_unique_address) >= 201803L && !defined(__NVCC__) && !defined(__PGI) && (__cplusplus >= 202002L || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L)) + // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) this macro will be needed until C++20 + #define BOOST_MULTI_NO_UNIQUE_ADDRESS [[no_unique_address]] + #endif #endif #ifndef BOOST_MULTI_NO_UNIQUE_ADDRESS -# define BOOST_MULTI_NO_UNIQUE_ADDRESS + #if defined(_MSC_VER) + #define BOOST_MULTI_NO_UNIQUE_ADDRESS // [[msvc::no_unique_address]] + #else + #define BOOST_MULTI_NO_UNIQUE_ADDRESS + #endif #endif -// clang-format on +// klang-format on #endif // BOOST_MULTI_DETAIL_CONFIG_NO_UNIQUE_ADDRESS_HPP diff --git a/external_codes/boost_multi/multi/include/boost/multi/detail/implicit_cast.hpp b/external_codes/boost_multi/multi/include/boost/multi/detail/implicit_cast.hpp index 29cd0541f6..50c196c95e 100644 --- a/external_codes/boost_multi/multi/include/boost/multi/detail/implicit_cast.hpp +++ b/external_codes/boost_multi/multi/include/boost/multi/detail/implicit_cast.hpp @@ -6,15 +6,18 @@ #define BOOST_MULTI_DETAIL_IMPLICIT_CAST_HPP #pragma once +#include +#include + namespace boost::multi::detail { template constexpr bool is_implicitly_convertible_v = std::is_convertible_v; template constexpr bool is_explicitly_convertible_v = std::is_constructible_v; -template, int> =0> +template, int> =0> // NOLINT(modernize-use-constraints) TODO(correaa) constexpr auto implicit_cast(From&& ref) -> To {return static_cast(std::forward(ref));} -template && ! std::is_convertible_v, int> =0> +template && ! std::is_convertible_v, int> =0> // NOLINT(modernize-use-constraints) TODO(correaa) constexpr auto explicit_cast(From&& ref) -> To {return static_cast(std::forward(ref));} } // end namespace boost::multi::detail diff --git a/external_codes/boost_multi/multi/include/boost/multi/detail/index_range.hpp b/external_codes/boost_multi/multi/include/boost/multi/detail/index_range.hpp index c6df08e0d2..e69b1cdc92 100644 --- a/external_codes/boost_multi/multi/include/boost/multi/detail/index_range.hpp +++ b/external_codes/boost_multi/multi/include/boost/multi/detail/index_range.hpp @@ -11,11 +11,14 @@ #include #include -#include // for std::min -#include // for std::plus<> -#include // for std::random_iterator_tag // std::reverse_iterator -#include // for numeric_limits -#include // for forward +#include // for min, max +#include // for ptrdiff_t +#include // for minus, plus +#include // for reverse_iterator, random_access_iterator_tag +#include // for numeric_limits +#include // for pointer_traits +#include // for declval, true_type, decay_t, enable_if_t +#include // for forward namespace boost::multi { @@ -24,12 +27,11 @@ using boost::multi::detail::tuple; template< class Self, class ValueType, class AccessCategory, - class Reference = ValueType&, class DifferenceType = typename std::pointer_traits::difference_type, class Pointer = ValueType* -> + class Reference = ValueType&, class DifferenceType = typename std::pointer_traits::difference_type, class Pointer = ValueType*> class iterator_facade { using self_type = Self; - [[nodiscard]] constexpr auto self_() & {return static_cast(*this);} - [[nodiscard]] constexpr auto self_() const& {return static_cast(*this);} + [[nodiscard]] constexpr auto self_() & { return static_cast(*this); } + [[nodiscard]] constexpr auto self_() const& { return static_cast(*this); } public: using value_type = ValueType; @@ -38,23 +40,31 @@ class iterator_facade { using difference_type = DifferenceType; using iterator_category = AccessCategory; - friend constexpr auto operator!=(self_type const& self, self_type const& other) {return !(self == other);} + // friend constexpr auto operator!=(self_type const& self, self_type const& other) { return !(self == other); } - friend constexpr auto operator<=(self_type const& self, self_type const& other) {return (self < other) || (self == other);} - friend constexpr auto operator> (self_type const& self, self_type const& other) {return !(self <= other);} - friend constexpr auto operator>=(self_type const& self, self_type const& other) {return !(self < other);} + friend constexpr auto operator<=(self_type const& self, self_type const& other) { return (self < other) || (self == other); } + friend constexpr auto operator>(self_type const& self, self_type const& other) { return !(self <= other); } + friend constexpr auto operator>=(self_type const& self, self_type const& other) { return !(self < other); } - constexpr auto operator-(difference_type n) const {return self_type{self_()} -= n;} - constexpr auto operator+(difference_type n) const {return self_type{self_()} += n;} - friend constexpr auto operator+(difference_type n, self_type const& self) {return self + n;} + constexpr auto operator-(difference_type n) const { return self_type{self_()} -= n; } + constexpr auto operator+(difference_type n) const { return self_type{self_()} += n; } + friend constexpr auto operator+(difference_type n, self_type const& self) { return self + n; } - friend constexpr auto operator++(self_type& self, int) -> self_type {self_type ret = self; ++self; return ret;} - friend constexpr auto operator--(self_type& self, int) -> self_type {self_type ret = self; --self; return ret;} + friend constexpr auto operator++(self_type& self, int) -> self_type { + self_type ret = self; + ++self; + return ret; + } + friend constexpr auto operator--(self_type& self, int) -> self_type { + self_type ret = self; + --self; + return ret; + } - constexpr auto operator[](difference_type n) const {return *(self_() + n);} + constexpr auto operator[](difference_type n) const { return *(self_() + n); } }; -template, class Minus = std::minus<> > +template, class Minus = std::minus<>> class range { IndexType first_ = {}; IndexTypeLast last_ = first_; // TODO(correaa) check how to do partially initialzed @@ -62,17 +72,17 @@ class range { public: template // , class ArT = multi::archive_traits> void serialize(Archive& arxiv, unsigned /*version*/) { - arxiv & multi::archive_traits::make_nvp("first", first_); - // arxiv & BOOST_SERIALIZATION_NVP( first_); - // arxiv & cereal:: make_nvp("first", first_); - // arxiv & CEREAL_NVP( first_); - // arxiv & first_ ; - - arxiv & multi::archive_traits::make_nvp("last" , last_ ); - // arxiv & BOOST_SERIALIZATION_NVP( last_ ); - // arxiv & cereal:: make_nvp("last" , last_ ); - // arxiv & CEREAL_NVP( last_ ); - // arxiv & last_ ; + arxiv& multi::archive_traits::make_nvp("first", first_); + // arxiv & BOOST_SERIALIZATION_NVP( first_); + // arxiv & cereal:: make_nvp("first", first_); + // arxiv & CEREAL_NVP( first_); + // arxiv & first_ ; + + arxiv& multi::archive_traits::make_nvp("last", last_); + // arxiv & BOOST_SERIALIZATION_NVP( last_ ); + // arxiv & cereal:: make_nvp("last" , last_ ); + // arxiv & CEREAL_NVP( last_ ); + // arxiv & last_ ; } using value_type = IndexType; @@ -88,34 +98,26 @@ class range { // range(range const&) = default; template>, int> =0, - decltype( - detail::implicit_cast(std::declval().first()), - detail::implicit_cast(std::declval().last()) - )* = nullptr - > + std::enable_if_t>, int> = 0, + decltype(detail::implicit_cast(std::declval().first()), + detail::implicit_cast(std::declval().last()) + )* = nullptr> // cppcheck-suppress noExplicitConstructor ; // NOLINTNEXTLINE(runtime/explicit) constexpr /*implicit*/ range(Range&& other) // NOLINT(bugprone-forwarding-reference-overload,google-explicit-constructor,hicpp-explicit-conversions) // NOSONAR(cpp:S1709) ranges are implicitly convertible if elements are implicitly convertible : first_{std::forward(other).first()}, last_{std::forward(other).last()} {} template< class Range, - std::enable_if_t>, int> =0, - decltype( - detail::explicit_cast(std::declval().first()), - detail::explicit_cast(std::declval().last()) - )* =nullptr - > - constexpr explicit range(Range&& other) // NOLINT(bugprone-forwarding-reference-overload) + std::enable_if_t>, int> = 0, + decltype(detail::explicit_cast(std::declval().first()), + detail::explicit_cast(std::declval().last()) + )* = nullptr> + constexpr explicit range(Range&& other) // NOLINT(bugprone-forwarding-reference-overload) : first_{std::forward(other).first()}, last_{std::forward(other).last()} {} constexpr range(IndexType first, IndexTypeLast last) : first_{first}, last_{last} {} - class const_iterator : public boost::multi::iterator_facade< - const_iterator, - value_type, std::random_access_iterator_tag, - const_reference, difference_type - > { + class const_iterator : public boost::multi::iterator_facade { typename const_iterator::value_type curr_; constexpr explicit const_iterator(value_type current) : curr_{current} {} friend class range; @@ -123,57 +125,78 @@ class range { public: const_iterator() = default; - constexpr auto operator==(const_iterator const& other) const -> bool {return curr_ == other.curr_;} - constexpr auto operator< (const_iterator const& other) const -> bool {return curr_ < other.curr_;} + constexpr auto operator==(const_iterator const& other) const -> bool { return curr_ == other.curr_; } + constexpr auto operator!=(const_iterator const& other) const -> bool { return curr_ != other.curr_; } + + constexpr auto operator<(const_iterator const& other) const -> bool { return curr_ < other.curr_; } + + constexpr auto operator++() -> const_iterator& { + ++curr_; + return *this; + } + constexpr auto operator--() -> const_iterator& { + --curr_; + return *this; + } + + constexpr auto operator-=(typename const_iterator::difference_type n) -> const_iterator& { + curr_ -= n; + return *this; + } + constexpr auto operator+=(typename const_iterator::difference_type n) -> const_iterator& { + curr_ += n; + return *this; + } - constexpr auto operator++() -> const_iterator& {++curr_; return *this;} - constexpr auto operator--() -> const_iterator& {--curr_; return *this;} + constexpr auto operator-(typename const_iterator::difference_type n) const -> const_iterator { + return const_iterator{*this} -= n; + } - constexpr auto operator-=(typename const_iterator::difference_type n) -> const_iterator& {curr_ -= n; return *this;} - constexpr auto operator+=(typename const_iterator::difference_type n) -> const_iterator& {curr_ += n; return *this;} + constexpr auto operator+(typename const_iterator::difference_type n) const -> const_iterator { + return const_iterator{*this} += n; + } - constexpr auto operator-(const_iterator const& other) const {return curr_ - other.curr_;} - constexpr auto operator*() const -> typename const_iterator::reference {return curr_;} + constexpr auto operator-(const_iterator const& other) const { return curr_ - other.curr_; } + constexpr auto operator*() const noexcept -> typename const_iterator::reference { return curr_; } }; - using iterator = const_iterator ; - using reverse_iterator = std::reverse_iterator< iterator>; + using iterator = const_iterator; + using reverse_iterator = std::reverse_iterator; using const_reverse_iterator = std::reverse_iterator; - [[nodiscard]] constexpr auto first() const -> const_reference {return first_;} - [[nodiscard]] constexpr auto last() const -> const_reference {return last_ ;} + [[nodiscard]] constexpr auto first() const -> const_reference { return first_; } + [[nodiscard]] constexpr auto last() const -> const_reference { return last_; } - constexpr auto operator[](difference_type n) const -> const_reference {return first() + n;} + constexpr auto operator[](difference_type n) const -> const_reference { return first() + n; } - [[nodiscard]] constexpr auto front() const -> const_reference {return first() ;} - [[nodiscard]] constexpr auto back() const -> const_reference {return last() - 1;} + [[nodiscard]] constexpr auto front() const -> const_reference { return first(); } + [[nodiscard]] constexpr auto back() const -> const_reference { return last() - 1; } - [[nodiscard]] constexpr auto cbegin() const {return const_iterator{first_};} - [[nodiscard]] constexpr auto cend() const {return const_iterator{last_ };} + [[nodiscard]] constexpr auto cbegin() const { return const_iterator{first_}; } + [[nodiscard]] constexpr auto cend() const { return const_iterator{last_}; } - [[nodiscard]] constexpr auto rbegin() const {return reverse_iterator{end() };} - [[nodiscard]] constexpr auto rend() const {return reverse_iterator{begin()};} + [[nodiscard]] constexpr auto rbegin() const { return reverse_iterator{end()}; } + [[nodiscard]] constexpr auto rend() const { return reverse_iterator{begin()}; } - [[nodiscard]] constexpr auto begin() const -> const_iterator {return cbegin();} - [[nodiscard]] constexpr auto end() const -> const_iterator {return cend() ;} + [[nodiscard]] constexpr auto begin() const -> const_iterator { return cbegin(); } + [[nodiscard]] constexpr auto end() const -> const_iterator { return cend(); } - constexpr auto is_empty() const& noexcept {return first_ == last_;} - friend constexpr auto is_empty(range const& self) noexcept {return self.is_empty();} + constexpr auto is_empty() const& noexcept { return first_ == last_; } + friend constexpr auto is_empty(range const& self) noexcept { return self.is_empty(); } - [[nodiscard]] - constexpr auto empty() const& noexcept {return is_empty();} - friend constexpr auto empty(range const& self) noexcept {return self.empty();} + [[nodiscard]] constexpr auto empty() const& noexcept { return is_empty(); } + friend constexpr auto empty(range const& self) noexcept { return self.empty(); } - constexpr auto size() const& noexcept -> size_type {return last_ - first_;} - friend constexpr auto size(range const& self) noexcept -> size_type {return self.size();} + constexpr auto size() const& noexcept -> size_type { return last_ - first_; } + friend constexpr auto size(range const& self) noexcept -> size_type { return self.size(); } - friend constexpr auto begin(range const& self) {return self.begin();} - friend constexpr auto end (range const& self) {return self.end() ;} + friend constexpr auto begin(range const& self) { return self.begin(); } + friend constexpr auto end(range const& self) { return self.end(); } friend constexpr auto operator==(range const& self, range const& other) { return (self.empty() && other.empty()) || (self.first_ == other.first_ && self.last_ == other.last_); } - friend constexpr auto operator!=(range const& self, range const& other) {return !(self == other);} + friend constexpr auto operator!=(range const& self, range const& other) { return !(self == other); } [[nodiscard]] constexpr auto find(value_type const& value) const -> range::const_iterator { if(value >= last_ || value < first_) { @@ -181,21 +204,22 @@ class range { } return begin() + (value - front()); } - template [[nodiscard]] constexpr auto contains(Value const& value) const -> bool {return (value >=first_) && (value < last_);} - template [[nodiscard]] constexpr auto count (Value const& value) const -> value_type {return contains(value);} + template [[nodiscard]] constexpr auto contains(Value const& value) const -> bool { return (value >= first_) && (value < last_); } + template [[nodiscard]] constexpr auto count(Value const& value) const -> value_type { return contains(value); } friend constexpr auto intersection(range const& self, range const& other) { - using std::max; using std::min; + using std::max; + using std::min; auto new_first = max(self.first(), other.first()); - auto new_last = min(self.last() , other.last() ); - new_first = min(new_first, new_last); + auto new_last = min(self.last(), other.last()); + new_first = min(new_first, new_last); return range(new_first, new_last); } - [[nodiscard]] constexpr auto contains(value_type const& value) const {return value >= first_ && value < last_;} + [[nodiscard]] constexpr auto contains(value_type const& value) const { return value >= first_ && value < last_; } }; -template // , class Plus = std::plus<>, class Minus = std::minus<> > -range(IndexType, IndexTypeLast) -> range; // #3 +template // , class Plus = std::plus<>, class Minus = std::minus<> > +range(IndexType, IndexTypeLast) -> range; // #3 template constexpr auto make_range(IndexType first, IndexTypeLast last) -> range { @@ -204,11 +228,16 @@ constexpr auto make_range(IndexType first, IndexTypeLast last) -> range class intersecting_range { - range impl_{std::numeric_limits::min(), std::numeric_limits::max()}; + range impl_{ + (std::numeric_limits::min)(), // parent needed for MSVC min/max macros + (std::numeric_limits::max)() + }; constexpr intersecting_range() = default; // MSVC 19.07 needs constexpr to initialize ALL later static constexpr auto make_(IndexType first, IndexType last) -> intersecting_range { - intersecting_range ret; ret.impl_ = range{first, last}; return ret; + intersecting_range ret; + ret.impl_ = range{first, last}; + return ret; } friend constexpr auto intersection(intersecting_range const& self, range const& other) { return intersection(self.impl_, other); @@ -224,19 +253,20 @@ class intersecting_range { } public: - constexpr auto operator*() const& -> intersecting_range const& {return *this;} - static constexpr auto all() noexcept {return intersecting_range{};} + constexpr auto operator*() const& -> intersecting_range const& { return *this; } + static constexpr auto all() noexcept { return intersecting_range{}; } }; -[[maybe_unused]] constexpr intersecting_range<> ALL = intersecting_range<>::all(); -[[maybe_unused]] constexpr intersecting_range<> _ = ALL; // NOLINT(readability-identifier-length) -[[maybe_unused]] constexpr intersecting_range<> U = ALL; // NOLINT(readability-identifier-length) -[[maybe_unused]] constexpr intersecting_range<> ooo = ALL; +[[maybe_unused]] constexpr intersecting_range<> ALL = intersecting_range<>::all(); +[[maybe_unused]] constexpr intersecting_range<> _ = ALL; // NOLINT(readability-identifier-length) +[[maybe_unused]] constexpr intersecting_range<> U = ALL; // NOLINT(readability-identifier-length) +[[maybe_unused]] constexpr intersecting_range<> ooo = ALL; -[[maybe_unused]] constexpr intersecting_range<> V = U; // NOLINT(readability-identifier-length) -[[maybe_unused]] constexpr intersecting_range<> A = V; // NOLINT(readability-identifier-length) +[[maybe_unused]] constexpr intersecting_range<> V = U; // NOLINT(readability-identifier-length) +[[maybe_unused]] constexpr intersecting_range<> A = V; // NOLINT(readability-identifier-length) -//[[maybe_unused]] constexpr intersecting_range<> https://www.compart.com/en/unicode/U+2200 = V; +// [[maybe_unused]] constexpr intersecting_range<> ∀ = V; +// [[maybe_unused]] constexpr intersecting_range<> https://www.compart.com/en/unicode/U+2200 = V; template() + 1)> struct extension_t : public range { @@ -284,7 +314,7 @@ constexpr auto make_extension_t(IndexType first, IndexTypeLast last) -> extensio } template -constexpr auto make_extension_t(IndexTypeLast last) {return make_extension_t(IndexTypeLast{0}, last);} +constexpr auto make_extension_t(IndexTypeLast last) { return make_extension_t(IndexTypeLast{0}, last); } using index_range = range; using index_extension = extension_t; @@ -297,17 +327,15 @@ template struct append_to_type_seq {}; template class TT> -struct append_to_type_seq > { - using type = TT; +struct append_to_type_seq> { + using type = TT; }; template class TT> struct repeat { - using type = typename - append_to_type_seq< - T, - typename repeat::type - >::type; + using type = typename append_to_type_seq< + T, + typename repeat::type>::type; }; template class TT> @@ -321,8 +349,8 @@ template using index_extensions = typename detail::repeat template constexpr auto contains(index_extensions const& iex, Tuple const& tup) { -// using detail::head; -// using detail::tail; + // using detail::head; + // using detail::tail; return contains(head(iex), head(tup)) && contains(tail(iex), tail(tup)); } diff --git a/external_codes/boost_multi/multi/include/boost/multi/detail/type_traits.hpp b/external_codes/boost_multi/multi/include/boost/multi/detail/is_trivial.hpp similarity index 75% rename from external_codes/boost_multi/multi/include/boost/multi/detail/type_traits.hpp rename to external_codes/boost_multi/multi/include/boost/multi/detail/is_trivial.hpp index d16dc5c507..7845ee68a6 100644 --- a/external_codes/boost_multi/multi/include/boost/multi/detail/type_traits.hpp +++ b/external_codes/boost_multi/multi/include/boost/multi/detail/is_trivial.hpp @@ -2,10 +2,10 @@ // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt -#ifndef BOOST_MULTI_DETAIL_TYPE_TRAITS_HPP -#define BOOST_MULTI_DETAIL_TYPE_TRAITS_HPP +#ifndef BOOST_MULTI_DETAIL_IS_TRIVIAL_HPP +#define BOOST_MULTI_DETAIL_IS_TRIVIAL_HPP -#include +#include namespace boost { // NOLINT(modernize-concat-nested-namespaces) namespace multi { @@ -17,4 +17,4 @@ template struct is_trivial : std::is_trivial {}; } // end namespace multi } // end namespace boost -#endif +#endif // BOOST_MULTI_DETAIL_IS_TRIVIAL_HPP diff --git a/external_codes/boost_multi/multi/include/boost/multi/detail/layout.hpp b/external_codes/boost_multi/multi/include/boost/multi/detail/layout.hpp index 4dd952a43b..bae315617f 100644 --- a/external_codes/boost_multi/multi/include/boost/multi/detail/layout.hpp +++ b/external_codes/boost_multi/multi/include/boost/multi/detail/layout.hpp @@ -5,20 +5,33 @@ #ifndef BOOST_MULTI_DETAIL_LAYOUT_HPP #define BOOST_MULTI_DETAIL_LAYOUT_HPP -#include -#include -#include - -#include - -#include -#include // for make_signed_t -#include // for swap +#include +#include // IWYU pragma: export // for index_extension, extension_t, tuple, intersection, range, operator!=, operator== +#include // IWYU pragma: export // for equality_comparable +#include // IWYU pragma: export // for archive_traits +#include // IWYU pragma: export // for get, tuple, tuple_prepend, tail, tuple_prepend_t, ht_tuple +#include // IWYU pragma: export // for dimensionality_type, index, size_type, difference_type, size_t + +#include // for max +#include // for array +#include // for assert +#include // for size_t, ptrdiff_t, __GLIBCXX__ +#include // for abs +#include // for initializer_list +#include // for swap +#include // for tuple_element, tuple, tuple_size, tie, make_index_sequence, index_sequence +#include // for enable_if_t, integral_constant, decay_t, declval, make_signed_t, common_type_t +#include // for forward + +// clang-format off +namespace boost::multi { template struct layout_t; } +namespace boost::multi::detail { template class tuple; } +// clang-format on #if defined(__NVCC__) -#define BOOST_MULTI_HD __host__ __device__ + #define BOOST_MULTI_HD __host__ __device__ #else -#define BOOST_MULTI_HD + #define BOOST_MULTI_HD #endif namespace boost::multi { @@ -39,7 +52,7 @@ constexpr auto tuple_tail(Tuple&& t) // NOLINT(readability-identifier-length) s } // end namespace detail -template struct layout_t; +// template struct layout_t; template struct extensions_t : boost::multi::detail::tuple_prepend_t::base_> { @@ -54,66 +67,66 @@ struct extensions_t : boost::multi::detail::tuple_prepend_t = 0> + template = 0> // NOLINT(modernize-use-constraints) TODO(correaa) // cppcheck-suppress noExplicitConstructor ; to allow passing tuple // NOLINTNEXTLINE(runtime/explicit) constexpr extensions_t(multi::size_t size) : extensions_t{index_extension{size}} {} // NOLINT(google-explicit-constructor,hicpp-explicit-conversions) : allow terse syntax - template = 0> + template = 0> // NOLINT(modernize-use-constraints) TODO(correaa) // cppcheck-suppress noExplicitConstructor ; to allow passing tuple // NOLINTNEXTLINE(runtime/explicit) constexpr extensions_t(index_extension ext1) : base_{ext1} {} // NOLINT(google-explicit-constructor,hicpp-explicit-conversions) allow terse syntax - template = 0> + template = 0> // NOLINT(modernize-use-constraints) TODO(correaa) constexpr extensions_t(index_extension ext1, index_extension ext2) : base_{ext1, ext2} {} - template = 0> + template = 0> // NOLINT(modernize-use-constraints) TODO(correaa) constexpr extensions_t(index_extension ext1, index_extension ext2, index_extension ext3) : base_{ext1, ext2, ext3} {} - template = 0> + template = 0> // NOLINT(modernize-use-constraints) TODO(correaa) constexpr extensions_t(index_extension ext1, index_extension ext2, index_extension ext3, index_extension ext4) noexcept : base_{ext1, ext2, ext3, ext4} {} - template = 0> + template = 0> // NOLINT(modernize-use-constraints) TODO(correaa) constexpr extensions_t(index_extension ext1, index_extension ext2, index_extension ext3, index_extension ext4, index_extension ext5) : base_{ext1, ext2, ext3, ext4, ext5} {} - template = 0> + template = 0> // NOLINT(modernize-use-constraints) TODO(correaa) constexpr extensions_t(index_extension ext1, index_extension ext2, index_extension ext3, index_extension ext4, index_extension ext5, index_extension ext6) : base_{ext1, ext2, ext3, ext4, ext5, ext6} {} - template{}}), std::enable_if_t = 0> + template{}}), std::enable_if_t = 0> // NOLINT(modernize-use-constraints) TODO(correaa) // cppcheck-suppress noExplicitConstructor ; to allow passing tuple // NOLINTNEXTLINE(runtime/explicit) constexpr extensions_t(tuple extensions) : base_{std::move(extensions)} {} // NOLINT(google-explicit-constructor,hicpp-explicit-conversions) - template{}}), std::enable_if_t = 0> + template{}}), std::enable_if_t = 0> // NOLINT(modernize-use-constraints) TODO(correaa) // cppcheck-suppress noExplicitConstructor ; to allow passing tuple // NOLINTNEXTLINE(runtime/explicit) constexpr extensions_t(::std::tuple extensions) : base_{std::move(extensions)} {} // NOLINT(google-explicit-constructor,hicpp-explicit-conversions) - template{}}), std::enable_if_t = 0> + template{}}), std::enable_if_t = 0> // NOLINT(modernize-use-constraints) TODO(correaa) // cppcheck-suppress noExplicitConstructor ; to allow passing tuple // NOLINTNEXTLINE(runtime/explicit) constexpr extensions_t(tuple extensions) : base_{std::move(extensions)} {} // NOLINT(google-explicit-constructor,hicpp-explicit-conversions) - template{}}), std::enable_if_t = 0> + template{}}), std::enable_if_t = 0> // NOLINT(modernize-use-constraints) TODO(correaa) // cppcheck-suppress noExplicitConstructor ; to allow passing tuple // NOLINTNEXTLINE(runtime/explicit) constexpr extensions_t(::std::tuple extensions) : base_{std::move(extensions)} {} // NOLINT(google-explicit-constructor,hicpp-explicit-conversions) - template{}}), std::enable_if_t = 0> + template{}}), std::enable_if_t = 0> // NOLINT(modernize-use-constraints) TODO(correaa) // cppcheck-suppress noExplicitConstructor ; to allow passing tuple // NOLINTNEXTLINE(runtime/explicit) constexpr extensions_t(tuple extensions) : base_{std::move(extensions)} {} // NOLINT(google-explicit-constructor,hicpp-explicit-conversions) - template{}}), std::enable_if_t = 0> + template{}}), std::enable_if_t = 0> // NOLINT(modernize-use-constraints) TODO(correaa) // cppcheck-suppress noExplicitConstructor ; to allow passing tuple // NOLINTNEXTLINE(runtime/explicit) constexpr extensions_t(::std::tuple extensions) : base_{std::move(extensions)} {} // NOLINT(google-explicit-constructor,hicpp-explicit-conversions) - template{}}), std::enable_if_t = 0> + template{}}), std::enable_if_t = 0> // NOLINT(modernize-use-constraints) TODO(correaa) // cppcheck-suppress noExplicitConstructor ; to allow passing tuple // NOLINTNEXTLINE(runtime/explicit) constexpr extensions_t(tuple extensions) : base_{std::move(extensions)} {} // NOLINT(google-explicit-constructor,hicpp-explicit-conversions) - template{}}), std::enable_if_t = 0> + template{}}), std::enable_if_t = 0> // NOLINT(modernize-use-constraints) TODO(correaa) // cppcheck-suppress noExplicitConstructor ; to allow passing tuple // NOLINTNEXTLINE(runtime/explicit) constexpr extensions_t(::std::tuple extensions) : base_{std::move(extensions)} {} // NOLINT(google-explicit-constructor,hicpp-explicit-conversions) - template{}}), std::enable_if_t = 0> + template{}}), std::enable_if_t = 0> // NOLINT(modernize-use-constraints) TODO(correaa) // cppcheck-suppress noExplicitConstructor ; to allow passing tuple // NOLINTNEXTLINE(runtime/explicit) constexpr extensions_t(tuple extensions) : base_{std::move(extensions)} {} // NOLINT(google-explicit-constructor,hicpp-explicit-conversions) - template{}}), std::enable_if_t = 0> + template{}}), std::enable_if_t = 0> // NOLINT(modernize-use-constraints) TODO(correaa) // cppcheck-suppress noExplicitConstructor ; to allow passing tuple // NOLINTNEXTLINE(runtime/explicit) constexpr extensions_t(::std::tuple extensions) : base_{std::move(extensions)} {} // NOLINT(google-explicit-constructor,hicpp-explicit-conversions) @@ -179,6 +192,9 @@ struct extensions_t : boost::multi::detail::tuple_prepend_tget<0>().size();} + auto sizes() const {return this->apply([](auto const&... xs){return multi::detail::mk_tuple(xs.size()...);});} + private: template void serialize_impl_(Archive& arxiv, std::index_sequence /*unused012*/) { @@ -220,19 +236,22 @@ struct extensions_t : boost::multi::detail::tuple_prepend_t =0> + template =0> // NOLINT(modernize-use-constraints) TODO(correaa) friend constexpr auto get(extensions_t const& self) -> typename std::tuple_element::type { using boost::multi::detail::get; return get(self.base()); } - template =0> + template =0> // NOLINT(modernize-use-constraints) TODO(correaa) constexpr auto get() const -> typename std::tuple_element::type { using boost::multi::detail::get; return get(this->base()); } - // constexpr operator base_ const&() const { return impl_; } // NOLINT(google-explicit-constructor,hicpp-explicit-conversions) TODO(correaa) use inheritance from tuple to avoid this and implement get in std:: + template + constexpr auto apply(Fn&& fn) const -> decltype(auto) { + return std::apply(std::forward(fn), this->base()); + } }; template<> struct extensions_t<0> : tuple<> { @@ -337,7 +356,7 @@ template<> struct extensions_t<1> : tuple { static constexpr auto to_linear(index const& idx) -> difference_type /*const*/ {return idx;} constexpr auto operator()(index const& idx) const -> difference_type {return to_linear(idx);} constexpr auto operator[](index idx) const { - return multi::detail::tuple{std::get<0>(this->base())[idx]}; + return multi::detail::tuple{this->base().get<0>()[idx]}; } template @@ -375,13 +394,13 @@ template<> struct extensions_t<1> : tuple { arxiv & multi::archive_traits::make_nvp("extension", extension_); } - template =0> + template =0> // NOLINT(modernize-use-constraints) TODO(correaa) constexpr auto get() const -> decltype(auto) { // -> typename std::tuple_element::type { using boost::multi::detail::get; return get(this->base()); } - template =0> + template =0> // NOLINT(modernize-use-constraints) TODO(correaa) friend constexpr auto get(extensions_t const& self) -> decltype(auto) { // -> typename std::tuple_element::type { using boost::multi::detail::get; return get(self.base()); @@ -394,6 +413,14 @@ template constexpr auto array_size_impl(boost::multi::extensions_t const&) -> std::integral_constant(D)>; +extensions_t(multi::size_t) -> extensions_t<1>; +extensions_t(multi::size_t, multi::size_t) -> extensions_t<2>; +extensions_t(multi::size_t, multi::size_t, multi::size_t) -> extensions_t<3>; +extensions_t(multi::size_t, multi::size_t, multi::size_t, multi::size_t) -> extensions_t<4>; +extensions_t(multi::size_t, multi::size_t, multi::size_t, multi::size_t, multi::size_t) -> extensions_t<5>; +extensions_t(multi::size_t, multi::size_t, multi::size_t, multi::size_t, multi::size_t, multi::size_t) -> extensions_t<6>; +extensions_t(multi::size_t, multi::size_t, multi::size_t, multi::size_t, multi::size_t, multi::size_t, multi::size_t) -> extensions_t<7>; + } // end namespace boost::multi // Some versions of Clang throw warnings that stl uses class std::tuple_size instead @@ -417,7 +444,7 @@ struct std::tuple_element> { // NOLINT(cer using type = typename std::tuple_element::base_>::type; }; -namespace std { +namespace std { // NOLINT(cert-dcl58-cpp) // clang wants tuple_size to be a class, not a struct with -Wmismatched-tags #if !defined(__GLIBCXX__) || (__GLIBCXX__ <= 20190406) @@ -437,22 +464,35 @@ template<> class tuple_size> : public std::integra #endif #if !defined(_MSC_VER) && (!defined(__GLIBCXX__) || (__GLIBCXX__ <= 20240707) ) -template -constexpr auto get(boost::multi::extensions_t const& tp) // NOLINT(cert-dcl58-cpp) normal idiom to defined tuple get, gcc workaround +template +constexpr auto get(::boost::multi::extensions_t const& tp) // NOLINT(cert-dcl58-cpp) normal idiom to defined tuple get, gcc workaround ->decltype(tp.template get()) { return tp.template get(); } -template -constexpr auto get(boost::multi::extensions_t& tp) // NOLINT(cert-dcl58-cpp) normal idiom to defined tuple get, gcc workaround + +// template // , boost::multi::dimensionality_type D> +// constexpr auto get(boost::multi::extensions_t<2> const& tp) // NOLINT(cert-dcl58-cpp) normal idiom to defined tuple get, gcc workaround +// // ->decltype(tp.template get()) { +// -> decltype(auto) { +// return tp.template get(); } + +template +constexpr auto get(::boost::multi::extensions_t& tp) // NOLINT(cert-dcl58-cpp) normal idiom to defined tuple get, gcc workaround ->decltype(tp.template get()) { return tp.template get(); } template -constexpr auto get(boost::multi::extensions_t&& tp) // NOLINT(cert-dcl58-cpp) normal idiom to defined tuple get, gcc workaround +constexpr auto get(::boost::multi::extensions_t&& tp) // NOLINT(cert-dcl58-cpp) normal idiom to defined tuple get, gcc workaround ->decltype(std::move(tp).template get()) { return std::move(tp).template get(); } #endif +template +constexpr auto +apply(Fn&& fn, boost::multi::extensions_t const& xs) noexcept -> decltype(auto) { // NOLINT(cert-dcl58-cpp) I have to specialize std::apply as a workaround + return xs.apply(std::forward(fn)); +} + } // end namespace std namespace boost::multi { @@ -494,17 +534,20 @@ struct layout_t<0, SSize> friend constexpr auto dimensionality(layout_t const& /*self*/) {return rank_v;} private: - sub_type sub_ = {}; // TODO(correaa) use [[no_unique_address]] in C++20 - stride_type stride_ = {}; // TODO(correaa) use [[no_unique_address]] in C++20 - offset_type offset_ = 0; - nelems_type nelems_ = 1; // TODO(correaa) : or std::numeric_limits::max(); ? + BOOST_MULTI_NO_UNIQUE_ADDRESS sub_type sub_ ; + BOOST_MULTI_NO_UNIQUE_ADDRESS stride_type stride_; // = {}; + offset_type offset_; + nelems_type nelems_; template friend struct layout_t; public: layout_t() = default; - BOOST_MULTI_HD constexpr explicit layout_t(extensions_type const& /*nil*/) {} - BOOST_MULTI_HD constexpr explicit layout_t(extensions_type const& /*nil*/, strides_type const& /*nil*/) {} + + BOOST_MULTI_HD constexpr explicit layout_t(extensions_type const& /*nil*/) + : offset_{0}, nelems_{1} {} + + // BOOST_MULTI_HD constexpr explicit layout_t(extensions_type const& /*nil*/, strides_type const& /*nil*/) {} BOOST_MULTI_HD constexpr layout_t(sub_type sub, stride_type stride, offset_type offset, nelems_type nelems) // NOLINT(bugprone-easily-swappable-parameters) : sub_{sub}, stride_{stride}, offset_{offset}, nelems_{nelems} {} @@ -523,7 +566,7 @@ struct layout_t<0, SSize> [[nodiscard]] constexpr auto nelemss() const {return nelemss_type{};} constexpr auto operator()() const {return offset_;} - constexpr explicit operator offset_type() const {return offset_;} + // constexpr explicit operator offset_type() const {return offset_;} constexpr auto stride() const -> stride_type = delete; constexpr auto offset() const -> offset_type {return offset_;} @@ -556,6 +599,14 @@ struct layout_t<0, SSize> == std::tie(other.sub_, other.stride_, other.offset_, other.nelems_) ; } + + friend BOOST_MULTI_HD constexpr auto operator!=(layout_t const& self, layout_t const& other) { + return + std::tie(self .sub_, self .stride_, self .offset_, self .nelems_) + != std::tie(other.sub_, other.stride_, other.offset_, other.nelems_) + ; + } + constexpr auto operator< (layout_t const& other) const -> bool { return std::tie(offset_, nelems_) < std::tie(other.offset_, other.nelems_); } @@ -600,18 +651,19 @@ struct layout_t [[deprecated("for compatibility with Boost.MultiArray, use static `dimensionality` instead")]] static constexpr auto num_dimensions() {return dimensionality;} // NOSONAR(cpp:S1133) - friend constexpr auto dimensionality(layout_t const& /*self*/) {return rank_v;} + friend constexpr auto dimensionality(layout_t const& /*self*/) { return rank_v; } private: - sub_type sub_ = {}; - stride_type stride_ = 1; // or std::numeric_limits::max()? - offset_type offset_ = 0; - nelems_type nelems_ = 0; + sub_type sub_ ; + stride_type stride_ ; // = 1; // or std::numeric_limits::max()? + offset_type offset_ ; + nelems_type nelems_ ; template friend struct layout_t; public: layout_t() = default; + BOOST_MULTI_HD constexpr explicit layout_t(extensions_type const& extensions) : sub_{ std::apply( @@ -671,6 +723,14 @@ struct layout_t == std::tie(other.sub_, other.stride_, other.offset_, other.nelems_) ; } + + friend BOOST_MULTI_HD constexpr auto operator!=(layout_t const& self, layout_t const& other) -> bool { + return + std::tie(self .sub_, self .stride_, self .offset_, self. nelems_) + != std::tie(other.sub_, other.stride_, other.offset_, other.nelems_) + ; + } + constexpr BOOST_MULTI_HD auto operator< (layout_t const& other) const -> bool { return std::tie( sub_, stride_, offset_, nelems_) @@ -692,10 +752,11 @@ struct layout_t friend constexpr auto size(layout_t const& self) noexcept -> size_type {return self.size();} constexpr auto size() const noexcept -> size_type { - // if(nelems_ == 0) {return 0;} - BOOST_MULTI_ACCESS_ASSERT(stride_); // NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay) : normal in a constexpr function + if(nelems_ == 0) {return 0;} + // BOOST_MULTI_ACCESS_ASSERT(stride_); // NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay) : normal in a constexpr function // if(nelems_ != 0) {MULTI_ACCESS_ASSERT(stride_ != 0);} // return nelems_ == 0?0:nelems_/stride_; + // assert(stride_ != 0); return nelems_/stride_; } @@ -751,11 +812,18 @@ struct layout_t return *this; } + template + constexpr static void ce_swap(TT& t1, TT& t2) { + TT tmp = std::move(t1); + t1 = std::move(t2); + t2 = tmp; + } + constexpr auto transpose() -> layout_t& { - using std::swap; - swap(stride_, sub_.stride_); - swap(offset_, sub_.offset_); - swap(nelems_, sub_.nelems_); + // using std::swap; + ce_swap(stride_, sub_.stride_); + ce_swap(offset_, sub_.offset_); + ce_swap(nelems_, sub_.nelems_); return *this; } constexpr auto reverse() -> layout_t& { @@ -795,7 +863,7 @@ constexpr auto operator*(extensions_t<1> const& extensions_1d, extensions_t<1> c } // end namespace boost::multi -namespace boost::multi { +namespace boost::multi::detail { template struct convertible_tuple : Tuple { @@ -813,21 +881,20 @@ namespace boost::multi { /*explicit*/ operator array_type() const& noexcept {return to_array();} // NOLINT(google-explicit-constructor,hicpp-explicit-conversions) /*explicit*/ operator array_type() && noexcept {return to_array();} // NOLINT(google-explicit-constructor,hicpp-explicit-conversions) - [[deprecated("dangling conversion")]] - operator std::ptrdiff_t const*() const { // NOLINT(google-explicit-constructor,hicpp-explicit-conversions) - #ifdef __clang__ - #pragma clang diagnostic push - #pragma clang diagnostic ignored "-Wreturn-stack-address" - #endif - return to_array().data(); - #ifdef __clang__ - #pragma clang diagnostic pop - #endif - } + #ifdef __clang__ + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wreturn-stack-address" + #endif + [[deprecated("This is here for nominal compatiblity with Boost.MultiArray, this would be a dangling conversion")]] + operator std::ptrdiff_t const*() const &&; /*{ return to_array().data(); }*/ // NOLINT(google-explicit-constructor,hicpp-explicit-conversions) + #ifdef __clang__ + #pragma clang diagnostic pop + #endif - template), int> =0> + template), int> =0> // NOLINT(modernize-use-constraints) TODO(correaa) friend constexpr auto get(convertible_tuple const& self) -> typename std::tuple_element::type { - return std::get(static_cast(self)); + using std::get; + return get(static_cast(self)); } }; @@ -839,15 +906,16 @@ namespace boost::multi { [[deprecated("possible dangling conversion, use `std::array p` instead of `auto* p`")]] constexpr operator std::ptrdiff_t const*() const {return Array::data();} // NOLINT(google-explicit-constructor,hicpp-explicit-conversions) - template), int> =0> + template), int> =0> // NOLINT(modernize-use-constraints) TODO(correaa) friend constexpr auto get(decaying_array const& self) -> typename std::tuple_element::type { - return std::get(static_cast(self)); + using std::get; + return get(static_cast(self)); } }; -} // end namespace boost::multi +} // end namespace boost::multi::detail -template struct std::tuple_size> : std::integral_constant> {}; // NOLINT(cert-dcl58-cpp) normal idiom to defined tuple size -template struct std::tuple_size> : std::integral_constant> {}; // NOLINT(cert-dcl58-cpp) normal idiom to defined tuple size +template struct std::tuple_size> : std::integral_constant> {}; // NOLINT(cert-dcl58-cpp) normal idiom to defined tuple size +template struct std::tuple_size> : std::integral_constant> {}; // NOLINT(cert-dcl58-cpp) normal idiom to defined tuple size #ifdef __clang__ # pragma clang diagnostic pop diff --git a/external_codes/boost_multi/multi/include/boost/multi/detail/memory.hpp b/external_codes/boost_multi/multi/include/boost/multi/detail/memory.hpp index dfeb09a590..9adcc41673 100644 --- a/external_codes/boost_multi/multi/include/boost/multi/detail/memory.hpp +++ b/external_codes/boost_multi/multi/include/boost/multi/detail/memory.hpp @@ -6,8 +6,12 @@ #define BOOST_MULTI_DETAIL_MEMORY_HPP #pragma once -#include // for std::allocator_traits -#include // for std::void_t +#include // for has_rank, to_address + +#include // for copy, iterator_traits +#include // for allocator_traits +#include // for declval, enable_if_t, false_type, is_trivially_default_constructible, true_type, void_t +#include // for addressof, forward namespace boost::multi { @@ -17,20 +21,20 @@ struct allocator_traits : std::allocator_traits {}; // https://en.cppreference.com/w/cpp/memory/destroy template< class Alloc, class ForwardIt, - std::enable_if_t::value, int> =0 + std::enable_if_t::value, int> =0 // NOLINT(modernize-use-constraints) TODO(correaa) > void destroy(Alloc& alloc, ForwardIt first, ForwardIt last) { for(; first != last; ++first) {allocator_traits::destroy(alloc, std::addressof(*first));} // NOLINT(altera-unroll-loops) TODO(correaa) consider using an algorithm } -template::value && ForwardIt::rank_v == 1, int> = 0> +template::value && ForwardIt::rank_v == 1, int> = 0> // NOLINT(modernize-use-constraints) TODO(correaa) void destroy(Alloc& alloc, ForwardIt first, ForwardIt last) { // using multi::to_address; std::for_each(first, last, [&](auto& elem) {alloc.destroy(addressof(elem));}); // for(; first != last; ++first) {alloc.destroy(to_address(first));} // NOLINT(altera-unroll-loops) TODO(correaa) consider using an algorithm } -template::value && ForwardIt::rank_v != 1, int> = 0> +template::value && ForwardIt::rank_v != 1, int> = 0> // NOLINT(modernize-use-constraints) TODO(correaa) void destroy(Alloc& alloc, ForwardIt first, ForwardIt last) { for(; first != last; ++first) {destroy(alloc, begin(*first), end(*first));} // NOLINT(altera-unroll-loops) TODO(correaa) consider using an algorithm } @@ -62,7 +66,7 @@ auto uninitialized_default_construct_n(Alloc& alloc, ForwardIt first, Size n) -> template< class Alloc, class ForwardIt, class Size, typename T = typename std::iterator_traits::value_type, - typename = std::enable_if_t{}> + typename = std::enable_if_t{}> // NOLINT(modernize-use-constraints) TODO(correaa) > auto uninitialized_value_construct_n(Alloc& alloc, ForwardIt first, Size n) -> ForwardIt { ForwardIt current = first; // using std::addressof; @@ -82,7 +86,7 @@ template auto std_copy(Args&&... args) { namespace xtd { -template{}> > +template{}> > // NOLINT(modernize-use-constraints) TODO(correaa) auto alloc_uninitialized_copy(Alloc& alloc, InputIt first, InputIt last, MIt dest) -> MIt { MIt current = dest; // using multi::to_address; @@ -107,12 +111,12 @@ template constexpr bool is_allocator_v = is_allocator::value // template // auto uninitialized_copy(InputIt first, InputIt last, ForwardIt dest) { -// while(first!=last) { // NOLINT(altera-unroll-loops) TODO(correaa) consider using an algorithm -// uninitialized_copy(begin(*first), end(*first), begin(*dest)); -// ++first; -// ++dest; -// } -// return dest; +// while(first!=last) { // NOLINT(altera-unroll-loops) TODO(correaa) consider using an algorithm +// uninitialized_copy(begin(*first), end(*first), begin(*dest)); +// ++first; +// ++dest; +// } +// return dest; // } } // end namespace boost::multi diff --git a/external_codes/boost_multi/multi/include/boost/multi/detail/monotonic_allocator_.hpp b/external_codes/boost_multi/multi/include/boost/multi/detail/monotonic_allocator_.hpp deleted file mode 100644 index 4e4624d43c..0000000000 --- a/external_codes/boost_multi/multi/include/boost/multi/detail/monotonic_allocator_.hpp +++ /dev/null @@ -1,187 +0,0 @@ -// -*-indent-tabs-mode:t;c-basic-offset:4;tab-width:4;autowrap:nil;-*- -// Copyright 2018-2021 Alfredo A. Correa - -#ifndef BOOST_MULTI_DETAIL_MONOTONIC_ALLOCATOR_HPP -#define BOOST_MULTI_DETAIL_MONOTONIC_ALLOCATOR_HPP - -#include // for max -#include -#include // for max_align_t -#include -#include - -#include "generic_allocator.hpp" - -namespace boost { -namespace multi { - -template -struct block : std::pointer_traits{ - template block(char(&t)[N]) : start_{t}, lenght_{N} {} // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) support legacy c-arrays - typename block::pointer start_; - typename block::size_type lenght_; - bool contains(typename block::pointer p) const{ - using std::distance; - return distance(start_, p) < static_cast(lenght_); - } -}; - -template -class monotonic_buffer : block { - size_type hits_ = 0; - size_type misses_ = 0; - size_type allocated_bytes_ = 0; - size_type deallocated_bytes_ = 0; -// size_type position_ = 0; - - static std::size_t const max_alignment = A; - - static size_type align_up(size_type n) noexcept { - return (n + (max_alignment-1)) & ~(max_alignment-1); - } - - public: - size_type size() const {return size_;} - size_type hits() const {return hits_;} - size_type misses() const {return misses_;} - - size_type allocated_bytes() const {return allocated_bytes_;} - size_type deallocated_bytes() const {return deallocated_bytes_;} - - using block::block; - monotonic_buffer& operator=(block const& b) { - position_ = 0; - block::operator=(b); return *this; - } - - monotonic_buffer(monotonic_buffer const&) = delete; - monotonic_buffer& operator=(monotonic_buffer const&) = delete; - - ~monotonic_buffer() { -#ifndef _BOOST_MULTI_RELAX_MONOTONIC_LEAK_CONDITION - assert(allocated_bytes() == deallocated_bytes()); -#endif - } - using void_pointer = monotonic_buffer; - - template - void_pointer allocate(size_type req_bytes, size_type al = RequiredAlignment) { - static_assert(RequiredAlignment <= max_alignment, "!"); // requested alignment is too large for this MR - - assert( al <= max_alignment ); - auto bytes = this->align_up(req_bytes); - if(position_ + bytes < size_) { - auto old_position_ = position_; - position_ += bytes; - ++hits_; - allocated_bytes_ += bytes; - return buffer_ + old_position_; - } - ++misses_; - auto p = alloc_.allocate(bytes/sizeof(std::max_align_t)); - if(p) allocated_bytes_ += bytes; - return p; - } - void deallocate(void_pointer p, size_type req_bytes){ - auto bytes = align_up(req_bytes); - deallocated_bytes_ += bytes; - if(not in_buffer(static_cast(p))) { - alloc_.deallocate(static_cast(p), bytes); - } - } -}; - -template -using monotonic_allocator = multi::generic_allocator>>; - -} // end namespace multi -} // end namespace boost - -#if _TEST_BOOST_MULTI_DETAIL_MONOTONIC_ALLOCATOR - -#include "../../multi/array.hpp" - -#include -#include -#include - -namespace multi = boost::multi; -using std::cout; - -int main() { - std::cout << sizeof(std::max_align_t) <<" "<< alignof(std::max_align_t) << std::endl; - - { - multi::monotonic_buffer<> buf(250*sizeof(double)); - { - multi::array > A({10, 10}, &buf); - multi::array > B({10, 10}, &buf); - multi::array > C({10, 10}, &buf); - } - assert( buf.hits() == 2 ); - assert( buf.misses() == 1 ); - cout - <<"size: "<< buf.size() - <<"\nsaved: "<< buf.hits() - <<"\nmisses "<< buf.misses() - <<"\nallocated(bytes) "<< buf.allocated_bytes() - <<"\nreleased(bytes) "<< buf.deallocated_bytes() - << std::endl; - } - cout<<"----------"<> buf(guess*sizeof(double)); - - for(int i = 0; i != 3; ++i) { - cout<<"pass "<< i << std::endl; - { - multi::array > A({10, 10}, &buf); - multi::array > B({10, 10}, &buf); - multi::array > C({10, 10}, &buf); - } - cout - <<" size: "<< buf.size() - <<"\n save: "<< buf.hits() - <<"\n misses "<< buf.misses() - <<"\n allocated(bytes) "<< buf.allocated_bytes() - <<"\n released(bytes) "<< buf.deallocated_bytes() - << std::endl; - // guess = std::max(guess, buf.allocated_bytes()); - buf.reset(buf.allocated_bytes()); - } - } - cout<<"----------monotonic"<> buf(guess_bytes); - - { - multi::array > A({10, 10}, &buf); - - for(int i = 0; i != 3; ++i) { - multi::array > B({10, 10}, &buf); - std::vector> v(3, &buf); - v.push_back(33); v.push_back(33); - } - - multi::array > C({10, 10}, &buf); - } - - cout - <<" size: "<< buf.size() - <<"\n hits: "<< buf.hits() - <<"\n misses "<< buf.misses() - <<"\n allocated(bytes) "<< buf.allocated_bytes() - <<"\n released(bytes) "<< buf.deallocated_bytes() - << std::endl; - guess_bytes = std::max(guess_bytes, buf.allocated_bytes()); - } - } -} -#endif -#endif - diff --git a/external_codes/boost_multi/multi/include/boost/multi/detail/operators.hpp b/external_codes/boost_multi/multi/include/boost/multi/detail/operators.hpp index 3bd9709a62..4f5743ad1e 100644 --- a/external_codes/boost_multi/multi/include/boost/multi/detail/operators.hpp +++ b/external_codes/boost_multi/multi/include/boost/multi/detail/operators.hpp @@ -4,15 +4,16 @@ #ifndef BOOST_MULTI_DETAIL_OPERATORS_HPP #define BOOST_MULTI_DETAIL_OPERATORS_HPP -#pragma once -#include // for enable_if -#include // for forward +#include // for ptrdiff_t +#include // for random_access_iterator_tag +#include // for enable_if_t, is_base_of +#include // for forward #if defined(__NVCC__) -#define BOOST_MULTI_HD __host__ __device__ + #define BOOST_MULTI_HD __host__ __device__ #else -#define BOOST_MULTI_HD + #define BOOST_MULTI_HD #endif namespace boost::multi { @@ -44,7 +45,7 @@ struct totally_ordered2 : equality_comparable2 self_type const& { return static_cast(*this); } // friend auto operator< (totally_ordered2 const& self, totally_ordered2 const& other) -> bool {return self.self() < other.self() ;} - friend auto operator==(totally_ordered2 const& self, totally_ordered2 const& other) -> bool { return !(self.self() < other.self()) && !(other.self() < self.self()); } + friend constexpr auto operator==(totally_ordered2 const& self, totally_ordered2 const& other) -> bool { return !(self.self() < other.self()) && !(other.self() < self.self()); } // friend auto operator!=(totally_ordered2 const& self, totally_ordered2 const& other) {return (s.self() < o.self()) or (o.self() < s.self());} friend auto operator<=(totally_ordered2 const& self, totally_ordered2 const& other) -> bool { return !(other.self() < self.self()); } @@ -59,8 +60,8 @@ template struct totally_ordered2 { // template // friend constexpr auto operator<=(T const& self, U const& other) { return (self < other) || (self == other); } - //template - //friend constexpr auto operator>=(T const& self, U const& other) { return (other < self) || (self == other); } + // template + // friend constexpr auto operator>=(T const& self, U const& other) { return (other < self) || (self == other); } // template // friend constexpr auto operator>(T const& self, U const& other) { return other < self; } }; @@ -89,7 +90,7 @@ template struct incrementable : totally_ordered { // , self_m template struct decrementable : weakly_decrementable { - template>> + template>> // NOLINT(modernize-use-constraints) TODO(correaa) friend constexpr auto operator--(U& self, int) -> T { T tmp{self}; --self; @@ -181,13 +182,13 @@ struct random_accessable // NOLINT(fuchsia-multiple-inheritance) template struct addable2 { using difference_type = D; - template{}>> + template{}>> // NOLINT(modernize-use-constraints) TODO(correaa) friend constexpr auto operator+(TT&& self, difference_type const& diff) -> T { T tmp{std::forward(self)}; tmp += diff; return tmp; } - template{}>> + template{}>> // NOLINT(modernize-use-constraints) TODO(correaa) friend constexpr auto operator+(difference_type const& diff, TT&& self) -> T { return std::forward(self) + diff; } }; diff --git a/external_codes/boost_multi/multi/include/boost/multi/detail/serialization.hpp b/external_codes/boost_multi/multi/include/boost/multi/detail/serialization.hpp index b1dda081e0..c64d286d73 100644 --- a/external_codes/boost_multi/multi/include/boost/multi/detail/serialization.hpp +++ b/external_codes/boost_multi/multi/include/boost/multi/detail/serialization.hpp @@ -4,44 +4,34 @@ #ifndef BOOST_MULTI_DETAIL_SERIALIZATION_HPP_ #define BOOST_MULTI_DETAIL_SERIALIZATION_HPP_ +#pragma once -#include // for std::for_each -#include // for std::byte -#include // for std::uint32_t -#include +#include // for std::for_each // IWYU pragma: keep // bug in iwyu 0.18 +#include // for size_t, byte +#include // for uint32_t +#include // for next +#include // for enable_if_t, decay_t +#include // for forward -namespace boost { // NOLINT(modernize-concat-nested-namespaces) keep c++14 compat -namespace archive { // NOLINT(modernize-concat-nested-namespaces) keep c++14 compat -namespace detail { - -template class common_iarchive; -template class common_oarchive; - -} // end namespace detail -} // end namespace archive +namespace boost::archive::detail { template class common_iarchive; } // lines 24-24 +namespace boost::archive::detail { template class common_oarchive; } // lines 25-25 -namespace serialization { // NOLINT(modernize-concat-nested-namespaces) keep c++14 compat +namespace boost::serialization { struct binary_object; } +namespace boost::serialization { template class array_wrapper; } +namespace boost::serialization { template class nvp; } -template class nvp; // dependency "in name only" -template class array_wrapper; // dependency "in name only" -struct binary_object; // dependency "in name only", if you get an error here, it means that eventually you need to include #include +namespace cereal { template struct InputArchive; } +namespace cereal { template struct OutputArchive; } +namespace cereal { template class NameValuePair; } // if you get an error here you many need to #include at some point // IWYU pragma: keep // bug in iwyu 0.18 -template struct version; +// namespace boost { +// namespace serialization { // template//, std::enable_if_t>{}, int> =0> // auto operator>>(Archive& ar, T&& t) -> Archive& {return ar>> t;} -} // end namespace serialization -} // end namespace boost - -namespace cereal { - -template struct OutputArchive; -template struct InputArchive; - -template class NameValuePair; // dependency "in name only", if you get an error here you many need to #include at some point - -} // end namespace cereal +// } // end namespace serialization +// } // end namespace boost namespace boost { // NOLINT(modernize-concat-nested-namespaces) keep c++14 compat namespace multi { @@ -49,22 +39,22 @@ namespace multi { template struct archive_traits { template - /*inline*/ static auto make_nvp(char const* /*n*/, T&& value) noexcept { return std::forward(value); } + /*inline*/ static auto make_nvp(char const* /*n*/, T&& value) noexcept { return std::forward(value); } // match original boost declaration }; -template> && (MA::dimensionality > -1), int> = 0> +template> && (MA::dimensionality > -1), int> = 0> // NOLINT(modernize-use-constraints) TODO(correaa) auto operator>>(Archive& arxiv, MA&& self) // this is for compatibility with Archive type -> decltype(arxiv >> static_cast(std::forward(self))) { return arxiv >> static_cast(std::forward(self)); } -template> && (MA::dimensionality > -1), int> = 0> +template> && (MA::dimensionality > -1), int> = 0> // NOLINT(modernize-use-constraints) TODO(correaa) auto operator<<(Archive& arxiv, MA&& self) // this is for compatibility with Archive type -> decltype(arxiv << static_cast(std::forward(self))) { return arxiv << static_cast(std::forward(self)); } -template> && (MA::dimensionality > -1), int> = 0> +template> && (MA::dimensionality > -1), int> = 0> // NOLINT(modernize-use-constraints) TODO(correaa) auto operator&(Archive& arxiv, MA&& self) // this is for compatibility with Archive type -> decltype(arxiv & static_cast(std::forward(self))) { return arxiv & static_cast(std::forward(self)); @@ -134,12 +124,12 @@ struct archive_traits< } // end namespace multi } // end namespace boost -namespace boost { +// namespace boost { -template -class multi_array; +// template +// class multi_array; -} // end namespace boost +// } // end namespace boost namespace boost { // NOLINT(modernize-concat-nested-namespaces) keep c++14 compat namespace serialization { diff --git a/external_codes/boost_multi/multi/include/boost/multi/detail/stack_allocator_.hpp b/external_codes/boost_multi/multi/include/boost/multi/detail/stack_allocator_.hpp deleted file mode 100644 index f7144d34c5..0000000000 --- a/external_codes/boost_multi/multi/include/boost/multi/detail/stack_allocator_.hpp +++ /dev/null @@ -1,161 +0,0 @@ -// -*-indent-tabs-mode:t;c-basic-offset:4;tab-width:4;autowrap:nil;-*- -// Copyright 2021 Alfredo A. Correa - -#ifndef BOOST_MULTI_DETAIL_STACK_ALLOCATOR_HPP -#define BOOST_MULTI_DETAIL_STACK_ALLOCATOR_HPP - -#include "monotonic_allocator.hpp" - -#include -#include -#include -#include - -namespace boost { -namespace multi { - -template< - class Alloc = std::allocator, - typename std::allocator_traits::size_type MaxAlignemnt = alignof(std::max_align_t) -> -class stack_buffer : private monotonic_buffer{ - using base_ = monotonic_buffer; - - public: - using typename base_::pointer; - using typename base_::void_pointer; - using typename base_::char_pointer; - using typename base_::allocator_type; - using typename base_::size_type; - using typename base_::difference_type; - - private: - std::stack positions_ = {}; - size_type stack_recovered_ = 0; - size_type max_needed_ = 0; - - public: - using base_::hits; - using base_::misses; - using base_::allocated_bytes; - using base_::deallocated_bytes; - size_type max_needed() const {return max_needed_;} - size_type stack_recovered() const {return stack_recovered_;} - - using base_::size; - using base_::allocator; - - stack_buffer(size_type bytes, allocator_type alloc) - : monotonic_buffer{bytes, alloc} {} - - explicit stack_buffer(size_type bytes) : stack_buffer{bytes, allocator_type{}} {} - - - void reset(size_type bytes = 0) { - assert(this->position_ == 0 and positions_.empty()); - base_::reset(bytes); - } - - template - void_pointer allocate(size_type req_bytes, size_type al = RequiredAlignment) { - if(req_bytes == 0) return this->buffer_ + this->position_; - static_assert( RequiredAlignment <= MaxAlignemnt, "!"); - assert( al <= this->max_alignment ); - auto bytes = this->align_up(req_bytes); - if(this->position_ + bytes <= this->size_) { - auto old_position_ = this->position_; - positions_.push(this->position_); - this->position_ += bytes; - ++this->hits_; - this->allocated_bytes_ += bytes; - max_needed_ = std::max(max_needed_, this->allocated_bytes_ - this->deallocated_bytes_); - return this->buffer_ + old_position_; - } - ++this->misses_; - auto p = allocator_type::allocate(bytes/sizeof(std::max_align_t)); - if(p) { - this->allocated_bytes_ += bytes; - max_needed_ = std::max(max_needed_, this->allocated_bytes_ - this->deallocated_bytes_); - } - return p; - } - - void deallocate(void_pointer p, size_type req_bytes) { - if(req_bytes == 0) return; - auto bytes = this->align_up(req_bytes); - this->deallocated_bytes_ += bytes; - if(not this->in_buffer(static_cast(p))) { - allocator_type::deallocate(static_cast(p), bytes/sizeof(std::max_align_t)); - } else { - if(std::distance(static_cast(static_cast(this->buffer_)), static_cast(p)) == static_cast(positions_.top())) { - this->position_ -= bytes; - positions_.pop(); - stack_recovered_ += bytes; - #ifndef _BOOST_MULTI_RELAX_STACK_CONDITION - } else { - assert(0 && "stack violation"); // throw std::logic_error{"stack violation!"}; // careful with throwing from deallocation! TODO should invalidate the buffer? - #endif - } - } - } -}; - -template, typename std::allocator_traits::size_type MaxAlignemnt = alignof(std::max_align_t)> -using stack_allocator = multi::generic_allocator>; - -} // end namespace multi -} // end namespace boost - -#if _TEST_BOOST_MULTI_DETAIL_STACK_ALLOCATOR - -#include "../../multi/array.hpp" -#include - -#include -#include -#include - -namespace multi = boost::multi; -using std::cout; -using boost::alignment::is_aligned; - -int main() { - { - std::size_t guess_bytes = 120; - multi::stack_buffer, 32> buf{guess_bytes}; - - for(int i = 0; i != 3; ++i) { - cout<<"pass "<< i << std::endl; - { - multi::stack_allocator, 32> sa(&buf); - multi::array, 32>> A({2, 10}, &buf); assert( is_aligned(alignof(double), &A[1][3]) ); - multi::array, 32>> B({3, 10}, &buf); assert( is_aligned(alignof(double), &B[2][3]) ); - multi::array, 32>> C({4, 10}, &buf); assert( is_aligned(alignof(double), &C[3][3]) ); - std::vector, 32>> v(3, &buf); assert( is_aligned(alignof(int), &v[1]) ); - - for(int j = 0; j != 100; ++j) { - multi::array, 32> > D({4, 10}, &buf); assert( is_aligned(alignof(double), &D[2][1]) ); - multi::array > E({4, 10}, &buf); assert( is_aligned(alignof(float), &E[3][3]) ); - } - - multi::array > F({4, 10}, &buf); assert( is_aligned(alignof(double), &F[2][1]) ); - } - cout<<" size: "<< buf.size() - <<"\n hits: "<< buf.hits() - <<"\n misses "<< buf.misses() - <<"\n allocated(bytes) "<< buf.allocated_bytes() - <<"\n deallocated(bytes) "<< buf.deallocated_bytes() - <<"\n max_needed(bytes) "<< buf.max_needed() - <<"\n stack recovered(bytes) " << buf.stack_recovered() - < sad{&buf}; - multi::stack_allocator sai{sad}; // check constructor - } -} -#endif -#endif - diff --git a/external_codes/boost_multi/multi/include/boost/multi/detail/static_allocator.hpp b/external_codes/boost_multi/multi/include/boost/multi/detail/static_allocator.hpp index e0f54f16f9..db7f4ab24c 100644 --- a/external_codes/boost_multi/multi/include/boost/multi/detail/static_allocator.hpp +++ b/external_codes/boost_multi/multi/include/boost/multi/detail/static_allocator.hpp @@ -16,18 +16,18 @@ namespace boost::multi::detail { template -class static_allocator { //NOSONAR(cpp:S4963) this allocator has special semantics +class static_allocator { // NOSONAR(cpp:S4963) this allocator has special semantics bool dirty_ = false; #ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable : 4324) // Warning that the structure is padded due to the below -#endif - + #pragma warning(push) + #pragma warning(disable : 4324) // Warning that the structure is padded due to the below +#endif + BOOST_MULTI_NO_UNIQUE_ADDRESS alignas(T) std::array buffer_; #ifdef _MSC_VER -#pragma warning(pop) + #pragma warning(pop) #endif public: @@ -48,30 +48,27 @@ class static_allocator { //NOSONAR(cpp:S4963) this allocator has special semant static_assert(NN == N); } - static_allocator(static_allocator const& /*other*/) // std::vector makes a copy right away + static_allocator(static_allocator const& /*other*/) // std::vector makes a copy right away // = default; // this copies the internal buffer {} - [[deprecated("don't move dynamic container with static_allocator")]] + // [[deprecated("don't move dynamic container with static_allocator")]] static_allocator(static_allocator&& /*other*/) // this is called *by the elements* during move construction of a vector - // = delete; - // {throw std::runtime_error("don't move dynamic container with static_allocator");} // this is called *by the elements* during move construction of a vector - noexcept {} + // = delete; + // {throw std::runtime_error("don't move dynamic container with static_allocator");} // this is called *by the elements* during move construction of a vector + noexcept {} // noexcept {std::memmove(buffer_.data(), other.buffer_.data(), sizeof(T)*N);} // noexcept : buffer_{std::move(other.buffer_)} {} // noexcept = default; [[deprecated("don't move dynamic container with static_allocator")]] - auto operator=(static_allocator const& /*other*/) -> static_allocator& - = delete; + auto operator=(static_allocator const& /*other*/) -> static_allocator& = delete; - [[deprecated("don't move dynamic container with static_allocator")]] auto operator=(static_allocator&& other) -> static_allocator& - = delete; + [[deprecated("don't move dynamic container with static_allocator")]] auto operator=(static_allocator&& other) -> static_allocator& = delete; ~static_allocator() = default; - auto select_on_container_copy_construction() noexcept -> static_allocator - = delete; + auto select_on_container_copy_construction() noexcept -> static_allocator = delete; // {return static_allocator{};} using propagate_on_container_move_assignment = std::false_type; // this forces to call move assignment of the allocator by std::vector @@ -80,13 +77,24 @@ class static_allocator { //NOSONAR(cpp:S4963) this allocator has special semant static constexpr auto capacity() { return N; } +#ifdef _MSC_VER +#pragma warning( push ) +#pragma warning( disable : 4068) // bug in MSVC 14.2/14.3 +#endif BOOST_MULTI_NODISCARD("because otherwise it will generate a memory leak") auto allocate([[maybe_unused]] std::size_t n) -> pointer { assert(n <= N); - assert(! dirty_); // do not attempt to resize a vector with static_allocator + assert(!dirty_); // do not attempt to resize a vector with static_allocator dirty_ = true; - return reinterpret_cast(buffer_.data()); // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wcast-align" // buffer_ is aligned as T + return reinterpret_cast(&buffer_); // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast) +#pragma GCC diagnostic pop } +#ifdef _MSC_VER +#pragma warning( pop ) +#endif + void deallocate(pointer /*ptr*/, [[maybe_unused]] std::size_t n) { assert(n <= N); } @@ -95,16 +103,15 @@ class static_allocator { //NOSONAR(cpp:S4963) this allocator has special semant }; template -constexpr auto operator==(static_allocator const& /*a1*/, static_allocator const& /*a2*/) noexcept -{ return true; } // &a1 == &a2; } +constexpr auto operator==(static_allocator const& /*a1*/, static_allocator const& /*a2*/) noexcept { return true; } // &a1 == &a2; } // = delete; -template -auto operator!=(static_allocator const& /*a1*/, static_allocator const& /*a2*/) noexcept // this is used *by the elements* when resizing a vector -{ return false; } // &a1 != &a2;} +template +auto operator!=(static_allocator const& /*a1*/, static_allocator const& /*a2*/) noexcept // this is used *by the elements* when resizing a vector +{ return false; } // &a1 != &a2;} // = delete -template +template [[deprecated("don't swap dynamic container with static_allocator")]] void swap(static_allocator& a1, static_allocator& a2) noexcept = delete; diff --git a/external_codes/boost_multi/multi/include/boost/multi/detail/tuple_zip.hpp b/external_codes/boost_multi/multi/include/boost/multi/detail/tuple_zip.hpp index a85395bdae..7065abb112 100644 --- a/external_codes/boost_multi/multi/include/boost/multi/detail/tuple_zip.hpp +++ b/external_codes/boost_multi/multi/include/boost/multi/detail/tuple_zip.hpp @@ -6,10 +6,10 @@ #define BOOST_MULTI_DETAIL_TUPLE_ZIP_HPP #pragma once -#include -#include - -#include // for deprecated functions +#include // for size_t +#include // for deprecated functions // for make_index_sequence, index_sequence, tuple_element, tuple_size, apply, tuple +#include // for declval, decay_t, conditional_t, true_type +#include // for forward, move namespace boost::multi { // NOLINT(modernize-concat-nested-namespaces) keep c++14 compat namespace detail { @@ -37,7 +37,7 @@ template class tuple : tuple { // NOLI public: constexpr auto head() const& -> T0 const& { return head_; } - constexpr auto head() && -> decltype(auto) { return std::move(head_); } + constexpr auto head() && -> T0&& { return std::move(head_); } constexpr auto head() & -> T0& { return head_; } constexpr auto tail() const& -> tail_type const& { return static_cast(*this); } @@ -86,6 +86,21 @@ template class tuple : tuple { // NOLI return tail() > other.tail(); } + private: + + template + constexpr auto apply_impl_(F&& fn, std::index_sequence /*012*/) const -> decltype(auto) { // NOLINT(cert-dcl58-cpp) normal idiom to defined tuple get + return std::forward(fn)(this->get()...); + } + + public: + template + constexpr auto apply(F&& fn) const -> decltype(auto) { // NOLINT(cert-dcl58-cpp) normal idiom to defined tuple get + return apply_impl_(std::forward(fn), std::make_index_sequence{}); + } + + // constexpr explicit operator std::tuple() const {return this->apply([](auto const&... xs) {return std::tuple(xs...);});} + private: template struct priority : std::conditional_t> {}; @@ -282,9 +297,9 @@ constexpr auto get(tuple&& tup) -> auto&& { #endif template -struct std::tuple_size> { // NOLINT(cert-dcl58-cpp) to have structured bindings - // cppcheck-suppress unusedStructMember - static constexpr std::size_t value = sizeof...(Ts); +struct std::tuple_size> : std::integral_constant { // NOLINT(cert-dcl58-cpp) to have structured bindings + // // cppcheck-suppress unusedStructMember + // static constexpr std::size_t value = sizeof...(Ts); }; template<> @@ -307,25 +322,29 @@ struct std::tuple_element> { // NOLIN using type = typename tuple_element>::type; }; -namespace std { // NOLINT(cert-dcl58-cpp) to implement structured bindings +// namespace std { // NOLINT(cert-dcl58-cpp) to implement structured bindings -template -constexpr auto get(boost::multi::detail::tuple const& tp) // NOLINT(cert-dcl58-cpp) normal idiom to defined tuple get - -> decltype(boost::multi::detail::get(tp)) { - return boost::multi::detail::get(tp); -} +// template +// constexpr auto get(boost::multi::detail::tuple const& tp) // NOLINT(cert-dcl58-cpp) normal idiom to defined tuple get +// -> decltype(boost::multi::detail::get(tp)) { +// return boost::multi::detail::get(tp); +// } -template -constexpr auto get(boost::multi::detail::tuple& tp) // NOLINT(cert-dcl58-cpp) normal idiom to defined tuple get - -> decltype(boost::multi::detail::get(tp)) { - return boost::multi::detail::get(tp); -} +// template +// constexpr auto get(boost::multi::detail::tuple& tp) // NOLINT(cert-dcl58-cpp) normal idiom to defined tuple get +// -> decltype(boost::multi::detail::get(tp)) { +// return boost::multi::detail::get(tp); +// } -template -constexpr auto get(boost::multi::detail::tuple&& tp) // NOLINT(cert-dcl58-cpp) normal idiom to defined tuple get - -> decltype(boost::multi::detail::get(std::move(tp))) { - return boost::multi::detail::get(std::move(tp)); -} +// template +// constexpr auto get(boost::multi::detail::tuple&& tp) // NOLINT(cert-dcl58-cpp) normal idiom to defined tuple get +// -> decltype(boost::multi::detail::get(std::move(tp))) { +// return boost::multi::detail::get(std::move(tp)); +// } + +// } // end namespace std + +namespace std { // NOLINT(cert-dcl58-cpp) to implement structured bindings template constexpr auto std_apply_timpl(F&& fn, Tuple&& tp, std::index_sequence /*012*/) -> decltype(auto) { // NOLINT(cert-dcl58-cpp) normal idiom to defined tuple get diff --git a/external_codes/boost_multi/multi/include/boost/multi/detail/types.hpp b/external_codes/boost_multi/multi/include/boost/multi/detail/types.hpp index 37ee09b7d7..952a38badc 100644 --- a/external_codes/boost_multi/multi/include/boost/multi/detail/types.hpp +++ b/external_codes/boost_multi/multi/include/boost/multi/detail/types.hpp @@ -7,7 +7,6 @@ #include // for std::size_t #include // for make_signed_t -#include // for forward namespace boost::multi { diff --git a/external_codes/boost_multi/multi/include/boost/multi/pmr_.hpp b/external_codes/boost_multi/multi/include/boost/multi/pmr_.hpp deleted file mode 100644 index 8da23c7df6..0000000000 --- a/external_codes/boost_multi/multi/include/boost/multi/pmr_.hpp +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright 2018-2024 Alfredo A. Correa -// Distributed under the Boost Software License, Version 1.0. -// https://www.boost.org/LICENSE_1_0.txt - -#ifndef BOOST_MULTI_PMR_HPP_ -#define BOOST_MULTI_PMR_HPP_ - -#include - -#endif diff --git a/external_codes/boost_multi/multi/include/boost/multi/utility.hpp b/external_codes/boost_multi/multi/include/boost/multi/utility.hpp index 1416a3f219..aca861c5bc 100644 --- a/external_codes/boost_multi/multi/include/boost/multi/utility.hpp +++ b/external_codes/boost_multi/multi/include/boost/multi/utility.hpp @@ -6,17 +6,14 @@ #define BOOST_MULTI_UTILITY_HPP #pragma once -#include +#include // IWYU pragma: export #include #include // for std::invoke +#include // for std::size (in c++17) #include // for allocator<> #include // for std::invoke_result -#if(__cplusplus >= 201703L) -#include // for std::size (in c++17) -#endif - #if defined(__NVCC__) #define BOOST_MULTI_HD __host__ __device__ #else @@ -101,7 +98,7 @@ struct transform_ptr { template(std::declval

()))* =nullptr> constexpr explicit transform_ptr(Other const& other) : p_{other.p_}, f_{other.f_} {} - constexpr auto functor() const -> UF {return f_;} + // constexpr auto functor() const -> UF {return f_;} constexpr auto base() const -> Ptr const& {return p_;} constexpr auto operator*() const -> reference { // NOLINT(readability-const-return-type) in case synthesis reference is a `T const` // invoke allows for example to use .transformed( &member) instead of .transformed( std::mem_fn(&member) ) @@ -109,9 +106,19 @@ struct transform_ptr { // return f_(*p_); // NOLINT(readability-const-return-type) in case synthesis reference is a `T const` } + #if defined(__clang__) + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wunknown-warning-option" + #pragma clang diagnostic ignored "-Wunsafe-buffer-usage" // TODO(correaa) use checked span + #endif + constexpr auto operator+=(difference_type n) -> transform_ptr& {p_ += n; return *this;} constexpr auto operator-=(difference_type n) -> transform_ptr& {p_ -= n; return *this;} + #if defined(__clang__) + #pragma clang diagnostic pop + #endif + constexpr auto operator+(difference_type n) const -> transform_ptr {transform_ptr ret{*this}; ret += n; return ret;} constexpr auto operator-(difference_type n) const -> transform_ptr {transform_ptr ret{*this}; ret -= n; return ret;} @@ -149,6 +156,13 @@ template struct has_rank : decltype(has_rank_aux(std::declval())){}; template struct rank; +template().move())> + auto has_member_move_aux(T const&) -> std::true_type; +inline auto has_member_move_aux(... ) -> std::false_type; + +template struct has_member_move : decltype(has_member_move_aux(std::declval())) {}; + + template{}> > constexpr auto rank_aux(T const&) -> typename T::rank; @@ -157,10 +171,10 @@ constexpr auto rank_aux(T const&) -> std::integral_constant struct rank : decltype(rank_aux(std::declval())) {}; -template{}, int> = 0> // special sfinae trick +template{}, int> = 0> // NOLINT(modernize-use-constraints) TODO(correaa) special sfinae trick constexpr auto stride(Pointer /*ptr*/) -> std::ptrdiff_t {return 1;} -template{}, int> =0> // special sfinae trick +template{}, int> =0> // NOLINT(modernize-use-constraints) TODO(correaa) special sfinae trick constexpr auto base(Pointer ptr) -> Pointer {return ptr;} template @@ -198,20 +212,20 @@ auto has_get_allocator_aux(T const& cont) -> decltype(cont.get_allocator(), std: template struct has_get_allocator : decltype(has_get_allocator_aux(std::declval())) {}; -template // std::common_type_t> -auto common(T1 const& val1, T2 const& val2) -> Ret { - return val1 == val2? - val1: - Ret{} - ; -} +// template // std::common_type_t> +// auto common(T1 const& val1, T2 const& val2) -> Ret { +// return val1 == val2? +// val1: +// Ret{} +// ; +// } template auto has_num_elements_aux(T const& /*array*/)->decltype(std::declval().num_elements() + 1, std::true_type {}); inline auto has_num_elements_aux(... )->decltype( std::false_type{}); template struct has_num_elements : decltype(has_num_elements_aux(std::declval())) {}; // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg,cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay) -template{}> > +template{}> > // NOLINT(modernize-use-constraints) TODO(correaa) for C++20 constexpr auto num_elements(A const& arr) ->std::make_signed_t { return static_cast>(arr.num_elements()); @@ -239,23 +253,23 @@ inline auto has_data_aux(... ) -> decltype( std::fa } // end namespace detail template struct has_data : decltype(detail::has_data_aux(std::declval())) {}; // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg,cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay) -template>::value && !has_data_elements>::value, int> =0> +template>::value && !has_data_elements>::value, int> =0> // NOLINT(modernize-use-constraints) TODO(correaa) for C++20 auto data_elements(Array& arr) {return std::data(arr);} -template>::value && !has_data_elements>::value, int> =0> +template>::value && !has_data_elements>::value, int> =0> // NOLINT(modernize-use-constraints) TODO(correaa) for C++20 auto data_elements(Array const& arr) {return std::data(arr);} // .data();} -template::value && has_size::value && has_data::value, int> =0> +template::value && has_size::value && has_data::value, int> =0> // NOLINT(modernize-use-constraints) TODO(correaa) in C++20 constexpr auto num_elements(A const& arr) -> std::make_signed_t { return static_cast>(std::size(arr)); // (arr.size()); } -template{}, int> =0> +template{}, int> =0> // NOLINT(modernize-use-constraints) TODO(correaa) for C++20 constexpr auto data_elements(A const& arr) ->decltype(arr.data_elements()) { return arr.data_elements(); } -template> && ! has_data_elements>::value && !has_data>::value, int> =0> +template> && ! has_data_elements>::value && !has_data>::value, int> =0> // NOLINT(modernize-use-constraints) TODO(correaa) for C++20 constexpr auto data_elements(T& value) -> decltype(&value) {return &value;} template struct num_elements_t: std::integral_constant {}; @@ -293,7 +307,7 @@ template inline auto has_dimensionality_aux(... )->decltype( std::false_type{}); template struct has_dimensionality : decltype(has_dimensionality_aux(std::declval())) {}; // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg,cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay) -template{}, int> =0> +template{}, int> =0> // NOLINT(modernize-use-constraints) TODO(correaa) for C++20 constexpr auto dimensionality(Container const& /*container*/) ->std::decay_t { return Container::rank_v;} @@ -303,14 +317,17 @@ template inline auto has_dimensionaliy_member_aux(... ) -> decltype( std::false_type{}); template struct has_dimensionality_member : decltype(has_dimensionaliy_member_aux(std::declval())) {}; // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg,cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay) -template{}>> +template{}>> // NOLINT(modernize-use-constraints) TODO(correaa) constexpr auto dimensionality(T const&/*, void* = nullptr*/) {return 0;} template constexpr auto dimensionality(T const(&array)[N]) {return 1 + dimensionality(array[0]);} // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) : for backwards compatibility -template -constexpr auto sizes(T const& /*unused*/) noexcept -> tuple<> {return {};} +template().sizes())> +constexpr auto sizes(T const& arr) noexcept -> Ret {return arr.sizes();} + +template::value,int> =0> // NOLINT(modernize-use-constraints) TODO(correaa) in C++20 +constexpr auto sizes(T const& /*unused*/) noexcept {return tuple<>{};} template constexpr auto sizes(const T(&array)[N]) noexcept { // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) for backwards compatibility @@ -328,15 +345,12 @@ constexpr auto base(T(&array)[N]) noexcept { // NOLINT(cppcoreguidelines-avoid- template constexpr auto base(T(*&array)[N]) noexcept {return base(*array);} // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) for backwards compatibility -template>> +template>> // NOLINT(modernize-use-constraints) TODO(correaa) constexpr auto base(T const* ptr) noexcept {return ptr;} -template>> +template>> // NOLINT(modernize-use-constraints) TODO(correaa) constexpr auto base(T* ptr) noexcept {return ptr;} -template && std::is_trivial_v, int> =0> -auto base(T& array) {return &array;} - template constexpr auto corigin(const T& value) {return &value;} @@ -348,7 +362,7 @@ template().extension())> inline auto has_extension_aux(... ) -> std::false_type; template struct has_extension : decltype(has_extension_aux(std::declval())) {}; // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg,cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay) -template::value>> +template::value>> // NOLINT(modernize-use-constraints) TODO(correaa) auto extension(Container const& cont) // TODO(correaa) consider "extent" ->decltype(multi::extension_t>(0, static_cast>(size(cont)))) { return multi::extension_t>(0, static_cast>(size(cont))); } @@ -365,7 +379,7 @@ inline auto has_extensions_aux(... ) -> std::false_type; template struct has_extensions : decltype(has_extensions_aux(std::declval())) {}; // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg,cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay) trick -template::value, int> =0> +template::value, int> =0> // NOLINT(modernize-use-constraints) TODO(correaa) for C++20 [[nodiscard]] constexpr auto extensions(T const& array) -> std::decay_\ t { return array.extensions(); } @@ -377,7 +391,7 @@ constexpr auto extensions_aux2(BoostMultiArray const& arr, std::index_sequence::value, int> =0> +template::value, int> =0> // NOLINT(modernize-use-constraints) TODO(correaa) in C++20 [[nodiscard]] auto extensions_of(T const& array) { if constexpr(std::is_convertible_v) { return boost::multi::extensions_t<0>{}; @@ -387,13 +401,20 @@ template::value, int> } } +template auto what() -> std::tuple = delete; +template auto what(Ts&&...) -> std::tuple = delete; // NOLINT(cppcoreguidelines-missing-std-forward) + +template +auto transposed(Arr2D&& arr) +->decltype(std::forward(arr).transposed()) { + return std::forward(arr).transposed(); } // template::value && !has_extensions::value, int> =0> // constexpr auto extensions(BoostMultiArray const& array) { // return extensions_aux2(array, std::make_index_sequence{}); // } -template::value /*&& !has_shape::value*/, int> =0> +template::value /*&& !has_shape::value*/, int> =0> // NOLINT(modernize-use-constraints) TODO(correaa) in C++20 constexpr auto extensions(T const& /*unused*/) -> multi::layout_t<0>::extensions_type {return {};} template @@ -437,12 +458,12 @@ inline auto has_layout_member_aux(... ) -> std::false_type; template struct has_layout_member : decltype(has_layout_member_aux(std::declval())) {}; // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg,cppcoreguidelines-pro-bounds-array-to-pointer-decay,hicpp-no-array-decay) -template{}> > +template{}> > // NOLINT(modernize-use-constraints) TODO(correaa) in C++20 auto layout(T const& array) ->decltype(array.layout()) { return array.layout(); } -template{}> > +template{}> > // NOLINT(modernize-use-constraints) TODO(correaa) in C++20 auto layout(T const& /*unused*/) -> layout_t<0> {return {};} template @@ -501,14 +522,6 @@ constexpr auto dimensionality(std::array, N> const& arr) -> boo return 1 + dimensionality(arr[0]); } -#if (__cplusplus < 201703L) -// this conflicts with std::size in nvcc 11 and c++17 -template -constexpr auto size(std::array const& /*arr*/) { - return multi::size_type{N}; -} -#endif - template constexpr auto extensions(std::array const& /*arr*/) { return multi::extensions_t<1>{multi::index_extension(0, N)}; diff --git a/external_codes/boost_multi/multi/pre-push b/external_codes/boost_multi/multi/pre-push index a8ac2d3273..86e9163c17 100755 --- a/external_codes/boost_multi/multi/pre-push +++ b/external_codes/boost_multi/multi/pre-push @@ -1,38 +1,79 @@ #!/bin/bash # -*-indent-tabs-mode:t;c-basic-offset:4;tab-width:4;autowrap:nil;-*- -# sudo apt install ccache clang clang-tidy cmake cppcheck g++ git lcov libblas-dev pkg-config libfftw3-dev libboost-test-dev libboost-timer-dev make ninja-build valgrind +# sudo dpkg --add-architecture i386 +# sudo apt install ccache clang clang-tidy cmake cppcheck g++ git iwyu lcov libblas-dev pkg-config libfftw3-dev libboost-test-dev libboost-timer-dev libopenblas-dev libtbb-dev make ninja-build valgrind libboost-test-dev:i386 libboost-timer-dev:i386 # sudo dnf install boost-devel blas-devel ccache clang clang-tools-extra cmake cppcheck fftw-devel git lcov libasan liblas-devel libubsan ninja-build valgrind -# install circle # mkdir -p $HOME/bin && wget https://www.circle-lang.org/linux/build_latest.tgz -P $HOME/tmp/ && tar -zxvf $HOME/tmp/build_latest.tgz --directory $HOME/bin/ && $HOME/bin/circle --version -# install nvc++ # ($ echo 'deb [trusted=yes] https://developer.download.nvidia.com/hpc-sdk/ubuntu/amd64 /' | sudo tee /etc/apt/sources.list.d/nvhpc.list) && sudo apt-get updatesudo apt-get update && sudo apt-get install nvhpc-22-7 -# # sudo yum-config-manager --add-repo https://developer.download.nvidia.com/hpc-sdk/rhel/nvhpc.repo && sudo yum install -y nvhpc-cuda-multi-23.1 +# install circle # mkdir -p $HOME/bin && wget https://www.circle-lang.org/linux/build_latest.tgz -P $HOME/tmp/ && tar zxvf $HOME/tmp/build_latest.tgz --directory $HOME/bin/ && $HOME/bin/circle --version +# install nvc++ +# on Ubuntu: +# curl https://developer.download.nvidia.com/hpc-sdk/ubuntu/DEB-GPG-KEY-NVIDIA-HPC-SDK | sudo gpg --dearmor -o /usr/share/keyrings/nvidia-hpcsdk-archive-keyring.gpg +# echo 'deb [signed-by=/usr/share/keyrings/nvidia-hpcsdk-archive-keyring.gpg] https://developer.download.nvidia.com/hpc-sdk/ubuntu/amd64 /' | sudo tee /etc/apt/sources.list.d/nvhpc.list +# sudo apt-get update -y +# sudo apt-get install -y nvhpc-24-7 +# on Fedora: +# sudo yum-config-manager --add-repo https://developer.download.nvidia.com/hpc-sdk/rhel/nvhpc.repo && sudo yum install -y nvhpc-cuda-multi-24.5 +# install oneAPI +# wget -O- https://apt.repos.intel.com/intel-gpg-keys/GPG-PUB-KEY-INTEL-SW-PRODUCTS.PUB | gpg --dearmor | sudo tee /usr/share/keyrings/oneapi-archive-keyring.gpg > /dev/null +# echo "deb [signed-by=/usr/share/keyrings/oneapi-archive-keyring.gpg] https://apt.repos.intel.com/oneapi all main" | sudo tee /etc/apt/sources.list.d/oneAPI.list +# sudo apt update +# sudo apt install intel-hpckit #CXX=g++-12 cmake --fresh .. -DENABLE_CUDA=1 -DCMAKE_CUDA_COMPILER=nvcc -DCMAKE_CUDA_HOST_COMPILER=g++-12 -DCMAKE_CUDA_ARCHITECTURES=61 export VALGRIND_EXE="valgrind --leak-check=full --track-origins=yes --show-leak-kinds=all --suppressions=.valgrind_suppressions --gen-suppressions=all --error-exitcode=1 " + export CMAKE_GENERATOR=Ninja + +export CMAKE_CUDA_COMPILER_LAUNCHER="ccache" export CMAKE_CXX_COMPILER_LAUNCHER="ccache" - (mkdir -p .build.g++.std23 && cd .build.g++.std23 && CXX=g++ cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_STANDARD=23 && cmake --build . && ctest -j 12 --output-on-failure) || exit 666 - (mkdir -p .build.clang++ && cd .build.clang++ && CXX=clang++ cmake .. -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_FLAGS="-Wfatal-errors" && cmake --build . && ctest -j 12 --output-on-failure) || exit 666 - (mkdir -p .build.circle && cd .build.circle && CXX="$HOME/bin/circle" cmake .. -GNinja -DCMAKE_BUILD_TYPE=Debug -DENABLE_CIRCLE=1 -DCMAKE_CXX_COMPILER_LAUNCHER="ccache" && cmake --build . && ctest -j 12 --output-on-failure) || exit 666 - (mkdir -p .build.clang++.tidy && cd .build.clang++.tidy && CXX=clang++ cmake .. -GNinja -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_CLANG_TIDY="clang-tidy" -DBOOST_MULTI_STANDALONE=1 -DBUILD_TESTING=0 -DCMAKE_CXX_FLAGS="-D_GLIBCXX_DEBUG=0 -D_LIBCPP_DEBUG=0 -Wfatal-errors" && cmake --build . && ASAN_OPTIONS="new_delete_type_mismatch=0" ctest -j 12 --output-on-failure) || exit 666 -#(mkdir -p .build.g++.m32 && cd .build.g++.m32 && CXX=g++ CXXFLAGS="-m32" cmake .. -GNinja -DCMAKE_BUILD_TYPE=Release && cmake --build . --verbose && ctest -j 12 --output-on-failure) || exit 666 - (mkdir -p .build.clang++.m32 && cd .build.clang++.m32 && CXX=clang++ CXXFLAGS="-m32" cmake .. -GNinja -DCMAKE_BUILD_TYPE=Release && cmake --build . --verbose && ctest -j 12 --output-on-failure) || exit 666 - (mkdir -p .build.clang++-17 && cd .build.clang++-17 && CXX=clang++-17 cmake .. -GNinja -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_FLAGS="-Wfatal-errors" -DCMAKE_CXX_COMPILER_LAUNCHER="ccache" && cmake --build . && ctest -j 12 --output-on-failure) || exit 666 -#(mkdir -p .build.icpc && cd .build.icpc && CXX=/home/correaa/intel/oneapi/compiler/latest/linux/bin/intel64/icpc cmake .. -GNinja DCMAKE_BUILD_TYPE=Release && cmake --build . && ctest -j 12 --output-on-failure) || exit 666 - (mkdir -p .build.icpx && cd .build.icpx && CXX=/opt/intel/oneapi/compiler/latest/bin/icpx cmake .. -GNinja -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_COMPILER_LAUNCHER="ccache" && cmake --build . && ctest -j 12 --output-on-failure) || exit 666 - (mkdir -p .build.nvc++ && cd .build.nvc++ && CXX=/opt/nvidia/hpc_sdk/Linux_x86_64/2024/compilers/bin/nvc++ cmake .. -GNinja -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_FLAGS="-stdpar=multicore" -DCMAKE_CXX_COMPILER_LAUNCHER="ccache" && cmake --build . && ctest -j 12 --output-on-failure) || exit 666 -#(mkdir -p .build.cunvc++ && cd .build.cunvc++ && CXX=/opt/nvidia/hpc_sdk/Linux_x86_64/2024/compilers/bin/nvc++ cmake .. -GNinja -DCMAKE_BUILD_TYPE=Debug -DENABLE_CUDA=1 -DCMAKE_CUDA_COMPILER=/opt/nvidia/hpc_sdk/Linux_x86_64/2024/compilers/bin/nvc++ -DCMAKE_CUDA_ARCHITECTURES=75 && cmake --build . && ctest -j 12 --output-on-failure) || exit 666 - (mkdir -p .build.nvcc && cd .build.nvcc && CXX=g++ cmake .. -GNinja -DCMAKE_BUILD_TYPE=Release -DENABLE_CUDA=1 -DCMAKE_CUDA_COMPILER=nvcc -DCMAKE_CUDA_HOST_COMPILER=g++-12 -DCMAKE_CXX_COMPILER_LAUNCHER="ccache" -DCMAKE_CUDA_COMPILER_LAUNCHER="ccache" && cmake --build . --parallel 12 --verbose && ctest -j 12 --output-on-failure) || exit 666 - (mkdir -p .build.culang && cd .build.culang && cmake .. -GNinja -DCMAKE_BUILD_TYPE=Release -DENABLE_CUDA=1 -DCMAKE_CUDA_COMPILER=clang++-17 -DCMAKE_CXX_COMPILER=clang++-17 -DCMAKE_CUDA_ARCHITECTURES=75 && cmake --build . --verbose --parallel 4 && ctest -j 1 --output-on-failure) || exit 666 - (mkdir -p .build.clang++.std20 && cd .build.clang++.std20 && CXX=clang++ cmake .. -GNinja -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_STANDARD=20 -DCMAKE_CXX_FLAGS="-Wfatal-errors" -DCMAKE_CXX_COMPILER_LAUNCHER="ccache" && cmake --build . && ctest -j 12 --output-on-failure) || exit 666 - (mkdir -p .build.g++.anlys-std23-memchk && cd .build.g++.anlys-std23-memchk && CXX=g++ cmake .. -GNinja -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_STANDARD=23 -DBLA_VENDOR=OpenBLAS `#-DCMAKE_CXX_INCLUDE_WHAT_YOU_USE="iwyu"` -DCMAKE_CXX_FLAGS="-fanalyzer -Wno-analyzer-null-dereference -Wno-analyzer-possible-null-dereference -Wno-analyzer-malloc-leak -Wno-analyzer-use-of-uninitialized-value -Wno-analyzer-use-after-free" -DCMAKE_CXX_COMPILER_LAUNCHER="ccache" && cmake --build . && ctest -j 12 --output-on-failure -T memcheck) || exit 666 -#(mkdir -p .build.clang++.tidy && cd .build.clang++.tidy && CXX=clang++ CXXFLAGS="-D_LIBCPP_ENABLE_DEBUG_MODE=1 -stdlib=libc++" cmake .. -GNinja -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_CLANG_TIDY="clang-tidy" -DCMAKE_CXX_FLAGS="-D_GLIBCXX_DEBUG=1 -D_LIBCPP_DEBUG=1 -Wfatal-errors" && cmake --build . && ASAN_OPTIONS="new_delete_type_mismatch=0" ctest -j 12 --output-on-failure) || exit 666 -#(mkdir -p .build.hip && cd .build.hip && cmake .. -GNinja -DCMAKE_BUILD_TYPE=Release -DBOOST_MULTI_STANDALONE=1 -DBUILD_TESTING=0 -DENABLE_HIP=1 -DCMAKE_HIP_ARCHITECTURES=gfx90a && cmake --build . ) || exit 666 - (mkdir -p .build.g++-.check-cov && cd .build.g++-.check-cov && CXX=g++ cmake .. -GNinja -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_CPPCHECK="cppcheck;--enable=all;--suppress=missingIncludeSystem;--inline-suppr;--std=c++17;--check-config;--error-exitcode=1" -DCMAKE_CXX_FLAGS="-D_GLIBCXX_DEBUG=1 -Wfatal-errors --coverage -lgcov -fno-inline -fno-inline-small-functions -fno-default-inline" -DCMAKE_EXE_LINKER_FLAGS="-lgcov --coverage" && cmake --build . && ASAN_OPTIONS="new_delete_type_mismatch=0" ctest -j 12 --output-on-failure -T Test `# && lcov --directory . --capture --output-file coverage.info && lcov --remove coverage.info '/usr/*' --output-file coverage.info && lcov --list coverage.info && genhtml coverage.info`) || exit 666 - (mkdir -p .build.g++-release && cd .build.g++-release && CXX=g++ cmake .. -GNinja -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_COMPILER_LAUNCHER="ccache" && cmake --build . && ctest -j 1 --output-on-failure -T Test) || exit 666 +export CMAKE_EXE_LINKER_FLAGS="-fuse-ld=mold" +export CMAKE_SHARED_LINKER_FLAGS="-fuse-ld=mold" + +if [[ $(uname -m) != 'arm64' ]]; then + +export VALGRIND_EXE="valgrind --trace-children=yes --leak-check=full --track-origins=yes --show-leak-kinds=all --suppressions=.valgrind_suppressions --gen-suppressions=all --error-exitcode=1 " + + (mkdir -p .build.g++ && cd .build.g++ && CXX=g++ cmake .. -DCMAKE_BUILD_TYPE=Deub -DCMAKE_EXPORT_COMPILE_COMMANDS=ON && cmake --build . && ctest --parallel 2 --output-on-failure) || exit 666 + (mkdir -p .build.clang++-rel && cd .build.clang++-rel && CXX=clang++ cmake .. -DCMAKE_BUILD_TYPE=Release && cmake --build . && ctest --parallel 2 --output-on-failure) || exit 666 + (mkdir -p .build.clang++ && cd .build.clang++ && CXX=clang++ cmake .. -DCMAKE_BUILD_TYPE=Debug && cmake --build . && ctest --parallel 2 --output-on-failure) || exit 666 + (mkdir -p .build.g++-rel && cd .build.g++-rel && CXX=g++ cmake .. -DCMAKE_BUILD_TYPE=Release && cmake --build . && ctest --parallel --output-on-failure --rerun-failed) || exit 666 + (mkdir -p .build.nvcc && cd .build.nvcc && cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_STANDARD=20 -DENABLE_CUDA=1 -DCMAKE_CUDA_COMPILER=nvcc -DCMAKE_CUDA_HOST_COMPILER=g++ -DCMAKE_CXX_COMPILER=g++ -DCMAKE_CUDA_ARCHITECTURES=75 && cmake --build . && ctest --parallel --output-on-failure --rerun-failed) || exit 666 + (mkdir -p .build.circle && cd .build.circle && CXX="$HOME/bin/circle" cmake .. -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_EXTENSIONS=OFF -DCMAKE_CXX_STANDARD=20 -DDISABLE_MPI=1 -DENABLE_CIRCLE=1 -DCMAKE_THREAD_LIBS_INIT="-lpthread" && cmake --build . && ctest --parallel --output-on-failure --rerun-failed) || exit 666 +#(mkdir -p .build.g++.m32 && cd .build.g++.m32 && CXX=g++ CXXFLAGS="-m32" cmake .. -DCMAKE_BUILD_TYPE=Debug && cmake --build . && ctest --parallel --output-on-failure --rerun-failed) || exit 666 + (mkdir -p .build.icpx && cd .build.icpx && CXX=/opt/intel/oneapi/compiler/latest/bin/icpx cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_STANDARD=23 && cmake --build . && ctest --parallel --output-on-failure --rerun-failed) || exit 666 + (mkdir -p .build.nvc++ && cd .build.nvc++ && CXX=/opt/nvidia/hpc_sdk/Linux_x86_64/2024/compilers/bin/nvc++ cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_FLAGS="-stdpar=multicore" -DBLA_PREFER_PKGCONFIG=ON -DCMAKE_C_COMPILER=/opt/nvidia/hpc_sdk/Linux_x86_64/2024/compilers/bin/nvc -DCMAKE_CXX_COMPILER=/opt/nvidia/hpc_sdk/Linux_x86_64/2024/compilers/bin/nvc++ -DCMAKE_Fortran_COMPILER=/opt/nvidia/hpc_sdk/Linux_x86_64/2024/compilers/bin/nvfortran && cmake --build . && ctest --parallel --output-on-failure --rerun-failed) || exit 666 + (mkdir -p .build.culang && cd .build.culang && cmake .. -DCMAKE_BUILD_TYPE=Release -DENABLE_CUDA=1 -DCMAKE_CUDA_COMPILER=clang++ -DCMAKE_CUDA_HOST_COMPILER=clang++ -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_CUDA_ARCHITECTURES=75 && cmake --build . && ctest --parallel --output-on-failure --rerun-failed) || exit 666 + (mkdir -p .build.g++.plus && cd .build.g++.plus && CXX=g++ cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_STANDARD=23 -DBLA_VENDOR=OpenBLAS `#-DCMAKE_CXX_CPPCHECK="cppcheck;--enable=all;--suppress=missingIncludeSystem;--inline-suppr;--std=c++17;--checkers-report=cppcheck.report;--error-exitcode=1"` -DCMAKE_CXX_FLAGS="-D_GLIBCXX_DEBUG=1" -DCMAKE_CXX_FLAGS="-fimplicit-constexpr -fanalyzer -Wno-analyzer-null-dereference -Wno-analyzer-possible-null-dereference -Wno-analyzer-malloc-leak -Wno-analyzer-use-of-uninitialized-value -Wno-analyzer-use-after-free" && cmake --build . && ctest --parallel --output-on-failure -T memcheck) || exit 666 + (mkdir -p .build.clang++.plus && cd .build.clang++.plus && CXX=clang++ cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_STANDARD=20 -DBLA_VENDOR=Generic -DCMAKE_CXX_CLANG_TIDY="clang-tidy" `#-DCMAKE_CXX_INCLUDE_WHAT_YOU_USE="iwyu;-Xiwyu;--mapping_file=/home/correaa/boost-multi/.iwyu-test.imp;-Xiwyu;--no_fwd_decls"` && cmake --build . && ASAN_OPTIONS="new_delete_type_mismatch=0" ctest --parallel --output-on-failure) || exit 666 +#(mkdir -p .build.hip && cd .build.hip && CXX=clang++ cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_HIP_COMPILER=/opt/rocm/llvm/bin/clang++ -DCMAKE_CXX_FLAGS="-DMULTI_USE_HIP" -DCMAKE_HIP_FLAGS="-DMULTI_USE_HIP" -DENABLE_HIP=1 -DCMAKE_HIP_ARCHITECTURES=gfx90a && cmake --build . ) || exit 666 +#(mkdir -p .build.g++-.cov && cd .build.g++-.cov && CXX=g++ cmake .. -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_FLAGS="--coverage -lgcov -fno-inline -fno-inline-small-functions -fno-default-inline" -DCMAKE_EXE_LINKER_FLAGS="-lgcov --coverage" && cmake --build . && ASAN_OPTIONS="new_delete_type_mismatch=0" ctest -j 12 --output-on-failure -T Test `# && lcov --directory . --capture --output-file coverage.info && lcov --remove coverage.info '/usr/*' --output-file coverage.info && lcov --list coverage.info && genhtml coverage.info`) || exit 666 + +# find ./detail/ -name "*.hpp" \( -exec iwyu -std=c++17 -Xiwyu --mapping_file=/usr/share/include-what-you-use/stl.c.headers.imp -Xiwyu --mapping_file=$HOME/boost-multi/.iwyu-test.imp -Xiwyu --error=0 -Xiwyu --max_line_length=200 -Xiwyu --quoted_includes_first -Xiwyu --cxx17ns {} -I$HOME/boost-multi/include/ \; -o -quit \) + +## sudo setfacl --modify user:correaa:rw /var/run/docker.sock +# gitlab-runner exec docker rocm + +# to recover from GPU error (e.g. after hibernating) +# fuser --kill /dev/nvidia-uvm +# sudo modprobe -r nvidia_uvm +# sudo modprobe nvidia_uvm +else +export CMAKE_GENERATOR=Ninja +# export CMAKE_CXX_COMPILER_LAUNCHER="ccache" + + (mkdir -p .build.g++-14 && cd .build.g++-14 && CXX=g++-14 cmake .. -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_STANDARD=23 && cmake --build . && ctest -j 12 --output-on-failure) || exit 666 + (mkdir -p .build.c++.std23 && cd .build.c++.std23 && CXX=c++ CXXFLAGS="-fexperimental-library" cmake .. -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_STANDARD=23 && cmake --build . && ctest -j 12 --output-on-failure) || exit 666 + (mkdir -p .build.c++.asan && cd .build.c++.asan && CXX=c++ cmake .. -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_FLAGS="-D_LIBCPP_DEBUG=1 -fsanitize=undefined -fsanitize=pointer-overflow -fsanitize-trap=pointer-overflow -fsanitize=address -fno-omit-frame-pointer" && cmake --build . && ASAN_OPTIONS="new_delete_type_mismatch=1" ctest -j 12 --output-on-failure) || exit 666 + (mkdir -p .build.c++.m32 && cd .build.c++.m32 && CXX=c++ cmake .. -DCMAKE_BUILD_TYPE=Debug && cmake --build . && ctest -j 12 --output-on-failure) || exit 666 + (mkdir -p .build.c++.tidy && cd .build.c++.tidy && CXX=c++ cmake .. -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_CLANG_TIDY=clang-tidy -DCMAKE_CXX_CPPLINT="cpplint;--quiet" -DCMAKE_CXX_CPPCHECK="cppcheck;--enable=all;--suppress=missingIncludeSystem;--checkers-report=cppcheck.report;--suppress=checkersReport;--inline-suppr;--std=c++17;--error-exitcode=1" -DCMAKE_CXX_INCLUDE_WHAT_YOU_USE="include-what-you-use;-Xiwyu;--mapping_file=/Users/correatedesco1/boost-multi/.iwyu-test.imp;-Xiwyu;--no_fwd_decls;-Xiwyu;--error" && cmake --build . --verbose --parallel && ctest -j 12 --output-on-failure) || exit 666 #(mkdir -p .build.clang++.iwyu && cd .build.clang++.iwyu && CXX=clang++ cmake .. -DCMAKE_CXX_INCLUDE_WHAT_YOU_USE="iwyu" && make -j 10 && ctest -j 12 --output-on-failure) || exit -# cmake .. -GNinja -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_INCLUDE_WHAT_YOU_USE="include-what-you-use;-Xiwyu;--mapping_file=/Users/correatedesco1/boost-multi/boost-test.imp;-Xiwyu;--mapping_file=/opt/homebrew/Cellar/include-what-you-use/0.22/libexec/share/include-what-you-use/boost-all.imp" -DCMAKE_VERIFY_INTERFACE_HEADER_SETS=ON # TODO(correaa) make cppcheck work for all the code #(find . -name '*.hpp' -exec cppcheck --enable=all --inline-suppr --suppress=unmatchedSuppression:{} --suppress=syntaxError --suppress=missingInclude --suppress=missingIncludeSystem --suppress=preprocessorErrorDirective --suppress=syntaxError --suppress=unusedFunction --suppress=arithOperationsOnVoidPointer --suppress=sizeofDereferencedVoidPointer -D__align__ -DCUDARTAPI --language=c++ --std=c++17 --error-exitcode=666 --suppress=unmatchedSuppression {} \;) || exit +fi + +# fuser --kill /dev/nvidia-uvm +# while fuser --silent /dev/nvidia-uvm; do sleep 1; done +# echo "$0 $@: reload nvidia_uvm" +# modprobe -r nvidia_uvm && modprobe nvidia_uvm diff --git a/external_codes/boost_multi/multi/pre-push.macos b/external_codes/boost_multi/multi/pre-push.macos deleted file mode 100755 index 745de0d8b7..0000000000 --- a/external_codes/boost_multi/multi/pre-push.macos +++ /dev/null @@ -1,22 +0,0 @@ -#!/bin/bash -# -*-indent-tabs-mode:t;c-basic-offset:4;tab-width:4;autowrap:nil;-*- -# sudo apt install ccache clang clang-tidy cmake cppcheck g++ git lcov libblas-dev pkg-config libfftw3-dev libboost-test-dev libboost-timer-dev make ninja-build valgrind -# sudo dnf install boost-devel blas-devel ccache clang clang-tools-extra cmake cppcheck fftw-devel git lcov libasan liblas-devel libubsan ninja-build valgrind -# install circle # mkdir -p $HOME/bin && wget https://www.circle-lang.org/linux/build_latest.tgz -P $HOME/tmp/ && tar -zxvf $HOME/tmp/build_latest.tgz --directory $HOME/bin/ && $HOME/bin/circle --version -# install nvc++ # ($ echo 'deb [trusted=yes] https://developer.download.nvidia.com/hpc-sdk/ubuntu/amd64 /' | sudo tee /etc/apt/sources.list.d/nvhpc.list) && sudo apt-get updatesudo apt-get update && sudo apt-get install nvhpc-22-7 -# # sudo yum-config-manager --add-repo https://developer.download.nvidia.com/hpc-sdk/rhel/nvhpc.repo && sudo yum install -y nvhpc-cuda-multi-23.1 - -#CXX=g++-12 cmake --fresh .. -DENABLE_CUDA=1 -DCMAKE_CUDA_COMPILER=nvcc -DCMAKE_CUDA_HOST_COMPILER=g++-12 -DCMAKE_CUDA_ARCHITECTURES=61 - -export CMAKE_GENERATOR=Ninja -export CMAKE_CXX_COMPILER_LAUNCHER="ccache" - - (mkdir -p .build.c++.std23 && cd .build.c++.std23 && CXX=c++ cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_STANDARD=23 && cmake --build . && ctest -j 12 --output-on-failure) || exit 666 - (mkdir -p .build.c++.asan && cd .build.c++.asan && CXX=c++ cmake .. -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_FLAGS="-D_LIBCPP_DEBUG=1 -fsanitize=address -fno-omit-frame-pointer" && cmake --build . && ASAN_OPTIONS="new_delete_type_mismatch=1" ctest -j 12 --output-on-failure) || exit 666 - (mkdir -p .build.c++.m32 && cd .build.c++.m32 && CXX=c++ cmake .. -DCMAKE_BUILD_TYPE=Release && cmake --build . && ctest -j 12 --output-on-failure) || exit 666 - (mkdir -p .build.z++ && cd .build.z++ && CXX="zig c++" cmake .. -DCMAKE_BUILD_TYPE=Release && cmake --build . && ctest -j 12 --output-on-failure) || exit 666 - (mkdir -p .build.c++.tidy && cd .build.c++.tidy && CXX=c++ cmake .. -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_CLANG_TIDY="clang-tidy" -DCMAKE_CXX_CPPLINT="cpplint;--quiet" -DCMAKE_CXX_CPPCHECK="cppcheck;--enable=all;--suppress=missingIncludeSystem;--suppress=checkersReport;--inline-suppr;--std=c++17;--error-exitcode=1" && cmake --build . && ctest -j 12 --output-on-failure) || exit 666 - -#(mkdir -p .build.clang++.iwyu && cd .build.clang++.iwyu && CXX=clang++ cmake .. -DCMAKE_CXX_INCLUDE_WHAT_YOU_USE="iwyu" && make -j 10 && ctest -j 12 --output-on-failure) || exit -# TODO(correaa) make cppcheck work for all the code -#(find . -name '*.hpp' -exec cppcheck --enable=all --inline-suppr --suppress=unmatchedSuppression:{} --suppress=syntaxError --suppress=missingInclude --suppress=missingIncludeSystem --suppress=preprocessorErrorDirective --suppress=syntaxError --suppress=unusedFunction --suppress=arithOperationsOnVoidPointer --suppress=sizeofDereferencedVoidPointer -D__align__ -DCUDARTAPI --language=c++ --std=c++17 --error-exitcode=666 --suppress=unmatchedSuppression {} \;) || exit diff --git a/external_codes/boost_multi/multi/test/CMakeLists.txt b/external_codes/boost_multi/multi/test/CMakeLists.txt index 57bd1a7ef0..e69b75d8ee 100644 --- a/external_codes/boost_multi/multi/test/CMakeLists.txt +++ b/external_codes/boost_multi/multi/test/CMakeLists.txt @@ -3,7 +3,7 @@ # Distributed under the Boost Software License, Version 1.0. # See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt -cmake_minimum_required(VERSION 3.16) +cmake_minimum_required(VERSION 3.16) # 3.16 for precompiled_headers if (DEFINED BOOST_SUPERPROJECT_VERSION AND NOT DEFINED BOOST_MULTI_STANDALONE AND BUILD_TESTING) @@ -11,7 +11,7 @@ if (DEFINED BOOST_SUPERPROJECT_VERSION AND NOT DEFINED BOOST_MULTI_STANDALONE AN if(HAVE_BOOST_TEST) - boost_test_jamfile(FILE Jamfile LINK_LIBRARIES Boost::multi Boost::unit_test_framework Boost::multi_array Boost::iterator) + boost_test_jamfile(FILE Jamfile LINK_LIBRARIES Boost::multi Boost::multi_array Boost::iterator) endif() @@ -22,7 +22,7 @@ else() set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) - find_package(Boost COMPONENTS unit_test_framework) # tests require Boost.Test `sudo apt install libboost-test-dev` + find_package(Boost) # COMPONENTS boost unit_test_framework) # tests require Boost.Test `sudo apt install libboost-test-dev` if(ENABLE_CUDA) enable_language(CUDA) @@ -39,38 +39,45 @@ else() set(WARNS $<$: - -Xcompiler=-Werror,-Wall,-Wextra,-Wcast-align,-Wcast-qual,-Wdouble-promotion,-Wduplicated-branches,-Wduplicated-cond,-Wformat-truncation,-Wformat=2,-Wlogical-op,-Wmisleading-indentation,-Wno-missing-include-dirs,-Wnon-virtual-dtor,-Wno-missing-declarations,-Wnon-virtual-dtor,-Wnull-dereference,-Woverloaded-virtual,-Wpointer-arith,-Wno-redundant-decls,-Wno-shadow,-Wno-switch-enum,-Wno-unknown-pragmas,-Wtrampolines,-Wuninitialized,-Wunused,-Wunused-but-set-variable,-Wunused-result,-Wno-zero-as-null-pointer-constant - #--expt-relaxed-constexpr --extended-lambda - --Werror=cross-execution-space-call -Xcudafe=--display_error_number -Xcudafe=--diag_error=incompatible_assignment_operands -Xcudafe=--diag_error=returning_ptr_to_local_variable -Xcudafe=--diag_error=subscript_out_of_range -Xcudafe=--diag_error=used_before_set -Xcudafe=--diag_error=undefined_preproc_id -Xcudafe=--diag_error=implicit_func_decl -Xcudafe=--diag_error=implicit_return_from_non_void_function -Xcudafe=--diag_error=missing_type_specifier + -Xcompiler=-Werror,-Wall,-Wextra,-Wcast-align,-Wcast-qual,-Wdouble-promotion,-Wduplicated-branches,-Wduplicated-cond,-Wformat-truncation,-Wformat=2,-Wlogical-op,-Wmisleading-indentation,-Wno-missing-include-dirs,-Wnon-virtual-dtor,-Wno-missing-declarations,-Wnon-virtual-dtor,-Wnull-dereference,-Woverloaded-virtual,-Wpointer-arith,-Wno-redundant-decls,-Wno-shadow,-Wno-switch-enum,-Wno-unknown-pragmas,-Wtrampolines,-Wuninitialized,-Wunused,-Wunused-but-set-variable,-Wunused-result,-Wno-zero-as-null-pointer-constant + #--Werror=cross-execution-space-call + --Werror ext-lambda-captures-this + --use_fast_math + --extra-device-vectorization + --restrict + -Xcudafe=--display_error_number -Xcudafe=--diag_error=incompatible_assignment_operands -Xcudafe=--diag_error=returning_ptr_to_local_variable -Xcudafe=--diag_error=subscript_out_of_range -Xcudafe=--diag_error=used_before_set -Xcudafe=--diag_error=undefined_preproc_id -Xcudafe=--diag_error=implicit_func_decl -Xcudafe=--diag_error=implicit_return_from_non_void_function -Xcudafe=--diag_error=missing_type_specifier > - $<$,$>,$>>: -Werror # -Wno-unknown-warning (activates -Wunknown-pragmas) - # -WNSObject-attribute # (gcc 12, not in 11) + $<$,$>,$>>: -Werror + $<$,12>:-ftrivial-auto-var-init=pattern> + # -WNSObject-attribute # (gcc 12, not in 11) # -Wabi=13 -Wabi-tag # (maybe important when linking with very old libraries) -Waddress - #-Waddress-of-packed-member # (gcc 11, not in gcc 8) + $<$,11>:-Waddress-of-packed-member> -Wno-aggregate-return # (disallow return classes or structs, seems a C-compatibility warning) -Waggressive-loop-optimizations -Waligned-new=all # (gcc 12, not in 11) # -Walloc-size-larger-than= # (gcc 12, not in 11) - -Walloc-zero # -Walloc-size-larger-than= + -Walloc-zero -Walloca # -Walloca-larger-than= - # -Warith-conversion # (gcc 11, not in gcc 9) + $<$,11>:-Warith-conversion> -Warray-bounds # -Warray-bounds=<0,2> - # -Warray-compare # (gcc 12, not in gcc 9) + $<$,12>:-Warray-compare> # -Warray-parameter #=<0,2> # (gcc 11, not in gcc 10) - #-Wattribute-alias #=<0,2> # (gcc 12, not in 11, not in 7) - #-Wattribute-warning # (gcc 9, not in 8) + # -Wattribute-alias #=<0,2> # (gcc 12, not in 11, not in 7) + $<$,9>:-Wattribute-warning> -Wattributes -Wbool-compare -Wbool-operation - # -Wbidi-chars -Wbidi-chars=any # (gcc 12, not in 11) + $<$,12>:-Wbidi-chars -Wbidi-chars=any> -Wbuiltin-declaration-mismatch -Wbuiltin-macro-redefined #-Wc++-compat -Wc++0x-compat -Wc++11-compat -Wc++14-compat -Wc++17-compat - # -Wc++17-extensions # (gcc 12, not in 9) + $<$,12>:-Wc++17-extensions> -Wc++1z-compat - # -Wc++20-compat -Wc++20-extensions -Wc++23-extensions -Wc++2a-compat # (gcc 11, not in gcc 9) + $<$,11>:-Wc++20-compat> + $<$,12>:-Wc++20-extensions -Wc++23-extensions> + $<$,11>:-Wc++2a-compat> #-Wcannot-profile # (gcc 9, not in gcc 8) - #-Wcast-align=strict -Wcast-function-type # (gcc 8, not in gcc 7) + $<$,8>:-Wcast-align=strict -Wcast-function-type> # (gcc 8, not in gcc 7) -Wcast-qual #-Wcatch-value #=<0, 3> # (gcc 8, not in gcc 7) -Wchar-subscripts @@ -82,7 +89,7 @@ else() -Wconditionally-supported -Wconversion -Wconversion-null -Wcoverage-mismatch -Wcpp - # -Wctad-maybe-unsupported # (gcc 12, not in 9) + $<$,12>:-Wctad-maybe-unsupported> -Wctor-dtor-privacy -Wdangling-else # -Wdangling-pointer # (gcc 12, not in 11) @@ -113,8 +120,8 @@ else() -Wframe-address # -Wframe-larger-than= -Wfree-nonheap-object -Whsa # -Wif-not-aligned # (gcc 8, not in 7) - -Wignored-attributes # -Wignored-qualifiers - -Wno-ignored-qualifiers + -Wignored-attributes + -Wignored-qualifiers -Wimplicit-fallthrough #=3 # -Wimplicit-fallthrough=<0,5> # -Winaccessible-base # (gcc 12, not in 11) # -Winfinite-recursion # (gcc 12, not in 9) @@ -149,6 +156,7 @@ else() -Wnon-template-friend -Wnon-virtual-dtor -Wnonnull -Wnonnull-compare -Wnormalized #=nfc -Wnormalized=[none|id|nfc|nfkc] + # -Wnrvo # (not in gcc 12) -Wnull-dereference -Wodr -Wold-style-cast # TODO(correaa) fix this @@ -186,7 +194,7 @@ else() -Wstrict-aliasing #=3 # -Wstrict-aliasing=<0,3> -Wstrict-null-sentinel #=1 -Wstrict-overflow=<0,5> -Wstrict-overflow=2 - # -Wstrict-overflow=3 # not compatible with Boost.Test + # -Wstrict-overflow=3 # incompatible with index_range operator- # -Wstrict-overflow=4 # not compatible with stl heap # -Wstrict-overflow=5 # not compatible with Boost.Test # -Wstring-compare # (gcc 11, not in 9) @@ -200,7 +208,9 @@ else() -Wsuggest-attribute=noreturn # -Wsuggest-attribute=pure # (false positive in gcc 8.5.0 RedHat) -Wsuggest-final-methods -Wsuggest-final-types -Wsuggest-override # (gcc 12, not in gcc 11) - -Wswitch -Wswitch-bool -Wswitch-default -Wswitch-enum + -Wswitch -Wswitch-bool + -Wno-switch-default + -Wswitch-enum # -Wswitch-outside-range # (gcc 11, not in gcc 9) -Wswitch-unreachable -Wsync-nand -Wsynth @@ -230,7 +240,7 @@ else() -Wzero-as-null-pointer-constant # -Wzero-length-bounds # (gcc 12, not in 11) > - $<$,$,$>:-Werror -Wall -Wpedantic -Wextra + $<$,$,$>:-Werror -Wall -Wpedantic -Wextra -Wno-error=\#warnings # -Wno-\#warnings disable this working for a bug in rocm ~5.6 -WCFString-literal -WCL4 @@ -346,6 +356,7 @@ else() -Wcovered-switch-default -Wcpp -Wcstring-format-directive + $<$,18>:-Wctad-maybe-unsupported> -Wctor-dtor-privacy # -Wctu # (not in clang 7) -Wcuda-compat @@ -389,7 +400,7 @@ else() # -Wdeprecated-volatile (clang 11, not in clang 9) -Wdeprecated-writable-strings -Wdirect-ivar-access - # -Wdisabled-macro-expansion (Boost.Test) + -Wdisabled-macro-expansion -Wdisabled-optimization -Wdiscard-qual -Wdistributed-object-modifiers @@ -434,8 +445,7 @@ else() # -Wfixed-point-overflow (clang 11, not in clang 9) -Wflag-enum -Wflexible-array-extensions - -Wfloat-conversion -Wfloat-equal - -Wfloat-overflow-conversion -Wfloat-zero-conversion + -Wfloat-conversion -Wfloat-equal -Wfloat-overflow-conversion -Wfloat-zero-conversion -Wfor-loop-analysis -Wformat -Wformat-extra-args # -Wformat-insufficient-args (clang 13, not in clang 11) @@ -453,7 +463,7 @@ else() # -Wfuture-attribute-extensions (clang 15, not in clang 13) # -Wfuture-compat # -Wgcc-compat - # -Wglobal-constructors (Boost.Test) + -Wglobal-constructors # -Wglobal-isel (clang 11, not in clang 9) -Wgnu -Wgnu-alignof-expression -Wgnu-anonymous-struct -Wgnu-array-member-paren-init -Wgnu-auto-type -Wgnu-binary-literal -Wgnu-case-range -Wgnu-complex-integer -Wgnu-compound-literal-initializer -Wgnu-conditional-omitted-operand -Wgnu-designator -Wgnu-empty-initializer -Wgnu-empty-struct -Wgnu-flexible-array-initializer -Wgnu-flexible-array-union-member -Wgnu-folding-constant -Wgnu-imaginary-constant -Wgnu-include-next # -Wgnu-inline-cpp-without-extern (clang 11, not in clang 9) @@ -471,7 +481,7 @@ else() #-Wignored-pragma-intrinsic #-Wignored-pragma-optimize #-Wignored-pragmas (other compilers need pragmas) - -Wno-ignored-qualifiers # turns out that returning const types is not really ignored by the compiler and prevents certain misleading syntaxes + -Wignored-qualifiers # turns out that returning const types is not really ignored by the compiler and prevents certain misleading syntaxes # -Wignored-reference-qualifiers (clang 15, not in clang 13) -Wimplicit -Wimplicit-atomic-properties # -Wimplicit-const-int-float-conversion (clang 11, not in clang 9) @@ -509,7 +519,7 @@ else() -Wkeyword-compat -Wkeyword-macro -Wknr-promoted-parameter -Wlanguage-extension-token - -Wlarge-by-value-copy + -Wno-large-by-value-copy # subarray references can be large -Wliblto # -Wlinker-warnings (clang 15, not in clang 13) -Wliteral-conversion -Wliteral-range @@ -595,10 +605,13 @@ else() -Woverlength-strings -Woverloaded-shift-op-parentheses -Woverloaded-virtual # -Woverride-init (not in clang 7) - -Woverride-module -Woverriding-method-mismatch -Woverriding-t-option + -Woverride-module -Woverriding-method-mismatch + # -Woverriding-option (not in clang 14) + # -Woverriding-t-option (not in clang 18) -Wpacked # -Wpadded (ask for aligment) - -Wparentheses -Wparentheses-equality + -Wparentheses + -Wparentheses-equality -Wpartial-availability # -Rpass -Rpass-analysis -Wpass-failed @@ -707,7 +720,9 @@ else() -Wsuper-class-method-mismatch -Wsuspicious-bzero -Wsuspicious-memaccess # -Wswift-name-attribute (clang 13, not in clang 11) - -Wswitch -Wswitch-bool -Wswitch-default -Wswitch-enum + -Wswitch -Wswitch-bool + -Wno-switch-default + -Wswitch-enum -Wsync-fetch-and-nand-semantics-changed -Wsynth # -Wtarget-clones-mixed-specifiers (clang 15, not in clang 13) @@ -756,7 +771,7 @@ else() -Wunreachable-code -Wunreachable-code-aggressive -Wunreachable-code-break # -Wunreachable-code-fallthrough (clang 15, not in clang 13) -Wunreachable-code-loop-increment -Wunreachable-code-return - -Wunsafe-buffer-usage + $<$,15>:-Wunsafe-buffer-usage> -Wunsequenced # -Wunsupported-abi (clang 15, not in clang 13) -Wunsupported-abs -Wunsupported-availability-guard -Wunsupported-cb -Wunsupported-dll-base-class-template @@ -766,7 +781,7 @@ else() -Wunused -Wunused-argument # -Wunused-but-set-parameter -Wunused-but-set-variable (clang 13, not in clang 11) -Wunused-command-line-argument -Wunused-comparison -Wunused-const-variable -Wunused-exception-parameter -Wunused-function -Wunused-getter-return-value -Wunused-label -Wunused-lambda-capture -Wunused-local-typedef -Wunused-local-typedefs -Wunused-macros -Wunused-member-function -Wunused-parameter -Wunused-private-field -Wunused-property-ivar -Wunused-result -Wunused-template -Wunused-value -Wunused-variable -Wunused-volatile-lvalue - # -Wused-but-marked-unused (Boost.Test) + -Wused-but-marked-unused -Wuser-defined-literals -Wuser-defined-warnings -Wvarargs -Wvariadic-macros @@ -838,9 +853,24 @@ else() -Wformat=2 -Wshadow -Wuninitialized + --diag_suppress unrecognized_gcc_pragma > $<$: - /WX /W4 /permissive- /volatile:iso # /EHsc /Zc:wchar_t /Zc:forScope /Zc:inline + /GS # Enables buffer security check (can help detect stack-based buffer overflows) + /Wall /EHsc # /volatile:iso /WX /Zc:wchar_t /Zc:forScope /Zc:inline /permissive- /W4 + /wd4371 # layout of class may have changed from a previous version of the compiler due to better packing of member + /wd4514 # unreferenced inline function has been removed + /wd4623 # default constructor was implicitly defined as deleted #TODO(correaa) investigate + /wd4625 # copy constructor was implicitly defined as deleted + /wd4626 # assignment operator was implicitly defined as deleted #TODO(correaa) investigate + /wd4710 # function not inlined + /wd4711 # function selected for automatic inline expansion + /wd4820 # bytes padding added after base class + /wd4866 # compiler may not enforce left-to-right evaluation order for call + /wd4848 # support for attribute [[msvc::no_unique_address]] in C++17 and earlier is a vendor extension + /wd4868 # compiler may not enforce left-to-right evaluation order in braced initializer list + /wd5026 # move constructor was implicitly defined as deleted + /wd5027 # move assignment operator was implicitly defined as deleted > ) @@ -858,14 +888,12 @@ else() # target_link_libraries(main PRIVATE multi) target_compile_features (main PUBLIC cxx_std_17) target_include_directories(main PRIVATE ${PROJECT_SOURCE_DIR}/include) - target_compile_definitions(main PUBLIC BOOST_TEST_MODULE="C++ Unit Tests for Multi main") - target_compile_definitions(main PRIVATE "$<$:BOOST_PP_VARIADICS>") + # target_compile_definitions(main PRIVATE "$<$:BOOST_PP_VARIADICS>") if(NOT DEFINED ENABLE_CIRCLE) target_compile_options(main PRIVATE ${WARNS}) else() - target_compile_definitions(main PRIVATE "BOOST_TEST_DYN_LINK=1") target_compile_options (main PRIVATE -Werror -Wall) endif() add_test(NAME main COMMAND $) @@ -880,30 +908,24 @@ else() set_source_files_properties(${TEST_FILE} PROPERTIES LANGUAGE CUDA) endif() - # target_include_directories(${TEST_EXE} PRIVATE ${PROJECT_SOURCE_DIR}/include) - # target_include_directories(${TEST_EXE} SYSTEM PRIVATE ${Boost_INCLUDE_DIRS} ) - target_link_libraries(${TEST_EXE} PRIVATE multi) - target_link_libraries (${TEST_EXE} PRIVATE multi Boost::unit_test_framework ) + target_include_directories(${TEST_EXE} SYSTEM PRIVATE ${Boost_INCLUDE_DIRS}) + # target_link_libraries (${TEST_EXE} PRIVATE multi Boost::boost ) if(TBB_FOUND) target_link_libraries (${TEST_EXE} PRIVATE TBB::tbb) target_compile_definitions(${TEST_EXE} PUBLIC TBB_FOUND=1) endif() - target_compile_definitions(${TEST_EXE} PUBLIC BOOST_TEST_MODULE="C++ Unit Tests for Multi ${TEST_EXE}") - target_compile_definitions(${TEST_EXE} PUBLIC BOOST_TEST_DYN_LINK=1) - target_compile_definitions(${TEST_EXE} PUBLIC BOOST_NO_CXX98_FUNCTION_BASE=1) - - target_compile_definitions(${TEST_EXE} PRIVATE "$<$:BOOST_PP_VARIADICS>") - if(NOT DEFINED ENABLE_CIRCLE) target_compile_options(${TEST_EXE} PRIVATE ${WARNS}) else() - target_compile_definitions(${TEST_EXE} PRIVATE "BOOST_TEST_DYN_LINK=1") target_compile_options (${TEST_EXE} PRIVATE -Werror -Wall) endif() add_test(NAME ${TEST_EXE} COMMAND $) endforeach() + + # find_package(BLAS REQUIRED) + # target_link_libraries(redux.cpp.x PRIVATE BLAS::BLAS) endif() diff --git a/external_codes/boost_multi/multi/test/allocator.cpp b/external_codes/boost_multi/multi/test/allocator.cpp index 57c07d00bd..01309f6973 100644 --- a/external_codes/boost_multi/multi/test/allocator.cpp +++ b/external_codes/boost_multi/multi/test/allocator.cpp @@ -4,237 +4,356 @@ // https://www.boost.org/LICENSE_1_0.txt #include - -#include - -#include - -// Suppress warnings from boost.test -#if defined(__clang__) -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wold-style-cast" -# pragma clang diagnostic ignored "-Wundef" -# pragma clang diagnostic ignored "-Wconversion" -# pragma clang diagnostic ignored "-Wsign-conversion" -# pragma clang diagnostic ignored "-Wfloat-equal" -#elif defined(__GNUC__) -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wold-style-cast" -# pragma GCC diagnostic ignored "-Wundef" -# pragma GCC diagnostic ignored "-Wconversion" -# pragma GCC diagnostic ignored "-Wsign-conversion" -# pragma GCC diagnostic ignored "-Wfloat-equal" +#include // TODO(correaa) export IWYU + +#include // for transform, is_sorted +#include // for array, operator== +#include // for _LIBCPP_VERSION // IWYU pragma: keep +#include // for __GLIBCXX__, size_t +#include // for size, back_insert... +#include // for make_unique, uniq... +#ifdef BOOST_MULTI_HAS_MEMORY_RESOURCE + #include // for monotonic_buffer_... #endif +#include // for operator new // NOLINT(misc-include-cleaner) +#include // for basic_string, string +#include // for move, forward +#include // for vector, allocator -#ifndef BOOST_TEST_MODULE -# define BOOST_TEST_MAIN -#endif +namespace multi = boost::multi; -#include +template +using small_array = multi::static_array>; +// https://godbolt.org/z/d8ozWahna -namespace multi = boost::multi; +#include +#define BOOST_AUTO_TEST_CASE(CasenamE) /**/ + +auto main() -> int { // NOLINT(readability-function-cognitive-complexity,bugprone-exception-escape) +BOOST_AUTO_TEST_CASE(static_array_allocator) { + multi::array const ma({2, 3}, 99); + multi::static_array> const sma(ma(), std::allocator{}); + BOOST_TEST( sma == ma ); +} BOOST_AUTO_TEST_CASE(empty_stride) { multi::array ma; - BOOST_REQUIRE(ma.size() == 0); - BOOST_REQUIRE(ma.stride() != 0); - BOOST_REQUIRE(size(ma) == 0); + BOOST_TEST(ma.size() == 0); + BOOST_TEST(ma.stride() != 0); + BOOST_TEST(size(ma) == 0); multi::array ma0({0, 0}, 0.0); - BOOST_REQUIRE(ma0.size() == 0); - BOOST_REQUIRE(ma0.stride() != 0); + BOOST_TEST(ma0.size() == 0); + BOOST_TEST(ma0.stride() != 0); #ifndef _MSC_VER // doesn't work with msvc 14.3 c++17 permissive mode - BOOST_REQUIRE(size(ma0) == 0); + BOOST_TEST(size(ma0) == 0); #endif } +BOOST_AUTO_TEST_CASE(std_vector_of_arrays_check_size) { + multi::array const ma; + BOOST_TEST( ma.size() == 0 ); + BOOST_TEST( ma.num_elements() == 0 ); + + std::vector> va(1); // NOLINT(fuchsia-default-arguments-calls) vector + + BOOST_TEST( va[0].size() == 0 ); +} + +BOOST_AUTO_TEST_CASE(std_vector_of_arrays_manual_emplaceback_ctor) { + std::vector> va; + + va.emplace_back(multi::extensions_t<2>{3, 3}, 3); + va.emplace_back(multi::extensions_t<2>{2, 2}, 2); + va.emplace_back(multi::extensions_t<2>{1, 1}, 1); + va.emplace_back(multi::extensions_t<2>{0, 0}, 0); +} + +BOOST_AUTO_TEST_CASE(std_vector_of_arrays_manual_emplaceback) { + std::vector> va; + + va.emplace_back(multi::array({2, 2}, 2)); + va.emplace_back(multi::array({1, 1}, 1)); + va.emplace_back(multi::array({0, 0}, 0)); +} + +BOOST_AUTO_TEST_CASE(std_vector_of_arrays_manual_pushback) { + std::vector> va; + + va.push_back(multi::array({2, 2}, 2)); + va.push_back(multi::array({1, 1}, 1)); + va.push_back(multi::array({0, 0}, 0)); +} + BOOST_AUTO_TEST_CASE(std_vector_of_arrays) { - std::vector> va; + std::vector> va; + + std::transform( + multi::iextension(3).begin(), multi::iextension(3).end(), + std::back_inserter(va), + [](auto idx) { return multi::array({idx, idx}, static_cast(idx)); } + ); + +#ifndef _MSC_VER // doesn't work with msvc 14.3 c++17 permissive mode + BOOST_TEST( size(va[0]) == 0 ); + BOOST_TEST( size(va[1]) == 1 ); + BOOST_TEST( size(va[2]) == 2 ); +#endif + + BOOST_TEST( va[1] [0][0] == 1 ); + BOOST_TEST( va[2] [0][0] == 2 ); + + using namespace std::string_literals; // NOLINT(build/namespaces) + +#ifndef _MSC_VER // doesn't work with msvc 14.3 c++17 permissive mode + // NOLINTNEXTLINE(fuchsia-default-arguments-calls) + std::vector> const wa = { + multi::array({0, 0}, 0), + multi::array({1, 1}, 1), + multi::array({2, 2}, 2), + }; +#else + // NOLINTNEXTLINE(fuchsia-default-arguments-calls) + std::vector> const wa = { + multi::array(multi::extensions_t<2>(0, 0), 0), + multi::array(multi::extensions_t<2>(1, 1), 1), + multi::array(multi::extensions_t<2>(2, 2), 2), + }; +#endif + + BOOST_TEST( va.size() == wa.size() ); + BOOST_TEST( va == wa ); + + std::vector> ua(3, std::allocator>{}); + + auto iex = multi::iextension(static_cast(ua.size())); + + std::transform( + begin(iex), end(iex), + begin(ua), + [](auto idx) { return multi::array({idx, idx}, static_cast(idx)); } + ); + BOOST_TEST( ua == va ); +} + +BOOST_AUTO_TEST_CASE(std_vector_of_arrays_with_string_instead_of_int) { + // NOLINTBEGIN(fuchsia-default-arguments-calls) // string uses default parameter + std::vector> va; std::transform( begin(multi::iextension(3)), end(multi::iextension(3)), std::back_inserter(va), - [](auto idx){return multi::array({idx, idx}, static_cast(idx));} + [](auto idx) { return multi::array({idx, idx}, std::to_string(idx)); } ); #ifndef _MSC_VER // doesn't work with msvc 14.3 c++17 permissive mode - BOOST_REQUIRE( size(va[0]) == 0 ); - BOOST_REQUIRE( size(va[1]) == 1 ); - BOOST_REQUIRE( size(va[2]) == 2 ); + BOOST_TEST( size(va[0]) == 0 ); + BOOST_TEST( size(va[1]) == 1 ); + BOOST_TEST( size(va[2]) == 2 ); #endif + using namespace std::string_literals; // NOLINT(build/namespaces) - BOOST_REQUIRE( va[1] [0][0] == 1 ); - BOOST_REQUIRE( va[2] [0][0] == 2 ); + BOOST_TEST( va[1] [0][0] == "1"s ); // NOLINT(misc-include-cleaner) bug in clang-tidy 18 + BOOST_TEST( va[2] [0][0] == "2"s ); -#ifndef _MSC_VER // doesn't work with msvc 14.3 c++17 permissive mode - std::vector> const wa = { // testing std::vector of multi:array NOLINT(fuchsia-default-arguments-calls,-warnings-as-errors) - multi::array({0, 0}, 0.0), - multi::array({1, 1}, 1.0), - multi::array({2, 2}, 2.0), +#ifndef _MSC_VER // doesn't work with msvc 14.3 c++17 permissive mode + std::vector> const wa = { + multi::array({0, 0}, "0"s), + multi::array({1, 1}, "1"s), + multi::array({2, 2}, "2"s), }; #else - std::vector> const wa = { // testing std::vector of multi:array NOLINT(fuchsia-default-arguments-calls,-warnings-as-errors) - multi::array(multi::extensions_t<2>(0, 0), 0.0), - multi::array(multi::extensions_t<2>(1, 1), 1.0), - multi::array(multi::extensions_t<2>(2, 2), 2.0), + std::vector> const wa = { + multi::array(multi::extensions_t<2>(0, 0), "0"s), + multi::array(multi::extensions_t<2>(1, 1), "1"s), + multi::array(multi::extensions_t<2>(2, 2), "2"s), }; #endif #ifndef _MSC_VER // doesn't work with msvc 14.3 c++17 permissive mode - BOOST_REQUIRE( size(va) == size(wa) ); + BOOST_TEST( size(va) == size(wa) ); #endif - BOOST_REQUIRE( va == wa ); + BOOST_TEST( va == wa ); + + std::vector> ua(3, std::allocator>{}); - std::vector> ua(3, std::allocator>{}); auto iex = multi::iextension(static_cast(ua.size())); + std::transform( begin(iex), end(iex), begin(ua), - [](auto idx) {return multi::array({idx, idx}, static_cast(idx));} + [](auto idx) { return multi::array({idx, idx}, std::to_string(idx)); } ); - BOOST_REQUIRE( ua == va ); + + BOOST_TEST( ua == va ); + + // NOLINTEND(fuchsia-default-arguments-calls) // string uses default parameter } // TODO(correaa) make this code work with nvcc compiler (non device function called from device host through adl uninitialized_fill) #if !(defined(__NVCC__) || defined(__HIP_PLATFORM_NVIDIA__) || defined(__HIP_PLATFORM_AMD__) || defined(__HIPCC__)) BOOST_AUTO_TEST_CASE(array1d_of_arrays2d) { - multi::array, 1> arr(multi::extensions_t<1>(multi::iextension{10}), multi::array{}); - BOOST_REQUIRE( size(arr) == 10 ); + multi::array, 1> arr(multi::extensions_t<1>(multi::iextension{10}), multi::array{}); + BOOST_TEST( size(arr) == 10 ); std::transform( begin(extension(arr)), end(extension(arr)), begin(arr), - [](auto idx) {return multi::array({idx, idx}, static_cast(idx));} + [](auto idx) { return multi::array({idx, idx}, std::to_string(idx)); } ); - BOOST_REQUIRE( size(arr[0]) == 0 ); - BOOST_REQUIRE( size(arr[1]) == 1 ); - BOOST_REQUIRE( size(arr[8]) == 8 ); - BOOST_REQUIRE( arr[8][4][4] == 8.0 ); + BOOST_TEST( size(arr[0]) == 0 ); + BOOST_TEST( size(arr[1]) == 1 ); + BOOST_TEST( size(arr[8]) == 8 ); + + using namespace std::string_literals; // NOLINT(build/namespaces) + BOOST_TEST( arr[8][4][4] == "8"s ); } -BOOST_AUTO_TEST_CASE(array_3d_of_array_2d) { - multi::array, 2> AA({10, 20}, multi::array{}); - std::transform(extension(AA).begin(), extension(AA).end(), AA.begin(), AA.begin(), [](auto idx, auto&& row) -> decltype(row) { - std::transform(extension(row).begin(), extension(row).end(), row.begin(), [idx](auto jdx) { - return multi::array({idx + jdx, idx + jdx, idx + jdx}, 99.0); +BOOST_AUTO_TEST_CASE(array_3d_of_array_2d) { + multi::array, 2> AA({10, 20}, multi::array{}); + std::transform(AA.extension().begin(), AA.extension().end(), AA.begin(), AA.begin(), [](auto idx, auto&& row) -> decltype(row) { + std::transform(row.extension().begin(), row.extension().end(), row.begin(), [idx](auto jdx) { + return multi::array({idx + jdx, idx + jdx, idx + jdx}, 99); }); return std::forward(row); }); - BOOST_REQUIRE( size(AA[9][19]) == 9 + 19 ); - BOOST_REQUIRE( AA[9][19][1][1][1] == 99.0 ); + // BOOST_TEST( AA[9][19].size() == 9 + 19 ); + + // BOOST_TEST( std::size(AA[9][19]) == 9 + 19 ); // doesn't work on nvhpc 22.11 + // BOOST_TEST( size(AA[9][19]) == 9 + 19 ); + + // BOOST_TEST( AA[9][19][1][1][1] == 99 ); } -BOOST_AUTO_TEST_CASE(array_3d_of_array_2d_no_init) { - multi::array, 2> AA({10, 20}); +BOOST_AUTO_TEST_CASE(array_3d_of_array_2d_no_init) { + multi::array, 2> AA({10, 20}); std::transform(extension(AA).begin(), extension(AA).end(), AA.begin(), AA.begin(), [](auto idx, auto&& row) -> decltype(row) { std::transform(extension(row).begin(), extension(row).end(), row.begin(), [idx](auto jdx) { - return multi::array({idx + jdx, idx + jdx, idx + jdx}, 99.0); + return multi::array({idx + jdx, idx + jdx, idx + jdx}, 99); }); return std::forward(row); }); - BOOST_REQUIRE( size(AA[9][19]) == 9 + 19 ); - BOOST_REQUIRE( AA[9][19][1][1][1] == 99. ); + BOOST_TEST( AA[9][19].size() == 9 + 19 ); + // BOOST_TEST( std::size(AA[9][19]) == 9 + 19 ); // doesn't work on nvhpc 22.11 + BOOST_TEST( size(AA[9][19]) == 9 + 19 ); + + BOOST_TEST( AA[9][19][1][1][1] == 99 ); } #endif BOOST_AUTO_TEST_CASE(const_elements) { - auto ptr = std::make_unique(2.0); -// *ptr = 3.0; // ok, can't assign - BOOST_REQUIRE( *ptr == 2.0 ); - -// multi::array> arr({10, 10}, 99.0); -// BOOST_REQUIRE( arr[1][2] == 99.0 ); + auto ptr = std::make_unique(2); + // ok, can't assign // *ptr = 3.0; + BOOST_TEST( *ptr == 2 ); } #ifdef BOOST_MULTI_HAS_MEMORY_RESOURCE BOOST_AUTO_TEST_CASE(pmr) { - std::array buffer = {{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C'}}; + std::array buffer = { + {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C'} + }; + std::pmr::monotonic_buffer_resource pool{std::data(buffer), std::size(buffer)}; multi::array> Aarr({2, 2}, 'x', &pool); - Aarr[0][0] = 'x'; Aarr[0][1] = 'y'; - Aarr[1][0] = 'z'; Aarr[1][1] = '&'; + Aarr[0][0] = 'x'; + Aarr[0][1] = 'y'; + Aarr[1][0] = 'z'; + Aarr[1][1] = '&'; multi::array> Barr({3, 2}, 'o', &pool); - BOOST_REQUIRE(( buffer != std::array{{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C'}} )); + BOOST_TEST(( buffer != std::array{{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C'}} )); -#if defined(__GLIBCXX__) - BOOST_REQUIRE(( buffer == std::array{{'x', 'y', 'z', '&', 'o', 'o', 'o', 'o', 'o', 'o', 'A', 'B', 'C'}} )); -#endif -#if defined(_LIBCPP_VERSION) - BOOST_REQUIRE(( buffer == std::array{{'0', '1', '2', 'o', 'o', 'o', 'o', 'o', 'o', 'x', 'y', 'z', '&'}} )); -#endif + #if defined(__GLIBCXX__) + BOOST_TEST(( buffer == std::array{{'x', 'y', 'z', '&', 'o', 'o', 'o', 'o', 'o', 'o', 'A', 'B', 'C'}} )); + #endif + #if defined(_LIBCPP_VERSION) + BOOST_TEST(( buffer == std::array{{'0', '1', '2', 'o', 'o', 'o', 'o', 'o', 'o', 'x', 'y', 'z', '&'}} )); + #endif - BOOST_REQUIRE(Aarr[0][0] == 'x'); - BOOST_REQUIRE(Barr[0][0] == 'o'); + BOOST_TEST(Aarr[0][0] == 'x'); + BOOST_TEST(Barr[0][0] == 'o'); } BOOST_AUTO_TEST_CASE(pmr2) { + // clang-format off std::array buffer = {{'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X'}}; + // clang-format on + std::pmr::monotonic_buffer_resource pool{std::data(buffer), std::size(buffer)}; -#ifndef _MSC_VER + #ifndef _MSC_VER multi::pmr::array Aarr({2, 2}, 'a', &pool); multi::pmr::array Barr({3, 2}, 'b', &pool); -#else + #else multi::pmr::array Aarr(multi::extensions_t<2>{2, 2}, 'a', &pool); multi::pmr::array Barr(multi::extensions_t<2>{3, 2}, 'b', &pool); -#endif + #endif -#if defined(__GLIBCXX__) - BOOST_REQUIRE(( buffer == std::array{{'a', 'a', 'a', 'a', 'b', 'b', 'b', 'b', 'b', 'b', 'X', 'X', 'X'}} )); -#endif -#if defined(_LIBCPP_VERSION) - BOOST_REQUIRE(( buffer == std::array{{'X', 'X', 'X', 'b', 'b', 'b', 'b', 'b', 'b', 'a', 'a', 'a', 'a'}} )); -#endif + #if defined(__GLIBCXX__) + BOOST_TEST(( buffer == std::array{{'a', 'a', 'a', 'a', 'b', 'b', 'b', 'b', 'b', 'b', 'X', 'X', 'X'}} )); + #endif + #if defined(_LIBCPP_VERSION) + BOOST_TEST(( buffer == std::array{{'X', 'X', 'X', 'b', 'b', 'b', 'b', 'b', 'b', 'a', 'a', 'a', 'a'}} )); + #endif - BOOST_REQUIRE(Aarr[0][0] == 'a'); - BOOST_REQUIRE(Barr[0][0] == 'b'); + BOOST_TEST(Aarr[0][0] == 'a'); + BOOST_TEST(Barr[0][0] == 'b'); } BOOST_AUTO_TEST_CASE(pmr_double_uninitialized) { - std::array buffer = {{4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.00, 11.0, 996.0, 997.0, 998.0, 999.0}}; - std::pmr::monotonic_buffer_resource pool{static_cast(std::data(buffer)), 12*sizeof(double)}; + std::array buffer{ + {4, 5, 6, 7, 8, 9, 10, 11, 996, 997, 998, 999} + }; - multi::pmr::array Aarr({2, 2}, &pool); + std::pmr::monotonic_buffer_resource pool{static_cast(std::data(buffer)), 12 * sizeof(int)}; - BOOST_TEST( buffer[0] == 4.0 ); - BOOST_TEST( buffer[1] == 5.0 ); + multi::pmr::array Aarr({2, 2}, &pool); -#if defined(__GLIBCXX__) - BOOST_REQUIRE(Aarr[0][0] == 4.0); -#endif -#if defined(_LIBCPP_VERSION) - BOOST_REQUIRE(Aarr[0][0] == 996.0); -#endif + BOOST_TEST( buffer[0] == 4 ); + BOOST_TEST( buffer[1] == 5 ); + + #if defined(__GLIBCXX__) + BOOST_TEST(Aarr[0][0] == 4); + #endif + #if defined(_LIBCPP_VERSION) + BOOST_TEST(Aarr[0][0] == 996); + #endif } #endif BOOST_AUTO_TEST_CASE(static_allocator) { using T = int; multi::detail::static_allocator sa{}; + auto* pp = sa.allocate(10); - new(std::next(pp, 8)) T{42}; - BOOST_REQUIRE( *std::next(pp, 8) == 42 ); + + new (std::next(pp, 8)) T{42}; + + BOOST_TEST( *std::next(pp, 8) == 42 ); // (pp + 8)->~double(); sa.deallocate(pp, 10); } -#if defined( __cpp_constexpr) && (__cpp_constexpr > 202306L) +#if defined(__cpp_constexpr) && (__cpp_constexpr > 202306L) constexpr auto f() { - std::vector v = {1, 2, 3}; - return v.size(); + std::vector v = {1, 2, 3}; + return v.size(); } BOOST_AUTO_TEST_CASE(constexpr_allocator_vector) { static_assert(f() == 3); - BOOST_REQUIRE( f() == 3 ); + BOOST_TEST( f() == 3 ); } constexpr auto g() { - multi::array arr = {{4, 5, 6}, {1, 2, 3}, {7, 8, 9}}; + multi::array arr = { + {4, 5, 6}, + {1, 2, 3}, + {7, 8, 9}, + }; std::sort(arr.begin(), arr.end()); for(auto it = arr.diagonal().begin(); it != arr.diagonal().end(); ++it) { *it += 5; @@ -245,42 +364,32 @@ constexpr auto g() { BOOST_AUTO_TEST_CASE(constexpr_allocator) { constexpr auto gg = g(); - static_assert( gg == 10 ); - BOOST_REQUIRE( gg == 10 ); + static_assert(gg == 10); + BOOST_TEST( gg == 10 ); } #endif #if !defined(_MSC_VER) // static allocator does not work with MSVC implementation pf vector BOOST_AUTO_TEST_CASE(static_allocator_on_vector_int) { std::vector> vv(10, 42); // NOLINT(fuchsia-default-arguments-calls) - BOOST_REQUIRE( vv[3] == 42 ); - - auto ww = vv; - BOOST_REQUIRE( ww[3] == 42 ); + BOOST_TEST( vv[3] == 42 ); - ww[3] = 51; - BOOST_REQUIRE( ww[3] == 51 ); - BOOST_REQUIRE( vv[3] == 42 ); + // auto ww = vv; + // BOOST_TEST( ww[3] == 42 ); - auto xx = std::move(ww); - BOOST_REQUIRE( ww.empty() ); // NOLINT(bugprone-use-after-move,hicpp-invalid-access-moved) - BOOST_REQUIRE( vv[3] == 42 ); - BOOST_REQUIRE( xx[3] == 51 ); + // ww[3] = 51; + // BOOST_TEST( ww[3] == 51 ); + // BOOST_TEST( vv[3] == 42 ); - // swap(xx, vv); - // BOOST_REQUIRE( vv[3] == 51 ); - // BOOST_REQUIRE( xx[3] == 42 ); + // auto xx = std::move(ww); + // BOOST_TEST( ww.empty() ); // NOLINT(bugprone-use-after-move,hicpp-invalid-access-moved) + // BOOST_TEST( vv[3] == 42 ); + // BOOST_TEST( xx[3] == 51 ); - { - std::vector< std::vector> > const VV = {vv, xx, vv}; // NOLINT(fuchsia-default-arguments-calls) - BOOST_REQUIRE( VV.size() == 3 ); - // swap(VV[0], VV[1]); - // std::sort(VV.begin(), VV.end()); - // BOOST_REQUIRE( std::is_sorted(VV.begin(), VV.end()) ); - // VV.resize(10, xx); - // std::sort(VV.begin(), VV.end()); - // BOOST_REQUIRE( std::is_sorted(VV.begin(), VV.end()) ); - } + // { + // std::vector>> const VV = {vv, xx, vv}; // NOLINT(fuchsia-default-arguments-calls) + // BOOST_TEST( VV.size() == 3 ); + // } } BOOST_AUTO_TEST_CASE(static_allocator_on_vector_string) { @@ -288,127 +397,128 @@ BOOST_AUTO_TEST_CASE(static_allocator_on_vector_string) { std::string const dog = "dogdogdogdogdogdogdogdogdogdogdogdogdogdogdogdogdogdogdogdogdogdogdogdog"; // NOLINT(fuchsia-default-arguments-calls) std::vector> vv(10, cat); // NOLINT(fuchsia-default-arguments-calls) - BOOST_REQUIRE( vv[3] == cat ); + BOOST_TEST( vv[3] == cat ); auto ww = vv; - BOOST_REQUIRE( ww[3] == cat ); + BOOST_TEST( ww[3] == cat ); ww[3] = dog; - BOOST_REQUIRE( ww[3] == dog ); - BOOST_REQUIRE( vv[3] == cat ); + BOOST_TEST( ww[3] == dog ); + BOOST_TEST( vv[3] == cat ); auto xx = std::move(ww); - BOOST_REQUIRE( vv[3] == cat ); - BOOST_REQUIRE( xx[3] == dog ); - BOOST_REQUIRE( ww.empty() ); // NOLINT(bugprone-use-after-move,hicpp-invalid-access-moved) + BOOST_TEST( vv[3] == cat ); + BOOST_TEST( xx[3] == dog ); + BOOST_TEST( ww.empty() ); // NOLINT(bugprone-use-after-move,hicpp-invalid-access-moved) // vv.resize(15); // swap(xx, vv); - // BOOST_REQUIRE( vv[3] == dog ); - // BOOST_REQUIRE( xx[3] == cat ); + // BOOST_TEST( vv[3] == dog ); + // BOOST_TEST( xx[3] == cat ); { - std::vector< std::vector> > const VV = {vv, xx, vv}; // NOLINT(fuchsia-default-arguments-calls) - BOOST_REQUIRE( VV.size() == 3 ); + std::vector>> const VV = {vv, xx, vv}; // NOLINT(fuchsia-default-arguments-calls) + BOOST_TEST( VV.size() == 3 ); // swap(VV[0], VV[1]); // std::sort(VV.begin(), VV.end()); - // BOOST_REQUIRE( std::is_sorted(VV.begin(), VV.end()) ); + // BOOST_TEST( std::is_sorted(VV.begin(), VV.end()) ); // VV.resize(10, xx); // std::sort(VV.begin(), VV.end()); - // BOOST_REQUIRE( std::is_sorted(VV.begin(), VV.end()) ); + // BOOST_TEST( std::is_sorted(VV.begin(), VV.end()) ); } } #endif -template -using small_array = multi::static_array>; -// https://godbolt.org/z/d8ozWahna - #if !defined(_MSC_VER) || (_MSC_VER > 193030706) // TODO(correaa) doesn't work on MSVC 14.3 in c++17 mode BOOST_AUTO_TEST_CASE(small_array_int) { - small_array vv({4, 4}, 42); + small_array vv({4, 4}, 42); - BOOST_REQUIRE( vv[3][3] == 42 ); + BOOST_TEST( vv[3][3] == 42 ); auto ww = vv; - BOOST_REQUIRE( ww[3][3] == 42 ); - BOOST_REQUIRE( ww.base() != vv.base() ); - auto* wwb = ww.base(); - auto* vvb = vv.base(); + + BOOST_TEST( ww[3][3] == 42 ); + BOOST_TEST( ww.base() != vv.base() ); + + auto const* wwb = ww.base(); + auto const* vvb = vv.base(); ww[3][3] = 51; - BOOST_REQUIRE( ww[3][3] == 51 ); - BOOST_REQUIRE( vv[3][3] == 42 ); + + BOOST_TEST( ww[3][3] == 51 ); + BOOST_TEST( vv[3][3] == 42 ); swap(ww, vv); - BOOST_REQUIRE( vv[3][3] == 51 ); - BOOST_REQUIRE( ww[3][3] == 42 ); - BOOST_REQUIRE( ww.base() == wwb ); - BOOST_REQUIRE( vv.base() == vvb ); + BOOST_TEST( vv[3][3] == 51 ); + BOOST_TEST( ww[3][3] == 42 ); - auto xx = std::move(ww); + BOOST_TEST( ww.base() == wwb ); + BOOST_TEST( vv.base() == vvb ); - BOOST_REQUIRE( vv[3][3] == 51 ); - BOOST_REQUIRE( xx[3][3] == 42 ); - // BOOST_REQUIRE( ww[3][3] == 42 ); - BOOST_REQUIRE( xx.base() != vv.base() ); - // BOOST_REQUIRE( ww.empty() ); + auto xx{std::move(ww)}; - small_array yy({4, 4}); + BOOST_TEST( vv[3][3] == 51 ); + BOOST_TEST( xx[3][3] == 42 ); + // BOOST_TEST( ww[3][3] == 42 ); + BOOST_TEST( xx.base() != vv.base() ); + // BOOST_TEST( ww.empty() ); + + small_array yy({4, 4}); yy = vv; - BOOST_REQUIRE( yy == vv ); -// #ifndef _MSC_VER // TODO(correaa) does not compile in MSVC 1.43 in c++17 mode + BOOST_TEST( yy == vv ); + yy = std::move(vv); - BOOST_REQUIRE( vv.size() == 4 ); // NOLINT(clang-analyzer-cplusplus.Move,bugprone-use-after-move,hicpp-invalid-access-moved) -// #endif + BOOST_TEST( vv.size() == 4 ); // NOLINT(clang-analyzer-cplusplus.Move,bugprone-use-after-move,hicpp-invalid-access-moved) { - std::vector< small_array > VV = {vv, xx, vv}; // NOLINT(fuchsia-default-arguments-calls) - BOOST_REQUIRE( VV.size() == 3 ); + std::vector> VV = {vv, xx, vv}; // NOLINT(fuchsia-default-arguments-calls) + BOOST_TEST( VV.size() == 3 ); swap(VV[0], VV[1]); std::sort(VV.begin(), VV.end()); - BOOST_REQUIRE( std::is_sorted(VV.begin(), VV.end()) ); + BOOST_TEST( std::is_sorted(VV.begin(), VV.end()) ); VV.resize(10, xx); std::sort(VV.begin(), VV.end()); - BOOST_REQUIRE( std::is_sorted(VV.begin(), VV.end()) ); + BOOST_TEST( std::is_sorted(VV.begin(), VV.end()) ); } } #endif BOOST_AUTO_TEST_CASE(props_of_static_allocator) { { - std::vector vv(20, 11); // NOLINT(fuchsia-default-arguments-calls) - std::vector ww = vv; - BOOST_REQUIRE( ww == vv ); + std::vector vv(20, 11); // NOLINT(fuchsia-default-arguments-calls) + std::vector ww = vv; + BOOST_TEST( ww == vv ); - ww = vv; - BOOST_REQUIRE( ww == vv ); + ww = vv; + BOOST_TEST( ww == vv ); - ww = std::move(vv); - BOOST_REQUIRE( vv.size() == 0 ); // NOLINT(readability-container-size-empty,bugprone-use-after-move,hicpp-invalid-access-moved,clang-analyzer-cplusplus.Move) + ww = std::move(vv); + BOOST_TEST( vv.size() == 0 ); // NOLINT(readability-container-size-empty,bugprone-use-after-move,hicpp-invalid-access-moved,clang-analyzer-cplusplus.Move) - std::vector xx(20, 22); // NOLINT(fuchsia-default-arguments-calls) - swap( ww, xx ); - BOOST_REQUIRE( ww == std::vector(20, 22) ); // NOLINT(fuchsia-default-arguments-calls) - } + std::vector xx(20, 22); // NOLINT(fuchsia-default-arguments-calls) + swap(ww, xx); + BOOST_TEST( ww == std::vector(20, 22) ); // NOLINT(fuchsia-default-arguments-calls) + } #if !defined(_MSC_VER) // static_allocator doesn't work with MSVC implementation of vector { std::vector> vv(20, 11); // NOLINT(fuchsia-default-arguments-calls) std::vector> ww = vv; - BOOST_REQUIRE( ww == vv ); + BOOST_TEST( ww == vv ); ww = vv; - BOOST_REQUIRE( ww == vv ); + BOOST_TEST( ww == vv ); ww = std::move(vv); - BOOST_REQUIRE( vv.size() == 0 ); // NOLINT(readability-container-size-empty,bugprone-use-after-move,hicpp-invalid-access-moved,clang-analyzer-cplusplus.Move) + BOOST_TEST( vv.size() == 0 ); // NOLINT(readability-container-size-empty,bugprone-use-after-move,hicpp-invalid-access-moved,clang-analyzer-cplusplus.Move) std::vector> xx(20, 22); // NOLINT(fuchsia-default-arguments-calls) - swap( ww, xx ); - BOOST_REQUIRE(( ww == std::vector>(20, 22) )); // NOLINT(fuchsia-default-arguments-calls) + swap(ww, xx); + BOOST_TEST(( ww == std::vector>(20, 22) )); // NOLINT(fuchsia-default-arguments-calls) } #endif } + +return boost::report_errors();} diff --git a/external_codes/boost_multi/multi/test/array_cref.cpp b/external_codes/boost_multi/multi/test/array_cref.cpp index fcd64db12b..cc40099464 100644 --- a/external_codes/boost_multi/multi/test/array_cref.cpp +++ b/external_codes/boost_multi/multi/test/array_cref.cpp @@ -3,119 +3,119 @@ // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt -#include - -#include -#include - -// Suppress warnings from boost.test -#if defined(__clang__) -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wold-style-cast" -# pragma clang diagnostic ignored "-Wundef" -# pragma clang diagnostic ignored "-Wconversion" -# pragma clang diagnostic ignored "-Wsign-conversion" -# pragma clang diagnostic ignored "-Wfloat-equal" -#elif defined(__GNUC__) -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wold-style-cast" -# pragma GCC diagnostic ignored "-Wundef" -# pragma GCC diagnostic ignored "-Wconversion" -# pragma GCC diagnostic ignored "-Wsign-conversion" -# pragma GCC diagnostic ignored "-Wfloat-equal" -#endif - -#ifndef BOOST_TEST_MODULE -# define BOOST_TEST_MAIN -#endif +#include // for array, array_ref, subarray, arra... -#include +#include // for complex, operator== +#include // for initializer_list +#include // for pointer_traits +#include // for is_same +#include // for vector namespace multi = boost::multi; +#include +#define BOOST_AUTO_TEST_CASE(CasenamE) /**/ + +auto main() -> int { // NOLINT(readability-function-cognitive-complexity,bugprone-exception-escape) BOOST_AUTO_TEST_CASE(array_cref) { using complex = std::complex; - static_assert( std::is_same::element_type, complex>{}, "!"); - static_assert( std::is_same::rebind, complex const*>{}, "!"); + static_assert(std::is_same::element_type, complex>{}, "!"); + static_assert(std::is_same::rebind, complex const*>{}, "!"); - std::vector vec(100, 0.); // testing std::vector vs multi:array NOLINT(fuchsia-default-arguments-calls,-warnings-as-errors) - std::vector const cvec(100); // testing std::vector vs multi:array NOLINT(fuchsia-default-arguments-calls,-warnings-as-errors) + std::vector vec(100, 0.0); // testing std::vector vs multi:array NOLINT(fuchsia-default-arguments-calls,-warnings-as-errors) + std::vector const cvec(100); // testing std::vector vs multi:array NOLINT(fuchsia-default-arguments-calls,-warnings-as-errors) - multi::array_ref A2D(vec.data(), multi::extensions_t<2>{10, 10}); + multi::array_ref A2D(vec.data(), multi::extensions_t<2>{10, 10}); multi::array_ref B2D(vec.data(), {10, 10}); - static_assert( multi::array_ref::rank::value == 2 , "!" ); + using std::get; - BOOST_REQUIRE( &A2D[3][4] == &B2D[3][4] ); + BOOST_TEST( get<0>( A2D().sizes() ) == 10 ); + BOOST_TEST( get<1>( A2D().sizes() ) == 10 ); - multi::array_ref const D2D(cvec.data(), {10, 10}); - multi::array_cref F2D( vec.data(), {10, 10}); + BOOST_TEST( get<0>( A2D().sizes() ) == 10 ); + BOOST_TEST( get<1>( A2D().sizes() ) == 10 ); - BOOST_REQUIRE( D2D.layout() == F2D.layout() ); + static_assert( multi::array_ref::rank::value == 2 ); - A2D[7][8] = 3.; - BOOST_REQUIRE( F2D[7][8] == 3. ); - BOOST_REQUIRE( &A2D[7][8] == &F2D[7][8] ); + BOOST_TEST( &A2D[3][4] == &B2D[3][4] ); -// #if defined(__cpp_deduction_guides) and not defined(__NVCC__) -// multi::array_ref G2D(dc.data(), {10, 10}); // TODO(correaa) -// BOOST_REQUIRE( G2D == D2D ); -// #endif + multi::array_ref const D2D(cvec.data(), {10, 10}); + multi::array_cref F2D(vec.data(), {10, 10}); + + BOOST_TEST( D2D.layout() == F2D.layout() ); + + A2D[7][8] = 3.0; + BOOST_TEST( F2D[7][8] == 3.0 ); + BOOST_TEST( &A2D[7][8] == &F2D[7][8] ); + + // #if defined(__cpp_deduction_guides) and not defined(__NVCC__) + // multi::array_ref G2D(dc.data(), {10, 10}); // TODO(correaa) + // BOOST_TEST( G2D == D2D ); + // #endif } #ifndef _MSC_VER // TODO(correaa) doesn't work on MSVC 14.3 in c++17 mode BOOST_AUTO_TEST_CASE(arrays_1D_from_carray) { - double a_c_array[] = {1.0, 2.0, 3.0}; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) test legacy types - multi::array an_array_value (a_c_array); // ok, it is a copy - multi::array_cref an_array_const_reference(a_c_array); // ok, it is read only reference - multi::array_ref an_array_reference (a_c_array); // ok, it is a reference - - BOOST_REQUIRE( an_array_value .size() == 3 && an_array_value [1] == 2.0 ); - BOOST_REQUIRE( an_array_const_reference.size() == 3 && an_array_const_reference[1] == 2.0 ); - BOOST_REQUIRE( an_array_reference .size() == 3 && an_array_reference [1] == 2.0 ); + // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) test legacy types + int a_c_array[] = {10, 20, 30}; + multi::array an_array_value(a_c_array); // ok, it is a copy + multi::array_cref an_array_const_reference(a_c_array); // ok, it is read only reference + multi::array_ref an_array_reference(a_c_array); // ok, it is a reference + + BOOST_TEST( an_array_value .size() == 3 && an_array_value [1] == 20 ); + BOOST_TEST( an_array_const_reference.size() == 3 && an_array_const_reference[1] == 20 ); + BOOST_TEST( an_array_reference .size() == 3 && an_array_reference [1] == 20 ); } BOOST_AUTO_TEST_CASE(arrays_1D_from_const_carray) { - double const a_c_array[] = {1.0, 2.0, 3.0}; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) test legacy types - multi::array an_array_value (a_c_array); // ok, it is a copy - multi::array_cref an_array_const_reference(a_c_array); // ok, it is read only reference -// multi::array_ref an_array_reference (a_c_array); // not ok, c array is const - - BOOST_REQUIRE( an_array_value .size() == 3 && an_array_value [1] == 2.0 ); - BOOST_REQUIRE( an_array_const_reference.size() == 3 && an_array_const_reference[1] == 2.0 ); -// BOOST_REQUIRE( an_array_reference .size() == 3 && an_array_reference [1] == 2. ); + // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) test legacy types + int const a_c_array[] = {10, 20, 30}; + multi::array an_array_value(a_c_array); // ok, it is a copy + multi::array_cref an_array_const_reference(a_c_array); // ok, it is read only reference + + // multi::array_ref an_array_reference (a_c_array); // not ok, c array is const + + BOOST_TEST( an_array_value .size() == 3 && an_array_value [1] == 20 ); + BOOST_TEST( an_array_const_reference.size() == 3 && an_array_const_reference[1] == 20 ); + // BOOST_TEST( an_array_reference .size() == 3 && an_array_reference [1] == 20 ); } #endif BOOST_AUTO_TEST_CASE(arrays_1D_from_explict_init_list) { - std::initializer_list const il = {1.0, 2.0, 3.0}; - multi::array an_array_value (il); // ok, it is a copy - multi::array_cref an_array_const_reference(il); // ok, it is read only -// multi::array_ref an_array_reference ({1., 2., 3.}); // not allowed, the init list elems are const - - BOOST_REQUIRE( an_array_value .size() == 3 && an_array_value [1] == 2.0 ); - BOOST_REQUIRE( an_array_const_reference.size() == 3 && an_array_const_reference[1] == 2.0 ); -// BOOST_REQUIRE( an_array_reference .size() == 3 && an_array_reference [1] == 2. ); + std::initializer_list const il = {10, 20, 30}; + multi::array an_array_value(il); // ok, it is a copy + multi::array_cref an_array_const_reference(il); // ok, it is read only + + // multi::array_ref an_array_reference ({10, 20, 30}); // not allowed, the init list elems are const + + BOOST_TEST( an_array_value .size() == 3 && an_array_value [1] == 20 ); + BOOST_TEST( an_array_const_reference.size() == 3 && an_array_const_reference[1] == 20 ); + // BOOST_TEST( an_array_reference .size() == 3 && an_array_reference [1] == 20 ); } BOOST_AUTO_TEST_CASE(arrays_1D_from_explict_auto_init_list) { - auto il = {1.0, 2.0, 3.0}; - multi::array an_array_value (il); // ok, it is a copy - multi::array_cref an_array_const_reference(il); // ok, it is read only -// multi::array_ref an_array_reference ({1., 2., 3.}); // not allowed, the init list elems are const - - BOOST_REQUIRE( an_array_value .size() == 3 && an_array_value [1] == 2.0 ); - BOOST_REQUIRE( an_array_const_reference.size() == 3 && an_array_const_reference[1] == 2.0 ); -// BOOST_REQUIRE( an_array_reference .size() == 3 && an_array_reference [1] == 2. ); + auto il = {10, 20, 30}; + multi::array an_array_value(il); // ok, it is a copy + multi::array_cref an_array_const_reference(il); // ok, it is read only + + // multi::array_ref an_array_reference ({10, 20, 30}); // not allowed, the init list elems are const + + BOOST_TEST( an_array_value .size() == 3 && an_array_value [1] == 20 ); + BOOST_TEST( an_array_const_reference.size() == 3 && an_array_const_reference[1] == 20 ); + // BOOST_TEST( an_array_reference .size() == 3 && an_array_reference [1] == 20 ); } BOOST_AUTO_TEST_CASE(arrays_1D_from_init_list) { - multi::array an_array_value ({1.0, 2.0, 3.0}); // ok, it is a copy -// multi::array_cref an_array_const_reference({1.0, 2.0, 3.0}); // not ok, constructor disable because memcheck detects use after scope -// multi::array_ref an_array_reference ({1., 2., 3.}); // not allowed, the init list elems are const + multi::array an_array_value({10, 20, 30}); // ok, it is a copy + + // multi::array_cref an_array_const_reference({10, 20, 30}); // not ok, constructor disable because memcheck detects use after scope + // multi::array_ref an_array_reference ({10, 20, 30}); // not allowed, the init list elems are const - BOOST_REQUIRE( an_array_value .size() == 3 && an_array_value [1] == 2. ); -// BOOST_REQUIRE( an_array_const_reference.size() == 3 && an_array_const_reference[1] == 2.0 ); -// BOOST_REQUIRE( an_array_reference .size() == 3 && an_array_reference [1] == 2. ); + BOOST_TEST( an_array_value .size() == 3 && an_array_value [1] == 20 ); + // BOOST_TEST( an_array_const_reference.size() == 3 && an_array_const_reference[1] == 20 ); + // BOOST_TEST( an_array_reference .size() == 3 && an_array_reference [1] == 20 ); } + +return boost::report_errors();} diff --git a/external_codes/boost_multi/multi/test/array_fancyref.cpp b/external_codes/boost_multi/multi/test/array_fancyref.cpp index 132ccacb08..3b96cabf57 100644 --- a/external_codes/boost_multi/multi/test/array_fancyref.cpp +++ b/external_codes/boost_multi/multi/test/array_fancyref.cpp @@ -3,39 +3,12 @@ // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt -#include - -// Suppress warnings from boost.test -#if defined(__clang__) -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wold-style-cast" -# pragma clang diagnostic ignored "-Wundef" -# pragma clang diagnostic ignored "-Wconversion" -# pragma clang diagnostic ignored "-Wsign-conversion" -# pragma clang diagnostic ignored "-Wfloat-equal" -#elif defined(__GNUC__) -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wold-style-cast" -# pragma GCC diagnostic ignored "-Wundef" -# pragma GCC diagnostic ignored "-Wconversion" -# pragma GCC diagnostic ignored "-Wsign-conversion" -# pragma GCC diagnostic ignored "-Wfloat-equal" -#elif defined(_MSC_VER) -# pragma warning(push) -# pragma warning(disable : 4285) // Recursive return type for fancy_ptr if infix notationis applied -#endif - -#ifndef BOOST_TEST_MODULE -# define BOOST_TEST_MAIN -#endif - -#include - -#if defined(__clang__) -# pragma clang diagnostic pop -#elif defined(__GNUC__) -# pragma GCC diagnostic pop -#endif +#include // for array, array_iterator, static_array + +#include // for size_t, nullptr_t, ptrdiff_t +#include // for random_access_iterator_tag +#include // for allocator +#include // for decay_t namespace fancy { @@ -61,28 +34,15 @@ template class ptr { // NOLINT(cppcoreguidelines-special-member constexpr ptr(ptr const& /*other*/) = default; // vvv it is important that these two functions are device or device host functions - // NOLINTNEXTLINE(fuchsia-overloaded-operator, fuchsia-trailing-return): this class simulates pointer constexpr auto operator*() const noexcept -> reference { return reference{}; } - // NOLINTNEXTLINE(fuchsia-overloaded-operator, fuchsia-trailing-return): this class simulates pointer constexpr auto operator+(difference_type /*unused*/) const noexcept -> ptr { return *this; } - // NOLINTNEXTLINE(fuchsia-overloaded-operator, fuchsia-trailing-return): this class simulates pointer - + constexpr auto operator[](difference_type dist) const noexcept -> reference { return *(*this + dist); } auto operator+=(difference_type /*difference*/) noexcept -> ptr& { return *this; } - // NOLINTNEXTLINE(fuchsia-overloaded-operator, fuchsia-trailing-return): this class simulates pointer auto operator++() noexcept -> ptr& { return operator+=(1); } - // NOLINTNEXTLINE(fuchsia-overloaded-operator, fuchsia-trailing-return): this class simulates pointer friend auto operator-(ptr const& /*a*/, ptr const& /*b*/) noexcept -> difference_type { return 0; } - // NOLINTNEXTLINE(fuchsia-overloaded-operator, fuchsia-trailing-return): this class simulates pointer auto operator==(ptr const& /*other*/) const noexcept -> bool { return true; } - // NOLINTNEXTLINE(fuchsia-overloaded-operator, fuchsia-trailing-return): this class simulates pointer auto operator!=(ptr const& /*other*/) const noexcept -> bool { return false; } - // explicit operator T*() const{return &value;} - // NOLINTNEXTLINE(fuchsia-overloaded-operator, fuchsia-trailing-return): this class simulates pointer - auto operator->() const noexcept -> ptr const& { return *this; } - // NOLINTNEXTLINE(fuchsia-trailing-return): this class simulates pointer - // friend auto to_address(ptr const& pointer) -> ptr {return pointer;} explicit operator bool() const noexcept { return false; } - // operator double*() const{return &value;} friend auto get_allocator(ptr const& /*self*/) noexcept { return std::allocator{}; } }; @@ -177,25 +137,21 @@ auto copy(It /*first*/, It /*last*/, multi::array_iterator> return dest; } -// template // custom copy 2D (aka double strided copy) -// auto uninitialized_copy(Alloc&, It first, It last, multi::array_iterator> const& dest){ -// std::cerr << "2D uninitialized_copy(...) calls raw copy 2D" << std::endl; -// return copy(first, last, dest); -// } - } // end namespace boost::multi -//////////////////////////////////////////////////////////////////////////////// -// user code -//////////////////////////////////////////////////////////////////////////////// +#include +#define BOOST_AUTO_TEST_CASE(CasenamE) /**/ -BOOST_AUTO_TEST_CASE(multi_fancy) { - namespace multi = boost::multi; +auto main() -> int { // NOLINT(readability-function-cognitive-complexity,bugprone-exception-escape) + BOOST_AUTO_TEST_CASE(multi_fancy) { + namespace multi = boost::multi; - multi::array> arr({5, 5}); - BOOST_REQUIRE( arr.size() == 5 ); - BOOST_REQUIRE( arr[1][1] == arr[2][2] ); + multi::array> arr({5, 5}); + BOOST_TEST( arr.size() == 5 ); + BOOST_TEST( arr[1][1] == arr[2][2] ); - multi::array> const arr2({0, 0}); - BOOST_REQUIRE( arr2.size() == 0 ); + multi::array> const arr2({0, 0}); + BOOST_TEST( arr2.size() == 0 ); + } + return boost::report_errors(); } diff --git a/external_codes/boost_multi/multi/test/array_legacy_c.cpp b/external_codes/boost_multi/multi/test/array_legacy_c.cpp index 8833c172df..f52768047a 100644 --- a/external_codes/boost_multi/multi/test/array_legacy_c.cpp +++ b/external_codes/boost_multi/multi/test/array_legacy_c.cpp @@ -3,40 +3,13 @@ // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt -#include +#include // for array, rotated, subarray, dimens... -#include -#include -#include - -// Suppress warnings from boost.test -#if defined(__clang__) -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wold-style-cast" -# pragma clang diagnostic ignored "-Wundef" -# pragma clang diagnostic ignored "-Wconversion" -# pragma clang diagnostic ignored "-Wsign-conversion" -# pragma clang diagnostic ignored "-Wfloat-equal" -#elif defined(__GNUC__) -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wold-style-cast" -# pragma GCC diagnostic ignored "-Wundef" -# pragma GCC diagnostic ignored "-Wconversion" -# pragma GCC diagnostic ignored "-Wsign-conversion" -# pragma GCC diagnostic ignored "-Wfloat-equal" -#endif - -#ifndef BOOST_TEST_MODULE -# define BOOST_TEST_MAIN -#endif - -#include - -#if defined(__clang__) -# pragma clang diagnostic pop -#elif defined(__GNUC__) -# pragma GCC diagnostic pop -#endif +#include // for array +#include // for complex +#include // for apply // IWYU pragma: keep +// IWYU pragma: no_include // for remove_reference<>::type +#include // for move namespace multi = boost::multi; @@ -59,24 +32,31 @@ void fftw_plan_dft( } // end namespace fake +constexpr auto f2(multi::array_ref&& array) -> double& { return std::move(array)[2]; } + +#include +#define BOOST_AUTO_TEST_CASE(CasenamE) + +auto main() -> int { // NOLINT(readability-function-cognitive-complexity,bugprone-exception-escape) BOOST_AUTO_TEST_CASE(array_legacy_c) { - using complex = std::complex; + using complex = std::complex; + multi::array const in = { - {{150.0, 0.0}, {16.0, 0.0}, {17.0, 0.0}, {18.0, 0.0}, {19.0, 0.0}}, - { {5.0, 0.0}, {5.0, 0.0}, {5.0, 0.0}, {5.0, 0.0}, {5.0, 0.0}}, - {{100.0, 0.0}, {11.0, 0.0}, {12.0, 0.0}, {13.0, 0.0}, {14.0, 0.0}}, - { {50.0, 0.0}, {6.0, 0.0}, {7.0, 0.0}, {8.0, 0.0}, {9.0, 0.0}}, + {{ 150.0, 0.0 }, { 16.0, 0.0 }, { 17.0, 0.0 }, { 18.0, 0.0 }, { 19.0, 0.0 }}, + { { 5.0, 0.0 }, { 5.0, 0.0 }, { 5.0, 0.0 }, { 5.0, 0.0 }, { 5.0, 0.0 }}, + {{ 100.0, 0.0 }, { 11.0, 0.0 }, { 12.0, 0.0 }, { 13.0, 0.0 }, { 14.0, 0.0 }}, + { { 50.0, 0.0 }, { 6.0, 0.0 }, { 7.0, 0.0 }, { 8.0, 0.0 }, { 9.0, 0.0 }}, }; multi::array, 2> out(extensions(in)); - BOOST_REQUIRE( dimensionality(out) == dimensionality(in) ); - BOOST_REQUIRE( sizes(out) == sizes(in) ); + BOOST_TEST( dimensionality(out) == dimensionality(in) ); + BOOST_TEST( sizes(out) == sizes(in) ); static_assert(sizeof(complex) == sizeof(fake::fftw_complex), "!"); fake::fftw_plan_dft( decltype(in)::dimensionality, - std::apply([](auto... sizes) { return std::array{{static_cast(sizes)...}}; }, in.sizes()).data(), + std::apply([](auto... sizes) { return std::array{ { static_cast(sizes)... } }; }, in.sizes()).data(), // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast,cppcoreguidelines-pro-type-const-cast) testing legacy code reinterpret_cast(const_cast(in.data_elements())), // NOSONAR // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast): testing legacy code @@ -93,27 +73,39 @@ BOOST_AUTO_TEST_CASE(array_legacy_c) { }; // #if __has_cpp_attribute(no_unique_address) >=201803L and not defined(__NVCC__) and not defined(__PGI) - // BOOST_REQUIRE( sizeof(d2D)==sizeof(double*)+7*sizeof(std::size_t) ); + // BOOST_TEST( sizeof(d2D)==sizeof(double*)+7*sizeof(std::size_t) ); // #endif - BOOST_REQUIRE( d2D.is_compact() ); - BOOST_REQUIRE( rotated(d2D).is_compact() ); - BOOST_REQUIRE( d2D[3].is_compact() ); - BOOST_REQUIRE( ! rotated(d2D)[2].is_compact() ); + BOOST_TEST( d2D.is_compact() ); + BOOST_TEST( d2D.rotated().is_compact() ); + BOOST_TEST( d2D[3].is_compact() ); + BOOST_TEST( !(d2D.rotated()[2].is_compact()) ); } { - multi::array d2D({5, 3}); - BOOST_REQUIRE( d2D.is_compact() ); - BOOST_REQUIRE( rotated(d2D).is_compact() ); - BOOST_REQUIRE( d2D[3].is_compact() ); - BOOST_REQUIRE( ! rotated(d2D)[2].is_compact() ); + multi::array d2D({ 5, 3 }); + BOOST_TEST( d2D.is_compact() ); + BOOST_TEST( d2D.rotated().is_compact() ); + BOOST_TEST( d2D[3].is_compact() ); + BOOST_TEST( !d2D.rotated()[2].is_compact() ); } } #ifndef _MSC_VER // TODO(correaa) not supported by MSVC 14.3 in c++17 mode -constexpr auto f2(multi::array_ref&& array) -> double& { return std::move(array)[2]; } + +#if defined(__clang__) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunknown-warning-option" +#pragma clang diagnostic ignored "-Wunsafe-buffer-usage" +#endif BOOST_AUTO_TEST_CASE(array_legacy_c_2) { - double arr[5] = {150.0, 16.0, 17.0, 18.0, 19.0}; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) - BOOST_REQUIRE( &f2(arr) == &arr[2] ); + double arr[5] = { 150.0, 16.0, 17.0, 18.0, 19.0 }; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) + BOOST_TEST( &f2(arr) == &arr[2] ); } + +#if defined(__clang__) +#pragma clang diagnostic pop #endif + +#endif + +return boost::report_errors();} diff --git a/external_codes/boost_multi/multi/test/array_ptr.cpp b/external_codes/boost_multi/multi/test/array_ptr.cpp index c0ebf7348b..a79f873873 100644 --- a/external_codes/boost_multi/multi/test/array_ptr.cpp +++ b/external_codes/boost_multi/multi/test/array_ptr.cpp @@ -3,217 +3,283 @@ // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt -#include - -#include - -// Suppress warnings from boost.test -#if defined(__clang__) -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wold-style-cast" -# pragma clang diagnostic ignored "-Wundef" -# pragma clang diagnostic ignored "-Wconversion" -# pragma clang diagnostic ignored "-Wsign-conversion" -# pragma clang diagnostic ignored "-Wfloat-equal" -#elif defined(__GNUC__) -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wold-style-cast" -# pragma GCC diagnostic ignored "-Wundef" -# pragma GCC diagnostic ignored "-Wconversion" -# pragma GCC diagnostic ignored "-Wsign-conversion" -# pragma GCC diagnostic ignored "-Wfloat-equal" -#endif +#include // for layout_t, apply, subarray, array... // IWYU pragma: keep // bug in iwyu 8.22 + +#include // for equal +#include // for array // IWYU pragma: keep // bug in iwyu 8.22 +#include // for addressof +#include // for is_trivially_copy_assignable_v +#include // for as_const, addressof, exchange, move +#include // for vector + +// NOLINTNEXTLINE(fuchsia-trailing-return): trailing return helps readability +template auto fwd_array(T&& array) -> T&& { return std::forward(array); } -#ifndef BOOST_TEST_MODULE -# define BOOST_TEST_MAIN +#include +#define BOOST_AUTO_TEST_CASE(CasenamE) /**/ + +auto main() -> int { // NOLINT(readability-function-cognitive-complexity,bugprone-exception-escape) + namespace multi = boost::multi; + +#ifndef _MSC_VER // MSVC 14.40 is not constexpr ready? + // BOOST_AUTO_TEST_CASE(constexpr_ptr_access) { + // static constexpr auto test = [] { + // std::array buffer{{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}}; + // multi::array_ref arr({3, 3}, buffer.data()); + // auto ptr = &arr; + + // return (ptr->base() == buffer.data()); + // }(); + // static_assert(test); + // } #endif -#include + BOOST_AUTO_TEST_CASE(multi_array_ptr_equality) { + multi::array arr = { + {10, 20, 30}, + {40, 50, 60}, + {70, 80, 90}, + {10, 20, 30}, + }; + BOOST_TEST( arr[2] == arr[2] ); + BOOST_TEST( &arr[2] == &arr[2] ); + BOOST_TEST( !(&arr[2] == &(arr[2]({0, 2}))) ); + + BOOST_TEST( arr[2].base() == arr[2]({0, 2}).base() ); + BOOST_TEST( arr[2].layout() != arr[2]({0, 2}).layout() ); -namespace multi = boost::multi; + // what( arr[2], arr[2].sliced(0, 2), &(arr[2].sliced(0, 2)) ); + BOOST_TEST( &arr[2] != &(arr[2].sliced(0, 2)) ); -// NOLINTNEXTLINE(fuchsia-trailing-return): trailing return helps readability -template auto fwd_array(T&& array) -> T&& { return std::forward(array); } + BOOST_TEST( !( &arr[2] == &std::as_const(arr)[2]({0, 2})) ); + BOOST_TEST( &arr[2] == &fwd_array(arr[2]) ); + BOOST_TEST( &fwd_array(arr[2]) == &arr[2] ); -BOOST_AUTO_TEST_CASE(multi_array_ptr_equality) { - multi::array arr = { - {1.0, 2.0, 3.0}, - {4.0, 5.0, 6.0}, - {7.0, 8.0, 9.0}, - {1.0, 2.0, 3.0}, - }; - BOOST_REQUIRE( arr[2] == arr[2] ); - BOOST_REQUIRE( &arr[2] == &arr[2] ); - BOOST_REQUIRE( &arr[2] != &(arr[2]({0, 2})) ); - BOOST_REQUIRE( !( &arr[2] == &std::as_const(arr)[2]({0, 2})) ); - BOOST_REQUIRE( &arr[2] == &fwd_array(arr[2]) ); - BOOST_REQUIRE( &fwd_array(arr[2]) == &arr[2] ); - - auto arr_ptr = &arr[2]; - BOOST_REQUIRE( arr_ptr == arr_ptr ); - - auto& arr_ptr_ref = arr_ptr; - arr_ptr = arr_ptr_ref; - arr_ptr = std::move(arr_ptr_ref); - - auto arr_ptr2 = &std::as_const(arr)[2]; - BOOST_REQUIRE( arr_ptr == arr_ptr2 ); - BOOST_REQUIRE( arr_ptr2 == arr_ptr ); - BOOST_REQUIRE( !(arr_ptr != arr_ptr) ); - - auto& arr_ptr2_ref = arr_ptr2; - arr_ptr2 = arr_ptr2_ref; - arr_ptr2_ref = arr_ptr2; - - auto const& carr2 = arr[2]; - BOOST_REQUIRE( carr2[0] == arr[2][0] ); - BOOST_REQUIRE( carr2.base() == arr[2].base() ); - BOOST_REQUIRE( &carr2 == &std::as_const(arr)[2] ); - BOOST_REQUIRE( &carr2 == & arr [2] ); - - auto const& ac2 = carr2; // fwd_array(A[2]); - BOOST_REQUIRE( &ac2 == &std::as_const(arr)[2] ); - BOOST_REQUIRE( &std::as_const(arr)[2] == &ac2 ); - BOOST_REQUIRE( &ac2 == & arr [2] ); -} + auto arr_ptr = &arr[2]; + BOOST_TEST( arr_ptr == arr_ptr ); + + auto& arr_ptr_ref = arr_ptr; + arr_ptr = arr_ptr_ref; + + auto arr_ptr2 = &std::as_const(arr)[2]; + BOOST_TEST( arr_ptr == arr_ptr2 ); + BOOST_TEST( arr_ptr2 == arr_ptr ); + BOOST_TEST( !(arr_ptr != arr_ptr) ); + + auto& arr_ptr2_ref = arr_ptr2; + arr_ptr2 = arr_ptr2_ref; + arr_ptr2_ref = arr_ptr2; + + auto const& carr2 = arr[2]; + BOOST_TEST( carr2[0] == arr[2][0] ); + BOOST_TEST( carr2.base() == arr[2].base() ); + BOOST_TEST( &carr2 == &std::as_const(arr)[2] ); + BOOST_TEST( &carr2 == & arr [2] ); + + auto const& ac2 = carr2; // fwd_array(A[2]); + BOOST_TEST( &ac2 == &std::as_const(arr)[2] ); + BOOST_TEST( &std::as_const(arr)[2] == &ac2 ); + BOOST_TEST( &ac2 == & arr [2] ); + } + + BOOST_AUTO_TEST_CASE(subarray_ptr_1D) { + multi::subarray_ptr const ptr = nullptr; + BOOST_TEST(( ptr == multi::subarray_ptr{nullptr} )); + } + + BOOST_AUTO_TEST_CASE(subarray_ptr_2D) { + multi::subarray_ptr const ptr = nullptr; + BOOST_TEST(( ptr == multi::subarray_ptr{nullptr} )); + } -BOOST_AUTO_TEST_CASE(multi_array_ptr) { - { - // clang-format off + BOOST_AUTO_TEST_CASE(multi_array_ptr) { + { + // clang-format off std::array, 4> arr{ {{{0.0, 1.0, 2.0, 3.0, 4.0}}, {{5.0, 6.0, 7.0, 8.0, 9.0}}, {{10.0, 11.0, 12.0, 13.0, 14.0}}, {{15.0, 16.0, 17.0, 18.0, 19.0}}}, }; - // clang-format on + // clang-format on - multi::array_ptr const arrP{&arr}; + multi::array_ptr const arrP{&arr}; - BOOST_REQUIRE( arrP->extensions() == multi::extensions(arr) ); - BOOST_REQUIRE( extensions(*arrP) == multi::extensions(arr) ); + static_assert(std::is_trivially_copy_assignable_v>); + static_assert(std::is_trivially_copyable_v>); - using multi::extensions; - BOOST_REQUIRE( extensions(*arrP) == extensions(arr) ); - BOOST_REQUIRE( &arrP->operator[](1)[1] == &arr[1][1] ); - - multi::array_ptr const arrP2{&arr}; - BOOST_REQUIRE( arrP == arrP2 ); - BOOST_REQUIRE( ! (arrP != arrP2) ); - - std::array, 4> arr2{}; - multi::array_ptr arr2P{&arr2}; - BOOST_REQUIRE( arr2P != arrP ); - BOOST_REQUIRE( ! (arr2P == arrP) ); +#ifndef _MSC_VER + static_assert(std::is_trivially_default_constructible_v>); + static_assert(std::is_trivially_default_constructible_v>); + static_assert(std::is_trivially_default_constructible_v>); +#endif - arr2P = arrP; - BOOST_REQUIRE( arrP == arr2P ); - BOOST_REQUIRE( *arrP == *arr2P ); - BOOST_REQUIRE( arrP->operator==(*arrP) ); + static_assert(std::is_trivially_copyable_v>); + static_assert(std::is_trivially_copyable_v>); + static_assert(std::is_trivially_copyable_v>); - auto&& arrR = *arrP; - BOOST_REQUIRE( &arrR[1][1] == &arr[1][1] ); - BOOST_REQUIRE( arrR == *arrP ); - BOOST_REQUIRE( std::equal(arrR.begin(), arrR.end(), arrP->begin(), arrP->end()) ); - BOOST_REQUIRE( size(arrR) == arrP->size() ); +#ifndef _MSC_VER + static_assert(std::is_trivially_default_constructible_v>); +#endif + static_assert(std::is_trivially_copy_assignable_v>); + static_assert(std::is_trivially_copyable_v>); + + BOOST_TEST( (*arrP).extensions() == multi::extensions(arr) ); + BOOST_TEST( arrP->extensions() == multi::extensions(arr) ); + BOOST_TEST( extensions(*arrP) == multi::extensions(arr) ); + + using multi::extensions; + BOOST_TEST( extensions(*arrP) == extensions(arr) ); + + BOOST_TEST( &(*arrP).operator[](1)[1] == &arr[1][1] ); + BOOST_TEST( &arrP->operator[](1)[1] == &arr[1][1] ); + + multi::array_ptr const arrP2{&arr}; + BOOST_TEST( arrP == arrP2 ); + BOOST_TEST( !(arrP != arrP2) ); + + std::array, 4> arr2{}; + multi::array_ptr arr2P{&arr2}; + BOOST_TEST( arr2P != arrP ); + BOOST_TEST( !(arr2P == arrP) ); + + arr2P = arrP; + BOOST_TEST( arrP == arr2P ); + BOOST_TEST( *arrP == *arr2P ); + + BOOST_TEST( (*arrP).operator==(*arrP) ); + BOOST_TEST( arrP->operator==(*arrP) ); + + auto&& arrR = *arrP; + BOOST_TEST( &arrR[1][1] == &arr[1][1] ); + BOOST_TEST( arrR == *arrP ); + + BOOST_TEST( std::equal(arrR.begin(), arrR.end(), (*arrP).begin(), (*arrP).end()) ); + BOOST_TEST( std::equal(arrR.begin(), arrR.end(), arrP->begin(), arrP->end()) ); + + BOOST_TEST( arrR.size() == (*arrP).size() ); + BOOST_TEST( size(arrR) == arrP->size() ); + } + { + // clang-format off + std::array, 4> arr = {{ + std::array{ { 00, 10, 20, 30, 40 } }, + std::array{ { 50, 60, 70, 80, 90 } }, + std::array{ { 100, 110, 120, 130, 140 } }, + std::array{ { 150, 160, 170, 180, 190 } }, + }}; + // clang-format on + + std::vector> ptrs; + ptrs.emplace_back(&arr[0][0], 5); // NOLINT(readability-container-data-pointer) test access + ptrs.emplace_back(arr[2].data(), 5); + ptrs.emplace_back(&arr[3][0], 5); // NOLINT(readability-container-data-pointer) test access + + BOOST_TEST( &(*ptrs[2])[4] == &arr[3][4] ); + BOOST_TEST( (*ptrs[2])[4] == 190 ); + BOOST_TEST( ptrs[2]->operator[](4) == 190 ); + } + { + std::vector v1(100, 30); // testing std::vector of multi:array NOLINT(fuchsia-default-arguments-calls) + std::vector const v2(100, 40); // testing std::vector of multi:array NOLINT(fuchsia-default-arguments-calls) + + multi::array_ptr const v1P2D(v1.data(), {10, 10}); + multi::array_cptr const v2P2D(v2.data(), {10, 10}); + + *v1P2D = *v2P2D; + (*v1P2D).operator=(*v2P2D); + BOOST_TEST( v1[8] == 40 ); + + v1P2D->operator=(*v2P2D); + BOOST_TEST( v1[8] == 40 ); + } } - { - std::array, 4> arr = { - {std::array{{0.0, 1.0, 2.0, 3.0, 4.0}}, - std::array{{5.0, 6.0, 7.0, 8.0, 9.0}}, - std::array{{10.0, 11.0, 12.0, 13.0, 14.0}}, - std::array{{15.0, 16.0, 17.0, 18.0, 19.0}}}, - }; - std::vector> ptrs; - ptrs.emplace_back(&arr[0][0], 5); // NOLINT(readability-container-data-pointer) test access - ptrs.emplace_back(arr[2].data(), 5); - ptrs.emplace_back(&arr[3][0], 5); // NOLINT(readability-container-data-pointer) test access + BOOST_AUTO_TEST_CASE(span_like) { + std::vector vec = {00, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100}; // testing std::vector of multi:array NOLINT(fuchsia-default-arguments-calls) - BOOST_REQUIRE( &(*ptrs[2])[4] == &arr[3][4] ); - BOOST_REQUIRE( (*ptrs[2])[4] == 19 ); - BOOST_REQUIRE( ptrs[2]->operator[](4) == 19 ); - } - { - std::vector v1(100, 3.0); // testing std::vector of multi:array NOLINT(fuchsia-default-arguments-calls) - std::vector const v2(100, 4.0); // testing std::vector of multi:array NOLINT(fuchsia-default-arguments-calls) - multi::array_ptr const v1P2D(v1.data(), {10, 10}); - multi::array_cptr const v2P2D(v2.data(), {10, 10}); + using my_span = multi::array_ref; - *v1P2D = *v2P2D; - v1P2D->operator=(*v2P2D); + #if defined(__clang__) + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wunknown-warning-option" + #pragma clang diagnostic ignored "-Wunsafe-buffer-usage" + #endif - BOOST_REQUIRE( v1[8] == 4.0 ); - } -} + auto aP = &my_span{vec.data() + 2, {5}}; // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic) -BOOST_AUTO_TEST_CASE(span_like) { - std::vector vec = {0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0}; // testing std::vector of multi:array NOLINT(fuchsia-default-arguments-calls) + #if defined(__clang__) + #pragma clang diagnostic pop + #endif - using my_span = multi::array_ref; + BOOST_TEST( (*aP).size() == 5 ); + BOOST_TEST( aP->size() == 5 ); // doesn't work on MSVC? - auto aP = &my_span{vec.data() + 2, {5}}; // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic) - BOOST_REQUIRE( aP->size() == 5 ); - BOOST_REQUIRE( (*aP)[0] == 2.0 ); + BOOST_TEST( (*aP)[0] == 20 ); - auto const& aCRef = *aP; - BOOST_REQUIRE( aCRef.size() == 5 ); + auto const& aCRef = *aP; + BOOST_TEST( aCRef.size() == 5 ); - BOOST_REQUIRE( &aCRef[0] == &vec[2] ); - BOOST_REQUIRE( aCRef[0] == 2.0 ); + BOOST_TEST( &aCRef[0] == &vec[2] ); + BOOST_TEST( aCRef[0] == 20 ); - auto&& aRef = *aP; - aRef[0] = 99.0; - BOOST_REQUIRE( vec[2] == 99.0 ); -} + auto&& aRef = *aP; + // what(aP, aRef); + // (*aP)[0] = 990; + aRef[0] = 990; + BOOST_TEST( vec[2] == 990 ); + } -BOOST_AUTO_TEST_CASE(multi_array_ptr_assignment) { - multi::array arr = { - {1.0, 2.0, 3.0}, - {4.0, 5.0, 6.0}, - {7.0, 8.0, 9.0}, - {1.0, 2.0, 3.0}, - }; - { - auto rowP = &arr[2]; + BOOST_AUTO_TEST_CASE(multi_array_ptr_assignment) { + multi::array arr = { + {1.0, 2.0, 3.0}, + {4.0, 5.0, 6.0}, + {7.0, 8.0, 9.0}, + {1.0, 2.0, 3.0}, + }; + { + auto rowP = &arr[2]; - rowP = *std::addressof(rowP); + rowP = *std::addressof(rowP); - auto rowP2 = rowP; - rowP2 = rowP; // self assigment + auto rowP2 = rowP; + rowP2 = rowP; // self assigment - BOOST_REQUIRE( rowP == rowP2 ); - BOOST_REQUIRE( ! (rowP != rowP2) ); + BOOST_TEST( rowP == rowP2 ); + BOOST_TEST( !(rowP != rowP2) ); - auto rowP0 = &arr[0]; + auto rowP0 = &arr[0]; - BOOST_REQUIRE( rowP0 != rowP2 ); - BOOST_REQUIRE( ! (rowP0 == rowP2) ); + BOOST_TEST( rowP0 != rowP2 ); + BOOST_TEST( !(rowP0 == rowP2) ); - rowP2 = decltype(rowP2){nullptr}; - BOOST_REQUIRE( ! rowP2 ); + rowP2 = decltype(rowP2){nullptr}; + BOOST_TEST( !rowP2 ); - auto rowP3 = std::exchange(rowP, nullptr); - BOOST_REQUIRE( rowP3 == &arr[2] ); - BOOST_REQUIRE( rowP == nullptr ); - BOOST_REQUIRE( ! rowP ); - } - { - auto rowP = &arr(); + auto rowP3 = std::exchange(rowP, nullptr); + BOOST_TEST( rowP3 == &arr[2] ); + BOOST_TEST( rowP == nullptr ); + // BOOST_TEST( !rowP ); + } + { + auto rowP = &arr(); - rowP = *std::addressof(rowP); + rowP = *std::addressof(rowP); - decltype(rowP) rowP2; - rowP2 = rowP; + decltype(rowP) rowP2; + rowP2 = rowP; - BOOST_REQUIRE( rowP == rowP2 ); + BOOST_TEST( rowP == rowP2 ); - rowP2 = decltype(rowP2){nullptr}; - BOOST_REQUIRE( ! rowP2 ); + rowP2 = decltype(rowP2){nullptr}; + BOOST_TEST( !rowP2 ); - auto rowP3 = std::exchange(rowP, nullptr); - BOOST_REQUIRE( rowP3 == &arr() ); - BOOST_REQUIRE( rowP == nullptr ); - BOOST_REQUIRE( ! rowP ); + auto rowP3 = std::exchange(rowP, nullptr); + BOOST_TEST( rowP3 == &arr() ); + BOOST_TEST( rowP == nullptr ); + BOOST_TEST( !rowP ); + } } + + return boost::report_errors(); } diff --git a/external_codes/boost_multi/multi/test/array_ref.cpp b/external_codes/boost_multi/multi/test/array_ref.cpp index 8b476544ba..98b818ac98 100644 --- a/external_codes/boost_multi/multi/test/array_ref.cpp +++ b/external_codes/boost_multi/multi/test/array_ref.cpp @@ -3,136 +3,267 @@ // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt -#include +#include // for implicit_cast, explicit_cast + +#include // for for_each, equal +#include // for array +#include // for assert +#include // for int64_t +#include // for char_traits, operator<<, basic_o... +#include // for size +#include // for allocator, unique_ptr +#include // for accumulate, iota +#ifdef BOOST_MULTI_HAS_SPAN + #include // for span +#endif +#include // for basic_string, operator""s, string +// IWYU pragma: no_include // for tuple_element<>::type, __tuple_e... +#include // for remove_reference, remove_const +// #include // for bad_cast +#include // for as_const, move +#include // for vector + +namespace multi = boost::multi; + +#include +#define BOOST_AUTO_TEST_CASE(CasenamE) /**/ + +namespace boost::multi { -#include -#include // for std::cout -#include // for std::iota +template>> +using Array = + std::conditional_t< + std::is_reference_v, + std::conditional_t< + std::is_const_v>, + boost::multi::array_ref>, D> const&, + boost::multi::array_ref, D>& + >, + multi::array + >; + +} // end namespace boost::multi -// Suppress warnings from boost.test #if defined(__clang__) #pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wold-style-cast" -#pragma clang diagnostic ignored "-Wundef" -#pragma clang diagnostic ignored "-Wconversion" -#pragma clang diagnostic ignored "-Wsign-conversion" -#pragma clang diagnostic ignored "-Wfloat-equal" -#elif defined(__GNUC__) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wold-style-cast" -#pragma GCC diagnostic ignored "-Wundef" -#pragma GCC diagnostic ignored "-Wconversion" -#pragma GCC diagnostic ignored "-Wsign-conversion" -#pragma GCC diagnostic ignored "-Wfloat-equal" +#pragma clang diagnostic ignored "-Wunknown-warning-option" +#pragma clang diagnostic ignored "-Wunsafe-buffer-usage" // TODO(correaa) use checked span #endif -#ifndef BOOST_TEST_MODULE -#define BOOST_TEST_MAIN +auto f1d5(int const (&carr)[5]) -> int; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) +auto f1d5(int const (&carr)[5]) -> int { // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) + return carr[1]; +} + +void f2d54(int const (&carr)[5][4]); // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) +void f2d54(int const (&carr)[5][4]) { // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) + BOOST_TEST(carr[0][1] == 1); +} + +#if defined(__clang__) +#pragma clang diagnostic pop #endif -#include +template +auto trace_array_deduce(multi::array const& arr) -> T { + auto const& diag = arr.diagonal(); + return std::accumulate(diag.begin(), diag.end(), T{0}); +} + +template int trace_array_deduce(multi::array const&); -namespace multi = boost::multi; +template +auto trace_generic(Array const& arr) -> T { + auto const& diag = arr.diagonal(); + return std::accumulate(diag.begin(), diag.end(), T{0}); +} + +template double trace_generic>(multi::array const&); + +inline auto trace_separate_ref(multi::array_ref const& arr) -> int { + auto const& diag = arr.diagonal(); + return std::accumulate(diag.begin(), diag.end(), 0); +} + +inline auto trace_separate_sub(multi::subarray const& arr) -> int { + auto const& diag = arr.diagonal(); + return std::accumulate(diag.begin(), diag.end(), 0); +} + +inline auto trace_separate_ref2(multi::array_const_view arr) -> int { + auto const& diag = arr.diagonal(); + return std::accumulate(diag.begin(), diag.end(), 0); +} + +// unusable for arrays +inline auto trace_separate_ref3(multi::array_view arr) -> int { + auto const& diag = arr.diagonal(); + return std::accumulate(diag.begin(), diag.end(), 0); +} + +// unusable for arrays +inline auto trace_separate_ref4(multi::array_ref arr) -> int { + auto const& diag = arr.diagonal(); + return std::accumulate(diag.begin(), diag.end(), 0); +} + +// unusable for arrays +inline auto trace_separate_sub4(multi::subarray arr) -> int { + auto const& diag = arr.diagonal(); + return std::accumulate(diag.begin(), diag.end(), 0); +} + +template +auto mut_trace_array_deduce(multi::array& arr) -> T { + arr[0][1] = 40; + + auto const& diag = arr.diagonal(); + return std::accumulate(diag.begin(), diag.end(), T{0}); +} + +template double mut_trace_array_deduce(multi::array&); + +template +auto mut_trace_generic(Array& arr) -> T { + arr[0][1] = 40; + + auto const& diag = arr.diagonal(); + return std::accumulate(diag.begin(), diag.end(), T{0}); +} + +auto main() -> int { // NOLINT(readability-function-cognitive-complexity,bugprone-exception-escape) BOOST_AUTO_TEST_CASE(array_ref_from_carray) { + #if defined(__clang__) + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wunknown-warning-option" + #pragma clang diagnostic ignored "-Wunsafe-buffer-usage" + #endif + // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays): test - double arr[4][5] = { - { 0.0, 1.0, 2.0, 3.0, 4.0}, - { 5.0, 6.0, 7.0, 8.0, 9.0}, - {10.0, 11.0, 12.0, 13.0, 14.0}, - {15.0, 16.0, 17.0, 18.0, 19.0}, + int arr[4][5] = { + { 0, 10, 20, 30, 40}, + { 50, 60, 70, 80, 90}, + {100, 110, 120, 130, 140}, + {150, 160, 170, 180, 190}, }; - multi::array_ptr const map{&arr}; - BOOST_REQUIRE( &map->operator[](1)[1] == &arr[1][1] ); - BOOST_REQUIRE( (*&arr)[1][1] == 6.0 ); + multi::array_ptr const map{&arr}; - multi::array_ref&& mar = *map; + BOOST_TEST( &(*map).operator[](1)[1] == &arr[1][1] ); + BOOST_TEST( &map->operator[](1)[1] == &arr[1][1] ); - BOOST_REQUIRE( &mar[1][1] == &arr[1][1] ); + BOOST_TEST( (*&arr)[1][1] == 60 ); - mar[1][1] = 9.0; - BOOST_REQUIRE( &mar[1][1] == &arr[1][1] ); + multi::array_ref&& mar = *map; + + BOOST_TEST( &mar[1][1] == &arr[1][1] ); + + mar[1][1] = 90; + BOOST_TEST( &mar[1][1] == &arr[1][1] ); auto const& a_const = arr; - // double const(&a_const)[4][5] = a; - BOOST_REQUIRE(&a_const[1][1] == &arr[1][1]); + // int const(&a_const)[4][5] = a; + BOOST_TEST(&a_const[1][1] == &arr[1][1]); static_assert(decltype(mar(2, {1, 3}))::rank_v == 1); - BOOST_REQUIRE( size(mar(2, {1, 3})) == 2 ); - BOOST_REQUIRE( &mar(2, {1, 3})[1] == &arr[2][2] ); + BOOST_TEST( size(mar(2, {1, 3})) == 2 ); + BOOST_TEST( &mar(2, {1, 3})[1] == &arr[2][2] ); - [[maybe_unused]] multi::array_ref const& cmar = *map; + [[maybe_unused]] multi::array_ref const& cmar = *map; // *(cmar.base()) = 99.0; // *(cmar[0].base()) = 88.0; // *(cmar.data_elements()) = 99.0; + + #if defined(__clang__) + #pragma clang diagnostic pop + #endif } +#if !defined(__NVCC__) BOOST_AUTO_TEST_CASE(array_ref_test_ub) { + #if defined(__GNUC__) || defined(__NVCC__) + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Warray-bounds" + #endif + // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays): test - double arr[4][4] = { - { 0.0, 1.0, 2.0, 3.0}, - { 5.0, 6.0, 7.0, 8.0}, - {10.0, 11.0, 12.0, 13.0}, - {15.0, 16.0, 17.0, 18.0}, + int arr[][4] = { + { 0, 10, 20, 30}, + { 50, 60, 70, 80}, + {100, 110, 120, 130}, + {150, 160, 170, 180}, }; - multi::array_ref const map{arr}; // multi::array_ref const map(&arr[0][0], {4, 4}); + multi::array_ref const map{arr}; // multi::array_ref const map(&arr[0][0], {4, 4}); auto const& diag = map.diagonal(); - BOOST_REQUIRE( diag.begin() != diag.end() ); - // -Werror=array-bounds - // BOOST_REQUIRE( std::accumulate(diag.begin(), diag.end(), 0.0) == 0.0 + 6.0 + 12.0 + 18.0 ); + BOOST_TEST( diag.begin() != diag.end() ); + // BOOST_TEST( std::accumulate(diag.begin(), diag.end(), 0) == 0 + 6 + 12 + 18 ); + #if defined(__GNUC__) + #pragma GCC diagnostic pop + #endif } +#endif BOOST_AUTO_TEST_CASE(array_ref_test_no_ub) { // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays): test - double arr[5][4] = { - { 0.0, 1.0, 2.0, 3.0}, - { 5.0, 6.0, 7.0, 8.0}, - {10.0, 11.0, 12.0, 13.0}, - {15.0, 16.0, 17.0, 18.0}, + int arr[5][4] = { + { 00, 10, 20, 30}, + { 50, 60, 70, 80}, + {100, 110, 120, 130}, + {150, 160, 170, 180}, }; - multi::array_ref const map(&arr[0][0], {4, 4}); - // multi::array_ref const map{reinterpret_cast(arr)}; // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast,cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) + multi::array_ref const map(&arr[0][0], {4, 4}); + auto const& diag = map.diagonal(); - BOOST_REQUIRE( diag.begin() != diag.end() ); - BOOST_REQUIRE( std::accumulate(diag.begin(), diag.end(), 0.0) == 0.0 + 6.0 + 12.0 + 18.0 ); + BOOST_TEST( diag.begin() != diag.end() ); + BOOST_TEST( std::accumulate(diag.begin(), diag.end(), 0) == 0 + 60 + 120 + 180 ); } BOOST_AUTO_TEST_CASE(array_ref_test_no_ub2) { + #if defined(__clang__) + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wunknown-warning-option" + #pragma clang diagnostic ignored "-Wunsafe-buffer-usage" + #endif + // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays): test - double arr[][4] = { + int arr[][4] = { {}, - {0.0, 1.0, 2.0, 3.0}, - {5.0, 6.0, 7.0, 8.0}, - {10.0, 11.0, 12.0, 13.0}, - {15.0, 16.0, 17.0, 18.0}, + {00, 10, 20, 30}, + {50, 60, 70, 80}, + {100, 110, 120, 130}, + {150, 160, 170, 180}, {}, }; - multi::array_ref const map(&arr[1][0], {4, 4}); - // multi::array_ref const map{reinterpret_cast(arr)}; // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast,cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) - auto const& diag = map.diagonal(); - BOOST_REQUIRE( diag.begin() != diag.end() ); - BOOST_REQUIRE( std::accumulate(diag.begin(), diag.end(), 0.0) == 0.0 + 6.0 + 12.0 + 18.0 ); + multi::array_ref const map(&arr[1][0], {4, 4}); + + #if defined(__clang__) + #pragma clang diagnostic pop + #endif + + auto const& diag = map.diagonal(); + BOOST_TEST( diag.begin() != diag.end() ); + BOOST_TEST( std::accumulate(diag.begin(), diag.end(), 0) == 0 + 60 + 120 + 180 ); } BOOST_AUTO_TEST_CASE(array_ref_test_allocated_ub_unique_ptr) { // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) for illustration - std::unique_ptr const arrp(new double const [4UL * 4UL] { 0.0, 1.0, 2.0, 3.0, 5.0, 6.0, 7.0, 8.0, 10.0, 11.0, 12.0, 13.0, 15.0, 16.0, 17.0, 18.0 }); + std::unique_ptr const arrp(new int const[4UL * 4UL]{0, 10, 20, 30, 50, 60, 70, 80, 100, 110, 120, 130, 150, 160, 170, 180}); - BOOST_REQUIRE( arrp[3] == 3.0 ); + BOOST_TEST( arrp[3] == 30 ); { - multi::array_ref const map(arrp.get(), {4, 4}); // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast,cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) + multi::array_ref const map(arrp.get(), {4, 4}); auto const& diag = map.diagonal(); - BOOST_REQUIRE( diag.begin() != diag.end() ); - BOOST_REQUIRE( std::accumulate(diag.begin(), diag.end(), 0.0) == 0.0 + 6.0 + 12.0 + 18.0 ); // is this UB? + BOOST_TEST( diag.begin() != diag.end() ); + BOOST_TEST( std::accumulate(diag.begin(), diag.end(), 00) == 00 + 60 + 120 + 180 ); // is this UB? } } @@ -140,55 +271,63 @@ BOOST_AUTO_TEST_CASE(array_ref_1D_reindexed) { using namespace std::string_literals; // NOLINT(build/namespaces) for literal "string"s // clang-format off - std::array stdarr = {{"a"s, "b"s, "c"s, "d"s, "e"s}}; + std::array stdarr = {{"a"s, "b"s, "c"s, "d"s, "e"s}}; // NOLINT(misc-include-cleaner) bug in clang-tidy 18.1.3 // clang-format on multi::array_ref mar = *multi::array_ptr(&stdarr); - BOOST_REQUIRE( &mar[1] == &stdarr[1] ); - BOOST_REQUIRE( sizes(mar.reindexed(1)) == sizes(mar) ); + BOOST_TEST( &mar[1] == &stdarr[1] ); + BOOST_TEST( sizes(mar.reindexed(1)) == sizes(mar) ); auto diff = &(mar.reindexed(1)[1]) - &mar[0]; - BOOST_REQUIRE( diff == 0 ); + BOOST_TEST( diff == 0 ); - BOOST_REQUIRE( &mar.blocked(2, 4)[2] == &mar[2] ); - for(auto idx : extension(mar.stenciled({2, 4}))) { - BOOST_REQUIRE( &mar.stenciled({2, 4})[idx] == &mar[idx] ); + BOOST_TEST( &mar.blocked(2, 4)[2] == &mar[2] ); + for(auto idx : extension(mar.stenciled({2, 4}))) { // NOLINT(altera-unroll-loops) + BOOST_TEST( &mar.stenciled({2, 4})[idx] == &mar[idx] ); } // clang-format off multi::array arr({{2, 7}}, std::string{"xx"}); // NOLINT(fuchsia-default-arguments-calls) std::string // clang-format on - BOOST_REQUIRE( size(arr) == 5 ); - BOOST_REQUIRE( extension(arr) == multi::iextension(2, 7) ); + BOOST_TEST( size(arr) == 5 ); + BOOST_TEST( extension(arr) == multi::iextension(2, 7) ); arr[2] = "a"; arr[3] = "b"; arr[4] = "c"; arr[5] = "d"; arr[6] = "e"; - BOOST_REQUIRE( std::equal(arr.begin(), arr.end(), mar.begin(), mar.end()) ); + BOOST_TEST( std::equal(arr.begin(), arr.end(), mar.begin(), mar.end()) ); auto arrB = multi::array({"a", "b", "c", "d", "e"}).reindex(2); // std::string NOLINT(fuchsia-default-arguments-calls) - BOOST_REQUIRE( size(arrB) == 5 ); - BOOST_REQUIRE( arrB[2] == "a" ); - BOOST_REQUIRE( arrB[6] == "e" ); + BOOST_TEST( size(arrB) == 5 ); + BOOST_TEST( arrB[2] == "a" ); + BOOST_TEST( arrB[6] == "e" ); } BOOST_AUTO_TEST_CASE(array_ref_of_nested_std_array_reindexed) { - std::array, 4> arr = { - {{{0.0, 1.0, 2.0, 3.0, 4.0}}, - {{5.0, 6.0, 7.0, 8.0, 9.0}}, - {{10.0, 11.0, 12.0, 13.0, 14.0}}, - {{15.0, 16.0, 17.0, 18.0, 19.0}}}, - }; + // clang-format off + std::array, 4> arr = {{ + { { 0.0, 1.0, 2.0, 3.0, 4.0 } }, + { { 5.0, 6.0, 7.0, 8.0, 9.0 } }, + { { 10.0, 11.0, 12.0, 13.0, 14.0 } }, + { { 15.0, 16.0, 17.0, 18.0, 19.0 } } + }}; + // clang-format on // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays): test type multi::array_ref mar = *multi::array_ptr(&arr); - BOOST_REQUIRE( &mar[1][1] == &arr[1][1] ); + BOOST_TEST( &mar[1][1] == &arr[1][1] ); } BOOST_AUTO_TEST_CASE(array_ref_reindexed) { + #if defined(__clang__) + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wunknown-warning-option" + #pragma clang diagnostic ignored "-Wunsafe-buffer-usage" + #endif + // NOLINTNEXTLINE(hicpp-avoid-c-arrays, modernize-avoid-c-arrays, cppcoreguidelines-avoid-c-arrays): test double arr[4][5] = { { 0.0, 1.0, 2.0, 3.0, 4.0}, @@ -200,37 +339,42 @@ BOOST_AUTO_TEST_CASE(array_ref_reindexed) { // NOLINTNEXTLINE(hicpp-avoid-c-arrays, modernize-avoid-c-arrays, cppcoreguidelines-avoid-c-arrays): special type multi::array_ref mar = *multi::array_ptr(&arr); - BOOST_REQUIRE( &mar[1][1] == &arr[1][1] ); - BOOST_REQUIRE( size(mar .reindexed(1)) == size(mar) ); - BOOST_REQUIRE( size(mar[0].reindexed(1)) == size(mar[0]) ); + BOOST_TEST( &mar[1][1] == &arr[1][1] ); + + #if defined(__clang__) + #pragma clang diagnostic pop + #endif + + BOOST_TEST( size(mar .reindexed(1)) == size(mar) ); + BOOST_TEST( size(mar[0].reindexed(1)) == size(mar[0]) ); - BOOST_REQUIRE( sizes(mar.reindexed(1)) == sizes(mar) ); + BOOST_TEST( sizes(mar.reindexed(1)) == sizes(mar) ); - BOOST_REQUIRE( &mar.reindexed(1)[1][0] == &mar[0][0] ); + BOOST_TEST( &mar.reindexed(1)[1][0] == &mar[0][0] ); - BOOST_REQUIRE( sizes(mar[0].reindexed(1)) == sizes(mar[0]) ); - BOOST_REQUIRE( mar[0].reindexed(1).extension().first() == mar[0].extension().first () + 1 ); - BOOST_REQUIRE( mar[0].reindexed(1).extension().last() == mar[0].extension().last() + 1 ); + BOOST_TEST( mar[0].reindexed(1).sizes() == mar[0].sizes() ); + BOOST_TEST( mar[0].reindexed(1).extension().first() == mar[0].extension().first () + 1 ); + BOOST_TEST( mar[0].reindexed(1).extension().last() == mar[0].extension().last() + 1 ); auto diff = &mar[0].reindexed(1)[1] - &mar[0][0]; - BOOST_REQUIRE( diff == 0 ); + BOOST_TEST( diff == 0 ); - // BOOST_REQUIRE( &(((mar<<1).reindexed(2)>>1).reindexed(1))[1][2] == &mar[0][0] ); - BOOST_REQUIRE( &mar.reindexed(1, 2)[1][2] == &mar[0][0] ); + // BOOST_TEST( &(((mar<<1).reindexed(2)>>1).reindexed(1))[1][2] == &mar[0][0] ); + BOOST_TEST( &mar.reindexed(1, 2)[1][2] == &mar[0][0] ); - BOOST_REQUIRE( &mar.reindexed(1)({1, 5})[1][0] == &mar[0][0] ); + BOOST_TEST( &mar.reindexed(1)({1, 5})[1][0] == &mar[0][0] ); - BOOST_REQUIRE(( sizes(mar.stenciled({2, 4})) == decltype(sizes(mar.stenciled({2, 4}))){2, 5} )); - BOOST_REQUIRE( &mar.stenciled({2, 4})[2][0] == &mar[2][0] ); - BOOST_REQUIRE( &mar.stenciled({2, 4}, {1, 3})[2][1] == &mar[2][1] ); + BOOST_TEST(( sizes(mar.stenciled({2, 4})) == decltype(sizes(mar.stenciled({2, 4}))){2, 5} )); + BOOST_TEST( &mar.stenciled({2, 4})[2][0] == &mar[2][0] ); + BOOST_TEST( &mar.stenciled({2, 4}, {1, 3})[2][1] == &mar[2][1] ); - // BOOST_REQUIRE( &mar[0][0] == mar.origin() ); // origin changed meaning in on 2020/Dec/16 - // BOOST_REQUIRE( mar.base() == mar.origin() ); + // BOOST_TEST( &mar[0][0] == mar.origin() ); // origin changed meaning in on 2020/Dec/16 + // BOOST_TEST( mar.base() == mar.origin() ); - // BOOST_REQUIRE( mar.stenciled({2, 4}).origin() == mar.origin() ); // origin changed meaning in on 2020/Dec/16 - BOOST_REQUIRE( mar.stenciled({2, 4}).base() != mar.base() ); + // BOOST_TEST( mar.stenciled({2, 4}).origin() == mar.origin() ); // origin changed meaning in on 2020/Dec/16 + BOOST_TEST( mar.stenciled({2, 4}).base() != mar.base() ); - BOOST_REQUIRE( &mar.stenciled({2, 4})[2][0] == mar.stenciled({2, 4}).base() ); + BOOST_TEST( &mar.stenciled({2, 4})[2][0] == mar.stenciled({2, 4}).base() ); { // NOLINTBEGIN(fuchsia-default-arguments-calls) std::string ctor @@ -241,8 +385,8 @@ BOOST_AUTO_TEST_CASE(array_ref_reindexed) { }; // NOLINTEND(fuchsia-default-arguments-calls) std::string ctor arrB.reindex(2); - BOOST_REQUIRE( size(arrB) == 3 ); - BOOST_REQUIRE( arrB[2][0] == "a" ); + BOOST_TEST( size(arrB) == 3 ); + BOOST_TEST( arrB[2][0] == "a" ); } { // NOLINTBEGIN(fuchsia-default-arguments-calls) std::string ctor @@ -253,8 +397,8 @@ BOOST_AUTO_TEST_CASE(array_ref_reindexed) { }; // NOLINTEND(fuchsia-default-arguments-calls) std::string ctor arrB.reindex(2, 1); - BOOST_REQUIRE( size(arrB) == 3 ); - BOOST_REQUIRE( arrB[2][1] == "a" ); + BOOST_TEST( size(arrB) == 3 ); + BOOST_TEST( arrB[2][1] == "a" ); } { using namespace std::string_literals; // NOLINT(build/namespaces) for literal "string"s @@ -264,15 +408,15 @@ BOOST_AUTO_TEST_CASE(array_ref_reindexed) { {"h"s, "i"s, "j"s, "k"s, "l"s}, }); // .reindex(2, 1); // std::string NOLINT(fuchsia-default-arguments-calls) - BOOST_REQUIRE( arrB.reindex(2).extension() == multi::iextension(2, 5) ); + BOOST_TEST( arrB.reindex(2).extension() == multi::iextension(2, 5) ); auto exts = arrB.reindexed(2).extensions(); multi::array const arrC(exts); - BOOST_REQUIRE( size(arrC) == 3 ); - BOOST_REQUIRE( size(arrC) == size(arrB) ); + BOOST_TEST( size(arrC) == 3 ); + BOOST_TEST( size(arrC) == size(arrB) ); - BOOST_REQUIRE( arrC.extension().first() == 2 ); - BOOST_REQUIRE( arrC.extension().last() == 5 ); + BOOST_TEST( arrC.extension().first() == 2 ); + BOOST_TEST( arrC.extension().last() == 5 ); } } @@ -283,9 +427,10 @@ BOOST_AUTO_TEST_CASE(array_ref_with_stencil) { {{10.0, 11.0, 12.0, 13.0, 14.0}}, {{15.0, 16.0, 17.0, 18.0, 19.0}}}, }; + // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) test type auto const& mar = *multi::array_ptr(&arr); - BOOST_REQUIRE( mar.size() == 4 ); + BOOST_TEST( mar.size() == 4 ); // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) test type multi::array ss = { @@ -295,8 +440,8 @@ BOOST_AUTO_TEST_CASE(array_ref_with_stencil) { }; auto const& stencil = ss.reindexed(-1, -1); - BOOST_REQUIRE( stencil.size() == 3 ); - BOOST_REQUIRE( &stencil[-1][-1] == stencil.base() ); + BOOST_TEST( stencil.size() == 3 ); + BOOST_TEST( &stencil[-1][-1] == stencil.base() ); } BOOST_AUTO_TEST_CASE(array_ref_1D_from_vector) { @@ -304,8 +449,8 @@ BOOST_AUTO_TEST_CASE(array_ref_1D_from_vector) { // clang-format off multi::array_ref aref({{1, 3}}, vec.data()); // clang-format on - BOOST_REQUIRE( aref.extension() == multi::iextension(1, 3) ); - BOOST_REQUIRE( &aref[1] == vec.data() ); + BOOST_TEST( aref.extension() == multi::iextension(1, 3) ); + BOOST_TEST( &aref[1] == vec.data() ); } BOOST_AUTO_TEST_CASE(array_ref_2D_from_vector) { @@ -313,7 +458,27 @@ BOOST_AUTO_TEST_CASE(array_ref_2D_from_vector) { multi::array_ref aref({2, 3}, vec.data()); - BOOST_REQUIRE( &aref[1][0] == &vec[3] ); + BOOST_TEST( &aref[1][0] == &vec[3] ); +} + +BOOST_AUTO_TEST_CASE(array_ref_from_subarray) { + std::vector vec = { // std::string NOLINT(fuchsia-default-arguments-calls) + 1, 2, 3, 4, + 5, 6, 7, 8, + 9, 10, 11, 12, + 13, 14, 15, 16 + }; + + multi::array_ref aref({4, 4}, vec.data()); + + multi::array barr = { + { 1, 2, 3, 4}, + { 5, 6, 7, 8}, + { 9, 10, 11, 12}, + {13, 14, 15, 16} + }; + + aref = barr(); } BOOST_AUTO_TEST_CASE(array_ref_2D_from_vector_with_offset) { @@ -327,114 +492,143 @@ BOOST_AUTO_TEST_CASE(array_ref_2D_from_vector_with_offset) { #ifndef _MSC_VER auto const [exts0, exts1] = exts; #else - auto const exts0 = std::get<0>(exts); - auto const exts1 = std::get<1>(exts); + auto const exts0 = get<0>(exts); + auto const exts1 = get<1>(exts); #endif - BOOST_REQUIRE( exts0 == multi::iextension(1, 3) ); + BOOST_TEST( exts0 == multi::iextension(1, 3) ); - BOOST_REQUIRE( exts1.first() == 1 ); - BOOST_REQUIRE( exts1.last () == 4 ); + BOOST_TEST( exts1.first() == 1 ); + BOOST_TEST( exts1.last () == 4 ); - BOOST_REQUIRE( exts1 == multi::iextension(1, 4) ); + BOOST_TEST( exts1 == multi::iextension(1, 4) ); - BOOST_REQUIRE( exts == decltype(exts)(multi::iextension(1, 3), multi::iextension(1, 4)) ); + BOOST_TEST( exts == decltype(exts)(multi::iextension(1, 3), multi::iextension(1, 4)) ); } { auto exts = aref.extensions(); - BOOST_REQUIRE( std::get<0>(exts) == multi::iextension(1, 3) ); - BOOST_REQUIRE( std::get<1>(exts).first() == 1 ); - BOOST_REQUIRE( std::get<1>(exts).last () == 4 ); - BOOST_REQUIRE( std::get<1>(exts) == multi::iextension(1, 4) ); - BOOST_REQUIRE( exts == decltype(exts)(multi::iextension(1, 3), multi::iextension(1, 4)) ); + + using std::get; + + BOOST_TEST( get<0>(exts) == multi::iextension(1, 3) ); + BOOST_TEST( get<1>(exts).first() == 1 ); + BOOST_TEST( get<1>(exts).last () == 4 ); + BOOST_TEST( get<1>(exts) == multi::iextension(1, 4) ); + BOOST_TEST( exts == decltype(exts)(multi::iextension(1, 3), multi::iextension(1, 4)) ); } { auto const exts = aref.extensions(); - BOOST_REQUIRE( std::get<0>(exts) == multi::iextension(1, 3) ); - BOOST_REQUIRE( std::get<1>(exts).first() == 1 ); - BOOST_REQUIRE( std::get<1>(exts).last () == 4 ); - BOOST_REQUIRE( std::get<1>(exts) == multi::iextension(1, 4) ); - BOOST_REQUIRE( exts == decltype(exts)(multi::iextension(1, 3), multi::iextension(1, 4)) ); + + using std::get; + + BOOST_TEST( get<0>(exts) == multi::iextension(1, 3) ); + BOOST_TEST( get<1>(exts).first() == 1 ); + BOOST_TEST( get<1>(exts).last () == 4 ); + BOOST_TEST( get<1>(exts) == multi::iextension(1, 4) ); + + BOOST_TEST( exts == decltype(exts)(multi::iextension(1, 3), multi::iextension(1, 4)) ); } { auto const exts = aref.extensions(); - BOOST_REQUIRE( exts.get<0>() == multi::iextension(1, 3) ); - BOOST_REQUIRE( exts.get<1>().first() == 1 ); - BOOST_REQUIRE( exts.get<1>().last () == 4 ); - BOOST_REQUIRE( exts.get<1>() == multi::iextension(1, 4) ); - BOOST_REQUIRE(( exts == decltype(exts){multi::iextension(1, 3), multi::iextension(1, 4)} )); + BOOST_TEST( exts.get<0>() == multi::iextension(1, 3) ); + BOOST_TEST( exts.get<1>().first() == 1 ); + BOOST_TEST( exts.get<1>().last () == 4 ); + BOOST_TEST( exts.get<1>() == multi::iextension(1, 4) ); + BOOST_TEST(( exts == decltype(exts){multi::iextension(1, 3), multi::iextension(1, 4)} )); } { auto const exts = aref.extensions(); - BOOST_REQUIRE( std::get<0>(exts) == multi::iextension(1, 3) ); - BOOST_REQUIRE( std::get<1>(exts).first() == 1 ); - BOOST_REQUIRE( std::get<1>(exts).last () == 4 ); - BOOST_REQUIRE( std::get<1>(exts) == multi::iextension(1, 4) ); - BOOST_REQUIRE( exts == decltype(exts)(multi::iextension(1, 3), multi::iextension(1, 4)) ); + + using std::get; + + BOOST_TEST( get<0>(exts) == multi::iextension(1, 3) ); + BOOST_TEST( get<1>(exts).first() == 1 ); + BOOST_TEST( get<1>(exts).last () == 4 ); + BOOST_TEST( get<1>(exts) == multi::iextension(1, 4) ); + + BOOST_TEST( exts == decltype(exts)(multi::iextension(1, 3), multi::iextension(1, 4)) ); } { - BOOST_REQUIRE( std::get<0>(aref.extensions()) == multi::iextension(1, 3) ); - BOOST_REQUIRE( std::get<1>(aref.extensions()).first() == 1 ); - BOOST_REQUIRE( std::get<1>(aref.extensions()).last () == 4 ); - BOOST_REQUIRE( std::get<1>(aref.extensions()) == multi::iextension(1, 4) ); - BOOST_REQUIRE( aref.extensions() == decltype(aref.extensions())(multi::iextension(1, 3), multi::iextension(1, 4)) ); + using std::get; // workaround use of function template name with no prior declaration in function call with explicit template arguments is a C++20 extension [-Wc++20-extensions] + + BOOST_TEST( get<0>(aref.extensions()) == multi::iextension(1, 3) ); + + BOOST_TEST( get<1>(aref.extensions()).first() == 1 ); + BOOST_TEST( get<1>(aref.extensions()).last () == 4 ); + + BOOST_TEST( get<1>(aref.extensions()) == multi::iextension(1, 4) ); + BOOST_TEST( aref.extensions() == decltype(aref.extensions())(multi::iextension(1, 3), multi::iextension(1, 4)) ); } { + using std::get; // workaround use of function template name with no prior declaration in function call with explicit template arguments is a C++20 extension [-Wc++20-extensions] + auto ss = aref.sizes(); - BOOST_REQUIRE( std::get<0>(ss) == 2 ); - BOOST_REQUIRE( std::get<1>(ss) == 3 ); - BOOST_REQUIRE( ss == decltype(ss)(2, 3) ); + BOOST_TEST( get<0>(ss) == 2 ); + BOOST_TEST( get<1>(ss) == 3 ); + BOOST_TEST( ss == decltype(ss)(2, 3) ); } { auto [nn, mm] = aref.sizes(); - BOOST_REQUIRE( nn == 2 ); - BOOST_REQUIRE( mm == 3 ); + BOOST_TEST( nn == 2 ); + BOOST_TEST( mm == 3 ); } { + using std::get; + auto const ss = aref.sizes(); - BOOST_REQUIRE( std::get<0>(ss) == 2 ); - BOOST_REQUIRE( std::get<1>(ss) == 3 ); - BOOST_REQUIRE( ss == decltype(ss)(2, 3) ); + BOOST_TEST( get<0>(ss) == 2 ); + BOOST_TEST( get<1>(ss) == 3 ); + BOOST_TEST( ss == decltype(ss)(2, 3) ); } { - BOOST_REQUIRE( std::get<0>(aref.sizes()) == 2 ); - BOOST_REQUIRE( std::get<1>(aref.sizes()) == 3 ); - BOOST_REQUIRE( aref.sizes() == decltype(aref.sizes())(2, 3) ); + using std::get; // workaround use of function template name with no prior declaration in function call with explicit template arguments is a C++20 extension [-Wc++20-extensions] + + BOOST_TEST( get<0>(aref.sizes()) == 2 ); + BOOST_TEST( get<1>(aref.sizes()) == 3 ); + BOOST_TEST( aref.sizes() == decltype(aref.sizes())(2, 3) ); } { auto const ss = aref.sizes(); - using std::get; - BOOST_REQUIRE( get<0>(ss) == 2 ); - BOOST_REQUIRE( get<1>(ss) == 3 ); - BOOST_REQUIRE( ss == decltype(ss)(2, 3) ); + + using std::get; // workaround use of function template name with no prior declaration in function call with explicit template arguments is a C++20 extension [-Wc++20-extensions] + + BOOST_TEST( get<0>(ss) == 2 ); + BOOST_TEST( get<1>(ss) == 3 ); + BOOST_TEST( ss == decltype(ss)(2, 3) ); } { using std::get; - BOOST_REQUIRE( get<0>(aref.sizes()) == 2 ); - BOOST_REQUIRE( get<1>(aref.sizes()) == 3 ); - BOOST_REQUIRE( aref.sizes() == decltype(aref.sizes())(2, 3) ); + BOOST_TEST( get<0>(aref.sizes()) == 2 ); + BOOST_TEST( get<1>(aref.sizes()) == 3 ); + BOOST_TEST( aref.sizes() == decltype(aref.sizes())(2, 3) ); } -#if __cplusplus >= 202002L || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L) // GCC: use of function template name with no prior declaration in function call with explicit template arguments is a C++20 extension + +// vvv GCC: use of function template name with no prior declaration in function call with explicit template arguments is a C++20 extension +#if __cplusplus >= 202002L || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L) { + using std::get; // workaround use of function template name with no prior declaration in function call with explicit template arguments is a C++20 extension [-Wc++20-extensions] + auto const ss = aref.sizes(); - BOOST_REQUIRE( get<0>(ss) == 2 ); - BOOST_REQUIRE( get<1>(ss) == 3 ); - BOOST_REQUIRE( ss == decltype(ss)(2, 3) ); + BOOST_TEST( get<0>(ss) == 2 ); + BOOST_TEST( get<1>(ss) == 3 ); + BOOST_TEST( ss == decltype(ss)(2, 3) ); } { - BOOST_REQUIRE( get<0>(aref.sizes()) == 2 ); - BOOST_REQUIRE( get<1>(aref.sizes()) == 3 ); - BOOST_REQUIRE( aref.sizes() == decltype(aref.sizes())(2, 3) ); + using std::get; // workaround use of function template name with no prior declaration in function call with explicit template arguments is a C++20 extension [-Wc++20-extensions] + + BOOST_TEST( get<0>(aref.sizes()) == 2 ); + BOOST_TEST( get<1>(aref.sizes()) == 3 ); + BOOST_TEST( aref.sizes() == decltype(aref.sizes())(2, 3) ); } #endif - BOOST_REQUIRE( &aref[1][1] == vec.data() ); + BOOST_TEST( &aref[1][1] == vec.data() ); } BOOST_AUTO_TEST_CASE(array_2D_with_offset) { multi::array const arr({multi::iextension(1, 3), multi::iextension(2, 5)}, 1.2); - BOOST_REQUIRE( arr.extension().first() == 1 ); - BOOST_REQUIRE( arr.extension().last () == 3 ); + BOOST_TEST( arr.extension().first() == 1 ); + BOOST_TEST( arr.extension().last () == 3 ); } BOOST_AUTO_TEST_CASE(array_ref_1D) { @@ -445,25 +639,25 @@ BOOST_AUTO_TEST_CASE(array_ref_1D) { multi::array_ref&& mar = *multi::array_ptr{&arr}; // multi::Array mar = *multi::Array(&a); - BOOST_REQUIRE( extension(mar).first() == 0 ); - BOOST_REQUIRE( extension(mar).last() == 5 ); + BOOST_TEST( extension(mar).first() == 0 ); + BOOST_TEST( extension(mar).last() == 5 ); auto&& mar1 = mar.reindexed(1); - BOOST_REQUIRE( extension(mar1).size() == extension(mar).size() ); + BOOST_TEST( extension(mar1).size() == extension(mar).size() ); - BOOST_REQUIRE( mar1.extension() == extension(mar1) ); - BOOST_REQUIRE( extension(mar1).first() == 1 ); - BOOST_REQUIRE( mar1.extension().first() == 1 ); - BOOST_REQUIRE( mar1.extension().last() == 6 ); - BOOST_REQUIRE( *extension(mar1).begin() == 1 ); + BOOST_TEST( mar1.extension() == extension(mar1) ); + BOOST_TEST( extension(mar1).first() == 1 ); + BOOST_TEST( mar1.extension().first() == 1 ); + BOOST_TEST( mar1.extension().last() == 6 ); + BOOST_TEST( *extension(mar1).begin() == 1 ); - BOOST_REQUIRE( size(mar1) == size(mar) ); - BOOST_REQUIRE( mar1.layout().extension().first() == 1 ); - BOOST_REQUIRE( extension(mar1).first() == 1 ); - BOOST_REQUIRE( &mar1[1] == &arr[0] ); // NOLINT(readability-container-data-pointer) test access - BOOST_REQUIRE( mar1.base() == &arr[0] ); // NOLINT(readability-container-data-pointer) test access - BOOST_REQUIRE( mar1.base() == arr.data() ); + BOOST_TEST( size(mar1) == size(mar) ); + BOOST_TEST( mar1.layout().extension().first() == 1 ); + BOOST_TEST( extension(mar1).first() == 1 ); + BOOST_TEST( &mar1[1] == &arr[0] ); // NOLINT(readability-container-data-pointer) test access + BOOST_TEST( mar1.base() == &arr[0] ); // NOLINT(readability-container-data-pointer) test access + BOOST_TEST( mar1.base() == arr.data() ); } BOOST_AUTO_TEST_CASE(array_ref_original_tests_carray) { @@ -477,28 +671,45 @@ BOOST_AUTO_TEST_CASE(array_ref_original_tests_carray) { multi::array_ref crefc(&darr[0][0], {4, 5}); multi::array_cref ref2(&darr[0][0], {4, 5}); - BOOST_REQUIRE( &ref[1][2] == &cref [1][2] ); - BOOST_REQUIRE( &ref[1][2] == &crefc[1][2] ); - BOOST_REQUIRE( &ref[1][2] == & ref2[1][2] ); + BOOST_TEST( &ref[1][2] == &cref [1][2] ); + BOOST_TEST( &ref[1][2] == &crefc[1][2] ); + BOOST_TEST( &ref[1][2] == & ref2[1][2] ); ref[1][1] = 2.0; + #if defined(__clang__) + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wunknown-warning-option" + #pragma clang diagnostic ignored "-Wunsafe-buffer-usage" + #endif + // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) test legacy type double darr2[4][5] = { {1.0, 0.0}, {2.0, 3.0}, }; + darr2[1][0] = 2.0; // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) test legacy type auto const& dd = std::as_const(darr2); - BOOST_REQUIRE( &(dd[1][2]) == &(darr2[1][2]) ); - BOOST_REQUIRE(( & ref[1].static_array_cast()[1] == &ref[1][1] )); - BOOST_REQUIRE(( &multi::static_array_cast(ref[1])[1] == &ref[1][1] )); + BOOST_TEST( &(dd[1][2]) == &(darr2[1][2]) ); + BOOST_TEST(( & ref[1].static_array_cast()[1] == &ref[1][1] )); + BOOST_TEST(( &multi::static_array_cast(ref[1])[1] == &ref[1][1] )); + + #if defined(__clang__) + #pragma clang diagnostic pop + #endif } BOOST_AUTO_TEST_CASE(array_ref_cast_carray) { + #if defined(__clang__) + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wunknown-warning-option" + #pragma clang diagnostic ignored "-Wunsafe-buffer-usage" + #endif + // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) test legacy type double darr[2][2] = { {1.0, 2.0}, @@ -506,29 +717,43 @@ BOOST_AUTO_TEST_CASE(array_ref_cast_carray) { }; multi::array_ref ref(&darr[0][0], {2, 2}); - auto&& other_darr = static_cast(ref); // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) test legacy type + // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) test legacy type + auto&& other_darr = static_cast(ref); - double(&other_darr2)[2][2] = static_cast(ref); // NOLINT(hicpp-use-auto,modernize-use-auto,cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) test legacy type + // NOLINTNEXTLINE(hicpp-use-auto,modernize-use-auto,cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) test legacy type + double(&other_darr2)[2][2] = static_cast(ref); double(&other_darr3)[2][2](ref); // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) test legacy type - BOOST_REQUIRE( &ref [1][0] == &darr[1][0] ); - BOOST_REQUIRE( &other_darr [1][0] == &darr[1][0] ); - BOOST_REQUIRE( &other_darr2[1][0] == &darr[1][0] ); - BOOST_REQUIRE( &other_darr3[1][0] == &darr[1][0] ); + BOOST_TEST( &ref [1][0] == &darr[1][0] ); + BOOST_TEST( &other_darr [1][0] == &darr[1][0] ); + BOOST_TEST( &other_darr2[1][0] == &darr[1][0] ); + BOOST_TEST( &other_darr3[1][0] == &darr[1][0] ); + + #if defined(__clang__) + #pragma clang diagnostic pop + #endif +// TODO(correaa) adapt this test to Boost Test Lightweight // Homebrew GCC-13 terminates rather than having the expected exception caught. -#if !(defined(__GNUC__) && __GNUC__ >= 5 && defined(__APPLE__)) - BOOST_REQUIRE_THROW( - ([&] { - double(&other_darr4)[3][3](ref); // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) test legacy type - other_darr4[1][1] += 1.0; - }()), - std::bad_cast - ); -#endif +// MSVC 17.10 fails to compile +// #if !(defined(__GNUC__) && __GNUC__ >= 5 && defined(__APPLE__)) && !defined(_MSC_VER) +// BOOST_REQUIRE_THROW( +// ([&] { +// double(&other_darr4)[3][3](ref); // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) test legacy type +// other_darr4[1][1] += 1.0; +// }()), +// std::bad_cast +// ); +// #endif } BOOST_AUTO_TEST_CASE(array_ref_original_tests_const_carray) { + #if defined(__clang__) + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wunknown-warning-option" + #pragma clang diagnostic ignored "-Wunsafe-buffer-usage" + #endif + // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) test legacy type double const d2D[4][5] = { {1.0, 2.0}, @@ -536,12 +761,18 @@ BOOST_AUTO_TEST_CASE(array_ref_original_tests_const_carray) { }; multi::array_ref d2Rce(&d2D[0][0], {4, 5}); - BOOST_REQUIRE( &d2Rce[2][3] == &d2D[2][3] ); - BOOST_REQUIRE( d2Rce.size() == 4 ); - BOOST_REQUIRE( num_elements(d2Rce) == 20 ); + BOOST_TEST( &d2Rce[2][3] == &d2D[2][3] ); + BOOST_TEST( d2Rce.size() == 4 ); + BOOST_TEST( num_elements(d2Rce) == 20 ); + + #if defined(__clang__) + #pragma clang diagnostic pop + #endif } BOOST_AUTO_TEST_CASE(array_ref_original_tests_const_carray_string) { + using std::get; // workaround use of function template name with no prior declaration in function call with explicit template arguments is a C++20 extension [-Wc++20-extensions] + // NOLINTBEGIN(fuchsia-default-arguments-calls) std::string ctor // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) test legacy type std::string const dc3D[4][2][3] = { @@ -553,35 +784,37 @@ BOOST_AUTO_TEST_CASE(array_ref_original_tests_const_carray_string) { // NOLINTEND(fuchsia-default-arguments-calls) std::string ctor multi::array_cref cref(&dc3D[0][0][0], {4, 2, 3}); - BOOST_REQUIRE( num_elements(cref) == 24 && cref[2][1][1] == "C1b" ); + BOOST_TEST( num_elements(cref) == 24 && cref[2][1][1] == "C1b" ); auto const& A2 = cref.sliced(0, 3).rotated()[1].sliced(0, 2).unrotated(); - BOOST_REQUIRE( multi::rank>{} == 2 && num_elements(A2) == 6 ); + BOOST_TEST( multi::rank>{} == 2 && num_elements(A2) == 6 ); - BOOST_REQUIRE( std::get<0>(sizes(A2)) == 3 && std::get<1>(sizes(A2)) == 2 ); + BOOST_TEST( get<0>(sizes(A2)) == 3 && get<1>(sizes(A2)) == 2 ); auto const& A3 = cref({0, 3}, 1, {0, 2}); - BOOST_REQUIRE( multi::rank>{} == 2 && num_elements(A3) == 6 ); + BOOST_TEST( multi::rank>{} == 2 && num_elements(A3) == 6 ); - BOOST_REQUIRE( A2.layout()[2][1] == &A2[2][1] - A2.base() ); - BOOST_REQUIRE( A2.rotated().layout()[1][2] == &A2.rotated()[1][2] - A2.rotated().base() ); + BOOST_TEST( A2.layout()[2][1] == &A2[2][1] - A2.base() ); + BOOST_TEST( A2.rotated().layout()[1][2] == &A2.rotated()[1][2] - A2.rotated().base() ); } BOOST_AUTO_TEST_CASE(array_ref_sizes_assingment) { multi::array_cref const cref(nullptr, {4, 2, 3}); { auto [sizes1, sizes2, sizes3] = cref.sizes(); - BOOST_REQUIRE( sizes1 == 4 ); - BOOST_REQUIRE( sizes2 == 2 ); - BOOST_REQUIRE( sizes3 == 3 ); + BOOST_TEST( sizes1 == 4 ); + BOOST_TEST( sizes2 == 2 ); + BOOST_TEST( sizes3 == 3 ); } { - auto sizes1 = std::get<0>(cref.sizes()); - auto sizes2 = std::get<1>(cref.sizes()); - auto sizes3 = std::get<2>(cref.sizes()); - BOOST_REQUIRE( sizes1 == 4 ); - BOOST_REQUIRE( sizes2 == 2 ); - BOOST_REQUIRE( sizes3 == 3 ); + using std::get; // workaround use of function template name with no prior declaration in function call with explicit template arguments is a C++20 extension [-Wc++20-extensions] + + auto sizes1 = get<0>(cref.sizes()); + auto sizes2 = get<1>(cref.sizes()); + auto sizes3 = get<2>(cref.sizes()); + BOOST_TEST( sizes1 == 4 ); + BOOST_TEST( sizes2 == 2 ); + BOOST_TEST( sizes3 == 3 ); } { multi::size_t sizes1; // NOLINT(cppcoreguidelines-init-variables) @@ -589,16 +822,16 @@ BOOST_AUTO_TEST_CASE(array_ref_sizes_assingment) { multi::size_t sizes3; // NOLINT(cppcoreguidelines-init-variables) multi::tie(sizes1, sizes2, sizes3) = cref.sizes(); - BOOST_REQUIRE( sizes1 == 4 ); - BOOST_REQUIRE( sizes2 == 2 ); - BOOST_REQUIRE( sizes3 == 3 ); + BOOST_TEST( sizes1 == 4 ); + BOOST_TEST( sizes2 == 2 ); + BOOST_TEST( sizes3 == 3 ); } { auto const [sizes1, sizes2, sizes3] = cref.sizes(); - BOOST_REQUIRE( sizes1 == 4 ); - BOOST_REQUIRE( sizes2 == 2 ); - BOOST_REQUIRE( sizes3 == 3 ); + BOOST_TEST( sizes1 == 4 ); + BOOST_TEST( sizes2 == 2 ); + BOOST_TEST( sizes3 == 3 ); } // { // // NOLINTNEXTLINE(runtime/int) @@ -610,9 +843,9 @@ BOOST_AUTO_TEST_CASE(array_ref_sizes_assingment) { // multi::tie(sizes1, sizes2, sizes3) = static_cast>(cref.sizes()); - // BOOST_REQUIRE( sizes1 == 4L ); - // BOOST_REQUIRE( sizes2 == 2L ); - // BOOST_REQUIRE( sizes3 == 3L ); + // BOOST_TEST( sizes1 == 4L ); + // BOOST_TEST( sizes2 == 2L ); + // BOOST_TEST( sizes3 == 3L ); // } { // NOLINTNEXTLINE(runtime/int) @@ -623,9 +856,9 @@ BOOST_AUTO_TEST_CASE(array_ref_sizes_assingment) { long long sizes3; // NOLINT(google-runtime-int,cppcoreguidelines-init-variables) test bad idiom multi::tie(sizes1, sizes2, sizes3) = cref.sizes(); - BOOST_REQUIRE( sizes1 == 4 ); - BOOST_REQUIRE( sizes2 == 2 ); - BOOST_REQUIRE( sizes3 == 3 ); + BOOST_TEST( sizes1 == 4 ); + BOOST_TEST( sizes2 == 2 ); + BOOST_TEST( sizes3 == 3 ); } { int64_t sizes1; // NOLINT(cppcoreguidelines-init-variables) @@ -633,44 +866,44 @@ BOOST_AUTO_TEST_CASE(array_ref_sizes_assingment) { int64_t sizes3; // NOLINT(cppcoreguidelines-init-variables) multi::tie(sizes1, sizes2, sizes3) = cref.sizes(); - BOOST_REQUIRE( sizes1 == 4 ); - BOOST_REQUIRE( sizes2 == 2 ); - BOOST_REQUIRE( sizes3 == 3 ); + BOOST_TEST( sizes1 == 4 ); + BOOST_TEST( sizes2 == 2 ); + BOOST_TEST( sizes3 == 3 ); } } -BOOST_AUTO_TEST_CASE(array_ref_rebuild_2D) { - // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) test legacy type - double d2D[4][5] = { - {1.0, 2.0}, - {2.0, 3.0}, - }; - multi::array_ref d2R(&d2D[0][0], {4, 5}); +// BOOST_AUTO_TEST_CASE(array_ref_rebuild_2D) { +// // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) test legacy type +// int d2D[4][5] = { +// {10, 20}, +// {20, 30}, +// }; +// multi::array_ref d2R(&d2D[0][0], {4, 5}); - auto&& d2B = d2R(); - auto&& d2B_ref = multi::ref(d2B.begin(), d2B.end()); +// auto&& d2B = d2R(); +// auto&& d2B_ref = multi::ref(d2B.begin(), d2B.end()); - BOOST_REQUIRE( d2B[0][0] == d2B_ref[0][0] ); - BOOST_REQUIRE( &d2B[0][0] == &d2B_ref[0][0] ); +// BOOST_TEST( d2B[0][0] == d2B_ref[0][0] ); +// BOOST_TEST( &d2B[0][0] == &d2B_ref[0][0] ); - BOOST_REQUIRE( d2B.base() == d2B_ref.base() ); - BOOST_REQUIRE( d2B.layout() == d2B_ref.layout() ); +// BOOST_TEST( d2B.base() == d2B_ref.base() ); +// BOOST_TEST( d2B.layout() == d2B_ref.layout() ); - BOOST_REQUIRE( &d2R() == &multi::ref(d2B.begin(), d2B.end()) ); -} +// BOOST_TEST( &d2R() == &multi::ref(d2B.begin(), d2B.end()) ); +// } -BOOST_AUTO_TEST_CASE(array_ref_rebuild_1D) { - double d1D[5] = {1.0, 2.0, 3.0, 4.0, 5.0}; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) test legacy type +// BOOST_AUTO_TEST_CASE(array_ref_rebuild_1D) { + // double d1D[5] = {1.0, 2.0, 3.0, 4.0, 5.0}; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) test legacy type - multi::array_ref d1R(&d1D[0], {5}); + // multi::array_ref d1R(&d1D[0], {5}); - auto&& d1B = d1R(); - auto&& d1B_ref = multi::ref(d1B.begin(), d1B.end()); + // auto&& d1B = d1R(); + // auto&& d1B_ref = multi::ref(d1B.begin(), d1B.end()); - BOOST_REQUIRE( d1B.base() == d1B_ref.base() ); - BOOST_REQUIRE( d1B.layout() == d1B_ref.layout() ); - BOOST_REQUIRE( &d1R() == &multi::ref(d1B.begin(), d1B.end()) ); -} + // BOOST_TEST( d1B.base() == d1B_ref.base() ); + // BOOST_TEST( d1B.layout() == d1B_ref.layout() ); + // BOOST_TEST( &d1R() == &multi::ref(d1B.begin(), d1B.end()) ); +//} BOOST_AUTO_TEST_CASE(array_ref_move_assigment_2D) { { @@ -685,7 +918,7 @@ BOOST_AUTO_TEST_CASE(array_ref_move_assigment_2D) { Bref = Aref; - BOOST_REQUIRE( arr2 == arr ); + BOOST_TEST( arr2 == arr ); } { multi::array arr({5, 4}); @@ -698,7 +931,7 @@ BOOST_AUTO_TEST_CASE(array_ref_move_assigment_2D) { ref2 = multi::array_ref({5, 4}, arr.data_elements()); - BOOST_REQUIRE( arr2 == arr ); + BOOST_TEST( arr2 == arr ); } { multi::array arr({5, 4}); @@ -712,63 +945,72 @@ BOOST_AUTO_TEST_CASE(array_ref_move_assigment_2D) { ref2 = std::move(ref); - BOOST_REQUIRE( arr2 == arr ); + BOOST_TEST( arr2 == arr ); } } -auto f1d5(double const (&carr)[5]) -> double; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) -auto f1d5(double const (&carr)[5]) -> double { // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) - return carr[1]; -} - -void f2d54(double const (&carr)[5][4]); // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) -void f2d54(double const (&carr)[5][4]) { // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) - BOOST_REQUIRE(carr[0][1] == 1.0); -} - BOOST_AUTO_TEST_CASE(array_ref_conversion_1D) { - multi::array arr({5}, double{}); - BOOST_REQUIRE( arr.size() == 5 ); - std::iota(arr.elements().begin(), arr.elements().end(), 0.0); + multi::array arr({5}, int{}); + BOOST_TEST( arr.size() == 5 ); + std::iota(arr.elements().begin(), arr.elements().end(), 0); + + #if defined(__clang__) + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wunknown-warning-option" + #pragma clang diagnostic ignored "-Wunsafe-buffer-usage" + #endif { - auto& carr = static_cast(arr); // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) - BOOST_REQUIRE( &carr[3] == &arr[3] ); + auto& carr = static_cast(arr); // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) + BOOST_TEST( &carr[3] == &arr[3] ); - BOOST_REQUIRE(f1d5(static_cast(arr)) == 1.0); // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) + BOOST_TEST(f1d5(static_cast(arr)) == 1 ); // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) } { - double(&carr)[5](arr); // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) - BOOST_REQUIRE( &carr[3] == &arr[3] ); + int(&carr)[5](arr); // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) + BOOST_TEST( &carr[3] == &arr[3] ); } + + #if defined(__clang__) + #pragma clang diagnostic pop + #endif } BOOST_AUTO_TEST_CASE(array_ref_conversion_2D) { - multi::array arr({5, 4}); - std::iota(arr.elements().begin(), arr.elements().end(), 0.0); + multi::array arr({5, 4}); + std::iota(arr.elements().begin(), arr.elements().end(), 0); + + #if defined(__clang__) + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wunknown-warning-option" + #pragma clang diagnostic ignored "-Wunsafe-buffer-usage" + #endif { - auto& carr = static_cast(arr); // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) - BOOST_REQUIRE( &carr[3][2] == &arr[3][2] ); + auto& carr = static_cast(arr); // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) + BOOST_TEST( &carr[3][2] == &arr[3][2] ); - f2d54(static_cast(arr)); // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) + f2d54(static_cast(arr)); // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) } { - double(&carr)[5][4](arr); // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) - BOOST_REQUIRE( &carr[3][2] == &arr[3][2] ); - // f2d54((double(&)[5][4])(arr)); // this will warn with -Wold-style-cast NOLINT(google-readability-casting,cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) + int(&carr)[5][4](arr); // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) + BOOST_TEST( &carr[3][2] == &arr[3][2] ); } + + #if defined(__clang__) + #pragma clang diagnostic pop + #endif } #ifndef _MSC_VER BOOST_AUTO_TEST_CASE(as_span) { -#ifdef BOOST_MULTI_HAS_SPAN + #ifdef BOOST_MULTI_HAS_SPAN auto print_me0 = [](std::span rng) { std::cout << "rng.size(): " << rng.size() << '\n'; // (4) std::for_each(rng.begin(), rng.end(), [](auto const& elem) { std::cout << elem << ' '; }); std::cout << "\n\n"; }; -#endif + #endif auto print_me1 = [](multi::array_ref const& rng) { std::cout << "rng.size(): " << rng.size() << '\n'; // (4) @@ -782,7 +1024,7 @@ BOOST_AUTO_TEST_CASE(as_span) { std::cout << "\n\n"; }; -#ifdef BOOST_MULTI_HAS_SPAN + #ifdef BOOST_MULTI_HAS_SPAN { int arr[] = {1, 2, 3, 4}; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) test legacy arrays print_me0(arr); @@ -797,7 +1039,7 @@ BOOST_AUTO_TEST_CASE(as_span) { print_me0(arr2); } -#endif + #endif { int arr[] = {1, 2, 3, 4}; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) test c-arrays @@ -816,24 +1058,24 @@ BOOST_AUTO_TEST_CASE(as_span) { print_me1(*multi::array_ptr{arr2.data(), {6}}); multi::static_array marr( -// #ifdef _MSC_VER // problems with MSVC 14.3 c++17 + // #ifdef _MSC_VER // problems with MSVC 14.3 c++17 multi::extensions_t<1> -// #endif + // #endif {10}, 99 ); print_me1(*multi::array_ptr(marr.data_elements(), 10)); - // #ifndef _MSC_VER + // #ifndef _MSC_VER auto& alias = marr; marr = alias; - BOOST_REQUIRE(marr[5] == 99); + BOOST_TEST(marr[5] == 99); marr = alias(); - BOOST_REQUIRE(marr[5] == 99); - // #endif + BOOST_TEST(marr[5] == 99); + // #endif } { int arr[] = {1, 2, 3, 4}; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) test c-arrays @@ -857,28 +1099,38 @@ BOOST_AUTO_TEST_CASE(as_span) { #endif BOOST_AUTO_TEST_CASE(diagonal) { + #if defined(__clang__) + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wunknown-warning-option" + #pragma clang diagnostic ignored "-Wunsafe-buffer-usage" + #endif + // NOLINTNEXTLINE(hicpp-avoid-c-arrays, modernize-avoid-c-arrays, cppcoreguidelines-avoid-c-arrays): test - double arr[4][3] = { - { 0.0, 1.0, 2.0}, - { 5.0, 1.0, 7.0}, - {10.0, 11.0, 2.0}, - {99.0, 99.0, 99.9}, + int arr[4][3] = { + { 0, 10, 20}, + { 50, 10, 70}, + {100, 110, 20}, + {990, 990, 999}, }; // NOLINTNEXTLINE(hicpp-avoid-c-arrays, modernize-avoid-c-arrays, cppcoreguidelines-avoid-c-arrays): special type - multi::array_ref mar = *multi::array_ptr(&arr); + multi::array_ref mar = *multi::array_ptr(&arr); + + BOOST_TEST( &mar({0, 3}, {0, 3}).diagonal()[0] == &arr[0][0] ); + BOOST_TEST( &mar({0, 3}, {0, 3}).diagonal()[1] == &arr[1][1] ); + BOOST_TEST( &mar({0, 3}, {0, 3}).diagonal()[2] == &arr[2][2] ); - BOOST_REQUIRE( &mar({0, 3}, {0, 3}).diagonal()[0] == &arr[0][0] ); - BOOST_REQUIRE( &mar({0, 3}, {0, 3}).diagonal()[1] == &arr[1][1] ); - BOOST_REQUIRE( &mar({0, 3}, {0, 3}).diagonal()[2] == &arr[2][2] ); + #if defined(__clang__) + #pragma clang diagnostic pop + #endif - auto sum = 0.0; + auto sum = 0; // NOLINTNEXTLINE(altera-unroll-loops) test for-range loop for(auto const& aii : mar.diagonal()) { sum += aii; } - BOOST_REQUIRE( sum == mar[0][0] + mar[1][1] + mar[2][2]); + BOOST_TEST( sum == mar[0][0] + mar[1][1] + mar[2][2]); } BOOST_AUTO_TEST_CASE(function_passing) { @@ -892,17 +1144,6 @@ BOOST_AUTO_TEST_CASE(function_passing) { assert(&arrR[0][0] == &arr[0][0]); } -namespace boost::multi { -template>> -using Array = - std::conditional_t, - std::conditional_t< - std::is_const_v>, - boost::multi::array_ref>, D> const&, - boost::multi::array_ref, D>&>, - multi::array>; -} // end namespace boost::multi - BOOST_AUTO_TEST_CASE(function_passing_2) { multi::Array arr({3, 3}); [[maybe_unused]] multi::Array arrR = arr; @@ -920,163 +1161,135 @@ BOOST_AUTO_TEST_CASE(function_passing_2) { assert(&arrR[0][0] == &arr[0][0]); } -template -auto trace_array_deduce(multi::array const& arr) -> T { - auto const& diag = arr.diagonal(); - return std::accumulate(diag.begin(), diag.end(), T{0}); -} +BOOST_AUTO_TEST_CASE(function_passing_3) { + multi::array const arr({3, 3}, 10); -template double trace_array_deduce(multi::array const&); + BOOST_TEST( trace_array_deduce (arr) == 30 ); + BOOST_TEST( trace_array_deduce(arr) == 30 ); -template -auto trace_generic(Array const& arr) -> T { - auto const& diag = arr.diagonal(); - return std::accumulate(diag.begin(), diag.end(), T{0}); -} + multi::array const arr_paren_copy{arr()}; + BOOST_TEST( arr_paren_copy.size() == 3 ); -template double trace_generic>(multi::array const&); + BOOST_TEST( trace_generic (arr) == 30 ); + BOOST_TEST(( trace_generic >(arr) == 30 )); + // BOOST_TEST(( trace_generic&>(arr) == 3 )); // can't generate element_type -inline auto trace_separate_ref(multi::array_ref const& arr) -> double { - auto const& diag = arr.diagonal(); - return std::accumulate(diag.begin(), diag.end(), 0.0); -} + BOOST_TEST( trace_generic (arr()) == 30 ); + BOOST_TEST(( trace_generic >(+arr()) == 30 )); // this will make a copy + // BOOST_TEST(( trace_generic&>(arr()) == 3 )); // can't generate element_type -inline auto trace_separate_sub(multi::subarray const& arr) -> double { - auto const& diag = arr.diagonal(); - return std::accumulate(diag.begin(), diag.end(), 0.0); -} + BOOST_TEST(( trace_generic >(arr) == 30 )); + // BOOST_TEST(( trace_generic&>(arr) == 3 )); // can't generate element_type + BOOST_TEST(( trace_generic >(arr) == 30 )); + // BOOST_TEST(( trace_generic&>(arr) == 3 )); // can't generate element_type -inline auto trace_separate_ref2(multi::array_const_view arr) -> double { - auto const& diag = arr.diagonal(); - return std::accumulate(diag.begin(), diag.end(), 0.0); -} + // BOOST_TEST(( trace_generic >(arr({0, 3}, {0, 3})) == 3 )); + // BOOST_TEST(( trace_generic&>(arr()) == 3 )); // can't generate element_type -// unusable for arrays -inline auto trace_separate_ref3(multi::array_view arr) -> double { - auto const& diag = arr.diagonal(); - return std::accumulate(diag.begin(), diag.end(), 0.0); -} + BOOST_TEST(( trace_separate_ref (arr) == 30 )); + BOOST_TEST(( trace_separate_sub (arr) == 30 )); -// unusable for arrays -inline auto trace_separate_ref4(multi::array_ref arr) -> double { - auto const& diag = arr.diagonal(); - return std::accumulate(diag.begin(), diag.end(), 0.0); -} + // BOOST_TEST(( trace_separate_ref2 (arr) == 3 )); // not allowed + // BOOST_TEST(( trace_separate_ref3 (arr) == 3 )); // not allowed -// unusable for arrays -inline auto trace_separate_sub4(multi::subarray arr) -> double { - auto const& diag = arr.diagonal(); - return std::accumulate(diag.begin(), diag.end(), 0.0); + // BOOST_TEST(( trace_separate_ref4 (arr) == 3 )); // not allowed + // BOOST_TEST(( trace_separate_sub4 (arr) == 3 )); // not allowed } -BOOST_AUTO_TEST_CASE(function_passing_3) { - multi::array const arr({3, 3}, 1.0); +#if __cplusplus > 202002L || (defined(_MSVC_LANG) && _MSVC_LANG > 202002L) +BOOST_AUTO_TEST_CASE(function_passing_3_lambdas) { + auto buffer = std::make_unique(9); + std::fill_n(buffer.get(), 9, 1); - BOOST_REQUIRE( trace_array_deduce (arr) == 3 ); - BOOST_REQUIRE( trace_array_deduce(arr) == 3 ); + multi::array const arr({3, 3}, 1); + multi::array_ref const aref(buffer.get(), {3, 3}); - multi::array const arr_paren_copy(arr()); - BOOST_REQUIRE( arr_paren_copy.size() == 3 ); + auto const& asub = arr({0, 3}, {0, 3}); - BOOST_REQUIRE( trace_generic (arr) == 3 ); - BOOST_REQUIRE(( trace_generic >(arr) == 3 )); - // BOOST_REQUIRE(( trace_generic&>(arr) == 3 )); // can't generate element_type + auto deduce_array = [](Arr const& a) { + return std::accumulate(a.diagonal().begin(), a.diagonal().end(), typename Arr::element_type{0}); + }; // NOLINT(readability/braces) bug in cpplint 1.6.1 - BOOST_REQUIRE( trace_generic (arr()) == 3 ); - BOOST_REQUIRE(( trace_generic >(arr()) == 3 )); // this will make a copy - // BOOST_REQUIRE(( trace_generic&>(arr()) == 3 )); // can't generate element_type + BOOST_TEST( deduce_array(arr ) == 3 ); + BOOST_TEST( deduce_array(aref) == 3 ); + BOOST_TEST( deduce_array(asub) == 3 ); - BOOST_REQUIRE(( trace_generic >(arr) == 3 )); - // BOOST_REQUIRE(( trace_generic&>(arr) == 3 )); // can't generate element_type - BOOST_REQUIRE(( trace_generic >(arr) == 3 )); - // BOOST_REQUIRE(( trace_generic&>(arr) == 3 )); // can't generate element_type + auto deduce_element = [](multi::array const& a) { + return std::accumulate(a.diagonal().begin(), a.diagonal().end(), T{0}); + }; // NOLINT(readability/braces) bug in cpplint 1.6.1 - // BOOST_REQUIRE(( trace_generic >(arr({0, 3}, {0, 3})) == 3 )); - // BOOST_REQUIRE(( trace_generic&>(arr()) == 3 )); // can't generate element_type + BOOST_TEST( deduce_element(arr) == 3 ); + // BOOST_TEST( deduce_element(aref) == 30 ); + // BOOST_TEST( deduce_element(asub) == 30 ); - BOOST_REQUIRE(( trace_separate_ref (arr) == 3 )); - BOOST_REQUIRE(( trace_separate_sub (arr) == 3 )); + auto deduce_element_ref = [](multi::array_ref const& a) { + return std::accumulate(a.diagonal().begin(), a.diagonal().end(), T{0}); + }; // NOLINT(readability/braces) cpplint 1.6.1 gets confused -// BOOST_REQUIRE(( trace_separate_ref2 (arr) == 3 )); // not allowed - // BOOST_REQUIRE(( trace_separate_ref3 (arr) == 3 )); // not allowed + BOOST_TEST( deduce_element_ref(arr) == 3 ); + BOOST_TEST( deduce_element_ref(aref) == 3 ); + // BOOST_TEST( deduce_element_ref(asub) == 3 ); - // BOOST_REQUIRE(( trace_separate_ref4 (arr) == 3 )); // not allowed - // BOOST_REQUIRE(( trace_separate_sub4 (arr) == 3 )); // not allowed -} + auto deduce_element_sub = [](multi::const_subarray const& a) { + return std::accumulate(a.diagonal().begin(), a.diagonal().end(), T{0}); + }; // NOLINT(readability/braces) cpplint 1.6.1 gets confused -#if __cplusplus > 202002L || (defined(_MSVC_LANG) && _MSVC_LANG > 202002L) -BOOST_AUTO_TEST_CASE(function_passing_3_lambdas) { - auto buffer = std::make_unique(9); - std::fill_n(buffer.get(), 9, 1.0); + BOOST_TEST( deduce_element_sub(arr) == 3 ); + BOOST_TEST( deduce_element_sub(aref) == 3 ); + BOOST_TEST( deduce_element_sub(asub) == 3 ); +} +#endif - multi::array const arr({3, 3}, 1.0); - multi::array_ref const aref(buffer.get(), {3, 3}); - auto const& asub = arr({0, 3}, {0, 3}); +BOOST_AUTO_TEST_CASE(function_passing_4) { + multi::array arr({3, 3}, 10); - auto deduce_array = [](Arr const& a) { return std::accumulate(a.diagonal().begin(), a.diagonal().end(), typename Arr::element_type{0}); }; // NOLINT(readability/braces) cpplint 1.6.1 gets confused + BOOST_TEST( mut_trace_array_deduce (arr) == 30 ); + BOOST_TEST( mut_trace_array_deduce(arr) == 30 ); - BOOST_REQUIRE( deduce_array(arr) == 3 ); - BOOST_REQUIRE( deduce_array(aref) == 3 ); - BOOST_REQUIRE( deduce_array(asub) == 3 ); + BOOST_TEST( mut_trace_generic (arr) == 30 ); + BOOST_TEST(( mut_trace_generic >(arr) == 30 )); +} - auto deduce_element = [](multi::array const& a) { return std::accumulate(a.diagonal().begin(), a.diagonal().end(), T{0}); }; // NOLINT(readability/braces) cpplint 1.6.1 gets confused +BOOST_AUTO_TEST_CASE(array_fill_constructor) { + multi::array arr(3, multi::array{10, 20, 30, 40}); - BOOST_REQUIRE( deduce_element(arr) == 3 ); - // BOOST_REQUIRE( deduce_element(aref) == 3 ); - // BOOST_REQUIRE( deduce_element(asub) == 3 ); + BOOST_TEST( arr[0][1] == 20 ); + BOOST_TEST( arr[1][1] == 20 ); +} - auto deduce_element_ref = [](multi::array_ref const& a) { return std::accumulate(a.diagonal().begin(), a.diagonal().end(), T{0}); }; // NOLINT(readability/braces) cpplint 1.6.1 gets confused +BOOST_AUTO_TEST_CASE(array_fill_constructor_1D) { + using std::get; // workaround use of function template name with no prior declaration in function call with explicit template arguments is a C++20 extension [-Wc++20-extensions] - BOOST_REQUIRE( deduce_element_ref(arr) == 3 ); - BOOST_REQUIRE( deduce_element_ref(aref) == 3 ); - // BOOST_REQUIRE( deduce_element_ref(asub) == 3 ); + multi::array arr(3, 10); - auto deduce_element_sub = [](multi::subarray const& a) { return std::accumulate(a.diagonal().begin(), a.diagonal().end(), T{0}); }; // NOLINT(readability/braces) cpplint 1.6.1 gets confused + BOOST_TEST( arr[0] == 10 ); + BOOST_TEST( arr[1] == 10 ); - BOOST_REQUIRE( deduce_element_sub(arr) == 3 ); - BOOST_REQUIRE( deduce_element_sub(aref) == 3 ); - BOOST_REQUIRE( deduce_element_sub(asub) == 3 ); -} -#endif + BOOST_TEST( get<0>(arr().sizes()) == 3 ); + BOOST_TEST( get<0>(sizes(arr())) == 3 ); -template -auto mut_trace_array_deduce(multi::array& arr) -> T { - arr[0][1] = 4.0; + // BOOST_TEST( get<1>(sizes(arr())) == 10 ); - auto const& diag = arr.diagonal(); - return std::accumulate(diag.begin(), diag.end(), T{0}); + // BOOST_TEST( get<0>(sizes(arr)) == 3 ); + // BOOST_TEST( get<1>(sizes(arr)) == 10 ); } -template double mut_trace_array_deduce(multi::array&); +BOOST_AUTO_TEST_CASE(array_fill_constructor_2D) { + using std::get; // workaround use of function template name with no prior declaration in function call with explicit template arguments is a C++20 extension [-Wc++20-extensions] -template -auto mut_trace_generic(Array& arr) -> T { - arr[0][1] = 4.0; + multi::array arr({3, 4}, 10); - auto const& diag = arr.diagonal(); - return std::accumulate(diag.begin(), diag.end(), T{0}); -} + BOOST_TEST( get<0>(arr().sizes()) == 3 ); + BOOST_TEST( get<0>(sizes(arr())) == 3 ); -BOOST_AUTO_TEST_CASE(function_passing_4) { - multi::array arr({3, 3}, 1.0); + BOOST_TEST( get<1>(arr().sizes()) == 4 ); + BOOST_TEST( get<1>(sizes(arr())) == 4 ); - BOOST_REQUIRE( mut_trace_array_deduce (arr) == 3 ); - BOOST_REQUIRE( mut_trace_array_deduce(arr) == 3 ); + // BOOST_TEST( get<1>(sizes(arr())) == 10 ); - BOOST_REQUIRE( mut_trace_generic (arr) == 3 ); - BOOST_REQUIRE(( mut_trace_generic >(arr) == 3 )); + // BOOST_TEST( get<0>(sizes(arr)) == 3 ); + // BOOST_TEST( get<1>(sizes(arr)) == 10 ); } -BOOST_AUTO_TEST_CASE(array_fill_constructor) { - multi::array arr(3, multi::array{1.0, 2.0, 3.0, 4.0}); - - BOOST_REQUIRE( arr[0][1] == 2.0 ); - BOOST_REQUIRE( arr[1][1] == 2.0 ); -} - -BOOST_AUTO_TEST_CASE(array_fill_constructor_1D) { - multi::array arr(3, 1.0); - - BOOST_REQUIRE( arr[0] == 1.0 ); - BOOST_REQUIRE( arr[1] == 1.0 ); +return boost::report_errors(); } diff --git a/external_codes/boost_multi/multi/test/assignments.cpp b/external_codes/boost_multi/multi/test/assignments.cpp index 72f67342f5..6ceeb05a83 100644 --- a/external_codes/boost_multi/multi/test/assignments.cpp +++ b/external_codes/boost_multi/multi/test/assignments.cpp @@ -3,125 +3,152 @@ // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt -#include - -#include - -// Suppress warnings from boost.test -#if defined(__clang__) -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wold-style-cast" -#pragma clang diagnostic ignored "-Wundef" -#pragma clang diagnostic ignored "-Wconversion" -#pragma clang diagnostic ignored "-Wsign-conversion" -#elif defined(__GNUC__) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wold-style-cast" -#pragma GCC diagnostic ignored "-Wundef" -#pragma GCC diagnostic ignored "-Wconversion" -#pragma GCC diagnostic ignored "-Wsign-conversion" -#elif defined(_MSC_VER) -#pragma warning(push) -#pragma warning(disable : 4244) -#endif +// #if defined(__clang__) +// #pragma clang diagnostic push +// #pragma clang diagnostic ignored "-Wunknown-warning-option" +// #pragma clang diagnostic ignored "-Wconversion" +// #pragma clang diagnostic ignored "-Wextra-semi-stmt" +// #pragma clang diagnostic ignored "-Wold-style-cast" +// #pragma clang diagnostic ignored "-Wsign-conversion" +// #pragma clang diagnostic ignored "-Wswitch-default" +// #pragma clang diagnostic ignored "-Wundef" +// #elif defined(__GNUC__) +// #pragma GCC diagnostic push +// #if (__GNUC__ > 7) +// #pragma GCC diagnostic ignored "-Wcast-function-type" +// #endif +// #pragma GCC diagnostic ignored "-Wconversion" +// #pragma GCC diagnostic ignored "-Wold-style-cast" +// #pragma GCC diagnostic ignored "-Wsign-conversion" +// #pragma GCC diagnostic ignored "-Wundef" +// #elif defined(_MSC_VER) +// #pragma warning(push) +// #pragma warning(disable : 4244) +// #endif -#ifndef BOOST_TEST_MODULE -#define BOOST_TEST_MAIN -#endif +// #ifndef BOOST_TEST_MODULE +// #define BOOST_TEST_MAIN +// #endif -#include +// #include // #if defined(__clang__) -// #pragma clang diagnostic pop +// #pragma clang diagnostic pop // #elif defined(__GNUC__) -// #pragma GCC diagnostic pop +// #pragma GCC diagnostic pop // #elif defined(_MSC_VER) -// #pragma warning(pop) +// #pragma warning(pop) // #endif +#include // for array, apply, operator==, layout_t + +#include // for fill +#include // for complex +#include // for size_t +#include // for size +#include // for std::allocator // IWYU pragma: keep +// IWYU pragma: no_include // for decay_t +#include // for move +#include // for vector, allocator + namespace multi = boost::multi; namespace { constexpr auto make_ref(int* ptr) { - return multi::array_ref(ptr, {5, 7}); + return multi::array_ref(ptr, { 5, 7 }); } } // namespace +template +auto eye(multi::extensions_t<2> exts, Allocator alloc) { + multi::array ret(exts, 0, alloc); + std::fill(ret.diagonal().begin(), ret.diagonal().end(), 1); + return ret; +} + +template +auto eye(multi::extensions_t<2> exts) { return eye(exts, std::allocator{}); } + +#include +#define BOOST_AUTO_TEST_CASE(CasenamE) + +auto main() -> int { // NOLINT(readability-function-cognitive-complexity,bugprone-exception-escape) BOOST_AUTO_TEST_CASE(equality_1D) { - multi::array arr = {1.0, 2.0, 3.0}; - multi::array arr2 = {1.0, 2.0, 3.0}; + multi::array arr = { 10, 20, 30 }; + multi::array arr2 = { 10, 20, 30 }; - BOOST_REQUIRE( arr == arr2 ); - BOOST_REQUIRE( ! (arr != arr2) ); + BOOST_TEST( arr == arr2 ); + BOOST_TEST( !(arr != arr2) ); - BOOST_REQUIRE( arr() == arr2() ); - BOOST_REQUIRE( ! (arr() != arr2()) ); + BOOST_TEST( arr() == arr2() ); + BOOST_TEST( !(arr() != arr2()) ); } BOOST_AUTO_TEST_CASE(equality_2D) { - multi::array arr = { - {1.0, 2.0, 3.0}, - {4.0, 5.0, 6.0}, + multi::array arr = { + { 10, 20, 30 }, + { 40, 50, 60 }, }; - multi::array arr2 = { - {1.0, 2.0, 3.0}, - {4.0, 5.0, 6.0}, + multi::array arr2 = { + { 10, 20, 30 }, + { 40, 50, 60 }, }; - BOOST_REQUIRE( arr == arr2 ); - BOOST_REQUIRE( ! (arr != arr2) ); - BOOST_REQUIRE( arr() == arr2() ); - BOOST_REQUIRE( ! (arr() != arr2()) ); + BOOST_TEST( arr == arr2 ); + BOOST_TEST( !(arr != arr2) ); + + BOOST_TEST( arr() == arr2() ); + BOOST_TEST( !(arr() != arr2()) ); - BOOST_REQUIRE( arr[0] == arr2[0] ); - BOOST_REQUIRE( ! (arr[0] != arr2[0]) ); + BOOST_TEST( arr[0] == arr2[0] ); + BOOST_TEST( !(arr[0] != arr2[0]) ); } BOOST_AUTO_TEST_CASE(multi_copy_move) { - multi::array arr({3, 3}, 0.0); + multi::array arr({ 3, 3 }, 0.0); multi::array arr2 = arr; - BOOST_REQUIRE( arr == arr2 ); + BOOST_TEST( arr == arr2 ); auto* arr_data = arr.data_elements(); multi::array arr3 = std::move(arr); - BOOST_REQUIRE( arr3.data_elements() == arr_data ); + BOOST_TEST( arr3.data_elements() == arr_data ); multi::array const arr4(std::move(arr2)); - BOOST_REQUIRE( size(arr4) == 3 ); + BOOST_TEST( size(arr4) == 3 ); } BOOST_AUTO_TEST_CASE(range_assignment) { { auto const ext = multi::make_extension_t(10L); - multi::array vec(ext.begin(), ext.end()); + multi::array vec(ext.begin(), ext.end()); - BOOST_REQUIRE( ext.size() == vec.size() ); - BOOST_REQUIRE( vec[1] = 10 ); + BOOST_TEST( ext.size() == vec.size() ); + BOOST_TEST( vec[1] == 1L ); } { - multi::array vec(multi::extensions_t<1>{multi::iextension{10}}); + multi::array vec(multi::extensions_t<1>{ multi::iextension{ 10 } }); auto const ext = extension(vec); vec.assign(ext.begin(), ext.end()); - BOOST_REQUIRE( vec[1] == 1 ); + BOOST_TEST( vec[1] == 1 ); } } BOOST_AUTO_TEST_CASE(rearranged_assignment) { - multi::array tmp( + multi::array const tmp( #ifdef _MSC_VER // problem with 14.3 c++17 multi::extensions_t<4> #endif - {14, 14, 7, 4} + { 14, 14, 7, 4 } ); - auto const ext5 = multi::extensions_t<5>{2, 14, 14, 7, 2}; + auto const ext5 = multi::extensions_t<5>{ 2, 14, 14, 7, 2 }; [[maybe_unused]] auto const ext52 = ext5; @@ -131,33 +158,42 @@ BOOST_AUTO_TEST_CASE(rearranged_assignment) { #ifdef _MSC_VER // problem with 14.3 c++17 multi::extensions_t<5> #endif - {2, 14, 14, 7, 2} + { 2, 14, 14, 7, 2 } ); src[0][1][2][3][1] = 99; - BOOST_REQUIRE( extensions(tmp.unrotated().partitioned(2).transposed().rotated()) == extensions(src) ); + // BOOST_TEST( tmp.unrotated().partitioned(2).transposed().rotated().extensions() == src.extensions() ); + // BOOST_TEST( extensions(tmp.unrotated().partitioned(2).transposed().rotated()) == extensions(src) ); } BOOST_AUTO_TEST_CASE(rearranged_assignment_resize) { - multi::array const arrA({4, 5}); - multi::array arrB({2, 3}); + multi::array const arrA({ 4, 5 }); + multi::array arrB({ 2, 3 }); arrB = arrA; - BOOST_REQUIRE( arrB.size() == 4 ); + BOOST_TEST( arrB.size() == 4 ); } +#ifndef _MSVER // TODO(correaa) fix +// seems to produce a deterministic divide by zero +// Assertion failed: stride_ != 0, file D:\a\boost-multi\boost-root\boost/multi/detail/layout.hpp, line 767 +// D:\a\boost-multi\boost-root\boost\multi\detail\layout.hpp(770) : error C2220: the following warning is treated as an error +// D:\a\boost-multi\boost-root\boost\multi\detail\layout.hpp(770) : warning C4723: potential divide by 0 +// D:\a\boost-multi\boost-root\boost\multi\detail\layout.hpp(770) : warning C4723: potential divide by 0 + BOOST_AUTO_TEST_CASE(rvalue_assignments) { using complex = std::complex; std::vector const vec1(200, 99.0); // NOLINT(fuchsia-default-arguments-calls) - std::vector vec2(200); // NOLINT(fuchsia-default-arguments-calls) + std::vector vec2(200); // NOLINT(fuchsia-default-arguments-calls) auto linear1 = [&] { return multi::array_cptr(vec1.data(), 200); }; auto linear2 = [&] { return multi::array_ptr(vec2.data(), 200); }; *linear2() = *linear1(); } +#endif BOOST_AUTO_TEST_CASE(assignments) { { @@ -165,26 +201,28 @@ BOOST_AUTO_TEST_CASE(assignments) { constexpr int val = 33; - multi::array const arr({5, 7}, val); - multi::array_ref(vec.data(), {5, 7}) = arr(); // arr() is a subarray + multi::array const arr({ 5, 7 }, val); + multi::array_ref(vec.data(), { 5, 7 }) = arr(); // arr() is a subarray - BOOST_REQUIRE( vec[9] == val ); - BOOST_REQUIRE( ! vec.empty() ); - BOOST_REQUIRE( ! is_empty(arr) ); + BOOST_TEST( vec[9] == val ); + BOOST_TEST( !vec.empty() ); + BOOST_TEST( !is_empty(arr) ); } { std::vector vec(5 * 7L, 99); // NOLINT(fuchsia-default-arguments-calls) std::vector wec(5 * 7L, 33); // NOLINT(fuchsia-default-arguments-calls) - multi::array_ptr const Bp(wec.data(), {5, 7}); + multi::array_ptr const Bp(wec.data(), { 5, 7 }); make_ref(vec.data()) = *Bp; auto&& mref = make_ref(vec.data()); + // mref = (*Bp).sliced(0, 5); mref = Bp->sliced(0, 5); + // make_ref(vec.data()) = (*Bp).sliced(0, 5); make_ref(vec.data()) = Bp->sliced(0, 5); - BOOST_REQUIRE( vec[9] == 33 ); + BOOST_TEST( vec[9] == 33 ); } { std::vector vec(5 * 7L, 99); // NOLINT(fuchsia-default-arguments-calls) @@ -192,23 +230,15 @@ BOOST_AUTO_TEST_CASE(assignments) { make_ref(vec.data()) = make_ref(wec.data()); - BOOST_REQUIRE( vec[9] == 33 ); + BOOST_TEST( vec[9] == 33 ); } } -template -auto eye(multi::extensions_t<2> exts, Allocator alloc) { - multi::array ret(exts, 0, alloc); - ret.diagonal().fill(1); - return ret; -} - -template -auto eye(multi::extensions_t<2> exts) { return eye(exts, std::allocator{}); } - BOOST_AUTO_TEST_CASE(assigment_temporary) { - multi::array Id = eye(multi::extensions_t<2>({3, 3})); - BOOST_REQUIRE( Id == eye({3, 3}) ); - BOOST_REQUIRE( Id[1][1] == 1 ); - BOOST_REQUIRE( Id[1][0] == 0 ); + multi::array Id = eye(multi::extensions_t<2>({ 3, 3 })); + BOOST_TEST( Id == eye({3, 3}) ); + BOOST_TEST( Id[1][1] == 1 ); + BOOST_TEST( Id[1][0] == 0 ); } + +return boost::report_errors();} diff --git a/external_codes/boost_multi/multi/test/boost_array_concept.cpp b/external_codes/boost_multi/multi/test/boost_array_concept.disable_cpp similarity index 64% rename from external_codes/boost_multi/multi/test/boost_array_concept.cpp rename to external_codes/boost_multi/multi/test/boost_array_concept.disable_cpp index aa71370a6a..872705a3a0 100644 --- a/external_codes/boost_multi/multi/test/boost_array_concept.cpp +++ b/external_codes/boost_multi/multi/test/boost_array_concept.disable_cpp @@ -4,54 +4,54 @@ // https://www.boost.org/LICENSE_1_0.txt // Test explicitly calls deprecated function -// #if defined(__clang__) -// # pragma clang diagnostic push -// # pragma clang diagnositc ignored "-Wdeprecated-declarations" -// #elif defined(__GNUC__) -// # pragma GCC diagnostic push -// # pragma GCC diagnositc ignored "-Wdeprecated-declarations" -// #endif - -#include - -// #if defined(__clang__) -// # pragma clang diagnostic pop -// #elif defined(__GNUC__) -// # pragma GCC diagnostic pop -// #endif - -// Suppress warnings from other boost libraries #if defined(__clang__) -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wold-style-cast" -# pragma clang diagnostic ignored "-Wundef" -# pragma clang diagnostic ignored "-Wconversion" -# pragma clang diagnostic ignored "-Wsign-conversion" -# pragma clang diagnostic ignored "-Wfloat-equal" -# pragma clang diagnostic ignored "-Wunknown-pragmas" -// # pragma clang diagnositc ignored "-Wdeprecated-declarations" -# pragma clang diagnostic ignored "-Wunused-variable" + #pragma clang diagnostic push + #pragma clang diagnositc ignored "-Wdeprecated-declarations" #elif defined(__GNUC__) -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wold-style-cast" -# pragma GCC diagnostic ignored "-Wundef" -# pragma GCC diagnostic ignored "-Wconversion" -# pragma GCC diagnostic ignored "-Wsign-conversion" -# pragma GCC diagnostic ignored "-Wfloat-equal" -# pragma GCC diagnostic ignored "-Wunknown-pragmas" -// # pragma GCC diagnositc ignored "-Wdeprecated-declarations" -# pragma GCC diagnostic ignored "-Wunused-variable" + #pragma GCC diagnostic push + #pragma GCC diagnositc ignored "-Wdeprecated-declarations" +#endif + +#if defined(__clang__) + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wold-style-cast" + #pragma clang diagnostic ignored "-Wundef" + #pragma clang diagnostic ignored "-Wconversion" + #pragma clang diagnostic ignored "-Wsign-conversion" + #pragma clang diagnostic ignored "-Wunknown-pragmas" + #pragma clang diagnostic ignored "-Wunused-variable" +#elif defined(__GNUC__) + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wold-style-cast" + #pragma GCC diagnostic ignored "-Wundef" + #pragma GCC diagnostic ignored "-Wconversion" + #pragma GCC diagnostic ignored "-Wsign-conversion" + #pragma GCC diagnostic ignored "-Wunknown-pragmas" + #pragma GCC diagnostic ignored "-Wunused-variable" #endif #ifndef BOOST_TEST_MODULE -# define BOOST_TEST_MAIN + #define BOOST_TEST_MAIN #endif -#include +#include -#include +#if defined(__clang__) + #pragma clang diagnostic pop +#elif defined(__GNUC__) + #pragma GCC diagnostic pop +#endif -#include +#include // for operator!=, implicit... +// IWYU pragma: no_include // for const_sub_array, sub_array + +#include // for BOOST_CONCEPT_ASSERT +#include // for Assignable, CopyCons... +#include // for multi_array +#include // for ConstMultiArrayConcept + +#include // for ptrdiff_t +#include // for vector BOOST_AUTO_TEST_CASE(concepts_boost_array) { using BMA [[maybe_unused]] = boost::multi_array; // maybe_unused for bug in nvcc 11.8 @@ -70,40 +70,40 @@ BOOST_AUTO_TEST_CASE(concepts_boost_array_1D) { namespace multi = boost::multi; BOOST_AUTO_TEST_CASE(backwards) { - multi::array const MA({2, 2}); + multi::array const MA({ 2, 2 }); - #ifdef __GNUC__ +#ifdef __GNUC__ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdeprecated-declarations" - #endif +#endif // BOOST_REQUIRE(A.index_bases()[0] == 0); // dangles? // BOOST_REQUIRE(A.index_bases()[1] == 0); - #ifdef __GNUC__ +#ifdef __GNUC__ #pragma GCC diagnostic pop - #endif +#endif { - #ifdef __NVCC__ - #pragma nv_diagnostic push - #pragma nv_diag_suppress = deprecated_entity_with_custom_message // nvcc #? - #endif - - #ifdef __GNUC__ - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wdeprecated-declarations" - #endif - // auto ib = MA.index_bases(); (void)ib; - // BOOST_REQUIRE(ib[0] == 0); // dangles? - // BOOST_REQUIRE(ib[1] == 0); - - #ifdef __GNUC__ - #pragma GCC diagnostic pop - #endif - - #ifdef __NVCC__ - #pragma nv_diagnostic pop - #endif +#ifdef __NVCC__ + #pragma nv_diagnostic push + #pragma nv_diag_suppress = deprecated_entity_with_custom_message // nvcc #? +#endif + +#ifdef __GNUC__ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#endif + // auto ib = MA.index_bases(); (void)ib; + // BOOST_REQUIRE(ib[0] == 0); // dangles? + // BOOST_REQUIRE(ib[1] == 0); + +#ifdef __GNUC__ + #pragma GCC diagnostic pop +#endif + +#ifdef __NVCC__ + #pragma nv_diagnostic pop +#endif } // { // #pragma GCC diagnostic push @@ -114,55 +114,53 @@ BOOST_AUTO_TEST_CASE(backwards) { // #pragma GCC diagnostic pop // } { - #ifdef __GNUC__ - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wdeprecated-declarations" - #endif - // BOOST_REQUIRE(static_cast(MA.index_bases())[0] == 0); // dangles - // BOOST_REQUIRE(static_cast(MA.index_bases())[1] == 0); - - #ifdef __GNUC__ - #pragma GCC diagnostic pop - #endif - } - { - #ifdef __GNUC__ - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wdeprecated-declarations" - #endif - // BOOST_REQUIRE(MA.index_bases()[0] == 0); // dangles - // BOOST_REQUIRE(MA.index_bases()[1] == 0); - - #ifdef __GNUC__ - #pragma GCC diagnostic pop - #endif - } - { - #ifdef __GNUC__ - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wdeprecated-declarations" - #endif - // std::ptrdiff_t const* ib = MA.index_bases(); - // BOOST_REQUIRE(ib); - // BOOST_REQUIRE(ib[0] == 0); // dangles - // BOOST_REQUIRE(ib[1] == 0); - #ifdef __GNUC__ - #pragma GCC diagnostic pop - #endif - } - { - #ifdef __GNUC__ - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wdeprecated-declarations" - #endif - std::vector const ib(2); (void)ib; // NOLINT(fuchsia-default-arguments-calls) - // std::copy_n(static_cast(MA.index_bases()), 2, ib.begin()); - // BOOST_REQUIRE(ib[0] == 0); // dangles - // BOOST_REQUIRE(ib[1] == 0); - - #ifdef __GNUC__ - #pragma GCC diagnostic pop - #endif +#ifdef __GNUC__ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#endif + // BOOST_REQUIRE(static_cast(MA.index_bases())[0] == 0); // dangles + // BOOST_REQUIRE(static_cast(MA.index_bases())[1] == 0); + +#ifdef __GNUC__ + #pragma GCC diagnostic pop +#endif + } { +#ifdef __GNUC__ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#endif + // BOOST_REQUIRE(MA.index_bases()[0] == 0); // dangles + // BOOST_REQUIRE(MA.index_bases()[1] == 0); + +#ifdef __GNUC__ + #pragma GCC diagnostic pop +#endif + } { +#ifdef __GNUC__ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#endif + // std::ptrdiff_t const* ib = MA.index_bases(); + // BOOST_REQUIRE(ib); + // BOOST_REQUIRE(ib[0] == 0); // dangles + // BOOST_REQUIRE(ib[1] == 0); +#ifdef __GNUC__ + #pragma GCC diagnostic pop +#endif + } { +#ifdef __GNUC__ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#endif + std::vector const ib(2); + (void)ib; // NOLINT(fuchsia-default-arguments-calls) + // std::copy_n(static_cast(MA.index_bases()), 2, ib.begin()); + // BOOST_REQUIRE(ib[0] == 0); // dangles + // BOOST_REQUIRE(ib[1] == 0); + +#ifdef __GNUC__ + #pragma GCC diagnostic pop +#endif } // { // #pragma GCC diagnostic push @@ -194,7 +192,8 @@ BOOST_AUTO_TEST_CASE(concepts_array) { BOOST_CONCEPT_ASSERT((boost::UnaryFunction)); BOOST_CONCEPT_ASSERT((boost::BinaryFunction)); - // BOOST_CONCEPT_ASSERT((boost::AdaptableGenerator>)); // needs result_type TODO(correaa) add to array?, should result_type be array? or subarray? + // vvv needs result_type TODO(correaa) add to array?, should result_type be array? or subarray? + // BOOST_CONCEPT_ASSERT((boost::AdaptableGenerator>)); // BOOST_CONCEPT_ASSERT((boost::AdaptableUnaryFunction)); // BOOST_CONCEPT_ASSERT((boost::AdaptableBinaryFunction)); @@ -230,7 +229,8 @@ BOOST_AUTO_TEST_CASE(concepts_array_1D) { BOOST_CONCEPT_ASSERT((boost::UnaryFunction)); // BOOST_CONCEPT_ASSERT((boost::BinaryFunction)); - // BOOST_CONCEPT_ASSERT((boost::AdaptableGenerator>)); // needs result_type TODO(correaa) add to array?, should result_type be array? or subarray? + // vvv--- needs result_type TODO(correaa) add to array?, should result_type be array? or subarray? + // BOOST_CONCEPT_ASSERT((boost::AdaptableGenerator>)); // BOOST_CONCEPT_ASSERT((boost::AdaptableUnaryFunction)); // BOOST_CONCEPT_ASSERT((boost::AdaptableBinaryFunction)); @@ -259,7 +259,7 @@ BOOST_AUTO_TEST_CASE(concepts_iterator) { BOOST_CONCEPT_ASSERT((boost::InputIterator)); BOOST_CONCEPT_ASSERT((boost::OutputIterator)); - BOOST_CONCEPT_ASSERT((boost::OutputIterator)); + BOOST_CONCEPT_ASSERT((boost::OutputIterator)); // Iterator Concept Checking Classes BOOST_CONCEPT_ASSERT((boost::ForwardIterator)); @@ -285,9 +285,15 @@ BOOST_AUTO_TEST_CASE(concepts_const_iterator) { // BOOST_CONCEPT_ASSERT((boost::OutputIterator)); BOOST_CONCEPT_ASSERT((boost::ForwardIterator)); -// BOOST_CONCEPT_ASSERT((boost::Mutable_ForwardIterator)); + // BOOST_CONCEPT_ASSERT((boost::Mutable_ForwardIterator)); BOOST_CONCEPT_ASSERT((boost::BidirectionalIterator)); -// BOOST_CONCEPT_ASSERT((boost::Mutable_BidirectionalIterator)); + // BOOST_CONCEPT_ASSERT((boost::Mutable_BidirectionalIterator)); BOOST_CONCEPT_ASSERT((boost::RandomAccessIterator)); -// BOOST_CONCEPT_ASSERT((boost::Mutable_RandomAccessIterator)); + // BOOST_CONCEPT_ASSERT((boost::Mutable_RandomAccessIterator)); } + +#if defined(__clang__) + #pragma clang diagnostic pop +#elif defined(__GNUC__) + #pragma GCC diagnostic pop +#endif diff --git a/external_codes/boost_multi/multi/test/broadcast.cpp b/external_codes/boost_multi/multi/test/broadcast.cpp new file mode 100644 index 0000000000..34a07d519c --- /dev/null +++ b/external_codes/boost_multi/multi/test/broadcast.cpp @@ -0,0 +1,48 @@ +// Copyright 2023-2024 Alfredo A. Correa +// Copyright 2024 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include + +#include + +#include // for std::ranges::fold_left +#include // IWYU pragma: keep for std::abs +// IWYU pragma: no_include // for abs +// IWYU pragma: no_include // for abs + +#define BOOST_AUTO_TEST_CASE(CasenamE) /**/ + +namespace multi = boost::multi; + +auto main() -> int { // NOLINT(readability-function-cognitive-complexity,bugprone-exception-escape) +BOOST_AUTO_TEST_CASE(broadcast_as_fill) { + multi::array bb = { 10, 11 }; + + multi::array BB({ 10, 2 }); + + // std::fill (BB.begin(), BB.end(), bb); // canonical way + std::fill_n(BB.begin(), BB.size(), bb); // canonical way + + // std::copy_n(bb.broadcasted().begin(), BB.size(), BB.begin()); // doesn't work because faulty implementation of copy_n + // thrust::copy_n(bb.broadcasted().begin(), BB.size(), BB.begin()); // equivalent, using broadcast + + // std::copy_n(bb.broadcasted().begin(), bb.broadcasted().size(), BB.begin()); // incorrect, undefined behavior, no useful size() + // std::copy (bb.broadcasted().begin(), bb.broadcasted().end(), BB.begin()); // incorrect, undefined behavior, non-terminating loop (end is not reacheable) + // BB = bb.broadcasted(); + + BOOST_TEST( BB[0] == bb ); + BOOST_TEST( BB[1] == bb ); + + BOOST_TEST( std::all_of(BB.begin(), BB.end(), [&bb](auto const& row) { return row == bb; }) ); + + multi::array const one{1.0}; + + BOOST_TEST( one == 1.0 ); + + auto const& ones = one.broadcasted(); + BOOST_TEST( std::abs( *ones.begin() - 1.0 ) < 1.0e-8 ); +} + +return boost::report_errors();} diff --git a/external_codes/boost_multi/multi/test/comparisons.cpp b/external_codes/boost_multi/multi/test/comparisons.cpp index 1c281f6a21..9ec184f94e 100644 --- a/external_codes/boost_multi/multi/test/comparisons.cpp +++ b/external_codes/boost_multi/multi/test/comparisons.cpp @@ -3,50 +3,33 @@ // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt -#include - -#include - -// Suppress warnings from boost.test -#if defined(__clang__) -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wold-style-cast" -#pragma clang diagnostic ignored "-Wundef" -#pragma clang diagnostic ignored "-Wconversion" -#pragma clang diagnostic ignored "-Wsign-conversion" -#pragma clang diagnostic ignored "-Wfloat-equal" -#elif defined(__GNUC__) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wold-style-cast" -#pragma GCC diagnostic ignored "-Wundef" -#pragma GCC diagnostic ignored "-Wconversion" -#pragma GCC diagnostic ignored "-Wsign-conversion" -#pragma GCC diagnostic ignored "-Wfloat-equal" -#endif - -#ifndef BOOST_TEST_MODULE -# define BOOST_TEST_MAIN -#endif - -#include +#include // for array, apply, operator!=, operat... + +#include // for equal +#include // for complex, operator== +#include // for begin, end, cbegin, cend, size namespace multi = boost::multi; +#include +#define BOOST_AUTO_TEST_CASE(CasenamE) /**/ + +auto main() -> int { // NOLINT(readability-function-cognitive-complexity,bugprone-exception-escape) BOOST_AUTO_TEST_CASE(comparison_complex) { using complex = std::complex; { - multi::array arr = {1.0, 2.0, 3.0}; + multi::array arr = { 1.0, 2.0, 3.0 }; multi::array arr2 = { {1.0, 0.0}, {2.0, 0.0}, {3.0, 0.0}, }; - BOOST_REQUIRE( arr[1] == arr2[1] ); - BOOST_REQUIRE( arr == arr2 ); - BOOST_REQUIRE( ! (arr != arr2) ); - BOOST_REQUIRE( arr2 == arr ); - BOOST_REQUIRE( ! (arr2 != arr) ); + BOOST_TEST( arr[1] == arr2[1] ); + BOOST_TEST( arr == arr2 ); + BOOST_TEST( !(arr != arr2) ); + BOOST_TEST( arr2 == arr ); + BOOST_TEST( !(arr2 != arr) ); } { multi::array const arr = { @@ -55,92 +38,94 @@ BOOST_AUTO_TEST_CASE(comparison_complex) { }; multi::array const arr2 = { - {{1.0, 0.0}, {2.0, 0.0}, {3.0, 0.0}}, - {{4.0, 0.0}, {5.0, 0.0}, {6.0, 0.0}}, + {{ 1.0, 0.0 }, { 2.0, 0.0 }, { 3.0, 0.0 }}, + {{ 4.0, 0.0 }, { 5.0, 0.0 }, { 6.0, 0.0 }}, }; - BOOST_REQUIRE( arr[1][1] == arr2[1][1] ); - BOOST_REQUIRE( arr == arr2 ); - BOOST_REQUIRE( ! (arr != arr2) ); - BOOST_REQUIRE( arr2 == arr ); - BOOST_REQUIRE( ! (arr2 != arr) ); - BOOST_REQUIRE( std::equal(arr[1].begin(), arr[1].end(), begin(arr2[1]), end(arr2[1])) ); + BOOST_TEST( arr[1][1] == arr2[1][1] ); + BOOST_TEST( arr == arr2 ); + BOOST_TEST( !(arr != arr2) ); + BOOST_TEST( arr2 == arr ); + BOOST_TEST( !(arr2 != arr) ); + BOOST_TEST( std::equal(arr[1].begin(), arr[1].end(), begin(arr2[1]), end(arr2[1])) ); } } BOOST_AUTO_TEST_CASE(multi_comparisons_swap) { multi::array arr = { - { {1.2, 1.1}, {2.4, 1.0}}, - {{11.2, 3.0}, {34.4, 4.0}}, - { {1.2, 1.1}, {2.4, 1.0}}, + { { 1.2, 1.1 }, { 2.4, 1.0 }}, + {{ 11.2, 3.0 }, { 34.4, 4.0 }}, + { { 1.2, 1.1 }, { 2.4, 1.0 }}, }; - BOOST_REQUIRE( arr[0] < arr[1] ); + BOOST_TEST( arr[0] < arr[1] ); swap(arr[0], arr[1]); - BOOST_REQUIRE( arr[1] < arr[0] ); + BOOST_TEST( arr[1] < arr[0] ); swap(arr[0], arr[1]); - BOOST_REQUIRE( arr[0] < arr[1] ); + BOOST_TEST( arr[0] < arr[1] ); } BOOST_AUTO_TEST_CASE(comparisons_equality) { multi::array arr = { - { {1.2, 1.1}, {2.4, 1.0}}, - {{11.2, 3.0}, {34.4, 4.0}}, - { {1.2, 1.1}, {2.4, 1.0}}, + { { 1.2, 1.1 }, { 2.4, 1.0 }}, + {{ 11.2, 3.0 }, { 34.4, 4.0 }}, + { { 1.2, 1.1 }, { 2.4, 1.0 }}, }; multi::array_ref ref(arr.data_elements(), extensions(arr)); multi::array_cref cref(data_elements(arr), extensions(arr)); - BOOST_REQUIRE( arr == arr ); - BOOST_REQUIRE( ! (arr != arr) ); - BOOST_REQUIRE( ref == arr ); - BOOST_REQUIRE( ! (ref != arr) ); - BOOST_REQUIRE( ref == cref ); - BOOST_REQUIRE( ! (ref != cref) ); + BOOST_TEST( arr == arr ); + BOOST_TEST( !(arr != arr) ); + BOOST_TEST( ref == arr ); + BOOST_TEST( !(ref != arr) ); + BOOST_TEST( ref == cref ); + BOOST_TEST( !(ref != cref) ); - BOOST_REQUIRE( arr[0] == arr[2] ); - BOOST_REQUIRE( ref[0] == arr[2] ); - BOOST_REQUIRE( ref[0] == cref[2] ); + BOOST_TEST( arr[0] == arr[2] ); + BOOST_TEST( ref[0] == arr[2] ); + BOOST_TEST( ref[0] == cref[2] ); - BOOST_REQUIRE( ! ( arr[0] != arr[2]) ); - BOOST_REQUIRE( ! ( ref[0] != ref[2]) ); + BOOST_TEST( !( arr[0] != arr[2]) ); + BOOST_TEST( !( ref[0] != ref[2]) ); - BOOST_REQUIRE( ! ( arr[0] != arr[2]) ); - BOOST_REQUIRE( ! ( ref[0] != ref[2]) ); + BOOST_TEST( !( arr[0] != arr[2]) ); + BOOST_TEST( !( ref[0] != ref[2]) ); } BOOST_AUTO_TEST_CASE(comparisons_ordering) { - multi::array arr = { - { {12, 11}, {24, 10}}, - {{112, 30}, {344, 40}}, - { {12, 11}, {24, 10}}, + multi::array arr = { + { { 12, 11 }, { 24, 10 }}, + {{ 112, 30 }, { 344, 40 }}, + { { 12, 11 }, { 24, 10 }}, }; - multi::array_ref ref(arr.data_elements(), extensions(arr)); + multi::array_ref ref(arr.data_elements(), extensions(arr)); - multi::array_cref cref(data_elements(arr), extensions(arr)); + multi::array_cref cref(data_elements(arr), extensions(arr)); - BOOST_REQUIRE( arr[0] <= arr[1] ); - BOOST_REQUIRE( ref[0] <= arr[1] ); - BOOST_REQUIRE( cref[0] <= cref[1] ); + BOOST_TEST( arr[0] <= arr[1] ); + BOOST_TEST( ref[0] <= arr[1] ); + BOOST_TEST( cref[0] <= cref[1] ); - BOOST_REQUIRE( arr[0][0] <= arr[0][1] ); - BOOST_REQUIRE( ref[0][0] <= arr[0][1] ); + BOOST_TEST( arr[0][0] <= arr[0][1] ); + BOOST_TEST( ref[0][0] <= arr[0][1] ); - BOOST_REQUIRE( arr[1][0][0] == 112 ); - BOOST_REQUIRE( ref[1][0][0] == 112 ); - BOOST_REQUIRE( cref[1][0][0] == 112 ); + BOOST_TEST( arr[1][0][0] == 112 ); + BOOST_TEST( ref[1][0][0] == 112 ); + BOOST_TEST( cref[1][0][0] == 112 ); - BOOST_REQUIRE( arr[0][0][0] == 12 ); - BOOST_REQUIRE( ref[0][0][0] == 12 ); - BOOST_REQUIRE( cref[0][0][0] == 12 ); + BOOST_TEST( arr[0][0][0] == 12 ); + BOOST_TEST( ref[0][0][0] == 12 ); + BOOST_TEST( cref[0][0][0] == 12 ); swap(ref[0], ref[1]); - BOOST_REQUIRE( begin(arr) < end(arr) ); - BOOST_REQUIRE( cbegin(arr) < cend(arr) ); + BOOST_TEST( begin(arr) < end(arr) ); + BOOST_TEST( cbegin(arr) < cend(arr) ); - BOOST_REQUIRE( end(arr) - begin(arr) == size(arr) ); + BOOST_TEST( end(arr) - begin(arr) == size(arr) ); } + +return boost::report_errors();} diff --git a/external_codes/boost_multi/multi/test/concepts.cpp b/external_codes/boost_multi/multi/test/concepts.cpp index faf72923a9..bf7463c6f8 100644 --- a/external_codes/boost_multi/multi/test/concepts.cpp +++ b/external_codes/boost_multi/multi/test/concepts.cpp @@ -1,60 +1,146 @@ -// Copyright 2022-2023 Alfredo A. Correa +// Copyright 2022-2024 Alfredo A. Correa // Copyright 2024 Matt Borland // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt -#include +// #if defined(__clang__) +// #pragma clang diagnostic push +// #pragma clang diagnostic ignored "-Wunknown-warning-option" +// #pragma clang diagnostic ignored "-Wconversion" +// #pragma clang diagnostic ignored "-Wextra-semi-stmt" +// #pragma clang diagnostic ignored "-Wold-style-cast" +// #pragma clang diagnostic ignored "-Wsign-conversion" +// #pragma clang diagnostic ignored "-Wswitch-default" +// #pragma clang diagnostic ignored "-Wundef" +// #elif defined(__GNUC__) +// #pragma GCC diagnostic push +// #if (__GNUC__ > 7) +// #pragma GCC diagnostic ignored "-Wcast-function-type" +// #endif +// #pragma GCC diagnostic ignored "-Wconversion" +// #pragma GCC diagnostic ignored "-Wold-style-cast" +// #pragma GCC diagnostic ignored "-Wsign-conversion" +// #pragma GCC diagnostic ignored "-Wundef" +// #endif + +// #ifndef BOOST_TEST_MODULE +// #define BOOST_TEST_MAIN +// #endif + +// #include + +// #if defined(__clang__) +// #pragma clang diagnostic pop +// #elif defined(__GNUC__) +// #pragma GCC diagnostic pop +// #endif -// Suppress warnings from boost.test #if defined(__clang__) -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wold-style-cast" -# pragma clang diagnostic ignored "-Wundef" -# pragma clang diagnostic ignored "-Wconversion" -# pragma clang diagnostic ignored "-Wsign-conversion" -# pragma clang diagnostic ignored "-Wfloat-equal" + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wconversion" + #pragma clang diagnostic ignored "-Wold-style-cast" + #pragma clang diagnostic ignored "-Wshadow" + #pragma clang diagnostic ignored "-Wsign-conversion" #elif defined(__GNUC__) -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wold-style-cast" -# pragma GCC diagnostic ignored "-Wundef" -# pragma GCC diagnostic ignored "-Wconversion" -# pragma GCC diagnostic ignored "-Wsign-conversion" -# pragma GCC diagnostic ignored "-Wfloat-equal" + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wconversion" + #pragma GCC diagnostic ignored "-Wold-style-cast" + #pragma GCC diagnostic ignored "-Wsign-conversion" #endif -#ifndef BOOST_TEST_MODULE -# define BOOST_TEST_MAIN +// NOLINTBEGIN(misc-include-cleaner) +#include // for BOOST_CONCEPT_ASSERT // IWYU pragma: keep +#include // for Assignable, CopyCons... // IWYU pragma: keep +#include // for operator- // IWYU pragma: keep +#include // for multi_array // IWYU pragma: keep +#include // for ConstMultiArrayConcept // IWYU pragma: keep +// NOLINTEND(misc-include-cleaner) + +#if defined(__clang__) + #pragma clang diagnostic pop +#elif defined(__GNUC__) + #pragma GCC diagnostic pop #endif -#include +#include // for operator!=, implicit... + +// #include // Boost.Test 1.67 needs test cases to be mpl list +// #include // for list -// #include -#include +// #include // for ptrdiff_t // IWYU pragma: keep +// #include // for vector // IWYU pragma: keep + +#include // for is_same_v, is_convertib... namespace multi = boost::multi; -// using NDArrays = boost::mp11::mp_list< // fails with Boost.Test 1.67 -using NDArrays = boost::mpl::list< - multi::array, - multi::array, - multi::array ->; +#include +#define BOOST_AUTO_TEST_CASE(CasenamE) /**/ + +auto main() -> int { // NOLINT(readability-function-cognitive-complexity,bugprone-exception-escape) + BOOST_AUTO_TEST_CASE(convertibles_1D) { + using NDArray = multi::array; + + NDArray const nda; + + static_assert(std::is_same_v::value_type>); + static_assert(std::is_same_v::reference>); + + using NDRef = typename NDArray::ref; + + static_assert(std::is_convertible_v); + +#ifndef __NVCC__ + static_assert(std::is_convertible_v); + static_assert(std::is_convertible_v); +#else + static_assert(std::is_convertible::value); + static_assert(std::is_convertible::value); +#endif + + static_assert(std::is_same_v::value_type>); + static_assert(std::is_same_v::reference>); + } + + BOOST_AUTO_TEST_CASE(convertibles_2D) { + using NDArray = multi::array; + + NDArray const nda; + + static_assert(std::is_same_v::value_type>); + static_assert(std::is_same_v::reference>); + + using NDRef = typename NDArray::ref; + + static_assert(std::is_convertible_v); + + static_assert(std::is_convertible_v); + static_assert(std::is_convertible_v); + + static_assert(std::is_same_v::value_type>); + static_assert(std::is_same_v::reference>); + } + + BOOST_AUTO_TEST_CASE(convertibles_3D) { + using NDArray = multi::array; + + NDArray const nda; + + static_assert(std::is_same_v::value_type>); + static_assert(std::is_same_v::reference>); -BOOST_AUTO_TEST_CASE_TEMPLATE(convertibles, NDArray, NDArrays) -{ - static_assert( std::is_convertible_v ); - static_assert( std::is_convertible_v ); + using NDRef = typename NDArray::ref; - static_assert( std::is_same_v::value_type>); - static_assert( std::is_same_v::reference >); + static_assert(std::is_convertible_v); - using NDRef = typename NDArray::ref; + // multi::what(); - static_assert( std::is_convertible_v ); + static_assert(std::is_convertible_v); + static_assert(std::is_convertible_v); - static_assert( std::is_convertible_v ); - static_assert( std::is_convertible_v ); + static_assert(std::is_same_v::value_type>); + static_assert(std::is_same_v::reference>); + } - static_assert( std::is_same_v::value_type> ); - static_assert( std::is_same_v::reference > ); + return boost::report_errors(); } diff --git a/external_codes/boost_multi/multi/test/constructors.cpp b/external_codes/boost_multi/multi/test/constructors.cpp index 1f3453d4d0..aef56da853 100644 --- a/external_codes/boost_multi/multi/test/constructors.cpp +++ b/external_codes/boost_multi/multi/test/constructors.cpp @@ -5,30 +5,14 @@ #include -#include - -// Suppress warnings from boost.test -#if defined(__clang__) -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wold-style-cast" -#pragma clang diagnostic ignored "-Wundef" -#pragma clang diagnostic ignored "-Wconversion" -#pragma clang diagnostic ignored "-Wsign-conversion" -#pragma clang diagnostic ignored "-Wfloat-equal" -#elif defined(__GNUC__) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wold-style-cast" -#pragma GCC diagnostic ignored "-Wundef" -#pragma GCC diagnostic ignored "-Wconversion" -#pragma GCC diagnostic ignored "-Wsign-conversion" -#pragma GCC diagnostic ignored "-Wfloat-equal" -#endif - -#ifndef BOOST_TEST_MODULE -#define BOOST_TEST_MAIN -#endif - -#include +// IWYU pragma: no_include +#include // for complex // IWYU pragma: keep // bug in iwyu 18.1.7 +#include // for size_t +#include // for size +#include // for string +#include // for is_copy_assignable_v, is_copy_co... +#include // for move +#include // for vector namespace multi = boost::multi; @@ -39,66 +23,70 @@ struct multiplies_bind1st { multi::array m_; }; +#include +#define BOOST_AUTO_TEST_CASE(CasenamE) /**/ + +auto main() -> int { // NOLINT(readability-function-cognitive-complexity,bugprone-exception-escape) BOOST_AUTO_TEST_CASE(multi_construct_1d) { - multi::static_array arr(multi::extensions_t<1>{multi::iextension{10}}, 1.0); - // multi::static_array arr(multi::array::extensions_type{10}, 1.0); - BOOST_REQUIRE( size(arr) == 10 ); - BOOST_REQUIRE( arr[1] == 1.0 ); + multi::static_array arr(multi::extensions_t<1>{ multi::iextension{ 10 } }, 10); + // multi::static_array arr(multi::array::extensions_type{10}, 10); + BOOST_TEST( size(arr) == 10 ); + BOOST_TEST( arr[1] == 10 ); } BOOST_AUTO_TEST_CASE(multi_constructors_inqnvcc_bug) { using complex = std::complex; - multi::array marr({10, 10}); + multi::array marr({ 10, 10 }); multiplies_bind1st(std::move(marr)); } BOOST_AUTO_TEST_CASE(multi_constructors_1d) { { - multi::array const arr(multi::extensions_t<1>{multi::iextension{10}}); - BOOST_REQUIRE( size(arr)==10 ); + multi::array const arr(multi::extensions_t<1>{ multi::iextension{ 10 } }); + BOOST_TEST( size(arr) == 10 ); } { - multi::array arr(multi::extensions_t<1>{multi::iextension{10}}, double{}); - BOOST_REQUIRE( size(arr)==10 ); - BOOST_REQUIRE( arr[5]== double{} ); + multi::array arr(multi::extensions_t<1>{ multi::iextension{ 10 } }, int{}); + BOOST_TEST( size(arr) == 10 ); + BOOST_TEST( arr[5] == int{} ); } { - multi::array arr(multi::extensions_t<1>{multi::iextension{10}}, double{}); - BOOST_REQUIRE( size(arr)==10 ); - BOOST_REQUIRE( arr[5]== double{} ); + multi::array arr(multi::extensions_t<1>{ multi::iextension{ 10 } }, int{}); + BOOST_TEST( size(arr) == 10 ); + BOOST_TEST( arr[5] == int{} ); } #if defined(__cpp_deduction_guides) && !defined(__NVCC__) { - multi::array arr(multi::extensions_t<1>({0, 10}), double{}); - BOOST_REQUIRE( size(arr)==10 ); - BOOST_REQUIRE( arr[5]== double{} ); + multi::array arr(multi::extensions_t<1>({ 0, 10 }), int{}); + BOOST_TEST( size(arr) == 10 ); + BOOST_TEST( arr[5] == int{} ); } { // clang-format off - multi::array arr({{0, 10}}, double{}); + multi::array arr({{0, 10}}, int{}); // clang-format on - BOOST_REQUIRE( size(arr)==10 ); - BOOST_REQUIRE( arr[5]== double{} ); + BOOST_TEST( size(arr) == 10 ); + BOOST_TEST( arr[5] == int{} ); } { - multi::array arr({10}, double{}); - BOOST_REQUIRE( size(arr)==10 ); - BOOST_REQUIRE( arr[5]== double{} ); + multi::array arr({ 10 }, int{}); + BOOST_TEST( size(arr) == 10 ); + BOOST_TEST( arr[5] == int{} ); } { - multi::array arr(10, double{}); - BOOST_REQUIRE( size(arr)==10 ); - BOOST_REQUIRE( arr[5]== double{} ); + multi::array arr(10, int{}); + BOOST_TEST( size(arr) == 10 ); + BOOST_TEST( arr[5] == int{} ); } #endif } BOOST_AUTO_TEST_CASE(multi_constructors_2d_ctad) { #if defined(__cpp_deduction_guides) && !defined(__NVCC__) - multi::array arr({10, 20}, double{}); - BOOST_REQUIRE( size(arr)==10 ); - BOOST_REQUIRE( arr[5][6] == double{} ); + multi::array arr({ 10, 20 }, int{}); + BOOST_TEST( size(arr) == 10 ); + BOOST_TEST( arr[5][6] == int{} ); #endif } @@ -114,43 +102,49 @@ BOOST_AUTO_TEST_CASE(multi_constructors) { } { // multi::array arr({10}, {}); assert(size(arr)==10); // error ambiguous } { - multi::array arr = {10}; - BOOST_REQUIRE( size(arr)==1 && arr[0]==10 ); + multi::array arr = { 10 }; + BOOST_TEST( size(arr) == 1 ); + BOOST_TEST( arr[0] == 10 ); } { - multi::array arr = {10}; - BOOST_REQUIRE( size(arr)==1 && arr[0]==10 ); + multi::array arr = { 10 }; + BOOST_TEST( size(arr) == 1 ); + BOOST_TEST( arr[0] == 10 ); } { - multi::array arr = {10}; - BOOST_REQUIRE( size(arr)==1 && arr[0]==10 ); + multi::array arr = { 10 }; + BOOST_TEST( size(arr) == 1 ); + BOOST_TEST( arr[0] == 10 ); } { - multi::array arr({10}); - BOOST_REQUIRE( size(arr)==1 && arr[0]==10 ); + multi::array arr({ 10 }); + BOOST_TEST( size(arr) == 1 ); + BOOST_TEST( arr[0] == 10 ); } { - multi::array arr({10}); - BOOST_REQUIRE( size(arr)==1 && arr[0]==10 ); + multi::array arr({ 10 }); + BOOST_TEST( size(arr) == 1 ); + BOOST_TEST( arr[0] == 10 ); } { - multi::array arr({10}); - BOOST_REQUIRE( size(arr)==1 && arr[0]==10 ); + multi::array arr({ 10 }); + BOOST_TEST( size(arr) == 1 ); + BOOST_TEST( arr[0] == 10 ); //}{ multi::array arr({{10}}) ; assert( size(arr)==1 and arr[0]==10 ); // clang warns about double bracked //}{ multi::array arr({{10}}) ; assert( size(arr)==1 and arr[0]==10 ); // clang warns about double bracked //}{ multi::array arr({{10}}) ; assert( size(arr)==1 and arr[0]==10 ); // clang warns about double bracked } { - multi::array const arr({0, 10}); - BOOST_REQUIRE( size(arr)==2 ); + multi::array const arr({ 0, 10 }); + BOOST_TEST( size(arr) == 2 ); } { - multi::array const arr({0, 10}); - BOOST_REQUIRE( size(arr)==2 ); + multi::array const arr({ 0, 10 }); + BOOST_TEST( size(arr) == 2 ); } { - multi::array const arr({0, 10}); - BOOST_REQUIRE( size(arr)==2 ); + multi::array const arr({ 0, 10 }); + BOOST_TEST( size(arr) == 2 ); } { using T = multi::array; @@ -209,7 +203,7 @@ BOOST_AUTO_TEST_CASE(views_cannot_be_elements2) { // {3.0, 4.0}, // }; // [[maybe_unused]] auto pp = std::unique_ptr>(new multi::array{AA[0]}); // NOLINT(modernize-make-unique) testing new -// BOOST_REQUIRE(pp); +// BOOST_TEST(pp); // } // vvv this test gives an error with Windows' GCC @@ -226,3 +220,5 @@ BOOST_AUTO_TEST_CASE(views_cannot_be_elements2) { // pd1->~D1(); // NOSONAR(cpp:S3432) testing placement new // ::operator delete(buf); // } + +return boost::report_errors();} diff --git a/external_codes/boost_multi/multi/test/conversions.cpp b/external_codes/boost_multi/multi/test/conversions.cpp index c711b4a2ac..9b91ffa611 100644 --- a/external_codes/boost_multi/multi/test/conversions.cpp +++ b/external_codes/boost_multi/multi/test/conversions.cpp @@ -3,48 +3,32 @@ // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt +#if defined(_MSC_VER) + #pragma warning(push) + #pragma warning(disable : 4244) // allow conversion from double to float in uninitialized_construct algorithms +#endif + #include #include +// #include // for abs // IWYU pragma: keep +#include // for abs -// Suppress warnings from boost.test -#if defined(__clang__) -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wold-style-cast" -# pragma clang diagnostic ignored "-Wundef" -# pragma clang diagnostic ignored "-Wconversion" -# pragma clang diagnostic ignored "-Wsign-conversion" -// # pragma clang diagnostic ignored "-Wfloat-equal" -#elif defined(__GNUC__) -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wold-style-cast" -# pragma GCC diagnostic ignored "-Wundef" -# pragma GCC diagnostic ignored "-Wconversion" -# pragma GCC diagnostic ignored "-Wsign-conversion" -// # pragma GCC diagnostic ignored "-Wfloat-equal" -#elif defined(_MSC_VER) -# pragma warning(push) -# pragma warning(disable : 4244) -#endif - -#ifndef BOOST_TEST_MODULE -# define BOOST_TEST_MAIN -#endif +namespace multi = boost::multi; -#include +void fun(multi::array, 2> arr); +void fun(multi::array, 2> arr) { arr.clear(); } -#if defined(__clang__) -# pragma clang diagnostic pop -#elif defined(__GNUC__) -# pragma GCC diagnostic pop -#elif defined(_MSC_VER) -# pragma warning(pop) -# pragma warning(disable : 4244) -#endif +void gun(multi::array, 2> const& /*unused*/); +void gun(multi::array, 2> const& /*unused*/) { + /* no-op */ +} -namespace multi = boost::multi; +#include +#define BOOST_AUTO_TEST_CASE(CasenamE) /**/ -// NOLINTBEGIN(fuchsia-default-arguments-calls) // this is a defect in std::complex, not in the library +auto main() -> int { // NOLINT(readability-function-cognitive-complexity,bugprone-exception-escape) +// NOLINTBEGIN(fuchsia-default-arguments-calls) // std::complex has a constructor with a default argument, not in the library BOOST_AUTO_TEST_CASE(complex_conversion_float_to_double) { std::complex const cee{1.0, 2.0}; @@ -53,7 +37,7 @@ BOOST_AUTO_TEST_CASE(complex_conversion_float_to_double) { static_assert(multi::detail::is_explicitly_convertible_v, std::complex>); static_assert(multi::detail::is_implicitly_convertible_v, std::complex>); - BOOST_CHECK_CLOSE( cee.real(), static_cast(zee.real()), 1E-6 ); + BOOST_TEST( std::abs( cee.real() - static_cast(zee.real())) < 1E-6F ); multi::static_array, 1> const CEE1(10, std::complex{}); // NOLINT(fuchsia-default-arguments-calls) multi::static_array, 1> const ZEE1 = CEE1; @@ -62,12 +46,12 @@ BOOST_AUTO_TEST_CASE(complex_conversion_float_to_double) { BOOST_AUTO_TEST_CASE(complex_conversion_double_to_float) { std::complex const zee{1.0, 2.0}; - static_assert( multi::detail::is_explicitly_convertible_v, std::complex>); + static_assert(multi::detail::is_explicitly_convertible_v, std::complex>); static_assert(!multi::detail::is_implicitly_convertible_v, std::complex>); std::complex const cee{zee}; - BOOST_CHECK_CLOSE( cee.real(), static_cast(zee.real()) , 1E-6); + BOOST_TEST( std::abs( cee.real() - static_cast(zee.real()) ) < 1E-6F ); multi::static_array, 1> const ZEE1(10, std::complex{}); multi::static_array, 1> const CEE1{ZEE1}; @@ -78,38 +62,48 @@ BOOST_AUTO_TEST_CASE(double_to_complex_conversion_documentation) { double const dee = 5.0; std::complex const zee = dee; - BOOST_REQUIRE_CLOSE( zee.real(), 5.0, 1E-6 ); - BOOST_REQUIRE_CLOSE( zee.imag(), 0.0, 1E-6 ); + BOOST_TEST( std::abs( zee.real() - 5.0 ) < 1E-6 ); + BOOST_TEST( std::abs( zee.imag() - 0.0 ) < 1E-6 ); // ... therefore from array of reals to arrays of complex is also multi::array DEE({10, 10}, dee); multi::array, 2> ZEE = DEE; - BOOST_REQUIRE_CLOSE( ZEE[3][4].real(), 5.0, 1E-6 ); - BOOST_REQUIRE_CLOSE( ZEE[3][4].imag(), 0.0, 1E-6 ); + BOOST_TEST( std::abs( ZEE[3][4].real() - 5.0 ) < 1E-6); + BOOST_TEST( std::abs( ZEE[3][4].imag() - 0.0 ) < 1E-6); multi::array, 2> ZEE2{DEE}; - BOOST_REQUIRE_CLOSE( ZEE2[3][4].real(), 5.0, 1E-6); - BOOST_REQUIRE_CLOSE( ZEE2[3][4].imag(), 0.0, 1E-6 ); + BOOST_TEST( std::abs( ZEE2[3][4].real() - 5.0 ) < 1E-6); + BOOST_TEST( std::abs( ZEE2[3][4].imag() - 0.0 ) < 1E-6); // multi::array DEE2{ZEE}; // compilation error, good } -void fun(multi::array, 2> arr); -void fun(multi::array, 2> arr) { arr.clear(); } - -void gun(multi::array, 2> const& /*unused*/); -void gun(multi::array, 2> const& /*unused*/) { - /* no-op */ -} - BOOST_AUTO_TEST_CASE(conversion_in_function_call) { multi::array, 2> ZEE({10, 10}); fun(multi::array, 2>{ZEE}); gun(multi::array, 2>{ZEE}); } +BOOST_AUTO_TEST_CASE(float_to_double) { + float const dee = 5.0F; + // float const eff{dee}; // -Wc++11-narrowing // NOLINT(bugprone-narrowing-conversions) + // float const eff = dee; // NOLINT(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) + // float const eff(dee); // NOLINT(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) + auto const eff = static_cast(dee); + + BOOST_TEST( std::abs( eff - 5.0) < 1E-6 ); + + multi::array const DEE({10, 10}, dee); + // multi::array const EFF(DEE); + auto const EFF = static_cast>(DEE); // TODO(correaa) investigate producing intermediate types accessible through interminediate types + + BOOST_TEST( std::abs( EFF[3][4] - 5.0 ) < 1E-6 ); + + // multi::array const EFF = DEE; +} + BOOST_AUTO_TEST_CASE(double_to_float) { double const dee = 5.0; // float const eff{dee}; // -Wc++11-narrowing // NOLINT(bugprone-narrowing-conversions) @@ -117,14 +111,14 @@ BOOST_AUTO_TEST_CASE(double_to_float) { // float const eff(dee); // NOLINT(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) auto const eff = static_cast(dee); - // BOOST_REQUIRE( eff == 5.0 ); // -Wdouble-promotion - BOOST_REQUIRE_CLOSE( eff, 5.0F, 1E-6 ); + BOOST_TEST( std::abs( eff - 5.0F) < 1E-6F ); multi::array const DEE({10, 10}, dee); + // multi::array const EFF(DEE); auto const EFF = static_cast>(DEE); // TODO(correaa) investigate producing intermediate types accessible through interminediate types - BOOST_REQUIRE_CLOSE( EFF[3][4], 5.0F, 1E-6 ); + BOOST_TEST( std::abs( EFF[3][4] - 5.0F ) < 1E-6F ); // multi::array const EFF = DEE; } @@ -133,25 +127,30 @@ BOOST_AUTO_TEST_CASE(complex_to_complex_conversion) { std::complex const cee{1.0, 2.0}; std::complex const zee = cee; - BOOST_REQUIRE_CLOSE( zee.real(), 1.0, 1E-6 ); - BOOST_REQUIRE_CLOSE( zee.imag(), 2.0, 1E-6 ); + BOOST_TEST( std::abs( zee.real() - 1.0) < 1E-6); + BOOST_TEST( std::abs( zee.imag() - 2.0) < 1E-6); // std::complex cee2 = zee; // implicit conversion, compilation error std::complex const cee2{zee}; - BOOST_REQUIRE_CLOSE( cee2.real(), 1.0F, 1E-6 ); - BOOST_REQUIRE_CLOSE( cee2.imag(), 2.0F, 1E-6 ); + BOOST_TEST( std::abs( cee2.real() - 1.0F ) < 1E-6F ); + BOOST_TEST( std::abs( cee2.imag() - 2.0F ) < 1E-6F ); multi::array, 2> const CEE({10, 10}, cee); multi::array, 2> const ZEE = CEE; - BOOST_REQUIRE_CLOSE( ZEE[3][4].real(), 1.0, 1E-6); - BOOST_REQUIRE_CLOSE( ZEE[3][4].imag(), 2.0, 1E-6); + BOOST_TEST( std::abs( ZEE[3][4].real() - 1.0 ) < 1E-6 ); + BOOST_TEST( std::abs( ZEE[3][4].imag() - 2.0 ) < 1E-6 ); // multi::array, 2> const CEE2 = ZEE; // implicit conversion, compilation error multi::array, 2> const CEE2{ZEE}; - BOOST_REQUIRE_CLOSE( CEE2[3][4].real(), 1.0F, 1E-6 ); - BOOST_REQUIRE_CLOSE( CEE2[3][4].imag(), 2.0F, 1E-6 ); + BOOST_TEST( std::abs( CEE2[3][4].real() - 1.0F ) < 1E-6F ); + BOOST_TEST( std::abs( CEE2[3][4].imag() - 2.0F ) < 1E-6F ); } // NOLINTEND(fuchsia-default-arguments-calls) +return boost::report_errors();} + +#if defined(_MSC_VER) + #pragma warning(pop) +#endif diff --git a/external_codes/boost_multi/multi/test/cursor.cpp b/external_codes/boost_multi/multi/test/cursor.cpp new file mode 100644 index 0000000000..a69b44c108 --- /dev/null +++ b/external_codes/boost_multi/multi/test/cursor.cpp @@ -0,0 +1,306 @@ +// Copyright 2018-2024 Alfredo A. Correa +// Copyright 2024 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include + +#include // for array, implicit_cast, explicit_cast + +#include // for is_same_v, is_same + +namespace multi = boost::multi; + +auto main() -> int { // NOLINT(readability-function-cognitive-complexity,bugprone-exception-escape) + { + static_assert(std::is_trivially_default_constructible_v::cursor>); + static_assert(std::is_trivially_copy_constructible_v ::cursor>); + static_assert(std::is_trivially_copy_assignable_v ::cursor>); + } + + // BOOST_AUTO_TEST_CASE(iterator_1d) + { + static_assert(std::is_trivially_default_constructible_v::cursor>); + static_assert(std::is_trivially_copy_constructible_v ::cursor>); + static_assert(std::is_trivially_copy_assignable_v ::cursor>); + } + // BOOST_AUTO_TEST_CASE(iterator_2d) + { + static_assert(std::is_trivially_default_constructible_v::cursor>); + static_assert(std::is_trivially_copy_constructible_v ::cursor>); + static_assert(std::is_trivially_copy_assignable_v ::cursor>); + + // { + // multi::array arr(multi::extensions_t<1>{multi::iextension{100}}, 99.0); + // BOOST_TEST( arr.size() == 100 ); + // BOOST_TEST( arr.begin() < arr.end() ); + // BOOST_TEST( arr.end() - arr.begin() == arr.size() ); + + // multi::array::const_iterator const cbarr = arr.cbegin(); + // multi::array::iterator barr = arr.begin(); + + // [[maybe_unused]] multi::array::const_iterator const cbarr3{barr}; + + // BOOST_TEST( barr == cbarr ); // problem in C++20 + // BOOST_TEST( cbarr == barr ); // problem in C++20 + + // barr += 1; + // barr -= 1; + // BOOST_TEST( cbarr == barr ); + + // multi::array::const_iterator const cbarr2 = begin(arr); + // BOOST_TEST( cbarr2 == cbarr ); + // } + // { + // multi::array arr(multi::extensions_t<1>{multi::iextension{100}}, 99.0); + // BOOST_TEST( arr.size() == 100 ); + // BOOST_TEST( arr.begin() < arr.end() ); + + // auto arr2 = arr.begin(); + // multi::array::const_iterator const cbb = arr2; + // BOOST_TEST( cbb == arr2 ); + // // BOOST_TEST( arr2 == cbb ); // TODO(correaa) problem in C++20 + // } + // { + // multi::array arr(multi::extensions_t<1>{multi::iextension{100}}, 99.0); + // BOOST_TEST( arr.size() == 100 ); + // BOOST_TEST( arr.begin() < arr.end() ); + + // auto const arrend = arr.end(); + // auto const arrlast = arrend - 1; + + // BOOST_TEST( arrlast + 1 == arrend ); + // } + } + + // BOOST_AUTO_TEST_CASE(iterator_2d) { + // BOOST_TEST((std::is_trivially_copy_constructible_v >)); + // BOOST_TEST((std::is_trivially_copy_assignable_v >)); + // BOOST_TEST((std::is_trivially_default_constructible_v>)); + + // BOOST_TEST((std::is_trivially_copy_constructible_v >)); + // BOOST_TEST((std::is_trivially_copy_assignable_v >)); + // BOOST_TEST((std::is_trivially_default_constructible_v>)); + + // // BOOST_TEST((std::is_trivially_default_constructible_v::iterator>)); // TODO(correaa) + // BOOST_TEST((std::is_trivially_copy_constructible_v ::iterator>)); + // BOOST_TEST((std::is_trivially_copy_assignable_v ::iterator>)); + + // { + // multi::array const arr({120, 140}, 99.0); + + // BOOST_TEST( arr.size() == 120 ); + // BOOST_TEST( arr.cbegin() < arr.cend() ); + // BOOST_TEST( arr.cend() - arr.cbegin() == arr.size() ); + + // using iter = multi::array::iterator; + // static_assert(std::is_same_v); + // static_assert(std::is_same_v>); + // static_assert(std::is_same_v>); + // static_assert(std::is_same_v); + + // using citer = multi::array::const_iterator; + // static_assert(std::is_same_v); + // static_assert(std::is_same_v>); + + // static_assert(std::is_same_v>); + // static_assert(std::is_same_v); + + // auto const arrend = arr.end(); + // auto const arrlast = arrend - 1; + + // BOOST_TEST( arrlast + 1 == arrend ); + // } + // { + // std::vector vec(10000); // std::vector NOLINT(fuchsia-default-arguments-calls) + // multi::array_ref arr(vec.data(), {100, 100}); + // BOOST_TEST(arr.size() == 100); + // begin(arr)[4][3] = 2.0; + // } + // } + + // BOOST_AUTO_TEST_CASE(iterator_interface) { + // multi::array arr = { + // { {12, 11}, {24, 10}}, + // {{112, 30}, {344, 40}}, + // { {12, 11}, {24, 10}} + // }; + + // BOOST_TEST( size(arr) == 3 ); + // BOOST_TEST( size(arr[0]) == 2 ); + // BOOST_TEST( size(arr[0][0]) == 2 ); + // BOOST_TEST( arr[0][0][1] == 11 ); + + // BOOST_TEST( begin(arr) < end(arr) ); + // BOOST_TEST( cbegin(arr) < cend(arr) ); + // BOOST_TEST( begin(arr[0]) < end(arr[0]) ); + // BOOST_TEST( begin(arr[0]) < end(arr[0]) ); + + // // BOOST_TEST(( multi::array::reverse_iterator {A.begin()} == rend(A) )); + + // // BOOST_TEST( rbegin(A) < rend(A) ); + + // BOOST_TEST( end(arr) - begin(arr) == size(arr) ); + // // BOOST_TEST( rend(A) - rbegin(A) == size(A) ); + + // BOOST_TEST( size(*begin(arr) ) == 2 ); + // BOOST_TEST( size( begin(arr)[1]) == 2 ); + + // BOOST_TEST( &(arr[1][1].begin()[0]) == &arr[1][1][0] ); // NOLINT(readability-container-data-pointer) test access + // BOOST_TEST( &arr[0][1][0] == &arr[0][1][0] ); + // BOOST_TEST( &((*arr.begin())[1][0]) == &arr[0][1][0] ); + + // BOOST_TEST( &((*arr.begin()).operator[](1)[0]) == &arr[0][1][0] ); + // BOOST_TEST( &( arr.begin()->operator[](1)[0]) == &arr[0][1][0] ); + + // BOOST_TEST( &((*arr.begin()).operator[](1).begin()[0]) == &arr[0][1][0] ); // NOLINT(readability-container-data-pointer) test access + // BOOST_TEST( &( arr.begin()->operator[](1).begin()[0]) == &arr[0][1][0] ); // NOLINT(readability-container-data-pointer) test access + + // BOOST_TEST( &((*(arr.begin()+1)).operator[](1).begin()[0]) == &arr[1][1][0] ); // NOLINT(readability-container-data-pointer) test access + // BOOST_TEST( &( (arr.begin()+1)->operator[](1).begin()[0]) == &arr[1][1][0] ); // NOLINT(readability-container-data-pointer) test access + + // BOOST_TEST( &((*(begin(arr)+1)).operator[](1).begin()[0]) == &arr[1][1][0] ); // NOLINT(readability-container-data-pointer) test access + // BOOST_TEST( &(( begin(arr)+1)->operator[](1).begin()[0]) == &arr[1][1][0] ); // NOLINT(readability-container-data-pointer) test access + + // BOOST_TEST( &((*(cbegin(arr)+1)).operator[](1).begin()[0]) == &arr[1][1][0] ); // NOLINT(readability-container-data-pointer) test access + // BOOST_TEST( &(( cbegin(arr)+1)->operator[](1).begin()[0]) == &arr[1][1][0] ); // NOLINT(readability-container-data-pointer) test access + // } + + // BOOST_AUTO_TEST_CASE(iterator_semantics) { + // multi::array arr = { + // { {1.2, 1.1}, {2.4, 1.0}}, + // {{11.2, 3.0}, {34.4, 4.0}}, + // { {1.2, 1.1}, {2.4, 1.0}} + // }; + + // multi::array::iterator it; + // // BOOST_TEST(( multi::array::iterator{} == it )); // `it` is uninitialized + // // BOOST_TEST(( it == multi::array::iterator{} )); + + // it = begin(arr); + // BOOST_TEST( it == begin(arr) ); + + // it += 1; + // it -= 1; + // BOOST_TEST( it == begin(arr) ); + + // auto const& arrc = arr(); + // BOOST_TEST( &arrc[0][0][0] == &arr[0][0][0] ); + + // auto const& arrc2 = arr(); + + // BOOST_TEST( arrc.addressof() == arrc2.addressof() ); // BOOST_TEST( &arrc == &arrc2 ); + + // multi::array::iterator const it2 = begin(arr); + // BOOST_TEST(it == it2); + + // it = end(arr); + // BOOST_TEST(it != it2); + // BOOST_TEST(it > it2); + + // multi::array::iterator const it3{it}; + // BOOST_TEST( it3 == it ); + + // static_assert(std::is_same::iterator::element_ptr, double*>{}); + + // // cit = it3; + // // BOOST_REQUIRE( cit == it3 ); // TODO(correaa) + // // BOOST_REQUIRE( it3 == cit ); // TODO(correaa) + + // // cit = it3; + // // BOOST_TEST( cit == it3 ); // TODO(correaa) + // // BOOST_TEST( it3 == cit ); // TODO(correaa) + + // BOOST_TEST( &arr[0][2][1] == &begin(arr)[0][2][1] ); + + // [[maybe_unused]] multi::array::const_iterator const cit2 = it3; + + // static_assert(decltype(begin(arr))::rank_v == 3, "!"); + // static_assert(decltype(begin(arr))::rank{} == 3, "!"); + + // // auto&& ref = multi::ref(begin(arr), end(arr)); + + // // BOOST_TEST( arr.base() == ref.base() ); + // // BOOST_TEST( arr[0][2][1] == ref[0][2][1] ); + // // BOOST_TEST( &arr[0][2][1] == &ref[0][2][1] ); + // // BOOST_TEST( arr.layout().stride() == ref.layout().stride()); + // // BOOST_TEST( arr.layout().offset() == ref.layout().offset()); + // // BOOST_TEST( arr.layout().nelems() == ref.layout().nelems()); + + // // BOOST_TEST( arr.num_elements() == ref.num_elements() ); + // // BOOST_TEST( arr.stride() == ref.stride() ); + // // BOOST_TEST( arr.layout() == ref.layout() ); + + // // BOOST_TEST( &multi::ref(begin(arr), end(arr)) == &arr ); + // } + + // BOOST_AUTO_TEST_CASE(iterator_arrow_operator) { + // // NOLINTBEGIN(fuchsia-default-arguments-calls) std::string has a default constructor + // multi::array arr = { + // {"00", "01"}, + // {"10", "11"}, + // {"20", "21"} + // }; + // // NOLINTEND(fuchsia-default-arguments-calls) + + // BOOST_TEST( arr[1][0] == "10" ); + + // BOOST_TEST( std::is_sorted(begin(arr), end(arr)) ); // sorted by rows + // BOOST_TEST( std::is_sorted(begin(arr.rotated()), end(arr.rotated())) ); // sorted by cols + + // BOOST_TEST( (*begin( arr )).size() == arr[0].size() ); + // BOOST_TEST( begin( arr )->size() == arr[0].size() ); + + // BOOST_TEST( (*begin( arr.rotated() )).size() == arr.size() ); + // BOOST_TEST( begin( arr.rotated() )->size() == arr.size() ); + + // BOOST_TEST( &((*begin( arr )).operator[](1)) == &(arr[0][1]) ); + // BOOST_TEST( &( begin( arr )->operator[](1)) == &(arr[0][1]) ); + + // BOOST_TEST( &((*begin( arr.rotated() )).operator[](1)) == &(arr[1][0]) ); + // BOOST_TEST( &( begin( arr.rotated() )->operator[](1)) == &(arr[1][0]) ); + // } + + // BOOST_AUTO_TEST_CASE(index_range_iteration) { + // multi::index_range irng(0, 5); // semiopen interval + // std::ostringstream out; + // std::copy(irng.begin(), irng.end(), std::ostream_iterator{out, ","}); + // BOOST_TEST_EQ(out.str(), std::string{"0,1,2,3,4,"}); // NOLINT(fuchsia-default-arguments-calls) + + // BOOST_TEST( std::accumulate(begin(irng), end(irng), static_cast(0U)) == irng.size()*(irng.size()-1)/2 ); + + // auto const sum_of_cubes = [](auto&& acc, auto const& elem) { + // return std::forward(acc) + elem * elem * elem; + // }; + // BOOST_TEST( std::accumulate(begin(irng), end(irng), multi::index_range::value_type{}, sum_of_cubes) > 0 ); + // } + + // BOOST_AUTO_TEST_CASE(multi_reverse_iterator_1D) { + // multi::array arr(100, 66.0); + // BOOST_TEST( &arr[99] == &*std::make_reverse_iterator(arr.end()) ); + + // auto rbegin = std::make_reverse_iterator(arr.end()); + // rbegin += 100; + // multi::array::iterator const begin{rbegin.base()}; + // BOOST_TEST( begin == arr.begin() ); + // } + + // BOOST_AUTO_TEST_CASE(multi_reverse_iterator_2D) { + // multi::array arr = { + // { 10, 20}, + // { 100, 200}, + // {1000, 2000} + // }; + // BOOST_TEST( (*arr.begin())[1] == 20 ); + // BOOST_TEST( arr.begin()->operator[](1) == 20 ); + + // auto rbegin = std::make_reverse_iterator(arr.end()); + + // BOOST_TEST( (*rbegin)[1] == 2000 ); + + // BOOST_TEST( arr.begin() < arr.begin() + 1 ); + // BOOST_TEST( arr.end() - 1 < arr.end() ); + // } + + return boost::report_errors(); +} diff --git a/external_codes/boost_multi/multi/test/diagonal.cpp b/external_codes/boost_multi/multi/test/diagonal.cpp index 41aadfe768..6bb31f1555 100644 --- a/external_codes/boost_multi/multi/test/diagonal.cpp +++ b/external_codes/boost_multi/multi/test/diagonal.cpp @@ -3,32 +3,11 @@ // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt -#include - -#include - -// Suppress warnings from boost.test -#if defined(__clang__) -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wold-style-cast" -# pragma clang diagnostic ignored "-Wundef" -# pragma clang diagnostic ignored "-Wconversion" -# pragma clang diagnostic ignored "-Wsign-conversion" -# pragma clang diagnostic ignored "-Wfloat-equal" -#elif defined(__GNUC__) -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wold-style-cast" -# pragma GCC diagnostic ignored "-Wundef" -# pragma GCC diagnostic ignored "-Wconversion" -# pragma GCC diagnostic ignored "-Wsign-conversion" -# pragma GCC diagnostic ignored "-Wfloat-equal" -#endif - -#ifndef BOOST_TEST_MODULE -# define BOOST_TEST_MAIN -#endif - -#include +#include // for array, layout_t, static_array + +#include // for transform +#include // for plus // IWYU pragma: keep +#include // for accumulate namespace multi = boost::multi; @@ -55,12 +34,18 @@ auto trace_with_accumulate(Array2D const& arr) { return std::accumulate(arr.diagonal().begin(), arr.diagonal().end(), static_cast(0)); } +#include +#define BOOST_AUTO_TEST_CASE(CasenamE) /**/ + +auto main() -> int { // NOLINT(readability-function-cognitive-complexity,bugprone-exception-escape) BOOST_AUTO_TEST_CASE(trace_test) { using int_element = multi::index; multi::array arr({5, 5}, 0); auto [is, js] = extensions(arr); - for(auto i : is) { // NOLINT(altera-unroll-loops) testing loops + + // NOLINTNEXTLINE(altera-unroll-loops) testing loops + for(auto i : is) { for(auto j : js) { // NOLINT(altera-unroll-loops) testing loops arr[i][j] = 10 * i + j; } @@ -68,17 +53,27 @@ BOOST_AUTO_TEST_CASE(trace_test) { auto tr = trace_with_diagonal(arr); - BOOST_REQUIRE( tr == 00 + 11 + 22 + 33 + 44 ); + BOOST_TEST( tr == 00 + 11 + 22 + 33 + 44 ); + + BOOST_TEST( trace_with_diagonal(arr) == trace_with_indices(arr) ); + BOOST_TEST( trace_with_diagonal(arr) == trace_with_accumulate(arr) ); +} + +BOOST_AUTO_TEST_CASE(broadcasted) { + multi::array const arr = { + {0, 1, 2}, + {4, 5, 6}, + {8, 9, 10}, + }; - BOOST_REQUIRE( trace_with_diagonal(arr) == trace_with_indices(arr) ); - BOOST_REQUIRE( trace_with_diagonal(arr) == trace_with_accumulate(arr) ); -// BOOST_REQUIRE( trace_with_diagonal(arr) == trace_with_reduce(arr) ); + BOOST_TEST( arr.diagonal().begin() != arr.diagonal().end() ); + BOOST_TEST( arr.diagonal().end() - arr.diagonal().begin() == 3 ); } BOOST_AUTO_TEST_CASE(broadcasted) { multi::array const arr = { - {0, 1, 2, 3}, - {4, 5, 6, 7}, + {0, 1, 2, 3}, + {4, 5, 6, 7}, {8, 9, 10, 11}, }; @@ -89,29 +84,21 @@ BOOST_AUTO_TEST_CASE(broadcasted) { { auto const& arr_instance = a3D[0]; - BOOST_REQUIRE( &arr_instance[3][1] == &arr[3][1] ); + BOOST_TEST( &arr_instance[3][1] == &arr[3][1] ); } { auto const& arr_instance = a3D[99]; - BOOST_REQUIRE( &arr_instance[3][1] == &arr[3][1] ); + BOOST_TEST( &arr_instance[3][1] == &arr[3][1] ); } { auto const& arr_instance = a3D[-99]; - BOOST_REQUIRE( &arr_instance[3][1] == &arr[3][1] ); + BOOST_TEST( &arr_instance[3][1] == &arr[3][1] ); } { auto const& a3D_self = a3D(); BOOST_TEST( &a3D_self[ 4][3][1] == &arr[3][1] ); BOOST_TEST( &a3D_self[99][3][1] == &arr[3][1] ); } - { - // [[maybe_unused]] auto const& a3D_finite = a3D({0, 9}); - // BOOST_TEST( &a3D_finite[ 4][3][1] == &arr[3][1] ); - // BOOST_TEST( &a3D_finite[99][3][1] == &arr[3][1] ); - } - -// BOOST_REQUIRE( a3D_finite.size() == 5 ); -// BOOST_REQUIRE( a3D_finite.begin() + 5 == a3D_finite.end() ); } BOOST_AUTO_TEST_CASE(broadcast_1D) { @@ -124,7 +111,7 @@ BOOST_AUTO_TEST_CASE(broadcast_1D) { } BOOST_AUTO_TEST_CASE(broadcast_0D) { - multi::array arr = {0, 1, 2, 3}; + multi::array arr = {0, 1, 2, 3}; multi::array const vv(2); auto const& v1D = vv.broadcasted(); @@ -137,9 +124,8 @@ BOOST_AUTO_TEST_CASE(broadcast_0D) { BOOST_TEST( r1D[3] == arr[3] + 2 ); - std::transform(arr.begin(), arr.end(), v1D.begin(), arr.begin(), [](auto, auto ve) {return ve;}); + std::transform(arr.begin(), arr.end(), v1D.begin(), arr.begin(), [](auto, auto ve) { return ve; }); BOOST_TEST( arr[3] == 2 ); - - // std::copy_n(v1D.begin(), arr.size(), arr.begin()); - // BOOST_TEST( arr[3] == 2 ); } + +return boost::report_errors();} diff --git a/external_codes/boost_multi/multi/test/element_access.cpp b/external_codes/boost_multi/multi/test/element_access.cpp index 8b471bfff8..27971f14bf 100644 --- a/external_codes/boost_multi/multi/test/element_access.cpp +++ b/external_codes/boost_multi/multi/test/element_access.cpp @@ -3,269 +3,302 @@ // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt -#include - -#include -#include -#include // for std::iota - -// Suppress warnings from boost.test -#if defined(__clang__) -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wold-style-cast" -# pragma clang diagnostic ignored "-Wundef" -# pragma clang diagnostic ignored "-Wconversion" -# pragma clang diagnostic ignored "-Wsign-conversion" -// # pragma clang diagnostic ignored "-Wfloat-equal" -#elif defined(__GNUC__) -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wold-style-cast" -# pragma GCC diagnostic ignored "-Wundef" -# pragma GCC diagnostic ignored "-Wconversion" -# pragma GCC diagnostic ignored "-Wsign-conversion" -// # pragma GCC diagnostic ignored "-Wfloat-equal" -#elif defined(_MSC_VER) -# pragma warning(push) -# pragma warning(disable : 4244) -#endif - -#ifndef BOOST_TEST_MODULE -# define BOOST_TEST_MAIN -#endif - -#include +#include // for array, layout_t, subarray, range + +#include // for copy +#include // for array, get +#include // for deque, operator== +#include // for size, back_inserter +#include // for iota +#include // for operator""s, allocator, basic_st... +#include // for apply, make_tuple, tuple +#include // for is_assignable_v +#include // for move, forward +#include // for vector, operator== namespace multi = boost::multi; -BOOST_AUTO_TEST_CASE(empty_intersection) { - multi::array arr({10}); - multi::array arr2; - - auto const is = intersection(arr.extension(), arr2.extension()); - BOOST_REQUIRE( arr(is).is_empty() ); - arr2(is) = arr(is); - - BOOST_REQUIRE( arr2(is) == arr(is) ); +template +void assign_elements_from_to(Array1D&& arr, std::deque>& dest) { // NOLINT(google-runtime-references) dest is mutated + std::copy(std::forward(arr).begin(), std::forward(arr).end(), std::back_inserter(dest)); } -BOOST_AUTO_TEST_CASE(multi_tests_element_access_with_tuple) { - multi::array arr({3, 3}, 'k'); +#include +#define BOOST_AUTO_TEST_CASE(CasenamE) /**/ - std::array point = { - {1, 2} - }; +auto main() -> int { // NOLINT(readability-function-cognitive-complexity,bugprone-exception-escape) + BOOST_AUTO_TEST_CASE(empty_intersection) { + multi::array arr({10}); + multi::array arr2; - BOOST_REQUIRE( arr[point[0]][point[1]] == arr(1, 2) ); - BOOST_REQUIRE( &arr(point[0], point[1]) == &arr[point[0]][point[1]] ); + auto const is = intersection(arr.extension(), arr2.extension()); + BOOST_TEST( arr(is).is_empty() ); + arr2(is) = arr(is); - BOOST_REQUIRE( &arr[point[0]][point[1]] == &arr(point[0], point[1]) ); - BOOST_REQUIRE( &arr(point[0], point[1]) == &arr.apply(point) ); + BOOST_TEST( arr2(is) == arr(is) ); + } - BOOST_REQUIRE( &arr[point[0]][point[1]] == &std::apply(arr, point) ); - BOOST_REQUIRE( &arr[point[0]][point[1]] == & apply(arr, point) ); -} + BOOST_AUTO_TEST_CASE(multi_tests_element_access_with_tuple) { + multi::array arr({3, 3}, 'k'); -BOOST_AUTO_TEST_CASE(multi_tests_extension_with_tuple) { - { - multi::array::extensions_type const ext = {3, 4}; + std::array point = { + {1, 2} + }; - multi::array const arr(ext, 44.0); + BOOST_TEST( arr[point[0]][point[1]] == arr(1, 2) ); + BOOST_TEST( &arr(point[0], point[1]) == &arr[point[0]][point[1]] ); - BOOST_REQUIRE( size(arr) == 3 ); - } - { - auto const [en, em] = std::make_tuple(3, 4); - multi::array const arr({en, em}, 44.0); - BOOST_REQUIRE( size(arr) == 3 ); + BOOST_TEST( &arr[point[0]][point[1]] == &arr(point[0], point[1]) ); + BOOST_TEST( &arr(point[0], point[1]) == &arr.apply(point) ); + + BOOST_TEST( &arr[point[0]][point[1]] == &std::apply(arr, point) ); + BOOST_TEST( &arr[point[0]][point[1]] == & apply(arr, point) ); } - { - auto arr = std::apply([](auto const&... szs) { return multi::array({szs...}, 55.0); }, std::make_tuple(3, 4)); - BOOST_REQUIRE( size(arr) == 3 ); - BOOST_REQUIRE( std::get<0>(sizes(arr)) == 3 ); - BOOST_REQUIRE( std::get<1>(sizes(arr)) == 4 ); + + BOOST_AUTO_TEST_CASE(multi_tests_extension_with_tuple) { + { + multi::array::extensions_type const ext = {3, 4}; + + multi::array const arr(ext, 44.0); + + BOOST_TEST( size(arr) == 3 ); + } + { + auto const [en, em] = std::make_tuple(3, 4); + multi::array const arr({en, em}, 44.0); + BOOST_TEST( size(arr) == 3 ); + } + { + auto arr = std::apply([](auto const&... szs) { return multi::array({szs...}, 55.0); }, std::make_tuple(3, 4)); + BOOST_TEST( size(arr) == 3 ); + + using std::get; + + BOOST_TEST( get<0>(arr.sizes()) == 3 ); + BOOST_TEST( get<1>(arr.sizes()) == 4 ); + } } -} -BOOST_AUTO_TEST_CASE(multi_test_constness_reference) { - multi::array const carr({10, 10}, '9'); + BOOST_AUTO_TEST_CASE(multi_test_constness_reference) { + multi::array const carr({10, 10}, '9'); - BOOST_REQUIRE( size( carr(1, {0, 3}) ) == 3 ); + BOOST_TEST( size( carr(1, {0, 3}) ) == 3 ); - BOOST_REQUIRE( carr(1, {0, 3})[1] == '9' ); - static_assert(decltype(carr({0, 3}, 1))::rank_v == 1); - BOOST_REQUIRE( size(carr.sliced(0, 3)) == 3 ); + BOOST_TEST( carr(1, {0, 3})[1] == '9' ); + static_assert(decltype(carr({0, 3}, 1))::rank_v == 1); + BOOST_TEST( size(carr.sliced(0, 3)) == 3 ); - BOOST_REQUIRE( carr.range({0, 3}).rotated()[1].unrotated().size() == 3 ); + BOOST_TEST( carr.range({0, 3}).rotated()[1].unrotated().size() == 3 ); - BOOST_REQUIRE( carr({0, 3}, {0, 3})[1][1] == '9' ); + BOOST_TEST( carr({0, 3}, {0, 3})[1][1] == '9' ); - static_assert(! std::is_assignable_v); -} + static_assert(!std::is_assignable_v); + } -BOOST_AUTO_TEST_CASE(multi_test_stencil) { - using namespace std::string_literals; // NOLINT(build/namespaces) ""s + BOOST_AUTO_TEST_CASE(multi_test_stencil) { + using namespace std::string_literals; // NOLINT(build/namespaces) ""s + + // NOLINTBEGIN(misc-include-cleaner) bug in clang-tidy 18 + multi::array arr = { + {"a"s, "b"s, "c"s, "d"s, "e"s}, + {"f"s, "g"s, "h"s, "f"s, "g"s}, + {"h"s, "i"s, "j"s, "k"s, "l"s}, + }; + // NOLINTEND(misc-include-cleaner) bug in clang-tidy 18 + + BOOST_TEST( size(arr) == 3 ); + BOOST_TEST( arr.num_elements() == 3*5L ); + BOOST_TEST( arr[1][2] == "h" ); + + BOOST_TEST( size(arr ({1, 3}, {2, 5})) == 2 ); + BOOST_TEST( extension(arr ({1, 3}, {2, 5})).first() == 0 ); + BOOST_TEST( arr ({1, 3}, {2, 5}).num_elements() == 2*3L ); + BOOST_TEST( arr ({1, 3}, {2, 5}).num_elements() == 2*3L ); + BOOST_TEST( arr ({1, 3}, {2, 5})[0][0] == "h" ); + BOOST_TEST( &arr ({1, 3}, {2, 5})[0][0] == &arr[1][2] ); + + BOOST_TEST( size(arr.stenciled({1, 3}, {2, 5})) == 2 ); + BOOST_TEST( extension(arr.stenciled({1, 3}, {2, 5})).first() == 1 ); + BOOST_TEST( arr.stenciled({1, 3}, {2, 5}).num_elements() == 2*3L ); + BOOST_TEST( arr.stenciled({1, 3}, {2, 5}) [1][2] == "h" ); + BOOST_TEST( &arr.stenciled({1, 3}, {2, 5}) [1][2] == &arr[1][2] ); + + BOOST_TEST( arr().elements().size() == arr.num_elements() ); + + BOOST_TEST( &arr({1, 3}, {2, 5}).elements()[0] == &arr(1, 2) ); + BOOST_TEST( &arr({1, 3}, {2, 5}).elements()[arr({1, 3}, {2, 5}).elements().size() - 1] == &arr(2, 4) ); + + BOOST_TEST( &arr({1, 3}, {2, 5}).elements().front() == &arr(1, 2) ); + BOOST_TEST( &arr({1, 3}, {2, 5}).elements().back() == &arr(2, 4) ); + } - multi::array arr = { - {"a"s, "b"s, "c"s, "d"s, "e"s}, - {"f"s, "g"s, "h"s, "f"s, "g"s}, - {"h"s, "i"s, "j"s, "k"s, "l"s}, - }; + BOOST_AUTO_TEST_CASE(empty_elements) { + multi::array arr1; + multi::array arr2; - BOOST_REQUIRE( size(arr) == 3 ); - BOOST_REQUIRE( arr.num_elements() == 3*5L ); - BOOST_REQUIRE( arr[1][2] == "h" ); + BOOST_TEST( arr1.elements().size() == 0 ); + BOOST_TEST( arr2.elements().size() == 0 ); + BOOST_TEST( arr1.elements() == arr2.elements() ); + BOOST_TEST( !(arr1.elements() != arr2.elements()) ); + } - BOOST_REQUIRE( size(arr ({1, 3}, {2, 5})) == 2 ); - BOOST_REQUIRE( extension(arr ({1, 3}, {2, 5})).first() == 0 ); - BOOST_REQUIRE( arr ({1, 3}, {2, 5}).num_elements() == 2*3L ); - BOOST_REQUIRE( arr ({1, 3}, {2, 5}).num_elements() == 2*3L ); - BOOST_REQUIRE( arr ({1, 3}, {2, 5})[0][0] == "h" ); - BOOST_REQUIRE( &arr ({1, 3}, {2, 5})[0][0] == &arr[1][2] ); + BOOST_AUTO_TEST_CASE(multi_test_elements_1D) { + multi::array arr = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + BOOST_TEST( arr.size() == 10 ); - BOOST_REQUIRE( size(arr.stenciled({1, 3}, {2, 5})) == 2 ); - BOOST_REQUIRE( extension(arr.stenciled({1, 3}, {2, 5})).first() == 1 ); - BOOST_REQUIRE( arr.stenciled({1, 3}, {2, 5}).num_elements() == 2*3L ); - BOOST_REQUIRE( arr.stenciled({1, 3}, {2, 5}) [1][2] == "h" ); - BOOST_REQUIRE( &arr.stenciled({1, 3}, {2, 5}) [1][2] == &arr[1][2] ); + BOOST_TEST( arr.elements().size() == 10 ); + BOOST_TEST( &arr.elements()[0] == &arr[0] ); + BOOST_TEST( &arr.elements()[9] == &arr[9] ); - BOOST_REQUIRE( arr().elements().size() == arr.num_elements() ); + BOOST_TEST( arr.elements().begin() < arr.elements().end() ); + BOOST_TEST( arr.elements().end() > arr.elements().begin() ); + BOOST_TEST( arr.elements().begin() != arr.elements().end() ); + BOOST_TEST( !( arr.elements().begin() == arr.elements().end() ) ); - BOOST_REQUIRE( &arr({1, 3}, {2, 5}).elements()[0] == &arr(1, 2) ); - BOOST_REQUIRE( &arr({1, 3}, {2, 5}).elements()[arr({1, 3}, {2, 5}).elements().size() - 1] == &arr(2, 4) ); + BOOST_TEST( arr().elements().begin() < arr().elements().end() ); + BOOST_TEST( arr().elements().begin() == arr().elements().begin() ); - BOOST_REQUIRE( &arr({1, 3}, {2, 5}).elements().front() == &arr(1, 2) ); - BOOST_REQUIRE( &arr({1, 3}, {2, 5}).elements().back() == &arr(2, 4) ); -} + BOOST_TEST( arr().elements().begin() < arr().elements().end() || arr().elements().begin() == arr().elements().end() ); + BOOST_TEST( arr().elements().begin() <= arr().elements().end() ); -BOOST_AUTO_TEST_CASE(empty_elements) { - multi::array arr1; - multi::array arr2; + BOOST_TEST( arr().elements().end() > arr().elements().begin() ); + BOOST_TEST( arr().elements().end() >= arr().elements().begin() ); - BOOST_REQUIRE( arr1.elements().size() == 0 ); - BOOST_REQUIRE( arr2.elements().size() == 0 ); - BOOST_REQUIRE( arr1.elements() == arr2.elements() ); - BOOST_REQUIRE( !(arr1.elements() != arr2.elements()) ); -} + arr.elements() = {9, 8, 7, 6, 5, 4, 3, 2, 1, 0}; + BOOST_TEST( arr[2] == 7 ); + BOOST_TEST( arr.elements()[2] == 7 ); + } -BOOST_AUTO_TEST_CASE(multi_test_elements_1D) { - multi::array arr = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; - BOOST_REQUIRE( arr.size() == 10 ); + BOOST_AUTO_TEST_CASE(multi_test_elements_1D_as_range) { + multi::array arr = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + BOOST_TEST( arr.size() == 10 ); - BOOST_REQUIRE( arr.elements().size() == 10 ); - BOOST_REQUIRE( &arr.elements()[0] == &arr[0] ); - BOOST_REQUIRE( &arr.elements()[9] == &arr[9] ); + arr().elements() = {9, 8, 7, 6, 5, 4, 3, 2, 1, 0}; + BOOST_TEST( arr[2] == 7 ); + BOOST_TEST( arr.elements()[2] == 7 ); - BOOST_REQUIRE( arr.elements().begin() < arr.elements().end() ); - BOOST_REQUIRE( arr.elements().end() > arr.elements().begin() ); - BOOST_REQUIRE( arr.elements().begin() != arr.elements().end() ); - BOOST_REQUIRE( !( arr.elements().begin() == arr.elements().end() ) ); + arr(2) = 9; + BOOST_TEST( arr[2] == 9 ); + } - BOOST_REQUIRE( arr().elements().begin() < arr().elements().end() ); - BOOST_REQUIRE( arr().elements().begin() == arr().elements().begin() ); + BOOST_AUTO_TEST_CASE(elements_from_init_list_2D) { + multi::array arr({3, 2}); + arr().elements() = {1, 2, 3, 4, 5, 6}; + BOOST_TEST(arr[1][0] == 3); - BOOST_REQUIRE( arr().elements().begin() < arr().elements().end() || arr().elements().begin() == arr().elements().end() ); - BOOST_REQUIRE( arr().elements().begin() <= arr().elements().end() ); + arr.elements() = {10, 20, 30, 40, 50, 60}; + BOOST_TEST(arr[1][0] == 30); + } - BOOST_REQUIRE( arr().elements().end() > arr().elements().begin() ); - BOOST_REQUIRE( arr().elements().end() >= arr().elements().begin() ); + BOOST_AUTO_TEST_CASE(front_back_2D) { + multi::array arr({3, 4}); + std::iota(arr.elements().begin(), arr.elements().end(), int{}); - arr.elements() = {9, 8, 7, 6, 5, 4, 3, 2, 1, 0}; - BOOST_REQUIRE( arr[2] == 7 ); - BOOST_REQUIRE( arr.elements()[2] == 7 ); -} + BOOST_TEST( arr.front()[2] == arr[0][2] ); + BOOST_TEST( &arr.front()[2] == &arr[0][2] ); -BOOST_AUTO_TEST_CASE(multi_test_elements_1D_as_range) { - multi::array arr = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; - BOOST_REQUIRE( arr.size() == 10 ); + BOOST_TEST( (*(arr.begin() + 2)).base() == arr[2].base() ); + BOOST_TEST( (arr.begin() + 2)->base() == arr[2].base() ); - arr().elements() = {9, 8, 7, 6, 5, 4, 3, 2, 1, 0}; - BOOST_REQUIRE( arr[2] == 7 ); - BOOST_REQUIRE( arr.elements()[2] == 7 ); -} + BOOST_TEST( (*(arr.end() - 1)).base() == arr[2].base() ); + BOOST_TEST( (arr.end() - 1)->base() == arr[2].base() ); -BOOST_AUTO_TEST_CASE(elements_from_init_list_2D) { - multi::array arr({3, 2}); - arr().elements() = {1, 2, 3, 4, 5, 6}; - BOOST_REQUIRE(arr[1][0] == 3); + // auto const prv = std::prev(arr.end()); + // BOOST_TEST( (*(prv)).base() == arr[2].base() ); // TODO(correaa) investigate why this fails in NVCC - arr.elements() = {10, 20, 30, 40, 50, 60}; - BOOST_REQUIRE(arr[1][0] == 30); -} + // BOOST_TEST( (*(std::prev(arr.end()))).base() == arr[2].base() ); // TODO(correaa) investigate why this fails in NVCC + // BOOST_TEST( (*(std::prev(arr.end(), 1))).base() == arr[2].base() ); // TODO(correaa) investigate why this fails in NVCC -BOOST_AUTO_TEST_CASE(front_back_2D) { - multi::array arr({3, 4}); - std::iota(arr.data_elements(), arr.data_elements() + arr.num_elements(), 0); + BOOST_TEST( arr.back ().base() == arr[2].base() ); + BOOST_TEST( arr.back () == arr[2] ); - BOOST_REQUIRE( arr.front()[2] == arr[0][2] ); - BOOST_REQUIRE( &arr.front()[2] == &arr[0][2] ); + BOOST_TEST( arr.back ()[2] == arr[2][2] ); + BOOST_TEST( &arr.back ()[2] == &arr[2][2] ); + } - BOOST_REQUIRE( arr.back ()[2] == arr[2][2] ); - BOOST_REQUIRE( &arr.back ()[2] == &arr[2][2] ); -} + BOOST_AUTO_TEST_CASE(front_back_1D) { + multi::array arr({30}, int{}); + std::iota(arr.elements().begin(), arr.elements().end(), 0); -BOOST_AUTO_TEST_CASE(front_back_1D) { - multi::array arr({30}, double{}); - std::iota(arr.data_elements(), arr.data_elements() + arr.num_elements(), 0); + BOOST_TEST( arr.front() == arr[ 0] ); + BOOST_TEST( &arr.front() == &arr[ 0] ); - BOOST_REQUIRE( arr.front() == arr[ 0] ); - BOOST_REQUIRE( &arr.front() == &arr[ 0] ); + BOOST_TEST( arr.back () == arr[29] ); + BOOST_TEST( &arr.back () == &arr[29] ); + } - BOOST_REQUIRE( arr.back () == arr[29] ); - BOOST_REQUIRE( &arr.back () == &arr[29] ); -} + BOOST_AUTO_TEST_CASE(elements_rvalues) { + using movable_type = std::vector; + movable_type const movable_value(5, 99); // NOLINT(fuchsia-default-arguments-calls) -BOOST_AUTO_TEST_CASE(elements_rvalues) { - using movable_type = std::vector; - movable_type const movable_value(5, 99); // NOLINT(fuchsia-default-arguments-calls) + multi::array arr = {movable_value, movable_value, movable_value}; + BOOST_TEST( arr.size() == 3 ); - multi::array arr = {movable_value, movable_value, movable_value}; - BOOST_REQUIRE( arr.size() == 3 ); + movable_type const front = std::move(arr)[0]; - movable_type const front = std::move(arr)[0]; + BOOST_TEST( front == movable_value ); + BOOST_TEST( arr[0].empty() ); // NOLINT(bugprone-use-after-move,hicpp-invalid-access-moved) for testing purposes + BOOST_TEST( arr[1] == movable_value ); // NOLINT(bugprone-use-after-move,hicpp-invalid-access-moved) for testing purposes - BOOST_REQUIRE( front == movable_value ); - BOOST_REQUIRE( arr[0].empty() ); // NOLINT(bugprone-use-after-move,hicpp-invalid-access-moved) for testing purposes - BOOST_REQUIRE( arr[1] == movable_value ); // NOLINT(bugprone-use-after-move,hicpp-invalid-access-moved) for testing purposes + std::move(arr)[1] = movable_value; + } - std::move(arr)[1] = movable_value; -} + BOOST_AUTO_TEST_CASE(elements_rvalues_nomove) { + using movable_type = std::vector; + movable_type const movable_value(5, 99.0); // NOLINT(fuchsia-default-arguments-calls) -template -void assign_elements_from_to(Array1D&& arr, std::deque>& dest) { // NOLINT(google-runtime-references) dest is mutated - std::copy(std::forward(arr).begin(), std::forward(arr).end(), std::back_inserter(dest)); -} + multi::array arr = {movable_value, movable_value, movable_value}; + BOOST_TEST( arr.size() == 3 ); -BOOST_AUTO_TEST_CASE(elements_rvalues_nomove) { - using movable_type = std::vector; - movable_type const movable_value(5., 99.0); // NOLINT(fuchsia-default-arguments-calls) + std::deque> q1; - multi::array arr = {movable_value, movable_value, movable_value}; - BOOST_REQUIRE( arr.size() == 3 ); + assign_elements_from_to(arr, q1); - std::deque> q1; + BOOST_TEST( arr[0] == movable_value ); - assign_elements_from_to(arr, q1); + std::deque> q2; - BOOST_REQUIRE( arr[0] == movable_value ); + assign_elements_from_to(std::move(arr), q2); - std::deque> q2; + // BOOST_TEST( arr[0].empty() ); // NOLINT(bugprone-use-after-move,hicpp-invalid-access-moved) for testing purposes - assign_elements_from_to(std::move(arr), q2); + BOOST_TEST( q1 == q2 ); + } - // BOOST_REQUIRE( arr[0].empty() ); // NOLINT(bugprone-use-after-move,hicpp-invalid-access-moved) for testing purposes + BOOST_AUTO_TEST_CASE(elements_rvalues_assignment) { + std::vector vec = {1.0, 2.0, 3.0}; // NOLINT(fuchsia-default-arguments-calls) - BOOST_REQUIRE( q1 == q2 ); -} + std::move(vec) = std::vector{3.0, 4.0, 5.0}; // NOLINT(fuchsia-default-arguments-calls) + + std::move(vec)[1] = 99.0; // it compiles // NOLINT(bugprone-use-after-move,hicpp-invalid-access-moved) for testing purposes -BOOST_AUTO_TEST_CASE(elements_rvalues_assignment) { - std::vector vec = {1.0, 2.0, 3.0}; // NOLINT(fuchsia-default-arguments-calls) + multi::array arr1 = {1.0, 2.0, 3.0}; + multi::array const arr2 = {1.0, 2.0, 3.0}; - std::move(vec) = std::vector{3.0, 4.0, 5.0}; // NOLINT(fuchsia-default-arguments-calls) + std::move(arr1) = arr2; // this compiles TODO(correaa) should it? + } + + BOOST_AUTO_TEST_CASE(range_2) { + multi::array arr3({3, 4, 5}, 99); + multi::array const brr3({2, 2, 5}, 88); + + // what(arr3, arr3({0, 2}, {0, 2})); + // what(arr3, arr3.range({0, 2}), arr3.paren_aux_({0, 2}), arr3({0, 2}), arr3({0, 2}, {0, 2})); + arr3({0, 2}, {0, 2}) = brr3; - std::move(vec)[1] = 99.0; // it compiles // NOLINT(bugprone-use-after-move,hicpp-invalid-access-moved) for testing purposes + BOOST_TEST( arr3[0][0][0] == 88 ); // should not compile + } - multi::array arr1 = {1.0, 2.0, 3.0}; - multi::array const arr2 = {1.0, 2.0, 3.0}; + { + multi::array const A2D({3, 3}, 11); + multi::array B2D({2, 2}, 22); + multi::array v1D(3, 33); + + using boost::multi::_; + v1D( _ ) = A2D( _ , 0 ); // v1D() = A2D( _ , 0); + v1D( _ ) = A2D( 0 , _ ); // v1D() = A2D( 0 ) ; + B2D( _ , _ ) = A2D({0, 2}, {0, 2}); // B2D() = A2D({0, 2}, {0, 2}); + } - std::move(arr1) = arr2; // this compiles TODO(correaa) should it? + return boost::report_errors(); } diff --git a/external_codes/boost_multi/multi/test/element_moved.cpp b/external_codes/boost_multi/multi/test/element_moved.cpp new file mode 100644 index 0000000000..07d3652b0f --- /dev/null +++ b/external_codes/boost_multi/multi/test/element_moved.cpp @@ -0,0 +1,76 @@ +// Copyright 2024 Alfredo A. Correa +// Distributed under the Boost Software License, Version 10. +// https://www.boost.org/LICENSE_1_0.txt + +#include + +#include // for array, apply, array_types<>::ele... + +// IWYU pragma: no_include // for remove_reference<>::type +// IWYU pragma: no_include +// IWYU pragma: no_include +// IWYU pragma: no_include +// IWYU pragma: no_include // for fill_n +// IWYU pragma: no_include +// IWYU pragma: no_include +#include // for move, swap +#include // for vector, operator==, vector<>::va... + +namespace multi = boost::multi; + +auto main() -> int { // NOLINT(readability-function-cognitive-complexity,bugprone-exception-escape) + // explicit_move_subarray_vector_2d_assign + { + multi::array, 2> arrA({10, 10}, std::vector(5, {}, {})); + + BOOST_TEST( arrA[2][2].size() == 5 ); + { + using std::move; + multi::array, 2> arrB(arrA().element_moved()); // (arrA.extensions()); + // arrB = arrA().element_moved(); + + BOOST_TEST( arrA.size() == 10 ); + BOOST_TEST( arrB.size() == 10 ); + BOOST_TEST( arrA[2][2].empty() ); + BOOST_TEST( arrB[2][2].size() == 5 ); + } + } + + // explicit_move_subarray_vector_2d_ctor + // { + // multi::array, 2> arrA({10, 10}, std::vector(5)); + + // BOOST_TEST( arrA[2][2].size() == 5 ); + // { + // using std::move; + // multi::array, 2> arrB{arrA().element_moved()}; + + // BOOST_TEST( arrA.size() == 10 ); + // BOOST_TEST( arrB.size() == 10 ); + // BOOST_TEST( arrA[2][2].size() == 0 ); + // BOOST_TEST( arrB[2][2].size() == 5 ); + // } + // } + + // BOOST_AUTO_TEST_CASE(explicit_move_subarray_vector_1d) + // { + // multi::array, 1> arrA(10, std::vector(5)); + + // BOOST_TEST( arrA[2].size() == 5 ); + // { + // using std::move; + // multi::array, 1> arrB(arrA.extensions()); + // arrB() = arrA().element_moved(); + // // std::copy(arrA().element_moved().begin(), arrA().element_moved().end(), arrB.begin()); + + // BOOST_TEST( arrA.size() == 10 ); + // BOOST_TEST( arrB.size() == 10 ); + // BOOST_TEST( arrA[2].size() == 0 ); + // BOOST_TEST( arrB[2].size() == 5 ); + // } + // } + + + + return boost::report_errors(); +} diff --git a/external_codes/boost_multi/multi/test/element_transformed.cpp b/external_codes/boost_multi/multi/test/element_transformed.cpp index 612dafb518..d64995f45d 100644 --- a/external_codes/boost_multi/multi/test/element_transformed.cpp +++ b/external_codes/boost_multi/multi/test/element_transformed.cpp @@ -3,91 +3,13 @@ // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt -#include - -#include -#include - -// Suppress warnings from boost.test -#if defined(__clang__) -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wold-style-cast" -# pragma clang diagnostic ignored "-Wundef" -# pragma clang diagnostic ignored "-Wconversion" -# pragma clang diagnostic ignored "-Wsign-conversion" -# pragma clang diagnostic ignored "-Wfloat-equal" -# pragma clang diagnostic ignored "-Wignored-qualifiers" -#elif defined(__GNUC__) -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wold-style-cast" -# pragma GCC diagnostic ignored "-Wundef" -# pragma GCC diagnostic ignored "-Wconversion" -# pragma GCC diagnostic ignored "-Wsign-conversion" -# pragma GCC diagnostic ignored "-Wfloat-equal" -#elif defined(_MSC_VER) -# pragma warning(push) -# pragma warning(disable : 4244) -#endif - -#ifndef BOOST_TEST_MODULE -# define BOOST_TEST_MAIN -#endif - -#include +#include // for transform_ptr, array, subarray -namespace multi = boost::multi; - -BOOST_AUTO_TEST_CASE(element_transformed_1D_conj_using_function_reference) { - using complex = std::complex; - auto const I = complex{0.0, 1.0}; // NOLINT(readability-identifier-length) I imaginary unit - - multi::array arr = {1.0 + 2.0 * I, 3.0 + 4.0 * I}; - - constexpr auto conj = static_cast(std::conj); - - auto const& conjd_arr = arr.element_transformed(conj); - BOOST_REQUIRE( conjd_arr[0] == conj(arr[0]) ); - BOOST_REQUIRE( conjd_arr[1] == conj(arr[1]) ); - - // Ac[0] = 5. + 4.*I; // this doesn't compile, good! - BOOST_REQUIRE( conjd_arr[0] == 1. - 2.*I ); - - BOOST_TEST_REQUIRE( real(std::inner_product(arr.begin(), arr.end(), conjd_arr.begin(), complex{0.0, 0.0})) == std::norm(arr[0]) + std::norm(arr[1]) ); - BOOST_REQUIRE( imag(std::inner_product(arr.begin(), arr.end(), conjd_arr.begin(), complex{0.0, 0.0})) == 0. ); - - BOOST_TEST_REQUIRE( std::inner_product(arr.begin(), arr.end(), conjd_arr.begin(), complex{0.0, 0.0}) == std::norm(arr[0]) + std::norm(arr[1]) ); -} - -BOOST_AUTO_TEST_CASE(element_transformed_1D_conj_using_lambda) { - using complex = std::complex; - auto const I = complex{0.0, 1.0}; // NOLINT(readability-identifier-length) I imaginary unit - - multi::array arr = {1.0 + 2.0 * I, 3.0 + 4.0 * I}; - - // g++ -std=20 needs the transformation (lambda) to be noexcept - auto const& conjd_arr = arr.element_transformed([](auto const& cee) noexcept { return std::conj(cee); }); - BOOST_REQUIRE( conjd_arr[0] == std::conj(arr[0]) ); - BOOST_REQUIRE( conjd_arr[1] == std::conj(arr[1]) ); - - // Ac[0] = 5. + 4.*I; // this doesn't compile, good! - BOOST_REQUIRE( conjd_arr[0] == 1.0 - 2.0*I ); -} - -BOOST_AUTO_TEST_CASE(element_transformed_1D_conj_using_lambda_with_const_return) { - using complex = std::complex; - auto const I = complex{0.0, 1.0}; // NOLINT(readability-identifier-length) I imaginary unit - - multi::array arr = {1.0 + 2.0 * I, 3.0 + 4.0 * I}; - - // g++ -std=20 needs the transformation (lambda) to be noexcept - // NOLINTNEXTLINE(readability-const-return-type) a way to disable assignment - auto&& conjd_arr = arr.element_transformed([](auto const& cee) noexcept -> auto const { return std::conj(cee); }); // `const` allows this idiom. it needs -Wno-nonportable-cfstrings and -Wignored-qualifiers in clang - BOOST_REQUIRE( conjd_arr[0] == std::conj(arr[0]) ); - BOOST_REQUIRE( conjd_arr[1] == std::conj(arr[1]) ); - - // conjd_arr[0] = 5.0 + 4.0*I; // this doesn't compile, good! otherwise it would be misleading (see above) - BOOST_REQUIRE( conjd_arr[0] == 1.0 - 2.0*I ); -} +// IWYU pragma: no_include // for copy // for GNU stdlib +// IWYU pragma: no_include // for declval // for GNU stdlib +#include // for complex, operator*, operator+ +#include // for declval, forward +#include // for vector template struct Conjd; // NOLINT(readability-identifier-naming) for testing @@ -103,7 +25,8 @@ template struct Conjd { // NOLINT(readability-identifier-naming) for testing using decay_type = decltype(+std::declval()); - // explicit constexpr operator decay_type() const { return std::conj(c_); } // NOLINT(google-explicit-constructor,hicpp-explicit-conversions) // NOSONAR(cpp:S1709) + // NOLINTNEXTLINE(google-explicit-constructor,hicpp-explicit-conversions) + // explicit constexpr operator decay_type() const {return std::conj(c_); } // NOSONAR(cpp:S1709) friend constexpr auto operator==(decay_type const& other, Conjd const& self) -> bool { return std::conj(self.c_) == other; } friend constexpr auto operator!=(decay_type const& other, Conjd const& self) -> bool { return std::conj(self.c_) != other; } @@ -125,156 +48,244 @@ struct Conjd { // NOLINT(readability-identifier-naming) for testing friend decltype(Conj); }; -BOOST_AUTO_TEST_CASE(element_transformed_1D_conj_using_proxy) { - using complex = std::complex; - auto const I = complex{0.0, 1.0}; // NOLINT(readability-identifier-length) I imaginary unit +namespace multi = boost::multi; - multi::array const arr = {1.0 + 2.0 * I, 3.0 + 4.0 * I}; +#include +#define BOOST_AUTO_TEST_CASE(CasenamE) /**/ - auto const& conj_arr = arr.element_transformed(Conj); - BOOST_REQUIRE( std::conj(arr[0]) == conj_arr[0] ); - BOOST_REQUIRE( std::conj(arr[1]) == conj_arr[1] ); +auto main() -> int { // NOLINT(readability-function-cognitive-complexity,bugprone-exception-escape) + BOOST_AUTO_TEST_CASE(element_transformed_1D_conj_using_function_reference) { + using complex = std::complex; + auto const I = complex{0.0, 1.0}; // NOLINT(readability-identifier-length) I imaginary unit - // Ac[0] = 5. + 4.*I; // not allowed, compile error, Ac is const - BOOST_REQUIRE( conj_arr[0] == 1.0 - 2.0*I ); -} + multi::array arr = {1.0 + 2.0 * I, 3.0 + 4.0 * I}; -BOOST_AUTO_TEST_CASE(element_transformed_1D_conj_using_mutable_proxy) { - using complex = std::complex; - auto const I = complex{0.0, 1.0}; // NOLINT(readability-identifier-length) I imaginary unit + constexpr auto conj = static_cast(std::conj); - multi::array arr = {1.0 + 2.0 * I, 3.0 + 4.0 * I}; + auto const& conjd_arr = arr.element_transformed(conj); + BOOST_TEST( conjd_arr[0] == conj(arr[0]) ); + BOOST_TEST( conjd_arr[1] == conj(arr[1]) ); - auto&& conj_arr = arr.element_transformed(Conj); // NOLINT(readability-const-return-type) to disable assignment + // Ac[0] = 5. + 4.*I; // this doesn't compile, good! + BOOST_TEST( conjd_arr[0] == 1.0 - 2.0*I ); - BOOST_REQUIRE( std::conj(arr[0]) == conj_arr[0] ); - BOOST_REQUIRE( std::conj(arr[1]) == conj_arr[1] ); + // BOOST_REQUIRE_CLOSE(real(std::inner_product(arr.begin(), arr.end(), conjd_arr.begin(), complex{ 0.0, 0.0 })), std::norm(arr[0]) + std::norm(arr[1]), 1E-6); + // BOOST_REQUIRE_CLOSE(imag(std::inner_product(arr.begin(), arr.end(), conjd_arr.begin(), complex{ 0.0, 0.0 })), 0.0, 1E-6); - conj_arr[0] = 5.0 + 4.0 * I; - BOOST_REQUIRE( conj_arr[0] == 5.0 + 4.0*I ); - BOOST_REQUIRE( arr[0] == 5.0 - 4.0*I ); -} + // BOOST_TEST_REQUIRE( std::inner_product(arr.begin(), arr.end(), conjd_arr.begin(), complex{0.0, 0.0}) == std::norm(arr[0]) + std::norm(arr[1]) ); + } -BOOST_AUTO_TEST_CASE(transform_ptr_single_value) { - using complex = std::complex; - auto const I = complex{0.0, 1.0}; // NOLINT(readability-identifier-length) I imaginary unit + BOOST_AUTO_TEST_CASE(element_transformed_1D_conj_using_lambda) { + using complex = std::complex; + auto const I = complex{0.0, 1.0}; // NOLINT(readability-identifier-length) I imaginary unit - complex cee = 1.0 + 2.0 * I; + multi::array arr = {1.0 + 2.0 * I, 3.0 + 4.0 * I}; - // NOLINTNEXTLINE(readability-const-return-type,clang-diagnostic-ignored-qualifiers) to prevent assignment - constexpr auto conj_ro = [](auto const& zee) noexcept { return std::conj(zee); }; // g++ -std=20 needs the transformation (lambda) to be noexcept + // g++ -std=20 needs the transformation (lambda) to be noexcept + auto const& conjd_arr = arr.element_transformed([](auto const& cee) noexcept { return std::conj(cee); }); + BOOST_TEST( conjd_arr[0] == std::conj(arr[0]) ); + BOOST_TEST( conjd_arr[1] == std::conj(arr[1]) ); - multi::transform_ptr const conjd_ceeP{&cee, conj_ro}; - BOOST_REQUIRE( *conjd_ceeP == std::conj(1.0 + 2.0*I) ); -} + // Ac[0] = 5. + 4.*I; // this doesn't compile, good! + BOOST_TEST( conjd_arr[0] == 1.0 - 2.0*I ); + } -BOOST_AUTO_TEST_CASE(transform_ptr_1D_array) { - using complex = std::complex; - auto const I = complex{0.0, 1.0}; // NOLINT(readability-identifier-length) I imaginary unit + BOOST_AUTO_TEST_CASE(element_transformed_1D_conj_using_lambda_with_const_return) { + using complex = std::complex; + auto const I = complex{0.0, 1.0}; // NOLINT(readability-identifier-length) I imaginary unit - multi::array arr = {1.0 + 2.0 * I, 3.0 + 4.0 * I}; + multi::array arr = {1.0 + 2.0 * I, 3.0 + 4.0 * I}; - // NOLINT(readability-const-return-type,clang-diagnostic-ignored-qualifiers) to prevent assignment - constexpr auto conj_ro = [](auto const& zee) noexcept { return std::conj(zee); }; // g++ -std=20 needs the transformation (lambda) to be noexcept + // g++ -std=20 needs the transformation (lambda) to be noexcept + auto&& conjd_arr = arr.element_transformed([](auto const& cee) noexcept { return std::conj(cee); }); - auto const& conjd_arr = arr.element_transformed(conj_ro); - BOOST_REQUIRE( conjd_arr[0] == conj_ro(arr[0]) ); - BOOST_REQUIRE( conjd_arr[1] == conj_ro(arr[1]) ); + BOOST_TEST( conjd_arr[0] == std::conj(arr[0]) ); + BOOST_TEST( conjd_arr[1] == std::conj(arr[1]) ); - // Ac[0] = 5. + 4.i; // doesn't compile thanks to the `auto const` in the `conj` def -} + // conjd_arr[0] = 5.0 + 4.0*I; // this compiles, but classes the implement operator= naively can be misleading here + BOOST_TEST( conjd_arr[0] == 1.0 - 2.0*I ); + } -BOOST_AUTO_TEST_CASE(arthur_odwyer_array_transform_int) { - struct S { // NOLINT(readability-identifier-naming) - int a; - int b; - }; + BOOST_AUTO_TEST_CASE(element_transformed_1D_conj_using_proxy) { + using complex = std::complex; + auto const I = complex{0.0, 1.0}; // NOLINT(readability-identifier-length) I imaginary unit - multi::array arr({2}, S{}); - auto&& ref = arr.element_transformed(&S::a); - ref[0] = 99.0; + multi::array const arr = {1.0 + 2.0 * I, 3.0 + 4.0 * I}; - BOOST_REQUIRE( arr[0].a == 99.0 ); + auto const& conj_arr = arr.element_transformed(Conj); + BOOST_TEST( std::conj(arr[0]) == conj_arr[0] ); + BOOST_TEST( std::conj(arr[1]) == conj_arr[1] ); - auto const& cref = arr.element_transformed(&S::a); - BOOST_REQUIRE( cref[0] == 99.0 ); - // cr[0] = 99.; // compile error "assignment of read-only location" -} + // Ac[0] = 5. + 4.*I; // not allowed, compile error, Ac is const + BOOST_TEST( conj_arr[0] == 1.0 - 2.0*I ); + } + + BOOST_AUTO_TEST_CASE(element_transformed_1D_conj_using_mutable_proxy) { + using complex = std::complex; + auto const I = complex{0.0, 1.0}; // NOLINT(readability-identifier-length) I imaginary unit -BOOST_AUTO_TEST_CASE(arthur_odwyer_array_transform_int_array) { - struct S { // NOLINT(readability-identifier-naming) - int a[10]; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) testing - int b; - }; + multi::array arr = {1.0 + 2.0 * I, 3.0 + 4.0 * I}; - multi::array vec({2}, S{}); + auto&& conj_arr = arr.element_transformed(Conj); // NOLINT(readability-const-return-type) to disable assignment - auto&& ref = vec.element_transformed(&S::a); + BOOST_TEST( std::conj(arr[0]) == conj_arr[0] ); + BOOST_TEST( std::conj(arr[1]) == conj_arr[1] ); - ref[0][1] = 99.0; + conj_arr[0] = 5.0 + 4.0 * I; + BOOST_TEST( conj_arr[0] == 5.0 + 4.0*I ); + BOOST_TEST( arr[0] == 5.0 - 4.0*I ); + } - BOOST_REQUIRE( ref[0][1] == 99.0 ); - BOOST_REQUIRE( vec[0].a[1] == 99.0 ); + BOOST_AUTO_TEST_CASE(transform_ptr_single_value) { + using complex = std::complex; + auto const I = complex{0.0, 1.0}; // NOLINT(readability-identifier-length) I imaginary unit - auto const& cref = vec.element_transformed(&S::a); - BOOST_REQUIRE( cref[0][1] == 99.0 ); - // cref[0][1] = 99.0; // compile error "assignment of read-only location" -} + complex cee = 1.0 + 2.0 * I; -BOOST_AUTO_TEST_CASE(indirect_transformed) { - std::vector vec = {0.0, 1.1, 2.2, 3.3, 4.4, 5.5}; // std::vector NOLINT(fuchsia-default-arguments-calls) + // NOLINTNEXTLINE(readability-const-return-type,clang-diagnostic-ignored-qualifiers) to prevent assignment + constexpr auto conj_ro = [](auto const& zee) noexcept { + return std::conj(zee); + }; // g++ -std=20 needs the transformation (lambda) to be noexcept - using index_t = std::vector::size_type; + multi::transform_ptr const conjd_ceeP{&cee, conj_ro}; + BOOST_TEST( *conjd_ceeP == std::conj(1.0 + 2.0*I) ); + } + + BOOST_AUTO_TEST_CASE(transform_ptr_1D_array) { + using complex = std::complex; + auto const I = complex{0.0, 1.0}; // NOLINT(readability-identifier-length) I imaginary unit - multi::array const arr = {4, 3, 2, 1, 0}; + multi::array arr = {1.0 + 2.0 * I, 3.0 + 4.0 * I}; - auto&& indirect_v = arr.element_transformed([&vec](index_t idx) noexcept -> double& { return vec[idx]; }); + // NOLINT(readability-const-return-type,clang-diagnostic-ignored-qualifiers) to prevent assignment + constexpr auto conj_ro = [](auto const& zee) noexcept { + return std::conj(zee); + }; // g++ -std=20 needs the transformation (lambda) to be noexcept - BOOST_REQUIRE( indirect_v[1] == vec[3] ); - BOOST_REQUIRE( &indirect_v[1] == &vec[3] ); + auto const& conjd_arr = arr.element_transformed(conj_ro); + BOOST_TEST( conjd_arr[0] == conj_ro(arr[0]) ); + BOOST_TEST( conjd_arr[1] == conj_ro(arr[1]) ); - indirect_v[1] = 99.0; - BOOST_REQUIRE( vec[3] == 99.0 ); + // Ac[0] = 5. + 4.i; // doesn't compile thanks to the `auto const` in the `conj` def + } - // for(auto&& elem : indirect_v) {elem = 88.;} - // std::fill(indirect_v.begin(), indirect_v.end(), 88.0); + BOOST_AUTO_TEST_CASE(arthur_odwyer_array_transform_int) { + struct S { // NOLINT(readability-identifier-naming) + int a; + int b; + }; -#if !defined(_MSC_VER) - indirect_v.fill(88.0); - BOOST_REQUIRE( vec[3] == 88.0 ); + multi::array arr({2}, S{}); - auto const& const_indirect_v = indirect_v; - (void)const_indirect_v; - // const_indirect_v[1] = 999.; // does not compile, good! - BOOST_REQUIRE(const_indirect_v[3] == 88.0); -#endif -} + auto&& ref = arr.element_transformed(&S::a); + + ref[0] = 990; + + BOOST_TEST( arr[0].a == 990 ); + + auto const& cref = arr.element_transformed(&S::a); + BOOST_TEST( cref[0] == 990 ); + // cr[0] = 99.; // compile error "assignment of read-only location" + } + + BOOST_AUTO_TEST_CASE(arthur_odwyer_array_transform_int_array) { + struct S { // NOLINT(readability-identifier-naming) + int a[10]; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) testing + int b; + }; + + multi::array vec({2}, S{}); + + auto&& ref = vec.element_transformed(&S::a); + + #if defined(__clang__) + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wunknown-warning-option" + #pragma clang diagnostic ignored "-Wunsafe-buffer-usage" + #endif + + ref[0][1] = 990; + + BOOST_TEST( ref[0][1] == 990 ); + + BOOST_TEST( vec[0].a[1] == 990 ); + + auto const& cref = vec.element_transformed(&S::a); + BOOST_TEST( cref[0][1] == 990 ); + // cref[0][1] = 990; // compile error "assignment of read-only location" -BOOST_AUTO_TEST_CASE(indirect_transformed_carray) { - // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) testing legacy types - double carr[5][3] = { - { 0.0, 1.0, 2.0}, - {10.0, 11.0, 12.0}, - {20.0, 21.0, 22.0}, - {30.0, 31.0, 32.0}, - {40.0, 41.0, 42.0}, - }; + #if defined(__clang__) + #pragma clang diagnostic pop + #endif + } + + BOOST_AUTO_TEST_CASE(indirect_transformed) { + std::vector vec = {00, 11, 22, 33, 44, 55}; // std::vector NOLINT(fuchsia-default-arguments-calls) + + using index_t = std::vector::size_type; + + multi::array const arr = {4, 3, 2, 1, 0}; + + auto&& indirect_v = arr.element_transformed([&vec](index_t idx) noexcept -> int& { return vec[idx]; }); + + BOOST_TEST( indirect_v[1] == vec[3] ); + BOOST_TEST( &indirect_v[1] == &vec[3] ); + + indirect_v[1] = 990; + BOOST_TEST( vec[3] == 990 ); + + // for(auto&& elem : indirect_v) {elem = 88.;} + // std::fill(indirect_v.begin(), indirect_v.end(), 88.0); - using index_t = std::vector::size_type; + #if !defined(_MSC_VER) + indirect_v.fill(880); + BOOST_TEST( vec[3] == 880 ); - multi::array const arr = {4, 3, 2, 1, 0}; + auto const& const_indirect_v = indirect_v; + (void)const_indirect_v; + // const_indirect_v[1] = 9990; // does not compile, good! + BOOST_TEST(const_indirect_v[3] == 880); + #endif + } + + BOOST_AUTO_TEST_CASE(indirect_transformed_carray) { + #if defined(__clang__) + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wunknown-warning-option" + #pragma clang diagnostic ignored "-Wunsafe-buffer-usage" + #endif + + // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) testing legacy types + int carr[5][3] = { + { 00, 10, 20}, + {100, 110, 120}, + {200, 210, 220}, + {300, 310, 320}, + {400, 410, 420}, + }; + + using index_t = std::vector::size_type; - // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) - auto&& indirect_v = arr.element_transformed([&carr](index_t idx) noexcept -> double(&)[3] { return carr[idx]; }); + multi::array const arr = {4, 3, 2, 1, 0}; - BOOST_REQUIRE( &indirect_v[1][2] == &carr[3][2] ); - BOOST_REQUIRE( indirect_v[1][2] == 32.0 ); + // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) + auto&& indirect_v = arr.element_transformed([&carr](index_t idx) noexcept -> int(&)[3] { return carr[idx]; }); - indirect_v[1][2] = 11111.0; - BOOST_TEST ( indirect_v[1][2] == 11111.0 ); + BOOST_TEST( &indirect_v[1][2] == &carr[3][2] ); + BOOST_TEST( indirect_v[1][2] == 320 ); - auto const& const_indirect_v = indirect_v; + indirect_v[1][2] = 111110; + BOOST_TEST ( indirect_v[1][2] == 111110 ); + + auto const& const_indirect_v = indirect_v; + + BOOST_TEST( const_indirect_v[1][2] == 111110 ); // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic) testing legacy type + + // const_indirect_v[1][2] = 999.0; // doesn't compile, good! + #if defined(__clang__) + #pragma clang diagnostic pop + #endif + } - BOOST_REQUIRE( const_indirect_v[1][2] == 11111.0 ); // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic) testing legacy type - // const_indirect_v[1][2] = 999.; // doesn't compile, good! + return boost::report_errors(); } diff --git a/external_codes/boost_multi/multi/test/execution_policy.disable_cpp b/external_codes/boost_multi/multi/test/execution_policy.disable_cpp index 52972f0d8b..5226e1514c 100644 --- a/external_codes/boost_multi/multi/test/execution_policy.disable_cpp +++ b/external_codes/boost_multi/multi/test/execution_policy.disable_cpp @@ -26,14 +26,12 @@ # pragma clang diagnostic ignored "-Wundef" # pragma clang diagnostic ignored "-Wconversion" # pragma clang diagnostic ignored "-Wsign-conversion" -# pragma clang diagnostic ignored "-Wfloat-equal" #elif defined(__GNUC__) # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wold-style-cast" # pragma GCC diagnostic ignored "-Wundef" # pragma GCC diagnostic ignored "-Wconversion" # pragma GCC diagnostic ignored "-Wsign-conversion" -# pragma GCC diagnostic ignored "-Wfloat-equal" #endif #ifndef BOOST_TEST_MODULE diff --git a/external_codes/boost_multi/multi/test/extensions.cpp b/external_codes/boost_multi/multi/test/extensions.cpp new file mode 100644 index 0000000000..90601bc0f0 --- /dev/null +++ b/external_codes/boost_multi/multi/test/extensions.cpp @@ -0,0 +1,53 @@ +// Copyright 2021-2024 Alfredo A. Correa +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include + +#include + +#include // IWYU pragma: keep + +namespace multi = boost::multi; + +auto main() -> int { // NOLINT(bugprone-exception-escape) + multi::array A2D({5, 7}, 1); + auto const A2Dx = A2D.extension(); + + BOOST_TEST( &A2D() == &A2D(A2Dx) ); + + auto const A2Dxs = A2D.extensions(); + + using std::get; + + BOOST_TEST( get<0>(A2Dxs) == A2Dx ); + BOOST_TEST( get<1>(A2Dxs) == A2D[0].extension() ); + + using std::get; + + BOOST_TEST( &A2D() == &A2D(get<0>(A2D.extensions()), get<1>(A2D.extensions())) ); + BOOST_TEST( &A2D() == &std::apply(A2D, A2Dxs) ); + + BOOST_TEST( A2Dxs.size() == A2D.size() ); + BOOST_TEST( A2Dxs.sizes() == A2D.sizes() ); + + auto const [ni, nj] = A2Dxs.sizes(); + for(int i = 0; i != ni; ++i) { // NOLINT(altera-unroll-loops) + for(int j = 0; j != nj; ++j) { // NOLINT(altera-unroll-loops) + auto const [first, second] = A2Dxs[i][j]; + BOOST_TEST( first == i ); + BOOST_TEST( second == j ); + } + } + + auto const [is, js] = A2Dxs; + for(auto const i : is) { // NOLINT(altera-unroll-loops) + for(auto const j : js) { // NOLINT(altera-unroll-loops) + auto const [first, second] = A2Dxs[i][j]; + BOOST_TEST( first == i ); + BOOST_TEST( second == j ); + } + } + + return boost::report_errors(); +} diff --git a/external_codes/boost_multi/multi/test/fill.cpp b/external_codes/boost_multi/multi/test/fill.cpp index b431923929..d4f15d182a 100644 --- a/external_codes/boost_multi/multi/test/fill.cpp +++ b/external_codes/boost_multi/multi/test/fill.cpp @@ -3,39 +3,18 @@ // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt -#include - -#include // for std::transform -#include -#include // for std::accumulate -#include -#include // for std::enable_if_t - -// Suppress warnings from boost.test -#if defined(__clang__) -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wold-style-cast" -# pragma clang diagnostic ignored "-Wundef" -# pragma clang diagnostic ignored "-Wconversion" -# pragma clang diagnostic ignored "-Wsign-conversion" -# pragma clang diagnostic ignored "-Wfloat-equal" -#elif defined(__GNUC__) -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wold-style-cast" -# pragma GCC diagnostic ignored "-Wundef" -# pragma GCC diagnostic ignored "-Wconversion" -# pragma GCC diagnostic ignored "-Wsign-conversion" -# pragma GCC diagnostic ignored "-Wfloat-equal" -#elif defined(_MSC_VER) -# pragma warning(push) -# pragma warning(disable : 4244) -#endif - -#ifndef BOOST_TEST_MODULE -# define BOOST_TEST_MAIN -#endif - -#include +#include + +#include // for array, apply, operator== + +#include // for fill, all_of, transform +#include // for ptrdiff_t +#include // for uint64_t +#include // for begin, end, size, next +#include // for numeric_limits +#include // for accumulate +#include // for uniform_int_distribution +#include // for enable_if_t, is_same_v namespace { @@ -55,10 +34,16 @@ class fnv1a_t { public: using result_type = fnv1a_size; - static constexpr auto min() { return std::numeric_limits::min(); } - static constexpr auto max() { return std::numeric_limits::max(); } - void operator()(unsigned char const* key, std::ptrdiff_t len) noexcept { h_ = fnv1a(key, len, h_); } - template, int> = 0> + static constexpr auto(min)() { // paren for MSVC macros + return (std::numeric_limits::min)(); + } + static constexpr auto(max)() { + return (std::numeric_limits::max)(); + } + + void operator()(unsigned char const* key, std::ptrdiff_t len) noexcept { h_ = fnv1a(key, len, h_); } + + template, int> = 0> // NOLINT(modernize-use-constraints) TODO(correaa) for C++20 auto operator()(T const& value) noexcept -> decltype(auto) { operator()(&value, sizeof(value)); return *this; @@ -69,180 +54,164 @@ class fnv1a_t { explicit operator result_type() const& noexcept { return h_; } }; -BOOST_AUTO_TEST_CASE(fill_1d_a) { - namespace multi = boost::multi; +#define BOOST_AUTO_TEST_CASE(CasenamE) /**/ - multi::array d1D(multi::extensions_t<1>{multi::iextension{10}}); - static_assert(std::is_same_v::value_type, multi::index>, "!"); +auto main() -> int { // NOLINT(readability-function-cognitive-complexity,bugprone-exception-escape) + BOOST_AUTO_TEST_CASE(fill_1d_a) { + namespace multi = boost::multi; - using std::copy; - copy(begin(extension(d1D)), end(extension(d1D)), begin(d1D)); - BOOST_REQUIRE( d1D[0] == 0 ); - BOOST_REQUIRE( d1D[1] == 1 ); - BOOST_REQUIRE( d1D[9] == 9 ); + multi::array d1D(multi::extensions_t<1>{multi::iextension{10}}); + static_assert(std::is_same_v::value_type, multi::index>); - d1D.assign(extension(d1D)); - BOOST_REQUIRE( d1D[0] == 0 ); - BOOST_REQUIRE( d1D[1] == 1 ); - BOOST_REQUIRE( d1D[9] == 9 ); -} + using std::copy; + copy(begin(extension(d1D)), end(extension(d1D)), begin(d1D)); + BOOST_TEST( d1D[0] == 0 ); + BOOST_TEST( d1D[1] == 1 ); + BOOST_TEST( d1D[9] == 9 ); -BOOST_AUTO_TEST_CASE(fill_1d_b) { - namespace multi = boost::multi; + d1D.assign(extension(d1D)); + BOOST_TEST( d1D[0] == 0 ); + BOOST_TEST( d1D[1] == 1 ); + BOOST_TEST( d1D[9] == 9 ); + } - multi::array d1D(begin(multi::index_extension(10)), end(multi::index_extension(10))); - BOOST_REQUIRE( size(d1D) == 10 ); - BOOST_REQUIRE( d1D[0] == 0 ); - BOOST_REQUIRE( d1D[1] == 1 ); - BOOST_REQUIRE( d1D[9] == 9 ); -} + BOOST_AUTO_TEST_CASE(fill_1d_b) { + namespace multi = boost::multi; -BOOST_AUTO_TEST_CASE(fill_1d_c) { - namespace multi = boost::multi; + multi::array d1D(begin(multi::index_extension(10)), end(multi::index_extension(10))); + BOOST_TEST( size(d1D) == 10 ); + BOOST_TEST( d1D[0] == 0 ); + BOOST_TEST( d1D[1] == 1 ); + BOOST_TEST( d1D[9] == 9 ); + } - multi::array d1D(multi::extensions_t<1>{multi::iextension{10}}); - BOOST_REQUIRE( size(d1D) == 10 ); + BOOST_AUTO_TEST_CASE(fill_1d_c) { + namespace multi = boost::multi; - d1D.assign(begin(extension(d1D)), end(extension(d1D))); - BOOST_REQUIRE( d1D[0] == 0 ); - BOOST_REQUIRE( d1D[1] == 1 ); - BOOST_REQUIRE( d1D[9] == 9 ); -} + multi::array d1D(multi::extensions_t<1>{multi::iextension{10}}); + BOOST_TEST( size(d1D) == 10 ); -BOOST_AUTO_TEST_CASE(fill_1d_d) { - namespace multi = boost::multi; + d1D.assign(begin(extension(d1D)), end(extension(d1D))); + BOOST_TEST( d1D[0] == 0 ); + BOOST_TEST( d1D[1] == 1 ); + BOOST_TEST( d1D[9] == 9 ); + } - multi::array d1D(multi::extensions_t<1>{multi::iextension{10}}); - d1D.assign(extension(d1D)); - BOOST_REQUIRE( d1D[0] == 0 ); - BOOST_REQUIRE( d1D[1] == 1 ); - BOOST_REQUIRE( d1D[9] == 9 ); -} + BOOST_AUTO_TEST_CASE(fill_1d_d) { + namespace multi = boost::multi; -BOOST_AUTO_TEST_CASE(fill_member) { - namespace multi = boost::multi; + multi::array d1D(multi::extensions_t<1>{multi::iextension{10}}); + d1D.assign(extension(d1D)); + BOOST_TEST( d1D[0] == 0 ); + BOOST_TEST( d1D[1] == 1 ); + BOOST_TEST( d1D[9] == 9 ); + } - multi::array d1D = {1.0, 2.0, 3.0, 4.0}; - d1D.fill(42.0); + BOOST_AUTO_TEST_CASE(fill_member) { + namespace multi = boost::multi; - multi::array d2D = { - {150.0, 16.0, 17.0, 18.0, 19.0}, - { 5.0, 5.0, 5.0, 5.0, 5.0}, - {100.0, 11.0, 12.0, 13.0, 14.0}, - { 50.0, 6.0, 7.0, 8.0, 9.0}, - }; + multi::array d1D = {10, 20, 30, 40}; + d1D.fill(420); - BOOST_REQUIRE( d2D.elements().size() == d2D.num_elements() ); - BOOST_REQUIRE( d2D.elements().base() == d2D.base() ); - BOOST_REQUIRE( d2D.elements()[3] == 18.0 ); - BOOST_REQUIRE( &*d2D.elements().begin() == d2D.data_elements() ); - BOOST_REQUIRE( &*d2D.elements().end() == d2D.data_elements() + d2D.num_elements() ); + multi::array d2D = { + {1500, 160, 170, 180, 190}, + { 50, 50, 50, 50, 50}, + {1000, 110, 120, 130, 140}, + { 500, 60, 70, 80, 90}, + }; - // std::fill( d2D.elements().begin(), d2D.elements().end() , 99. ); - // multi::adl_fill_n( d2D.elements().begin(), d2D.elements().size(), 99. ); - d2D.elements().fill(99.0); + BOOST_TEST( d2D.elements().size() == d2D.num_elements() ); + BOOST_TEST( d2D.elements().base() == d2D.base() ); + BOOST_TEST( d2D.elements()[3] == 180 ); - BOOST_REQUIRE( d2D[1][1] == 99.0 ); -} + std::fill(d2D.elements().begin(), d2D.elements().end(), 990); -BOOST_AUTO_TEST_CASE(fill) { - std::random_device randdev; + BOOST_TEST( d2D[1][1] == 990 ); + } - namespace multi = boost::multi; + BOOST_AUTO_TEST_CASE(simple_fill) { + namespace multi = boost::multi; - multi::array d2D = { - {150.0, 16.0, 17.0, 18.0, 19.0}, - { 5.0, 5.0, 5.0, 5.0, 5.0}, - {100.0, 11.0, 12.0, 13.0, 14.0}, - { 50.0, 6.0, 7.0, 8.0, 9.0}, - }; - using std::all_of; - BOOST_REQUIRE( all_of(begin(d2D[1]), end(d2D[1]), [](auto const& elem) { return elem == 5.0;}) ); + multi::array d1D = {10, 20, 30, 40}; + std::fill_n(d1D.begin(), d1D.size(), 420); - using std::fill; - fill(d2D[1].begin(), d2D[1].end(), 8.0); + multi::array d2D = { + {1500, 160, 170, 180, 190}, + { 50, 50, 50, 50, 50}, + {1000, 110, 120, 130, 140}, + { 500, 60, 70, 80, 90}, + }; - BOOST_REQUIRE( all_of(begin(d2D[1]), end(d2D[1]), [](auto const& elem) { return elem == 8.0;}) ); + BOOST_TEST( d2D.elements().size() == d2D.num_elements() ); + BOOST_TEST( d2D.elements().base() == d2D.base() ); + BOOST_TEST( d2D.elements()[3] == 180 ); - fill(begin(rotated(d2D)[1]), end(rotated(d2D)[1]), 8.0); - BOOST_REQUIRE( all_of(begin(rotated(d2D)[1]), end(rotated(d2D)[1]), [](auto&& elem) { return elem == 8.0;}) ); + std::fill(d2D.elements().begin(), d2D.elements().end(), 990); - fill(begin((d2D.rotated())[1]), end((d2D.rotated())[1]), 8.0); - BOOST_REQUIRE( all_of(begin((d2D.rotated())[1]), end((d2D.rotated())[1]), [](auto&& elem) { return elem == 8.0;}) ); + BOOST_TEST( d2D[1][1] == 990 ); + } - auto rand = [gauss = std::normal_distribution<>{}, gen = std::mt19937_64(randdev())]() mutable { return gauss(gen); }; // NOSONAR + BOOST_AUTO_TEST_CASE(fill) { + std::random_device randdev; - multi::array r2D({5, 5}); - std::for_each(begin(r2D), end(r2D), [&](decltype(r2D)::reference elem) { std::generate(begin(elem), end(elem), rand); }); -} + namespace multi = boost::multi; -namespace multi = boost::multi; + multi::array d2D = { + {1500, 160, 170, 180, 190}, + { 50, 50, 50, 50, 50}, + {1000, 110, 120, 130, 140}, + { 500, 60, 70, 80, 90}, + }; + using std::all_of; + BOOST_TEST( all_of(begin(d2D[1]), end(d2D[1]), [](auto const& elem) { return elem == 50;}) ); -BOOST_AUTO_TEST_CASE(fill_1D) { - multi::array const arr = {1.0, 2.0, 3.0}; + using std::fill; + fill(d2D[1].begin(), d2D[1].end(), 80); - multi::array arr2({10, 3}); + BOOST_TEST( all_of(begin(d2D[1]), end(d2D[1]), [](auto const& elem) { return elem == 80;}) ); - std::fill(begin(arr2), end(arr2), arr); + fill(begin(d2D.rotated()[1]), end(d2D.rotated()[1]), 80); + BOOST_TEST( all_of(begin(d2D.rotated()[1]), end(d2D.rotated()[1]), [](auto&& elem) { return elem == 80;}) ); - BOOST_REQUIRE( arr2[0] == arr ); - BOOST_REQUIRE( arr2[1] == arr ); + fill(begin((d2D.rotated())[1]), end((d2D.rotated())[1]), 80); + BOOST_TEST( all_of(begin((d2D.rotated())[1]), end((d2D.rotated())[1]), [](auto&& elem) { return elem == 80;}) ); - BOOST_REQUIRE( arr2[9] == arr ); -} + auto rand = [gauss = std::uniform_int_distribution<>(0, 10), gen = std::mt19937_64(randdev())]() mutable { return gauss(gen); }; // NOSONAR -template -auto broadcast(BinaryOp op, Column const& col, Array const& in, Out&& out) -> Out&& { // NOLINT(readability-identifier-length) clang-tidy 14 bug - std::transform( - begin(~in), end(~in), begin(~out), begin(~out), - [acol = (~col)[0], &op](auto const& Acol, auto&& Bcol) { - std::transform(begin(Acol), end(Acol), begin(acol), begin(Bcol), op); - return std::forward(Bcol); - } - ); + multi::array r2D({5, 5}); + std::for_each(begin(r2D), end(r2D), [&](decltype(r2D)::reference elem) { std::generate(begin(elem), end(elem), rand); }); + } - return std::forward(out); -} + BOOST_AUTO_TEST_CASE(fill_1D) { + namespace multi = boost::multi; + + multi::array const arr = {1.0, 2.0, 3.0}; + + multi::array arr2({10, 3}); + + std::fill(begin(arr2), end(arr2), arr); + + BOOST_TEST( arr2[0] == arr ); + BOOST_TEST( arr2[1] == arr ); + + BOOST_TEST( arr2[9] == arr ); + } + + BOOST_AUTO_TEST_CASE(fill_n_1D) { + namespace multi = boost::multi; + + multi::array arr = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + + std::fill_n(arr.dropped(3).begin(), 4, 99); + // std::fill_n(arr.begin() + 3, 4, 99); + + BOOST_TEST( arr[2] == 2 ); + BOOST_TEST( arr[3] == 99 ); + BOOST_TEST( arr[4] == 99 ); + BOOST_TEST( arr[5] == 99 ); + BOOST_TEST( arr[6] == 99 ); + BOOST_TEST( arr[7] == 7 ); + } -BOOST_AUTO_TEST_CASE(julia_broadcast, *boost::unit_test::tolerance(0.00001)) { - multi::array const col = { - {0.1}, - {0.2}, - }; - multi::array arr = { - {1.10813, 1.72068, 1.15387}, - {1.36851, 1.66401, 1.47846}, - }; - - // "broadcast" - multi::array arr2(extensions(arr)); - broadcast(std::plus<>{}, col, arr, arr2); - - BOOST_TEST( arr2[0][0] == 1.20813 ); - BOOST_TEST( arr2[0][1] == 1.82068 ); - BOOST_TEST( arr2[0][2] == 1.25387 ); - BOOST_TEST( arr2[1][0] == 1.56851 ); - BOOST_TEST( arr2[1][1] == 1.86401 ); - BOOST_TEST( arr2[1][2] == 1.67846 ); - - // inefficient: replicate the vector before summing elementwise - multi::array ax3({2, 3}); - - std::fill(begin(~ax3), end(~ax3), (~col)[0]); - BOOST_TEST( ax3[0][0] == 0.1 ); - BOOST_TEST( ax3[0][1] == 0.1 ); - BOOST_TEST( ax3[0][2] == 0.1 ); - BOOST_TEST( ax3[1][0] == 0.2 ); - BOOST_TEST( ax3[1][1] == 0.2 ); - BOOST_TEST( ax3[1][2] == 0.2 ); - - multi::array Ap(extensions(arr)); - std::transform(begin(arr.elements()), end(arr.elements()), begin(ax3.elements()), begin(Ap.elements()), std::plus<>{}); - - BOOST_TEST( Ap[0][0] == 1.20813 ); - BOOST_TEST( Ap[0][1] == 1.82068 ); - BOOST_TEST( Ap[0][2] == 1.25387 ); - BOOST_TEST( Ap[1][0] == 1.56851 ); - BOOST_TEST( Ap[1][1] == 1.86401 ); - BOOST_TEST( Ap[1][2] == 1.67846 ); + return boost::report_errors(); } diff --git a/external_codes/boost_multi/multi/test/fix_complex.cpp b/external_codes/boost_multi/multi/test/fix_complex.cpp index 46a2f00647..512362e787 100644 --- a/external_codes/boost_multi/multi/test/fix_complex.cpp +++ b/external_codes/boost_multi/multi/test/fix_complex.cpp @@ -4,33 +4,19 @@ // https://www.boost.org/LICENSE_1_0.txt #include -// #include - -#include -#include - -// Suppress warnings from boost.test -#if defined(__clang__) -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wold-style-cast" -# pragma clang diagnostic ignored "-Wundef" -# pragma clang diagnostic ignored "-Wconversion" -# pragma clang diagnostic ignored "-Wsign-conversion" -# pragma clang diagnostic ignored "-Wfloat-equal" -#elif defined(__GNUC__) -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wold-style-cast" -# pragma GCC diagnostic ignored "-Wundef" -# pragma GCC diagnostic ignored "-Wconversion" -# pragma GCC diagnostic ignored "-Wsign-conversion" -# pragma GCC diagnostic ignored "-Wfloat-equal" -#endif -#ifndef BOOST_TEST_MODULE -# define BOOST_TEST_MAIN -#endif +#include // for array +#include // for _LIBCPP_VERSION // IWYU pragma: keep +#include // for abs // IWYU pragma: keep +// IWYU pragma: no_include // for abs +// IWYU pragma: no_include // for abs +#include // for complex, operator== +// IWYU pragma: no_include // for __GLIBCXX__ +#include // for data -#include +#ifdef BOOST_MULTI_HAS_MEMORY_RESOURCE + #include // for monotonic_buffer_resource +#endif namespace multi = boost::multi; @@ -45,140 +31,163 @@ template inline constexpr bool multi::force_element_trivial_default_construction> = std::is_trivially_default_constructible_v; #endif +#include +#define BOOST_AUTO_TEST_CASE(CasenamE) /**/ + +auto main() -> int { // NOLINT(readability-function-cognitive-complexity,bugprone-exception-escape) BOOST_AUTO_TEST_CASE(pmr_double) { - multi::array, 2> Aarr({2, 2}, std::complex(4.0, 5.0)); - BOOST_REQUIRE(Aarr[0][0] == std::complex(4.0, 5.0) ); + multi::array, 2> Aarr({ 2, 2 }, std::complex(4.0, 5.0)); + BOOST_TEST(Aarr[0][0] == std::complex(4.0, 5.0) ); } #ifdef BOOST_MULTI_HAS_MEMORY_RESOURCE BOOST_AUTO_TEST_CASE(pmr_double_uninitialized) { { - std::array buffer = {{4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.00, 11.0, 996.0, 997.0, 998.0, 999.0}}; - std::pmr::monotonic_buffer_resource pool(static_cast(std::data(buffer)), 12*sizeof(double)); + std::array buffer = { + { 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.00, 11.0, 996.0, 997.0, 998.0, 999.0 } + }; + std::pmr::monotonic_buffer_resource pool(static_cast(std::data(buffer)), 12 * sizeof(double)); - multi::pmr::array Aarr({2, 2}, &pool); + multi::pmr::array Aarr({ 2, 2 }, &pool); - BOOST_TEST( buffer[0] == 4.0 ); - BOOST_TEST( buffer[1] == 5.0 ); + BOOST_TEST( std::abs( buffer[0] - 4.0 ) < 1E-6 ); + BOOST_TEST( std::abs( buffer[1] - 5.0 ) < 1E-6 ); #if defined(__GLIBCXX__) - BOOST_TEST( &Aarr[0][0] == buffer.data() ); - BOOST_TEST( Aarr[0][0] == 4.0); + BOOST_TEST ( &Aarr[0][0] == buffer.data() ); + BOOST_TEST( std::abs( Aarr[0][0] - 4.0 ) < 1E-6); #elif defined(_LIBCPP_VERSION) - BOOST_TEST( &Aarr[0][0] == buffer.data() + (buffer.size() - 4) ); // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic) - BOOST_TEST( Aarr[0][0] == 996.0); + BOOST_TEST ( &Aarr[0][0] == &buffer[buffer.size() - 4] ); // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic) + BOOST_TEST( std::abs( Aarr[0][0] - 996.0 ) < 1E-6 ); #endif } { - std::array buffer = {{4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.00, 11.0, 996.0, 997.0, 998.0, 999.0}}; - std::pmr::monotonic_buffer_resource pool(static_cast(std::data(buffer)), 12*sizeof(double)); + std::array buffer = { + { 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.00, 11.0, 996.0, 997.0, 998.0, 999.0 } + }; + std::pmr::monotonic_buffer_resource pool(static_cast(std::data(buffer)), 12 * sizeof(double)); - multi::pmr::array Aarr({2, 2}, double{}, &pool); + multi::pmr::array Aarr({ 2, 2 }, double{}, &pool); #if defined(__GLIBCXX__) - BOOST_TEST( buffer[0] == 0.0 ); - BOOST_TEST( buffer[1] == 0.0 ); + BOOST_TEST( std::abs( buffer[0] - 0.0 ) < 1E-6 ); + BOOST_TEST( std::abs( buffer[1] - 0.0 ) < 1E-6 ); + BOOST_TEST( &Aarr[0][0] == buffer.data() ); #elif defined(_LIBCPP_VERSION) - BOOST_TEST( buffer[0] == 4.0 ); - BOOST_TEST( buffer[1] == 5.0 ); - BOOST_TEST( buffer[buffer.size()-4] == 0.0 ); - BOOST_TEST( buffer[buffer.size()-3] == 0.0 ); - BOOST_TEST( buffer[buffer.size()-5] == 11.0 ); - BOOST_TEST( &Aarr[0][0] == buffer.data() + (buffer.size() - 4) ); // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic) + BOOST_TEST( std::abs( buffer[0] - 4.0 ) < 1E-6); + BOOST_TEST( std::abs( buffer[1] - 5.0 ) < 1E-6 ); + BOOST_TEST( std::abs( buffer[buffer.size()-4] - 0.0 ) < 1E-6 ); + BOOST_TEST( std::abs( buffer[buffer.size()-3] - 0.0 ) < 1E-6 ); + BOOST_TEST( std::abs( buffer[buffer.size()-5] - 11.0 ) < 1E-6 ); + + BOOST_TEST( &Aarr[0][0] == &buffer[buffer.size() - 4] ); // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic) #endif - BOOST_TEST( Aarr[0][0] == 0.0); + BOOST_TEST( std::abs( Aarr[0][0] - 0.0 ) < 1E-6); } } BOOST_AUTO_TEST_CASE(pmr_complex_initialized_2) { - std::array buffer = {{4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.00, 11.0, 996.0, 997.0, 998.0, 999.0}}; - std::pmr::monotonic_buffer_resource pool{static_cast(std::data(buffer)), 12*sizeof(double)}; - - multi::pmr::array, 2> Aarr({2, 2}, &pool); - -#if defined(__GLIBCXX__) - BOOST_TEST( buffer[0] == 4.0 ); - BOOST_TEST( buffer[1] == 5.0 ); - BOOST_REQUIRE(Aarr[0][0] == std::complex(4.0, 5.0) ); -#elif defined(_LIBCPP_VERSION) - BOOST_TEST( buffer[buffer.size() - 4] == 996.0 ); - BOOST_TEST( buffer[buffer.size() - 3] == 997.0 ); - BOOST_TEST(Aarr[0][0].real() == 8.0 ); - BOOST_TEST(Aarr[0][0].imag() == 9.0 ); -#endif - Aarr[0][0] = std::complex{40.0, 50.0}; - -#if defined(__GLIBCXX__) - BOOST_TEST( buffer[0] == 40.0 ); - BOOST_TEST( buffer[1] == 50.0 ); -#elif defined(_LIBCPP_VERSION) - BOOST_TEST( buffer[buffer.size() - 4] == 996.0 ); - BOOST_TEST( buffer[buffer.size() - 3] == 997.0 ); -#endif + std::array buffer = { + { 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.00, 11.0, 996.0, 997.0, 998.0, 999.0 } + }; + std::pmr::monotonic_buffer_resource pool{ static_cast(std::data(buffer)), 12 * sizeof(double) }; + + multi::pmr::array, 2> Aarr({ 2, 2 }, &pool); + + #if defined(__GLIBCXX__) + BOOST_TEST( std::abs( buffer[0] - 4.0 ) < 1E-6 ); + BOOST_TEST( std::abs( buffer[1] - 5.0 ) < 1E-6 ); + BOOST_TEST( Aarr[0][0] == std::complex(4.0, 5.0) ); + #elif defined(_LIBCPP_VERSION) + BOOST_TEST( std::abs( buffer[buffer.size() - 4] - 996.0 ) < 1E-6 ); + BOOST_TEST( std::abs( buffer[buffer.size() - 3] - 997.0 ) < 1E-6 ); + BOOST_TEST( std::abs( Aarr[0][0].real() - 8.0 ) < 1E-6 ); + BOOST_TEST( std::abs( Aarr[0][0].imag() - 9.0 ) < 1E-6 ); + #endif + Aarr[0][0] = std::complex{ 40.0, 50.0 }; + + #if defined(__GLIBCXX__) + BOOST_TEST( std::abs( buffer[0] - 40.0 ) < 1E-6 ); + BOOST_TEST( std::abs( buffer[1] - 50.0 ) < 1E-6 ); + #elif defined(_LIBCPP_VERSION) + BOOST_TEST( std::abs( buffer[buffer.size() - 4] - 996.0 ) < 1E-6 ); + BOOST_TEST( std::abs( buffer[buffer.size() - 3] - 997.0 ) < 1E-6 ); + #endif } BOOST_AUTO_TEST_CASE(pmr_complex_initialized_4) { - std::array buffer = {{4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.00, 11.0, 999.9, 999.9, 999.9, 999.9}}; - std::pmr::monotonic_buffer_resource pool{static_cast(std::data(buffer)), 12*sizeof(double)}; + std::array buffer = { + { 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.00, 11.0, 999.9, 999.9, 999.9, 999.9 } + }; + std::pmr::monotonic_buffer_resource pool{ static_cast(std::data(buffer)), 12 * sizeof(double) }; - multi::pmr::array, 2> Aarr({2, 2}, &pool); + multi::pmr::array, 2> Aarr({ 2, 2 }, &pool); -#if defined(__GLIBCXX__) - BOOST_REQUIRE(Aarr[0][0] == std::complex(4.0, 5.0) ); -#elif defined(_LIBCPP_VERSION) - BOOST_REQUIRE(Aarr[0][0] == std::complex(8.0, 9.0) ); -#endif + #if defined(__GLIBCXX__) + BOOST_TEST( std::abs( Aarr[0][0].real() - 4.0 ) < 1E-6 ); + BOOST_TEST( std::abs( Aarr[0][0].imag() - 5.0 ) < 1E-6 ); + #elif defined(_LIBCPP_VERSION) + BOOST_TEST( std::abs( Aarr[0][0].real() - 8.0 ) < 1E-6 ); + BOOST_TEST( std::abs( Aarr[0][0].imag() - 9.0 ) < 1E-6 ); + #endif - BOOST_TEST( buffer[0] == 4.0 ); - BOOST_TEST( buffer[1] == 5.0 ); + BOOST_TEST( std::abs( buffer[0] - 4.0 ) < 1E-6 ); + BOOST_TEST( std::abs( buffer[1] - 5.0 ) < 1E-6 ); -#if defined(__GLIBCXX__) + #if defined(__GLIBCXX__) BOOST_TEST( static_cast(buffer.data()) == static_cast(&Aarr[0][0]) ); -#elif defined(_LIBCPP_VERSION) - BOOST_TEST( static_cast(buffer.data() + 4) == static_cast(&Aarr[0][0]) ); // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic) -#endif + #elif defined(_LIBCPP_VERSION) + BOOST_TEST( static_cast(&buffer[4]) == static_cast(&Aarr[0][0]) ); // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic) + #endif } BOOST_AUTO_TEST_CASE(pmr_complex_initialized_3) { - std::array buffer = {{4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.00, 11.0, 996.0, 997.0, 998.0, 999.0}}; - std::pmr::monotonic_buffer_resource pool{static_cast(std::data(buffer)), 12*sizeof(double)}; + std::array buffer = { + { 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.00, 11.0, 996.0, 997.0, 998.0, 999.0 } + }; + std::pmr::monotonic_buffer_resource pool{ static_cast(std::data(buffer)), 12 * sizeof(double) }; - multi::pmr::array, 2> const Aarr({2, 2}, std::complex{40.0, 50.0}, &pool); + multi::pmr::array, 2> const Aarr({ 2, 2 }, std::complex{ 40.0, 50.0 }, &pool); - BOOST_TEST( Aarr[0][0] == (std::complex{40.0, 50.0}) ); + BOOST_TEST( std::abs( Aarr[0][0].real() - 40.0 ) < 1E-6 ); + BOOST_TEST( std::abs( Aarr[0][0].imag() - 50.0 ) < 1E-6 ); -#if defined(__GLIBCXX__) - BOOST_TEST( buffer[0] == 40.0 ); - BOOST_TEST( buffer[1] == 50.0 ); -#elif defined(_LIBCPP_VERSION) - BOOST_TEST( buffer[buffer.size() - 4] == 40.0 ); - BOOST_TEST( buffer[buffer.size() - 3] == 50.0 ); -#endif + #if defined(__GLIBCXX__) + BOOST_TEST( std::abs( buffer[0] - 40.0 ) < 1E-6 ); + BOOST_TEST( std::abs( buffer[1] - 50.0 ) < 1E-6 ); + #elif defined(_LIBCPP_VERSION) + BOOST_TEST( std::abs( buffer[buffer.size() - 4] - 40.0 ) < 1E-6 ); + BOOST_TEST( std::abs( buffer[buffer.size() - 3] - 50.0 ) < 1E-6 ); + #endif } BOOST_AUTO_TEST_CASE(pmr_complex_initialized) { - std::array buffer = {{4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.00, 11.0, 996.0, 997.0, 998.0, 999.0}}; - std::pmr::monotonic_buffer_resource pool{static_cast(std::data(buffer)), 12*sizeof(double)}; + std::array buffer = { + { 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.00, 11.0, 996.0, 997.0, 998.0, 999.0 } + }; + std::pmr::monotonic_buffer_resource pool{ static_cast(std::data(buffer)), 12 * sizeof(double) }; - multi::pmr::array, 2> Aarr({2, 2}, &pool); + multi::pmr::array, 2> Aarr({ 2, 2 }, &pool); if constexpr(multi::force_element_trivial_default_construction>) { - BOOST_TEST( buffer[0] == 4.0 ); - BOOST_TEST( buffer[1] == 5.0 ); + BOOST_TEST( std::abs( buffer[0] - 4.0 ) < 1E-6 ); + BOOST_TEST( std::abs( buffer[1] - 5.0 ) < 1E-6 ); #if defined(__GLIBCXX__) - BOOST_REQUIRE(Aarr[0][0] == std::complex(4.0, 5.0) ); + BOOST_TEST(Aarr[0][0] == std::complex(4.0, 5.0) ); #elif defined(_LIBCPP_VERSION) - BOOST_TEST(Aarr[0][0].real() == 8.0 ); - BOOST_TEST(Aarr[0][0].imag() == 9.0 ); + BOOST_TEST( std::abs( Aarr[0][0].real() - 8.0 ) < 1E-6 ); + BOOST_TEST( std::abs( Aarr[0][0].imag() - 9.0 ) < 1E-6 ); #endif } else { - BOOST_TEST( buffer[0] == 0.0 ); - BOOST_TEST( buffer[1] == 0.0 ); + BOOST_TEST( std::abs( buffer[0] - 0.0 ) < 1E-6 ); + BOOST_TEST( std::abs( buffer[1] - 0.0 ) < 1E-6); - BOOST_REQUIRE(Aarr[0][0] == 0.0); + BOOST_TEST( std::abs( Aarr[0][0] - 0.0 ) < 1E-6); } } #endif +return boost::report_errors();} + diff --git a/external_codes/boost_multi/multi/test/flatted.cpp b/external_codes/boost_multi/multi/test/flatted.cpp index 9438a3c50d..f357aa2c87 100644 --- a/external_codes/boost_multi/multi/test/flatted.cpp +++ b/external_codes/boost_multi/multi/test/flatted.cpp @@ -1,66 +1,60 @@ -// Copyright 2018-2023 Alfredo A. Correa +// Copyright 2018-2024 Alfredo A. Correa // Copyright 2024 Matt Borland // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt #include -// Suppress warnings from boost.test -#if defined(__clang__) -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wold-style-cast" -# pragma clang diagnostic ignored "-Wundef" -# pragma clang diagnostic ignored "-Wconversion" -# pragma clang diagnostic ignored "-Wsign-conversion" -# pragma clang diagnostic ignored "-Wfloat-equal" -#elif defined(__GNUC__) -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wold-style-cast" -# pragma GCC diagnostic ignored "-Wundef" -# pragma GCC diagnostic ignored "-Wconversion" -# pragma GCC diagnostic ignored "-Wsign-conversion" -# pragma GCC diagnostic ignored "-Wfloat-equal" -#endif +namespace multi = boost::multi; -#ifndef BOOST_TEST_MODULE -# define BOOST_TEST_MAIN -#endif +#include +#define BOOST_AUTO_TEST_CASE(CasenamE) -#include +auto main() -> int { // NOLINT(readability-function-cognitive-complexity,bugprone-exception-escape) +BOOST_AUTO_TEST_CASE(array_flatted_2d) { + multi::array arr = { + {0, 1, 2}, + {3, 4, 5}, + }; -namespace multi = boost::multi; + BOOST_TEST( arr.flatted()[1] == 1 ); + BOOST_TEST( arr.flatted()[4] == 4 ); + + arr.flatted()[4] = 44; +} BOOST_AUTO_TEST_CASE(array_flatted_3d) { - multi::array arr({13, 4, 5}); + multi::array arr({ 13, 4, 5 }); - BOOST_REQUIRE( arr.size() == 13 ); - // BOOST_REQUIRE( arr.rotated().is_flattable() ); + BOOST_TEST( arr.size() == 13 ); + // BOOST_TEST( arr.rotated().is_flattable() ); { auto&& arrRFU = arr.rotated().flatted().unrotated(); // TODO(correaa) remove flatted? - BOOST_REQUIRE( &arrRFU[11][7] == &arr[11][1][2] ); + BOOST_TEST( &arrRFU[11][7] == &arr[11][1][2] ); } { auto&& arrRFU = (arr.rotated()).flatted().unrotated(); - BOOST_REQUIRE( &arrRFU[11][7] == &arr[11][7/5][7%5] ); + BOOST_TEST( &arrRFU[11][7] == &arr[11][7/5][7%5] ); } } BOOST_AUTO_TEST_CASE(array_flatted_3d_bis) { - multi::array const arr({13, 4, 5}); - BOOST_REQUIRE( arr.size() == 13 ); - // BOOST_REQUIRE( arr.is_flattable() ); - BOOST_REQUIRE( arr.flatted().size() == 52 ); + multi::array const arr({ 13, 4, 5 }); + BOOST_TEST( arr.size() == 13 ); + // BOOST_TEST( arr.is_flattable() ); + BOOST_TEST( arr.flatted().size() == 52 ); } BOOST_AUTO_TEST_CASE(empty_array_3D_flatted) { multi::array const arr; - // BOOST_REQUIRE( arr.is_flattable() ); - BOOST_REQUIRE( arr.flatted().size() == 0 ); + // BOOST_TEST( arr.is_flattable() ); + BOOST_TEST( arr.flatted().size() == 0 ); } BOOST_AUTO_TEST_CASE(empty_array_2D_flatted) { multi::array const arr; - // BOOST_REQUIRE( arr.is_flattable() ); - BOOST_REQUIRE( arr.flatted().size() == 0 ); + // BOOST_TEST( arr.is_flattable() ); + BOOST_TEST( arr.flatted().size() == 0 ); } +return boost::report_errors();} diff --git a/external_codes/boost_multi/multi/test/index_range.cpp b/external_codes/boost_multi/multi/test/index_range.cpp index 2ff1d6f7de..6d84f2d1e2 100644 --- a/external_codes/boost_multi/multi/test/index_range.cpp +++ b/external_codes/boost_multi/multi/test/index_range.cpp @@ -5,117 +5,55 @@ #include -#include // for accumulate - -// Suppress warnings from boost -#if defined(__clang__) -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wold-style-cast" -# pragma clang diagnostic ignored "-Wundef" -# pragma clang diagnostic ignored "-Wconversion" -# pragma clang diagnostic ignored "-Wsign-conversion" -# pragma clang diagnostic ignored "-Wfloat-equal" -#elif defined(__GNUC__) -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wold-style-cast" -# pragma GCC diagnostic ignored "-Wundef" -# pragma GCC diagnostic ignored "-Wconversion" -# pragma GCC diagnostic ignored "-Wsign-conversion" -# pragma GCC diagnostic ignored "-Wfloat-equal" -#elif defined(_MSC_VER) -# pragma warning(push) -# pragma warning(disable : 4244) -#endif - -#ifndef BOOST_TEST_MODULE -# define BOOST_TEST_MAIN -#endif - -#include - -#include +#include // for equal +#include // for accumulate +#include // for vector namespace multi = boost::multi; -BOOST_AUTO_TEST_CASE(multi_range) { -#if defined(__cpp_deduction_guides) && __cpp_deduction_guides && ! defined(__NVCC__) - BOOST_REQUIRE(( multi::range{5, 5}.empty() )); -#else - BOOST_REQUIRE(( multi::range{5, 5}.empty() )); -#endif - { - auto drng = multi::range{5, 10}; - std::vector vec(drng.begin(), drng.end()); // testing std::vector NOLINT(fuchsia-default-arguments-calls) - BOOST_REQUIRE( vec[1] == 6 ); - } - { - auto drng = multi::range{5, 10}; - - auto fun = [](auto idx) { return idx + 1; }; - - std::vector vec( // testing std::vector NOLINT(fuchsia-default-arguments-calls) - boost::make_transform_iterator(drng.begin(), fun), - boost::make_transform_iterator(drng.end(), fun) - ); - BOOST_REQUIRE( vec[1] == 7 ); - } -} - -BOOST_AUTO_TEST_CASE(crazy_range) { - // auto trng = multi::range( - // multi::detail::tuple{5, 3}, - // multi::detail::tuple{5, 9}, - // [](auto t , int d) {return std::get<1>(t) + d;} - // [](auto t1, auto t2) {return std::get<1>(t1) - std::get<1>(t2);} - // ); - - // BOOST_REQUIRE( trng[0] == (std::tuple{5, 3}) ); - // BOOST_REQUIRE( trng[1] == (std::tuple{5, 4}) ); - - // BOOST_REQUIRE( *trng.begin() == (std::tuple{5, 3}) ); - // BOOST_REQUIRE( *(trng.begin() + 1) == (std::tuple{5, 4}) ); -} +#include +#define BOOST_AUTO_TEST_CASE(CasenamE) /**/ +auto main() -> int { // NOLINT(readability-function-cognitive-complexity,bugprone-exception-escape) BOOST_AUTO_TEST_CASE(multi_range_in_constexpr) { - // BOOST_REQUIRE( multi::extension_t{5} == 5 ); - BOOST_REQUIRE(( multi::extension_t{5, 12}.contains(10) )); + BOOST_TEST(( multi::extension_t{5, 12}.contains(10) )); - multi::range const irng{5, 12}; + multi::range const irng{ 5, 12 }; - BOOST_REQUIRE( irng.contains(6) ); - BOOST_REQUIRE( ! irng.contains(12) ); + BOOST_TEST( irng.contains(6) ); + BOOST_TEST( !irng.contains(12) ); - BOOST_REQUIRE( * irng.begin() == 5 ); - BOOST_REQUIRE( *(irng.begin() + 1) == 6 ); + BOOST_TEST( * irng.begin() == 5 ); + BOOST_TEST( *(irng.begin() + 1) == 6 ); - BOOST_REQUIRE( irng.first() == 5 ); - BOOST_REQUIRE( irng.last() == 12 ); + BOOST_TEST( irng.first() == 5 ); + BOOST_TEST( irng.last() == 12 ); - BOOST_REQUIRE( irng.front() == 5 ); - BOOST_REQUIRE( irng.back () == 11 ); + BOOST_TEST( irng.front() == 5 ); + BOOST_TEST( irng.back () == 11 ); - std::vector vec = {5, 6, 7, 8, 9, 10, 11}; // testing std::vector of multi:array NOLINT(fuchsia-default-arguments-calls) + std::vector vec = { 5, 6, 7, 8, 9, 10, 11 }; // testing std::vector of multi:array NOLINT(fuchsia-default-arguments-calls) - BOOST_REQUIRE(std::equal(irng.begin(), irng.end(), vec.begin(), vec.end())); // testing std::vector of multi:array NOLINT(fuchsia-default-arguments-calls) + BOOST_TEST(std::equal(irng.begin(), irng.end(), vec.begin(), vec.end())); // testing std::vector of multi:array NOLINT(fuchsia-default-arguments-calls) auto sum = std::accumulate(irng.begin(), irng.end(), 0); - BOOST_REQUIRE( sum == 5 + 6 + 7 + 8 + 9 + 10 + 11 ); + BOOST_TEST( sum == 5 + 6 + 7 + 8 + 9 + 10 + 11 ); } BOOST_AUTO_TEST_CASE(multi_range2) { multi::index_extension const iex(10); - BOOST_REQUIRE( *begin(iex) == 0 ); - BOOST_REQUIRE( size(iex) == 10 ); - BOOST_REQUIRE( iex[0] == 0 ); - BOOST_REQUIRE( iex[1] == 1 ); - BOOST_REQUIRE( iex[9] == 9 ); + BOOST_TEST( *begin(iex) == 0 ); + BOOST_TEST( size(iex) == 10 ); + BOOST_TEST( iex[0] == 0 ); + BOOST_TEST( iex[1] == 1 ); + BOOST_TEST( iex[9] == 9 ); auto const xbeg = begin(iex); - BOOST_REQUIRE( xbeg[0] == iex[0] ); - BOOST_REQUIRE( xbeg[1] == iex[1] ); + BOOST_TEST( xbeg[0] == iex[0] ); + BOOST_TEST( xbeg[1] == iex[1] ); - BOOST_REQUIRE( std::accumulate( begin(iex), end(iex), static_cast(0U)) == 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 ); + BOOST_TEST( std::accumulate( begin(iex), end(iex), static_cast(0U)) == 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 ); { multi::iextensions<3> const ies({ @@ -124,23 +62,26 @@ BOOST_AUTO_TEST_CASE(multi_range2) { {0, 5}, }); - auto const ies0 = std::get<0>(ies); - auto const ies1 = std::get<1>(ies); - auto const ies2 = std::get<2>(ies); + using std::get; - BOOST_REQUIRE( ies0.size() == 3 ); - BOOST_REQUIRE( ies1.size() == 4 ); - BOOST_REQUIRE( ies2.size() == 5 ); + auto const ies0 = get<0>(ies); + auto const ies1 = get<1>(ies); + auto const ies2 = get<2>(ies); - BOOST_REQUIRE( std::get<0>(ies).size() == 3 ); - BOOST_REQUIRE( std::get<1>(ies).size() == 4 ); - BOOST_REQUIRE( std::get<2>(ies).size() == 5 ); + BOOST_TEST( ies0.size() == 3 ); + BOOST_TEST( ies1.size() == 4 ); + BOOST_TEST( ies2.size() == 5 ); - #ifndef _MSC_VER // doesn't work in MSVC 14.3 in c++17 mode - auto [eyes, jays, kays] = ies; - BOOST_REQUIRE( eyes.size() == 3 ); - BOOST_REQUIRE( jays.size() == 4 ); - BOOST_REQUIRE( kays.size() == 5 ); - #endif + BOOST_TEST( get<0>(ies).size() == 3 ); + BOOST_TEST( get<1>(ies).size() == 4 ); + BOOST_TEST( get<2>(ies).size() == 5 ); + +#ifndef _MSC_VER // doesn't work in MSVC 14.3 in c++17 mode + auto const [eyes, jays, kays] = ies; + BOOST_TEST( eyes.size() == 3 ); + BOOST_TEST( jays.size() == 4 ); + BOOST_TEST( kays.size() == 5 ); +#endif } } +return boost::report_errors();} diff --git a/external_codes/boost_multi/multi/test/initializer_list.cpp b/external_codes/boost_multi/multi/test/initializer_list.cpp index 75026c93a7..38713156cc 100644 --- a/external_codes/boost_multi/multi/test/initializer_list.cpp +++ b/external_codes/boost_multi/multi/test/initializer_list.cpp @@ -1,234 +1,243 @@ -// Copyright 2019-2023 Alfredo A. Correa +// Copyright 2019-2024 Alfredo A. Correa // Copyright 2024 Matt Borland // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt -#include - -#include -#include - -// Suppress warnings from boost.test -#if defined(__clang__) -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wold-style-cast" -#pragma clang diagnostic ignored "-Wundef" -#pragma clang diagnostic ignored "-Wconversion" -#pragma clang diagnostic ignored "-Wsign-conversion" -#pragma clang diagnostic ignored "-Wfloat-equal" -#elif defined(__GNUC__) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wold-style-cast" -#pragma GCC diagnostic ignored "-Wundef" -#pragma GCC diagnostic ignored "-Wconversion" -#pragma GCC diagnostic ignored "-Wsign-conversion" -#pragma GCC diagnostic ignored "-Wfloat-equal" -#endif - -#ifndef BOOST_TEST_MODULE -#define BOOST_TEST_MAIN -#endif +#include // for array, static_array, num_elements -#include +// IWYU pragma: no_include // for copy // bug in iwyu 14.0.6? with GNU stdlib +#include // for array +#include // for operator*, operator+, complex +#include // for initializer_list, begin, end +#include // for size, begin, end +#include // for basic_string, allocator, char_tr... +#include // for is_same_v +#include // for vector namespace multi = boost::multi; -BOOST_AUTO_TEST_CASE(multi_tests_initializer_list_1d) { - { - std::vector const vec = {1.0, 2.0, 3.0}; // NOLINT(fuchsia-default-arguments-calls) - BOOST_REQUIRE( vec[1] == 2. ); - } - { - multi::static_array arr = {12, 34, 56}; - BOOST_REQUIRE( size(arr) == 3 ); - BOOST_REQUIRE( arr[2] == 56 ); - } - { - multi::static_array const arr = {12, 34, 56}; - BOOST_REQUIRE( size(arr) == 3 ); - BOOST_REQUIRE( arr[2] == 56 ); - } - { - auto const il = {1.2, 3.4, 5.6}; - - multi::static_array const arr(il); - BOOST_REQUIRE( size(arr) == 3 ); - BOOST_REQUIRE( arr[2] == il.begin()[2] ); // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic) - } - { - auto const il = {1.2, 3.4, 5.6}; - - multi::static_array const arr(begin(il), end(il)); - BOOST_REQUIRE( size(arr) == 3 ); - BOOST_REQUIRE( arr[2] == il.begin()[2] ); // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic) - } - { - multi::static_array const arr = {12, 34, 56}; - BOOST_TEST_REQUIRE( size(arr) == 3 ); - BOOST_TEST_REQUIRE( arr[2] == 56 ); - BOOST_TEST_REQUIRE(( arr == multi::static_array{12, 34, 56} )); - BOOST_TEST_REQUIRE(( arr == decltype(arr){12, 34, 56} )); - } - { - auto const values = {12, 34, 56}; - - multi::array const arr(values.begin(), values.end()); - BOOST_TEST_REQUIRE( size(arr) == 3 ); - BOOST_TEST_REQUIRE( arr[2] == 56 ); - } - { - multi::array const arr = {12, 34, 56}; - - BOOST_TEST_REQUIRE( size(arr) == 3 ); - BOOST_TEST_REQUIRE( arr[2] == 56 ); - - BOOST_TEST_REQUIRE(( arr == multi::array{12, 34, 56} )); - BOOST_TEST_REQUIRE(( arr == decltype(arr){12, 34, 56} )); - BOOST_TEST_REQUIRE(( arr == decltype(arr)::decay_type({12, 34, 56}) )); - } - { - std::array const stdarr = { - {11, 22, 33}, - }; - using multi::num_elements; - BOOST_TEST_REQUIRE( num_elements(stdarr) == 3 ); - - using std::begin; - using std::end; - multi::static_array const arr(begin(stdarr), end(stdarr)); - BOOST_TEST_REQUIRE( size(arr) == 3 ); - } -} - -BOOST_AUTO_TEST_CASE(multi_tests_initializer_list_1d_ctad) { +#include +#define BOOST_AUTO_TEST_CASE(CasenamE) /**/ + +auto main() -> int { // NOLINT(readability-function-cognitive-complexity,bugprone-exception-escape) + BOOST_AUTO_TEST_CASE(multi_tests_initializer_list_1d) { + { + std::vector const vec = {10, 20, 30}; // NOLINT(fuchsia-default-arguments-calls) + BOOST_TEST( vec[1] == 20 ); + } + { + multi::static_array arr = {12, 34, 56}; + BOOST_TEST( size(arr) == 3 ); + BOOST_TEST( arr[2] == 56 ); + } + { + multi::static_array const arr = {12, 34, 56}; + BOOST_TEST( size(arr) == 3 ); + BOOST_TEST( arr[2] == 56 ); + } + { + auto const il = {12, 34, 56}; + + multi::static_array const arr(il); + BOOST_TEST( size(arr) == 3 ); + BOOST_TEST( arr[2] == 56 ); // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic) + } + { + auto const il = {12, 34, 56}; + + multi::static_array const arr(begin(il), end(il)); + BOOST_TEST( size(arr) == 3 ); + BOOST_TEST( arr[2] == 56 ); // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic) + } + { + multi::static_array const arr = {12, 34, 56}; + BOOST_TEST( size(arr) == 3 ); + BOOST_TEST( arr[2] == 56 ); + BOOST_TEST(( arr == multi::static_array{12, 34, 56} )); + BOOST_TEST(( arr == decltype(arr){12, 34, 56} )); + } + { + auto const values = {12, 34, 56}; + + multi::array const arr(values.begin(), values.end()); + BOOST_TEST( size(arr) == 3 ); + BOOST_TEST( arr[2] == 56 ); + } + { + multi::array const arr = {12, 34, 56}; + + BOOST_TEST( size(arr) == 3 ); + BOOST_TEST( arr[2] == 56 ); + + BOOST_TEST(( arr == multi::array{12, 34, 56} )); + BOOST_TEST(( arr == decltype(arr){12, 34, 56} )); + BOOST_TEST(( arr == decltype(arr)::decay_type({12, 34, 56}) )); + } + { + std::array const stdarr = { + {11, 22, 33}, + }; + using multi::num_elements; + BOOST_TEST( num_elements(stdarr) == 3 ); + + using std::begin; + using std::end; + multi::static_array const arr(begin(stdarr), end(stdarr)); + BOOST_TEST( size(arr) == 3 ); + } + } + + BOOST_AUTO_TEST_CASE(multi_tests_initializer_list_1d_ctad) { #if defined(__cpp_deduction_guides) && !defined(__NVCC__) -#if !defined(__circle_build__) || (__circle_build__ > 200 ) // crashes circle 187-200 in docker - { - multi::static_array const arr = {12, 34, 56}; - BOOST_TEST_REQUIRE( size(arr) == 3 ); - BOOST_TEST_REQUIRE( arr[2] == 56 ); - BOOST_TEST_REQUIRE(( arr == multi::static_array{12, 34, 56} )); - } + // #if __cplusplus >= 202002L + // static constexpr auto f = [] + // { + // multi::array arr(3); + // arr[0] = 12; arr[1] = 34; arr[2] = 56; // TODO(correaa) getting "assignment to object outside its lifetime is not allowed in a constant expression" + // return (arr.size() == 3); + // }(); + // static_assert(f); + // #endif + + { + multi::static_array const arr = {12, 34, 56}; + BOOST_TEST( size(arr) == 3 ); + BOOST_TEST( arr[2] == 56 ); + BOOST_TEST(( arr == multi::static_array{12, 34, 56} )); + } + { + multi::array arr(std::initializer_list{12, 34, 56}); + BOOST_TEST( size(arr) == 3 ); + BOOST_TEST( arr[2] == 56 ); + BOOST_TEST(( arr == multi::array(std::initializer_list{12, 34, 56}) )); + } + { + multi::array arr({12, 34, 56}); + BOOST_TEST( size(arr) == 3 ); + BOOST_TEST( arr[2] == 56 ); + BOOST_TEST(( arr == multi::array({12, 34, 56}) )); + } + #if !defined(__GNUC__) || (__GNUC__ < 14) // workaround bug in gcc 14.2 + { + multi::array arr({12, 34, 56}); + BOOST_TEST( size(arr) == 3 ); + BOOST_TEST( arr[2] == 56 ); + BOOST_TEST(( arr == multi::array({12, 34, 56}) )); + } + #endif #endif - { - multi::array arr({12, 34, 56}); - BOOST_TEST_REQUIRE( size(arr) == 3 ); - BOOST_TEST_REQUIRE( arr[2] == 56 ); - BOOST_TEST_REQUIRE(( arr == multi::array({12, 34, 56}) )); } -#endif -} -BOOST_AUTO_TEST_CASE(multi_tests_initializer_list_array) { + BOOST_AUTO_TEST_CASE(multi_tests_initializer_list_array) { #if defined(__INTEL_COMPILER) || (defined(__clang__) && (__clang_major__ >= 10)) // doesn't work on gcc - { -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wc99-designator" - // double const a[] = { [8] = 8.0, 9.0, 10.0 }; - std::array const stdarr = { - {[8] = 8.0, 9.0, 10.0}, - }; -#pragma GCC diagnostic pop - multi::array arr = stdarr; - BOOST_REQUIRE( arr.size() == 11 ); - BOOST_REQUIRE( arr[9] == 9.0 ); - } + { + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wc99-designator" + // double const a[] = { [8] = 8.0, 9.0, 10.0 }; + std::array const stdarr = { + {[8] = 8.0, 9.0, 10.0}, + }; + #pragma GCC diagnostic pop + multi::array arr = stdarr; + BOOST_TEST( arr.size() == 11 ); + BOOST_TEST( arr[9] == 9.0 ); + } #endif -} - -BOOST_AUTO_TEST_CASE(multi_initialize_from_carray_1d) { - { - multi::static_array const arr = {11, 22, 33}; - BOOST_REQUIRE( size(arr) == 3 ); - BOOST_REQUIRE( arr[1] == 22 ); } - { -#if defined(__cpp_deduction_guides) && ! defined(__NVCC__) + + BOOST_AUTO_TEST_CASE(multi_initialize_from_carray_1d) { + { + multi::static_array const arr = {11, 22, 33}; + BOOST_TEST( size(arr) == 3 ); + BOOST_TEST( arr[1] == 22 ); + } + { +#if defined(__cpp_deduction_guides) && !defined(__NVCC__) // multi::array arr = {{1.1, 2.2, 3.3}}; // static_assert( decltype(arr)::dimensionality == 1 , "!"); -// BOOST_REQUIRE( size(arr)==3 && arr[1] == 2.2 ); +// BOOST_TEST( size(arr)==3 && arr[1] == 2.2 ); #endif - } - { - std::array stdarr = { - {1.1, 2.2, 3.3} - }; - multi::array const arr(begin(stdarr), end(stdarr)); - BOOST_REQUIRE(( arr == decltype(arr){1.1, 2.2, 3.3} )); - } -} - -BOOST_AUTO_TEST_CASE(multi_tests_initializer_list_2d) { - { - multi::static_array const arr = { - { 1.2, 2.4, 3.6, 8.9}, - {11.2, 34.4, 5.6, 1.1}, - {15.2, 32.4, 5.6, 3.4}, - }; - BOOST_REQUIRE( size(arr) == 3 ); - BOOST_REQUIRE( size(arr[0]) == 4 ); - BOOST_REQUIRE(( arr == decltype(arr){ + } + { + std::array stdarr = { + {1.1, 2.2, 3.3} + }; + multi::array const arr(begin(stdarr), end(stdarr)); + BOOST_TEST(( arr == decltype(arr){1.1, 2.2, 3.3} )); + } + } + + BOOST_AUTO_TEST_CASE(multi_tests_initializer_list_2d) { + { + multi::static_array const arr = { + { 1.2, 2.4, 3.6, 8.9}, + {11.2, 34.4, 5.6, 1.1}, + {15.2, 32.4, 5.6, 3.4}, + }; + BOOST_TEST( size(arr) == 3 ); + BOOST_TEST( size(arr[0]) == 4 ); + BOOST_TEST(( arr == decltype(arr){ { 1.2, 2.4, 3.6, 8.9}, {11.2, 34.4, 5.6, 1.1}, {15.2, 32.4, 5.6, 3.4}, })); - } - { - multi::array const arr = { - { 12, 24, 36}, - {112, 344, 56}, - {152, 324, 56}, - }; - BOOST_TEST( size(arr) == 3 ); - BOOST_TEST( size(arr[0]) == 3 ); - BOOST_TEST( arr[1][1] == 344 ); - } - { - multi::array arr = { - { 12, 24, 36}, - {112, 344, 56}, - {152, 324, 56}, - }; - - BOOST_TEST( size(arr) == 3 ); - BOOST_TEST( size(arr) == 3 ); - BOOST_TEST( size(arr[0]) == 3 ); - BOOST_TEST( arr[1][1] == 344 ); - - arr = { - {100, 10, 20}, - {100, 110, 120}, - {200, 210, 220}, - }; - BOOST_TEST( arr[1][2] == 120 ); - } - { - multi::array vec; - vec = {40, 55}; - BOOST_TEST( size(vec) == 2 ); - BOOST_TEST( vec[1] == 55 ); - } - { - std::array, 3> const nested = { - {{{12, 24}}, {{112, 344}}, {{152, 324}}} - }; - - using std::begin; - using std::end; - - multi::static_array arr(begin(nested), end(nested)); - - BOOST_TEST( size(arr) == 3 ); - BOOST_TEST( size(arr[0]) == 2 ); - BOOST_TEST( arr[1][0] == 112 ); - } - { - std::array, 3> const nested = { - {{{12, 24}}, {{112, 344}}, {{152, 324}}} - }; - multi::static_array const arr(std::begin(nested), std::end(nested)); - - BOOST_TEST(( + } + { + multi::array const arr = { + { 12, 24, 36}, + {112, 344, 56}, + {152, 324, 56}, + }; + BOOST_TEST( size(arr) == 3 ); + BOOST_TEST( size(arr[0]) == 3 ); + BOOST_TEST( arr[1][1] == 344 ); + } + { + multi::array arr = { + { 12, 24, 36}, + {112, 344, 56}, + {152, 324, 56}, + }; + + BOOST_TEST( size(arr) == 3 ); + BOOST_TEST( size(arr) == 3 ); + BOOST_TEST( size(arr[0]) == 3 ); + BOOST_TEST( arr[1][1] == 344 ); + + arr = { + {100, 10, 20}, + {100, 110, 120}, + {200, 210, 220}, + }; + BOOST_TEST( arr[1][2] == 120 ); + } + { + multi::array vec; + vec = {40, 55}; + BOOST_TEST( size(vec) == 2 ); + BOOST_TEST( vec[1] == 55 ); + } + { + std::array, 3> const nested = { + {{{12, 24}}, {{112, 344}}, {{152, 324}}} + }; + + using std::begin; + using std::end; + + multi::static_array arr(begin(nested), end(nested)); + + BOOST_TEST( size(arr) == 3 ); + BOOST_TEST( size(arr[0]) == 2 ); + BOOST_TEST( arr[1][0] == 112 ); + } + { + std::array, 3> const nested = { + {{{12, 24}}, {{112, 344}}, {{152, 324}}} + }; + multi::static_array const arr(std::begin(nested), std::end(nested)); + + BOOST_TEST(( arr == multi::array {{ {{ 12, 24}}, {{112, 344}}, @@ -236,174 +245,206 @@ BOOST_AUTO_TEST_CASE(multi_tests_initializer_list_2d) { }} )); - BOOST_TEST(!( arr != multi::array{ + BOOST_TEST(!( arr != multi::array{ { 12, 24}, {112, 344}, {152, 324}, } )); - BOOST_TEST(( + BOOST_TEST(( arr == decltype(arr){ { 12, 24}, {112, 344}, {152, 324}, } )); - } - { - std::array, 3> nested = { - {{{10, 20}}, - {{20, 40}}, - {{30, 60}}}, + } + { + std::array, 3> const nested = { + { + {{10, 20}}, + {{20, 40}}, + {{30, 60}}, + } + }; + multi::array arr(begin(nested), end(nested)); + BOOST_TEST( num_elements(arr) == 6 ); + BOOST_TEST( arr[2][1] == 60 ); + } + { + using complex = std::complex; + + complex const I{0.0, 1.0}; // NOLINT(readability-identifier-length) imaginary unit + + multi::array arr = { + {2.0 + 1.0 * I, 1.0 + 3.0 * I, 1.0 + 7.0 * I}, + {3.0 + 4.0 * I, 4.0 + 2.0 * I, 0.0 + 0.0 * I}, + }; + BOOST_TEST( arr[1][1] == 4.0 + 2.0*I ); + } + } + + BOOST_AUTO_TEST_CASE(multi_tests_static_array_initializer_list) { + multi::static_array, 2> SA = { + {{1.0, 0.0}, {2.0, 0.0}}, + {{3.0, 0.0}, {4.0, 0.0}}, }; - multi::array arr(begin(nested), end(nested)); - BOOST_TEST( num_elements(arr) == 6 ); - BOOST_TEST( arr[2][1] == 60 ); + BOOST_TEST( SA[1][1] == 4.0 ); } - { - using complex = std::complex; - - complex const I{0.0, 1.0}; // NOLINT(readability-identifier-length) imaginary unit - multi::array arr = { - {2.0 + 1.0 * I, 1.0 + 3.0 * I, 1.0 + 7.0 * I}, - {3.0 + 4.0 * I, 4.0 + 2.0 * I, 0.0 + 0.0 * I}, + BOOST_AUTO_TEST_CASE(multi_tests_initializer_list_3d) { + multi::array const arr = { + { {12, 100}, {24, 10}}, + { {112, 30}, {344, 40}}, + {{152, 990}, {324, 20}}, }; - BOOST_REQUIRE( arr[1][1] == 4.0 + 2.0*I ); + BOOST_TEST( arr[1][1][0] == 344 ); + BOOST_TEST( arr[1][1][1] == 40 ); } -} -BOOST_AUTO_TEST_CASE(multi_tests_static_array_initializer_list) { - multi::static_array, 2> SA = { - {{1.0, 0.0}, {2.0, 0.0}}, - {{3.0, 0.0}, {4.0, 0.0}}, - }; - BOOST_REQUIRE( SA[1][1] == 4.0 ); -} + BOOST_AUTO_TEST_CASE(multi_tests_initializer_list_3d_string) { + { + using std::string; -BOOST_AUTO_TEST_CASE(multi_tests_initializer_list_3d) { - multi::array const arr = { - { {12, 100}, {24, 10}}, - { {112, 30}, {344, 40}}, - {{152, 990}, {324, 20}}, - }; - BOOST_REQUIRE( arr[1][1][0] == 344 ); - BOOST_REQUIRE( arr[1][1][1] == 40 ); -} + // NOLINTBEGIN(fuchsia-default-arguments-calls) + multi::array B3 = { + {{"000", "001", "002"}, {"010", "011", "012"}}, + {{"100", "101", "102"}, {"110", "111", "112"}}, + }; + // NOLINTEND(fuchsia-default-arguments-calls) -BOOST_AUTO_TEST_CASE(multi_tests_initializer_list_3d_string) { - { - using std::string; + BOOST_TEST( num_elements(B3) == 12 ); + BOOST_TEST( B3[1][0][1] == "101" ); + } + } - // NOLINTBEGIN(fuchsia-default-arguments-calls) - multi::array B3 = { - {{"000", "001", "002"}, {"010", "011", "012"}}, - {{"100", "101", "102"}, {"110", "111", "112"}}, - }; - // NOLINTEND(fuchsia-default-arguments-calls) +#if defined(__cpp_deduction_guides) && !defined(__NVCC__) + BOOST_AUTO_TEST_CASE(initializer_list_1d_static) { + multi::static_array arr({10, 20, 30}); - BOOST_REQUIRE( num_elements(B3)==12 && B3[1][0][1] == "101" ); - } -} + static_assert(std::is_same_v); + + BOOST_TEST( size(arr) == 3 && num_elements(arr) == 3 ); + BOOST_TEST( multi::rank::value == 1); + BOOST_TEST( num_elements(arr) == 3 ); + BOOST_TEST( arr[1] == 20 ); -#if defined(__cpp_deduction_guides) && ! defined(__NVCC__) -BOOST_AUTO_TEST_CASE(initializer_list_1d_static) { -#if !defined(__circle_build__) || (__circle_build__ > 200 ) // crashes circle 187-200 in docker - { - multi::static_array arr({1.0, 2.0, 3.0}); - static_assert(std::is_same_v); - BOOST_REQUIRE( size(arr) == 3 && num_elements(arr) == 3 ); - BOOST_REQUIRE( multi::rank{}==1 && num_elements(arr)==3 && arr[1] == 2.0 ); static_assert(typename decltype(arr)::rank{} == 1); } -#endif -} -BOOST_AUTO_TEST_CASE(initializer_list_1d) { - { - multi::array arr({1.0, 2.0, 3.0}); - static_assert(std::is_same_v); - BOOST_REQUIRE( size(arr) == 3 && num_elements(arr) == 3 ); - BOOST_REQUIRE( multi::rank{}==1 && num_elements(arr)==3 && arr[1] == 2.0 ); + #if !defined(__GNUC__) || (__GNUC__ < 14) // workaround bug in gcc 14.2 + BOOST_AUTO_TEST_CASE(initializer_list_1d_a) { + multi::array arr({10, 20, 30}); + + static_assert(std::is_same_v); + + BOOST_TEST( size(arr) == 3 ); + BOOST_TEST( num_elements(arr) == 3 ); + BOOST_TEST( multi::rank::value == 1 ); + BOOST_TEST( num_elements(arr) == 3 ); + BOOST_TEST( arr[1] == 20 ); + static_assert(typename decltype(arr)::rank{} == 1); } - { - multi::array arr({1.0, 2.0}); - static_assert(std::is_same_v); - BOOST_REQUIRE( size(arr) == 2 && num_elements(arr) == 2 ); - BOOST_REQUIRE( multi::rank{}==1 && num_elements(arr) == 2 && arr[1] == 2.0 ); - BOOST_REQUIRE( multi::rank{} == 1 ); + + BOOST_AUTO_TEST_CASE(initializer_list_1d_b) { + multi::array arr({10, 20}); + static_assert(std::is_same_v); + + BOOST_TEST( size(arr) == 2 ); + BOOST_TEST( num_elements(arr) == 2 ); + BOOST_TEST( multi::rank::value == 1 ); + BOOST_TEST( num_elements(arr) == 2 ); + BOOST_TEST( arr[1] == 20 ); + BOOST_TEST( multi::rank::value == 1 ); } - { + + BOOST_AUTO_TEST_CASE(initializer_list_1d_c) { multi::array arr({0, 2}); // multi::array arr = {0, 2}; not working with CTAD + static_assert(std::is_same_v); - BOOST_REQUIRE( size(arr) == 2 && num_elements(arr) == 2 ); - BOOST_REQUIRE( multi::rank{} == 1 && num_elements(arr) == 2 && arr[1] == 2.0 ); - BOOST_REQUIRE( multi::rank{} == 1 ); - } - { - multi::array arr({9.0}); // multi::array arr = {9.0}; not working with CTAD - static_assert(std::is_same_v); - BOOST_REQUIRE( multi::rank{}==1 && num_elements(arr)==1 && arr[0]==9.0 ); - BOOST_REQUIRE( multi::rank{}==1 ); + + BOOST_TEST( size(arr) == 2 ); + BOOST_TEST( num_elements(arr) == 2 ); + BOOST_TEST( multi::rank{} == 1 ); + BOOST_TEST( num_elements(arr) == 2 ); + BOOST_TEST( arr[1] == 2 ); + BOOST_TEST( multi::rank{} == 1 ); } - { - multi::array arr({9}); // multi::array arr = {9}; not working with CTAD + + BOOST_AUTO_TEST_CASE(initializer_list_1d_d) { + multi::array arr({90}); // multi::array arr = {90}; not working with CTAD + static_assert(std::is_same_v); - BOOST_REQUIRE( size(arr) == 1 && num_elements(arr) == 1 ); - BOOST_REQUIRE( multi::rank{} == 1 ); - BOOST_REQUIRE( num_elements(arr) == 1 && arr[0] == 9.0 ); - } -} -BOOST_AUTO_TEST_CASE(initializer_list_2d) { -#if !defined(__circle_build__) || (__circle_build__ > 200 ) // crashes circle 187-200 in docker - { - multi::static_array const arr({ - {1.0, 2.0, 3.0}, - {4.0, 5.0, 6.0}, - }); - BOOST_TEST_REQUIRE( multi::rank{} == 2 ); - BOOST_TEST_REQUIRE( num_elements(arr) == 6 ); - } - { - multi::array const arr({ - {1.0, 2.0, 3.0}, - {4.0, 5.0, 6.0}, - }); - BOOST_TEST_REQUIRE( multi::rank{} == 2 ); - BOOST_TEST_REQUIRE( num_elements(arr) == 6 ); + BOOST_TEST( multi::rank::value == 1 ); + BOOST_TEST( num_elements(arr) == 1 ); + BOOST_TEST( arr[0] == 90 ); + BOOST_TEST( multi::rank::value == 1 ); } -#endif -} + + BOOST_AUTO_TEST_CASE(initializer_list_1d_e) { + multi::array arr({90}); // multi::array arr = {90}; not working with CTAD + + static_assert(std::is_same_v); + + BOOST_TEST( size(arr) == 1 ); + BOOST_TEST( num_elements(arr) == 1 ); + BOOST_TEST( multi::rank::value == 1 ); + BOOST_TEST( num_elements(arr) == 1 ); + BOOST_TEST( arr[0] == 90 ); + } + + BOOST_AUTO_TEST_CASE(initializer_list_2d) { + { + multi::static_array const arr({ + {1.0, 2.0, 3.0}, + {4.0, 5.0, 6.0}, + }); + BOOST_TEST( multi::rank{} == 2 ); + BOOST_TEST( num_elements(arr) == 6 ); + } + { + multi::array const arr({ + {1.0, 2.0, 3.0}, + {4.0, 5.0, 6.0}, + }); + BOOST_TEST( multi::rank::value == 2 ); + BOOST_TEST( num_elements(arr) == 6 ); + } + } + #endif #endif -BOOST_AUTO_TEST_CASE(partially_formed) { - multi::array arr1({10, 10}, double{}); - multi::array arr2({10, 10}, {}); - multi::array arr3({10, 10}, 0.0); + BOOST_AUTO_TEST_CASE(partially_formed) { + multi::array arr1({10, 10}, int{}); + multi::array arr2({10, 10}, {}); + multi::array arr3({10, 10}, 0); - BOOST_REQUIRE( arr1[0][0] == 0.0); - BOOST_REQUIRE( arr2[0][0] == 0.0); - BOOST_REQUIRE( arr3[0][0] == 0.0); -} + BOOST_TEST( arr1[0][0] == 0); + BOOST_TEST( arr2[0][0] == 0); + BOOST_TEST( arr3[0][0] == 0); + } -BOOST_AUTO_TEST_CASE(partially_formed_int_1) { - multi::array arr1({10, 10}, static_cast(1U)); - multi::array arr2({10, 10}, {1}); - multi::array arr3({10, 10}, 1); + BOOST_AUTO_TEST_CASE(partially_formed_int_1) { + multi::array arr1({10, 10}, static_cast(1U)); + multi::array arr2({10, 10}, {1}); + multi::array arr3({10, 10}, 1); - BOOST_REQUIRE( arr1[0][0] == 1); - BOOST_REQUIRE( arr2[0][0] == 1); - BOOST_REQUIRE( arr3[0][0] == 1); -} + BOOST_TEST( arr1[0][0] == 1); + BOOST_TEST( arr2[0][0] == 1); + BOOST_TEST( arr3[0][0] == 1); + } + + BOOST_AUTO_TEST_CASE(partially_formed_int_0) { + multi::array arr1({10, 10}, int{}); + multi::array arr2({10, 10}, {}); + multi::array arr3({10, 10}, 0); -BOOST_AUTO_TEST_CASE(partially_formed_int_0) { - multi::array arr1({10, 10}, int{}); - multi::array arr2({10, 10}, {}); - multi::array arr3({10, 10}, 0); + BOOST_TEST( arr1[0][0] == 0); + BOOST_TEST( arr2[0][0] == 0); + BOOST_TEST( arr3[0][0] == 0); + } - BOOST_REQUIRE( arr1[0][0] == 0); - BOOST_REQUIRE( arr2[0][0] == 0); - BOOST_REQUIRE( arr3[0][0] == 0); + return boost::report_errors(); } diff --git a/external_codes/boost_multi/multi/test/iterator.cpp b/external_codes/boost_multi/multi/test/iterator.cpp index 146617571c..c2062fcec7 100644 --- a/external_codes/boost_multi/multi/test/iterator.cpp +++ b/external_codes/boost_multi/multi/test/iterator.cpp @@ -1,282 +1,316 @@ -// Copyright 2018-2023 Alfredo A. Correa +// Copyright 2018-2024 Alfredo A. Correa // Copyright 2024 Matt Borland // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt -#include - -#include -#include - -// Suppress warnings from boost.test -#if defined(__clang__) -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wold-style-cast" -# pragma clang diagnostic ignored "-Wundef" -# pragma clang diagnostic ignored "-Wconversion" -# pragma clang diagnostic ignored "-Wsign-conversion" -# pragma clang diagnostic ignored "-Wfloat-equal" -#elif defined(__GNUC__) -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wold-style-cast" -# pragma GCC diagnostic ignored "-Wundef" -# pragma GCC diagnostic ignored "-Wconversion" -# pragma GCC diagnostic ignored "-Wsign-conversion" -# pragma GCC diagnostic ignored "-Wfloat-equal" -#elif defined(_MSC_VER) -# pragma warning(push) -# pragma warning(disable : 4244) -#endif - -#ifndef BOOST_TEST_MODULE -# define BOOST_TEST_MAIN -#endif - -#include +#include -namespace multi = boost::multi; +#include // for array, implicit_cast, explicit_cast -template auto take(Array&& array) -> auto& {return std::forward(array)[0];} +#include // for is_sorted, copy +#include // for begin, end, size, cbegin, make_r... +#include // for accumulate +#include // for basic_ostringstream, basic_ostre... +#include // for basic_string, char_traits, opera... +#include // for is_same_v, is_same +#include // for forward +#include // for allocator, vector -BOOST_AUTO_TEST_CASE(iterator_1d) { - { - multi::array arr(multi::extensions_t<1>{multi::iextension{100}}, 99.0); - BOOST_REQUIRE( size(arr) == 100 ); - BOOST_REQUIRE( begin(arr) < end(arr) ); - BOOST_REQUIRE( end(arr) - begin(arr) == size(arr) ); +namespace multi = boost::multi; - multi::array::const_iterator const cbarr = cbegin(arr); - multi::array::iterator barr = begin(arr); +template auto take(Array&& array) -> auto& { return std::forward(array)[0]; } - [[maybe_unused]] multi::array::const_iterator const cbarr3{barr}; +#define BOOST_AUTO_TEST_CASE(CasenamE) /**/ - BOOST_REQUIRE( barr == cbarr ); - BOOST_REQUIRE( cbarr == barr ); +auto main() -> int { // NOLINT(readability-function-cognitive-complexity,bugprone-exception-escape) + BOOST_AUTO_TEST_CASE(iterator_1d) { + BOOST_TEST((std::is_trivially_copy_constructible_v >)); + BOOST_TEST((std::is_trivially_copy_assignable_v >)); + BOOST_TEST((std::is_trivially_default_constructible_v>)); - barr += 1; - barr -= 1; - BOOST_REQUIRE( cbarr == barr ); + BOOST_TEST((std::is_trivially_copy_constructible_v >)); + BOOST_TEST((std::is_trivially_copy_assignable_v >)); + BOOST_TEST((std::is_trivially_default_constructible_v>)); - multi::array::const_iterator const cbarr2 = begin(arr); - BOOST_REQUIRE( cbarr2 == cbarr ); - } - { - multi::array arr(multi::extensions_t<1>{multi::iextension{100}}, 99.0); - BOOST_REQUIRE( size(arr) == 100 ); - BOOST_REQUIRE( begin(arr) < end(arr) ); - - auto arr2 = arr.begin(); - multi::array::const_iterator const cbb = arr2; - BOOST_REQUIRE( cbb == arr2 ); - BOOST_REQUIRE( arr2 == cbb ); - } - { - multi::array arr(multi::extensions_t<1>{multi::iextension{100}}, 99.0); - BOOST_REQUIRE( size(arr) == 100 ); - BOOST_REQUIRE( begin(arr) < end(arr) ); + BOOST_TEST((std::is_trivially_copy_constructible_v >)); + BOOST_TEST((std::is_trivially_copy_assignable_v >)); + BOOST_TEST((std::is_trivially_default_constructible_v>)); - auto const arrend = arr.end(); - auto const arrlast = arrend - 1; + BOOST_TEST((std::is_trivially_default_constructible_v::iterator>)); + BOOST_TEST((std::is_trivially_copy_constructible_v ::iterator>)); + BOOST_TEST((std::is_trivially_copy_assignable_v ::iterator>)); - BOOST_REQUIRE( arrlast + 1 == arrend ); - } -} + { + multi::array arr(multi::extensions_t<1>{multi::iextension{100}}, 99.0); + BOOST_TEST( arr.size() == 100 ); + BOOST_TEST( arr.begin() < arr.end() ); + BOOST_TEST( arr.end() - arr.begin() == arr.size() ); -BOOST_AUTO_TEST_CASE(iterator_2d) { - { - multi::array const arr({120, 140}, 99.0); + multi::array::const_iterator const cbarr = arr.cbegin(); + multi::array::iterator barr = arr.begin(); - BOOST_REQUIRE( arr.size() == 120 ); - BOOST_REQUIRE( size(arr) == 120 ); - BOOST_REQUIRE( arr.cbegin() < arr.cend() ); - BOOST_REQUIRE( arr.cend() - arr.cbegin() == arr.size() ); + [[maybe_unused]] multi::array::const_iterator const cbarr3{barr}; - using iter = multi::array::iterator; - static_assert( std::is_same_v< iter::element , double > ); - static_assert( std::is_same_v< iter::value_type, multi::array > ); - static_assert( std::is_same_v< iter::reference, multi::subarray> ); - static_assert( std::is_same_v< iter::element_ptr, double*> ); + BOOST_TEST( barr == cbarr ); // problem in C++20 + BOOST_TEST( cbarr == barr ); // problem in C++20 - using citer = multi::array::const_iterator; - static_assert( std::is_same_v< citer::element , double > ); - static_assert( std::is_same_v< citer::value_type, multi::array > ); - static_assert( std::is_same_v< citer::reference, multi::subarray> ); - static_assert( std::is_same_v< citer::element_ptr, double const* > ); + barr += 1; + barr -= 1; + BOOST_TEST( cbarr == barr ); - auto const arrend = arr.end(); - auto const arrlast = arrend - 1; + multi::array::const_iterator const cbarr2 = begin(arr); + BOOST_TEST( cbarr2 == cbarr ); + } + { + multi::array arr(multi::extensions_t<1>{multi::iextension{100}}, 99.0); + BOOST_TEST( arr.size() == 100 ); + BOOST_TEST( arr.begin() < arr.end() ); + + auto arr2 = arr.begin(); + multi::array::const_iterator const cbb = arr2; + BOOST_TEST( cbb == arr2 ); + // BOOST_TEST( arr2 == cbb ); // TODO(correaa) problem in C++20 + } + { + multi::array arr(multi::extensions_t<1>{multi::iextension{100}}, 99.0); + BOOST_TEST( arr.size() == 100 ); + BOOST_TEST( arr.begin() < arr.end() ); - BOOST_REQUIRE( arrlast + 1 == arrend ); - } - { - std::vector vec(10000); // std::vector NOLINT(fuchsia-default-arguments-calls) - multi::array_ref arr(vec.data(), {100, 100}); - BOOST_REQUIRE(size(arr) == 100); - begin(arr)[4][3] = 2.0; + auto const arrend = arr.end(); + auto const arrlast = arrend - 1; + + BOOST_TEST( arrlast + 1 == arrend ); + } } -} -BOOST_AUTO_TEST_CASE(iterator_interface ) { - multi::array arr = { - { - { 12, 11}, { 24, 10} - }, + BOOST_AUTO_TEST_CASE(iterator_2d) { + BOOST_TEST((std::is_trivially_copy_constructible_v >)); + BOOST_TEST((std::is_trivially_copy_assignable_v >)); + BOOST_TEST((std::is_trivially_default_constructible_v>)); + + BOOST_TEST((std::is_trivially_copy_constructible_v >)); + BOOST_TEST((std::is_trivially_copy_assignable_v >)); + BOOST_TEST((std::is_trivially_default_constructible_v>)); + + // BOOST_TEST((std::is_trivially_default_constructible_v::iterator>)); // TODO(correaa) + BOOST_TEST((std::is_trivially_copy_constructible_v ::iterator>)); + BOOST_TEST((std::is_trivially_copy_assignable_v ::iterator>)); + { - {112, 30}, {344, 40} - }, + multi::array const arr({120, 140}, 99.0); + + BOOST_TEST( arr.size() == 120 ); + BOOST_TEST( arr.cbegin() < arr.cend() ); + BOOST_TEST( arr.cend() - arr.cbegin() == arr.size() ); + + using iter = multi::array::iterator; + static_assert(std::is_same_v); + static_assert(std::is_same_v>); + static_assert(std::is_same_v>); + static_assert(std::is_same_v); + + using citer = multi::array::const_iterator; + static_assert(std::is_same_v); + static_assert(std::is_same_v>); + + static_assert(std::is_same_v>); + static_assert(std::is_same_v); + + auto const arrend = arr.end(); + auto const arrlast = arrend - 1; + + BOOST_TEST( arrlast + 1 == arrend ); + } { - { 12, 11}, { 24, 10} + std::vector vec(10000); // std::vector NOLINT(fuchsia-default-arguments-calls) + multi::array_ref arr(vec.data(), {100, 100}); + BOOST_TEST(arr.size() == 100); + begin(arr)[4][3] = 2.0; } - }; + } - BOOST_REQUIRE( size(arr) == 3 ); - BOOST_REQUIRE( size(arr[0]) == 2 ); - BOOST_REQUIRE( size(arr[0][0]) == 2 ); - BOOST_REQUIRE( arr[0][0][1] == 11 ); + BOOST_AUTO_TEST_CASE(iterator_interface) { + multi::array arr = { + { {12, 11}, {24, 10}}, + {{112, 30}, {344, 40}}, + { {12, 11}, {24, 10}} + }; - BOOST_REQUIRE( begin(arr) < end(arr) ); - BOOST_REQUIRE( cbegin(arr) < cend(arr) ); - BOOST_REQUIRE( begin(arr[0]) < end(arr[0]) ); - BOOST_REQUIRE( begin(arr[0]) < end(arr[0]) ); + BOOST_TEST( size(arr) == 3 ); + BOOST_TEST( size(arr[0]) == 2 ); + BOOST_TEST( size(arr[0][0]) == 2 ); + BOOST_TEST( arr[0][0][1] == 11 ); -// BOOST_REQUIRE(( multi::array::reverse_iterator {A.begin()} == rend(A) )); + BOOST_TEST( begin(arr) < end(arr) ); + BOOST_TEST( cbegin(arr) < cend(arr) ); + BOOST_TEST( begin(arr[0]) < end(arr[0]) ); + BOOST_TEST( begin(arr[0]) < end(arr[0]) ); -// BOOST_REQUIRE( rbegin(A) < rend(A) ); + // BOOST_TEST(( multi::array::reverse_iterator {A.begin()} == rend(A) )); - BOOST_REQUIRE( end(arr) - begin(arr) == size(arr) ); -// BOOST_REQUIRE( rend(A) - rbegin(A) == size(A) ); + // BOOST_TEST( rbegin(A) < rend(A) ); - BOOST_REQUIRE( size(*begin(arr) ) == 2 ); - BOOST_REQUIRE( size( begin(arr)[1]) == 2 ); + BOOST_TEST( end(arr) - begin(arr) == size(arr) ); + // BOOST_TEST( rend(A) - rbegin(A) == size(A) ); - BOOST_REQUIRE( &(arr[1][1].begin()[0]) == &arr[1][1][0] ); // NOLINT(readability-container-data-pointer) test access - BOOST_REQUIRE( &arr[0][1][0] == &arr[0][1][0] ); - BOOST_REQUIRE( &((*arr.begin())[1][0]) == &arr[0][1][0] ); - BOOST_REQUIRE( &((*arr.begin()).operator[](1)[0]) == &arr[0][1][0] ); - BOOST_REQUIRE( &(arr.begin()->operator[](1)[0]) == &arr[0][1][0] ); - BOOST_REQUIRE( &(arr.begin()->operator[](1).begin()[0]) == &arr[0][1][0] ); // NOLINT(readability-container-data-pointer) test access - BOOST_REQUIRE( &((arr.begin()+1)->operator[](1).begin()[0]) == &arr[1][1][0] ); // NOLINT(readability-container-data-pointer) test access - BOOST_REQUIRE( &((begin(arr)+1)->operator[](1).begin()[0]) == &arr[1][1][0] ); // NOLINT(readability-container-data-pointer) test access - BOOST_REQUIRE( &((cbegin(arr)+1)->operator[](1).begin()[0]) == &arr[1][1][0] ); // NOLINT(readability-container-data-pointer) test access -} + BOOST_TEST( size(*begin(arr) ) == 2 ); + BOOST_TEST( size( begin(arr)[1]) == 2 ); -BOOST_AUTO_TEST_CASE(iterator_semantics) { - multi::array arr = { - {{ 1.2, 1.1}, { 2.4, 1.0}}, - {{11.2, 3.0}, {34.4, 4.0}}, - {{ 1.2, 1.1}, { 2.4, 1.0}} - }; + BOOST_TEST( &(arr[1][1].begin()[0]) == &arr[1][1][0] ); // NOLINT(readability-container-data-pointer) test access + BOOST_TEST( &arr[0][1][0] == &arr[0][1][0] ); + BOOST_TEST( &((*arr.begin())[1][0]) == &arr[0][1][0] ); - multi::array::iterator it; - BOOST_REQUIRE(( multi::array::iterator{} == it )); - BOOST_REQUIRE(( it == multi::array::iterator{} )); + BOOST_TEST( &((*arr.begin()).operator[](1)[0]) == &arr[0][1][0] ); + BOOST_TEST( &( arr.begin()->operator[](1)[0]) == &arr[0][1][0] ); - it = begin(arr); - BOOST_REQUIRE( it == begin(arr) ); + BOOST_TEST( &((*arr.begin()).operator[](1).begin()[0]) == &arr[0][1][0] ); // NOLINT(readability-container-data-pointer) test access + BOOST_TEST( &( arr.begin()->operator[](1).begin()[0]) == &arr[0][1][0] ); // NOLINT(readability-container-data-pointer) test access - it += 1; - it -= 1; - BOOST_REQUIRE( it == begin(arr) ); + BOOST_TEST( &((*(arr.begin()+1)).operator[](1).begin()[0]) == &arr[1][1][0] ); // NOLINT(readability-container-data-pointer) test access + BOOST_TEST( &( (arr.begin()+1)->operator[](1).begin()[0]) == &arr[1][1][0] ); // NOLINT(readability-container-data-pointer) test access - auto const& arrc = arr(); - BOOST_REQUIRE( &arrc[0][0][0] == &arr[0][0][0] ); + BOOST_TEST( &((*(begin(arr)+1)).operator[](1).begin()[0]) == &arr[1][1][0] ); // NOLINT(readability-container-data-pointer) test access + BOOST_TEST( &(( begin(arr)+1)->operator[](1).begin()[0]) == &arr[1][1][0] ); // NOLINT(readability-container-data-pointer) test access - auto const& arrc2 = arr(); + BOOST_TEST( &((*(cbegin(arr)+1)).operator[](1).begin()[0]) == &arr[1][1][0] ); // NOLINT(readability-container-data-pointer) test access + BOOST_TEST( &(( cbegin(arr)+1)->operator[](1).begin()[0]) == &arr[1][1][0] ); // NOLINT(readability-container-data-pointer) test access + } - BOOST_REQUIRE( arrc.addressof() == arrc2.addressof() ); // BOOST_REQUIRE( &arrc == &arrc2 ); + BOOST_AUTO_TEST_CASE(iterator_semantics) { + multi::array arr = { + { {1.2, 1.1}, {2.4, 1.0}}, + {{11.2, 3.0}, {34.4, 4.0}}, + { {1.2, 1.1}, {2.4, 1.0}} + }; - multi::array::iterator const it2 = begin(arr); - BOOST_REQUIRE(it == it2); + multi::array::iterator it; + // BOOST_TEST(( multi::array::iterator{} == it )); // `it` is uninitialized + // BOOST_TEST(( it == multi::array::iterator{} )); - it = end(arr); - BOOST_REQUIRE(it != it2); - BOOST_REQUIRE(it > it2); + it = begin(arr); + BOOST_TEST( it == begin(arr) ); - multi::array::iterator const it3{it}; - BOOST_REQUIRE( it3 == it ); + it += 1; + it -= 1; + BOOST_TEST( it == begin(arr) ); - multi::array::const_iterator cit; - static_assert( std::is_same::iterator::element_ptr, double*>{}, "!"); + auto const& arrc = arr(); + BOOST_TEST( &arrc[0][0][0] == &arr[0][0][0] ); - [[maybe_unused]] multi::array::const_iterator const cit3{it3}; + auto const& arrc2 = arr(); - cit = it3; - BOOST_REQUIRE( cit == it3 ); - BOOST_REQUIRE( it3 == cit ); - BOOST_REQUIRE( &arr[0][2][1] == &begin(arr)[0][2][1] ); + BOOST_TEST( arrc.addressof() == arrc2.addressof() ); // BOOST_TEST( &arrc == &arrc2 ); - [[maybe_unused]] multi::array::const_iterator const cit2 = it3; + multi::array::iterator const it2 = begin(arr); + BOOST_TEST(it == it2); - static_assert( decltype(begin(arr))::rank_v == 3 , "!" ); - static_assert( decltype(begin(arr))::rank {} == 3 , "!" ); + it = end(arr); + BOOST_TEST(it != it2); + BOOST_TEST(it > it2); - auto&& ref = multi::ref(begin(arr), end(arr)); + multi::array::iterator const it3{it}; + BOOST_TEST( it3 == it ); - BOOST_TEST( arr.base() == ref.base() ); - BOOST_TEST( arr[0][2][1] == ref[0][2][1] ); - BOOST_TEST( &arr[0][2][1] == &ref[0][2][1] ); - BOOST_TEST( arr.layout().stride() == ref.layout().stride()); - BOOST_TEST( arr.layout().offset() == ref.layout().offset()); - BOOST_TEST( arr.layout().nelems() == ref.layout().nelems()); + static_assert(std::is_same::iterator::element_ptr, double*>{}); - BOOST_REQUIRE( arr.num_elements() == ref.num_elements() ); - BOOST_REQUIRE( arr.stride() == ref.stride() ); - BOOST_REQUIRE( arr.layout() == ref.layout() ); + // cit = it3; + // BOOST_REQUIRE( cit == it3 ); // TODO(correaa) + // BOOST_REQUIRE( it3 == cit ); // TODO(correaa) - BOOST_REQUIRE( &multi::ref(begin(arr), end(arr)) == &arr ); -} + // cit = it3; + // BOOST_TEST( cit == it3 ); // TODO(correaa) + // BOOST_TEST( it3 == cit ); // TODO(correaa) -BOOST_AUTO_TEST_CASE(iterator_arrow_operator) { - multi::array arr = { - {"00", "01"}, // std::string NOLINT(fuchsia-default-arguments-calls) std::string has a default constructor - {"10", "11"}, // std::string NOLINT(fuchsia-default-arguments-calls) - {"20", "21"} // std::string NOLINT(fuchsia-default-arguments-calls) - }; + BOOST_TEST( &arr[0][2][1] == &begin(arr)[0][2][1] ); - BOOST_REQUIRE( arr[1][0] == "10" ); + [[maybe_unused]] multi::array::const_iterator const cit2 = it3; - BOOST_REQUIRE( std::is_sorted(begin(arr), end(arr)) ); // sorted by rows - BOOST_REQUIRE( std::is_sorted(begin(arr.rotated()), end(arr.rotated())) ); // sorted by cols + static_assert(decltype(begin(arr))::rank_v == 3, "!"); + static_assert(decltype(begin(arr))::rank{} == 3, "!"); - BOOST_REQUIRE( begin( arr )->size() == arr[0].size() ); - BOOST_REQUIRE( begin( arr.rotated() )->size() == arr.size() ); + // auto&& ref = multi::ref(begin(arr), end(arr)); - BOOST_REQUIRE( &(begin( arr )->operator[](1)) == &(arr[0][1]) ); - BOOST_REQUIRE( &(begin( arr.rotated() )->operator[](1)) == &(arr[1][0]) ); -} + // BOOST_TEST( arr.base() == ref.base() ); + // BOOST_TEST( arr[0][2][1] == ref[0][2][1] ); + // BOOST_TEST( &arr[0][2][1] == &ref[0][2][1] ); + // BOOST_TEST( arr.layout().stride() == ref.layout().stride()); + // BOOST_TEST( arr.layout().offset() == ref.layout().offset()); + // BOOST_TEST( arr.layout().nelems() == ref.layout().nelems()); -BOOST_AUTO_TEST_CASE(index_range_iteration) { - multi::index_range irng{0, 5}; // semiopen interval - std::ostringstream out; - std::copy(begin(irng), end(irng), std::ostream_iterator{out, ","}); - BOOST_REQUIRE( out.str() == "0,1,2,3,4," ); + // BOOST_TEST( arr.num_elements() == ref.num_elements() ); + // BOOST_TEST( arr.stride() == ref.stride() ); + // BOOST_TEST( arr.layout() == ref.layout() ); - BOOST_REQUIRE( std::accumulate(begin(irng), end(irng), static_cast(0U)) == irng.size()*(irng.size()-1)/2 ); + // BOOST_TEST( &multi::ref(begin(arr), end(arr)) == &arr ); + } - BOOST_REQUIRE( std::accumulate(begin(irng), end(irng), static_cast(0U), [](auto&& acc, auto const& elem) {return acc + elem*elem*elem;}) > 0 ); // sum of cubes -} + BOOST_AUTO_TEST_CASE(iterator_arrow_operator) { + // NOLINTBEGIN(fuchsia-default-arguments-calls) std::string has a default constructor + multi::array arr = { + {"00", "01"}, + {"10", "11"}, + {"20", "21"} + }; + // NOLINTEND(fuchsia-default-arguments-calls) -BOOST_AUTO_TEST_CASE(multi_reverse_iterator_1D) { - multi::array arr(100, 66.0); - BOOST_REQUIRE( &arr[99] == &*std::make_reverse_iterator(arr.end()) ); + BOOST_TEST( arr[1][0] == "10" ); - auto rbegin = std::make_reverse_iterator(arr.end()); - rbegin += 100; - multi::array::iterator const begin{rbegin.base()}; - BOOST_REQUIRE( begin == arr.begin() ); -} + BOOST_TEST( std::is_sorted(begin(arr), end(arr)) ); // sorted by rows + BOOST_TEST( std::is_sorted(begin(arr.rotated()), end(arr.rotated())) ); // sorted by cols + + BOOST_TEST( (*begin( arr )).size() == arr[0].size() ); + BOOST_TEST( begin( arr )->size() == arr[0].size() ); + + BOOST_TEST( (*begin( arr.rotated() )).size() == arr.size() ); + BOOST_TEST( begin( arr.rotated() )->size() == arr.size() ); + + BOOST_TEST( &((*begin( arr )).operator[](1)) == &(arr[0][1]) ); + BOOST_TEST( &( begin( arr )->operator[](1)) == &(arr[0][1]) ); -BOOST_AUTO_TEST_CASE(multi_reverse_iterator_2D) { - multi::array arr = { - { 1.0, 2.0}, - { 10.0, 20.0}, - {100.0, 200.0} - }; - BOOST_REQUIRE( (*arr.begin())[1] == 2.0 ); - auto rbegin = std::make_reverse_iterator(arr.end()); + BOOST_TEST( &((*begin( arr.rotated() )).operator[](1)) == &(arr[1][0]) ); + BOOST_TEST( &( begin( arr.rotated() )->operator[](1)) == &(arr[1][0]) ); + } + + BOOST_AUTO_TEST_CASE(index_range_iteration) { + multi::index_range irng(0, 5); // semiopen interval + std::ostringstream out; + std::copy(irng.begin(), irng.end(), std::ostream_iterator{out, ","}); + BOOST_TEST_EQ(out.str(), std::string{"0,1,2,3,4,"}); // NOLINT(fuchsia-default-arguments-calls) + + BOOST_TEST( std::accumulate(begin(irng), end(irng), static_cast(0U)) == irng.size()*(irng.size()-1)/2 ); + + auto const sum_of_cubes = [](auto&& acc, auto const& elem) { + return std::forward(acc) + elem * elem * elem; + }; + BOOST_TEST( std::accumulate(begin(irng), end(irng), multi::index_range::value_type{}, sum_of_cubes) > 0 ); + } + + BOOST_AUTO_TEST_CASE(multi_reverse_iterator_1D) { + multi::array arr(100, 66.0); + BOOST_TEST( &arr[99] == &*std::make_reverse_iterator(arr.end()) ); - BOOST_TEST( (*rbegin)[1] == 200.0 ); + auto rbegin = std::make_reverse_iterator(arr.end()); + rbegin += 100; + multi::array::iterator const begin{rbegin.base()}; + BOOST_TEST( begin == arr.begin() ); + } + + BOOST_AUTO_TEST_CASE(multi_reverse_iterator_2D) { + multi::array arr = { + { 10, 20}, + { 100, 200}, + {1000, 2000} + }; + BOOST_TEST( (*arr.begin())[1] == 20 ); + BOOST_TEST( arr.begin()->operator[](1) == 20 ); + + auto rbegin = std::make_reverse_iterator(arr.end()); + + BOOST_TEST( (*rbegin)[1] == 2000 ); + + BOOST_TEST( arr.begin() < arr.begin() + 1 ); + BOOST_TEST( arr.end() - 1 < arr.end() ); + } - BOOST_REQUIRE( arr.begin() < arr.begin() + 1 ); - BOOST_REQUIRE( arr.end() - 1 < arr.end() ); + return boost::report_errors(); } diff --git a/external_codes/boost_multi/multi/test/layout.cpp b/external_codes/boost_multi/multi/test/layout.cpp index b1d3405ef7..3b7cb98cc7 100644 --- a/external_codes/boost_multi/multi/test/layout.cpp +++ b/external_codes/boost_multi/multi/test/layout.cpp @@ -2,83 +2,64 @@ // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt -// See: https://github.com/llvm/llvm-project/issues/61415 -// Should be fixed in 18, but we know 16 and 17 are broken -#if !(defined(__clang__) && (__clang_major__ == 16 || __clang_major__ == 17) && __cplusplus > 202002L) - -#include -#include - -#include - -#include -#include - -// Suppress warnings from boost.test -#if defined(__clang__) -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wold-style-cast" -# pragma clang diagnostic ignored "-Wundef" -# pragma clang diagnostic ignored "-Wconversion" -# pragma clang diagnostic ignored "-Wsign-conversion" -// # pragma clang diagnostic ignored "-Wfloat-equal" -#elif defined(__GNUC__) -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wold-style-cast" -# pragma GCC diagnostic ignored "-Wundef" -# pragma GCC diagnostic ignored "-Wconversion" -# pragma GCC diagnostic ignored "-Wsign-conversion" -// # pragma GCC diagnostic ignored "-Wfloat-equal" -#elif defined(_MSC_VER) -# pragma warning(push) -# pragma warning(disable : 4244) // 'conversion' conversion from 'type1' to 'type2', possible loss of data -#endif +#include // for range, layout_t, get, extensions_t -#ifndef BOOST_TEST_MODULE -# define BOOST_TEST_MAIN +#include // for array, array<>::value_type +#include // for size +#if __cplusplus > 201703L +#if __has_include() +#include // NOLINT(misc-include-cleaner) IWYU pragma: keep #endif - -#include +#endif +#include // for make_tuple, tuple_element<>::type +// IWYU pragma: no_include +// IWYU pragma: no_#include namespace multi = boost::multi; namespace { auto second_finish(multi::extensions_t<3> exts) { - return std::get<1>(exts).last(); + using std::get; // workaround: function call with explicit template arguments is a C++20 extension [-Wc++20-extensions] + return get<1>(exts).last(); } } // namespace +#include +#define BOOST_AUTO_TEST_CASE(CasenamE) /**/ + +auto main() -> int { // NOLINT(readability-function-cognitive-complexity,bugprone-exception-escape) BOOST_AUTO_TEST_CASE(extensions_3D) { - BOOST_REQUIRE( 20 == second_finish( multi::extensions_t<3> { {0, 10}, {0, 20}, {0, 30} } ) ); - BOOST_REQUIRE( 20 == second_finish( multi::extensions_t<3>( { {0, 10}, {0, 20}, {0, 30} } )) ); - BOOST_REQUIRE( 20 == second_finish( { {0, 10}, {0, 20}, {0, 30} } ) ); + BOOST_TEST( 20 == second_finish( multi::extensions_t<3> { {0, 10}, {0, 20}, {0, 30} } ) ); + BOOST_TEST( 20 == second_finish( multi::extensions_t<3>( { {0, 10}, {0, 20}, {0, 30} } )) ); + BOOST_TEST( 20 == second_finish( { {0, 10}, {0, 20}, {0, 30} } ) ); multi::extensions_t<3> const exts({0, 10}, {0, 20}, {0, 30}); - BOOST_REQUIRE( 20 == second_finish(exts ) ); + BOOST_TEST( 20 == second_finish(exts) ); } + BOOST_AUTO_TEST_CASE(extensions_to_linear) { multi::extensions_t<3> exts{4, 5, 3}; - BOOST_REQUIRE( exts.to_linear(0, 0, 0) == 0 ); - BOOST_REQUIRE( exts.to_linear(0, 0, 1) == 1 ); - BOOST_REQUIRE( exts.to_linear(0, 0, 2) == 2 ); - BOOST_REQUIRE( exts.to_linear(0, 1, 0) == 3 ); - BOOST_REQUIRE( exts.to_linear(0, 1, 1) == 4 ); - BOOST_REQUIRE( exts.to_linear(0, 1, 2) == 5 ); - BOOST_REQUIRE( exts.to_linear(1, 0, 0) == 15 ); + BOOST_TEST( exts.to_linear(0, 0, 0) == 0 ); + BOOST_TEST( exts.to_linear(0, 0, 1) == 1 ); + BOOST_TEST( exts.to_linear(0, 0, 2) == 2 ); + BOOST_TEST( exts.to_linear(0, 1, 0) == 3 ); + BOOST_TEST( exts.to_linear(0, 1, 1) == 4 ); + BOOST_TEST( exts.to_linear(0, 1, 2) == 5 ); + BOOST_TEST( exts.to_linear(1, 0, 0) == 15 ); for(int eye = 0; eye != 4; ++eye) { for(int jay = 0; jay != 5; ++jay) { - for(int kay = 0; kay != 3; ++kay) { - BOOST_REQUIRE(( exts.from_linear(exts.to_linear(eye, jay, kay)) == decltype(exts.from_linear(exts.to_linear(eye, jay, kay))){eye, jay, kay} )); + for(int kay = 0; kay != 3; ++kay) { // NOLINT(altera-unroll-loops) + BOOST_TEST(( exts.from_linear(exts.to_linear(eye, jay, kay)) == decltype(exts.from_linear(exts.to_linear(eye, jay, kay))){eye, jay, kay} )); } } } - BOOST_REQUIRE( exts.to_linear(4, 0, 0) == exts.num_elements() ); + BOOST_TEST( exts.to_linear(4, 0, 0) == exts.num_elements() ); - for(int idx = 0; idx != exts.num_elements(); ++idx) { - BOOST_REQUIRE( std::apply([&](auto... indices) { return exts.to_linear(indices...);}, exts.from_linear(idx)) == idx ); + for(int idx = 0; idx != exts.num_elements(); ++idx) { // NOLINT(altera-unroll-loops) + BOOST_TEST( std::apply([&](auto... indices) { return exts.to_linear(indices...);}, exts.from_linear(idx)) == idx ); } } @@ -92,14 +73,24 @@ BOOST_AUTO_TEST_CASE(extensions_layout_to_linear) { auto&& sub = arr({10, 30}, {20, 32}, {60, 75}); + #if defined(__clang__) + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wunknown-warning-option" + #pragma clang diagnostic ignored "-Wunsafe-buffer-usage" // TODO(correaa) use checked span + #endif + for(int i = 0; i != 10; ++i) { for(int j = 0; j != 12; ++j) { - for(int k = 0; k != 15; ++k) { - BOOST_REQUIRE( & sub.base() [sub.layout()(i, j, k)] == &sub(i, j, k) ); - BOOST_REQUIRE( &*(sub.base() + sub.layout()(i, j, k)) == &sub(i, j, k) ); + for(int k = 0; k != 15; ++k) { // NOLINT(altera-unroll-loops) + BOOST_TEST( & sub.base() [sub.layout()(i, j, k)] == &sub(i, j, k) ); + BOOST_TEST( &*(sub.base() + sub.layout()(i, j, k)) == &sub(i, j, k) ); } } } + + #if defined(__clang__) + #pragma clang diagnostic pop + #endif } BOOST_AUTO_TEST_CASE(extensions_layout_to_linear_2) { @@ -114,21 +105,26 @@ BOOST_AUTO_TEST_CASE(extensions_layout_to_linear_2) { auto const& rot = sub.rotated(); -#ifndef _MSC_VER auto const [is, js, ks] = rot.extensions(); -#else - auto const is = std::get<0>(rot.extensions()); - auto const js = std::get<0>(rot.extensions()); - auto const ks = std::get<0>(rot.extensions()); -#endif + + #if defined(__clang__) + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wunknown-warning-option" + #pragma clang diagnostic ignored "-Wunsafe-buffer-usage" + #endif + for(auto const i : is) { for(auto const j : js) { - for(auto const k : ks) { - BOOST_REQUIRE( & rot.base() [rot.layout()(i, j, k)] == &rot(i, j, k) ); - BOOST_REQUIRE( &*(rot.base() + rot.layout()(i, j, k)) == &rot(i, j, k) ); + for(auto const k : ks) { // NOLINT(altera-unroll-loops) + BOOST_TEST( & rot.base() [rot.layout()(i, j, k)] == &rot(i, j, k) ); + BOOST_TEST( &*(rot.base() + rot.layout()(i, j, k)) == &rot(i, j, k) ); } } } + + #if defined(__clang__) + #pragma clang diagnostic pop + #endif } BOOST_AUTO_TEST_CASE(linearize) { @@ -139,71 +135,83 @@ BOOST_AUTO_TEST_CASE(linearize) { {10, 20, 30} ); - BOOST_REQUIRE(( 25 % extensions(arr) == decltype( 25 % extensions(arr)){0, 0, 25} )); - BOOST_REQUIRE(( 55 % extensions(arr) == decltype( 55 % extensions(arr))(0, 1, 25) )); - BOOST_REQUIRE(( 655 % extensions(arr) == decltype( 655 % extensions(arr))(1, 1, 25) )); - BOOST_REQUIRE((1255 % extensions(arr) == decltype(1255 % extensions(arr))(2, 1, 25) )); + BOOST_TEST(( 25 % extensions(arr) == decltype( 25 % extensions(arr)){0, 0, 25} )); + BOOST_TEST(( 55 % extensions(arr) == decltype( 55 % extensions(arr))(0, 1, 25) )); + BOOST_TEST(( 655 % extensions(arr) == decltype( 655 % extensions(arr))(1, 1, 25) )); + BOOST_TEST((1255 % extensions(arr) == decltype(1255 % extensions(arr))(2, 1, 25) )); auto const point = arr.extensions().from_linear(655); - // BOOST_REQUIRE( p == std::make_tuple(1, 1, 25) ); + // BOOST_TEST( p == std::make_tuple(1, 1, 25) ); using multi::detail::get; - BOOST_REQUIRE( get<0>(point) == 1 ); - BOOST_REQUIRE( get<1>(point) == 1 ); - BOOST_REQUIRE( get<2>(point) == 25 ); + BOOST_TEST( get<0>(point) == 1 ); + BOOST_TEST( get<1>(point) == 1 ); + BOOST_TEST( get<2>(point) == 25 ); } BOOST_AUTO_TEST_CASE(layout_tuple_2d) { multi::extensions_t<2> const x1({51, 52}); - multi::extensions_t<2> const x2({multi::iextension{0, 51}, multi::iextension{0, 52}}); - BOOST_REQUIRE( x1 == x2 ); + multi::extensions_t<2> const x2({multi::iextension(0, 51), multi::iextension(0, 52)}); + + BOOST_TEST( x1 == x2 ); multi::extensions_t<2> const x3(std::make_tuple(multi::iextension{0, 51}, multi::iextension{0, 52})); - BOOST_REQUIRE( x1 == x3 ); + BOOST_TEST( x1 == x3 ); multi::extensions_t<2> const x4 = std::make_tuple(multi::iextension{0, 51}, multi::iextension{0, 52}); - BOOST_REQUIRE( x1 == x4 ); + BOOST_TEST( x1 == x4 ); - multi::extensions_t<2> const x5 = std::tuple{multi::iextension{0, 51}, multi::iextension{0, 52}}; - BOOST_REQUIRE( x1 == x5 ); + multi::extensions_t<2> const x5 = std::tuple{ + multi::iextension{0, 51}, + multi::iextension{0, 52} + }; + BOOST_TEST( x1 == x5 ); multi::extensions_t<2> const x6 = std::tuple{51, 52}; - BOOST_REQUIRE( x1 == x6 ); + BOOST_TEST( x1 == x6 ); multi::extensions_t<2> const x7{51, 52}; - BOOST_REQUIRE( x1 == x7 ); + BOOST_TEST( x1 == x7 ); multi::extensions_t<2> const x8 = {51, 52}; - BOOST_REQUIRE( x1 == x8 ); + BOOST_TEST( x1 == x8 ); auto const x9 = multi::extensions_t<2>{51, 52}; - BOOST_REQUIRE( x1 == x9 ); + BOOST_TEST( x1 == x9 ); // multi::extensions_t x10{51, 52, 53}; // TODO(correaa) should it work? - // BOOST_REQUIRE( x1 == x10 ); + // BOOST_TEST( x1 == x10 ); } BOOST_AUTO_TEST_CASE(layout_tuple_3d) { multi::extensions_t<3> const x1({51, 52, 53}); - multi::extensions_t<3> const x2({multi::iextension{0, 51}, multi::iextension{0, 52}, multi::iextension{0, 53}}); - BOOST_REQUIRE( x1 == x2 ); + multi::extensions_t<3> const x2({ + multi::iextension{0, 51}, + multi::iextension{0, 52}, + multi::iextension{0, 53} + }); + BOOST_TEST( x1 == x2 ); multi::extensions_t<3> const x3(std::make_tuple(multi::iextension{0, 51}, multi::iextension{0, 52}, multi::iextension{0, 53})); - BOOST_REQUIRE( x1 == x3 ); + BOOST_TEST( x1 == x3 ); multi::extensions_t<3> const x4 = std::make_tuple(multi::iextension{0, 51}, multi::iextension{0, 52}, multi::iextension{0, 53}); - BOOST_REQUIRE( x1 == x4 ); + BOOST_TEST( x1 == x4 ); - multi::extensions_t<3> const x5 = std::tuple{multi::iextension{0, 51}, multi::iextension{0, 52}, multi::iextension{0, 53}}; - BOOST_REQUIRE( x1 == x5 ); + multi::extensions_t<3> const x5 = std::tuple{ + multi::iextension{0, 51}, + multi::iextension{0, 52}, + multi::iextension{0, 53} + }; + BOOST_TEST( x1 == x5 ); multi::extensions_t<3> const x6 = std::tuple{51, 52, 53}; - BOOST_REQUIRE( x1 == x6 ); + BOOST_TEST( x1 == x6 ); multi::extensions_t<3> const x7{51, 52, 53}; - BOOST_REQUIRE( x1 == x7 ); + BOOST_TEST( x1 == x7 ); // multi::extensions_t x8{51, 52, 53}; // TODO(correaa) should it work? - // BOOST_REQUIRE( x1 == x8 ); + // BOOST_TEST( x1 == x8 ); } BOOST_AUTO_TEST_CASE(layout_0) { @@ -214,36 +222,38 @@ BOOST_AUTO_TEST_CASE(layout_0) { {51, 52, 53} ); - BOOST_REQUIRE( size(arr) == 51 ); - BOOST_REQUIRE( arr.size() == 51 ); + BOOST_TEST( size(arr) == 51 ); + BOOST_TEST( arr.size() == 51 ); - BOOST_REQUIRE( size(arr[0]) == 52 ); - BOOST_REQUIRE( arr[0].size() == 52 ); + BOOST_TEST( size(arr[0]) == 52 ); + BOOST_TEST( arr[0].size() == 52 ); - BOOST_REQUIRE( size(arr[0][0]) == 53 ); - BOOST_REQUIRE( arr[0][0].size() == 53 ); + BOOST_TEST( size(arr[0][0]) == 53 ); + BOOST_TEST( arr[0][0].size() == 53 ); } BOOST_AUTO_TEST_CASE(layout_1) { // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays): testing feature - double arr[50][50][50]; + double arr[25][25][25]; // this can overflow the stack: double arr[50][50][50]; 50*50*50*8bytes = 1MB + using multi::size; - BOOST_REQUIRE( size(arr) == 50 ); + BOOST_TEST( size(arr) == 25 ); using multi::extension; - BOOST_REQUIRE(( extension(arr) == multi::index_extension{0, 50} )); - BOOST_REQUIRE(( extension(arr) == multi::iextension{0, 50} )); - // BOOST_REQUIRE(( extension(arr) == multi::irange{0, 50} )); + + BOOST_TEST(( extension(arr) == multi::index_extension{0, 25} )); + BOOST_TEST(( extension(arr) == multi::iextension {0, 25} )); + // BOOST_TEST(( extension(arr) == multi::irange{0, 25} )); } BOOST_AUTO_TEST_CASE(layout_2) { - std::array, 50>, 50> const arr{}; + std::array, 25>, 25> const arr{}; using multi::size; - BOOST_REQUIRE( size(arr) == 50 ); + BOOST_TEST( size(arr) == 25 ); using multi::extension; - BOOST_REQUIRE(( extension(arr) == multi::index_extension{0, 50} )); - BOOST_REQUIRE(( extension(arr) == multi::iextension{0, 50} )); + BOOST_TEST(( extension(arr) == multi::index_extension{0, 25} )); + BOOST_TEST(( extension(arr) == multi::iextension {0, 25} )); } BOOST_AUTO_TEST_CASE(layout_3) { @@ -253,761 +263,773 @@ BOOST_AUTO_TEST_CASE(layout_3) { #endif {50, 50} ); - BOOST_REQUIRE( size(arr) == 50 ); - BOOST_REQUIRE( arr.size() == 50 ); + BOOST_TEST( size(arr) == 50 ); + BOOST_TEST( arr.size() == 50 ); - BOOST_REQUIRE( arr[0].sliced(10, 20).size() == 10 ); - BOOST_REQUIRE( size(arr[0].sliced(10, 20)) == 10 ); + BOOST_TEST( arr[0].sliced(10, 20).size() == 10 ); + BOOST_TEST( size(arr[0].sliced(10, 20)) == 10 ); - static_assert(decltype(arr(0, {10, 20}))::rank_v == 1, "!"); + static_assert(decltype(arr(0, {10, 20}))::rank_v == 1); - BOOST_REQUIRE( size(arr(0, {10, 20})) == 10 ); + BOOST_TEST( size(arr(0, {10, 20})) == 10 ); - BOOST_REQUIRE( arr.layout() == arr.layout() ); - BOOST_REQUIRE( ! (arr.layout() < arr.layout()) ); + BOOST_TEST( arr.layout() == arr.layout() ); + BOOST_TEST( !(arr.layout() < arr.layout()) ); } -BOOST_AUTO_TEST_CASE(layout) { - { - multi::array const A2 = { - {1.0, 2.0, 3.0}, - {4.0, 5.0, 6.0}, - {7.0, 8.0, 9.0}, - }; +BOOST_AUTO_TEST_CASE(layout_AA) { + multi::array const A2 = { + {1, 2, 3}, + {4, 5, 6}, + {7, 8, 9}, + }; + +#if defined(__cpp_lib_ranges) && (__cpp_lib_ranges >= 201911L) +#if !defined(__clang_major__) || ((__clang_major__ < 14) && (__clang_major__ != 10)) +#if !defined(__NVCC__) +#if !defined(_MSC_VER) + static_assert( std::ranges::random_access_range ); + + auto tiA2 = std::views::transform( + // A2.extension(), + std::views::iota(0L, A2.size()), + [](auto idx) noexcept {return idx;} + ); + BOOST_TEST( *tiA2.begin() == 0 ); + BOOST_TEST( tiA2[0] == 0 ); +#endif +#endif +#endif +#endif - BOOST_REQUIRE( size(A2) == 3 ); + BOOST_TEST( size(A2) == 3 ); - multi::array B2( + multi::array B2( #ifdef _MSC_VER // problem with MSVC 14.3 c++17 multi::extensions_t<2> #endif - {4, 4} - ); - BOOST_REQUIRE( size(B2) == 4 ); - B2[3][3] = 99.0; + {4, 4} + ); - auto B2copy = +B2({0, 2}, {0, 2}); + BOOST_TEST( size(B2) == 4 ); + B2[3][3] = 99; - BOOST_REQUIRE( &B2copy[1][1] != &B2({0, 2}, {0, 2})[1][1] ); + multi::array B2copy{B2({0, 2}, {0, 2})}; - // clang-format off - std::array, 2> - B2blk = {{ - {{B2({0, 2}, {0, 2}), B2({0, 2}, {2, 4})}}, - {{B2({2, 4}, {0, 2}), B2({2, 4}, {2, 4})}}, - }} - ; - // clang-format on + auto B2copy2 = B2({0, 2}, {0, 2}).decay(); - BOOST_REQUIRE( &B2blk[1][1][1][1] == &B2[3][3] ); - } - { - // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) test legacy type - double arr[3][4][5] = {}; - using multi::dimensionality; - static_assert( dimensionality(arr) == 3 ); - using multi::extensions; - auto xA = extensions(arr); + BOOST_TEST( &B2copy[1][1] != &B2({0, 2}, {0, 2})[1][1] ); - BOOST_REQUIRE( size(std::get<0>(xA)) == 3 ); - BOOST_REQUIRE( size(std::get<1>(xA)) == 4 ); - BOOST_REQUIRE( size(std::get<2>(xA)) == 5 ); + // clang-format off + std::array, 2> B2blk = {{ + {{B2({0, 2}, {0, 2}), B2({0, 2}, {2, 4})}}, + {{B2({2, 4}, {0, 2}), B2({2, 4}, {2, 4})}}, + }}; + // clang-format on - static_assert(multi::stride(arr) == 20); + BOOST_TEST( &B2blk[1][1][1][1] == &B2[3][3] ); +} - static_assert(multi::stride(arr[1]) == 5); - static_assert(multi::stride(arr[0][0]) == 1); +// BOOST_AUTO_TEST_CASE(layout_BB) { +// { +// // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) test legacy type +// double arr[3][4][5] = {}; +// using multi::dimensionality; +// static_assert(dimensionality(arr) == 3); +// using multi::extensions; +// auto xA = extensions(arr); - multi::array AA({3, 4, 5}); - using multi::layout; - BOOST_REQUIRE( layout(AA) == layout(arr) ); +// BOOST_TEST( size(std::get<0>(xA)) == 3 ); +// BOOST_TEST( size(std::get<1>(xA)) == 4 ); +// BOOST_TEST( size(std::get<2>(xA)) == 5 ); - BOOST_REQUIRE( AA.stride() == 20 ); - } - { - std::array, 4>, 3> arr = {}; - static_assert(multi::dimensionality(arr) == 3); +// static_assert(multi::stride(arr) == 20); - using multi::extensions; - auto xA = extensions(arr); - using std::get; - BOOST_REQUIRE( size(std::get<0>(xA)) == 3 ); - BOOST_REQUIRE( size(std::get<1>(xA)) == 4 ); - BOOST_REQUIRE( size(std::get<2>(xA)) == 5 ); +// static_assert(multi::stride(arr[1]) == 5); +// static_assert(multi::stride(arr[0][0]) == 1); - multi::array AA({3, 4, 5}); - using multi::layout; - BOOST_REQUIRE( layout(AA) == layout(arr) ); +// multi::array AA({3, 4, 5}); +// using multi::layout; +// BOOST_TEST( layout(AA) == layout(arr) ); - BOOST_REQUIRE( AA.stride() == 20 ); +// BOOST_TEST( AA.stride() == 20 ); +// } +// { +// std::array, 4>, 3> arr = {}; +// static_assert(multi::dimensionality(arr) == 3); - static_assert(multi::stride(arr) == 20); +// using multi::extensions; +// auto xA = extensions(arr); +// using std::get; +// BOOST_TEST( size(std::get<0>(xA)) == 3 ); +// BOOST_TEST( size(std::get<1>(xA)) == 4 ); +// BOOST_TEST( size(std::get<2>(xA)) == 5 ); - BOOST_REQUIRE( multi::stride(arr[0]) == 5 ); - BOOST_REQUIRE( multi::stride(arr[1]) == 5 ); - BOOST_REQUIRE( multi::stride(arr[0][0]) == 1 ); - } - { - multi::array const B2 = { - {1.0}, - {2.0}, - {3.0}, - }; - BOOST_REQUIRE( size(B2) == 3 ); - BOOST_REQUIRE( size(rotated(B2)) == 1 ); - BOOST_REQUIRE( size(B2[0]) == 1); - BOOST_REQUIRE( B2 .stride() == 1 ); - BOOST_REQUIRE( B2[0].stride() == 1 ); - } -} +// multi::array AA({3, 4, 5}); +// using multi::layout; +// BOOST_TEST( layout(AA) == layout(arr) ); -BOOST_AUTO_TEST_CASE(multi_layout_with_offset) { - { - multi::layout_t<1> const l1(multi::iextension(2, 5)); - BOOST_REQUIRE( l1.extension().first() == 2 ); - BOOST_REQUIRE( l1.extension().last() == 5 ); - } - { - boost::multi::layout_t<2>::extensions_type const exts{ - multi::iextension(2, 5), - multi::iextension(0, 5)}; - multi::layout_t<2> const l2(exts); - BOOST_REQUIRE( l2.extension().first() == std::get<0>(exts).first() ); - BOOST_REQUIRE( l2.extension().last () == std::get<0>(exts).last() ); - } - { - multi::layout_t<2> const l2({multi::iextension(0, 3), multi::iextension(2, 7)}); - BOOST_REQUIRE( std::get<1>(l2.extensions()).first() == 2 ); - BOOST_REQUIRE( std::get<1>(l2.extensions()).last() == 7 ); - } -} +// BOOST_TEST( AA.stride() == 20 ); -BOOST_AUTO_TEST_CASE(multi_layout_part1) { - { - multi::layout_t<0> const lyt; - static_assert(decltype(lyt)::rank_v == 0); - BOOST_REQUIRE( num_elements(lyt) == 1 ); - } - { - multi::iextensions<0> const exts{}; - multi::layout_t<0> const lyt(exts); - BOOST_REQUIRE(lyt.num_elements() == 1); - } - { - multi::layout_t<1> const lyt{}; - static_assert(decltype(lyt)::rank_v == 1); - BOOST_REQUIRE( num_elements(lyt) == 0 ); - BOOST_REQUIRE( size(lyt) == 0 ); - BOOST_REQUIRE( size(extension(lyt))==0 ); - BOOST_REQUIRE( stride(lyt)!=0 ); - BOOST_REQUIRE( is_empty(lyt) ); - } - { - multi::layout_t<2> const lyt({2, 10}); - static_assert(decltype(lyt)::rank_v == 2); - BOOST_REQUIRE( num_elements(lyt) == 20 ); - BOOST_REQUIRE( size(lyt) == 2 ); - BOOST_REQUIRE( size(extension(lyt))==2 ); - BOOST_REQUIRE( stride(lyt)==10 ); - BOOST_REQUIRE( ! is_empty(lyt) ); - } - { - multi::layout_t<1> const lyt(multi::iextensions<1>{20}); - static_assert(decltype(lyt)::rank_v == 1, "!"); - BOOST_REQUIRE( num_elements(lyt) == 20 ); - BOOST_REQUIRE( size(lyt) == 20 ); - BOOST_REQUIRE( stride(lyt) == 1 ); - } -} +// static_assert(multi::stride(arr) == 20); -BOOST_AUTO_TEST_CASE(multi_layout_part2) { - { - multi::layout_t<1> const lyt(multi::iextensions<1>{1}); - static_assert(decltype(lyt)::rank_v == 1); - BOOST_REQUIRE( num_elements(lyt) == 1 ); - BOOST_REQUIRE( size(lyt) == 1 ); - BOOST_REQUIRE( stride(lyt) == 1 ); - } - { - multi::layout_t<2> const lyt({1, 10}); - static_assert(decltype(lyt)::rank_v == 2); - BOOST_REQUIRE( num_elements(lyt) == 10 ); - BOOST_REQUIRE( size(lyt) == 1); - BOOST_REQUIRE( ! is_empty(lyt) ); - BOOST_REQUIRE( size(extension(lyt))==1 ); - BOOST_REQUIRE( stride(lyt)== 10 ); // std::numeric_limits::max() ); - - using std::get; - BOOST_REQUIRE( get<0>(strides(lyt)) == 10); - BOOST_REQUIRE( get<1>(strides(lyt)) == 1 ); - } -} +// BOOST_TEST( multi::stride(arr[0]) == 5 ); +// BOOST_TEST( multi::stride(arr[1]) == 5 ); +// BOOST_TEST( multi::stride(arr[0][0]) == 1 ); +// } +// { +// multi::array const B2 = { +// {1.0}, +// {2.0}, +// {3.0}, +// }; +// BOOST_TEST( size(B2) == 3 ); +// BOOST_TEST( B2.rotated().size() == 1 ); +// BOOST_TEST( size(B2[0]) == 1); +// BOOST_TEST( B2 .stride() == 1 ); +// BOOST_TEST( B2[0].stride() == 1 ); +// } +// } -BOOST_AUTO_TEST_CASE(multi_layout_part3) { - { - multi::layout_t<2> const lyt({10, 1}); - static_assert(decltype(lyt)::rank_v == 2); - BOOST_REQUIRE( num_elements(lyt) == 10 ); - BOOST_REQUIRE( size(lyt) == 10 ); - using std::get; - BOOST_REQUIRE( get<0>(strides(lyt)) == 1 ); - BOOST_REQUIRE( get<1>(strides(lyt)) == 1 ); - } - { - multi::layout_t<2> const lyt{}; - BOOST_REQUIRE( dimensionality(lyt)==2 ); - BOOST_REQUIRE( num_elements(lyt) == 0 ); - BOOST_REQUIRE( size(lyt) == 0 ); - BOOST_REQUIRE( size(extension(lyt))==0 ); - BOOST_REQUIRE( stride(lyt)!=0 ); - BOOST_REQUIRE( is_empty(lyt) ); - } - { - multi::layout_t<3> const lyt{}; - BOOST_REQUIRE( num_elements(lyt) == 0 ); - } - { - multi::layout_t<3> const lyt({ - {0, 10}, - {0, 10}, - {0, 10}, - }); - BOOST_REQUIRE( num_elements(lyt) == 1000 ); - } - { - multi::layout_t<3> const lyt({{10}, {10}, {10}}); - BOOST_REQUIRE( num_elements(lyt) == 1000 ); - } - { - multi::layout_t<3> const lyt({10, 10, 10}); - BOOST_REQUIRE( num_elements(lyt) == 1000 ); - } - { - multi::layout_t<3> const lyt({ - multi::index_extension{0, 10}, - {0, 10}, - {0, 10}, - }); - BOOST_REQUIRE( num_elements(lyt) == 1000 ); - } - { - multi::layout_t<3> const lyt(multi::layout_t<3>::extensions_type{ - {0, 10}, - {0, 10}, - {0, 10}, - }); - BOOST_REQUIRE( num_elements(lyt) == 1000 ); - } -} +// BOOST_AUTO_TEST_CASE(multi_layout_with_offset) { +// static_assert( std::is_trivially_default_constructible_v< multi::layout_t<0> > ); +// static_assert( std::is_trivially_default_constructible_v< multi::layout_t<1> > ); +// static_assert( std::is_trivially_default_constructible_v< multi::layout_t<2> > ); -BOOST_AUTO_TEST_CASE(layout_to_offset) { - multi::layout_t<3> const lyt({10, 20, 30}); - multi::array const arr({10, 20, 30}); - BOOST_REQUIRE( lyt[0][0][0] == &arr[0][0][0] - arr.data_elements() ); - BOOST_REQUIRE( lyt[0][0][1] == &arr[0][0][1] - arr.data_elements() ); - BOOST_REQUIRE( lyt[0][0][2] == &arr[0][0][2] - arr.data_elements() ); +// static_assert( std::is_trivially_copyable_v< multi::layout_t<2> > ); - BOOST_TEST_REQUIRE(lyt[0][1][2] == &arr[0][1][2] - arr.data_elements()); - BOOST_TEST_REQUIRE(lyt[3][1][2] == &arr[3][1][2] - arr.data_elements()); -} +// { +// multi::layout_t<1> const l1(multi::iextension(2, 5)); +// BOOST_TEST( l1.extension().first() == 2 ); +// BOOST_TEST( l1.extension().last() == 5 ); +// } +// { +// boost::multi::layout_t<2>::extensions_type const exts{ +// multi::iextension(2, 5), +// multi::iextension(0, 5) +// }; +// multi::layout_t<2> const l2(exts); +// BOOST_TEST( l2.extension().first() == std::get<0>(exts).first() ); +// BOOST_TEST( l2.extension().last () == std::get<0>(exts).last() ); +// } +// { +// multi::layout_t<2> const l2({multi::iextension(0, 3), multi::iextension(2, 7)}); +// BOOST_TEST( std::get<1>(l2.extensions()).first() == 2 ); +// BOOST_TEST( std::get<1>(l2.extensions()).last() == 7 ); +// } +// } -BOOST_AUTO_TEST_CASE(layout_to_offset_sub) { - multi::array arr({10, 20, 30}); +// BOOST_AUTO_TEST_CASE(multi_layout_part1) { +// { +// multi::layout_t<0> const lyt; +// static_assert(decltype(lyt)::rank_v == 0); +// BOOST_TEST( num_elements(lyt) == 1 ); +// } +// { +// multi::iextensions<0> const exts{}; +// multi::layout_t<0> const lyt(exts); +// BOOST_TEST(lyt.num_elements() == 1); +// } +// { +// multi::layout_t<1> const lyt{}; +// static_assert(decltype(lyt)::rank_v == 1); +// BOOST_TEST( num_elements(lyt) == 0 ); +// BOOST_TEST( size(lyt) == 0 ); +// BOOST_TEST( size(extension(lyt)) == 0 ); +// BOOST_TEST( stride(lyt) != 0 ); +// BOOST_TEST( is_empty(lyt) ); +// } +// { +// multi::layout_t<2> const lyt({2, 10}); +// static_assert(decltype(lyt)::rank_v == 2); +// BOOST_TEST( num_elements(lyt) == 20 ); +// BOOST_TEST( size(lyt) == 2 ); +// BOOST_TEST( size(extension(lyt)) == 2 ); +// BOOST_TEST( stride(lyt) == 10 ); +// BOOST_TEST( !is_empty(lyt) ); +// } +// { +// multi::layout_t<1> const lyt(multi::iextensions<1>{20}); +// static_assert(decltype(lyt)::rank_v == 1); +// BOOST_TEST( num_elements(lyt) == 20 ); +// BOOST_TEST( size(lyt) == 20 ); +// BOOST_TEST( stride(lyt) == 1 ); +// } +// } - auto&& sub = arr({2, 6}, {4, 8}, {10, 20}); +// BOOST_AUTO_TEST_CASE(multi_layout_part2) { +// { +// multi::layout_t<1> const lyt(multi::iextensions<1>{1}); +// static_assert(decltype(lyt)::rank_v == 1); +// BOOST_TEST( num_elements(lyt) == 1 ); +// BOOST_TEST( size(lyt) == 1 ); +// BOOST_TEST( stride(lyt) == 1 ); +// } +// { +// multi::layout_t<2> const lyt({1, 10}); +// static_assert(decltype(lyt)::rank_v == 2); +// BOOST_TEST( num_elements(lyt) == 10 ); +// BOOST_TEST( size(lyt) == 1); +// BOOST_TEST( !is_empty(lyt) ); +// BOOST_TEST( size(extension(lyt)) == 1 ); +// BOOST_TEST( stride(lyt) == 10 ); // std::numeric_limits::max() ); + +// using std::get; +// BOOST_TEST( get<0>(strides(lyt)) == 10); +// BOOST_TEST( get<1>(strides(lyt)) == 1 ); +// } +// } - auto const lyt = sub.layout(); +// BOOST_AUTO_TEST_CASE(multi_layout_part3) { +// { +// multi::layout_t<2> const lyt({10, 1}); +// static_assert(decltype(lyt)::rank_v == 2); +// BOOST_TEST( num_elements(lyt) == 10 ); +// BOOST_TEST( size(lyt) == 10 ); +// using std::get; +// BOOST_TEST( get<0>(strides(lyt)) == 1 ); +// BOOST_TEST( get<1>(strides(lyt)) == 1 ); +// } +// { +// multi::layout_t<2> const lyt{}; +// BOOST_TEST( dimensionality(lyt) == 2 ); +// BOOST_TEST( num_elements(lyt) == 0 ); +// BOOST_TEST( size(lyt) == 0 ); +// BOOST_TEST( size(extension(lyt)) == 0 ); +// BOOST_TEST( stride(lyt) != 0 ); +// BOOST_TEST( is_empty(lyt) ); +// } +// { +// multi::layout_t<3> const lyt{}; +// BOOST_TEST( num_elements(lyt) == 0 ); +// } +// { +// multi::layout_t<3> const lyt({ +// {0, 10}, +// {0, 10}, +// {0, 10}, +// }); +// BOOST_TEST( num_elements(lyt) == 1000 ); +// } +// { +// multi::layout_t<3> const lyt({{10}, {10}, {10}}); +// BOOST_TEST( num_elements(lyt) == 1000 ); +// } +// { +// multi::layout_t<3> const lyt({10, 10, 10}); +// BOOST_TEST( num_elements(lyt) == 1000 ); +// } +// { +// multi::layout_t<3> const lyt({ +// multi::index_extension{0, 10}, +// {0, 10}, +// {0, 10}, +// }); +// BOOST_TEST( num_elements(lyt) == 1000 ); +// } +// { +// multi::layout_t<3> const lyt(multi::layout_t<3>::extensions_type{ +// {0, 10}, +// {0, 10}, +// {0, 10}, +// }); +// BOOST_TEST( num_elements(lyt) == 1000 ); +// } +// } - BOOST_REQUIRE( lyt[0][0][0] == &sub[0][0][0] - base(sub) ); - BOOST_REQUIRE( lyt[0][0][1] == &sub[0][0][1] - base(sub) ); - BOOST_REQUIRE( lyt[0][0][2] == &sub[0][0][2] - base(sub) ); - BOOST_REQUIRE( lyt[0][1][2] == &sub[0][1][2] - base(sub) ); - BOOST_REQUIRE( lyt[3][1][2] == &sub[3][1][2] - base(sub) ); -} +// BOOST_AUTO_TEST_CASE(layout_to_offset) { +// multi::layout_t<3> const lyt({10, 20, 30}); +// multi::array const arr({10, 20, 30}); +// BOOST_TEST( lyt[0][0][0] == &arr[0][0][0] - arr.data_elements() ); +// BOOST_TEST( lyt[0][0][1] == &arr[0][0][1] - arr.data_elements() ); +// BOOST_TEST( lyt[0][0][2] == &arr[0][0][2] - arr.data_elements() ); -BOOST_AUTO_TEST_CASE(continued_part1) { - { - multi::layout_t<3> const lyt(multi::layout_t<3>::extensions_type{ - {0, 10}, - {0, 10}, - {0, 10}, - }); - BOOST_REQUIRE( num_elements(lyt) == 1000); - } - { - multi::layout_t<3> const lyt({ - multi::iextension{0, 10}, - multi::iextension{0, 10}, - multi::iextension{0, 10}, - }); - BOOST_REQUIRE(lyt.num_elements() == 1000); - } - { - multi::layout_t<3> const lyt({multi::iextension{10}, multi::iextension{10}, multi::iextension{10}}); - BOOST_REQUIRE( num_elements(lyt) == 1000); - } - { - multi::layout_t<3> const lyt({10, 10, multi::iextension{10}}); - BOOST_REQUIRE( num_elements(lyt) == 1000 ); - } - { - multi::layout_t<1> const lyt; - BOOST_REQUIRE( size(lyt) == 0 ); - } - { - multi::layout_t<1> lyt({ - {0, 10}, - }); - BOOST_REQUIRE( size(lyt) == 10 ); - BOOST_REQUIRE( extension(lyt).first() == 0 ); - BOOST_REQUIRE( extension(lyt).last () == 10 ); - - lyt.reindex(1); - BOOST_REQUIRE( size(lyt) == 10 ); - BOOST_REQUIRE( extension(lyt).first() == 1 ); - BOOST_REQUIRE( extension(lyt).last () == 11 ); - } - { - multi::layout_t<2> const lyt; - BOOST_REQUIRE( size(lyt) == 0 ); - } - { - multi::layout_t<2> lyt(multi::extensions_t<2>({ - {0, 10}, - {0, 20}, - })); - BOOST_REQUIRE( size(lyt) == 10 ); - BOOST_REQUIRE( extension(lyt).first() == 0 ); - BOOST_REQUIRE( extension(lyt).last () == 10 ); - - lyt.reindex(1); - BOOST_REQUIRE( extension(lyt).first() == 1 ); - BOOST_REQUIRE( extension(lyt).last () == 11 ); - - lyt.rotate().reindex(3).unrotate(); - BOOST_TEST_REQUIRE( extension(lyt).first() == 1 ); - BOOST_TEST_REQUIRE( extension(lyt).last () == 11 ); - - BOOST_TEST_REQUIRE( std::get<0>(extensions(lyt)).first() == 1 ); - BOOST_TEST_REQUIRE( std::get<1>(extensions(lyt)).first() == 3 ); - BOOST_TEST_REQUIRE( std::get<1>(extensions(lyt)).last () == 23 ); - } - // { - // multi::layout_t<2> lyt({ - // {0, 10}, - // {0, 20}, - // }); - // BOOST_REQUIRE( size(lyt) == 10 ); - // } -} +// BOOST_TEST_REQUIRE(lyt[0][1][2] == &arr[0][1][2] - arr.data_elements()); +// BOOST_TEST_REQUIRE(lyt[3][1][2] == &arr[3][1][2] - arr.data_elements()); +// } -BOOST_AUTO_TEST_CASE(continued_part2) { - multi::layout_t<3> const lyt({ - {0, 10}, - {0, 20}, - {0, 30}, - }); +// BOOST_AUTO_TEST_CASE(layout_to_offset_sub) { +// multi::array arr({10, 20, 30}); + +// auto&& sub = arr({2, 6}, {4, 8}, {10, 20}); + +// auto const lyt = sub.layout(); + +// BOOST_TEST( lyt[0][0][0] == &sub[0][0][0] - base(sub) ); +// BOOST_TEST( lyt[0][0][1] == &sub[0][0][1] - base(sub) ); +// BOOST_TEST( lyt[0][0][2] == &sub[0][0][2] - base(sub) ); +// BOOST_TEST( lyt[0][1][2] == &sub[0][1][2] - base(sub) ); +// BOOST_TEST( lyt[3][1][2] == &sub[3][1][2] - base(sub) ); +// } + +// BOOST_AUTO_TEST_CASE(continued_part1) { +// { +// multi::layout_t<3> const lyt(multi::layout_t<3>::extensions_type{ +// {0, 10}, +// {0, 10}, +// {0, 10}, +// }); +// BOOST_TEST( num_elements(lyt) == 1000); +// } +// { +// multi::layout_t<3> const lyt({ +// multi::iextension{0, 10}, +// multi::iextension{0, 10}, +// multi::iextension{0, 10}, +// }); +// BOOST_TEST(lyt.num_elements() == 1000); +// } +// { +// multi::layout_t<3> const lyt({multi::iextension{10}, multi::iextension{10}, multi::iextension{10}}); +// BOOST_TEST( num_elements(lyt) == 1000); +// } +// { +// multi::layout_t<3> const lyt({10, 10, multi::iextension{10}}); +// BOOST_TEST( num_elements(lyt) == 1000 ); +// } +// { +// multi::layout_t<1> const lyt; +// BOOST_TEST( size(lyt) == 0 ); +// } +// { +// multi::layout_t<1> lyt({ +// {0, 10}, +// }); +// BOOST_TEST( size(lyt) == 10 ); +// BOOST_TEST( extension(lyt).first() == 0 ); +// BOOST_TEST( extension(lyt).last () == 10 ); + +// lyt.reindex(1); +// BOOST_TEST( size(lyt) == 10 ); +// BOOST_TEST( extension(lyt).first() == 1 ); +// BOOST_TEST( extension(lyt).last () == 11 ); +// } +// { +// multi::layout_t<2> const lyt; +// BOOST_TEST( size(lyt) == 0 ); +// } +// { +// multi::layout_t<2> lyt(multi::extensions_t<2>({ +// {0, 10}, +// {0, 20}, +// })); +// BOOST_TEST( size(lyt) == 10 ); +// BOOST_TEST( extension(lyt).first() == 0 ); +// BOOST_TEST( extension(lyt).last () == 10 ); + +// lyt.reindex(1); +// BOOST_TEST( extension(lyt).first() == 1 ); +// BOOST_TEST( extension(lyt).last () == 11 ); + +// lyt.rotate().reindex(3).unrotate(); +// BOOST_TEST_REQUIRE( extension(lyt).first() == 1 ); +// BOOST_TEST_REQUIRE( extension(lyt).last () == 11 ); + +// BOOST_TEST_REQUIRE( std::get<0>(extensions(lyt)).first() == 1 ); +// BOOST_TEST_REQUIRE( std::get<1>(extensions(lyt)).first() == 3 ); +// BOOST_TEST_REQUIRE( std::get<1>(extensions(lyt)).last () == 23 ); +// } +// } - BOOST_REQUIRE( ! lyt.empty() ); +// BOOST_AUTO_TEST_CASE(continued_part2) { +// multi::layout_t<3> const lyt({ +// {0, 10}, +// {0, 20}, +// {0, 30}, +// }); - BOOST_REQUIRE( stride(lyt) == lyt.stride() ); - BOOST_REQUIRE( offset(lyt) == lyt.offset() ); - BOOST_REQUIRE( nelems(lyt) == lyt.nelems() ); +// BOOST_TEST( !lyt.empty() ); - BOOST_REQUIRE( stride(lyt) == 20*30L ); - BOOST_REQUIRE( offset(lyt) == 0 ); - BOOST_REQUIRE( nelems(lyt) == 10*20L*30L ); +// BOOST_TEST( stride(lyt) == lyt.stride() ); +// BOOST_TEST( offset(lyt) == lyt.offset() ); +// BOOST_TEST( nelems(lyt) == lyt.nelems() ); - BOOST_REQUIRE( lyt.stride() == stride(lyt) ); - BOOST_REQUIRE( lyt.offset() == offset(lyt) ); - BOOST_REQUIRE( lyt.nelems() == nelems(lyt) ); +// BOOST_TEST( stride(lyt) == 20*30L ); +// BOOST_TEST( offset(lyt) == 0 ); +// BOOST_TEST( nelems(lyt) == 10*20L*30L ); - using boost::multi::detail::get; - BOOST_REQUIRE( get<1>(lyt.strides()) == 30 ); - BOOST_REQUIRE( get<1>(lyt.offsets()) == 0 ); - BOOST_REQUIRE( get<1>(lyt.nelemss()) == 20*30L ); +// BOOST_TEST( lyt.stride() == stride(lyt) ); +// BOOST_TEST( lyt.offset() == offset(lyt) ); +// BOOST_TEST( lyt.nelems() == nelems(lyt) ); - BOOST_REQUIRE( get<2>(lyt.strides()) == 1 ); - BOOST_REQUIRE( get<2>(lyt.offsets()) == 0 ); - BOOST_REQUIRE( get<2>(lyt.nelemss()) == 30 ); -} +// using boost::multi::detail::get; +// BOOST_TEST( get<1>(lyt.strides()) == 30 ); +// BOOST_TEST( get<1>(lyt.offsets()) == 0 ); +// BOOST_TEST( get<1>(lyt.nelemss()) == 20*30L ); -BOOST_AUTO_TEST_CASE(continued_part3) { - multi::layout_t<3> const lyt({ - {0, 10}, - {0, 20}, - {0, 30}, - }); +// BOOST_TEST( get<2>(lyt.strides()) == 1 ); +// BOOST_TEST( get<2>(lyt.offsets()) == 0 ); +// BOOST_TEST( get<2>(lyt.nelemss()) == 30 ); +// } - BOOST_REQUIRE( lyt.num_elements() == num_elements(lyt) ); - BOOST_REQUIRE( lyt.size() == size(lyt) ); - BOOST_REQUIRE( lyt.extension() == extension(lyt) ); +// BOOST_AUTO_TEST_CASE(continued_part3) { +// multi::layout_t<3> const lyt({ +// {0, 10}, +// {0, 20}, +// {0, 30}, +// }); - BOOST_REQUIRE( num_elements(lyt) == 10*20L*30L ); - BOOST_REQUIRE( size(lyt) == 10 ); - BOOST_REQUIRE( extension(lyt).first() == 0 ); - BOOST_REQUIRE( extension(lyt).last() == 10 ); +// BOOST_TEST( lyt.num_elements() == num_elements(lyt) ); +// BOOST_TEST( lyt.size() == size(lyt) ); +// BOOST_TEST( lyt.extension() == extension(lyt) ); - BOOST_REQUIRE( std::get<0>(lyt.extensions()) == lyt.extension() ); +// BOOST_TEST( num_elements(lyt) == 10*20L*30L ); +// BOOST_TEST( size(lyt) == 10 ); +// BOOST_TEST( extension(lyt).first() == 0 ); +// BOOST_TEST( extension(lyt).last() == 10 ); - boost::multi::extensions_t<2> const exts2; +// BOOST_TEST( std::get<0>(lyt.extensions()) == lyt.extension() ); - using boost::multi::detail::get; - using std::get; +// boost::multi::extensions_t<2> const exts2; - BOOST_REQUIRE( get<0>(exts2).is_empty() ); +// using boost::multi::detail::get; +// using std::get; - // BOOST_REQUIRE( std::get<0>(L.sizes()) == L.size(0) ); - // BOOST_REQUIRE( std::get<0>(L.extensions()) == L.extension(0) ); +// BOOST_TEST( get<0>(exts2).is_empty() ); - BOOST_REQUIRE(( get<0>(lyt.extensions()) == multi::index_extension{0, 10} )); +// // BOOST_TEST( std::get<0>(L.sizes()) == L.size(0) ); +// // BOOST_TEST( std::get<0>(L.extensions()) == L.extension(0) ); - BOOST_REQUIRE( get<0>(lyt.extensions()).first() == 0 ); - BOOST_REQUIRE( get<0>(lyt.extensions()).last() == 10 ); +// BOOST_TEST(( get<0>(lyt.extensions()) == multi::index_extension{0, 10} )); - // BOOST_REQUIRE( L.size(1) == 20 ); - BOOST_REQUIRE( get<1>(lyt.extensions()).first() == 0 ); - BOOST_REQUIRE( get<1>(lyt.extensions()).last() == 20 ); +// BOOST_TEST( get<0>(lyt.extensions()).first() == 0 ); +// BOOST_TEST( get<0>(lyt.extensions()).last() == 10 ); - // BOOST_REQUIRE( L.size(2) == 30 ); - BOOST_REQUIRE( get<2>(lyt.extensions()).first() == 0 ); - BOOST_REQUIRE( get<2>(lyt.extensions()).last() == 30 ); +// // BOOST_TEST( L.size(1) == 20 ); +// BOOST_TEST( get<1>(lyt.extensions()).first() == 0 ); +// BOOST_TEST( get<1>(lyt.extensions()).last() == 20 ); - using std::get; - BOOST_REQUIRE( get<0>(strides(lyt)) == lyt.stride() ); +// // BOOST_TEST( L.size(2) == 30 ); +// BOOST_TEST( get<2>(lyt.extensions()).first() == 0 ); +// BOOST_TEST( get<2>(lyt.extensions()).last() == 30 ); - auto const& strides = lyt.strides(); - BOOST_REQUIRE( get<0>(strides) == lyt.stride() ); -} +// using std::get; +// BOOST_TEST( get<0>(strides(lyt)) == lyt.stride() ); -BOOST_AUTO_TEST_CASE(continued) { - { - multi::layout_t<3> const lyt; - BOOST_REQUIRE( size(lyt) == 0 ); - } - { - multi::layout_t<3> const lyt({ - {0, 10}, - {0, 20}, - {0, 30}, - }); - BOOST_REQUIRE( stride(lyt) == 20*30L ); - } - { - multi::layout_t<1> const lyt({ - {0, 10}, - }); - BOOST_REQUIRE( extension(lyt).first() == 0 ); - BOOST_REQUIRE( extension(lyt).last() == 10 ); - } - { - multi::layout_t<1> const lyt({ - {8, 18}, - }); - BOOST_REQUIRE( extension(lyt).first() == 8 ); - BOOST_REQUIRE( extension(lyt).last() == 18 ); - } - { - multi::layout_t<2> const lyt(multi::extensions_t<2>({ - {0, 10}, - {0, 20}, - })); - BOOST_REQUIRE( extension(lyt).first() == 0 ); - BOOST_REQUIRE( extension(lyt).last() == 10 ); - } - // { // this is ambiguous in nvcc - // multi::layout_t<2> const lyt({ - // {0, 10}, - // {0, 20}, - // }); - // BOOST_REQUIRE( extension(lyt).first() == 0 ); - // BOOST_REQUIRE( extension(lyt).last() == 10 ); - // } - { - multi::layout_t<2> const lyt(multi::extensions_t<2>({ - { 0, 10}, - {11, 31}, - })); - BOOST_REQUIRE( size(lyt) == 10 ); - BOOST_REQUIRE( stride(lyt) == 20 ); - BOOST_REQUIRE( offset(lyt) == 0 ); - } - { // this is ambiguous in nvcc - multi::layout_t<2> const lyt(multi::extensions_t<2>({ - { 0, 10}, - {11, 31}, - })); - BOOST_REQUIRE( size(lyt) == 10 ); - BOOST_REQUIRE( stride(lyt) == 20 ); - BOOST_REQUIRE( offset(lyt) == 0 ); - } - { - multi::layout_t<2> const lyt(multi::extensions_t<2>({ - {8, 18}, - {0, 20}, - })); - BOOST_REQUIRE( size(lyt) == 10 ); - BOOST_REQUIRE( stride(lyt) == 20 ); - } - // { - // multi::layout_t<3> const lyt(multi::extensions_t<3>({ - // { 0, 3}, - // { 0, 5}, - // {10, 17}, - // })); - // BOOST_REQUIRE( stride(lyt) == 5*7L ); - // BOOST_REQUIRE( stride(lyt.sub().sub()) == 1 ); - // } - { - multi::layout_t<3> const lyt({ - {0, 10}, - {0, 20}, - {0, 30}, - }); - BOOST_REQUIRE( size(lyt) == 10 ); - BOOST_REQUIRE( stride(lyt) == 20*30L ); - BOOST_REQUIRE( offset(lyt) == 0 ); - BOOST_REQUIRE( nelems(lyt) == 10*20L*30L ); - } - { - multi::layout_t<3> const lyt({ - {10, 20}, - {10, 30}, - {10, 40}, - }); - BOOST_REQUIRE( stride(lyt) == 20*30L ); - } - { - auto const ttt = boost::multi::tuple{1, 2, 3}; - auto const arr = std::apply([](auto... elems) { return std::array{{elems...}}; }, ttt); - BOOST_REQUIRE(arr[1] == 2); - } -} +// auto const& strides = lyt.strides(); +// BOOST_TEST( get<0>(strides) == lyt.stride() ); +// } -// BOOST_AUTO_TEST_CASE(tuple_zip_test) { // TODO(correaa) make it work -// auto t1 = std::make_tuple( 1, 2, 3); -// auto t2 = std::make_tuple(10, 20, 30); -// auto t3 = std::make_tuple(std::string{"10"}, std::string{"20"}, std::string{"30"}); -// auto t123 = boost::multi::detail::tuple_zip(t1, t2, t3); -// BOOST_REQUIRE( std::get<2>(std::get<0>(t123)) == std::string{"10"} ); +// BOOST_AUTO_TEST_CASE(continued) { +// { +// multi::layout_t<3> const lyt; +// BOOST_TEST( size(lyt) == 0 ); +// } +// { +// multi::layout_t<3> const lyt({ +// {0, 10}, +// {0, 20}, +// {0, 30}, +// }); +// BOOST_TEST( stride(lyt) == 20*30L ); +// } +// { +// multi::layout_t<1> const lyt({ +// {0, 10}, +// }); +// BOOST_TEST( extension(lyt).first() == 0 ); +// BOOST_TEST( extension(lyt).last() == 10 ); +// } +// { +// multi::layout_t<1> const lyt({ +// {8, 18}, +// }); +// BOOST_TEST( extension(lyt).first() == 8 ); +// BOOST_TEST( extension(lyt).last() == 18 ); +// } +// { +// multi::layout_t<2> const lyt(multi::extensions_t<2>({ +// {0, 10}, +// {0, 20}, +// })); +// BOOST_TEST( extension(lyt).first() == 0 ); +// BOOST_TEST( extension(lyt).last() == 10 ); +// } +// // { // this is ambiguous in nvcc +// // multi::layout_t<2> const lyt({ +// // {0, 10}, +// // {0, 20}, +// // }); +// // BOOST_TEST( extension(lyt).first() == 0 ); +// // BOOST_TEST( extension(lyt).last() == 10 ); +// // } +// { +// multi::layout_t<2> const lyt(multi::extensions_t<2>({ +// { 0, 10}, +// {11, 31}, +// })); +// BOOST_TEST( size(lyt) == 10 ); +// BOOST_TEST( stride(lyt) == 20 ); +// BOOST_TEST( offset(lyt) == 0 ); +// } +// { // this is ambiguous in nvcc +// multi::layout_t<2> const lyt(multi::extensions_t<2>({ +// { 0, 10}, +// {11, 31}, +// })); +// BOOST_TEST( size(lyt) == 10 ); +// BOOST_TEST( stride(lyt) == 20 ); +// BOOST_TEST( offset(lyt) == 0 ); // } +// { +// multi::layout_t<2> const lyt(multi::extensions_t<2>({ +// {8, 18}, +// {0, 20}, +// })); +// BOOST_TEST( size(lyt) == 10 ); +// BOOST_TEST( stride(lyt) == 20 ); +// } +// // { +// // multi::layout_t<3> const lyt(multi::extensions_t<3>({ +// // { 0, 3}, +// // { 0, 5}, +// // {10, 17}, +// // })); +// // BOOST_TEST( stride(lyt) == 5*7L ); +// // BOOST_TEST( stride(lyt.sub().sub()) == 1 ); +// // } +// { +// multi::layout_t<3> const lyt({ +// {0, 10}, +// {0, 20}, +// {0, 30}, +// }); +// BOOST_TEST( size(lyt) == 10 ); +// BOOST_TEST( stride(lyt) == 20*30L ); +// BOOST_TEST( offset(lyt) == 0 ); +// BOOST_TEST( nelems(lyt) == 10*20L*30L ); +// } +// { +// multi::layout_t<3> const lyt({ +// {10, 20}, +// {10, 30}, +// {10, 40}, +// }); +// BOOST_TEST( stride(lyt) == 20*30L ); +// } +// { +// auto const ttt = boost::multi::tuple{1, 2, 3}; +// auto const arr = std::apply([](auto... elems) { return std::array{{elems...}}; }, ttt); +// BOOST_TEST(arr[1] == 2); +// } +// } -BOOST_AUTO_TEST_CASE(extensions_from_linear_1d) { - multi::extensions_t<1> const exts{11}; +// BOOST_AUTO_TEST_CASE(extensions_from_linear_1d) { +// multi::extensions_t<1> const exts{11}; - auto ijk = exts.from_linear(9); +// auto ijk = exts.from_linear(9); - using multi::detail::get; - BOOST_TEST_REQUIRE( get<0>(ijk) == 9 ); +// using multi::detail::get; +// BOOST_TEST_REQUIRE( get<0>(ijk) == 9 ); - multi::layout_t<1> const lyt{exts}; - BOOST_TEST_REQUIRE( lyt[get<0>(ijk)] == 9 ); - BOOST_TEST_REQUIRE( lyt(get<0>(ijk)) == 9 ); +// multi::layout_t<1> const lyt{exts}; +// BOOST_TEST_REQUIRE( lyt[get<0>(ijk)] == 9 ); +// BOOST_TEST_REQUIRE( lyt(get<0>(ijk)) == 9 ); - BOOST_TEST_REQUIRE( lyt(std::get<0>(lyt.extensions().from_linear(9))) == 9 ); +// BOOST_TEST_REQUIRE( lyt(std::get<0>(lyt.extensions().from_linear(9))) == 9 ); - BOOST_TEST_REQUIRE( std::apply(lyt, lyt.extensions().from_linear(9)) == 9 ); -} +// BOOST_TEST_REQUIRE( std::apply(lyt, lyt.extensions().from_linear(9)) == 9 ); +// } -BOOST_AUTO_TEST_CASE(extensions_from_linear_2d_structured_binding) { - multi::extensions_t<2> const exts{3, 5}; - auto [eye, jay] = exts.from_linear(7); +// BOOST_AUTO_TEST_CASE(extensions_from_linear_2d_structured_binding) { +// multi::extensions_t<2> const exts{3, 5}; +// auto [eye, jay] = exts.from_linear(7); - BOOST_TEST_REQUIRE( eye == 1 ); - BOOST_TEST_REQUIRE( jay == 2 ); - // BOOST_TEST_REQUIRE( std::apply(l, l.extensions().from_linear(9)) == 9 ); -} +// BOOST_TEST_REQUIRE( eye == 1 ); +// BOOST_TEST_REQUIRE( jay == 2 ); +// // BOOST_TEST_REQUIRE( std::apply(l, l.extensions().from_linear(9)) == 9 ); +// } -BOOST_AUTO_TEST_CASE(extensions_from_linear_2d_std_get) { - multi::extensions_t<2> const exts{3, 5}; - auto eye = std::get<0>(exts.from_linear(7)); - auto jay = std::get<1>(exts.from_linear(7)); - BOOST_TEST_REQUIRE( eye == 1 ); - BOOST_TEST_REQUIRE( jay == 2 ); -} +// BOOST_AUTO_TEST_CASE(extensions_from_linear_2d_std_get) { +// multi::extensions_t<2> const exts{3, 5}; +// auto eye = std::get<0>(exts.from_linear(7)); +// auto jay = std::get<1>(exts.from_linear(7)); +// BOOST_TEST_REQUIRE( eye == 1 ); +// BOOST_TEST_REQUIRE( jay == 2 ); +// } -BOOST_AUTO_TEST_CASE(extensions_from_linear_2d_std_get_using) { - multi::extensions_t<2> const exts{3, 5}; - using std::get; - auto fl = exts.from_linear(7L); - auto const eye = get<0>(fl); - auto const jay = get<1>(fl); - BOOST_TEST_REQUIRE( eye == 1 ); - BOOST_TEST_REQUIRE( jay == 2 ); -} +// BOOST_AUTO_TEST_CASE(extensions_from_linear_2d_std_get_using) { +// multi::extensions_t<2> const exts{3, 5}; +// using std::get; +// auto fl = exts.from_linear(7L); +// auto const eye = get<0>(fl); +// auto const jay = get<1>(fl); +// BOOST_TEST_REQUIRE( eye == 1 ); +// BOOST_TEST_REQUIRE( jay == 2 ); +// } -BOOST_AUTO_TEST_CASE(extensions_from_linear_2d_get_using) { - multi::extensions_t<2> const exts{3, 5}; +// BOOST_AUTO_TEST_CASE(extensions_from_linear_2d_get_using) { +// multi::extensions_t<2> const exts{3, 5}; - using multi::detail::get; +// using multi::detail::get; - auto eye = get<0>(exts.from_linear(7)); - auto jay = get<1>(exts.from_linear(7)); - BOOST_TEST_REQUIRE( eye == 1 ); - BOOST_TEST_REQUIRE( jay == 2 ); -} +// auto eye = get<0>(exts.from_linear(7)); +// auto jay = get<1>(exts.from_linear(7)); +// BOOST_TEST_REQUIRE( eye == 1 ); +// BOOST_TEST_REQUIRE( jay == 2 ); +// } -BOOST_AUTO_TEST_CASE(extensions_from_linear_2d) { - multi::extensions_t<2> const exts{3, 5}; +// BOOST_AUTO_TEST_CASE(extensions_from_linear_2d) { +// multi::extensions_t<2> const exts{3, 5}; - auto ij = exts.from_linear(7); +// auto ij = exts.from_linear(7); - using multi::detail::get; +// using multi::detail::get; - BOOST_TEST_REQUIRE( get<0>(ij) == 1 ); - BOOST_TEST_REQUIRE( get<1>(ij) == 2 ); +// BOOST_TEST_REQUIRE( get<0>(ij) == 1 ); +// BOOST_TEST_REQUIRE( get<1>(ij) == 2 ); - multi::layout_t<2> const lyt{exts}; - BOOST_TEST_REQUIRE( lyt[get<0>(ij)][get<1>(ij)] == 7 ); -} +// multi::layout_t<2> const lyt{exts}; +// BOOST_TEST_REQUIRE( lyt[get<0>(ij)][get<1>(ij)] == 7 ); +// } -BOOST_AUTO_TEST_CASE(extensions_from_linear_3d_std_get) { - multi::extensions_t<3> const exts{11, 13, 17}; +// BOOST_AUTO_TEST_CASE(extensions_from_linear_3d_std_get) { +// multi::extensions_t<3> const exts{11, 13, 17}; - BOOST_TEST_REQUIRE( std::get<0>(exts.from_linear( 0)) == 0 ); - BOOST_TEST_REQUIRE( std::get<1>(exts.from_linear( 0)) == 0 ); - BOOST_TEST_REQUIRE( std::get<2>(exts.from_linear( 0)) == 0 ); +// BOOST_TEST_REQUIRE( std::get<0>(exts.from_linear( 0)) == 0 ); +// BOOST_TEST_REQUIRE( std::get<1>(exts.from_linear( 0)) == 0 ); +// BOOST_TEST_REQUIRE( std::get<2>(exts.from_linear( 0)) == 0 ); - BOOST_TEST_REQUIRE( std::get<0>(exts.from_linear( 1)) == 0 ); - BOOST_TEST_REQUIRE( std::get<1>(exts.from_linear( 1)) == 0 ); - BOOST_TEST_REQUIRE( std::get<2>(exts.from_linear( 1)) == 1 ); +// BOOST_TEST_REQUIRE( std::get<0>(exts.from_linear( 1)) == 0 ); +// BOOST_TEST_REQUIRE( std::get<1>(exts.from_linear( 1)) == 0 ); +// BOOST_TEST_REQUIRE( std::get<2>(exts.from_linear( 1)) == 1 ); - BOOST_TEST_REQUIRE( std::get<0>(exts.from_linear(16)) == 0 ); - BOOST_TEST_REQUIRE( std::get<1>(exts.from_linear(16)) == 0 ); - BOOST_TEST_REQUIRE( std::get<2>(exts.from_linear(16)) == 16 ); +// BOOST_TEST_REQUIRE( std::get<0>(exts.from_linear(16)) == 0 ); +// BOOST_TEST_REQUIRE( std::get<1>(exts.from_linear(16)) == 0 ); +// BOOST_TEST_REQUIRE( std::get<2>(exts.from_linear(16)) == 16 ); - BOOST_TEST_REQUIRE( std::get<0>(exts.from_linear(17)) == 0 ); - BOOST_TEST_REQUIRE( std::get<1>(exts.from_linear(17)) == 1 ); - BOOST_TEST_REQUIRE( std::get<2>(exts.from_linear(17)) == 0 ); +// BOOST_TEST_REQUIRE( std::get<0>(exts.from_linear(17)) == 0 ); +// BOOST_TEST_REQUIRE( std::get<1>(exts.from_linear(17)) == 1 ); +// BOOST_TEST_REQUIRE( std::get<2>(exts.from_linear(17)) == 0 ); - BOOST_TEST_REQUIRE( std::get<0>(exts.from_linear(18)) == 0 ); - BOOST_TEST_REQUIRE( std::get<1>(exts.from_linear(18)) == 1 ); - BOOST_TEST_REQUIRE( std::get<2>(exts.from_linear(18)) == 1 ); +// BOOST_TEST_REQUIRE( std::get<0>(exts.from_linear(18)) == 0 ); +// BOOST_TEST_REQUIRE( std::get<1>(exts.from_linear(18)) == 1 ); +// BOOST_TEST_REQUIRE( std::get<2>(exts.from_linear(18)) == 1 ); - multi::layout_t<3> const lyt{exts}; +// multi::layout_t<3> const lyt{exts}; - using std::get; - BOOST_TEST_REQUIRE( lyt[get<0>(exts.from_linear(19))][get<1>(exts.from_linear(19))][get<2>(exts.from_linear(19))] == 19 ); - BOOST_TEST_REQUIRE( lyt(get<0>(exts.from_linear(19)), get<1>(exts.from_linear(19)), get<2>(exts.from_linear(19))) == 19 ); -} +// using std::get; +// BOOST_TEST_REQUIRE( lyt[get<0>(exts.from_linear(19))][get<1>(exts.from_linear(19))][get<2>(exts.from_linear(19))] == 19 ); +// BOOST_TEST_REQUIRE( lyt(get<0>(exts.from_linear(19)), get<1>(exts.from_linear(19)), get<2>(exts.from_linear(19))) == 19 ); +// } -BOOST_AUTO_TEST_CASE(extensions_from_linear_3d_std_get_using) { - multi::extensions_t<3> const exts{11, 13, 17}; +// BOOST_AUTO_TEST_CASE(extensions_from_linear_3d_std_get_using) { +// multi::extensions_t<3> const exts{11, 13, 17}; - using std::get; +// using std::get; - BOOST_TEST_REQUIRE( get<0>(exts.from_linear( 0)) == 0 ); - BOOST_TEST_REQUIRE( get<1>(exts.from_linear( 0)) == 0 ); - BOOST_TEST_REQUIRE( get<2>(exts.from_linear( 0)) == 0 ); +// BOOST_TEST_REQUIRE( get<0>(exts.from_linear( 0)) == 0 ); +// BOOST_TEST_REQUIRE( get<1>(exts.from_linear( 0)) == 0 ); +// BOOST_TEST_REQUIRE( get<2>(exts.from_linear( 0)) == 0 ); - BOOST_TEST_REQUIRE( get<0>(exts.from_linear( 1)) == 0 ); - BOOST_TEST_REQUIRE( get<1>(exts.from_linear( 1)) == 0 ); - BOOST_TEST_REQUIRE( get<2>(exts.from_linear( 1)) == 1 ); +// BOOST_TEST_REQUIRE( get<0>(exts.from_linear( 1)) == 0 ); +// BOOST_TEST_REQUIRE( get<1>(exts.from_linear( 1)) == 0 ); +// BOOST_TEST_REQUIRE( get<2>(exts.from_linear( 1)) == 1 ); - BOOST_TEST_REQUIRE( get<0>(exts.from_linear(16)) == 0 ); - BOOST_TEST_REQUIRE( get<1>(exts.from_linear(16)) == 0 ); - BOOST_TEST_REQUIRE( get<2>(exts.from_linear(16)) == 16 ); +// BOOST_TEST_REQUIRE( get<0>(exts.from_linear(16)) == 0 ); +// BOOST_TEST_REQUIRE( get<1>(exts.from_linear(16)) == 0 ); +// BOOST_TEST_REQUIRE( get<2>(exts.from_linear(16)) == 16 ); - BOOST_TEST_REQUIRE( get<0>(exts.from_linear(17)) == 0 ); - BOOST_TEST_REQUIRE( get<1>(exts.from_linear(17)) == 1 ); - BOOST_TEST_REQUIRE( get<2>(exts.from_linear(17)) == 0 ); +// BOOST_TEST_REQUIRE( get<0>(exts.from_linear(17)) == 0 ); +// BOOST_TEST_REQUIRE( get<1>(exts.from_linear(17)) == 1 ); +// BOOST_TEST_REQUIRE( get<2>(exts.from_linear(17)) == 0 ); - BOOST_TEST_REQUIRE( get<0>(exts.from_linear(18)) == 0 ); - BOOST_TEST_REQUIRE( get<1>(exts.from_linear(18)) == 1 ); - BOOST_TEST_REQUIRE( get<2>(exts.from_linear(18)) == 1 ); +// BOOST_TEST_REQUIRE( get<0>(exts.from_linear(18)) == 0 ); +// BOOST_TEST_REQUIRE( get<1>(exts.from_linear(18)) == 1 ); +// BOOST_TEST_REQUIRE( get<2>(exts.from_linear(18)) == 1 ); - BOOST_TEST_REQUIRE( get<0>(exts.from_linear(19)) == 0 ); - BOOST_TEST_REQUIRE( get<1>(exts.from_linear(19)) == 1 ); - BOOST_TEST_REQUIRE( get<2>(exts.from_linear(19)) == 2 ); +// BOOST_TEST_REQUIRE( get<0>(exts.from_linear(19)) == 0 ); +// BOOST_TEST_REQUIRE( get<1>(exts.from_linear(19)) == 1 ); +// BOOST_TEST_REQUIRE( get<2>(exts.from_linear(19)) == 2 ); - multi::layout_t<3> const lyt{exts}; - BOOST_TEST_REQUIRE( lyt[get<0>(exts.from_linear(19))][get<1>(exts.from_linear(19))][get<2>(exts.from_linear(19))] == 19 ); - BOOST_TEST_REQUIRE( lyt(get<0>(exts.from_linear(19)), get<1>(exts.from_linear(19)), get<2>(exts.from_linear(19))) == 19 ); -} +// multi::layout_t<3> const lyt{exts}; +// BOOST_TEST_REQUIRE( lyt[get<0>(exts.from_linear(19))][get<1>(exts.from_linear(19))][get<2>(exts.from_linear(19))] == 19 ); +// BOOST_TEST_REQUIRE( lyt(get<0>(exts.from_linear(19)), get<1>(exts.from_linear(19)), get<2>(exts.from_linear(19))) == 19 ); +// } -BOOST_AUTO_TEST_CASE(extensions_from_linear_3d_struct_bind) { - multi::extensions_t<3> const exts{11, 13, 17}; +// BOOST_AUTO_TEST_CASE(extensions_from_linear_3d_struct_bind) { +// multi::extensions_t<3> const exts{11, 13, 17}; - using std::get; - { - auto [eye, jay, kay] = exts.from_linear(0); - BOOST_TEST_REQUIRE(eye == 0); - BOOST_TEST_REQUIRE(jay == 0); - BOOST_TEST_REQUIRE(kay == 0); - } - { - auto [eye, jay, kay] = exts.from_linear(1); - BOOST_TEST_REQUIRE(eye == 0); - BOOST_TEST_REQUIRE(jay == 0); - BOOST_TEST_REQUIRE(kay == 1); - } - { - auto [eye, jay, kay] = exts.from_linear(16); - BOOST_TEST_REQUIRE(eye == 0); - BOOST_TEST_REQUIRE(jay == 0); - BOOST_TEST_REQUIRE(kay == 16); - } - { - auto [eye, jay, kay] = exts.from_linear(17); - BOOST_TEST_REQUIRE(eye == 0); - BOOST_TEST_REQUIRE(jay == 1); - BOOST_TEST_REQUIRE(kay == 0); - } - { - auto [eye, jay, kay] = exts.from_linear(18); - BOOST_TEST_REQUIRE(eye == 0); - BOOST_TEST_REQUIRE(jay == 1); - BOOST_TEST_REQUIRE(kay == 1); - - multi::layout_t<3> const lyt{exts}; - BOOST_TEST_REQUIRE(lyt[eye][jay][kay] == 18); - BOOST_TEST_REQUIRE(lyt(eye, jay, kay) == 18); - } -} +// using std::get; +// { +// auto [eye, jay, kay] = exts.from_linear(0); +// BOOST_TEST_REQUIRE(eye == 0); +// BOOST_TEST_REQUIRE(jay == 0); +// BOOST_TEST_REQUIRE(kay == 0); +// } +// { +// auto [eye, jay, kay] = exts.from_linear(1); +// BOOST_TEST_REQUIRE(eye == 0); +// BOOST_TEST_REQUIRE(jay == 0); +// BOOST_TEST_REQUIRE(kay == 1); +// } +// { +// auto [eye, jay, kay] = exts.from_linear(16); +// BOOST_TEST_REQUIRE(eye == 0); +// BOOST_TEST_REQUIRE(jay == 0); +// BOOST_TEST_REQUIRE(kay == 16); +// } +// { +// auto [eye, jay, kay] = exts.from_linear(17); +// BOOST_TEST_REQUIRE(eye == 0); +// BOOST_TEST_REQUIRE(jay == 1); +// BOOST_TEST_REQUIRE(kay == 0); +// } +// { +// auto [eye, jay, kay] = exts.from_linear(18); +// BOOST_TEST_REQUIRE(eye == 0); +// BOOST_TEST_REQUIRE(jay == 1); +// BOOST_TEST_REQUIRE(kay == 1); + +// multi::layout_t<3> const lyt{exts}; +// BOOST_TEST_REQUIRE(lyt[eye][jay][kay] == 18); +// BOOST_TEST_REQUIRE(lyt(eye, jay, kay) == 18); +// } +// } -BOOST_AUTO_TEST_CASE(extensions_from_linear_3d) { - multi::extensions_t<3> const exts{11, 13, 17}; +// BOOST_AUTO_TEST_CASE(extensions_from_linear_3d) { +// multi::extensions_t<3> const exts{11, 13, 17}; - auto ijk = exts.from_linear(19); +// auto ijk = exts.from_linear(19); - { - using std::get; - BOOST_TEST_REQUIRE(get<0>(exts.from_linear(19)) == 0); - BOOST_TEST_REQUIRE(get<1>(exts.from_linear(19)) == 1); - BOOST_TEST_REQUIRE(get<2>(exts.from_linear(19)) == 2); - } - { - using std::get; - // using multi::detail::get; - BOOST_TEST_REQUIRE(get<0>(ijk) == 0); - BOOST_TEST_REQUIRE(get<1>(ijk) == 1); - BOOST_TEST_REQUIRE(get<2>(ijk) == 2); +// { +// using std::get; +// BOOST_TEST_REQUIRE(get<0>(exts.from_linear(19)) == 0); +// BOOST_TEST_REQUIRE(get<1>(exts.from_linear(19)) == 1); +// BOOST_TEST_REQUIRE(get<2>(exts.from_linear(19)) == 2); +// } +// { +// using std::get; +// // using multi::detail::get; +// BOOST_TEST_REQUIRE(get<0>(ijk) == 0); +// BOOST_TEST_REQUIRE(get<1>(ijk) == 1); +// BOOST_TEST_REQUIRE(get<2>(ijk) == 2); - multi::layout_t<3> const lyt{exts}; +// multi::layout_t<3> const lyt{exts}; - BOOST_TEST_REQUIRE(lyt[get<0>(ijk)][get<1>(ijk)][get<2>(ijk)] == 19); - BOOST_TEST_REQUIRE(lyt(get<0>(ijk), get<1>(ijk), get<2>(ijk)) == 19); - } -} +// BOOST_TEST_REQUIRE(lyt[get<0>(ijk)][get<1>(ijk)][get<2>(ijk)] == 19); +// BOOST_TEST_REQUIRE(lyt(get<0>(ijk), get<1>(ijk), get<2>(ijk)) == 19); +// } +// } -BOOST_AUTO_TEST_CASE(extension_1D_iteration) { - multi::extension_t const ext(10); - BOOST_TEST_REQUIRE(ext[0] == 0); - BOOST_TEST_REQUIRE(ext[1] == 1); -} +// BOOST_AUTO_TEST_CASE(extension_1D_iteration) { +// multi::extension_t const ext(10); +// BOOST_TEST_REQUIRE(ext[0] == 0); +// BOOST_TEST_REQUIRE(ext[1] == 1); +// } -BOOST_AUTO_TEST_CASE(extensionS_1D_iteration) { - { - multi::extensions_t<1> const exts(10); - BOOST_TEST_REQUIRE(std::get<0>(exts[0]) == 0); - BOOST_TEST_REQUIRE(std::get<0>(exts[1]) == 1); - } - { - multi::extensions_t<1> const exts(multi::iextension{0, 10}); - BOOST_TEST_REQUIRE(std::get<0>(exts[0]) == 0); - BOOST_TEST_REQUIRE(std::get<0>(exts[1]) == 1); - } -} +// BOOST_AUTO_TEST_CASE(extensionS_1D_iteration) { +// { +// multi::extensions_t<1> const exts(10); +// BOOST_TEST_REQUIRE(std::get<0>(exts[0]) == 0); +// BOOST_TEST_REQUIRE(std::get<0>(exts[1]) == 1); +// } +// { +// multi::extensions_t<1> const exts(multi::iextension{0, 10}); +// BOOST_TEST_REQUIRE(std::get<0>(exts[0]) == 0); +// BOOST_TEST_REQUIRE(std::get<0>(exts[1]) == 1); +// } +// } // BOOST_AUTO_TEST_CASE(extensionS_2D_iteration) { // { @@ -1022,35 +1044,29 @@ BOOST_AUTO_TEST_CASE(extensionS_1D_iteration) { // } // } -BOOST_AUTO_TEST_CASE(layout_1D_iteration) { - multi::layout_t<1> const lyt{multi::extensions_t<1>(10)}; - BOOST_REQUIRE( lyt[0] == 0 ); - BOOST_REQUIRE( lyt[1] == 1 ); - BOOST_REQUIRE( lyt[2] == 2 ); +// BOOST_AUTO_TEST_CASE(layout_1D_iteration) { +// multi::layout_t<1> const lyt{multi::extensions_t<1>(10)}; +// BOOST_TEST( lyt[0] == 0 ); +// BOOST_TEST( lyt[1] == 1 ); +// BOOST_TEST( lyt[2] == 2 ); - // BOOST_TEST_REQUIRE(std::get<0>(exts[0]) == 0); - // BOOST_TEST_REQUIRE(std::get<0>(exts[1]) == 1); -} - -BOOST_AUTO_TEST_CASE(layout_2D_iteration) { - multi::layout_t<2> const lyt{multi::extensions_t<2>({5, 3})}; - BOOST_REQUIRE( lyt[0][0] == 0 ); - BOOST_REQUIRE( lyt[0][1] == 1 ); - BOOST_REQUIRE( lyt[0][2] == 2 ); +// // BOOST_TEST_REQUIRE(std::get<0>(exts[0]) == 0); +// // BOOST_TEST_REQUIRE(std::get<0>(exts[1]) == 1); +// } - BOOST_REQUIRE( lyt[1][0] == 3 ); - BOOST_REQUIRE( lyt[1][1] == 4 ); - BOOST_REQUIRE( lyt[1][2] == 5 ); +// BOOST_AUTO_TEST_CASE(layout_2D_iteration) { +// multi::layout_t<2> const lyt{multi::extensions_t<2>({5, 3})}; +// BOOST_TEST( lyt[0][0] == 0 ); +// BOOST_TEST( lyt[0][1] == 1 ); +// BOOST_TEST( lyt[0][2] == 2 ); - // BOOST_TEST_REQUIRE(std::get<0>(exts[0]) == 0); - // BOOST_TEST_REQUIRE(std::get<0>(exts[1]) == 1); -} +// BOOST_TEST( lyt[1][0] == 3 ); +// BOOST_TEST( lyt[1][1] == 4 ); +// BOOST_TEST( lyt[1][2] == 5 ); -#else +// // BOOST_TEST_REQUIRE(std::get<0>(exts[0]) == 0); +// // BOOST_TEST_REQUIRE(std::get<0>(exts[1]) == 1); +// } -int main() -{ - return 0; +return boost::report_errors(); } - -#endif diff --git a/external_codes/boost_multi/multi/test/member_array_cast.cpp b/external_codes/boost_multi/multi/test/member_array_cast.cpp index a9a4afd944..720753a326 100644 --- a/external_codes/boost_multi/multi/test/member_array_cast.cpp +++ b/external_codes/boost_multi/multi/test/member_array_cast.cpp @@ -3,206 +3,217 @@ // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt -#include +#include // for array, transform_ptr, static_array + +// IWYU pragma: no_include // for equal // bug in iwyu 14.0.6? with GNU stdlib +// IWYU pragma: no_include // for addressof // bug in iwyu 14.0.6? with GNU stdlib +#include // for array, operator== +#include // for offsetof, size_t +#include // for mem_fn // IWYU pragma: keep +#include // for size +#include // for addressof // IWYU pragma: keep +#include // for operator""s, allocator, char_traits +#include // for tie, operator==, tuple -#include - -// Suppress warnings from boost.test #if defined(__clang__) -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wold-style-cast" -# pragma clang diagnostic ignored "-Wundef" -# pragma clang diagnostic ignored "-Wconversion" -# pragma clang diagnostic ignored "-Wsign-conversion" -#elif defined(__GNUC__) -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wold-style-cast" -# pragma GCC diagnostic ignored "-Wundef" -# pragma GCC diagnostic ignored "-Wconversion" -# pragma GCC diagnostic ignored "-Wsign-conversion" + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wunknown-warning-option" + #pragma clang diagnostic ignored "-Winvalid-offsetof" // Explicit padding, for particle example #elif defined(_MSC_VER) -# pragma warning(push) -# pragma warning(disable : 4324) // Explicit padding required -#endif - -#ifndef BOOST_TEST_MODULE -# define BOOST_TEST_MAIN + #pragma warning(push) + #pragma warning(disable : 4324) // Explicit padding, for particle example #endif -#include - namespace multi = boost::multi; -BOOST_AUTO_TEST_CASE(member_array_cast_soa_aos) { - using v3d = std::array; - - // some members might need explicit padding to work well with member_cast - struct particle { - int mass; - v3d position alignas(2 * sizeof(double)); // __attribute__((aligned(2*sizeof(double)))) - }; - - class particles_soa { - multi::array masses_; - multi::array positions_; - - public: // NOLINT(whitespace/indent) nested class - // NOLINTNEXTLINE(runtime/explicit) - explicit particles_soa(multi::array const& AoS) // NOLINT(google-explicit-constructor,hicpp-explicit-conversions) : particle_soa can represent a particles' AoS - : masses_{AoS.member_cast(&particle::mass)}, positions_{AoS.member_cast(&particle::position)} {} +#include +#define BOOST_AUTO_TEST_CASE(CasenamE) /**/ - struct reference { // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions) // NOSONAR - int& mass; // NOLINT(misc-non-private-member-variables-in-classes,cppcoreguidelines-avoid-const-or-ref-data-members) exposed by design - v3d& position; // NOLINT(misc-non-private-member-variables-in-classes,cppcoreguidelines-avoid-const-or-ref-data-members) exposed by design +auto main() -> int { // NOLINT(readability-function-cognitive-complexity,bugprone-exception-escape) + BOOST_AUTO_TEST_CASE(member_array_cast_soa_aos) { + using v3d = std::array; - operator particle() const { return {mass, position}; } // NOLINT(google-explicit-constructor, hicpp-explicit-conversions) // NOSONAR(cpp:S1709) allow direct assignment - auto operator+() const { return operator particle(); } - - reference(int& mss, v3d& pos) : mass{mss}, position{pos} {} // NOLINT(google-runtime-references) - // unused: explicit reference(particle& other) : reference{other.mass, other.position} {} + // some members might need explicit padding to work well with member_cast + struct particle { + int mass; + v3d position alignas(2 * sizeof(double)); // __attribute__((aligned(2*sizeof(double)))) + }; - private: // NOLINT(whitespace/indent) nested class - friend class particles_soa; + class particles_soa { + multi::array masses_; + multi::array positions_; public: // NOLINT(whitespace/indent) nested class - auto operator=(reference const& other) && -> reference& { - if(this == std::addressof(other)) { + // NOLINT(google-explicit-constructor,hicpp-explicit-conversions) : particle_soa can represent a particles' AoS + explicit particles_soa(multi::array const& AoS) // NOLINTNEXTLINE(runtime/explicit) + : masses_{AoS.member_cast(&particle::mass)}, positions_{AoS.member_cast(&particle::position)} {} + + // NOLINTNEXTLINE(cppcoreguidelines-special-member-functions,hicpp-special-member-functions) // NOSONAR + struct reference { + int& mass; // NOLINT(misc-non-private-member-variables-in-classes,cppcoreguidelines-avoid-const-or-ref-data-members) exposed by design + v3d& position; // NOLINT(misc-non-private-member-variables-in-classes,cppcoreguidelines-avoid-const-or-ref-data-members) exposed by design + + // NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions) + operator particle() const { return {mass, position}; } // NOSONAR(cpp:S1709) allow direct assignment + auto operator+() const { return operator particle(); } + + reference(int& mss, v3d& pos) : mass{mss}, position{pos} {} // NOLINT(google-runtime-references) + // unused: explicit reference(particle& other) : reference{other.mass, other.position} {} + + private: // NOLINT(whitespace/indent) nested class + friend class particles_soa; + + public: // NOLINT(whitespace/indent) nested class + auto operator=(reference const& other) && -> reference& { + if(this == std::addressof(other)) { + return *this; + } + std::tie(mass, position) = std::tie(other.mass, other.position); return *this; } - std::tie(mass, position) = std::tie(other.mass, other.position); - return *this; - } - auto operator==(reference const& other) const { return std::tie(mass, position) == std::tie(other.mass, other.position); } - auto operator!=(reference const& other) const { return std::tie(mass, position) != std::tie(other.mass, other.position); } + auto operator==(reference const& other) const { return std::tie(mass, position) == std::tie(other.mass, other.position); } + auto operator!=(reference const& other) const { return std::tie(mass, position) != std::tie(other.mass, other.position); } + }; + + auto operator()(int eye, int jay) { return reference{masses_[eye][jay], positions_[eye][jay]}; } }; - auto operator()(int eye, int jay) { return reference{masses_[eye][jay], positions_[eye][jay]}; } - }; + multi::array AoS({2, 2}, particle{}); + AoS[1][1] = particle{99, v3d{{1.0, 2.0}}}; - multi::array AoS({2, 2}, particle{}); - AoS[1][1] = particle{99, v3d{{1.0, 2.0}}}; + auto&& masses = AoS.member_cast(&particle::mass); + BOOST_TEST(size(masses) == 2); + BOOST_TEST(masses[1][1] == 99 ); - auto&& masses = AoS.member_cast(&particle::mass); - BOOST_REQUIRE(size(masses) == 2); - BOOST_REQUIRE(masses[1][1] == 99 ); + multi::array masses_copy{masses}; + BOOST_TEST(&masses_copy[1][1] != &masses[1][1]); - multi::array masses_copy = masses; - BOOST_REQUIRE(&masses_copy[1][1] != &masses[1][1]); + particles_soa SoA{AoS}; - particles_soa SoA{AoS}; + BOOST_TEST( SoA(1, 1).mass == 99 ); - BOOST_REQUIRE( SoA(1, 1).mass == 99 ); + particle const p11 = SoA(1, 1); + BOOST_TEST(p11.mass == 99 ); - particle const p11 = SoA(1, 1); - BOOST_REQUIRE(p11.mass == 99 ); + auto autop11 = +SoA(1, 1); + BOOST_TEST(autop11.mass == 99 ); - auto autop11 = +SoA(1, 1); - BOOST_REQUIRE(autop11.mass == 99 ); + SoA(1, 1).mass = 88; + BOOST_TEST( SoA(1, 1).mass == 88 ); - SoA(1, 1).mass = 88; - BOOST_REQUIRE( SoA(1, 1).mass == 88 ); + SoA(1, 1) = SoA(0, 0); + BOOST_TEST( SoA(1, 1).mass == SoA(0, 0).mass); + BOOST_TEST( SoA(1, 1) == SoA(0, 0)); + BOOST_TEST( !(SoA(1, 1) != SoA(0, 0))); + } - SoA(1, 1) = SoA(0, 0); - BOOST_REQUIRE( SoA(1, 1).mass == SoA(0, 0).mass); - BOOST_REQUIRE( SoA(1, 1) == SoA(0, 0)); - BOOST_REQUIRE( ! (SoA(1, 1) != SoA(0, 0))); -} + struct employee_dummy { + std::string name; + // NOLINTNEXTLINE(runtime/int) + short salary; // NOLINT(google-runtime-int) + std::size_t age; + }; + + struct employee { + std::string name; -struct employee_dummy { - std::string name; - // NOLINTNEXTLINE(runtime/int) - short salary; // NOLINT(google-runtime-int) - std::size_t age; -}; - -struct employee { - std::string name; - // NOLINTNEXTLINE(runtime/int) - short salary; // NOLINT(google-runtime-int) - std::size_t age; + // NOLINTNEXTLINE(runtime/int) + short salary; // NOLINT(google-runtime-int) + std::size_t age; + + // clang-format off // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) - char padding_[(((offsetof(employee_dummy, age) + sizeof(age)) / sizeof(std::string) + 1) * sizeof(std::string) - (offsetof(employee_dummy, age) + sizeof(age)))] = {}; -}; + char padding_[ + ((offsetof(employee_dummy, age) + sizeof(age)) / sizeof(std::string) + 1) * sizeof(std::string) + - (offsetof(employee_dummy, age) + sizeof(age)) + ] = {}; + // clang-format on + }; // TODO(correaa) this doesn't work with NVCC (triggered by adl fill) #if !(defined(__NVCC__) || defined(__HIPCC__)) -BOOST_AUTO_TEST_CASE(member_array_cast_soa_aos_employee) { - using namespace std::string_literals; // NOLINT(build/namespaces) for ""s + BOOST_AUTO_TEST_CASE(member_array_cast_soa_aos_employee) { + using namespace std::string_literals; // NOLINT(build/namespaces) for ""s - multi::array d1D = { - { "Al"s, 1430, 35}, - {"Bob"s, 3212, 34}, - }; + // NOLINTBEGIN(misc-include-cleaner) bug in clang-tidy 18 + multi::array d1D = { + { "Al"s, 1430, 35}, + {"Bob"s, 3212, 34}, + }; + // NOLINTEND(misc-include-cleaner) bug in clang-tidy 18 - auto&& d1D_names = d1D.member_cast(&employee::name); - BOOST_REQUIRE(size(d1D_names) == size(d1D)); - BOOST_REQUIRE(d1D_names[1] == d1D[1].name); - BOOST_REQUIRE(&d1D_names[1] == &d1D[1].name); + auto&& d1D_names = d1D.member_cast(&employee::name); + BOOST_TEST(size(d1D_names) == size(d1D)); + BOOST_TEST(d1D_names[1] == d1D[1].name); + BOOST_TEST(&d1D_names[1] == &d1D[1].name); - multi::array d2D = { - { {"Al"s, 1430, 35}, {"Bob"s, 3212, 34}}, - {{"Carl"s, 1589, 32}, {"David"s, 2300, 38}}, - }; - BOOST_REQUIRE(d2D[0][0].name == "Al"); - BOOST_REQUIRE(d2D[0][0].salary == 1430); - BOOST_REQUIRE(d2D[0][0].age == 35); - - auto&& d2D_names = d2D.member_cast(&employee::name); - BOOST_REQUIRE(size(d2D_names) == size(d2D)); - BOOST_REQUIRE(d2D_names[1][1] == "David"); - -#if !(defined(__clang__) && defined(__CUDACC__)) -#if !defined(__circle_build__) || (__circle_build__ > 200 ) - multi::array d2D_names_copy_members = d2D.element_transformed(&employee::name); - BOOST_REQUIRE(d2D_names_copy_members[1][1] == "David"); - BOOST_REQUIRE(d2D_names_copy_members == d2D_names); -#endif + multi::array d2D = { + { {"Al"s, 1430, 35}, {"Bob"s, 3212, 34}}, + {{"Carl"s, 1589, 32}, {"David"s, 2300, 38}}, + }; + BOOST_TEST(d2D[0][0].name == "Al"); + BOOST_TEST(d2D[0][0].salary == 1430); + BOOST_TEST(d2D[0][0].age == 35); + + auto&& d2D_names = d2D.member_cast(&employee::name); + BOOST_TEST(size(d2D_names) == size(d2D)); + BOOST_TEST(d2D_names[1][1] == "David"); + + #if !(defined(__clang__) && defined(__CUDACC__)) + multi::array d2D_names_copy_members{d2D.element_transformed(&employee::name)}; + BOOST_TEST(d2D_names_copy_members[1][1] == "David"); + BOOST_TEST(d2D_names_copy_members == d2D_names); + + multi::array d2D_names_copy{d2D_names}; + BOOST_TEST( d2D_names == d2D_names_copy); + BOOST_TEST( d2D_names.base() != d2D_names_copy.base() ); + #endif + } #endif -#if !(defined(__clang__) && defined(__CUDACC__)) - multi::array d2D_names_copy{d2D_names}; - BOOST_REQUIRE(d2D_names == d2D_names_copy); - BOOST_REQUIRE(base(d2D_names) != base(d2D_names_copy)); -#endif -} -#endif + BOOST_AUTO_TEST_CASE(element_transformed_from_member) { + struct record { + int id; + double data; + }; -#if !defined(__circle_build__) || (__circle_build__ > 200 ) -BOOST_AUTO_TEST_CASE(element_transformed_from_member) { - struct record { - int id; - double data; - }; + multi::array const recs = { + {{1, 1.1}, {2, 2.2}}, + {{3, 3.3}, {4, 4.4}}, + }; - multi::array const recs = { - {{1, 1.1}, {2, 2.2}}, - {{3, 3.3}, {4, 4.4}}, - }; + // multi::array ids = recs.element_transformed(std::mem_fn(& A::id)); + multi::array ids{recs.element_transformed(&record::id)}; - // multi::array ids = recs.element_transformed(std::mem_fn(& A::id)); - multi::array ids = recs.element_transformed(&record::id); + BOOST_TEST( ids[1][1] == 4 ); + BOOST_TEST( ids == recs.member_cast(&record::id) ); - BOOST_REQUIRE( ids[1][1] == 4 ); - BOOST_REQUIRE( ids == recs.member_cast(&record::id) ); - - // recs.element_transformed(std::mem_fn(& A::id) )[1][1] = 5; // not assignable, ok - // BOOST_REQUIRE( recs[1][1].id == 5 ); -} -#endif + // recs.element_transformed(std::mem_fn(& A::id) )[1][1] = 5; // not assignable, ok + // BOOST_TEST( recs[1][1].id == 5 ); + } // TODO(correaa) this doesn't work with NVCC (triggered by adl fill) #if !(defined(__NVCC__) || defined(__HIPCC__)) -BOOST_AUTO_TEST_CASE(element_transformed_from_member_no_amp) { - using namespace std::string_literals; // NOLINT(build/namespaces) for ""s + BOOST_AUTO_TEST_CASE(element_transformed_from_member_no_amp) { + using namespace std::string_literals; // NOLINT(build/namespaces) for ""s - multi::array d2D = { - { {"Al"s, 1430, 35}, {"Bob"s, 3212, 34}}, - {{"Carl"s, 1589, 32}, {"David"s, 2300, 38}}, - }; + multi::array d2D = { + { {"Al"s, 1430, 35}, {"Bob"s, 3212, 34}}, + {{"Carl"s, 1589, 32}, {"David"s, 2300, 38}}, + }; - // multi::array d2D_ages_copy = - d2D.element_transformed(std::mem_fn(&employee::age)); - BOOST_REQUIRE( d2D.element_transformed(std::mem_fn(&employee::age)) == d2D.element_transformed(&employee::age) ); + // multi::array d2D_ages_copy = + d2D.element_transformed(std::mem_fn(&employee::age)); + BOOST_TEST( d2D.element_transformed(std::mem_fn(&employee::age)) == d2D.element_transformed(&employee::age) ); + } +#endif + + return boost::report_errors(); } + +#if defined(__clang__) + #pragma clang diagnostic pop +#elif defined(_MSC_VER) + #pragma warning(pop) #endif diff --git a/external_codes/boost_multi/multi/test/minimalistic_ptr.cpp b/external_codes/boost_multi/multi/test/minimalistic_ptr.cpp index 8d2d152558..8bc370b7ee 100644 --- a/external_codes/boost_multi/multi/test/minimalistic_ptr.cpp +++ b/external_codes/boost_multi/multi/test/minimalistic_ptr.cpp @@ -1,35 +1,14 @@ -// -*-indent-tabs-mode:t;c-basic-offset:4;tab-width:4;autowrap:nil;-*- -// Copyright 2018-2023 Alfredo A. Correa +// Copyright 2018-2024 Alfredo A. Correa // Copyright 2024 Matt Borland // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt -#include - -#include - -// Suppress warnings from boost.test -#if defined(__clang__) -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wold-style-cast" -# pragma clang diagnostic ignored "-Wundef" -# pragma clang diagnostic ignored "-Wconversion" -# pragma clang diagnostic ignored "-Wsign-conversion" -# pragma clang diagnostic ignored "-Wfloat-equal" -#elif defined(__GNUC__) -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wold-style-cast" -# pragma GCC diagnostic ignored "-Wundef" -# pragma GCC diagnostic ignored "-Wconversion" -# pragma GCC diagnostic ignored "-Wsign-conversion" -# pragma GCC diagnostic ignored "-Wfloat-equal" -#endif - -#ifndef BOOST_TEST_MODULE -# define BOOST_TEST_MAIN -#endif - -#include +#include // for array_ptr, array_ref, subarray + +#include // for array +#include // for iterator_traits +#include // for allocator +#include // for is_same, is_convertible, enable... namespace multi = boost::multi; @@ -43,24 +22,37 @@ class ptr : public std::iterator_traits { // minimalistic pointer public: ptr() = default; - constexpr explicit ptr(T* impl) : impl_{impl} {} - template{}> > + constexpr explicit ptr(T* impl) : impl_{ impl } {} + template> // NOLINT(modernize-use-constraints) TODO(correaa) for C++20 + > // cppcheck-suppress [noExplicitConstructor,unmatchedSuppression] - ptr(ptr const& other) : impl_{other.impl_} {} // NOLINT(google-explicit-constructor, hicpp-explicit-conversions) // NOSONAR(cpp:S1709) ptr -> ptr + ptr(ptr const& other) : impl_{ other.impl_ } {} // NOLINT(google-explicit-constructor, hicpp-explicit-conversions) // NOSONAR(cpp:S1709) using typename std::iterator_traits::reference; using typename std::iterator_traits::difference_type; + // NOLINTNEXTLINE(fuchsia-overloaded-operator, fuchsia-trailing-return): operator* used because this class simulates a pointer, trailing return helps - constexpr auto operator*() const -> reference {return *impl_;} + constexpr auto operator*() const -> reference { return *impl_; } + + #if defined(__clang__) + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wunknown-warning-option" + #pragma clang diagnostic ignored "-Wunsafe-buffer-usage" + #endif // NOLINTNEXTLINE(fuchsia-overloaded-operator, cppcoreguidelines-pro-bounds-pointer-arithmetic): operator+ is overloaded to simulate a pointer - constexpr auto operator+(difference_type n) const {return ptr{impl_ + n};} + constexpr auto operator+(difference_type n) const { return ptr{ impl_ + n }; } // NOLINTNEXTLINE(fuchsia-overloaded-operator, cppcoreguidelines-pro-bounds-pointer-arithmetic): operator+ is overloaded to simulate a pointer - constexpr auto operator-(difference_type n) const {return ptr{impl_ - n};} + constexpr auto operator-(difference_type n) const { return ptr{ impl_ - n }; } + + #if defined(__clang__) + #pragma clang diagnostic pop + #endif -// T& operator[](difference_type n) const{return impl_[n];} // optional + // T& operator[](difference_type n) const{return impl_[n];} // optional using default_allocator_type = std::allocator; - template auto operator==(ptr const& other) const& {return impl_ == other.impl_;} + template auto operator==(ptr const& other) const& { return impl_ == other.impl_; } template friend class ptr2; }; @@ -69,55 +61,73 @@ class ptr2 : public std::iterator_traits { // minimalistic pointer T* impl_; public: - constexpr explicit ptr2(T* impl) : impl_{impl} {} - constexpr explicit ptr2(ptr const& other) : impl_{other.impl_} {} - template>> + constexpr explicit ptr2(T* impl) : impl_{ impl } {} + constexpr explicit ptr2(ptr const& other) : impl_{ other.impl_ } {} + template>> // NOLINT(modernize-use-constraints) TODO(correaa) for C++20 // cppcheck-suppress [noExplicitConstructor, unmatchedSuppression] - ptr2(ptr2 const& other) : impl_{other.impl_} {} // NOLINT(google-explicit-constructor, hicpp-explicit-conversions) // NOSONAR(cpp:S1709) ptr -> ptr + ptr2(ptr2 const& other) : impl_{ other.impl_ } {} // NOLINT(google-explicit-constructor, hicpp-explicit-conversions) // NOSONAR(cpp:S1709) using typename std::iterator_traits::reference; using typename std::iterator_traits::difference_type; // NOLINTNEXTLINE(fuchsia-overloaded-operator, fuchsia-trailing-return): operator* used because this class simulates a pointer, trailing return helps - constexpr auto operator*() const -> reference {return *impl_;} + constexpr auto operator*() const -> reference { return *impl_; } + + #if defined(__clang__) + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wunknown-warning-option" + #pragma clang diagnostic ignored "-Wunsafe-buffer-usage" + #endif // NOLINTNEXTLINE(fuchsia-overloaded-operator, cppcoreguidelines-pro-bounds-pointer-arithmetic): operator+ is overloaded to simulate a pointer - constexpr auto operator+(difference_type n) const {return ptr2{impl_ + n};} + constexpr auto operator+(difference_type n) const { return ptr2{ impl_ + n }; } // NOLINTNEXTLINE(fuchsia-overloaded-operator, cppcoreguidelines-pro-bounds-pointer-arithmetic): operator+ is overloaded to simulate a pointer - constexpr auto operator-(difference_type n) const {return ptr2{impl_ - n};} + constexpr auto operator-(difference_type n) const { return ptr2{ impl_ - n }; } + + #if defined(__clang__) + #pragma clang diagnostic pop + #endif -// T& operator[](std::ptrdiff_t n) const{return impl_[n];} // optional + // T& operator[](std::ptrdiff_t n) const{return impl_[n];} // optional using default_allocator_type = std::allocator; }; } // end namespace minimalistic +#include +#define BOOST_AUTO_TEST_CASE(CasenamE) /**/ + +auto main() -> int { // NOLINT(readability-function-cognitive-complexity,bugprone-exception-escape) BOOST_AUTO_TEST_CASE(test_minimalistic_ptr) { std::array buffer{}; - BOOST_REQUIRE( buffer.size() == 400 ); + BOOST_TEST( buffer.size() == 400 ); using pointer_type = minimalistic::ptr; - multi::array_ptr const CCP(pointer_type{buffer.data()}, {20, 20}); - (*CCP)[2]; // requires operator+ + multi::array_ptr const CCP(pointer_type{ buffer.data() }, { 20, 20 }); + (*CCP)[2]; // requires operator+ (*CCP)[1][1]; (*CCP)[1][1] = 9; - BOOST_REQUIRE( &(*CCP)[1][1] == &buffer[21] ); + BOOST_TEST( &(*CCP)[1][1] == &buffer[21] ); + // auto&& CC2 = (*CCP).static_array_cast>(); auto&& CC2 = CCP->static_array_cast>(); - BOOST_REQUIRE( &CC2[1][1] == &(*CCP)[1][1] ); + BOOST_TEST( &CC2[1][1] == &(*CCP)[1][1] ); - static_assert( std::is_convertible{}, "!"); + static_assert(std::is_convertible{}, "!"); - minimalistic::ptr const pd{nullptr}; - minimalistic::ptr const pcd = pd; - BOOST_REQUIRE( pcd == pd ); + minimalistic::ptr const pd{ nullptr }; + minimalistic::ptr const pcd = pd; + BOOST_TEST( pcd == pd ); { - auto&& REF = *CCP; (void)REF; - static_assert( std::is_same>{}, "!" ); + auto&& REF = *CCP; + (void)REF; + static_assert( std::is_same_v> ); } { - auto const& REF = *CCP; (void)REF; - static_assert( std::is_same>{}, "!" ); + auto const& REF = *CCP; + (void)REF; + static_assert( std::is_same_v> ); } } +return boost::report_errors();} diff --git a/external_codes/boost_multi/multi/test/move.cpp b/external_codes/boost_multi/multi/test/move.cpp index f37bb0f68c..ba7c538c90 100644 --- a/external_codes/boost_multi/multi/test/move.cpp +++ b/external_codes/boost_multi/multi/test/move.cpp @@ -1,537 +1,713 @@ // Copyright 2020-2024 Alfredo A. Correa // Copyright 2024 Matt Borland -// Distributed under the Boost Software License, Version 1.0. +// Distributed under the Boost Software License, Version 10. // https://www.boost.org/LICENSE_1_0.txt -#include - -#include // for std::move -#include -#include - -// Suppress warnings from boost.test -#if defined(__clang__) -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wold-style-cast" -# pragma clang diagnostic ignored "-Wundef" -# pragma clang diagnostic ignored "-Wconversion" -# pragma clang diagnostic ignored "-Wsign-conversion" -# pragma clang diagnostic ignored "-Wfloat-equal" -#elif defined(__GNUC__) -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wold-style-cast" -# pragma GCC diagnostic ignored "-Wundef" -# pragma GCC diagnostic ignored "-Wconversion" -# pragma GCC diagnostic ignored "-Wsign-conversion" -# pragma GCC diagnostic ignored "-Wfloat-equal" -#endif +#include -#ifndef BOOST_TEST_MODULE -# define BOOST_TEST_MAIN -#endif +#include // for array, apply, array_types<>::ele... -#include +#include // for copy, equal, fill_n, move +#include // for size, back_insert_iterator, back... +#include // for unique_ptr, make_unique, allocat... +// IWYU pragma: no_include // for remove_reference<>::type +// IWYU pragma: no_include +// IWYU pragma: no_include +// IWYU pragma: no_include +#include // for move, swap +#include // for vector, operator==, vector<>::va... -#include // this is from Boost.MultiArray, not this library +// IWYU pragma: no_include // for move namespace multi = boost::multi; -BOOST_AUTO_TEST_CASE(move_unique_ptr_1D) { +#define BOOST_AUTO_TEST_CASE(CasenamE) /**/ + +namespace { + +void move_element_1d_array() { { - multi::array, 1> arr(multi::extensions_t<1>{10}); - arr[1] = std::make_unique(42); + std::vector > varr(3, multi::array({5}, 99), {}); + multi::array marr({3, 5}, 99); + marr[0] = std::move(varr[0]); + marr[1] = std::move(varr[1]); + marr[2] = std::move(varr[2]); + + BOOST_TEST( marr[0][0] == 99 ); + BOOST_TEST( !varr[0].empty() ); + } + { + multi::array, 1> arr(10, std::vector(5, {}, {})); + multi::array, 1> brr(10, {}, {}); - multi::array, 1> arr2(multi::extensions_t<1>{10}); - std::move(arr.begin(), arr.end(), arr2.begin()); + std::copy_n( std::move(arr).begin(), brr.size(), brr.begin() ); + BOOST_TEST( arr[0].empty() ); // NOLINT(bugprone-use-after-move,hicpp-invalid-access-moved) + BOOST_TEST( brr[0].size() == 5 ); + } + { + multi::array, 1> arr(10, std::vector(5, {}, {})); + multi::array, 1> brr(10, {}, {}); + + std::copy_n( arr.mbegin(), arr.size(), brr.begin() ); + BOOST_TEST( arr[0].empty() ); + BOOST_TEST( brr[0].size() == 5 ); + } + { + multi::array, 1> arr(10, std::vector(5, {}, {})); + + using std::move; // not necessary, just testing if it works + auto vec = move(arr({2, 6}))[0]; + BOOST_TEST( vec.size() == 5 ); + BOOST_TEST( arr[2].empty() ); + } + { + multi::array, 1> arr(10, std::vector(5, {}, {})); + + auto mbeg = arr({2, 6}).mbegin(); + auto vec = *mbeg; + BOOST_TEST( vec.size() == 5 ); + BOOST_TEST( arr[2].empty() ); + } + { + multi::array, 1> arr(10, std::vector(5, {}, {})); + + auto mbeg = arr({2, 6}).mbegin(); + auto vec = *mbeg; + BOOST_TEST( vec.size() == 5 ); + BOOST_TEST( arr[2].empty() ); + } + { + multi::array, 1> arr(10, std::vector(5, {}, {})); + + std::vector> out_vec(4, {}, {}); + std::copy(arr({2, 6}).mbegin(), arr({2, 6}).mend(), out_vec.begin()); + BOOST_TEST( out_vec[0].size() == 5 ); + BOOST_TEST( arr[2].empty() ); + } + { + multi::array, 1> arr(10, std::vector(5, {}, {})); + + std::vector> out_vec(4, {}, {}); + std::copy(multi::move(arr({2, 6})).begin(), multi::move(arr({2, 6})).end(), out_vec.begin()); + BOOST_TEST( out_vec[0].size() == 5 ); + BOOST_TEST( arr[2].empty() ); + } + { + multi::array, 1> arr(10, std::vector(5, {}, {})); - BOOST_REQUIRE( !arr[1] ); - BOOST_REQUIRE( arr2[1] ); - BOOST_REQUIRE( *arr2[1] == 42 ); + std::vector> out_vec(4, {}, {}); + auto&& marr62 = multi::move(arr({2, 6})); + std::copy(std::move(marr62).begin(), std::move(marr62).end(), out_vec.begin()); // NOLINT(bugprone-use-after-move,hicpp-invalid-access-moved) + BOOST_TEST( out_vec[0].size() == 5 ); + BOOST_TEST( arr[2].empty() ); } { - multi::array, 1> arr(multi::extensions_t<1>{10}); - arr[1] = std::make_unique(42); + multi::array, 1> arr(10, std::vector(5, {}, {})); + + std::vector> out_vec(4, {}, {}); + auto&& marr62 = arr({2, 6}); + std::copy(multi::move(marr62).begin(), multi::move(marr62).end(), out_vec.begin()); // NOLINT(bugprone-use-after-move,hicpp-invalid-access-moved) + BOOST_TEST( out_vec[0].size() == 5 ); + BOOST_TEST( out_vec[1].size() == 5 ); + BOOST_TEST( arr[2].empty() ); + } + { + multi::array, 1> arr(10, std::vector(5, {}, {})); - multi::array, 1> arr2 = std::move(arr); - BOOST_REQUIRE( arr.is_empty() ); // NOLINT(bugprone-use-after-move,hicpp-invalid-access-moved,clang-analyzer-cplusplus.Move) - BOOST_REQUIRE( arr2[1] ); - BOOST_REQUIRE( *arr2[1] == 42 ); + std::vector> out_vec(4, {}, {}); + auto&& marr62 = multi::move(arr({2, 6})); + std::copy(marr62.begin(), marr62.end(), out_vec.begin()); + BOOST_TEST( out_vec[0].size() == 5 ); + BOOST_TEST( !arr[2].empty() ); } +} + +void move_element_2d_array() { + multi::array, 2> arr({10, 10}, std::vector(5, {}, {})); + + using std::move; + auto vec = move(arr({2, 6}, {2, 6}))[0][0]; + BOOST_TEST( vec.size() == 5 ); + BOOST_TEST( arr[2][2].empty() ); +} + +void move_element_1d_total_array() { { - multi::array, 1> arr(multi::extensions_t<1>{10}); - arr[1] = std::make_unique(42); + multi::array, 1> arr(10, std::vector(5, {}, {})); - multi::array, 1> arr2; // (multi::extensions_t<1>{10}); - arr2 = std::move(arr); - BOOST_REQUIRE( arr.is_empty() ); // NOLINT(bugprone-use-after-move,hicpp-invalid-access-moved,clang-analyzer-cplusplus.Move) - BOOST_REQUIRE( arr2[1] ); - BOOST_REQUIRE( *arr2[1] == 42 ); + auto vec = std::move(arr)[2]; + BOOST_TEST( vec.size() == 5 ); + BOOST_TEST( arr[2].empty() ); // NOLINT(bugprone-use-after-move,hicpp-invalid-access-moved) } { - multi::array, 1> arr(multi::extensions_t<1>{10}); - arr[1] = std::make_unique(42); + multi::array, 1> arr(10, std::vector(5, {}, {})); - multi::array, 1> arr2(multi::extensions_t<1>{10}); - // arr2() = arr(); // fails to compile, elements are not copy assignable - arr2() = arr().element_moved(); - BOOST_REQUIRE( !arr[1] ); - BOOST_REQUIRE( arr2[1] ); - BOOST_REQUIRE( *arr2[1] == 42 ); + using std::move; + auto vec = move(arr)[2]; + BOOST_TEST( vec.size() == 5 ); + BOOST_TEST( arr[2].empty() ); } } +} // namespace + +auto main() -> int { // NOLINT(readability-function-cognitive-complexity,bugprone-exception-escape) + move_element_1d_array(); + move_element_2d_array(); + + move_element_1d_total_array(); + + BOOST_AUTO_TEST_CASE(move_unique_ptr_1D) { + { + multi::array, 1> arr(multi::extensions_t<1>{10}); + arr[1] = std::make_unique(42); + + multi::array, 1> arr2(multi::extensions_t<1>{10}); + std::move(arr.begin(), arr.end(), arr2.begin()); + + BOOST_TEST( !arr[1] ); + BOOST_TEST( arr2[1] ); + BOOST_TEST( *arr2[1] == 42 ); + } + { + multi::array, 1> arr(multi::extensions_t<1>{10}); + arr[1] = std::make_unique(42); + + multi::array, 1> arr2 = std::move(arr); + BOOST_TEST( arr.is_empty() ); // NOLINT(bugprone-use-after-move,hicpp-invalid-access-moved,clang-analyzer-cplusplus.Move) + BOOST_TEST( arr2[1] ); + BOOST_TEST( *arr2[1] == 42 ); + } + { + multi::array, 1> arr(multi::extensions_t<1>{10}); + arr[1] = std::make_unique(42); + + multi::array, 1> arr2; // (multi::extensions_t<1>{10}); + arr2 = std::move(arr); + BOOST_TEST( arr.is_empty() ); // NOLINT(bugprone-use-after-move,hicpp-invalid-access-moved,clang-analyzer-cplusplus.Move) + BOOST_TEST( arr2[1] ); + BOOST_TEST( *arr2[1] == 42 ); + } + // { + // multi::array, 1> arr(multi::extensions_t<1>{10}); + // arr[1] = std::make_unique(42); + + // multi::array, 1> arr2(multi::extensions_t<1>{10}); + // // arr2() = arr(); // fails to compile, elements are not copy assignable + // arr2() = arr().element_moved(); + // BOOST_TEST( !arr[1] ); + // BOOST_TEST( arr2[1] ); + // BOOST_TEST( *arr2[1] == 42 ); + // } + } -BOOST_AUTO_TEST_CASE(multi_swap) { + BOOST_AUTO_TEST_CASE(multi_swap) { #ifndef _MSC_VER // problems with 14.3 c++17 - multi::array arr({3, 5}, 99.0); - multi::array arr2({7, 11}, 88.0); + multi::array arr({3, 5}, 990); + multi::array arr2({7, 11}, 880); #else - multi::array arr(multi::extensions_t<2>{3, 5}, 99.0); - multi::array arr2(multi::extensions_t<2>{7, 11}, 88.0); + multi::array arr(multi::extensions_t<2>{3, 5}, 990); + multi::array arr2(multi::extensions_t<2>{7, 11}, 880); #endif - swap(arr, arr2); + swap(arr, arr2); - BOOST_REQUIRE( size(arr) == 7 ); - BOOST_REQUIRE( arr[1][2] == 88.0 ); - BOOST_REQUIRE( arr2[1][2] == 99.0 ); -} + BOOST_TEST( size(arr) == 7 ); + BOOST_TEST( arr[1][2] == 880 ); + BOOST_TEST( arr2[1][2] == 990 ); + } -BOOST_AUTO_TEST_CASE(multi_std_swap) { + BOOST_AUTO_TEST_CASE(multi_std_swap) { #ifndef _MSC_VER // problems with 14.3 c++17 - multi::array arr({3, 5}, 99.0); - multi::array arr2({7, 11}, 88.0); + multi::array arr({3, 5}, 990); + multi::array arr2({7, 11}, 880); #else - multi::array arr(multi::extensions_t<2>{3, 5}, 99.0); - multi::array arr2(multi::extensions_t<2>{7, 11}, 88.0); + multi::array arr(multi::extensions_t<2>{3, 5}, 990); + multi::array arr2(multi::extensions_t<2>{7, 11}, 880); #endif - using std::swap; - swap(arr, arr2); + using std::swap; + swap(arr, arr2); - BOOST_REQUIRE( size(arr) == 7 ); - BOOST_REQUIRE( arr[1][2] == 88.0 ); - BOOST_REQUIRE( arr2[1][2] == 99.0 ); -} + BOOST_TEST( size(arr) == 7 ); + BOOST_TEST( arr[1][2] == 880 ); + BOOST_TEST( arr2[1][2] == 990 ); + } -BOOST_AUTO_TEST_CASE(multi_array_clear) { - multi::array arr({10, 10}, 99.0); + BOOST_AUTO_TEST_CASE(multi_array_clear) { + multi::array arr({10, 10}, 990); - arr.clear(); + arr.clear(); - BOOST_REQUIRE(arr.is_empty()); + BOOST_TEST(arr.is_empty()); - arr.reextent({20, 20}, 99.0); - // BOOST_REQUIRE(! arr.is_empty()); + arr.reextent({20, 20}, 990); + // BOOST_TEST(! arr.is_empty()); - // clear(arr).reextent({30, 30}, 88.0); - // BOOST_REQUIRE(arr[15][15] == 88.0); -} + // clear(arr).reextent({30, 30}, 88.0); + // BOOST_TEST(arr[15][15] == 88.0); + } -BOOST_AUTO_TEST_CASE(multi_array_move) { - std::vector > Av(10, multi::array({4, 5}, 99.0)); // std::vector NOLINT(fuchsia-default-arguments-calls) - multi::array arr2(std::move(Av[0]), std::allocator{}); + BOOST_AUTO_TEST_CASE(multi_array_move) { + std::vector> Av(10, multi::array({4, 5}, 990)); // std::vector NOLINT(fuchsia-default-arguments-calls) + multi::array arr2(std::move(Av[0]), std::allocator{}); - BOOST_REQUIRE( is_empty(Av[0]) ); - BOOST_REQUIRE( size(arr2) == 4 ); - BOOST_REQUIRE( arr2[1][2] == 99.0 ); -} + BOOST_TEST( is_empty(Av[0]) ); + BOOST_TEST( size(arr2) == 4 ); + BOOST_TEST( arr2[1][2] == 990 ); + } -BOOST_AUTO_TEST_CASE(multi_array_move_into_vector) { - std::vector > Av(10, multi::array({4, 5}, 99.0)); // NOLINT(fuchsia-default-arguments-calls) - std::vector > Bv; Bv.reserve(Av.size()); // NOLINT(fuchsia-default-arguments-calls) + BOOST_AUTO_TEST_CASE(multi_array_move_into_vector) { + std::vector> Av(10, multi::array({4, 5}, 990)); // NOLINT(fuchsia-default-arguments-calls) + std::vector> Bv; + Bv.reserve(Av.size()); // NOLINT(fuchsia-default-arguments-calls) - std::move( begin(Av), end(Av), std::back_inserter(Bv) ); + std::move(begin(Av), end(Av), std::back_inserter(Bv)); - BOOST_REQUIRE( size(Bv) == size(Av) ); - BOOST_REQUIRE( is_empty(Av[4]) ); - BOOST_REQUIRE( size(Bv[5]) == 4 ); - BOOST_REQUIRE( Bv[5][1][2] == 99.0 ); -} + BOOST_TEST( size(Bv) == size(Av) ); + BOOST_TEST( is_empty(Av[4]) ); + BOOST_TEST( size(Bv[5]) == 4 ); + BOOST_TEST( Bv[5][1][2] == 990 ); + } -BOOST_AUTO_TEST_CASE(multi_array_move_into_vector_reserve) { - std::vector > Av(10, multi::array({4, 5}, 99.0)); // NOLINT(fuchsia-default-arguments-calls) - std::vector > Bv; Bv.reserve(Av.size()); + BOOST_AUTO_TEST_CASE(multi_array_move_into_vector_reserve) { + std::vector> Av(10, multi::array({4, 5}, 990)); // NOLINT(fuchsia-default-arguments-calls) + std::vector> Bv; + Bv.reserve(Av.size()); -// for(auto& v: Av) Bv.emplace_back(std::move(v), std::allocator{}); // segfaults nvcc 11.0 but not nvcc 11.1 - std::move(begin(Av), end(Av), std::back_inserter(Bv)); + // for(auto& v: Av) Bv.emplace_back(std::move(v), std::allocator{}); // segfaults nvcc 11.0 but not nvcc 11.1 + std::move(begin(Av), end(Av), std::back_inserter(Bv)); - BOOST_REQUIRE( size(Bv) == size(Av) ); - BOOST_REQUIRE( is_empty(Av[4]) ); - BOOST_REQUIRE( size(Bv[5]) == 4 ); - BOOST_REQUIRE( Bv[5][1][2] == 99.0 ); -} + BOOST_TEST( size(Bv) == size(Av) ); + BOOST_TEST( is_empty(Av[4]) ); + BOOST_TEST( size(Bv[5]) == 4 ); + BOOST_TEST( Bv[5][1][2] == 990 ); + } -BOOST_AUTO_TEST_CASE(multi_array_move_into_vector_move) { - std::vector > Av(10, multi::array({4, 5}, 99.0)); // std::vector NOLINT(fuchsia-default-arguments-calls) - std::vector > Bv = std::move(Av); + BOOST_AUTO_TEST_CASE(multi_array_move_into_vector_move) { + std::vector> Av(10, multi::array({4, 5}, 990)); // std::vector NOLINT(fuchsia-default-arguments-calls) + std::vector> Bv = std::move(Av); - Av.clear(); - BOOST_REQUIRE( size(Av) == 0 ); - BOOST_REQUIRE( size(Bv) == 10 ); - BOOST_REQUIRE( size(Bv[5]) == 4 ); - BOOST_REQUIRE( Bv[5][1][2] == 99.0 ); -} + Av.clear(); -BOOST_AUTO_TEST_CASE(multi_array_move_array) { - multi::array, 2> arr({10, 10}, std::vector(5) ); // std::vector NOLINT(fuchsia-default-arguments-calls) - auto arr2 = std::move(arr); - BOOST_REQUIRE( arr . empty() ); // NOLINT(bugprone-use-after-move,hicpp-invalid-access-moved,clang-analyzer-cplusplus.Move) test deterministic moved from state - BOOST_REQUIRE( arr .is_empty() ); // NOLINT(bugprone-use-after-move,hicpp-invalid-access-moved,clang-analyzer-cplusplus.Move) test deterministic moved from state - BOOST_REQUIRE( arr2.size() == 10 ); -} + BOOST_TEST( size(Av) == 0 ); + BOOST_TEST( size(Bv) == 10 ); + BOOST_TEST( size(Bv[5]) == 4 ); + BOOST_TEST( Bv[5][1][2] == 990 ); + } -BOOST_AUTO_TEST_CASE(multi_array_move_elements) { - multi::array, 1> arr({10}, std::vector(5) ); // std::vector NOLINT(fuchsia-default-arguments-calls) + BOOST_AUTO_TEST_CASE(multi_array_move_array) { + multi::array, 2> arr({10, 10}, std::vector(5)); // std::vector NOLINT(fuchsia-default-arguments-calls) + auto arr2 = std::move(arr); - std::vector> sink(5); // std::vector NOLINT(fuchsia-default-arguments-calls) + // NOLINTNEXTLINE(bugprone-use-after-move,hicpp-invalid-access-moved,clang-analyzer-cplusplus.Move) test deterministic moved from state + BOOST_TEST( arr . empty() ); - auto* ptr1 = arr[1].data(); + // NOLINTNEXTLINE(bugprone-use-after-move,hicpp-invalid-access-moved,clang-analyzer-cplusplus.Move) test deterministic moved from state + BOOST_TEST( arr .is_empty() ); + BOOST_TEST( arr2.size() == 10 ); + } - std::copy( arr({0, 5}).element_moved().begin(), arr({0, 5}).element_moved().end(), sink.begin() ); - BOOST_REQUIRE( arr[1].empty() ); - BOOST_REQUIRE( ! arr[5].empty() ); + BOOST_AUTO_TEST_CASE(multi_array_move_elements) { + multi::array, 1> arr({10}, std::vector(5)); // std::vector NOLINT(fuchsia-default-arguments-calls) - BOOST_REQUIRE( sink[1].data() == ptr1 ); -} + std::vector> sink(5); // std::vector NOLINT(fuchsia-default-arguments-calls) -BOOST_AUTO_TEST_CASE(multi_array_move_elements_range) { - multi::array, 1> arr({10}, std::vector(5) ); // std::vector NOLINT(fuchsia-default-arguments-calls) + auto* ptr1 = arr[1].data(); - std::vector> sink(5); // NOLINT(fuchsia-default-arguments-calls) + std::copy(arr({0, 5}).element_moved().begin(), arr({0, 5}).element_moved().end(), sink.begin()); + BOOST_TEST( arr[1].empty() ); + BOOST_TEST( !arr[5].empty() ); - auto* ptr1 = arr[1].data(); + BOOST_TEST( sink[1].data() == ptr1 ); + } - std::copy( arr({0, 5}).element_moved().elements().begin(), arr({0, 5}).element_moved().elements().end(), sink.begin() ); - BOOST_REQUIRE( arr[1].empty() ); - BOOST_REQUIRE( ! arr[5].empty() ); + BOOST_AUTO_TEST_CASE(multi_array_move_elements_range) { + multi::array, 1> arr({10}, std::vector(5)); // std::vector NOLINT(fuchsia-default-arguments-calls) - BOOST_REQUIRE( sink[1].data() == ptr1 ); -} + std::vector> sink(5); // NOLINT(fuchsia-default-arguments-calls) -BOOST_AUTO_TEST_CASE(multi_array_move_elements_to_array) { - multi::array, 1> arr({10}, std::vector(5, 99.0) ); // std::vector NOLINT(fuchsia-default-arguments-calls) - BOOST_REQUIRE( arr.size() == 10 ); - multi::array, 1> arr2({ 5}, {}, {}); // std::vector NOLINT(fuchsia-default-arguments-calls) + auto* ptr1 = arr[1].data(); - auto* ptr1 = arr[1].data(); + std::copy(arr({0, 5}).element_moved().elements().begin(), arr({0, 5}).element_moved().elements().end(), sink.begin()); + BOOST_TEST( arr[1].empty() ); + BOOST_TEST( !arr[5].empty() ); - arr2().elements() = arr({0, 5}).element_moved().elements(); + BOOST_TEST( sink[1].data() == ptr1 ); + } - BOOST_REQUIRE( arr2[1].size() == 5 ); - BOOST_REQUIRE( arr2[1][4] == 99.0 ); + BOOST_AUTO_TEST_CASE(multi_array_move_elements_to_array) { + multi::array, 1> arr({10}, std::vector(5, 990)); // std::vector NOLINT(fuchsia-default-arguments-calls) + BOOST_TEST( arr.size() == 10 ); + multi::array, 1> arr2({5}, {}, {}); // std::vector NOLINT(fuchsia-default-arguments-calls) - BOOST_REQUIRE( arr[1].empty() ); - BOOST_REQUIRE( ! arr[5].empty() ); + auto* ptr1 = arr[1].data(); - BOOST_REQUIRE( arr2[1].data() == ptr1 ); -} + arr2().elements() = arr({0, 5}).element_moved().elements(); -BOOST_AUTO_TEST_CASE(move_range_vector_1D) { - std::vector> arr(10, std::vector{1.0, 2.0, 3.0}); // NOLINT(fuchsia-default-arguments-calls) - std::vector> arr2(10); // NOLINT(fuchsia-default-arguments-calls) - std::move(arr.begin(), arr.end(), arr2.begin()); + BOOST_TEST( arr2[1].size() == 5 ); + BOOST_TEST( arr2[1][4] == 990 ); - BOOST_REQUIRE( arr2[0] == std::vector({1.0, 2.0, 3.0}) ); // NOLINT(fuchsia-default-arguments-calls) - BOOST_REQUIRE( arr2[1] == std::vector({1.0, 2.0, 3.0}) ); // NOLINT(fuchsia-default-arguments-calls) + BOOST_TEST( arr[1].empty() ); + BOOST_TEST( !arr[5].empty() ); - BOOST_REQUIRE( arr[0].empty() ); - BOOST_REQUIRE( arr[1].empty() ); -} + BOOST_TEST( arr2[1].data() == ptr1 ); + } -BOOST_AUTO_TEST_CASE(copy_range_1D) { - multi::array, 1> arr({3}, std::vector{1.0, 2.0, 3.0}); // std::vector NOLINT(fuchsia-default-arguments-calls) - BOOST_REQUIRE( arr.size() == 3 ); - multi::array, 1> arr2({3}, std::vector{}); - std::copy(arr.begin(), arr.end(), arr2.begin()); + BOOST_AUTO_TEST_CASE(move_range_vector_1D) { + std::vector> arr(10, std::vector{10, 20, 30}); // NOLINT(fuchsia-default-arguments-calls) + std::vector> arr2(10); // NOLINT(fuchsia-default-arguments-calls) + std::move(arr.begin(), arr.end(), arr2.begin()); - BOOST_REQUIRE( arr2[0] == std::vector({1.0, 2.0, 3.0}) ); // NOLINT(fuchsia-default-arguments-calls) - BOOST_REQUIRE( arr2[1] == std::vector({1.0, 2.0, 3.0}) ); // NOLINT(fuchsia-default-arguments-calls) + BOOST_TEST( arr2[0] == std::vector({10, 20, 30}) ); // NOLINT(fuchsia-default-arguments-calls) + BOOST_TEST( arr2[1] == std::vector({10, 20, 30}) ); // NOLINT(fuchsia-default-arguments-calls) - BOOST_REQUIRE( arr [0] == std::vector({1.0, 2.0, 3.0}) ); // NOLINT(fuchsia-default-arguments-calls) - BOOST_REQUIRE( arr [1] == std::vector({1.0, 2.0, 3.0}) ); // NOLINT(fuchsia-default-arguments-calls) -} + BOOST_TEST( arr[0].empty() ); + BOOST_TEST( arr[1].empty() ); + } -BOOST_AUTO_TEST_CASE(move_range_1D) { - multi::array, 1> arr({3}, std::vector{1.0, 2.0, 3.0}); // std::vector NOLINT(fuchsia-default-arguments-calls) - BOOST_REQUIRE( arr.size() == 3 ); - multi::array, 1> arr2({3}, std::vector{}); // std::vector NOLINT(fuchsia-default-arguments-calls) - std::move(arr.begin(), arr.end(), arr2.begin()); + BOOST_AUTO_TEST_CASE(copy_range_1D) { + multi::array, 1> arr({3}, std::vector{10, 20, 30}); // std::vector NOLINT(fuchsia-default-arguments-calls) + BOOST_TEST( arr.size() == 3 ); + multi::array, 1> arr2({3}, std::vector{}); + std::copy(arr.begin(), arr.end(), arr2.begin()); - BOOST_REQUIRE( arr2[0] == std::vector({1.0, 2.0, 3.0}) ); // NOLINT(fuchsia-default-arguments-calls) - BOOST_REQUIRE( arr2[1] == std::vector({1.0, 2.0, 3.0}) ); // NOLINT(fuchsia-default-arguments-calls) + BOOST_TEST( arr2[0] == std::vector({10, 20, 30}) ); // NOLINT(fuchsia-default-arguments-calls) + BOOST_TEST( arr2[1] == std::vector({10, 20, 30}) ); // NOLINT(fuchsia-default-arguments-calls) - BOOST_REQUIRE( arr[0].empty() ); - BOOST_REQUIRE( arr[1].empty() ); -} + BOOST_TEST( arr [0] == std::vector({10, 20, 30}) ); // NOLINT(fuchsia-default-arguments-calls) + BOOST_TEST( arr [1] == std::vector({10, 20, 30}) ); // NOLINT(fuchsia-default-arguments-calls) + } -BOOST_AUTO_TEST_CASE(move_range_1D_moved_begin) { - multi::array, 1> arr({3}, std::vector{1.0, 2.0, 3.0}); // std::vector NOLINT(fuchsia-default-arguments-calls) - BOOST_REQUIRE( arr.size() == 3 ); - multi::array, 1> arr2({3}, std::vector{}); // std::vector NOLINT(fuchsia-default-arguments-calls) - std::copy(arr.mbegin(), arr.mend(), arr2.begin()); + BOOST_AUTO_TEST_CASE(move_range_1D) { + multi::array, 1> arr({3}, std::vector{10, 20, 30}); // std::vector NOLINT(fuchsia-default-arguments-calls) + BOOST_TEST( arr.size() == 3 ); + multi::array, 1> arr2({3}, std::vector{}); // std::vector NOLINT(fuchsia-default-arguments-calls) + std::move(arr.begin(), arr.end(), arr2.begin()); - BOOST_REQUIRE( arr2[0] == std::vector({1.0, 2.0, 3.0}) ); // NOLINT(fuchsia-default-arguments-calls) - BOOST_REQUIRE( arr2[1] == std::vector({1.0, 2.0, 3.0}) ); // NOLINT(fuchsia-default-arguments-calls) + BOOST_TEST( arr2[0] == std::vector({10, 20, 30}) ); // NOLINT(fuchsia-default-arguments-calls) + BOOST_TEST( arr2[1] == std::vector({10, 20, 30}) ); // NOLINT(fuchsia-default-arguments-calls) - BOOST_REQUIRE( arr[0].empty() ); - BOOST_REQUIRE( arr[1].empty() ); -} + BOOST_TEST( arr[0].empty() ); + BOOST_TEST( arr[1].empty() ); + } -BOOST_AUTO_TEST_CASE(copy_move_range) { - multi::array, 2> arr ({10, 20}, std::vector{1.0, 2.0, 3.0}); // std::vector NOLINT(fuchsia-default-arguments-calls) - multi::array, 2> arr2({10, 20}, std::vector{} ); // std::vector NOLINT(fuchsia-default-arguments-calls) + // BOOST_AUTO_TEST_CASE(move_range_1D_moved_begin) { + // multi::array, 1> arr({3}, std::vector{10, 20, 30}); // std::vector NOLINT(fuchsia-default-arguments-calls) + // BOOST_TEST( arr.size() == 3 ); + // multi::array, 1> arr2({3}, std::vector{}); // std::vector NOLINT(fuchsia-default-arguments-calls) + // std::copy(arr.mbegin(), arr.mend(), arr2.begin()); - std::copy(arr.mbegin(), arr.mend(), arr2.begin()); + // BOOST_TEST( arr2[0] == std::vector({10, 20, 30}) ); // NOLINT(fuchsia-default-arguments-calls) + // BOOST_TEST( arr2[1] == std::vector({10, 20, 30}) ); // NOLINT(fuchsia-default-arguments-calls) - BOOST_REQUIRE( arr2[0][0] == std::vector({1.0, 2.0, 3.0}) ); // NOLINT(fuchsia-default-arguments-calls) - BOOST_REQUIRE( arr2[0][1] == std::vector({1.0, 2.0, 3.0}) ); // NOLINT(fuchsia-default-arguments-calls) + // BOOST_TEST( arr[0].empty() ); + // BOOST_TEST( arr[1].empty() ); + // } - BOOST_REQUIRE( arr2[1][0] == std::vector({1.0, 2.0, 3.0}) ); // NOLINT(fuchsia-default-arguments-calls) - BOOST_REQUIRE( arr2[1][1] == std::vector({1.0, 2.0, 3.0}) ); // NOLINT(fuchsia-default-arguments-calls) + // BOOST_AUTO_TEST_CASE(copy_move_range) { + // multi::array, 2> arr({10, 20}, std::vector{10, 20, 30}); // std::vector NOLINT(fuchsia-default-arguments-calls) + // multi::array, 2> arr2({10, 20}, std::vector{}); // std::vector NOLINT(fuchsia-default-arguments-calls) - BOOST_REQUIRE( arr[0][0].empty() ); - BOOST_REQUIRE( arr[0][1].empty() ); + // std::copy(arr.mbegin(), arr.mend(), arr2.begin()); - BOOST_REQUIRE( arr[1][0].empty() ); - BOOST_REQUIRE( arr[1][1].empty() ); -} + // BOOST_TEST( arr2[0][0] == std::vector({10, 20, 30}) ); // NOLINT(fuchsia-default-arguments-calls) + // BOOST_TEST( arr2[0][1] == std::vector({10, 20, 30}) ); // NOLINT(fuchsia-default-arguments-calls) -BOOST_AUTO_TEST_CASE(copy_move_range_moved_begin) { - multi::array, 2> arr ({10, 20}, std::vector{1.0, 2.0, 3.0}); // NOLINT(fuchsia-default-arguments-calls) - multi::array, 2> arr2({10, 20}, std::vector{} ); // NOLINT(fuchsia-default-arguments-calls) + // BOOST_TEST( arr2[1][0] == std::vector({10, 20, 30}) ); // NOLINT(fuchsia-default-arguments-calls) + // BOOST_TEST( arr2[1][1] == std::vector({10, 20, 30}) ); // NOLINT(fuchsia-default-arguments-calls) - std::copy(arr.element_moved().begin(), arr.element_moved().end(), arr2.begin()); + // BOOST_TEST( arr[0][0].empty() ); + // BOOST_TEST( arr[0][1].empty() ); - BOOST_REQUIRE( arr2[0][0] == std::vector({1.0, 2.0, 3.0}) ); // NOLINT(fuchsia-default-arguments-calls) - BOOST_REQUIRE( arr2[0][1] == std::vector({1.0, 2.0, 3.0}) ); // NOLINT(fuchsia-default-arguments-calls) + // BOOST_TEST( arr[1][0].empty() ); + // BOOST_TEST( arr[1][1].empty() ); + // } - BOOST_REQUIRE( arr2[1][0] == std::vector({1.0, 2.0, 3.0}) ); // NOLINT(fuchsia-default-arguments-calls) - BOOST_REQUIRE( arr2[1][1] == std::vector({1.0, 2.0, 3.0}) ); // NOLINT(fuchsia-default-arguments-calls) + BOOST_AUTO_TEST_CASE(copy_move_range_moved_begin) { + multi::array, 2> arr({10, 20}, std::vector{10, 20, 30}); // NOLINT(fuchsia-default-arguments-calls) + multi::array, 2> arr2({10, 20}, std::vector{}); // NOLINT(fuchsia-default-arguments-calls) - BOOST_REQUIRE( arr[0][0].empty() ); - BOOST_REQUIRE( arr[0][1].empty() ); + std::copy(arr.element_moved().begin(), arr.element_moved().end(), arr2.begin()); - BOOST_REQUIRE( arr[1][0].empty() ); - BOOST_REQUIRE( arr[1][1].empty() ); -} + BOOST_TEST( arr2[0][0] == std::vector({10, 20, 30}) ); // NOLINT(fuchsia-default-arguments-calls) + BOOST_TEST( arr2[0][1] == std::vector({10, 20, 30}) ); // NOLINT(fuchsia-default-arguments-calls) -BOOST_AUTO_TEST_CASE(copy_move_range_moved_begin_block) { - multi::array, 2> arr ({10, 20}, std::vector{1.0, 2.0, 3.0}); // NOLINT(fuchsia-default-arguments-calls) - multi::array, 2> arr2({ 3, 5}, std::vector{} ); + BOOST_TEST( arr2[1][0] == std::vector({10, 20, 30}) ); // NOLINT(fuchsia-default-arguments-calls) + BOOST_TEST( arr2[1][1] == std::vector({10, 20, 30}) ); // NOLINT(fuchsia-default-arguments-calls) - std::copy(arr({5, 8}, {10, 15}).element_moved().begin(), arr({5, 8}, {10, 15}).element_moved().end(), arr2.begin()); + // BOOST_TEST( arr[0][0].size() == 0); + // BOOST_TEST( arr[0][0].empty() ); + // BOOST_TEST( arr[0][1].empty() ); - BOOST_REQUIRE( arr2[0][0] == std::vector({1.0, 2.0, 3.0}) ); // NOLINT(fuchsia-default-arguments-calls) - BOOST_REQUIRE( arr2[0][1] == std::vector({1.0, 2.0, 3.0}) ); // NOLINT(fuchsia-default-arguments-calls) + // BOOST_TEST( arr[1][0].empty() ); + // BOOST_TEST( arr[1][1].empty() ); + } - BOOST_REQUIRE( arr2[1][0] == std::vector({1.0, 2.0, 3.0}) ); // NOLINT(fuchsia-default-arguments-calls) - BOOST_REQUIRE( arr2[1][1] == std::vector({1.0, 2.0, 3.0}) ); // NOLINT(fuchsia-default-arguments-calls) + BOOST_AUTO_TEST_CASE(copy_move_range_moved_begin_block) { + multi::array, 2> arr({10, 20}, std::vector{10, 20, 30}); // NOLINT(fuchsia-default-arguments-calls) + multi::array, 2> arr2({3, 5}, std::vector{}); - BOOST_REQUIRE( arr[5][10].empty() ); - BOOST_REQUIRE( arr[5][11].empty() ); + std::copy(arr({5, 8}, {10, 15}).element_moved().begin(), arr({5, 8}, {10, 15}).element_moved().end(), arr2.begin()); - BOOST_REQUIRE( arr[6][10].empty() ); - BOOST_REQUIRE( arr[6][11].empty() ); -} + BOOST_TEST( arr2[0][0] == std::vector({10, 20, 30}) ); // NOLINT(fuchsia-default-arguments-calls) + BOOST_TEST( arr2[0][1] == std::vector({10, 20, 30}) ); // NOLINT(fuchsia-default-arguments-calls) + BOOST_TEST( arr2[1][0] == std::vector({10, 20, 30}) ); // NOLINT(fuchsia-default-arguments-calls) + BOOST_TEST( arr2[1][1] == std::vector({10, 20, 30}) ); // NOLINT(fuchsia-default-arguments-calls) -BOOST_AUTO_TEST_CASE(move_reference_range) { - multi::array, 2> arr ({10, 20}, std::vector{1.0, 2.0, 3.0}); // std::vector NOLINT(fuchsia-default-arguments-calls) - multi::array, 2> arr2({10, 20}, std::vector{} ); // std::vector NOLINT(fuchsia-default-arguments-calls) + // BOOST_TEST( arr[5][10].empty() ); + // BOOST_TEST( arr[5][11].empty() ); -// arr2() = arr().element_moved(); - std::copy(arr().element_moved().begin(), arr().element_moved().end(), arr2().begin()); + // BOOST_TEST( arr[6][10].empty() ); + // BOOST_TEST( arr[6][11].empty() ); + } - BOOST_REQUIRE( arr2[0][0] == std::vector({1.0, 2.0, 3.0}) ); // NOLINT(fuchsia-default-arguments-calls) - BOOST_REQUIRE( arr2[0][1] == std::vector({1.0, 2.0, 3.0}) ); // NOLINT(fuchsia-default-arguments-calls) + BOOST_AUTO_TEST_CASE(move_reference_range) { + multi::array, 2> arr({10, 20}, std::vector{10, 20, 30}); // std::vector NOLINT(fuchsia-default-arguments-calls) + multi::array, 2> arr2({10, 20}, std::vector{}); // std::vector NOLINT(fuchsia-default-arguments-calls) - BOOST_REQUIRE( arr2[1][0] == std::vector({1.0, 2.0, 3.0}) ); // NOLINT(fuchsia-default-arguments-calls) - BOOST_REQUIRE( arr2[1][1] == std::vector({1.0, 2.0, 3.0}) ); // NOLINT(fuchsia-default-arguments-calls) + // arr2() = arr().element_moved(); + std::copy(arr().element_moved().begin(), arr().element_moved().end(), arr2().begin()); - BOOST_REQUIRE( arr[0][0].empty() ); - BOOST_REQUIRE( arr[0][1].empty() ); + BOOST_TEST( arr2[0][0] == std::vector({10, 20, 30}) ); // NOLINT(fuchsia-default-arguments-calls) + BOOST_TEST( arr2[0][1] == std::vector({10, 20, 30}) ); // NOLINT(fuchsia-default-arguments-calls) - BOOST_REQUIRE( arr[1][0].empty() ); - BOOST_REQUIRE( arr[1][1].empty() ); -} + BOOST_TEST( arr2[1][0] == std::vector({10, 20, 30}) ); // NOLINT(fuchsia-default-arguments-calls) + BOOST_TEST( arr2[1][1] == std::vector({10, 20, 30}) ); // NOLINT(fuchsia-default-arguments-calls) -BOOST_AUTO_TEST_CASE(move_array_elements) { // NOLINT(readability-function-cognitive-complexity) - { - auto arr = multi::array, 1>({ 5}, std::vector(7)); // std::vector NOLINT(fuchsia-default-arguments-calls) - auto arr2 = std::move(arr); - BOOST_REQUIRE( arr2.size() == 5 ); - BOOST_REQUIRE( arr2[0].size() == 7 ); - BOOST_REQUIRE( arr.is_empty() ); // NOLINT(bugprone-use-after-move,hicpp-invalid-access-moved,clang-analyzer-cplusplus.Move) + // BOOST_TEST( arr[0][0].empty() ); + // BOOST_TEST( arr[0][1].empty() ); + + // BOOST_TEST( arr[1][0].empty() ); + // BOOST_TEST( arr[1][1].empty() ); } - { - auto arr = multi::array, 1>({ 5}, std::vector(7)); // std::vector NOLINT(fuchsia-default-arguments-calls) - std::vector const v0 = std::move(arr[0]); - BOOST_REQUIRE( v0.size() == 7 ); - BOOST_REQUIRE( arr[0].empty() ); + BOOST_AUTO_TEST_CASE(move_array_elements) { // NOLINT(readability-function-cognitive-complexity) + { + auto arr = multi::array, 1>({5}, std::vector(7)); // std::vector NOLINT(fuchsia-default-arguments-calls) + auto arr2 = std::move(arr); + BOOST_TEST( arr2.size() == 5 ); + BOOST_TEST( arr2[0].size() == 7 ); + BOOST_TEST( arr.is_empty() ); // NOLINT(bugprone-use-after-move,hicpp-invalid-access-moved,clang-analyzer-cplusplus.Move) + } + { + auto arr = multi::array, 1>({5}, std::vector(7)); // std::vector NOLINT(fuchsia-default-arguments-calls) + + std::vector const v0 = std::move(arr[0]); + BOOST_TEST( v0.size() == 7 ); + BOOST_TEST( arr[0].empty() ); + + std::vector const v1 = std::move(arr)[1]; + BOOST_TEST( v1.size() == 7 ); + BOOST_TEST( arr[1].empty() ); // NOLINT(bugprone-use-after-move,hicpp-invalid-access-moved,clang-analyzer-cplusplus.Move) for test + + auto arr2 = multi::array, 1>({1}, std::vector{}); + + arr2({0, 1}) = arr({2, 3}); + BOOST_TEST( arr2[0].size() == 7 ); + BOOST_TEST( arr [2].size() == 7 ); + } + { + auto arr = multi::array, 1>({5}, std::vector(7)); // std::vector NOLINT(fuchsia-default-arguments-calls) + auto arr2 = multi::array, 1>({5}, std::vector{}); + + arr2() = arr(); + BOOST_TEST( arr2[0].size() == 7 ); + BOOST_TEST( arr [2].size() == 7 ); + + arr2() = std::move(arr)(); + BOOST_TEST( arr2[0].size() == 7 ); + // BOOST_TEST( arr [2].empty() ); // NOLINT(bugprone-use-after-move,hicpp-invalid-access-moved) for testing + } + { + auto arr = multi::array, 1>({5}, std::vector(7)); // std::vector NOLINT(fuchsia-default-arguments-calls) + auto arr2 = multi::array, 1>({5}, std::vector{}); + + arr2() = arr(); + BOOST_TEST( arr2[0].size() == 7 ); + BOOST_TEST( arr [0].size() == 7 ); + } + { + auto arr = multi::array, 1>({5}, std::vector(7)); // std::vector NOLINT(fuchsia-default-arguments-calls) + auto arr2 = multi::array, 1>({5}, std::vector{}); + + arr2() = std::move(arr)(); + BOOST_TEST( arr2[0].size() == 7 ); + // BOOST_TEST( arr [0].empty() ); // NOLINT(bugprone-use-after-move,hicpp-invalid-access-moved) for testing + } + { + auto arr = multi::array, 1>({5}, std::vector(7)); // std::vector NOLINT(fuchsia-default-arguments-calls) + auto arr2 = multi::array, 1>({5}, std::vector{}); + + auto&& mAp = std::move(arr)(); + arr2() = mAp; + BOOST_TEST( arr2[0].size() == 7 ); + BOOST_TEST( arr [0].size() == 7 ); // NOLINT(bugprone-use-after-move,hicpp-invalid-access-moved) for testing + } + { + auto arr = multi::array, 1>({5}, std::vector(7)); // std::vector NOLINT(fuchsia-default-arguments-calls) + auto arr2 = multi::array, 1>({5}, std::vector{}); + + arr2({0, 5}) = std::move(arr)(); + BOOST_TEST( arr2[0].size() == 7 ); + // BOOST_TEST( arr [0].empty() ); // NOLINT(bugprone-use-after-move,hicpp-invalid-access-moved) for testing + } + { + auto arr = multi::array, 1>({5}, std::vector(7)); // std::vector NOLINT(fuchsia-default-arguments-calls) + auto arr2 = multi::array, 1>({5}, std::vector{}); + + arr2() = arr.taked(5); + BOOST_TEST( arr2[0].size() == 7 ); + BOOST_TEST( arr [0].size() == 7); // NOLINT(bugprone-use-after-move,hicpp-invalid-access-moved) for testing + } + { + auto arr = multi::array, 1>({5}, std::vector(7)); // std::vector NOLINT(fuchsia-default-arguments-calls) + auto arr2 = multi::array, 1>({5}, std::vector{}); + + arr2() = std::move(arr).taked(5); + BOOST_TEST( arr2[0].size() == 7 ); + // BOOST_TEST( arr [0].empty() ); // NOLINT(bugprone-use-after-move,hicpp-invalid-access-moved) for testing + } + { + auto arr = multi::array, 1>({5}, std::vector(7)); // std::vector NOLINT(fuchsia-default-arguments-calls) + auto arr2 = multi::array, 1>({5}, std::vector{}); + auto&& mAt5 = std::move(arr).taked(5); + arr2() = mAt5; + BOOST_TEST( arr2[0].size() == 7 ); + BOOST_TEST( arr [0].size() == 7 ); // NOLINT(bugprone-use-after-move,hicpp-invalid-access-moved) for testing + } + { + auto arr = multi::array, 1>({5}, std::vector(7)); // std::vector NOLINT(fuchsia-default-arguments-calls) + auto arr2 = multi::array, 1>({5}, std::vector{}); + auto&& mAt5 = std::move(arr).taked(5); + arr2() = mAt5; + BOOST_TEST( arr2[0].size() == 7 ); + BOOST_TEST( arr [0].size() == 7 ); // NOLINT(bugprone-use-after-move,hicpp-invalid-access-moved) for testing + } + { + auto arr = multi::array, 1>({5}, std::vector(7)); // std::vector NOLINT(fuchsia-default-arguments-calls) + auto arr2 = multi::array, 1>({5}, std::vector{}); + auto&& mAt5 = std::move(arr).taked(5); + arr2() = std::move(mAt5); // NOLINT(hicpp-move-const-arg,performance-move-const-arg) just testing + BOOST_TEST( arr2[0].size() == 7 ); + // BOOST_TEST( arr[0].empty() ); // NOLINT(bugprone-use-after-move,hicpp-invalid-access-moved) for testing + } + { + auto arr = multi::array, 1>({5}, std::vector(7)); // std::vector NOLINT(fuchsia-default-arguments-calls) + auto arr2 = multi::array, 1>({5}, std::vector{}); + auto&& mAt5 = std::move(arr).taked(5); + arr2() = std::move(mAt5).taked(5); + BOOST_TEST( arr2[0].size() == 7 ); + // BOOST_TEST( arr[0].empty() ); // NOLINT(bugprone-use-after-move,hicpp-invalid-access-moved) for testing + } + { + auto arr = multi::array, 1>({5}, std::vector(7)); // std::vector NOLINT(fuchsia-default-arguments-calls) + auto arr2 = multi::array, 1>({5}, std::vector{}); + auto&& mAt5 = std::move(arr).taked(5); + auto&& mAt5t5 = std::move(mAt5).taked(5); + arr2() = mAt5t5; + BOOST_TEST( arr2[0].size() == 7 ); + BOOST_TEST( arr[0].size() == 7 ); // NOLINT(bugprone-use-after-move,hicpp-invalid-access-moved) for testing + } + { + auto arr = multi::array, 1>({5}, std::vector(7)); // std::vector NOLINT(fuchsia-default-arguments-calls) + auto arr2 = multi::array, 1>({5}, std::vector{}); + auto&& mAt5 = std::move(arr).taked(5); + arr2() = std::move(mAt5).dropped(0); + BOOST_TEST( arr2[0].size() == 7 ); + // BOOST_TEST( arr[0].empty() ); // NOLINT(bugprone-use-after-move,hicpp-invalid-access-moved) for testing + } + { + auto arr = multi::array, 1>({5}, std::vector(7)); // std::vector NOLINT(fuchsia-default-arguments-calls) + auto arr2 = multi::array, 1>({4}, std::vector{}); // std::vector NOLINT(fuchsia-default-arguments-calls) + arr2() = std::move(arr).dropped(1); + BOOST_TEST( arr2[0].size() == 7 ); + BOOST_TEST( arr [0].size() == 7 ); // NOLINT(bugprone-use-after-move,hicpp-invalid-access-moved) for testing + // BOOST_TEST( arr [1].empty() ); // NOLINT(bugprone-use-after-move,hicpp-invalid-access-moved) for testing + } + } - std::vector const v1 = std::move(arr)[1]; - BOOST_REQUIRE( v1.size() == 7 ); - BOOST_REQUIRE( arr[1].empty() ); // NOLINT(bugprone-use-after-move,hicpp-invalid-access-moved,clang-analyzer-cplusplus.Move) for test + BOOST_AUTO_TEST_CASE(multi_array_view_swap) { + multi::array arrA({4, 5}, 99); + multi::array arrB({4, 5}, 88); - auto arr2 = multi::array, 1>({ 1}, std::vector{}); + arrA().swap(arrB()); - arr2({0, 1}) = arr({2, 3}); - BOOST_REQUIRE( arr2[0].size() == 7 ); - BOOST_REQUIRE( arr [2].size() == 7 ); + BOOST_TEST( arrA[0][0] == 88 ); + BOOST_TEST( arrB[0][0] == 99 ); } - { - auto arr = multi::array, 1>({ 5}, std::vector(7)); // std::vector NOLINT(fuchsia-default-arguments-calls) - auto arr2 = multi::array, 1>({ 5}, std::vector{} ); - arr2() = arr(); - BOOST_REQUIRE( arr2[0].size() == 7 ); - BOOST_REQUIRE( arr [2].size() == 7 ); + BOOST_AUTO_TEST_CASE(multi_array_view_swap_dimension_1) { + multi::array arrA({4, 5}, 99); + multi::array arrB({4, 5}, 88); - arr2() = std::move(arr)(); - BOOST_REQUIRE( arr2[0].size() == 7 ); - BOOST_REQUIRE( arr [2].empty() ); // NOLINT(bugprone-use-after-move,hicpp-invalid-access-moved) for testing - } - { - auto arr = multi::array, 1>({ 5}, std::vector(7)); // std::vector NOLINT(fuchsia-default-arguments-calls) - auto arr2 = multi::array, 1>({ 5}, std::vector{} ); + arrA[0].swap(arrB[0]); - arr2() = arr(); - BOOST_REQUIRE( arr2[0].size() == 7 ); - BOOST_REQUIRE( arr [0].size() == 7 ); - } - { - auto arr = multi::array, 1>({ 5}, std::vector(7)); // std::vector NOLINT(fuchsia-default-arguments-calls) - auto arr2 = multi::array, 1>({ 5}, std::vector{} ); + BOOST_TEST( arrA[0][0] == 88 ); + BOOST_TEST( arrB[0][0] == 99 ); - arr2() = std::move(arr)(); - BOOST_REQUIRE( arr2[0].size() == 7 ); - BOOST_REQUIRE( arr [0].empty() ); // NOLINT(bugprone-use-after-move,hicpp-invalid-access-moved) for testing + BOOST_TEST( arrA[1][0] == 99 ); + BOOST_TEST( arrB[1][0] == 88 ); } - { - auto arr = multi::array, 1>({ 5}, std::vector(7)); // std::vector NOLINT(fuchsia-default-arguments-calls) - auto arr2 = multi::array, 1>({ 5}, std::vector{} ); - auto&& mAp = std::move(arr)(); - arr2() = mAp; - BOOST_REQUIRE( arr2[0].size() == 7 ); - BOOST_REQUIRE( arr [0].size() == 7 ); // NOLINT(bugprone-use-after-move,hicpp-invalid-access-moved) for testing - } - { - auto arr = multi::array, 1>({ 5}, std::vector(7)); // std::vector NOLINT(fuchsia-default-arguments-calls) - auto arr2 = multi::array, 1>({ 5}, std::vector{} ); + BOOST_AUTO_TEST_CASE(multi_array_view_swap_dimension_1_free) { + multi::array arrA({4, 5}, 99); + multi::array arrB({4, 5}, 88); - arr2({0, 5}) = std::move(arr)(); - BOOST_REQUIRE( arr2[0].size() == 7 ); - BOOST_REQUIRE( arr [0].empty() ); // NOLINT(bugprone-use-after-move,hicpp-invalid-access-moved) for testing - } - { - auto arr = multi::array, 1>({ 5}, std::vector(7)); // std::vector NOLINT(fuchsia-default-arguments-calls) - auto arr2 = multi::array, 1>({ 5}, std::vector{} ); + swap(arrA[0], arrB[0]); - arr2() = arr.taked(5); - BOOST_REQUIRE( arr2[0].size() == 7 ); - BOOST_REQUIRE( arr [0].size() == 7); // NOLINT(bugprone-use-after-move,hicpp-invalid-access-moved) for testing - } - { - auto arr = multi::array, 1>({ 5}, std::vector(7)); // std::vector NOLINT(fuchsia-default-arguments-calls) - auto arr2 = multi::array, 1>({ 5}, std::vector{} ); + BOOST_TEST( arrA[0][0] == 88 ); + BOOST_TEST( arrB[0][0] == 99 ); - arr2() = std::move(arr).taked(5); - BOOST_REQUIRE( arr2[0].size() == 7 ); - BOOST_REQUIRE( arr [0].empty() ); // NOLINT(bugprone-use-after-move,hicpp-invalid-access-moved) for testing - } - { - auto arr = multi::array, 1>({ 5}, std::vector(7)); // std::vector NOLINT(fuchsia-default-arguments-calls) - auto arr2 = multi::array, 1>({ 5}, std::vector{} ); - auto&& mAt5 = std::move(arr).taked(5); - arr2() = mAt5; - BOOST_REQUIRE( arr2[0].size() == 7 ); - BOOST_REQUIRE( arr [0].size() == 7 ); // NOLINT(bugprone-use-after-move,hicpp-invalid-access-moved) for testing - } - { - auto arr = multi::array, 1>({ 5}, std::vector(7)); // std::vector NOLINT(fuchsia-default-arguments-calls) - auto arr2 = multi::array, 1>({ 5}, std::vector{} ); - auto&& mAt5 = std::move(arr).taked(5); - arr2() = mAt5; - BOOST_REQUIRE( arr2[0].size() == 7 ); - BOOST_REQUIRE( arr [0].size() == 7 ); // NOLINT(bugprone-use-after-move,hicpp-invalid-access-moved) for testing - } - { - auto arr = multi::array, 1>({ 5}, std::vector(7)); // std::vector NOLINT(fuchsia-default-arguments-calls) - auto arr2 = multi::array, 1>({ 5}, std::vector{} ); - auto&& mAt5 = std::move(arr).taked(5); - arr2() = std::move(mAt5); - BOOST_REQUIRE( arr2[0].size() == 7 ); - BOOST_REQUIRE( arr[0].empty() ); // NOLINT(bugprone-use-after-move,hicpp-invalid-access-moved) for testing + BOOST_TEST( arrA[1][0] == 99 ); + BOOST_TEST( arrB[1][0] == 88 ); } - { - auto arr = multi::array, 1>({ 5}, std::vector(7)); // std::vector NOLINT(fuchsia-default-arguments-calls) - auto arr2 = multi::array, 1>({ 5}, std::vector{} ); - auto&& mAt5 = std::move(arr).taked(5); - arr2() = std::move(mAt5).taked(5); - BOOST_REQUIRE( arr2[0].size() == 7 ); - BOOST_REQUIRE( arr[0].empty() ); // NOLINT(bugprone-use-after-move,hicpp-invalid-access-moved) for testing - } - { - auto arr = multi::array, 1>({ 5}, std::vector(7)); // std::vector NOLINT(fuchsia-default-arguments-calls) - auto arr2 = multi::array, 1>({ 5}, std::vector{} ); - auto&& mAt5 = std::move(arr).taked(5); - auto&& mAt5t5 = std::move(mAt5).taked(5); - arr2() = mAt5t5; - BOOST_REQUIRE( arr2[0].size() == 7 ); - BOOST_REQUIRE( arr[0].size() == 7 ); // NOLINT(bugprone-use-after-move,hicpp-invalid-access-moved) for testing - } - { - auto arr = multi::array, 1>({ 5}, std::vector(7)); // std::vector NOLINT(fuchsia-default-arguments-calls) - auto arr2 = multi::array, 1>({ 5}, std::vector{} ); - auto&& mAt5 = std::move(arr).taked(5); - arr2() = std::move(mAt5).dropped(0); - BOOST_REQUIRE( arr2[0].size() == 7 ); - BOOST_REQUIRE( arr[0].empty() ); // NOLINT(bugprone-use-after-move,hicpp-invalid-access-moved) for testing - } - { - auto arr = multi::array, 1>({ 5}, std::vector(7)); // std::vector NOLINT(fuchsia-default-arguments-calls) - auto arr2 = multi::array, 1>({ 4}, std::vector{} ); // std::vector NOLINT(fuchsia-default-arguments-calls) - arr2() = std::move(arr).dropped(1); - BOOST_REQUIRE( arr2[0].size() == 7 ); - BOOST_REQUIRE( arr [0].size() == 7 ); // NOLINT(bugprone-use-after-move,hicpp-invalid-access-moved) for testing - BOOST_REQUIRE( arr [1].empty() ); // NOLINT(bugprone-use-after-move,hicpp-invalid-access-moved) for testing - } -} -BOOST_AUTO_TEST_CASE(multi_array_view_swap) { - multi::array arrA({4, 5}, 99); - multi::array arrB({4, 5}, 88); + BOOST_AUTO_TEST_CASE(move_array_vector_1d) { + multi::array, 1> arrA(10, std::vector(5, 0.0, {})); - arrA().swap(arrB()); + BOOST_TEST( arrA[2].size() == 5 ); + { + multi::array, 1> arrB = std::move(arrA); - BOOST_REQUIRE( arrA[0][0] == 88 ); - BOOST_REQUIRE( arrB[0][0] == 99 ); -} + BOOST_TEST( arrA.empty() ); // NOLINT(bugprone-use-after-move,hicpp-invalid-access-moved,clang-analyzer-cplusplus.Move) + BOOST_TEST( arrB.size() == 10 ); + BOOST_TEST( arrB[2].size() == 5 ); + } + } -BOOST_AUTO_TEST_CASE(multi_array_view_swap_dimension_1) { - multi::array arrA({4, 5}, 99); - multi::array arrB({4, 5}, 88); + BOOST_AUTO_TEST_CASE(move_subarray_vector_1d) { + multi::array, 1> arrA(10, std::vector(5, 0.0)); // NOLINT(fuchsia-default-arguments-calls) - arrA[0].swap(arrB[0]); + BOOST_TEST( arrA[2].size() == 5 ); + { + // this is not wrong but it is misleading since std::move is not doing anything on a reference-like type + // using std::move; + // multi::array, 1> arrB = move(arrA()); // NOLINT(clang-diagnostic-unqualified-std-cast-call) - BOOST_REQUIRE( arrA[0][0] == 88 ); - BOOST_REQUIRE( arrB[0][0] == 99 ); + multi::array, 1> arrB = arrA(); // NOLINT(clang-diagnostic-unqualified-std-cast-call) - BOOST_REQUIRE( arrA[1][0] == 99 ); - BOOST_REQUIRE( arrB[1][0] == 88 ); -} + BOOST_TEST( arrA.size() == 10 ); + BOOST_TEST( arrB.size() == 10 ); + BOOST_TEST( arrA[2].size() == 5 ); + BOOST_TEST( arrB[2].size() == 5 ); + } + } -BOOST_AUTO_TEST_CASE(multi_array_view_swap_dimension_1_free) { - multi::array arrA({4, 5}, 99); - multi::array arrB({4, 5}, 88); + // BOOST_AUTO_TEST_CASE(smart_move_subarray_vector_1d) { + // multi::array, 1> arrA(10, std::vector(5)); - swap(arrA[0], arrB[0]); + // BOOST_TEST( arrA[2].size() == 5 ); + // { + // using std::move; + // multi::array, 1> arrB = move(arrA()); - BOOST_REQUIRE( arrA[0][0] == 88 ); - BOOST_REQUIRE( arrB[0][0] == 99 ); + // BOOST_TEST( arrA.size() == 10 ); + // BOOST_TEST( arrB.size() == 10 ); + // BOOST_TEST( arrA[2].size() == 0 ); + // BOOST_TEST( arrB[2].size() == 5 ); + // } + // } - BOOST_REQUIRE( arrA[1][0] == 99 ); - BOOST_REQUIRE( arrB[1][0] == 88 ); + return boost::report_errors(); } diff --git a/external_codes/boost_multi/multi/test/nico_const_correctness.cpp b/external_codes/boost_multi/multi/test/nico_const_correctness.cpp index baa19b6cd4..bddb339558 100644 --- a/external_codes/boost_multi/multi/test/nico_const_correctness.cpp +++ b/external_codes/boost_multi/multi/test/nico_const_correctness.cpp @@ -3,32 +3,15 @@ // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt -#include - -#include - -// Suppress warnings from boost.test -#if defined(__clang__) -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wold-style-cast" -# pragma clang diagnostic ignored "-Wundef" -# pragma clang diagnostic ignored "-Wconversion" -# pragma clang diagnostic ignored "-Wsign-conversion" -# pragma clang diagnostic ignored "-Wfloat-equal" -#elif defined(__GNUC__) -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wold-style-cast" -# pragma GCC diagnostic ignored "-Wundef" -# pragma GCC diagnostic ignored "-Wconversion" -# pragma GCC diagnostic ignored "-Wsign-conversion" -# pragma GCC diagnostic ignored "-Wfloat-equal" -#endif - -#ifndef BOOST_TEST_MODULE -# define BOOST_TEST_MAIN -#endif - -#include +#include + +#include // for subarray, array, range, operator!= + +#include // for fill, copy, for_each +#include // for operator<<, basic_ostream::opera... +#include // for begin, end, ostream_iterator +#include // for decay_t +#include // for forward namespace multi = boost::multi; @@ -40,41 +23,12 @@ void print(Array1D const& coll) { std::cout << '\n'; } -BOOST_AUTO_TEST_CASE(const_views) { - multi::array coll1 = {0, 8, 15, 47, 11, 42}; - print(coll1); // prints "0, 8, 15, 47, 11, 42" - - print(coll1({0, 3})); // similar to coll1 | take(3) // prints "0, 8, 15" - - auto&& coll1_take3 = coll1({0, 3}); - print(coll1_take3); // prints "0, 8, 15" -} - template auto fill_99(Array1D&& col) -> Array1D&& { std::fill(std::begin(col), std::end(col), 99); return std::forward(col); } -BOOST_AUTO_TEST_CASE(mutating_views) { - multi::array coll1 = {0, 8, 15, 47, 11, 42}; - - fill_99(coll1); - fill_99(coll1({0, 3})); - - auto&& coll1_take3 = coll1({0, 3}); - fill_99(coll1_take3); - - auto const& coll2 = coll1; - // fill_99( coll2 ); // doesn't compile because coll2 is const ("assignment of read-only" inside fill_99) - // fill_99( coll2({0, 3}) ); // similar to coll2 | take(3) doesn't compile ("assignment of read-only") - - auto const& coll1_take3_const = coll1({0, 3}); - // fill_99( coll1_take3_const ); // doesn't compile because coll1_take3_const is const ("assignment of read-only") - - (void)coll2, (void)coll1_take3_const, (void)coll1_take3; -} - template void print_2d(Array2D const& coll) { // *(coll.begin()->begin()) = 99; // doesn't compile "assignment of read-only location" @@ -85,20 +39,6 @@ void print_2d(Array2D const& coll) { }); } -BOOST_AUTO_TEST_CASE(const_views_2d) { - multi::array coll1 = { - {0, 8, 15, 47, 11, 42}, - {0, 8, 15, 47, 11, 42}, - }; - - print_2d(coll1); // prints "0, 8, 15, 47, 11, 42" - - print_2d(coll1({0, 2}, {0, 3})); // similar to coll1 | take(3) // prints "0, 8, 15" - - auto&& coll1_take3 = coll1({0, 2}, {0, 3}); - print_2d(coll1_take3); // prints "0, 8, 15" -} - template auto fill_2d_99(Array1D&& coll) -> Array1D&& { // for(auto const& row : coll) { // does not work because it would make it const @@ -112,24 +52,91 @@ auto fill_2d_99(Array1D&& coll) -> Array1D&& { return std::forward(coll); } -BOOST_AUTO_TEST_CASE(mutating_views_2d) { - multi::array coll1 = { - {0, 8, 15, 47, 11, 42}, - {0, 8, 15, 47, 11, 42}, - }; +#define BOOST_AUTO_TEST_CASE(CasenamE) /**/ + +auto main() -> int { // NOLINT(readability-function-cognitive-complexity,bugprone-exception-escape) + BOOST_AUTO_TEST_CASE(const_views) { + multi::array coll1 = {0, 8, 15, 47, 11, 42}; + print(coll1); // prints "0, 8, 15, 47, 11, 42" + + print(coll1({0, 3})); // similar to coll1 | take(3) // prints "0, 8, 15" + + auto&& coll1_take3 = coll1({0, 3}); + print(coll1_take3); // prints "0, 8, 15" + } + + BOOST_AUTO_TEST_CASE(mutating_views) { + multi::array coll1 = {0, 8, 15, 47, 11, 42}; + + fill_99(coll1); + fill_99(coll1({0, 3})); + + auto&& coll1_take3 = coll1({0, 3}); + fill_99(coll1_take3); + + auto const& coll2 = coll1; + // fill_99( coll2 ); // doesn't compile because coll2 is const ("assignment of read-only" inside fill_99) + // fill_99( coll2({0, 3}) ); // similar to coll2 | take(3) doesn't compile ("assignment of read-only") + + auto const& coll1_take3_const = coll1({0, 3}); + // fill_99( coll1_take3_const ); // doesn't compile because coll1_take3_const is const ("assignment of read-only") + + (void)coll2, (void)coll1_take3_const, (void)coll1_take3; + } + + BOOST_AUTO_TEST_CASE(const_views_2d) { + multi::array coll1 = { + {0, 8, 15, 47, 11, 42}, + {0, 8, 15, 47, 11, 42}, + }; + + print_2d(coll1); // prints "0, 8, 15, 47, 11, 42" + + print_2d(coll1({0, 2}, {0, 3})); // similar to coll1 | take(3) // prints "0, 8, 15" + + auto&& coll1_take3 = coll1({0, 2}, {0, 3}); + print_2d(coll1_take3); // prints "0, 8, 15" + } + + BOOST_AUTO_TEST_CASE(mutating_views_2d) { + multi::array coll1 = { + {0, 8, 15, 47, 11, 42}, + {0, 8, 15, 47, 11, 42}, + }; + + fill_2d_99(coll1); + fill_2d_99(coll1({0, 2}, {0, 3})); + + auto&& coll1_take3 = coll1({0, 2}, {0, 3}); + fill_2d_99(coll1_take3); + + auto const& coll2 = coll1; + // fill_99( coll2 ); // doesn't compile because coll2 is const ("assignment of read-only" inside fill_99) + // fill_99( coll2({0, 3}) ); // similar to coll2 | take(3) doesn't compile ("assignment of read-only") + + auto const& coll1_take3_const = coll1({0, 2}, {0, 3}); + // fill_99( coll1_take3_const ); // doesn't compile because coll1_take3_const is const ("assignment of read-only") + + (void)coll2, (void)coll1_take3_const, (void)coll1_take3; + } + + { + multi::array arr1d = {1, 2, 3}; - fill_2d_99(coll1); - fill_2d_99(coll1({0, 2}, {0, 3})); + // multi::array::const_iterator cfirst = arr1d.cbegin(); + // *cfirst.base() = 5; + // *cfirst = 5; // correctly fails to compile + // cfirst[0] = 5; // correctly fails to compile - auto&& coll1_take3 = coll1({0, 2}, {0, 3}); - fill_2d_99(coll1_take3); + BOOST_TEST( arr1d[0] == 1 ); + } + { + multi::array const arr1d = {1, 2, 3}; - auto const& coll2 = coll1; - // fill_99( coll2 ); // doesn't compile because coll2 is const ("assignment of read-only" inside fill_99) - // fill_99( coll2({0, 3}) ); // similar to coll2 | take(3) doesn't compile ("assignment of read-only") + // multi::array::iterator cfirst = arr1d.begin(); // correctly fails to compile - auto const& coll1_take3_const = coll1({0, 2}, {0, 3}); - // fill_99( coll1_take3_const ); // doesn't compile because coll1_take3_const is const ("assignment of read-only") + BOOST_TEST( arr1d[0] == 1 ); + } - (void)coll2, (void)coll1_take3_const, (void)coll1_take3; + return boost::report_errors(); } diff --git a/external_codes/boost_multi/multi/test/one_based.cpp b/external_codes/boost_multi/multi/test/one_based.cpp index 8abe3c5829..1a2fb3885c 100644 --- a/external_codes/boost_multi/multi/test/one_based.cpp +++ b/external_codes/boost_multi/multi/test/one_based.cpp @@ -1,134 +1,145 @@ -// Copyright 2019-2023 Alfredo A. Correa +// Copyright 2019-2024 Alfredo A. Correa // Copyright 2024 Matt Borland // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt #include -#include - -// Suppress warnings from boost.test -#if defined(__clang__) -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wold-style-cast" -# pragma clang diagnostic ignored "-Wundef" -# pragma clang diagnostic ignored "-Wconversion" -# pragma clang diagnostic ignored "-Wsign-conversion" -# pragma clang diagnostic ignored "-Wfloat-equal" -#elif defined(__GNUC__) -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wold-style-cast" -# pragma GCC diagnostic ignored "-Wundef" -# pragma GCC diagnostic ignored "-Wconversion" -# pragma GCC diagnostic ignored "-Wsign-conversion" -# pragma GCC diagnostic ignored "-Wfloat-equal" -#endif - -#ifndef BOOST_TEST_MODULE -# define BOOST_TEST_MAIN -#endif - -#include +#include // for equal +#include // for array +#include // for size, begin, end +#include // for is_assignable_v namespace multi = boost::multi; -BOOST_AUTO_TEST_CASE(one_based_1D) { - multi::array const Ac({{0, 10}}, 0.0); - BOOST_REQUIRE( Ac.size() == 10 ); - -// multi::array Af({{1, 1 + 10}}, 0.); -// Af[1] = 1.; -// Af[2] = 2.; -// Af[3] = 3.; - -// BOOST_REQUIRE( Af[1] = 1. ); -// BOOST_REQUIRE( *Af.data_elements() == 1. ); -// BOOST_REQUIRE( size(Af) == 10 ); -// BOOST_REQUIRE( extension(Af).start() == 1 ); -// BOOST_REQUIRE( extension(Af).finish() == 11 ); - -// auto Af1 = multi::array(multi::extensions_t<1>{multi::iextension{10}}, 0.).reindex(1); - -// BOOST_REQUIRE( size(Af1) == 10 ); -// BOOST_REQUIRE( Af1[10] == 0. ); - -// multi::array B({{0, 10}}, 0.); -// B[0] = 1.; -// B[1] = 2.; -// B[2] = 3.; - -// BOOST_REQUIRE( size(B) == 10 ); -// BOOST_REQUIRE( B != Af ); -// BOOST_REQUIRE( std::equal(begin(Af), end(Af), begin(B), end(B) ) ); - -// BOOST_REQUIRE( Af.reindexed(0) == B ); -} +#include +#define BOOST_AUTO_TEST_CASE(CasenamE) /**/ -BOOST_AUTO_TEST_CASE(one_based_2D) { - multi::array const Ac({{0, 10}, {0, 20}}, 0.0); - BOOST_REQUIRE( Ac.size() == 10 ); - -// multi::array Af({{1, 1 + 10}, {1, 1 + 20}}, 0.); -// Af[1][1] = 1.; -// Af[2][2] = 2.; -// Af[3][3] = 3.; -// Af[10][20] = 99.; - -// BOOST_REQUIRE( Af[1][1] = 1. ); -// BOOST_REQUIRE( Af[10][20] == 99. ); -// BOOST_REQUIRE( *Af.data_elements() == 1. ); -// BOOST_REQUIRE( Af.data_elements()[Af.num_elements()-1] == 99. ); -// BOOST_REQUIRE( size(Af) == 10 ); -// BOOST_REQUIRE( extension(Af).start() == 1 ); -// BOOST_REQUIRE( extension(Af).finish() == 11 ); - -// auto Af1 = multi::array({10, 10}, 0.).reindex(1, 1); - -// BOOST_REQUIRE( size(Af1) == 10 ); -// BOOST_REQUIRE( Af1[10][10] == 0. ); - -// multi::array B({{0, 10}, {0, 20}}, 0.); -// B[0][0] = 1.; -// B[1][1] = 2.; -// B[2][2] = 3.; -// B[9][19] = 99.; - -// BOOST_REQUIRE( size(B) == 10 ); -// BOOST_REQUIRE( B != Af ); -// BOOST_REQUIRE( std::equal(begin(Af.reindexed(0, 0)), end(Af.reindexed(0, 0)), begin(B), end(B)) ); -// BOOST_REQUIRE( std::equal(begin(Af), end(Af), begin(B.reindexed(1, 1)), end(B.reindexed(1, 1)) ) ); -// BOOST_REQUIRE( std::equal(begin(Af), end(Af), begin(B.reindexed(0, 1)), end(B.reindexed(0, 1)) ) ); - -// BOOST_REQUIRE( Af.reindexed(0, 0) == B ); - -// B = Af; // TODO(correaa) implement assignment for 1-based arrays -// BOOST_REQUIRE( B[1][1] = 1. ); -// BOOST_REQUIRE( B[10][20] == 99. ); -// BOOST_REQUIRE( B == Af ); -} - -BOOST_AUTO_TEST_CASE(one_base_2D_ref) { - std::array, 3> arr = {{ - {{ 1.0, 2.0, 3.0, 4.0, 5.0}}, - {{ 6.0, 7.0, 8.0, 9.0, 10.0}}, - {{11.0, 12.0, 13.0, 14.0, 15.0}}, +auto main() -> int { // NOLINT(readability-function-cognitive-complexity,bugprone-exception-escape) + BOOST_AUTO_TEST_CASE(one_based_1D) { + // clang-format off + multi::array const Ac({{0, 10}}, 0.0); + // clang-format on + + BOOST_TEST( Ac.size() == 10 ); + + // multi::array Af({{1, 1 + 10}}, 0.); + // Af[1] = 1.; + // Af[2] = 2.; + // Af[3] = 3.; + + // BOOST_TEST( Af[1] = 1. ); + // BOOST_TEST( *Af.data_elements() == 1. ); + // BOOST_TEST( size(Af) == 10 ); + // BOOST_TEST( extension(Af).start() == 1 ); + // BOOST_TEST( extension(Af).finish() == 11 ); + + // auto Af1 = multi::array(multi::extensions_t<1>{multi::iextension{10}}, 0.).reindex(1); + + // BOOST_TEST( size(Af1) == 10 ); + // BOOST_TEST( Af1[10] == 0. ); + + // multi::array B({{0, 10}}, 0.); + // B[0] = 1.; + // B[1] = 2.; + // B[2] = 3.; + + // BOOST_TEST( size(B) == 10 ); + // BOOST_TEST( B != Af ); + // BOOST_TEST( std::equal(begin(Af), end(Af), begin(B), end(B) ) ); + + // BOOST_TEST( Af.reindexed(0) == B ); + } + + BOOST_AUTO_TEST_CASE(one_based_2D) { + multi::array const Ac({ + {0, 10}, + {0, 20} + }, + 0); + BOOST_TEST( Ac.size() == 10 ); + + multi::array Af({ + {1, 1 + 10}, + {1, 1 + 20} + }, + 0); + Af[1][1] = 10; + Af[2][2] = 20; + Af[3][3] = 30; + Af[10][20] = 990; + + BOOST_TEST( Af[1][1] == 10 ); + BOOST_TEST( Af[10][20] == 990 ); + BOOST_TEST( *Af.elements().begin() == 10 ); + BOOST_TEST( Af.elements()[Af.num_elements()-1] == 990 ); + BOOST_TEST( size(Af) == 10 ); + + BOOST_TEST( extension(Af).first() == 1 ); + BOOST_TEST( extension(Af).last() == 11 ); + + auto Af1 = multi::array({10, 10}, 0).reindex(1, 1); + + BOOST_TEST( size(Af1) == 10 ); + BOOST_TEST( Af1[10][10] == 0 ); + + multi::array BB({ + {0, 10}, + {0, 20} + }, + 0); + BB[0][0] = 10; + BB[1][1] = 20; + BB[2][2] = 30; + BB[9][19] = 990; + + BOOST_TEST( BB.size() == 10 ); + BOOST_TEST( BB != Af ); + BOOST_TEST( std::equal(begin(Af.reindexed(0, 0)), end(Af.reindexed(0, 0)), BB.begin(), BB.end()) ); + // BOOST_TEST( std::equal(begin(Af), end(Af), begin(B.reindexed(1, 1)), end(B.reindexed(1, 1)) ) ); + // BOOST_TEST( std::equal(begin(Af), end(Af), begin(B.reindexed(0, 1)), end(B.reindexed(0, 1)) ) ); + + // BOOST_TEST( Af.reindexed(0, 0) == B ); + + // B = Af; // TODO(correaa) implement assignment for 1-based arrays + // BOOST_TEST( B[1][1] = 1. ); + // BOOST_TEST( B[10][20] == 99.0 ); + // BOOST_TEST( B == Af ); + } + + BOOST_AUTO_TEST_CASE(one_base_2D_ref) { + // clang-format off + std::array, 3> arr = {{ + {{ 10, 20, 30, 40, 50 }}, + {{ 60, 70, 80, 90, 100 }}, + {{ 110, 120, 130, 140, 150 }}, }}; - - BOOST_REQUIRE( arr[0][0] == 1.0 ); - -// multi::array_ref const& Ar = *multi::array_ptr(&arr[0][0], {3, 5}); -// BOOST_REQUIRE( &Ar[1][3] == &arr[1][3] ); - -// multi::array_ref const& Ar2 = *multi::array_ptr(&arr[0][0], {{1, 1+3}, {1, 1+5}}); -// BOOST_REQUIRE( sizes(Ar) == sizes(Ar2) ); -// BOOST_REQUIRE( &Ar2[1][1] == &arr[0][0] ); -// BOOST_REQUIRE( &Ar2[2][4] == &arr[1][3] ); - -// BOOST_REQUIRE( Ar2.extensions() != Ar.extensions() ); -// BOOST_REQUIRE( not(Ar2 == Ar) ); -// BOOST_REQUIRE( Ar2 != Ar ); -// BOOST_REQUIRE( extensions(Ar2.reindexed(0, 0)) == extensions(Ar) ); -// BOOST_REQUIRE( Ar2.reindexed(0, 0) == Ar ); - -// static_assert( not std::is_assignable{}, "!" ); + // clang-format on + + BOOST_TEST( arr[0][0] == 10 ); + + multi::array_ref const& Ar = *multi::array_ptr(arr[0].data(), {3, 5}); + BOOST_TEST( &Ar[1][3] == &arr[1][3] ); + + multi::array_ref const& Ar2 = *multi::array_ptr( + arr[0].data(), + { + {1, 1 + 3}, + {1, 1 + 5}, + } + ); + + BOOST_TEST( sizes(Ar) == sizes(Ar2) ); + BOOST_TEST( &Ar2[1][1] == arr[0].data() ); + BOOST_TEST( &Ar2[2][4] == &arr[1][3] ); + + BOOST_TEST( Ar2.extensions() != Ar.extensions() ); + BOOST_TEST( !(Ar2 == Ar) ); + BOOST_TEST( Ar2 != Ar ); + BOOST_TEST( extensions(Ar2.reindexed(0, 0)) == extensions(Ar) ); + BOOST_TEST( Ar2.reindexed(0, 0) == Ar ); + + static_assert(!std::is_assignable_v); + } + return boost::report_errors(); } diff --git a/external_codes/boost_multi/multi/test/overload.cpp b/external_codes/boost_multi/multi/test/overload.cpp index 1f27b32286..06241d1663 100644 --- a/external_codes/boost_multi/multi/test/overload.cpp +++ b/external_codes/boost_multi/multi/test/overload.cpp @@ -1,41 +1,54 @@ -// -*-indent-tabs-mode:t;c-basic-offset:4;tab-width:4;autowrap:nil;-*- -// Copyright 2018-2023 Alfredo A. Correa +// Copyright 2018-2024 Alfredo A. Correa // Copyright 2024 Matt Borland // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt -#include - -#include - -// Suppress warnings from boost.test -#if defined(__clang__) -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wold-style-cast" -# pragma clang diagnostic ignored "-Wundef" -# pragma clang diagnostic ignored "-Wconversion" -# pragma clang diagnostic ignored "-Wsign-conversion" -# pragma clang diagnostic ignored "-Wfloat-equal" -#elif defined(__GNUC__) -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wold-style-cast" -# pragma GCC diagnostic ignored "-Wundef" -# pragma GCC diagnostic ignored "-Wconversion" -# pragma GCC diagnostic ignored "-Wsign-conversion" -# pragma GCC diagnostic ignored "-Wfloat-equal" -#endif - -#ifndef BOOST_TEST_MODULE -# define BOOST_TEST_MAIN -#endif - -#include +// #if defined(__clang__) +// #pragma clang diagnostic push +// #pragma clang diagnostic ignored "-Wunknown-warning-option" +// #pragma clang diagnostic ignored "-Wconversion" +// #pragma clang diagnostic ignored "-Wextra-semi-stmt" +// #pragma clang diagnostic ignored "-Wold-style-cast" +// #pragma clang diagnostic ignored "-Wsign-conversion" +// #pragma clang diagnostic ignored "-Wswitch-default" +// #pragma clang diagnostic ignored "-Wundef" +// #elif defined(__GNUC__) +// #pragma GCC diagnostic push +// #if (__GNUC__ > 7) +// #pragma GCC diagnostic ignored "-Wcast-function-type" +// #endif +// #pragma GCC diagnostic ignored "-Wconversion" +// #pragma GCC diagnostic ignored "-Wold-style-cast" +// #pragma GCC diagnostic ignored "-Wsign-conversion" +// #pragma GCC diagnostic ignored "-Wundef" +// #endif + +// #ifndef BOOST_TEST_MODULE +// #define BOOST_TEST_MAIN +// #endif + +// #include + +// #if defined(__clang__) +// #pragma clang diagnostic pop +// #elif defined(__GNUC__) +// #pragma GCC diagnostic pop +// #endif + +#include // for array + +#include // for complex +#include // for operator==, string namespace multi = boost::multi; -inline auto what_is(multi::array const& /*arr*/) { return std::string{"real"}; } // std::string NOLINT(fuchsia-default-arguments-calls) -inline auto what_is(multi::array, 2> const& /*arr*/) { return std::string{"complex"}; } // std::string NOLINT(fuchsia-default-arguments-calls) +inline auto what_is(multi::array const& /*arr*/) { return std::string{"real"}; } // NOLINT(fuchsia-default-arguments-calls) +inline auto what_is(multi::array, 2> const& /*arr*/) { return std::string{"complex"}; } // NOLINT(fuchsia-default-arguments-calls) +#include +#define BOOST_AUTO_TEST_CASE(CasenamE) /**/ + +auto main() -> int { // NOLINT(readability-function-cognitive-complexity,bugprone-exception-escape) BOOST_AUTO_TEST_CASE(multi_array_overload) { multi::array const real_A({10, 20}); multi::array, 2> const cplx_A({10, 20}); @@ -43,6 +56,7 @@ BOOST_AUTO_TEST_CASE(multi_array_overload) { std::string const real_str = what_is(real_A); std::string const complex_str = what_is(cplx_A); - BOOST_REQUIRE( real_str == "real" ); - BOOST_REQUIRE( complex_str == "complex" ); + BOOST_TEST( real_str == "real" ); + BOOST_TEST( complex_str == "complex" ); } +return boost::report_errors();} diff --git a/external_codes/boost_multi/multi/test/partitioned.cpp b/external_codes/boost_multi/multi/test/partitioned.cpp index 402b0f7f46..06aaf1d23e 100644 --- a/external_codes/boost_multi/multi/test/partitioned.cpp +++ b/external_codes/boost_multi/multi/test/partitioned.cpp @@ -3,174 +3,189 @@ // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt -#include - -#include - -// Suppress warnings from boost.test -#if defined(__clang__) -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wold-style-cast" -# pragma clang diagnostic ignored "-Wundef" -# pragma clang diagnostic ignored "-Wconversion" -# pragma clang diagnostic ignored "-Wsign-conversion" -# pragma clang diagnostic ignored "-Wfloat-equal" -#elif defined(__GNUC__) -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wold-style-cast" -# pragma GCC diagnostic ignored "-Wundef" -# pragma GCC diagnostic ignored "-Wconversion" -# pragma GCC diagnostic ignored "-Wsign-conversion" -# pragma GCC diagnostic ignored "-Wfloat-equal" -#endif +#include // for array, apply, subarray, operator== + +#include // for is_sorted +#include // for array +#include // for ptrdiff_t +// #include +#include // for size +#include // for operator""s, string, string_lite... +#include // for apply // IWYU pragma: keep +#include // for declval, decay_t, decay, decay<>... +#include // for move -#ifndef BOOST_TEST_MODULE -# define BOOST_TEST_MAIN -#endif +namespace multi = boost::multi; -#include +template class propagate_const; -namespace multi = boost::multi; +template class propagate_const { + T& r_; // NOLINT(cppcoreguidelines-avoid-const-or-ref-data-members) -BOOST_AUTO_TEST_CASE(array_partitioned_1d) { - multi::array A1 = {0.0, 1.0, 2.0, 3.0, 4.0, 5.0}; + public: + explicit propagate_const(T& other) : r_{other} {} + propagate_const(propagate_const const&) = delete; + propagate_const(propagate_const&&) = delete; - auto&& A2_ref = A1.partitioned(2); + auto operator=(propagate_const const&) -> propagate_const& = default; + auto operator=(propagate_const&&) noexcept -> propagate_const& = default; - static_assert(std::decay::type::rank{} == decltype(A1)::rank{} + 1); - static_assert(std::decay_t::rank_v == decltype(A1)::rank_v + 1); + auto operator=(T const& other) -> propagate_const& { + r_ = other; + return *this; + } - BOOST_REQUIRE( size(A2_ref ) == 2 ); - BOOST_REQUIRE( size(A2_ref[0]) == 3 ); + ~propagate_const() noexcept = default; - BOOST_REQUIRE( &A2_ref[1][0] == &A1[3] ); + explicit operator T const&() const noexcept { return r_; } + explicit operator T&() noexcept { return r_; } +}; - BOOST_REQUIRE(( A2_ref == multi::array{ {0, 1, 2}, {3, 4, 5} } )); -} +template class propagate_const { + T const& r_; // NOLINT(cppcoreguidelines-avoid-const-or-ref-data-members) -BOOST_AUTO_TEST_CASE(array_partitioned_2d) { - multi::array A2 = { - { 0.0, 1.0, 2.0, 3.0, 4.0, 5.0}, - { 6.0, 7.0, 8.0, 9.0, 10.0, 11.0}, + public: + explicit propagate_const(T const& other) : r_{other} {} + auto operator=(T const& other) -> propagate_const& = delete; + explicit operator T const&() const noexcept { return r_; } +}; - {12.0, 13.0, 14.0, 15.0, 16.0, 17.0}, - {18.0, 19.0, 20.0, 21.0, 22.0, 23.0}, - }; - auto&& A3_ref = A2.partitioned(2); +#include +#define BOOST_AUTO_TEST_CASE(CasenamE) /**/ - static_assert(std::decay_t::rank{} == decltype(A2)::rank{} + 1); - static_assert(std::decay_t::rank_v == decltype(A2)::rank_v + 1); +auto main() -> int { // NOLINT(readability-function-cognitive-complexity,bugprone-exception-escape) + BOOST_AUTO_TEST_CASE(array_partitioned_1d) { + multi::array A1 = {0, 10, 20, 30, 40, 50}; - BOOST_REQUIRE( num_elements(A3_ref) == num_elements(A2) ); - BOOST_REQUIRE( size(A3_ref)==2 ); - BOOST_REQUIRE( size(A3_ref[0])==2 ); - BOOST_REQUIRE( size(A3_ref[0][0])==6 ); - BOOST_REQUIRE( &A3_ref[1][1][0] == &A2[3][0] ); -} + auto&& A2_ref = A1.partitioned(2); -BOOST_AUTO_TEST_CASE(array_partitioned) { - using namespace std::string_literals; // NOLINT(build/namespaces) for ""s + static_assert(std::decay::type::rank{} == decltype(A1)::rank{} + 1); + static_assert(std::decay_t::rank_v == decltype(A1)::rank_v + 1); - multi::array A2 = { - {"s0P0"s, "s1P0"s}, - {"s0P1"s, "s1P1"s}, - {"s0P2"s, "s1P2"s}, - {"s0P3"s, "s1P3"s}, - {"s0P4"s, "s1P4"s}, - {"s0P5"s, "s1P5"s}, - }; + BOOST_TEST( size(A2_ref ) == 2 ); + BOOST_TEST( size(A2_ref[0]) == 3 ); - BOOST_REQUIRE( size(A2) == 6 ); + BOOST_TEST( &A2_ref[1][0] == &A1[3] ); - BOOST_REQUIRE( std::get<0>(A2.sizes()) == 6 ); - BOOST_REQUIRE( std::get<1>(A2.sizes()) == 2 ); + BOOST_TEST(( A2_ref == multi::array{ {0, 10, 20}, {30, 40, 50} } )); + } - BOOST_REQUIRE(( A2.sizes() == decltype(A2.sizes()){6, 2} )); + BOOST_AUTO_TEST_CASE(array_partitioned_2d) { + multi::array A2 = { + { 00, 10, 20, 30, 40, 50}, + { 60, 70, 80, 90, 100, 110}, + + {120, 130, 140, 150, 160, 170}, + {180, 190, 200, 210, 220, 230}, + }; + + BOOST_TEST(( + A2.partitioned(2) == multi::array{ + { + { 00, 10, 20, 30, 40, 50}, + { 60, 70, 80, 90, 100, 110}, + }, + { + {120, 130, 140, 150, 160, 170}, + {180, 190, 200, 210, 220, 230}, + }, + } + )); - BOOST_REQUIRE( std::get<0>(sizes(A2)) == 6 ); - BOOST_REQUIRE( std::get<1>(sizes(A2)) == 2 ); + auto&& A3_ref = A2.partitioned(2); - BOOST_REQUIRE( size(A2.partitioned(3)) == 3 ); + static_assert(std::decay_t::rank{} == decltype(A2)::rank{} + 1); + static_assert(std::decay_t::rank_v == decltype(A2)::rank_v + 1); - static_assert(decltype(A2.partitioned(3))::rank{} == 3); - static_assert(decltype(A2.partitioned(3))::rank::value == 3); - static_assert(decltype(A2.partitioned(3))::rank_v == 3); + BOOST_TEST( num_elements(A3_ref) == num_elements(A2) ); + BOOST_TEST( size(A3_ref) == 2 ); + BOOST_TEST( size(A3_ref[0]) == 2 ); + BOOST_TEST( size(A3_ref[0][0]) == 6 ); + BOOST_TEST( &A3_ref[1][1][0] == &A2[3][0] ); - BOOST_REQUIRE(( sizes(A2.partitioned(3)) == decltype(sizes(A2.partitioned(3))){3, 2, 2} )); + A3_ref[0][0][0] = 99; + } - BOOST_REQUIRE( std::get<0>(sizes(A2.partitioned(3))) == 3 ); - BOOST_REQUIRE( std::get<1>(sizes(A2.partitioned(3))) == 2 ); - BOOST_REQUIRE( std::get<2>(sizes(A2.partitioned(3))) == 2 ); + BOOST_AUTO_TEST_CASE(array_partitioned) { + using namespace std::string_literals; // NOLINT(build/namespaces) for ""s + using std::get; // workaround: function call with explicit template arguments is a C++20 extension [-Wc++20-extensions] - BOOST_REQUIRE( size(A2.partitioned(1)) == 1 ); + // NOLINTBEGIN(misc-include-cleaner) bug in clang-tidy 18 + multi::array A2 = { + {"s0P0"s, "s1P0"s}, + {"s0P1"s, "s1P1"s}, + {"s0P2"s, "s1P2"s}, + {"s0P3"s, "s1P3"s}, + {"s0P4"s, "s1P4"s}, + {"s0P5"s, "s1P5"s}, + }; + // NOLINTEND(misc-include-cleaner) - static_assert(decltype(A2.partitioned(1))::rank{} == 3); - static_assert(decltype(A2.partitioned(1))::rank::value == 3); - static_assert(decltype(A2.partitioned(1))::rank_v == 3); + BOOST_TEST( size(A2) == 6 ); - BOOST_REQUIRE( &A2.partitioned(1).rotated()[3][1][0] == &A2[3][1] ); -} + BOOST_TEST( get<0>(A2.sizes()) == 6 ); + BOOST_TEST( get<1>(A2.sizes()) == 2 ); -template class propagate_const; + BOOST_TEST(( A2.sizes() == decltype(A2.sizes()){6, 2} )); -template class propagate_const { - T& r_; // NOLINT(cppcoreguidelines-avoid-const-or-ref-data-members) + BOOST_TEST( get<0>(A2.sizes()) == 6 ); + BOOST_TEST( get<1>(A2.sizes()) == 2 ); - public: - explicit propagate_const(T& other) : r_{other} {} - propagate_const(propagate_const const&) = delete; - propagate_const(propagate_const&&) = delete; + BOOST_TEST( size(A2.partitioned(3)) == 3 ); - auto operator=(propagate_const const&) -> propagate_const& = default; - auto operator=(propagate_const&&) noexcept -> propagate_const& = default; + static_assert(decltype(A2.partitioned(3))::rank{} == 3); + static_assert(decltype(A2.partitioned(3))::rank::value == 3); + static_assert(decltype(A2.partitioned(3))::rank_v == 3); - auto operator=(T const& other) -> propagate_const& { - r_ = other; - return *this; - } + BOOST_TEST(( sizes(A2.partitioned(3)) == decltype(sizes(A2.partitioned(3))){3, 2, 2} )); - ~propagate_const() noexcept = default; + BOOST_TEST( get<0>(sizes(A2.partitioned(3))) == 3 ); + BOOST_TEST( get<1>(sizes(A2.partitioned(3))) == 2 ); + BOOST_TEST( get<2>(sizes(A2.partitioned(3))) == 2 ); - explicit operator T const&() const noexcept { return r_; } - explicit operator T&() noexcept { return r_; } -}; + BOOST_TEST( size(A2.partitioned(1)) == 1 ); -template class propagate_const { - T const& r_; // NOLINT(cppcoreguidelines-avoid-const-or-ref-data-members) + static_assert(decltype(A2.partitioned(1))::rank{} == 3); + static_assert(decltype(A2.partitioned(1))::rank::value == 3); + static_assert(decltype(A2.partitioned(1))::rank_v == 3); - public: - explicit propagate_const(T const& other) : r_{other} {} - auto operator=(T const& other) -> propagate_const& = delete; - explicit operator T const&() const noexcept { return r_; } -}; + BOOST_TEST( &A2.partitioned(1).rotated()[3][1][0] == &A2[3][1] ); + } -BOOST_AUTO_TEST_CASE(array_encoded_subarray) { - // arr[walker][encoded_property] // 7 walkers - multi::array arr = { - {990, 990, 1000, 001, 10, 11, 20, 21, 990}, - {990, 990, 100, 101, 110, 111, 120, 121, 990}, - {990, 990, 200, 201, 210, 211, 220, 221, 990}, - {990, 990, 300, 301, 310, 311, 320, 321, 990}, - {990, 990, 400, 401, 410, 411, 420, 421, 990}, - {990, 990, 500, 501, 510, 511, 520, 521, 990}, - {990, 990, 600, 601, 610, 611, 620, 621, 990}, - }; + BOOST_AUTO_TEST_CASE(array_encoded_subarray) { + using std::get; // workaround: function call with explicit template arguments is a C++20 extension [-Wc++20-extensions] - multi::iextension const encoded_3x2_range = {2, 8}; + // arr[walker][encoded_property] // 7 walkers + multi::array arr = { + {990, 990, 1000, 001, 10, 11, 20, 21, 990}, + {990, 990, 100, 101, 110, 111, 120, 121, 990}, + {990, 990, 200, 201, 210, 211, 220, 221, 990}, + {990, 990, 300, 301, 310, 311, 320, 321, 990}, + {990, 990, 400, 401, 410, 411, 420, 421, 990}, + {990, 990, 500, 501, 510, 511, 520, 521, 990}, + {990, 990, 600, 601, 610, 611, 620, 621, 990}, + }; - auto&& arrRPU = arr.rotated()(encoded_3x2_range).partitioned(3).unrotated(); + // multi::iextension const encoded_3x2_range = {2, 8}; - static_assert(decltype(+arrRPU)::rank::value == 3); - static_assert(decltype(+arrRPU)::rank{} == 3); - static_assert(decltype(+arrRPU)::rank_v == 3); + auto&& arrRPU = arr.rotated().sliced(2, 8).partitioned(3).unrotated(); - BOOST_REQUIRE(( sizes(arrRPU) == decltype(sizes(arrRPU)){7, 3, 2} )); - BOOST_REQUIRE( arrRPU[4].num_elements() == 3*2L ); + static_assert(decltype(+arrRPU)::rank::value == 3); + static_assert(decltype(+arrRPU)::rank{} == 3); + static_assert(decltype(+arrRPU)::rank_v == 3); - BOOST_REQUIRE( &arrRPU[4][1][0] == &arr[4][4] ); - BOOST_REQUIRE( arrRPU[4][1][0] == 410 ); + BOOST_TEST( get<0>(arrRPU.sizes()) == 7 ); + BOOST_TEST( get<1>(arrRPU.sizes()) == 3 ); + BOOST_TEST( get<2>(arrRPU.sizes()) == 2 ); - BOOST_REQUIRE(( + BOOST_TEST(( arrRPU.sizes() == decltype(arrRPU.sizes()){7, 3, 2} )); + BOOST_TEST(( sizes(arrRPU) == decltype(sizes(arrRPU)){7, 3, 2} )); + BOOST_TEST( arrRPU[4].num_elements() == 3*2L ); + + BOOST_TEST( &arrRPU[4][1][0] == &arr[4][4] ); + BOOST_TEST( arrRPU[4][1][0] == 410 ); + + BOOST_TEST(( arrRPU[4] == multi::array{ {400, 401}, {410, 411}, @@ -178,81 +193,194 @@ BOOST_AUTO_TEST_CASE(array_encoded_subarray) { } )); - arrRPU[4][1][0] = 11110; - BOOST_REQUIRE( arr[4][4] == 11110 ); + arrRPU[4][1][0] = 11110; + BOOST_TEST( arr[4][4] == 11110 ); - class walker_ref { - using raw_source_reference = decltype(std::declval&>()[0]); - using internal_array_type = decltype(std::declval()({2, 8}).partitioned(3)); + class walker_ref { + using raw_source_reference = decltype(std::declval&>()[0]); + using internal_array_type = decltype(std::declval().sliced(2, 8).partitioned(3)); - public: // NOLINT(whitespace/indent) bug in cpplint - propagate_const prop1; // NOLINT(misc-non-private-member-variables-in-classes) - propagate_const prop2; // NOLINT(misc-non-private-member-variables-in-classes) - internal_array_type slater_array; // NOLINT(misc-non-private-member-variables-in-classes) - propagate_const prop3; // NOLINT(misc-non-private-member-variables-in-classes) + public: // NOLINT(whitespace/indent) bug in cpplint + propagate_const prop1; // NOLINT(misc-non-private-member-variables-in-classes) + propagate_const prop2; // NOLINT(misc-non-private-member-variables-in-classes) + internal_array_type slater_array; // NOLINT(misc-non-private-member-variables-in-classes) + propagate_const prop3; // NOLINT(misc-non-private-member-variables-in-classes) - explicit walker_ref(raw_source_reference&& row) : prop1{row[0]}, prop2{row[1]}, slater_array{row({2, 8}).partitioned(3)}, prop3{std::move(row)[8]} {} - }; + explicit walker_ref(raw_source_reference&& row) + : prop1{row[0]}, prop2{row[1]}, slater_array{row.sliced(2, 8).partitioned(3)}, prop3{std::move(row)[8]} {} + }; - auto&& wr = walker_ref(arr[5]); + auto&& wr = walker_ref(arr[5]); - wr.prop1 = 88; + wr.prop1 = 88; - BOOST_REQUIRE( wr.slater_array[2][1] == 521 ); + BOOST_TEST( wr.slater_array[2][1] == 521 ); - wr.slater_array[2][1] = 99990; -} - -BOOST_AUTO_TEST_CASE(array_partitioned_add_to_last) { - multi::array arr = { - { - { 0.0, 1.0, 2.0, 3.0, 4.0, 5.0}, - { 6.0, 7.0, 8.0, 9.0, 10.0, 11.0}, - { 12.0, 13.0, 14.0, 15.0, 16.0, 17.0}, - { 18.0, 19.0, 20.0, 21.0, 22.0, 23.0}, - }, - { - { 0.0, 1.0, 2.0, 3.0, 4.0, 5.0}, - { 6.0, 7.0, 8.0, 9.0, 10.0, 11.0}, - { 12.0, 13.0, 14.0, 15.0, 16.0, 17.0}, - { 18.0, 19.0, 20.0, 21.0, 22.0, 23.0}, - } - }; - - auto strides = std::apply([](auto... strds) { return std::array{{strds...}}; }, arr.layout().strides()); - // auto strides = std::apply([](auto... strds) { return std::array{{strds...}}; }, arr.strides()); + // what( wr , wr.slater_array, wr.slater_array[2][1] ); + wr.slater_array[2][1] = 99990; + } - BOOST_REQUIRE( std::is_sorted(strides.rbegin(), strides.rend()) && arr.num_elements() == arr.nelems() ); // contiguous c-ordering + BOOST_AUTO_TEST_CASE(array_partitioned_add_to_last) { + multi::array arr = { + { + {0.0, 1.0, 2.0, 3.0, 4.0, 5.0}, + {6.0, 7.0, 8.0, 9.0, 10.0, 11.0}, + {12.0, 13.0, 14.0, 15.0, 16.0, 17.0}, + {18.0, 19.0, 20.0, 21.0, 22.0, 23.0}, + }, + { + {0.0, 1.0, 2.0, 3.0, 4.0, 5.0}, + {6.0, 7.0, 8.0, 9.0, 10.0, 11.0}, + {12.0, 13.0, 14.0, 15.0, 16.0, 17.0}, + {18.0, 19.0, 20.0, 21.0, 22.0, 23.0}, + }, + }; + + auto strides = std::apply([](auto... strds) { return std::array{{strds...}}; }, arr.layout().strides()); + // auto strides = std::apply([](auto... strds) { return std::array{{strds...}}; }, arr.strides()); + + BOOST_TEST( std::is_sorted(strides.rbegin(), strides.rend()) && arr.num_elements() == arr.nelems() ); // contiguous c-ordering #ifndef _MSC_VER // problem with MSVC 14.3 c++17 - auto&& A4 = arr.reinterpret_array_cast(1); + auto&& A4 = arr.reinterpret_array_cast(1); - BOOST_REQUIRE(( arr.extensions() == decltype(arr.extensions()){2, 4, 6} )); - BOOST_REQUIRE(( A4.extensions() == decltype(A4.extensions()){2, 4, 6, 1} )); + BOOST_TEST(( arr.extensions() == decltype(arr.extensions()){2, 4, 6} )); + BOOST_TEST(( A4.extensions() == decltype(A4.extensions()){2, 4, 6, 1} )); -// BOOST_REQUIRE( A4.is_flattable() ); -// BOOST_REQUIRE( A4.flatted().is_flattable() ); + // BOOST_TEST( A4.is_flattable() ); + // BOOST_TEST( A4.flatted().is_flattable() ); - BOOST_REQUIRE( &A4[1][2][3][0] == &arr[1][2][3] ); + BOOST_TEST( &A4[1][2][3][0] == &arr[1][2][3] ); #endif -} + } -BOOST_AUTO_TEST_CASE(array_partitioned_vs_chunked_1D) { - multi::array arr = {0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0}; - BOOST_REQUIRE( size(arr.partitioned(3)) == 3 ); - BOOST_REQUIRE( arr.partitioned(3)[1] == decltype(+arr.partitioned(3)[1])({4.0, 5.0, 6.0, 7.0}) ); - BOOST_REQUIRE( &arr.partitioned(3)[1][2] == &arr[6] ); + BOOST_AUTO_TEST_CASE(array_partitioned_vs_chunked_1D) { + multi::array arr = {0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0}; + BOOST_TEST( size(arr.partitioned(3)) == 3 ); + BOOST_TEST(( arr.partitioned(3)[1] == multi::array{4.0, 5.0, 6.0, 7.0} )); + BOOST_TEST( &arr.partitioned(3)[1][2] == &arr[6] ); - BOOST_REQUIRE( size(arr.chunked(3)) == 4 ); - BOOST_REQUIRE( arr.chunked(3)[1] == decltype(+arr.chunked(3)[1])({3.0, 4.0, 5.0}) ); - BOOST_REQUIRE( &arr.chunked(3)[1][2] == &arr[5] ); -} + BOOST_TEST( size(arr.chunked(3)) == 4 ); + BOOST_TEST(( arr.chunked(3)[1] == multi::array({3.0, 4.0, 5.0}) )); + BOOST_TEST( &arr.chunked(3)[1][2] == &arr[5] ); + } + + BOOST_AUTO_TEST_CASE(array_partitioned_vs_chunked_2D) { + multi::array arr({100, 53}); + BOOST_TEST( arr.partitioned(20).size() == 20 ); + BOOST_TEST( &arr.partitioned(20)[1][2] == &arr[7] ); + + BOOST_TEST( size(arr.chunked(5)) == 20 ); + BOOST_TEST( &arr.chunked(5)[1][2] == &arr[7] ); + } + + BOOST_AUTO_TEST_CASE(chunked_subarrays) { + using std::get; // workaround: function call with explicit template arguments is a C++20 extension [-Wc++20-extensions] + + multi::array const arr = { + { 0, 1, /**/ 2, 3, /**/ 4, 5}, + { 6, 7, /**/ 8, 9, /**/ 10, 11}, + /*********************************/ + {12, 13, /**/ 14, 15, /**/ 16, 17}, + {18, 19, /**/ 20, 21, /**/ 22, 23}, + /*********************************/ + {24, 25, /**/ 26, 27, /**/ 28, 29}, + {30, 31, /**/ 32, 33, /**/ 34, 35}, + /*********************************/ + {36, 37, /**/ 38, 39, /**/ 40, 41}, + {42, 43, /**/ 44, 45, /**/ 46, 47} + }; + + BOOST_TEST( arr.dimensionality == 2 ); + BOOST_TEST( arr.size() == 8 ); + BOOST_TEST( get<1>(arr.sizes()) == 6 ); + + BOOST_TEST( arr.chunked(2).dimensionality == 3 ); + BOOST_TEST( arr.chunked(2).size() == 4 ); + BOOST_TEST( get<1>(arr.chunked(2).sizes()) == 2 ); + BOOST_TEST( get<2>(arr.chunked(2).sizes()) == 6 ); + + auto const&& block_arr = arr.chunked(2).rotated().rotated().chunked(2).transposed().rotated().transposed(); + BOOST_TEST( block_arr.dimensionality == 4 ); + + BOOST_TEST( block_arr.size() == 4 ); + BOOST_TEST( get<1>(block_arr.sizes()) == 3 ); + BOOST_TEST( get<2>(block_arr.sizes()) == 2 ); + BOOST_TEST( get<3>(block_arr.sizes()) == 2 ); + + BOOST_TEST(( + block_arr[2][1] + == + multi::array{ + {26, 27}, + {32, 33} + } + )); + } + + BOOST_AUTO_TEST_CASE(partitined_subarrays) { + using std::get; // workaround: function call with explicit template arguments is a C++20 extension [-Wc++20-extensions] + + multi::array const arr = { + { 0, 1, /**/ 2, 3, /**/ 4, 5}, + { 6, 7, /**/ 8, 9, /**/ 10, 11}, + /******************************************/ + {12, 13, /**/ 14, 15, /**/ 16, 17}, + {18, 19, /**/ 20, 21, /**/ 22, 23}, + /******************************************/ + {24, 25, /**/ 26, 27, /**/ 28, 29}, + {30, 31, /**/ 32, 33, /**/ 34, 35}, + /******************************************/ + {36, 37, /**/ 38, 39, /**/ 40, 41}, + {42, 43, /**/ 44, 45, /**/ 46, 47} + }; + + BOOST_TEST( arr.dimensionality == 2 ); + BOOST_TEST( arr.partitioned(4).dimensionality == 3 ); + + BOOST_TEST( arr.partitioned(4).size() == 4 ); + BOOST_TEST( get<1>(arr.partitioned(4).sizes()) == 2 ); + BOOST_TEST( get<2>(arr.partitioned(4).sizes()) == 6 ); + + auto const&& block_arr = arr.partitioned(4).rotated().rotated().partitioned(3).transposed().rotated().transposed(); + BOOST_TEST( block_arr.dimensionality == 4 ); + + BOOST_TEST( block_arr.size() == 4 ); + BOOST_TEST( get<1>(block_arr.sizes()) == 3 ); + BOOST_TEST( get<2>(block_arr.sizes()) == 2 ); + BOOST_TEST( get<3>(block_arr.sizes()) == 2 ); + + BOOST_TEST(( + block_arr[2][1] + == + multi::array{ + {26, 27}, + {32, 33} + } + )); + } + + BOOST_AUTO_TEST_CASE(tiled_1D) { + multi::array const arr = {0, 1, 2, /**/ 3, 4, 5, /**/ 6, 7}; + + BOOST_TEST( arr.size() == 8 ); -BOOST_AUTO_TEST_CASE(array_partitioned_vs_chunked_2D) { - multi::array arr({100, 53}); - BOOST_REQUIRE( size(arr.partitioned(20)) == 20 ); - BOOST_REQUIRE( &arr.partitioned(20)[1][2] == &arr[7] ); + BOOST_TEST(( arr.tiled(3).quotient[0].size() == 3 )); + BOOST_TEST(( arr.tiled(3).quotient[1].size() == 3 )); + + BOOST_TEST(( arr.tiled(3).remainder.size() == 2 )); + + auto [tiles, border] = arr.tiled(3); + BOOST_TEST( tiles.size() == 2 ); + BOOST_TEST(( tiles[0].size() == 3 )); + BOOST_TEST(( tiles[1].size() == 3 )); + + BOOST_TEST(( tiles[0] == multi::array{0, 1, 2} )); + BOOST_TEST(( tiles[1] == multi::array{3, 4, 5} )); + + BOOST_TEST( border.size() == 2 ); + BOOST_TEST(( border == multi::array{6, 7} )); + } - BOOST_REQUIRE( size(arr.chunked(5)) == 20 ); - BOOST_REQUIRE( &arr.chunked(5)[1][2] == &arr[7] ); + return boost::report_errors(); } diff --git a/external_codes/boost_multi/multi/test/pmr.cpp b/external_codes/boost_multi/multi/test/pmr.cpp index db410edfcc..6fdd2bef59 100644 --- a/external_codes/boost_multi/multi/test/pmr.cpp +++ b/external_codes/boost_multi/multi/test/pmr.cpp @@ -3,124 +3,129 @@ // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt -#include - -#include - -// Suppress warnings from boost.test -#if defined(__clang__) -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wold-style-cast" -# pragma clang diagnostic ignored "-Wundef" -# pragma clang diagnostic ignored "-Wconversion" -# pragma clang diagnostic ignored "-Wsign-conversion" -# pragma clang diagnostic ignored "-Wfloat-equal" -#elif defined(__GNUC__) -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wold-style-cast" -# pragma GCC diagnostic ignored "-Wundef" -# pragma GCC diagnostic ignored "-Wconversion" -# pragma GCC diagnostic ignored "-Wsign-conversion" -# pragma GCC diagnostic ignored "-Wfloat-equal" -#elif defined(_MSC_VER) -# pragma warning(push) -# pragma warning(disable : 4244) // narrowing conversion +#include // for array, extension_t, static_array + +#include // for fill_n +#include // for high_resolution_clock, operator- // NOLINT(build/c++11) +#include // for abs // IWYU pragma: keep +// IWYU pragma: no_include // for abs +#include // for int64_t +#include // for plus // IWYU pragma: keep +#include // for char_traits, basic_ostream, oper... +#include // for size, data + +#if __has_include() + #include // for polymorphic_allocator, monotonic... #endif -#ifndef BOOST_TEST_MODULE -# define BOOST_TEST_MAIN -#endif - -#include +#include // for accumulate, transform_reduce namespace multi = boost::multi; -BOOST_AUTO_TEST_CASE(pmr_dummy) { -} +#include +#define BOOST_AUTO_TEST_CASE(CasenamE) /**/ + +auto main() -> int { // NOLINT(readability-function-cognitive-complexity,bugprone-exception-escape) + BOOST_AUTO_TEST_CASE(dummy_test) { + } #ifdef BOOST_MULTI_HAS_MEMORY_RESOURCE -BOOST_AUTO_TEST_CASE(pmr_partially_formed) { - { - char buffer[] = "0123456789012345678901234567890123456789012345678901234567890123456789"; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) use raw memory + BOOST_AUTO_TEST_CASE(pmr_partially_formed) { + { + #if defined(__clang__) + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wunknown-warning-option" + #pragma clang diagnostic ignored "-Wunsafe-buffer-usage" + #endif + + // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) use raw memory + char buffer[] = "0123456789012345678901234567890123456789012345678901234567890123456789"; + + std::pmr::monotonic_buffer_resource mbr{std::data(buffer), std::size(buffer)}; + static_assert(std::size(buffer) > 6 * sizeof(double)); + + multi::array> const arr({2, 3}, &mbr); + BOOST_TEST( buffer[ 0] == '0' ); // buffer is intact when initializing without value + BOOST_TEST( buffer[13] == '3' ); + + #if defined(__clang__) + #pragma clang diagnostic pop + #endif + + BOOST_TEST( arr.num_elements() == 2*3L ); + // BOOST_TEST( arr[0][0] != 0.0 ); + // BOOST_TEST( arr[1][2] != 0.0 ); + } + { + // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) use raw memory + char buffer[] = "0123456789012345678901234567890123456789012345678901234567890123456789"; - std::pmr::monotonic_buffer_resource mbr{std::data(buffer), std::size(buffer)}; - static_assert( std::size(buffer) > 6*sizeof(double) ); + std::pmr::monotonic_buffer_resource mbr(std::data(buffer), std::size(buffer)); + static_assert(std::size(buffer) > 6 * sizeof(double)); - multi::array> const arr({2, 3}, &mbr); - BOOST_TEST( buffer[ 0] == '0' ); // buffer is intact when initializing without value - BOOST_TEST( buffer[13] == '3' ); + multi::array> A({2, 3}, 0.0, &mbr); // NOLINT(readability-identifier-length) - BOOST_TEST( arr.num_elements() == 2*3 ); - // BOOST_TEST( arr[0][0] != 0.0 ); - // BOOST_TEST( arr[1][2] != 0.0 ); - } - { - char buffer[] = "0123456789012345678901234567890123456789012345678901234567890123456789"; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) use raw memory + BOOST_TEST( std::abs( A[0][0] - 0.0 ) < 1E-6 ); + BOOST_TEST( std::abs( A[1][2] - 0.0 ) < 1E-6 ); + } + { + // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) use raw memory + char buffer[] = "0123456789012345678901234567890123456789012345678901234567890123456789"; - std::pmr::monotonic_buffer_resource mbr(std::data(buffer), std::size(buffer)); - static_assert( std::size(buffer) > 6*sizeof(double) ); + std::pmr::monotonic_buffer_resource mbr(std::data(buffer), std::size(buffer)); + static_assert(std::size(buffer) > 6 * sizeof(double)); - multi::array> A({2, 3}, 0.0, &mbr); // NOLINT(readability-identifier-length) - // BOOST_TEST( buffer[ 0] != '0' ); // buffer not is intact when initializing with value - // BOOST_TEST( buffer[13] != '3' ); + multi::array> arr({2, 3}, {}, &mbr); - BOOST_TEST( A[0][0] == 0.0 ); - BOOST_TEST( A[1][2] == 0.0 ); - } - { - char buffer[] = "0123456789012345678901234567890123456789012345678901234567890123456789"; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) use raw memory + BOOST_TEST( std::abs( arr[0][0] - double{} ) < 1E-6 ); + BOOST_TEST( std::abs( arr[1][2] - double{} ) < 1E-6 ); + } + { + // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) use raw memory + char buffer[] = "0123456789012345678901234567890123456789012345678901234567890123456789"; - std::pmr::monotonic_buffer_resource mbr(std::data(buffer), std::size(buffer)); - static_assert( std::size(buffer) > 6*sizeof(double) ); + std::pmr::monotonic_buffer_resource mbr{std::data(buffer), std::size(buffer)}; + static_assert(std::size(buffer) > 6 * sizeof(double)); - multi::array> arr({2, 3}, {}, &mbr); - // BOOST_TEST( buffer[ 0] != '0' ); // buffer not is intact when initializing with value - // BOOST_TEST( buffer[13] != '3' ); + multi::array> arr({2, 3}, 666.0, &mbr); - BOOST_TEST( arr[0][0] == double{} ); - BOOST_TEST( arr[1][2] == double{} ); + BOOST_TEST( std::abs( arr[0][0] - 666.0 ) < 1E-6 ); + BOOST_TEST( std::abs( arr[1][2] - 666.0 ) < 1E-6 ); + } } - { - char buffer[] = "0123456789012345678901234567890123456789012345678901234567890123456789"; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) use raw memory - std::pmr::monotonic_buffer_resource mbr{std::data(buffer), std::size(buffer)}; - static_assert( std::size(buffer) > 6*sizeof(double) ); + #ifndef _MSC_VER // problems with MSVC 14.3 c++17 + BOOST_AUTO_TEST_CASE(pmr_benchmark) { + // auto* resp = std::pmr::unsynchronized_pool_resource(std::pmr::get_default_resource()); + auto* resp = std::pmr::get_default_resource(); - multi::array> arr({2, 3}, 666.0, &mbr); - // BOOST_TEST( buffer[ 0] != '0' ); // buffer not is intact when initializing with value - // BOOST_TEST( buffer[13] != '3' ); + auto count = 50; - BOOST_TEST( arr[0][0] == 666.0 ); - BOOST_TEST( arr[1][2] == 666.0 ); - } -} + auto start_time = std::chrono::high_resolution_clock::now(); -#ifndef _MSC_VER // problems with MSVC 14.3 c++17 -BOOST_AUTO_TEST_CASE(pmr_benchmark) { - // auto* resp = std::pmr::unsynchronized_pool_resource(std::pmr::get_default_resource()); - auto* resp = std::pmr::get_default_resource(); - - auto count = 50; - auto start_time = std::chrono::high_resolution_clock::now(); - - multi::extension_t const exts{0, count}; - auto acc = std::transform_reduce( - exts.begin(), exts.end(), int64_t{0}, - std::plus<>{}, - [&resp](auto idx) { - multi::array> arr( - multi::extensions_t<2>{1000 - idx%10, 1000 + idx%10}, // MSVC needs multi::extensions_t<2> - resp - ); - std::fill_n(arr.data_elements(), arr.num_elements(), 1); - auto* be = arr.data_elements(); - decltype(be) en = arr.data_elements() + arr.num_elements(); - return std::accumulate(be, en, int64_t{}, std::plus{}); - } - ); + multi::extension_t const exts{0, count}; + + auto acc = std::transform_reduce( + exts.begin(), exts.end(), int64_t{0}, + std::plus<>{}, + [&resp](auto idx) { + multi::array> arr( + multi::extensions_t<2>{1000 - idx % 10, 1000 + idx % 10}, // MSVC needs multi::extensions_t<2> + resp + ); + std::fill_n(arr.data_elements(), arr.num_elements(), 1); + + auto const be = arr.elements().begin(); + auto const en = arr.elements().end(); + return std::accumulate(be, en, int64_t{0}, std::plus{}); + } + ); + + auto time = std::chrono::high_resolution_clock::now() - start_time; + std::cout << time.count() / count << " " << acc << '\n'; + } + #endif - auto time = std::chrono::high_resolution_clock::now() - start_time; - std::cout<< time.count() / count <<" "<< acc << '\n'; -} -#endif #endif + return boost::report_errors(); +} diff --git a/external_codes/boost_multi/multi/test/ranges.cpp b/external_codes/boost_multi/multi/test/ranges.cpp index d06d7aad4d..376b9cd6d8 100644 --- a/external_codes/boost_multi/multi/test/ranges.cpp +++ b/external_codes/boost_multi/multi/test/ranges.cpp @@ -3,112 +3,120 @@ // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt -#include - -#include // for std::ranges::fold_left - -// Suppress warnings from boost.test -#if defined(__clang__) -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wold-style-cast" -#pragma clang diagnostic ignored "-Wundef" -#pragma clang diagnostic ignored "-Wconversion" -#pragma clang diagnostic ignored "-Wsign-conversion" -#elif defined(__GNUC__) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wold-style-cast" -#pragma GCC diagnostic ignored "-Wundef" -#pragma GCC diagnostic ignored "-Wconversion" -#pragma GCC diagnostic ignored "-Wsign-conversion" -#endif +#include -#ifndef BOOST_TEST_MODULE -#define BOOST_TEST_MAIN -#endif +#include // for std::ran // IWYU pragma: keep // NOLINT(misc-include-cleaner) -#include +#include // for array, subarray, static_array // IWYU pragma: keep -#if defined(__clang__) -#pragma clang diagnostic pop -#elif defined(__GNUC__) -#pragma GCC diagnostic pop +#if defined(__cpp_lib_ranges_fold) && (__cpp_lib_ranges_fold >= 202207L) + #include // for complex, real, operator==, imag // IWYU pragma: keep + #include // for size, begin, end // IWYU pragma: keep + #include // for iota // IWYU pragma: keep + #include // for is_same_v // IWYU pragma: keep + #include // for pair // IWYU pragma: keep #endif -BOOST_AUTO_TEST_CASE(range_accumulate) { +#define BOOST_AUTO_TEST_CASE(CasenamE) /**/ + +auto main() -> int { // NOLINT(readability-function-cognitive-complexity,bugprone-exception-escape) + { + namespace multi = boost::multi; + multi::array const arr({10}, 99); + for(auto const& elem : arr) { // NOLINT(altera-unroll-loops) test plain loop + BOOST_TEST( elem == 99 ); + } + } + // range accumulate + { #if defined(__cpp_lib_ranges_fold) && (__cpp_lib_ranges_fold >= 202207L) - namespace multi = boost::multi; + namespace multi = boost::multi; - static constexpr auto accumulate = [](auto const& R) { return std::ranges::fold_left(R, 0, std::plus<>{}); }; + static constexpr auto accumulate = [](auto const& R) { + return std::ranges::fold_left(R, 0, std::plus<>{}); + }; - auto const values = multi::array{ - {2, 0, 2, 2}, - {2, 2, 0, 4}, - {2, 2, 0, 4}, - {2, 2, 0, 0}, - {2, 7, 0, 2}, - {2, 2, 4, 4}, - }; + auto const values = multi::array{ + {2, 0, 2, 2}, + {2, 2, 0, 4}, + {2, 2, 0, 4}, + {2, 2, 0, 0}, + {2, 7, 0, 2}, + {2, 2, 4, 4}, + }; - boost::multi::array> aaa = {1, 2, 3}; + boost::multi::array> aaa = {1, 2, 3}; - constexpr auto rowOddSum = [](auto const& arr) { - return std::ranges::find_if(arr, [](auto const& row) { return (accumulate(row) & 1) == 1; }); - }; + constexpr auto rowOddSum = [](auto const& arr) { + return std::ranges::find_if(arr, [](auto const& row) { return (accumulate(row) & 1) == 1; }); + }; - auto const result = rowOddSum(values); + auto const result = rowOddSum(values); - BOOST_REQUIRE( result - values.begin() == 4 ); + BOOST_TEST( result - values.begin() == 4 ); #endif -} + } -BOOST_AUTO_TEST_CASE(range_find) { + BOOST_AUTO_TEST_CASE(range_find) { #if defined(__cpp_lib_ranges_fold) && (__cpp_lib_ranges_fold >= 202207L) - namespace multi = boost::multi; - - using Array2D = multi::array; - - Array2D const a = { - {1, 2}, - {3, 4}, - }; - { - auto const needle = std::ranges::find_if(a, [](auto const& row) { return row[0] == 9; }); - BOOST_REQUIRE(needle == a.end()); + namespace multi = boost::multi; + + using Array2D = multi::array; + + Array2D const a = { + {1, 2}, + {3, 4}, + }; + { + auto const needle = std::ranges::find_if(a, [](auto const& row) { return row[0] == 9; }); + BOOST_TEST(needle == a.end()); + } + { + std::ranges::equal_to eto; + + auto a1 = a[1]; + auto a1_val = +a[1]; + + bool const res = eto(a1_val, a1); + BOOST_TEST( res ); + } + { + auto&& a1 = a[1]; + + auto const needle = std::ranges::find(a, a1); + BOOST_TEST(needle != a.end()); + BOOST_TEST( *needle == a1 ); + BOOST_TEST( *needle == a[1] ); + } + [&] { + auto const needle = std::ranges::find(a, a[1]); + BOOST_TEST(needle != a.end()); + BOOST_TEST( *needle == a[1] ); + }(); +#endif } - { - std::ranges::equal_to eto; - auto a2 = a(); + // #if defined(__cpp_lib_ranges) && (__cpp_lib_ranges >= 201911L) + // BOOST_AUTO_TEST_CASE(range_copy_n_1D) { + // namespace multi = boost::multi; - [[maybe_unused]] auto const& _84 = static_cast> const&>(a); - [[maybe_unused]] auto const& _85 = static_cast> const&>(std::as_const(a)); + // multi::array const X1 = {1, 2, 3}; + // multi::array X2(X1.extensions()); - auto a1 = a[1]; - auto a1_val = +a[1]; + // std::ranges::copy_n(X1.begin(), 10, X2.begin()); - // [[maybe_unused]] auto const& _90 = static_cast>&>(a1_val); - // [[maybe_unused]] auto const& _91 = static_cast>&>(std::as_const(a1_val)); + // BOOST_TEST( X1 == X2 ); + // } - // static_assert( std::convertible_to>&, const boost::multi::subarray>&> ); - // static_assert( std::equality_comparable_with>&,boost::multi::subarray>&> ); - - bool const res = eto(a1_val, a1); - BOOST_REQUIRE( res ); - // std::ranges::equal_to&,boost::multi::array>&,boost::multi::subarray>& - } + // BOOST_AUTO_TEST_CASE(range_copy_n) { + // namespace multi = boost::multi; - { - auto&& a1 = a[1]; - auto const needle = std::ranges::find(a, a1); - BOOST_REQUIRE(needle != a.end()); - BOOST_REQUIRE( *needle == a1 ); - BOOST_REQUIRE( *needle == a[1] ); - } + // multi::array const X1({ 10, 10 }, 99); + // multi::array X2(X1.extensions()); - { - auto const needle = std::ranges::find(a, a[1]); - BOOST_REQUIRE(needle != a.end()); - BOOST_REQUIRE( *needle == a[1] ); - } -#endif + // std::ranges::copy_n(X1.begin(), 10, X2.begin()); + // BOOST_TEST( X1 == X2 ); + // } + // #endif + return boost::report_errors(); } diff --git a/external_codes/boost_multi/multi/test/redux.cpp b/external_codes/boost_multi/multi/test/redux.cpp new file mode 100644 index 0000000000..def05bd8d0 --- /dev/null +++ b/external_codes/boost_multi/multi/test/redux.cpp @@ -0,0 +1,411 @@ +// Copyright 2018-2024 Alfredo A. Correa +// Copyright 2024 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#if defined(__GNUC__) + #pragma GCC diagnostic ignored "-Wdouble-promotion" +#endif + +#include // IWYU pragma: keep +#include // for array, implicit_cast, explicit_cast + +#include + +#include // IWYU pragma: keep +#include // NOLINT(build/c++11) +#include // IWYU pragma: keep +#include +#include // IWYU pragma: keep +#include +#include +// IWYU pragma: no_include // for abs + +// IWYU pragma: no_include // for reduce, transform_reduce +// IWYU pragma: no_include // for abs +// IWYU pragma: no_include // for bad_alloc + +#ifndef __NVCC__ + #if defined(__has_include) && __has_include() && (!defined(__INTEL_LLVM_COMPILER) || (__INTEL_LLVM_COMPILER > 20240000)) + #if !(defined(__clang__) && defined(__CUDA__)) + #include // IWYU pragma: keep + #endif + #endif +#endif + +namespace multi = boost::multi; + +class watch { + std::chrono::time_point start_ = std::chrono::high_resolution_clock::now(); + + std::string msg_; + + public: + explicit watch(std::string_view msg) : msg_(msg) {} // NOLINT(fuchsia-default-arguments-calls) + ~watch() { + std::cerr << msg_ << ": " << std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - start_).count() << " ms\n"; + } + watch(watch const&) = delete; + watch(watch&&) = delete; + auto operator=(watch const&) = delete; + auto operator=(watch&&) = delete; + // non-default destructor but does not define a copy constructor, a copy assignment operator, a move constructor or a move assignment operator +}; + +auto main() -> int { // NOLINT(readability-function-cognitive-complexity,bugprone-exception-escape) + // multi::array::size_type const maxsize = 39062; // 390625; + // multi::array::size_type const nmax = 1000; // 10000; + + // auto pp = [] /*__host__ __device__*/ (long ix, long iy) -> double { return double(ix) * double(iy); }; + + auto nx = 40000; // nmax; // for(long nx = 1; nx <= nmax; nx *= 10) + auto ny = 2000; // maxsize; // for(long ny = 1; ny <= maxsize; ny *= 5) + + // auto total = nx*ny; + + // nx = 2; + // ny = total / nx; + + multi::array K2D({nx, ny}); + + for(multi::array::index ix = 0; ix != nx; ++ix) { // NOLINT(altera-id-dependent-backward-branch) + for(multi::array::index iy = 0; iy != ny; ++iy) { // NOLINT(altera-id-dependent-backward-branch,altera-unroll-loops) + K2D[ix][iy] = static_cast(ix) * static_cast(iy); + } + } + +#if defined(NDEBUG) && !defined(RUNNING_ON_VALGRIND) + + { + auto const accumulator = [&](watch = watch("raw loop")) { // NOLINT(fuchsia-default-arguments-declarations) + multi::array ret({nx}, 0.0); + for(multi::array::index ix = 0; ix != nx; ++ix) { // NOLINT(altera-id-dependent-backward-branch) + for(multi::array::index iy = 0; iy != ny; ++iy) { // NOLINT(altera-id-dependent-backward-branch,altera-unroll-loops) + ret[ix] += K2D[ix][iy]; + } + } + return ret; + }(); // NOLINT(fuchsia-default-arguments-calls) + + for(multi::array::index ix = 0; ix != nx; ++ix) { // NOLINT(altera-unroll-loops) + BOOST_TEST( std::abs( accumulator[ix] - static_cast(ix) * ny * (ny - 1.0) / 2.0 ) < 1.0e-8); + } + } + + { + auto const accumulator = [&] { + watch const _("accumulate for"); + return std::accumulate( + (~K2D).begin(), (~K2D).end(), multi::array(K2D.extension(), 0.0), [](auto const& acc, auto const& col) { + multi::array res(acc.extensions()); + for(auto const i : col.extension()) { // NOLINT(altera-unroll-loops) + res[i] = acc[i] + col[i]; + } + return res; + } + ); + }(); + + for(multi::array::index ix = 0; ix != nx; ++ix) { // NOLINT(altera-unroll-loops) + BOOST_TEST( std::abs( accumulator[ix] - static_cast(ix) * ny * (ny - 1.0) / 2.0 ) < 1.0e-8); + } + } + + { + auto const accumulator = [&](auto init) { + watch const _("accumulate move"); + return std::accumulate( + (~K2D).begin(), (~K2D).end(), std::move(init), [](auto&& acc, auto const& col) { + multi::array ret(std::forward(acc)); + for(auto const i : col.extension()) { // NOLINT(altera-unroll-loops) + ret[i] += col[i]; + } + return ret; + } + ); + }(multi::array(K2D.extension(), 0.0)); + + for(multi::array::index ix = 0; ix != nx; ++ix) { // NOLINT(altera-unroll-loops) + BOOST_TEST( std::abs( accumulator[ix] - static_cast(ix) * ny * (ny - 1.0) / 2.0 ) < 1.0e-8); + } + } + + { + auto const accumulator = [&](auto init) { + watch const _("accumulate forward"); + return std::accumulate( + (~K2D).begin(), (~K2D).end(), std::move(init), [](auto&& acc, auto const& col) -> decltype(acc) { + for(auto const i : col.extension()) { // NOLINT(altera-unroll-loops) + acc[i] += col[i]; + } + return std::forward(acc); + } + ); + }(multi::array(K2D.extension(), 0.0)); + + for(multi::array::index ix = 0; ix != nx; ++ix) { // NOLINT(altera-unroll-loops) + BOOST_TEST( std::abs( accumulator[ix] - static_cast(ix) * ny * (ny - 1.0) / 2.0 ) < 1.0e-8); + } + } + + { + auto const accumulator = [&](auto init, watch = watch("accumulate transform forward")) { // NOLINT(fuchsia-default-arguments-declarations) + return std::accumulate( + (~K2D).begin(), (~K2D).end(), std::move(init), [](auto&& acc, auto const& col) -> decltype(acc) { + std::transform(col.begin(), col.end(), acc.begin(), acc.begin(), [](auto const& cole, auto&& acce) { return std::forward(acce) + cole; }); + return std::forward(acc); + } + ); + }(multi::array(K2D.extension(), 0.0)); // NOLINT(fuchsia-default-arguments-calls) + + for(multi::array::index ix = 0; ix != nx; ++ix) { // NOLINT(altera-unroll-loops) + BOOST_TEST( std::abs( accumulator[ix] - static_cast(ix) * ny * (ny - 1.0) / 2.0 ) < 1.0e-8); + } + } + + #if(!defined(__GLIBCXX__) || (__GLIBCXX__ >= 20190502)) + { + auto const accumulator = [&] { + watch const _("reduce transform forward"); + return std::reduce( + (~K2D).begin(), (~K2D).end(), multi::array(K2D.extension(), 0.0), [](auto acc, auto const& col) { + multi::array ret(std::move(acc)); + std::transform(col.begin(), col.end(), ret.begin(), ret.begin(), [](auto const& cole, auto&& acce) { return std::forward(acce) + cole; }); + return ret; + } + ); + }(); + + for(multi::array::index ix = 0; ix != nx; ++ix) { // NOLINT(altera-unroll-loops) + BOOST_TEST( std::abs( accumulator[ix] - static_cast(ix) * ny * (ny - 1.0) / 2.0 ) < 1.0e-8); + } + } + #endif + + { + auto const accumulator = [&] { + watch const _("transform accumulate element zero"); + + multi::array ret(K2D.extension()); + std::transform( + K2D.begin(), K2D.end(), ret.begin(), [](auto const& row) { return std::accumulate(row.begin(), row.end(), 0.0); } + ); + return ret; + }(); + + for(multi::array::index ix = 0; ix != nx; ++ix) { // NOLINT(altera-unroll-loops) + BOOST_TEST( std::abs( accumulator[ix] - static_cast(ix) * ny * (ny - 1.0) / 2.0 ) < 1.0e-8); + } + } + + #if(!defined(__GLIBCXX__) || (__GLIBCXX__ >= 20190502)) + { + auto const accumulator = [&] { + watch const _("transform reduce element zero"); + + multi::array ret(K2D.extension()); + std::transform( + K2D.begin(), K2D.end(), ret.begin(), [](auto const& row) { return std::reduce(row.begin(), row.end(), 0.0); } + ); + return ret; + }(); + + for(multi::array::index ix = 0; ix != nx; ++ix) { // NOLINT(altera-unroll-loops) + BOOST_TEST( std::abs( accumulator[ix] - static_cast(ix) * ny * (ny - 1.0) / 2.0 ) < 1.0e-8); + } + } + #endif + + { + auto const accumulator = [&](auto&& init) { + watch const _("transform accumulate"); + std::transform( + K2D.begin(), K2D.end(), init.begin(), init.begin(), [](auto const& row, auto rete) { return std::accumulate(row.begin(), row.end(), std::move(rete)); } + ); + return std::forward(init); + }(multi::array(K2D.extension(), 0.0)); + + for(multi::array::index ix = 0; ix != nx; ++ix) { // NOLINT(altera-unroll-loops) + BOOST_TEST( std::abs( accumulator[ix] - static_cast(ix) * ny * (ny - 1.0) / 2.0 ) < 1.0e-8); + } + } + + #if(!defined(__GLIBCXX__) || (__GLIBCXX__ >= 20200000)) + { + auto const accumulator = [&](auto&& init) { + watch const _("> transform reduce"); + std::transform( + K2D.begin(), K2D.end(), init.begin(), init.begin(), [](auto const& row, auto rete) { return std::reduce(row.begin(), row.end(), std::move(rete)); } + ); + return std::forward(init); + }(multi::array(K2D.extension(), 0.0)); + + for(multi::array::index ix = 0; ix != nx; ++ix) { // NOLINT(altera-unroll-loops) + BOOST_TEST( std::abs( accumulator[ix] - static_cast(ix) * ny * (ny - 1.0) / 2.0 ) < 1.0e-8); + } + } + #endif + + #if(defined(__has_include) && __has_include()) + #if !defined(__NVCC__) && !defined(__NVCOMPILER) && !(defined(__clang__) && defined(__CUDA__)) && (!defined(__clang_major__) || (__clang_major__ > 7)) + #if(!defined(__GLIBCXX__) || (__GLIBCXX__ >= 20220000)) && !defined(_LIBCPP_VERSION) + #if !defined(__apple_build_version__) && (!defined(__INTEL_LLVM_COMPILER) || (__INTEL_LLVM_COMPILER > 20240000)) + { + auto const accumulator = [&] (watch = watch("transform reduce[unseq]")) { // NOLINT(fuchsia-default-arguments-declarations) + multi::array ret(K2D.extension(), 0.0); + std::transform( + K2D.begin(), K2D.end(), + ret.begin(), + ret.begin(), + [](auto const& row, auto rete) { return std::reduce(std::execution::unseq, row.begin(), row.end(), std::move(rete)); } + ); + return ret; + }(); // NOLINT(fuchsia-default-arguments-calls) + + for(multi::array::index ix = 0; ix != nx; ++ix) { // NOLINT(altera-unroll-loops) + BOOST_TEST( std::abs( accumulator[ix] - static_cast(ix) * ny * (ny - 1.0) / 2.0 ) < 1.0e-8); + } + } + + { + auto const accumulator = [&] { + watch const _("transform reduce[par]"); + + multi::array ret(K2D.extension(), 0.0); + std::transform( + K2D.begin(), K2D.end(), + ret.begin(), + ret.begin(), + [](auto const& row, auto rete) { return std::reduce(std::execution::par, row.begin(), row.end(), std::move(rete)); } + ); + return ret; + }(); + + for(multi::array::index ix = 0; ix != nx; ++ix) { // NOLINT(altera-unroll-loops) + BOOST_TEST( std::abs( accumulator[ix] - static_cast(ix) * ny * (ny - 1.0) / 2.0 ) < 1.0e-8); + } + } + + { + auto const accumulator = [&] { + watch const _("transform reduce[par_unseq]"); + + multi::array ret(K2D.extension(), 0.0); + std::transform( + K2D.begin(), K2D.end(), + ret.begin(), + ret.begin(), + [](auto const& row, auto rete) { return std::reduce(std::execution::par_unseq, row.begin(), row.end(), std::move(rete)); } + ); + return ret; + }(); + + for(multi::array::index ix = 0; ix != nx; ++ix) { // NOLINT(altera-unroll-loops) + BOOST_TEST( std::abs( accumulator[ix] - static_cast(ix) * ny * (ny - 1.0) / 2.0 ) < 1.0e-8); + } + } + + { + auto const accumulator = [&]() { + watch const _("transform[par] reduce"); + + multi::array ret(K2D.extension(), 0.0); + std::transform( + std::execution::par, + K2D.begin(), K2D.end(), + ret.begin(), + ret.begin(), + [](auto const& row, auto rete) { return std::reduce(row.begin(), row.end(), std::move(rete)); } + ); + return ret; + }(); + + for(multi::array::index ix = 0; ix != nx; ++ix) { // NOLINT(altera-unroll-loops) + BOOST_TEST( std::abs( accumulator[ix] - static_cast(ix) * ny * (ny - 1.0) / 2.0 ) < 1.0e-8); + } + } + + { + auto const accumulator = [&](auto ret) { + watch const _("* transform[par] reduce[unseq]"); + std::transform( + std::execution::par, + K2D.begin(), K2D.end(), + ret.begin(), + ret.begin(), + [](auto const& row, auto rete) { return std::reduce(std::execution::unseq, row.begin(), row.end(), std::move(rete)); } + ); + return ret; + }(multi::array(K2D.extension(), 0.0)); + + for(multi::array::index ix = 0; ix != nx; ++ix) { // NOLINT(altera-unroll-loops) + BOOST_TEST( std::abs( accumulator[ix] - static_cast(ix) * ny * (ny - 1.0) / 2.0 ) < 1.0e-8); + } + } + + { + multi::array accumulator(K2D.extension(), 0.0); + [&](auto acc_begin) { + watch const _("transform[par] reduce[unseq] iterator"); + return std::transform( + std::execution::par, + K2D.begin(), K2D.end(), + acc_begin, acc_begin, + [](auto const& row, auto rete) { return std::reduce(std::execution::unseq, row.begin(), row.end(), std::move(rete)); } + ); + }(accumulator.begin()); + + for(multi::array::index ix = 0; ix != nx; ++ix) { // NOLINT(altera-unroll-loops) + BOOST_TEST( std::abs( accumulator[ix] - static_cast(ix) * ny * (ny - 1.0) / 2.0 ) < 1.0e-8); + } + } + + { + auto const accumulator = [&](auto zero_elem, watch = watch("transform[par] reduce[unseq] element zero")) { // NOLINT(fuchsia-default-arguments-declarations) + multi::array ret(K2D.extension()); + std::transform( + std::execution::par, + K2D.begin(), K2D.end(), + ret.begin(), + [zz = std::move(zero_elem)](auto const& row) { return std::reduce(std::execution::unseq, row.begin(), row.end(), std::move(zz)); } + ); + return ret; + }(0.0); // NOLINT(fuchsia-default-arguments-calls) + + for(multi::array::index ix = 0; ix != nx; ++ix) { // NOLINT(altera-unroll-loops) + BOOST_TEST( std::abs( accumulator[ix] - static_cast(ix) * ny * (ny - 1.0) / 2.0 ) < 1.0e-8); + } + } + #endif + #endif + #endif + #endif +#endif // __NVCC__ + + // { + // auto const accumulator = [&](auto&& init) { + // watch const _("blas gemv"); + // multi::array ones({init.extension()}, 1.0); + // multi::blas::gemv_n(1.0, K2D.begin(), K2D.size(), ones.begin(), 0.0, init.begin()); + // return std::forward(init); + // }(multi::array(K2D.extension(), 0.0)); + + // for(multi::array::index ix = 0; ix != nx; ++ix) { // NOLINT(altera-unroll-loops) + // BOOST_TEST( std::abs( accumulator[ix] - static_cast(ix) * ny * (ny - 1.0) / 2.0 ) < 1.0e-8); + // } + // } + + // { + // auto const accumulator = [&](auto&& init) { + // watch const _("blas gemv smart"); + // multi::blas::gemv_n(1.0, K2D.begin(), K2D.size(), init[0].begin(), 0.0, init[1].begin()); + // return +init[1]; + // }(multi::array({2, K2D.extension()}, 1.0)); + + // for(multi::array::index ix = 0; ix != nx; ++ix) { // NOLINT(altera-unroll-loops) + // BOOST_TEST( std::abs( accumulator[ix] - static_cast(ix) * ny * (ny - 1.0) / 2.0 ) < 1.0e-8); + // } + // } + + return boost::report_errors(); +} diff --git a/external_codes/boost_multi/multi/test/reextent.cpp b/external_codes/boost_multi/multi/test/reextent.cpp index 6788ba14db..65b9634ee8 100644 --- a/external_codes/boost_multi/multi/test/reextent.cpp +++ b/external_codes/boost_multi/multi/test/reextent.cpp @@ -3,293 +3,282 @@ // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt -#include - -// Suppress warnings from boost.test -#if defined(__clang__) -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wold-style-cast" -# pragma clang diagnostic ignored "-Wundef" -# pragma clang diagnostic ignored "-Wconversion" -# pragma clang diagnostic ignored "-Wsign-conversion" -# pragma clang diagnostic ignored "-Wfloat-equal" -#elif defined(__GNUC__) -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wold-style-cast" -# pragma GCC diagnostic ignored "-Wundef" -# pragma GCC diagnostic ignored "-Wconversion" -# pragma GCC diagnostic ignored "-Wsign-conversion" -# pragma GCC diagnostic ignored "-Wfloat-equal" -#elif defined(_MSC_VER) -# pragma warning(push) -# pragma warning(disable : 4244) -#endif - -#ifndef BOOST_TEST_MODULE -# define BOOST_TEST_MAIN -#endif +#include // for array, static_array, num_elements -#include +// IWYU pragma: no_include // for fill_n // bug in iwyu 14.0.6? with GNU stdlib +#include // for size +#include // for make_unsigned_t +#include // for move +#include // for vector namespace multi = boost::multi; -BOOST_AUTO_TEST_CASE(array_reextent) { - multi::array arr({2, 3}); - BOOST_REQUIRE( num_elements(arr) == 6 ); +template +constexpr auto comp_equal(T left, U right) noexcept -> bool { + using UT = std::make_unsigned_t; + using UU = std::make_unsigned_t; + if constexpr(std::is_signed_v == std::is_signed_v) { + return left == right; + } else if constexpr(std::is_signed_v) { + return left < 0 ? false : static_cast(left) == right; + } else { + return right < 0 ? false : left == UU(right); + } +#if !defined(__INTEL_COMPILER) && !defined(__NVCOMPILER) && !defined(_MSC_VER) + __builtin_unreachable(); +#endif +} - arr[1][2] = 6.0; - BOOST_REQUIRE( arr[1][2] == 6.0 ); +#include +#define BOOST_AUTO_TEST_CASE(CasenamE) /**/ - multi::array arr3({2, 3}); - BOOST_REQUIRE(size(arr3) == 2); - BOOST_REQUIRE(size(arr3[0]) == 3); +auto main() -> int { // NOLINT(readability-function-cognitive-complexity,bugprone-exception-escape) + BOOST_AUTO_TEST_CASE(array_reextent) { + multi::array arr({2, 3}); + BOOST_TEST( num_elements(arr) == 6 ); - arr.reextent({5, 4}, 99.0); - BOOST_REQUIRE( num_elements(arr)== 5L*4L ); - BOOST_REQUIRE( arr[1][2] == 6.0 ); // reextent preserves values when it can... - BOOST_REQUIRE( arr[4][3] == 99.0 ); // ...and gives selected value to the rest -} + arr[1][2] = 60; + BOOST_TEST( arr[1][2] == 60 ); -BOOST_AUTO_TEST_CASE(array_reextent_noop) { - multi::array arr({2, 3}); - BOOST_REQUIRE( num_elements(arr) == 6 ); + multi::array arr3({2, 3}); + BOOST_TEST(size(arr3) == 2); + BOOST_TEST(size(arr3[0]) == 3); - arr[1][2] = 6.; - BOOST_REQUIRE( arr[1][2] == 6. ); + arr.reextent({5, 4}, 990); + BOOST_TEST( num_elements(arr)== 5L*4L ); + BOOST_TEST( arr[1][2] == 60 ); // reextent preserves values when it can... + BOOST_TEST( arr[4][3] == 990 ); // ...and gives selected value to the rest + } - multi::array arr3({2, 3}); - BOOST_REQUIRE(size(arr3) == 2); - BOOST_REQUIRE(size(arr3[0]) == 3); + BOOST_AUTO_TEST_CASE(array_reextent_noop) { + multi::array arr({2, 3}); + BOOST_TEST( num_elements(arr) == 6 ); - auto* const A_base = arr.base(); - arr.reextent({2, 3}); - BOOST_REQUIRE( num_elements(arr)== 2L*3L ); - BOOST_REQUIRE( arr[1][2] == 6.0 ); // reextent preserves values when it can... + arr[1][2] = 60; + BOOST_TEST( arr[1][2] == 60 ); - BOOST_REQUIRE( A_base == arr.base() ); -} + multi::array arr3({2, 3}); + BOOST_TEST(size(arr3) == 2); + BOOST_TEST(size(arr3[0]) == 3); -BOOST_AUTO_TEST_CASE(array_reextent_noop_with_init) { - multi::array arr({2, 3}); - BOOST_REQUIRE( num_elements(arr) == 6 ); + auto* const A_base = arr.base(); + arr.reextent({2, 3}); + BOOST_TEST( num_elements(arr)== 2L*3L ); + BOOST_TEST( arr[1][2] == 60 ); // reextent preserves values when it can... - arr[1][2] = 6.0; - BOOST_REQUIRE( arr[1][2] == 6.0 ); + BOOST_TEST( A_base == arr.base() ); + } - multi::array arr3({2, 3}); - BOOST_REQUIRE(size(arr3) == 2); - BOOST_REQUIRE(size(arr3[0]) == 3); + BOOST_AUTO_TEST_CASE(array_reextent_noop_with_init) { + multi::array arr({2, 3}); + BOOST_TEST( num_elements(arr) == 6 ); - auto* const A_base = arr.base(); - arr.reextent({2, 3}, 99.0); - BOOST_REQUIRE( num_elements(arr)== 2L*3L ); - BOOST_REQUIRE( arr[1][2] == 6.0 ); // reextent preserves values when it can... + arr[1][2] = 60; + BOOST_TEST( arr[1][2] == 60 ); - BOOST_REQUIRE( A_base == arr.base() ); -} + multi::array arr3({2, 3}); + BOOST_TEST(size(arr3) == 2); + BOOST_TEST(size(arr3[0]) == 3); -BOOST_AUTO_TEST_CASE(array_reextent_moved) { - multi::array arr({2, 3}); - BOOST_REQUIRE( num_elements(arr) == 6 ); + auto* const A_base = arr.base(); + arr.reextent({2, 3}, 990); + BOOST_TEST( num_elements(arr)== 2L*3L ); + BOOST_TEST( arr[1][2] == 60 ); // reextent preserves values when it can... - arr[1][2] = 6.; - BOOST_REQUIRE( arr[1][2] == 6.0 ); + BOOST_TEST( A_base == arr.base() ); + } - auto* const A_base = arr.base(); + BOOST_AUTO_TEST_CASE(array_reextent_moved) { + multi::array arr({2, 3}); + BOOST_TEST( num_elements(arr) == 6 ); - arr = std::move(arr).reextent({2, 3}); // "arr = ..." suppresses linter bugprone-use-after-move,hicpp-invalid-access-moved + arr[1][2] = 60; + BOOST_TEST( arr[1][2] == 60 ); - BOOST_TEST_REQUIRE( arr.size() == 2 ); - BOOST_REQUIRE( arr.num_elements() == 2L*3L ); - BOOST_REQUIRE( num_elements(arr)== 2L*3L ); - BOOST_TEST(arr[1][2] == 6.0); // after move the original elments might not be the same + auto* const A_base = arr.base(); - BOOST_REQUIRE( A_base == arr.base() ); -} + arr = std::move(arr).reextent({2, 3}); // "arr = ..." suppresses linter bugprone-use-after-move,hicpp-invalid-access-moved -BOOST_AUTO_TEST_CASE(array_reextent_moved_trivial) { - multi::array arr({2, 3}); - BOOST_REQUIRE( num_elements(arr) == 6 ); + BOOST_TEST( arr.size() == 2 ); + BOOST_TEST( arr.num_elements() == 2L*3L ); + BOOST_TEST( num_elements(arr)== 2L*3L ); + BOOST_TEST(arr[1][2] == 60); // after move the original elments might not be the same - arr[1][2] = 6.0; - BOOST_REQUIRE( arr[1][2] == 6.0 ); + BOOST_TEST( A_base == arr.base() ); + } - auto* const A_base = arr.base(); - arr = std::move(arr).reextent({2, 3}); // "arr = ..." suppresses linter bugprone-use-after-move,hicpp-invalid-access-moved - BOOST_REQUIRE( num_elements(arr)== 2L*3L ); - BOOST_REQUIRE( arr[1][2] == 6.0 ); // after move the original elments might not be the same + BOOST_AUTO_TEST_CASE(array_reextent_moved_trivial) { + multi::array arr({2, 3}); + BOOST_TEST( num_elements(arr) == 6 ); - BOOST_REQUIRE( A_base == arr.base() ); -} + arr[1][2] = 60; + BOOST_TEST( arr[1][2] == 60 ); -BOOST_AUTO_TEST_CASE(array_reextent_moved_trivial_change_extents) { - multi::array arr({2, 3}); - BOOST_REQUIRE( num_elements(arr) == 6 ); + auto* const A_base = arr.base(); - arr[1][2] = 6.0; - BOOST_REQUIRE( arr[1][2] == 6.0 ); + arr = std::move(arr).reextent({2, 3}); // "arr = ..." suppresses linter bugprone-use-after-move,hicpp-invalid-access-moved - auto* const A_base = arr.base(); - arr = std::move(arr).reextent({4, 5}); - BOOST_REQUIRE( num_elements(arr)== 4L*5L ); - // BOOST_REQUIRE( arr[1][2] != 6.0 ); // after move the original elements might not be the same, but it is not 100% possible to check + BOOST_TEST( num_elements(arr)== 2L*3L ); + BOOST_TEST( arr[1][2] == 60 ); // after move the original elments might not be the same - BOOST_REQUIRE( A_base != arr.base() ); -} + BOOST_TEST( A_base == arr.base() ); + } -BOOST_AUTO_TEST_CASE(array_move_clear) { - multi::array const iarr; - multi::array arr({2, 3}); + BOOST_AUTO_TEST_CASE(array_reextent_moved_trivial_change_extents) { + multi::array arr({2, 3}); + BOOST_TEST( num_elements(arr) == 6 ); - arr = multi::array(extensions(arr), 123.0); - BOOST_REQUIRE( arr[1][2] == 123.0 ); + arr[1][2] = 60; + BOOST_TEST( arr[1][2] == 60 ); - arr.clear(); // clear(arr); - BOOST_REQUIRE( num_elements(arr) == 0 ); - BOOST_REQUIRE( size(arr) == 0 ); + auto* const A_base = arr.base(); - arr.reextent({5, 4}, 66.0); - BOOST_REQUIRE( arr[4][3] == 66.0 ); + arr = std::move(arr).reextent({4, 5}); - BOOST_REQUIRE(iarr.is_empty()); -} + BOOST_TEST( num_elements(arr)== 4L*5L ); + // BOOST_TEST( arr[1][2] != 6.0 ); // after move the original elements might not be the same, but it is not 100% possible to check -BOOST_AUTO_TEST_CASE(array_reextent_1d) { - multi::array arr(multi::extensions_t<1>{multi::iextension{10}}, 4.0); - BOOST_REQUIRE( size(arr) == 10 ); - BOOST_REQUIRE( arr[9] == 4.0 ); + BOOST_TEST( A_base != arr.base() ); + } - arr.reextent(multi::extensions_t<1>{multi::iextension{20}}); - BOOST_REQUIRE( size(arr) == 20 ); - BOOST_REQUIRE( arr[9] == 4.0 ); - // BOOST_REQUIRE( arr[19] == 0.0 ); // impossible to know since it is only sometimes 0.0 + BOOST_AUTO_TEST_CASE(array_move_clear) { + multi::array arr({2, 3}); - arr.reextent(boost::multi::tuple(22)); - BOOST_REQUIRE( size(arr) == 22 ); - BOOST_REQUIRE( arr[9] == 4.0 ); + arr = multi::array(extensions(arr), 1230); + BOOST_TEST( arr[1][2] == 1230 ); - arr.reextent({23}); - BOOST_REQUIRE( size(arr) == 23 ); -} + arr.clear(); + BOOST_TEST( num_elements(arr) == 0 ); + BOOST_TEST( size(arr) == 0 ); -BOOST_AUTO_TEST_CASE(tuple_decomposition) { - boost::multi::tuple const tup{1, 2}; - auto [t0, t1] = tup; - BOOST_REQUIRE( t0 == 1 ); - BOOST_REQUIRE( t1 == 2 ); -} + arr.reextent({5, 4}, 660); + BOOST_TEST( arr[4][3] == 660 ); + } -BOOST_AUTO_TEST_CASE(array_reextent_0D) { - multi::array const arr({}, 4.0); - // arr.reextent(arr.extensions()); // TODO(correaa) : fix unused for D = 0 - BOOST_REQUIRE( *arr.data_elements() == 4.0 ); -} + BOOST_AUTO_TEST_CASE(array_reextent_1d) { + multi::array arr(multi::extensions_t<1>{multi::iextension{10}}, 40); + BOOST_TEST( size(arr) == 10 ); + BOOST_TEST( arr[9] == 40 ); -BOOST_AUTO_TEST_CASE(array_reextent_1d_with_initialization) { - multi::array arr(multi::extensions_t<1>{multi::iextension{10}}, 4.0); - BOOST_REQUIRE( size(arr) == 10 ); - BOOST_REQUIRE( arr[9] == 4.0 ); + arr.reextent(multi::extensions_t<1>{multi::iextension{20}}); + BOOST_TEST( size(arr) == 20 ); + BOOST_TEST( arr[9] == 40 ); + // BOOST_TEST( arr[19] == 0.0 ); // impossible to know since it is only sometimes 0.0 - arr.reextent(multi::extensions_t<1>{multi::iextension{20}}, 8.0); - BOOST_REQUIRE( size(arr) == 20 ); - BOOST_REQUIRE( arr[9] == 4.0 ); - BOOST_REQUIRE( arr[19] == 8.0 ); -} + arr.reextent(boost::multi::tuple(22)); + BOOST_TEST( size(arr) == 22 ); + BOOST_TEST( arr[9] == 40 ); -BOOST_AUTO_TEST_CASE(array_reextent_2d) { - multi::array arr({10, 20}, 4.0); - BOOST_REQUIRE( arr[1][2] == 4.0 ); + arr.reextent({23}); + BOOST_TEST( size(arr) == 23 ); + } - arr.clear(); - BOOST_REQUIRE( num_elements(arr) == 0 ); - BOOST_REQUIRE( size(arr) == 0 ); + BOOST_AUTO_TEST_CASE(tuple_decomposition) { + boost::multi::tuple const tup{1, 2}; + auto [t0, t1] = tup; + BOOST_TEST( t0 == 1 ); + BOOST_TEST( t1 == 2 ); + } - arr.reextent({20, 30}, 9.0); - BOOST_REQUIRE( arr[1][2] = 9. ); - BOOST_REQUIRE( arr[11][22] = 9.0 ); -} + BOOST_AUTO_TEST_CASE(array_reextent_0D) { + multi::array arr({}, 40); + arr.reextent(arr.extensions()); + BOOST_TEST( *arr.data_elements() == 40 ); + } -BOOST_AUTO_TEST_CASE(array_reextent_2d_with_move) { - multi::array arr = { - {1, 2, 3}, - {4, 5, 6}, - }; - BOOST_REQUIRE( arr.size() == 2 ); + BOOST_AUTO_TEST_CASE(array_reextent_1d_with_initialization) { + multi::array arr(multi::extensions_t<1>{multi::iextension{10}}, 40); + BOOST_TEST( size(arr) == 10 ); + BOOST_TEST( arr[9] == 40 ); - arr = std::move(arr).reextent({3, 2}); + arr.reextent(multi::extensions_t<1>{multi::iextension{20}}, 80); + BOOST_TEST( size(arr) == 20 ); + BOOST_TEST( arr[9] == 40 ); + BOOST_TEST( arr[19] == 80 ); + } - BOOST_REQUIRE( arr.size() == 3 ); - BOOST_REQUIRE( arr[1][2] = 10 ); -} + BOOST_AUTO_TEST_CASE(array_reextent_2d) { + multi::array arr({10, 20}, 40); + BOOST_TEST( arr[1][2] == 40 ); -BOOST_AUTO_TEST_CASE(array_reextent_2d_array) { - multi::array arr({10, 20}, 4.0); - BOOST_REQUIRE( arr[1][2] == 4.0 ); + arr.clear(); + BOOST_TEST( num_elements(arr) == 0 ); + BOOST_TEST( size(arr) == 0 ); - arr.clear(); - BOOST_REQUIRE( num_elements(arr) == 0 ); - BOOST_REQUIRE( size(arr) == 0 ); -} + arr.reextent({20, 30}, 90); + BOOST_TEST( arr[1][2] == 90 ); + BOOST_TEST( arr[11][22] == 90 ); + } -template -constexpr auto comp_equal(T left, U right) noexcept -> bool { - using UT = std::make_unsigned_t; - using UU = std::make_unsigned_t; - if constexpr(std::is_signed_v == std::is_signed_v) { - return left == right; - } else if constexpr(std::is_signed_v) { - return left < 0 ? false : static_cast(left) == right; - } else { - return right < 0 ? false : left == UU(right); + BOOST_AUTO_TEST_CASE(array_reextent_2d_with_move) { + multi::array arr = { + {1, 2, 3}, + {4, 5, 6}, + }; + BOOST_TEST( arr.size() == 2 ); + + arr = std::move(arr).reextent({3, 2}); + + BOOST_TEST( arr.size() == 3 ); } -#if !defined(__INTEL_COMPILER) && !defined(__NVCOMPILER) && !defined(_MSC_VER) - __builtin_unreachable(); -#endif -} -BOOST_AUTO_TEST_CASE(array_vector_size) { - std::vector const vec(100); // std::vector NOLINT(fuchsia-default-arguments-calls) - { - // multi::array a( vec.size() ); // warning: sign-conversion - multi::array const arr(static_cast(vec.size())); - BOOST_REQUIRE( comp_equal(arr.size(), vec.size()) ); + BOOST_AUTO_TEST_CASE(array_reextent_2d_array) { + multi::array arr({10, 20}, 40); + BOOST_TEST( arr[1][2] == 40 ); + + arr.clear(); + BOOST_TEST( num_elements(arr) == 0 ); + BOOST_TEST( size(arr) == 0 ); } - { - multi::array const arr(multi::iextensions<1>(static_cast(vec.size()))); // warning: sign-conversion - // multi::array a(static_cast(v.size())); - BOOST_REQUIRE( comp_equal(arr.size(), vec.size()) ); + + BOOST_AUTO_TEST_CASE(array_vector_size) { + std::vector const vec(100); // std::vector NOLINT(fuchsia-default-arguments-calls) + { + multi::array const arr(static_cast(vec.size())); + BOOST_TEST( comp_equal(arr.size(), vec.size()) ); + } + { + multi::array const arr(multi::iextensions<1>(static_cast(vec.size()))); // warning: sign-conversion + // multi::array a(static_cast(v.size())); + BOOST_TEST( comp_equal(arr.size(), vec.size()) ); + } } -} -BOOST_AUTO_TEST_CASE(array_iota) { - multi::array const Aarr(10); - multi::array Barr(Aarr.extension().begin(), Aarr.extension().end()); - BOOST_REQUIRE( Barr[0] == 0 ); - BOOST_REQUIRE( Barr[1] == 1 ); - BOOST_REQUIRE( Barr[9] == 9 ); + BOOST_AUTO_TEST_CASE(array_iota) { + multi::array const Aarr(10); + multi::array::index, 1> const Barr(Aarr.extension().begin(), Aarr.extension().end()); - multi::array Carr(Aarr.extension()); - BOOST_REQUIRE( Carr[0] == 0 ); - BOOST_REQUIRE( Carr[1] == 1 ); - BOOST_REQUIRE( Carr[9] == 9 ); + BOOST_TEST( Barr[0] == 0 ); + BOOST_TEST( Barr[1] == 1 ); + BOOST_TEST( Barr[9] == 9 ); - multi::array const Darr(Aarr.extensions()); - BOOST_REQUIRE( Darr.extensions() == Aarr.extensions() ); -} + multi::array::index, 1> const Carr(Aarr.extension()); + BOOST_TEST( Carr[0] == 0 ); + BOOST_TEST( Carr[1] == 1 ); + BOOST_TEST( Carr[9] == 9 ); + + multi::array::index, 1> const Darr(Aarr.extensions()); + BOOST_TEST( Darr.extensions() == Aarr.extensions() ); + } #ifndef __INTEL_COMPILER -BOOST_AUTO_TEST_CASE(extension_index_op) { - multi::array const Aarr({11, 13}); - auto Aext = Aarr.extensions(); - BOOST_REQUIRE( std::get<0>(Aext[3][5]) == 3 ); - BOOST_REQUIRE( std::get<1>(Aext[3][5]) == 5 ); - - for(int i = 0; i != 3; ++i) { - for(int j = 0; j != 5; ++j) { - auto [ip, jp] = Aext[i][j]; - BOOST_REQUIRE(ip == i); - BOOST_REQUIRE(jp == j); + BOOST_AUTO_TEST_CASE(extension_index_op) { + multi::array const Aarr({11, 13}); + auto const Aext = Aarr.extensions(); + + using std::get; // workaround use of function template name with no prior declaration in function call with explicit template arguments is a C++20 extension [-Wc++20-extensions] + + BOOST_TEST( get<0>(Aext[3][5]) == 3 ); + BOOST_TEST( get<1>(Aext[3][5]) == 5 ); + + for(int i = 0; i != 3; ++i) { + for(int j = 0; j != 5; ++j) { // NOLINT(altera-unroll-loops) + auto [ip, jp] = Aext[i][j]; + BOOST_TEST(ip == i); + BOOST_TEST(jp == j); + } } } -} #endif + return boost::report_errors(); +} diff --git a/external_codes/boost_multi/multi/test/reinterpret_array_cast.cpp b/external_codes/boost_multi/multi/test/reinterpret_array_cast.cpp index 7a076dd72b..9ad605c329 100644 --- a/external_codes/boost_multi/multi/test/reinterpret_array_cast.cpp +++ b/external_codes/boost_multi/multi/test/reinterpret_array_cast.cpp @@ -1,316 +1,361 @@ -// Copyright 2018-2023 Alfredo A. Correa +// Copyright 2018-2024 Alfredo A. Correa // Copyright 2024 Matt Borland // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt -#include +#include // for array, subarray, static_array -#include -#include -#include +#include -// Suppress warnings from boost.test -#if defined(__clang__) -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wold-style-cast" -#pragma clang diagnostic ignored "-Wundef" -#pragma clang diagnostic ignored "-Wconversion" -#pragma clang diagnostic ignored "-Wsign-conversion" -#pragma clang diagnostic ignored "-Wfloat-equal" -#elif defined(__GNUC__) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wold-style-cast" -#pragma GCC diagnostic ignored "-Wundef" -#pragma GCC diagnostic ignored "-Wconversion" -#pragma GCC diagnostic ignored "-Wsign-conversion" -#pragma GCC diagnostic ignored "-Wfloat-equal" -#endif - -#ifndef BOOST_TEST_MODULE -#define BOOST_TEST_MAIN -#endif - -#include +#include // for get, array +#include // for abs // IWYU pragma: keep +#include // for complex, real, operator==, imag +// IWYU pragma: no_include // for abs +#include // for size, begin, end +// IWYU pragma: no_include // for allocator +#include // for iota +#include // for is_same_v +#include // for pair namespace multi = boost::multi; -BOOST_AUTO_TEST_CASE(multi_reinterpret_array_cast_struct_to_dimension) { - struct vec3 { - double x; - double y; - double z; - }; - multi::array arr(multi::extensions_t<1>{multi::iextension{100}}); - arr[8] = {1.0, 2.0, 3.0}; - BOOST_REQUIRE( arr[8].y == 2.0 ); - -#ifndef _MSC_VER // problems with MSVC 14.3 c++17 - BOOST_REQUIRE( arr.reinterpret_array_cast(3)[8][1] == arr[8].y ); - - multi::array A2D = arr.reinterpret_array_cast(3); - - BOOST_REQUIRE( decltype(A2D)::dimensionality == decltype(arr)::dimensionality + 1 ); - BOOST_REQUIRE( dimensionality(A2D) == dimensionality(arr) + 1 ); - - BOOST_REQUIRE( size(A2D) == size(arr) ); - BOOST_REQUIRE( A2D[8][1] == arr[8].y ); - BOOST_REQUIRE( &A2D[8][1] != &arr[8].y ); +template struct complex_dummy { + T real; + T imag; +}; - BOOST_REQUIRE( & arr[8].x == & arr.reinterpret_array_cast(3)[8][0] ); - BOOST_REQUIRE( & arr[8].y == & arr.reinterpret_array_cast(3)[8][1] ); - BOOST_REQUIRE( & arr[8].z == & arr.reinterpret_array_cast(3)[8][2] ); -#endif -} +#define BOOST_AUTO_TEST_CASE(CasenamE) /**/ -BOOST_AUTO_TEST_CASE(multi_lower_dimension) { - struct vec3 { - double x; - double y; - double z; - - // [[maybe_unused]] auto operator==(vec3 const& other) const -> bool { return x == other.x && y == other.y && z == other.z; } - }; - - multi::array arr = { - {0.0, 0.1, 0.2}, - {1.0, 1.1, 1.2}, - {2.0, 2.1, 2.2}, - {3.0, 3.1, 3.2}, - }; +auto main() -> int { // NOLINT(readability-function-cognitive-complexity,bugprone-exception-escape) + // simple class reinterpret { - BOOST_TEST( arr.size() == 4 ); - BOOST_TEST( arr.flatted().size() == 12 ); - BOOST_TEST( arr.flatted().strided(3).size() == 4 ); - BOOST_TEST( arr.flatted().strided(3).reinterpret_array_cast().size() == 4 ); + struct int_class {int val_;}; - auto&& arrvec3 = arr.flatted().strided(3).reinterpret_array_cast(); + multi::array arr1d({3}, int_class{}); + arr1d[0].val_ = 5; + BOOST_TEST( arr1d.reinterpret_array_cast()[0] == 5 ); - BOOST_TEST( arr.flatted().size() == arrvec3.size()*3 ); - BOOST_TEST( &arrvec3[2].x == &arr[2][0] ); + multi::array arr2d({3, 3}, int_class{}); + arr2d[0][0].val_ = 5; + BOOST_TEST( arr2d.reinterpret_array_cast()[0][0] == 5 ); } -} -BOOST_AUTO_TEST_CASE(multi_lower_dimension_2d) { - struct vec3 { - double x; - double y; - double z; - }; + BOOST_AUTO_TEST_CASE(multi_reinterpret_array_cast_struct_to_dimension) { + struct vec3 { + double x; + double y; + double z; + }; + multi::array arr(multi::extensions_t<1>{multi::iextension{100}}); + arr[8] = {1.0, 2.0, 3.0}; + BOOST_TEST( std::abs( arr[8].y - 2.0 ) < 1E-6 ); - multi::array d2 = { - {0.0, 0.1, 0.2, 0.0, 0.1, 0.2, 0.0, 0.1, 0.2}, - {1.0, 1.1, 1.2, 1.0, 1.1, 1.2, 1.0, 1.1, 1.2}, - {2.0, 2.1, 2.2, 2.0, 2.1, 2.2, 2.0, 2.1, 2.2}, - {3.0, 3.1, 3.2, 3.0, 3.1, 3.2, 3.0, 3.1, 3.2}, - }; +#ifndef _MSC_VER // problems with MSVC 14.3 c++17 + BOOST_TEST( std::abs( arr.reinterpret_array_cast(3)[8][1] - arr[8].y ) < 1E-6 ); - { - auto&& d2strided3 = d2.unrotated().strided(3).rotated(); - BOOST_TEST( d2strided3.size() == 4 ); - BOOST_TEST( d2strided3[0].size() == 3 ); - BOOST_TEST( &d2strided3[1][2] == &d2[1][6] ); - } - { - auto&& v2view = d2.unrotated().strided(3).rotated().reinterpret_array_cast(); - BOOST_TEST( v2view.size() == 4 ); - BOOST_TEST( v2view[0].size() == 3 ); - BOOST_TEST( &v2view[1][2].x == &d2[1][6] ); - } -} + multi::array A2D{arr.reinterpret_array_cast(3)}; -BOOST_AUTO_TEST_CASE(multi_lower_dimension_3d) { - struct vec3 { - double x; - double y; - double z; - }; + BOOST_TEST( decltype(A2D)::dimensionality == decltype(arr)::dimensionality + 1 ); + BOOST_TEST( dimensionality(A2D) == dimensionality(arr) + 1 ); - multi::array d3({4, 15, 9}, 0.0); + BOOST_TEST( size(A2D) == size(arr) ); + BOOST_TEST( std::abs( A2D[8][1] - arr[8].y ) < 1E-6); + BOOST_TEST( &A2D[8][1] != &arr[8].y ); - { - auto&& d3strided3 = d3.unrotated().strided(3).rotated(); - BOOST_TEST( d3strided3.size() == 4 ); - BOOST_TEST( d3strided3[0][0].size() == 3 ); - BOOST_TEST( &d3strided3[3][1][2] == &d3[3][1][6] ); + BOOST_TEST( & arr[8].x == & arr.reinterpret_array_cast(3)[8][0] ); + BOOST_TEST( & arr[8].y == & arr.reinterpret_array_cast(3)[8][1] ); + BOOST_TEST( & arr[8].z == & arr.reinterpret_array_cast(3)[8][2] ); +#endif } - { - auto&& v3view = d3.unrotated().strided(3).rotated().reinterpret_array_cast(); - BOOST_TEST( v3view.size() == 4 ); - BOOST_TEST( v3view[0][0].size() == 3 ); - BOOST_TEST( &v3view[3][1][2].x == &d3[3][1][6] ); - BOOST_TEST( &v3view[3][1][2].y == &d3[3][1][7] ); - BOOST_TEST( &v3view[3][1][2].z == &d3[3][1][8] ); + + BOOST_AUTO_TEST_CASE(multi_lower_dimension) { + struct vec3 { + double x; + double y; + double z; + + // [[maybe_unused]] auto operator==(vec3 const& other) const -> bool { return x == other.x && y == other.y && z == other.z; } + }; + + multi::array arr = { + {0.0, 0.1, 0.2}, + {1.0, 1.1, 1.2}, + {2.0, 2.1, 2.2}, + {3.0, 3.1, 3.2}, + }; + { + BOOST_TEST( arr.size() == 4 ); + BOOST_TEST( arr.flatted().size() == 12 ); + BOOST_TEST( arr.flatted().strided(3).size() == 4 ); + BOOST_TEST( arr.flatted().strided(3).reinterpret_array_cast().size() == 4 ); + + auto&& arrvec3 = arr.flatted().strided(3).reinterpret_array_cast(); + + BOOST_TEST( arr.flatted().size() == arrvec3.size()*3 ); + BOOST_TEST( &arrvec3[2].x == &arr[2][0] ); + } } -} -BOOST_AUTO_TEST_CASE(multi_reinterpret_array_cast_complex_to_real_extra_dimension) { - using complex = std::complex; - multi::array arr(multi::extensions_t<1>{multi::iextension{100}}, complex{1.0, 2.0}); - BOOST_REQUIRE( size(arr) == 100 ); + BOOST_AUTO_TEST_CASE(multi_lower_dimension_2d) { + struct vec3 { + double x; + double y; + double z; + }; + + multi::array d2 = { + {0.0, 0.1, 0.2, 0.0, 0.1, 0.2, 0.0, 0.1, 0.2}, + {1.0, 1.1, 1.2, 1.0, 1.1, 1.2, 1.0, 1.1, 1.2}, + {2.0, 2.1, 2.2, 2.0, 2.1, 2.2, 2.0, 2.1, 2.2}, + {3.0, 3.1, 3.2, 3.0, 3.1, 3.2, 3.0, 3.1, 3.2}, + }; + + { + auto&& d2strided3 = d2.unrotated().strided(3).rotated(); + BOOST_TEST( d2strided3.size() == 4 ); + BOOST_TEST( d2strided3[0].size() == 3 ); + BOOST_TEST( &d2strided3[1][2] == &d2[1][6] ); + } + { + auto&& v2view = d2.unrotated().strided(3).rotated().reinterpret_array_cast(); + BOOST_TEST( v2view.size() == 4 ); + BOOST_TEST( v2view[0].size() == 3 ); + BOOST_TEST( &v2view[1][2].x == &d2[1][6] ); + } + } - { - complex const arr0 = arr[0]; - BOOST_TEST_REQUIRE( arr0.real() == 1.0 ); - BOOST_TEST_REQUIRE( arr0.imag() == 2.0 ); + BOOST_AUTO_TEST_CASE(multi_lower_dimension_3d) { + struct vec3 { + double x; + double y; + double z; + }; + + multi::array d3({4, 15, 9}, 0.0); + + { + auto&& d3strided3 = d3.unrotated().strided(3).rotated(); + BOOST_TEST( d3strided3.size() == 4 ); + BOOST_TEST( d3strided3[0][0].size() == 3 ); + BOOST_TEST( &d3strided3[3][1][2] == &d3[3][1][6] ); + } + { + auto&& v3view = d3.unrotated().strided(3).rotated().reinterpret_array_cast(); + BOOST_TEST( v3view.size() == 4 ); + BOOST_TEST( v3view[0][0].size() == 3 ); + BOOST_TEST( &v3view[3][1][2].x == &d3[3][1][6] ); + BOOST_TEST( &v3view[3][1][2].y == &d3[3][1][7] ); + BOOST_TEST( &v3view[3][1][2].z == &d3[3][1][8] ); + } } - BOOST_TEST_REQUIRE( arr[0].real() == 1.0 ); - BOOST_TEST_REQUIRE( arr[0].imag() == 2.0 ); + BOOST_AUTO_TEST_CASE(multi_reinterpret_array_cast_complex_to_real_extra_dimension) { + using complex = std::complex; + multi::array arr(multi::extensions_t<1>{multi::iextension{100}}, complex{1.0, 2.0}); + BOOST_TEST( size(arr) == 100 ); - BOOST_TEST_REQUIRE( std::real(arr[0]) == 1.0 ); - BOOST_TEST_REQUIRE( std::imag(arr[0]) == 2.0 ); + { + complex const arr0 = arr[0]; + BOOST_TEST( std::abs( arr0.real() - 1.0 ) < 1E-6 ); + BOOST_TEST( std::abs( arr0.imag() - 2.0 ) < 1E-6 ); + } - BOOST_TEST_REQUIRE( real(arr[0]) == 1.0 ); - BOOST_TEST_REQUIRE( imag(arr[0]) == 2.0 ); + BOOST_TEST( std::abs( arr[0].real() - 1.0 ) < 1E-6 ); + BOOST_TEST( std::abs( arr[0].imag() - 2.0 ) < 1E-6 ); - BOOST_REQUIRE(( arr[0] == complex{1.0, 2.0} )); + BOOST_TEST( std::abs( std::real(arr[0]) - 1.0 ) < 1E-6 ); + BOOST_TEST( std::abs( std::imag(arr[0]) - 2.0 ) < 1E-6 ); -#ifndef _MSC_VER // problem with MVSC 14.3 c++17 - multi::array arr2 = arr.reinterpret_array_cast(); - BOOST_REQUIRE( dimensionality(arr2) == dimensionality(arr) ); - BOOST_REQUIRE( arr2[0] == 1 && arr2[1] == 1 ); + BOOST_TEST( std::abs( real(arr[0]) - 1.0 ) < 1E-6 ); + BOOST_TEST( std::abs( imag(arr[0]) - 2.0 ) < 1E-6 ); - multi::array arr3 = arr.reinterpret_array_cast(2); + BOOST_TEST( std::abs( arr[0] - complex{1.0, 2.0} ) < 1E-6 ); - BOOST_REQUIRE(( sizes(arr3)==decltype(sizes(arr3)){100, 2} )); - BOOST_REQUIRE( arr3[5][0] == real(arr[5]) ); - BOOST_REQUIRE( arr3[5][1] == imag(arr[5]) ); -#endif -} +#ifndef _MSC_VER // problem with MVSC 14.3 c++17 + multi::array arr2{arr.reinterpret_array_cast()}; + BOOST_TEST( dimensionality(arr2) == dimensionality(arr) ); + BOOST_TEST( std::abs( arr2[0] - 1.0 ) < 1E-6 ); + BOOST_TEST( std::abs( arr2[1] - 1.0 ) < 1E-6 ); -BOOST_AUTO_TEST_CASE(multi_reinterpret_array_cast_tuple_as_extra_dimension) { - using vector3 = std::array; + multi::array arr3{arr.reinterpret_array_cast(2)}; - vector3 v3d; + BOOST_TEST(( arr3.sizes() == decltype(arr3.sizes()){100, 2} )); + BOOST_TEST( std::abs( arr3[5][0] - real(arr[5]) ) < 1E-6 ); + BOOST_TEST( std::abs( arr3[5][1] - imag(arr[5]) ) < 1E-6 ); - // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast, cppcoreguidelines-avoid-c-arrays, hicpp-avoid-c-arrays, modernize-avoid-c-arrays): test - BOOST_REQUIRE( &reinterpret_cast(v3d)[1] == &std::get<1>(v3d) ); + arr.reinterpret_array_cast(2)[0][0] = 99.9; + arr().reinterpret_array_cast(2)[0][0] = 99.9; -#ifndef _MSC_VER // problem with MVSC 14.3 c++17 - { - multi::array arr(multi::extensions_t<1>{multi::iextension{10}}); - BOOST_REQUIRE( &arr.reinterpret_array_cast(3)[2][1] == &std::get<1>(arr[2]) ); - } - { - multi::array arr({10, 20}); - BOOST_REQUIRE( &arr.reinterpret_array_cast(3)[5][7][2] == &std::get<2>(arr[5][7]) ); - } - { - multi::array const arr({ - 4, 5 - }, - vector3{{1.0, 2.0, 3.0}}); - - BOOST_REQUIRE( arr.reinterpret_array_cast(3).dimensionality == 3 ); - BOOST_REQUIRE( decltype(arr.reinterpret_array_cast(3))::dimensionality == 3 ); - BOOST_REQUIRE( dimensionality(arr.reinterpret_array_cast(3)) == 3 ); - - BOOST_REQUIRE( arr.reinterpret_array_cast(3).num_elements() == arr.num_elements()*3 ); - BOOST_REQUIRE( arr.reinterpret_array_cast(3).size() == 4 ); - BOOST_REQUIRE( arr.reinterpret_array_cast(3)[0].size() == 5 ); - BOOST_REQUIRE( arr.reinterpret_array_cast(3)[0][0].size() == 3 ); - BOOST_REQUIRE( &arr.reinterpret_array_cast(3)[2][3][0] == &std::get<0>(arr[2][3]) ); - BOOST_REQUIRE( &arr.reinterpret_array_cast(3)[2][3][1] == &std::get<1>(arr[2][3]) ); - BOOST_REQUIRE( &arr.reinterpret_array_cast(3)[2][3][2] == &std::get<2>(arr[2][3]) ); - - multi::array const arr2 = arr.reinterpret_array_cast(3); - BOOST_REQUIRE( arr2[2][3][0] == std::get<0>(arr[2][3]) ); - BOOST_REQUIRE( arr2[2][3][1] == std::get<1>(arr[2][3]) ); - BOOST_REQUIRE( arr2[2][3][2] == std::get<2>(arr[2][3]) ); - - auto arr3 = +arr.reinterpret_array_cast(3); - BOOST_REQUIRE( arr3 == arr2 ); +#endif } + + BOOST_AUTO_TEST_CASE(multi_reinterpret_array_cast_tuple_as_extra_dimension) { + using vector3 = std::array; + + vector3 v3d; + +#if defined(__clang__) + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wunknown-warning-option" + #pragma clang diagnostic ignored "-Wunsafe-buffer-usage" #endif -} -template struct complex_dummy { - T real; - T imag; -}; + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast, cppcoreguidelines-avoid-c-arrays, hicpp-avoid-c-arrays, modernize-avoid-c-arrays): test + BOOST_TEST( &reinterpret_cast(v3d)[1] == &std::get<1>(v3d) ); -BOOST_AUTO_TEST_CASE(multi_reinterpret_array_cast) { - { - std::complex cee{1.0, 2.0}; +#if defined(__clang__) + #pragma clang diagnostic pop +#endif - auto* ptr = reinterpret_cast*>(&cee); // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast) - ptr->real = 11; - BOOST_REQUIRE(real(cee)==11); - } - { - multi::array, 1> arr(multi::extensions_t<1>{multi::iextension{10}}); - std::iota(begin(arr), end(arr), 1.0); - BOOST_REQUIRE( arr[8] == 9.0 ); - auto&& arr2 = arr.reinterpret_array_cast>(); - arr2[8].real = 1000.0; - BOOST_REQUIRE( arr[8] == 1000.0 ); +#ifndef _MSC_VER // problem with MVSC 14.3 c++17 + { + multi::array arr(multi::extensions_t<1>{multi::iextension{10}}); + BOOST_TEST( &arr.reinterpret_array_cast(3)[2][1] == &std::get<1>(arr[2]) ); + } + { + multi::array arr({10, 20}); + BOOST_TEST( &arr.reinterpret_array_cast(3)[5][7][2] == &std::get<2>(arr[5][7]) ); + } + { + multi::array const arr({4, 5}, vector3{{1.0, 2.0, 3.0}}); + + BOOST_TEST( arr.reinterpret_array_cast(3).dimensionality == 3 ); + BOOST_TEST( decltype(arr.reinterpret_array_cast(3))::dimensionality == 3 ); + BOOST_TEST( dimensionality(arr.reinterpret_array_cast(3)) == 3 ); + + BOOST_TEST( arr.reinterpret_array_cast(3).num_elements() == arr.num_elements()*3 ); + BOOST_TEST( arr.reinterpret_array_cast(3).size() == 4 ); + BOOST_TEST( arr.reinterpret_array_cast(3)[0].size() == 5 ); + BOOST_TEST( arr.reinterpret_array_cast(3)[0][0].size() == 3 ); + BOOST_TEST( &arr.reinterpret_array_cast(3)[2][3][0] == &std::get<0>(arr[2][3]) ); + BOOST_TEST( &arr.reinterpret_array_cast(3)[2][3][1] == &std::get<1>(arr[2][3]) ); + BOOST_TEST( &arr.reinterpret_array_cast(3)[2][3][2] == &std::get<2>(arr[2][3]) ); + + multi::array const arr2{arr.reinterpret_array_cast(3)}; + BOOST_TEST( std::abs( arr2[2][3][0] - std::get<0>(arr[2][3]) ) < 1E-6 ); + BOOST_TEST( std::abs( arr2[2][3][1] - std::get<1>(arr[2][3]) ) < 1E-6 ); + BOOST_TEST( std::abs( arr2[2][3][2] - std::get<2>(arr[2][3]) ) < 1E-6 ); + + auto arr3 = +arr.reinterpret_array_cast(3); + BOOST_TEST( arr3 == arr2 ); + } +#endif } -} -BOOST_AUTO_TEST_CASE(multi_reinterpret_array_cast_realcomplex) { - using complex = std::complex; - { - complex cee{1.0, 2.0}; - auto* conjd_cee = reinterpret_cast*>(&cee); // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast) - (*conjd_cee)[0] = 11; - BOOST_REQUIRE( conjd_cee ); - BOOST_REQUIRE( real(cee)==11 ); - } - { - complex cee{1, 2}; - // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast, cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays): test purposes - auto* ceePC = reinterpret_cast(&cee); - (*ceePC)[0] = 11; - BOOST_REQUIRE( ceePC ); - BOOST_REQUIRE( real(cee)==11 ); + BOOST_AUTO_TEST_CASE(multi_reinterpret_array_cast) { + { + std::complex cee{1.0, 2.0}; + + auto* ptr = reinterpret_cast*>(&cee); // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast) + ptr->real = 11.0; + BOOST_TEST( std::abs( real(cee) - 11.0 ) < 1E-6 ); + } + { + multi::array, 1> arr(multi::extensions_t<1>{multi::iextension{10}}); + std::iota(begin(arr), end(arr), 1.0); + BOOST_TEST( std::abs( real(arr[8]) - 9.0 ) < 1E-6); + auto&& arr2 = arr.reinterpret_array_cast>(); + arr2[8].real = 1000.0; + BOOST_TEST( std::abs( real(arr[8]) - 1000.0 ) < 1E-6 ); + } } + + BOOST_AUTO_TEST_CASE(multi_reinterpret_array_cast_realcomplex) { + using complex = std::complex; + { + complex cee{1.0, 2.0}; + auto* conjd_cee = reinterpret_cast*>(&cee); // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast) + (*conjd_cee)[0] = 11.0; + BOOST_TEST( conjd_cee ); + BOOST_TEST( std::abs( real(cee) - 11.0 ) < 1E-6 ); + } + { + complex cee{1.0, 2.0}; + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast, cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays): test purposes + auto* ceePC = reinterpret_cast(&cee); + (*ceePC)[0] = 11.0; + BOOST_TEST( ceePC ); + BOOST_TEST( std::abs( real(cee) - 11.0 ) < 1E-6 ); + } #ifndef _MSC_VER // problem with MSVC 14.3 c++17 - { - multi::array arr(multi::extensions_t<1>{multi::iextension{10}}); + { + multi::array arr(multi::extensions_t<1>{multi::iextension{10}}); - auto&& arr2 = arr.reinterpret_array_cast(2); + auto&& arr2 = arr.reinterpret_array_cast(2); - arr2[8][0] = 1000.0; - arr2[8][1] = 2000.0; + arr2[8][0] = 1000.0; + arr2[8][1] = 2000.0; - BOOST_REQUIRE(( arr[8] == std::complex{1000.0, 2000.0} )); - } + BOOST_TEST(( arr[8] == std::complex{1000.0, 2000.0} )); + } #endif -} + } -BOOST_AUTO_TEST_CASE(multi_reinterpret_array_cast_pair_to_complex) { - using complex = std::complex; - using pair = std::pair; - multi::array arr({10, 10}, complex{3.0, 4.0}); + BOOST_AUTO_TEST_CASE(multi_reinterpret_array_cast_pair_to_complex) { + using complex = std::complex; + using pair = std::pair; + multi::array arr({10, 10}, complex{3.0, 4.0}); - multi::array const& Aconst = arr; - auto&& A_block = Aconst({0, 5}, {0, 5}); + multi::array const& Aconst = arr; + auto&& A_block = Aconst({0, 5}, {0, 5}); - auto const& Apair_block = A_block.template reinterpret_array_cast(); // const is important // cppcheck 1.90 needs `template` to avoid internal bug - BOOST_REQUIRE( &Apair_block[1][2] == static_cast(&arr[1][2]) ); + // const is important below + auto const& Apair_block = A_block.template reinterpret_array_cast(); // cppcheck 1.90 needs `template` to avoid internal bug + + BOOST_TEST( &Apair_block[1][2] == static_cast(&arr[1][2]) ); #ifndef _MSC_VER // problems with MSVC 14.3 c++17 - auto&& Adoubles_block = A_block.reinterpret_array_cast(2); - BOOST_REQUIRE( &Adoubles_block[1][2][0] == static_cast(&arr[1][2]) ); + auto&& Adoubles_block = A_block.reinterpret_array_cast(2); + BOOST_TEST( &Adoubles_block[1][2][0] == static_cast(&arr[1][2]) ); #endif -} + } -BOOST_AUTO_TEST_CASE(multi_reinterpret_array_cast_pointer) { - multi::array arr({10, 10}, 5.0); + BOOST_AUTO_TEST_CASE(multi_reinterpret_array_cast_pointer) { + multi::array arr({10, 10}, 5.0); - auto&& Aconstcast = arr.reinterpret_array_cast(); - BOOST_REQUIRE( &arr[0][0] == &Aconstcast[0][0] ); - static_assert(std::is_same_v); -} + auto&& Aconstcast = arr.reinterpret_array_cast(); + BOOST_TEST( &arr[0][0] == &Aconstcast[0][0] ); + static_assert(std::is_same_v); + } + + BOOST_AUTO_TEST_CASE(const_array_cast) { + multi::array arr({10, 10}, 5.0); // NOLINT(misc-const-correctness) test const cast + + multi::array const& carr = arr; -BOOST_AUTO_TEST_CASE(const_array_cast) { - multi::array arr({10, 10}, 5.0); // NOLINT(misc-const-correctness) test const cast + auto&& marr = carr.const_array_cast(); - multi::array const& carr = arr; + marr[1][1] = 6.0; - auto&& marr = carr.const_array_cast(); + BOOST_TEST( std::abs( carr[1][1] - 6.0 ) < 1E-6 ); + } + + // test packing 4 doubles +#ifndef _MSC_VER + { + using packed_type = std::array; + multi::array arr_4pc({10, 25}); + + BOOST_TEST( arr_4pc[0].size() == 25 ); + + arr_4pc[0][0] = packed_type{{1.0, 2.0, 3.0, 4.0}}; + arr_4pc[0][1] = packed_type{{5.0, 6.0, 7.0, 8.0}}; - marr[1][1] = 6.0; + auto&& arr = arr_4pc.reinterpret_array_cast(4).rotated().flatted().unrotated(); + + BOOST_TEST( arr[0].size() == 100 ); + + BOOST_TEST( std::abs( arr[0][0] - 1.0 ) < 1E-6 ); + BOOST_TEST( std::abs( arr[0][1] - 2.0 ) < 1E-6 ); + BOOST_TEST( std::abs( arr[0][2] - 3.0 ) < 1E-6 ); + BOOST_TEST( std::abs( arr[0][3] - 4.0 ) < 1E-6 ); + + BOOST_TEST( std::abs( arr[0][4] - 5.0 ) < 1E-6 ); + BOOST_TEST( std::abs( arr[0][5] - 6.0 ) < 1E-6 ); + BOOST_TEST( std::abs( arr[0][6] - 7.0 ) < 1E-6 ); + BOOST_TEST( std::abs( arr[0][7] - 8.0 ) < 1E-6 ); + } +#endif - BOOST_REQUIRE( carr[1][1] == 6.0 ); + return boost::report_errors(); } diff --git a/external_codes/boost_multi/multi/test/reversed.cpp b/external_codes/boost_multi/multi/test/reversed.cpp index 5fd104aef2..0a3c19caf5 100644 --- a/external_codes/boost_multi/multi/test/reversed.cpp +++ b/external_codes/boost_multi/multi/test/reversed.cpp @@ -1,86 +1,69 @@ -// -*-indent-tabs-mode:t;c-basic-offset:4;tab-width:4;autowrap:nil;-*- -// Copyright 2019-2022 Alfredo A. Correa +// Copyright 2019-2024 Alfredo A. Correa // Copyright 2024 Matt Borland // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt #include -// Suppress warnings from boost.test -#if defined(__clang__) -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wold-style-cast" -# pragma clang diagnostic ignored "-Wundef" -# pragma clang diagnostic ignored "-Wconversion" -# pragma clang diagnostic ignored "-Wsign-conversion" -# pragma clang diagnostic ignored "-Wfloat-equal" -#elif defined(__GNUC__) -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wold-style-cast" -# pragma GCC diagnostic ignored "-Wundef" -# pragma GCC diagnostic ignored "-Wconversion" -# pragma GCC diagnostic ignored "-Wsign-conversion" -# pragma GCC diagnostic ignored "-Wfloat-equal" -#endif - -#ifndef BOOST_TEST_MODULE -# define BOOST_TEST_MAIN -#endif - -#include +#include // for forward namespace multi = boost::multi; -BOOST_AUTO_TEST_CASE(multi_reversed_3d) { - multi::array arr({30, 40, 50}); - - BOOST_TEST_REQUIRE( arr.reversed().size() == 50 ); - - BOOST_REQUIRE( & arr.reversed()[3][5][7] == &arr[7][5][3] ); -} - template auto flatted_last(Array&& arr) { - return reversed(flatted(transposed(reversed(std::forward(arr))))); + return reversed(reversed(std::forward(arr)).transposed().flatted()); } template auto partitioned_last(Array&& arr, multi::size_type n) { - return reversed(transposed(partitioned(reversed(std::forward(arr)), n))); + return reversed( reversed(std::forward(arr)).partitioned(n).transposed().transposed()); } -BOOST_AUTO_TEST_CASE(multi_reversed_4d) { - multi::array arr({13, 5, 7, 11}); +#include +#define BOOST_AUTO_TEST_CASE(CasenamE) /**/ - BOOST_TEST_REQUIRE( arr.reversed().size() == 11 ); +auto main() -> int { // NOLINT(readability-function-cognitive-complexity,bugprone-exception-escape) +BOOST_AUTO_TEST_CASE(multi_reversed_3d) { + multi::array arr({ 30, 40, 50 }); + + BOOST_TEST( arr.reversed().size() == 50 ); + + BOOST_TEST( & arr.reversed()[3][5][7] == &arr[7][5][3] ); +} + +BOOST_AUTO_TEST_CASE(multi_reversed_4d) { + using std::get; // workaround use of function template name with no prior declaration in function call with explicit template arguments is a C++20 extension [-Wc++20-extensions] - BOOST_REQUIRE( &arr.reversed()[1][2][3][4] == &arr[4][3][2][1] ); + multi::array arr({ 13, 5, 7, 11 }); + BOOST_TEST( arr.reversed().size() == 11 ); - BOOST_REQUIRE( std::get<0>( arr.reversed().transposed().flatted().reversed().sizes() ) == 13 ); - BOOST_REQUIRE( std::get<1>( arr.reversed().transposed().flatted().reversed().sizes() ) == 5 ); - BOOST_REQUIRE( std::get<2>( arr.reversed().transposed().flatted().reversed().sizes() ) == 77 ); + BOOST_TEST( &arr.reversed()[1][2][3][4] == &arr[4][3][2][1] ); - BOOST_REQUIRE(( sizes(arr.reversed().transposed().flatted().reversed()) == decltype(sizes(arr.reversed().transposed().flatted().reversed())){13, 5, 77} )); + BOOST_TEST( get<0>( arr.reversed().transposed().flatted().reversed().sizes() ) == 13 ); + BOOST_TEST( get<1>( arr.reversed().transposed().flatted().reversed().sizes() ) == 5 ); + BOOST_TEST( get<2>( arr.reversed().transposed().flatted().reversed().sizes() ) == 77 ); - BOOST_REQUIRE( &arr.reversed().transposed().flatted().reversed()[1][2][ 5] == & arr[1][2][0][ 5] ); - BOOST_REQUIRE( &arr.reversed().transposed().flatted().reversed()[1][2][10] == & arr[1][2][0][10] ); - BOOST_REQUIRE( &arr.reversed().transposed().flatted().reversed()[1][2][11] == & arr[1][2][1][ 0] ); - BOOST_REQUIRE( &arr.reversed().transposed().flatted().reversed()[1][2][12] == & arr[1][2][1][ 1] ); + BOOST_TEST(( sizes(arr.reversed().transposed().flatted().reversed()) == decltype(sizes(arr.reversed().transposed().flatted().reversed())){13, 5, 77} )); + BOOST_TEST( &arr.reversed().transposed().flatted().reversed()[1][2][ 5] == & arr[1][2][0][ 5] ); + BOOST_TEST( &arr.reversed().transposed().flatted().reversed()[1][2][10] == & arr[1][2][0][10] ); + BOOST_TEST( &arr.reversed().transposed().flatted().reversed()[1][2][11] == & arr[1][2][1][ 0] ); + BOOST_TEST( &arr.reversed().transposed().flatted().reversed()[1][2][12] == & arr[1][2][1][ 1] ); - BOOST_REQUIRE( & flatted_last(arr)[1][2][12] == & arr[1][2][1][1] ); + BOOST_TEST( & flatted_last(arr)[1][2][12] == & arr[1][2][1][1] ); } BOOST_AUTO_TEST_CASE(multi_reversed_4d_partition_last) { - multi::array arr({11, 5, 7, 12}); + multi::array arr({ 11, 5, 7, 12 }); - BOOST_REQUIRE( arr.reversed().size() == 12 ); + BOOST_TEST( arr.reversed().size() == 12 ); - BOOST_REQUIRE( & arr.reversed()[1][2][3][4] == &arr[4][3][2][1] ); + BOOST_TEST( & arr.reversed()[1][2][3][4] == &arr[4][3][2][1] ); - BOOST_REQUIRE( & arr.reversed().partitioned(3).transposed().reversed()[1][2][3][0][1] == & arr[1][2][3][1] ); - BOOST_REQUIRE( & arr.reversed().partitioned(3).transposed().reversed()[1][2][3][1][0] == & arr[1][2][3][4] ); - BOOST_REQUIRE( & arr.reversed().partitioned(3).transposed().reversed()[1][2][3][1][1] == & arr[1][2][3][5] ); + BOOST_TEST( & arr.reversed().partitioned(3).transposed().reversed()[1][2][3][0][1] == & arr[1][2][3][1] ); + BOOST_TEST( & arr.reversed().partitioned(3).transposed().reversed()[1][2][3][1][0] == & arr[1][2][3][4] ); + BOOST_TEST( & arr.reversed().partitioned(3).transposed().reversed()[1][2][3][1][1] == & arr[1][2][3][5] ); - BOOST_REQUIRE( & partitioned_last(arr, 3)[1][2][3][1][1] == & arr[1][2][3][5] ); + BOOST_TEST( & partitioned_last(arr, 3)[1][2][3][1][1] == & arr[1][2][3][5] ); } +return boost::report_errors();} diff --git a/external_codes/boost_multi/multi/test/rotated.cpp b/external_codes/boost_multi/multi/test/rotated.cpp index aa2a6521d7..139ed7bed4 100644 --- a/external_codes/boost_multi/multi/test/rotated.cpp +++ b/external_codes/boost_multi/multi/test/rotated.cpp @@ -1,167 +1,342 @@ -// Copyright 2021-2023 Alfredo A. Correa +// Copyright 2021-2024 Alfredo A. Correa // Copyright 2024 Matt Borland // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt -#include - -#include -#include // for std::iota - -// Suppress warnings from boost.test -#if defined(__clang__) -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wold-style-cast" -# pragma clang diagnostic ignored "-Wundef" -# pragma clang diagnostic ignored "-Wconversion" -# pragma clang diagnostic ignored "-Wsign-conversion" -# pragma clang diagnostic ignored "-Wfloat-equal" -#elif defined(__GNUC__) -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wold-style-cast" -# pragma GCC diagnostic ignored "-Wundef" -# pragma GCC diagnostic ignored "-Wconversion" -# pragma GCC diagnostic ignored "-Wsign-conversion" -# pragma GCC diagnostic ignored "-Wfloat-equal" -#endif +#include -#ifndef BOOST_TEST_MODULE -# define BOOST_TEST_MAIN -#endif +#include // for array, layout_t, subarray, sizes -#include +#include // for array +#include // for iota +#if(__cplusplus >= 202002L) + #include // IWYU pragma: keep +#endif +#include // for is_assignable_v namespace multi = boost::multi; -BOOST_AUTO_TEST_CASE(multi_rotate_3d) { - multi::array arr({3, 4, 5}); +#if(__cplusplus >= 202002L) + #if defined(__cpp_lib_ranges_repeat) && (__cpp_lib_ranges_repeat >= 202207L) - BOOST_REQUIRE( std::get<0>(sizes(arr)) == 3 ); - BOOST_REQUIRE( std::get<1>(sizes(arr)) == 4 ); - BOOST_REQUIRE( std::get<2>(sizes(arr)) == 5 ); +template +auto meshgrid(X1D const& x, Y1D const& y) { + return std::pair{x.broadcasted().rotated(), y.broadcasted()}; +} - auto&& RA = rotated(arr); - BOOST_REQUIRE(( sizes(RA) == decltype(sizes(RA)){4, 5, 3} )); - BOOST_REQUIRE( &arr[0][1][2] == &RA[1][2][0] ); +template +auto meshgrid_copy(X1D const& x, Y1D const& y) { + auto ret = std::pair{ + multi::array({x.size(), y.size()}), + multi::array(std::views::repeat(y, x.size())) + }; - auto&& UA = unrotated(arr); - BOOST_REQUIRE(( sizes(UA) == decltype(sizes(UA)){5, 3, 4} )); - BOOST_REQUIRE( &arr[0][1][2] == &UA[2][0][1] ); + std::fill(ret.first.rotated().begin(), ret.first.rotated().end(), x); + // std::ranges::fill(ret.first.rotated(), x); - auto&& RRA = rotated(RA); - BOOST_REQUIRE(( sizes(RRA) == decltype(sizes(RRA)){5, 3, 4} )); - BOOST_REQUIRE( &arr[0][1][2] == &RRA[2][0][1] ); + return ret; } + #endif +#endif -BOOST_AUTO_TEST_CASE(multi_rotate_4d) { - multi::array original({14, 14, 7, 4}); +#define BOOST_AUTO_TEST_CASE(CasenamE) /**/ - auto&& unrotd = original.unrotated(); - BOOST_REQUIRE(( sizes(unrotd) == decltype(sizes(unrotd)){4, 14, 14, 7} )); - BOOST_REQUIRE( &original[0][1][2][3] == &unrotd[3][0][1][2] ); +auto main() -> int { // NOLINT(readability-function-cognitive-complexity,bugprone-exception-escape) +#ifndef _MSC_VER // msvc 14.40 gets confused with constexpr + BOOST_AUTO_TEST_CASE(constexpr_carray_rotated_end) { + constexpr auto test = [] { + std::array + buffer = { + {0, 1, 2, 3, 4, 5, 6, 7, 8} + }; // , 10, 11}; - auto&& unrotd2 = original.unrotated().unrotated(); - BOOST_REQUIRE(( sizes(unrotd2) == decltype(sizes(unrotd2)){7, 4, 14, 14} )); - BOOST_REQUIRE( &original[0][1][2][3] == &unrotd2[2][3][0][1] ); -} + multi::array_ref arr({3, 3}, buffer.data()); // // TODO(correaa) think how to handle references to arrays (UB) -BOOST_AUTO_TEST_CASE(multi_rotate_4d_op) { - multi::array original({14, 14, 7, 4}); + auto const& arrrot1 = arr.rotated()[1]; + return (arrrot1.end() != arrrot1.begin()); + }(); + BOOST_TEST(test); + } - auto&& unrotd = (original.unrotated()); - BOOST_REQUIRE(( sizes(unrotd) == decltype(sizes(unrotd)){4, 14, 14, 7} )); - BOOST_REQUIRE( &original[0][1][2][3] == &unrotd[3][0][1][2] ); + BOOST_AUTO_TEST_CASE(constexpr_carray_rotated_end_interval) { + constexpr auto test = [] { + std::array + buffer = { + {0, 1, 2, 3, 4, 5, 6, 7, 8} + }; // , 10, 11}; - auto&& unrotd2 = (original.unrotated().unrotated()); - BOOST_REQUIRE(( sizes(unrotd2) == decltype(sizes(unrotd2)){7, 4, 14, 14} )); - BOOST_REQUIRE( &original[0][1][2][3] == &unrotd2[2][3][0][1] ); -} + multi::array_ref arr({3, 3}, buffer.data()); // // TODO(correaa) think how to handle references to arrays (UB) -BOOST_AUTO_TEST_CASE(multi_rotate_part1) { - // clang-format off - std::array, 4> stdarr = {{ - {{ 0.0, 1.0, 2.0, 3.0, 4.0}}, - {{ 5.0, 6.0, 7.0, 8.0, 9.0}}, - {{10.0, 11.0, 12.0, 13.0, 14.0}}, - {{15.0, 16.0, 17.0, 18.0, 19.0}}, - }}; - // clang-format on - - std::array, 4> stdarr2 = {}; - - multi::array_ref arr(&stdarr[0][0], {4, 5}); // NOLINT(readability-container-data-pointer) test access - multi::array_ref arr2(&stdarr2[0][0], {4, 5}); // NOLINT(readability-container-data-pointer) test access - - rotated(arr2) = rotated(arr); - BOOST_REQUIRE( arr2[1][1] == 6 ); - BOOST_REQUIRE( arr2[2][1] == 11 ); - BOOST_REQUIRE( arr2[1][2] == 7 ); - BOOST_REQUIRE( (arr2.rotated() ) == (arr.rotated() ) ); - BOOST_REQUIRE( (arr2.rotated() )[2][1] == 7 ); -} + return arr.rotated()[1]({3, 3}).size() == 0; + }(); + BOOST_TEST(test); + } -BOOST_AUTO_TEST_CASE(multi_rotate) { - { - multi::array arr = { - {00.0, 01.0}, - {10.0, 11.0}, + BOOST_AUTO_TEST_CASE(constexpr_carray_diagonal_end_2D) { + constexpr auto test = [] { + std::array + buffer = {}; + + multi::array_ref arr({3, 4}, buffer.data()); // // TODO(correaa) think how to handle references to arrays (UB) + + return arr.diagonal().end() != arr.diagonal().begin(); + }(); + BOOST_TEST(test); + } + + BOOST_AUTO_TEST_CASE(constexpr_carray_rotated_end_3D) { + constexpr auto test = [] { + std::array + buffer = {}; + + multi::array_ref arr({3, 4, 5}, buffer.data()); // // TODO(correaa) think how to handle references to arrays (UB) + + return arr.diagonal().diagonal().end() != arr.diagonal().diagonal().begin(); + }(); + BOOST_TEST(test); + } + + #if __cplusplus >= 202002L + #if defined(__GNUC__) && !defined(__clang__) && !defined(__NVCOMPILER) && !defined(__NVCC__) + BOOST_AUTO_TEST_CASE(constexpr_dynamic_array_rotated_end) { + constexpr auto test = [] { + multi::array arr({3, 3}, 99); + return arr.rotated()[1].end() != arr.rotated()[1].begin(); + }(); + BOOST_TEST(test); + } + #endif + #endif + +#endif // MSVC + + BOOST_AUTO_TEST_CASE(multi_2d_const) { + multi::array const arr = { + {10, 20}, + {30, 40}, + }; + + BOOST_TEST( arr.rotated()[1][1] == 40 ); + static_assert(!std::is_assignable_v); + } + + BOOST_AUTO_TEST_CASE(multi_2d) { + multi::array arr = { + {10, 20}, + {30, 40}, }; - BOOST_REQUIRE( arr[1][0] == 10 ); - BOOST_REQUIRE( (arr.rotated())[0][1] == 10 ); - BOOST_REQUIRE( & arr[1][0] == &(arr.rotated() )[0][1] ); - BOOST_REQUIRE( arr.transposed()[0][1] == 10 ); - BOOST_REQUIRE( transposed(arr)[0][1] == 10 ); - BOOST_REQUIRE( (~arr)[0][1] == 10 ); - BOOST_REQUIRE( &arr[1][0] == &arr.transposed()[0][1] ); + BOOST_TEST( arr.rotated()[1][1] == 40 ); + + // what(arr.rotated()[0][0]); + + static_assert(std::is_assignable_v); - (arr.rotated())[0][1] = 100; - BOOST_REQUIRE( arr[1][0] == 100 ); + // arr.rotated()[1][1] = 50; } - { - multi::array arr({11, 13, 17}); - BOOST_REQUIRE( & arr[3][5][7] == & arr.transposed()[5][3][7] ); - BOOST_REQUIRE( & arr[3][5][7] == & transposed(arr) [5][3][7] ); - BOOST_REQUIRE( & arr[3][5][7] == & (~arr) [5][3][7] ); - BOOST_REQUIRE( & arr[3][5][7] == & arr[3].transposed()[7][5] ); - BOOST_REQUIRE( & arr[3][5][7] == & (~arr[3]) [7][5] ); - BOOST_REQUIRE( & arr[3][5] == & (~arr)[5][3] ); + BOOST_AUTO_TEST_CASE(multi_rotate_3d) { + multi::array arr({3, 4, 5}); + + using std::get; + + BOOST_TEST( get<0>(arr.sizes()) == 3 ); + BOOST_TEST( get<1>(arr.sizes()) == 4 ); + BOOST_TEST( get<2>(arr.sizes()) == 5 ); + + auto&& RA = arr.rotated(); + BOOST_TEST(( sizes(RA) == decltype(RA.sizes()){4, 5, 3} )); + BOOST_TEST( &arr[0][1][2] == &RA[1][2][0] ); + + auto&& UA = arr.unrotated(); + BOOST_TEST(( sizes(UA) == decltype(sizes(UA)){5, 3, 4} )); + BOOST_TEST( &arr[0][1][2] == &UA[2][0][1] ); + + auto&& RRA = RA.rotated(); + BOOST_TEST(( sizes(RRA) == decltype(sizes(RRA)){5, 3, 4} )); + BOOST_TEST( &arr[0][1][2] == &RRA[2][0][1] ); + } + + BOOST_AUTO_TEST_CASE(multi_rotate_4d) { + using std::get; // workaround use of function template name with no prior declaration in function call with explicit template arguments is a C++20 extension [-Wc++20-extensions] + + multi::array original({14, 14, 7, 4}); - BOOST_REQUIRE( & ~~arr == & arr ); - BOOST_REQUIRE( & (arr.rotated().rotated().rotated() ) == & arr ); - BOOST_REQUIRE( & arr() == & (arr.rotated().rotated().rotated() ) ); - BOOST_REQUIRE( & (arr.rotated() ) != & arr ); - BOOST_REQUIRE( & (arr.unrotated().rotated()) == & arr ); + auto&& unrotd = original.unrotated(); + BOOST_TEST( get<0>(unrotd.sizes()) == 4 ); + BOOST_TEST( get<1>(unrotd.sizes()) == 14 ); + BOOST_TEST( get<2>(unrotd.sizes()) == 14 ); + BOOST_TEST( get<3>(unrotd.sizes()) == 7 ); - std::iota(arr.data_elements(), arr.data_elements() + arr.num_elements(), 0.1); - BOOST_REQUIRE( ~~arr == arr ); - BOOST_REQUIRE( arr.unrotated().rotated() == arr ); + BOOST_TEST(( unrotd.sizes() == decltype(unrotd.sizes()){4, 14, 14, 7} )); + BOOST_TEST( &original[0][1][2][3] == &unrotd[3][0][1][2] ); + + auto&& unrotd2 = original.unrotated().unrotated(); + BOOST_TEST(( sizes(unrotd2) == decltype(sizes(unrotd2)){7, 4, 14, 14} )); + BOOST_TEST( &original[0][1][2][3] == &unrotd2[2][3][0][1] ); + } + + BOOST_AUTO_TEST_CASE(multi_rotate_4d_op) { + multi::array original({14, 14, 7, 4}); + + auto&& unrotd = (original.unrotated()); + BOOST_TEST(( sizes(unrotd) == decltype(sizes(unrotd)){4, 14, 14, 7} )); + BOOST_TEST( &original[0][1][2][3] == &unrotd[3][0][1][2] ); + + auto&& unrotd2 = (original.unrotated().unrotated()); + BOOST_TEST(( sizes(unrotd2) == decltype(sizes(unrotd2)){7, 4, 14, 14} )); + BOOST_TEST( &original[0][1][2][3] == &unrotd2[2][3][0][1] ); + } + + BOOST_AUTO_TEST_CASE(multi_rotate_part1) { + // clang-format off + std::array, 4> stdarr = {{ + {{ 0, 1, 2, 3, 4}}, + {{ 5, 6, 7, 8, 9}}, + {{10, 11, 12, 13, 14}}, + {{15, 16, 17, 18, 19}}, + }}; + // clang-format on + + std::array, 4> stdarr2 = {}; + + multi::array_ref arr(&stdarr[0][0], {4, 5}); // NOLINT(readability-container-data-pointer) test access + multi::array_ref arr2(&stdarr2[0][0], {4, 5}); // NOLINT(readability-container-data-pointer) test access + + arr2.rotated() = arr.rotated(); + + BOOST_TEST( arr2[1][1] == 6 ); + BOOST_TEST( arr2[2][1] == 11 ); + BOOST_TEST( arr2[1][2] == 7 ); + + BOOST_TEST( arr2.rotated() == arr.rotated() ); + BOOST_TEST( arr2.rotated()[2][1] == 7 ); + } + + BOOST_AUTO_TEST_CASE(multi_rotate) { + { + multi::array arr = { + {00, 01}, + {10, 11}, + }; + BOOST_TEST( arr[1][0] == 10 ); + BOOST_TEST( (arr.rotated())[0][1] == 10 ); + BOOST_TEST( & arr[1][0] == &(arr.rotated() )[0][1] ); + + BOOST_TEST( arr.transposed()[0][1] == 10 ); + BOOST_TEST( arr.transposed()[0][1] == 10 ); + BOOST_TEST( (~arr)[0][1] == 10 ); + BOOST_TEST( &arr[1][0] == &arr.transposed()[0][1] ); + + (arr.rotated())[0][1] = 100; + BOOST_TEST( arr[1][0] == 100 ); + } + { + multi::array arr({11, 13, 17}); + BOOST_TEST( & arr[3][5][7] == & arr .transposed()[5][3][7] ); + BOOST_TEST( & arr[3][5][7] == & arr .transposed()[5][3][7] ); + BOOST_TEST( & arr[3][5][7] == & (~arr) [5][3][7] ); + BOOST_TEST( & arr[3][5][7] == & arr[3].transposed()[7][5] ); + BOOST_TEST( & arr[3][5][7] == & (~arr[3]) [7][5] ); + + BOOST_TEST( & arr[3][5] == & (~arr)[5][3] ); + + // BOOST_TEST( & ~~arr == & arr ); + // BOOST_TEST( & (arr.rotated().rotated().rotated() ) == & arr ); + // BOOST_TEST( & arr() == & (arr.rotated().rotated().rotated() ) ); + // BOOST_TEST( & (arr.rotated() ) != & arr ); + // BOOST_TEST( & (arr.unrotated().rotated()) == & arr ); + + std::iota(arr.elements().begin(), arr.elements().end(), 0.1); + BOOST_TEST( ~~arr == arr ); + BOOST_TEST( arr.unrotated().rotated() == arr ); + } + { + multi::array const arr = { + {00, 01}, + {10, 11}, + }; + BOOST_TEST( arr.rotated() [0][1] == 10 ); + BOOST_TEST( &(arr.rotated())[1][0] == &arr[0][1] ); + BOOST_TEST( &(~arr)[1][0] == &arr[0][1] ); + } + } + + BOOST_AUTO_TEST_CASE(multi_transposed) { + multi::array const arr0 = { + { 9, 24, 30, 9}, + { 4, 10, 12, 7}, + {14, 16, 36, 1}, + }; + multi::array const arr1 = arr0.transposed(); + multi::array const arr2 = ~arr0; + BOOST_TEST( arr1 == arr2 ); + } + + BOOST_AUTO_TEST_CASE(miguel) { + multi::array G2D({41, 35}); + auto const& G3D = G2D.rotated().partitioned(7).sliced(0, 3).unrotated(); + + BOOST_TEST( &G3D[0][0][0] == &G2D[0][0] ); } { - multi::array const arr = { + multi::array const arr = { {00, 01}, {10, 11}, }; - BOOST_REQUIRE( arr.rotated() [0][1] == 10 ); - BOOST_REQUIRE( &(arr.rotated())[1][0] == &arr[0][1] ); - BOOST_REQUIRE( &(~arr)[1][0] == &arr[0][1] ); + BOOST_TEST( arr.rotated() [0][1] == 10 ); + BOOST_TEST( &(arr.rotated())[1][0] == &arr[0][1] ); + BOOST_TEST( &(~arr)[1][0] == &arr[0][1] ); } -} -BOOST_AUTO_TEST_CASE(multi_transposed) { - multi::array const arr0 = { - { 9.0, 24.0, 30.0, 9.0}, - { 4.0, 10.0, 12.0, 7.0}, - {14.0, 16.0, 36.0, 1.0}, - }; - multi::array const arr1 = arr0.transposed(); - multi::array const arr2 = ~arr0; - BOOST_REQUIRE( arr1 == arr2 ); -} + BOOST_AUTO_TEST_CASE(multi_transposed) { + multi::array const arr0 = { + { 9, 24, 30, 9}, + { 4, 10, 12, 7}, + {14, 16, 36, 1}, + }; + multi::array const arr1{arr0.transposed()}; + multi::array const arr2{~arr0}; + BOOST_TEST( arr1 == arr2 ); + } + + BOOST_AUTO_TEST_CASE(miguel) { + multi::array G2D({41, 35}); + auto const& G3D = G2D.rotated().partitioned(7).sliced(0, 3).unrotated(); + + BOOST_TEST( &G3D[0][0][0] == &G2D[0][0] ); + } + +#if(__cplusplus >= 202002L) + #if defined(__cpp_lib_ranges_repeat) && (__cpp_lib_ranges_repeat >= 202207L) + #if !defined(__GNUC__) || (__GNUC__ < 14) + BOOST_AUTO_TEST_CASE(matlab_meshgrid) { + auto const x = multi::array{1, 2, 3}; + auto const y = multi::array{1, 2, 3, 4, 5}; -BOOST_AUTO_TEST_CASE(miguel) { - multi::array G2D({41, 35}); - auto const& G3D = G2D.rotated().partitioned(7).sliced(0, 3).unrotated(); - BOOST_REQUIRE( &G3D[0][0][0] == &G2D[0][0] ); + auto const& [X, Y] = meshgrid(x, y); + + auto const [X_copy, Y_copy] = meshgrid_copy(x, y); + + for(auto i : x.extension()) { + for(auto j : y.extension()) { + BOOST_TEST( X[i][j] == X_copy[i][j] ); + BOOST_TEST( Y[i][j] == Y_copy[i][j] ); + } + } + } + #endif + #endif +#endif + return boost::report_errors(); } diff --git a/external_codes/boost_multi/multi/test/scoped_allocator.cpp b/external_codes/boost_multi/multi/test/scoped_allocator.cpp index dd595ebc45..f9c3149a8e 100644 --- a/external_codes/boost_multi/multi/test/scoped_allocator.cpp +++ b/external_codes/boost_multi/multi/test/scoped_allocator.cpp @@ -3,34 +3,16 @@ // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt -#include - -#include -#include -#include - -// Suppress warnings from boost.test -#if defined(__clang__) -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wold-style-cast" -# pragma clang diagnostic ignored "-Wundef" -# pragma clang diagnostic ignored "-Wconversion" -# pragma clang diagnostic ignored "-Wsign-conversion" -# pragma clang diagnostic ignored "-Wfloat-equal" -#elif defined(__GNUC__) -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wold-style-cast" -# pragma GCC diagnostic ignored "-Wundef" -# pragma GCC diagnostic ignored "-Wconversion" -# pragma GCC diagnostic ignored "-Wsign-conversion" -# pragma GCC diagnostic ignored "-Wfloat-equal" -#endif - -#ifndef BOOST_TEST_MODULE -# define BOOST_TEST_MAIN -#endif +#include // for static_array, array -#include +// IWYU pragma: no_include // for max // bug in iwyu 14.0.6? with GNU stdlib +#include // for assert +#include // for size_t +#include // for int64_t, int32_t +// IWYU pragma: no_include // for allocator_traits<>::value_type +#include // for bad_alloc +#include // for scoped_allocator_adaptor +#include // for vector namespace multi = boost::multi; @@ -44,9 +26,11 @@ class allocator1 { using value_type = T; allocator1() noexcept = delete; - // NOLINTNEXTLINE(runtime/explicit) - allocator1(int* heap) : heap_{heap} { assert(heap_); } // NOLINT(google-explicit-constructor,hicpp-explicit-conversions) // NOSONAR(cpp:S1709) mimic memory resource syntax (pass pointer) - template allocator1(allocator1 const& other) noexcept : heap_{other.heap_} {} // NOLINT(google-explicit-constructor,hicpp-explicit-conversions) // NOSONAR(cpp:S1709) allocator conversions are not explicit + // NOLINTNEXTLINE(google-explicit-constructor,hicpp-explicit-conversions) + allocator1(int* heap) : heap_{heap} { assert(heap_); } // NOLINT(runtime/explicit) // NOSONAR(cpp:S1709) mimic memory resource syntax (pass pointer) + + // NOLINTNEXTLINE(google-explicit-constructor,hicpp-explicit-conversions) + template allocator1(allocator1 const& other) noexcept : heap_{other.heap_} {} // NOSONAR(cpp:S1709) allocator conversions are not explicit auto allocate(std::size_t n) { if(n == 0) { @@ -72,10 +56,10 @@ class allocator1 { }; template -auto operator!=(allocator1 const& self, allocator1 const& other) noexcept -> bool { return ! (self == other); } +auto operator!=(allocator1 const& self, allocator1 const& other) noexcept -> bool { return !(self == other); } template -auto operator==(allocator1 const& self, allocator1 const& other) noexcept -> bool { return (self == other); } +auto operator==(allocator1 const& self, allocator1 const& other) noexcept -> bool { return (self == other); } template class allocator2 { @@ -87,17 +71,19 @@ class allocator2 { using value_type = T; allocator2() noexcept = default; - // NOLINTNEXTLINE(runtime/explicit) - allocator2(std::int64_t* heap) : heap_{heap} { assert(heap_); } // NOLINT(google-explicit-constructor,hicpp-explicit-conversions) // NOSONAR(cpp:S1709) mimic memory resource syntax (pass pointer) - template allocator2(allocator2 const& other) noexcept : heap_{other.heap_} {} // NOLINT(google-explicit-constructor,hicpp-explicit-conversions) // NOSONAR(cpp:S1709) allocator conversions are not explicit + // NOLINTNEXTLINE(google-explicit-constructor,hicpp-explicit-conversions) + allocator2(std::int64_t* heap) : heap_{heap} { assert(heap_); } // NOLINT(runtime/explicit) // NOSONAR(cpp:S1709) mimic memory resource syntax (pass pointer) + + // NOLINTNEXTLINE(google-explicit-constructor,hicpp-explicit-conversions) + template allocator2(allocator2 const& other) noexcept : heap_{other.heap_} {} // NOSONAR(cpp:S1709) allocator conversions are not explicit auto allocate(std::size_t n) { if(n == 0) { return static_cast(nullptr); } - if(heap_ == nullptr) { + if(heap_ == nullptr) { // this cuts branches with UB (null deref) for the sanitizer throw std::bad_alloc{}; - } // this cuts branches with UB (null deref) for the sanitizer + } ++*heap_; return static_cast(::operator new(n * sizeof(value_type))); } @@ -118,7 +104,7 @@ class allocator2 { template auto operator!=(allocator2 const& self, allocator2 const& other) noexcept -> bool { - return ! (self == other); + return !(self == other); } template @@ -126,6 +112,10 @@ auto operator==(allocator2 const& self, allocator2 const& other) noexcept return (self == other); } +#include +#define BOOST_AUTO_TEST_CASE(CasenamE) /**/ + +auto main() -> int { // NOLINT(readability-function-cognitive-complexity,bugprone-exception-escape) BOOST_AUTO_TEST_CASE(scoped_allocator_vector) { std::int32_t heap1 = 0; std::int64_t heap2 = 0; @@ -137,10 +127,7 @@ BOOST_AUTO_TEST_CASE(scoped_allocator_vector) { InnerCont, std::scoped_allocator_adaptor< allocator1, - allocator2 - > - > - ; + allocator2>>; // OuterCont cont({&heap1, &heap2}); // gives ambiguous construction in libc++ OuterCont cont({&heap1, allocator2{&heap2}}); @@ -153,11 +140,11 @@ BOOST_AUTO_TEST_CASE(scoped_allocator_vector) { cont.back().resize(100); cont.back().resize(300); - // these values are depdenent on the implementation of std::vector - #if !defined(_MSC_VER) +// these values are depdenent on the implementation of std::vector +#if !defined(_MSC_VER) BOOST_TEST( heap1 == 1 ); BOOST_TEST( heap2 == 1L ); - #endif +#endif } BOOST_TEST( heap1 == 0 ); @@ -173,9 +160,9 @@ BOOST_AUTO_TEST_CASE(scoped_allocator_array_vector) { { OuterCont cont( - #ifdef _MSC_VER // problem with MSVC 14.3 c++17 +#ifdef _MSC_VER // problem with MSVC 14.3 c++17 multi::extensions_t<2> - #endif +#endif {3, 4}, {&heap1, allocator2{&heap2}} // without allocator2<>{...} gives ambiguous construction in libc++ ); @@ -184,11 +171,11 @@ BOOST_AUTO_TEST_CASE(scoped_allocator_array_vector) { cont[1][2].resize(100); cont[1][2].resize(200); - // these values are depdenent on the implementation of std::vector - #if !defined(_MSC_VER) +// these values are depdenent on the implementation of std::vector +#if !defined(_MSC_VER) BOOST_TEST( heap1 == 1 ); BOOST_TEST( heap2 == 1L ); - #endif +#endif } } @@ -233,3 +220,4 @@ BOOST_AUTO_TEST_CASE(scoped_allocator_array_vector) { // BOOST_TEST( heap2 == 1L ); // } // } +return boost::report_errors();} diff --git a/external_codes/boost_multi/multi/test/select_column.cpp b/external_codes/boost_multi/multi/test/select_column.cpp index ee99829ae8..c9c23ef284 100644 --- a/external_codes/boost_multi/multi/test/select_column.cpp +++ b/external_codes/boost_multi/multi/test/select_column.cpp @@ -3,44 +3,24 @@ // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt -#include - -// Suppress warnings from boost.test -#if defined(__clang__) -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wold-style-cast" -# pragma clang diagnostic ignored "-Wundef" -# pragma clang diagnostic ignored "-Wconversion" -# pragma clang diagnostic ignored "-Wsign-conversion" -#elif defined(__GNUC__) -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wold-style-cast" -# pragma GCC diagnostic ignored "-Wundef" -# pragma GCC diagnostic ignored "-Wconversion" -# pragma GCC diagnostic ignored "-Wsign-conversion" -#endif - -#ifndef BOOST_TEST_MODULE -# define BOOST_TEST_MAIN -#endif - -#include - -#if defined(__clang__) -# pragma clang diagnostic pop -#elif defined(__GNUC__) -# pragma GCC diagnostic pop -#endif +#include // for intersecting_range, array, size + +#include // for size namespace multi = boost::multi; +#include +#define BOOST_AUTO_TEST_CASE(CasenamE) /**/ + +auto main() -> int { // NOLINT(readability-function-cognitive-complexity,bugprone-exception-escape) BOOST_AUTO_TEST_CASE(multi_array_range_section_1D) { - multi::array arr = {0, 10, 20}; (void)arr; - BOOST_REQUIRE( arr == arr(multi::ALL) ); - BOOST_REQUIRE( size(arr( 1 <= multi::ALL )) == 2 ); - BOOST_REQUIRE( arr( 1 <= multi::ALL )[0] == 10 ); - BOOST_REQUIRE( size(arr( multi::ALL < 2 )) == 2 ); - BOOST_REQUIRE( arr( multi::ALL < 2 )[1] == 10 ); + multi::array arr = { 0, 10, 20 }; + (void)arr; + BOOST_TEST( arr == arr(multi::ALL) ); + BOOST_TEST( size(arr( 1 <= multi::ALL )) == 2 ); + BOOST_TEST( arr( 1 <= multi::ALL )[0] == 10 ); + BOOST_TEST( size(arr( multi::ALL < 2 )) == 2 ); + BOOST_TEST( arr( multi::ALL < 2 )[1] == 10 ); } BOOST_AUTO_TEST_CASE(multi_array_range_section_part1) { @@ -54,25 +34,25 @@ BOOST_AUTO_TEST_CASE(multi_array_range_section_part1) { using multi::_; using multi::U; - BOOST_REQUIRE( size( arr( multi::ALL , 2) ) == size(arr) ); - BOOST_REQUIRE( size( arr( multi::_ , 2) ) == size(arr) ); - BOOST_REQUIRE( size( arr( *multi::_ , 2) ) == size(arr) ); - BOOST_REQUIRE( size( arr( multi::U , 2) ) == size(arr) ); - - BOOST_REQUIRE( size( arr( multi::ALL , 2) ) == 4 ); - BOOST_REQUIRE( size( arr( multi::ALL < 2 , 2) ) == 2 ); - BOOST_REQUIRE( size( arr( 1 <= multi::ALL , 2) ) == 3 ); - BOOST_REQUIRE( size( arr( 1 <= multi::ALL < 3 , 2) ) == 2 ); // NOLINT(bugprone-chained-comparison) - - BOOST_REQUIRE( size( arr( multi::_ , 2) ) == 4 ); - BOOST_REQUIRE( size( arr( multi::_ < 2 , 2) ) == 2 ); - BOOST_REQUIRE( size( arr( 1 <= multi::_ , 2) ) == 3 ); - BOOST_REQUIRE( size( arr( 1 <= multi::_ < 3 , 2) ) == 2 ); // NOLINT(bugprone-chained-comparison) - - BOOST_REQUIRE( size( arr( _ , 2) ) == 4 ); - BOOST_REQUIRE( size( arr( _ < 2 , 2) ) == 2 ); - BOOST_REQUIRE( size( arr( 1 <= _ , 2) ) == 3 ); - BOOST_REQUIRE( size( arr( 1 <= _ < 3 , 2) ) == 2 ); // NOLINT(bugprone-chained-comparison) + BOOST_TEST( size( arr( multi::ALL , 2) ) == size(arr) ); + BOOST_TEST( size( arr( multi::_ , 2) ) == size(arr) ); + BOOST_TEST( size( arr( *multi::_ , 2) ) == size(arr) ); + BOOST_TEST( size( arr( multi::U , 2) ) == size(arr) ); + + BOOST_TEST( size( arr( multi::ALL , 2) ) == 4 ); + BOOST_TEST( size( arr( multi::ALL < 2 , 2) ) == 2 ); + BOOST_TEST( size( arr( 1 <= multi::ALL , 2) ) == 3 ); + BOOST_TEST( size( arr( 1 <= multi::ALL < 3 , 2) ) == 2 ); // NOLINT(bugprone-chained-comparison) + + BOOST_TEST( size( arr( multi::_ , 2) ) == 4 ); + BOOST_TEST( size( arr( multi::_ < 2 , 2) ) == 2 ); + BOOST_TEST( size( arr( 1 <= multi::_ , 2) ) == 3 ); + BOOST_TEST( size( arr( 1 <= multi::_ < 3 , 2) ) == 2 ); // NOLINT(bugprone-chained-comparison) + + BOOST_TEST( size( arr( _ , 2) ) == 4 ); + BOOST_TEST( size( arr( _ < 2 , 2) ) == 2 ); + BOOST_TEST( size( arr( 1 <= _ , 2) ) == 3 ); + BOOST_TEST( size( arr( 1 <= _ < 3 , 2) ) == 2 ); // NOLINT(bugprone-chained-comparison) } BOOST_AUTO_TEST_CASE(multi_array_range_section_part2) { @@ -83,24 +63,24 @@ BOOST_AUTO_TEST_CASE(multi_array_range_section_part2) { {300, 310, 320}, }; - BOOST_REQUIRE( size( arr(arr.extension(), 2) ) == size(arr) ); + BOOST_TEST( size( arr(arr.extension(), 2) ) == size(arr) ); - auto&& col2( arr(arr.extension(), 2) ); // select column #2 + auto&& col2(arr(arr.extension(), 2)); // select column #2 // same as arr(extesion(arr), 2) // same as arr(arr.extension(0), 2); // same as rotated(arr)[2]; -// BOOST_REQUIRE( col2.size(0) == size(arr) ); - - BOOST_REQUIRE( dimensionality(col2) == 1 ); - BOOST_REQUIRE( size(col2) == size(arr) ); - BOOST_REQUIRE( col2.size() == size(arr) ); - BOOST_REQUIRE( col2.stride() == 3 ); - BOOST_REQUIRE( col2[0] == 20 ); - BOOST_REQUIRE( col2[1] == 120 ); - BOOST_REQUIRE(( col2 == multi::array{20, 120, 220, 320} )); - BOOST_REQUIRE(( col2 == multi::array(rotated(arr)[2]) )); - BOOST_REQUIRE(( col2 == rotated(arr)[2] )); - BOOST_REQUIRE(( col2 == arr(arr.extension(), 2) )); + // BOOST_TEST( col2.size(0) == size(arr) ); + + BOOST_TEST( dimensionality(col2) == 1 ); + BOOST_TEST( size(col2) == size(arr) ); + BOOST_TEST( col2.size() == size(arr) ); + BOOST_TEST( col2.stride() == 3 ); + BOOST_TEST( col2[0] == 20 ); + BOOST_TEST( col2[1] == 120 ); + BOOST_TEST(( col2 == multi::array{20, 120, 220, 320} )); + BOOST_TEST(( col2 == multi::array(arr.rotated()[2]) )); + BOOST_TEST(( col2 == arr.rotated()[2] )); + BOOST_TEST(( col2 == arr(arr.extension(), 2) )); } BOOST_AUTO_TEST_CASE(multi_array_range_section_syntax) { @@ -112,35 +92,36 @@ BOOST_AUTO_TEST_CASE(multi_array_range_section_syntax) { }; using multi::_; - BOOST_REQUIRE( size( arr( _ , 2) ) == size(arr) ); - BOOST_REQUIRE( size( arr( *_ , 2) ) == size(arr) ); + BOOST_TEST( size( arr( _ , 2) ) == size(arr) ); + BOOST_TEST( size( arr( *_ , 2) ) == size(arr) ); - BOOST_REQUIRE( size( arr( (_) , 2) ) == size(arr) ); + BOOST_TEST( size( arr( (_) , 2) ) == size(arr) ); using multi::U; - BOOST_REQUIRE( size( arr( U , 2) ) == size(arr) ); - BOOST_REQUIRE( size( arr( U , 2) ) == size(arr) ); + BOOST_TEST( size( arr( U , 2) ) == size(arr) ); + BOOST_TEST( size( arr( U , 2) ) == size(arr) ); - BOOST_REQUIRE( size( arr( U , 2) ) == size(arr) ); + BOOST_TEST( size( arr( U , 2) ) == size(arr) ); using multi::V; - BOOST_REQUIRE( size( arr( V , 2) ) == size(arr) ); - BOOST_REQUIRE( size( arr( V , 2) ) == size(arr) ); + BOOST_TEST( size( arr( V , 2) ) == size(arr) ); + BOOST_TEST( size( arr( V , 2) ) == size(arr) ); - BOOST_REQUIRE( size( arr( V , 2) ) == size(arr) ); + BOOST_TEST( size( arr( V , 2) ) == size(arr) ); - BOOST_REQUIRE( size( arr( _ < 2 , 2) ) == 2 ); - BOOST_REQUIRE( size( arr( *_ < 2 , 2) ) == 2 ); - BOOST_REQUIRE( size( arr( U < 2 , 2) ) == 2 ); + BOOST_TEST( size( arr( _ < 2 , 2) ) == 2 ); + BOOST_TEST( size( arr( *_ < 2 , 2) ) == 2 ); + BOOST_TEST( size( arr( U < 2 , 2) ) == 2 ); - BOOST_REQUIRE( size( arr( 1 <= _ , 2) ) == 3 ); - BOOST_REQUIRE( size( arr( 1 <= *_ , 2) ) == 3 ); - BOOST_REQUIRE( size( arr( 1 <= U , 2) ) == 3 ); + BOOST_TEST( size( arr( 1 <= _ , 2) ) == 3 ); + BOOST_TEST( size( arr( 1 <= *_ , 2) ) == 3 ); + BOOST_TEST( size( arr( 1 <= U , 2) ) == 3 ); - BOOST_REQUIRE( size( arr( 1 <= _ < 3 , 2) ) == 2 ); // NOLINT(bugprone-chained-comparison) - BOOST_REQUIRE( size( arr( 1 <= *_ < 3 , 2) ) == 2 ); // NOLINT(bugprone-chained-comparison) - BOOST_REQUIRE( size( arr( 1 <= U < 3 , 2) ) == 2 ); // NOLINT(bugprone-chained-comparison) + BOOST_TEST( size( arr( 1 <= _ < 3 , 2) ) == 2 ); // NOLINT(bugprone-chained-comparison) + BOOST_TEST( size( arr( 1 <= *_ < 3 , 2) ) == 2 ); // NOLINT(bugprone-chained-comparison) + BOOST_TEST( size( arr( 1 <= U < 3 , 2) ) == 2 ); // NOLINT(bugprone-chained-comparison) - BOOST_REQUIRE( size( arr( *_ < 2 , 2) ) == 2 ); - BOOST_REQUIRE( size( arr( U < 2 , 2) ) == 2 ); + BOOST_TEST( size( arr( *_ < 2 , 2) ) == 2 ); + BOOST_TEST( size( arr( U < 2 , 2) ) == 2 ); } +return boost::report_errors();} diff --git a/external_codes/boost_multi/multi/test/sliced.cpp b/external_codes/boost_multi/multi/test/sliced.cpp index 43da678541..9d9bc67cc8 100644 --- a/external_codes/boost_multi/multi/test/sliced.cpp +++ b/external_codes/boost_multi/multi/test/sliced.cpp @@ -1,4 +1,4 @@ -// Copyright 2021-2023 Alfredo A. Correa +// Copyright 2021-2024 Alfredo A. Correa // Copyright 2024 Matt Borland // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt @@ -7,73 +7,48 @@ #include // std::iota -// Suppress warnings from boost.test -#if defined(__clang__) -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wold-style-cast" -# pragma clang diagnostic ignored "-Wundef" -# pragma clang diagnostic ignored "-Wconversion" -# pragma clang diagnostic ignored "-Wsign-conversion" -// # pragma clang diagnostic ignored "-Wfloat-equal" -#elif defined(__GNUC__) -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wold-style-cast" -# pragma GCC diagnostic ignored "-Wundef" -# pragma GCC diagnostic ignored "-Wconversion" -# pragma GCC diagnostic ignored "-Wsign-conversion" -// # pragma GCC diagnostic ignored "-Wfloat-equal" -#endif - -#ifndef BOOST_TEST_MODULE -# define BOOST_TEST_MAIN -#endif - -#include - -#if defined(__clang__) -# pragma clang diagnostic pop -#elif defined(__GNUC__) -# pragma GCC diagnostic pop -#endif - namespace multi = boost::multi; +#include +#define BOOST_AUTO_TEST_CASE(CasenamE) /**/ + +auto main() -> int { // NOLINT(readability-function-cognitive-complexity,bugprone-exception-escape) BOOST_AUTO_TEST_CASE(multi_array_sliced_empty) { multi::array const arr({0, 0}, 99.0); - BOOST_REQUIRE( arr.sliced(0, 0).is_empty() ); - // BOOST_REQUIRE( arr.sliced(1, 1).is_empty() ); // this results in offsetting nullptr + BOOST_TEST( arr.sliced(0, 0).is_empty() ); + // BOOST_TEST( arr.sliced(1, 1).is_empty() ); // this results in offsetting nullptr } BOOST_AUTO_TEST_CASE(multi_array_sliced) { multi::array arr({10, 20, 30, 40}, 99); std::iota(arr.elements().begin(), arr.elements().end(), 0); - static_assert( decltype( arr.sliced(0, 5) )::rank::value == 4); - static_assert( decltype( arr.sliced(0, 5) )::rank{} == 4); - static_assert( decltype( arr.sliced(0, 5) )::rank_v == 4); + static_assert(decltype(arr.sliced(0, 5))::rank::value == 4); + static_assert(decltype(arr.sliced(0, 5))::rank{} == 4); + static_assert(decltype(arr.sliced(0, 5))::rank_v == 4); - BOOST_REQUIRE( arr.sliced( 0, 5)[1][2][3][4] == arr[1][2][3][4] ); - BOOST_REQUIRE( &arr.sliced( 0, 5)[1][2][3][4] == &arr[1][2][3][4] ); + BOOST_TEST( arr.sliced( 0, 5)[1][2][3][4] == arr[1][2][3][4] ); + BOOST_TEST( &arr.sliced( 0, 5)[1][2][3][4] == &arr[1][2][3][4] ); - BOOST_REQUIRE( arr.sliced( 0, 5)[1] == arr[1] ); - BOOST_REQUIRE( &arr.sliced( 0, 5)[1] == &arr[1] ); + BOOST_TEST( arr.sliced( 0, 5)[1] == arr[1] ); + BOOST_TEST( &arr.sliced( 0, 5)[1] == &arr[1] ); - BOOST_REQUIRE( arr.sliced( 0, 0).empty() ); - BOOST_REQUIRE( arr.sliced( 1, 1).empty() ); - BOOST_REQUIRE( arr.sliced( 0, 10).size() == 10 ); + BOOST_TEST( arr.sliced( 0, 0).empty() ); + BOOST_TEST( arr.sliced( 1, 1).empty() ); + BOOST_TEST( arr.sliced( 0, 10).size() == 10 ); - BOOST_REQUIRE( arr[1].sliced(0, 5)[2][3][4] == arr[1][2][3][4] ); - BOOST_REQUIRE( &arr[1].sliced(0, 5)[2][3][4] == &arr[1][2][3][4] ); + BOOST_TEST( arr[1].sliced(0, 5)[2][3][4] == arr[1][2][3][4] ); + BOOST_TEST( &arr[1].sliced(0, 5)[2][3][4] == &arr[1][2][3][4] ); - BOOST_REQUIRE( arr[1].sliced(0, 5)[2] == arr[1][2] ); - BOOST_REQUIRE( &arr[1].sliced(0, 5)[2] == &arr[1][2] ); + BOOST_TEST( arr[1].sliced(0, 5)[2] == arr[1][2] ); + BOOST_TEST( &arr[1].sliced(0, 5)[2] == &arr[1][2] ); - BOOST_REQUIRE( arr[1].sliced(0, 0).is_empty() ); - BOOST_REQUIRE( arr[1].sliced(1, 1).is_empty() ); - BOOST_REQUIRE( arr[1].sliced(0, 20).size() == 20 ); + BOOST_TEST( arr[1].sliced(0, 0).is_empty() ); + BOOST_TEST( arr[1].sliced(1, 1).is_empty() ); + BOOST_TEST( arr[1].sliced(0, 20).size() == 20 ); - BOOST_REQUIRE( (arr.rotated()).sliced(0, 5)[1][2][3][4] == (arr.rotated())[1][2][3][4] ); - BOOST_REQUIRE( &(arr.rotated()).sliced(0, 5)[1][2][3][4] == &(arr.rotated())[1][2][3][4] ); + BOOST_TEST( (arr.rotated()).sliced(0, 5)[1][2][3][4] == (arr.rotated())[1][2][3][4] ); + BOOST_TEST( &(arr.rotated()).sliced(0, 5)[1][2][3][4] == &(arr.rotated())[1][2][3][4] ); } BOOST_AUTO_TEST_CASE(multi_array_stride) { @@ -83,7 +58,7 @@ BOOST_AUTO_TEST_CASE(multi_array_stride) { { 90, 100, 110, 120}, {130, 140, 150, 160}, }; - BOOST_REQUIRE(( + BOOST_TEST(( arr.strided(2) == multi::array{ { 10, 20, 30, 40}, { 90, 100, 110, 120}, @@ -98,7 +73,7 @@ BOOST_AUTO_TEST_CASE(multi_array_take) { { 90, 100, 110, 120}, {130, 140, 150, 160}, }; - BOOST_REQUIRE(( + BOOST_TEST(( arr.taked(2) == multi::array{ { 10, 20, 30, 40}, { 50, 60, 70, 80}, @@ -113,10 +88,11 @@ BOOST_AUTO_TEST_CASE(drop) { { 90, 100, 110, 120}, {130, 140, 150, 160}, }; - BOOST_REQUIRE(( + BOOST_TEST(( arr.dropped(2) == multi::array{ { 90, 100, 110, 120}, {130, 140, 150, 160}, } )); } +return boost::report_errors();} diff --git a/external_codes/boost_multi/multi/test/sort.cpp b/external_codes/boost_multi/multi/test/sort.cpp index f5df9537ed..c7f309cb6e 100644 --- a/external_codes/boost_multi/multi/test/sort.cpp +++ b/external_codes/boost_multi/multi/test/sort.cpp @@ -3,112 +3,121 @@ // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt -#include - -#include // for std::stable_sort -#include -#include - -// Suppress warnings from boost.test -#if defined(__clang__) -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wold-style-cast" -# pragma clang diagnostic ignored "-Wundef" -# pragma clang diagnostic ignored "-Wconversion" -# pragma clang diagnostic ignored "-Wsign-conversion" -# pragma clang diagnostic ignored "-Wfloat-equal" -#elif defined(__GNUC__) -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wold-style-cast" -# pragma GCC diagnostic ignored "-Wundef" -# pragma GCC diagnostic ignored "-Wconversion" -# pragma GCC diagnostic ignored "-Wsign-conversion" -# pragma GCC diagnostic ignored "-Wfloat-equal" -#endif - -#ifndef BOOST_TEST_MODULE -# define BOOST_TEST_MAIN +#include // for apply, operator!=, operator== + +#include // for is_sorted, stable_sort +#include // for array +#include // for abs // IWYU pragma: keep +// IWYU pragma: no_include // for abs +// #include // for __cpp_lib_ranges // IWYU pragma: keep +#include // for begin, end +#include // for accumulate +#include // for vector +// IWYU pragma: no_include // for __cpp_lib_ranges +#if defined(__cpp_lib_ranges) + #include // IWYU pragma: keep #endif -#include - namespace multi = boost::multi; -BOOST_AUTO_TEST_CASE(array_1D_partial_order_syntax) { - multi::array const tt = {1, 1, 1}; - multi::array const uu = {2, 2, 2}; - - BOOST_REQUIRE( tt < uu ); - BOOST_REQUIRE( ! (tt > uu) ); - BOOST_REQUIRE( tt <= uu ); - BOOST_REQUIRE( ! (tt >= uu) ); - BOOST_REQUIRE( ! (tt == uu) ); - BOOST_REQUIRE( (tt != uu) ); - BOOST_REQUIRE( ! (uu < tt) ); - BOOST_REQUIRE( (uu > tt) ); - BOOST_REQUIRE( ! (uu <= tt) ); - BOOST_REQUIRE( (uu >= tt) ); -} +#include +#define BOOST_AUTO_TEST_CASE(CasenamE) /**/ + +auto main() -> int { // NOLINT(readability-function-cognitive-complexity,bugprone-exception-escape) + BOOST_AUTO_TEST_CASE(array_1D_partial_order_syntax) { + multi::array const tt = {1, 1, 1}; + multi::array const uu = {2, 2, 2}; + + BOOST_TEST( tt < uu ); + BOOST_TEST( !(tt > uu) ); + BOOST_TEST( tt <= uu ); + BOOST_TEST( !(tt >= uu) ); + BOOST_TEST( !(tt == uu) ); + BOOST_TEST( (tt != uu) ); + BOOST_TEST( !(uu < tt) ); + BOOST_TEST( (uu > tt) ); + BOOST_TEST( !(uu <= tt) ); + BOOST_TEST( (uu >= tt) ); + } #if defined(__cpp_lib_ranges) -BOOST_AUTO_TEST_CASE(sort_2D) { - multi::array A = { - {3, 3, 3}, - {2, 2, 2}, - {1, 1, 1}, - }; - BOOST_REQUIRE(! std::ranges::is_sorted(A)); + BOOST_AUTO_TEST_CASE(sort_2D) { + multi::array A2D = { + {3, 3, 3}, + {2, 2, 2}, + {1, 1, 1}, + }; + BOOST_TEST( !std::ranges::is_sorted(A2D) ); // NOLINT(fuchsia-default-arguments-calls) - std::ranges::sort(A); + using it = boost::multi::array_iterator; - BOOST_REQUIRE( std::ranges::is_sorted(A)); + static_assert(std::forward_iterator); - static_assert(std::permutable>); -} + using In = it; + using Out = it; -BOOST_AUTO_TEST_CASE(sort_strings) { - auto A = multi::array{ - {'S', 'e', 'a', 'n', ' ', ' '}, - {'A', 'l', 'e', 'x', ' ', ' '}, - {'B', 'j', 'a', 'r', 'n', 'e'}, - }; - BOOST_REQUIRE(! std::ranges::is_sorted(A)); + static_assert(std::indirectly_readable); - std::ranges::sort(A); + static_assert(std::indirectly_writable>); + static_assert(std::indirectly_writable>); + static_assert(std::indirectly_movable); + static_assert(std::indirectly_writable>); + static_assert(std::movable>); + static_assert(std::constructible_from, std::iter_rvalue_reference_t>); + static_assert(std::assignable_from&, std::iter_rvalue_reference_t>); - BOOST_REQUIRE( std::ranges::is_sorted(A)); + static_assert(std::indirectly_movable_storable); + static_assert(std::indirectly_swappable); + static_assert(std::permutable); - BOOST_REQUIRE(( - A == multi::array{ - {'A', 'l', 'e', 'x', ' ', ' '}, - {'B', 'j', 'a', 'r', 'n', 'e' }, - {'S', 'e', 'a', 'n', ' ', ' '}, - } - )); + // std::sort(A.begin(), A.end()); + std::ranges::sort(A2D); // NOLINT(fuchsia-default-arguments-calls) - std::ranges::sort(~A); - BOOST_REQUIRE( std::ranges::is_sorted(~A)); + BOOST_TEST( std::ranges::is_sorted(A2D) ); // NOLINT(fuchsia-default-arguments-calls) + } - static_assert(std::permutable>); -} + BOOST_AUTO_TEST_CASE(sort_strings) { + auto A2D = multi::array{ + {'S', 'e', 'a', 'n', ' ', ' '}, + {'A', 'l', 'e', 'x', ' ', ' '}, + {'B', 'j', 'a', 'r', 'n', 'e'}, + }; + BOOST_TEST( !std::ranges::is_sorted(A2D) ); // NOLINT(fuchsia-default-arguments-calls) + + std::ranges::sort(A2D); // NOLINT(fuchsia-default-arguments-calls) + + BOOST_TEST( std::ranges::is_sorted(A2D)); // NOLINT(fuchsia-default-arguments-calls) + BOOST_TEST(( + A2D == multi::array{ + {'A', 'l', 'e', 'x', ' ', ' '}, + {'B', 'j', 'a', 'r', 'n', 'e' }, + {'S', 'e', 'a', 'n', ' ', ' '}, + } + )); + + std::ranges::sort(~A2D); // NOLINT(fuchsia-default-arguments-calls) + BOOST_TEST(std::ranges::is_sorted(~A2D)); // NOLINT(fuchsia-default-arguments-calls) + + static_assert(std::permutable>); + } #endif -BOOST_AUTO_TEST_CASE(multi_array_stable_sort) { - std::vector vec = {1.0, 2.0, 3.0}; // NOLINT(fuchsia-default-arguments-calls) - BOOST_REQUIRE( std::is_sorted(begin(vec), end(vec)) ); + BOOST_AUTO_TEST_CASE(multi_array_stable_sort) { + std::vector vec = {1.0, 2.0, 3.0}; // NOLINT(fuchsia-default-arguments-calls) + BOOST_TEST( std::is_sorted(begin(vec), end(vec)) ); // NOLINT(fuchsia-default-arguments-calls) - multi::array d2D = { - {150.0, 16.0, 17.0, 18.0, 19.0}, - { 30.0, 1.0, 2.0, 3.0, 4.0}, - {100.0, 11.0, 12.0, 13.0, 14.0}, - { 50.0, 6.0, 7.0, 8.0, 9.0}, - }; - BOOST_REQUIRE( ! std::is_sorted(begin(d2D), end(d2D) ) ); + multi::array d2D = { + {150.0, 16.0, 17.0, 18.0, 19.0}, + { 30.0, 1.0, 2.0, 3.0, 4.0}, + {100.0, 11.0, 12.0, 13.0, 14.0}, + { 50.0, 6.0, 7.0, 8.0, 9.0}, + }; + BOOST_TEST( !std::is_sorted(begin(d2D), end(d2D) ) ); // NOLINT(fuchsia-default-arguments-calls) - std::stable_sort(begin(d2D), end(d2D)); - BOOST_REQUIRE( std::is_sorted( begin(d2D), end(d2D) ) ); + std::stable_sort(begin(d2D), end(d2D)); + BOOST_TEST( std::is_sorted( begin(d2D), end(d2D) ) ); // NOLINT(fuchsia-default-arguments-calls) - BOOST_REQUIRE(( + BOOST_TEST(( d2D == decltype(d2D){ { 30.0, 1.0, 2.0, 3.0, 4.0}, { 50.0, 6.0, 7.0, 8.0, 9.0}, @@ -117,13 +126,13 @@ BOOST_AUTO_TEST_CASE(multi_array_stable_sort) { } )); - BOOST_REQUIRE( ! std::is_sorted( begin(d2D.rotated()), end(d2D.rotated()) ) ); + BOOST_TEST( !std::is_sorted( begin(d2D.rotated()), end(d2D.rotated()) ) ); - std::stable_sort(begin(d2D.rotated()), end(d2D.rotated())); - BOOST_REQUIRE( std::is_sorted( begin(d2D.rotated()), end(d2D.rotated()) ) ); - BOOST_REQUIRE( std::is_sorted( begin(d2D ), end(d2D ) ) ); + std::stable_sort(begin(d2D.rotated()), end(d2D.rotated())); + BOOST_TEST( std::is_sorted( begin(d2D.rotated()), end(d2D.rotated()) ) ); + BOOST_TEST( std::is_sorted( begin(d2D ), end(d2D ) ) ); - BOOST_REQUIRE(( + BOOST_TEST(( d2D == decltype(d2D){ { 1.0, 2.0, 3.0, 4.0, 30.0}, { 6.0, 7.0, 8.0, 9.0, 50.0}, @@ -131,94 +140,125 @@ BOOST_AUTO_TEST_CASE(multi_array_stable_sort) { {16.0, 17.0, 18.0, 19.0, 150.0}, } )); -} + } -BOOST_AUTO_TEST_CASE(multi_array_ref_stable_sort) { - std::vector vec = {1.0, 2.0, 3.0}; // NOLINT(fuchsia-default-arguments-calls) - BOOST_REQUIRE( std::is_sorted(begin(vec), end(vec)) ); + BOOST_AUTO_TEST_CASE(multi_array_ref_stable_sort) { + std::vector vec = {1.0, 2.0, 3.0}; // NOLINT(fuchsia-default-arguments-calls) + BOOST_TEST( std::is_sorted(begin(vec), end(vec)) ); - // clang-format off + // clang-format off std::array, 4> d2D {{ {{150.0, 16.0, 17.0, 18.0, 19.0}}, {{ 30.0, 1.0, 2.0, 3.0, 4.0}}, {{100.0, 11.0, 12.0, 13.0, 14.0}}, {{ 50.0, 6.0, 7.0, 8.0, 9.0}} }}; - // clang-format on + // clang-format on - auto&& d2D_ref = *multi::array_ptr(&d2D[0][0], {4, 5}); // NOLINT(readability-container-data-pointer) test access + auto&& d2D_ref = *multi::array_ptr(&d2D[0][0], {4, 5}); // NOLINT(readability-container-data-pointer) test access - BOOST_REQUIRE( ! std::is_sorted(begin(d2D_ref), end(d2D_ref) ) ); - std::stable_sort(begin(d2D_ref), end(d2D_ref)); - BOOST_REQUIRE( std::is_sorted( begin(d2D_ref), end(d2D_ref) ) ); + BOOST_TEST( !std::is_sorted(begin(d2D_ref), end(d2D_ref) ) ); + std::stable_sort(begin(d2D_ref), end(d2D_ref)); + BOOST_TEST( std::is_sorted( begin(d2D_ref), end(d2D_ref) ) ); - BOOST_REQUIRE( ! std::is_sorted( begin(d2D_ref.rotated()), end(d2D_ref.rotated()) ) ); - std::stable_sort(begin(d2D_ref.rotated()), end(d2D_ref.rotated())); - BOOST_REQUIRE( std::is_sorted( begin(d2D_ref.rotated()), end(d2D_ref.rotated()) ) ); -} + BOOST_TEST( !std::is_sorted( begin(d2D_ref.rotated()), end(d2D_ref.rotated()) ) ); + std::stable_sort(begin(d2D_ref.rotated()), end(d2D_ref.rotated())); + BOOST_TEST( std::is_sorted( begin(d2D_ref.rotated()), end(d2D_ref.rotated()) ) ); + } -BOOST_AUTO_TEST_CASE(lexicographical_compare) { - multi::array const name1 = {'a', 'b', 'c'}; - multi::array const name2 = {'a', 'c', 'c'}; - BOOST_REQUIRE(name1 != name2 ); - BOOST_REQUIRE(name1 < name2); - BOOST_REQUIRE(name1 <= name2); - BOOST_REQUIRE(!(name1 > name2)); - BOOST_REQUIRE(!(name1 > name2)); -} + BOOST_AUTO_TEST_CASE(lexicographical_compare) { + multi::array const name1 = {'a', 'b', 'c'}; + multi::array const name2 = {'a', 'c', 'c'}; -BOOST_AUTO_TEST_CASE(lexicographical_compare_offset) { - multi::array const name1 = {'a', 'b', 'c'}; - multi::array name2({{1, 4}}, '\0'); + BOOST_TEST( name1 != name2 ); + BOOST_TEST( name1 < name2); + BOOST_TEST( name1 <= name2); + BOOST_TEST(!(name1 > name2)); + BOOST_TEST(!(name1 > name2)); + } - BOOST_REQUIRE( name2.size() == 3 ); - BOOST_REQUIRE(( name2.extension() == multi::extension_t{1, 4} )); - BOOST_REQUIRE(( name2.extension() == multi::extension_t{multi::index{1}, multi::index{4}} )); + BOOST_AUTO_TEST_CASE(lexicographical_compare_offset) { + multi::array const name1 = {'a', 'b', 'c'}; + // clang-format off + multi::array name2({{ 1, 4 }}, '\0'); + // clang-format on - // BOOST_REQUIRE(( name2.extension() == multi::extension_t{1L, 4L} )); + BOOST_TEST( name2.size() == 3 ); + BOOST_TEST(( name2.extension() == multi::extension_t{1, 4} )); + BOOST_TEST(( name2.extension() == multi::extension_t{multi::index{1}, multi::index{4}} )); - BOOST_REQUIRE(( name2.extension() == multi::extension_t<>{1, 4} )); - // BOOST_REQUIRE(( name2.extension() == multi::extension_t{1 , 4 } )); TODO(correaa) solve ambiguity + // BOOST_TEST(( name2.extension() == multi::extension_t{1L, 4L} )); - name2[1] = 'a'; - name2[2] = 'b'; - name2[3] = 'c'; + BOOST_TEST(( name2.extension() == multi::extension_t<>{1, 4} )); + // BOOST_TEST(( name2.extension() == multi::extension_t{1 , 4 } )); TODO(correaa) solve ambiguity - BOOST_REQUIRE( name2 != name1 ); - BOOST_REQUIRE(!(name2 == name1)); + name2[1] = 'a'; + name2[2] = 'b'; + name2[3] = 'c'; - BOOST_REQUIRE( name2 < name1 ); - BOOST_REQUIRE( name2 <= name1 ); + BOOST_TEST( name2 != name1 ); + BOOST_TEST(!(name2 == name1)); - BOOST_REQUIRE(!(name2 > name1)); - BOOST_REQUIRE(!(name2 >= name1)); + BOOST_TEST( name2 < name1 ); + BOOST_TEST( name2 <= name1 ); - // BOOST_REQUIRE(!(name1 > name2)); - // BOOST_REQUIRE(!(name1 > name2)); -} + BOOST_TEST(!(name2 > name1)); + BOOST_TEST(!(name2 >= name1)); + + // BOOST_TEST(!(name1 > name2)); + // BOOST_TEST(!(name1 > name2)); + } -BOOST_AUTO_TEST_CASE(lexicographical_compare_offset_2d) { - multi::array const name1 = {{'a', 'b'}, {'b', 'c'}, {'c', 'd'}}; - multi::array name2({{1, 4}, {0, 2}}, '\0'); + BOOST_AUTO_TEST_CASE(lexicographical_compare_offset_2d) { + multi::array const name1 = { + {'a', 'b'}, + {'b', 'c'}, + {'c', 'd'} + }; - BOOST_REQUIRE( name2.size() == 3 ); - BOOST_REQUIRE(( name2.extension() == multi::extension_t{1, 4} )); - BOOST_REQUIRE(( name2.extension() == multi::extension_t<>{1, 4} )); - // BOOST_REQUIRE(( name2.extension() == multi::extension_t{1 , 4 } )); TODO(correaa) solve ambiguity + // clang-format off + multi::array name2({{1, 4}, {0, 2}}, '\0'); + // clang-format on - name2[1][0] = 'a'; name2[1][1] = 'a'; - name2[2][0] = 'b'; name2[2][1] = 'a'; - name2[3][0] = 'c'; name2[3][1] = 'a'; + BOOST_TEST( name2.size() == 3 ); + BOOST_TEST(( name2.extension() == multi::extension_t{1, 4} )); + BOOST_TEST(( name2.extension() == multi::extension_t<>{1, 4} )); + // BOOST_TEST(( name2.extension() == multi::extension_t{1 , 4 } )); TODO(correaa) solve ambiguity - BOOST_REQUIRE( name2 != name1 ); - BOOST_REQUIRE(!(name2 == name1)); + name2[1][0] = 'a'; + name2[1][1] = 'a'; + name2[2][0] = 'b'; + name2[2][1] = 'a'; + name2[3][0] = 'c'; + name2[3][1] = 'a'; - BOOST_REQUIRE( name2 < name1 ); - BOOST_REQUIRE( name2 <= name1 ); + BOOST_TEST( name2 != name1 ); + BOOST_TEST(!(name2 == name1)); - // BOOST_REQUIRE(!(name2 > name1)); - // BOOST_REQUIRE(!(name2 >= name1)); + BOOST_TEST( name2 < name1 ); + BOOST_TEST( name2 <= name1 ); + + // BOOST_TEST(!(name2 > name1)); + // BOOST_TEST(!(name2 >= name1)); + + BOOST_TEST( name1 > name2 ); + BOOST_TEST(!(name1 < name2)); + } + + BOOST_AUTO_TEST_CASE(accumulate_1d) { + { + std::vector vec = {1.0, 2.0, 3.0}; // NOLINT(fuchsia-default-arguments-calls) + + auto const sum = std::accumulate(vec.begin(), vec.end(), double{}); + BOOST_TEST(std::abs(sum - 6.0) < 1e-10); + } + { + multi::array arr = {1.0, 2.0, 3.0}; + + auto const sum = std::accumulate(arr.begin(), arr.end(), double{}); + BOOST_TEST(std::abs(sum - 6.0) < 1e-10); + } + } - BOOST_REQUIRE( name1 > name2 ); - BOOST_REQUIRE(!(name1 < name2)); + return boost::report_errors(); } diff --git a/external_codes/boost_multi/multi/test/static_array_cast.cpp b/external_codes/boost_multi/multi/test/static_array_cast.cpp index 254d7a09b2..32bbe964fd 100644 --- a/external_codes/boost_multi/multi/test/static_array_cast.cpp +++ b/external_codes/boost_multi/multi/test/static_array_cast.cpp @@ -5,38 +5,20 @@ #include #include // TODO(correaa) remove in c++20 -#include - -// Suppress warnings from boost.test -#if defined(__clang__) -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wold-style-cast" -# pragma clang diagnostic ignored "-Wundef" -# pragma clang diagnostic ignored "-Wconversion" -# pragma clang diagnostic ignored "-Wsign-conversion" -# pragma clang diagnostic ignored "-Wfloat-equal" -#elif defined(__GNUC__) -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wold-style-cast" -# pragma GCC diagnostic ignored "-Wundef" -# pragma GCC diagnostic ignored "-Wconversion" -# pragma GCC diagnostic ignored "-Wsign-conversion" -# pragma GCC diagnostic ignored "-Wfloat-equal" -#endif - -#ifndef BOOST_TEST_MODULE -# define BOOST_TEST_MAIN -#endif - -#include +#include // for equal +#include // for assert +#include // for negate // IWYU pragma: keep +#include // for begin, end +#include // for pointer_t... +#include // for iota +#include // for decay_t +#include // for move, dec... namespace multi = boost::multi; -template class involuter; - template class involuted { - Ref r_; // NOLINT(cppcoreguidelines-avoid-const-or-ref-data-members) + Ref r_; // NOLINT(cppcoreguidelines-avoid-const-or-ref-data-members) BOOST_MULTI_NO_UNIQUE_ADDRESS Involution f_; // TODO(correaa) put nounique members first? public: @@ -52,7 +34,9 @@ class involuted { ~involuted() = default; - constexpr operator decay_type() const& noexcept { return f_(r_); } // NOLINT(google-explicit-constructor,hicpp-explicit-conversions) // NOSONAR(cpp:S1709) simulates a reference + // NOLINTNEXTLINE(google-explicit-constructor,hicpp-explicit-conversions) + constexpr operator decay_type() const& noexcept { return f_(r_); } // NOSONAR(cpp:S1709) simulates a reference + // NOLINTNEXTLINE(fuchsia-trailing-return,-warnings-as-errors): trailing return helps reading template constexpr auto operator=(DecayType&& other) & -> involuted& { r_ = f_(std::forward(other)); @@ -73,7 +57,7 @@ class involuted { template class involuter { - It it_; + It it_; BOOST_MULTI_NO_UNIQUE_ADDRESS F f_; template friend class involuter; @@ -90,7 +74,8 @@ class involuter { constexpr involuter(It it, F fun) : it_{std::move(it)}, f_{std::move(fun)} {} // NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions): this is needed to make involuter implicitly convertible to involuter - template constexpr involuter(involuter const& other) : it_{multi::detail::implicit_cast(other.it_)}, f_{other.f_} {} // NOSONAR(cpp:S1709) + template constexpr involuter(involuter const& other) // NOSONAR(cpp:S1709) + : it_{multi::detail::implicit_cast(other.it_)}, f_{other.f_} {} constexpr auto operator*() const { return reference{*it_, f_}; } constexpr auto operator->() const { return pointer{&*it_, f_}; } @@ -99,15 +84,37 @@ class involuter { constexpr auto operator!=(involuter const& other) const { return it_ != other.it_; } constexpr auto operator<(involuter const& other) const { return it_ < other.it_; } + #if defined(__clang__) + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wunknown-warning-option" + #pragma clang diagnostic ignored "-Wunsafe-buffer-usage" + #endif + constexpr auto operator+=(typename involuter::difference_type n) -> decltype(auto) { it_ += n; return *this; } + + #if defined(__clang__) + #pragma clang diagnostic pop + #endif + + #if defined(__clang__) + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wunknown-warning-option" + #pragma clang diagnostic ignored "-Wunsafe-buffer-usage" + #endif + constexpr auto operator+(typename involuter::difference_type n) const { return involuter{it_ + n, f_}; } constexpr auto operator-(typename involuter::difference_type n) const { return involuter{it_ - n, f_}; } - constexpr auto operator-(involuter const& other) const { return it_ - other.it_; } constexpr auto operator[](typename involuter::difference_type n) const { return reference{*(it_ + n), f_}; } + + #if defined(__clang__) + #pragma clang diagnostic pop + #endif + + constexpr auto operator-(involuter const& other) const { return it_ - other.it_; } }; #if defined(__cpp_deduction_guides) @@ -117,17 +124,21 @@ template involuted(T&&, F) -> involuted; template using negated = involuted>; template using negater = involuter>; +#include +#define BOOST_AUTO_TEST_CASE(CasenamE) /**/ + +auto main() -> int { // NOLINT(readability-function-cognitive-complexity,bugprone-exception-escape) BOOST_AUTO_TEST_CASE(multi_array_involution) { - double doub = 5; + int doub = 50; - auto&& cee = involuted>{doub}; - BOOST_REQUIRE( cee == -5.0 ); + auto&& cee = involuted>{doub}; + BOOST_TEST( cee == -50 ); - cee = 10.; - BOOST_REQUIRE( doub = -10.0 ); + cee = 100; + BOOST_TEST( doub == -100 ); - auto m5 = involuted>(5.0); - BOOST_REQUIRE( m5 == -5.0 ); + auto m5 = involuted>(50); + BOOST_TEST( m5 == -50 ); } BOOST_AUTO_TEST_CASE(static_array_cast) { @@ -135,66 +146,67 @@ BOOST_AUTO_TEST_CASE(static_array_cast) { auto&& ref = arr.static_array_cast(); - BOOST_REQUIRE( &ref[2] == &arr[2] ); - BOOST_REQUIRE( &arr[2] == &ref[2] ); + BOOST_TEST( &ref[2] == &arr[2] ); + BOOST_TEST( &arr[2] == &ref[2] ); - BOOST_REQUIRE( std::equal(begin(ref), end(ref), begin(arr), end(arr)) ); + BOOST_TEST( std::equal(begin(ref), end(ref), begin(arr), end(arr)) ); - BOOST_REQUIRE( ref == arr() ); - BOOST_REQUIRE( arr() == ref ); + BOOST_TEST( ref == arr() ); + BOOST_TEST( arr() == ref ); - BOOST_REQUIRE( ref == arr ); - BOOST_REQUIRE( arr == ref ); + BOOST_TEST( ref == arr ); + BOOST_TEST( arr == ref ); } BOOST_AUTO_TEST_CASE(static_array_cast_2) { - multi::array arr({2, 5}); - std::iota(arr.elements().begin(), arr.elements().end(), 0.0); + multi::array arr({2, 5}); + std::iota(arr.elements().begin(), arr.elements().end(), 0); - auto&& ref = arr.static_array_cast(); + auto&& ref = arr.static_array_cast(); - BOOST_REQUIRE( ref[1][1] == arr[1][1] ); - BOOST_REQUIRE( std::equal(begin(ref[1]), end(ref[1]), begin(arr[1]), end(arr[1])) ); - BOOST_REQUIRE( ref[1] == arr[1] ); + BOOST_TEST( ref[1][1] == arr[1][1] ); + BOOST_TEST( std::equal(begin(ref[1]), end(ref[1]), begin(arr[1]), end(arr[1])) ); + BOOST_TEST( ref[1] == arr[1] ); - BOOST_REQUIRE( std::equal(begin(ref), end(ref), begin(arr), end(arr)) ); + BOOST_TEST( std::equal(begin(ref), end(ref), begin(arr), end(arr)) ); - BOOST_REQUIRE( ref == arr ); - BOOST_REQUIRE( arr == ref ); + BOOST_TEST( ref == arr ); + BOOST_TEST( arr == ref ); } BOOST_AUTO_TEST_CASE(static_array_cast_3) { { - multi::static_array const arr = {+0.0, +1.0, +2.0, +3.0, +4.0}; - multi::static_array arr2 = {-0.0, -1.0, -2.0, -3.0, -4.0}; + multi::static_array const arr = {+00, +10, +20, +30, +40}; + multi::static_array arr2 = {-00, -10, -20, -30, -40}; - auto&& neg_arr = multi::static_array_cast>>(arr); + auto&& neg_arr = multi::static_array_cast>>(arr); - BOOST_REQUIRE( neg_arr[2] == arr2[2] ); - BOOST_REQUIRE( arr2[2] == neg_arr[2] ); - BOOST_REQUIRE( std::equal(begin(neg_arr), end(neg_arr), begin(arr2), end(arr2)) ); - BOOST_REQUIRE( neg_arr == arr2 ); - BOOST_REQUIRE( arr2 == neg_arr ); + BOOST_TEST( neg_arr[2] == arr2[2] ); + BOOST_TEST( arr2[2] == neg_arr[2] ); + BOOST_TEST( std::equal(begin(neg_arr), end(neg_arr), begin(arr2), end(arr2)) ); + BOOST_TEST( neg_arr == arr2 ); + BOOST_TEST( arr2 == neg_arr ); } { - multi::static_array arr({4, 5}, 0.0); - std::iota(elements(arr).begin(), elements(arr).end(), 0.0); + multi::static_array arr({4, 5}, 0); + std::iota(elements(arr).begin(), elements(arr).end(), 0); - multi::array arr2({4, 5}); + multi::array arr2({4, 5}); std::transform(begin(elements(arr)), end(elements(arr)), begin(elements(arr2)), std::negate<>{}); - auto&& neg_arr = arr.static_array_cast>(); + auto&& neg_arr = arr.static_array_cast>(); - BOOST_REQUIRE( neg_arr[1][1] == arr2[1][1] ); - BOOST_REQUIRE( arr2[1][1] == neg_arr[1][1] ); + BOOST_TEST( neg_arr[1][1] == arr2[1][1] ); + BOOST_TEST( arr2[1][1] == neg_arr[1][1] ); - BOOST_REQUIRE( std::equal(begin(arr2[1]), end(arr2[1]), begin(neg_arr[1]), end(neg_arr[1])) ); + BOOST_TEST( std::equal(begin(arr2[1]), end(arr2[1]), begin(neg_arr[1]), end(neg_arr[1])) ); - BOOST_REQUIRE( arr2[1] == neg_arr[1] ); - BOOST_REQUIRE( neg_arr[1] == arr2[1] ); + BOOST_TEST( arr2[1] == neg_arr[1] ); + BOOST_TEST( neg_arr[1] == arr2[1] ); - BOOST_REQUIRE( std::equal(begin(arr2), end(arr2), begin(neg_arr), end(neg_arr)) ); - BOOST_REQUIRE( neg_arr == arr2 ); - BOOST_REQUIRE( arr2 == neg_arr ); + BOOST_TEST( std::equal(begin(arr2), end(arr2), begin(neg_arr), end(neg_arr)) ); + BOOST_TEST( neg_arr == arr2 ); + BOOST_TEST( arr2 == neg_arr ); } } +return boost::report_errors();} diff --git a/external_codes/boost_multi/multi/test/std_vector_substitutability.cpp b/external_codes/boost_multi/multi/test/std_vector_substitutability.cpp index f14c88deff..b62ef8c653 100644 --- a/external_codes/boost_multi/multi/test/std_vector_substitutability.cpp +++ b/external_codes/boost_multi/multi/test/std_vector_substitutability.cpp @@ -3,43 +3,11 @@ // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt -#include - -#include - -// Suppress warnings from boost.test -#if defined(__clang__) -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wold-style-cast" -#pragma clang diagnostic ignored "-Wundef" -#pragma clang diagnostic ignored "-Wconversion" -#pragma clang diagnostic ignored "-Wsign-conversion" -#elif defined(__GNUC__) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wold-style-cast" -#pragma GCC diagnostic ignored "-Wundef" -#pragma GCC diagnostic ignored "-Wconversion" -#pragma GCC diagnostic ignored "-Wsign-conversion" -#endif - -#ifndef BOOST_TEST_MODULE -#define BOOST_TEST_MAIN -#endif - -#include - -#if defined(__clang__) -#pragma clang diagnostic pop -#elif defined(__GNUC__) -#pragma GCC diagnostic pop -#endif - -// workaround for libc++ and boost test -// namespace boost::unit_test::ut_detail { -// auto normalize_test_case_name(const_string name) -> std::string { -// return ( name[0] == '&' ? std::string(name.begin()+1, name.size()-1) : std::string(name.begin(), name.size() )); // NOLINT(fuchsia-default-arguments-calls) -// } -// } // end namespace boost::unit_test::ut_detail +#include // for array, layout_t, operator==, imp... + +#include // for equal +#include // for decay_t +#include // for vector namespace multi = boost::multi; @@ -55,12 +23,14 @@ void resize_copy_2(std::vector const& source, DynamicArray& darr) { template // e.g. std::vector or multi::array void resize_copy_3(std::vector const& source, DynamicArray& darr) { - darr = std::decay_t(source.begin(), source.end()); // testing std::vector vs multi:array NOLINT(fuchsia-default-arguments-calls,-warnings-as-errors) + // NOLINTNEXTLINE(fuchsia-default-arguments-calls,-warnings-as-errors) + darr = std::decay_t(source.begin(), source.end()); // testing std::vector vs multi:array } template // e.g. std::vector or multi::array void resize_copy_4(It first, It last, DynamicArray& darr) { - darr = DynamicArray(first, last); // or std::decay_t(source.begin(), source.end()) // testing std::vector vs multi:array NOLINT(fuchsia-default-arguments-calls,-warnings-as-errors) + // NOLINTNEXTLINE(fuchsia-default-arguments-calls,-warnings-as-errors) testing std::vector vs multi:array + darr = DynamicArray(first, last); // or std::decay_t(source.begin(), source.end()) } template // e.g. std::vector or multi::array @@ -70,24 +40,28 @@ void resize_copy_5(It first, It last, DynamicArray& darr) { // void resize_copy_6 ----> see below test_resize_copy_6 +#include +#define BOOST_AUTO_TEST_CASE(CasenamE) /**/ + +auto main() -> int { // NOLINT(readability-function-cognitive-complexity,bugprone-exception-escape) BOOST_AUTO_TEST_CASE(test_resize_copy_1) { std::vector const source = {0, 1, 2, 3}; // testing std::vector vs multi:array NOLINT(fuchsia-default-arguments-calls,-warnings-as-errors) std::vector dest_v = {99, 99}; // testing std::vector vs multi:array NOLINT(fuchsia-default-arguments-calls,-warnings-as-errors) multi::array dest_a = {88, 88}; - BOOST_REQUIRE( dest_v.size() == 2 ); - BOOST_REQUIRE( dest_a.size() == 2 ); + BOOST_TEST( dest_v.size() == 2 ); + BOOST_TEST( dest_a.size() == 2 ); resize_copy_1(source, dest_v); - BOOST_REQUIRE( dest_v.size() == 4 ); - BOOST_REQUIRE( dest_v[3] == 3 ); + BOOST_TEST( dest_v.size() == 4 ); + BOOST_TEST( dest_v[3] == 3 ); resize_copy_1(source, dest_a); - BOOST_REQUIRE( dest_v.size() == 4 ); - BOOST_REQUIRE( dest_v[3] == 3 ); + BOOST_TEST( dest_v.size() == 4 ); + BOOST_TEST( dest_v[3] == 3 ); } BOOST_AUTO_TEST_CASE(test_resize_copy_2) { @@ -96,18 +70,18 @@ BOOST_AUTO_TEST_CASE(test_resize_copy_2) { std::vector dest_v = {99, 99}; // testing std::vector vs multi:array NOLINT(fuchsia-default-arguments-calls,-warnings-as-errors) multi::array dest_a = {88, 88}; - BOOST_REQUIRE( dest_v.size() == 2 ); - BOOST_REQUIRE( dest_a.size() == 2 ); + BOOST_TEST( dest_v.size() == 2 ); + BOOST_TEST( dest_a.size() == 2 ); resize_copy_2(source, dest_v); - BOOST_REQUIRE( dest_v.size() == 4 ); - BOOST_REQUIRE( dest_v[3] == 3 ); + BOOST_TEST( dest_v.size() == 4 ); + BOOST_TEST( dest_v[3] == 3 ); resize_copy_2(source, dest_a); - BOOST_REQUIRE( dest_v.size() == 4 ); - BOOST_REQUIRE( dest_v[3] == 3 ); + BOOST_TEST( dest_v.size() == 4 ); + BOOST_TEST( dest_v[3] == 3 ); } BOOST_AUTO_TEST_CASE(test_resize_copy_3) { @@ -116,18 +90,18 @@ BOOST_AUTO_TEST_CASE(test_resize_copy_3) { std::vector dest_v = {990, 990}; // testing std::vector vs multi:array NOLINT(fuchsia-default-arguments-calls,-warnings-as-errors) multi::array dest_a = {880, 880}; - BOOST_REQUIRE( dest_v.size() == 2 ); - BOOST_REQUIRE( dest_a.size() == 2 ); + BOOST_TEST( dest_v.size() == 2 ); + BOOST_TEST( dest_a.size() == 2 ); resize_copy_3(source, dest_v); - BOOST_REQUIRE( dest_v.size() == 4 ); - BOOST_REQUIRE( dest_v[3] == 30 ); + BOOST_TEST( dest_v.size() == 4 ); + BOOST_TEST( dest_v[3] == 30 ); resize_copy_3(source, dest_a); - BOOST_REQUIRE( dest_v.size() == 4 ); - BOOST_REQUIRE( dest_v[3] == 30 ); + BOOST_TEST( dest_v.size() == 4 ); + BOOST_TEST( dest_v[3] == 30 ); } BOOST_AUTO_TEST_CASE(test_resize_copy_4) { @@ -136,18 +110,18 @@ BOOST_AUTO_TEST_CASE(test_resize_copy_4) { std::vector dest_v = {990, 990}; // testing std::vector vs multi:array NOLINT(fuchsia-default-arguments-calls,-warnings-as-errors) multi::array dest_a = {880, 880}; - BOOST_REQUIRE( dest_v.size() == 2 ); - BOOST_REQUIRE( dest_a.size() == 2 ); + BOOST_TEST( dest_v.size() == 2 ); + BOOST_TEST( dest_a.size() == 2 ); resize_copy_4(source.begin(), source.end(), dest_v); - BOOST_REQUIRE( dest_v.size() == 4 ); - BOOST_REQUIRE( dest_v[3] == 30 ); + BOOST_TEST( dest_v.size() == 4 ); + BOOST_TEST( dest_v[3] == 30 ); resize_copy_4(source.begin(), source.end(), dest_a); - BOOST_REQUIRE( dest_v.size() == 4 ); - BOOST_REQUIRE( dest_v[3] == 30 ); + BOOST_TEST( dest_v.size() == 4 ); + BOOST_TEST( dest_v[3] == 30 ); } BOOST_AUTO_TEST_CASE(test_resize_copy_5) { @@ -156,18 +130,18 @@ BOOST_AUTO_TEST_CASE(test_resize_copy_5) { std::vector dest_v = {990, 990}; // testing std::vector vs multi:array NOLINT(fuchsia-default-arguments-calls,-warnings-as-errors) multi::array dest_a = {880, 880}; - BOOST_REQUIRE( dest_v.size() == 2 ); - BOOST_REQUIRE( dest_a.size() == 2 ); + BOOST_TEST( dest_v.size() == 2 ); + BOOST_TEST( dest_a.size() == 2 ); resize_copy_5(source.begin(), source.end(), dest_v); - BOOST_REQUIRE( dest_v.size() == 4 ); - BOOST_REQUIRE( dest_v[3] == 30 ); + BOOST_TEST( dest_v.size() == 4 ); + BOOST_TEST( dest_v[3] == 30 ); resize_copy_5(source.begin(), source.end(), dest_a); - BOOST_REQUIRE( dest_v.size() == 4 ); - BOOST_REQUIRE( dest_v[3] == 30 ); + BOOST_TEST( dest_v.size() == 4 ); + BOOST_TEST( dest_v[3] == 30 ); } BOOST_AUTO_TEST_CASE(test_resize_copy_6) { @@ -176,22 +150,22 @@ BOOST_AUTO_TEST_CASE(test_resize_copy_6) { std::vector dest_v = {990, 990}; // testing std::vector vs multi:array NOLINT(fuchsia-default-arguments-calls,-warnings-as-errors) multi::array dest_a = {880, 880}; - BOOST_REQUIRE( dest_v.size() == 2 ); - BOOST_REQUIRE( dest_a.size() == 2 ); + BOOST_TEST( dest_v.size() == 2 ); + BOOST_TEST( dest_a.size() == 2 ); { // look same code as below dest_v = decltype(dest_v)(source); } - BOOST_REQUIRE( dest_v.size() == 4 ); - BOOST_REQUIRE( dest_v[3] == 30 ); + BOOST_TEST( dest_v.size() == 4 ); + BOOST_TEST( dest_v[3] == 30 ); { // look same code as above dest_a = decltype(dest_a)(source); } - BOOST_REQUIRE( dest_v.size() == 4 ); - BOOST_REQUIRE( dest_v[3] == 30 ); + BOOST_TEST( dest_v.size() == 4 ); + BOOST_TEST( dest_v[3] == 30 ); } BOOST_AUTO_TEST_CASE(assign_equality) { @@ -199,38 +173,38 @@ BOOST_AUTO_TEST_CASE(assign_equality) { multi::array const AA = {10, 20, 30}; std::vector const aa = {10, 20, 30}; // NOLINT(fuchsia-default-arguments-calls) - BOOST_REQUIRE( std::equal(AA.begin(), AA.end(), aa.begin() ) ); + BOOST_TEST( std::equal(AA.begin(), AA.end(), aa.begin() ) ); } { multi::array const AA = {10, 20, 30}; std::vector const aa(AA.begin(), AA.end()); // NOLINT(fuchsia-default-arguments-calls) - BOOST_REQUIRE( std::equal(AA.begin(), AA.end(), aa.begin() ) ); + BOOST_TEST( std::equal(AA.begin(), AA.end(), aa.begin() ) ); } { multi::array const AA = {10, 20, 30}; auto const aa(AA().operator std::vector()); - BOOST_REQUIRE( std::equal(AA.begin(), AA.end(), aa.begin() ) ); + BOOST_TEST( std::equal(AA.begin(), AA.end(), aa.begin() ) ); } // { // multi::array const AA = {1.0, 2.0, 3.0}; // std::vector const aa(AA); - // BOOST_REQUIRE( std::equal(AA.begin(), AA.end(), aa.begin() ) ); + // BOOST_TEST( std::equal(AA.begin(), AA.end(), aa.begin() ) ); // } { std::vector const aa = {10, 20, 30}; // NOLINT(fuchsia-default-arguments-calls) multi::array const AA(aa.begin(), aa.end()); - BOOST_REQUIRE( std::equal(AA.begin(), AA.end(), aa.begin() ) ); + BOOST_TEST( std::equal(AA.begin(), AA.end(), aa.begin() ) ); } { std::vector const aa = {10, 20, 30}; // NOLINT(fuchsia-default-arguments-calls) multi::array const AA(aa); - BOOST_REQUIRE( std::equal(AA.begin(), AA.end(), aa.begin() ) ); + BOOST_TEST( std::equal(AA.begin(), AA.end(), aa.begin() ) ); } } @@ -240,7 +214,7 @@ BOOST_AUTO_TEST_CASE(construct_from_vector_2D) { {10, 20}, {30, 40}, }; - BOOST_REQUIRE( AA.num_elements() == 4 ); + BOOST_TEST( AA.num_elements() == 4 ); std::vector> const aa(AA.begin(), AA.end()); // NOLINT(fuchsia-default-arguments-calls) } @@ -249,7 +223,7 @@ BOOST_AUTO_TEST_CASE(construct_from_vector_2D) { {10, 20}, {30, 40}, }; - BOOST_REQUIRE( AA.num_elements() == 4 ); + BOOST_TEST( AA.num_elements() == 4 ); auto const aa(AA().operator std::vector>()); } @@ -258,7 +232,7 @@ BOOST_AUTO_TEST_CASE(construct_from_vector_2D) { {10, 20}, {30, 40}, }; - BOOST_REQUIRE( AA.num_elements() == 4 ); + BOOST_TEST( AA.num_elements() == 4 ); auto const aa = AA.operator std::vector>(); } @@ -267,42 +241,39 @@ BOOST_AUTO_TEST_CASE(construct_from_vector_2D) { {10, 20}, {30, 40}, }; - BOOST_REQUIRE( AA.num_elements() == 4 ); + BOOST_TEST( AA.num_elements() == 4 ); auto const aa = static_cast>>(AA); } -#if !defined(__circle_build__) || (__circle_build__ > 200) // crashes circle 187-200 in docker { multi::array const AA = { {1.0, 2.0}, {3.0, 4.0}, }; - BOOST_REQUIRE( AA.num_elements() == 4 ); + BOOST_TEST( AA.num_elements() == 4 ); std::vector> const aa(AA); - BOOST_REQUIRE( aa.size() == 2 ); + BOOST_TEST( aa.size() == 2 ); // std::vector> const aaa = AA; // doesn't compile, needs implicit conversion } -#endif { multi::array const AA = { {1.0, 2.0}, {3.0, 4.0}, }; - BOOST_REQUIRE( AA.num_elements() == 4 ); + BOOST_TEST( AA.num_elements() == 4 ); } -#if !defined(__circle_build__) || (__circle_build__ > 200 ) // crashes circle 187-200 in docker { multi::array const AA = { {1.0, 2.0}, {3.0, 4.0}, }; - BOOST_REQUIRE( AA.num_elements() == 4 ); + BOOST_TEST( AA.num_elements() == 4 ); std::vector> const aa(AA); - BOOST_REQUIRE( aa.size() == 2 ); + BOOST_TEST( aa.size() == 2 ); } -#endif } +return boost::report_errors();} diff --git a/external_codes/boost_multi/multi/test/subarray.cpp b/external_codes/boost_multi/multi/test/subarray.cpp new file mode 100644 index 0000000000..45e528fd82 --- /dev/null +++ b/external_codes/boost_multi/multi/test/subarray.cpp @@ -0,0 +1,95 @@ +// Copyright 2019-2024 Alfredo A. Correa +// Copyright 2024 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include // for implicit_cast, explicit_cast + +#include + +// IWYU pragma: no_include // for add_const_t +#include // for as_const + +namespace multi = boost::multi; + +auto main() -> int { // NOLINT(readability-function-cognitive-complexity,bugprone-exception-escape) + /* subarray_assignment */ + { + multi::array A1({3, 4, 5}, 99); + A1[2][1][1] = 88; + + auto constA2 = std::as_const(A1)[2]; + BOOST_TEST( constA2[1][1] == 88 ); + + auto A2 = A1[2]; + BOOST_TEST( A2[1][1] == 88 ); + + A2[1][1] = 77; + BOOST_TEST( A2[1][1] == 77 ); + } + + /* subarray_base */ + { + multi::array A1({3, 4, 5}, 99); + + auto&& Asub = A1(); + *Asub.base() = 88; + + BOOST_TEST( A1[0][0][0] == 88 ); + + *A1().base() = 77; + + BOOST_TEST( A1[0][0][0] == 77 ); + + // *std::as_const(Asub).base() = 66; // should not compile, read-only + } + + /* test ref(begin, end)*/ + { + multi::array A2D = { + {1, 2}, + {3, 4} + }; + BOOST_TEST( A2D[0][0] == 1 ); + + multi::const_subarray R2D(A2D.begin(), A2D.end()); + BOOST_TEST( R2D.addressof()== A2D.addressof() ); + } + + /* test ref(begin, end)*/ + // { + // multi::array A2D = { + // {1, 2}, + // {3, 4} + // }; + // BOOST_TEST( A2D[0][0] == 1 ); + + // multi::const_subarray R2D(A2D.home(), A2D.sizes()); + // BOOST_TEST( R2D.addressof()== A2D.addressof() ); + // } + + /* test ref(begin, end)*/ + { + multi::array A2D = { + {1, 2}, + {3, 4} + }; + BOOST_TEST( A2D[0][0] == 1 ); + + multi::subarray R2D(A2D.begin(), A2D.end()); + BOOST_TEST( R2D.addressof()== A2D.addressof() ); + R2D[0][0] = 77; + } + + // { + // multi::array A2D({10000, 10000}, 55.5); + // auto const& A2D_block = A2D({1000, 9000}, {1000, 9000}); + + // multi::array B2D({10000, 10000}, 66.6); + // auto const& B2D_block = B2D({1000, 9000}, {1000, 9000}); + + // *B2D_block.begin() = *A2D_block.begin(); // doesn't compile, CORRECT + // } + + return boost::report_errors(); +} diff --git a/external_codes/boost_multi/multi/test/subrange.cpp b/external_codes/boost_multi/multi/test/subrange.cpp index da42e71136..d28a84aab1 100644 --- a/external_codes/boost_multi/multi/test/subrange.cpp +++ b/external_codes/boost_multi/multi/test/subrange.cpp @@ -7,222 +7,203 @@ #include // for std::iota -// Suppress warnings from boost.test -#if defined(__clang__) -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wold-style-cast" -# pragma clang diagnostic ignored "-Wundef" -# pragma clang diagnostic ignored "-Wconversion" -# pragma clang diagnostic ignored "-Wsign-conversion" -# pragma clang diagnostic ignored "-Wfloat-equal" -#elif defined(__GNUC__) -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wold-style-cast" -# pragma GCC diagnostic ignored "-Wundef" -# pragma GCC diagnostic ignored "-Wconversion" -# pragma GCC diagnostic ignored "-Wsign-conversion" -# pragma GCC diagnostic ignored "-Wfloat-equal" -#endif - -#ifndef BOOST_TEST_MODULE -# define BOOST_TEST_MAIN -#endif - -#include - namespace multi = boost::multi; +#include +#define BOOST_AUTO_TEST_CASE(CasenamE) /**/ + +auto main() -> int { // NOLINT(readability-function-cognitive-complexity,bugprone-exception-escape) BOOST_AUTO_TEST_CASE(multi_array_range_section) { { - #ifndef _MSC_VER - multi::array arr({10, 20, 30, 40}, 99.0); - #else - multi::array arr(multi::extensions_t<4>{10, 20, 30, 40}, 99.0); - #endif +#ifndef _MSC_VER + multi::array arr({ 10, 20, 30, 40 }, 99.0); +#else + multi::array arr(multi::extensions_t<4>{ 10, 20, 30, 40 }, 99.0); +#endif std::iota(arr.elements().begin(), arr.elements().end(), 0.0); { - static_assert(decltype(arr({0, 10}, {0, 20}, {0, 30}, {0, 40}))::rank::value == 4); - static_assert(decltype(arr(5, {0, 20}, {0, 30}, {0, 40}))::rank::value == 3); - static_assert(decltype(arr({0, 10}, 10, {0, 30}, {0, 40}))::rank::value == 3); - static_assert(decltype(arr({0, 10}, {0, 20}, 15, {0, 40}))::rank::value == 3); - static_assert(decltype(arr({0, 10}, {0, 20}, {0, 30}, 20))::rank::value == 3); - - static_assert(decltype(arr(5, 6, {0, 30}, {0, 40}))::rank::value == 2); - static_assert(decltype(arr({0, 10}, 6, 15, {0, 40}))::rank::value == 2); - static_assert(decltype(arr({0, 10}, {0, 20}, 15, 20))::rank::value == 2); - - static_assert(decltype(arr({0, 10}, {0, 20}, {0, 30}, {0, 40}))::rank_v == 4); - static_assert(decltype(arr(5, {0, 20}, {0, 30}, {0, 40}))::rank_v == 3); - static_assert(decltype(arr({0, 10}, 10, {0, 30}, {0, 40}))::rank_v == 3); - static_assert(decltype(arr({0, 10}, {0, 20}, 15, {0, 40}))::rank_v == 3); - static_assert(decltype(arr({0, 10}, {0, 20}, {0, 30}, 20))::rank_v == 3); - - static_assert(decltype(arr(5, 6, {0, 30}, {0, 40}))::rank_v == 2); - static_assert(decltype(arr({0, 10}, 6, 15, {0, 40}))::rank_v == 2); - static_assert(decltype(arr({0, 10}, {0, 20}, 15, 20))::rank_v == 2); + static_assert(decltype(arr({ 0, 10 }, { 0, 20 }, { 0, 30 }, { 0, 40 }))::rank::value == 4); + static_assert(decltype(arr(5, { 0, 20 }, { 0, 30 }, { 0, 40 }))::rank::value == 3); + static_assert(decltype(arr({ 0, 10 }, 10, { 0, 30 }, { 0, 40 }))::rank::value == 3); + static_assert(decltype(arr({ 0, 10 }, { 0, 20 }, 15, { 0, 40 }))::rank::value == 3); + static_assert(decltype(arr({ 0, 10 }, { 0, 20 }, { 0, 30 }, 20))::rank::value == 3); + + static_assert(decltype(arr(5, 6, { 0, 30 }, { 0, 40 }))::rank::value == 2); + static_assert(decltype(arr({ 0, 10 }, 6, 15, { 0, 40 }))::rank::value == 2); + static_assert(decltype(arr({ 0, 10 }, { 0, 20 }, 15, 20))::rank::value == 2); + + static_assert(decltype(arr({ 0, 10 }, { 0, 20 }, { 0, 30 }, { 0, 40 }))::rank_v == 4); + static_assert(decltype(arr(5, { 0, 20 }, { 0, 30 }, { 0, 40 }))::rank_v == 3); + static_assert(decltype(arr({ 0, 10 }, 10, { 0, 30 }, { 0, 40 }))::rank_v == 3); + static_assert(decltype(arr({ 0, 10 }, { 0, 20 }, 15, { 0, 40 }))::rank_v == 3); + static_assert(decltype(arr({ 0, 10 }, { 0, 20 }, { 0, 30 }, 20))::rank_v == 3); + + static_assert(decltype(arr(5, 6, { 0, 30 }, { 0, 40 }))::rank_v == 2); + static_assert(decltype(arr({ 0, 10 }, 6, 15, { 0, 40 }))::rank_v == 2); + static_assert(decltype(arr({ 0, 10 }, { 0, 20 }, 15, 20))::rank_v == 2); } { - auto&& all = arr({0, 10}, {0, 20}, {0, 30}, {0, 40}); - BOOST_REQUIRE( &arr[1][2][3][4] == &all[1][2][3][4] ); - BOOST_REQUIRE( &arr[1][2][3][4] == &arr({0, 10}, {0, 20}, {0, 30}, {0, 40})[1][2][3][4] ); + auto&& all = arr({ 0, 10 }, { 0, 20 }, { 0, 30 }, { 0, 40 }); + BOOST_TEST( &arr[1][2][3][4] == &all[1][2][3][4] ); + BOOST_TEST( &arr[1][2][3][4] == &arr({0, 10}, {0, 20}, {0, 30}, {0, 40})[1][2][3][4] ); } { using multi::_; - auto&& all = arr({0, 10}, {0, 20}); - BOOST_REQUIRE( &arr[1][2][3][4] == &all[1][2][3][4] ); + auto&& all = arr({ 0, 10 }, { 0, 20 }); + BOOST_TEST( &arr[1][2][3][4] == &all[1][2][3][4] ); } { - BOOST_REQUIRE( &arr(0, 0, 0, 0) == &arr[0][0][0][0] ); + BOOST_TEST( &arr(0, 0, 0, 0) == &arr[0][0][0][0] ); } { - auto&& sub = arr({0, 5}, {0, 10}, {0, 15}, {0, 20}); - BOOST_REQUIRE( &sub[1][2][3][4] == &arr[1][2][3][4] ); + auto&& sub = arr({ 0, 5 }, { 0, 10 }, { 0, 15 }, { 0, 20 }); + BOOST_TEST( &sub[1][2][3][4] == &arr[1][2][3][4] ); } } { - multi::array arr = { - {1.0, 2.0, 3.0, 4.0}, - {5.0, 6.0, 7.0, 8.0}, - {9.0, 0.0, 1.0, 2.0}, - {3.0, 4.0, 5.0, 6.0}, + multi::array arr = { + { 10, 20, 30, 40 }, + { 50, 60, 70, 80 }, + { 90, 00, 10, 20 }, + { 30, 40, 50, 60 }, }; - multi::array arr2 = { - {91.0, 92.0, 93.0, 94.0}, - {95.0, 96.0, 97.0, 98.0}, - {99.0, 90.0, 91.0, 92.0}, - {93.0, 94.0, 95.0, 96.0}, + multi::array arr2 = { + { 910, 920, 930, 940 }, + { 950, 960, 970, 980 }, + { 990, 900, 910, 920 }, + { 930, 940, 950, 960 }, }; - arr({0, 2}, {0, 2}) = arr2({0, 2}, {0, 2}); - BOOST_REQUIRE( arr != arr2 ); - BOOST_REQUIRE( arr({0, 2}, {0, 2}) == arr2({0, 2}, {0, 2}) ); - BOOST_REQUIRE( arr[1][1] == 96. ); + arr({ 0, 2 }, { 0, 2 }) = arr2({ 0, 2 }, { 0, 2 }); + BOOST_TEST( arr != arr2 ); + BOOST_TEST( arr({0, 2}, {0, 2}) == arr2({0, 2}, {0, 2}) ); + BOOST_TEST( arr[1][1] == 960 ); } } BOOST_AUTO_TEST_CASE(subrange_assignment) { - multi::array const arr = { - {1.0, 2.0, 3.0, 4.0}, - {5.0, 6.0, 7.0, 8.0}, - {9.0, 0.0, 1.0, 2.0}, - {3.0, 4.0, 5.0, 6.0}, + multi::array const arr = { + { 10, 20, 30, 40 }, + { 50, 60, 70, 80 }, + { 90, 00, 10, 20 }, + { 30, 40, 50, 60 }, }; { - multi::array arr2 = { - {9.0, 9.0, 9.0}, - {9.0, 9.0, 9.0}, - {9.0, 9.0, 9.0}, + multi::array arr2 = { + { 90, 90, 90 }, + { 90, 90, 90 }, + { 90, 90, 90 }, }; - arr2({0, 3}, {0, 3}) = arr({0, 3}, {0, 3}); - BOOST_REQUIRE( arr2[1][2] == arr[1][2] ); + arr2({ 0, 3 }, { 0, 3 }) = arr({ 0, 3 }, { 0, 3 }); + BOOST_TEST( arr2[1][2] == arr[1][2] ); } { - multi::array arr2 = { - {9.0, 9.0, 9.0}, - {9.0, 9.0, 9.0}, - {9.0, 9.0, 9.0}, + multi::array arr2 = { + { 90, 90, 90 }, + { 90, 90, 90 }, + { 90, 90, 90 }, }; - arr2() = arr({0, 3}, {0, 3}); - BOOST_REQUIRE( arr2[1][2] == arr[1][2] ); - BOOST_REQUIRE( arr2() == arr({0, 3}, {0, 3}) ); + arr2() = arr({ 0, 3 }, { 0, 3 }); + BOOST_TEST( arr2[1][2] == arr[1][2] ); + BOOST_TEST( arr2() == arr({0, 3}, {0, 3}) ); } { - multi::array arr2 = { - {9.0, 9.0, 9.0}, - {9.0, 9.0, 9.0}, - {9.0, 9.0, 9.0}, + multi::array arr2 = { + { 90, 90, 90 }, + { 90, 90, 90 }, + { 90, 90, 90 }, }; - arr2 = arr({0, 3}, {0, 3}); - BOOST_REQUIRE( arr2[1][2] == arr[1][2] ); - BOOST_REQUIRE( arr2 == arr({0, 3}, {0, 3}) ); + arr2 = arr({ 0, 3 }, { 0, 3 }); + BOOST_TEST( arr2[1][2] == arr[1][2] ); + BOOST_TEST( arr2 == arr({0, 3}, {0, 3}) ); } } BOOST_AUTO_TEST_CASE(subrange_ranges_sliced_1D) { - multi::array arr = {1.0, 2.0, 3.0, 4.0}; + multi::array arr = { 1.0, 2.0, 3.0, 4.0 }; auto&& Ab = arr.sliced(1, 3); - BOOST_REQUIRE( &Ab[0] == &arr[1] ); + BOOST_TEST( &Ab[0] == &arr[1] ); auto&& Ab2 = Ab; - BOOST_REQUIRE( &Ab2[0] == &arr[1] ); + BOOST_TEST( &Ab2[0] == &arr[1] ); // auto Abb = Ab; // not allowed! // auto Abb = std::move(Ab); (void)Abb; auto const& Abc = arr.sliced(1, 3); - BOOST_REQUIRE( &Abc[0] == &arr[1] ); + BOOST_TEST( &Abc[0] == &arr[1] ); auto Aba = arr.sliced(1, 3); - BOOST_REQUIRE( &Aba[0] == &arr[1] ); + BOOST_TEST( &Aba[0] == &arr[1] ); } BOOST_AUTO_TEST_CASE(subrange_ranges_sliced) { multi::array arr = { - {1.0, 2.0, 3.0, 4.0}, - {5.0, 6.0, 7.0, 8.0}, - {9.0, 0.0, 1.0, 2.0}, - {3.0, 4.0, 5.0, 6.0}, + { 1.0, 2.0, 3.0, 4.0 }, + { 5.0, 6.0, 7.0, 8.0 }, + { 9.0, 0.0, 1.0, 2.0 }, + { 3.0, 4.0, 5.0, 6.0 }, }; auto&& Ab = arr.sliced(0, 3); - BOOST_REQUIRE( &Ab[2][2] == &arr[2][2] ); + BOOST_TEST( &Ab[2][2] == &arr[2][2] ); auto const& Abc = arr.sliced(0, 3); - BOOST_REQUIRE( &Abc[2][2] == &arr[2][2] ); + BOOST_TEST( &Abc[2][2] == &arr[2][2] ); auto AB = arr.sliced(0, 3); - BOOST_REQUIRE( &AB[2][2] == &arr[2][2] ); + BOOST_TEST( &AB[2][2] == &arr[2][2] ); } BOOST_AUTO_TEST_CASE(subrange_ranges) { multi::array arr = { - {1.0, 2.0, 3.0, 4.0}, - {5.0, 6.0, 7.0, 8.0}, - {9.0, 0.0, 1.0, 2.0}, - {3.0, 4.0, 5.0, 6.0}, + { 1.0, 2.0, 3.0, 4.0 }, + { 5.0, 6.0, 7.0, 8.0 }, + { 9.0, 0.0, 1.0, 2.0 }, + { 3.0, 4.0, 5.0, 6.0 }, }; - auto&& Ab = arr({0, 3}, {0, 3}); - BOOST_REQUIRE( &Ab[2][2] == &arr[2][2] ); + auto&& Ab = arr({ 0, 3 }, { 0, 3 }); + BOOST_TEST( &Ab[2][2] == &arr[2][2] ); - auto const& Abc = arr({0, 3}, {0, 3}); - BOOST_REQUIRE( &Abc[2][2] == &arr[2][2] ); + auto const& Abc = arr({ 0, 3 }, { 0, 3 }); + BOOST_TEST( &Abc[2][2] == &arr[2][2] ); - auto AB = arr({0, 3}, {0, 3}); - BOOST_REQUIRE( &AB[2][2] == &arr[2][2] ); + auto AB = arr({ 0, 3 }, { 0, 3 }); + BOOST_TEST( &AB[2][2] == &arr[2][2] ); } BOOST_AUTO_TEST_CASE(subrange_1D_issue129) { - multi::array arr({1024}, double{}); - std::iota(arr.elements().begin(), arr.elements().end(), 0.0); + multi::array arr({ 1024 }, int{}); + std::iota(arr.elements().begin(), arr.elements().end(), 0); - BOOST_REQUIRE( arr.sliced(0, 512, 2)[ 1] == 2.0 ); - BOOST_REQUIRE( arr.sliced(0, 512, 2)[255] == 510.0 ); + BOOST_TEST( arr.sliced(0, 512, 2)[ 1] == 2 ); + BOOST_TEST( arr.sliced(0, 512, 2)[255] == 510 ); - BOOST_REQUIRE( arr.sliced(0, 512)[ 1] == 1.0 ); - BOOST_REQUIRE( arr.sliced(0, 512)[511] == 511.0 ); + BOOST_TEST( arr.sliced(0, 512)[ 1] == 1 ); + BOOST_TEST( arr.sliced(0, 512)[511] == 511 ); - BOOST_REQUIRE( arr({0, 512})[ 1] == 1.0 ); - BOOST_REQUIRE( arr({0, 512})[511] == 511.0 ); + BOOST_TEST( arr({0, 512})[ 1] == 1 ); + BOOST_TEST( arr({0, 512})[511] == 511 ); - // BOOST_REQUIRE( arr({0, 512, 2})[ 1] == 2. ); // TODO(correaa) coompilation error - // BOOST_REQUIRE( arr({0, 512, 2})[255] == 510. ); // TODO(correaa) coompilation error + // BOOST_TEST( arr({0, 512, 2})[ 1] == 2 ); // TODO(correaa) coompilation error + // BOOST_TEST( arr({0, 512, 2})[255] == 510 ); // TODO(correaa) coompilation error } BOOST_AUTO_TEST_CASE(subrange_2D_issue129) { - multi::array arr({66, 1024}, double{}); - std::iota(arr.elements().begin(), arr.elements().end(), 0.0); + multi::array arr({ 66, 1024 }, int{}); + std::iota(arr.elements().begin(), arr.elements().end(), 0); - BOOST_REQUIRE( arr[0].sliced(0, 512, 2)[ 1] == 2.0 ); - BOOST_REQUIRE( arr[0].sliced(0, 512, 2)[255] == 510.0 ); + BOOST_TEST( arr[0].sliced(0, 512, 2)[ 1] == 2 ); + BOOST_TEST( arr[0].sliced(0, 512, 2)[255] == 510 ); - BOOST_REQUIRE( arr[0].sliced(0, 512)[ 1] == 1.0 ); - BOOST_REQUIRE( arr[0].sliced(0, 512)[511] == 511.0 ); + BOOST_TEST( arr[0].sliced(0, 512)[ 1] == 1 ); + BOOST_TEST( arr[0].sliced(0, 512)[511] == 511 ); - BOOST_REQUIRE( arr(0, {0, 512})[ 1] == 1.0 ); - BOOST_REQUIRE( arr(0, {0, 512})[511] == 511.0 ); + BOOST_TEST( arr(0, {0, 512})[ 1] == 1 ); + BOOST_TEST( arr(0, {0, 512})[511] == 511 ); - // BOOST_REQUIRE( arr(0, {0, 512, 2})[ 1] == 2. ); // TODO(correaa) coompilation error - // BOOST_REQUIRE( arr(0, {0, 512, 2})[255] == 510. ); // TODO(correaa) coompilation error + // BOOST_TEST( arr(0, {0, 512, 2})[ 1] == 2 ); // TODO(correaa) coompilation error + // BOOST_TEST( arr(0, {0, 512, 2})[255] == 510 ); // TODO(correaa) coompilation error } class rng3_t { @@ -230,37 +211,38 @@ class rng3_t { int finish_; public: - rng3_t(int start, int finish) : start_{start}, finish_{finish} {} // NOLINT(bugprone-easily-swappable-parameters) + rng3_t(int start, int finish) : start_{ start }, finish_{ finish } {} // NOLINT(bugprone-easily-swappable-parameters) auto first() const { return start_; } auto last() const { return finish_; } }; BOOST_AUTO_TEST_CASE(subrange_start_finish) { multi::array arr = { - { 1.0, 2.0}, - { 3.0, 4.0}, - { 5.0, 6.0}, - { 7.0, 8.0}, - { 9.0, 10.0}, - {11.0, 12.0}, - {13.0, 14.0}, + { 1.0, 2.0 }, + { 3.0, 4.0 }, + { 5.0, 6.0 }, + { 7.0, 8.0 }, + { 9.0, 10.0 }, + { 11.0, 12.0 }, + { 13.0, 14.0 }, }; - BOOST_REQUIRE( &arr({2, 5}, 1)[0] == &arr[2][1] ); + BOOST_TEST( &arr({2, 5}, 1)[0] == &arr[2][1] ); multi::irange const rng(2, 5); - BOOST_REQUIRE( &arr(rng, 1)[0] == &arr[2][1] ); + BOOST_TEST( &arr(rng, 1)[0] == &arr[2][1] ); struct : multi::irange { using multi::irange::irange; } const rng2(2, 5); - BOOST_REQUIRE( &arr(rng2, 1)[0] == &arr[2][1] ); + BOOST_TEST( &arr(rng2, 1)[0] == &arr[2][1] ); - rng3_t const rng3{2, 5}; + rng3_t const rng3{ 2, 5 }; multi::irange const rng4(rng3); - BOOST_REQUIRE( &arr(rng4, 1)[0] == &arr[2][1] ); + BOOST_TEST( &arr(rng4, 1)[0] == &arr[2][1] ); - BOOST_REQUIRE( &arr(rng3, 1)[0] == &arr[2][1] ); + BOOST_TEST( &arr(rng3, 1)[0] == &arr[2][1] ); } +return boost::report_errors();} diff --git a/external_codes/boost_multi/multi/test/swap.cpp b/external_codes/boost_multi/multi/test/swap.cpp new file mode 100644 index 0000000000..97e68a2063 --- /dev/null +++ b/external_codes/boost_multi/multi/test/swap.cpp @@ -0,0 +1,98 @@ +// Copyright 2020-2024 Alfredo A. Correa +// Copyright 2024 Matt Borland +// Distributed under the Boost Software License, Version 10. +// https://www.boost.org/LICENSE_1_0.txt + +#include // for array, apply, array_types<>::ele... + +#include // for swap // IWYU pragma: keep // for std::swap +// IWYU pragma: no_include // for swap +// IWYU pragma: no_include // for swap + +namespace multi = boost::multi; + +#include +#define BOOST_AUTO_TEST_CASE(CasenamE) /**/ + +auto main() -> int { // NOLINT(readability-function-cognitive-complexity,bugprone-exception-escape) +BOOST_AUTO_TEST_CASE(swap_array_1D) { + multi::array arr1 = { 0, 1, 2, 3}; + multi::array arr2 = {100, 101, 102}; + + using std::swap; + swap(arr1, arr2); + + BOOST_TEST( arr1[1] == 101 ); + BOOST_TEST( arr2[1] == 1 ); +} + +BOOST_AUTO_TEST_CASE(swap_array_2D) { + multi::array arr1 = { + {00, 01, 02, 03}, + {10, 11, 12, 13}, + {20, 21, 22, 23}, + }; + + multi::array arr2 = { + {100, 101, 102, 103}, + {110, 111, 112, 113}, + }; + + using std::swap; + swap(arr1, arr2); + + BOOST_TEST( arr1[1][1] == 111 ); + BOOST_TEST( arr2[1][1] == 11 ); +} + +BOOST_AUTO_TEST_CASE(swap_subarray_1D) { + multi::array arr1 = { 0, 1, 2, 3}; + multi::array arr2 = {100, 101, 102, 103}; + + using std::swap; + swap(arr1(), arr2()); + + BOOST_TEST( arr1[1] == 101 ); + BOOST_TEST( arr2[1] == 1 ); +} + +BOOST_AUTO_TEST_CASE(swap_subarray_2D) { + multi::array arr1 = { + {00, 01, 02, 03}, + {10, 11, 12, 13}, + {20, 21, 22, 23}, + }; + + multi::array arr2 = { + {100, 101, 102, 103}, + {110, 111, 112, 113}, + {120, 121, 122, 123}, + }; + + using std::swap; + swap(arr1(), arr2()); + + BOOST_TEST( arr1[1][1] == 111 ); + BOOST_TEST( arr2[1][1] == 11 ); +} + +BOOST_AUTO_TEST_CASE(swap_const_subarray_2D) { + multi::array const arr1 = { + {00, 01, 02, 03}, + {10, 11, 12, 13}, + {20, 21, 22, 23}, + }; + + multi::array arr2 = { + {100, 101, 102, 103}, + {110, 111, 112, 113}, + {120, 121, 122, 123}, + }; + + // using std::swap; + // swap(arr1(), arr2()); + + BOOST_TEST( arr1[1][1] == 11 ); + BOOST_TEST( arr2[1][1] == 111 ); +} +return boost::report_errors();} diff --git a/external_codes/boost_multi/multi/test/transform.cpp b/external_codes/boost_multi/multi/test/transform.cpp index 44ef532fce..60fbf4904d 100644 --- a/external_codes/boost_multi/multi/test/transform.cpp +++ b/external_codes/boost_multi/multi/test/transform.cpp @@ -3,33 +3,19 @@ // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt -#include +#include // for array, subarray, static_array -#include -#include +#include -// Suppress warnings from boost.test -#if defined(__clang__) -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wold-style-cast" -#pragma clang diagnostic ignored "-Wundef" -#pragma clang diagnostic ignored "-Wconversion" -#pragma clang diagnostic ignored "-Wsign-conversion" -#pragma clang diagnostic ignored "-Wfloat-equal" -#elif defined(__GNUC__) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wold-style-cast" -#pragma GCC diagnostic ignored "-Wundef" -#pragma GCC diagnostic ignored "-Wconversion" -#pragma GCC diagnostic ignored "-Wsign-conversion" -#pragma GCC diagnostic ignored "-Wfloat-equal" -#endif - -#ifndef BOOST_TEST_MODULE -#define BOOST_TEST_MAIN -#endif - -#include +#include // for array // IWYU pragma: keep +#include // for complex, operator*, operator+ +#include // for ptrdiff_t +#include // for abs +#include // for negate // IWYU pragma: keep +#include // for iterator_traits +#include // for pointer_traits +#include // for decay_t, conditional_t, true_type +#include // for move, declval #define BOOST_MULTI_DECLRETURN(ExpR) \ ->decltype(ExpR) { return ExpR; } // NOLINT(cppcoreguidelines-macro-usage) saves a lot of typing @@ -46,8 +32,6 @@ constexpr inline neg_t neg; namespace test { -template class involuter; - template class involuted { Ref r_; // NOLINT(cppcoreguidelines-avoid-const-or-ref-data-members) @@ -58,6 +42,11 @@ class involuted { public: using decay_type = std::decay_t()(std::declval()))>; constexpr involuted(Involution /*stateless*/, Ref ref) : r_{ref} {} + involuted(involuted const&) = default; + involuted(involuted&&) noexcept = default; + + auto operator=(involuted&&) -> involuted& = delete; + auto operator=(involuted const&) -> involuted& = default; auto operator=(decay_type const& other) -> involuted& { // NOLINT(fuchsia-trailing-return) simulate reference r_ = Involution{}(other); return *this; @@ -68,13 +57,28 @@ class involuted { // NOLINTNEXTLINE(google-runtime-operator): simulated reference // constexpr auto operator&() & { return involuter())>{Involution{}, &r_}; } // NOLINT(runtime/operator) // NOLINTNEXTLINE(google-runtime-operator): simulated reference - // constexpr auto operator&() const& { return involuter())>{Involution{}, &r_}; } // NOLINT(runtime/operator) + // constexpr auto operator&() const& { // NOLINT(runtime/operator) + // return involuter())>{Involution{}, &r_}; + // } auto operator==(involuted const& other) const { return r_ == other.r_; } auto operator!=(involuted const& other) const { return r_ == other.r_; } +#if defined(__clang__) + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wfloat-equal" +#elif defined(__GNUC__) + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wfloat-equal" +#endif auto operator==(decay_type const& other) const { return Involution{}(r_) == other; } auto operator!=(decay_type const& other) const { return Involution{}(r_) != other; } +#if defined(__clang__) + #pragma clang diagnostic pop +#elif defined(__GNUC__) + #pragma GCC diagnostic pop +#endif + ~involuted() = default; }; template @@ -112,8 +116,18 @@ class involuter { return *this; } +#if defined(__clang__) + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wunknown-warning-option" + #pragma clang diagnostic ignored "-Wunsafe-buffer-usage" +#endif + constexpr auto operator+(difference_type n) const { return involuter{it_ + n}; } constexpr auto operator-(difference_type n) const { return involuter{it_ - n}; } + +#if defined(__clang__) + #pragma clang diagnostic pop +#endif }; template using negated = involuted, Ref>; @@ -146,13 +160,15 @@ struct conjugate<> : private basic_conjugate_t { }; #if defined(__NVCC__) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wsubobject-linkage" + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wsubobject-linkage" #endif template struct conjd : test::involuted, ComplexRef> { explicit conjd(ComplexRef ref) : test::involuted, ComplexRef>(conjugate<>{}, ref) {} - auto real() const { return underlying(*this).real(); } - auto imag() const { return negated, ComplexRef> const&>()).imag())>{std::negate<>{}, underlying(*this).imag()}; } + auto real() const { return underlying(*this).real(); } + auto imag() const { + return negated, ComplexRef> const&>()).imag())>{std::negate<>{}, underlying(*this).imag()}; + } friend auto real(conjd const& self) -> decltype(auto) { using std::real; return real(static_cast(self)); @@ -163,7 +179,7 @@ template struct conjd : test::involuted, ComplexRe } }; #if defined(__NVCC__) -#pragma GCC diagnostic pop + #pragma GCC diagnostic pop #endif #if defined(__cpp_deduction_guides) @@ -191,124 +207,191 @@ class indirect_real { } // namespace test -BOOST_AUTO_TEST_CASE(transformed_array) { - namespace multi = boost::multi; - { - using complex = std::complex; - complex cee{1.0, 2.0}; - - auto&& zee = test::conjd{cee}; - BOOST_REQUIRE(( zee == complex{1.0, -2.0} )); +#define BOOST_AUTO_TEST_CASE(CasenamE) /**/ - BOOST_REQUIRE( real(zee) == 1.0 ); - BOOST_REQUIRE( imag(zee) == -2.0 ); - BOOST_REQUIRE( zee.real() == 1.0 ); - BOOST_REQUIRE( zee.imag() == -2.0 ); - } - { - double doub = 5.0; +auto main() -> int { // NOLINT(readability-function-cognitive-complexity,bugprone-exception-escape) + BOOST_AUTO_TEST_CASE(transformed_array) { + namespace multi = boost::multi; + { + using complex = std::complex; + complex cee{1.0, 2.0}; - auto&& negd_a = test::involuted(test::neg, doub); - BOOST_REQUIRE( negd_a == -5.0 ); + auto&& zee = test::conjd{cee}; + BOOST_TEST(( zee == complex{1.0, -2.0} )); - negd_a = 10.0; - BOOST_REQUIRE( negd_a == 10.0 ); - BOOST_REQUIRE( doub = -10.0 ); - } - { - multi::array arr = {0.0, 1.0, 2.0, 3.0, 4.0}; - auto&& ref = arr.static_array_cast(); - BOOST_REQUIRE( ref[2] == arr[2] ); - } + BOOST_TEST( std::abs( real(zee) - +1.0 ) < 1E-6); + BOOST_TEST( std::abs( imag(zee) - -2.0 ) < 1E-6); + } + { + int val = 50; - { - multi::array const arr = {+0.0, +1.0, +2.0, +3.0, +4.0}; - multi::array neg = {-0.0, -1.0, -2.0, -3.0, -4.0}; - auto&& negd_arr = arr.static_array_cast>(); - BOOST_REQUIRE( negd_arr[2] == neg[2] ); - } - { - multi::array const arr = { - { +0.0, +1.0, +2.0, +3.0, +4.0}, - { +5.0, +6.0, +7.0, +8.0, +9.0}, - {+10.0, +11.0, +12.0, +13.0, +14.0}, - {+15.0, +16.0, +17.0, +18.0, +19.0}, - }; - multi::array neg = { - { -0.0, -1.0, -2.0, -3.0, -4.0}, - { -5.0, -6.0, -7.0, -8.0, -9.0}, - {-10.0, -11.0, -12.0, -13.0, -14.0}, - {-15.0, -16.0, -17.0, -18.0, -19.0}, - }; - // auto&& negd_arr = arr.static_array_cast>(); // not compile, ok, read only - auto&& negd_arr = arr.static_array_cast>(); - BOOST_REQUIRE( negd_arr[1][1] == neg[1][1] ); - BOOST_REQUIRE( negd_arr[1][1] == -6.0 ); - // negd_arr2[1][1] = 3.0; // can't compile, ok, read-only - } - { -#if defined(__cpp_deduction_guides) - // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) : testing legacy types - double zee[4][5]{ - { 0.0, 1.0, 2.0, 3.0, 4.0}, - { 5.0, 6.0, 7.0, 8.0, 9.0}, - {10.0, 11.0, 12.0, 13.0, 14.0}, - {15.0, 16.0, 17.0, 18.0, 19.0}, - }; - auto&& d2DC = multi::make_array_ref(test::involuter{test::neg, &zee[0][0]}, {4, 5}); + auto&& negd_a = test::involuted(test::neg, val); + BOOST_TEST( negd_a == -50 ); - d2DC[1][1] = -66.0; - BOOST_REQUIRE( zee[1][1] == 66.0 ); -#endif + negd_a = 100; + BOOST_TEST( negd_a == 100 ); + BOOST_TEST( val == -100 ); + } { - using complex = std::complex; - - multi::array d2D = { - { {0.0, 3.0}, {1.0, 9.0}, {2.0, 4.0}, {3.0, 0.0}, {4.0, 0.0}}, - { {5.0, 0.0}, {6.0, 3.0}, {7.0, 5.0}, {8.0, 0.0}, {9.0, 0.0}}, - { {1.0, 4.0}, {9.0, 1.0}, {12.0, 0.0}, {13.0, 0.0}, {14.0, 0.0}}, - {{15.0, 0.0}, {16.0, 0.0}, {17.0, 0.0}, {18.0, 0.0}, {19.0, 0.0}}, + multi::array arr = {0.0, 1.0, 2.0, 3.0, 4.0}; + auto&& ref = arr.static_array_cast(); + BOOST_TEST( std::abs(ref[2] - arr[2]) < 1E-6 ); + } + { + multi::array const arr = {+0.0, +1.0, +2.0, +3.0, +4.0}; + multi::array neg = {-0.0, -1.0, -2.0, -3.0, -4.0}; + auto&& negd_arr = arr.static_array_cast>(); + BOOST_TEST( negd_arr[2] == neg[2] ); + } + { + multi::array const arr = { + { +0.0, +1.0, +2.0, +3.0, +4.0}, + { +5.0, +6.0, +7.0, +8.0, +9.0}, + {+10.0, +11.0, +12.0, +13.0, +14.0}, + {+15.0, +16.0, +17.0, +18.0, +19.0}, }; + multi::array neg = { + { -0.0, -1.0, -2.0, -3.0, -4.0}, + { -5.0, -6.0, -7.0, -8.0, -9.0}, + {-10.0, -11.0, -12.0, -13.0, -14.0}, + {-15.0, -16.0, -17.0, -18.0, -19.0}, + }; + // auto&& negd_arr = arr.static_array_cast>(); // not compile, ok, read only + auto&& negd_arr = arr.static_array_cast>(); + BOOST_TEST( negd_arr[1][1] == neg[1][1] ); + BOOST_TEST( negd_arr[1][1] == -6.0 ); + // negd_arr2[1][1] = 3.0; // can't compile, ok, read-only + } + { +#if defined(__cpp_deduction_guides) + #if defined(__clang__) + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wunknown-warning-option" + #pragma clang diagnostic ignored "-Wunsafe-buffer-usage" + #endif + + // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) : testing legacy types + double zee[4][5]{ + { 0.0, 1.0, 2.0, 3.0, 4.0}, + { 5.0, 6.0, 7.0, 8.0, 9.0}, + {10.0, 11.0, 12.0, 13.0, 14.0}, + {15.0, 16.0, 17.0, 18.0, 19.0}, + }; + auto&& d2DC = multi::make_array_ref(test::involuter{test::neg, &zee[0][0]}, {4, 5}); - auto&& d2Dreal = d2D.reinterpret_array_cast(); - BOOST_REQUIRE( d2Dreal[2][1] == 9.0 ); + d2DC[1][1] = -66.0; - d2Dreal[2][1] = 12.0; - BOOST_REQUIRE( d2D[2][1] == complex(12.0, 1.0) ); + BOOST_TEST( std::abs( zee[1][1] - 66.0) < 1E-6 ); - auto&& d2DrealT = rotated(d2D).reinterpret_array_cast(); - BOOST_REQUIRE( d2DrealT[2][1] == 7.0 ); + #if defined(__clang__) + #pragma clang diagnostic pop + #endif - multi::array const d2Dreal_copy = d2D.template reinterpret_array_cast(); - BOOST_REQUIRE( d2Dreal_copy == d2Dreal ); +#endif + { + using complex = std::complex; + + multi::array d2D = { + { {0.0, 3.0}, {1.0, 9.0}, {2.0, 4.0}, {3.0, 0.0}, {4.0, 0.0}}, + { {5.0, 0.0}, {6.0, 3.0}, {7.0, 5.0}, {8.0, 0.0}, {9.0, 0.0}}, + { {1.0, 4.0}, {9.0, 1.0}, {12.0, 0.0}, {13.0, 0.0}, {14.0, 0.0}}, + {{15.0, 0.0}, {16.0, 0.0}, {17.0, 0.0}, {18.0, 0.0}, {19.0, 0.0}}, + }; + + auto&& d2Dreal = d2D.reinterpret_array_cast(); + BOOST_TEST( std::abs( d2Dreal[2][1] - 9.0) < 1E-6 ); + + d2Dreal[2][1] = 12.0; + BOOST_TEST( d2D[2][1] == complex(12.0, 1.0) ); + + auto&& d2DrealT = d2D.rotated().reinterpret_array_cast(); + BOOST_TEST( std::abs( d2DrealT[2][1] - 7.0) < 1E-6); + + multi::array const d2Dreal_copy{d2D.template reinterpret_array_cast()}; + BOOST_TEST( d2Dreal_copy == d2Dreal ); + } + { + using complex = std::complex; + + auto const I = complex{0.0, 1.0}; // NOLINT(readability-identifier-length) imaginary unit + + multi::array arr = { + {1.0 + 3.0 * I, 3.0 - 2.0 * I, 4.0 + 1.0 * I}, + {9.0 + 1.0 * I, 7.0 - 8.0 * I, 1.0 - 3.0 * I}, + }; + auto conjd_arr = arr.static_array_cast>(); + BOOST_TEST( conjd_arr[1][2] == conj(arr[1][2]) ); + } } - { - using complex = std::complex; + } - auto const I = complex{0.0, 1.0}; // NOLINT(readability-identifier-length) imaginary unit +#if !defined(__NVCC__) && defined(__GNU_MINOR__) && (__GNUC_MINOR__ > 7) + BOOST_AUTO_TEST_CASE(transformed_to_string) { + namespace multi = boost::multi; - multi::array arr = { - {1.0 + 3.0 * I, 3.0 - 2.0 * I, 4.0 + 1.0 * I}, - {9.0 + 1.0 * I, 7.0 - 8.0 * I, 1.0 - 3.0 * I}, - }; - auto conjd_arr = arr.static_array_cast>(); - BOOST_REQUIRE( conjd_arr[1][2] == conj(arr[1][2]) ); - } + multi::array const AA = { + {1, 2}, + {3, 4}, + }; + multi::array BB = AA.element_transformed([](int ee) noexcept { return std::to_string(ee); }); + + BOOST_TEST( BB[1][1] == "4" ); } -} +#endif + + /* accumulate rows */ + { + namespace multi = boost::multi; -#if !defined(__NVCC__) && (__GNUC_MINOR__ > 7) -BOOST_AUTO_TEST_CASE(transformed_to_string) { - namespace multi = boost::multi; + multi::array Arr({100, 200}, 1); - multi::array const AA = { - {1, 2}, - {3, 4}, - }; - multi::array BB = AA.element_transformed([](int ee) noexcept { return std::to_string(ee); }); + multi::array vv({200}, 0); + for(auto i : Arr.extension()) { // NOLINT(altera-unroll-loops) + for(auto j : vv.extension()) { // NOLINT(altera-unroll-loops) + vv[j] += Arr[i][j]; + } + } + + // auto const v = std::reduce( + // A.begin(), A.end(), + // multi::array({200}, 0), + // [](auto&& acc, auto&& row) { + // std::transform( + // acc.begin(), vv.end(), row.begin(), acc.begin(), + // [](auto const& e1, auto const& e2) { + // return e1 + e2; + // } + // ); + // return acc; + // } + // ); + + // auto const v = std::transform_reduce( + // A.begin(), A.end(), + // multi::array({200}, 0), + // [](auto&& vv, auto&& row) { + // std::transform( + // vv.begin(), vv.end(), row.begin(), vv.begin(), + // [](auto const& e1, auto const& e2) { + // return e1 + e2; + // } + // ); + // return vv; + // }, + // [](auto&& vv) {return vv;} + // ); + + // multi::array v({200}, 0); + + // std::transform( + // (~A).begin(), (~A).end(), v.begin(), + // [](auto const& col) { return std::reduce(col.begin(), col.end()); } + // ); + + BOOST_TEST(vv[0] == 100); + } - BOOST_REQUIRE( BB[1][1] == "4" ); + return boost::report_errors(); } -#endif #undef BOOST_MULTI_DECLRETURN diff --git a/external_codes/boost_multi/multi/test/utility.cpp b/external_codes/boost_multi/multi/test/utility.cpp index 9cdccab573..38bd70201f 100644 --- a/external_codes/boost_multi/multi/test/utility.cpp +++ b/external_codes/boost_multi/multi/test/utility.cpp @@ -3,69 +3,56 @@ // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt -#include -#include - -#include -#include // for iota - -// Suppress warnings from boost.test -#if defined(__clang__) -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wold-style-cast" -# pragma clang diagnostic ignored "-Wundef" -# pragma clang diagnostic ignored "-Wconversion" -# pragma clang diagnostic ignored "-Wsign-conversion" -# pragma clang diagnostic ignored "-Wfloat-equal" -#elif defined(__GNUC__) -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wold-style-cast" -# pragma GCC diagnostic ignored "-Wundef" -# pragma GCC diagnostic ignored "-Wconversion" -# pragma GCC diagnostic ignored "-Wsign-conversion" -# pragma GCC diagnostic ignored "-Wfloat-equal" -#endif - -#ifndef BOOST_TEST_MODULE -# define BOOST_TEST_MAIN -#endif +#include // for array_ref, data_elements, num_el... -#include +// IWYU pragma: no_include // for fill_n +#include // for array +#include // for begin, end, iterator_traits, rend +#include // for addressof // IWYU pragma: keep +#include // for iota +#include // for is_same +// IWYU pragma: no_include +#include // for vector, allocator namespace multi = boost::multi; // TODO(correaa) add test for reinterpret_pointer_cast + +#include +#define BOOST_AUTO_TEST_CASE(CasenamE) /**/ + +auto main() -> int { // NOLINT(readability-function-cognitive-complexity,bugprone-exception-escape) BOOST_AUTO_TEST_CASE(std_array_extensions_3d) { std::array, 4>, 3> arr = {}; static_assert(std::is_same::element, double>{}); - BOOST_REQUIRE( multi::dimensionality(arr) == 3 ); - - // BOOST_REQUIRE( multi::extension(arr) == 3 ); + BOOST_TEST( multi::dimensionality(arr) == 3 ); - BOOST_REQUIRE(( multi::extensions(arr) == decltype(multi::extensions(arr)){3, 4, 5} )); + BOOST_TEST(( multi::extensions(arr) == (decltype(multi::extensions(arr))({3, 4, 5})) )); + BOOST_TEST(( multi::extensions(arr) == decltype(multi::extensions(arr))({3, 4, 5}) )); + BOOST_TEST(( multi::extensions(arr) == decltype(multi::extensions(arr)) {3, 4, 5} )); #ifndef _MSC_VER // problem with 14.3 c++17 using multi::data_elements; - BOOST_REQUIRE( data_elements(arr) == &arr[0][0][0] ); // NOLINT(readability-container-data-pointer) - BOOST_REQUIRE( data_elements(arr) == arr[0][0].data() ); + BOOST_TEST( data_elements(arr) == &arr[0][0][0] ); // NOLINT(readability-container-data-pointer) + BOOST_TEST( data_elements(arr) == arr[0][0].data() ); using multi::num_elements; - BOOST_REQUIRE( num_elements(arr) == 60 ); + BOOST_TEST( num_elements(arr) == 60 ); #endif multi::array const marr( #ifdef _MSC_VER // problem with 14.3 c++17 multi::extensions_t<3> #endif - {3, 4, 5} + { 3, 4, 5 } ); using multi::layout; - BOOST_REQUIRE( layout(arr) == layout(marr) ); + BOOST_TEST( layout(arr) == layout(marr) ); - BOOST_REQUIRE( multi::extensions(arr) == extensions(marr) ); + BOOST_TEST( multi::extensions(arr) == extensions(marr) ); } BOOST_AUTO_TEST_CASE(std_array_extensions_2d) { @@ -74,27 +61,27 @@ BOOST_AUTO_TEST_CASE(std_array_extensions_2d) { static_assert(std::is_same::element, double>{}); using multi::dimensionality; - BOOST_REQUIRE( dimensionality(arr) == 2 ); + BOOST_TEST( dimensionality(arr) == 2 ); // using multi::extension; - // BOOST_REQUIRE( extension(arr) == 3 ); + // BOOST_TEST( extension(arr) == 3 ); using multi::extensions; - BOOST_REQUIRE(( extensions(arr) == decltype(extensions(arr)){3, 4} )); + BOOST_TEST(( extensions(arr) == decltype(extensions(arr)){3, 4} )); using multi::data_elements; - BOOST_REQUIRE( data_elements(arr) == &arr[0][0] ); // NOLINT(readability-container-data-pointer) test access - BOOST_REQUIRE( data_elements(arr) == arr[0].data() ); - BOOST_REQUIRE( data_elements(arr) == arr.front().data() ); + BOOST_TEST( data_elements(arr) == &arr[0][0] ); // NOLINT(readability-container-data-pointer) test access + BOOST_TEST( data_elements(arr) == arr[0].data() ); + BOOST_TEST( data_elements(arr) == arr.front().data() ); using multi::num_elements; - BOOST_REQUIRE( num_elements(arr) == 12 ); + BOOST_TEST( num_elements(arr) == 12 ); - multi::array const marr({3, 4}); + multi::array const marr({ 3, 4 }); using multi::layout; - BOOST_REQUIRE( layout(arr) == layout(marr) ); + BOOST_TEST( layout(arr) == layout(marr) ); - BOOST_REQUIRE( extensions(arr) == extensions(marr) ); + BOOST_TEST( extensions(arr) == extensions(marr) ); } BOOST_AUTO_TEST_CASE(std_array_extensions_1d) { @@ -103,90 +90,101 @@ BOOST_AUTO_TEST_CASE(std_array_extensions_1d) { static_assert(std::is_same::element, double>{}); using multi::dimensionality; - BOOST_REQUIRE( dimensionality(arr) == 1 ); + BOOST_TEST( dimensionality(arr) == 1 ); // using multi::extension; - // BOOST_REQUIRE( extension(arr) == 4 ); + // BOOST_TEST( extension(arr) == 4 ); using multi::extensions; - BOOST_REQUIRE(( extensions(arr) == decltype(extensions(arr)){multi::iextension{4}} )); + BOOST_TEST(( extensions(arr) == decltype(extensions(arr)){multi::iextension{4}} )); using multi::data_elements; - BOOST_REQUIRE( data_elements(arr) == &arr[0] ); // NOLINT(readability-container-data-pointer) test access - BOOST_REQUIRE( data_elements(arr) == arr.data() ); + BOOST_TEST( data_elements(arr) == &arr[0] ); // NOLINT(readability-container-data-pointer) test access + BOOST_TEST( data_elements(arr) == arr.data() ); using multi::num_elements; - BOOST_REQUIRE( num_elements(arr) == 4 ); + BOOST_TEST( num_elements(arr) == 4 ); } BOOST_AUTO_TEST_CASE(test_utility_1d) { - // clang-format off - std::array carr = {{0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0}}; - // clang-format on + std::array carr = { + {0, 1, 2, 3, 4, 5, 6, 7, 8, 9} + }; - multi::array_ref marr(carr.data(), {multi::iextension{10}}); + multi::array_ref marr(carr.data(), { multi::iextension{ 10 } }); - std::vector varr(10); // NOLINT(fuchsia-default-arguments-calls) - std::iota(begin(varr), end(varr), 0.0); - std::array aarr{}; - std::iota(begin(aarr), end(aarr), 0.0); + std::vector varr(10); // NOLINT(fuchsia-default-arguments-calls) + std::iota(varr.begin(), varr.end(), 0); + std::array aarr{}; + std::iota(aarr.begin(), aarr.end(), 0); - BOOST_REQUIRE( size(marr) == 10 ); + BOOST_TEST( size(marr) == 10 ); - BOOST_REQUIRE( static_cast(carr.size()) == size(marr) ); - BOOST_REQUIRE( static_cast(aarr.size()) == size(marr) ); + BOOST_TEST( static_cast(carr.size()) == size(marr) ); + BOOST_TEST( static_cast(aarr.size()) == size(marr) ); - BOOST_REQUIRE( carr[7] == marr[7] ); - BOOST_REQUIRE( varr[7] == marr[7] ); - BOOST_REQUIRE( aarr[7] == marr[7] ); + BOOST_TEST( carr[7] == marr[7] ); + BOOST_TEST( varr[7] == marr[7] ); + BOOST_TEST( aarr[7] == marr[7] ); - BOOST_REQUIRE( &carr[7] == &marr[7] ); + BOOST_TEST( &carr[7] == &marr[7] ); using multi::num_elements; - BOOST_REQUIRE( num_elements(carr) == num_elements(marr) ); - // BOOST_REQUIRE( num_elements(varr) == num_elements(marr) ); - BOOST_REQUIRE( num_elements(aarr) == num_elements(aarr) ); + BOOST_TEST( num_elements(carr) == num_elements(marr) ); + // BOOST_TEST( num_elements(varr) == num_elements(marr) ); + BOOST_TEST( num_elements(aarr) == num_elements(aarr) ); using multi::data_elements; - BOOST_REQUIRE( carr.data() == data_elements(marr) ); + BOOST_TEST( carr.data() == data_elements(marr) ); - BOOST_REQUIRE( *begin(varr) == *begin(marr) ); + BOOST_TEST( *begin(varr) == *begin(marr) ); using std::begin; - BOOST_REQUIRE( *begin(carr) == *begin(marr) ); + BOOST_TEST( *begin(carr) == *begin(marr) ); using std::rend; - BOOST_REQUIRE( *(end(varr)-1) == *(end(marr)-1) ); + BOOST_TEST( *(end(varr)-1) == *(end(marr)-1) ); + + #if defined(__clang__) + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wunknown-warning-option" + #pragma clang diagnostic ignored "-Wunsafe-buffer-usage" + #endif using std::end; - BOOST_REQUIRE( *(end(carr)-1) == *(end(marr)-1) ); + BOOST_TEST( *(end(carr)-1) == *(end(marr)-1) ); + + #if defined(__clang__) + #pragma clang diagnostic pop + #endif } BOOST_AUTO_TEST_CASE(test_utility_2d) { // clang-format off - std::array, 3> carr{{ - {{ 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0}}, - {{10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0}}, - {{20.0, 21.0, 22.0, 23.0, 24.0, 25.0, 26.0, 27.0, 28.0, 29.0}}, + std::array, 3> carr{{ + {{ 00, 10, 20, 30, 40, 50, 60, 70, 80, 90 }}, + {{ 100, 110, 120, 130, 140, 150, 160, 170, 180, 190 }}, + {{ 200, 210, 220, 230, 240, 250, 260, 270, 280, 290 }}, }}; // clang-format on - multi::array_ref marr(&carr[0][0], {3, 10}); // NOLINT(readability-container-data-pointer) tests access - BOOST_REQUIRE( static_cast(carr.size()) == size(marr) ); + multi::array_ref marr(&carr[0][0], { 3, 10 }); // NOLINT(readability-container-data-pointer) tests access + + BOOST_TEST( static_cast(carr.size()) == size(marr) ); - BOOST_REQUIRE( carr[1][7] == marr[1][7] ); + BOOST_TEST( carr[1][7] == marr[1][7] ); - BOOST_REQUIRE( &carr[1][7] == &marr[1][7] ); + BOOST_TEST( &carr[1][7] == &marr[1][7] ); using multi::num_elements; - BOOST_REQUIRE( num_elements(carr) == num_elements(marr) ); + BOOST_TEST( num_elements(carr) == num_elements(marr) ); using multi::data_elements; - BOOST_REQUIRE( data_elements(carr) == data_elements(marr) ); + BOOST_TEST( data_elements(carr) == data_elements(marr) ); } BOOST_AUTO_TEST_CASE(multi_utility_test) { - static_assert(std::is_same::value_type, double>{}, "!"); + static_assert(std::is_same_v::value_type, int>); using multi::corigin; using multi::dimensionality; @@ -196,45 +194,48 @@ BOOST_AUTO_TEST_CASE(multi_utility_test) { using multi::size; using multi::sizes; { - double arr[4] = {1.0, 2.0, 3.0, 4.0}; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) test legacy types - BOOST_REQUIRE( dimensionality(arr) == 1 ); - BOOST_REQUIRE( extension(arr).first() == 0 ); - BOOST_REQUIRE( extension(arr).last() == 4 ); + int arr[4] = { 10, 20, 30, 40 }; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) test legacy types + BOOST_TEST( dimensionality(arr) == 1 ); + BOOST_TEST( extension(arr).first() == 0 ); + BOOST_TEST( extension(arr).last() == 4 ); - BOOST_REQUIRE( size(arr) == 4 ); + BOOST_TEST( size(arr) == 4 ); using boost::multi::detail::get; - BOOST_REQUIRE( get<0>(sizes(arr)) == size(arr) ); + BOOST_TEST( get<0>(sizes(arr)) == size(arr) ); using multi::get_allocator; - static_assert(std::is_same>{}); + static_assert(std::is_same_v>); using std::addressof; using multi::data_elements; - static_assert(std::is_same{}); - // BOOST_REQUIRE( data(A) == addressof(A[0]) ); - BOOST_REQUIRE(data_elements(arr) == addressof(arr[0])); + static_assert(std::is_same_v); + // BOOST_TEST( data(A) == addressof(A[0]) ); + BOOST_TEST(data_elements(arr) == addressof(arr[0])); } { - double arr[2][3] = { // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) : test legacy types - {1.0, 2.0, 3.0}, - {4.0, 5.0, 6.0}, + // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) : test legacy types + int arr[2][3] = { + {10, 20, 30}, + {40, 50, 60}, }; - BOOST_REQUIRE( dimensionality(arr) == 2 ); - BOOST_REQUIRE( extension(arr).first() == 0 ); - BOOST_REQUIRE( extension(arr).last() == 2 ); + BOOST_TEST( dimensionality(arr) == 2 ); + BOOST_TEST( extension(arr).first() == 0 ); + BOOST_TEST( extension(arr).last() == 2 ); - arr[0][0] = 99.0; + arr[0][0] = 990; - BOOST_REQUIRE( arr[0][0] == 99.0 ); - BOOST_REQUIRE( corigin(arr) == &arr[0][0] ); - BOOST_REQUIRE( size(arr) == 2 ); + BOOST_TEST( arr[0][0] == 990 ); + BOOST_TEST( corigin(arr) == &arr[0][0] ); + BOOST_TEST( size(arr) == 2 ); using multi::detail::get; - BOOST_REQUIRE( get<0>(sizes(arr)) == size(arr) ); - BOOST_REQUIRE( num_elements(arr) == 6 ); + BOOST_TEST( get<0>(sizes(arr)) == size(arr) ); + BOOST_TEST( num_elements(arr) == 6 ); static_assert(num_elements(arr) == 6); } } + +return boost::report_errors();} diff --git a/external_codes/boost_multi/multi/test/zero_dimensionality.cpp b/external_codes/boost_multi/multi/test/zero_dimensionality.cpp index 460c0128f3..ab4c16e57a 100644 --- a/external_codes/boost_multi/multi/test/zero_dimensionality.cpp +++ b/external_codes/boost_multi/multi/test/zero_dimensionality.cpp @@ -3,113 +3,103 @@ // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt -#include - -#include - -// Suppress warnings from boost.test -#if defined(__clang__) -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wold-style-cast" -# pragma clang diagnostic ignored "-Wundef" -# pragma clang diagnostic ignored "-Wconversion" -# pragma clang diagnostic ignored "-Wsign-conversion" -# pragma clang diagnostic ignored "-Wfloat-equal" -#elif defined(__GNUC__) -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wold-style-cast" -# pragma GCC diagnostic ignored "-Wundef" -# pragma GCC diagnostic ignored "-Wconversion" -# pragma GCC diagnostic ignored "-Wsign-conversion" -# pragma GCC diagnostic ignored "-Wfloat-equal" -#endif - -#ifndef BOOST_TEST_MODULE -# define BOOST_TEST_MAIN -#endif +#include // for array_ref, static_array, array_ptr -#include +// IWYU pragma: no_include // for copy +#include // for complex +#include // for allocator // IWYU pragma: keep +// IWYU pragma: no_include // for remove_reference<>::type +// #include // for move +#include // for vector, allocator namespace multi = boost::multi; -BOOST_AUTO_TEST_CASE(zero_dimensionality_part1) { - { - std::vector v1 = {10, 20, 30}; // NOLINT(fuchsia-default-arguments-calls) - - multi::array_ref m1(v1.data(), multi::extensions_t<1>{multi::iextension{3}}); - BOOST_REQUIRE( size(m1) == 3 ); - BOOST_REQUIRE( &m1[1] == &v1[1] ); - BOOST_REQUIRE( num_elements(m1) == 3 ); - - multi::array_ref m0(v1.data(), {}); -// BOOST_REQUIRE(( &m0 == multi::array_ptr(v1.data(), {}) )); - BOOST_REQUIRE( data_elements(m0) == v1.data() ); - BOOST_REQUIRE( num_elements(m0) == 1 ); - - m0 = 51; - BOOST_REQUIRE( v1[0] == 51 ); - - int const& doub = std::move(m0); - BOOST_REQUIRE( doub == 51 ); - } - { - multi::static_array a0 = multi::static_array{45.0}; // TODO(correaa) this might trigger a compiler crash with g++ 7.5 because of operator&() && overloads - BOOST_REQUIRE( num_elements(a0) == 1 ); - BOOST_REQUIRE( a0 == 45.0 ); - - a0 = multi::static_array{60.0}; - BOOST_REQUIRE( a0 == 60.0 ); +#include +#define BOOST_AUTO_TEST_CASE(CasenamE) /**/ + +auto main() -> int { // NOLINT(readability-function-cognitive-complexity,bugprone-exception-escape) + BOOST_AUTO_TEST_CASE(zero_dimensionality_part1) { + { + std::vector v1 = {10, 20, 30}; // NOLINT(fuchsia-default-arguments-calls) + + multi::array_ref m1(v1.data(), multi::extensions_t<1>{multi::iextension{3}}); + BOOST_TEST( size(m1) == 3 ); + BOOST_TEST( &m1[1] == &v1[1] ); + BOOST_TEST( num_elements(m1) == 3 ); + + multi::array_ref const m0(v1.data(), {}); + // BOOST_TEST(( &m0 == multi::array_ptr(v1.data(), {}) )); + BOOST_TEST( m0.data_elements() == v1.data() ); + BOOST_TEST( m0.num_elements() == 1 ); + + // m0 = 51; + // BOOST_TEST( v1[0] == 51 ); + + // int const& doub = std::move(m0); + // BOOST_TEST( doub == 51 ); + } + { + // vvv--- TODO(correaa) this might trigger a compiler crash with g++ 7.5 because of operator&() && overloads + multi::static_array a0 = multi::static_array{45.0}; + BOOST_TEST( num_elements(a0) == 1 ); + BOOST_TEST( a0 == 45.0 ); + + a0 = multi::static_array{60.0}; + BOOST_TEST( a0 == 60.0 ); + } + { + std::allocator const alloc; + multi::static_array a0(45.0, alloc); + BOOST_TEST( num_elements(a0) == 1 ); + BOOST_TEST( a0 == 45.0 ); + + a0 = multi::static_array{60.0}; + BOOST_TEST( a0 == 60.0 ); + } } - { - std::allocator const alloc; - multi::static_array a0(45.0, alloc); - BOOST_REQUIRE( num_elements(a0) == 1 ); - BOOST_REQUIRE( a0 == 45.0 ); - - a0 = multi::static_array{60.0}; - BOOST_REQUIRE( a0 == 60.0 ); - } -} -BOOST_AUTO_TEST_CASE(zero_dimensionality_part2) { - { - multi::array, 2> const arr( - #ifdef _MSC_VER // problem with 14.3 c++17 - multi::extensions_t<2> - #endif - {1, 2}, - std::allocator>{} - ); - BOOST_REQUIRE( arr.size() == 1 ); - } - { - double doub = 2.0; - multi::array_ref arr(doub); - double const& the_doub = static_cast(arr); - BOOST_REQUIRE( the_doub == doub ); - BOOST_REQUIRE( &the_doub == &doub ); + BOOST_AUTO_TEST_CASE(zero_dimensionality_part2) { + { + multi::array, 2> const arr( +#ifdef _MSC_VER // problem with 14.3 c++17 + multi::extensions_t<2> +#endif + {1, 2}, + std::allocator>{} + ); + BOOST_TEST( arr.size() == 1 ); + } + { + int doub = 20; + multi::array_ref arr(doub); + int const& the_doub = static_cast(arr); + BOOST_TEST( the_doub == doub ); + BOOST_TEST( &the_doub == &doub ); + } + { + int doub = 20; + auto dd = static_cast(multi::array_ref(&doub, {})); + + BOOST_TEST( dd == doub ); + + multi::array_ptr const ap1(&doub, multi::extensions_t<1>({0, 1})); + BOOST_TEST( (*ap1).base() == &doub ); + BOOST_TEST( ap1->base() == &doub ); + + // multi::array_ptr const ap0(&doub, {}); + + // BOOST_TEST(( ap0 == multi::array_ptr(&doub, {}) )); + // BOOST_TEST(( ap0 != multi::array_ptr(&dd, {}) )); + // // BOOST_TEST( ap0->base() == &doub ); + // // BOOST_TEST( (*ap0).base() == &doub ); + + // multi::array_ptr const ap0dd{&dd}; + // BOOST_TEST( ap0dd != ap0 ); + // BOOST_TEST( *ap0 == *ap0dd ); + // int d3 = 3141592; + // BOOST_TEST(( *multi::array_ptr(&d3, {}) == 3141592 )); + } } - { - double doub = 2.0; - double dd{multi::array_ref(&doub, {})}; - - BOOST_REQUIRE( dd == doub ); - multi::array_ptr const ap1(&doub, multi::extensions_t<1>{{0, 1}}); - BOOST_REQUIRE( ap1->base() == &doub ); - BOOST_REQUIRE( (*ap1).base() == &doub ); - - multi::array_ptr const ap0(&doub, {}); - - BOOST_REQUIRE(( ap0 == multi::array_ptr(&doub, {}) )); - BOOST_REQUIRE(( ap0 != multi::array_ptr(&dd, {}) )); - BOOST_REQUIRE( ap0->base() == &doub ); - BOOST_REQUIRE( (*ap0).base() == &doub ); - - multi::array_ptr const ap0dd{&dd}; - BOOST_REQUIRE( ap0dd != ap0 ); - BOOST_REQUIRE( *ap0 == *ap0dd ); - double d3 = 3.14159265358979323846; - BOOST_REQUIRE(( *multi::array_ptr(&d3, {}) == 3.14159265358979323846 )); - } + return boost::report_errors(); } diff --git a/external_codes/boost_multi/multi/test_adaptors/CMakeLists.txt b/external_codes/boost_multi/multi/test_adaptors/CMakeLists.txt index 835b90f75b..5fee541a0b 100644 --- a/external_codes/boost_multi/multi/test_adaptors/CMakeLists.txt +++ b/external_codes/boost_multi/multi/test_adaptors/CMakeLists.txt @@ -116,7 +116,7 @@ else() add_subdirectory(test) # if(MULTI_BUILD_TESTS) - find_package(Boost 1.65 COMPONENTS unit_test_framework) # 1.65 needed for BOOST_TEST_GLOBAL_FIXTURE, you can use your own Boost and use `cmake -DBOOST_ROOT=$HOME/local` + find_package(Boost 1.65 COMPONENTS) # unit_test_framework) # 1.65 needed for BOOST_TEST_GLOBAL_FIXTURE, you can use your own Boost and use `cmake -DBOOST_ROOT=$HOME/local` if(NOT Boost_FOUND) message(WARNING "Cannot find Boost 1.65+, Multi library will not be fully tested.") else() diff --git a/src/AFQMC/Estimators/BackPropagatedEstimator.hpp b/src/AFQMC/Estimators/BackPropagatedEstimator.hpp index c55f208c2c..96e4df05b5 100644 --- a/src/AFQMC/Estimators/BackPropagatedEstimator.hpp +++ b/src/AFQMC/Estimators/BackPropagatedEstimator.hpp @@ -187,15 +187,16 @@ class BackPropagatedEstimator : public EstimatorBase int ncol(NAEA + ((walker_type == CLOSED) ? 0 : NAEB)); int nx((walker_type == COLLINEAR) ? 2 : 1); + using std::get; // 1. check structures - if (std::get<0>(Refs.sizes()) != wset.size() || std::get<1>(Refs.sizes()) != nrefs || std::get<2>(Refs.sizes()) != nrow * ncol) + if (get<0>(Refs.sizes()) != wset.size() || get<1>(Refs.sizes()) != nrefs || get<2>(Refs.sizes()) != nrow * ncol) Refs = mpi3CTensor({wset.size(), nrefs, nrow * ncol}, Refs.get_allocator()); DeviceBufferManager buffer_manager; StaticMatrix detR({wset.size(), nrefs * nx}, buffer_manager.get_generator().template get_allocator()); int n0, n1; - std::tie(n0, n1) = FairDivideBoundary(TG.getLocalTGRank(), int(std::get<2>(Refs.sizes())), TG.getNCoresPerTG()); + std::tie(n0, n1) = FairDivideBoundary(TG.getLocalTGRank(), int(get<2>(Refs.sizes())), TG.getNCoresPerTG()); boost::multi::array_ref Refs_(to_address(Refs.origin()), Refs.extensions()); // 2. setup back propagated references diff --git a/src/AFQMC/Estimators/EnergyEstimator.h b/src/AFQMC/Estimators/EnergyEstimator.h index 24ba850d05..bef526fc0b 100644 --- a/src/AFQMC/Estimators/EnergyEstimator.h +++ b/src/AFQMC/Estimators/EnergyEstimator.h @@ -59,11 +59,13 @@ class EnergyEstimator : public EstimatorBase { ScopedTimer local_timer(AFQMCTimers[energy_timer]); size_t nwalk = wset.size(); - if (std::get<0>(eloc.sizes()) != nwalk || std::get<1>(eloc.sizes()) != 3) + + using std::get; + if (get<0>(eloc.sizes()) != nwalk || get<1>(eloc.sizes()) != 3) eloc.reextent({static_cast(nwalk), 3}); - if (std::get<0>(ovlp.sizes()) != nwalk) + if (get<0>(ovlp.sizes()) != nwalk) ovlp.reextent(iextensions<1u>(nwalk)); - if (std::get<0>(wprop.sizes()) != 4 || std::get<1>(wprop.sizes()) != nwalk) + if (get<0>(wprop.sizes()) != 4 || get<1>(wprop.sizes()) != nwalk) wprop.reextent({4, static_cast(nwalk)}); ComplexType dum, et; diff --git a/src/AFQMC/Estimators/FullObsHandler.hpp b/src/AFQMC/Estimators/FullObsHandler.hpp index b09d80d005..b47db8b32d 100644 --- a/src/AFQMC/Estimators/FullObsHandler.hpp +++ b/src/AFQMC/Estimators/FullObsHandler.hpp @@ -193,10 +193,12 @@ class FullObsHandler : public AFQMCInfo APP_ABORT("Runtime Error: iav out of range in full1rdm::accumulate. \n\n\n"); int nw(wset.size()); - int nrefs(std::get<1>(Refs.sizes())); + + using std::get; + int nrefs(get<1>(Refs.sizes())); double LogOverlapFactor(wset.getLogOverlapFactor()); LocalTGBufferManager shm_buffer_manager; - StaticSHM4Tensor G4D({nw, nspins, std::get<0>(Gdims), std::get<1>(Gdims)}, + StaticSHM4Tensor G4D({nw, nspins, get<0>(Gdims), get<1>(Gdims)}, shm_buffer_manager.get_generator().template get_allocator()); StaticSHMVector DevOv(iextensions<1u>{2 * nw}, shm_buffer_manager.get_generator().template get_allocator()); diff --git a/src/AFQMC/Estimators/MixedRDMEstimator.h b/src/AFQMC/Estimators/MixedRDMEstimator.h index 5bd42764d9..1074735120 100644 --- a/src/AFQMC/Estimators/MixedRDMEstimator.h +++ b/src/AFQMC/Estimators/MixedRDMEstimator.h @@ -92,9 +92,11 @@ class MixedRDMEstimator : public EstimatorBase wset.getProperty(WEIGHT, wgt); int nx((wset.getWalkerType() == COLLINEAR) ? 2 : 1); - if (std::get<0>(wDMsum.sizes()) != wset.size() || std::get<1>(wDMsum.sizes()) != nx) + + using std::get; + if (get<0>(wDMsum.sizes()) != wset.size() || get<1>(wDMsum.sizes()) != nx) wDMsum.reextent({wset.size(), nx}); - if (std::get<0>(wOvlp.sizes()) != wset.size() || std::get<1>(wOvlp.sizes()) != nx) + if (get<0>(wOvlp.sizes()) != wset.size() || get<1>(wOvlp.sizes()) != nx) wOvlp.reextent({wset.size(), nx}); if (!importanceSampling) @@ -126,8 +128,10 @@ class MixedRDMEstimator : public EstimatorBase denom_average[0] /= block_size; dump.push("Mixed"); std::string padded_iblock = std::string(n_zero - std::to_string(iblock).length(), '0') + std::to_string(iblock); - boost::multi::array_ref wOvlp_(wOvlp.origin(), {std::get<0>(wOvlp.sizes()) * std::get<1>(wOvlp.sizes())}); - boost::multi::array_ref wDMsum_(wDMsum.origin(), {std::get<0>(wDMsum.sizes()) * std::get<1>(wDMsum.sizes())}); + + using std::get; + boost::multi::array_ref wOvlp_(wOvlp.origin(), {get<0>(wOvlp.sizes()) * get<1>(wOvlp.sizes())}); + boost::multi::array_ref wDMsum_(wDMsum.origin(), {get<0>(wDMsum.sizes()) * get<1>(wDMsum.sizes())}); dump.write(DMAverage, "one_rdm_" + padded_iblock); dump.write(denom_average, "one_rdm_denom_" + padded_iblock); dump.write(wOvlp_, "one_rdm_walker_overlaps_" + padded_iblock); diff --git a/src/AFQMC/Estimators/Observables/atomcentered_correlators.hpp b/src/AFQMC/Estimators/Observables/atomcentered_correlators.hpp index 8165f77f35..28986513c0 100644 --- a/src/AFQMC/Estimators/Observables/atomcentered_correlators.hpp +++ b/src/AFQMC/Estimators/Observables/atomcentered_correlators.hpp @@ -253,6 +253,7 @@ class atomcentered_correlators : public AFQMCInfo else nsp = 2; + using std::get; // check structure dimensions if (iref == 0) { @@ -260,19 +261,19 @@ class atomcentered_correlators : public AFQMCInfo { denom = mpi3CVector(iextensions<1u>{nw}, shared_allocator{TG.TG_local()}); } - if (std::get<0>(DMWork1D.sizes()) != nw || std::get<1>(DMWork1D.sizes()) != 3 || std::get<2>(DMWork1D.sizes()) != nsites) + if (get<0>(DMWork1D.sizes()) != nw || get<1>(DMWork1D.sizes()) != 3 || get<2>(DMWork1D.sizes()) != nsites) { DMWork1D = mpi3CTensor({nw, 3, nsites}, shared_allocator{TG.TG_local()}); } - if (std::get<0>(DMWork2D.sizes()) != nw || std::get<1>(DMWork2D.sizes()) != 3 || std::get<2>(DMWork2D.sizes()) != ns2) + if (get<0>(DMWork2D.sizes()) != nw || get<1>(DMWork2D.sizes()) != 3 || get<2>(DMWork2D.sizes()) != ns2) { DMWork2D = mpi3CTensor({nw, 3, ns2}, shared_allocator{TG.TG_local()}); } - if (std::get<0>(NwIJ.sizes()) != nsp || std::get<1>(NwIJ.sizes()) != nw || std::get<2>(NwIJ.sizes()) != nsites || std::get<3>(NwIJ.sizes()) != nsites) + if (get<0>(NwIJ.sizes()) != nsp || get<1>(NwIJ.sizes()) != nw || get<2>(NwIJ.sizes()) != nsites || get<3>(NwIJ.sizes()) != nsites) { NwIJ = mpi3C4Tensor({nsp, nw, nsites, nsites}, shared_allocator{TG.TG_local()}); } - if (std::get<0>(NwI.sizes()) != nsp || std::get<1>(NwI.sizes()) != nw || std::get<2>(NwI.sizes()) != nsites) + if (get<0>(NwI.sizes()) != nsp || get<1>(NwI.sizes()) != nw || get<2>(NwI.sizes()) != nsites) { NwI = mpi3CTensor({nsp, nw, nsites}, shared_allocator{TG.TG_local()}); } @@ -284,12 +285,12 @@ class atomcentered_correlators : public AFQMCInfo } else { - if (std::get<0>(denom.sizes()) != nw || std::get<0>(DMWork1D.sizes()) != nw || std::get<1>(DMWork1D.sizes()) != 3 || std::get<2>(DMWork1D.sizes()) != nsites || - std::get<0>(DMWork2D.sizes()) != nw || std::get<1>(DMWork2D.sizes()) != 3 || std::get<2>(DMWork2D.sizes()) != ns2 || std::get<0>(NwI.sizes()) != nsp || - std::get<1>(NwI.sizes()) != nw || std::get<2>(NwI.sizes()) != nsites || std::get<0>(NwIJ.sizes()) != nsp || std::get<1>(NwIJ.sizes()) != nw || - std::get<2>(NwIJ.sizes()) != nsites || std::get<3>(NwIJ.sizes()) != nsites || std::get<0>(DMAverage1D.sizes()) != nave || std::get<1>(DMAverage1D.sizes()) != 3 || - std::get<2>(DMAverage1D.sizes()) != nsites || std::get<0>(DMAverage2D.sizes()) != nave || std::get<1>(DMAverage2D.sizes()) != 3 || - std::get<2>(DMAverage2D.sizes()) != ns2) + if (get<0>(denom.sizes()) != nw || get<0>(DMWork1D.sizes()) != nw || get<1>(DMWork1D.sizes()) != 3 || get<2>(DMWork1D.sizes()) != nsites || + get<0>(DMWork2D.sizes()) != nw || get<1>(DMWork2D.sizes()) != 3 || get<2>(DMWork2D.sizes()) != ns2 || get<0>(NwI.sizes()) != nsp || + get<1>(NwI.sizes()) != nw || get<2>(NwI.sizes()) != nsites || get<0>(NwIJ.sizes()) != nsp || get<1>(NwIJ.sizes()) != nw || + get<2>(NwIJ.sizes()) != nsites || get<3>(NwIJ.sizes()) != nsites || get<0>(DMAverage1D.sizes()) != nave || get<1>(DMAverage1D.sizes()) != 3 || + get<2>(DMAverage1D.sizes()) != nsites || get<0>(DMAverage2D.sizes()) != nave || get<1>(DMAverage2D.sizes()) != 3 || + get<2>(DMAverage2D.sizes()) != ns2) APP_ABORT(" Error: Invalid state in accumulate_reference. \n\n\n"); } diff --git a/src/AFQMC/Estimators/Observables/diagonal2rdm.hpp b/src/AFQMC/Estimators/Observables/diagonal2rdm.hpp index ab75a4fcda..c7d5002dc7 100644 --- a/src/AFQMC/Estimators/Observables/diagonal2rdm.hpp +++ b/src/AFQMC/Estimators/Observables/diagonal2rdm.hpp @@ -133,6 +133,7 @@ class diagonal2rdm : public AFQMCInfo assert(G.num_elements() == G_host.num_elements()); assert(G.extensions() == G_host.extensions()); + using std::get; // check structure dimensions if (iref == 0) { @@ -140,7 +141,7 @@ class diagonal2rdm : public AFQMCInfo { denom = mpi3CVector(iextensions<1u>{nw}, shared_allocator{TG.TG_local()}); } - if (std::get<0>(DMWork.sizes()) != nw || std::get<1>(DMWork.sizes()) != dm_size) + if (get<0>(DMWork.sizes()) != nw || get<1>(DMWork.sizes()) != dm_size) { DMWork = mpi3CMatrix({nw, dm_size}, shared_allocator{TG.TG_local()}); } @@ -149,8 +150,8 @@ class diagonal2rdm : public AFQMCInfo } else { - if (std::get<0>(denom.sizes()) != nw || std::get<0>(DMWork.sizes()) != nw || std::get<1>(DMWork.sizes()) != dm_size || std::get<0>(DMAverage.sizes()) != nave || - std::get<1>(DMAverage.sizes()) != dm_size) + if (get<0>(denom.sizes()) != nw || get<0>(DMWork.sizes()) != nw || get<1>(DMWork.sizes()) != dm_size || get<0>(DMAverage.sizes()) != nave || + get<1>(DMAverage.sizes()) != dm_size) APP_ABORT(" Error: Invalid state in accumulate_reference. \n\n\n"); } diff --git a/src/AFQMC/Estimators/Observables/full1rdm.hpp b/src/AFQMC/Estimators/Observables/full1rdm.hpp index cf93020cd7..6b5b4aa2d9 100644 --- a/src/AFQMC/Estimators/Observables/full1rdm.hpp +++ b/src/AFQMC/Estimators/Observables/full1rdm.hpp @@ -131,7 +131,8 @@ class full1rdm : public AFQMCInfo stdCMatrix R; if (!dump.readEntry(R, "RotationMatrix")) APP_ABORT("Error reading RotationMatrix.\n"); - if (std::get<1>(R.sizes()) != NMO) + using std::get; + if (get<1>(R.sizes()) != NMO) APP_ABORT("Error Wrong dimensions in RotationMatrix.\n"); dim[0] = R.size(); dim[1] = 0; @@ -143,9 +144,10 @@ class full1rdm : public AFQMCInfo { if (!dump.readEntry(I, "Indices")) APP_ABORT("Error reading Indices.\n"); - if (std::get<1>(I.sizes()) != 2) + using std::get; + if (get<1>(I.sizes()) != 2) APP_ABORT("Error Wrong dimensions in Indices.\n"); - dim[1] = std::get<0>(I.sizes()); + dim[1] = get<0>(I.sizes()); } TG.Node().broadcast_n(dim, 2, 0); XRot = sharedCMatrix({dim[0], NMO}, make_node_allocator(TG)); @@ -244,6 +246,7 @@ class full1rdm : public AFQMCInfo assert(G.num_elements() == G_host.num_elements()); assert(G.extensions() == G_host.extensions()); + using std::get; // check structure dimensions if (iref == 0) { @@ -251,7 +254,7 @@ class full1rdm : public AFQMCInfo { denom = mpi3CVector(iextensions<1u>{nw}, shared_allocator{TG.TG_local()}); } - if (std::get<0>(DMWork.sizes()) != nw || std::get<1>(DMWork.sizes()) != dm_size) + if (get<0>(DMWork.sizes()) != nw || get<1>(DMWork.sizes()) != dm_size) { DMWork = mpi3CMatrix({nw, dm_size}, shared_allocator{TG.TG_local()}); } @@ -260,8 +263,8 @@ class full1rdm : public AFQMCInfo } else { - if (std::get<0>(denom.sizes()) != nw || std::get<0>(DMWork.sizes()) != nw || std::get<1>(DMWork.sizes()) != dm_size || std::get<0>(DMAverage.sizes()) != nave || - std::get<1>(DMAverage.sizes()) != dm_size) + if (get<0>(denom.sizes()) != nw || get<0>(DMWork.sizes()) != nw || get<1>(DMWork.sizes()) != dm_size || get<0>(DMAverage.sizes()) != nave || + get<1>(DMAverage.sizes()) != dm_size) APP_ABORT(" Error: Invalid state in accumulate_reference. \n\n\n"); } @@ -427,9 +430,11 @@ class full1rdm : public AFQMCInfo template void acc_with_rotation(MatG&& G, CVec&& Xw) { + using std::get; + int nw(G.size()); - assert(std::get<2>(G.sizes()) == std::get<3>(G.sizes())); - assert(std::get<2>(G.sizes()) == std::get<1>(XRot.sizes())); + assert(get<2>(G.sizes()) == get<3>(G.sizes())); + assert(get<2>(G.sizes()) == get<1>(XRot.sizes())); if (walker_type == NONCOLLINEAR) APP_ABORT("Error: Not yet implemented: acc_with_rotation && noncollinear.\n"); diff --git a/src/AFQMC/Estimators/Observables/full2rdm.hpp b/src/AFQMC/Estimators/Observables/full2rdm.hpp index 1886966a9e..3836b21927 100644 --- a/src/AFQMC/Estimators/Observables/full2rdm.hpp +++ b/src/AFQMC/Estimators/Observables/full2rdm.hpp @@ -114,6 +114,8 @@ class full2rdm : public AFQMCInfo apply_rotation = true; int dim[2]; + using std::get; + hdf_archive dump; if (TG.Node().root()) { @@ -124,7 +126,7 @@ class full2rdm : public AFQMCInfo stdCMatrix R; if (!dump.readEntry(R, "RotationMatrix")) APP_ABORT("Error reading RotationMatrix.\n"); - if (std::get<1>(R.sizes()) != NMO) + if (get<1>(R.sizes()) != NMO) APP_ABORT("Error Wrong dimensions in RotationMatrix.\n"); dim[0] = R.size(); dim[1] = 0; @@ -196,6 +198,7 @@ class full2rdm : public AFQMCInfo assert(G.num_elements() == G_host.num_elements()); assert(G.extensions() == G_host.extensions()); + using std::get; // check structure dimensions if (iref == 0) { @@ -203,7 +206,7 @@ class full2rdm : public AFQMCInfo { denom = mpi3CVector(iextensions<1u>{nw}, shared_allocator{TG.TG_local()}); } - if (std::get<0>(DMWork.sizes()) != nw || std::get<1>(DMWork.sizes()) != dm_size) + if (get<0>(DMWork.sizes()) != nw || get<1>(DMWork.sizes()) != dm_size) { DMWork = mpi3CMatrix({nw, dm_size}, shared_allocator{TG.TG_local()}); } @@ -212,8 +215,8 @@ class full2rdm : public AFQMCInfo } else { - if (std::get<0>(denom.sizes()) != nw || std::get<0>(DMWork.sizes()) != nw || std::get<1>(DMWork.sizes()) != dm_size || std::get<0>(DMAverage.sizes()) != nave || - std::get<1>(DMAverage.sizes()) != dm_size) + if (get<0>(denom.sizes()) != nw || get<0>(DMWork.sizes()) != nw || get<1>(DMWork.sizes()) != dm_size || get<0>(DMAverage.sizes()) != nave || + get<1>(DMAverage.sizes()) != dm_size) APP_ABORT(" Error: Invalid state in accumulate_reference. \n\n\n"); } diff --git a/src/AFQMC/Estimators/Observables/generalizedFockMatrix.hpp b/src/AFQMC/Estimators/Observables/generalizedFockMatrix.hpp index 26614fc29c..98df7f20d3 100644 --- a/src/AFQMC/Estimators/Observables/generalizedFockMatrix.hpp +++ b/src/AFQMC/Estimators/Observables/generalizedFockMatrix.hpp @@ -133,6 +133,7 @@ class generalizedFockMatrix : public AFQMCInfo assert(G.extensions() == G_host.extensions()); assert(G[0].num_elements() == dm_size); + using std::get; // check structure dimensions if (iref == 0) { @@ -140,7 +141,7 @@ class generalizedFockMatrix : public AFQMCInfo { denom = mpi3CVector(iextensions<1u>{nw}, shared_allocator{TG.TG_local()}); } - if (std::get<0>(DMWork.sizes()) != 3 || std::get<1>(DMWork.sizes()) != nw || std::get<2>(DMWork.sizes()) != dm_size) + if (get<0>(DMWork.sizes()) != 3 || get<1>(DMWork.sizes()) != nw || get<2>(DMWork.sizes()) != dm_size) { DMWork = mpi3CTensor({3, nw, dm_size}, shared_allocator{TG.TG_local()}); } @@ -149,8 +150,8 @@ class generalizedFockMatrix : public AFQMCInfo } else { - if (std::get<0>(denom.sizes()) != nw || std::get<0>(DMWork.sizes()) != 2 || std::get<1>(DMWork.sizes()) != nw || std::get<2>(DMWork.sizes()) != dm_size || - std::get<0>(DMAverage.sizes()) != 2 || std::get<1>(DMAverage.sizes()) != nave || std::get<2>(DMAverage.sizes()) != dm_size) + if (get<0>(denom.sizes()) != nw || get<0>(DMWork.sizes()) != 2 || get<1>(DMWork.sizes()) != nw || get<2>(DMWork.sizes()) != dm_size || + get<0>(DMAverage.sizes()) != 2 || get<1>(DMAverage.sizes()) != nave || get<2>(DMAverage.sizes()) != dm_size) APP_ABORT(" Error: Invalid state in accumulate_reference. \n\n\n"); } diff --git a/src/AFQMC/Estimators/Observables/n2r.hpp b/src/AFQMC/Estimators/Observables/n2r.hpp index 60490231e9..8ee083a44e 100644 --- a/src/AFQMC/Estimators/Observables/n2r.hpp +++ b/src/AFQMC/Estimators/Observables/n2r.hpp @@ -224,6 +224,7 @@ class n2r : public AFQMCInfo else nsp = 2; + using std::get; // check structure dimensions if (iref == 0) { @@ -231,7 +232,7 @@ class n2r : public AFQMCInfo { denom = mpi3CVector(iextensions<1u>{nw}, shared_allocator{TG.TG_local()}); } - if (std::get<0>(DMWork.sizes()) != nw || std::get<1>(DMWork.sizes()) != dm_size) + if (get<0>(DMWork.sizes()) != nw || get<1>(DMWork.sizes()) != dm_size) { DMWork = mpi3CMatrix({nw, dm_size}, shared_allocator{TG.TG_local()}); } @@ -240,8 +241,8 @@ class n2r : public AFQMCInfo } else { - if (std::get<0>(denom.sizes()) != nw || std::get<0>(DMWork.sizes()) != nw || std::get<1>(DMWork.sizes()) != dm_size || std::get<0>(DMAverage.sizes()) != nave || - std::get<1>(DMAverage.sizes()) != dm_size) + if (get<0>(denom.sizes()) != nw || get<0>(DMWork.sizes()) != nw || get<1>(DMWork.sizes()) != dm_size || get<0>(DMAverage.sizes()) != nave || + get<1>(DMAverage.sizes()) != dm_size) APP_ABORT(" Error: Invalid state in accumulate_reference. \n\n\n"); } diff --git a/src/AFQMC/Estimators/Observables/realspace_correlators.hpp b/src/AFQMC/Estimators/Observables/realspace_correlators.hpp index 597fb0e381..011581317c 100644 --- a/src/AFQMC/Estimators/Observables/realspace_correlators.hpp +++ b/src/AFQMC/Estimators/Observables/realspace_correlators.hpp @@ -224,7 +224,9 @@ class realspace_correlators : public AFQMCInfo using std::fill_n; // assumes G[nwalk][spin][M][M] int nw(G.size()); - int npts(std::get<1>(Orbitals.sizes())); + + using std::get; + int npts(get<1>(Orbitals.sizes())); assert(G.size() == wgt.size()); assert(wgt.size() == nw); assert(Xw.size() == nw); @@ -245,11 +247,11 @@ class realspace_correlators : public AFQMCInfo { denom = mpi3CVector(iextensions<1u>{nw}, shared_allocator{TG.TG_local()}); } - if (std::get<0>(DMWork.sizes()) != nw || std::get<1>(DMWork.sizes()) != 3 || std::get<2>(DMWork.sizes()) != dm_size) + if (get<0>(DMWork.sizes()) != nw || get<1>(DMWork.sizes()) != 3 || get<2>(DMWork.sizes()) != dm_size) { DMWork = mpi3CTensor({nw, 3, dm_size}, shared_allocator{TG.TG_local()}); } - if (std::get<0>(Gr_host.sizes()) != nw || std::get<1>(Gr_host.sizes()) != nsp || std::get<2>(Gr_host.sizes()) != npts || std::get<3>(Gr_host.sizes()) != npts) + if (get<0>(Gr_host.sizes()) != nw || get<1>(Gr_host.sizes()) != nsp || get<2>(Gr_host.sizes()) != npts || get<3>(Gr_host.sizes()) != npts) { Gr_host = mpi3C4Tensor({nw, nsp, npts, npts}, shared_allocator{TG.TG_local()}); } @@ -258,9 +260,9 @@ class realspace_correlators : public AFQMCInfo } else { - if (std::get<0>(denom.sizes()) != nw || std::get<0>(DMWork.sizes()) != nw || std::get<1>(DMWork.sizes()) != 3 || std::get<2>(DMWork.sizes()) != dm_size || - std::get<0>(Gr_host.sizes()) != nw || std::get<1>(Gr_host.sizes()) != nsp || std::get<2>(Gr_host.sizes()) != npts || std::get<3>(Gr_host.sizes()) != npts || - std::get<0>(DMAverage.sizes()) != nave || std::get<1>(DMAverage.sizes()) != 3 || std::get<2>(DMAverage.sizes()) != dm_size) + if (get<0>(denom.sizes()) != nw || get<0>(DMWork.sizes()) != nw || get<1>(DMWork.sizes()) != 3 || get<2>(DMWork.sizes()) != dm_size || + get<0>(Gr_host.sizes()) != nw || get<1>(Gr_host.sizes()) != nsp || get<2>(Gr_host.sizes()) != npts || get<3>(Gr_host.sizes()) != npts || + get<0>(DMAverage.sizes()) != nave || get<1>(DMAverage.sizes()) != 3 || get<2>(DMAverage.sizes()) != dm_size) APP_ABORT(" Error: Invalid state in accumulate_reference. \n\n\n"); } @@ -277,7 +279,7 @@ class realspace_correlators : public AFQMCInfo // T1[iw][ispin][i][r] = sum_j G[iw][ispin][i][j] * Psi(j,r) int i0, iN; - std::tie(i0, iN) = FairDivideBoundary(TG.TG_local().rank(), int(std::get<0>(G2D.sizes())), TG.TG_local().size()); + std::tie(i0, iN) = FairDivideBoundary(TG.TG_local().rank(), int(get<0>(G2D.sizes())), TG.TG_local().size()); ma::product(G2D.sliced(i0, iN), Orbitals, T.sliced(i0, iN)); TG.TG_local().barrier(); diff --git a/src/AFQMC/Estimators/tests/test_estimators.cpp b/src/AFQMC/Estimators/tests/test_estimators.cpp index 518096769e..3995e6a0a2 100644 --- a/src/AFQMC/Estimators/tests/test_estimators.cpp +++ b/src/AFQMC/Estimators/tests/test_estimators.cpp @@ -144,9 +144,11 @@ void reduced_density_matrix(boost::mpi3::communicator& world) WalkerSet wset(TG, doc3.getRoot(), InfoMap["info0"], rng); auto initial_guess = WfnFac.getInitialGuess(wfn_name); - REQUIRE(std::get<0>(initial_guess.sizes()) == 2); - REQUIRE(std::get<1>(initial_guess.sizes()) == NMO); - REQUIRE(std::get<2>(initial_guess.sizes()) == NAEA); + + using std::get; + REQUIRE(get<0>(initial_guess.sizes()) == 2); + REQUIRE(get<1>(initial_guess.sizes()) == NMO); + REQUIRE(get<2>(initial_guess.sizes()) == NAEA); wset.resize(nwalk, initial_guess[0], initial_guess[0]); using EstimPtr = std::shared_ptr; std::vector estimators; diff --git a/src/AFQMC/HamiltonianOperations/KP3IndexFactorization.hpp b/src/AFQMC/HamiltonianOperations/KP3IndexFactorization.hpp index f305229e22..9a23a78b49 100644 --- a/src/AFQMC/HamiltonianOperations/KP3IndexFactorization.hpp +++ b/src/AFQMC/HamiltonianOperations/KP3IndexFactorization.hpp @@ -317,11 +317,13 @@ class KP3IndexFactorization bool addEJ = true, bool addEXX = true) { + using std::get; // for C++17 compatibility + int nkpts = nopk.size(); - assert(std::get<1>(E.sizes()) >= 3); + assert(get<1>(E.sizes()) >= 3); assert(nd >= 0 && nd < nelpk.size()); - int nwalk = std::get<1>(Gc.sizes()); + int nwalk = get<1>(Gc.sizes()); int nspin = (walker_type == COLLINEAR ? 2 : 1); int npol = (walker_type == NONCOLLINEAR ? 2 : 1); int nmo_tot = std::accumulate(nopk.begin(), nopk.end(), 0); @@ -334,7 +336,7 @@ class KP3IndexFactorization noccb_tot = std::accumulate(nelpk[nd].begin() + nkpts, nelpk[nd].begin() + 2 * nkpts, 0); int getKr = KEright != nullptr; int getKl = KEleft != nullptr; - if (std::get<0>(E.sizes()) != nwalk || std::get<1>(E.sizes()) < 3) + if (get<0>(E.sizes()) != nwalk || get<1>(E.sizes()) < 3) APP_ABORT( " Error in AFQMC/HamiltonianOperations/KP3IndexFactorization::energy(). Incorrect matrix dimensions \n"); @@ -361,17 +363,18 @@ class KP3IndexFactorization Knr = nwalk; Knc = local_nCV; cnt = 0; + using std::get; // for C++17 compatibility #if defined(MIXED_PRECISION) if (getKr) { - assert(std::get<0>(KEright->sizes()) == nwalk && std::get<1>(KEright->sizes()) == local_nCV); - assert(KEright->stride() == std::get<1>(KEright->sizes())); + assert(get<0>(KEright->sizes()) == nwalk && get<1>(KEright->sizes()) == local_nCV); + assert(KEright->stride() == get<1>(KEright->sizes())); } #else if (getKr) { - assert(std::get<0>(KEright->sizes()) == nwalk && std::get<1>(KEright->sizes()) == local_nCV); - assert(KEright->stride() == std::get<1>(KEright->sizes())); + assert(get<0>(KEright->sizes()) == nwalk && get<1>(KEright->sizes()) == local_nCV); + assert(KEright->stride() == get<1>(KEright->sizes())); Krptr = to_address(KEright->origin()); } else @@ -383,14 +386,14 @@ class KP3IndexFactorization #if defined(MIXED_PRECISION) if (getKl) { - assert(std::get<0>(KEleft->sizes()) == nwalk && std::get<1>(KEleft->sizes()) == local_nCV); - assert(KEleft->stride() == std::get<1>(KEleft->sizes())); + assert(get<0>(KEleft->sizes()) == nwalk && get<1>(KEleft->sizes()) == local_nCV); + assert(KEleft->stride() == get<1>(KEleft->sizes())); } #else if (getKl) { - assert(std::get<0>(KEleft->sizes()) == nwalk && std::get<1>(KEleft->sizes()) == local_nCV); - assert(KEleft->stride() == std::get<1>(KEleft->sizes())); + assert(get<0>(KEleft->sizes()) == nwalk && get<1>(KEleft->sizes()) == local_nCV); + assert(KEleft->stride() == get<1>(KEleft->sizes())); Klptr = to_address(KEleft->origin()); } else @@ -687,11 +690,13 @@ class KP3IndexFactorization APP_ABORT(" Error: Incomplete implementation. \n"); // need to finish modifications for distribution of Q + using std::get; // for C++17 compatibility + int nkpts = nopk.size(); - assert(std::get<1>(E.sizes()) >= 3); + assert(get<1>(E.sizes()) >= 3); assert(nd >= 0 && nd < nelpk.size()); - int nwalk = std::get<1>(Gc.sizes()); + int nwalk = get<1>(Gc.sizes()); int nspin = (walker_type == COLLINEAR ? 2 : 1); int nmo_tot = std::accumulate(nopk.begin(), nopk.end(), 0); int nmo_max = *std::max_element(nopk.begin(), nopk.end()); @@ -703,7 +708,7 @@ class KP3IndexFactorization noccb_tot = std::accumulate(nelpk[nd].begin() + nkpts, nelpk[nd].begin() + 2 * nkpts, 0); int getKr = KEright != nullptr; int getKl = KEleft != nullptr; - if (std::get<0>(E.sizes()) != nwalk || std::get<1>(E.sizes()) < 3) + if (get<0>(E.sizes()) != nwalk || get<1>(E.sizes()) < 3) APP_ABORT(" Error in AFQMC/HamiltonianOperations/KP3IndexFactorization::energy(). Incorrect matrix dimensions\n"); size_t mem_needs(nwalk * nkpts * nkpts * nspin * nocca_max * nmo_max); @@ -732,14 +737,14 @@ class KP3IndexFactorization #if defined(MIXED_PRECISION) if (getKr) { - assert(std::get<0>(KEright->sizes()) == nwalk && std::get<1>(KEright->sizes()) == local_nCV); - assert(KEright->stride() == std::get<1>(KEright->sizes())); + assert(get<0>(KEright->sizes()) == nwalk && get<1>(KEright->sizes()) == local_nCV); + assert(KEright->stride() == get<1>(KEright->sizes())); } #else if (getKr) { - assert(std::get<0>(KEright->sizes()) == nwalk && std::get<1>(KEright->sizes()) == local_nCV); - assert(KEright->stride() == std::get<1>(KEright->sizes())); + assert(get<0>(KEright->sizes()) == nwalk && get<1>(KEright->sizes()) == local_nCV); + assert(KEright->stride() == get<1>(KEright->sizes())); Krptr = to_address(KEright->origin()); } else @@ -751,14 +756,14 @@ class KP3IndexFactorization #if defined(MIXED_PRECISION) if (getKl) { - assert(std::get<0>(KEleft->sizes()) == nwalk && std::get<1>(KEleft->sizes()) == local_nCV); - assert(KEleft->stride() == std::get<1>(KEleft->sizes())); + assert(get<0>(KEleft->sizes()) == nwalk && get<1>(KEleft->sizes()) == local_nCV); + assert(KEleft->stride() == get<1>(KEleft->sizes())); } #else if (getKl) { - assert(std::get<0>(KEleft->sizes()) == nwalk && std::get<1>(KEleft->sizes()) == local_nCV); - assert(KEleft->stride() == std::get<1>(KEleft->sizes())); + assert(get<0>(KEleft->sizes()) == nwalk && get<1>(KEleft->sizes()) == local_nCV); + assert(KEleft->stride() == get<1>(KEleft->sizes())); Klptr = to_address(KEleft->origin()); } else @@ -842,9 +847,11 @@ class KP3IndexFactorization // move calculation of H1 here // NOTE: For CLOSED/NONCOLLINEAR, can do all walkers simultaneously to improve perf. of GEMM // Not sure how to do it for COLLINEAR. + + using std::get; // for C++17 compatibility if (addEXX) { - if (std::get<0>(Qwn.sizes()) != nwalk || std::get<1>(Qwn.sizes()) != nsampleQ) + if (get<0>(Qwn.sizes()) != nwalk || get<1>(Qwn.sizes()) != nsampleQ) Qwn.reextent({nwalk, nsampleQ}); comm->barrier(); if (comm->root()) @@ -1125,8 +1132,9 @@ class KP3IndexFactorization typename = typename std::enable_if_t<(std::decay::type::dimensionality == 2)>> void vHS(MatA& Xw, MatB&& v, double a = 1., double c = 0.) { + using std::get; // for C++17 compatibility int nkpts = nopk.size(); - int nwalk = std::get<1>(Xw.sizes()); + int nwalk = get<1>(Xw.sizes()); assert(v.size() == nwalk); int nspin = (walker_type == COLLINEAR ? 2 : 1); int nmo_tot = std::accumulate(nopk.begin(), nopk.end(), 0); @@ -1326,14 +1334,15 @@ class KP3IndexFactorization typename = typename std::enable_if_t<(std::decay::type::dimensionality == 2)>> void vbias(const MatA& Gw, MatB&& v, double a = 1., double c = 0., int nd = 0) { + using std::get; // for C++17 compatibility using std::copy_n; using GType = typename std::decay_t; using vType = typename std::decay::type::element; int nkpts = nopk.size(); assert(nd >= 0 && nd < nelpk.size()); - int nwalk = std::get<1>(Gw.sizes()); - assert(std::get<0>(v.sizes()) == 2 * local_nCV); - assert(std::get<1>(v.sizes()) == nwalk); + int nwalk = get<1>(Gw.sizes()); + assert(get<0>(v.sizes()) == 2 * local_nCV); + assert(get<1>(v.sizes()) == nwalk); int nspin = (walker_type == COLLINEAR ? 2 : 1); int npol = (walker_type == NONCOLLINEAR ? 2 : 1); int nmo_tot = std::accumulate(nopk.begin(), nopk.end(), 0); @@ -1662,9 +1671,10 @@ class KP3IndexFactorization template void GKaKjw_to_GKKwaj(int nd, MatA const& GKaKj, MatB&& GKKaj, int nocca_tot, int noccb_tot, int nmo_tot, int akmax) { + using std::get; // for C++17 compatibility int nspin = (walker_type == COLLINEAR ? 2 : 1); int npol = (walker_type == NONCOLLINEAR ? 2 : 1); - int nwalk = std::get<1>(GKaKj.sizes()); + int nwalk = get<1>(GKaKj.sizes()); int nkpts = nopk.size(); assert(GKaKj.num_elements() == (nocca_tot + noccb_tot) * npol * nmo_tot * nwalk); assert(GKKaj.num_elements() == nspin * nkpts * nkpts * npol * akmax * nwalk); @@ -1750,8 +1760,9 @@ class KP3IndexFactorization template void GwAK_to_GAKw(MatA const& GwAK, MatB&& GAKw) { - int nwalk = std::get<0>(GwAK.sizes()); - int nAK = std::get<1>(GwAK.sizes()); + using std::get; // for C++17 compatibility + int nwalk = get<0>(GwAK.sizes()); + int nAK = get<1>(GwAK.sizes()); for (int w = 0; w < nwalk; w++) for (int AK = 0; AK < nAK; AK++) GAKw[AK][w] = GwAK[w][AK]; diff --git a/src/AFQMC/HamiltonianOperations/KP3IndexFactorization_batched.hpp b/src/AFQMC/HamiltonianOperations/KP3IndexFactorization_batched.hpp index ce34182343..4f9409519d 100644 --- a/src/AFQMC/HamiltonianOperations/KP3IndexFactorization_batched.hpp +++ b/src/AFQMC/HamiltonianOperations/KP3IndexFactorization_batched.hpp @@ -40,6 +40,8 @@ namespace afqmc // testing the use of dynamic data transfer during execution to reduce memory in GPU // when an approach is found, integrate in original class through additional template parameter +using std::get; // for C++17 compatibility + template class KP3IndexFactorization_batched { @@ -181,10 +183,11 @@ class KP3IndexFactorization_batched dev_Q2vbias(typename IVector::extensions_type{nopk.size()}, IAllocator{allocator_}), dev_Qmap(Qmap), dev_nelpk(nelpk), - dev_a0pk(typename IMatrix::extensions_type{std::get<0>(nelpk.sizes()), std::get<1>(nelpk.sizes())}, IAllocator{allocator_}), + dev_a0pk(typename IMatrix::extensions_type{get<0>(nelpk.sizes()), get<1>(nelpk.sizes())}, IAllocator{allocator_}), dev_QKToK2(QKToK2), EQ(nopk.size() + 2) { + using std::get; using std::copy_n; using std::fill_n; nocc_max = *std::max_element(nelpk.origin(), nelpk.origin() + nelpk.num_elements()); @@ -478,13 +481,15 @@ class KP3IndexFactorization_batched bool addEJ = true, bool addEXX = true) { + using std::get; // for C++17 compatibility + using std::copy_n; using std::fill_n; int nkpts = nopk.size(); - assert(std::get<1>(E.sizes()) >= 3); + assert(get<1>(E.sizes()) >= 3); assert(nd >= 0 && nd < nelpk.size()); - int nwalk = std::get<1>(Gc.sizes()); + int nwalk = get<1>(Gc.sizes()); int nspin = (walker_type == COLLINEAR ? 2 : 1); int npol = (walker_type == NONCOLLINEAR ? 2 : 1); int nmo_tot = std::accumulate(nopk.begin(), nopk.end(), 0); @@ -497,7 +502,7 @@ class KP3IndexFactorization_batched noccb_tot = std::accumulate(nelpk[nd].begin() + nkpts, nelpk[nd].begin() + 2 * nkpts, 0); int getKr = KEright != nullptr; int getKl = KEleft != nullptr; - if (std::get<0>(E.sizes()) != nwalk || std::get<1>(E.sizes()) < 3) + if (get<0>(E.sizes()) != nwalk || get<1>(E.sizes()) < 3) APP_ABORT(" Error in AFQMC/HamiltonianOperations/sparse_matrix_energy::calculate_energy(). Incorrect matrix " "dimensions \n"); @@ -523,13 +528,13 @@ class KP3IndexFactorization_batched Knc = local_nCV; if (getKr) { - assert(std::get<0>(KEright->sizes()) == nwalk && std::get<1>(KEright->sizes()) == local_nCV); - assert(KEright->stride(0) == std::get<1>(KEright->sizes())); + assert(get<0>(KEright->sizes()) == nwalk && get<1>(KEright->sizes()) == local_nCV); + assert(KEright->stride(0) == get<1>(KEright->sizes())); } if (getKl) { - assert(std::get<0>(KEleft->sizes()) == nwalk && std::get<1>(KEleft->sizes()) == local_nCV); - assert(KEleft->stride(0) == std::get<1>(KEleft->sizes())); + assert(get<0>(KEleft->sizes()) == nwalk && get<1>(KEleft->sizes()) == local_nCV); + assert(KEleft->stride(0) == get<1>(KEleft->sizes())); } } else if (getKr or getKl) @@ -938,7 +943,7 @@ class KP3IndexFactorization_batched } } - // move calculation of H1 here + // move calculation of H1 here // NOTE: For CLOSED/NONCOLLINEAR, can do all walkers simultaneously to improve perf. of GEMM // Not sure how to do it for COLLINEAR. if(addEXX) { @@ -1198,8 +1203,9 @@ class KP3IndexFactorization_batched > void vHS(MatA& X, MatB&& v, double a = 1., double c = 0.) { + using std::get; // for C++17 compatibility int nkpts = nopk.size(); - int nwalk = std::get<1>(X.sizes()); + int nwalk = get<1>(X.sizes()); assert(v.size() == nwalk); int nspin = (walker_type == COLLINEAR ? 2 : 1); int nmo_tot = std::accumulate(nopk.begin(), nopk.end(), 0); @@ -1367,13 +1373,14 @@ class KP3IndexFactorization_batched > void vbias(const MatA& G, MatB&& v, double a = 1., double c = 0., int nd = 0) { + using std::get; // for C++17 compatibility using ma::gemmBatched; int nkpts = nopk.size(); assert(nd >= 0 && nd < nelpk.size()); - int nwalk = std::get<1>(G.sizes()); - assert(std::get<0>(v.sizes()) == 2 * local_nCV); - assert(std::get<1>(v.sizes()) == nwalk); + int nwalk = get<1>(G.sizes()); + assert(get<0>(v.sizes()) == 2 * local_nCV); + assert(get<1>(v.sizes()) == nwalk); int nspin = (walker_type == COLLINEAR ? 2 : 1); int npol = (walker_type == NONCOLLINEAR ? 2 : 1); int nmo_tot = std::accumulate(nopk.begin(), nopk.end(), 0); @@ -1583,11 +1590,13 @@ class KP3IndexFactorization_batched template void GKaKjw_to_GKKwaj(MatA const& GKaKj, MatB&& GKKaj, IVec&& nocc, IVec2&& dev_no, IVec2&& dev_a0) { + using std::get; // for C++17 compatibility + int npol = (walker_type == NONCOLLINEAR) ? 2 : 1; int nmo_max = *std::max_element(nopk.begin(), nopk.end()); // int nocc_max = *std::max_element(nocc.begin(),nocc.end()); - int nmo_tot = std::get<1>(GKaKj.sizes()); - int nwalk = std::get<2>(GKaKj.sizes()); + int nmo_tot = get<1>(GKaKj.sizes()); + int nwalk = get<2>(GKaKj.sizes()); int nkpts = nopk.size(); assert(GKKaj.num_elements() >= nkpts * nkpts * nwalk * nocc_max * npol * nmo_max); @@ -1602,8 +1611,10 @@ class KP3IndexFactorization_batched int npol = (walker_type == NONCOLLINEAR) ? 2 : 1; int nmo_max = *std::max_element(nopk.begin(), nopk.end()); // int nocc_max = *std::max_element(nocc.begin(),nocc.end()); - int nmo_tot = std::get<1>(GKaKj.sizes()); - int nwalk = std::get<2>(GKaKj.sizes()); + + using std::get; // for C++17 compatibility + int nmo_tot = get<1>(GKaKj.sizes()); + int nwalk = get<2>(GKaKj.sizes()); int nkpts = nopk.size(); assert(GQKaj.num_elements() >= nkpts * nkpts * nwalk * nocc_max * npol * nmo_max); @@ -1620,9 +1631,11 @@ class KP3IndexFactorization_batched template void vKKwij_to_vwKiKj(MatA const& vKK, MatB&& vKiKj) { + using std::get; + int nmo_max = *std::max_element(nopk.begin(), nopk.end()); - int nwalk = std::get<0>(vKiKj.sizes()); - int nmo_tot = std::get<1>(vKiKj.sizes()); + int nwalk = get<0>(vKiKj.sizes()); + int nmo_tot = get<1>(vKiKj.sizes()); int nkpts = nopk.size(); using ma::vKKwij_to_vwKiKj; @@ -1633,8 +1646,10 @@ class KP3IndexFactorization_batched template void vbias_from_v1(ComplexType a, MatA const& v1, MatB&& vbias) { + using std::get; + using BType = typename std::decay::type::element; - int nwalk = std::get<1>(vbias.sizes()); + int nwalk = get<1>(vbias.sizes()); int nkpts = nopk.size(); int nchol_max = *std::max_element(ncholpQ.begin(), ncholpQ.end()); diff --git a/src/AFQMC/HamiltonianOperations/Real3IndexFactorization.hpp b/src/AFQMC/HamiltonianOperations/Real3IndexFactorization.hpp index 6301de667d..54171bd651 100644 --- a/src/AFQMC/HamiltonianOperations/Real3IndexFactorization.hpp +++ b/src/AFQMC/HamiltonianOperations/Real3IndexFactorization.hpp @@ -116,7 +116,8 @@ class Real3IndexFactorization vn0(std::move(vn0_)), SM_TMats({1, 1}, shared_allocator{TG.TG_local()}) { - local_nCV = std::get<1>(Likn.sizes()); + using std::get; + local_nCV = get<1>(Likn.sizes()); TG.Node().barrier(); } @@ -185,7 +186,8 @@ class Real3IndexFactorization bool addEJ = true, bool addEXX = true) { - assert(std::get<1>(E.sizes()) >= 3); + using std::get; + assert(get<1>(E.sizes()) >= 3); assert(nd >= 0); assert(nd < haj.size()); if (walker_type == COLLINEAR) @@ -199,18 +201,21 @@ class Real3IndexFactorization int nel[2]; nel[0] = Lank[nspin * nd].size(); nel[1] = ((nspin == 2) ? Lank[nspin * nd + 1].size() : 0); - assert(std::get<1>(Lank[nspin * nd].sizes()) == local_nCV); - assert(std::get<2>(Lank[nspin * nd].sizes()) == NMO); + using std::get; + assert(get<1>(Lank[nspin * nd].sizes()) == local_nCV); + assert(get<2>(Lank[nspin * nd].sizes()) == NMO); if (nspin == 2) { - assert(std::get<1>(Lank[nspin * nd + 1].sizes()) == local_nCV); - assert(std::get<2>(Lank[nspin * nd + 1].sizes()) == NMO); + assert(get<1>(Lank[nspin * nd + 1].sizes()) == local_nCV); + assert(get<2>(Lank[nspin * nd + 1].sizes()) == NMO); } assert(Gc.num_elements() == nwalk * (nel[0] + nel[1]) * NMO); int getKr = KEright != nullptr; int getKl = KEleft != nullptr; - if (std::get<0>(E.sizes()) != nwalk || std::get<1>(E.sizes()) < 3) + + using std::get; + if (get<0>(E.sizes()) != nwalk || get<1>(E.sizes()) < 3) APP_ABORT( " Error in AFQMC/HamiltonianOperations/Real3IndexFactorization::energy(...). Incorrect matrix dimensions \n"); @@ -241,26 +246,28 @@ class Real3IndexFactorization // messy SPComplexType* Klptr(nullptr); long Knr = 0, Knc = 0; + + using std::get; if (addEJ) { Knr = nwalk; Knc = local_nCV; if (getKr) { - assert(std::get<0>(KEright->sizes()) == nwalk && std::get<1>(KEright->sizes()) == local_nCV); - assert(KEright->stride(0) == std::get<1>(KEright->sizes())); + assert(get<0>(KEright->sizes()) == nwalk && get<1>(KEright->sizes()) == local_nCV); + assert(KEright->stride(0) == get<1>(KEright->sizes())); } #if defined(MIXED_PRECISION) if (getKl) { - assert(std::get<0>(KEleft->sizes()) == nwalk && std::get<1>(KEleft->sizes()) == local_nCV); - assert(KEleft->stride(0) == std::get<1>(KEleft->sizes())); + assert(get<0>(KEleft->sizes()) == nwalk && get<1>(KEleft->sizes()) == local_nCV); + assert(KEleft->stride(0) == get<1>(KEleft->sizes())); } #else if (getKl) { - assert(std::get<0>(KEleft->sizes()) == nwalk && std::get<1>(KEleft->sizes()) == local_nCV); - assert(KEleft->stride(0) == std::get<1>(KEleft->sizes())); + assert(get<0>(KEleft->sizes()) == nwalk && get<1>(KEleft->sizes()) == local_nCV); + assert(KEleft->stride(0) == get<1>(KEleft->sizes())); Klptr = to_address(KEleft->origin()); } else @@ -423,8 +430,10 @@ class Real3IndexFactorization { using BType = typename std::decay::type::element; using AType = typename std::decay::type::element; - boost::multi::array_ref< BType, 2> v_(to_address(v.origin()), {std::get<0>(v.sizes()), 1}); - boost::multi::array_ref X_(to_address(X.origin()), {std::get<0>(X.sizes()), 1}); + + using std::get; + boost::multi::array_ref< BType, 2> v_(to_address(v.origin()), {get<0>(v.sizes()), 1}); + boost::multi::array_ref X_(to_address(X.origin()), {get<0>(X.sizes()), 1}); return vHS(X_, v_, a, c); } @@ -436,9 +445,11 @@ class Real3IndexFactorization { using XType = typename std::decay_t; using vType = typename std::decay::type::element; - assert(std::get<1>(Likn.sizes()) == std::get<0>(X.sizes())); - assert(std::get<0>(Likn.sizes()) == std::get<0>(v.sizes())); - assert(std::get<1>(X.sizes()) == std::get<1>(v.sizes())); + + using std::get; + assert(get<1>(Likn.sizes()) == get<0>(X.sizes())); + assert(get<0>(Likn.sizes()) == get<0>(v.sizes())); + assert(get<1>(X.sizes()) == get<1>(v.sizes())); long ik0, ikN; std::tie(ik0, ikN) = FairDivideBoundary(long(TG.TG_local().rank()), long(Likn.size()), long(TG.TG_local().size())); // setup buffer space if changing precision in X or v @@ -484,9 +495,10 @@ class Real3IndexFactorization ma::product(SPValueType(a), Likn.sliced(ik0, ikN), Xsp, SPValueType(c), vsp.sliced(ik0, ikN)); + using std::get; if (not std::is_same::value) { - copy_n_cast(to_address(vsp[ik0].origin()), std::get<1>(vsp.sizes()) * (ikN - ik0), to_address(v[ik0].origin())); + copy_n_cast(to_address(vsp[ik0].origin()), get<1>(vsp.sizes()) * (ikN - ik0), to_address(v[ik0].origin())); } TG.TG_local().barrier(); } @@ -498,10 +510,12 @@ class Real3IndexFactorization typename = void> void vbias(const MatA& G, MatB&& v, double a = 1., double c = 0., int k = 0) { + using std::get; + using BType = typename std::decay::type::element; using AType = typename std::decay::type::element; - boost::multi::array_ref v_(to_address(v.origin()), {std::get<0>(v.sizes()), 1}); - boost::multi::array_cref G_(to_address(G.origin()), {std::get<0>(G.sizes()), 1}); + boost::multi::array_ref v_(to_address(v.origin()), {get<0>(v.sizes()), 1}); + boost::multi::array_cref G_(to_address(G.origin()), {get<0>(G.sizes()), 1}); return vbias(G_, v_, a, c, k); } @@ -556,13 +570,14 @@ class Real3IndexFactorization boost::multi::array_ref vsp(vptr, v.extensions()); TG.TG_local().barrier(); + using std::get; if (haj.size() == 1) { - assert(std::get<0>(Lakn.sizes()) == std::get<0>(G.sizes())); - assert(std::get<1>(Lakn.sizes()) == std::get<0>(v.sizes())); - assert(std::get<1>(G.sizes()) == std::get<1>(v.sizes())); + assert(get<0>(Lakn.sizes()) == get<0>(G.sizes())); + assert(get<1>(Lakn.sizes()) == get<0>(v.sizes())); + assert(get<1>(G.sizes()) == get<1>(v.sizes())); std::tie(ic0, icN) = - FairDivideBoundary(long(TG.TG_local().rank()), long(std::get<1>(Lakn.sizes())), long(TG.TG_local().size())); + FairDivideBoundary(long(TG.TG_local().rank()), long(get<1>(Lakn.sizes())), long(TG.TG_local().size())); if (walker_type == CLOSED) a *= 2.0; @@ -572,11 +587,11 @@ class Real3IndexFactorization else { // multideterminant is not half-rotated, so use Likn - assert(std::get<0>(Likn.sizes()) == std::get<0>(G.sizes())); - assert(std::get<1>(Likn.sizes()) == std::get<0>(v.sizes())); - assert(std::get<1>(G.sizes()) == std::get<1>(v.sizes())); + assert(get<0>(Likn.sizes()) == get<0>(G.sizes())); + assert(get<1>(Likn.sizes()) == get<0>(v.sizes())); + assert(get<1>(G.sizes()) == get<1>(v.sizes())); std::tie(ic0, icN) = - FairDivideBoundary(long(TG.TG_local().rank()), long(std::get<1>(Likn.sizes())), long(TG.TG_local().size())); + FairDivideBoundary(long(TG.TG_local().rank()), long(get<1>(Likn.sizes())), long(TG.TG_local().size())); if (walker_type == CLOSED) a *= 2.0; @@ -584,9 +599,10 @@ class Real3IndexFactorization vsp.sliced(ic0, icN)); } // copy data back if changing precision + using std::get; if (not std::is_same::value) { - copy_n_cast(to_address(vsp[ic0].origin()), std::get<1>(vsp.sizes()) * (icN - ic0), to_address(v[ic0].origin())); + copy_n_cast(to_address(vsp[ic0].origin()), get<1>(vsp.sizes()) * (icN - ic0), to_address(v[ic0].origin())); } TG.TG_local().barrier(); } diff --git a/src/AFQMC/HamiltonianOperations/Real3IndexFactorization_batched_v2.hpp b/src/AFQMC/HamiltonianOperations/Real3IndexFactorization_batched_v2.hpp index e2e375bca8..d407a66332 100644 --- a/src/AFQMC/HamiltonianOperations/Real3IndexFactorization_batched_v2.hpp +++ b/src/AFQMC/HamiltonianOperations/Real3IndexFactorization_batched_v2.hpp @@ -123,13 +123,14 @@ class Real3IndexFactorization_batched_v2 Lnak(std::move(move_vector(std::move(vnak)))), vn0(std::move(vn0_)) { - local_nCV = std::get<1>(Likn.sizes()); + using std::get; + local_nCV = get<1>(Likn.sizes()); size_t lnak(0); for (auto& v : Lnak) lnak += v.num_elements(); - for (int i = 0; i < std::get<0>(hij.sizes()); i++) + for (int i = 0; i < get<0>(hij.sizes()); i++) { - for (int j = 0; j < std::get<1>(hij.sizes()); j++) + for (int j = 0; j < get<1>(hij.sizes()); j++) { hij_dev[i][j] = ComplexType(hij[i][j]); } @@ -210,7 +211,8 @@ class Real3IndexFactorization_batched_v2 bool addEJ = true, bool addEXX = true) { - assert(std::get<1>(E.sizes()) >= 3); + using std::get; + assert(get<1>(E.sizes()) >= 3); assert(nd >= 0); assert(nd < haj.size()); if (walker_type == COLLINEAR) @@ -222,20 +224,21 @@ class Real3IndexFactorization_batched_v2 int nspin = (walker_type == COLLINEAR ? 2 : 1); int NMO = hij.size(); int nel[2]; - nel[0] = std::get<1>(Lnak[nspin * nd].sizes()); - nel[1] = ((nspin == 2) ? std::get<1>(Lnak[nspin * nd + 1].sizes()) : 0); - assert(std::get<0>(Lnak[nspin * nd].sizes()) == local_nCV); - assert(std::get<2>(Lnak[nspin * nd].sizes()) == NMO); + + nel[0] = get<1>(Lnak[nspin * nd].sizes()); + nel[1] = ((nspin == 2) ? get<1>(Lnak[nspin * nd + 1].sizes()) : 0); + assert(get<0>(Lnak[nspin * nd].sizes()) == local_nCV); + assert(get<2>(Lnak[nspin * nd].sizes()) == NMO); if (nspin == 2) { - assert(std::get<0>(Lnak[nspin * nd + 1].sizes()) == local_nCV); - assert(std::get<2>(Lnak[nspin * nd + 1].sizes()) == NMO); + assert(get<0>(Lnak[nspin * nd + 1].sizes()) == local_nCV); + assert(get<2>(Lnak[nspin * nd + 1].sizes()) == NMO); } assert(Gc.num_elements() == nwalk * (nel[0] + nel[1]) * NMO); int getKr = KEright != nullptr; int getKl = KEleft != nullptr; - if (std::get<0>(E.sizes()) != nwalk || std::get<1>(E.sizes()) < 3) + if (get<0>(E.sizes()) != nwalk || get<1>(E.sizes()) < 3) APP_ABORT(" Error in AFQMC/HamiltonianOperations/Real3IndexFactorization_batched_v2::energy(...). Incorrect " "matrix dimensions \n"); @@ -255,13 +258,13 @@ class Real3IndexFactorization_batched_v2 Knc = local_nCV; if (getKr) { - assert(std::get<0>(KEright->sizes()) == nwalk && std::get<1>(KEright->sizes()) == local_nCV); - assert(KEright->stride(0) == std::get<1>(KEright->sizes())); + assert(get<0>(KEright->sizes()) == nwalk && get<1>(KEright->sizes()) == local_nCV); + assert(KEright->stride(0) == get<1>(KEright->sizes())); } if (getKl) { - assert(std::get<0>(KEleft->sizes()) == nwalk && std::get<1>(KEleft->sizes()) == local_nCV); - assert(KEleft->stride(0) == std::get<1>(KEleft->sizes())); + assert(get<0>(KEleft->sizes()) == nwalk && get<1>(KEleft->sizes()) == local_nCV); + assert(KEleft->stride(0) == get<1>(KEleft->sizes())); } } else if (getKr or getKl) @@ -387,8 +390,10 @@ class Real3IndexFactorization_batched_v2 { using BType = typename std::decay::type::element; using AType = typename std::decay::type::element; - boost::multi::array_ref v_(v.origin(), {std::get<0>(v.sizes()), 1}); - boost::multi::array_ref X_(X.origin(), {std::get<0>(X.sizes()), 1}); + + using std::get; + boost::multi::array_ref v_(v.origin(), {get<0>(v.sizes()), 1}); + boost::multi::array_ref X_(X.origin(), {get<0>(X.sizes()), 1}); return vHS(X_, v_, a, c); } @@ -400,9 +405,11 @@ class Real3IndexFactorization_batched_v2 { using XType = typename std::decay_t; using vType = typename std::decay::type::element; - assert(std::get<1>(Likn.sizes()) == std::get<0>(X.sizes())); - assert(std::get<0>(Likn.sizes()) == std::get<0>(v.sizes())); - assert(std::get<1>(X.sizes()) == std::get<1>(v.sizes())); + + using std::get; + assert(get<1>(Likn.sizes()) == get<0>(X.sizes())); + assert(get<0>(Likn.sizes()) == get<0>(v.sizes())); + assert(get<1>(X.sizes()) == get<1>(v.sizes())); // setup buffer space if changing precision in X or v size_t vmem(0), Xmem(0); if (not std::is_same::value) @@ -506,25 +513,27 @@ class Real3IndexFactorization_batched_v2 boost::multi::array_cref Gsp(Gptr, G.extensions()); boost::multi::array_ref vsp(vptr, v.extensions()); + using std::get; + if (haj.size() == 1) { - int nwalk = std::get<1>(v.sizes()); + int nwalk = get<1>(v.sizes()); if (walker_type == COLLINEAR) { - assert(std::get<1>(G.sizes()) == std::get<1>(v.sizes())); + assert(get<1>(G.sizes()) == get<1>(v.sizes())); int NMO, nel[2]; - NMO = std::get<2>(Lnak[0].sizes()); - nel[0] = std::get<1>(Lnak[0].sizes()); - nel[1] = std::get<1>(Lnak[1].sizes()); + NMO = get<2>(Lnak[0].sizes()); + nel[0] = get<1>(Lnak[0].sizes()); + nel[1] = get<1>(Lnak[1].sizes()); double c_[2]; c_[0] = c; c_[1] = c; if (std::abs(c) < 1e-8) c_[1] = 1.0; - assert((nel[0]+nel[1])*NMO == std::get<0>(G.sizes())); + assert((nel[0]+nel[1])*NMO == get<0>(G.sizes())); for (int ispin = 0, is0 = 0; ispin < 2; ispin++) { - assert(std::get<0>(Lnak[ispin].sizes()) == std::get<0>(v.sizes())); + assert(get<0>(Lnak[ispin].sizes()) == get<0>(v.sizes())); SpCMatrix_ref Ln(make_device_ptr(Lnak[ispin].origin()), {local_nCV, nel[ispin] * NMO}); ma::product(SPComplexType(a), Ln, Gsp.sliced(is0, is0 + nel[ispin] * NMO), SPComplexType(c_[ispin]), vsp); is0 += nel[ispin] * NMO; @@ -532,19 +541,19 @@ class Real3IndexFactorization_batched_v2 } else { - assert(std::get<1>(G.sizes()) == std::get<1>(v.sizes())); - assert(std::get<1>(Lnak[0].sizes()) * std::get<2>(Lnak[0].sizes()) == std::get<0>(G.sizes())); - assert(std::get<0>(Lnak[0].sizes()) == std::get<0>(v.sizes())); - SpCMatrix_ref Ln(make_device_ptr(Lnak[0].origin()), {local_nCV, std::get<1>(Lnak[0].sizes()) * std::get<2>(Lnak[0].sizes())}); + assert(get<1>(G.sizes()) == get<1>(v.sizes())); + assert(get<1>(Lnak[0].sizes()) * get<2>(Lnak[0].sizes()) == get<0>(G.sizes())); + assert(get<0>(Lnak[0].sizes()) == get<0>(v.sizes())); + SpCMatrix_ref Ln(make_device_ptr(Lnak[0].origin()), {local_nCV, get<1>(Lnak[0].sizes()) * get<2>(Lnak[0].sizes())}); ma::product(SPComplexType(a), Ln, Gsp, SPComplexType(c), vsp); } } else { // multideterminant is not half-rotated, so use Likn - assert(std::get<0>(Likn.sizes()) == std::get<0>(G.sizes())); - assert(std::get<1>(Likn.sizes()) == std::get<0>(v.sizes())); - assert(std::get<1>(G.sizes()) == std::get<1>(v.sizes())); + assert(get<0>(Likn.sizes()) == get<0>(G.sizes())); + assert(get<1>(Likn.sizes()) == get<0>(v.sizes())); + assert(get<1>(G.sizes()) == get<1>(v.sizes())); ma::product(SPValueType(a), ma::T(Likn), Gsp, SPValueType(c), vsp); } diff --git a/src/AFQMC/HamiltonianOperations/SparseTensor.hpp b/src/AFQMC/HamiltonianOperations/SparseTensor.hpp index 6dee540a10..58a02350f8 100644 --- a/src/AFQMC/HamiltonianOperations/SparseTensor.hpp +++ b/src/AFQMC/HamiltonianOperations/SparseTensor.hpp @@ -188,25 +188,27 @@ class SparseTensor bool addEJ = true, bool addEXX = true) { - assert(std::get<1>(E.sizes()) >= 3); + using std::get; + assert(get<1>(E.sizes()) >= 3); assert(k >= 0 && k < haj.size()); assert(k >= 0 && k < Vakbl_view.size()); - if (Gcloc.num_elements() < std::get<1>(Gc.sizes()) * std::get<0>(Vakbl_view[k].sizes())) - Gcloc.reextent(iextensions<1u>(std::get<0>(Vakbl_view[k].sizes()) * std::get<1>(Gc.sizes()))); - boost::multi::array_ref buff(Gcloc.data(), {long(std::get<0>(Vakbl_view[k].sizes())), long(std::get<1>(Gc.sizes()))}); + using std::get; + if (Gcloc.num_elements() < get<1>(Gc.sizes()) * get<0>(Vakbl_view[k].sizes())) + Gcloc.reextent(iextensions<1u>(get<0>(Vakbl_view[k].sizes()) * get<1>(Gc.sizes()))); + boost::multi::array_ref buff(Gcloc.data(), {long(get<0>(Vakbl_view[k].sizes())), long(get<1>(Gc.sizes()))}); - int nwalk = std::get<1>(Gc.sizes()); + int nwalk = get<1>(Gc.sizes()); int getKr = Kr != nullptr; int getKl = Kl != nullptr; - if (std::get<0>(E.sizes()) != nwalk || std::get<1>(E.sizes()) < 3) + if (get<0>(E.sizes()) != nwalk || get<1>(E.sizes()) < 3) APP_ABORT(" Error in AFQMC/HamiltonianOperations/sparse_matrix_energy::calculate_energy(). Incorrect matrix " "dimensions \n"); for (int n = 0; n < nwalk; n++) std::fill_n(E[n].origin(), 3, ComplexType(0.)); if (addEJ and getKl) - assert(std::get<0>(Kl->sizes()) == nwalk && std::get<1>(Kl->sizes()) == std::get<0>(SpvnT[k].sizes())); + assert(get<0>(Kl->sizes()) == nwalk && get<1>(Kl->sizes()) == get<0>(SpvnT[k].sizes())); if (addEJ and getKr) - assert(std::get<0>(Kr->sizes()) == nwalk && std::get<1>(Kr->sizes()) == std::get<0>(SpvnT[k].sizes())); + assert(get<0>(Kr->sizes()) == nwalk && get<1>(Kr->sizes()) == get<0>(SpvnT[k].sizes())); #if defined(MIXED_PRECISION) size_t mem_needs = Gc.num_elements(); @@ -236,20 +238,23 @@ class SparseTensor shm::calculate_energy(std::forward(E), Gsp, buff, Vakbl_view[k]); } + using std::get; if (separateEJ && addEJ) { using ma::T; - if (Gcloc.num_elements() < std::get<0>(SpvnT[k].sizes()) * std::get<1>(Gc.sizes())) - Gcloc.reextent(iextensions<1u>(std::get<0>(SpvnT[k].sizes()) * std::get<1>(Gc.sizes()))); - assert(std::get<1>(SpvnT_view[k].sizes()) == std::get<0>(Gc.sizes())); + if (Gcloc.num_elements() < get<0>(SpvnT[k].sizes()) * get<1>(Gc.sizes())) + Gcloc.reextent(iextensions<1u>(get<0>(SpvnT[k].sizes()) * get<1>(Gc.sizes()))); + assert(get<1>(SpvnT_view[k].sizes()) == get<0>(Gc.sizes())); RealType scl = (walker_type == CLOSED ? 4.0 : 1.0); + + using std::get; // SpvnT*G - boost::multi::array_ref v_(Gcloc.origin() + SpvnT_view[k].local_origin()[0] * std::get<1>(Gc.sizes()), - {long(std::get<0>(SpvnT_view[k].sizes())), long(std::get<1>(Gc.sizes()))}); + boost::multi::array_ref v_(Gcloc.origin() + SpvnT_view[k].local_origin()[0] * get<1>(Gc.sizes()), + {long(get<0>(SpvnT_view[k].sizes())), long(get<1>(Gc.sizes()))}); ma::product(SpvnT_view[k], Gsp, v_); if (getKl || getKr) { - for (int wi = 0; wi < std::get<1>(Gc.sizes()); wi++) + for (int wi = 0; wi < get<1>(Gc.sizes()); wi++) { auto _v_ = v_(v_.extension(0), wi); if (getKl) @@ -266,7 +271,7 @@ class SparseTensor } } } - for (int wi = 0; wi < std::get<1>(Gc.sizes()); wi++) + for (int wi = 0; wi < get<1>(Gc.sizes()); wi++) E[wi][2] = 0.5 * scl * static_cast(ma::dot(v_(v_.extension(0), wi), v_(v_.extension(0), wi))); } #if defined(MIXED_PRECISION) @@ -301,9 +306,11 @@ class SparseTensor { using vType = typename std::decay::type::element; using XType = typename std::decay_t; - assert(std::get<1>(Spvn.sizes()) == std::get<0>(X.sizes())); - assert(std::get<0>(Spvn.sizes()) == std::get<0>(v.sizes())); - assert(std::get<1>(X.sizes()) == std::get<1>(v.sizes())); + + using std::get; + assert(get<1>(Spvn.sizes()) == get<0>(X.sizes())); + assert(get<0>(Spvn.sizes()) == get<0>(v.sizes())); + assert(get<1>(X.sizes()) == get<1>(v.sizes())); // setup buffer space if changing precision in X or v size_t vmem(0), Xmem(0); @@ -344,8 +351,9 @@ class SparseTensor boost::multi::array_ref vsp(vptr, v.extensions()); comm->barrier(); + using std::get; boost::multi::array_ref v_(to_address(vsp[Spvn_view.local_origin()[0]].origin()), - {long(std::get<0>(Spvn_view.sizes())), long(std::get<1>(vsp.sizes()))}); + {long(get<0>(Spvn_view.sizes())), long(get<1>(vsp.sizes()))}); ma::product(SPValueType(a), Spvn_view, Xsp, SPValueType(c), v_); // copy data back if changing precision @@ -363,10 +371,12 @@ class SparseTensor typename = void> void vbias(const MatA& G, MatB&& v, double a = 1., double c = 0., int k = 0) { + using std::get; + using BType = typename std::decay::type::element; using AType = typename std::decay::type::element; - boost::multi::array_ref v_(v.origin(), {std::get<0>(v.sizes()), 1}); - boost::multi::array_cref G_(G.origin(), {std::get<0>(G.sizes()), 1}); + boost::multi::array_ref v_(v.origin(), {get<0>(v.sizes()), 1}); + boost::multi::array_cref G_(G.origin(), {get<0>(G.sizes()), 1}); return vbias(G_, v_, a, c, k); } @@ -382,9 +392,11 @@ class SparseTensor k = 0; if (walker_type == CLOSED) a *= 2.0; - assert(std::get<1>(SpvnT[k].sizes()) == std::get<0>(G.sizes())); - assert(std::get<0>(SpvnT[k].sizes()) == std::get<0>(v.sizes())); - assert(std::get<1>(G.sizes()) == std::get<1>(v.sizes())); + + using std::get; + assert(get<1>(SpvnT[k].sizes()) == get<0>(G.sizes())); + assert(get<0>(SpvnT[k].sizes()) == get<0>(v.sizes())); + assert(get<1>(G.sizes()) == get<1>(v.sizes())); // setup buffer space if changing precision in G or v size_t vmem(0), Gmem(0); @@ -424,8 +436,10 @@ class SparseTensor boost::multi::array_cref Gsp(Gptr, G.extensions()); boost::multi::array_ref vsp(vptr, v.extensions()); comm->barrier(); + + using std::get; boost::multi::array_ref v_(to_address(vsp[SpvnT_view[k].local_origin()[0]].origin()), - {long(std::get<0>(SpvnT_view[k].sizes())), long(std::get<1>(vsp.sizes()))}); + {long(get<0>(SpvnT_view[k].sizes())), long(get<1>(vsp.sizes()))}); ma::product(SpT2(a), SpvnT_view[k], Gsp, SpT2(c), v_); // copy data back if changing precision diff --git a/src/AFQMC/HamiltonianOperations/THCOps.hpp b/src/AFQMC/HamiltonianOperations/THCOps.hpp index 631937eda5..ee9fb78160 100644 --- a/src/AFQMC/HamiltonianOperations/THCOps.hpp +++ b/src/AFQMC/HamiltonianOperations/THCOps.hpp @@ -133,33 +133,36 @@ class THCOps vn0(std::move(v0_)), E0(e0_) { - gnmu = std::get<1>(Luv.sizes()); - grotnmu = std::get<1>(rotMuv.sizes()); + using std::get; + gnmu = get<1>(Luv.sizes()); + grotnmu = get<1>(rotMuv.sizes()); if (haj.size() > 1) APP_ABORT(" Error: THC not yet implemented for multiple references.\n"); assert(comm); // current partition over 'u' for L/Piu - assert(Luv.size() == std::get<1>(Piu.sizes())); + assert(Luv.size() == get<1>(Piu.sizes())); + + using std::get; for (int i = 0; i < rotcPua.size(); i++) { // rot Ps are not yet distributed - assert(rotcPua[i].size() == std::get<1>(rotPiu.sizes())); + assert(rotcPua[i].size() == get<1>(rotPiu.sizes())); if (walker_type == CLOSED) - assert(std::get<1>(rotcPua[i].sizes()) == nup); + assert(get<1>(rotcPua[i].sizes()) == nup); else if (walker_type == COLLINEAR) - assert(std::get<1>(rotcPua[i].sizes()) == nup + ndown); + assert(get<1>(rotcPua[i].sizes()) == nup + ndown); else if (walker_type == NONCOLLINEAR) - assert(std::get<1>(rotcPua[i].sizes()) == nup + ndown); + assert(get<1>(rotcPua[i].sizes()) == nup + ndown); } for (int i = 0; i < cPua.size(); i++) { assert(cPua[i].size() == Luv.size()); if (walker_type == CLOSED) - assert(std::get<1>(cPua[i].sizes()) == nup); + assert(get<1>(cPua[i].sizes()) == nup); else if (walker_type == COLLINEAR) - assert(std::get<1>(cPua[i].sizes()) == nup + ndown); + assert(get<1>(cPua[i].sizes()) == nup + ndown); else if (walker_type == NONCOLLINEAR) - assert(std::get<1>(cPua[i].sizes()) == nup + ndown); + assert(get<1>(cPua[i].sizes()) == nup + ndown); } if (walker_type == NONCOLLINEAR) { @@ -257,8 +260,10 @@ class THCOps if (k > 0) APP_ABORT(" Error: THC not yet implemented for multiple references.\n"); // G[nel][nmo] - assert(std::get<0>(E.sizes()) == std::get<0>(G.sizes())); - assert(std::get<1>(E.sizes()) == 3); + + using std::get; + assert(get<0>(E.sizes()) == get<0>(G.sizes())); + assert(get<1>(E.sizes()) == 3); int nwalk = G.size(); int getKr = Kr != nullptr; int getKl = Kl != nullptr; @@ -274,17 +279,19 @@ class THCOps if (not(addEJ || addEXX)) return; + using std::get; + int nmo_ = rotPiu.size(); int nu = rotMuv.size(); int nu0 = rotnmu0; - int nv = std::get<1>(rotMuv.sizes()); - int nel_ = std::get<1>(rotcPua[0].sizes()); + int nv = get<1>(rotMuv.sizes()); + int nel_ = get<1>(rotcPua[0].sizes()); int nspin = (walker_type == COLLINEAR) ? 2 : 1; - assert(std::get<1>(G.sizes()) == nel_ * nmo_); + assert(get<1>(G.sizes()) == nel_ * nmo_); if (addEJ and getKl) - assert(std::get<0>(Kl->sizes()) == nwalk && std::get<1>(Kl->sizes()) == nu); + assert(get<0>(Kl->sizes()) == nwalk && get<1>(Kl->sizes()) == nu); if (addEJ and getKr) - assert(std::get<0>(Kr->sizes()) == nwalk && std::get<1>(Kr->sizes()) == nu); + assert(get<0>(Kr->sizes()) == nwalk && get<1>(Kr->sizes()) == nu); using ma::T; int u0, uN; std::tie(u0, uN) = FairDivideBoundary(comm->rank(), nu, comm->size()); @@ -681,18 +688,20 @@ class THCOps using ma::T; using XType = typename std::decay_t; using vType = typename std::decay::type::element; - int nwalk = std::get<1>(X.sizes()); + + using std::get; + int nwalk = get<1>(X.sizes()); #if defined(QMC_COMPLEX) - int nchol = 2 * std::get<1>(Luv.sizes()); + int nchol = 2 * get<1>(Luv.sizes()); #else - int nchol = std::get<1>(Luv.sizes()); + int nchol = get<1>(Luv.sizes()); #endif - int nmo_ = std::get<0>(Piu.sizes()); - int nu = std::get<1>(Piu.sizes()); - assert(std::get<0>(Luv.sizes()) == nu); - assert(std::get<0>(X.sizes()) == nchol); - assert(std::get<0>(v.sizes()) == nwalk); - assert(std::get<1>(v.sizes()) == nmo_ * nmo_); + int nmo_ = get<0>(Piu.sizes()); + int nu = get<1>(Piu.sizes()); + assert(get<0>(Luv.sizes()) == nu); + assert(get<0>(X.sizes()) == nchol); + assert(get<0>(v.sizes()) == nwalk); + assert(get<1>(v.sizes()) == nmo_ * nmo_); size_t memory_needs = nu * nwalk; if (not std::is_same::value) @@ -748,11 +757,13 @@ class THCOps std::tie(u0, uN) = FairDivideBoundary(comm->rank(), nu, comm->size()); Array_ref Tuw(make_device_ptr(SM_TMats.origin()) + cnt, {nu, nwalk}); // O[nwalk * nmu * nmu] + + using std::get; #if defined(QMC_COMPLEX) // reinterpret as RealType matrices with 2x the columns Array_ref Luv_R(pointer_cast(make_device_ptr(Luv.origin())), - {std::get<0>(Luv.sizes()), 2 * std::get<1>(Luv.sizes())}); - Array_cref X_R(pointer_cast(Xsp.origin()), {std::get<0>(Xsp.sizes()), 2 * std::get<1>(Xsp.sizes())}); + {get<0>(Luv.sizes()), 2 * get<1>(Luv.sizes())}); + Array_cref X_R(pointer_cast(Xsp.origin()), {get<0>(Xsp.sizes()), 2 * get<1>(Xsp.sizes())}); Array_ref Tuw_R(pointer_cast(Tuw.origin()), {nu, 2 * nwalk}); ma::product(Luv_R.sliced(u0, uN), X_R, Tuw_R.sliced(u0, uN)); #else @@ -822,10 +833,11 @@ class THCOps typename = void> void vbias(MatA const& G, MatB&& v, double a = 1., double c = 0., int k = 0) { + using std::get; using GType = typename std::decay_t; using vType = typename std::decay::type::element; - boost::multi::array_ref v_(v.origin(), {std::get<0>(v.sizes()), 1}); - boost::multi::array_ref G_(G.origin(), {1, std::get<0>(G.sizes())}); + boost::multi::array_ref v_(v.origin(), {get<0>(v.sizes()), 1}); + boost::multi::array_ref G_(G.origin(), {1, get<0>(G.sizes())}); vbias(G_, v_, a, c, k); } @@ -839,17 +851,19 @@ class THCOps using vType = typename std::decay::type::element; if (k > 0) APP_ABORT(" Error: THC not yet implemented for multiple references.\n"); - int nwalk = std::get<0>(G.sizes()); - int nmo_ = std::get<0>(Piu.sizes()); - int nu = std::get<1>(Piu.sizes()); - int nel_ = std::get<1>(cPua[0].sizes()); + + using std::get; + int nwalk = get<0>(G.sizes()); + int nmo_ = get<0>(Piu.sizes()); + int nu = get<1>(Piu.sizes()); + int nel_ = get<1>(cPua[0].sizes()); #if defined(QMC_COMPLEX) - int nchol = 2 * std::get<1>(Luv.sizes()); + int nchol = 2 * get<1>(Luv.sizes()); #else - int nchol = std::get<1>(Luv.sizes()); + int nchol = get<1>(Luv.sizes()); #endif - assert(std::get<1>(v.sizes()) == nwalk); - assert(std::get<0>(v.sizes()) == nchol); + assert(get<1>(v.sizes()) == nwalk); + assert(get<0>(v.sizes()) == nchol); using ma::T; int c0, cN; std::tie(c0, cN) = FairDivideBoundary(comm->rank(), nchol, comm->size()); @@ -895,6 +909,7 @@ class THCOps Array_cref Gsp(Gptr, G.extensions()); Array_ref vsp(vptr, v.extensions()); + using std::get; if (haj.size() == 1) { Array_ref Guu(make_device_ptr(SM_TMats.origin()) + cnt, {nu, nwalk}); @@ -902,9 +917,9 @@ class THCOps #if defined(QMC_COMPLEX) // reinterpret as RealType matrices with 2x the columns Array_ref Luv_R(pointer_cast(make_device_ptr(Luv.origin())), - {std::get<0>(Luv.sizes()), 2 * std::get<1>(Luv.sizes())}); + {get<0>(Luv.sizes()), 2 * get<1>(Luv.sizes())}); Array_ref Guu_R(pointer_cast(Guu.origin()), {nu, 2 * nwalk}); - Array_ref vsp_R(pointer_cast(vsp.origin()), {std::get<0>(vsp.sizes()), 2 * std::get<1>(vsp.sizes())}); + Array_ref vsp_R(pointer_cast(vsp.origin()), {get<0>(vsp.sizes()), 2 * get<1>(vsp.sizes())}); ma::product(SPRealType(a), T(Luv_R(Luv_R.extension(0), {c0, cN})), Guu_R, SPRealType(c), vsp_R.sliced(c0, cN)); #else ma::product(SPRealType(a), T(Luv(Luv.extension(0), {c0, cN})), Guu, SPRealType(c), vsp.sliced(c0, cN)); @@ -917,9 +932,9 @@ class THCOps #if defined(QMC_COMPLEX) // reinterpret as RealType matrices with 2x the columns Array_ref Luv_R(pointer_cast(make_device_ptr(Luv.origin())), - {std::get<0>(Luv.sizes()), 2 * std::get<1>(Luv.sizes())}); + {get<0>(Luv.sizes()), 2 * get<1>(Luv.sizes())}); Array_ref Guu_R(pointer_cast(Guu.origin()), {nu, 2 * nwalk}); - Array_ref vsp_R(pointer_cast(vsp.origin()), {std::get<0>(vsp.sizes()), 2 * std::get<1>(vsp.sizes())}); + Array_ref vsp_R(pointer_cast(vsp.origin()), {get<0>(vsp.sizes()), 2 * get<1>(vsp.sizes())}); ma::product(SPRealType(a), T(Luv_R(Luv_R.extension(0), {c0, cN})), Guu_R, SPRealType(c), vsp_R.sliced(c0, cN)); #else ma::product(SPRealType(a), T(Luv(Luv.extension(0), {c0, cN})), Guu, SPRealType(c), vsp.sliced(c0, cN)); @@ -927,7 +942,7 @@ class THCOps } if (not std::is_same::value) { - copy_n_cast(make_device_ptr(vsp[c0].origin()), std::get<1>(vsp.sizes()) * (cN - c0), make_device_ptr(v[c0].origin())); + copy_n_cast(make_device_ptr(vsp[c0].origin()), get<1>(vsp.sizes()) * (cN - c0), make_device_ptr(v[c0].origin())); } comm->barrier(); } @@ -939,13 +954,13 @@ class THCOps } bool distribution_over_cholesky_vectors() const { return false; } - int number_of_ke_vectors() const { return std::get<0>(rotMuv.sizes()); } + int number_of_ke_vectors() const { using std::get; return get<0>(rotMuv.sizes()); } #if defined(QMC_COMPLEX) - int local_number_of_cholesky_vectors() const { return 2 * std::get<1>(Luv.sizes()); } - int global_number_of_cholesky_vectors() const { return 2 * std::get<1>(Luv.sizes()); } + int local_number_of_cholesky_vectors() const { using std::get; return 2 * get<1>(Luv.sizes()); } + int global_number_of_cholesky_vectors() const { using std::get; return 2 * get<1>(Luv.sizes()); } #else - int local_number_of_cholesky_vectors() const { return std::get<1>(Luv.sizes()); } - int global_number_of_cholesky_vectors() const { return std::get<1>(Luv.sizes()); } + int local_number_of_cholesky_vectors() const { using std::get; return get<1>(Luv.sizes()); } + int global_number_of_cholesky_vectors() const { using std::get; return get<1>(Luv.sizes()); } #endif int global_origin_cholesky_vector() const { return 0; } @@ -964,16 +979,17 @@ class THCOps template void Guu_from_compact(MatA const& G, MatB&& Guu) { - int nmo_ = int(std::get<0>(Piu.sizes())); - int nu = int(std::get<1>(Piu.sizes())); - int nel_ = std::get<1>(cPua[0].sizes()); + using std::get; + int nmo_ = int(get<0>(Piu.sizes())); + int nu = int(get<1>(Piu.sizes())); + int nel_ = get<1>(cPua[0].sizes()); int u0, uN; std::tie(u0, uN) = FairDivideBoundary(comm->rank(), nu, comm->size()); - int nw = std::get<0>(G.sizes()); + int nw = get<0>(G.sizes()); - assert(std::get<0>(G.sizes()) == std::get<1>(Guu.sizes())); - assert(std::get<1>(G.sizes()) == nel_ * nmo_); - assert(std::get<0>(Guu.sizes()) == nu); + assert(get<0>(G.sizes()) == get<1>(Guu.sizes())); + assert(get<1>(G.sizes()) == nel_ * nmo_); + assert(get<0>(Guu.sizes()) == nu); ComplexType a = (walker_type == CLOSED) ? ComplexType(2.0) : ComplexType(1.0); Array T1({(uN - u0), nw * nel_}, @@ -1007,15 +1023,16 @@ class THCOps void Guu_from_full(MatA const& G, MatB&& Guu) { using std::fill_n; - int nmo_ = int(std::get<0>(Piu.sizes())); - int nu = int(std::get<1>(Piu.sizes())); + using std::get; + int nmo_ = int(get<0>(Piu.sizes())); + int nu = int(get<1>(Piu.sizes())); int u0, uN; std::tie(u0, uN) = FairDivideBoundary(comm->rank(), nu, comm->size()); int nwalk = G.size(); - assert(std::get<0>(G.sizes()) == std::get<1>(Guu.sizes())); - assert(std::get<0>(Guu.sizes()) == nu); - assert(std::get<1>(G.sizes()) == nmo_ * nmo_); + assert(get<0>(G.sizes()) == get<1>(Guu.sizes())); + assert(get<0>(Guu.sizes()) == nu); + assert(get<1>(G.sizes()) == nmo_ * nmo_); // calculate how many walkers can be done concurrently long Bytes = default_buffer_size_in_MB * 1024L * 1024L; @@ -1058,11 +1075,13 @@ class THCOps static_assert(std::decay::type::dimensionality == 3, "Wrong dimensionality"); static_assert(std::decay::type::dimensionality == 2, "Wrong dimensionality"); static_assert(std::decay::type::dimensionality == 3, "Wrong dimensionality"); - int nmo_ = int(std::get<0>(rotPiu.sizes())); - int nu = int(std::get<0>(rotMuv.sizes())); // potentially distributed over nodes - int nv = int(std::get<1>(rotMuv.sizes())); // not distributed over nodes + + using std::get; + int nmo_ = int(get<0>(rotPiu.sizes())); + int nu = int(get<0>(rotMuv.sizes())); // potentially distributed over nodes + int nv = int(get<1>(rotMuv.sizes())); // not distributed over nodes int nw = int(G.size()); - assert(std::get<1>(rotPiu.sizes()) == nv); + assert(get<1>(rotPiu.sizes()) == nv); int v0, vN; std::tie(v0, vN) = FairDivideBoundary(comm->rank(), nv, comm->size()); int k0, kN; diff --git a/src/AFQMC/HamiltonianOperations/THCOpsIO.hpp b/src/AFQMC/HamiltonianOperations/THCOpsIO.hpp index 365ff26673..07ca636118 100644 --- a/src/AFQMC/HamiltonianOperations/THCOpsIO.hpp +++ b/src/AFQMC/HamiltonianOperations/THCOpsIO.hpp @@ -295,8 +295,9 @@ inline void writeTHCOps(hdf_archive& dump, shmCMatrix& vn0, ValueType E0) { - size_t gnmu(std::get<1>(Luv.sizes())); - size_t grotnmu(std::get<1>(rotMuv.sizes())); + using std::get; + size_t gnmu(get<1>(Luv.sizes())); + size_t grotnmu(get<1>(rotMuv.sizes())); if (TGwfn.Global().root()) { dump.push("HamiltonianOperations"); diff --git a/src/AFQMC/HamiltonianOperations/sparse_matrix_energy.hpp b/src/AFQMC/HamiltonianOperations/sparse_matrix_energy.hpp index 51ff5d5276..36819d8a85 100644 --- a/src/AFQMC/HamiltonianOperations/sparse_matrix_energy.hpp +++ b/src/AFQMC/HamiltonianOperations/sparse_matrix_energy.hpp @@ -98,15 +98,16 @@ inline void calculate_energy(EMat&& locV, const MatA& Gc, MatB&& Gcloc, const Sp { // W[nwalk][2][NMO][NAEA] + using std::get; assert(locV.dimensionality == 2); - assert(std::get<1>(Gc.sizes()) == std::get<1>(Gcloc.sizes())); - assert(Vakbl.size(0) == std::get<0>(Gcloc.sizes())); - assert(std::get<0>(Gc.sizes()) == Vakbl.size(1)); + assert(get<1>(Gc.sizes()) == get<1>(Gcloc.sizes())); + assert(Vakbl.size(0) == get<0>(Gcloc.sizes())); + assert(get<0>(Gc.sizes()) == Vakbl.size(1)); using Type = typename std::decay::type::element; const Type half = Type(0.5); - int nwalk = std::get<1>(Gc.sizes()); + int nwalk = get<1>(Gc.sizes()); // Vakbl * Gc(bl,nw) = Gcloc(ak,nw) ma::product(Vakbl, Gc, std::forward(Gcloc)); diff --git a/src/AFQMC/HamiltonianOperations/tests/test_hamiltonian_operations.cpp b/src/AFQMC/HamiltonianOperations/tests/test_hamiltonian_operations.cpp index bfc7064c3a..e9f2c7d617 100644 --- a/src/AFQMC/HamiltonianOperations/tests/test_hamiltonian_operations.cpp +++ b/src/AFQMC/HamiltonianOperations/tests/test_hamiltonian_operations.cpp @@ -258,14 +258,15 @@ void ham_ops_basic_serial(boost::mpi3::communicator& world) HOps.vHS(X, vHS, sqrtdt); TG.local_barrier(); ComplexType Vsum = 0; + using std::get; if (HOps.transposed_vHS()) { - for (int i = 0; i < std::get<1>(vHS.sizes()); i++) + for (int i = 0; i < get<1>(vHS.sizes()); i++) Vsum += vHS[0][i]; } else { - for (int i = 0; i < std::get<0>(vHS.sizes()); i++) + for (int i = 0; i < get<0>(vHS.sizes()); i++) Vsum += vHS[i][0]; } if (std::abs(file_data.Vsum) > 1e-8) diff --git a/src/AFQMC/Hamiltonians/KPFactorizedHamiltonian.cpp b/src/AFQMC/Hamiltonians/KPFactorizedHamiltonian.cpp index 5dc2547b77..f80c2e0f38 100644 --- a/src/AFQMC/Hamiltonians/KPFactorizedHamiltonian.cpp +++ b/src/AFQMC/Hamiltonians/KPFactorizedHamiltonian.cpp @@ -163,13 +163,15 @@ HamiltonianOperations KPFactorizedHamiltonian::getHamiltonianOperations_shared(b APP_ABORT(""); } E0 = E_[0] + E_[1]; + + using std::get; if (nmo_per_kp.size() != nkpts || nchol_per_kp.size() != nkpts || kminus.size() != nkpts || - std::get<0>(QKtok2.sizes()) != nkpts || std::get<1>(QKtok2.sizes()) != nkpts) + get<0>(QKtok2.sizes()) != nkpts || get<1>(QKtok2.sizes()) != nkpts) { app_error() << " Error in KPFactorizedHamiltonian::getHamiltonianOperations():" << " Inconsistent dimension (NMOPerKP,NCholPerKP,QKtTok2): " << nkpts << " " << nmo_per_kp.size() - << " " << nchol_per_kp.size() << " " << kminus.size() << " " << std::get<0>(QKtok2.sizes()) << " " - << std::get<1>(QKtok2.sizes()) << std::endl; + << " " << nchol_per_kp.size() << " " << kminus.size() << " " << get<0>(QKtok2.sizes()) << " " + << get<1>(QKtok2.sizes()) << std::endl; APP_ABORT(""); } } @@ -265,11 +267,11 @@ HamiltonianOperations KPFactorizedHamiltonian::getHamiltonianOperations_shared(b << " Problems reading /Hamiltonian/KPFactorized/L" << Q << ". \n"; APP_ABORT(""); } - if (std::get<0>(LQKikn[Q].sizes()) != nkpts || std::get<1>(LQKikn[Q].sizes()) != nmo_max * nmo_max * nchol_per_kp[Q]) + if (get<0>(LQKikn[Q].sizes()) != nkpts || get<1>(LQKikn[Q].sizes()) != nmo_max * nmo_max * nchol_per_kp[Q]) { app_error() << " Error in KPFactorizedHamiltonian::getHamiltonianOperations():" << " Problems reading /Hamiltonian/KPFactorized/L" << Q << ". \n" - << " Unexpected dimensins: " << std::get<0>(LQKikn[Q].sizes()) << " " << std::get<1>(LQKikn[Q].sizes()) << std::endl; + << " Unexpected dimensins: " << get<0>(LQKikn[Q].sizes()) << " " << get<1>(LQKikn[Q].sizes()) << std::endl; APP_ABORT(""); } } @@ -441,14 +443,14 @@ HamiltonianOperations KPFactorizedHamiltonian::getHamiltonianOperations_shared(b { { // Alpha auto Psi = get_PsiK>(nmo_per_kp, PsiT[2 * nd], K); - assert(std::get<0>(Psi.sizes()) == na); + assert(get<0>(Psi.sizes()) == na); boost::multi::array_ref haj_r(to_address(haj[nd * nkpts + K].origin()), {na, ni}); if (na > 0) ma::product(Psi, H1[K]({0, ni}, {0, ni}), haj_r); } { // Beta auto Psi = get_PsiK>(nmo_per_kp, PsiT[2 * nd + 1], K); - assert(std::get<0>(Psi.sizes()) == nb); + assert(get<0>(Psi.sizes()) == nb); boost::multi::array_ref haj_r(to_address(haj[nd * nkpts + K].origin()) + na * ni, {nb, ni}); if (nb > 0) ma::product(Psi, H1[K]({0, ni}, {0, ni}), haj_r); @@ -458,7 +460,7 @@ HamiltonianOperations KPFactorizedHamiltonian::getHamiltonianOperations_shared(b { RealType scl = (type == CLOSED ? 2.0 : 1.0); auto Psi = get_PsiK>(nmo_per_kp, PsiT[nd], K, npol == 2); - assert(std::get<0>(Psi.sizes()) == na); + assert(get<0>(Psi.sizes()) == na); boost::multi::array_ref haj_r(to_address(haj[nd * nkpts + K].origin()), {na, npol * ni}); if (na > 0) ma::product(ComplexType(scl), Psi, H1[K]({0, npol * ni}, {0, npol * ni}), ComplexType(0.0), haj_r); @@ -485,11 +487,13 @@ HamiltonianOperations KPFactorizedHamiltonian::getHamiltonianOperations_shared(b int ni = nmo_per_kp[K]; int nk = nmo_per_kp[QK]; int nchol = nchol_per_kp[Q]; + + using std::get; if (type == COLLINEAR) { { // Alpha auto Psi = get_PsiK>(nmo_per_kp, PsiT[2 * nd], K); - assert(std::get<0>(Psi.sizes()) == nocc_per_kp[nd][K]); + assert(get<0>(Psi.sizes()) == nocc_per_kp[nd][K]); if (Q <= Qm) { Sp3Tensor_ref Likn(to_address(LQKikn[Q][K].origin()), {ni, nk, nchol}); @@ -505,7 +509,7 @@ HamiltonianOperations KPFactorizedHamiltonian::getHamiltonianOperations_shared(b } { // Beta auto Psi = get_PsiK>(nmo_per_kp, PsiT[2 * nd + 1], K); - assert(std::get<0>(Psi.sizes()) == nb); + assert(get<0>(Psi.sizes()) == nb); if (Q <= Qm) { Sp3Tensor_ref Likn(to_address(LQKikn[Q][K].origin()), {ni, nk, nchol}); @@ -523,7 +527,8 @@ HamiltonianOperations KPFactorizedHamiltonian::getHamiltonianOperations_shared(b else { auto Psi = get_PsiK(nmo_per_kp, PsiT[nd], K, npol == 2); - assert(std::get<0>(Psi.sizes()) == na); + using std::get; + assert(get<0>(Psi.sizes()) == na); if (Q <= Qm) { Sp3Tensor_ref Likn(to_address(LQKikn[Q][K].origin()), {ni, nk, nchol}); @@ -562,6 +567,8 @@ HamiltonianOperations KPFactorizedHamiltonian::getHamiltonianOperations_shared(b int nchol = nchol_per_kp[Q]; Sp3Tensor_ref Likn(to_address(LQKikn[Q][K].origin()), {ni, nk, nchol}); // NOTE: LQKbnl is indexed by the K index of 'b', L[Q][Kb] + using std::get; + if (type == COLLINEAR) { { // Alpha @@ -571,7 +578,7 @@ HamiltonianOperations KPFactorizedHamiltonian::getHamiltonianOperations_shared(b } { // Beta auto PsiQK = get_PsiK>(nmo_per_kp, PsiT[2 * nd + 1], QK); - assert(std::get<0>(PsiQK.sizes()) == nb); + assert(get<0>(PsiQK.sizes()) == nb); Sp3Tensor_ref Lbnl(to_address(LQKbnl[nq0 + number_of_symmetric_Q + Qmap[Q] - 1][QK].origin()), {nb, nchol, ni}); ma_rotate::getLank_from_Lkin(PsiQK, Likn, Lbnl, buff); @@ -580,7 +587,7 @@ HamiltonianOperations KPFactorizedHamiltonian::getHamiltonianOperations_shared(b else { auto PsiQK = get_PsiK(nmo_per_kp, PsiT[nd], QK, npol == 2); - assert(std::get<0>(PsiQK.sizes()) == na); + assert(get<0>(PsiQK.sizes()) == na); Sp3Tensor_ref Lbnl(to_address(LQKbnl[nq0 + Qmap[Q] - 1][QK].origin()), {na, nchol, npol * ni}); ma_rotate::getLank_from_Lkin(PsiQK, Likn, Lbnl, buff, npol == 2); } @@ -889,13 +896,16 @@ HamiltonianOperations KPFactorizedHamiltonian::getHamiltonianOperations_batched( APP_ABORT(""); } E0 = E_[0] + E_[1]; + + using std::get; + if (nmo_per_kp.size() != nkpts || nchol_per_kp.size() != nkpts || kminus.size() != nkpts || - std::get<0>(QKtok2.sizes()) != nkpts || std::get<1>(QKtok2.sizes()) != nkpts) + get<0>(QKtok2.sizes()) != nkpts || get<1>(QKtok2.sizes()) != nkpts) { app_error() << " Error in KPFactorizedHamiltonian::getHamiltonianOperations():" << " Inconsistent dimension (NMOPerKP,NCholPerKP,QKtTok2): " << nkpts << " " << nmo_per_kp.size() - << " " << nchol_per_kp.size() << " " << kminus.size() << " " << std::get<0>(QKtok2.sizes()) << " " - << std::get<1>(QKtok2.sizes()) << std::endl; + << " " << nchol_per_kp.size() << " " << kminus.size() << " " << get<0>(QKtok2.sizes()) << " " + << get<1>(QKtok2.sizes()) << std::endl; APP_ABORT(""); } } diff --git a/src/AFQMC/Hamiltonians/RealDenseHamiltonian.cpp b/src/AFQMC/Hamiltonians/RealDenseHamiltonian.cpp index 39ad191af1..4929670334 100644 --- a/src/AFQMC/Hamiltonians/RealDenseHamiltonian.cpp +++ b/src/AFQMC/Hamiltonians/RealDenseHamiltonian.cpp @@ -61,14 +61,16 @@ HamiltonianOperations RealDenseHamiltonian::getHamiltonianOperations(bool pureSD using RMatrix_ref = boost::multi::array_ref; using Sp3Tensor_ref = boost::multi::array_ref; + using std::get; + if (type == COLLINEAR) assert(PsiT.size() % 2 == 0); int nspins = ((type != COLLINEAR) ? 1 : 2); int ndet = PsiT.size() / nspins; - int nup = std::get<0>(PsiT[0].sizes()); + int nup = get<0>(PsiT[0].sizes()); int ndown = 0; if (nspins == 2) - ndown = std::get<0>(PsiT[1].sizes()); + ndown = get<0>(PsiT[1].sizes()); int NEL = nup + ndown; // distribute work over equivalent nodes in TGprop.TG() across TG.Global() @@ -176,11 +178,14 @@ HamiltonianOperations RealDenseHamiltonian::getHamiltonianOperations(bool pureSD << " Problems reading /Hamiltonian/DenseFactorized/L. \n"; APP_ABORT(""); } - if (std::get<0>(Likn.sizes()) != NMO * NMO || std::get<1>(Likn.sizes()) != local_ncv) + + using std::get; + + if (get<0>(Likn.sizes()) != NMO * NMO || get<1>(Likn.sizes()) != local_ncv) { app_error() << " Error in RealDenseHamiltonian::getHamiltonianOperations():" << " Problems reading /Hamiltonian/DenseFactorized/L. \n" - << " Unexpected dimensions: " << std::get<0>(Likn.sizes()) << " " << std::get<1>(Likn.sizes()) << std::endl; + << " Unexpected dimensions: " << get<0>(Likn.sizes()) << " " << get<1>(Likn.sizes()) << std::endl; APP_ABORT(""); } dump.pop(); diff --git a/src/AFQMC/Hamiltonians/RealDenseHamiltonian_v2.cpp b/src/AFQMC/Hamiltonians/RealDenseHamiltonian_v2.cpp index 29b4422def..1daa9193af 100644 --- a/src/AFQMC/Hamiltonians/RealDenseHamiltonian_v2.cpp +++ b/src/AFQMC/Hamiltonians/RealDenseHamiltonian_v2.cpp @@ -175,11 +175,12 @@ HamiltonianOperations RealDenseHamiltonian_v2::getHamiltonianOperations(bool pur << " Problems reading /Hamiltonian/DenseFactorized/L. \n"; APP_ABORT(""); } - if (std::get<0>(Likn.sizes()) != NMO * NMO || std::get<1>(Likn.sizes()) != local_ncv) + using std::get; + if (get<0>(Likn.sizes()) != NMO * NMO || get<1>(Likn.sizes()) != local_ncv) { app_error() << " Error in RealDenseHamiltonian_v2::getHamiltonianOperations():" << " Problems reading /Hamiltonian/DenseFactorized/L. \n" - << " Unexpected dimensins: " << std::get<0>(Likn.sizes()) << " " << std::get<1>(Likn.sizes()) << std::endl; + << " Unexpected dimensins: " << get<0>(Likn.sizes()) << " " << get<1>(Likn.sizes()) << std::endl; APP_ABORT(""); } dump.pop(); diff --git a/src/AFQMC/Hamiltonians/THCHamiltonian.cpp b/src/AFQMC/Hamiltonians/THCHamiltonian.cpp index a72d6674fc..131e6c177a 100644 --- a/src/AFQMC/Hamiltonians/THCHamiltonian.cpp +++ b/src/AFQMC/Hamiltonians/THCHamiltonian.cpp @@ -234,7 +234,9 @@ HamiltonianOperations THCHamiltonian::getHamiltonianOperations(bool pureSD, auto itT = Tuv.origin(); for (size_t i = 0; i < Muv.num_elements(); ++i, ++itT, ++itM) *(itT) = ma::conj(*itT) * (*itM); - boost::multi::array T_({static_cast(std::get<1>(Tuv.sizes())), NMO}); + + using std::get; + boost::multi::array T_({static_cast(get<1>(Tuv.sizes())), NMO}); ma::product(T(Tuv), H(Piu__), T_); ma::product(SPValueType(-0.5), T(T_), T(Piu__({0, long(NMO)}, {long(c0), long(cN)})), SPValueType(0.0), v0_); @@ -285,7 +287,9 @@ HamiltonianOperations THCHamiltonian::getHamiltonianOperations(bool pureSD, auto itT = Tuv.origin(); for (size_t i = 0; i < Muv.num_elements(); ++i, ++itT, ++itM) *(itT) = ma::conj(*itT) * (*itM); - boost::multi::array T_({static_cast(std::get<1>(Tuv.sizes())), NMO}); + + using std::get; + boost::multi::array T_({static_cast(get<1>(Tuv.sizes())), NMO}); ma::product(T(Tuv), H(Piu), T_); ma::product(SPValueType(-0.5), T(T_), T(Piu({0, long(NMO)}, {long(c0), long(cN)})), SPValueType(0.0), v0_); diff --git a/src/AFQMC/Hamiltonians/rotateHamiltonian.hpp b/src/AFQMC/Hamiltonians/rotateHamiltonian.hpp index f2c8a7162e..906d3e468a 100644 --- a/src/AFQMC/Hamiltonians/rotateHamiltonian.hpp +++ b/src/AFQMC/Hamiltonians/rotateHamiltonian.hpp @@ -773,6 +773,7 @@ inline void rotateHijkl_single_node(std::string& type, std::fill_n(Rl.origin(), Rl.num_elements(), SPComplexType(0.0)); { + using std::get; // Q(k,a,n) = sum_i ma::conj(Amat(i,a)) * V2_fact(ik,n) // R(l,a,n) = sum_i ma::conj(Amat(i,a)) * ma::conj(V2_fact(li,n)) @@ -798,7 +799,7 @@ inline void rotateHijkl_single_node(std::string& type, { // Qk[norb*NAEA,nvec] // Rl[nvec,norb*NAEA] - int n0_, n1_, sz_ = std::get<0>(Qk.sizes()); + int n0_, n1_, sz_ = get<0>(Qk.sizes()); std::tie(n0_, n1_) = FairDivideBoundary(coreid, sz_, ncores); if (n1_ - n0_ > 0) ma::transpose(Qk.sliced(n0_, n1_), Rl(Rl.extension(0), {n0_, n1_})); diff --git a/src/AFQMC/Hamiltonians/rotateHamiltonian_Helper2.hpp b/src/AFQMC/Hamiltonians/rotateHamiltonian_Helper2.hpp index c1624fd245..e97c57a66a 100644 --- a/src/AFQMC/Hamiltonians/rotateHamiltonian_Helper2.hpp +++ b/src/AFQMC/Hamiltonians/rotateHamiltonian_Helper2.hpp @@ -50,10 +50,12 @@ inline void count_Qk_x_Rl(WALKER_TYPES walker_type, MatTa&& Ta, const SPRealType cut) { + using std::get; + using Type = typename std::decay::type::element; - assert(std::get<0>(Qk.sizes()) == std::get<0>(Ta.sizes())); - assert(std::get<1>(Qk.sizes()) == std::get<0>(Rl.sizes())); - assert(std::get<1>(Rl.sizes()) == std::get<1>(Rl.sizes())); + assert(get<0>(Qk.sizes()) == get<0>(Ta.sizes())); + assert(get<1>(Qk.sizes()) == get<0>(Rl.sizes())); + assert(get<1>(Rl.sizes()) == get<1>(Rl.sizes())); int ncores = TG.getTotalCores(), coreid = TG.getCoreID(); bool amIAlpha = true; @@ -61,13 +63,13 @@ inline void count_Qk_x_Rl(WALKER_TYPES walker_type, amIAlpha = false; int bl0 = -1, blN = -1; - int nwork = std::min(int(std::get<1>(Rl.sizes())), ncores); + int nwork = std::min(int(get<1>(Rl.sizes())), ncores); if (coreid < nwork) - std::tie(bl0, blN) = FairDivideBoundary(coreid, int(std::get<1>(Rl.sizes())), nwork); + std::tie(bl0, blN) = FairDivideBoundary(coreid, int(get<1>(Rl.sizes())), nwork); int ka0 = -1, kaN = -1; - nwork = std::min(int(std::get<0>(Qk.sizes())), ncores); + nwork = std::min(int(get<0>(Qk.sizes())), ncores); if (coreid < nwork) - std::tie(ka0, kaN) = FairDivideBoundary(coreid, int(std::get<0>(Qk.sizes())), nwork); + std::tie(ka0, kaN) = FairDivideBoundary(coreid, int(get<0>(Qk.sizes())), nwork); Type four(4.0); Type two(2.0); @@ -210,10 +212,12 @@ inline void Qk_x_Rl(WALKER_TYPES walker_type, Container& Vijkl, const SPRealType cut) { + using std::get; + using Type = typename std::decay::type::element; - assert(std::get<0>(Qk.sizes()) == std::get<0>(Ta.sizes())); - assert(std::get<1>(Qk.sizes()) == std::get<0>(Rl.sizes())); - assert(std::get<1>(Rl.sizes()) == std::get<1>(Rl.sizes())); + assert(get<0>(Qk.sizes()) == get<0>(Ta.sizes())); + assert(get<1>(Qk.sizes()) == get<0>(Rl.sizes())); + assert(get<1>(Rl.sizes()) == get<1>(Rl.sizes())); int ncores = TG.getTotalCores(), coreid = TG.getCoreID(); bool amIAlpha = true; @@ -222,12 +226,12 @@ inline void Qk_x_Rl(WALKER_TYPES walker_type, int bl0 = -1, blN = -1; int ka0 = -1, kaN = -1; - int nwork = std::min(int(std::get<1>(Rl.sizes())), ncores); + int nwork = std::min(int(get<1>(Rl.sizes())), ncores); if (coreid < nwork) - std::tie(bl0, blN) = FairDivideBoundary(coreid, int(std::get<1>(Rl.sizes())), nwork); - nwork = std::min(int(std::get<0>(Qk.sizes())), ncores); + std::tie(bl0, blN) = FairDivideBoundary(coreid, int(get<1>(Rl.sizes())), nwork); + nwork = std::min(int(get<0>(Qk.sizes())), ncores); if (coreid < nwork) - std::tie(ka0, kaN) = FairDivideBoundary(coreid, int(std::get<0>(Qk.sizes())), nwork); + std::tie(ka0, kaN) = FairDivideBoundary(coreid, int(get<0>(Qk.sizes())), nwork); Type four(4.0); Type two(2.0); diff --git a/src/AFQMC/Matrix/csr_matrix_construct.hpp b/src/AFQMC/Matrix/csr_matrix_construct.hpp index c1d1942906..3ac0f41663 100644 --- a/src/AFQMC/Matrix/csr_matrix_construct.hpp +++ b/src/AFQMC/Matrix/csr_matrix_construct.hpp @@ -56,12 +56,14 @@ CSR construct_csr_matrix_single_input(MultiArray2D&& M, double cutoff, char TA, std::vector counts; using int_type = typename CSR::index_type; int_type nr, nc; + + using std::get; if (comm.rank() == 0) { if (TA == 'N') { - nr = std::get<0>(M.sizes()); - nc = std::get<1>(M.sizes()); + nr = get<0>(M.sizes()); + nc = get<1>(M.sizes()); counts.resize(nr); for (int_type i = 0; i < nr; i++) for (int_type j = 0; j < nc; j++) @@ -70,11 +72,11 @@ CSR construct_csr_matrix_single_input(MultiArray2D&& M, double cutoff, char TA, } else { - nr = std::get<1>(M.sizes()); - nc = std::get<0>(M.sizes()); + nr = get<1>(M.sizes()); + nc = get<0>(M.sizes()); counts.resize(nr); - for (int_type i = 0; i < std::get<0>(M.sizes()); i++) - for (int_type j = 0; j < std::get<1>(M.sizes()); j++) + for (int_type i = 0; i < get<0>(M.sizes()); i++) + for (int_type j = 0; j < get<1>(M.sizes()); j++) if (std::abs(M[i][j]) > cutoff) ++counts[j]; } @@ -88,6 +90,7 @@ CSR construct_csr_matrix_single_input(MultiArray2D&& M, double cutoff, char TA, CSR csr_mat(std::tuple{nr, nc}, std::tuple{0, 0}, counts, qmcplusplus::afqmc::shared_allocator(comm)); + using std::get; if (comm.rank() == 0) { if (TA == 'N') @@ -99,15 +102,15 @@ CSR construct_csr_matrix_single_input(MultiArray2D&& M, double cutoff, char TA, } else if (TA == 'T') { - for (int_type i = 0; i < std::get<1>(M.sizes()); i++) - for (int_type j = 0; j < std::get<0>(M.sizes()); j++) + for (int_type i = 0; i < get<1>(M.sizes()); i++) + for (int_type j = 0; j < get<0>(M.sizes()); j++) if (std::abs(M[j][i]) > cutoff) csr_mat.emplace_back({i, j}, static_cast(M[j][i])); } else if (TA == 'H') { - for (int_type i = 0; i < std::get<1>(M.sizes()); i++) - for (int_type j = 0; j < std::get<0>(M.sizes()); j++) + for (int_type i = 0; i < get<1>(M.sizes()); i++) + for (int_type j = 0; j < get<0>(M.sizes()); j++) if (std::abs(M[j][i]) > cutoff) csr_mat.emplace_back({i, j}, static_cast(ma::conj(M[j][i]))); } diff --git a/src/AFQMC/Matrix/ma_hdf5_readers.hpp b/src/AFQMC/Matrix/ma_hdf5_readers.hpp index 91129b41bb..acc95952ba 100644 --- a/src/AFQMC/Matrix/ma_hdf5_readers.hpp +++ b/src/AFQMC/Matrix/ma_hdf5_readers.hpp @@ -64,6 +64,8 @@ inline void write_distributed_MA(MultiArray& A, // data distribution depends on whether we have devices or not! int TG_number(TG.getTGNumber()); int TG_local_rank(TG.TG_local().rank()); + + using std::get; // assumes that Global.root() lives in TG_number if (TG.Global().root()) { @@ -71,15 +73,15 @@ inline void write_distributed_MA(MultiArray& A, std::vector ndim(4 * nnodes_per_TG); ndim[0] = offset[0]; ndim[1] = offset[1]; - ndim[2] = std::get<0>(A.sizes()); - ndim[3] = std::get<1>(A.sizes()); + ndim[2] = get<0>(A.sizes()); + ndim[3] = get<1>(A.sizes()); TG.TG_Cores().all_reduce_in_place_n(ndim.begin(), ndim.size(), std::plus<>()); // write local piece { using Mat_ref = boost::multi::array_ref; Mat_ref A_(to_address(A.origin()), A.extensions()); - hyperslab_proxy slab(A_, gdim, std::array{size_t(std::get<0>(A.sizes())), size_t(std::get<1>(A.sizes()))}, offset); + hyperslab_proxy slab(A_, gdim, std::array{size_t(get<0>(A.sizes())), size_t(get<1>(A.sizes()))}, offset); dump.write(slab, name); } @@ -101,8 +103,8 @@ inline void write_distributed_MA(MultiArray& A, // all tasks on the TG have a section of the matrix ndim[4 * TG.TG_Cores().rank()] = offset[0]; ndim[4 * TG.TG_Cores().rank() + 1] = offset[1]; - ndim[4 * TG.TG_Cores().rank() + 2] = std::get<0>(A.sizes()); - ndim[4 * TG.TG_Cores().rank() + 3] = std::get<1>(A.sizes()); + ndim[4 * TG.TG_Cores().rank() + 2] = get<0>(A.sizes()); + ndim[4 * TG.TG_Cores().rank() + 3] = get<1>(A.sizes()); TG.TG_Cores().all_reduce_in_place_n(ndim.begin(), ndim.size(), std::plus<>()); TG.TG_Cores().send_n(to_address(A.origin()), A.num_elements(), 0, TG.TG_Cores().rank()); } diff --git a/src/AFQMC/Matrix/tests/matrix_helpers.h b/src/AFQMC/Matrix/tests/matrix_helpers.h index 6cf3b31db8..2c43f070bc 100644 --- a/src/AFQMC/Matrix/tests/matrix_helpers.h +++ b/src/AFQMC/Matrix/tests/matrix_helpers.h @@ -46,8 +46,10 @@ void verify_approx(M1 const& A, M2 const& B) // casting in case operator[] returns a fancy reference using element1 = typename std::decay::type::element; using element2 = typename std::decay::type::element; - REQUIRE(std::get<0>(A.sizes()) == std::get<0>(B.sizes())); - for (int i = 0; i < std::get<0>(A.sizes()); i++) + + using std::get; + REQUIRE(get<0>(A.sizes()) == get<0>(B.sizes())); + for (int i = 0; i < get<0>(A.sizes()); i++) myCHECK(element1(A[i]), element2(B[i])); } diff --git a/src/AFQMC/Numerics/csr_blas.hpp b/src/AFQMC/Numerics/csr_blas.hpp index a9ed507cca..1d5d8d7858 100644 --- a/src/AFQMC/Numerics/csr_blas.hpp +++ b/src/AFQMC/Numerics/csr_blas.hpp @@ -41,8 +41,10 @@ template::type::dimensionality == 1>::type> MultiArray1D axpy(char TA, T a, SparseArray1D&& x, MultiArray1D&& y) { + using std::get; + using ma::conj; - assert(std::get<0>(x.sizes()) == std::get<0>(y.sizes())); + assert(get<0>(x.sizes()) == get<0>(y.sizes())); auto vals = x.non_zero_values_data(); auto cols = x.non_zero_indices2_data(); if (TA == 'C') @@ -378,8 +380,11 @@ MultiArray2D transpose(csr_matrix&& A, MultiArray2D&& AT) { using integer = typename std::decay::type::index_type; using Type = typename std::decay::type::element; - assert(std::get<0>(A.sizes()) == std::get<1>(AT.sizes())); - assert(std::get<1>(A.sizes()) == std::get<0>(AT.sizes())); + + using std::get; + + assert(get<0>(A.sizes()) == get<1>(AT.sizes())); + assert(get<1>(A.sizes()) == get<0>(AT.sizes())); auto& comm = *A.getAlloc().commP_; integer r0, rN, nrows = integer(A.size(0)); integer rank = comm.rank(), size = comm.size(); diff --git a/src/AFQMC/Numerics/ma_blas.hpp b/src/AFQMC/Numerics/ma_blas.hpp index 2d055fd743..71b53ca85a 100644 --- a/src/AFQMC/Numerics/ma_blas.hpp +++ b/src/AFQMC/Numerics/ma_blas.hpp @@ -48,14 +48,16 @@ MultiArray2DY&& copy(MultiArray2DX&& x, MultiArray2DY&& y) assert(x.stride(1) == 1); assert(y.stride(1) == 1); assert(x.size() == y.size()); - assert(std::get<1>(x.sizes()) == std::get<1>(y.sizes())); - if ((x.stride() == std::get<1>(x.sizes())) && (y.stride() == std::get<1>(y.sizes()))) + + using std::get; + assert(get<1>(x.sizes()) == get<1>(y.sizes())); + if ((x.stride() == get<1>(x.sizes())) && (y.stride() == get<1>(y.sizes()))) { copy(x.num_elements(), pointer_dispatch(x.origin()), 1, pointer_dispatch(y.origin()), 1); } else { - copy2D(x.size(), std::get<1>(x.sizes()), pointer_dispatch(x.origin()), x.stride(), pointer_dispatch(y.origin()), y.stride()); + copy2D(x.size(), get<1>(x.sizes()), pointer_dispatch(x.origin()), x.stride(), pointer_dispatch(y.origin()), y.stride()); } return std::forward(y); } @@ -68,18 +70,19 @@ template MultiArrayNDY&& copy(MultiArrayNDX&& x, MultiArrayNDY&& y) { + using std::get; #ifndef NDEBUG // only on contiguous arrays // long sz(x.size()); // for (int i = 1; i < int(std::decay::type::dimensionality); ++i) // sz *= x.size(i); // assert(x.num_elements() == sz); - assert(std::get::type::dimensionality - 1>(x.strides()) == 1); + assert(get::type::dimensionality - 1>(x.strides()) == 1); // sz = y.size(); // for (int i = 1; i < int(std::decay::type::dimensionality); ++i) // sz *= y.size(i); // assert(y.num_elements() == sz); - assert(std::get::type::dimensionality - 1>(y.strides()) == 1); + assert(get::type::dimensionality - 1>(y.strides()) == 1); assert(x.num_elements() == y.num_elements()); #endif copy(x.num_elements(), pointer_dispatch(x.origin()), 1, pointer_dispatch(y.origin()), 1); @@ -104,9 +107,10 @@ template typename std::decay::type::element dot(MultiArray2Dx&& x, MultiArray2Dy&& y) { - assert(x.stride() == std::get<1>(x.sizes())); // only on contiguous arrays + using std::get; + assert(x.stride() == get<1>(x.sizes())); // only on contiguous arrays assert(x.stride(1) == 1); // only on contiguous arrays - assert(y.stride() == std::get<1>(y.sizes())); // only on contiguous arrays + assert(y.stride() == get<1>(y.sizes())); // only on contiguous arrays assert(y.stride(1) == 1); // only on contiguous arrays assert(x.num_elements() == y.num_elements()); return dot(x.num_elements(), pointer_dispatch(x.origin()), 1, pointer_dispatch(y.origin()), 1); @@ -133,7 +137,8 @@ MultiArrayND&& scal(T a, MultiArrayND&& x) // for (int i = 1; i < int(std::decay::type::dimensionality); ++i) // sz *= x.size(i); // assert(x.num_elements() == sz); - assert(std::get::type::dimensionality - 1>(x.strides()) == 1); // only on contiguous arrays + using std::get; + assert(get::type::dimensionality - 1>(x.strides()) == 1); // only on contiguous arrays #endif scal(x.num_elements(), a, pointer_dispatch(x.origin()), 1); return std::forward(x); @@ -180,10 +185,11 @@ template MultiArray2DB&& axpy(T x, MultiArray2DA const& a, MultiArray2DB&& b) { + using std::get; assert(a.num_elements() == b.num_elements()); - assert(a.stride() == std::get<1>(a.sizes())); // only on contiguous arrays + assert(a.stride() == get<1>(a.sizes())); // only on contiguous arrays assert(a.stride(1) == 1); // only on contiguous arrays - assert(b.stride() == std::get<1>(b.sizes())); // only on contiguous arrays + assert(b.stride() == get<1>(b.sizes())); // only on contiguous arrays assert(b.stride(1) == 1); // only on contiguous arrays axpy(a.num_elements(), x, pointer_dispatch(a.origin()), 1, pointer_dispatch(b.origin()), 1); return std::forward(b); @@ -199,13 +205,14 @@ template< std::decay::type::dimensionality == 1>::type> MultiArray1DY&& gemv(T alpha, MultiArray2DA const& A, MultiArray1DX const& x, T beta, MultiArray1DY&& y) { + using std::get; assert((IN == 'N') || (IN == 'T') || (IN == 'C')); if (IN == 'T' or IN == 'C') - assert(x.size() == std::get<1>(A.sizes()) and y.size() == A.size()); + assert(x.size() == get<1>(A.sizes()) and y.size() == A.size()); else if (IN == 'N') - assert(x.size() == A.size() and y.size() == std::get<1>(A.sizes())); + assert(x.size() == A.size() and y.size() == get<1>(A.sizes())); assert(A.stride(1) == 1); // gemv is not implemented for arrays with non-leading stride != 1 - int M = std::get<1>(A.sizes()); + int M = get<1>(A.sizes()); int N = A.size(); gemv(IN, M, N, alpha, pointer_dispatch(A.origin()), A.stride(), pointer_dispatch(x.origin()), x.stride(), beta, pointer_dispatch(y.origin()), y.stride()); @@ -218,10 +225,10 @@ MultiArray1DY&& gemv(MultiArray2DA const& A, MultiArray1DX const& x, MultiArray1 return gemv(1., A, x, 0., std::forward(y)); } //y := alpha*A*x -// gemm<'T', 'T'>(1., A, B, 0., C); // C = T(A*B) = T(B)*T(A) or T(C) = A*B -// gemm<'N', 'N'>(1., A, B, 0., C); // C = B*A = T(T(A)*T(B)) or T(C) = T(A)*T(B) -// gemm<'T', 'N'>(1., A, B, 0., C); // C = T(A*T(B)) = B*T(A) or T(C) = A*T(B) -// gemm<'N', 'T'>(1., A, B, 0., C); // C = T(T(A)*B) = T(B)*A or T(C) = T(A)*B +// gemm<'T', 'T'>(1., A, B, 0., C); // C = T(A*B) = T(B)*T(A) or T(C) = A*B +// gemm<'N', 'N'>(1., A, B, 0., C); // C = B*A = T(T(A)*T(B)) or T(C) = T(A)*T(B) +// gemm<'T', 'N'>(1., A, B, 0., C); // C = T(A*T(B)) = B*T(A) or T(C) = A*T(B) +// gemm<'N', 'T'>(1., A, B, 0., C); // C = T(T(A)*B) = T(B)*A or T(C) = T(A)*B template< char TA, @@ -242,33 +249,34 @@ MultiArray2DC&& gemm(T alpha, MultiArray2DA const& a, MultiArray2DB const& b, T int M = -1; int N = -1; int K = -1; + using std::get; if (TA == 'N' and TB == 'N') { - M = std::get<1>(a.sizes()); + M = get<1>(a.sizes()); N = b.size(); K = a.size(); - assert(a.size() == std::get<1>(b.sizes()) and c.size() == b.size() and std::get<1>(c.sizes()) == std::get<1>(a.sizes())); + assert(a.size() == get<1>(b.sizes()) and c.size() == b.size() and get<1>(c.sizes()) == get<1>(a.sizes())); } if ((TA == 'T' or TA == 'C') and (TB == 'T' or TB == 'C')) { M = a.size(); - N = std::get<1>(b.sizes()); - K = std::get<1>(a.sizes()); - assert(std::get<1>(a.sizes()) == b.size() and c.size() == std::get<1>(b.sizes()) and std::get<1>(c.sizes()) == a.size()); + N = get<1>(b.sizes()); + K = get<1>(a.sizes()); + assert(get<1>(a.sizes()) == b.size() and c.size() == get<1>(b.sizes()) and get<1>(c.sizes()) == a.size()); } if ((TA == 'T' or TA == 'C') and TB == 'N') { M = a.size(); N = b.size(); - K = std::get<1>(a.sizes()); - assert(std::get<1>(a.sizes()) == std::get<1>(b.sizes()) and c.size() == b.size() and std::get<1>(c.sizes()) == a.size()); + K = get<1>(a.sizes()); + assert(get<1>(a.sizes()) == get<1>(b.sizes()) and c.size() == b.size() and get<1>(c.sizes()) == a.size()); } if (TA == 'N' and (TB == 'T' or TB == 'C')) { - M = std::get<1>(a.sizes()); - N = std::get<1>(b.sizes()); + M = get<1>(a.sizes()); + N = get<1>(b.sizes()); K = a.size(); - assert(a.size() == b.size() and c.size() == std::get<1>(b.sizes()) and std::get<1>(c.sizes()) == std::get<1>(a.sizes())); + assert(a.size() == b.size() and c.size() == get<1>(b.sizes()) and get<1>(c.sizes()) == get<1>(a.sizes())); } gemm(TA, TB, M, N, K, alpha, pointer_dispatch(a.origin()), a.stride(), pointer_dispatch(b.origin()), b.stride(), beta, pointer_dispatch(c.origin()), c.stride()); @@ -297,33 +305,35 @@ MultiArray3DC&& gemmStridedBatched(T alpha, MultiArray3DA const& a, MultiArray3D int M = -1; int N = -1; int K = -1; + + using std::get; if (TA == 'N' and TB == 'N') { - M = std::get<2>(a.sizes()); - N = std::get<1>(b.sizes()); - K = std::get<1>(a.sizes()); - assert(std::get<1>(a.sizes()) == std::get<2>(b.sizes()) and std::get<1>(c.sizes()) == std::get<1>(b.sizes()) and std::get<2>(c.sizes()) == std::get<2>(a.sizes())); + M = get<2>(a.sizes()); + N = get<1>(b.sizes()); + K = get<1>(a.sizes()); + assert(get<1>(a.sizes()) == get<2>(b.sizes()) and get<1>(c.sizes()) == get<1>(b.sizes()) and get<2>(c.sizes()) == get<2>(a.sizes())); } if ((TA == 'T' or TA == 'C') and (TB == 'T' or TB == 'C')) { - M = std::get<1>(a.sizes()); - N = std::get<2>(b.sizes()); - K = std::get<2>(a.sizes()); - assert(std::get<2>(a.sizes()) == std::get<1>(b.sizes()) and std::get<1>(c.sizes()) == std::get<2>(b.sizes()) and std::get<2>(c.sizes()) == std::get<1>(a.sizes())); + M = get<1>(a.sizes()); + N = get<2>(b.sizes()); + K = get<2>(a.sizes()); + assert(get<2>(a.sizes()) == get<1>(b.sizes()) and get<1>(c.sizes()) == get<2>(b.sizes()) and get<2>(c.sizes()) == get<1>(a.sizes())); } if ((TA == 'T' or TA == 'C') and TB == 'N') { - M = std::get<1>(a.sizes()); - N = std::get<1>(b.sizes()); - K = std::get<2>(a.sizes()); - assert(std::get<2>(a.sizes()) == std::get<2>(b.sizes()) and std::get<1>(c.sizes()) == std::get<1>(b.sizes()) and std::get<2>(c.sizes()) == std::get<1>(a.sizes())); + M = get<1>(a.sizes()); + N = get<1>(b.sizes()); + K = get<2>(a.sizes()); + assert(get<2>(a.sizes()) == get<2>(b.sizes()) and get<1>(c.sizes()) == get<1>(b.sizes()) and get<2>(c.sizes()) == get<1>(a.sizes())); } if (TA == 'N' and (TB == 'T' or TB == 'C')) { - M = std::get<2>(a.sizes()); - N = std::get<2>(b.sizes()); - K = std::get<1>(a.sizes()); - assert(std::get<1>(a.sizes()) == std::get<1>(b.sizes()) and std::get<1>(c.sizes()) == std::get<2>(b.sizes()) and std::get<2>(c.sizes()) == std::get<2>(a.sizes())); + M = get<2>(a.sizes()); + N = get<2>(b.sizes()); + K = get<1>(a.sizes()); + assert(get<1>(a.sizes()) == get<1>(b.sizes()) and get<1>(c.sizes()) == get<2>(b.sizes()) and get<2>(c.sizes()) == get<2>(a.sizes())); } gemmStridedBatched(TA, TB, M, N, K, alpha, pointer_dispatch(a.origin()), a.stride(1), a.stride(), pointer_dispatch(b.origin()), b.stride(1), b.stride(), beta, pointer_dispatch(c.origin()), @@ -353,27 +363,29 @@ MultiArray2DC&& geam(T alpha, MultiArray2DA const& a, T beta, MultiArray2DB cons assert(c.stride(1) == 1); assert((TA == 'N') || (TA == 'T') || (TA == 'C')); assert((TB == 'N') || (TB == 'T') || (TB == 'C')); + + using std::get; if (TA == 'N' and TB == 'N') { - assert(a.size() == c.size() and std::get<1>(a.sizes()) == std::get<1>(c.sizes())); - assert(b.size() == c.size() and std::get<1>(b.sizes()) == std::get<1>(c.sizes())); + assert(a.size() == c.size() and get<1>(a.sizes()) == get<1>(c.sizes())); + assert(b.size() == c.size() and get<1>(b.sizes()) == get<1>(c.sizes())); } if ((TA == 'T' or TA == 'C') and (TB == 'T' or TB == 'C')) { - assert(std::get<1>(a.sizes()) == c.size() and a.size() == std::get<1>(c.sizes())); - assert(std::get<1>(b.sizes()) == c.size() and b.size() == std::get<1>(c.sizes())); + assert(get<1>(a.sizes()) == c.size() and a.size() == get<1>(c.sizes())); + assert(get<1>(b.sizes()) == c.size() and b.size() == get<1>(c.sizes())); } if ((TA == 'T' or TA == 'C') and TB == 'N') { - assert(std::get<1>(a.sizes()) == c.size() and a.size() == std::get<1>(c.sizes())); - assert(b.size() == c.size() and std::get<1>(b.sizes()) == std::get<1>(c.sizes())); + assert(get<1>(a.sizes()) == c.size() and a.size() == get<1>(c.sizes())); + assert(b.size() == c.size() and get<1>(b.sizes()) == get<1>(c.sizes())); } if (TA == 'N' and (TB == 'T' or TB == 'C')) { - assert(a.size() == c.size() and std::get<1>(a.sizes()) == std::get<1>(c.sizes())); - assert(std::get<1>(b.sizes()) == c.size() and b.size() == std::get<1>(c.sizes())); + assert(a.size() == c.size() and get<1>(a.sizes()) == get<1>(c.sizes())); + assert(get<1>(b.sizes()) == c.size() and b.size() == get<1>(c.sizes())); } - geam(TA, TB, std::get<1>(c.sizes()), c.size(), alpha, pointer_dispatch(a.origin()), a.stride(), beta, + geam(TA, TB, get<1>(c.sizes()), c.size(), alpha, pointer_dispatch(a.origin()), a.stride(), beta, pointer_dispatch(b.origin()), b.stride(), pointer_dispatch(c.origin()), c.stride()); return std::forward(c); } @@ -389,15 +401,18 @@ MultiArray2DC&& geam(T alpha, MultiArray2DA const& a, MultiArray2DC&& c) assert(a.stride(1) == 1); assert(c.stride(1) == 1); assert((TA == 'N') || (TA == 'T') || (TA == 'C')); + + using std::get; if (TA == 'N') { - assert(a.size() == c.size() and std::get<1>(a.sizes()) == std::get<1>(c.sizes())); + assert(a.size() == c.size() and get<1>(a.sizes()) == get<1>(c.sizes())); } if ((TA == 'T' or TA == 'C')) { - assert(std::get<1>(a.sizes()) == c.size() and a.size() == std::get<1>(c.sizes())); + assert(get<1>(a.sizes()) == c.size() and a.size() == get<1>(c.sizes())); } - geam(TA, TA, std::get<1>(c.sizes()), c.size(), alpha, pointer_dispatch(a.origin()), a.stride(), T(0), + using std::get; + geam(TA, TA, get<1>(c.sizes()), c.size(), alpha, pointer_dispatch(a.origin()), a.stride(), T(0), pointer_dispatch(a.origin()), a.stride(), pointer_dispatch(c.origin()), c.stride()); return std::forward(c); } diff --git a/src/AFQMC/Numerics/ma_blas_extensions.hpp b/src/AFQMC/Numerics/ma_blas_extensions.hpp index 83675608aa..b88c00d87c 100644 --- a/src/AFQMC/Numerics/ma_blas_extensions.hpp +++ b/src/AFQMC/Numerics/ma_blas_extensions.hpp @@ -51,10 +51,11 @@ template::type::dimensionality == 1>::type> void adotpby(T const alpha, MultiArray2Dx const& x, MultiArray2Dy const& y, Q const beta, MultiArray1D res) { - if (std::get<0>(x.sizes()) != std::get<0>(y.sizes()) || std::get<0>(x.sizes()) != std::get<0>(res.sizes()) || std::get<1>(x.sizes()) != std::get<1>(y.sizes()) || x.stride(1) != 1 || + using std::get; + if (get<0>(x.sizes()) != get<0>(y.sizes()) || get<0>(x.sizes()) != get<0>(res.sizes()) || get<1>(x.sizes()) != get<1>(y.sizes()) || x.stride(1) != 1 || y.stride(1) != 1) throw std::runtime_error(" Error: Inconsistent matrix dimensions in adotpby(2D).\n"); - strided_adotpby(std::get<0>(x.sizes()), std::get<1>(x.sizes()), alpha, pointer_dispatch(x.origin()), x.stride(0), pointer_dispatch(y.origin()), + strided_adotpby(get<0>(x.sizes()), get<1>(x.sizes()), alpha, pointer_dispatch(x.origin()), x.stride(0), pointer_dispatch(y.origin()), y.stride(0), beta, to_address(res.origin()), res.stride(0)); } @@ -78,11 +79,12 @@ template MultiArray2DB&& axty(T const alpha, MultiArray2DA const& A, MultiArray2DB&& B) { + using std::get; assert(A.num_elements() == B.num_elements()); assert(A.stride(1) == 1); - assert(A.stride(0) == std::get<1>(A.sizes())); + assert(A.stride(0) == get<1>(A.sizes())); assert(B.stride(1) == 1); - assert(B.stride(0) == std::get<1>(B.sizes())); + assert(B.stride(0) == get<1>(B.sizes())); axty(A.num_elements(), alpha, pointer_dispatch(A.origin()), 1, pointer_dispatch(B.origin()), 1); return B; } @@ -98,11 +100,12 @@ template::type::dimensionality == 2)>> MultiArray2DB&& acAxpbB(T const alpha, MultiArray2DA const& A, MultiArray1D const& x, T const beta, MultiArray2DB&& B) { + using std::get; assert(A.num_elements() == B.num_elements()); - assert(std::get<0>(A.sizes()) == std::get<0>(B.sizes())); - assert(std::get<1>(A.sizes()) == std::get<1>(B.sizes())); - assert(std::get<1>(A.sizes()) == std::get<0>(x.sizes())); - acAxpbB(std::get<1>(A.sizes()), std::get<0>(A.sizes()), alpha, pointer_dispatch(A.origin()), A.stride(0), pointer_dispatch(x.origin()), + assert(get<0>(A.sizes()) == get<0>(B.sizes())); + assert(get<1>(A.sizes()) == get<1>(B.sizes())); + assert(get<1>(A.sizes()) == get<0>(x.sizes())); + acAxpbB(get<1>(A.sizes()), get<0>(A.sizes()), alpha, pointer_dispatch(A.origin()), A.stride(0), pointer_dispatch(x.origin()), x.stride(0), beta, pointer_dispatch(B.origin()), B.stride(0)); return B; } @@ -114,8 +117,9 @@ template::type::dimensionality == 1>::type> MultiArray1Dy&& adiagApy(T const alpha, MultiArray2DA const& A, MultiArray1Dy&& y) { - assert(std::get<0>(A.sizes()) == std::get<1>(A.sizes())); - assert(std::get<0>(A.sizes()) == y.size()); + using std::get; + assert(get<0>(A.sizes()) == get<1>(A.sizes())); + assert(get<0>(A.sizes()) == y.size()); adiagApy(y.size(), alpha, pointer_dispatch(A.origin()), A.stride(0), pointer_dispatch(y.origin()), y.stride(0)); return y; } @@ -133,8 +137,9 @@ template(A.sizes()), std::get<0>(A.sizes()), pointer_dispatch(A.origin()), A.stride(0)); + return sum(get<1>(A.sizes()), get<0>(A.sizes()), pointer_dispatch(A.origin()), A.stride(0)); } template auto sum(MultiArray3D const& A) { + using std::get; // only arrays and array_refs for now - assert(A.stride(0) == std::get<1>(A.sizes()) * std::get<2>(A.sizes())); - assert(A.stride(1) == std::get<2>(A.sizes())); + assert(A.stride(0) == get<1>(A.sizes()) * get<2>(A.sizes())); + assert(A.stride(1) == get<2>(A.sizes())); assert(A.stride(2) == 1); return sum(A.num_elements(), pointer_dispatch(A.origin()), 1); } @@ -157,10 +163,11 @@ template auto sum(MultiArray4D const& A) { + using std::get; // only arrays and array_refs for now - assert(A.stride(0) == std::get<1>(A.sizes()) * std::get<2>(A.sizes()) * std::get<3>(A.sizes())); - assert(A.stride(1) == std::get<2>(A.sizes()) * std::get<3>(A.sizes())); - assert(A.stride(2) == std::get<3>(A.sizes())); + assert(A.stride(0) == get<1>(A.sizes()) * get<2>(A.sizes()) * get<3>(A.sizes())); + assert(A.stride(1) == get<2>(A.sizes()) * get<3>(A.sizes())); + assert(A.stride(2) == get<3>(A.sizes())); assert(A.stride(3) == 1); return sum(A.num_elements(), pointer_dispatch(A.origin()), 1); } @@ -170,7 +177,8 @@ template::type::dimensionality == 1>> MultiArray1D&& setVector(T alpha, MultiArray1D&& a) { - set1D(std::get<0>(a.sizes()), alpha, pointer_dispatch(a.origin()), a.stride(0)); + using std::get; + set1D(get<0>(a.sizes()), alpha, pointer_dispatch(a.origin()), a.stride(0)); return std::forward(a); } @@ -183,7 +191,8 @@ void zero_complex_part(MultiArray1D&& a) template::type::dimensionality == 2>> MultiArray2D&& set_identity(MultiArray2D&& m) { - set_identity(std::get<1>(m.sizes()), std::get<0>(m.sizes()), pointer_dispatch(m.origin()), m.stride(0)); + using std::get; + set_identity(get<1>(m.sizes()), get<0>(m.sizes()), pointer_dispatch(m.origin()), m.stride(0)); return std::forward(m); } @@ -192,7 +201,8 @@ template MultiArray3D&& set_identity(MultiArray3D&& m) { - set_identity_strided(std::get<0>(m.sizes()), m.stride(0), std::get<2>(m.sizes()), std::get<1>(m.sizes()), pointer_dispatch(m.origin()), m.stride(1)); + using std::get; + set_identity_strided(get<0>(m.sizes()), m.stride(0), get<2>(m.sizes()), get<1>(m.sizes()), pointer_dispatch(m.origin()), m.stride(1)); return std::forward(m); } @@ -202,7 +212,8 @@ template(m.sizes()), std::get<1>(m.sizes()), pointer_dispatch(m.origin()), m.stride(0), value); + using std::get; + fill2D(get<0>(m.sizes()), get<1>(m.sizes()), pointer_dispatch(m.origin()), m.stride(0), value); return std::forward(m); } @@ -213,10 +224,11 @@ template::type::dimensionality == 2>> void get_diagonal_strided(MultiArray3D const& B, MultiArray2D&& A) { - if (std::get<0>(A.sizes()) != std::get<0>(B.sizes()) || std::get<1>(A.sizes()) != std::get<1>(B.sizes()) || std::get<1>(A.sizes()) != std::get<2>(B.sizes()) || A.stride(1) != 1 || + using std::get; + if (get<0>(A.sizes()) != get<0>(B.sizes()) || get<1>(A.sizes()) != get<1>(B.sizes()) || get<1>(A.sizes()) != get<2>(B.sizes()) || A.stride(1) != 1 || B.stride(2) != 1) throw std::runtime_error(" Error: Inconsistent matrix dimensions in get_diagonal_strided.\n"); - get_diagonal_strided(std::get<0>(A.sizes()), std::get<1>(A.sizes()), pointer_dispatch(B.origin()), B.stride(1), B.stride(0), + get_diagonal_strided(get<0>(A.sizes()), get<1>(A.sizes()), pointer_dispatch(B.origin()), B.stride(1), B.stride(0), pointer_dispatch(A.origin()), A.stride(0)); } @@ -226,18 +238,21 @@ template> void Matrix2MA(char TA, CSR const& A, MultiArray2D& M) { + using std::get; using Type = typename MultiArray2D::element; using int_type = typename CSR::int_type; + + using std::get; assert(TA == 'N' || TA == 'H' || TA == 'T' || TA == 'Z'); if (TA == 'N' || TA == 'Z') { - if (std::get<0>(M.sizes()) != std::get<0>(A.sizes()) or std::get<1>(M.sizes()) != std::get<1>(A.sizes())) + if (get<0>(M.sizes()) != get<0>(A.sizes()) or get<1>(M.sizes()) != get<1>(A.sizes())) M.reextent({static_cast(A.size(0)), static_cast(A.size(1))}); } else if (TA == 'T' || TA == 'H') { - if (std::get<0>(M.sizes()) != std::get<1>(A.sizes()) or std::get<1>(M.sizes()) != std::get<0>(A.sizes())) - M.reextent({static_cast(std::get<1>(A.sizes())), static_cast(std::get<0>(A.sizes()))}); + if (get<0>(M.sizes()) != get<1>(A.sizes()) or get<1>(M.sizes()) != get<0>(A.sizes())) + M.reextent({static_cast(get<1>(A.sizes())), static_cast(get<0>(A.sizes()))}); } else { @@ -287,12 +302,13 @@ template> void Matrix2MAREF(char TA, CSR const& A, MultiArray2D& M) { + using std::get; using Type = typename MultiArray2D::element; using int_type = typename CSR::int_type; assert(TA == 'N' || TA == 'H' || TA == 'T' || TA == 'Z'); - if ((TA == 'N' || TA == 'Z') && ((std::get<0>(M.sizes()) != std::get<0>(A.sizes())) || (std::get<1>(M.sizes()) != std::get<1>(A.sizes())))) + if ((TA == 'N' || TA == 'Z') && ((get<0>(M.sizes()) != get<0>(A.sizes())) || (get<1>(M.sizes()) != get<1>(A.sizes())))) throw std::runtime_error(" Error: Wrong dimensions in Matrix2MAREF.\n"); - else if ((TA == 'T' || TA == 'H') && ((std::get<0>(M.sizes()) != std::get<1>(A.sizes())) || (std::get<1>(M.sizes()) != std::get<0>(A.sizes())))) + else if ((TA == 'T' || TA == 'H') && ((get<0>(M.sizes()) != get<1>(A.sizes())) || (get<1>(M.sizes()) != get<0>(A.sizes())))) throw std::runtime_error(" Error: Wrong dimensions in Matrix2MAREF.\n"); using std::fill_n; fill_n(M.origin(), M.num_elements(), Type(0)); @@ -340,21 +356,25 @@ template> void Matrix2MA(char TA, CSR const& A, MultiArray2D& M, Vector const& occups) { + using std::get; + using Type = typename MultiArray2D::element; if (occups.size() == 0) throw std::runtime_error(" Error: Empty occupation array in Matrix2MA.\n"); assert(occups.size() <= A.size(0)); int nrows = occups.size(); + + using std::get; assert(TA == 'N' || TA == 'H' || TA == 'T' || TA == 'Z'); if (TA == 'N' || TA == 'Z') { - if (std::get<0>(M.sizes()) != nrows || std::get<1>(M.sizes()) != std::get<1>(A.sizes())) - M.reextent({nrows, static_cast(std::get<1>(A.sizes()))}); + if (get<0>(M.sizes()) != nrows || get<1>(M.sizes()) != get<1>(A.sizes())) + M.reextent({nrows, static_cast(get<1>(A.sizes()))}); } else if (TA == 'T' || TA == 'H') { - if (std::get<1>(M.sizes()) != nrows || std::get<0>(M.sizes()) != std::get<1>(A.sizes())) - M.reextent({static_cast(std::get<1>(A.sizes())), nrows}); + if (get<1>(M.sizes()) != nrows || get<0>(M.sizes()) != get<1>(A.sizes())) + M.reextent({static_cast(get<1>(A.sizes())), nrows}); } else throw std::runtime_error(" Error: Unknown operation in Matrix2MA.\n"); @@ -414,18 +434,20 @@ template void Matrix2MA(char TA, MA const& A, MultiArray2D& M) { + using std::get; + using Type1 = typename std::decay::type::element; using Type2 = typename MultiArray2D::element; assert(TA == 'N' || TA == 'H' || TA == 'T' || TA == 'Z'); if (TA == 'N' || TA == 'Z') { - if (std::get<0>(M.sizes()) != std::get<0>(A.sizes()) or std::get<1>(M.sizes()) != std::get<1>(A.sizes())) - M.reextent({std::get<0>(A.sizes()), std::get<1>(A.sizes())}); + if (get<0>(M.sizes()) != get<0>(A.sizes()) or get<1>(M.sizes()) != get<1>(A.sizes())) + M.reextent({get<0>(A.sizes()), get<1>(A.sizes())}); } else if (TA == 'T' || TA == 'H') { - if (std::get<0>(M.sizes()) != std::get<1>(A.sizes()) or std::get<1>(M.sizes()) != std::get<0>(A.sizes())) - M.reextent({std::get<1>(A.sizes()), std::get<0>(A.sizes())}); + if (get<0>(M.sizes()) != get<1>(A.sizes()) or get<1>(M.sizes()) != get<0>(A.sizes())) + M.reextent({get<1>(A.sizes()), get<0>(A.sizes())}); } else { @@ -439,34 +461,34 @@ void Matrix2MA(char TA, MA const& A, MultiArray2D& M) TA = 'C'; if (TA == 'Z') { - for (int i = 0; i < std::get<0>(M.sizes()); i++) - for (int j = 0; j < std::get<1>(M.sizes()); j++) + for (int i = 0; i < get<0>(M.sizes()); i++) + for (int j = 0; j < get<1>(M.sizes()); j++) M[i][j] = ma::conj(A[i][j]); } else if (not std::is_same::value) { if (TA == 'N') { - for (int i = 0; i < std::get<0>(M.sizes()); i++) - for (int j = 0; j < std::get<1>(M.sizes()); j++) + for (int i = 0; i < get<0>(M.sizes()); i++) + for (int j = 0; j < get<1>(M.sizes()); j++) M[i][j] = A[i][j]; } else if (TA == 'T') { - for (int i = 0; i < std::get<0>(M.sizes()); i++) - for (int j = 0; j < std::get<1>(M.sizes()); j++) + for (int i = 0; i < get<0>(M.sizes()); i++) + for (int j = 0; j < get<1>(M.sizes()); j++) M[i][j] = A[j][i]; } else if (TA == 'C') { - for (int i = 0; i < std::get<0>(M.sizes()); i++) - for (int j = 0; j < std::get<1>(M.sizes()); j++) + for (int i = 0; i < get<0>(M.sizes()); i++) + for (int j = 0; j < get<1>(M.sizes()); j++) M[i][j] = ma::conj(A[j][i]); } } else { - geam(TA, TA, std::get<1>(M.sizes()), std::get<0>(M.sizes()), Type2(1.0), pointer_dispatch(A.origin()), A.stride(0), Type2(0.0), + geam(TA, TA, get<1>(M.sizes()), get<0>(M.sizes()), Type2(1.0), pointer_dispatch(A.origin()), A.stride(0), Type2(0.0), pointer_dispatch(A.origin()), A.stride(0), pointer_dispatch(M.origin()), M.stride(0)); } } @@ -481,14 +503,16 @@ void Matrix2MAREF(char TA, MA const& A, MultiArray2D& M) using Type1 = typename std::decay::type::element; using Type2 = typename MultiArray2D::element; assert(TA == 'N' || TA == 'H' || TA == 'T' || TA == 'Z'); + + using std::get; if (TA == 'N' || TA == 'Z') { - if (std::get<0>(M.sizes()) != std::get<0>(A.sizes()) or std::get<1>(M.sizes()) != std::get<1>(A.sizes())) + if (get<0>(M.sizes()) != get<0>(A.sizes()) or get<1>(M.sizes()) != get<1>(A.sizes())) throw std::runtime_error(" Error: Wrong dimensions in Matrix2MAREF.\n"); } else if (TA == 'T' || TA == 'H') { - if (std::get<0>(M.sizes()) != std::get<1>(A.sizes()) or std::get<1>(M.sizes()) != std::get<0>(A.sizes())) + if (get<0>(M.sizes()) != get<1>(A.sizes()) or get<1>(M.sizes()) != get<0>(A.sizes())) throw std::runtime_error(" Error: Wrong dimensions in Matrix2MAREF.\n"); } else @@ -504,34 +528,34 @@ void Matrix2MAREF(char TA, MA const& A, MultiArray2D& M) if (TA == 'Z') { // bad i gpu's - for (int i = 0; i < std::get<0>(M.sizes()); i++) - for (int j = 0; j < std::get<1>(M.sizes()); j++) + for (int i = 0; i < get<0>(M.sizes()); i++) + for (int j = 0; j < get<1>(M.sizes()); j++) M[i][j] = ma::conj(A[i][j]); } else if (not std::is_same::value) { if (TA == 'N') { - for (int i = 0; i < std::get<0>(M.sizes()); i++) - for (int j = 0; j < std::get<1>(M.sizes()); j++) + for (int i = 0; i < get<0>(M.sizes()); i++) + for (int j = 0; j < get<1>(M.sizes()); j++) M[i][j] = A[i][j]; } else if (TA == 'T') { - for (int i = 0; i < std::get<0>(M.sizes()); i++) - for (int j = 0; j < std::get<1>(M.sizes()); j++) + for (int i = 0; i < get<0>(M.sizes()); i++) + for (int j = 0; j < get<1>(M.sizes()); j++) M[i][j] = A[j][i]; } else if (TA == 'C') { - for (int i = 0; i < std::get<0>(M.sizes()); i++) - for (int j = 0; j < std::get<1>(M.sizes()); j++) + for (int i = 0; i < get<0>(M.sizes()); i++) + for (int j = 0; j < get<1>(M.sizes()); j++) M[i][j] = ma::conj(A[j][i]); } } else { - geam(TA, TA, std::get<1>(M.sizes()), std::get<0>(M.sizes()), Type2(1.0), pointer_dispatch(A.origin()), A.stride(0), Type2(0.0), + geam(TA, TA, get<1>(M.sizes()), get<0>(M.sizes()), Type2(1.0), pointer_dispatch(A.origin()), A.stride(0), Type2(0.0), pointer_dispatch(A.origin()), A.stride(0), pointer_dispatch(M.origin()), M.stride(0)); } } diff --git a/src/AFQMC/Numerics/ma_lapack.hpp b/src/AFQMC/Numerics/ma_lapack.hpp index fe93adc32b..8ee74043bd 100644 --- a/src/AFQMC/Numerics/ma_lapack.hpp +++ b/src/AFQMC/Numerics/ma_lapack.hpp @@ -31,22 +31,24 @@ int getrf_optimal_workspace_size(MultiArray2D&& A) assert(A.stride(0) > 0); assert(A.stride(1) == 1); + using std::get; int res; - getrf_bufferSize(std::get<1>(A.sizes()), std::get<0>(A.sizes()), pointer_dispatch(A.origin()), A.stride(0), res); + getrf_bufferSize(get<1>(A.sizes()), get<0>(A.sizes()), pointer_dispatch(A.origin()), A.stride(0), res); return res; } template MultiArray2D&& getrf(MultiArray2D&& m, Array1D& pivot, Buffer&& WORK) { - assert(m.stride(0) >= std::max(std::size_t(1), std::size_t(std::get<1>(m.sizes())))); + using std::get; + assert(m.stride(0) >= std::max(std::size_t(1), std::size_t(get<1>(m.sizes())))); assert(m.stride(1) == 1); - assert(pivot.size() >= std::min(std::get<1>(m.sizes()), std::get<0>(m.sizes()) + 1)); + assert(pivot.size() >= std::min(get<1>(m.sizes()), get<0>(m.sizes()) + 1)); int status = -1; - getrf(std::get<1>(m.sizes()), std::get<0>(m.sizes()), pointer_dispatch(m.origin()), m.stride(0), pointer_dispatch(pivot.data()), status, + getrf(get<1>(m.sizes()), get<0>(m.sizes()), pointer_dispatch(m.origin()), m.stride(0), pointer_dispatch(pivot.data()), status, pointer_dispatch(WORK.data())); - //assert(status==0); + // assert(status==0); return std::forward(m); } @@ -54,7 +56,9 @@ template int getri_optimal_workspace_size(MultiArray2D&& A) { assert(A.stride(1) == 1); - assert(std::get<0>(A.sizes()) ==std::get<1>(A.sizes())); + + using std::get; + assert(get<0>(A.sizes()) == get<1>(A.sizes())); int lwork = -1; getri_bufferSize(A.size(), pointer_dispatch(A.origin()), A.stride(), lwork); return lwork; @@ -63,7 +67,7 @@ int getri_optimal_workspace_size(MultiArray2D&& A) template MultiArray2D&& getri(MultiArray2D&& A, MultiArray1D const& IPIV, Buffer&& WORK) { - // assert(A.stride(0) > std::max(std::size_t(1), A.size(1))); + // assert(A.stride(0) > std::max(std::size_t(1), A.size(1))); assert(A.stride(1) == 1); assert(IPIV.size() >= size_t(A.size())); assert(WORK.size() >= std::max(std::size_t(1), size_t(A.size()))); @@ -81,23 +85,25 @@ int geqrf_optimal_workspace_size(MultiArray2D&& A) assert(A.stride(0) > 0); assert(A.stride(1) == 1); + using std::get; int res; - geqrf_bufferSize(std::get<1>(A.sizes()), std::get<0>(A.sizes()), pointer_dispatch(A.origin()), A.stride(0), res); + geqrf_bufferSize(get<1>(A.sizes()), get<0>(A.sizes()), pointer_dispatch(A.origin()), A.stride(0), res); return res; } template MultiArray2D&& geqrf(MultiArray2D&& A, Array1D&& TAU, Buffer&& WORK) { + using std::get; // why was this here??? //assert(A.stride(0) > std::max(std::size_t(1), A.size(0))); assert(A.stride(1) == 1); assert(TAU.stride(0) == 1); - assert(TAU.size() >= std::max(std::size_t(1), size_t(std::min(std::get<0>(A.sizes()), std::get<1>(A.sizes()))))); + assert(TAU.size() >= std::max(std::size_t(1), size_t(std::min(get<0>(A.sizes()), get<1>(A.sizes()))))); assert(WORK.size() >= std::max(std::size_t(1), size_t(A.size()))); int status = -1; - geqrf(std::get<1>(A.sizes()), std::get<0>(A.sizes()), pointer_dispatch(A.origin()), A.stride(0), pointer_dispatch(TAU.origin()), + geqrf(get<1>(A.sizes()), get<0>(A.sizes()), pointer_dispatch(A.origin()), A.stride(0), pointer_dispatch(TAU.origin()), pointer_dispatch(WORK.data()), WORK.size(), status); assert(status == 0); return std::forward(A); @@ -109,22 +115,25 @@ int gelqf_optimal_workspace_size(MultiArray2D&& A) assert(A.stride(0) > 0); assert(A.stride(1) == 1); + using std::get; int res; - gelqf_bufferSize(std::get<1>(A.sizes()), std::get<0>(A.sizes()), pointer_dispatch(A.origin()), A.stride(0), res); + gelqf_bufferSize(get<1>(A.sizes()), get<0>(A.sizes()), pointer_dispatch(A.origin()), A.stride(0), res); return res; } template MultiArray2D&& gelqf(MultiArray2D&& A, Array1D&& TAU, Buffer&& WORK) { + using std::get; assert(A.stride(1) > 0); assert(A.stride(1) == 1); assert(TAU.stride(0) == 1); - assert(TAU.size() >= std::max(std::size_t(1), size_t(std::min(std::get<0>(A.sizes()), std::get<1>(A.sizes()))))); - assert(WORK.size() >= std::max(std::size_t(1), size_t(std::get<1>(A.sizes())))); + assert(TAU.size() >= std::max(std::size_t(1), size_t(std::min(get<0>(A.sizes()), get<1>(A.sizes()))))); + assert(WORK.size() >= std::max(std::size_t(1), size_t(get<1>(A.sizes())))); + using std::get; int status = -1; - gelqf(std::get<1>(A.sizes()), std::get<0>(A.sizes()), pointer_dispatch(A.origin()), A.stride(0), pointer_dispatch(TAU.data()), + gelqf(get<1>(A.sizes()), get<0>(A.sizes()), pointer_dispatch(A.origin()), A.stride(0), pointer_dispatch(TAU.data()), pointer_dispatch(WORK.data()), WORK.size(), status); assert(status == 0); return std::forward(A); @@ -137,8 +146,9 @@ int gqr_optimal_workspace_size(MultiArray2D&& A) assert(A.stride(0) > 0); assert(A.stride(1) == 1); + using std::get; int res; - gqr_bufferSize(std::get<1>(A.sizes()), std::get<0>(A.sizes()), std::max(std::size_t(1), size_t(std::min(std::get<0>(A.sizes()), std::get<1>(A.sizes())))), + gqr_bufferSize(get<1>(A.sizes()), get<0>(A.sizes()), std::max(std::size_t(1), size_t(std::min(get<0>(A.sizes()), get<1>(A.sizes())))), pointer_dispatch(A.origin()), A.stride(0), res); return res; } @@ -146,13 +156,14 @@ int gqr_optimal_workspace_size(MultiArray2D&& A) template MultiArray2D&& gqr(MultiArray2D&& A, Array1D&& TAU, Buffer&& WORK) { + using std::get; assert(A.stride(1) == 1); assert(TAU.stride(0) == 1); - assert(TAU.size() >= std::max(std::size_t(1), size_t(std::min(std::get<0>(A.sizes()), std::get<1>(A.sizes()))))); + assert(TAU.size() >= std::max(std::size_t(1), size_t(std::min(get<0>(A.sizes()), get<1>(A.sizes()))))); assert(WORK.size() >= std::max(std::size_t(1), size_t(A.size()))); int status = -1; - gqr(std::get<1>(A.sizes()), std::get<0>(A.sizes()), std::max(std::size_t(1), size_t(std::min(std::get<0>(A.sizes()), std::get<1>(A.sizes())))), + gqr(get<1>(A.sizes()), get<0>(A.sizes()), std::max(std::size_t(1), size_t(std::min(get<0>(A.sizes()), get<1>(A.sizes())))), pointer_dispatch(A.origin()), A.stride(0), pointer_dispatch(TAU.origin()), pointer_dispatch(WORK.data()), WORK.size(), status); assert(status == 0); @@ -165,8 +176,9 @@ int glq_optimal_workspace_size(MultiArray2D&& A) assert(A.stride(0) > 0); assert(A.stride(1) == 1); + using std::get; int res; - glq_bufferSize(std::get<1>(A.sizes()), std::get<0>(A.sizes()), std::max(std::size_t(1), size_t(std::min(std::get<0>(A.sizes()), std::get<1>(A.sizes())))), + glq_bufferSize(get<1>(A.sizes()), get<0>(A.sizes()), std::max(std::size_t(1), size_t(std::min(get<0>(A.sizes()), get<1>(A.sizes())))), pointer_dispatch(A.origin()), A.stride(0), res); return res; } @@ -174,13 +186,15 @@ int glq_optimal_workspace_size(MultiArray2D&& A) template MultiArray2D&& glq(MultiArray2D&& A, Array1D&& TAU, Buffer&& WORK) { + using std::get; + assert(A.stride(1) == 1); assert(TAU.stride(0) == 1); - assert(TAU.size() >= std::max(std::size_t(1), size_t(std::min(std::get<0>(A.sizes()), std::get<1>(A.sizes()))))); - assert(WORK.size() >= std::max(std::size_t(1), size_t(std::get<1>(A.sizes())))); + assert(TAU.size() >= std::max(std::size_t(1), size_t(std::min(get<0>(A.sizes()), get<1>(A.sizes()))))); + assert(WORK.size() >= std::max(std::size_t(1), size_t(get<1>(A.sizes())))); int status = -1; - glq(std::get<1>(A.sizes()), std::get<0>(A.sizes()), std::max(std::size_t(1), size_t(std::min(std::get<0>(A.sizes()), std::get<1>(A.sizes())))), + glq(get<1>(A.sizes()), get<0>(A.sizes()), std::max(std::size_t(1), size_t(std::min(get<0>(A.sizes()), get<1>(A.sizes())))), pointer_dispatch(A.origin()), A.stride(0), pointer_dispatch(TAU.data()), pointer_dispatch(WORK.data()), WORK.size(), status); assert(status == 0); @@ -203,8 +217,9 @@ int gesvd_optimal_workspace_size(MultiArray2D&& A) assert(A.stride(0) > 0); assert(A.stride(1) == 1); + using std::get; int res; - gesvd_bufferSize(std::get<1>(A.sizes()), std::get<0>(A.sizes()), pointer_dispatch(A.origin()), res); + gesvd_bufferSize(get<1>(A.sizes()), get<0>(A.sizes()), pointer_dispatch(A.origin()), res); return res; } @@ -221,11 +236,13 @@ MultiArray2D&& gesvd(char jobU, assert(A.stride(1) > 0); assert(A.stride(1) == 1); + using std::get; + // in C: A = U * S * VT // in F: At = (U * S * VT)t = VTt * S * Ut // so I need to switch U <--> VT when calling fortran interface int status = -1; - gesvd(jobVT, jobU, std::get<1>(A.sizes()), std::get<0>(A.sizes()), pointer_dispatch(A.origin()), A.stride(0), pointer_dispatch(S.origin()), + gesvd(jobVT, jobU, get<1>(A.sizes()), get<0>(A.sizes()), pointer_dispatch(A.origin()), A.stride(0), pointer_dispatch(S.origin()), pointer_dispatch(VT.origin()), VT.stride(0), // !!! pointer_dispatch(U.origin()), U.stride(0), // !!! pointer_dispatch(WORK.data()), WORK.size(), pointer_dispatch(RWORK.origin()), status); @@ -243,7 +260,9 @@ std::pair symEig(MultiArray2D const& A) using Type = typename MultiArray2D::element; using RealType = typename qmcplusplus::afqmc::remove_complex::value_type; using extensions = typename boost::multi::layout_t<1u>::extensions_type; - assert(A.size() == std::get<1>(A.sizes())); + + using std::get; + assert(A.size() == get<1>(A.sizes())); assert(A.stride(1) == 1); assert(A.size() > 0); int N = A.size(); @@ -316,10 +335,12 @@ std::pair symEigSelect(MultiArray2DA& A, int neig) static_assert(std::is_same::value, "Wrong types."); using RealType = typename qmcplusplus::afqmc::remove_complex::value_type; using extensions = typename boost::multi::layout_t<1u>::extensions_type; - assert(std::get<0>(A.sizes()) == std::get<1>(A.sizes())); + + using std::get; + assert(get<0>(A.sizes()) == get<1>(A.sizes())); assert(A.stride(1) == 1); - assert(std::get<0>(A.sizes()) > 0); - int N = std::get<0>(A.sizes()); + assert(get<0>(A.sizes()) > 0); + int N = get<0>(A.sizes()); int LDA = A.stride(0); MultiArray1D eigVal(extensions{neig}); @@ -394,14 +415,16 @@ std::pair genEigSelect(MultiArray2DA& A, MultiArray2 static_assert(std::is_same::value, "Wrong types."); using RealType = typename qmcplusplus::afqmc::remove_complex::value_type; using extensions = typename boost::multi::layout_t<1u>::extensions_type; - assert(std::get<0>(A.sizes()) == std::get<1>(A.sizes())); - assert(std::get<0>(A.sizes()) == std::get<0>(S.sizes())); - assert(std::get<0>(S.sizes()) == std::get<1>(S.sizes())); + + using std::get; + assert(get<0>(A.sizes()) == get<1>(A.sizes())); + assert(get<0>(A.sizes()) == get<0>(S.sizes())); + assert(get<0>(S.sizes()) == get<1>(S.sizes())); assert(A.stride(1) == 1); - assert(std::get<0>(A.sizes()) > 0); + assert(get<0>(A.sizes()) > 0); assert(S.stride(1) == 1); - assert(std::get<0>(S.sizes()) > 0); - int N = std::get<0>(A.sizes()); + assert(get<0>(S.sizes()) > 0); + int N = get<0>(A.sizes()); int LDA = A.stride(0); int LDS = S.stride(0); diff --git a/src/AFQMC/Numerics/ma_operations.hpp b/src/AFQMC/Numerics/ma_operations.hpp index 5e4c8c47f6..a0f2a83a30 100644 --- a/src/AFQMC/Numerics/ma_operations.hpp +++ b/src/AFQMC/Numerics/ma_operations.hpp @@ -42,11 +42,13 @@ using qmcplusplus::afqmc::to_address; template 1)>::type> bool is_hermitian(MultiArray2D const& A) { + using std::get; + using ma::conj; - if (A.size() != std::get<1>(A.sizes())) + if (A.size() != get<1>(A.sizes())) return false; - for (int i = 0; i != std::get<0>(A.sizes()); ++i) - for (int j = i + 1; j != std::get<1>(A.sizes()); ++j) + for (int i = 0; i != get<0>(A.sizes()); ++i) + for (int j = i + 1; j != get<1>(A.sizes()); ++j) if (std::abs(A[i][j] - ma::conj(A[j][i])) > 1e-12) return false; return true; @@ -256,20 +258,23 @@ MultiArray2DC&& product(T alpha, SparseMatrixA const& A, MultiArray2DB const& B, assert(op_tag::value == 'N'); assert(arg(B).stride(1) == 1); assert(std::forward(C).stride(1) == 1); + + using std::get; if (op_tag::value == 'N') { assert(arg(A).size() == std::forward(C).size()); assert( arg(A).size(1) == arg(B).size() ); - assert( std::get<1>(arg(B).sizes()) == std::get<1>(std::forward(C).sizes()) ); + + assert( get<1>(arg(B).sizes()) == get<1>(std::forward(C).sizes()) ); } else { assert(arg(A).size() == arg(B).size()); - assert(std::get<1>(arg(A).sizes()) == std::forward(C).size()); - assert(std::get<1>(arg(B).sizes()) == std::get<1>(std::forward(C).sizes())); + assert(get<1>(arg(A).sizes()) == std::forward(C).size()); + assert(get<1>(arg(B).sizes()) == get<1>(std::forward(C).sizes())); } - csrmm(op_tag::value, arg(A).size(), std::get<1>(arg(B).sizes()), std::get<1>(arg(A).sizes()), elementA(alpha), "GxxCxx", + csrmm(op_tag::value, arg(A).size(), get<1>(arg(B).sizes()), get<1>(arg(A).sizes()), elementA(alpha), "GxxCxx", pointer_dispatch(arg(A).non_zero_values_data()), pointer_dispatch(arg(A).non_zero_indices2_data()), pointer_dispatch(arg(A).pointers_begin()), pointer_dispatch(arg(A).pointers_end()), pointer_dispatch(arg(B).origin()), arg(B).stride(), elementA(beta), pointer_dispatch(C.origin()), C.stride()); @@ -336,13 +341,14 @@ void BatchedProduct(char TA, using pointerC = decltype(pointer_dispatch((*C[0]).origin())); using element = typename pointedType::element; - int M = std::get<1>((*C[0]).sizes()); + using std::get; + int M = get<1>((*C[0]).sizes()); int N = (*C[0]).size(); int K; if (TB == 'N') K = (*B[0]).size(); else - K = std::get<1>((*B[0]).sizes()); + K = get<1>((*B[0]).sizes()); int lda = (*A[0]).stride(); int ldb = (*B[0]).stride(); int ldc = (*C[0]).stride(); @@ -357,27 +363,27 @@ void BatchedProduct(char TA, assert(lda == (*A[i]).stride()); assert(ldb == (*B[i]).stride()); assert(ldc == (*C[i]).stride()); - assert(M == std::get<1>((*C[i]).sizes())); + assert(M == get<1>((*C[i]).sizes())); assert(N == (*C[i]).size()); if (TB == 'N') { assert(K == (*B[i]).size()); - assert(M == std::get<1>((*B[i]).sizes())); + assert(M == get<1>((*B[i]).sizes())); } else { - assert(K == std::get<1>((*B[i]).sizes())); + assert(K == get<1>((*B[i]).sizes())); assert(M == (*B[i]).size()); } if (TA == 'N') { - assert(K == std::get<1>((*A[i]).sizes())); + assert(K == get<1>((*A[i]).sizes())); assert(N == (*A[i]).size()); } else { assert(K == (*A[i]).size()); - assert(N == std::get<1>((*A[i]).sizes())); + assert(N == get<1>((*A[i]).sizes())); } Ai.emplace_back(pointer_dispatch((*A[i]).origin())); Bi.emplace_back(pointer_dispatch((*B[i]).origin())); @@ -426,9 +432,11 @@ void BatchedProduct(char TA, } */ + using std::get; + for (int i = 0; i < nbatch; i++) { - csrmm(TA, (*A[i]).size(), std::get<1>((*B[i]).sizes()), std::get<1>((*A[i]).sizes()), elementA(alpha), "GxxCxx", + csrmm(TA, (*A[i]).size(), get<1>((*B[i]).sizes()), get<1>((*A[i]).sizes()), elementA(alpha), "GxxCxx", pointer_dispatch((*A[i]).non_zero_values_data()), pointer_dispatch((*A[i]).non_zero_indices2_data()), pointer_dispatch((*A[i]).pointers_begin()), pointer_dispatch((*A[i]).pointers_end()), pointer_dispatch((*B[i]).origin()), (*B[i]).stride(), elementA(beta), pointer_dispatch((*C[i]).origin()), @@ -568,7 +576,7 @@ auto herm(MA2D&& arg) -> decltype(hermitian(std::forward(arg))) } //template auto norm(MA2D&& arg) //->decltype(normal(std::forward(arg))){ -// return normal(std::forward(arg)); +// return normal(std::forward(arg)); //} template @@ -592,8 +600,10 @@ T invert(MultiArray2D&& m, T LogOverlapFactor) getrf(std::forward(m), pivot, WORK); T detvalue = determinant_from_getrf(m.size(), pointer_dispatch(m.origin()), m.stride(), pointer_dispatch(pivot.data()), LogOverlapFactor); + using std::get; + if (std::abs(detvalue) == 0.0) - fill2D(m.size(), std::get<1>(m.sizes()), pointer_dispatch(m.origin()), m.stride(), element(0.0)); + fill2D(m.size(), get<1>(m.sizes()), pointer_dispatch(m.origin()), m.stride(), element(0.0)); else getri(std::forward(m), pivot, WORK); return detvalue; @@ -602,7 +612,8 @@ T invert(MultiArray2D&& m, T LogOverlapFactor) template T invert(MultiArray2D&& m, MultiArray1D&& pivot, Buffer&& WORK, T LogOverlapFactor) { - assert(m.size() == std::get<1>(m.sizes())); + using std::get; + assert(m.size() == get<1>(m.sizes())); assert(pivot.size() >= m.size() + 1); using element = typename std::decay::type::element; using qmcplusplus::afqmc::fill2D; @@ -610,8 +621,10 @@ T invert(MultiArray2D&& m, MultiArray1D&& pivot, Buffer&& WORK, T LogOverlapFact getrf(std::forward(m), pivot, WORK); T detvalue = determinant_from_getrf(m.size(), pointer_dispatch(m.origin()), m.stride(), pointer_dispatch(pivot.data()), LogOverlapFactor); + + using std::get; if (std::abs(detvalue) == 0.0) - fill2D(m.size(), std::get<1>(m.sizes()), pointer_dispatch(m.origin()), m.stride(), element(0.0)); + fill2D(m.size(), get<1>(m.sizes()), pointer_dispatch(m.origin()), m.stride(), element(0.0)); else getri(std::forward(m), pivot, WORK); return detvalue; @@ -646,7 +659,8 @@ void invert_withSVD(MultiArray2D&& m, MultiArray1DS&& S, MultiArray2DU&& U, Mult template T determinant(MultiArray2D&& m, MultiArray1D&& pivot, Buffer&& WORK, T LogOverlapFactor) { - assert(m.size() == std::get<1>(m.sizes())); + using std::get; + assert(m.size() == get<1>(m.sizes())); assert(pivot.size() >= m.size()); getrf(std::forward(m), std::forward(pivot), WORK); @@ -662,7 +676,9 @@ MultiArray2D exp(MultiArray2D const& A, bool printeV = false) using TVec = boost::multi::array; using TMat = boost::multi::array; using eigSys = std::pair; - assert(A.size() == std::get<1>(A.sizes())); + + using std::get; + assert(A.size() == get<1>(A.sizes())); typename MultiArray2D::size_type N = A.size(); MultiArray2D ExpA({N, N}); @@ -745,7 +761,7 @@ int main() std::vector m = { 9., 24., 30., 4., 10., 12., 14., 16., 36. //, - // 9., 6., 1. + // 9., 6., 1. }; boost::multi::array_ref M(m.data(), {3, 3}); assert(M.num_elements() == m.size()); diff --git a/src/AFQMC/Numerics/tests/test_batched_operations.cpp b/src/AFQMC/Numerics/tests/test_batched_operations.cpp index 875330bfe2..8811a0f19f 100644 --- a/src/AFQMC/Numerics/tests/test_batched_operations.cpp +++ b/src/AFQMC/Numerics/tests/test_batched_operations.cpp @@ -277,7 +277,9 @@ TEST_CASE("Awiu_Biu_Cuw", "[Numerics][batched_operations]") ComplexType alpha = 0.5; // C = alpha * numpy.einsum('wnu,nu->uw', A, B) using ma::Awiu_Biu_Cuw; - Awiu_Biu_Cuw(nu, nw, nn, alpha, A.origin(), B.origin(), std::get<1>(B.sizes()), C.origin(), std::get<1>(C.sizes())); + + using std::get; + Awiu_Biu_Cuw(nu, nw, nn, alpha, A.origin(), B.origin(), get<1>(B.sizes()), C.origin(), get<1>(C.sizes())); Tensor2D ref({nu, nw}, 4.0, alloc); ref[1][0] = 3.0; ref[1][1] = 3.0; @@ -296,7 +298,8 @@ TEST_CASE("Aijk_Bkj_Cik", "[Numerics][batched_operations]") Tensor2D C({ni, nk}, 0.0, alloc); // C = alpha * numpy.einsum('wnu,nu->uw', A, B) using ma::Aijk_Bkj_Cik; - Aijk_Bkj_Cik(ni, nj, nk, A.origin(), std::get<1>(A.sizes()), A.stride(0), B.origin(), B.stride(0), C.origin(), C.stride(0)); + using std::get; + Aijk_Bkj_Cik(ni, nj, nk, A.origin(), get<1>(A.sizes()), A.stride(0), B.origin(), B.stride(0), C.origin(), C.stride(0)); Tensor2D ref({ni, nk}, 4.0, alloc); ref[0][0] = 2.0; ref[1][0] = 2.0; @@ -331,8 +334,9 @@ TEST_CASE("element_wise_Aij_Bjk_Ckij", "[Numerics][batched_operations]") Tensor2D A({ni, nj}, 3.0, alloc); Tensor2D B({nj, nk}, 2.0, alloc); Tensor3D C({nk, ni, nj}, 0.0, alloc); - element_wise_Aij_Bjk_Ckij('N', ni, nj, nk, A.origin(), A.stride(0), B.origin(), B.stride(0), C.origin(), std::get<1>(C.sizes()), - std::get<2>(C.sizes())); + using std::get; + element_wise_Aij_Bjk_Ckij('N', ni, nj, nk, A.origin(), A.stride(0), B.origin(), B.stride(0), C.origin(), get<1>(C.sizes()), + get<2>(C.sizes())); Tensor3D ref({nk, ni, nj}, 6.0, alloc); verify_approx(C, ref); } @@ -340,8 +344,10 @@ TEST_CASE("element_wise_Aij_Bjk_Ckij", "[Numerics][batched_operations]") Tensor2D A({ni, nj}, ComplexType(0.0, -3.0), alloc); Tensor2D B({nj, nk}, ComplexType(1.0, 2.0), alloc); Tensor3D C({nk, ni, nj}, 0.0, alloc); - element_wise_Aij_Bjk_Ckij('C', ni, nj, nk, A.origin(), A.stride(0), B.origin(), B.stride(0), C.origin(), std::get<1>(C.sizes()), - std::get<2>(C.sizes())); + + using std::get; + element_wise_Aij_Bjk_Ckij('C', ni, nj, nk, A.origin(), A.stride(0), B.origin(), B.stride(0), C.origin(), get<1>(C.sizes()), + get<2>(C.sizes())); Tensor3D ref({nk, ni, nj}, ComplexType(-6.0, 3.0), alloc); verify_approx(C, ref); } @@ -359,7 +365,9 @@ void test_Aij_Bjk_Ckji() Tensor2D A({ni, nj}, -3.0, alloc_a); Tensor2D B({nj, nk}, T2(1.0, 2.0), alloc_b); Tensor3D C({nk, nj, ni}, 0.0, alloc_b); - element_wise_Aij_Bjk_Ckji(ni, nj, nk, A.origin(), A.stride(0), B.origin(), B.stride(0), C.origin(), std::get<2>(C.sizes()), + + using std::get; + element_wise_Aij_Bjk_Ckji(ni, nj, nk, A.origin(), A.stride(0), B.origin(), B.stride(0), C.origin(), get<2>(C.sizes()), C.stride(0)); Tensor3D ref({nk, nj, ni}, T2(-3.0, -6.0), alloc_b); verify_approx(C, ref); @@ -383,7 +391,8 @@ TEST_CASE("inplace_product", "[Numerics][batched_operations]") Tensor3D A({nb, ni, nj}, ComplexType(1.0, -3.0), alloc); Tensor2D B({ni, nj}, 2.0, dalloc); using ma::inplace_product; - inplace_product(nb, ni, nj, B.origin(), std::get<1>(B.sizes()), A.origin(), std::get<2>(A.sizes())); + using std::get; + inplace_product(nb, ni, nj, B.origin(), get<1>(B.sizes()), A.origin(), get<2>(A.sizes())); Tensor3D ref({nb, ni, nj}, ComplexType(2.0, -6.0), alloc); verify_approx(A, ref); } diff --git a/src/AFQMC/Numerics/tests/test_dense_numerics.cpp b/src/AFQMC/Numerics/tests/test_dense_numerics.cpp index 9d5bf2c717..2b14d6b10c 100644 --- a/src/AFQMC/Numerics/tests/test_dense_numerics.cpp +++ b/src/AFQMC/Numerics/tests/test_dense_numerics.cpp @@ -321,11 +321,12 @@ void test_dense_matrix_mult() array, 2> A({3, 3}); array, 2> B({3, 3}); - for (int i = 0, k = 0; i < std::get<0>(A.sizes()); i++) - for (int j = 0; j < std::get<1>(A.sizes()); j++, k++) + using std::get; + for (int i = 0, k = 0; i < get<0>(A.sizes()); i++) + for (int j = 0; j < get<1>(A.sizes()); j++, k++) A[i][j] = m_a[k]; - for (int i = 0, k = 0; i < std::get<0>(A.sizes()); i++) - for (int j = 0; j < std::get<1>(A.sizes()); j++, k++) + for (int i = 0, k = 0; i < get<0>(A.sizes()); i++) + for (int j = 0; j < get<1>(A.sizes()); j++, k++) B[i][j] = m_b[k]; array, 2> C = ma::exp(A); diff --git a/src/AFQMC/Numerics/tests/test_determinant.cpp b/src/AFQMC/Numerics/tests/test_determinant.cpp index 0b1a452b46..1f6006ce1a 100644 --- a/src/AFQMC/Numerics/tests/test_determinant.cpp +++ b/src/AFQMC/Numerics/tests/test_determinant.cpp @@ -79,7 +79,8 @@ TEST_CASE("determinant_from_getrf", "[Numerics][determinant]") double log_factor = 0.0; double detx = 0.06317052169675352; using ma::determinant_from_getrf; - double ovlp = determinant_from_getrf(std::get<0>(x.sizes()), lu.origin(), std::get<1>(lu.sizes()), pivot.origin(), log_factor); + using std::get; + double ovlp = determinant_from_getrf(get<0>(x.sizes()), lu.origin(), get<1>(lu.sizes()), pivot.origin(), log_factor); CHECK(ovlp == Approx(detx)); } @@ -104,8 +105,9 @@ TEST_CASE("strided_determinant_from_getrf", "[Numerics][determinant]") double log_factor = 0.0; double detx = 0.06317052169675352; using ma::strided_determinant_from_getrf; - strided_determinant_from_getrf(std::get<0>(x.sizes()), lus.origin(), std::get<1>(lu.sizes()), lu.num_elements(), pivot.origin(), std::get<1>(pivot.sizes()), - log_factor, to_address(ovlps.origin()), std::get<0>(lus.sizes())); + using std::get; + strided_determinant_from_getrf(get<0>(x.sizes()), lus.origin(), get<1>(lu.sizes()), lu.num_elements(), pivot.origin(), get<1>(pivot.sizes()), + log_factor, to_address(ovlps.origin()), get<0>(lus.sizes())); CHECK(ovlps[0] == Approx(detx)); CHECK(ovlps[1] == Approx(detx)); CHECK(ovlps[2] == Approx(detx)); @@ -132,7 +134,8 @@ TEST_CASE("batched_determinant_from_getrf", "[Numerics][determinant]") double log_factor = 0.0; double detx = 0.06317052169675352; using ma::batched_determinant_from_getrf; - batched_determinant_from_getrf(std::get<0>(x.sizes()), lu_array.data(), std::get<1>(lu.sizes()), pivot.origin(), std::get<1>(pivot.sizes()), log_factor, + using std::get; + batched_determinant_from_getrf(get<0>(x.sizes()), lu_array.data(), get<1>(lu.sizes()), pivot.origin(), get<1>(pivot.sizes()), log_factor, to_address(ovlps.origin()), lu_array.size()); CHECK(ovlps[0] == Approx(detx)); CHECK(ovlps[1] == Approx(detx)); @@ -160,7 +163,8 @@ TEST_CASE("batched_determinant_from_getrf_complex", "[Numerics][determinant]") std::complex log_factor = 0.0; std::complex detx = 0.06317052169675352; using ma::batched_determinant_from_getrf; - batched_determinant_from_getrf(std::get<0>(x.sizes()), lu_array.data(), std::get<1>(lu.sizes()), pivot.origin(), std::get<1>(pivot.sizes()), log_factor, + using std::get; + batched_determinant_from_getrf(get<0>(x.sizes()), lu_array.data(), get<1>(lu.sizes()), pivot.origin(), get<1>(pivot.sizes()), log_factor, to_address(ovlps.origin()), lu_array.size()); CHECK(ovlps[0] == ComplexApprox(detx)); CHECK(ovlps[1] == ComplexApprox(detx)); diff --git a/src/AFQMC/Numerics/tests/test_misc_kernels.cpp b/src/AFQMC/Numerics/tests/test_misc_kernels.cpp index 33566c7795..f0e11fcce5 100644 --- a/src/AFQMC/Numerics/tests/test_misc_kernels.cpp +++ b/src/AFQMC/Numerics/tests/test_misc_kernels.cpp @@ -76,13 +76,14 @@ TEST_CASE("axpyBatched", "[Numerics][misc_kernels]") Tensor2D> x({3, 4}, 1.0, alloc); Tensor1D> a(iextensions<1u>{3}, 2.0, alloc); std::vector>> x_batched, y_batched; - for (int i = 0; i < std::get<0>(x.sizes()); i++) + using std::get; + for (int i = 0; i < get<0>(x.sizes()); i++) { x_batched.emplace_back(x[i].origin()); y_batched.emplace_back(y[i].origin()); } using ma::axpyBatched; - axpyBatched(std::get<1>(x.sizes()), to_address(a.origin()), x_batched.data(), 1, y_batched.data(), 1, x_batched.size()); + axpyBatched(get<1>(x.sizes()), to_address(a.origin()), x_batched.data(), 1, y_batched.data(), 1, x_batched.size()); // 1 + 2 = 3. Tensor2D> ref({3, 4}, 3.0, alloc); verify_approx(y, ref); diff --git a/src/AFQMC/Propagators/AFQMCBasePropagator.icc b/src/AFQMC/Propagators/AFQMCBasePropagator.icc index 59c94ae606..b53f0e829a 100644 --- a/src/AFQMC/Propagators/AFQMCBasePropagator.icc +++ b/src/AFQMC/Propagators/AFQMCBasePropagator.icc @@ -56,13 +56,14 @@ void AFQMCBasePropagator::step(int nsteps_, WlkSet& wset, RealType Eshift, RealT if (transposed_G_) G_ext = iextensions<2u>{nwalk, Gsize}; - if (std::get<0>(MFfactor.sizes()) != nsteps || std::get<1>(MFfactor.sizes()) != nwalk) + using std::get; + if (get<0>(MFfactor.sizes()) != nsteps || get<1>(MFfactor.sizes()) != nwalk) MFfactor = CMatrix({long(nsteps), long(nwalk)}); - if (std::get<0>(hybrid_weight.sizes()) != nsteps || std::get<1>(hybrid_weight.sizes()) != nwalk) + if (get<0>(hybrid_weight.sizes()) != nsteps || get<1>(hybrid_weight.sizes()) != nwalk) hybrid_weight = CMatrix({long(nsteps), long(nwalk)}); - if (std::get<0>(new_overlaps.sizes()) != nwalk) + if (get<0>(new_overlaps.sizes()) != nwalk) new_overlaps = CVector(iextensions<1u>{nwalk}); - if (std::get<0>(new_energies.sizes()) != nwalk || std::get<1>(new_energies.sizes()) != 3) + if (get<0>(new_energies.sizes()) != nwalk || get<1>(new_energies.sizes()) != 3) new_energies = CMatrix({long(nwalk), 3}); @@ -279,16 +280,20 @@ void AFQMCBasePropagator::BackPropagate(int nbpsteps, int nStabalize, WlkSet& ws buffer_manager.get_generator().template get_allocator()); C3Tensor_ref vHS3D(make_device_ptr(vHS.origin()), vhs3d_ext); + using std::get; + auto&& Fields(*wset.getFields()); - assert(std::get<0>(Fields.sizes()) >= nbpsteps); - assert(std::get<1>(Fields.sizes()) == globalnCV); - assert(std::get<2>(Fields.sizes()) == nwalk); + assert(get<0>(Fields.sizes()) >= nbpsteps); + assert(get<1>(Fields.sizes()) == globalnCV); + assert(get<2>(Fields.sizes()) == nwalk); int nrow(NMO * npol); int ncol(NAEA + ((walker_type == CLOSED) ? 0 : NAEB)); assert(Refs.size() == nwalk); - int nrefs = std::get<1>(Refs.sizes()); - assert(std::get<2>(Refs.sizes()) == nrow * ncol); + + using std::get; + int nrefs = get<1>(Refs.sizes()); + assert(get<2>(Refs.sizes()) == nrow * ncol); int cv0, cvN; std::tie(cv0, cvN) = FairDivideBoundary(TG.getLocalTGRank(), globalnCV, TG.getNCoresPerTG()); @@ -299,8 +304,8 @@ void AFQMCBasePropagator::BackPropagate(int nbpsteps, int nStabalize, WlkSet& ws if (walker_type == COLLINEAR) nx = 2; - assert(std::get<0>(detR.sizes()) == nwalk); - assert(std::get<1>(detR.sizes()) == nrefs * nx); + assert(get<0>(detR.sizes()) == nwalk); + assert(get<1>(detR.sizes()) == nrefs * nx); std::fill_n(detR.origin(), detR.num_elements(), ComplexType(1.0, 0.0)); // from now on, individual work on each walker/step @@ -467,7 +472,8 @@ void AFQMCBasePropagator::apply_propagators(char TA, } else { - if (std::get<0>(local_vHS.sizes()) != NMO || std::get<1>(local_vHS.sizes()) != NMO) + using std::get; + if (get<0>(local_vHS.sizes()) != NMO || get<1>(local_vHS.sizes()) != NMO) local_vHS = CMatrix({NMO, NMO}); // vHS3D[M][M][nstep*nwalk]: need temporary buffer in this case if (walker_type == COLLINEAR) @@ -561,11 +567,12 @@ void AFQMCBasePropagator::apply_propagators_batched(char TA, WSet& wset, int ni, } else { - if (std::get<0>(local_vHS.sizes()) != nbatch || std::get<1>(local_vHS.sizes()) != NMO * NMO) + using std::get; + if (get<0>(local_vHS.sizes()) != nbatch || get<1>(local_vHS.sizes()) != NMO * NMO) local_vHS = CMatrix({nbatch, NMO * NMO}); // vHS3D[M][M][nstep*nwalk]: need temporary buffer in this case - int N2 = std::get<0>(vHS3D.sizes()) * std::get<1>(vHS3D.sizes()); - CMatrix_ref vHS2D(vHS3D.origin(), {N2, std::get<2>(vHS3D.sizes())}); + int N2 = get<0>(vHS3D.sizes()) * get<1>(vHS3D.sizes()); + CMatrix_ref vHS2D(vHS3D.origin(), {N2, get<2>(vHS3D.sizes())}); C3Tensor_ref local3D(local_vHS.origin(), {nbatch, NMO, NMO}); int nt = ni * nwalk; for (int iw = 0; iw < nwalk; iw += nbatch, nt += nbatch) diff --git a/src/AFQMC/Propagators/AFQMCDistributedPropagator.icc b/src/AFQMC/Propagators/AFQMCDistributedPropagator.icc index 3b63c4ba05..340708397a 100644 --- a/src/AFQMC/Propagators/AFQMCDistributedPropagator.icc +++ b/src/AFQMC/Propagators/AFQMCDistributedPropagator.icc @@ -60,14 +60,15 @@ void AFQMCDistributedPropagator::step(int nsteps_, WlkSet& wset, RealType Eshift if (transposed_G_) G_ext = iextensions<2u>{nwalk, Gsize}; - if (std::get<1>(MFfactor.sizes()) != nsteps || std::get<2>(MFfactor.sizes()) != nwalk) + using std::get; + if (get<1>(MFfactor.sizes()) != nsteps || get<2>(MFfactor.sizes()) != nwalk) MFfactor = C3Tensor({2, nsteps, nwalk}); - if (std::get<1>(hybrid_weight.sizes()) != nsteps || std::get<2>(hybrid_weight.sizes()) != nwalk) + if (get<1>(hybrid_weight.sizes()) != nsteps || get<2>(hybrid_weight.sizes()) != nwalk) hybrid_weight = C3Tensor({2, nsteps, nwalk}); - if (std::get<0>(new_overlaps.sizes()) != nwalk) + if (get<0>(new_overlaps.sizes()) != nwalk) new_overlaps = CVector(iextensions<1u>{nwalk}); - if (std::get<0>(new_energies.sizes()) != nwalk || std::get<1>(new_energies.sizes()) != 3) + if (get<0>(new_energies.sizes()) != nwalk || get<1>(new_energies.sizes()) != 3) new_energies = CMatrix({nwalk, 3}); // Summary of temporary memory usage: diff --git a/src/AFQMC/Propagators/AFQMCDistributedPropagatorDistCV.icc b/src/AFQMC/Propagators/AFQMCDistributedPropagatorDistCV.icc index 63ae868436..edf9e99717 100644 --- a/src/AFQMC/Propagators/AFQMCDistributedPropagatorDistCV.icc +++ b/src/AFQMC/Propagators/AFQMCDistributedPropagatorDistCV.icc @@ -66,13 +66,14 @@ void AFQMCDistributedPropagatorDistCV::step(int nsteps_, WlkSet& wset, RealType if (transposed_G_) G_ext = iextensions<2u>{nwalk, Gsize}; - if (std::get<0>(MFfactor.sizes()) != nsteps || std::get<1>(MFfactor.sizes()) != nwalk) + using std::get; + if (get<0>(MFfactor.sizes()) != nsteps || get<1>(MFfactor.sizes()) != nwalk) MFfactor = CMatrix({long(nsteps), long(nwalk)}); - if (std::get<0>(hybrid_weight.sizes()) != nsteps || std::get<1>(hybrid_weight.sizes()) != nwalk) + if (get<0>(hybrid_weight.sizes()) != nsteps || get<1>(hybrid_weight.sizes()) != nwalk) hybrid_weight = CMatrix({long(nsteps), long(nwalk)}); - if (std::get<0>(new_overlaps.sizes()) != nwalk) + if (get<0>(new_overlaps.sizes()) != nwalk) new_overlaps = CVector(iextensions<1u>{nwalk}); - if (std::get<0>(new_energies.sizes()) != nwalk || std::get<1>(new_energies.sizes()) != 3) + if (get<0>(new_energies.sizes()) != nwalk || get<1>(new_energies.sizes()) != 3) new_energies = CMatrix({long(nwalk), 3}); // Temporary memory usage summary: @@ -435,13 +436,14 @@ void AFQMCDistributedPropagatorDistCV::step_collective(int nsteps_, WlkSet& wset if (transposed_G_) G_ext = iextensions<2u>{nwalk, Gsize}; - if (std::get<0>(MFfactor.sizes()) != nsteps || std::get<1>(MFfactor.sizes()) != nwalk) + using std::get; + if (get<0>(MFfactor.sizes()) != nsteps || get<1>(MFfactor.sizes()) != nwalk) MFfactor = CMatrix({long(nsteps), long(nwalk)}); - if (std::get<0>(hybrid_weight.sizes()) != nsteps || std::get<1>(hybrid_weight.sizes()) != nwalk) + if (get<0>(hybrid_weight.sizes()) != nsteps || get<1>(hybrid_weight.sizes()) != nwalk) hybrid_weight = CMatrix({long(nsteps), long(nwalk)}); - if (std::get<0>(new_overlaps.sizes()) != nwalk) + if (get<0>(new_overlaps.sizes()) != nwalk) new_overlaps = CVector(iextensions<1u>{nwalk}); - if (std::get<0>(new_energies.sizes()) != nwalk || std::get<1>(new_energies.sizes()) != 3) + if (get<0>(new_energies.sizes()) != nwalk || get<1>(new_energies.sizes()) != 3) new_energies = CMatrix({long(nwalk), 3}); // Temporary memory usage summary: @@ -831,15 +833,19 @@ void AFQMCDistributedPropagatorDistCV::BackPropagate(int nbpsteps, TG.local_barrier(); auto&& Fields(*wset.getFields()); - assert(std::get<0>(Fields.sizes()) >= nbpsteps); - assert(std::get<1>(Fields.sizes()) == globalnCV); - assert(std::get<2>(Fields.sizes()) == nwalk); + + using std::get; + assert(get<0>(Fields.sizes()) >= nbpsteps); + assert(get<1>(Fields.sizes()) == globalnCV); + assert(get<2>(Fields.sizes()) == nwalk); int nrow(NMO * ((walker_type == NONCOLLINEAR) ? 2 : 1)); int ncol(NAEA + ((walker_type == CLOSED) ? 0 : NAEB)); - assert(std::get<0>(Refs.sizes()) == nwalk); - int nrefs = std::get<1>(Refs.sizes()); - assert(std::get<2>(Refs.sizes()) == nrow * ncol); + + using std::get; + assert(get<0>(Refs.sizes()) == nwalk); + int nrefs = get<1>(Refs.sizes()); + assert(get<2>(Refs.sizes()) == nrow * ncol); int cv0, cvN; std::tie(cv0, cvN) = FairDivideBoundary(TG.getLocalTGRank(), localnCV, TG.getNCoresPerTG()); @@ -852,8 +858,8 @@ void AFQMCDistributedPropagatorDistCV::BackPropagate(int nbpsteps, if (walker_type == COLLINEAR) nx = 2; - assert(std::get<0>(detR.sizes()) == nwalk); - assert(std::get<1>(detR.sizes()) == nrefs * nx); + assert(get<0>(detR.sizes()) == nwalk); + assert(get<1>(detR.sizes()) == nrefs * nx); std::fill_n(detR.origin(), detR.num_elements(), SPComplexType(1.0, 0.0)); // from now on, individual work on each walker/step diff --git a/src/AFQMC/Propagators/WalkerSetUpdate.hpp b/src/AFQMC/Propagators/WalkerSetUpdate.hpp index cfff10ceb4..6bc17936a7 100644 --- a/src/AFQMC/Propagators/WalkerSetUpdate.hpp +++ b/src/AFQMC/Propagators/WalkerSetUpdate.hpp @@ -37,10 +37,12 @@ void free_projection_walker_update(Wlk&& w, Mat&& hybrid_weight, WMat& work) { + using std::get; + int nwalk = w.size(); // constexpr if can be used to avoid the memory copy, by comparing the pointer types // between WMat and Mat/OMat - if (std::get<0>(work.sizes()) < 7 || std::get<1>(work.sizes()) < nwalk) + if (get<0>(work.sizes()) < 7 || get<1>(work.sizes()) < nwalk) work.reextent({7, nwalk}); w.getProperty(WEIGHT, work[0]); @@ -83,10 +85,12 @@ void hybrid_walker_update(Wlk&& w, Mat&& hybrid_weight, WMat& work) { + using std::get; + int nwalk = w.size(); // constexpr if can be used to avoid the memory copy, by comparing the pointer types // between WMat and Mat/OMat - if (std::get<0>(work.sizes()) < 7 || std::get<1>(work.sizes()) < nwalk) + if (get<0>(work.sizes()) < 7 || get<1>(work.sizes()) < nwalk) work.reextent({7, nwalk}); bool BackProp = (w.getBPPos() >= 0 && w.getBPPos() < w.NumBackProp()); @@ -177,10 +181,12 @@ void local_energy_walker_update(Wlk&& w, Mat&& hybrid_weight, WMat& work) { + using std::get; + int nwalk = w.size(); // constexpr if can be used to avoid the memory copy, by comparing the pointer types // between WMat and Mat/OMat - if (std::get<0>(work.sizes()) < 12 || std::get<1>(work.sizes()) < nwalk) + if (get<0>(work.sizes()) < 12 || get<1>(work.sizes()) < nwalk) work.reextent({12, nwalk}); bool BackProp = (w.getBPPos() >= 0 && w.getBPPos() < w.NumBackProp()); diff --git a/src/AFQMC/Propagators/generate1BodyPropagator.hpp b/src/AFQMC/Propagators/generate1BodyPropagator.hpp index 184ea70164..ec0035f79f 100644 --- a/src/AFQMC/Propagators/generate1BodyPropagator.hpp +++ b/src/AFQMC/Propagators/generate1BodyPropagator.hpp @@ -45,8 +45,9 @@ P_Type generate1BodyPropagator(TaskGroup_& TG, MultiArray2D const& H1, bool printP1eV = false) { + using std::get; assert(H1.dimensionality == 2); - assert(std::get<0>(H1.sizes()) == std::get<1>(H1.sizes())); + assert(get<0>(H1.sizes()) == get<1>(H1.sizes())); assert(H1.stride(1) == 1); int NMO = H1.size(); if (TG.TG_local().root()) @@ -83,13 +84,14 @@ P_Type generate1BodyPropagator(TaskGroup_& TG, MultiArray2DB const& H1ext, bool printP1eV = false) { + using std::get; assert(H1.dimensionality == 2); - assert(std::get<0>(H1.sizes()) == std::get<1>(H1.sizes())); + assert(get<0>(H1.sizes()) == get<1>(H1.sizes())); assert(H1.stride(1) == 1); assert(H1ext.dimensionality == 2); - assert(std::get<0>(H1ext.sizes()) == std::get<1>(H1ext.sizes())); + assert(get<0>(H1ext.sizes()) == get<1>(H1ext.sizes())); assert(H1ext.stride(1) == 1); - assert(std::get<0>(H1.sizes()) == std::get<1>(H1ext.sizes())); + assert(get<0>(H1.sizes()) == get<1>(H1ext.sizes())); int NMO = H1.size(); if (TG.TG_local().root()) { diff --git a/src/AFQMC/Propagators/tests/test_propagator_factory.cpp b/src/AFQMC/Propagators/tests/test_propagator_factory.cpp index be4974ec11..a2cc791649 100644 --- a/src/AFQMC/Propagators/tests/test_propagator_factory.cpp +++ b/src/AFQMC/Propagators/tests/test_propagator_factory.cpp @@ -143,9 +143,11 @@ void propg_fac_shared(boost::mpi3::communicator& world) WalkerSet wset(TG, doc3.getRoot(), InfoMap["info0"], rng); auto initial_guess = WfnFac.getInitialGuess(wfn_name); - REQUIRE(std::get<0>(initial_guess.sizes()) == 2); - REQUIRE(std::get<1>(initial_guess.sizes()) == NPOL * NMO); - REQUIRE(std::get<2>(initial_guess.sizes()) == NAEA); + + using std::get; + REQUIRE(get<0>(initial_guess.sizes()) == 2); + REQUIRE(get<1>(initial_guess.sizes()) == NPOL * NMO); + REQUIRE(get<2>(initial_guess.sizes()) == NAEA); wset.resize(nwalk, initial_guess[0], initial_guess[0]); // initial_guess[1](XXX.extension(0),{0,NAEB})); @@ -315,9 +317,11 @@ void propg_fac_distributed(boost::mpi3::communicator& world, int ngrp) WalkerSet wset(TG, doc3.getRoot(), InfoMap["info0"], rng); auto initial_guess = WfnFac.getInitialGuess(wfn_name); - REQUIRE(std::get<0>(initial_guess.sizes()) == 2); - REQUIRE(std::get<1>(initial_guess.sizes()) == NPOL * NMO); - REQUIRE(std::get<2>(initial_guess.sizes()) == NAEA); + + using std::get; + REQUIRE(get<0>(initial_guess.sizes()) == 2); + REQUIRE(get<1>(initial_guess.sizes()) == NPOL * NMO); + REQUIRE(get<2>(initial_guess.sizes()) == NAEA); wset.resize(nwalk, initial_guess[0], initial_guess[0]); const char* propg_xml_block0 = R"()"; diff --git a/src/AFQMC/SlaterDeterminantOperations/SlaterDetOperations_base.hpp b/src/AFQMC/SlaterDeterminantOperations/SlaterDetOperations_base.hpp index 66c09f8e4a..64d15513a8 100644 --- a/src/AFQMC/SlaterDeterminantOperations/SlaterDetOperations_base.hpp +++ b/src/AFQMC/SlaterDeterminantOperations/SlaterDetOperations_base.hpp @@ -82,8 +82,9 @@ class SlaterDetOperations_base template T MixedDensityMatrix(const MatA& hermA, const MatB& B, MatC&& C, T LogOverlapFactor, bool compact, bool herm = true) { - int NMO = (herm ? std::get<1>(hermA.sizes()) : std::get<0>(hermA.sizes())); - int NAEA = (herm ? std::get<0>(hermA.sizes()) : std::get<1>(hermA.sizes())); + using std::get; + int NMO = (herm ? get<1>(hermA.sizes()) : get<0>(hermA.sizes())); + int NAEA = (herm ? get<0>(hermA.sizes()) : get<1>(hermA.sizes())); TMatrix TNN({NAEA, NAEA}, buffer_manager.get_generator().template get_allocator()); TMatrix TNM({NAEA, NMO}, buffer_manager.get_generator().template get_allocator()); TVector WORK(iextensions<1u>{work_size}, buffer_manager.get_generator().template get_allocator()); @@ -95,8 +96,10 @@ class SlaterDetOperations_base template T MixedDensityMatrix(const MatA& A, MatC&& C, T LogOverlapFactor, bool compact = false) { - int NMO = std::get<0>(A.sizes()); - int NAEA = std::get<1>(A.sizes()); + using std::get; + + int NMO = get<0>(A.sizes()); + int NAEA = get<1>(A.sizes()); TMatrix TNN({NAEA, NAEA}, buffer_manager.get_generator().template get_allocator()); TMatrix TNM({NAEA, NMO}, buffer_manager.get_generator().template get_allocator()); TVector WORK(iextensions<1u>{work_size}, buffer_manager.get_generator().template get_allocator()); @@ -113,8 +116,9 @@ class SlaterDetOperations_base bool compact = false, bool useSVD = false) { - int NMO = std::get<0>(A.sizes()); - int NAEA = std::get<1>(A.sizes()); + using std::get; + int NMO = get<0>(A.sizes()); + int NAEA = get<1>(A.sizes()); if (useSVD) { TMatrix TNN1({NAEA, NAEA}, buffer_manager.get_generator().template get_allocator()); @@ -149,12 +153,13 @@ class SlaterDetOperations_base MatQ&& QQ0, bool compact = false) { - int Nact = std::get<0>(hermA.sizes()); - int NEL = std::get<1>(B.sizes()); - int NMO = std::get<0>(B.sizes()); - assert(std::get<1>(hermA.sizes()) == std::get<0>(B.sizes())); - assert(std::get<0>(QQ0.sizes()) == Nact); - assert(std::get<1>(QQ0.sizes()) == NEL); + using std::get; + int Nact = get<0>(hermA.sizes()); + int NEL = get<1>(B.sizes()); + int NMO = get<0>(B.sizes()); + assert(get<1>(hermA.sizes()) == get<0>(B.sizes())); + assert(get<0>(QQ0.sizes()) == Nact); + assert(get<1>(QQ0.sizes()) == NEL); TMatrix TNN({NEL, NEL}, buffer_manager.get_generator().template get_allocator()); TMatrix TAB({Nact, NEL}, buffer_manager.get_generator().template get_allocator()); TMatrix TNM({NEL, NMO}, buffer_manager.get_generator().template get_allocator()); @@ -174,10 +179,11 @@ class SlaterDetOperations_base integer* ref, bool compact = false) { - int Nact = std::get<0>(hermA.sizes()); - int NEL = std::get<1>(B.sizes()); - int NMO = std::get<0>(B.sizes()); - assert(std::get<1>(hermA.sizes()) == std::get<0>(B.sizes())); + using std::get; + int Nact = get<0>(hermA.sizes()); + int NEL = get<1>(B.sizes()); + int NMO = get<0>(B.sizes()); + assert(get<1>(hermA.sizes()) == get<0>(B.sizes())); TMatrix TNN({NEL, NEL}, buffer_manager.get_generator().template get_allocator()); TMatrix TAB({Nact, NEL}, buffer_manager.get_generator().template get_allocator()); TMatrix TNM({NEL, NMO}, buffer_manager.get_generator().template get_allocator()); @@ -191,7 +197,8 @@ class SlaterDetOperations_base template T Overlap(const MatA& A, T LogOverlapFactor) { - int NAEA = std::get<1>(A.sizes()); + using std::get; + int NAEA = get<1>(A.sizes()); TMatrix TNN({NAEA, NAEA}, buffer_manager.get_generator().template get_allocator()); TMatrix TNN2({NAEA, NAEA}, buffer_manager.get_generator().template get_allocator()); IVector IWORK(iextensions<1u>{NAEA + 1}, buffer_manager.get_generator().template get_allocator()); @@ -201,7 +208,8 @@ class SlaterDetOperations_base template T Overlap(const MatA& hermA, const MatB& B, T LogOverlapFactor, bool herm = true) { - int NAEA = (herm ? std::get<0>(hermA.sizes()) : std::get<1>(hermA.sizes())); + using std::get; + int NAEA = (herm ? get<0>(hermA.sizes()) : get<1>(hermA.sizes())); TMatrix TNN({NAEA, NAEA}, buffer_manager.get_generator().template get_allocator()); TMatrix TNN2({NAEA, NAEA}, buffer_manager.get_generator().template get_allocator()); IVector IWORK(iextensions<1u>{NAEA + 1}, buffer_manager.get_generator().template get_allocator()); @@ -211,7 +219,8 @@ class SlaterDetOperations_base template T Overlap_noHerm(const MatA& A, const MatB& B, T LogOverlapFactor) { - int NAEA = std::get<1>(A.sizes()); + using std::get; + int NAEA = get<1>(A.sizes()); TMatrix TNN({NAEA, NAEA}, buffer_manager.get_generator().template get_allocator()); TMatrix TNN2({NAEA, NAEA}, buffer_manager.get_generator().template get_allocator()); IVector IWORK(iextensions<1u>{NAEA + 1}, buffer_manager.get_generator().template get_allocator()); @@ -222,11 +231,12 @@ class SlaterDetOperations_base template T OverlapForWoodbury(const MatA& hermA, const MatB& B, T LogOverlapFactor, integer* ref, MatC&& QQ0) { - int Nact = std::get<0>(hermA.sizes()); - int NEL = std::get<1>(B.sizes()); - assert(std::get<1>(hermA.sizes()) == std::get<0>(B.sizes())); - assert(std::get<0>(QQ0.sizes()) == Nact); - assert(std::get<1>(QQ0.sizes()) == NEL); + using std::get; + int Nact = get<0>(hermA.sizes()); + int NEL = get<1>(B.sizes()); + assert(get<1>(hermA.sizes()) == get<0>(B.sizes())); + assert(get<0>(QQ0.sizes()) == Nact); + assert(get<1>(QQ0.sizes()) == NEL); TMatrix TNN({NEL, NEL}, buffer_manager.get_generator().template get_allocator()); TMatrix TMN({Nact, NEL}, buffer_manager.get_generator().template get_allocator()); TVector WORK(iextensions<1u>{work_size}, buffer_manager.get_generator().template get_allocator()); @@ -239,14 +249,18 @@ class SlaterDetOperations_base void Propagate(Mat&& A, const MatP1& P1, const MatV& V, int order = 6, char TA = 'N', bool noncollinear = false) { int npol = noncollinear ? 2 : 1; - int NMO = std::get<0>(A.sizes()); - int NAEA = std::get<1>(A.sizes()); + + using std::get; + int NMO = get<0>(A.sizes()); + int NAEA = get<1>(A.sizes()); int M = NMO / npol; assert(NMO % npol == 0); - assert(std::get<0>(P1.sizes()) == NMO); - assert(std::get<1>(P1.sizes()) == NMO); - assert(std::get<0>(V.sizes()) == M); - assert(std::get<1>(V.sizes()) == M); + + using std::get; + assert(get<0>(P1.sizes()) == NMO); + assert(get<1>(P1.sizes()) == NMO); + assert(get<0>(V.sizes()) == M); + assert(get<1>(V.sizes()) == M); TMatrix TMN({NMO, NAEA}, buffer_manager.get_generator().template get_allocator()); TMatrix T1({M, NAEA}, buffer_manager.get_generator().template get_allocator()); TMatrix T2({M, NAEA}, buffer_manager.get_generator().template get_allocator()); @@ -279,10 +293,11 @@ class SlaterDetOperations_base template T Orthogonalize(Mat&& A, T LogOverlapFactor) { + using std::get; #if defined(ENABLE_CUDA) || defined(ENABLE_HIP) // QR on the transpose - int NMO = std::get<0>(A.sizes()); - int NAEA = std::get<1>(A.sizes()); + int NMO = get<0>(A.sizes()); + int NAEA = get<1>(A.sizes()); TMatrix AT({NAEA, NMO}, buffer_manager.get_generator().template get_allocator()); TVector scl(iextensions<1u>{NMO}, buffer_manager.get_generator().template get_allocator()); TVector TAU(iextensions<1u>{NMO}, buffer_manager.get_generator().template get_allocator()); @@ -292,10 +307,10 @@ class SlaterDetOperations_base ma::geqrf(AT, TAU, WORK); using ma::determinant_from_geqrf; using ma::scale_columns; - T res = determinant_from_geqrf(std::get<0>(AT.sizes()), AT.origin(), AT.stride(0), scl.origin(), LogOverlapFactor); + T res = determinant_from_geqrf(get<0>(AT.sizes()), AT.origin(), AT.stride(0), scl.origin(), LogOverlapFactor); ma::gqr(AT, TAU, WORK); ma::transpose(AT, A); - scale_columns(std::get<0>(A.sizes()), std::get<1>(A.sizes()), A.origin(), A.stride(0), scl.origin()); + scale_columns(get<0>(A.sizes()), get<1>(A.sizes()), A.origin(), A.stride(0), scl.origin()); #else int NMO = A.size(); TVector TAU(iextensions<1u>{NMO}, buffer_manager.get_generator().template get_allocator()); @@ -303,7 +318,9 @@ class SlaterDetOperations_base IVector IWORK(iextensions<1u>{NMO + 1}, buffer_manager.get_generator().template get_allocator()); ma::gelqf(std::forward(A), TAU, WORK); T res(0.0); - for (int i = 0; i < std::get<1>(A.sizes()); i++) + + using std::get; + for (int i = 0; i < get<1>(A.sizes()); i++) { if (real(A[i][i]) < 0) IWORK[i] = -1; @@ -313,8 +330,8 @@ class SlaterDetOperations_base } res = std::exp(res - LogOverlapFactor); ma::glq(std::forward(A), TAU, WORK); - for (int i = 0; i < std::get<0>(A.sizes()); ++i) - for (int j = 0; j < std::get<1>(A.sizes()); ++j) + for (int i = 0; i < get<0>(A.sizes()); ++i) + for (int j = 0; j < get<1>(A.sizes()); ++j) A[i][j] *= T(IWORK[j]); #endif return res; diff --git a/src/AFQMC/SlaterDeterminantOperations/SlaterDetOperations_serial.hpp b/src/AFQMC/SlaterDeterminantOperations/SlaterDetOperations_serial.hpp index 03f656e641..b2c82a0eee 100644 --- a/src/AFQMC/SlaterDeterminantOperations/SlaterDetOperations_serial.hpp +++ b/src/AFQMC/SlaterDeterminantOperations/SlaterDetOperations_serial.hpp @@ -149,21 +149,25 @@ class SlaterDetOperations_serial : public SlaterDetOperations_base::dimensionality == 2, " dimenionality == 2"); static_assert(std::decay::type::dimensionality == 3, " dimenionality == 3"); if (Ai.size() == 0) return; - assert(Ai.size() == std::get<0>(V.sizes())); + assert(Ai.size() == get<0>(V.sizes())); int nbatch = Ai.size(); int npol = noncollinear ? 2 : 1; - int NMO = std::get<0>((*Ai[0]).sizes()); - int NAEA = std::get<1>((*Ai[0]).sizes()); + int NMO = get<0>((*Ai[0]).sizes()); + int NAEA = get<1>((*Ai[0]).sizes()); int M = NMO / npol; assert(NMO % npol == 0); - assert(std::get<0>(P1.sizes()) == NMO); - assert(std::get<1>(P1.sizes()) == NMO); - assert(std::get<1>(V.sizes()) == M); - assert(std::get<2>(V.sizes()) == M); + + using std::get; + assert(get<0>(P1.sizes()) == NMO); + assert(get<1>(P1.sizes()) == NMO); + assert(get<1>(V.sizes()) == M); + assert(get<2>(V.sizes()) == M); TTensor TMN({nbatch, NMO, NAEA}, buffer_manager.get_generator().template get_allocator()); TTensor T1({nbatch, NMO, NAEA}, buffer_manager.get_generator().template get_allocator()); TTensor T2({nbatch, NMO, NAEA}, buffer_manager.get_generator().template get_allocator()); @@ -233,8 +237,10 @@ class SlaterDetOperations_serial : public SlaterDetOperations_base::dimensionality == 2, "Wrong dimensionality"); static_assert(std::decay::type::dimensionality == 3, "Wrong dimensionality"); static_assert(std::decay::type::dimensionality == 1, "Wrong dimensionality"); - int NMO = (herm ? std::get<1>((*hermA[0]).sizes()) : std::get<0>((*hermA[0]).sizes())); - int NAEA = (herm ? std::get<0>((*hermA[0]).sizes()) : std::get<1>((*hermA[0]).sizes())); + + using std::get; + int NMO = (herm ? get<1>((*hermA[0]).sizes()) : get<0>((*hermA[0]).sizes())); + int NAEA = (herm ? get<0>((*hermA[0]).sizes()) : get<1>((*hermA[0]).sizes())); int nbatch = Bi.size(); assert(C.size() == nbatch); assert(ovlp.size() == nbatch); @@ -269,8 +275,10 @@ class SlaterDetOperations_serial : public SlaterDetOperations_base::dimensionality == 2, "Wrong dimensionality"); static_assert(pointedType::dimensionality == 2, "Wrong dimensionality"); static_assert(std::decay::type::dimensionality == 1, "Wrong dimensionality"); - int NMO = (herm ? std::get<1>((*Left[0]).sizes()) : std::get<0>((*Left[0]).sizes())); - int NAEA = (herm ? std::get<0>((*Left[0]).sizes()) : std::get<1>((*Left[0]).sizes())); + + using std::get; + int NMO = (herm ? get<1>((*Left[0]).sizes()) : get<0>((*Left[0]).sizes())); + int NAEA = (herm ? get<0>((*Left[0]).sizes()) : get<1>((*Left[0]).sizes())); int nbatch = Left.size(); assert(Right.size() == nbatch); assert(G.size() == nbatch); @@ -301,8 +309,10 @@ class SlaterDetOperations_serial : public SlaterDetOperations_base 0); static_assert(std::decay::type::dimensionality == 1, "Wrong dimensionality"); - int NMO = (herm ? std::get<1>((*hermA[0]).sizes()) : std::get<0>((*hermA[0]).sizes())); - int NAEA = (herm ? std::get<0>((*hermA[0]).sizes()) : std::get<1>((*hermA[0]).sizes())); + + using std::get; + int NMO = (herm ? get<1>((*hermA[0]).sizes()) : get<0>((*hermA[0]).sizes())); + int NAEA = (herm ? get<0>((*hermA[0]).sizes()) : get<1>((*hermA[0]).sizes())); int nbatch = Bi.size(); assert(ovlp.size() == nbatch); TTensor TNN3D({nbatch, NAEA, NAEA}, buffer_manager.get_generator().template get_allocator()); @@ -315,12 +325,14 @@ class SlaterDetOperations_serial : public SlaterDetOperations_base& Ai, T LogOverlapFactor, PTR detR) { static_assert(pointedType::dimensionality == 2, "Wrong dimensionality"); + + using std::get; #if defined(ENABLE_CUDA) || defined(ENABLE_HIP) // QR on the transpose if (Ai.size() == 0) return; - int NMO = std::get<0>((*Ai[0]).sizes()); - int NAEA = std::get<1>((*Ai[0]).sizes()); + int NMO = get<0>((*Ai[0]).sizes()); + int NAEA = get<1>((*Ai[0]).sizes()); int nbatch = Ai.size(); TTensor AT({nbatch, NAEA, NMO}, buffer_manager.get_generator().template get_allocator()); TMatrix T_({nbatch, NMO}, buffer_manager.get_generator().template get_allocator()); @@ -353,12 +365,13 @@ class SlaterDetOperations_serial : public SlaterDetOperations_base void BatchedOrthogonalize(std::vector& Ai, T LogOverlapFactor) { + using std::get; #if defined(ENABLE_CUDA) || defined(ENABLE_HIP) // QR on the transpose if (Ai.size() == 0) return; - int NMO = std::get<0>((*Ai[0]).sizes()); - int NAEA = std::get<1>((*Ai[0]).sizes()); + int NMO = get<0>((*Ai[0]).sizes()); + int NAEA = get<1>((*Ai[0]).sizes()); int nbatch = Ai.size(); TTensor AT({nbatch, NAEA, NMO}, buffer_manager.get_generator().template get_allocator()); TMatrix T_({nbatch, NMO}, buffer_manager.get_generator().template get_allocator()); diff --git a/src/AFQMC/SlaterDeterminantOperations/SlaterDetOperations_shared.hpp b/src/AFQMC/SlaterDeterminantOperations/SlaterDetOperations_shared.hpp index e4cf5b96f6..77ef5cc597 100644 --- a/src/AFQMC/SlaterDeterminantOperations/SlaterDetOperations_shared.hpp +++ b/src/AFQMC/SlaterDeterminantOperations/SlaterDetOperations_shared.hpp @@ -74,8 +74,10 @@ class SlaterDetOperations_shared : public SlaterDetOperations_base(hermA.sizes()) : std::get<0>(hermA.sizes())); - int NAEA = (herm ? std::get<0>(hermA.sizes()) : std::get<1>(hermA.sizes())); + using std::get; + + int NMO = (herm ? get<1>(hermA.sizes()) : get<0>(hermA.sizes())); + int NAEA = (herm ? get<0>(hermA.sizes()) : get<1>(hermA.sizes())); set_shm_buffer(comm, NAEA * (NAEA + NMO)); assert(SM_TMats->num_elements() >= NAEA * (NAEA + NMO)); boost::multi::array_ref TNN(to_address(SM_TMats->origin()), {NAEA, NAEA}); @@ -96,12 +98,14 @@ class SlaterDetOperations_shared : public SlaterDetOperations_base(hermA.sizes()); - int NEL = std::get<1>(B.sizes()); - int NMO = std::get<0>(B.sizes()); - assert(std::get<1>(hermA.sizes()) == std::get<0>(B.sizes())); - assert(std::get<0>(QQ0.sizes()) == Nact); - assert(std::get<1>(QQ0.sizes()) == NEL); + using std::get; + + int Nact = get<0>(hermA.sizes()); + int NEL = get<1>(B.sizes()); + int NMO = get<0>(B.sizes()); + assert(get<1>(hermA.sizes()) == get<0>(B.sizes())); + assert(get<0>(QQ0.sizes()) == Nact); + assert(get<1>(QQ0.sizes()) == NEL); set_shm_buffer(comm, NEL * (NEL + Nact + NMO)); assert(SM_TMats->num_elements() >= NEL * (NEL + Nact + NMO)); @@ -122,7 +126,8 @@ class SlaterDetOperations_shared : public SlaterDetOperations_base T Overlap(const MatA& hermA, const MatB& B, T LogOverlapFactor, communicator& comm, bool herm = true) { - int NAEA = (herm ? std::get<0>(hermA.sizes()) : std::get<1>(hermA.sizes())); + using std::get; + int NAEA = (herm ? get<0>(hermA.sizes()) : get<1>(hermA.sizes())); set_shm_buffer(comm, 2 * NAEA * NAEA); assert(SM_TMats->num_elements() >= 2 * NAEA * NAEA); boost::multi::array_ref TNN(to_address(SM_TMats->origin()), {NAEA, NAEA}); @@ -139,11 +144,13 @@ class SlaterDetOperations_shared : public SlaterDetOperations_base(hermA.sizes()); - int NEL = std::get<1>(B.sizes()); - assert(std::get<1>(hermA.sizes()) == std::get<0>(B.sizes())); - assert(std::get<0>(QQ0.sizes()) == Nact); - assert(std::get<1>(QQ0.sizes()) == NEL); + using std::get; + + int Nact = get<0>(hermA.sizes()); + int NEL = get<1>(B.sizes()); + assert(get<1>(hermA.sizes()) == get<0>(B.sizes())); + assert(get<0>(QQ0.sizes()) == Nact); + assert(get<1>(QQ0.sizes()) == NEL); set_shm_buffer(comm, NEL * (Nact + NEL)); assert(SM_TMats->num_elements() >= NEL * (Nact + NEL)); boost::multi::array_ref TNN(to_address(SM_TMats->origin()), {NEL, NEL}); @@ -164,14 +171,16 @@ class SlaterDetOperations_shared : public SlaterDetOperations_base(A.sizes()); - int NAEA = std::get<1>(A.sizes()); + + using std::get; + int NMO = get<0>(A.sizes()); + int NAEA = get<1>(A.sizes()); int M = NMO / npol; assert(NMO % npol == 0); - assert(std::get<0>(P1.sizes()) == NMO); - assert(std::get<1>(P1.sizes()) == NMO); - assert(std::get<0>(V.sizes()) == M); - assert(std::get<1>(V.sizes()) == M); + assert(get<0>(P1.sizes()) == NMO); + assert(get<1>(P1.sizes()) == NMO); + assert(get<0>(V.sizes()) == M); + assert(get<1>(V.sizes()) == M); set_shm_buffer(comm, NAEA * (NMO + 2 * M)); assert(SM_TMats->num_elements() >= NAEA * (NMO + 2 * M)); boost::multi::array_ref T0(to_address(SM_TMats->origin()), {NMO, NAEA}); diff --git a/src/AFQMC/SlaterDeterminantOperations/apply_expM.hpp b/src/AFQMC/SlaterDeterminantOperations/apply_expM.hpp index 9d47d465d8..2ea72ca3bb 100644 --- a/src/AFQMC/SlaterDeterminantOperations/apply_expM.hpp +++ b/src/AFQMC/SlaterDeterminantOperations/apply_expM.hpp @@ -36,12 +36,13 @@ namespace base template inline void apply_expM(const MatA& V, MatB&& S, MatC& T1, MatC& T2, int order = 6, char TA = 'N') { - assert(std::get<0>(V.sizes()) == std::get<1>(V.sizes())); - assert(std::get<1>(V.sizes()) == std::get<0>(S.sizes())); - assert(std::get<0>(S.sizes()) == std::get<0>(T1.sizes())); - assert(std::get<1>(S.sizes()) == std::get<1>(T1.sizes())); - assert(std::get<0>(S.sizes()) == std::get<0>(T2.sizes())); - assert(std::get<1>(S.sizes()) == std::get<1>(T2.sizes())); + using std::get; + assert(get<0>(V.sizes()) == get<1>(V.sizes())); + assert(get<1>(V.sizes()) == get<0>(S.sizes())); + assert(get<0>(S.sizes()) == get<0>(T1.sizes())); + assert(get<1>(S.sizes()) == get<1>(T1.sizes())); + assert(get<0>(S.sizes()) == get<0>(T2.sizes())); + assert(get<1>(S.sizes()) == get<1>(T2.sizes())); using ma::H; using ma::T; @@ -56,7 +57,7 @@ inline void apply_expM(const MatA& V, MatB&& S, MatC& T1, MatC& T2, int order = // getting around issue in multi, fix later //T1 = S; - T1.sliced(0, std::get<0>(T1.sizes())) = S; + T1.sliced(0, get<0>(T1.sizes())) = S; for (int n = 1; n <= order; n++) { ComplexType fact = im * static_cast(1.0 / static_cast(n)); @@ -82,12 +83,13 @@ namespace shm template inline void apply_expM(const MatA& V, MatB&& S, MatC& T1, MatC& T2, communicator& comm, int order = 6, char TA = 'N') { - assert(std::get<0>(V.sizes()) == std::get<0>(S.sizes())); - assert(std::get<1>(V.sizes()) == std::get<0>(S.sizes())); - assert(std::get<0>(S.sizes()) == std::get<0>(T1.sizes())); - assert(std::get<1>(S.sizes()) == std::get<1>(T1.sizes())); - assert(std::get<0>(S.sizes()) == std::get<0>(T2.sizes())); - assert(std::get<1>(S.sizes()) == std::get<1>(T2.sizes())); + using std::get; + assert(get<0>(V.sizes()) == get<0>(S.sizes())); + assert(get<1>(V.sizes()) == get<0>(S.sizes())); + assert(get<0>(S.sizes()) == get<0>(T1.sizes())); + assert(get<1>(S.sizes()) == get<1>(T1.sizes())); + assert(get<0>(S.sizes()) == get<0>(T2.sizes())); + assert(get<1>(S.sizes()) == get<1>(T2.sizes())); using ComplexType = typename std::decay::type::element; @@ -118,7 +120,7 @@ inline void apply_expM(const MatA& V, MatB&& S, MatC& T1, MatC& T2, communicator ma::product(fact, V.sliced(M0, Mn), *pT1, zero, (*pT2).sliced(M0, Mn)); // overload += ??? for (int i = M0; i < Mn; i++) - for (int j = 0, je = std::get<1>(S.sizes()); j < je; j++) + for (int j = 0, je = get<1>(S.sizes()); j < je; j++) S[i][j] += (*pT2)[i][j]; comm.barrier(); std::swap(pT1, pT2); @@ -139,22 +141,24 @@ inline void apply_expM(const MatA& V, MatB&& S, MatC& T1, MatC& T2, int order = static_assert(std::decay::type::dimensionality == 3, " batched::apply_expM::dimenionality == 3"); static_assert(std::decay::type::dimensionality == 3, " batched::apply_expM::dimenionality == 3"); static_assert(std::decay::type::dimensionality == 3, " batched::apply_expM::dimenionality == 3"); - assert(std::get<0>(V.sizes()) == std::get<0>(S.sizes())); - assert(std::get<0>(V.sizes()) == std::get<0>(T1.sizes())); - assert(std::get<0>(V.sizes()) == std::get<0>(T2.sizes())); - assert(std::get<1>(V.sizes()) == std::get<2>(V.sizes())); - assert(std::get<2>(V.sizes()) == std::get<1>(S.sizes())); - assert(std::get<1>(S.sizes()) == std::get<1>(T1.sizes())); - assert(std::get<2>(S.sizes()) == std::get<2>(T1.sizes())); - assert(std::get<1>(S.sizes()) == std::get<1>(T2.sizes())); - assert(std::get<2>(S.sizes()) == std::get<2>(T2.sizes())); + + using std::get; + assert(get<0>(V.sizes()) == get<0>(S.sizes())); + assert(get<0>(V.sizes()) == get<0>(T1.sizes())); + assert(get<0>(V.sizes()) == get<0>(T2.sizes())); + assert(get<1>(V.sizes()) == get<2>(V.sizes())); + assert(get<2>(V.sizes()) == get<1>(S.sizes())); + assert(get<1>(S.sizes()) == get<1>(T1.sizes())); + assert(get<2>(S.sizes()) == get<2>(T1.sizes())); + assert(get<1>(S.sizes()) == get<1>(T2.sizes())); + assert(get<2>(S.sizes()) == get<2>(T2.sizes())); // for now limit to continuous - assert(S.stride(0) == std::get<1>(S.sizes()) * std::get<2>(S.sizes())); - assert(T1.stride(0) == std::get<1>(T1.sizes()) * std::get<2>(T1.sizes())); - assert(T2.stride(0) == std::get<1>(T2.sizes()) * std::get<2>(T2.sizes())); - assert(S.stride(1) == std::get<2>(S.sizes())); - assert(T1.stride(1) == std::get<2>(T1.sizes())); - assert(T2.stride(1) == std::get<2>(T2.sizes())); + assert(S.stride(0) == get<1>(S.sizes()) * get<2>(S.sizes())); + assert(T1.stride(0) == get<1>(T1.sizes()) * get<2>(T1.sizes())); + assert(T2.stride(0) == get<1>(T2.sizes()) * get<2>(T2.sizes())); + assert(S.stride(1) == get<2>(S.sizes())); + assert(T1.stride(1) == get<2>(T1.sizes())); + assert(T2.stride(1) == get<2>(T2.sizes())); assert(S.stride(2) == 1); assert(T1.stride(2) == 1); assert(T2.stride(2) == 1); @@ -197,22 +201,24 @@ inline void apply_expM_noncollinear(const MatA& V, MatB&& S, MatC& T1, MatC& T2, static_assert(std::decay::type::dimensionality == 3, " batched::apply_expM::dimenionality == 3"); static_assert(std::decay::type::dimensionality == 3, " batched::apply_expM::dimenionality == 3"); static_assert(std::decay::type::dimensionality == 3, " batched::apply_expM::dimenionality == 3"); - assert(std::get<0>(V.sizes()) * 2 == std::get<0>(S.sizes())); - assert(std::get<0>(V.sizes()) * 2 == std::get<0>(T1.sizes())); - assert(std::get<0>(V.sizes()) * 2 == std::get<0>(T2.sizes())); - assert(std::get<1>(V.sizes()) == std::get<2>(V.sizes())); - assert(std::get<2>(V.sizes()) == std::get<1>(S.sizes())); - assert(std::get<1>(S.sizes()) == std::get<1>(T1.sizes())); - assert(std::get<2>(S.sizes()) == std::get<2>(T1.sizes())); - assert(std::get<1>(S.sizes()) == std::get<1>(T2.sizes())); - assert(std::get<2>(S.sizes()) == std::get<2>(T2.sizes())); + + using std::get; + assert(get<0>(V.sizes()) * 2 == get<0>(S.sizes())); + assert(get<0>(V.sizes()) * 2 == get<0>(T1.sizes())); + assert(get<0>(V.sizes()) * 2 == get<0>(T2.sizes())); + assert(get<1>(V.sizes()) == get<2>(V.sizes())); + assert(get<2>(V.sizes()) == get<1>(S.sizes())); + assert(get<1>(S.sizes()) == get<1>(T1.sizes())); + assert(get<2>(S.sizes()) == get<2>(T1.sizes())); + assert(get<1>(S.sizes()) == get<1>(T2.sizes())); + assert(get<2>(S.sizes()) == get<2>(T2.sizes())); // for now limit to continuous - assert(S.stride(0) == std::get<1>(S.sizes()) * std::get<2>(S.sizes())); - assert(T1.stride(0) == std::get<1>(T1.sizes()) * std::get<2>(T1.sizes())); - assert(T2.stride(0) == std::get<1>(T2.sizes()) * std::get<2>(T2.sizes())); - assert(S.stride(1) == std::get<2>(S.sizes())); - assert(T1.stride(1) == std::get<2>(T1.sizes())); - assert(T2.stride(1) == std::get<2>(T2.sizes())); + assert(S.stride(0) == get<1>(S.sizes()) * get<2>(S.sizes())); + assert(T1.stride(0) == get<1>(T1.sizes()) * get<2>(T1.sizes())); + assert(T2.stride(0) == get<1>(T2.sizes()) * get<2>(T2.sizes())); + assert(S.stride(1) == get<2>(S.sizes())); + assert(T1.stride(1) == get<2>(T1.sizes())); + assert(T2.stride(1) == get<2>(T2.sizes())); assert(S.stride(2) == 1); assert(T1.stride(2) == 1); assert(T2.stride(2) == 1); @@ -230,9 +236,9 @@ inline void apply_expM_noncollinear(const MatA& V, MatB&& S, MatC& T1, MatC& T2, int nbatch = S.size(); int ldv = V.stride(1); - int M = std::get<2>(T2.sizes()); - int N = std::get<1>(T2.sizes()); - int K = std::get<1>(T1.sizes()); + int M = get<2>(T2.sizes()); + int N = get<1>(T2.sizes()); + int K = get<1>(T1.sizes()); std::vector Vi; std::vector T1i; diff --git a/src/AFQMC/SlaterDeterminantOperations/mixed_density_matrix.hpp b/src/AFQMC/SlaterDeterminantOperations/mixed_density_matrix.hpp index a0bc437725..b2390dc56e 100644 --- a/src/AFQMC/SlaterDeterminantOperations/mixed_density_matrix.hpp +++ b/src/AFQMC/SlaterDeterminantOperations/mixed_density_matrix.hpp @@ -62,24 +62,26 @@ Tp MixedDensityMatrix(const MatA& hermA, bool compact = true, bool herm = true) { + using std::get; // check dimensions are consistent - int NMO = (herm ? std::get<1>(hermA.sizes()) : std::get<0>(hermA.sizes())); - int NEL = (herm ? std::get<0>(hermA.sizes()) : std::get<1>(hermA.sizes())); - assert(NMO == std::get<0>(B.sizes())); - assert(NEL == std::get<1>(B.sizes())); + int NMO = (herm ? get<1>(hermA.sizes()) : get<0>(hermA.sizes())); + int NEL = (herm ? get<0>(hermA.sizes()) : get<1>(hermA.sizes())); + + assert(NMO == get<0>(B.sizes())); + assert(NEL == get<1>(B.sizes())); assert(NEL == T1.size()); - assert(std::get<1>(B.sizes()) == std::get<1>(T1.sizes())); + assert(get<1>(B.sizes()) == get<1>(T1.sizes())); if (compact) { - assert(std::get<0>(C.sizes()) == std::get<1>(T1.sizes())); - assert(std::get<1>(C.sizes()) == std::get<0>(B.sizes())); + assert(get<0>(C.sizes()) == get<1>(T1.sizes())); + assert(get<1>(C.sizes()) == get<0>(B.sizes())); } else { - assert(std::get<1>(T2.sizes()) == B.size()); - assert(T2.size() == std::get<1>(T1.sizes())); + assert(get<1>(T2.sizes()) == B.size()); + assert(T2.size() == get<1>(T1.sizes())); assert(C.size() == NMO); - assert(std::get<1>(C.sizes()) == std::get<1>(T2.sizes())); + assert(get<1>(C.sizes()) == get<1>(T2.sizes())); } using ma::H; @@ -152,26 +154,28 @@ Tp MixedDensityMatrixForWoodbury(const MatA& hermA, TBuffer& WORK, bool compact = true) { + using std::get; + // check dimensions are consistent - int NEL = std::get<1>(B.sizes()); - assert(std::get<1>(hermA.sizes()) == std::get<0>(B.sizes())); - assert(std::get<0>(hermA.sizes()) == std::get<0>(TAB.sizes())); - assert(std::get<1>(B.sizes()) == std::get<1>(TAB.sizes())); - assert(std::get<1>(B.sizes()) == std::get<0>(TNN.sizes())); - assert(std::get<1>(B.sizes()) == std::get<1>(TNN.sizes())); - assert(std::get<0>(hermA.sizes()) == std::get<0>(QQ0.sizes())); - assert(std::get<1>(B.sizes()) == std::get<1>(QQ0.sizes())); + int NEL = get<1>(B.sizes()); + assert(get<1>(hermA.sizes()) == get<0>(B.sizes())); + assert(get<0>(hermA.sizes()) == get<0>(TAB.sizes())); + assert(get<1>(B.sizes()) == get<1>(TAB.sizes())); + assert(get<1>(B.sizes()) == get<0>(TNN.sizes())); + assert(get<1>(B.sizes()) == get<1>(TNN.sizes())); + assert(get<0>(hermA.sizes()) == get<0>(QQ0.sizes())); + assert(get<1>(B.sizes()) == get<1>(QQ0.sizes())); if (compact) { - assert(std::get<0>(C.sizes()) == std::get<1>(TNN.sizes())); - assert(std::get<1>(C.sizes()) == std::get<0>(B.sizes())); + assert(get<0>(C.sizes()) == get<1>(TNN.sizes())); + assert(get<1>(C.sizes()) == get<0>(B.sizes())); } else { - assert(std::get<1>(TNM.sizes()) == std::get<0>(B.sizes())); - assert(std::get<0>(TNM.sizes()) == std::get<1>(TNN.sizes())); - assert(std::get<0>(C.sizes()) == std::get<1>(hermA.sizes())); - assert(std::get<1>(C.sizes()) == std::get<1>(TNM.sizes())); + assert(get<1>(TNM.sizes()) == get<0>(B.sizes())); + assert(get<0>(TNM.sizes()) == get<1>(TNN.sizes())); + assert(get<0>(C.sizes()) == get<1>(hermA.sizes())); + assert(get<1>(C.sizes()) == get<1>(TNM.sizes())); } using ma::T; @@ -233,24 +237,26 @@ Tp MixedDensityMatrixFromConfiguration(const MatA& hermA, TBuffer& WORK, bool compact = true) { + using std::get; + // check dimensions are consistent - int NEL = std::get<1>(B.sizes()); - assert(std::get<1>(hermA.sizes()) == std::get<0>(B.sizes())); - assert(std::get<0>(hermA.sizes()) == std::get<0>(TAB.sizes())); - assert(std::get<1>(B.sizes()) == std::get<1>(TAB.sizes())); - assert(std::get<1>(B.sizes()) == std::get<0>(TNN.sizes())); - assert(std::get<1>(B.sizes()) == std::get<1>(TNN.sizes())); + int NEL = get<1>(B.sizes()); + assert(get<1>(hermA.sizes()) == get<0>(B.sizes())); + assert(get<0>(hermA.sizes()) == get<0>(TAB.sizes())); + assert(get<1>(B.sizes()) == get<1>(TAB.sizes())); + assert(get<1>(B.sizes()) == get<0>(TNN.sizes())); + assert(get<1>(B.sizes()) == get<1>(TNN.sizes())); if (compact) { - assert(std::get<0>(C.sizes()) == std::get<1>(TNN.sizes())); - assert(std::get<1>(C.sizes()) == std::get<0>(B.sizes())); + assert(get<0>(C.sizes()) == get<1>(TNN.sizes())); + assert(get<1>(C.sizes()) == get<0>(B.sizes())); } else { - assert(std::get<1>(TNM.sizes()) == std::get<0>(B.sizes())); - assert(std::get<0>(TNM.sizes()) == std::get<1>(TNN.sizes())); - assert(std::get<0>(C.sizes()) == std::get<1>(hermA.sizes())); - assert(std::get<1>(C.sizes()) == std::get<1>(TNM.sizes())); + assert(get<1>(TNM.sizes()) == get<0>(B.sizes())); + assert(get<0>(TNM.sizes()) == get<1>(TNN.sizes())); + assert(get<0>(C.sizes()) == get<1>(hermA.sizes())); + assert(get<1>(C.sizes()) == get<1>(TNM.sizes())); } using ma::T; @@ -316,22 +322,24 @@ Tp MixedDensityMatrix_noHerm(const MatA& A, TBuffer& WORK, bool compact = true) { + using std::get; + // check dimensions are consistent - assert(std::get<0>(A.sizes()) == std::get<0>(B.sizes())); - assert(std::get<1>(A.sizes()) == std::get<1>(B.sizes())); - assert(std::get<1>(A.sizes()) == std::get<0>(T1.sizes())); - assert(std::get<1>(B.sizes()) == std::get<1>(T1.sizes())); + assert(get<0>(A.sizes()) == get<0>(B.sizes())); + assert(get<1>(A.sizes()) == get<1>(B.sizes())); + assert(get<1>(A.sizes()) == get<0>(T1.sizes())); + assert(get<1>(B.sizes()) == get<1>(T1.sizes())); if (compact) { - assert(std::get<0>(C.sizes()) == std::get<1>(T1.sizes())); - assert(std::get<1>(C.sizes()) == std::get<0>(B.sizes())); + assert(get<0>(C.sizes()) == get<1>(T1.sizes())); + assert(get<1>(C.sizes()) == get<0>(B.sizes())); } else { - assert(std::get<1>(T2.sizes()) == std::get<0>(B.sizes())); - assert(std::get<0>(T2.sizes()) == std::get<1>(T1.sizes())); - assert(std::get<0>(C.sizes()) == std::get<0>(A.sizes())); - assert(std::get<1>(C.sizes()) == std::get<1>(T2.sizes())); + assert(get<1>(T2.sizes()) == get<0>(B.sizes())); + assert(get<0>(T2.sizes()) == get<1>(T1.sizes())); + assert(get<0>(C.sizes()) == get<0>(A.sizes())); + assert(get<1>(C.sizes()) == get<1>(T2.sizes())); } using ma::H; @@ -380,27 +388,29 @@ Tp MixedDensityMatrix_noHerm_wSVD(const MatA& A, TBuffer& WORK, bool compact = true) { + using std::get; + // check dimensions are consistent - assert(std::get<0>(A.sizes()) == std::get<0>(B.sizes())); - assert(std::get<1>(A.sizes()) == std::get<1>(B.sizes())); - assert(std::get<1>(A.sizes()) == std::get<0>(U.sizes())); // [U] = [NxN] - assert(std::get<1>(A.sizes()) == std::get<1>(U.sizes())); - assert(std::get<1>(A.sizes()) == std::get<0>(VT.sizes())); // [V] = [NxN] - assert(std::get<1>(A.sizes()) == std::get<1>(VT.sizes())); - assert(std::get<1>(A.sizes()) <= (6 * S.size() + 1)); // [S] = [N+1] - assert(std::get<1>(A.sizes()) == std::get<0>(UA.sizes())); // [UA] = [NxM] - assert(std::get<0>(A.sizes()) == std::get<1>(UA.sizes())); + assert(get<0>(A.sizes()) == get<0>(B.sizes())); + assert(get<1>(A.sizes()) == get<1>(B.sizes())); + assert(get<1>(A.sizes()) == get<0>(U.sizes())); // [U] = [NxN] + assert(get<1>(A.sizes()) == get<1>(U.sizes())); + assert(get<1>(A.sizes()) == get<0>(VT.sizes())); // [V] = [NxN] + assert(get<1>(A.sizes()) == get<1>(VT.sizes())); + assert(get<1>(A.sizes()) <= (6 * S.size() + 1)); // [S] = [N+1] + assert(get<1>(A.sizes()) == get<0>(UA.sizes())); // [UA] = [NxM] + assert(get<0>(A.sizes()) == get<1>(UA.sizes())); if (compact) { - assert(std::get<0>(C.sizes()) == std::get<1>(B.sizes())); - assert(std::get<1>(C.sizes()) == std::get<0>(B.sizes())); + assert(get<0>(C.sizes()) == get<1>(B.sizes())); + assert(get<1>(C.sizes()) == get<0>(B.sizes())); } else { - assert( std::get<0>(A.sizes()) == std::get<0>(BV.sizes()) ); // [BV] = [MxN] - assert( std::get<1>(A.sizes()) == std::get<1>(BV.sizes()) ); - assert( std::get<0>(C.sizes()) == std::get<0>(A.sizes()) ); - assert( std::get<1>(C.sizes()) == std::get<0>(A.sizes()) ); + assert( get<0>(A.sizes()) == get<0>(BV.sizes()) ); // [BV] = [MxN] + assert( get<1>(A.sizes()) == get<1>(BV.sizes()) ); + assert( get<0>(C.sizes()) == get<0>(A.sizes()) ); + assert( get<1>(C.sizes()) == get<0>(A.sizes()) ); } using ma::determinant_from_geqrf; @@ -453,7 +463,7 @@ Tp MixedDensityMatrix_noHerm_wSVD(const MatA& A, // VT = VT * inv(S), which works since S is diagonal and real - term_by_term_matrix_vector(ma::TOp_DIV, 0, std::get<0>(VT.sizes()), std::get<1>(VT.sizes()), ma::pointer_dispatch(VT.origin()), VT.stride(0), + term_by_term_matrix_vector(ma::TOp_DIV, 0, get<0>(VT.sizes()), get<1>(VT.sizes()), ma::pointer_dispatch(VT.origin()), VT.stride(0), ma::pointer_dispatch(S.origin()), 1); // BV = H(VT) * H(U) @@ -473,7 +483,7 @@ Tp MixedDensityMatrix_noHerm_wSVD(const MatA& A, ma::product(B, H(VT), BV); // BV = BV * inv(S), which works since S is diagonal and real - term_by_term_matrix_vector(ma::TOp_DIV, 1, std::get<0>(BV.sizes()), std::get<1>(BV.sizes()), ma::pointer_dispatch(BV.origin()), BV.stride(0), + term_by_term_matrix_vector(ma::TOp_DIV, 1, get<0>(BV.sizes()), get<1>(BV.sizes()), ma::pointer_dispatch(BV.origin()), BV.stride(0), ma::pointer_dispatch(S.origin()), 1); // UA = H(U) * H(A) @@ -505,13 +515,14 @@ Tp Overlap(const MatA& hermA, Buffer&& WORK, bool herm = true) { - int NMO = (herm ? std::get<1>(hermA.sizes()) : std::get<0>(hermA.sizes())); - int NEL = (herm ? std::get<0>(hermA.sizes()) : std::get<1>(hermA.sizes())); + using std::get; + int NMO = (herm ? get<1>(hermA.sizes()) : get<0>(hermA.sizes())); + int NEL = (herm ? get<0>(hermA.sizes()) : get<1>(hermA.sizes())); // check dimensions are consistent - assert(NMO == std::get<0>(B.sizes())); - assert(NEL == std::get<1>(B.sizes())); - assert(NEL == std::get<0>(T1.sizes())); - assert(std::get<1>(B.sizes()) == std::get<1>(T1.sizes())); + assert(NMO == get<0>(B.sizes())); + assert(NEL == get<1>(B.sizes())); + assert(NEL == get<0>(T1.sizes())); + assert(get<1>(B.sizes()) == get<1>(T1.sizes())); using ma::H; using ma::T; @@ -544,15 +555,17 @@ Tp OverlapForWoodbury(const MatA& hermA, IBuffer& IWORK, TBuffer& WORK) { + using std::get; + // check dimensions are consistent - int NEL = std::get<1>(B.sizes()); - assert(std::get<1>(hermA.sizes()) == std::get<0>(B.sizes())); - assert(std::get<0>(hermA.sizes()) == std::get<0>(TMN.sizes())); - assert(std::get<1>(B.sizes()) == std::get<1>(TMN.sizes())); - assert(std::get<1>(B.sizes()) == std::get<0>(TNN.sizes())); - assert(std::get<1>(B.sizes()) == std::get<1>(TNN.sizes())); - assert(std::get<0>(hermA.sizes()) == std::get<0>(QQ0.sizes())); - assert(std::get<1>(B.sizes()) == std::get<1>(QQ0.sizes())); + int NEL = get<1>(B.sizes()); + assert(get<1>(hermA.sizes()) == get<0>(B.sizes())); + assert(get<0>(hermA.sizes()) == get<0>(TMN.sizes())); + assert(get<1>(B.sizes()) == get<1>(TMN.sizes())); + assert(get<1>(B.sizes()) == get<0>(TNN.sizes())); + assert(get<1>(B.sizes()) == get<1>(TNN.sizes())); + assert(get<0>(hermA.sizes()) == get<0>(QQ0.sizes())); + assert(get<1>(B.sizes()) == get<1>(QQ0.sizes())); using ma::T; @@ -592,11 +605,12 @@ Tp OverlapForWoodbury(const MatA& hermA, template Tp Overlap_noHerm(const MatA& A, const MatB& B, Tp LogOverlapFactor, Mat&& T1, IBuffer& IWORK, Buffer& WORK) { + using std::get; // check dimensions are consistent - assert(std::get<0>(A.sizes()) == std::get<0>(B.sizes())); - assert(std::get<1>(A.sizes()) == std::get<1>(B.sizes())); - assert(std::get<1>(A.sizes()) == std::get<0>(T1.sizes())); - assert(std::get<1>(B.sizes()) == std::get<1>(T1.sizes())); + assert(get<0>(A.sizes()) == get<0>(B.sizes())); + assert(get<1>(A.sizes()) == get<1>(B.sizes())); + assert(get<1>(A.sizes()) == get<0>(T1.sizes())); + assert(get<1>(B.sizes()) == get<1>(T1.sizes())); using ma::H; using ma::T; @@ -642,30 +656,32 @@ Tp MixedDensityMatrix(const MatA& hermA, bool compact = true, bool herm = true) { - int NMO = (herm ? std::get<1>(hermA.sizes()) : std::get<0>(hermA.sizes())); - int NEL = (herm ? std::get<0>(hermA.sizes()) : std::get<1>(hermA.sizes())); + using std::get; + int NMO = (herm ? get<1>(hermA.sizes()) : get<0>(hermA.sizes())); + int NEL = (herm ? get<0>(hermA.sizes()) : get<1>(hermA.sizes())); // check dimensions are consistent - assert(NMO == std::get<0>(B.sizes())); - assert(NEL == std::get<1>(B.sizes())); - assert(NEL == std::get<0>(T1.sizes())); - assert(std::get<1>(B.sizes()) == std::get<1>(T1.sizes())); + using std::get; + assert(NMO == get<0>(B.sizes())); + assert(NEL == get<1>(B.sizes())); + assert(NEL == get<0>(T1.sizes())); + assert(get<1>(B.sizes()) == get<1>(T1.sizes())); if (compact) { - assert(std::get<0>(C.sizes()) == std::get<1>(T1.sizes())); - assert(std::get<1>(C.sizes()) == std::get<0>(B.sizes())); + assert(get<0>(C.sizes()) == get<1>(T1.sizes())); + assert(get<1>(C.sizes()) == get<0>(B.sizes())); } else { - assert(std::get<1>(T2.sizes()) == std::get<0>(B.sizes())); - assert(std::get<0>(T2.sizes()) == std::get<1>(T1.sizes())); - assert(std::get<0>(C.sizes()) == NMO); - assert(std::get<1>(C.sizes()) == std::get<1>(T2.sizes())); + assert(get<1>(T2.sizes()) == get<0>(B.sizes())); + assert(get<0>(T2.sizes()) == get<1>(T1.sizes())); + assert(get<0>(C.sizes()) == NMO); + assert(get<1>(C.sizes()) == get<1>(T2.sizes())); } using ma::H; using ma::T; - int N0, Nn, sz = std::get<1>(B.sizes()); + int N0, Nn, sz = get<1>(B.sizes()); std::tie(N0, Nn) = FairDivideBoundary(comm.rank(), sz, comm.size()); // T(B)*conj(A) @@ -718,7 +734,7 @@ Tp MixedDensityMatrix(const MatA& hermA, comm.barrier(); - sz = std::get<1>(T2.sizes()); + sz = get<1>(T2.sizes()); std::tie(N0, Nn) = FairDivideBoundary(comm.rank(), sz, comm.size()); // C = conj(A) * T2 @@ -734,7 +750,7 @@ Tp MixedDensityMatrix(const MatA& hermA, comm.barrier(); - sz = std::get<1>(T2.sizes()); + sz = get<1>(T2.sizes()); std::tie(N0, Nn) = FairDivideBoundary(comm.rank(), sz, comm.size()); // C = T( B * T2) = T(T2) * T(B) @@ -768,18 +784,20 @@ Tp Overlap(const MatA& hermA, communicator& comm, bool herm = true) { - int NMO = (herm ? std::get<1>(hermA.sizes()) : std::get<0>(hermA.sizes())); - int NEL = (herm ? std::get<0>(hermA.sizes()) : std::get<1>(hermA.sizes())); + using std::get; + + int NMO = (herm ? get<1>(hermA.sizes()) : get<0>(hermA.sizes())); + int NEL = (herm ? get<0>(hermA.sizes()) : get<1>(hermA.sizes())); // check dimensions are consistent - assert(NMO == std::get<0>(B.sizes())); - assert(NEL == std::get<1>(B.sizes())); - assert(NEL == std::get<0>(T1.sizes())); - assert(std::get<1>(B.sizes()) == std::get<1>(T1.sizes())); + assert(NMO == get<0>(B.sizes())); + assert(NEL == get<1>(B.sizes())); + assert(NEL == get<0>(T1.sizes())); + assert(get<1>(B.sizes()) == get<1>(T1.sizes())); using ma::H; using ma::T; - int N0, Nn, sz = std::get<1>(B.sizes()); + int N0, Nn, sz = get<1>(B.sizes()); std::tie(N0, Nn) = FairDivideBoundary(comm.rank(), sz, comm.size()); // T(B)*conj(A) @@ -822,19 +840,20 @@ Tp OverlapForWoodbury(const MatA& hermA, TBuffer& WORK, communicator& comm) { + using std::get; // check dimensions are consistent - int NEL = std::get<1>(B.sizes()); - assert(std::get<1>(hermA.sizes()) == std::get<0>(B.sizes())); - assert(std::get<0>(hermA.sizes()) == std::get<0>(TMN.sizes())); - assert(std::get<1>(B.sizes()) == std::get<1>(TMN.sizes())); - assert(std::get<1>(B.sizes()) == std::get<0>(TNN.sizes())); - assert(std::get<1>(B.sizes()) == std::get<1>(TNN.sizes())); - assert(std::get<0>(hermA.sizes()) == std::get<0>(QQ0.sizes())); - assert(std::get<1>(B.sizes()) == std::get<1>(QQ0.sizes())); + int NEL = get<1>(B.sizes()); + assert(get<1>(hermA.sizes()) == get<0>(B.sizes())); + assert(get<0>(hermA.sizes()) == get<0>(TMN.sizes())); + assert(get<1>(B.sizes()) == get<1>(TMN.sizes())); + assert(get<1>(B.sizes()) == get<0>(TNN.sizes())); + assert(get<1>(B.sizes()) == get<1>(TNN.sizes())); + assert(get<0>(hermA.sizes()) == get<0>(QQ0.sizes())); + assert(get<1>(B.sizes()) == get<1>(QQ0.sizes())); using ma::T; - int N0, Nn, sz = std::get<1>(B.sizes()); + int N0, Nn, sz = get<1>(B.sizes()); std::tie(N0, Nn) = FairDivideBoundary(comm.rank(), sz, comm.size()); Tp ovlp; @@ -887,26 +906,28 @@ Tp MixedDensityMatrixForWoodbury(const MatA& hermA, communicator& comm, bool compact = true) { - // check dimensions are consistent - int NEL = std::get<1>(B.sizes()); - assert(std::get<1>(hermA.sizes()) == std::get<0>(B.sizes())); - assert(std::get<0>(hermA.sizes()) == std::get<0>(TAB.sizes())); - assert(std::get<1>(B.sizes()) == std::get<1>(TAB.sizes())); - assert(std::get<1>(B.sizes()) == std::get<0>(TNN.sizes())); - assert(std::get<1>(B.sizes()) == std::get<1>(TNN.sizes())); - assert(std::get<0>(hermA.sizes()) == std::get<0>(QQ0.sizes())); - assert(std::get<1>(B.sizes()) == std::get<1>(QQ0.sizes())); + using std::get; + + // check dimensions are consistent + int NEL = get<1>(B.sizes()); + assert(get<1>(hermA.sizes()) == get<0>(B.sizes())); + assert(get<0>(hermA.sizes()) == get<0>(TAB.sizes())); + assert(get<1>(B.sizes()) == get<1>(TAB.sizes())); + assert(get<1>(B.sizes()) == get<0>(TNN.sizes())); + assert(get<1>(B.sizes()) == get<1>(TNN.sizes())); + assert(get<0>(hermA.sizes()) == get<0>(QQ0.sizes())); + assert(get<1>(B.sizes()) == get<1>(QQ0.sizes())); if (compact) { - assert(std::get<0>(C.sizes()) == std::get<1>(TNN.sizes())); - assert(std::get<1>(C.sizes()) == std::get<0>(B.sizes())); + assert(get<0>(C.sizes()) == get<1>(TNN.sizes())); + assert(get<1>(C.sizes()) == get<0>(B.sizes())); } else { - assert(std::get<1>(TNM.sizes()) == std::get<0>(B.sizes())); - assert(std::get<0>(TNM.sizes()) == std::get<1>(TNN.sizes())); - assert(std::get<0>(C.sizes()) == std::get<1>(hermA.sizes())); - assert(std::get<1>(C.sizes()) == std::get<1>(TNM.sizes())); + assert(get<1>(TNM.sizes()) == get<0>(B.sizes())); + assert(get<0>(TNM.sizes()) == get<1>(TNN.sizes())); + assert(get<0>(C.sizes()) == get<1>(hermA.sizes())); + assert(get<1>(C.sizes()) == get<1>(TNM.sizes())); } using ma::T; @@ -933,7 +954,7 @@ Tp MixedDensityMatrixForWoodbury(const MatA& hermA, comm.broadcast_n(&ovlp, 1, 0); int P0, Pn; - std::tie(P0, Pn) = FairDivideBoundary(comm.rank(), int(std::get<0>(TAB.sizes())), comm.size()); + std::tie(P0, Pn) = FairDivideBoundary(comm.rank(), int(get<0>(TAB.sizes())), comm.size()); // QQ0 = TAB * inv(TNN) if (P0 != Pn) @@ -951,7 +972,7 @@ Tp MixedDensityMatrixForWoodbury(const MatA& hermA, if (N0 != Nn) ma::product(T(TNN(TNN.extension(0), {N0, Nn})), T(B), TNM.sliced(N0, Nn)); - int sz = std::get<1>(TNM.sizes()); + int sz = get<1>(TNM.sizes()); std::tie(N0, Nn) = FairDivideBoundary(comm.rank(), sz, comm.size()); comm.barrier(); @@ -992,26 +1013,27 @@ void MixedDensityMatrix(std::vector& hermA, using ma::H; using ma::T; + using std::get; int nbatch = Bi.size(); - int NMO = (herm ? std::get<1>((*hermA[0]).sizes()) : std::get<0>((*hermA[0]).sizes())); - int NEL = (herm ? std::get<0>((*hermA[0]).sizes()) : std::get<1>((*hermA[0]).sizes())); + int NMO = (herm ? get<1>((*hermA[0]).sizes()) : get<0>((*hermA[0]).sizes())); + int NEL = (herm ? get<0>((*hermA[0]).sizes()) : get<1>((*hermA[0]).sizes())); - assert(std::get<0>((*Bi[0]).sizes()) == NMO); - assert(std::get<1>((*Bi[0]).sizes()) == NEL); + assert(get<0>((*Bi[0]).sizes()) == NMO); + assert(get<1>((*Bi[0]).sizes()) == NEL); assert(C.size() == nbatch); - assert(std::get<2>(C.sizes()) == NMO); + assert(get<2>(C.sizes()) == NMO); if (compact) - assert(std::get<1>(C.sizes()) == NEL); + assert(get<1>(C.sizes()) == NEL); else - assert(std::get<1>(C.sizes()) == NMO); + assert(get<1>(C.sizes()) == NMO); assert(ovlp.size() == nbatch); - assert(std::get<1>(TNN3D.sizes()) == NEL); - assert(std::get<2>(TNN3D.sizes()) == NEL); + assert(get<1>(TNN3D.sizes()) == NEL); + assert(get<2>(TNN3D.sizes()) == NEL); if (not compact) { - assert(std::get<0>(TNM3D.sizes()) == nbatch); - assert(std::get<1>(TNM3D.sizes()) == NEL); - assert(std::get<2>(TNM3D.sizes()) == NMO); + assert(get<0>(TNM3D.sizes()) == nbatch); + assert(get<1>(TNM3D.sizes()) == NEL); + assert(get<2>(TNM3D.sizes()) == NMO); } assert(IWORK.num_elements() >= nbatch * (NEL + 1)); assert(TNN3D.stride(1) == NEL); // needed by getriBatched @@ -1148,26 +1170,27 @@ void DensityMatrices(std::vector const& Left, using ma::H; using ma::T; + using std::get; int nbatch = Right.size(); - int NMO = (herm ? std::get<1>((*Left[0]).sizes()) : std::get<0>((*Left[0]).sizes())); - int NEL = (herm ? std::get<0>((*Left[0]).sizes()) : std::get<1>((*Left[0]).sizes())); + int NMO = (herm ? get<1>((*Left[0]).sizes()) : get<0>((*Left[0]).sizes())); + int NEL = (herm ? get<0>((*Left[0]).sizes()) : get<1>((*Left[0]).sizes())); - assert(std::get<0>((*Right[0]).sizes()) == NMO); - assert(std::get<1>((*Right[0]).sizes()) == NEL); + assert(get<0>((*Right[0]).sizes()) == NMO); + assert(get<1>((*Right[0]).sizes()) == NEL); assert(G.size() == nbatch); - assert(std::get<1>((*G[0]).sizes()) == NMO); + assert(get<1>((*G[0]).sizes()) == NMO); if (compact) assert((*G[0]).size() == NEL); else assert((*G[0]).size() == NMO); assert(ovlp.size() == nbatch); - assert(std::get<1>(TNN3D.sizes()) == NEL); - assert(std::get<2>(TNN3D.sizes()) == NEL); + assert(get<1>(TNN3D.sizes()) == NEL); + assert(get<2>(TNN3D.sizes()) == NEL); if (not compact) { - assert(std::get<0>(TNM3D.sizes()) == nbatch); - assert(std::get<1>(TNM3D.sizes()) == NEL); - assert(std::get<2>(TNM3D.sizes()) == NMO); + assert(get<0>(TNM3D.sizes()) == nbatch); + assert(get<1>(TNM3D.sizes()) == NEL); + assert(get<2>(TNM3D.sizes()) == NMO); } assert(IWORK.num_elements() >= nbatch * (NEL + 1)); @@ -1273,16 +1296,18 @@ void Overlap(std::vector& hermA, using ma::H; using ma::T; + using std::get; + int nbatch = Bi.size(); assert(hermA.size() >= nbatch); - int NMO = (herm ? std::get<1>((*hermA[0]).sizes()) : std::get<0>((*hermA[0]).sizes())); - int NEL = (herm ? std::get<0>((*hermA[0]).sizes()) : std::get<1>((*hermA[0]).sizes())); + int NMO = (herm ? get<1>((*hermA[0]).sizes()) : get<0>((*hermA[0]).sizes())); + int NEL = (herm ? get<0>((*hermA[0]).sizes()) : get<1>((*hermA[0]).sizes())); - assert(std::get<0>((*Bi[0]).sizes()) == NMO); - assert(std::get<1>((*Bi[0]).sizes()) == NEL); + assert(get<0>((*Bi[0]).sizes()) == NMO); + assert(get<1>((*Bi[0]).sizes()) == NEL); assert(ovlp.size() == nbatch); - assert(std::get<1>(TNN3D.sizes()) == NEL); - assert(std::get<2>(TNN3D.sizes()) == NEL); + assert(get<1>(TNN3D.sizes()) == NEL); + assert(get<2>(TNN3D.sizes()) == NEL); assert(IWORK.num_elements() >= nbatch * (NEL + 1)); using pointer = typename std::decay::type::element_ptr; diff --git a/src/AFQMC/SlaterDeterminantOperations/rotate.hpp b/src/AFQMC/SlaterDeterminantOperations/rotate.hpp index 0d32328ee8..3e6fa9c90e 100644 --- a/src/AFQMC/SlaterDeterminantOperations/rotate.hpp +++ b/src/AFQMC/SlaterDeterminantOperations/rotate.hpp @@ -73,15 +73,16 @@ void halfRotateCholeskyMatrix(WALKER_TYPES type, double cutoff = 1e-6, bool reserve_to_fit_ = true) { + using std::get; // for C++17 compaitbility int NAEA = Alpha->size(0); int NAEB = Alpha->size(0); int NMO = Alpha->size(1); if (type == COLLINEAR) NAEB = Beta->size(0); - int nvec = std::get<1>(CholMat.sizes()); + int nvec = get<1>(CholMat.sizes()); int ncores = TG.getTotalCores(), coreid = TG.getCoreID(); - assert(std::get<0>(CholMat.sizes()) == NMO * NMO); + assert(get<0>(CholMat.sizes()) == NMO * NMO); assert(kN > k0); if (type == CLOSED && kN > NMO) APP_ABORT(" Error: kN > NMO in halfRotateCholeskyMatrix. \n"); @@ -296,18 +297,20 @@ SpCType_shm_csr_matrix halfRotateCholeskyMatrixForBias(WALKER_TYPES type, SpVType_shm_csr_matrix const& CholMat, double cutoff = 1e-6) { + using std::get; + int NAEA = Alpha->size(0); int NAEB = Alpha->size(0); int NMO = Alpha->size(1); if (type != CLOSED) NAEB = Beta->size(0); - int nvec = std::get<1>(CholMat.sizes()); + int nvec = get<1>(CholMat.sizes()); int ncores = TG.getTotalCores(), coreid = TG.getCoreID(); // to speed up, generate new communicator for eqv_nodes and split full work among all // cores in this comm. Then build from distributed container? - assert(std::get<0>(CholMat.sizes()) == NMO * NMO); + assert(get<0>(CholMat.sizes()) == NMO * NMO); std::size_t Qdim = NAEA * NMO; if (type == COLLINEAR) @@ -471,15 +474,17 @@ void halfRotateCholeskyMatrix(WALKER_TYPES type, bool conjV = false, double cutoff = 1e-6) { + using std::get; + int NAEA = Alpha->size(0); int NAEB = 0; int NMO = Alpha->size(1); if (type == COLLINEAR) NAEB = Beta->size(0); - int nvec = std::get<1>(CholMat.sizes()); + int nvec = get<1>(CholMat.sizes()); int ncores = TG.getTotalCores(), coreid = TG.getCoreID(); - assert(std::get<0>(CholMat.sizes()) == NMO * NMO); + assert(get<0>(CholMat.sizes()) == NMO * NMO); if (type == CLOSED && kN > NMO) APP_ABORT(" Error: kN > NMO in halfRotateCholeskyMatrix. \n"); @@ -500,13 +505,13 @@ void halfRotateCholeskyMatrix(WALKER_TYPES type, int Qdim = NAEA * (kN_alpha - k0_alpha) + NAEB * (kN_beta - k0_beta); if (transpose) { - assert(std::get<0>(Q.sizes()) == nvec); - assert(std::get<1>(Q.sizes()) == Qdim); + assert(get<0>(Q.sizes()) == nvec); + assert(get<1>(Q.sizes()) == Qdim); } else { - assert(std::get<0>(Q.sizes()) == Qdim); - assert(std::get<1>(Q.sizes()) == nvec); + assert(get<0>(Q.sizes()) == Qdim); + assert(get<1>(Q.sizes()) == nvec); } std::tie(ak0, ak1) = FairDivideBoundary(coreid, Qdim, ncores); @@ -623,21 +628,23 @@ void getLank(MultiArray2DA&& Aai, MultiArray2D&& buff, bool noncollinear = false) { + using std::get; + int npol = noncollinear ? 2 : 1; - int na = std::get<0>(Aai.sizes()); + int na = get<0>(Aai.sizes()); if (na == 0) return; - int ni = std::get<1>(Aai.sizes()) / npol; - int nk = std::get<1>(Likn.sizes()); - int nchol = std::get<2>(Likn.sizes()); - assert(std::get<0>(Likn.sizes()) == ni); - assert(std::get<0>(Lank.sizes()) == na); - assert(std::get<1>(Lank.sizes()) == nchol); - assert(std::get<2>(Lank.sizes()) == nk * npol); - assert(std::get<0>(buff.sizes()) >= npol * nk); - assert(std::get<1>(buff.sizes()) >= nchol); + int ni = get<1>(Aai.sizes()) / npol; + int nk = get<1>(Likn.sizes()); + int nchol = get<2>(Likn.sizes()); + assert(get<0>(Likn.sizes()) == ni); + assert(get<0>(Lank.sizes()) == na); + assert(get<1>(Lank.sizes()) == nchol); + assert(get<2>(Lank.sizes()) == nk * npol); + assert(get<0>(buff.sizes()) >= npol * nk); + assert(get<1>(buff.sizes()) >= nchol); if (noncollinear) - assert(Aai.stride(0) == std::get<1>(Aai.sizes())); // make sure it is contiguous + assert(Aai.stride(0) == get<1>(Aai.sizes())); // make sure it is contiguous using elementA = typename std::decay::type::element; using element = typename std::decay::type::element; @@ -670,20 +677,22 @@ void getLank_from_Lkin(MultiArray2DA&& Aai, MultiArray2D&& buff, bool noncollinear = false) { + using std::get; // for C++17 compatibility + int npol = noncollinear ? 2 : 1; - int na = std::get<0>(Aai.sizes()); + int na = get<0>(Aai.sizes()); if (na == 0) return; - int ni = std::get<1>(Aai.sizes()) / npol; - int nk = std::get<0>(Lkin.sizes()); - int nchol = std::get<2>(Lkin.sizes()); - assert(std::get<1>(Lkin.sizes()) == ni); - assert(std::get<0>(Lank.sizes()) == na); - assert(std::get<1>(Lank.sizes()) == nchol); - assert(std::get<2>(Lank.sizes()) == nk * npol); + int ni = get<1>(Aai.sizes()) / npol; + int nk = get<0>(Lkin.sizes()); + int nchol = get<2>(Lkin.sizes()); + assert(get<1>(Lkin.sizes()) == ni); + assert(get<0>(Lank.sizes()) == na); + assert(get<1>(Lank.sizes()) == nchol); + assert(get<2>(Lank.sizes()) == nk * npol); assert(buff.num_elements() >= na * npol * nchol); if (noncollinear) - assert(Aai.stride(0) == std::get<1>(Aai.sizes())); // make sure it is contiguous + assert(Aai.stride(0) == get<1>(Aai.sizes())); // make sure it is contiguous using Type = typename std::decay::type::element; using elementA = typename std::decay::type::element; @@ -713,26 +722,28 @@ void getLakn_Lank(MultiArray2DA&& Aai, MultiArray3DC&& Lank, bool noncollinear = false) { + using std::get; // for C++17 compatibility + int npol = noncollinear ? 2 : 1; - int na = std::get<0>(Aai.sizes()); + int na = get<0>(Aai.sizes()); if (na == 0) return; - int ni = std::get<1>(Aai.sizes()) / npol; + int ni = get<1>(Aai.sizes()) / npol; - int nmo = std::get<0>(Likn.sizes()); - int nchol = std::get<2>(Likn.sizes()); - assert(std::get<1>(Likn.sizes()) == nmo); + int nmo = get<0>(Likn.sizes()); + int nchol = get<2>(Likn.sizes()); + assert(get<1>(Likn.sizes()) == nmo); - assert(std::get<1>(Lakn.sizes()) == npol * nmo); - assert(std::get<2>(Lakn.sizes()) == nchol); + assert(get<1>(Lakn.sizes()) == npol * nmo); + assert(get<2>(Lakn.sizes()) == nchol); - assert(std::get<0>(Lakn.sizes()) >= na); - assert(std::get<0>(Lakn.sizes()) == std::get<0>(Lank.sizes())); - assert(std::get<1>(Lank.sizes()) == nchol); - assert(std::get<2>(Lank.sizes()) == npol * nmo); + assert(get<0>(Lakn.sizes()) >= na); + assert(get<0>(Lakn.sizes()) == get<0>(Lank.sizes())); + assert(get<1>(Lank.sizes()) == nchol); + assert(get<2>(Lank.sizes()) == npol * nmo); if (noncollinear) - assert(Aai.stride(0) == std::get<1>(Aai.sizes())); // make sure it is contiguous + assert(Aai.stride(0) == get<1>(Aai.sizes())); // make sure it is contiguous using elmA = typename std::decay::type::element; using elmB = typename std::decay::type::element; @@ -755,26 +766,28 @@ void getLakn_Lank_from_Lkin(MultiArray2DA&& Aai, MultiArray2D&& buff, bool noncollinear = false) { + using std::get; // for C++17 compatibility + int npol = noncollinear ? 2 : 1; - int na = std::get<0>(Aai.sizes()); + int na = get<0>(Aai.sizes()); if (na == 0) return; - int ni = std::get<1>(Aai.sizes()) / npol; + int ni = get<1>(Aai.sizes()) / npol; - int nmo = std::get<0>(Lkin.sizes()); - int nchol = std::get<2>(Lkin.sizes()); - assert(std::get<1>(Lkin.sizes()) == nmo); + int nmo = get<0>(Lkin.sizes()); + int nchol = get<2>(Lkin.sizes()); + assert(get<1>(Lkin.sizes()) == nmo); - assert(std::get<1>(Lakn.sizes()) == npol * nmo); - assert(std::get<2>(Lakn.sizes()) == nchol); + assert(get<1>(Lakn.sizes()) == npol * nmo); + assert(get<2>(Lakn.sizes()) == nchol); - assert(std::get<0>(Lakn.sizes()) >= na); - assert(std::get<0>(Lakn.sizes()) == std::get<0>(Lank.sizes())); - assert(std::get<1>(Lank.sizes()) == nchol); - assert(std::get<2>(Lank.sizes()) == npol * nmo); + assert(get<0>(Lakn.sizes()) >= na); + assert(get<0>(Lakn.sizes()) == get<0>(Lank.sizes())); + assert(get<1>(Lank.sizes()) == nchol); + assert(get<2>(Lank.sizes()) == npol * nmo); if (noncollinear) - assert(Aai.stride(0) == std::get<1>(Aai.sizes())); // make sure it is contiguous + assert(Aai.stride(0) == get<1>(Aai.sizes())); // make sure it is contiguous assert(buff.num_elements() >= na * npol * nchol); diff --git a/src/AFQMC/SlaterDeterminantOperations/tests/test_sdet_ops.cpp b/src/AFQMC/SlaterDeterminantOperations/tests/test_sdet_ops.cpp index 7ea884d817..aa16da73f0 100644 --- a/src/AFQMC/SlaterDeterminantOperations/tests/test_sdet_ops.cpp +++ b/src/AFQMC/SlaterDeterminantOperations/tests/test_sdet_ops.cpp @@ -62,10 +62,11 @@ void myCHECK(const std::complex& a, const std::complex& b) template void check(M1&& A, M2& B) { - REQUIRE(std::get<0>(A.sizes()) == std::get<0>(B.sizes())); - REQUIRE(std::get<1>(A.sizes()) == std::get<1>(B.sizes())); - for (int i = 0; i < std::get<0>(A.sizes()); i++) - for (int j = 0; j < std::get<1>(A.sizes()); j++) + using std::get; + REQUIRE(get<0>(A.sizes()) == get<0>(B.sizes())); + REQUIRE(get<1>(A.sizes()) == get<1>(B.sizes())); + for (int i = 0; i < get<0>(A.sizes()); i++) + for (int j = 0; j < get<1>(A.sizes()); j++) myCHECK(A[i][j], B[i][j]); } @@ -663,12 +664,13 @@ TEST_CASE("SDetOps_complex_mpi3", "[sdet_ops]") array A({NEL, NMO}); array B({NMO, NEL}); - for (int i = 0, k = 0; i < std::get<0>(A.sizes()); i++) - for (int j = 0; j < std::get<1>(A.sizes()); j++, k++) + using std::get; + for (int i = 0, k = 0; i < get<0>(A.sizes()); i++) + for (int j = 0; j < get<1>(A.sizes()); j++, k++) A[i][j] = m_a[k]; - for (int i = 0, k = 0; i < std::get<0>(B.sizes()); i++) - for (int j = 0; j < std::get<1>(B.sizes()); j++, k++) + for (int i = 0, k = 0; i < get<0>(B.sizes()); i++) + for (int j = 0; j < get<1>(B.sizes()); j++, k++) B[i][j] = m_b[k]; array_ref Aref(m_a.data(), {NEL, NMO}); @@ -836,12 +838,13 @@ TEST_CASE("SDetOps_complex_csr", "[sdet_ops]") array A({NMO, NEL}); // Will be transposed when Acsr is built array B({NMO, NEL}); - for (int i = 0, k = 0; i < std::get<0>(A.sizes()); i++) - for (int j = 0; j < std::get<1>(A.sizes()); j++, k++) + using std::get; + for (int i = 0, k = 0; i < get<0>(A.sizes()); i++) + for (int j = 0; j < get<1>(A.sizes()); j++, k++) A[i][j] = m_a[k]; - for (int i = 0, k = 0; i < std::get<0>(B.sizes()); i++) - for (int j = 0; j < std::get<1>(B.sizes()); j++, k++) + for (int i = 0, k = 0; i < get<0>(B.sizes()); i++) + for (int j = 0; j < get<1>(B.sizes()); j++, k++) B[i][j] = m_b[k]; boost::multi::array_ref Bref(m_b.data(), {NMO, NEL}); diff --git a/src/AFQMC/Walkers/WalkerControl.hpp b/src/AFQMC/Walkers/WalkerControl.hpp index 143a6f7cbb..627b4ef363 100644 --- a/src/AFQMC/Walkers/WalkerControl.hpp +++ b/src/AFQMC/Walkers/WalkerControl.hpp @@ -45,12 +45,14 @@ inline int swapWalkersSimple(WlkBucket& wset, IVec& NewNumPerNode, communicator& comm) { + using std::get; + int wlk_size = wset.single_walker_size() + wset.single_walker_bp_size(); int NumContexts, MyContext; NumContexts = comm.size(); MyContext = comm.rank(); static_assert(std::decay::type::dimensionality == 2, "Wrong dimensionality"); - if (wlk_size != std::get<1>(Wexcess.sizes())) + if (wlk_size != get<1>(Wexcess.sizes())) throw std::runtime_error("Array dimension error in swapWalkersSimple()."); if (1 != Wexcess.stride(1)) throw std::runtime_error("Array shape error in swapWalkersSimple()."); @@ -78,7 +80,7 @@ inline int swapWalkersSimple(WlkBucket& wset, int nsend = 0; if (deltaN <= 0 && wset.size() != CurrNumPerNode[MyContext]) throw std::runtime_error("error in swapWalkersSimple()."); - if (deltaN > 0 && (wset.size() != NewNumPerNode[MyContext] || int(std::get<0>(Wexcess.sizes())) != deltaN)) + if (deltaN > 0 && (wset.size() != NewNumPerNode[MyContext] || int(get<0>(Wexcess.sizes())) != deltaN)) throw std::runtime_error("error in swapWalkersSimple()."); std::vector buff; if (deltaN < 0) @@ -116,10 +118,12 @@ inline int swapWalkersAsync(WlkBucket& wset, int NumContexts, MyContext; NumContexts = comm.size(); MyContext = comm.rank(); + + using std::get; static_assert(std::decay::type::dimensionality == 2, "Wrong dimensionality"); - if (wlk_size != std::get<1>(Wexcess.sizes())) + if (wlk_size != get<1>(Wexcess.sizes())) throw std::runtime_error("Array dimension error in swapWalkersAsync()."); - if (1 != Wexcess.stride(1) || (std::get<0>(Wexcess.sizes()) > 0 && std::get<1>(Wexcess.sizes()) != Wexcess.stride(0))) + if (1 != Wexcess.stride(1) || (get<0>(Wexcess.sizes()) > 0 && get<1>(Wexcess.sizes()) != Wexcess.stride(0))) throw std::runtime_error("Array shape error in swapWalkersAsync()."); if (CurrNumPerNode.size() < NumContexts || NewNumPerNode.size() < NumContexts) throw std::runtime_error("Array dimension error in swapWalkersAsync()."); @@ -146,7 +150,7 @@ inline int swapWalkersAsync(WlkBucket& wset, int countSend = 1; if (deltaN <= 0 && wset.size() != CurrNumPerNode[MyContext]) throw std::runtime_error("error(1) in swapWalkersAsync()."); - if (deltaN > 0 && (wset.size() != NewNumPerNode[MyContext] || int(std::get<0>(Wexcess.sizes())) != deltaN)) + if (deltaN > 0 && (wset.size() != NewNumPerNode[MyContext] || int(get<0>(Wexcess.sizes())) != deltaN)) throw std::runtime_error("error(2) in swapWalkersAsync()."); std::vector buffers; std::vector requests; @@ -161,7 +165,7 @@ inline int swapWalkersAsync(WlkBucket& wset, } else { - requests.emplace_back(comm.isend(Wexcess[nsend].origin(), Wexcess[nsend].origin() + countSend * std::get<1>(Wexcess.sizes()), + requests.emplace_back(comm.isend(Wexcess[nsend].origin(), Wexcess[nsend].origin() + countSend * get<1>(Wexcess.sizes()), minus[ic], plus[ic] + 1999)); nsend += countSend; countSend = 1; diff --git a/src/AFQMC/Walkers/WalkerIO.hpp b/src/AFQMC/Walkers/WalkerIO.hpp index 3b94a00a63..d36ba79fe2 100644 --- a/src/AFQMC/Walkers/WalkerIO.hpp +++ b/src/AFQMC/Walkers/WalkerIO.hpp @@ -373,13 +373,15 @@ bool dumpToHDF5(WalkerSet& wset, hdf_archive& dump) displ.reextent({TG.TG_heads().size()}); wlk_per_blk.reserve(nblks); + using std::get; + int NMO, NAEA, NAEB = 0; { // to limit the scope auto w = wset[0]; - NMO = std::get<0>((*w.SlaterMatrix(Alpha)).sizes()); - NAEA = std::get<1>((*w.SlaterMatrix(Alpha)).sizes()); + NMO = get<0>((*w.SlaterMatrix(Alpha)).sizes()); + NAEA = get<1>((*w.SlaterMatrix(Alpha)).sizes()); if (walker_type == COLLINEAR) - NAEB = std::get<1>((*w.SlaterMatrix(Beta)).sizes()); + NAEB = get<1>((*w.SlaterMatrix(Beta)).sizes()); if (walker_type == NONCOLLINEAR) NMO /= 2; } diff --git a/src/AFQMC/Walkers/WalkerSetBase.h b/src/AFQMC/Walkers/WalkerSetBase.h index 3b55143765..ff11ff1383 100644 --- a/src/AFQMC/Walkers/WalkerSetBase.h +++ b/src/AFQMC/Walkers/WalkerSetBase.h @@ -132,7 +132,7 @@ class WalkerSetBase : public AFQMCInfo /* * Returns the maximum number of walkers in the set that can be stored without reallocation. */ - int capacity() const { return int(std::get<0>(walker_buffer.sizes())); } + int capacity() const { using std::get; return int(get<0>(walker_buffer.sizes())); } /* * Returns the maximum number of fields in the set that can be stored without reallocation. @@ -167,7 +167,8 @@ class WalkerSetBase : public AFQMCInfo */ iterator begin() { - assert(std::get<1>(walker_buffer.sizes()) == walker_size); + using std::get; + assert(get<1>(walker_buffer.sizes()) == walker_size); return iterator(0, boost::multi::static_array_cast(walker_buffer), data_displ, wlk_desc); } @@ -176,17 +177,18 @@ class WalkerSetBase : public AFQMCInfo */ const_iterator begin() const { - assert(std::get<1>(walker_buffer.sizes()) == walker_size); + using std::get; + assert(get<1>(walker_buffer.sizes()) == walker_size); return const_iterator(0, boost::multi::static_array_cast(walker_buffer), data_displ, wlk_desc); } - /* * Returns iterator to the past-the-end walker in the set */ iterator end() { - assert(std::get<1>(walker_buffer.sizes()) == walker_size); + using std::get; + assert(get<1>(walker_buffer.sizes()) == walker_size); return iterator(tot_num_walkers, boost::multi::static_array_cast(walker_buffer), data_displ, wlk_desc); } @@ -196,9 +198,10 @@ class WalkerSetBase : public AFQMCInfo */ reference operator[](int i) { + using std::get; if (i < 0 || i > tot_num_walkers) APP_ABORT("error: index out of bounds.\n"); - assert(std::get<1>(walker_buffer.sizes()) == walker_size); + assert(get<1>(walker_buffer.sizes()) == walker_size); return reference(boost::multi::static_array_cast(walker_buffer)[i], data_displ, wlk_desc); } @@ -209,7 +212,8 @@ class WalkerSetBase : public AFQMCInfo { if (i < 0 || i > tot_num_walkers) APP_ABORT("error: index out of bounds.\n"); - assert(std::get<1>(walker_buffer.sizes()) == walker_size); + using std::get; + assert(get<1>(walker_buffer.sizes()) == walker_size); return const_reference(boost::multi::static_array_cast(walker_buffer.const_array_cast())[i], data_displ, wlk_desc); } @@ -244,12 +248,13 @@ class WalkerSetBase : public AFQMCInfo template void resize(int n, MatA&& A, MatB&& B) { - assert(std::get<0>(A.sizes()) == wlk_desc[0]); - assert(std::get<1>(A.sizes()) == wlk_desc[1]); + using std::get; + assert(get<0>(A.sizes()) == wlk_desc[0]); + assert(get<1>(A.sizes()) == wlk_desc[1]); if (walkerType == COLLINEAR) { - assert(std::get<0>(B.sizes()) == wlk_desc[0]); - assert(std::get<1>(B.sizes()) == wlk_desc[2]); + assert(get<0>(B.sizes()) == wlk_desc[0]); + assert(get<1>(B.sizes()) == wlk_desc[2]); } reserve(n); if (n > tot_num_walkers) @@ -297,9 +302,11 @@ class WalkerSetBase : public AFQMCInfo void resize_bp(int nbp, int nCV, int nref) { - assert(std::get<1>(walker_buffer.sizes()) == walker_size); + using std::get; + + assert(get<1>(walker_buffer.sizes()) == walker_size); assert(bp_buffer.size() == bp_walker_size); - assert(walker_buffer.size() == std::get<1>(bp_buffer.sizes())); + assert(walker_buffer.size() == get<1>(bp_buffer.sizes())); // wlk_descriptor: {nmo, naea, naeb, nback_prop, nCV, nRefs, nHist} wlk_desc[3] = nbp; wlk_desc[4] = nCV; @@ -333,12 +340,12 @@ class WalkerSetBase : public AFQMCInfo data_displ[WEIGHT_HISTORY] = cnt; cnt += wlk_desc[6]; bp_walker_size = cnt; - if (std::get<0>(bp_buffer.sizes()) != bp_walker_size) + if (get<0>(bp_buffer.sizes()) != bp_walker_size) { - bp_buffer.reextent({bp_walker_size, std::get<0>(walker_buffer.sizes())}); + bp_buffer.reextent({bp_walker_size, get<0>(walker_buffer.sizes())}); using std::fill_n; - fill_n(bp_buffer.origin() + data_displ[WEIGHT_FAC] * std::get<1>(bp_buffer.sizes()), - wlk_desc[6] * std::get<1>(bp_buffer.sizes()), bp_element(1.0)); + fill_n(bp_buffer.origin() + data_displ[WEIGHT_FAC] * get<1>(bp_buffer.sizes()), + wlk_desc[6] * get<1>(bp_buffer.sizes()), bp_element(1.0)); } if (nbp > 0 && (data_displ[SMN] < 0 || data_displ[SM_AUX] < 0)) { @@ -347,7 +354,7 @@ class WalkerSetBase : public AFQMCInfo walker_size += nrow * ncol; data_displ[SM_AUX] = walker_size; walker_size += nrow * ncol; - CMatrix wb({std::get<0>(walker_buffer.sizes()), walker_size}, walker_buffer.get_allocator()); + CMatrix wb({get<0>(walker_buffer.sizes()), walker_size}, walker_buffer.get_allocator()); ma::copy(walker_buffer, wb(wb.extension(0), {0, sz})); walker_buffer = std::move(wb); } @@ -363,8 +370,10 @@ class WalkerSetBase : public AFQMCInfo int GlobalPopulation() const { + using std::get; + int res = 0; - assert(std::get<1>(walker_buffer.sizes()) == walker_size); + assert(get<1>(walker_buffer.sizes()) == walker_size); if (TG.TG_local().root()) res += tot_num_walkers; return (TG.Global() += res); @@ -372,8 +381,10 @@ class WalkerSetBase : public AFQMCInfo RealType GlobalWeight() const { + using std::get; + RealType res = 0; - assert(std::get<1>(walker_buffer.sizes()) == walker_size); + assert(get<1>(walker_buffer.sizes()) == walker_size); if (TG.TG_local().root()) { boost::multi::array buff(iextensions<1u>{tot_num_walkers}); @@ -390,10 +401,12 @@ class WalkerSetBase : public AFQMCInfo template void push_walkers(Mat&& M) { + using std::get; + static_assert(std::decay::type::dimensionality == 2, "Wrong dimensionality"); if (tot_num_walkers + M.size() > capacity()) APP_ABORT("Insufficient capacity"); - if (single_walker_size() + single_walker_bp_size() != std::get<1>(M.sizes())) + if (single_walker_size() + single_walker_bp_size() != get<1>(M.sizes())) APP_ABORT("Incorrect dimensions."); if (M.stride(1) != 1) APP_ABORT("Incorrect strides."); @@ -416,17 +429,18 @@ class WalkerSetBase : public AFQMCInfo template void pop_walkers(Mat&& M) { + using std::get; static_assert(std::decay::type::dimensionality == 2, "Wrong dimensionality"); if (tot_num_walkers < int(M.size())) APP_ABORT("Insufficient walkers"); if (wlk_desc[3] > 0) { - if (walker_size + bp_walker_size != int(std::get<1>(M.sizes()))) + if (walker_size + bp_walker_size != int(get<1>(M.sizes()))) APP_ABORT("Incorrect dimensions."); } else { - if (walker_size != int(std::get<1>(M.sizes()))) + if (walker_size != int(get<1>(M.sizes()))) APP_ABORT("Incorrect dimensions."); } if (M.stride(1) != 1) @@ -454,6 +468,8 @@ class WalkerSetBase : public AFQMCInfo std::vector>::iterator itend, Mat& M) { + using std::get; + if (std::distance(itbegin, itend) != tot_num_walkers) APP_ABORT("Error in WalkerSetBase::branch(): ptr_range != # walkers. \n"); @@ -461,13 +477,13 @@ class WalkerSetBase : public AFQMCInfo int nW = 0; for (auto it = itbegin; it != itend; ++it) nW += it->second; - if (int(std::get<0>(M.sizes())) < std::max(0, nW - targetN_per_TG)) + if (int(get<0>(M.sizes())) < std::max(0, nW - targetN_per_TG)) { std::cout << " Error in WalkerSetBase::branch(): Not enough space in excess matrix. \n" - << std::get<0>(M.sizes()) << " " << nW << " " << targetN_per_TG << std::endl; + << get<0>(M.sizes()) << " " << nW << " " << targetN_per_TG << std::endl; APP_ABORT("Error in WalkerSetBase::branch(): Not enough space in excess matrix.\n"); } - if (int(std::get<1>(M.sizes())) < walker_size + ((wlk_desc[3] > 0) ? bp_walker_size : 0)) + if (int(get<1>(M.sizes())) < walker_size + ((wlk_desc[3] > 0) ? bp_walker_size : 0)) APP_ABORT("Error in WalkerSetBase::branch(): Wrong dimensions in excess matrix.\n"); // if all walkers are dead, don't bother with routine, reset tot_num_walkers and return @@ -575,9 +591,11 @@ class WalkerSetBase : public AFQMCInfo template void scaleWeight(const T& w0, bool scale_last_history = false) { + using std::get; + if (!TG.TG_local().root()) return; - assert(std::get<1>(walker_buffer.sizes()) == walker_size); + assert(get<1>(walker_buffer.sizes()) == walker_size); auto W(boost::multi::static_array_cast(walker_buffer)); ma::scal(ComplexType(w0), W({0, tot_num_walkers}, data_displ[WEIGHT])); if (scale_last_history) @@ -631,9 +649,11 @@ class WalkerSetBase : public AFQMCInfo template void copyToIO(Vec&& x, int n) { + using std::get; + assert(n < tot_num_walkers); assert(x.size() >= walkerSizeIO()); - assert(std::get<1>(walker_buffer.sizes()) == walker_size); + assert(get<1>(walker_buffer.sizes()) == walker_size); auto W(boost::multi::static_array_cast(walker_buffer)); using std::copy_n; copy_n(W[n].origin(), walkerSizeIO(), x.origin()); @@ -642,9 +662,11 @@ class WalkerSetBase : public AFQMCInfo template void copyFromIO(Vec&& x, int n) { + using std::get; + assert(n < tot_num_walkers); assert(x.size() >= walkerSizeIO()); - assert(std::get<1>(walker_buffer.sizes()) == walker_size); + assert(get<1>(walker_buffer.sizes()) == walker_size); auto W(boost::multi::static_array_cast(walker_buffer)); using std::copy_n; copy_n(x.origin(), walkerSizeIO(), W[n].origin()); @@ -686,22 +708,26 @@ class WalkerSetBase : public AFQMCInfo { if (ip < 0 || ip > wlk_desc[3]) APP_ABORT(" Error: index out of bounds in getFields. \n"); - int skip = (data_displ[FIELDS] + ip * wlk_desc[4]) * std::get<1>(bp_buffer.sizes()); - return stdCMatrix_ptr(to_address(bp_buffer.origin()) + skip, {wlk_desc[4], std::get<1>(bp_buffer.sizes())}); + + using std::get; + int skip = (data_displ[FIELDS] + ip * wlk_desc[4]) * get<1>(bp_buffer.sizes()); + return stdCMatrix_ptr(to_address(bp_buffer.origin()) + skip, {wlk_desc[4], get<1>(bp_buffer.sizes())}); } stdCTensor_ptr getFields() { - return stdCTensor_ptr(to_address(bp_buffer.origin()) + data_displ[FIELDS] * std::get<1>(bp_buffer.sizes()), - {wlk_desc[3], wlk_desc[4], std::get<1>(bp_buffer.sizes())}); + using std::get; + return stdCTensor_ptr(to_address(bp_buffer.origin()) + data_displ[FIELDS] * get<1>(bp_buffer.sizes()), + {wlk_desc[3], wlk_desc[4], get<1>(bp_buffer.sizes())}); } template void storeFields(int ip, Mat&& V) { + using std::get; static_assert(std::decay::type::dimensionality == 2, "Wrong dimensionality"); auto&& F(*getFields(ip)); - if (V.stride(0) == std::get<1>(V.sizes())) + if (V.stride(0) == get<1>(V.sizes())) { using std::copy_n; copy_n(V.origin(), F.num_elements(), F.origin()); @@ -712,14 +738,16 @@ class WalkerSetBase : public AFQMCInfo stdCMatrix_ptr getWeightFactors() { - return stdCMatrix_ptr(to_address(bp_buffer.origin()) + data_displ[WEIGHT_FAC] * std::get<1>(bp_buffer.sizes()), - {wlk_desc[6], std::get<1>(bp_buffer.sizes())}); + using std::get; + return stdCMatrix_ptr(to_address(bp_buffer.origin()) + data_displ[WEIGHT_FAC] * get<1>(bp_buffer.sizes()), + {wlk_desc[6], get<1>(bp_buffer.sizes())}); } stdCMatrix_ptr getWeightHistory() { - return stdCMatrix_ptr(to_address(bp_buffer.origin()) + data_displ[WEIGHT_HISTORY] * std::get<1>(bp_buffer.sizes()), - {wlk_desc[6], std::get<1>(bp_buffer.sizes())}); + using std::get; + return stdCMatrix_ptr(to_address(bp_buffer.origin()) + data_displ[WEIGHT_HISTORY] * get<1>(bp_buffer.sizes()), + {wlk_desc[6], get<1>(bp_buffer.sizes())}); } double getLogOverlapFactor() const { return LogOverlapFactor; } @@ -730,7 +758,8 @@ class WalkerSetBase : public AFQMCInfo // LogOverlapFactor_new = LogOverlapFactor + f/nx void adjustLogOverlapFactor(const double f) { - assert(std::get<1>(walker_buffer.sizes()) == walker_size); + using std::get; + assert(get<1>(walker_buffer.sizes()) == walker_size); double nx = (walkerType == NONCOLLINEAR ? 1.0 : 2.0); if (TG.TG_local().root()) { diff --git a/src/AFQMC/Walkers/WalkerSetBase.icc b/src/AFQMC/Walkers/WalkerSetBase.icc index 757dac8b62..632b2dff2a 100644 --- a/src/AFQMC/Walkers/WalkerSetBase.icc +++ b/src/AFQMC/Walkers/WalkerSetBase.icc @@ -216,9 +216,11 @@ bool WalkerSetBase::clean() template void WalkerSetBase::reserve(int n) { - if (std::get<0>(walker_buffer.sizes()) < n || std::get<1>(walker_buffer.sizes()) != walker_size) + using std::get; + + if (get<0>(walker_buffer.sizes()) < n || get<1>(walker_buffer.sizes()) != walker_size) walker_buffer.reextent({n, walker_size}); - if (std::get<1>(bp_buffer.sizes()) < n || std::get<0>(bp_buffer.sizes()) != bp_walker_size) + if (get<1>(bp_buffer.sizes()) < n || get<0>(bp_buffer.sizes()) != bp_walker_size) { bp_buffer.reextent({bp_walker_size, n}); using std::fill_n; diff --git a/src/AFQMC/Wavefunctions/NOMSD.hpp b/src/AFQMC/Wavefunctions/NOMSD.hpp index 0ca56bf419..131cfae4a5 100644 --- a/src/AFQMC/Wavefunctions/NOMSD.hpp +++ b/src/AFQMC/Wavefunctions/NOMSD.hpp @@ -243,17 +243,18 @@ class NOMSD : public AFQMCInfo template void vbias(const MatG& G, MatA&& v, double a = 1.0) { + using std::get; if (transposed_G_for_vbias_) { - assert(std::get<0>(G.sizes()) == std::get<1>(v.sizes())); - assert(std::get<1>(G.sizes()) == size_of_G_for_vbias()); + assert(get<0>(G.sizes()) == get<1>(v.sizes())); + assert(get<1>(G.sizes()) == size_of_G_for_vbias()); } else { - assert(std::get<0>(G.sizes()) == size_of_G_for_vbias()); - assert(std::get<1>(G.sizes()) == std::get<1>(v.sizes())); + assert(get<0>(G.sizes()) == size_of_G_for_vbias()); + assert(get<1>(G.sizes()) == get<1>(v.sizes())); } - assert(std::get<0>(v.sizes()) == HamOp.local_number_of_cholesky_vectors()); + assert(get<0>(v.sizes()) == HamOp.local_number_of_cholesky_vectors()); if (ci.size() == 1) { // HamOp expects a compact Gc with alpha/beta components @@ -285,11 +286,12 @@ class NOMSD : public AFQMCInfo template void vHS(MatX&& X, MatA&& v, double a = 1.0) { - assert(std::get<0>(X.sizes()) == HamOp.local_number_of_cholesky_vectors()); + using std::get; + assert(get<0>(X.sizes()) == HamOp.local_number_of_cholesky_vectors()); if (transposed_vHS_) - assert(std::get<1>(X.sizes()) == std::get<0>(v.sizes())); + assert(get<1>(X.sizes()) == get<0>(v.sizes())); else - assert(std::get<1>(X.sizes()) == std::get<1>(v.sizes())); + assert(get<1>(X.sizes()) == get<1>(v.sizes())); HamOp.vHS(std::forward(X), std::forward(v), a); TG.local_barrier(); } @@ -538,13 +540,14 @@ class NOMSD : public AFQMCInfo } // TG.Node().root() TG.Node().barrier(); // for safety } - assert(std::get<0>(RefOrbMats.sizes()) == ndet); - assert(std::get<1>(RefOrbMats.sizes()) == std::get<1>(A.sizes())); + using std::get; + assert(get<0>(RefOrbMats.sizes()) == ndet); + assert(get<1>(RefOrbMats.sizes()) == get<1>(A.sizes())); auto&& RefOrbMats_(boost::multi::static_array_cast(RefOrbMats)); auto&& A_(boost::multi::static_array_cast(A)); using std::copy_n; int n0, n1; - std::tie(n0, n1) = FairDivideBoundary(TG.getLocalTGRank(), int(std::get<1>(A.sizes())), TG.getNCoresPerTG()); + std::tie(n0, n1) = FairDivideBoundary(TG.getLocalTGRank(), int(get<1>(A.sizes())), TG.getNCoresPerTG()); for (int i = 0; i < ndet; i++) copy_n(RefOrbMats_[i].origin() + n0, n1 - n0, A_[i].origin() + n0); TG.TG_local().barrier(); diff --git a/src/AFQMC/Wavefunctions/NOMSD.icc b/src/AFQMC/Wavefunctions/NOMSD.icc index fea03a098c..0239ad34e4 100644 --- a/src/AFQMC/Wavefunctions/NOMSD.icc +++ b/src/AFQMC/Wavefunctions/NOMSD.icc @@ -44,13 +44,17 @@ template template void NOMSD::Energy_shared(const WlkSet& wset, Mat&& E, TVec&& Ov) { + using std::get; + size_t nt = wset.size() * (1 + dm_size(false)); assert(E.dimensionality == 2); assert(Ov.dimensionality == 1); assert(E.size() == wset.size()); - assert(E.stride() == std::get<1>(E.sizes())); + assert(E.stride() == get<1>(E.sizes())); assert(Ov.size() == wset.size()); - assert(std::get<1>(E.sizes()) == 3); + + using std::get; + assert(get<1>(E.sizes()) == 3); // temporary runtime check for incompatible memory spaces { @@ -133,7 +137,9 @@ void NOMSD::Energy_distributed_singleDet(const WlkSet& wset, Mat&& E, T assert(Ov.dimensionality == 1); assert(E.size() == wset.size()); assert(Ov.size() == wset.size()); - assert(std::get<1>(E.sizes()) == 3); + + using std::get; + assert(get<1>(E.sizes()) == 3); int nr = Gsize, nc = nwalk; if (transposed_G_for_E_) @@ -237,7 +243,9 @@ void NOMSD::Energy_distributed_multiDet(const WlkSet& wset, Mat&& E, TV assert(Ov.dimensionality == 1); assert(E.size() == wset.size()); assert(Ov.size() == wset.size()); - assert(std::get<1>(E.sizes()) == 3); + + using std::get; + assert(get<1>(E.sizes()) == 3); int nr = Gsize, nc = nwalk; if (transposed_G_for_E_) @@ -343,7 +351,8 @@ void NOMSD::MixedDensityMatrix_for_E_from_SM(const MatSM& SM, auto Gsize = dm_size(false); const int nw = SM.size(); - assert(std::get<1>(G.strides()) == 1); + using std::get; + assert(get<1>(G.strides()) == 1); assert(Ov.stride() == 1); if (transposed_G_for_E_) @@ -355,7 +364,9 @@ void NOMSD::MixedDensityMatrix_for_E_from_SM(const MatSM& SM, assert((G.extensions() == boost::multi::extensions_t<2>{static_cast(dm_size(false)), nw})); } assert(Ov.size() >= nw); - assert(std::get<1>(SM.sizes()) == Gsize); + + using std::get; + assert(get<1>(SM.sizes()) == Gsize); // to force synchronization before modifying structures in SHM TG.local_barrier(); fill_n(Ov.origin(), nw, 0); @@ -450,7 +461,8 @@ void NOMSD::DensityMatrix_shared(const WlkSet& wset, bool compact, bool transposed) { - assert(std::get<1>(G.strides()) == 1); + using std::get; + assert(get<1>(G.strides()) == 1); assert(Ov.stride() == 1); if (transposed) { @@ -472,17 +484,18 @@ void NOMSD::DensityMatrix_shared(const WlkSet& wset, double LogOverlapFactor(wset.getLogOverlapFactor()); auto Gsize = dm_size(not compact); + using std::get; if (walker_type != COLLINEAR) { if (herm) { - assert(std::get<0>(RefA.sizes()) == dm_dims(false, Alpha).first && - std::get<1>(RefA.sizes()) == dm_dims(false, Alpha).second); + assert(get<0>(RefA.sizes()) == dm_dims(false, Alpha).first && + get<1>(RefA.sizes()) == dm_dims(false, Alpha).second); } else { - assert(std::get<1>(RefA.sizes()) == dm_dims(false, Alpha).first && - std::get<0>(RefA.sizes()) == dm_dims(false, Alpha).second); + assert(get<1>(RefA.sizes()) == dm_dims(false, Alpha).first && + get<0>(RefA.sizes()) == dm_dims(false, Alpha).second); } auto Gdims = dm_dims(not compact, Alpha); @@ -511,23 +524,23 @@ void NOMSD::DensityMatrix_shared(const WlkSet& wset, { if (herm) { - assert(std::get<0>(RefA.sizes()) == dm_dims(false, Alpha).first && - std::get<1>(RefA.sizes()) == dm_dims(false, Alpha).second); + assert(get<0>(RefA.sizes()) == dm_dims(false, Alpha).first && + get<1>(RefA.sizes()) == dm_dims(false, Alpha).second); } else { - assert(std::get<1>(RefA.sizes()) == dm_dims(false, Alpha).first && - std::get<0>(RefA.sizes()) == dm_dims(false, Alpha).second); + assert(get<1>(RefA.sizes()) == dm_dims(false, Alpha).first && + get<0>(RefA.sizes()) == dm_dims(false, Alpha).second); } if (herm) { - assert(std::get<0>(RefB.sizes()) == dm_dims(false, Beta).first && - std::get<1>(RefB.sizes()) == dm_dims(false, Beta).second); + assert(get<0>(RefB.sizes()) == dm_dims(false, Beta).first && + get<1>(RefB.sizes()) == dm_dims(false, Beta).second); } else { - assert(std::get<1>(RefB.sizes()) == dm_dims(false, Beta).first && - std::get<0>(RefB.sizes()) == dm_dims(false, Beta).second); + assert(get<1>(RefB.sizes()) == dm_dims(false, Beta).first && + get<0>(RefB.sizes()) == dm_dims(false, Beta).second); } StaticVector ovlp2(iextensions<1u>{2 * nw}, buffer_manager.get_generator().template get_allocator()); fill_n(ovlp2.origin(), 2 * nw, ComplexType(0.0)); @@ -593,7 +606,8 @@ void NOMSD::DensityMatrix_batched(const WlkSet& wset, auto dev_ptr(make_device_ptr(G.origin())); } - assert(std::get<1>(G.strides()) == 1); + using std::get; + assert(get<1>(G.strides()) == 1); assert(Ov.stride() == 1); if (transposed) @@ -617,7 +631,9 @@ void NOMSD::DensityMatrix_batched(const WlkSet& wset, StaticVector ovlp2(iextensions<1u>{2 * nbatch__}, buffer_manager.get_generator().template get_allocator()); fill_n(ovlp2.origin(), ovlp2.num_elements(), ComplexType(0.0)); - if (std::get<1>(G.sizes()) != G.stride()) + + using std::get; + if (get<1>(G.sizes()) != G.stride()) { APP_ABORT(" Error: FIX FIX FIX need strided fill_n\n"); } @@ -633,17 +649,18 @@ void NOMSD::DensityMatrix_batched(const WlkSet& wset, std::vector Oib; Oib.reserve(nw); + using std::get; if (walker_type != COLLINEAR) { if (herm) { - assert(std::get<0>(RefA.sizes()) == dm_dims(false, Alpha).first && - std::get<1>(RefA.sizes()) == dm_dims(false, Alpha).second); + assert(get<0>(RefA.sizes()) == dm_dims(false, Alpha).first && + get<1>(RefA.sizes()) == dm_dims(false, Alpha).second); } else { - assert(std::get<1>(RefA.sizes()) == dm_dims(false, Alpha).first && - std::get<0>(RefA.sizes()) == dm_dims(false, Alpha).second); + assert(get<1>(RefA.sizes()) == dm_dims(false, Alpha).first && + get<0>(RefA.sizes()) == dm_dims(false, Alpha).second); } Static3Tensor G3D_({nbatch__, GAdims.first, GAdims.second}, buffer_manager.get_generator().template get_allocator()); @@ -682,23 +699,23 @@ void NOMSD::DensityMatrix_batched(const WlkSet& wset, { if (herm) { - assert(std::get<0>(RefA.sizes()) == dm_dims(false, Alpha).first && - std::get<1>(RefA.sizes()) == dm_dims(false, Alpha).second); + assert(get<0>(RefA.sizes()) == dm_dims(false, Alpha).first && + get<1>(RefA.sizes()) == dm_dims(false, Alpha).second); } else { - assert(std::get<1>(RefA.sizes()) == dm_dims(false, Alpha).first && - std::get<0>(RefA.sizes()) == dm_dims(false, Alpha).second); + assert(get<1>(RefA.sizes()) == dm_dims(false, Alpha).first && + get<0>(RefA.sizes()) == dm_dims(false, Alpha).second); } if (herm) { - assert(std::get<0>(RefB.sizes()) == dm_dims(false, Beta).first && - std::get<1>(RefB.sizes()) == dm_dims(false, Beta).second); + assert(get<0>(RefB.sizes()) == dm_dims(false, Beta).first && + get<1>(RefB.sizes()) == dm_dims(false, Beta).second); } else { - assert(std::get<1>(RefB.sizes()) == dm_dims(false, Beta).first && - std::get<0>(RefB.sizes()) == dm_dims(false, Beta).second); + assert(get<1>(RefB.sizes()) == dm_dims(false, Beta).first && + get<0>(RefB.sizes()) == dm_dims(false, Beta).second); } auto GBdims = dm_dims(not compact, Beta); @@ -856,7 +873,8 @@ void NOMSD::MixedDensityMatrix_shared(const WlkSet& wset, MatG&& G, TVe auto dev_ptr(make_device_ptr(G.origin())); } - assert(std::get<1>(G.strides()) == 1); + using std::get; + assert(get<1>(G.strides()) == 1); assert(Ov.stride() == 1); if (transpose) { @@ -874,7 +892,7 @@ void NOMSD::MixedDensityMatrix_shared(const WlkSet& wset, MatG&& G, TVe assert(Ov.size() >= nw); fill_n(Ov.origin(), nw, 0); // need strided fill_n???? - if (std::get<1>(G.sizes()) != G.stride()) + if (get<1>(G.sizes()) != G.stride()) { APP_ABORT(" Error: FIX FIX FIX need strided fill_n\n"); } @@ -1100,10 +1118,11 @@ void NOMSD::MixedDensityMatrix_shared(const WlkSet& wset, MatG&& G, TVe } else { + using std::get; int ik0, ikN; std::tie(ik0, ikN) = FairDivideBoundary(TG.TG_local().rank(), int(G.size()), TG.TG_local().size()); using ma::term_by_term_matrix_vector; - term_by_term_matrix_vector(ma::TOp_DIV, 1, ikN - ik0, std::get<1>(G.sizes()), make_device_ptr(G[ik0].origin()), + term_by_term_matrix_vector(ma::TOp_DIV, 1, ikN - ik0, get<1>(G.sizes()), make_device_ptr(G[ik0].origin()), G.stride(), make_device_ptr(Ov.origin()), Ov.stride()); } TG.local_barrier(); @@ -1124,7 +1143,8 @@ void NOMSD::MixedDensityMatrix_batched(const WlkSet& wset, MatG&& G, TV auto dev_ptr(make_device_ptr(G.origin())); } - assert(std::get<1>(G.strides()) == 1); + using std::get; + assert(get<1>(G.strides()) == 1); assert(Ov.stride() == 1); if (transpose) { @@ -1147,7 +1167,9 @@ void NOMSD::MixedDensityMatrix_batched(const WlkSet& wset, MatG&& G, TV buffer_manager.get_generator().template get_allocator()); fill_n(ovlp2.origin(), ovlp2.num_elements(), ComplexType(0.0)); // need strided fill_n???? - if (std::get<1>(G.sizes()) != G.stride()) + + using std::get; + if (get<1>(G.sizes()) != G.stride()) { APP_ABORT(" Error: FIX FIX FIX need strided fill_n\n"); } @@ -1288,6 +1310,8 @@ void NOMSD::MixedDensityMatrix_batched(const WlkSet& wset, MatG&& G, TV } } copy_n(Ovl.origin(), nw, Ov.origin()); + + using std::get; // normalize G if (transpose) { @@ -1300,7 +1324,7 @@ void NOMSD::MixedDensityMatrix_batched(const WlkSet& wset, MatG&& G, TV else { using ma::term_by_term_matrix_vector; - term_by_term_matrix_vector(ma::TOp_DIV, 1, G.size(), std::get<1>(G.sizes()), make_device_ptr(G.origin()), + term_by_term_matrix_vector(ma::TOp_DIV, 1, G.size(), get<1>(G.sizes()), make_device_ptr(G.origin()), G.stride(), make_device_ptr(Ov.origin()), Ov.stride()); } TG.local_barrier(); @@ -1557,8 +1581,10 @@ void NOMSD::WalkerAveragedDensityMatrix_shared(const WlkSet& wset, assert(wgt.size() >= nwalk); double LogOverlapFactor(wset.getLogOverlapFactor()); auto wlk_dims = wset.walker_dims(); + + using std::get; // Transposed temporaries for back propagation. - if (std::get<1>(G.sizes()) != G.stride()) + if (get<1>(G.sizes()) != G.stride()) { APP_ABORT(" Error: FIX FIX FIX need strided fill_n\n"); } @@ -1567,12 +1593,13 @@ void NOMSD::WalkerAveragedDensityMatrix_shared(const WlkSet& wset, TG.TG_local().barrier(); if (Refs != nullptr) { + using std::get; assert(detR != nullptr); assert(wset.size() <= (*Refs).size()); - assert(ci.size() <= std::get<1>((*Refs).sizes())); - assert(nrow * ncol == std::get<2>((*Refs).sizes())); + assert(ci.size() <= get<1>((*Refs).sizes())); + assert(nrow * ncol == get<2>((*Refs).sizes())); assert(wset.size() == (*detR).size()); - assert(OrbMats.size() == std::get<1>((*detR).sizes())); + assert(OrbMats.size() == get<1>((*detR).sizes())); } if (walker_type != COLLINEAR) { @@ -1748,8 +1775,10 @@ void NOMSD::WalkerAveragedDensityMatrix_shared_single_det(const WlkSet& assert(wgt.size() >= nwalk); auto wlk_dims = wset.walker_dims(); double LogOverlapFactor(wset.getLogOverlapFactor()); + + using std::get; // Transposed temporaries for back propagation. - if (std::get<1>(G.sizes()) != G.stride()) + if (get<1>(G.sizes()) != G.stride()) { APP_ABORT(" Error: FIX FIX FIX need strided fill_n\n"); } @@ -1757,12 +1786,13 @@ void NOMSD::WalkerAveragedDensityMatrix_shared_single_det(const WlkSet& TG.TG_local().barrier(); if (Refs != nullptr) { + using std::get; assert(detR != nullptr); assert(wset.size() <= (*Refs).size()); - assert(ci.size() <= std::get<1>((*Refs).sizes())); - assert(nrow * ncol == std::get<2>((*Refs).sizes())); + assert(ci.size() <= get<1>((*Refs).sizes())); + assert(nrow * ncol == get<2>((*Refs).sizes())); assert(wset.size() == (*detR).size()); - assert(OrbMats.size() == std::get<1>((*detR).sizes())); + assert(OrbMats.size() == get<1>((*detR).sizes())); } fill_n(Ovlp.origin(), Ovlp.num_elements(), ComplexType(0.0)); @@ -1947,25 +1977,26 @@ void NOMSD::WalkerAveragedDensityMatrix_batched(const WlkSet& wset, auto dev_ptr_(make_device_ptr(Ov.origin())); auto dev_ptr(make_device_ptr(G.origin())); } - assert(std::get<1>(G.strides())==1); + using std::get; + assert(get<1>(G.strides())==1); const int nw = wset.size(); int nbatch__ = std::min(nw,(nbatch<0?nw:nbatch)); const int ndet = ci.size(); int nrow = NMO*((walker_type==NONCOLLINEAR)?2:1); int ncol = NAEA+((walker_type==CLOSED)?0:NAEB); assert(wgt.size() >= nw); - assert(std::get<1>(wgt.sizes()) >= ndet); - if(std::get<1>(G.sizes()) != G.stride()) { + assert(get<1>(wgt.sizes()) >= ndet); + if(get<1>(G.sizes()) != G.stride()) { APP_ABORT(" Error: FIX FIX FIX need strided fill_n\n"); } fill_n(G.origin(),G.num_elements(),ComplexType(0.0)); if(Refs!=nullptr) { assert(detR!=nullptr); assert(wset.size() <= (*Refs).size()); - assert(ci.size() <= std::get<1>((*Refs).sizes()) ); - assert(nrow*ncol == std::get<2>((*Refs).sizes()) ); + assert(ci.size() <= get<1>((*Refs).sizes()) ); + assert(nrow*ncol == get<2>((*Refs).sizes()) ); assert(wset.size() == (*detR).size()); - assert(OrbMats.size() == std::get<1>((*detR).sizes()) ); + assert(OrbMats.size() == get<1>((*detR).sizes()) ); } stdCVector hvec(iextensions<1u>{2*nbatch__}); TG.local_barrier(); @@ -2220,11 +2251,13 @@ template template void NOMSD::OrthogonalizeExcited(Mat&& A, SpinTypes spin, double LogOverlapFactor) { + using std::get; + if (walker_type == NONCOLLINEAR) APP_ABORT(" Error: OrthogonalizeExcited not implemented with NONCOLLINEAR.\n"); if (spin == Alpha) { - if (extendedMatAlpha.size() != NMO || std::get<1>(extendedMatAlpha.sizes()) != maxOccupExtendedMat.first) + if (extendedMatAlpha.size() != NMO || get<1>(extendedMatAlpha.sizes()) != maxOccupExtendedMat.first) extendedMatAlpha.reextent({NMO, maxOccupExtendedMat.first}); extendedMatAlpha(extendedMatAlpha.extension(0), {0, NAEA}) = A; extendedMatAlpha(extendedMatAlpha.extension(0), {NAEA + 1, maxOccupExtendedMat.first}) = @@ -2246,7 +2279,7 @@ void NOMSD::OrthogonalizeExcited(Mat&& A, SpinTypes spin, double LogOve } else { - if (extendedMatBeta.size() != NMO || std::get<1>(extendedMatBeta.sizes()) != maxOccupExtendedMat.second) + if (extendedMatBeta.size() != NMO || get<1>(extendedMatBeta.sizes()) != maxOccupExtendedMat.second) extendedMatBeta.reextent({NMO, maxOccupExtendedMat.second}); extendedMatBeta(extendedMatBeta.extension(0), {0, NAEB}) = A; extendedMatBeta(extendedMatBeta.extension(0), {NAEB + 1, maxOccupExtendedMat.second}) = diff --git a/src/AFQMC/Wavefunctions/PHMSD.hpp b/src/AFQMC/Wavefunctions/PHMSD.hpp index 911258a5fb..aabf6f6e28 100644 --- a/src/AFQMC/Wavefunctions/PHMSD.hpp +++ b/src/AFQMC/Wavefunctions/PHMSD.hpp @@ -253,22 +253,23 @@ class PHMSD : public AFQMCInfo template void vbias(const MatG& G, MatA&& v, double a = 1.0) { - assert(std::get<0>(v.sizes()) == HamOp.local_number_of_cholesky_vectors()); + using std::get; + assert(get<0>(v.sizes()) == HamOp.local_number_of_cholesky_vectors()); double scl = (walker_type == COLLINEAR) ? 0.5 : 1.0; if (transposed_G_for_vbias_) { - assert(std::get<0>(G.sizes()) == std::get<1>(v.sizes())); - assert(std::get<1>(G.sizes()) == size_of_G_for_vbias()); + assert(get<0>(G.sizes()) == get<1>(v.sizes())); + assert(get<1>(G.sizes()) == size_of_G_for_vbias()); HamOp.vbias(G(G.extension(), {0, long(OrbMats[0].size() * NMO)}), std::forward(v), scl * a, 0.0); if (walker_type == COLLINEAR) { APP_ABORT(" Error in PHMSD::vbias: transposed_G_for_vbias_ should be false. \n"); - HamOp.vbias(G(G.extension(), {long(OrbMats[0].size() * NMO), std::get<1>(G.sizes())}), std::forward(v), scl * a, 1.0); + HamOp.vbias(G(G.extension(), {long(OrbMats[0].size() * NMO), get<1>(G.sizes())}), std::forward(v), scl * a, 1.0); } } else { assert(G.size() == size_of_G_for_vbias()); - assert(std::get<1>(G.sizes()) == std::get<1>(v.sizes())); + assert(get<1>(G.sizes()) == get<1>(v.sizes())); HamOp.vbias(G.sliced(0, OrbMats[0].size() * NMO), std::forward(v), scl * a, 0.0); if (walker_type == COLLINEAR) HamOp.vbias(G.sliced(OrbMats[0].size() * NMO, G.size()), std::forward(v), scl * a, 1.0); @@ -284,11 +285,12 @@ class PHMSD : public AFQMCInfo template void vHS(MatX&& X, MatA&& v, double a = 1.0) { - assert(std::get<0>(X.sizes()) == HamOp.local_number_of_cholesky_vectors()); + using std::get; + assert(get<0>(X.sizes()) == HamOp.local_number_of_cholesky_vectors()); if (transposed_vHS_) - assert(std::get<1>(X.sizes()) == std::get<0>(v.sizes())); + assert(get<1>(X.sizes()) == get<0>(v.sizes())); else - assert(std::get<1>(X.sizes()) == std::get<1>(v.sizes())); + assert(get<1>(X.sizes()) == get<1>(v.sizes())); HamOp.vHS(std::forward(X), std::forward(v), a); TG.local_barrier(); } @@ -300,10 +302,11 @@ class PHMSD : public AFQMCInfo template void Energy(WlkSet& wset) { + using std::get; int nw = wset.size(); if (ovlp.num_elements() != nw) ovlp.reextent(iextensions<1u>{nw}); - if (std::get<0>(eloc.sizes()) != nw || std::get<1>(eloc.sizes()) != 3) + if (get<0>(eloc.sizes()) != nw || get<1>(eloc.sizes()) != 3) eloc.reextent({nw, 3}); Energy(wset, eloc, ovlp); TG.local_barrier(); @@ -495,17 +498,18 @@ class PHMSD : public AFQMCInfo int ncol(NAEA + NAEB); //careful here, spins are stored contiguously RefOrbMats.reextent({ndet, nrow * ncol}); TG.Node().barrier(); // for safety + using std::get; if (TG.Node().root()) { boost::multi::array OA_({ - static_cast(std::get<1>(OrbMats[0].sizes())), - static_cast(std::get<0>(OrbMats[0].sizes())) + static_cast(get<1>(OrbMats[0].sizes())), + static_cast(get<0>(OrbMats[0].sizes())) }); boost::multi::array OB_({0, 0}); if (OrbMats.size() > 1) OB_.reextent({ - static_cast(std::get<1>(OrbMats[1].sizes())), - static_cast(std::get<0>(OrbMats[1].sizes())) + static_cast(get<1>(OrbMats[1].sizes())), + static_cast(get<0>(OrbMats[1].sizes())) }); ma::Matrix2MAREF('H', OrbMats[0], OA_); if (OrbMats.size() > 1) @@ -538,13 +542,15 @@ class PHMSD : public AFQMCInfo } // TG.Node().root() TG.Node().barrier(); // for safety } - assert(std::get<0>(RefOrbMats.sizes()) == ndet); - assert(std::get<1>(RefOrbMats.sizes()) == std::get<1>(A.sizes())); + + using std::get; + assert(get<0>(RefOrbMats.sizes()) == ndet); + assert(get<1>(RefOrbMats.sizes()) == get<1>(A.sizes())); auto&& RefOrbMats_(boost::multi::static_array_cast(RefOrbMats)); auto&& A_(boost::multi::static_array_cast(A)); using std::copy_n; int n0, n1; - std::tie(n0, n1) = FairDivideBoundary(TG.getLocalTGRank(), int(std::get<1>(A.sizes())), TG.getNCoresPerTG()); + std::tie(n0, n1) = FairDivideBoundary(TG.getLocalTGRank(), int(get<1>(A.sizes())), TG.getNCoresPerTG()); for (int i = 0; i < ndet; i++) copy_n(RefOrbMats_[i].origin() + n0, n1 - n0, A_[i].origin() + n0); TG.TG_local().barrier(); diff --git a/src/AFQMC/Wavefunctions/PHMSD.icc b/src/AFQMC/Wavefunctions/PHMSD.icc index 439e3db409..74ccde3276 100644 --- a/src/AFQMC/Wavefunctions/PHMSD.icc +++ b/src/AFQMC/Wavefunctions/PHMSD.icc @@ -44,8 +44,9 @@ void PHMSD::Energy_shared(const WlkSet& wset, Mat&& E, TVec&& Ov) assert(E.dimensionality == 2); assert(Ov.dimensionality == 1); assert(E.size() == wset.size()); - assert(std::get<0>(Ov.sizes()) == wset.size()); - assert(std::get<1>(E.sizes()) == 3); + + assert(get<0>(Ov.sizes()) == wset.size()); + assert(get<1>(E.sizes()) == 3); ComplexType zero(0.0); auto Gsize = dm_size(false); @@ -61,13 +62,14 @@ void PHMSD::Energy_shared(const WlkSet& wset, Mat&& E, TVec&& Ov) GrefA.reextent({nwalk, dm_dims(false, Alpha).first, dm_dims(false, Alpha).second}); + using std::get; if (wgt.size() != nwalk) wgt.reextent(iextensions<1u>{nwalk}); if (opSpinEJ.size() != nwalk) opSpinEJ.reextent(iextensions<1u>{nwalk}); if (localGbuff.size() < 2 * Gsize) localGbuff.reextent(iextensions<1u>{2 * Gsize}); - if (std::get<0>(eloc2.sizes()) != nwalk || std::get<1>(eloc2.sizes()) != 3) + if (get<0>(eloc2.sizes()) != nwalk || get<1>(eloc2.sizes()) != 3) eloc2.reextent({nwalk, 3}); std::fill_n(Ov.origin(), nwalk, zero); @@ -423,18 +425,20 @@ void PHMSD::MixedDensityMatrix(const WlkSet& wset, MatG&& G, TVec&& Ov, bool com using ma::T; assert(G.stride(1) == 1); assert(Ov.stride(0) == 1); + + using std::get; if (transpose) - assert(std::get<0>(G.sizes()) == wset.size() && std::get<1>(G.sizes()) == size_t(dm_size(not compact))); + assert(get<0>(G.sizes()) == wset.size() && get<1>(G.sizes()) == size_t(dm_size(not compact))); else - assert(std::get<1>(G.sizes()) == wset.size() && std::get<0>(G.sizes()) == size_t(dm_size(not compact))); + assert(get<1>(G.sizes()) == wset.size() && get<0>(G.sizes()) == size_t(dm_size(not compact))); const int nw = wset.size(); auto refc = abij.reference_configuration(); double LogOverlapFactor(wset.getLogOverlapFactor()); assert(Ov.size() >= nw); std::fill_n(Ov.begin(), nw, 0); - for (int i = 0; i < std::get<0>(G.sizes()); i++) + for (int i = 0; i < get<0>(G.sizes()); i++) if (i % TG.TG_local().size() == TG.TG_local().rank()) - std::fill_n(G[i].origin(), std::get<1>(G.sizes()), ComplexType(0.0)); + std::fill_n(G[i].origin(), get<1>(G.sizes()), ComplexType(0.0)); TG.local_barrier(); auto Gsize = dm_size(not compact); if (compact) @@ -569,8 +573,9 @@ void PHMSD::MixedDensityMatrix(const WlkSet& wset, MatG&& G, TVec&& Ov, bool com if (compact) { ma::product(T(Rb), GB2D0_, GB2D_); - //G({GAdims.first*GAdims.second,std::get<0>(G.sizes())},iw) = GB1D_; - ma::copy(GB1D_, G({GAdims.first * GAdims.second, std::get<0>(G.sizes())}, iw)); + using std::get; + //G({GAdims.first*GAdims.second,get<0>(G.sizes())},iw) = GB1D_; + ma::copy(GB1D_, G({GAdims.first * GAdims.second, get<0>(G.sizes())}, iw)); } else { @@ -578,7 +583,7 @@ void PHMSD::MixedDensityMatrix(const WlkSet& wset, MatG&& G, TVec&& Ov, bool com ma::product(T(Rb), GB2D0_, GB2D_); ma::product(T(OrbMats.back()), GB2D_, Gfullb); //G({Gfulla.num_elements(),G.size(0)},iw) = G1D; - ma::copy(G1D, G({Gfulla.num_elements(), std::get<0>(G.sizes())}, iw)); + ma::copy(G1D, G({Gfulla.num_elements(), get<0>(G.sizes())}, iw)); } } } @@ -681,9 +686,10 @@ void PHMSD::MixedDensityMatrix(const WlkSet& wset, MatG&& G, TVec&& Ov, bool com ma::product(T(Ra), GA2D0_shm(GA2D0_shm.extension(0), {M0, Mn}), GA2D_(GA2D_.extension(0), {M0, Mn})); // can be local boost::multi::array_ref Gw(to_address(G.origin()), - {GAdims.first, GAdims.second, long(std::get<1>(G.sizes()))}); + {GAdims.first, GAdims.second, long(get<1>(G.sizes()))}); // copying by hand for now, implement strided copy in ma_blas - for (size_t k = 0; k < std::get<0>(GA2D_.sizes()); ++k) + using std::get; + for (size_t k = 0; k < get<0>(GA2D_.sizes()); ++k) for (size_t m = M0; m < Mn; ++m) Gw[k][m][iw] = GA2D_[k][m]; } @@ -693,10 +699,11 @@ void PHMSD::MixedDensityMatrix(const WlkSet& wset, MatG&& G, TVec&& Ov, bool com GA2D_(GA2D_.extension(0), {M0, Mn})); // can be local ma::product(T(OrbMats[0]), GA2D_(GA2D_.extension(0), {M0, Mn}), Gfulla(Gfulla.extension(0), {M0, Mn})); // can be local + using std::get; boost::multi::array_ref Gw(to_address(G.origin()), - {long(std::get<0>(Gfulla.sizes())), long(std::get<1>(Gfulla.sizes())), long(std::get<1>(G.sizes()))}); + {long(get<0>(Gfulla.sizes())), long(get<1>(Gfulla.sizes())), long(get<1>(G.sizes()))}); // copying by hand for now, implement strided copy in ma_blas - for (size_t k = 0; k < std::get<0>(Gfulla.sizes()); ++k) + for (size_t k = 0; k < get<0>(Gfulla.sizes()); ++k) for (size_t m = M0; m < Mn; ++m) Gw[k][m][iw] = Gfulla[k][m]; } @@ -731,10 +738,12 @@ void PHMSD::MixedDensityMatrix(const WlkSet& wset, MatG&& G, TVec&& Ov, bool com { ma::product(T(Rb), GB2D0_shm(GB2D0_shm.extension(0), {M0, Mn}), GB2D_(GB2D_.extension(0), {M0, Mn})); // can be local + using std::get; boost::multi::array_ref Gw(to_address(G[GAdims.first * GAdims.second].origin()), - {GBdims.first, GBdims.second, long(std::get<1>(G.sizes()))}); + {GBdims.first, GBdims.second, long(get<1>(G.sizes()))}); // copying by hand for now, implement strided copy in ma_blas - for (size_t k = 0; k < std::get<0>(GB2D_.sizes()); ++k) + using std::get; + for (size_t k = 0; k < get<0>(GB2D_.sizes()); ++k) for (size_t m = M0; m < Mn; ++m) Gw[k][m][iw] = GB2D_[k][m]; } @@ -744,10 +753,11 @@ void PHMSD::MixedDensityMatrix(const WlkSet& wset, MatG&& G, TVec&& Ov, bool com GB2D_(GB2D_.extension(0), {M0, Mn})); // can be local ma::product(T(OrbMats[0]), GB2D_(GB2D_.extension(0), {M0, Mn}), Gfullb(Gfullb.extension(0), {M0, Mn})); // can be local + using std::get; boost::multi::array_ref Gw(to_address(G[Gfulla.num_elements()].origin()), - {long(std::get<0>(Gfullb.sizes())), long(std::get<1>(Gfullb.sizes())), long(std::get<1>(G.sizes()))}); + {long(get<0>(Gfullb.sizes())), long(get<1>(Gfullb.sizes())), long(get<1>(G.sizes()))}); // copying by hand for now, implement strided copy in ma_blas - for (size_t k = 0; k < std::get<0>(Gfullb.sizes()); ++k) + for (size_t k = 0; k < get<0>(Gfullb.sizes()); ++k) for (size_t m = M0; m < Mn; ++m) Gw[k][m][iw] = Gfullb[k][m]; } @@ -769,8 +779,8 @@ void PHMSD::MixedDensityMatrix(const WlkSet& wset, MatG&& G, TVec&& Ov, bool com else { auto Ov_ = Ov.origin(); - const size_t nw_ = std::get<1>(G.sizes()); - for (int ik = 0; ik < std::get<0>(G.sizes()); ++ik) + const size_t nw_ = get<1>(G.sizes()); + for (int ik = 0; ik < get<0>(G.sizes()); ++ik) if (ik % TG.TG_local().size() == TG.TG_local().rank()) { auto Gik = to_address(G[ik].origin()); @@ -814,6 +824,7 @@ void PHMSD::DensityMatrix_shared(const WlkSet& wset, if (localGbuff.size() < Gsize) localGbuff.reextent(iextensions<1u>{Gsize}); + using std::get; if (walker_type != COLLINEAR) { if (herm) @@ -841,15 +852,15 @@ void PHMSD::DensityMatrix_shared(const WlkSet& wset, else { if (herm) - assert(std::get<0>(RefA.sizes()) == dm_dims(false, Alpha).first && RefA.size(1) == dm_dims(false, Alpha).second); + assert(get<0>(RefA.sizes()) == dm_dims(false, Alpha).first && RefA.size(1) == dm_dims(false, Alpha).second); else - assert(std::get<1>(RefA.sizes()) == dm_dims(false, Alpha).first && RefA.size(0) == dm_dims(false, Alpha).second); + assert(get<1>(RefA.sizes()) == dm_dims(false, Alpha).first && RefA.size(0) == dm_dims(false, Alpha).second); if (herm) - assert(std::get<0>(RefB.sizes()) == dm_dims(false, Beta).first && RefB.size(1) == dm_dims(false, Beta).second); + assert(get<0>(RefB.sizes()) == dm_dims(false, Beta).first && RefB.size(1) == dm_dims(false, Beta).second); else - assert(std::get<1>(RefB.sizes()) == dm_dims(false, Beta).first && RefB.size(0) == dm_dims(false, Beta).second); + assert(get<1>(RefB.sizes()) == dm_dims(false, Beta).first && RefB.size(0) == dm_dims(false, Beta).second); - if (std::get<0>(ovlp2.sizes()) < 2 * nw) + if (get<0>(ovlp2.sizes()) < 2 * nw) ovlp2.reextent(iextensions<1u>{2 * nw}); fill_n(ovlp2.origin(), 2 * nw, ComplexType(0.0)); auto GAdims = dm_dims(not compact, Alpha); @@ -1200,7 +1211,8 @@ void PHMSD::OrthogonalizeExcited(Mat&& A, SpinTypes spin, double LogOverlapFacto APP_ABORT(" Error: OrthogonalizeExcited not implemented with NONCOLLINEAR.\n"); if (spin == Alpha) { - if (std::get<0>(extendedMatAlpha.sizes()) != NMO || std::get<1>(extendedMatAlpha.sizes()) != maxOccupExtendedMat.first) + using std::get; + if (get<0>(extendedMatAlpha.sizes()) != NMO || get<1>(extendedMatAlpha.sizes()) != maxOccupExtendedMat.first) extendedMatAlpha.reextent({NMO, maxOccupExtendedMat.first}); extendedMatAlpha(extendedMatAlpha.extension(0), {0, NAEA}) = A; extendedMatAlpha(extendedMatAlpha.extension(0), {NAEA + 1, maxOccupExtendedMat.first}) = @@ -1222,7 +1234,8 @@ void PHMSD::OrthogonalizeExcited(Mat&& A, SpinTypes spin, double LogOverlapFacto } else { - if (std::get<0>(extendedMatBeta.sizes()) != NMO || std::get<1>(extendedMatBeta.sizes()) != maxOccupExtendedMat.second) + using std::get; + if (get<0>(extendedMatBeta.sizes()) != NMO || get<1>(extendedMatBeta.sizes()) != maxOccupExtendedMat.second) extendedMatBeta.reextent({NMO, maxOccupExtendedMat.second}); extendedMatBeta(extendedMatBeta.extension(0), {0, NAEB}) = A; extendedMatBeta(extendedMatBeta.extension(0), {NAEB + 1, maxOccupExtendedMat.second}) = diff --git a/src/AFQMC/Wavefunctions/phmsd_helpers.hpp b/src/AFQMC/Wavefunctions/phmsd_helpers.hpp index 2c4f8d3df4..b82fdcef70 100644 --- a/src/AFQMC/Wavefunctions/phmsd_helpers.hpp +++ b/src/AFQMC/Wavefunctions/phmsd_helpers.hpp @@ -126,9 +126,11 @@ inline void calculate_R(int rank, std::vector WORK(abij.maximum_excitation_number()[spin] * abij.maximum_excitation_number()[spin]); auto confgs = abij.configurations_begin(); auto refc = abij.reference_configuration(spin); - for (int i = 0; i < std::get<0>(R.sizes()); i++) - std::fill_n(R[i].origin(), std::get<1>(R.sizes()), ComplexType(0)); - int NEL = std::get<1>(T.sizes()); + + using std::get; + for (int i = 0; i < get<0>(R.sizes()); i++) + std::fill_n(R[i].origin(), get<1>(R.sizes()), ComplexType(0)); + int NEL = get<1>(T.sizes()); std::vector orbs(NEL); ComplexType ov_a; // add reference contribution!!! diff --git a/src/AFQMC/Wavefunctions/tests/test_phmsd.cpp b/src/AFQMC/Wavefunctions/tests/test_phmsd.cpp index 180b782809..c182ac1d93 100644 --- a/src/AFQMC/Wavefunctions/tests/test_phmsd.cpp +++ b/src/AFQMC/Wavefunctions/tests/test_phmsd.cpp @@ -233,9 +233,11 @@ void test_phmsd(boost::mpi3::communicator& world) RandomGenerator rng; WalkerSet wset(TG, doc3.getRoot(), InfoMap["info0"], rng); auto initial_guess = WfnFac.getInitialGuess(wfn_name); - REQUIRE(std::get<0>(initial_guess.sizes()) == 2); - REQUIRE(std::get<1>(initial_guess.sizes()) == NMO); - REQUIRE(std::get<2>(initial_guess.sizes()) == NAEA); + + using std::get; + REQUIRE(get<0>(initial_guess.sizes()) == 2); + REQUIRE(get<1>(initial_guess.sizes()) == NMO); + REQUIRE(get<2>(initial_guess.sizes()) == NAEA); wset.resize(nwalk, initial_guess[0], initial_guess[1](initial_guess.extension(1), {0, NAEB})); // 1. Test Overlap Explicitly diff --git a/src/AFQMC/Wavefunctions/tests/test_wfn_factory.cpp b/src/AFQMC/Wavefunctions/tests/test_wfn_factory.cpp index 2ea2f6446f..6512f0a097 100644 --- a/src/AFQMC/Wavefunctions/tests/test_wfn_factory.cpp +++ b/src/AFQMC/Wavefunctions/tests/test_wfn_factory.cpp @@ -154,9 +154,11 @@ void wfn_fac(boost::mpi3::communicator& world) //nwalk=nw; WalkerSet wset(TG, doc3.getRoot(), InfoMap["info0"], rng); auto initial_guess = WfnFac.getInitialGuess(wfn_name); - REQUIRE(std::get<0>(initial_guess.sizes()) == 2); - REQUIRE(std::get<1>(initial_guess.sizes()) == NPOL * NMO); - REQUIRE(std::get<2>(initial_guess.sizes()) == NAEA); + + using std::get; + REQUIRE(get<0>(initial_guess.sizes()) == 2); + REQUIRE(get<1>(initial_guess.sizes()) == NPOL * NMO); + REQUIRE(get<2>(initial_guess.sizes()) == NAEA); if (type == COLLINEAR) wset.resize(nwalk, initial_guess[0], initial_guess[1](initial_guess.extension(1), {0, NAEB})); @@ -240,6 +242,8 @@ void wfn_fac(boost::mpi3::communicator& world) TG.local_barrier(); t1 = Time.elapsed(); ComplexType Vsum = 0; + + using std::get; if (std::abs(file_data.Vsum) > 1e-8) { for (int n = 0; n < nwalk; n++) @@ -247,12 +251,12 @@ void wfn_fac(boost::mpi3::communicator& world) Vsum = 0; if (wfn.transposed_vHS()) { - for (int i = 0; i < std::get<1>(vHS.sizes()); i++) + for (int i = 0; i < get<1>(vHS.sizes()); i++) Vsum += vHS[n][i]; } else { - for (int i = 0; i < std::get<0>(vHS.sizes()); i++) + for (int i = 0; i < get<0>(vHS.sizes()); i++) Vsum += vHS[i][n]; } CHECK(real(Vsum) == Approx(real(file_data.Vsum))); @@ -264,12 +268,12 @@ void wfn_fac(boost::mpi3::communicator& world) Vsum = 0; if (wfn.transposed_vHS()) { - for (int i = 0; i < std::get<1>(vHS.sizes()); i++) + for (int i = 0; i < get<1>(vHS.sizes()); i++) Vsum += vHS[0][i]; } else { - for (int i = 0; i < std::get<0>(vHS.sizes()); i++) + for (int i = 0; i < get<0>(vHS.sizes()); i++) Vsum += vHS[i][0]; } app_log() << " Vsum: " << setprecision(12) << Vsum << " Time: " << t1 << std::endl; @@ -292,9 +296,10 @@ void wfn_fac(boost::mpi3::communicator& world) WalkerSet wset2(TG, doc3.getRoot(), InfoMap["info0"], rng); //auto initial_guess = WfnFac.getInitialGuess(wfn_name); - REQUIRE(std::get<0>(initial_guess.sizes()) == 2); - REQUIRE(std::get<1>(initial_guess.sizes()) == NPOL * NMO); - REQUIRE(std::get<2>(initial_guess.sizes()) == NAEA); + using std::get; + REQUIRE(get<0>(initial_guess.sizes()) == 2); + REQUIRE(get<1>(initial_guess.sizes()) == NPOL * NMO); + REQUIRE(get<2>(initial_guess.sizes()) == NAEA); if (type == COLLINEAR) wset2.resize(nwalk, initial_guess[0], initial_guess[1](initial_guess.extension(1), {0, NAEB})); @@ -364,12 +369,12 @@ void wfn_fac(boost::mpi3::communicator& world) Vsum = 0; if (wfn.transposed_vHS()) { - for (int i = 0; i < std::get<1>(vHS.sizes()); i++) + for (int i = 0; i < get<1>(vHS.sizes()); i++) Vsum += vHS[n][i]; } else { - for (int i = 0; i < std::get<0>(vHS.sizes()); i++) + for (int i = 0; i < get<0>(vHS.sizes()); i++) Vsum += vHS[i][n]; } CHECK(real(Vsum) == Approx(real(file_data.Vsum))); @@ -381,12 +386,12 @@ void wfn_fac(boost::mpi3::communicator& world) Vsum = 0; if (wfn.transposed_vHS()) { - for (int i = 0; i < std::get<1>(vHS.sizes()); i++) + for (int i = 0; i < get<1>(vHS.sizes()); i++) Vsum += vHS[0][i]; } else { - for (int i = 0; i < std::get<0>(vHS.sizes()); i++) + for (int i = 0; i < get<0>(vHS.sizes()); i++) Vsum += vHS[i][0]; } app_log() << " Vsum: " << setprecision(12) << Vsum << std::endl; @@ -490,9 +495,11 @@ void wfn_fac_distributed(boost::mpi3::communicator& world, int ngroups) WalkerSet wset(TG, doc3.getRoot(), InfoMap["info0"], rng); auto initial_guess = WfnFac.getInitialGuess(wfn_name); - REQUIRE(std::get<0>(initial_guess.sizes()) == 2); - REQUIRE(std::get<1>(initial_guess.sizes()) == NPOL * NMO); - REQUIRE(std::get<2>(initial_guess.sizes()) == NAEA); + + using std::get; + REQUIRE(get<0>(initial_guess.sizes()) == 2); + REQUIRE(get<1>(initial_guess.sizes()) == NPOL * NMO); + REQUIRE(get<2>(initial_guess.sizes()) == NAEA); if (type == COLLINEAR) wset.resize(nwalk, initial_guess[0], initial_guess[1](initial_guess.extension(1), {0, NAEB})); @@ -589,6 +596,8 @@ void wfn_fac_distributed(boost::mpi3::communicator& world, int ngroups) TG.local_barrier(); t1 = Time.elapsed(); ComplexType Vsum = 0; + + using std::get; if (std::abs(file_data.Vsum) > 1e-8) { for (int n = 0; n < nwalk; n++) @@ -598,12 +607,12 @@ void wfn_fac_distributed(boost::mpi3::communicator& world, int ngroups) { if (wfn.transposed_vHS()) { - for (int i = 0; i < std::get<1>(vHS.sizes()); i++) + for (int i = 0; i < get<1>(vHS.sizes()); i++) Vsum += vHS[n][i]; } else { - for (int i = 0; i < std::get<0>(vHS.sizes()); i++) + for (int i = 0; i < get<0>(vHS.sizes()); i++) Vsum += vHS[i][n]; } } @@ -619,12 +628,12 @@ void wfn_fac_distributed(boost::mpi3::communicator& world, int ngroups) { if (wfn.transposed_vHS()) { - for (int i = 0; i < std::get<1>(vHS.sizes()); i++) + for (int i = 0; i < get<1>(vHS.sizes()); i++) Vsum += vHS[0][i]; } else { - for (int i = 0; i < std::get<0>(vHS.sizes()); i++) + for (int i = 0; i < get<0>(vHS.sizes()); i++) Vsum += vHS[i][0]; } } @@ -649,9 +658,10 @@ void wfn_fac_distributed(boost::mpi3::communicator& world, int ngroups) WalkerSet wset2(TG, doc3.getRoot(), InfoMap["info0"], rng); //auto initial_guess = WfnFac.getInitialGuess(wfn_name); - REQUIRE(std::get<0>(initial_guess.sizes()) == 2); - REQUIRE(std::get<1>(initial_guess.sizes()) == NPOL * NMO); - REQUIRE(std::get<2>(initial_guess.sizes()) == NAEA); + using std::get; + REQUIRE(get<0>(initial_guess.sizes()) == 2); + REQUIRE(get<1>(initial_guess.sizes()) == NPOL * NMO); + REQUIRE(get<2>(initial_guess.sizes()) == NAEA); if (type == COLLINEAR) wset2.resize(nwalk, initial_guess[0], initial_guess[1](initial_guess.extension(1), {0, NAEB})); @@ -729,6 +739,8 @@ void wfn_fac_distributed(boost::mpi3::communicator& world, int ngroups) wfn2.vHS(X2, vHS, sqrtdt); TG.local_barrier(); Vsum = 0; + + using std::get; if (std::abs(file_data.Vsum) > 1e-8) { for (int n = 0; n < nwalk; n++) @@ -738,12 +750,12 @@ void wfn_fac_distributed(boost::mpi3::communicator& world, int ngroups) { if (wfn.transposed_vHS()) { - for (int i = 0; i < std::get<1>(vHS.sizes()); i++) + for (int i = 0; i < get<1>(vHS.sizes()); i++) Vsum += vHS[n][i]; } else { - for (int i = 0; i < std::get<0>(vHS.sizes()); i++) + for (int i = 0; i < get<0>(vHS.sizes()); i++) Vsum += vHS[i][n]; } } @@ -759,12 +771,12 @@ void wfn_fac_distributed(boost::mpi3::communicator& world, int ngroups) { if (wfn.transposed_vHS()) { - for (int i = 0; i < std::get<1>(vHS.sizes()); i++) + for (int i = 0; i < get<1>(vHS.sizes()); i++) Vsum += vHS[0][i]; } else { - for (int i = 0; i < std::get<0>(vHS.sizes()); i++) + for (int i = 0; i < get<0>(vHS.sizes()); i++) Vsum += vHS[i][0]; } } diff --git a/src/io/hdf/hdf_multi.h b/src/io/hdf/hdf_multi.h index 76ee11bee5..770b6f4cac 100644 --- a/src/io/hdf/hdf_multi.h +++ b/src/io/hdf/hdf_multi.h @@ -63,8 +63,9 @@ struct h5data_proxy> : public h5_space_type(a.sizes()); - dims[1] = std::get<1>(a.sizes()); + using std::get; + dims[0] = get<0>(a.sizes()); + dims[1] = get<1>(a.sizes()); } inline bool read(data_type& ref, hid_t grp, const std::string& aname, hid_t xfer_plist = H5P_DEFAULT) @@ -92,12 +93,13 @@ struct h5data_proxy> : public h5_space_type(grp, aname, FileSpace::rank, dims)) { if (dims[0] > 0) { std::cerr << " Error: multi::array_ref can't be resized in h5data_proxy<>::read." << std::endl; - std::cerr << dims[0] << " " << std::get<0>(ref.sizes()) << std::endl; + std::cerr << dims[0] << " " << get<0>(ref.sizes()) << std::endl; } return false; } @@ -120,18 +122,21 @@ struct h5data_proxy> : public h5_space_type(a.sizes()); - dims[1] = std::get<1>(a.sizes()); + using std::get; + dims[0] = get<0>(a.sizes()); + dims[1] = get<1>(a.sizes()); } inline bool read(data_type& ref, hid_t grp, const std::string& aname, hid_t xfer_plist = H5P_DEFAULT) { + using std::get; + if (!checkShapeConsistency(grp, aname, FileSpace::rank, dims)) { if (dims[0] * dims[1] > 0) { std::cerr << " Error: multi::array_ref can't be resized in h5data_proxy<>::read." << std::endl; - std::cerr << dims[0] << " " << dims[1] << " " << std::get<0>(ref.sizes()) << " " << std::get<1>(ref.sizes()) << std::endl; + std::cerr << dims[0] << " " << dims[1] << " " << get<0>(ref.sizes()) << " " << get<1>(ref.sizes()) << std::endl; } return false; } @@ -257,18 +262,20 @@ struct h5data_proxy>> : inline h5data_proxy(const data_type& a) { - dims[0] = std::get<0>(a.sizes()); - dims[1] = std::get<1>(a.sizes()); + using std::get; + dims[0] = get<0>(a.sizes()); + dims[1] = get<1>(a.sizes()); } inline bool read(data_type& ref, hid_t grp, const std::string& aname, hid_t xfer_plist = H5P_DEFAULT) { + using std::get; if (!checkShapeConsistency(grp, aname, FileSpace::rank, dims)) { if (dims[0] * dims[1] > 0) { std::cerr << " Error: multi::array_ref can't be resized in h5data_proxy<>::read." << std::endl; - std::cerr << dims[0] << " " << dims[1] << " " << std::get<0>(ref.sizes()) << " " << std::get<1>(ref.sizes()) << std::endl; + std::cerr << dims[0] << " " << dims[1] << " " << get<0>(ref.sizes()) << " " << get<1>(ref.sizes()) << std::endl; } return false; }