Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
146 changes: 146 additions & 0 deletions .github/workflows/big_endian.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
# 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:
pull_request:
branches:
- main
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:
big_endian_tests:
runs-on: ubuntu-22.04
continue-on-error: true
strategy:
fail-fast: false
matrix:
BUILD_PROP:
- [
"s390x (IBM Z Big Endian)",
"s390x-linux-gnu",
"s390x/ubuntu:22.04",
"s390x"
]
- [
"s390x - baseline(Z13)",
"s390x-linux-gnu",
"s390x/ubuntu:22.04",
"s390x"
]
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
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

- 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: 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: 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: 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/
'"
30 changes: 17 additions & 13 deletions quaddtype/numpy_quaddtype/src/quaddtype_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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

Expand Down
Loading