Skip to content

Commit 7d8c3a5

Browse files
authored
Merge pull request #240 from SwayamInSync/sleef-migration
2 parents ca1cfb6 + fda5ce2 commit 7d8c3a5

File tree

15 files changed

+261
-128
lines changed

15 files changed

+261
-128
lines changed

.github/workflows/big_endian.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ permissions:
2222

2323
jobs:
2424
big_endian_tests:
25-
runs-on: ubuntu-22.04
25+
runs-on: ubuntu-24.04
2626
continue-on-error: true
2727
strategy:
2828
fail-fast: false

.github/workflows/typecheck.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ jobs:
2525
- uses: astral-sh/[email protected]
2626
with:
2727
activate-environment: true
28-
python-version: "3.11"
28+
python-version: "3.12"
2929

3030
- name: install
3131
working-directory: quaddtype

quaddtype/meson.build

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,9 @@ if sleef_dep.found() and sleef_dep.type_name() != 'internal'
2525
# SLEEF found system-wide - verify quad-precision support
2626
cpp = meson.get_compiler('cpp')
2727
sleefquad_lib = cpp.find_library('sleefquad', required: false)
28+
tlfloat_lib = cpp.find_library('tlfloat', required: false)
2829

29-
if sleefquad_lib.found()
30+
if sleefquad_lib.found() and tlfloat_lib.found()
3031
sleefquad_test_code = '''
3132
#include <sleefquad.h>
3233
@@ -40,14 +41,17 @@ if sleef_dep.found() and sleef_dep.type_name() != 'internal'
4041
# this should compile and link
4142
quad_works = cpp.links(
4243
sleefquad_test_code,
43-
dependencies: [sleef_dep, sleefquad_lib],
44+
dependencies: [sleef_dep, sleefquad_lib, tlfloat_lib],
4445
name: 'SLEEF quad-precision support'
4546
)
4647

4748
if quad_works
4849
sleefquad_dep = declare_dependency(
4950
dependencies: [sleef_dep, sleefquad_lib]
5051
)
52+
tlfloat_dep = declare_dependency(
53+
dependencies: [tlfloat_lib]
54+
)
5155
use_system_sleef = true
5256
else
5357
fallback_reason = 'System-wide SLEEF installation found but a test for quad precision support failed.'
@@ -65,6 +69,7 @@ else
6569
sleef_subproj = subproject('sleef')
6670
sleef_dep = sleef_subproj.get_variable('sleef_dep')
6771
sleefquad_dep = sleef_subproj.get_variable('sleefquad_dep')
72+
tlfloat_dep = sleef_subproj.get_variable('tlfloat_dep')
6873
warning(fallback_reason)
6974
message('Proceeding with vendored SLEEF subproject instead')
7075
endif
@@ -84,7 +89,7 @@ message('Using NumPy version: @0@'.format(numpy_version))
8489
npymath_path = incdir_numpy / '..' / 'lib'
8590
npymath_lib = c.find_library('npymath', dirs: npymath_path)
8691

87-
dependencies = [py_dep, qblas_dep, sleef_dep, sleefquad_dep, npymath_lib]
92+
dependencies = [py_dep, qblas_dep, sleef_dep, sleefquad_dep, tlfloat_dep, npymath_lib]
8893

8994
# Add OpenMP dependency (optional, for threading)
9095
openmp_dep = dependency('openmp', required: false, static: false)
@@ -99,6 +104,11 @@ if not is_windows
99104
if cpp.has_argument('-fext-numeric-literals')
100105
add_project_arguments('-fext-numeric-literals', language: 'cpp')
101106
endif
107+
108+
# Suppress warnings from system headers (sleefquad.h has many unused inline functions)
109+
if cpp.has_argument('-Wno-unused-function')
110+
add_project_arguments('-Wno-unused-function', language: ['c', 'cpp'])
111+
endif
102112
endif
103113

104114
# Thread-local storage detection (borrowed from NumPy)

quaddtype/numpy_quaddtype/_quaddtype_main.pyi

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ class QuadPrecision(np.floating[_128Bit]):
129129
@override
130130
def __add__(self, other: _IntoQuad, /) -> Self: ... # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride]
131131
@override
132-
def __radd__(self, other: _IntoQuad, /) -> Self: ... # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride]
132+
def __radd__(self, other: _IntoQuad, /) -> Self: ... # type: ignore[override, misc] # pyright: ignore[reportIncompatibleMethodOverride]
133133
@override
134134
def __sub__(self, other: _IntoQuad, /) -> Self: ... # type: ignore[override] # pyright: ignore[reportIncompatibleMethodOverride]
135135
@override

quaddtype/numpy_quaddtype/src/dragon4.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,11 @@ Modifications are specific to support the SLEEF_QUAD
2626
#include "scalar.h"
2727

2828

29+
// Undefine NPY_TLS if already defined (avoid redefinition warning)
30+
#ifdef NPY_TLS
31+
#undef NPY_TLS
32+
#endif
33+
2934
#ifdef __cplusplus
3035
#define NPY_TLS thread_local
3136
#elif defined(HAVE_THREAD_LOCAL)
@@ -2005,8 +2010,6 @@ PyObject *
20052010
Dragon4_Positional(PyObject *obj, DigitMode digit_mode, CutoffMode cutoff_mode, int precision,
20062011
int min_digits, int sign, TrimMode trim, int pad_left, int pad_right)
20072012
{
2008-
npy_double v;
2009-
20102013
if (PyObject_TypeCheck(obj, &QuadPrecision_Type)) {
20112014
QuadPrecisionObject *quad_obj = (QuadPrecisionObject *)obj;
20122015
if (quad_obj->backend == BACKEND_SLEEF) {
@@ -2028,8 +2031,6 @@ PyObject *
20282031
Dragon4_Scientific(PyObject *obj, DigitMode digit_mode, int precision, int min_digits, int sign,
20292032
TrimMode trim, int pad_left, int exp_digits)
20302033
{
2031-
npy_double val;
2032-
20332034
if (PyObject_TypeCheck(obj, &QuadPrecision_Type)) {
20342035
QuadPrecisionObject *quad_obj = (QuadPrecisionObject *)obj;
20352036
if (quad_obj->backend == BACKEND_SLEEF) {

quaddtype/numpy_quaddtype/src/dtype.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -354,11 +354,11 @@ quadprec_scanfunc(FILE *fp, void *dptr, char *ignore, PyArray_Descr *descr_gener
354354
}
355355
buffer[i] = '\0';
356356

357-
/* Convert string to quad precision */
357+
/* Convert string to quad precision (supports inf/nan) */
358358
char *endptr;
359359
quad_value val;
360-
int err = cstring_to_quad(buffer, descr->backend, &val, &endptr, true);
361-
if (err < 0) {
360+
int err = NumPyOS_ascii_strtoq(buffer, descr->backend, &val, &endptr);
361+
if (err < 0 || *endptr != '\0') {
362362
return 0; /* Return 0 on parse error (no items read) */
363363
}
364364
if (descr->backend == BACKEND_SLEEF) {
@@ -376,7 +376,7 @@ quadprec_fromstr(char *s, void *dptr, char **endptr, PyArray_Descr *descr_generi
376376
{
377377
QuadPrecDTypeObject *descr = (QuadPrecDTypeObject *)descr_generic;
378378
quad_value val;
379-
int err = cstring_to_quad(s, descr->backend, &val, endptr, false);
379+
int err = NumPyOS_ascii_strtoq(s, descr->backend, &val, endptr);
380380
if (err < 0) {
381381
return -1;
382382
}

quaddtype/numpy_quaddtype/src/ops.hpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,13 @@ typedef Sleef_quad (*unary_op_quad_def)(const Sleef_quad *);
1313
// Unary Quad operations with 2 outputs (for modf, frexp)
1414
typedef void (*unary_op_2out_quad_def)(const Sleef_quad *, Sleef_quad *, Sleef_quad *);
1515

16-
static Sleef_quad
16+
static inline Sleef_quad
1717
quad_negative(const Sleef_quad *op)
1818
{
1919
return Sleef_negq1(*op);
2020
}
2121

22-
static Sleef_quad
22+
static inline Sleef_quad
2323
quad_positive(const Sleef_quad *op)
2424
{
2525
return *op;
@@ -929,15 +929,15 @@ static inline Sleef_quad quad_set_words64(int64_t hx, uint64_t lx)
929929
static inline Sleef_quad
930930
quad_nextafter(const Sleef_quad *x, const Sleef_quad *y)
931931
{
932-
int64_t hx, hy, ix, iy;
932+
int64_t hx, hy, ix;
933933
uint64_t lx, ly;
934934

935935
quad_get_words64(&hx, &lx, *x);
936936
quad_get_words64(&hy, &ly, *y);
937937

938938
// extracting absolute value
939939
ix = hx & 0x7fffffffffffffffLL;
940-
iy = hy & 0x7fffffffffffffffLL;
940+
(void)ly; // unused but needed for quad_get_words64
941941

942942
// NaN if either is NaN
943943
if (Sleef_iunordq1(*x, *y)) {

quaddtype/numpy_quaddtype/src/scalar.c

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -191,12 +191,21 @@ QuadPrecision_from_object(PyObject *value, QuadBackendType backend)
191191
else if (PyUnicode_Check(value)) {
192192
const char *s = PyUnicode_AsUTF8(value);
193193
char *endptr = NULL;
194-
int err = cstring_to_quad(s, backend, &self->value, &endptr, true);
194+
int err = NumPyOS_ascii_strtoq(s, backend, &self->value, &endptr);
195195
if (err < 0) {
196196
PyErr_SetString(PyExc_ValueError, "Unable to parse string to QuadPrecision");
197197
Py_DECREF(self);
198198
return NULL;
199199
}
200+
// Skip trailing whitespace (matches Python's float() behavior)
201+
while (ascii_isspace(*endptr)) {
202+
endptr++;
203+
}
204+
if (*endptr != '\0') {
205+
PyErr_SetString(PyExc_ValueError, "Unable to parse string to QuadPrecision");
206+
Py_DECREF(self);
207+
return NULL;
208+
}
200209
}
201210
else if (PyBytes_Check(value)) {
202211
const char *s = PyBytes_AsString(value);
@@ -205,12 +214,21 @@ QuadPrecision_from_object(PyObject *value, QuadBackendType backend)
205214
return NULL;
206215
}
207216
char *endptr = NULL;
208-
int err = cstring_to_quad(s, backend, &self->value, &endptr, true);
217+
int err = NumPyOS_ascii_strtoq(s, backend, &self->value, &endptr);
209218
if (err < 0) {
210219
PyErr_SetString(PyExc_ValueError, "Unable to parse bytes to QuadPrecision");
211220
Py_DECREF(self);
212221
return NULL;
213222
}
223+
// Skip trailing whitespace (matches Python's float() behavior)
224+
while (ascii_isspace(*endptr)) {
225+
endptr++;
226+
}
227+
if (*endptr != '\0') {
228+
PyErr_SetString(PyExc_ValueError, "Unable to parse bytes to QuadPrecision");
229+
Py_DECREF(self);
230+
return NULL;
231+
}
214232
}
215233
else if (PyLong_Check(value)) {
216234
return quad_from_py_int(value, backend, self);
@@ -320,19 +338,6 @@ QuadPrecision_str(QuadPrecisionObject *self)
320338
return PyUnicode_FromString(buffer);
321339
}
322340

323-
static PyObject *
324-
QuadPrecision_repr(QuadPrecisionObject *self)
325-
{
326-
PyObject *str = QuadPrecision_str(self);
327-
if (str == NULL) {
328-
return NULL;
329-
}
330-
const char *backend_str = (self->backend == BACKEND_SLEEF) ? "sleef" : "longdouble";
331-
PyObject *res = PyUnicode_FromFormat("QuadPrecision('%S', backend='%s')", str, backend_str);
332-
Py_DECREF(str);
333-
return res;
334-
}
335-
336341
static PyObject *
337342
QuadPrecision_repr_dragon4(QuadPrecisionObject *self)
338343
{

quaddtype/numpy_quaddtype/src/umath/umath.cpp

Lines changed: 0 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -25,60 +25,6 @@ extern "C" {
2525
#include "comparison_ops.h"
2626
#include "matmul.h"
2727

28-
// helper debugging function
29-
static const char *
30-
get_dtype_name(PyArray_DTypeMeta *dtype)
31-
{
32-
if (dtype == &QuadPrecDType) {
33-
return "QuadPrecDType";
34-
}
35-
else if (dtype == &PyArray_BoolDType) {
36-
return "BoolDType";
37-
}
38-
else if (dtype == &PyArray_ByteDType) {
39-
return "ByteDType";
40-
}
41-
else if (dtype == &PyArray_UByteDType) {
42-
return "UByteDType";
43-
}
44-
else if (dtype == &PyArray_ShortDType) {
45-
return "ShortDType";
46-
}
47-
else if (dtype == &PyArray_UShortDType) {
48-
return "UShortDType";
49-
}
50-
else if (dtype == &PyArray_IntDType) {
51-
return "IntDType";
52-
}
53-
else if (dtype == &PyArray_UIntDType) {
54-
return "UIntDType";
55-
}
56-
else if (dtype == &PyArray_LongDType) {
57-
return "LongDType";
58-
}
59-
else if (dtype == &PyArray_ULongDType) {
60-
return "ULongDType";
61-
}
62-
else if (dtype == &PyArray_LongLongDType) {
63-
return "LongLongDType";
64-
}
65-
else if (dtype == &PyArray_ULongLongDType) {
66-
return "ULongLongDType";
67-
}
68-
else if (dtype == &PyArray_FloatDType) {
69-
return "FloatDType";
70-
}
71-
else if (dtype == &PyArray_DoubleDType) {
72-
return "DoubleDType";
73-
}
74-
else if (dtype == &PyArray_LongDoubleDType) {
75-
return "LongDoubleDType";
76-
}
77-
else {
78-
return "UnknownDType";
79-
}
80-
}
81-
8228
int
8329
init_quad_umath(void)
8430
{

0 commit comments

Comments
 (0)