Skip to content
Open
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
22 changes: 19 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,27 @@ on:
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
numpy-version: ['2.3.2', 'nightly']

steps:
- uses: actions/checkout@v3
- name: Setup Python
uses: actions/setup-python@v3
with:
python-version: "3.10"
python-version: "3.11"
- name: Install build and test dependencies
run: |
python -m pip install -U pip build pytest unyt wheel meson ninja meson-python patchelf pandas numpy
python -m pip install -U pip build pytest unyt wheel meson ninja meson-python patchelf pandas
- name: Install numpy nightly
if: matrix.numpy-version == 'nightly'
run: |
pip install --pre --upgrade --timeout=60 -i https://pypi.anaconda.org/scientific-python-nightly-wheels/simple numpy
- name: Install numpy from PyPI
if: matrix.numpy-version != 'nightly'
run: |
pip install "numpy==${{ matrix.numpy-version }}"
- name: Install asciidtype
working-directory: asciidtype
run: |
Expand Down Expand Up @@ -63,8 +74,13 @@ jobs:
- name: Install quaddtype
working-directory: quaddtype
run: |
if [ "${{ matrix.numpy-version }}" == "nightly" ]; then
# obscure errors when using command line 2_4 if numpy does not define it
python -c "import numpy as np; assert np.__version__ >= '2.4'"
extra_args="-Csetup-args=-Dcpp_args=-DNPY_TARGET_VERSION=NPY_2_4_API_VERSION --no-build-isolation"
fi
export LDFLAGS="-fopenmp"
python -m pip install . -v
python -m pip install $extra_args . -v

- name: Run quaddtype tests
working-directory: quaddtype
Expand Down
99 changes: 92 additions & 7 deletions quaddtype/numpy_quaddtype/src/casts.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
#define PY_ARRAY_UNIQUE_SYMBOL QuadPrecType_ARRAY_API
#define PY_UFUNC_UNIQUE_SYMBOL QuadPrecType_UFUNC_API
#define NPY_NO_DEPRECATED_API NPY_2_0_API_VERSION
#define NPY_TARGET_VERSION NPY_2_0_API_VERSION
#ifndef NPY_TARGET_VERSION
#define NPY_TARGET_VERSION NPY_2_0_API_VERSION
#endif
#define NO_IMPORT_ARRAY
#define NO_IMPORT_UFUNC

Expand All @@ -21,6 +23,11 @@ extern "C" {
#include "casts.h"
#include "dtype.h"

#if NPY_FEATURE_VERSION < NPY_2_0_API_VERSION
#warning "Is NPY_TARGET_VERSION set too high for this numpy installation?"
#error "NPY_FEATURE_VERSION too low, must be > NPY_2_0_API_VERSION"
#endif

#define NUM_CASTS 34 // 16 to_casts + 16 from_casts + 1 quad_to_quad + 1 void_to_quad

static NPY_CASTING
Expand Down Expand Up @@ -157,7 +164,7 @@ void_to_quad_resolve_descriptors(PyObject *NPY_UNUSED(self), PyArray_DTypeMeta *
PyArray_Descr *given_descrs[2], PyArray_Descr *loop_descrs[2],
npy_intp *view_offset)
{
PyErr_SetString(PyExc_TypeError,
PyErr_SetString(PyExc_TypeError,
"Void to QuadPrecision cast is not implemented");
return (NPY_CASTING)-1;
}
Expand Down Expand Up @@ -401,7 +408,7 @@ to_quad<long double>(long double x, QuadBackendType backend)
}

template <typename T>
static NPY_CASTING
static int
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm... I think this is OK? I didn't see any new warnings, but there are thousands of build warnings when using sleef and I might have missed it.

numpy_to_quad_resolve_descriptors(PyObject *NPY_UNUSED(self), PyArray_DTypeMeta *dtypes[2],
PyArray_Descr *given_descrs[2], PyArray_Descr *loop_descrs[2],
npy_intp *view_offset)
Expand All @@ -419,7 +426,11 @@ numpy_to_quad_resolve_descriptors(PyObject *NPY_UNUSED(self), PyArray_DTypeMeta
}

loop_descrs[0] = PyArray_GetDefaultDescr(dtypes[0]);
#if defined(NPY_2_3_API_VERSION) && (NPY_TARGET_VERSION > NPY_2_3_API_VERSION)
return NPY_SAFE_CASTING | NPY_SAME_VALUE_CASTING_FLAG;
#else
return NPY_SAFE_CASTING;
#endif
}

