name: Linux SIMD tests

# To update the Intel SDE version (not handled by Dependabot setup-sde updates):
# update the sdeVersion inputs in the Intel SDE jobs below.
#
# This file is meant for testing different SIMD-related build options and
# optimization levels. See `meson_options.txt` for the available build options.
#
# Jobs and their purposes:
#
# - baseline_only:
#   Focuses on completing as quickly as possible and acts as a filter for other, more resource-intensive jobs.
#   Utilizes only the default baseline targets (e.g., X86_V2 on X86_64) without enabling any runtime dispatched features.
#
# - old_gcc:
#   Tests the oldest supported GCC version with default CPU/baseline/dispatch settings.
#
# - without_optimizations:
#   Completely disables all SIMD optimizations and other compiler optimizations such as loop unrolling.
#
# - native:
#   Tests against the host CPU features set as the baseline without enabling any runtime dispatched features.
#   Intended to assess the entire NumPy codebase against host flags, even for code sections lacking handwritten SIMD intrinsics.
#
# - without_avx512:
#   Uses runtime SIMD dispatching but disables AVX512.
#   Intended to evaluate 128-bit/256-bit SIMD extensions.
#
# - intel_sde:
#   Executes only the SIMD tests for various AVX512 SIMD extensions under the Intel Software Development Emulator (SDE).
#
on:
  pull_request:
    branches:
      - main
      - maintenance/**
    paths-ignore:
      - '**.pyi'
      - '**.md'
      - '**.rst'
      - 'tools/stubtest/**'

defaults:
  run:
    shell: 'script -q -e -c "bash --noprofile --norc -eo pipefail {0}"'

env:
  TERM: xterm-256color

concurrency:
  group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
  cancel-in-progress: true

permissions:
  contents: read # to fetch code (actions/checkout)

jobs:
  baseline_only:
    # To enable this workflow on a fork, comment out:
    if: github.repository == 'numpy/numpy'
    runs-on: ubuntu-latest
    env:
      MESON_ARGS: "-Dallow-noblas=true -Dcpu-dispatch=none"
    steps:
    - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
      with:
        submodules: recursive
        fetch-tags: true
        persist-credentials: false
    - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
      with:
        python-version: '3.12'
    - uses: ./.github/meson_actions
      name: Build/Test

  old_gcc:
    if: github.event_name != 'push'
    needs: [baseline_only]
    runs-on: ubuntu-latest
    env:
      MESON_ARGS: "-Dallow-noblas=true"
    steps:
    - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
      with:
        submodules: recursive
        fetch-tags: true
        persist-credentials: false
    - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
      with:
        python-version: '3.12'

    - name: Install GCC10
      run: |
        echo "deb http://archive.ubuntu.com/ubuntu focal main universe" | sudo tee /etc/apt/sources.list.d/focal.list
        sudo apt update
        sudo apt install -y g++-10

    - name: Enable gcc-10
      run: |
        sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-10 2
        sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-10 2

    - uses: ./.github/meson_actions
      name: Build/Test against gcc-10

  arm64_simd:
    if: github.repository == 'numpy/numpy'
    needs: [baseline_only]
    runs-on: ubuntu-22.04-arm
    strategy:
      fail-fast: false
      matrix:
        config:
          - name: "baseline only"
            args: "-Dallow-noblas=true -Dcpu-dispatch=none"
          - name: "with ASIMD"
            args: "-Dallow-noblas=true -Dcpu-baseline=asimd"
          - name: "native"
            args: "-Dallow-noblas=true -Dcpu-baseline=native -Dcpu-dispatch=none"
    name: "ARM64 SIMD - ${{ matrix.config.name }}"
    steps:
    - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
      with:
        submodules: recursive
        fetch-tags: true
    - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
      with:
        python-version: '3.12'
    - name: Install dependencies
      run: |
        python -m pip install -r requirements/build_requirements.txt -r requirements/test_requirements.txt
    - name: Build
      run: |
        spin build -- ${{ matrix.config.args }}
    - name: Test
      run: |
        spin test -- --timeout=600 --durations=10

  specialize:
    needs: [baseline_only]
    runs-on: ubuntu-latest
    if: github.event_name != 'push'
    continue-on-error: true
    strategy:
      fail-fast: false
      matrix:
        BUILD_PROP:
          - [
            "without optimizations",
            "-Dallow-noblas=true -Ddisable-optimization=true",
            "3.12"
          ]
          - [
            "native",
            "-Dallow-noblas=true -Dcpu-baseline=native -Dcpu-dispatch=none",
            "3.12"
          ]
          - [
            "without avx512",
            "-Dallow-noblas=true -Dcpu-dispatch=max-x86_v4",
            "3.12"
          ]

    env:
      MESON_ARGS: ${{ matrix.BUILD_PROP[1] }}

    name: "${{ matrix.BUILD_PROP[0] }}"
    steps:
    - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
      with:
        submodules: recursive
        fetch-tags: true
        persist-credentials: false
    - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
      with:
        python-version: "${{ matrix.BUILD_PROP[2] }}"
    - uses: ./.github/meson_actions
      name: Build/Test

  intel_sde_avx512:
    needs: [baseline_only]
    runs-on: ubuntu-24.04
    steps:
    - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
      with:
        submodules: recursive
        fetch-tags: true
        persist-credentials: false
    - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
      with:
        python-version: '3.12'

    - name: Install Intel SDE
      # setup-sde v5.0 installs Intel SDE 9.58.0 when requested below.
      uses: petarpetrovt/setup-sde@31aa4a8e85e109bef00f1d838613fcc6ec421271 # v5.0
      with:
        environmentVariableName: SDE_PATH
        sdeVersion: 9.58.0

    - name: Add Intel SDE to PATH
      run: echo "$SDE_PATH" >> "$GITHUB_PATH"

    - name: Install dependencies
      run: |
        python -m pip install -r requirements/build_requirements.txt -r requirements/test_requirements.txt

    - name: Build
      run: CC=gcc-13 CXX=g++-13 spin build -- -Denable-openmp=true -Dallow-noblas=true -Dcpu-baseline=X86_V4 -Dtest-simd='BASELINE,AVX512_ICL,AVX512_SPR'

    - name: Meson Log
      if: always()
      run: cat build/meson-logs/meson-log.txt

    - name: SIMD tests (SKX)
      run: |
        export NUMPY_SITE=$(realpath build-install/usr/lib/python*/site-packages/)
        export PYTHONPATH="$PYTHONPATH:$NUMPY_SITE"
        cd build-install &&
        sde -skx -- python -c "import numpy; numpy.show_config()" &&
        sde -skx -- python -m pytest $NUMPY_SITE/numpy/_core/tests/test_simd*

    - name: linalg/ufunc/umath tests (TGL)
      run: |
        export NUMPY_SITE=$(realpath build-install/usr/lib/python*/site-packages/)
        export PYTHONPATH="$PYTHONPATH:$NUMPY_SITE"
        cd build-install &&
        sde -tgl -- python -c "import numpy; numpy.show_config()" &&
        sde -tgl -- python -m pytest $NUMPY_SITE/numpy/_core/tests/test_umath* \
                                     $NUMPY_SITE/numpy/_core/tests/test_ufunc.py \
                                     $NUMPY_SITE/numpy/_core/tests/test_multiarray.py \
                                     $NUMPY_SITE/numpy/linalg/tests/test_*


  intel_sde_spr:
    needs: [baseline_only]
    runs-on: ubuntu-24.04
    steps:
    - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
      with:
        submodules: recursive
        fetch-tags: true
        persist-credentials: false
    - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
      with:
        python-version: '3.12'

    - name: Install Intel SDE
      # setup-sde v5.0 installs Intel SDE 9.58.0 when requested below.
      uses: petarpetrovt/setup-sde@31aa4a8e85e109bef00f1d838613fcc6ec421271 # v5.0
      with:
        environmentVariableName: SDE_PATH
        sdeVersion: 9.58.0

    - name: Add Intel SDE to PATH
      run: echo "$SDE_PATH" >> "$GITHUB_PATH"

    - name: Install dependencies
      run: |
        python -m pip install -r requirements/build_requirements.txt -r requirements/test_requirements.txt

    - name: Build
      run: CC=gcc-13 CXX=g++-13 spin build -- -Denable-openmp=true -Dallow-noblas=true -Dcpu-baseline=avx512_spr

    - name: Meson Log
      if: always()
      run: cat build/meson-logs/meson-log.txt

    - name: SIMD tests (SPR)
      run: |
        export NUMPY_SITE=$(realpath build-install/usr/lib/python*/site-packages/)
        export PYTHONPATH="$PYTHONPATH:$NUMPY_SITE"
        cd build-install &&
        sde -spr -- python -c "import numpy; numpy.show_config()" &&
        sde -spr -- python -m pytest $NUMPY_SITE/numpy/_core/tests/test_simd*

    - name: linalg/ufunc/umath tests on Intel SPR
      run: |
        export NUMPY_SITE=$(realpath build-install/usr/lib/python*/site-packages/)
        export PYTHONPATH="$PYTHONPATH:$NUMPY_SITE"
        cd build-install &&
        sde -spr -- python -c "import numpy; numpy.show_config()" &&
        sde -spr -- python -m pytest $NUMPY_SITE/numpy/_core/tests/test_umath* \
                                     $NUMPY_SITE/numpy/_core/tests/test_ufunc.py \
                                     $NUMPY_SITE/numpy/_core/tests/test_multiarray.py \
                                     $NUMPY_SITE/numpy/linalg/tests/test_*
