From 61406c54e08fe742fee8b48596a3fbce1836d331 Mon Sep 17 00:00:00 2001 From: swayaminsync Date: Mon, 21 Jul 2025 11:37:00 +0530 Subject: [PATCH 01/22] init big endian ci --- .github/workflows/big_endian.yml | 207 +++++++++++++++++++++++++++++++ 1 file changed, 207 insertions(+) create mode 100644 .github/workflows/big_endian.yml diff --git a/.github/workflows/big_endian.yml b/.github/workflows/big_endian.yml new file mode 100644 index 00000000..c631e784 --- /dev/null +++ b/.github/workflows/big_endian.yml @@ -0,0 +1,207 @@ +name: Test Big-Endian Systems + +on: + push: + branches: + - big-endian-ci + pull_request: + workflow_dispatch: + +jobs: + test-big-endian: + name: Test Big-Endian Systems + runs-on: ubuntu-latest + timeout-minutes: 120 # Big-endian emulation is slower + strategy: + fail-fast: false # Continue testing other architectures if one fails + matrix: + include: + - arch: s390x + platform: linux/s390x + name: "IBM Z (s390x)" + continue-on-error: true # Allow failures initially + - arch: ppc64 + platform: linux/ppc64 + name: "PowerPC 64-bit" + continue-on-error: true # Allow failures initially + + continue-on-error: ${{ matrix.continue-on-error }} + + steps: + - uses: actions/checkout@v3 + with: + submodules: recursive + + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + with: + platforms: ${{ matrix.platform }} + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Create test script + run: | + cat > test_script.sh << 'EOF' + #!/bin/bash + set -ex + + echo "=== Starting Big-Endian Test for ${{ matrix.name }} ===" + + # Update package list and install dependencies + echo "=== Installing System Dependencies ===" + apt-get update + apt-get install -y python3 python3-pip python3-dev python3-venv + apt-get install -y gcc g++ cmake make git pkg-config + apt-get install -y libmpfr-dev libssl-dev libfftw3-dev + + # Create and activate virtual environment + echo "=== Setting up Python Environment ===" + python3 -m venv /tmp/venv + source /tmp/venv/bin/activate + + # Install Python dependencies + pip install -U pip build pytest unyt wheel meson ninja meson-python patchelf pandas numpy + + # Verify we're on big-endian system + echo "=== Endianness Check ===" + python3 -c " + import sys + import struct + print(f'Byte order: {sys.byteorder}') + is_little = struct.pack('@I', 1) == struct.pack(' Date: Wed, 17 Sep 2025 13:09:24 +0000 Subject: [PATCH 02/22] inspiration from numpy test-1 --- .github/workflows/big_endian.yml | 460 ++++++++++++++++++------------- 1 file changed, 263 insertions(+), 197 deletions(-) diff --git a/.github/workflows/big_endian.yml b/.github/workflows/big_endian.yml index c631e784..f9359d0f 100644 --- a/.github/workflows/big_endian.yml +++ b/.github/workflows/big_endian.yml @@ -1,207 +1,273 @@ -name: Test Big-Endian Systems +# Cross-platform testing for quaddtype on high-endianness architectures using QEMU. +# This workflow uses Docker containers with QEMU emulation to test on different architectures, +# particularly focusing on big-endian systems where byte order matters for quad precision operations. +# +# The recommended practice is to rely on Docker to provide the cross-compile toolchain, +# enabling native execution via binfmt. + +name: Linux QEMU Endianness Tests on: - push: - branches: - - big-endian-ci pull_request: + branches: + - main + - maintenance/** + paths: + - "quaddtype/**" + - ".github/workflows/**" workflow_dispatch: +defaults: + run: + shell: bash + +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + +permissions: + contents: read + jobs: - test-big-endian: - name: Test Big-Endian Systems - runs-on: ubuntu-latest - timeout-minutes: 120 # Big-endian emulation is slower + linux_qemu_endian: + # Enable on forks only for workflow_dispatch + if: github.repository == 'numpy/numpy-user-dtypes' || github.event_name == 'workflow_dispatch' + runs-on: ubuntu-22.04 + continue-on-error: true strategy: - fail-fast: false # Continue testing other architectures if one fails + fail-fast: false matrix: - include: - - arch: s390x - platform: linux/s390x - name: "IBM Z (s390x)" - continue-on-error: true # Allow failures initially - - arch: ppc64 - platform: linux/ppc64 - name: "PowerPC 64-bit" - continue-on-error: true # Allow failures initially - - continue-on-error: ${{ matrix.continue-on-error }} + BUILD_PROP: + - [ + "ppc64le (Power9 Little Endian)", + "powerpc64le-linux-gnu", + "ppc64le/ubuntu:22.04", + "ppc64le" + ] + - [ + "ppc64le - baseline(Power9)", + "powerpc64le-linux-gnu", + "ppc64le/ubuntu:22.04", + "ppc64le" + ] + - [ + "s390x (IBM Z Big Endian)", + "s390x-linux-gnu", + "s390x/ubuntu:22.04", + "s390x" + ] + - [ + "s390x - baseline(Z13)", + "s390x-linux-gnu", + "s390x/ubuntu:22.04", + "s390x" + ] + - [ + "riscv64 (Little Endian)", + "riscv64-linux-gnu", + "riscv64/ubuntu:22.04", + "riscv64" + ] + env: + ARCH_NAME: ${{ matrix.BUILD_PROP[0] }} + TOOLCHAIN_NAME: ${{ matrix.BUILD_PROP[1] }} + DOCKER_CONTAINER: ${{ matrix.BUILD_PROP[2] }} + ARCH: ${{ matrix.BUILD_PROP[3] }} + TERM: xterm-256color + name: "${{ matrix.BUILD_PROP[0] }}" steps: - - uses: actions/checkout@v3 - with: - submodules: recursive - - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 - with: - platforms: ${{ matrix.platform }} - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - - name: Create test script - run: | - cat > test_script.sh << 'EOF' - #!/bin/bash - set -ex - - echo "=== Starting Big-Endian Test for ${{ matrix.name }} ===" - - # Update package list and install dependencies - echo "=== Installing System Dependencies ===" - apt-get update - apt-get install -y python3 python3-pip python3-dev python3-venv - apt-get install -y gcc g++ cmake make git pkg-config - apt-get install -y libmpfr-dev libssl-dev libfftw3-dev - - # Create and activate virtual environment - echo "=== Setting up Python Environment ===" - python3 -m venv /tmp/venv - source /tmp/venv/bin/activate - - # Install Python dependencies - pip install -U pip build pytest unyt wheel meson ninja meson-python patchelf pandas numpy - - # Verify we're on big-endian system - echo "=== Endianness Check ===" - python3 -c " - import sys - import struct - print(f'Byte order: {sys.byteorder}') - is_little = struct.pack('@I', 1) == struct.pack('=1.3.2 meson-python wheel numpy && + + # Install system dependencies for quaddtype (SLEEF dependencies) + apt install -y libssl-dev libfftw3-dev pkg-config + " + docker commit quaddtype_container quaddtype_container + mkdir -p "~/docker_${TOOLCHAIN_NAME}" + docker save -o "~/docker_${TOOLCHAIN_NAME}/quaddtype_container.tar" quaddtype_container + + - name: Load container from cache + if: steps.container-cache.outputs.cache-hit == 'true' + run: docker load -i "~/docker_${TOOLCHAIN_NAME}/quaddtype_container.tar" + + - name: Build quaddtype with cross-compilation + run: | + docker run --rm --platform=linux/${ARCH} -e "TERM=xterm-256color" \ + -v $(pwd):/workspace -v /:/host quaddtype_container \ + /bin/script -e -q -c "/bin/bash --noprofile --norc -eo pipefail -c ' + cd /workspace/quaddtype && + echo \"Building quaddtype for ${ARCH_NAME}...\" && + + # Set OpenMP linking for cross-compilation + export LDFLAGS=\"-fopenmp\" && + + # Install quaddtype with test dependencies + python -m pip install .[test] -v --no-build-isolation --force-reinstall + '" + + - name: Run quaddtype tests + run: | + docker run --rm --platform=linux/${ARCH} -e "TERM=xterm-256color" \ + -v $(pwd):/workspace -v /:/host quaddtype_container \ + /bin/script -e -q -c "/bin/bash --noprofile --norc -eo pipefail -c ' + cd /workspace/quaddtype && + echo \"Running quaddtype tests on ${ARCH_NAME} (endianness: \$(python -c \"import sys; print(sys.byteorder)\"))\" && + pytest -vvv --color=yes --timeout=600 --tb=short tests/ + '" + + linux_loongarch64_qemu: + # LoongArch64 testing (another architecture for comprehensive coverage) + if: github.repository == 'numpy/numpy-user-dtypes' || github.event_name == 'workflow_dispatch' + runs-on: ubuntu-24.04 + continue-on-error: true + strategy: + fail-fast: false + matrix: + BUILD_PROP: + - [ + "loongarch64 (LoongArch Little Endian)", + "loongarch64-linux-gnu", + "cnclarechen/numpy-loong64-debian:v1", + "loong64" + ] + env: + ARCH_NAME: ${{ matrix.BUILD_PROP[0] }} + TOOLCHAIN_NAME: ${{ matrix.BUILD_PROP[1] }} + DOCKER_CONTAINER: ${{ matrix.BUILD_PROP[2] }} + ARCH: ${{ matrix.BUILD_PROP[3] }} + TERM: xterm-256color + + name: "${{ matrix.BUILD_PROP[0] }}" + steps: + - uses: actions/checkout@v4 + with: + submodules: recursive + fetch-tags: true + + - name: Initialize binfmt_misc for qemu-user-static (LoongArch) + run: | + docker run --rm --privileged loongcr.lcpu.dev/multiarch/archlinux --reset -p yes + + - name: Install GCC cross-compilers for LoongArch + run: | + sudo apt update + sudo apt install -y ninja-build gcc-14-${TOOLCHAIN_NAME} g++-14-${TOOLCHAIN_NAME} gfortran-14-${TOOLCHAIN_NAME} + + - name: Cache LoongArch docker container + uses: actions/cache@v4 + id: container-cache + with: + path: ~/docker_${{ matrix.BUILD_PROP[1] }} + key: container-quaddtype-${{ runner.os }}-${{ matrix.BUILD_PROP[1] }}-${{ matrix.BUILD_PROP[2] }}-${{ hashFiles('quaddtype/pyproject.toml') }} + + - name: Create LoongArch cross-compilation container + if: steps.container-cache.outputs.cache-hit != 'true' + run: | + docker run --platform=linux/${ARCH} --name quaddtype_loong_container --interactive \ + -v /:/host -v $(pwd):/workspace ${DOCKER_CONTAINER} /bin/bash -c " + # Set up cross-compilation environment for LoongArch + mkdir -p /lib64 && ln -sf /host/lib64/ld-* /lib64/ && + ln -sf /host/lib/x86_64-linux-gnu /lib/x86_64-linux-gnu && + ln -sf /host/usr/${TOOLCHAIN_NAME} /usr/${TOOLCHAIN_NAME} && + ln -sf /host/usr/lib/gcc-cross/${TOOLCHAIN_NAME} /usr/lib/gcc/${TOOLCHAIN_NAME} && + + # Use GCC-14 for LoongArch + rm -f /usr/bin/gcc && ln -sf /host/usr/bin/${TOOLCHAIN_NAME}-gcc-14 /usr/bin/gcc && + rm -f /usr/bin/g++ && ln -sf /host/usr/bin/${TOOLCHAIN_NAME}-g++-14 /usr/bin/g++ && + rm -f /usr/bin/gfortran && ln -sf /host/usr/bin/${TOOLCHAIN_NAME}-gfortran-14 /usr/bin/gfortran && + rm -f /usr/bin/ar && ln -sf /host/usr/bin/${TOOLCHAIN_NAME}-ar /usr/bin/ar && + rm -f /usr/bin/as && ln -sf /host/usr/bin/${TOOLCHAIN_NAME}-as /usr/bin/as && + rm -f /usr/bin/ld && ln -sf /host/usr/bin/${TOOLCHAIN_NAME}-ld /usr/bin/ld && + rm -f /usr/bin/ld.bfd && ln -sf /host/usr/bin/${TOOLCHAIN_NAME}-ld.bfd /usr/bin/ld.bfd && + rm -f /usr/bin/ninja && ln -sf /host/usr/bin/ninja /usr/bin/ninja && + + git config --global --add safe.directory /workspace && + python -m pip install --break-system-packages meson>=1.3.2 meson-python wheel numpy + " + docker commit quaddtype_loong_container quaddtype_loong_container + mkdir -p "~/docker_${TOOLCHAIN_NAME}" + docker save -o "~/docker_${TOOLCHAIN_NAME}/quaddtype_loong_container.tar" quaddtype_loong_container + + - name: Load LoongArch container from cache + if: steps.container-cache.outputs.cache-hit == 'true' + run: docker load -i "~/docker_${TOOLCHAIN_NAME}/quaddtype_loong_container.tar" + + - name: Build quaddtype on LoongArch + run: | + docker run --rm --platform=linux/${ARCH} -e "TERM=xterm-256color" \ + -v $(pwd):/workspace -v /:/host quaddtype_loong_container \ + /bin/script -e -q -c "/bin/bash --noprofile --norc -eo pipefail -c ' + cd /workspace/quaddtype && + export LDFLAGS=\"-fopenmp\" && + python -m pip install --break-system-packages .[test] -v --no-build-isolation --force-reinstall + '" + + - name: Run LoongArch tests + run: | + docker run --rm --platform=linux/${ARCH} -e "TERM=xterm-256color" \ + -v $(pwd):/workspace -v /:/host quaddtype_loong_container \ + /bin/script -e -q -c "/bin/bash --noprofile --norc -eo pipefail -c ' + cd /workspace/quaddtype && + echo \"Running quaddtype tests on ${ARCH_NAME} (endianness: \$(python -c \"import sys; print(sys.byteorder)\"))\" && + pytest -vvv --color=yes tests/ + '" \ No newline at end of file From 33ed4c17af5d1b4e9e3877c6f98c19f43e4ee6c9 Mon Sep 17 00:00:00 2001 From: SwayamInSync Date: Wed, 17 Sep 2025 13:13:34 +0000 Subject: [PATCH 03/22] inspiration from numpy test-1 --- .github/workflows/big_endian.yml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/.github/workflows/big_endian.yml b/.github/workflows/big_endian.yml index f9359d0f..aa6a1d34 100644 --- a/.github/workflows/big_endian.yml +++ b/.github/workflows/big_endian.yml @@ -11,7 +11,6 @@ on: pull_request: branches: - main - - maintenance/** paths: - "quaddtype/**" - ".github/workflows/**" @@ -30,8 +29,6 @@ permissions: jobs: linux_qemu_endian: - # Enable on forks only for workflow_dispatch - if: github.repository == 'numpy/numpy-user-dtypes' || github.event_name == 'workflow_dispatch' runs-on: ubuntu-22.04 continue-on-error: true strategy: @@ -176,8 +173,6 @@ jobs: '" linux_loongarch64_qemu: - # LoongArch64 testing (another architecture for comprehensive coverage) - if: github.repository == 'numpy/numpy-user-dtypes' || github.event_name == 'workflow_dispatch' runs-on: ubuntu-24.04 continue-on-error: true strategy: From 09764a525d41172bd19b3bbfe6ebe2160a667493 Mon Sep 17 00:00:00 2001 From: SwayamInSync Date: Wed, 17 Sep 2025 13:27:00 +0000 Subject: [PATCH 04/22] onlynig-endian --- .github/workflows/big_endian.yml | 130 ++----------------------------- 1 file changed, 8 insertions(+), 122 deletions(-) diff --git a/.github/workflows/big_endian.yml b/.github/workflows/big_endian.yml index aa6a1d34..8bef5b7e 100644 --- a/.github/workflows/big_endian.yml +++ b/.github/workflows/big_endian.yml @@ -1,16 +1,14 @@ -# Cross-platform testing for quaddtype on high-endianness architectures using QEMU. -# This workflow uses Docker containers with QEMU emulation to test on different architectures, -# particularly focusing on big-endian systems where byte order matters for quad precision operations. -# -# The recommended practice is to rely on Docker to provide the cross-compile toolchain, -# enabling native execution via binfmt. +# Cross-platform testing for quaddtype on big-endian architectures using QEMU. +# This workflow focuses specifically on big-endian systems to test byte order handling +# in quad precision operations, since little-endian systems are already covered by standard CI. -name: Linux QEMU Endianness Tests +name: Big-Endian Architecture Tests on: pull_request: branches: - main + - maintenance/** paths: - "quaddtype/**" - ".github/workflows/**" @@ -28,25 +26,13 @@ permissions: contents: read jobs: - linux_qemu_endian: + big_endian_tests: runs-on: ubuntu-22.04 continue-on-error: true strategy: fail-fast: false matrix: BUILD_PROP: - - [ - "ppc64le (Power9 Little Endian)", - "powerpc64le-linux-gnu", - "ppc64le/ubuntu:22.04", - "ppc64le" - ] - - [ - "ppc64le - baseline(Power9)", - "powerpc64le-linux-gnu", - "ppc64le/ubuntu:22.04", - "ppc64le" - ] - [ "s390x (IBM Z Big Endian)", "s390x-linux-gnu", @@ -59,12 +45,6 @@ jobs: "s390x/ubuntu:22.04", "s390x" ] - - [ - "riscv64 (Little Endian)", - "riscv64-linux-gnu", - "riscv64/ubuntu:22.04", - "riscv64" - ] env: ARCH_NAME: ${{ matrix.BUILD_PROP[0] }} TOOLCHAIN_NAME: ${{ matrix.BUILD_PROP[1] }} @@ -169,100 +149,6 @@ jobs: /bin/script -e -q -c "/bin/bash --noprofile --norc -eo pipefail -c ' cd /workspace/quaddtype && echo \"Running quaddtype tests on ${ARCH_NAME} (endianness: \$(python -c \"import sys; print(sys.byteorder)\"))\" && + echo \"Note: Testing big-endian byte order handling in quad precision operations\" && pytest -vvv --color=yes --timeout=600 --tb=short tests/ - '" - - linux_loongarch64_qemu: - runs-on: ubuntu-24.04 - continue-on-error: true - strategy: - fail-fast: false - matrix: - BUILD_PROP: - - [ - "loongarch64 (LoongArch Little Endian)", - "loongarch64-linux-gnu", - "cnclarechen/numpy-loong64-debian:v1", - "loong64" - ] - env: - ARCH_NAME: ${{ matrix.BUILD_PROP[0] }} - TOOLCHAIN_NAME: ${{ matrix.BUILD_PROP[1] }} - DOCKER_CONTAINER: ${{ matrix.BUILD_PROP[2] }} - ARCH: ${{ matrix.BUILD_PROP[3] }} - TERM: xterm-256color - - name: "${{ matrix.BUILD_PROP[0] }}" - steps: - - uses: actions/checkout@v4 - with: - submodules: recursive - fetch-tags: true - - - name: Initialize binfmt_misc for qemu-user-static (LoongArch) - run: | - docker run --rm --privileged loongcr.lcpu.dev/multiarch/archlinux --reset -p yes - - - name: Install GCC cross-compilers for LoongArch - run: | - sudo apt update - sudo apt install -y ninja-build gcc-14-${TOOLCHAIN_NAME} g++-14-${TOOLCHAIN_NAME} gfortran-14-${TOOLCHAIN_NAME} - - - name: Cache LoongArch docker container - uses: actions/cache@v4 - id: container-cache - with: - path: ~/docker_${{ matrix.BUILD_PROP[1] }} - key: container-quaddtype-${{ runner.os }}-${{ matrix.BUILD_PROP[1] }}-${{ matrix.BUILD_PROP[2] }}-${{ hashFiles('quaddtype/pyproject.toml') }} - - - name: Create LoongArch cross-compilation container - if: steps.container-cache.outputs.cache-hit != 'true' - run: | - docker run --platform=linux/${ARCH} --name quaddtype_loong_container --interactive \ - -v /:/host -v $(pwd):/workspace ${DOCKER_CONTAINER} /bin/bash -c " - # Set up cross-compilation environment for LoongArch - mkdir -p /lib64 && ln -sf /host/lib64/ld-* /lib64/ && - ln -sf /host/lib/x86_64-linux-gnu /lib/x86_64-linux-gnu && - ln -sf /host/usr/${TOOLCHAIN_NAME} /usr/${TOOLCHAIN_NAME} && - ln -sf /host/usr/lib/gcc-cross/${TOOLCHAIN_NAME} /usr/lib/gcc/${TOOLCHAIN_NAME} && - - # Use GCC-14 for LoongArch - rm -f /usr/bin/gcc && ln -sf /host/usr/bin/${TOOLCHAIN_NAME}-gcc-14 /usr/bin/gcc && - rm -f /usr/bin/g++ && ln -sf /host/usr/bin/${TOOLCHAIN_NAME}-g++-14 /usr/bin/g++ && - rm -f /usr/bin/gfortran && ln -sf /host/usr/bin/${TOOLCHAIN_NAME}-gfortran-14 /usr/bin/gfortran && - rm -f /usr/bin/ar && ln -sf /host/usr/bin/${TOOLCHAIN_NAME}-ar /usr/bin/ar && - rm -f /usr/bin/as && ln -sf /host/usr/bin/${TOOLCHAIN_NAME}-as /usr/bin/as && - rm -f /usr/bin/ld && ln -sf /host/usr/bin/${TOOLCHAIN_NAME}-ld /usr/bin/ld && - rm -f /usr/bin/ld.bfd && ln -sf /host/usr/bin/${TOOLCHAIN_NAME}-ld.bfd /usr/bin/ld.bfd && - rm -f /usr/bin/ninja && ln -sf /host/usr/bin/ninja /usr/bin/ninja && - - git config --global --add safe.directory /workspace && - python -m pip install --break-system-packages meson>=1.3.2 meson-python wheel numpy - " - docker commit quaddtype_loong_container quaddtype_loong_container - mkdir -p "~/docker_${TOOLCHAIN_NAME}" - docker save -o "~/docker_${TOOLCHAIN_NAME}/quaddtype_loong_container.tar" quaddtype_loong_container - - - name: Load LoongArch container from cache - if: steps.container-cache.outputs.cache-hit == 'true' - run: docker load -i "~/docker_${TOOLCHAIN_NAME}/quaddtype_loong_container.tar" - - - name: Build quaddtype on LoongArch - run: | - docker run --rm --platform=linux/${ARCH} -e "TERM=xterm-256color" \ - -v $(pwd):/workspace -v /:/host quaddtype_loong_container \ - /bin/script -e -q -c "/bin/bash --noprofile --norc -eo pipefail -c ' - cd /workspace/quaddtype && - export LDFLAGS=\"-fopenmp\" && - python -m pip install --break-system-packages .[test] -v --no-build-isolation --force-reinstall - '" - - - name: Run LoongArch tests - run: | - docker run --rm --platform=linux/${ARCH} -e "TERM=xterm-256color" \ - -v $(pwd):/workspace -v /:/host quaddtype_loong_container \ - /bin/script -e -q -c "/bin/bash --noprofile --norc -eo pipefail -c ' - cd /workspace/quaddtype && - echo \"Running quaddtype tests on ${ARCH_NAME} (endianness: \$(python -c \"import sys; print(sys.byteorder)\"))\" && - pytest -vvv --color=yes tests/ - '" \ No newline at end of file + '" \ No newline at end of file From 77fcb35d20ab32fda582f43e7aa1f8bce820e8fe Mon Sep 17 00:00:00 2001 From: SwayamInSync Date: Wed, 17 Sep 2025 15:31:34 +0000 Subject: [PATCH 05/22] using python -m --- .github/workflows/big_endian.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/big_endian.yml b/.github/workflows/big_endian.yml index 8bef5b7e..74f3817d 100644 --- a/.github/workflows/big_endian.yml +++ b/.github/workflows/big_endian.yml @@ -8,7 +8,6 @@ on: pull_request: branches: - main - - maintenance/** paths: - "quaddtype/**" - ".github/workflows/**" @@ -150,5 +149,5 @@ jobs: cd /workspace/quaddtype && echo \"Running quaddtype tests on ${ARCH_NAME} (endianness: \$(python -c \"import sys; print(sys.byteorder)\"))\" && echo \"Note: Testing big-endian byte order handling in quad precision operations\" && - pytest -vvv --color=yes --timeout=600 --tb=short tests/ + python -m pytest -vvv --color=yes --timeout=600 --tb=short tests/ '" \ No newline at end of file From 96be1d73cf0016943146bc06fd5753fa345b1e17 Mon Sep 17 00:00:00 2001 From: SwayamInSync Date: Wed, 17 Sep 2025 15:45:54 +0000 Subject: [PATCH 06/22] install pytest man --- .github/workflows/big_endian.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/big_endian.yml b/.github/workflows/big_endian.yml index 74f3817d..72bb5f7c 100644 --- a/.github/workflows/big_endian.yml +++ b/.github/workflows/big_endian.yml @@ -114,6 +114,7 @@ jobs: # Install Python build dependencies python -m pip install --upgrade pip && python -m pip install meson>=1.3.2 meson-python wheel numpy && + python -m pip install pytest pytest-run-parallel pytest-timeout && # Install system dependencies for quaddtype (SLEEF dependencies) apt install -y libssl-dev libfftw3-dev pkg-config From c8819070647f4ac8f5336f5f5be7b73e8d052c2b Mon Sep 17 00:00:00 2001 From: Swayam Date: Wed, 17 Sep 2025 21:40:45 +0530 Subject: [PATCH 07/22] Fix test directory path in big_endian.yml --- .github/workflows/big_endian.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/big_endian.yml b/.github/workflows/big_endian.yml index 72bb5f7c..3c29ca33 100644 --- a/.github/workflows/big_endian.yml +++ b/.github/workflows/big_endian.yml @@ -147,8 +147,8 @@ jobs: docker run --rm --platform=linux/${ARCH} -e "TERM=xterm-256color" \ -v $(pwd):/workspace -v /:/host quaddtype_container \ /bin/script -e -q -c "/bin/bash --noprofile --norc -eo pipefail -c ' - cd /workspace/quaddtype && + cd /workspace && echo \"Running quaddtype tests on ${ARCH_NAME} (endianness: \$(python -c \"import sys; print(sys.byteorder)\"))\" && echo \"Note: Testing big-endian byte order handling in quad precision operations\" && - python -m pytest -vvv --color=yes --timeout=600 --tb=short tests/ - '" \ No newline at end of file + python -m pytest -vvv --color=yes --timeout=600 --tb=short /workspace/quaddtype/tests/ + '" From 68793e634bf0c76dd71e06d1f1fb3c8b100d71b0 Mon Sep 17 00:00:00 2001 From: SwayamInSync Date: Wed, 17 Sep 2025 16:28:16 +0000 Subject: [PATCH 08/22] building and testing in one --- .github/workflows/big_endian.yml | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/.github/workflows/big_endian.yml b/.github/workflows/big_endian.yml index 3c29ca33..97085187 100644 --- a/.github/workflows/big_endian.yml +++ b/.github/workflows/big_endian.yml @@ -127,7 +127,7 @@ jobs: if: steps.container-cache.outputs.cache-hit == 'true' run: docker load -i "~/docker_${TOOLCHAIN_NAME}/quaddtype_container.tar" - - name: Build quaddtype with cross-compilation + - name: Build quaddtype with cross-compilation and testing run: | docker run --rm --platform=linux/${ARCH} -e "TERM=xterm-256color" \ -v $(pwd):/workspace -v /:/host quaddtype_container \ @@ -140,15 +140,7 @@ jobs: # Install quaddtype with test dependencies python -m pip install .[test] -v --no-build-isolation --force-reinstall - '" - - - name: Run quaddtype tests - run: | - docker run --rm --platform=linux/${ARCH} -e "TERM=xterm-256color" \ - -v $(pwd):/workspace -v /:/host quaddtype_container \ - /bin/script -e -q -c "/bin/bash --noprofile --norc -eo pipefail -c ' - cd /workspace && - echo \"Running quaddtype tests on ${ARCH_NAME} (endianness: \$(python -c \"import sys; print(sys.byteorder)\"))\" && - echo \"Note: Testing big-endian byte order handling in quad precision operations\" && - python -m pytest -vvv --color=yes --timeout=600 --tb=short /workspace/quaddtype/tests/ + + cd .. + python -m pytest -vvv --color=yes --timeout=600 --tb=short quaddtype/tests/ '" From 814fafbb7bd90b0554b894919bda33082ee3ce1c Mon Sep 17 00:00:00 2001 From: SwayamInSync Date: Wed, 17 Sep 2025 17:23:27 +0000 Subject: [PATCH 09/22] fixing endianes detection --- .../numpy_quaddtype/src/quaddtype_main.c | 30 +++++++++++-------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/quaddtype/numpy_quaddtype/src/quaddtype_main.c b/quaddtype/numpy_quaddtype/src/quaddtype_main.c index 734de21b..de945c6e 100644 --- a/quaddtype/numpy_quaddtype/src/quaddtype_main.c +++ b/quaddtype/numpy_quaddtype/src/quaddtype_main.c @@ -11,6 +11,7 @@ #include "numpy/arrayobject.h" #include "numpy/dtype_api.h" #include "numpy/ufuncobject.h" +#include "numpy/npy_endian.h" #include "scalar.h" #include "dtype.h" @@ -33,23 +34,26 @@ py_is_longdouble_128(PyObject *self, PyObject *args) #ifdef SLEEF_QUAD_C static const Sleef_quad SMALLEST_SUBNORMAL_VALUE = SLEEF_QUAD_DENORM_MIN; #else -// Use the exact same struct layout as the original buggy code static const union { struct { -#if defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) - uint64_t h, l; -#else - uint64_t l, h; -#endif + #if NPY_BYTE_ORDER == NPY_BIG_ENDIAN + uint64_t high; + uint64_t low; + #elif NPY_BYTE_ORDER == NPY_LITTLE_ENDIAN + uint64_t low; + uint64_t high; + #else + #error "Unknown endianness - NPY_BYTE_ORDER not properly defined" + #endif } parts; Sleef_quad value; -} smallest_subnormal_const = {.parts = { -#if defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) - .h = 0x0000000000000000ULL, .l = 0x0000000000000001ULL -#else - .l = 0x0000000000000001ULL, .h = 0x0000000000000000ULL -#endif - }}; +} smallest_subnormal_const = { + .parts = { + .low = 0x0000000000000001ULL, + .high = 0x0000000000000000ULL + } +}; + #define SMALLEST_SUBNORMAL_VALUE (smallest_subnormal_const.value) #endif From 57fdfe0c2abd23b38de7b4b529aa55b3daf57c2b Mon Sep 17 00:00:00 2001 From: jorenham Date: Wed, 17 Sep 2025 22:47:27 +0200 Subject: [PATCH 10/22] TYP: Static typing support for `numpy_quaddtype` --- quaddtype/meson.build | 13 +- quaddtype/numpy_quaddtype/__init__.pyi | 56 ++++++++ quaddtype/numpy_quaddtype/_quaddtype_main.pyi | 134 ++++++++++++++++++ quaddtype/numpy_quaddtype/py.typed | 0 quaddtype/pyproject.toml | 16 ++- 5 files changed, 213 insertions(+), 6 deletions(-) create mode 100644 quaddtype/numpy_quaddtype/__init__.pyi create mode 100644 quaddtype/numpy_quaddtype/_quaddtype_main.pyi create mode 100644 quaddtype/numpy_quaddtype/py.typed diff --git a/quaddtype/meson.build b/quaddtype/meson.build index 04b506b7..75e9e382 100644 --- a/quaddtype/meson.build +++ b/quaddtype/meson.build @@ -35,7 +35,7 @@ if openmp_dep.found() dependencies += openmp_dep endif -# compiler flags for QBLAS compatibility +# compiler flags for QBLAS compatibility if not is_windows # QBLAS requires extended numeric literals for Q suffix support # if compiler supports (usually gcc) @@ -61,14 +61,14 @@ foreach optional_attr: optional_variable_attributes code = ''' #pragma GCC diagnostic error "-Wattributes" #pragma clang diagnostic error "-Wattributes" - + int @0@ foo; - + int main() { return 0; } '''.format(attr) - + if c.compiles(code, name: optional_attr[0]) cdata.set10(optional_attr[1], true) message('Thread-local storage support found: @0@'.format(attr)) @@ -122,6 +122,9 @@ srcs = [ py.install_sources( [ 'numpy_quaddtype/__init__.py', + 'numpy_quaddtype/__init__.pyi', + 'numpy_quaddtype/_quaddtype_main.pyi', + 'numpy_quaddtype/py.typed', ], subdir: 'numpy_quaddtype', pure: false @@ -134,4 +137,4 @@ py.extension_module('_quaddtype_main', install: true, subdir: 'numpy_quaddtype', include_directories: [includes, build_includes], -) \ No newline at end of file +) diff --git a/quaddtype/numpy_quaddtype/__init__.pyi b/quaddtype/numpy_quaddtype/__init__.pyi new file mode 100644 index 00000000..ae9aa25c --- /dev/null +++ b/quaddtype/numpy_quaddtype/__init__.pyi @@ -0,0 +1,56 @@ +from typing import Final + +from ._quaddtype_main import ( + QuadPrecDType, + QuadPrecision, + _IntoQuad, # type-check only # pyright: ignore[reportPrivateUsage] + get_num_threads, + get_quadblas_version, + is_longdouble_128, + set_num_threads, +) + +__all__ = [ + "QuadPrecision", + "QuadPrecDType", + "SleefQuadPrecision", + "LongDoubleQuadPrecision", + "SleefQuadPrecDType", + "LongDoubleQuadPrecDType", + "is_longdouble_128", + "pi", + "e", + "log2e", + "log10e", + "ln2", + "ln10", + "max_value", + "epsilon", + "smallest_normal", + "smallest_subnormal", + "bits", + "precision", + "resolution", + "set_num_threads", + "get_num_threads", + "get_quadblas_version", +] + +def SleefQuadPrecision(value: _IntoQuad) -> QuadPrecision: ... +def LongDoubleQuadPrecision(value: _IntoQuad) -> QuadPrecision: ... +def SleefQuadPrecDType() -> QuadPrecDType: ... +def LongDoubleQuadPrecDType() -> QuadPrecDType: ... + +pi: Final[QuadPrecision] = ... +e: Final[QuadPrecision] = ... +log2e: Final[QuadPrecision] = ... +log10e: Final[QuadPrecision] = ... +ln2: Final[QuadPrecision] = ... +ln10: Final[QuadPrecision] = ... +max_value: Final[QuadPrecision] = ... +epsilon: Final[QuadPrecision] = ... +smallest_normal: Final[QuadPrecision] = ... +smallest_subnormal: Final[QuadPrecision] = ... +resolution: Final[QuadPrecision] = ... +bits: Final = 128 +precision: Final = 33 diff --git a/quaddtype/numpy_quaddtype/_quaddtype_main.pyi b/quaddtype/numpy_quaddtype/_quaddtype_main.pyi new file mode 100644 index 00000000..72c334b1 --- /dev/null +++ b/quaddtype/numpy_quaddtype/_quaddtype_main.pyi @@ -0,0 +1,134 @@ +from typing import Any, Literal, TypeAlias, final + +import numpy as np +from typing_extensions import Never, Self, override + +_Backend: TypeAlias = Literal["sleef", "longdouble"] +_IntoQuad: TypeAlias = QuadPrecision | float | str +_CastsQuad: TypeAlias = _IntoQuad | np.floating[Any] | np.integer[Any] | np.bool_ + +@final +class QuadPrecDType(np.dtype[QuadPrecision]): # type: ignore[misc, type-var] # pyright: ignore[reportGeneralTypeIssues, reportInvalidTypeArguments] + def __new__(cls, /, backend: _Backend = "sleef") -> Self: ... + + # `numpy.dtype` overrides + names: None # pyright: ignore[reportIncompatibleVariableOverride] + @property + @override + def alignment(self) -> Literal[16]: ... + @property + @override + def itemsize(self) -> Literal[16]: ... + @property + @override + def name(self) -> Literal["QuadPrecDType128"]: ... + @property + @override + def byteorder(self) -> Literal["|"]: ... + @property + @override + def char(self) -> Literal["\x00"]: ... # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride] + @property + @override + def kind(self) -> Literal["\x00"]: ... # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride] + @property + @override + def num(self) -> Literal[-1]: ... # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride] + @property + @override + def shape(self) -> tuple[()]: ... + @property + @override + def ndim(self) -> Literal[0]: ... + @property + @override + def fields(self) -> None: ... + @property + @override + def base(self) -> Self: ... + @property + @override + def subdtype(self) -> None: ... + @property + @override + def hasobject(self) -> Literal[False]: ... + @property + @override + def isbuiltin(self) -> Literal[0]: ... + @property + @override + def isnative(self) -> Literal[True]: ... + @property + @override + def isalignedstruct(self) -> Literal[False]: ... + @override + def __getitem__(self, key: Never, /) -> Self: ... # type: ignore[override] + +@final +class QuadPrecision: # NOTE: It doesn't inherit from `np.generic` which is type-unsafe + def __new__(cls, /, value: _IntoQuad, backend: _Backend = "sleef") -> Self: ... + + # Rich comparison operators + # NOTE: Unlike other numpy scalars, these return `builtins.bool`, not `np.bool`. + @override + def __eq__(self, other: object, /) -> bool: ... + @override + def __ne__(self, other: object, /) -> bool: ... + def __lt__(self, other: _IntoQuad, /) -> bool: ... + def __le__(self, other: _IntoQuad, /) -> bool: ... + def __gt__(self, other: _IntoQuad, /) -> bool: ... + def __ge__(self, other: _IntoQuad, /) -> bool: ... + + # Binary operators + def __add__(self, other: _CastsQuad, /) -> Self: ... + def __radd__(self, other: _CastsQuad, /) -> Self: ... # type: ignore[misc] + def __sub__(self, other: _CastsQuad, /) -> Self: ... + def __rsub__(self, other: _CastsQuad, /) -> Self: ... + def __mul__(self, other: _CastsQuad, /) -> Self: ... + def __rmul__(self, other: _CastsQuad, /) -> Self: ... # type: ignore[misc] + def __pow__(self, other: _CastsQuad, mod: None = None, /) -> Self: ... + def __rpow__(self, other: _CastsQuad, mod: None = None, /) -> Self: ... + def __truediv__(self, other: _CastsQuad, /) -> Self: ... + def __rtruediv__(self, other: _CastsQuad, /) -> Self: ... + + # Unary operators + def __neg__(self, /) -> Self: ... + def __pos__(self, /) -> Self: ... + def __abs__(self, /) -> Self: ... + + # Conversion methods + def __bool__(self, /) -> bool: ... + def __int__(self, /) -> int: ... + def __float__(self, /) -> float: ... + + # String representation + @override + def __repr__(self, /) -> str: ... + @override + def __str__(self, /) -> str: ... + +# +def is_longdouble_128() -> bool: ... +def get_sleef_constant( + constant_name: Literal[ + "pi", + "e", + "log2e", + "log10e", + "ln2", + "ln10", + "max_value", + "epsilon", + "smallest_normal", + "smallest_subnormal", + "bits", + "precision", + "resolution", + ], + /, +) -> QuadPrecision: ... +def set_num_threads(num_threads: int, /) -> None: ... +def get_num_threads() -> int: ... +def get_quadblas_version() -> Literal[ + "QuadBLAS 1.0.0 - High Performance Quad Precision BLAS" +]: ... diff --git a/quaddtype/numpy_quaddtype/py.typed b/quaddtype/numpy_quaddtype/py.typed new file mode 100644 index 00000000..e69de29b diff --git a/quaddtype/pyproject.toml b/quaddtype/pyproject.toml index 466b5231..39341833 100644 --- a/quaddtype/pyproject.toml +++ b/quaddtype/pyproject.toml @@ -23,4 +23,18 @@ dependencies = [ test = [ "pytest", "pytest-run-parallel" -] \ No newline at end of file +] + +[tool.pyright] +include = ["numpy_quaddtype/*.pyi"] +typeCheckingMode = "strict" +enableTypeIgnoreComments = false +reportImplicitOverride = true +reportUnnecessaryTypeIgnoreComment = true + +[tool.mypy] +strict = true +strict_equality_for_none = true +exclude = ["build", "numpy_quaddtype/src", "subprojects", "tests"] +enable_error_code = ["ignore-without-code", "redundant-expr", "truthy-bool"] +warn_unreachable = false From 9182cdc1a937b292fcdd097fd55e85138c72c8c3 Mon Sep 17 00:00:00 2001 From: jorenham Date: Thu, 18 Sep 2025 08:46:25 +0200 Subject: [PATCH 11/22] TYP: Review suggestions from #154 Co-authored-by: Juniper Tyree <50025784+juntyr@users.noreply.github.com> --- quaddtype/numpy_quaddtype/_quaddtype_main.pyi | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/quaddtype/numpy_quaddtype/_quaddtype_main.pyi b/quaddtype/numpy_quaddtype/_quaddtype_main.pyi index 72c334b1..21e2850e 100644 --- a/quaddtype/numpy_quaddtype/_quaddtype_main.pyi +++ b/quaddtype/numpy_quaddtype/_quaddtype_main.pyi @@ -1,4 +1,4 @@ -from typing import Any, Literal, TypeAlias, final +from typing import Any, Literal, TypeAlias, final, overload import numpy as np from typing_extensions import Never, Self, override @@ -109,6 +109,10 @@ class QuadPrecision: # NOTE: It doesn't inherit from `np.generic` which is type # def is_longdouble_128() -> bool: ... + +@overload +def get_sleef_constant(constant_name: Literal["bits", "precision"], /) -> int: ... +@overload def get_sleef_constant( constant_name: Literal[ "pi", @@ -121,14 +125,11 @@ def get_sleef_constant( "epsilon", "smallest_normal", "smallest_subnormal", - "bits", - "precision", "resolution", ], /, ) -> QuadPrecision: ... + def set_num_threads(num_threads: int, /) -> None: ... def get_num_threads() -> int: ... -def get_quadblas_version() -> Literal[ - "QuadBLAS 1.0.0 - High Performance Quad Precision BLAS" -]: ... +def get_quadblas_version() -> str: ... From 18b303d02061ad55490ea3ff42462eb3bd7d219c Mon Sep 17 00:00:00 2001 From: jorenham Date: Thu, 18 Sep 2025 09:26:24 +0200 Subject: [PATCH 12/22] CI: Static typing validation workflow for quaddtype --- .github/workflows/typecheck.yml | 48 +++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 .github/workflows/typecheck.yml diff --git a/.github/workflows/typecheck.yml b/.github/workflows/typecheck.yml new file mode 100644 index 00000000..c35ae1fe --- /dev/null +++ b/.github/workflows/typecheck.yml @@ -0,0 +1,48 @@ +name: Validate static types in quaddtype +permissions: read-all + +on: + pull_request: + paths: + - .github/workflows/typecheck.yml + - quaddtype/numpy_quaddtype/* + - quaddtype/meson.build + - quaddtype/pyproject.toml + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + +jobs: + typecheck_quaddtype: + runs-on: ubuntu-latest + timeout-minutes: 2 + + steps: + - uses: actions/checkout@v5.0.0 + + - uses: astral-sh/setup-uv@v6.7.0 + with: + activate-environment: true + python-version: "3.10" + + - name: install + working-directory: quaddtype + run: uv pip install mypy pyright . + + - name: pyright + working-directory: quaddtype + run: pyright + + - name: pyright --verifytypes + working-directory: quaddtype + run: pyright --ignoreexternal --verifytypes numpy_quaddtype + + - name: mypy + working-directory: quaddtype + run: mypy --no-incremental --cache-dir=/dev/null . + + - name: stubtest + working-directory: quaddtype + run: stubtest --mypy-config-file pyproject.toml numpy_quaddtype From 7fb3cd6235a5665e67cc819e95630911ef36ced5 Mon Sep 17 00:00:00 2001 From: jorenham Date: Thu, 18 Sep 2025 09:56:52 +0200 Subject: [PATCH 13/22] DOC: "Numpy-QuadDType" => "NumPy-QuadDType" --- quaddtype/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/quaddtype/README.md b/quaddtype/README.md index 86eae750..80fa86af 100644 --- a/quaddtype/README.md +++ b/quaddtype/README.md @@ -1,4 +1,4 @@ -# Numpy-QuadDType +# NumPy-QuadDType A cross-platform Quad (128-bit) float Data-Type for NumPy. From d9ae0334656e575c882ad44811ecec2c2682b3c6 Mon Sep 17 00:00:00 2001 From: swayaminsync Date: Thu, 18 Sep 2025 20:45:44 +0530 Subject: [PATCH 14/22] switching to slee_q --- .github/workflows/big_endian.yml | 178 +++++++++--------- .../numpy_quaddtype/src/quaddtype_main.c | 32 +--- 2 files changed, 92 insertions(+), 118 deletions(-) diff --git a/.github/workflows/big_endian.yml b/.github/workflows/big_endian.yml index 97085187..6057f5d8 100644 --- a/.github/workflows/big_endian.yml +++ b/.github/workflows/big_endian.yml @@ -1,7 +1,3 @@ -# Cross-platform testing for quaddtype on big-endian architectures using QEMU. -# This workflow focuses specifically on big-endian systems to test byte order handling -# in quad precision operations, since little-endian systems are already covered by standard CI. - name: Big-Endian Architecture Tests on: @@ -35,14 +31,14 @@ jobs: - [ "s390x (IBM Z Big Endian)", "s390x-linux-gnu", - "s390x/ubuntu:22.04", - "s390x" + "s390x/ubuntu:22.04", + "s390x", ] - [ "s390x - baseline(Z13)", "s390x-linux-gnu", "s390x/ubuntu:22.04", - "s390x" + "s390x", ] env: ARCH_NAME: ${{ matrix.BUILD_PROP[0] }} @@ -53,94 +49,94 @@ jobs: name: "${{ matrix.BUILD_PROP[0] }}" steps: - - uses: actions/checkout@v4 - with: - submodules: recursive - fetch-tags: true - persist-credentials: false - - - name: Initialize binfmt_misc for qemu-user-static - run: | - # Enable QEMU user-mode emulation for cross-architecture execution - docker run --rm --privileged tonistiigi/binfmt:qemu-v9.2.2-52 --install all + - uses: actions/checkout@v4 + with: + submodules: recursive + fetch-tags: true + persist-credentials: false - - name: Install cross-compilation toolchain - run: | - sudo apt update - sudo apt install -y ninja-build gcc-${TOOLCHAIN_NAME} g++-${TOOLCHAIN_NAME} gfortran-${TOOLCHAIN_NAME} + - name: Initialize binfmt_misc for qemu-user-static + run: | + # Enable QEMU user-mode emulation for cross-architecture execution + docker run --rm --privileged tonistiigi/binfmt:qemu-v9.2.2-52 --install all - - name: Cache docker container - uses: actions/cache@v4 - id: container-cache - with: - path: ~/docker_${{ matrix.BUILD_PROP[1] }} - key: container-quaddtype-${{ runner.os }}-${{ matrix.BUILD_PROP[1] }}-${{ matrix.BUILD_PROP[2] }}-${{ hashFiles('quaddtype/pyproject.toml') }} + - name: Install cross-compilation toolchain + run: | + sudo apt update + sudo apt install -y ninja-build gcc-${TOOLCHAIN_NAME} g++-${TOOLCHAIN_NAME} gfortran-${TOOLCHAIN_NAME} - - name: Create cross-compilation container - if: steps.container-cache.outputs.cache-hit != 'true' - run: | - docker run --platform=linux/${ARCH} --name quaddtype_container --interactive \ - -v /:/host -v $(pwd):/workspace ${DOCKER_CONTAINER} /bin/bash -c " - # Update package manager and install essential tools - apt update && - apt install -y cmake git python3 python-is-python3 python3-dev python3-pip build-essential && - - # Create necessary symlinks for cross-compilation - mkdir -p /lib64 && ln -sf /host/lib64/ld-* /lib64/ || true && - ln -sf /host/lib/x86_64-linux-gnu /lib/x86_64-linux-gnu || true && - - # Link cross-compilation toolchain from host - rm -rf /usr/${TOOLCHAIN_NAME} && ln -sf /host/usr/${TOOLCHAIN_NAME} /usr/${TOOLCHAIN_NAME} && - rm -rf /usr/lib/gcc/${TOOLCHAIN_NAME} && ln -sf /host/usr/lib/gcc-cross/${TOOLCHAIN_NAME} /usr/lib/gcc/${TOOLCHAIN_NAME} && - - # Set up compiler symlinks - rm -f /usr/bin/gcc && ln -sf /host/usr/bin/${TOOLCHAIN_NAME}-gcc /usr/bin/gcc && - rm -f /usr/bin/g++ && ln -sf /host/usr/bin/${TOOLCHAIN_NAME}-g++ /usr/bin/g++ && - rm -f /usr/bin/gfortran && ln -sf /host/usr/bin/${TOOLCHAIN_NAME}-gfortran /usr/bin/gfortran && - - # Set up binutils - rm -f /usr/bin/ar && ln -sf /host/usr/bin/${TOOLCHAIN_NAME}-ar /usr/bin/ar && - rm -f /usr/bin/as && ln -sf /host/usr/bin/${TOOLCHAIN_NAME}-as /usr/bin/as && - rm -f /usr/bin/ld && ln -sf /host/usr/bin/${TOOLCHAIN_NAME}-ld /usr/bin/ld && - rm -f /usr/bin/ld.bfd && ln -sf /host/usr/bin/${TOOLCHAIN_NAME}-ld.bfd /usr/bin/ld.bfd && - - # Link build tools - rm -f /usr/bin/ninja && ln -sf /host/usr/bin/ninja /usr/bin/ninja && - rm -f /usr/local/bin/ninja && mkdir -p /usr/local/bin && ln -sf /host/usr/bin/ninja /usr/local/bin/ninja && - - # Configure git for workspace access - git config --global --add safe.directory /workspace && - - # Install Python build dependencies - python -m pip install --upgrade pip && - python -m pip install meson>=1.3.2 meson-python wheel numpy && - python -m pip install pytest pytest-run-parallel pytest-timeout && - - # Install system dependencies for quaddtype (SLEEF dependencies) - apt install -y libssl-dev libfftw3-dev pkg-config - " - docker commit quaddtype_container quaddtype_container - mkdir -p "~/docker_${TOOLCHAIN_NAME}" - docker save -o "~/docker_${TOOLCHAIN_NAME}/quaddtype_container.tar" quaddtype_container + - name: Cache docker container + uses: actions/cache@v4 + id: container-cache + with: + path: ~/docker_${{ matrix.BUILD_PROP[1] }} + key: container-quaddtype-${{ runner.os }}-${{ matrix.BUILD_PROP[1] }}-${{ matrix.BUILD_PROP[2] }}-${{ hashFiles('quaddtype/pyproject.toml') }} - - name: Load container from cache - if: steps.container-cache.outputs.cache-hit == 'true' - run: docker load -i "~/docker_${TOOLCHAIN_NAME}/quaddtype_container.tar" - - - name: Build quaddtype with cross-compilation and testing - run: | - docker run --rm --platform=linux/${ARCH} -e "TERM=xterm-256color" \ - -v $(pwd):/workspace -v /:/host quaddtype_container \ - /bin/script -e -q -c "/bin/bash --noprofile --norc -eo pipefail -c ' - cd /workspace/quaddtype && - echo \"Building quaddtype for ${ARCH_NAME}...\" && + - name: Create cross-compilation container + if: steps.container-cache.outputs.cache-hit != 'true' + run: | + docker run --platform=linux/${ARCH} --name quaddtype_container --interactive \ + -v /:/host -v $(pwd):/workspace ${DOCKER_CONTAINER} /bin/bash -c " + # Update package manager and install essential tools + apt update && + apt install -y cmake git python3 python-is-python3 python3-dev python3-pip build-essential && + + # Create necessary symlinks for cross-compilation + mkdir -p /lib64 && ln -sf /host/lib64/ld-* /lib64/ || true && + ln -sf /host/lib/x86_64-linux-gnu /lib/x86_64-linux-gnu || true && + + # Link cross-compilation toolchain from host + rm -rf /usr/${TOOLCHAIN_NAME} && ln -sf /host/usr/${TOOLCHAIN_NAME} /usr/${TOOLCHAIN_NAME} && + rm -rf /usr/lib/gcc/${TOOLCHAIN_NAME} && ln -sf /host/usr/lib/gcc-cross/${TOOLCHAIN_NAME} /usr/lib/gcc/${TOOLCHAIN_NAME} && - # Set OpenMP linking for cross-compilation - export LDFLAGS=\"-fopenmp\" && + # Set up compiler symlinks + rm -f /usr/bin/gcc && ln -sf /host/usr/bin/${TOOLCHAIN_NAME}-gcc /usr/bin/gcc && + rm -f /usr/bin/g++ && ln -sf /host/usr/bin/${TOOLCHAIN_NAME}-g++ /usr/bin/g++ && + rm -f /usr/bin/gfortran && ln -sf /host/usr/bin/${TOOLCHAIN_NAME}-gfortran /usr/bin/gfortran && - # Install quaddtype with test dependencies - python -m pip install .[test] -v --no-build-isolation --force-reinstall + # Set up binutils + rm -f /usr/bin/ar && ln -sf /host/usr/bin/${TOOLCHAIN_NAME}-ar /usr/bin/ar && + rm -f /usr/bin/as && ln -sf /host/usr/bin/${TOOLCHAIN_NAME}-as /usr/bin/as && + rm -f /usr/bin/ld && ln -sf /host/usr/bin/${TOOLCHAIN_NAME}-ld /usr/bin/ld && + rm -f /usr/bin/ld.bfd && ln -sf /host/usr/bin/${TOOLCHAIN_NAME}-ld.bfd /usr/bin/ld.bfd && - cd .. - python -m pytest -vvv --color=yes --timeout=600 --tb=short quaddtype/tests/ - '" + # Link build tools + rm -f /usr/bin/ninja && ln -sf /host/usr/bin/ninja /usr/bin/ninja && + rm -f /usr/local/bin/ninja && mkdir -p /usr/local/bin && ln -sf /host/usr/bin/ninja /usr/local/bin/ninja && + + # Configure git for workspace access + git config --global --add safe.directory /workspace && + + # Install Python build dependencies + python -m pip install --upgrade pip && + python -m pip install meson>=1.3.2 meson-python wheel numpy && + python -m pip install pytest pytest-run-parallel pytest-timeout && + + # Install system dependencies for quaddtype (SLEEF dependencies) + apt install -y libssl-dev libfftw3-dev pkg-config + " + docker commit quaddtype_container quaddtype_container + mkdir -p "~/docker_${TOOLCHAIN_NAME}" + docker save -o "~/docker_${TOOLCHAIN_NAME}/quaddtype_container.tar" quaddtype_container + + - name: Load container from cache + if: steps.container-cache.outputs.cache-hit == 'true' + run: docker load -i "~/docker_${TOOLCHAIN_NAME}/quaddtype_container.tar" + + - name: Build quaddtype with cross-compilation and testing + run: | + docker run --rm --platform=linux/${ARCH} -e "TERM=xterm-256color" \ + -v $(pwd):/workspace -v /:/host quaddtype_container \ + /bin/script -e -q -c "/bin/bash --noprofile --norc -eo pipefail -c ' + cd /workspace/quaddtype && + echo \"Building quaddtype for ${ARCH_NAME}...\" && + + # Set OpenMP linking for cross-compilation + export LDFLAGS=\"-fopenmp\" && + + # Install quaddtype with test dependencies + python -m pip install .[test] -v --no-build-isolation --force-reinstall + + cd .. + python -m pytest -vvv --color=yes --timeout=600 --tb=short quaddtype/tests/ + '" diff --git a/quaddtype/numpy_quaddtype/src/quaddtype_main.c b/quaddtype/numpy_quaddtype/src/quaddtype_main.c index de945c6e..966c8bc0 100644 --- a/quaddtype/numpy_quaddtype/src/quaddtype_main.c +++ b/quaddtype/numpy_quaddtype/src/quaddtype_main.c @@ -31,32 +31,6 @@ py_is_longdouble_128(PyObject *self, PyObject *args) } } -#ifdef SLEEF_QUAD_C -static const Sleef_quad SMALLEST_SUBNORMAL_VALUE = SLEEF_QUAD_DENORM_MIN; -#else -static const union { - struct { - #if NPY_BYTE_ORDER == NPY_BIG_ENDIAN - uint64_t high; - uint64_t low; - #elif NPY_BYTE_ORDER == NPY_LITTLE_ENDIAN - uint64_t low; - uint64_t high; - #else - #error "Unknown endianness - NPY_BYTE_ORDER not properly defined" - #endif - } parts; - Sleef_quad value; -} smallest_subnormal_const = { - .parts = { - .low = 0x0000000000000001ULL, - .high = 0x0000000000000000ULL - } -}; - -#define SMALLEST_SUBNORMAL_VALUE (smallest_subnormal_const.value) -#endif - static PyObject * get_sleef_constant(PyObject *self, PyObject *args) { @@ -98,7 +72,11 @@ get_sleef_constant(PyObject *self, PyObject *args) result->value.sleef_value = SLEEF_QUAD_MIN; } else if (strcmp(constant_name, "smallest_subnormal") == 0) { - result->value.sleef_value = SMALLEST_SUBNORMAL_VALUE; + #ifdef SLEEF_QUAD_C + result->value.sleef_value = SLEEF_QUAD_DENORM_MIN; + #else + result->value.sleef_value = sleef_q(+0x0000000000000LL, 0x0000000000000001ULL, -16383); + #endif } else if (strcmp(constant_name, "bits") == 0) { Py_DECREF(result); From 96e60faecea8084b29afc40714037b6e8b7130bc Mon Sep 17 00:00:00 2001 From: SwayamInSync Date: Thu, 18 Sep 2025 17:59:33 +0000 Subject: [PATCH 15/22] lets verify macros are working or not --- quaddtype/numpy_quaddtype/src/quaddtype_main.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/quaddtype/numpy_quaddtype/src/quaddtype_main.c b/quaddtype/numpy_quaddtype/src/quaddtype_main.c index 966c8bc0..8ecaaa99 100644 --- a/quaddtype/numpy_quaddtype/src/quaddtype_main.c +++ b/quaddtype/numpy_quaddtype/src/quaddtype_main.c @@ -31,6 +31,12 @@ py_is_longdouble_128(PyObject *self, PyObject *args) } } +#if defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) +#warning "Big-endian platform detected" +#else +#warning "Little Endian" +#endif + static PyObject * get_sleef_constant(PyObject *self, PyObject *args) { From d777529e5bc4ed6d82c4df300e3116a4ff60f5c7 Mon Sep 17 00:00:00 2001 From: SwayamInSync Date: Thu, 18 Sep 2025 19:40:52 +0000 Subject: [PATCH 16/22] it was dragon4 all along --- quaddtype/numpy_quaddtype/src/dragon4.c | 5 ++++ .../numpy_quaddtype/src/quaddtype_main.c | 27 ++++++++++++++----- 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/quaddtype/numpy_quaddtype/src/dragon4.c b/quaddtype/numpy_quaddtype/src/dragon4.c index 8e96c0bc..58431411 100644 --- a/quaddtype/numpy_quaddtype/src/dragon4.c +++ b/quaddtype/numpy_quaddtype/src/dragon4.c @@ -1885,8 +1885,13 @@ Dragon4_PrintFloat_Sleef_quad(Sleef_quad *value, Dragon4_Options *opt) union { Sleef_quad q; struct { +#if defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) + npy_uint64 hi; + npy_uint64 lo; +#else npy_uint64 lo; npy_uint64 hi; +#endif } i; } u; u.q = *value; diff --git a/quaddtype/numpy_quaddtype/src/quaddtype_main.c b/quaddtype/numpy_quaddtype/src/quaddtype_main.c index 8ecaaa99..a46d121f 100644 --- a/quaddtype/numpy_quaddtype/src/quaddtype_main.c +++ b/quaddtype/numpy_quaddtype/src/quaddtype_main.c @@ -31,10 +31,26 @@ py_is_longdouble_128(PyObject *self, PyObject *args) } } +#ifdef SLEEF_QUAD_C +static const Sleef_quad SMALLEST_SUBNORMAL_VALUE = SLEEF_QUAD_DENORM_MIN; +#else +static const union { + struct { #if defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) -#warning "Big-endian platform detected" + uint64_t h, l; #else -#warning "Little Endian" + uint64_t l, h; +#endif + } parts; + Sleef_quad value; +} smallest_subnormal_const = {.parts = { +#if defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) + .h = 0x0000000000000000ULL, .l = 0x0000000000000001ULL +#else + .l = 0x0000000000000001ULL, .h = 0x0000000000000000ULL +#endif + }}; +#define SMALLEST_SUBNORMAL_VALUE (smallest_subnormal_const.value) #endif static PyObject * @@ -78,11 +94,8 @@ get_sleef_constant(PyObject *self, PyObject *args) result->value.sleef_value = SLEEF_QUAD_MIN; } else if (strcmp(constant_name, "smallest_subnormal") == 0) { - #ifdef SLEEF_QUAD_C - result->value.sleef_value = SLEEF_QUAD_DENORM_MIN; - #else - result->value.sleef_value = sleef_q(+0x0000000000000LL, 0x0000000000000001ULL, -16383); - #endif + // or just use sleef_q(+0x0000000000000LL, 0x0000000000000001ULL, -16383); + result->value.sleef_value = SMALLEST_SUBNORMAL_VALUE; } else if (strcmp(constant_name, "bits") == 0) { Py_DECREF(result); From 2d428064cfb1c4084f5037ff6bf1974bd3809fa1 Mon Sep 17 00:00:00 2001 From: SwayamInSync Date: Thu, 18 Sep 2025 19:42:40 +0000 Subject: [PATCH 17/22] win fix --- quaddtype/numpy_quaddtype/src/quaddtype_main.c | 1 - 1 file changed, 1 deletion(-) diff --git a/quaddtype/numpy_quaddtype/src/quaddtype_main.c b/quaddtype/numpy_quaddtype/src/quaddtype_main.c index a46d121f..b8c2bc42 100644 --- a/quaddtype/numpy_quaddtype/src/quaddtype_main.c +++ b/quaddtype/numpy_quaddtype/src/quaddtype_main.c @@ -11,7 +11,6 @@ #include "numpy/arrayobject.h" #include "numpy/dtype_api.h" #include "numpy/ufuncobject.h" -#include "numpy/npy_endian.h" #include "scalar.h" #include "dtype.h" From c760b8879e1b1646a777058b537a5962816f7741 Mon Sep 17 00:00:00 2001 From: jorenham Date: Thu, 18 Sep 2025 10:14:20 +0200 Subject: [PATCH 18/22] BLD: update ``numpy_quaddtype`` licensing metadata to use PEP 639 --- quaddtype/pyproject.toml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/quaddtype/pyproject.toml b/quaddtype/pyproject.toml index 39341833..f1e81464 100644 --- a/quaddtype/pyproject.toml +++ b/quaddtype/pyproject.toml @@ -1,7 +1,7 @@ [build-system] requires = [ "meson>=1.3.2", - "meson-python", + "meson-python>=0.18.0", "wheel", "numpy" ] @@ -12,7 +12,8 @@ name = "numpy_quaddtype" description = "Quad (128-bit) float dtype for numpy" version = "0.2.0" readme = 'README.md' -license = { file = "LICENSE" } +license = "BSD-3-Clause" +license-files = ["LICENSE"] authors = [{name = "Swayam Singh", email = "singhswayam008@gmail.com"}] requires-python = ">=3.10.0" dependencies = [ From de87cb00940ecc06d767c893f29ef1309a4bd096 Mon Sep 17 00:00:00 2001 From: jorenham Date: Thu, 18 Sep 2025 10:16:39 +0200 Subject: [PATCH 19/22] BLD: Trove classifiers for ``numpy_quaddtype`` --- quaddtype/pyproject.toml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/quaddtype/pyproject.toml b/quaddtype/pyproject.toml index f1e81464..385be28a 100644 --- a/quaddtype/pyproject.toml +++ b/quaddtype/pyproject.toml @@ -15,6 +15,16 @@ readme = 'README.md' license = "BSD-3-Clause" license-files = ["LICENSE"] authors = [{name = "Swayam Singh", email = "singhswayam008@gmail.com"}] +classifiers = [ + "Development Status :: 4 - Beta", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", + "Programming Language :: Python :: 3.14", + "Typing :: Typed", +] requires-python = ">=3.10.0" dependencies = [ "numpy" From 0455be2e8595f32e667f6eccf4feb8b131f430e7 Mon Sep 17 00:00:00 2001 From: jorenham Date: Thu, 18 Sep 2025 10:20:56 +0200 Subject: [PATCH 20/22] BLD: add urls to the project metadata of ``numpy_quaddtype`` --- quaddtype/pyproject.toml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/quaddtype/pyproject.toml b/quaddtype/pyproject.toml index 385be28a..fcc93bb2 100644 --- a/quaddtype/pyproject.toml +++ b/quaddtype/pyproject.toml @@ -36,6 +36,11 @@ test = [ "pytest-run-parallel" ] +[project.urls] +Repository = "https://github.com/numpy/numpy-user-dtypes" +Documentation = "https://github.com/numpy/numpy-user-dtypes/tree/main/quaddtype" +Issues = "https://github.com/numpy/numpy-user-dtypes/issues" + [tool.pyright] include = ["numpy_quaddtype/*.pyi"] typeCheckingMode = "strict" From 4f4b86ff60a9ecfda769dccfc3a6d28ea285c00c Mon Sep 17 00:00:00 2001 From: jorenham Date: Thu, 18 Sep 2025 21:58:20 +0200 Subject: [PATCH 21/22] BLD: Add free threading trove classifier Co-authored-by: Swayam <74960567+SwayamInSync@users.noreply.github.com> --- quaddtype/pyproject.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/quaddtype/pyproject.toml b/quaddtype/pyproject.toml index fcc93bb2..dc9f777a 100644 --- a/quaddtype/pyproject.toml +++ b/quaddtype/pyproject.toml @@ -23,6 +23,7 @@ classifiers = [ "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", "Programming Language :: Python :: 3.14", + "Programming Language :: Python :: Free Threading", "Typing :: Typed", ] requires-python = ">=3.10.0" From 6e0d708b8f17287e584831a927c4ce580375f194 Mon Sep 17 00:00:00 2001 From: mattip Date: Sun, 28 Sep 2025 19:05:55 +0300 Subject: [PATCH 22/22] remove macros that override NumPy macros --- quaddtype/numpy_quaddtype/src/casts.cpp | 2 +- quaddtype/numpy_quaddtype/src/dragon4.c | 6 +++--- quaddtype/numpy_quaddtype/src/scalar.h | 5 +---- 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/quaddtype/numpy_quaddtype/src/casts.cpp b/quaddtype/numpy_quaddtype/src/casts.cpp index bfd42966..3e25eaa7 100644 --- a/quaddtype/numpy_quaddtype/src/casts.cpp +++ b/quaddtype/numpy_quaddtype/src/casts.cpp @@ -904,4 +904,4 @@ free_casts(void) } } spec_count = 0; -} \ No newline at end of file +} diff --git a/quaddtype/numpy_quaddtype/src/dragon4.c b/quaddtype/numpy_quaddtype/src/dragon4.c index 58431411..dac8fa0b 100644 --- a/quaddtype/numpy_quaddtype/src/dragon4.c +++ b/quaddtype/numpy_quaddtype/src/dragon4.c @@ -2007,7 +2007,7 @@ Dragon4_Positional(PyObject *obj, DigitMode digit_mode, CutoffMode cutoff_mode, { npy_double v; - if (PyArray_IsScalar(obj, QuadPrecDType)) { + if (PyObject_TypeCheck(obj, &QuadPrecision_Type)) { QuadPrecisionObject *quad_obj = (QuadPrecisionObject *)obj; if (quad_obj->backend == BACKEND_SLEEF) { return Dragon4_Positional_QuadDType(&quad_obj->value.sleef_value, digit_mode, @@ -2030,7 +2030,7 @@ Dragon4_Scientific(PyObject *obj, DigitMode digit_mode, int precision, int min_d { npy_double val; - if (PyArray_IsScalar(obj, QuadPrecDType)) { + if (PyObject_TypeCheck(obj, &QuadPrecision_Type)) { QuadPrecisionObject *quad_obj = (QuadPrecisionObject *)obj; if (quad_obj->backend == BACKEND_SLEEF) { return Dragon4_Scientific_QuadDType(&quad_obj->value.sleef_value, digit_mode, precision, @@ -2044,4 +2044,4 @@ Dragon4_Scientific(PyObject *obj, DigitMode digit_mode, int precision, int min_d } return NULL; -} \ No newline at end of file +} diff --git a/quaddtype/numpy_quaddtype/src/scalar.h b/quaddtype/numpy_quaddtype/src/scalar.h index 4fac1adf..7499b1ad 100644 --- a/quaddtype/numpy_quaddtype/src/scalar.h +++ b/quaddtype/numpy_quaddtype/src/scalar.h @@ -31,11 +31,8 @@ QuadPrecision_from_object(PyObject *value, QuadBackendType backend); int init_quadprecision_scalar(void); -#define PyArray_IsScalar(obj, QuadPrecDType) PyObject_TypeCheck(obj, &QuadPrecision_Type) -#define PyArrayScalar_VAL(obj, QuadPrecDType) (((QuadPrecisionObject *)obj)->value) - #ifdef __cplusplus } #endif -#endif \ No newline at end of file +#endif