template <typename T>
Expand Down Expand Up @@ -667,6 +678,27 @@ from_quad<long double>(quad_value x, QuadBackendType backend)
}

template <typename T>
static inline int
from_quad_checked(quad_value x, QuadBackendType backend, typename NpyType<T>::TYPE *ret) {
*ret = from_quad<typename NpyType<T>::TYPE>(x, backend);
quad_value check = to_quad<typename NpyType<T>::TYPE>(*ret, backend);
if (backend == BACKEND_SLEEF) {
if (check.sleef_value == x.sleef_value) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we just compare sleef values here? Should this use equality with NaN = NaN?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we just compare sleef values here?

I was following the pattern from elsewhere. Is it guaranteed that the sleef backend is used?

Should this use equality with NaN = NaN?

Good point!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the SLEEF branch, I was thinking of Sleef_icmpeqq1(a, b) | (Sleef_iunordq1(a, a) & Sleef_iunordq1(b, b))

return 0;
}
}
else {
if (check.longdouble_value == x.longdouble_value) {
return 0;
}
}
NPY_ALLOW_C_API_DEF;
NPY_ALLOW_C_API;
PyErr_SetString(PyExc_ValueError, "could not cast 'same_value' to QuadType");
NPY_DISABLE_C_API;
return -1;
}

static NPY_CASTING
quad_to_numpy_resolve_descriptors(PyObject *NPY_UNUSED(self), PyArray_DTypeMeta *dtypes[2],
PyArray_Descr *given_descrs[2], PyArray_Descr *loop_descrs[2],
Expand Down Expand Up @@ -694,6 +726,28 @@ quad_to_numpy_strided_loop_unaligned(PyArrayMethod_Context *context, char *const

size_t elem_size = (backend == BACKEND_SLEEF) ? sizeof(Sleef_quad) : sizeof(long double);

#if defined(NPY_2_3_API_VERSION) && (NPY_TARGET_VERSION > NPY_2_3_API_VERSION)
int same_value_casting = 0;
if (PyArray_GetNDArrayCFeatureVersion() > NPY_2_3_API_VERSION) {
same_value_casting = ((context->flags & NPY_SAME_VALUE_CONTEXT_FLAG) == NPY_SAME_VALUE_CONTEXT_FLAG);
}
if (same_value_casting) {
while (N--) {
quad_value in_val;
memcpy(&in_val, in_ptr, elem_size);
typename NpyType<T>::TYPE out_val;
if (from_quad_checked<T>(in_val, backend, &out_val) < 0) {
return -1;
}
memcpy(out_ptr, &out_val, sizeof(typename NpyType<T>::TYPE));

in_ptr += strides[0];
out_ptr += strides[1];
}
} else {
#else
{
#endif
while (N--) {
quad_value in_val;
memcpy(&in_val, in_ptr, elem_size);
Expand All @@ -703,7 +757,7 @@ quad_to_numpy_strided_loop_unaligned(PyArrayMethod_Context *context, char *const

in_ptr += strides[0];
out_ptr += strides[1];
}
}}
return 0;
}

Expand All @@ -720,6 +774,33 @@ quad_to_numpy_strided_loop_aligned(PyArrayMethod_Context *context, char *const d
QuadPrecDTypeObject *quad_descr = (QuadPrecDTypeObject *)context->descriptors[0];
QuadBackendType backend = quad_descr->backend;

#if defined(NPY_2_3_API_VERSION) && (NPY_TARGET_VERSION > NPY_2_3_API_VERSION)
int same_value_casting = 0;
if (PyArray_GetNDArrayCFeatureVersion() > NPY_2_3_API_VERSION) {
same_value_casting = ((context->flags & NPY_SAME_VALUE_CONTEXT_FLAG) == NPY_SAME_VALUE_CONTEXT_FLAG);
}
if (same_value_casting) {
while (N--) {
quad_value in_val;
if (backend == BACKEND_SLEEF) {
in_val.sleef_value = *(Sleef_quad *)in_ptr;
}
else {
in_val.longdouble_value = *(long double *)in_ptr;
}

typename NpyType<T>::TYPE out_val;
if (from_quad_checked<T>(in_val, backend, &out_val) < 0) {
return -1;
}
*(typename NpyType<T>::TYPE *)(out_ptr) = out_val;

in_ptr += strides[0];
out_ptr += strides[1];
}} else {
#else
{
#endif
while (N--) {
quad_value in_val;
if (backend == BACKEND_SLEEF) {
Expand All @@ -734,7 +815,7 @@ quad_to_numpy_strided_loop_aligned(PyArrayMethod_Context *context, char *const d

in_ptr += strides[0];
out_ptr += strides[1];
}
}}
return 0;
}

Expand Down Expand Up @@ -762,7 +843,7 @@ add_cast_from(PyArray_DTypeMeta *to)
PyArray_DTypeMeta **dtypes = new PyArray_DTypeMeta *[2]{&QuadPrecDType, to};

PyType_Slot *slots = new PyType_Slot[]{
{NPY_METH_resolve_descriptors, (void *)&quad_to_numpy_resolve_descriptors<T>},
{NPY_METH_resolve_descriptors, (void *)&quad_to_numpy_resolve_descriptors},
{NPY_METH_strided_loop, (void *)&quad_to_numpy_strided_loop_aligned<T>},
{NPY_METH_unaligned_strided_loop, (void *)&quad_to_numpy_strided_loop_unaligned<T>},
{0, nullptr}};
Expand All @@ -771,7 +852,11 @@ add_cast_from(PyArray_DTypeMeta *to)
.name = "cast_QuadPrec_to_NumPy",
.nin = 1,
.nout = 1,
#if defined(NPY_2_3_API_VERSION) && (NPY_TARGET_VERSION > NPY_2_3_API_VERSION)
.casting = NPY_SAME_VALUE_CASTING,
#else
.casting = NPY_UNSAFE_CASTING,
#endif
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not clear how this is used, doesn't the resolver actually state which casting is supported?

.flags = NPY_METH_SUPPORTS_UNALIGNED,
.dtypes = dtypes,
.slots = slots,
Expand Down Expand Up @@ -904,4 +989,4 @@ free_casts(void)
}
}
spec_count = 0;
}
}
25 changes: 17 additions & 8 deletions quaddtype/numpy_quaddtype/src/dragon4.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,16 @@ This code was extracted from NumPy and the original author was Allan Haldane(@ah
Modifications are specific to support the SLEEF_QUAD
*/

#define PY_ARRAY_UNIQUE_SYMBOL QuadPrecType_ARRAY_API
#define PY_UFUNC_UNIQUE_SYMBOL QuadPrecType_UFUNC_API
#define NPY_NO_DEPRECATED_API NPY_2_0_API_VERSION
#ifndef NPY_TARGET_VERSION
#define NPY_TARGET_VERSION NPY_2_0_API_VERSION
#endif
#define NO_IMPORT_ARRAY
#define NO_IMPORT_UFUNC


#include <numpy/npy_common.h>
#include <math.h>
#include <stdio.h>
Expand All @@ -14,17 +24,16 @@ Modifications are specific to support the SLEEF_QUAD
#include "quaddtype_config.h"


#define PY_ARRAY_UNIQUE_SYMBOL QuadPrecType_ARRAY_API
#define PY_UFUNC_UNIQUE_SYMBOL QuadPrecType_UFUNC_API
#define NPY_NO_DEPRECATED_API NPY_2_0_API_VERSION
#define NPY_TARGET_VERSION NPY_2_0_API_VERSION
#define NO_IMPORT_ARRAY
#define NO_IMPORT_UFUNC

#include "dragon4.h"
#include "dtype.h"
#include "scalar.h"

#if NPY_FEATURE_VERSION < NPY_2_0_API_VERSION
#warning "Is NPY_TARGET_VERSION set too high for this numpy installation?"
#warning "NPY_FEATURE_VERSION is NPY_TOSTRING(NPY_FEATURE_VERSION)"
#error "NPY_FEATURE_VERSION too low, must be > NPY_2_0_API_VERSION"
#endif


#ifdef __cplusplus
#define NPY_TLS thread_local
Expand Down Expand Up @@ -2044,4 +2053,4 @@ Dragon4_Scientific(PyObject *obj, DigitMode digit_mode, int precision, int min_d
}

return NULL;
}
}
11 changes: 9 additions & 2 deletions quaddtype/numpy_quaddtype/src/dtype.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
#define PY_ARRAY_UNIQUE_SYMBOL QuadPrecType_ARRAY_API
#define PY_UFUNC_UNIQUE_SYMBOL QuadPrecType_UFUNC_API
#define NPY_NO_DEPRECATED_API NPY_2_0_API_VERSION
#define NPY_TARGET_VERSION NPY_2_0_API_VERSION
#ifndef NPY_TARGET_VERSION
#define NPY_TARGET_VERSION NPY_2_0_API_VERSION
#endif
#define NO_IMPORT_ARRAY
#define NO_IMPORT_UFUNC
#include "numpy/arrayobject.h"
Expand All @@ -17,6 +19,11 @@
#include "dtype.h"
#include "dragon4.h"

#if NPY_FEATURE_VERSION < NPY_2_0_API_VERSION
#warning "Is NPY_TARGET_VERSION set too high for this numpy installation?"
#error "NPY_FEATURE_VERSION too low, must be > NPY_2_0_API_VERSION"
#endif

static inline int
quad_load(void *x, char *data_ptr, QuadBackendType backend)
{
Expand Down Expand Up @@ -263,4 +270,4 @@ init_quadprec_dtype(void)
free_casts();

return 0;
}
}
4 changes: 2 additions & 2 deletions quaddtype/numpy_quaddtype/src/quadblas_interface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
#include <algorithm>

#ifndef DISABLE_QUADBLAS
#include "../subprojects/qblas/include/quadblas/quadblas.hpp"
#include "quadblas/quadblas.hpp"
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I needed this to build with -e, i.e. pip install -Csetup-args="-Dbuildtype=debug" -e . --no-build-isolation 2>&1 | tee /tmp/build.txt. Otherwise the build failed.

#endif // DISABLE_QUADBLAS

extern "C" {
Expand Down Expand Up @@ -230,4 +230,4 @@ _quadblas_get_num_threads(void)

#endif // DISABLE_QUADBLAS

} // extern "C"
} // extern "C"
12 changes: 9 additions & 3 deletions quaddtype/numpy_quaddtype/src/quaddtype_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@
#define PY_ARRAY_UNIQUE_SYMBOL QuadPrecType_ARRAY_API
#define PY_UFUNC_UNIQUE_SYMBOL QuadPrecType_UFUNC_API
#define NPY_NO_DEPRECATED_API NPY_2_0_API_VERSION
#define NPY_TARGET_VERSION NPY_2_0_API_VERSION

#ifndef NPY_TARGET_VERSION
#define NPY_TARGET_VERSION NPY_2_0_API_VERSION
#endif
#include "numpy/arrayobject.h"
#include "numpy/dtype_api.h"
#include "numpy/ufuncobject.h"
Expand All @@ -19,6 +20,11 @@
#include "quadblas_interface.h"
#include "float.h"

#if NPY_FEATURE_VERSION < NPY_2_0_API_VERSION
#warning "Is NPY_TARGET_VERSION set too high for this numpy installation?"
#error "NPY_FEATURE_VERSION too low, must be > NPY_2_0_API_VERSION"
#endif

static PyObject *
py_is_longdouble_128(PyObject *self, PyObject *args)
{
Expand Down Expand Up @@ -177,4 +183,4 @@ PyInit__quaddtype_main(void)
error:
Py_XDECREF(m);
return NULL;
}
}
11 changes: 9 additions & 2 deletions quaddtype/numpy_quaddtype/src/scalar_ops.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#define PY_ARRAY_UNIQUE_SYMBOL QuadPrecType_ARRAY_API
#define NPY_NO_DEPRECATED_API NPY_2_0_API_VERSION
#define NPY_TARGET_VERSION NPY_2_0_API_VERSION
#ifndef NPY_TARGET_VERSION
#define NPY_TARGET_VERSION NPY_2_0_API_VERSION
#endif
#define NO_IMPORT_ARRAY

extern "C" {
Expand All @@ -18,6 +20,11 @@ extern "C" {
#include "scalar_ops.h"
#include "quad_common.h"

#if NPY_FEATURE_VERSION < NPY_2_0_API_VERSION
#warning "Is NPY_TARGET_VERSION set too high for this numpy installation?"
#error "NPY_FEATURE_VERSION too low, must be > NPY_2_0_API_VERSION"
#endif

template <unary_op_quad_def sleef_op, unary_op_longdouble_def longdouble_op>
static PyObject *
quad_unary_func(QuadPrecisionObject *self)
Expand Down Expand Up @@ -240,4 +247,4 @@ PyNumberMethods quad_as_scalar = {
.nb_int = (unaryfunc)QuadPrecision_int,
.nb_float = (unaryfunc)QuadPrecision_float,
.nb_true_divide = (binaryfunc)quad_binary_func<quad_div, ld_div>,
};
};
Loading
Loading