From 76d823f59a464e98f8fbdd8ec28b5a8bd97aaaa7 Mon Sep 17 00:00:00 2001 From: swayaminsync Date: Thu, 4 Sep 2025 13:39:02 +0530 Subject: [PATCH 01/55] fixing subnormal cross-platform --- .../numpy_quaddtype/src/quaddtype_main.c | 19 +++++++++++++++++++ quaddtype/tests/test_quaddtype.py | 10 ++++++++++ 2 files changed, 29 insertions(+) diff --git a/quaddtype/numpy_quaddtype/src/quaddtype_main.c b/quaddtype/numpy_quaddtype/src/quaddtype_main.c index 929927a4..9e98faa3 100644 --- a/quaddtype/numpy_quaddtype/src/quaddtype_main.c +++ b/quaddtype/numpy_quaddtype/src/quaddtype_main.c @@ -71,7 +71,26 @@ 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 + // On platforms with native __float128 support, use the correct literal result->value.sleef_value = SLEEF_QUAD_DENORM_MIN; +#else + // On platforms without native __float128, SLEEF_QUAD_DENORM_MIN is broken + // Manually constructing the smallest subnormal: 1 * 2^(-16382-112) = 2^(-16494) + // This represents 0x0.0000000000000000000000000001p-16382 +#if defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) + struct { + uint64_t h, l; + } c; +#else + struct { + uint64_t l, h; + } c; +#endif + c.h = 0x0000000000000000ULL; // exponent = 0 (subnormal), mantissa high = 0 + c.l = 0x0000000000000001ULL; // mantissa low = 1 (smallest possible) + memcpy(&result->value.sleef_value, &c, 16); +#endif } else if (strcmp(constant_name, "bits") == 0) { Py_DECREF(result); diff --git a/quaddtype/tests/test_quaddtype.py b/quaddtype/tests/test_quaddtype.py index 0a2cf3ff..1833c4e6 100644 --- a/quaddtype/tests/test_quaddtype.py +++ b/quaddtype/tests/test_quaddtype.py @@ -24,6 +24,16 @@ def test_finfo_constant(name): assert isinstance(getattr(numpy_quaddtype, name), QuadPrecision) +def test_smallest_subnormal_value(): + """Test that smallest_subnormal has the correct value across all platforms.""" + smallest_sub = numpy_quaddtype.smallest_subnormal + repr_str = repr(smallest_sub) + + # The repr should show QuadPrecision('6.0e-4966', backend='sleef') + assert "6.0e-4966" in repr_str, f"Expected '6.0e-4966' in repr, got {repr_str}" + + assert smallest_sub > 0, "smallest_subnormal should be positive" + @pytest.mark.parametrize("name,value", [("bits", 128), ("precision", 33)]) def test_finfo_int_constant(name, value): assert getattr(numpy_quaddtype, name) == value From 41bce9a7ec3400f824bb2b73eadf26984044e57c Mon Sep 17 00:00:00 2001 From: swayaminsync Date: Thu, 4 Sep 2025 18:10:30 +0530 Subject: [PATCH 02/55] using mutex before memcpy --- quaddtype/numpy_quaddtype/src/quaddtype_main.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/quaddtype/numpy_quaddtype/src/quaddtype_main.c b/quaddtype/numpy_quaddtype/src/quaddtype_main.c index 9e98faa3..76709c6a 100644 --- a/quaddtype/numpy_quaddtype/src/quaddtype_main.c +++ b/quaddtype/numpy_quaddtype/src/quaddtype_main.c @@ -18,6 +18,9 @@ #include "quad_common.h" #include "quadblas_interface.h" #include "float.h" +#include + +static pthread_mutex_t constant_mutex = PTHREAD_MUTEX_INITIALIZER; static PyObject * py_is_longdouble_128(PyObject *self, PyObject *args) @@ -75,6 +78,7 @@ get_sleef_constant(PyObject *self, PyObject *args) // On platforms with native __float128 support, use the correct literal result->value.sleef_value = SLEEF_QUAD_DENORM_MIN; #else + pthread_mutex_lock(&constant_mutex); // On platforms without native __float128, SLEEF_QUAD_DENORM_MIN is broken // Manually constructing the smallest subnormal: 1 * 2^(-16382-112) = 2^(-16494) // This represents 0x0.0000000000000000000000000001p-16382 @@ -90,6 +94,7 @@ get_sleef_constant(PyObject *self, PyObject *args) c.h = 0x0000000000000000ULL; // exponent = 0 (subnormal), mantissa high = 0 c.l = 0x0000000000000001ULL; // mantissa low = 1 (smallest possible) memcpy(&result->value.sleef_value, &c, 16); + pthread_mutex_unlock(&constant_mutex); #endif } else if (strcmp(constant_name, "bits") == 0) { From e41c8321c15329d43be0ecb4bc340eb2e52a717e Mon Sep 17 00:00:00 2001 From: swayaminsync Date: Thu, 4 Sep 2025 18:22:55 +0530 Subject: [PATCH 03/55] precomputing the value --- .../numpy_quaddtype/src/quaddtype_main.c | 36 ++++++++++--------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/quaddtype/numpy_quaddtype/src/quaddtype_main.c b/quaddtype/numpy_quaddtype/src/quaddtype_main.c index 76709c6a..d5565fd4 100644 --- a/quaddtype/numpy_quaddtype/src/quaddtype_main.c +++ b/quaddtype/numpy_quaddtype/src/quaddtype_main.c @@ -33,6 +33,24 @@ py_is_longdouble_128(PyObject *self, PyObject *args) } } +#ifndef SLEEF_QUAD_C +static const union { + struct { +#if defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) + uint64_t h, l; +#else + uint64_t l, h; +#endif + } parts; + Sleef_quad quad_value; + long double alignment_dummy __attribute__((aligned(16))); +} SMALLEST_SUBNORMAL_CONST = { + .parts = { + .h = 0x0000000000000000ULL, // exponent = 0 (subnormal), mantissa high = 0 + .l = 0x0000000000000001ULL // mantissa low = 1 (smallest possible) + }}; +#endif + static PyObject * get_sleef_constant(PyObject *self, PyObject *args) { @@ -78,23 +96,7 @@ get_sleef_constant(PyObject *self, PyObject *args) // On platforms with native __float128 support, use the correct literal result->value.sleef_value = SLEEF_QUAD_DENORM_MIN; #else - pthread_mutex_lock(&constant_mutex); - // On platforms without native __float128, SLEEF_QUAD_DENORM_MIN is broken - // Manually constructing the smallest subnormal: 1 * 2^(-16382-112) = 2^(-16494) - // This represents 0x0.0000000000000000000000000001p-16382 -#if defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) - struct { - uint64_t h, l; - } c; -#else - struct { - uint64_t l, h; - } c; -#endif - c.h = 0x0000000000000000ULL; // exponent = 0 (subnormal), mantissa high = 0 - c.l = 0x0000000000000001ULL; // mantissa low = 1 (smallest possible) - memcpy(&result->value.sleef_value, &c, 16); - pthread_mutex_unlock(&constant_mutex); + result->value.sleef_value = SMALLEST_SUBNORMAL_CONST.quad_value; #endif } else if (strcmp(constant_name, "bits") == 0) { From 1addb5286c222bad42452d8e74c03092df8f3c42 Mon Sep 17 00:00:00 2001 From: swayaminsync Date: Thu, 4 Sep 2025 19:10:38 +0530 Subject: [PATCH 04/55] precomputing the value --- quaddtype/numpy_quaddtype/src/quaddtype_main.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/quaddtype/numpy_quaddtype/src/quaddtype_main.c b/quaddtype/numpy_quaddtype/src/quaddtype_main.c index d5565fd4..fc697c99 100644 --- a/quaddtype/numpy_quaddtype/src/quaddtype_main.c +++ b/quaddtype/numpy_quaddtype/src/quaddtype_main.c @@ -18,9 +18,6 @@ #include "quad_common.h" #include "quadblas_interface.h" #include "float.h" -#include - -static pthread_mutex_t constant_mutex = PTHREAD_MUTEX_INITIALIZER; static PyObject * py_is_longdouble_128(PyObject *self, PyObject *args) From 1ff0191bd299afdc92c8376bd6420e56b9530717 Mon Sep 17 00:00:00 2001 From: swayaminsync Date: Thu, 4 Sep 2025 19:26:28 +0530 Subject: [PATCH 05/55] static union --- .../numpy_quaddtype/src/quaddtype_main.c | 22 ++++++++----------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/quaddtype/numpy_quaddtype/src/quaddtype_main.c b/quaddtype/numpy_quaddtype/src/quaddtype_main.c index fc697c99..e91016b0 100644 --- a/quaddtype/numpy_quaddtype/src/quaddtype_main.c +++ b/quaddtype/numpy_quaddtype/src/quaddtype_main.c @@ -30,22 +30,18 @@ py_is_longdouble_128(PyObject *self, PyObject *args) } } -#ifndef SLEEF_QUAD_C +#ifdef SLEEF_QUAD_C +// Native __float128 support +static const Sleef_quad SMALLEST_SUBNORMAL_VALUE = SLEEF_QUAD_DENORM_MIN; +#else +// Use static union for thread-safe initialization static const union { struct { -#if defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) - uint64_t h, l; -#else uint64_t l, h; -#endif } parts; - Sleef_quad quad_value; - long double alignment_dummy __attribute__((aligned(16))); -} SMALLEST_SUBNORMAL_CONST = { - .parts = { - .h = 0x0000000000000000ULL, // exponent = 0 (subnormal), mantissa high = 0 - .l = 0x0000000000000001ULL // mantissa low = 1 (smallest possible) - }}; + Sleef_quad value; +} smallest_subnormal_const = {.parts = {.l = 0x0000000000000001ULL, .h = 0x0000000000000000ULL}}; +#define SMALLEST_SUBNORMAL_VALUE (smallest_subnormal_const.value) #endif static PyObject * @@ -93,7 +89,7 @@ get_sleef_constant(PyObject *self, PyObject *args) // On platforms with native __float128 support, use the correct literal result->value.sleef_value = SLEEF_QUAD_DENORM_MIN; #else - result->value.sleef_value = SMALLEST_SUBNORMAL_CONST.quad_value; + result->value.sleef_value = SMALLEST_SUBNORMAL_VALUE; #endif } else if (strcmp(constant_name, "bits") == 0) { From e7104b7d50b24f6f0f2a9a02d355c53514b0c0b1 Mon Sep 17 00:00:00 2001 From: swayaminsync Date: Thu, 4 Sep 2025 19:53:05 +0530 Subject: [PATCH 06/55] precompile cache --- quaddtype/numpy_quaddtype/src/quaddtype_main.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/quaddtype/numpy_quaddtype/src/quaddtype_main.c b/quaddtype/numpy_quaddtype/src/quaddtype_main.c index e91016b0..6d68c5af 100644 --- a/quaddtype/numpy_quaddtype/src/quaddtype_main.c +++ b/quaddtype/numpy_quaddtype/src/quaddtype_main.c @@ -31,16 +31,25 @@ py_is_longdouble_128(PyObject *self, PyObject *args) } #ifdef SLEEF_QUAD_C -// Native __float128 support static const Sleef_quad SMALLEST_SUBNORMAL_VALUE = SLEEF_QUAD_DENORM_MIN; #else -// Use static union for thread-safe initialization +// 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 } parts; Sleef_quad value; -} smallest_subnormal_const = {.parts = {.l = 0x0000000000000001ULL, .h = 0x0000000000000000ULL}}; +} 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 From ea212dde1724f6b0a6b7ded808b0480cf0c5daa8 Mon Sep 17 00:00:00 2001 From: swayaminsync Date: Thu, 4 Sep 2025 20:11:01 +0530 Subject: [PATCH 07/55] using pymutex on object creation --- quaddtype/numpy_quaddtype/src/scalar.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/quaddtype/numpy_quaddtype/src/scalar.c b/quaddtype/numpy_quaddtype/src/scalar.c index 6c2e4b51..6292423a 100644 --- a/quaddtype/numpy_quaddtype/src/scalar.c +++ b/quaddtype/numpy_quaddtype/src/scalar.c @@ -15,10 +15,22 @@ #include "scalar_ops.h" #include "dragon4.h" +#ifdef Py_GIL_DISABLED +static PyMutex quad_creation_mutex = {0}; +#endif + QuadPrecisionObject * QuadPrecision_raw_new(QuadBackendType backend) { - QuadPrecisionObject *new = PyObject_New(QuadPrecisionObject, &QuadPrecision_Type); + QuadPrecisionObject *new; +#ifdef Py_GIL_DISABLED + PyMutex_Lock(&quad_creation_mutex); +#endif + new = PyObject_New(QuadPrecisionObject, &QuadPrecision_Type); +#ifdef Py_GIL_DISABLED + PyMutex_Unlock(&quad_creation_mutex); +#endif + if (!new) return NULL; new->backend = backend; From 4b250290d494d5129f509880973cc5f62920ec4c Mon Sep 17 00:00:00 2001 From: swayaminsync Date: Thu, 4 Sep 2025 20:21:57 +0530 Subject: [PATCH 08/55] repr string building with mutex --- quaddtype/numpy_quaddtype/src/scalar.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/quaddtype/numpy_quaddtype/src/scalar.c b/quaddtype/numpy_quaddtype/src/scalar.c index 6292423a..79dbc1c6 100644 --- a/quaddtype/numpy_quaddtype/src/scalar.c +++ b/quaddtype/numpy_quaddtype/src/scalar.c @@ -16,7 +16,7 @@ #include "dragon4.h" #ifdef Py_GIL_DISABLED -static PyMutex quad_creation_mutex = {0}; +static PyMutex scalar_mutex = {0}; #endif QuadPrecisionObject * @@ -24,11 +24,11 @@ QuadPrecision_raw_new(QuadBackendType backend) { QuadPrecisionObject *new; #ifdef Py_GIL_DISABLED - PyMutex_Lock(&quad_creation_mutex); + PyMutex_Lock(&scalar_mutex); #endif new = PyObject_New(QuadPrecisionObject, &QuadPrecision_Type); #ifdef Py_GIL_DISABLED - PyMutex_Unlock(&quad_creation_mutex); + PyMutex_Unlock(&scalar_mutex); #endif if (!new) @@ -196,6 +196,9 @@ QuadPrecision_str(QuadPrecisionObject *self) static PyObject * QuadPrecision_repr(QuadPrecisionObject *self) { +#ifdef Py_GIL_DISABLED + PyMutex_Lock(&scalar_mutex); +#endif PyObject *str = QuadPrecision_str(self); if (str == NULL) { return NULL; @@ -203,6 +206,9 @@ QuadPrecision_repr(QuadPrecisionObject *self) const char *backend_str = (self->backend == BACKEND_SLEEF) ? "sleef" : "longdouble"; PyObject *res = PyUnicode_FromFormat("QuadPrecision('%S', backend='%s')", str, backend_str); Py_DECREF(str); +#ifdef Py_GIL_DISABLED + PyMutex_Unlock(&scalar_mutex); +#endif return res; } From 378e86a245624bffa4d3eb0ecf1aefd2b5e6b047 Mon Sep 17 00:00:00 2001 From: swayaminsync Date: Thu, 4 Sep 2025 20:36:55 +0530 Subject: [PATCH 09/55] repr string building with mutex --- quaddtype/numpy_quaddtype/src/scalar.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/quaddtype/numpy_quaddtype/src/scalar.c b/quaddtype/numpy_quaddtype/src/scalar.c index 79dbc1c6..07b18bf0 100644 --- a/quaddtype/numpy_quaddtype/src/scalar.c +++ b/quaddtype/numpy_quaddtype/src/scalar.c @@ -215,6 +215,9 @@ QuadPrecision_repr(QuadPrecisionObject *self) static PyObject * QuadPrecision_repr_dragon4(QuadPrecisionObject *self) { +#ifdef Py_GIL_DISABLED + PyMutex_Lock(&scalar_mutex); +#endif Dragon4_Options opt = {.scientific = 1, .digit_mode = DigitMode_Unique, .cutoff_mode = CutoffMode_TotalLength, @@ -244,6 +247,9 @@ QuadPrecision_repr_dragon4(QuadPrecisionObject *self) const char *backend_str = (self->backend == BACKEND_SLEEF) ? "sleef" : "longdouble"; PyObject *res = PyUnicode_FromFormat("QuadPrecision('%S', backend='%s')", str, backend_str); Py_DECREF(str); +#ifdef Py_GIL_DISABLED + PyMutex_Unlock(&scalar_mutex); +#endif return res; } From 1d9514ba909121e3f55bc31da52d1769ee21bb3b Mon Sep 17 00:00:00 2001 From: SwayamInSync Date: Thu, 4 Sep 2025 17:23:25 +0000 Subject: [PATCH 10/55] selecting TLS support --- quaddtype/meson.build | 40 ++++++++++++++++++++++++- quaddtype/numpy_quaddtype/src/dragon4.c | 12 ++++++++ quaddtype/numpy_quaddtype/src/scalar.c | 21 ------------- 3 files changed, 51 insertions(+), 22 deletions(-) diff --git a/quaddtype/meson.build b/quaddtype/meson.build index e50f6937..735db3fc 100644 --- a/quaddtype/meson.build +++ b/quaddtype/meson.build @@ -30,6 +30,44 @@ if openmp_dep.found() dependencies += openmp_dep endif +# Thread-local storage detection (borrowed from NumPy) +optional_variable_attributes = [ + ['thread_local', 'HAVE_THREAD_LOCAL'], # C23 + ['_Thread_local', 'HAVE__THREAD_LOCAL'], # C11/C17 + ['__thread', 'HAVE___THREAD'], # GCC/Clang + ['__declspec(thread)', 'HAVE___DECLSPEC_THREAD_'] # MSVC +] + +if not is_variable('cdata') + cdata = configuration_data() +endif + +foreach optional_attr: optional_variable_attributes + attr = optional_attr[0] + 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)) + endif +endforeach + +configure_file( + output: 'quaddtype_config.h', + configuration: cdata +) + +build_includes = include_directories('.') + includes = include_directories( [ incdir_numpy, @@ -84,5 +122,5 @@ py.extension_module('_quaddtype_main', dependencies: dependencies, install: true, subdir: 'numpy_quaddtype', - include_directories: includes + include_directories: [includes, build_includes] ) \ No newline at end of file diff --git a/quaddtype/numpy_quaddtype/src/dragon4.c b/quaddtype/numpy_quaddtype/src/dragon4.c index 34ad4cbb..fc60a5f1 100644 --- a/quaddtype/numpy_quaddtype/src/dragon4.c +++ b/quaddtype/numpy_quaddtype/src/dragon4.c @@ -11,6 +11,9 @@ Modifications are specific to support the SLEEF_QUAD #include #include +#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 @@ -22,6 +25,15 @@ Modifications are specific to support the SLEEF_QUAD #include "dtype.h" #include "scalar.h" + +#if !defined(HAVE_THREAD_LOCAL) && !defined(HAVE__THREAD_LOCAL) && \ + !defined(HAVE___THREAD) && !defined(HAVE___DECLSPEC_THREAD_) && \ + !defined(__cplusplus) +#warning "No thread-local storage support detected! NPY_TLS will be empty, causing thread safety issues." +#else +#warning "NPY_TLS Thread-local storage support detected." +#endif + #if 0 #define DEBUG_ASSERT(stmnt) assert(stmnt) #else diff --git a/quaddtype/numpy_quaddtype/src/scalar.c b/quaddtype/numpy_quaddtype/src/scalar.c index 07b18bf0..6d82d198 100644 --- a/quaddtype/numpy_quaddtype/src/scalar.c +++ b/quaddtype/numpy_quaddtype/src/scalar.c @@ -15,21 +15,12 @@ #include "scalar_ops.h" #include "dragon4.h" -#ifdef Py_GIL_DISABLED -static PyMutex scalar_mutex = {0}; -#endif QuadPrecisionObject * QuadPrecision_raw_new(QuadBackendType backend) { QuadPrecisionObject *new; -#ifdef Py_GIL_DISABLED - PyMutex_Lock(&scalar_mutex); -#endif new = PyObject_New(QuadPrecisionObject, &QuadPrecision_Type); -#ifdef Py_GIL_DISABLED - PyMutex_Unlock(&scalar_mutex); -#endif if (!new) return NULL; @@ -196,9 +187,6 @@ QuadPrecision_str(QuadPrecisionObject *self) static PyObject * QuadPrecision_repr(QuadPrecisionObject *self) { -#ifdef Py_GIL_DISABLED - PyMutex_Lock(&scalar_mutex); -#endif PyObject *str = QuadPrecision_str(self); if (str == NULL) { return NULL; @@ -206,18 +194,12 @@ QuadPrecision_repr(QuadPrecisionObject *self) const char *backend_str = (self->backend == BACKEND_SLEEF) ? "sleef" : "longdouble"; PyObject *res = PyUnicode_FromFormat("QuadPrecision('%S', backend='%s')", str, backend_str); Py_DECREF(str); -#ifdef Py_GIL_DISABLED - PyMutex_Unlock(&scalar_mutex); -#endif return res; } static PyObject * QuadPrecision_repr_dragon4(QuadPrecisionObject *self) { -#ifdef Py_GIL_DISABLED - PyMutex_Lock(&scalar_mutex); -#endif Dragon4_Options opt = {.scientific = 1, .digit_mode = DigitMode_Unique, .cutoff_mode = CutoffMode_TotalLength, @@ -247,9 +229,6 @@ QuadPrecision_repr_dragon4(QuadPrecisionObject *self) const char *backend_str = (self->backend == BACKEND_SLEEF) ? "sleef" : "longdouble"; PyObject *res = PyUnicode_FromFormat("QuadPrecision('%S', backend='%s')", str, backend_str); Py_DECREF(str); -#ifdef Py_GIL_DISABLED - PyMutex_Unlock(&scalar_mutex); -#endif return res; } From 501cf7ef85f15bcadcdce69a90e16c96a2247c6a Mon Sep 17 00:00:00 2001 From: SwayamInSync Date: Thu, 4 Sep 2025 17:31:32 +0000 Subject: [PATCH 11/55] adding explicit macro def inside dragon4.c --- quaddtype/numpy_quaddtype/src/dragon4.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/quaddtype/numpy_quaddtype/src/dragon4.c b/quaddtype/numpy_quaddtype/src/dragon4.c index fc60a5f1..7f3904a3 100644 --- a/quaddtype/numpy_quaddtype/src/dragon4.c +++ b/quaddtype/numpy_quaddtype/src/dragon4.c @@ -25,7 +25,6 @@ Modifications are specific to support the SLEEF_QUAD #include "dtype.h" #include "scalar.h" - #if !defined(HAVE_THREAD_LOCAL) && !defined(HAVE__THREAD_LOCAL) && \ !defined(HAVE___THREAD) && !defined(HAVE___DECLSPEC_THREAD_) && \ !defined(__cplusplus) @@ -34,6 +33,20 @@ Modifications are specific to support the SLEEF_QUAD #warning "NPY_TLS Thread-local storage support detected." #endif +#ifdef __cplusplus + #define NPY_TLS thread_local +#elif defined(HAVE_THREAD_LOCAL) + #define NPY_TLS thread_local +#elif defined(HAVE__THREAD_LOCAL) + #define NPY_TLS _Thread_local +#elif defined(HAVE___THREAD) + #define NPY_TLS __thread +#elif defined(HAVE___DECLSPEC_THREAD_) + #define NPY_TLS __declspec(thread) +#else + #define NPY_TLS +#endif + #if 0 #define DEBUG_ASSERT(stmnt) assert(stmnt) #else From 0a9d1e3bc32ffe7ed56d2ee888c45841598c108b Mon Sep 17 00:00:00 2001 From: SwayamInSync Date: Thu, 4 Sep 2025 17:48:33 +0000 Subject: [PATCH 12/55] removing inline code warnings --- quaddtype/numpy_quaddtype/src/dragon4.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/quaddtype/numpy_quaddtype/src/dragon4.c b/quaddtype/numpy_quaddtype/src/dragon4.c index 7f3904a3..8e96c0bc 100644 --- a/quaddtype/numpy_quaddtype/src/dragon4.c +++ b/quaddtype/numpy_quaddtype/src/dragon4.c @@ -25,13 +25,6 @@ Modifications are specific to support the SLEEF_QUAD #include "dtype.h" #include "scalar.h" -#if !defined(HAVE_THREAD_LOCAL) && !defined(HAVE__THREAD_LOCAL) && \ - !defined(HAVE___THREAD) && !defined(HAVE___DECLSPEC_THREAD_) && \ - !defined(__cplusplus) -#warning "No thread-local storage support detected! NPY_TLS will be empty, causing thread safety issues." -#else -#warning "NPY_TLS Thread-local storage support detected." -#endif #ifdef __cplusplus #define NPY_TLS thread_local From 1ced8a6cfa82b7c19c6e4e0addc1318832ae586c Mon Sep 17 00:00:00 2001 From: SwayamInSync Date: Thu, 4 Sep 2025 19:11:30 +0000 Subject: [PATCH 13/55] remvoing redundant SLEEF_QUAD compile check --- quaddtype/numpy_quaddtype/src/quaddtype_main.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/quaddtype/numpy_quaddtype/src/quaddtype_main.c b/quaddtype/numpy_quaddtype/src/quaddtype_main.c index 6d68c5af..734de21b 100644 --- a/quaddtype/numpy_quaddtype/src/quaddtype_main.c +++ b/quaddtype/numpy_quaddtype/src/quaddtype_main.c @@ -94,12 +94,7 @@ 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 - // On platforms with native __float128 support, use the correct literal - result->value.sleef_value = SLEEF_QUAD_DENORM_MIN; -#else result->value.sleef_value = SMALLEST_SUBNORMAL_VALUE; -#endif } else if (strcmp(constant_name, "bits") == 0) { Py_DECREF(result); From 01101b90a4c94b25d1fbe82cb6ce4c901da6ba31 Mon Sep 17 00:00:00 2001 From: Nathan Goldbaum Date: Thu, 4 Sep 2025 15:02:15 -0600 Subject: [PATCH 14/55] Don't suggest -latomic in default build instructions --- quaddtype/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/quaddtype/README.md b/quaddtype/README.md index 3c58645a..35740398 100644 --- a/quaddtype/README.md +++ b/quaddtype/README.md @@ -54,7 +54,8 @@ source temp/bin/activate # Install the package pip install meson-python numpy pytest -export LDFLAGS="-Wl,-rpath,$SLEEF_DIR/lib -fopenmp -latomic -lpthread" +# If you see errors about a missing atomics library, you might need -latomic +export LDFLAGS="-Wl,-rpath,$SLEEF_DIR/lib -fopenmp -lpthread" export CFLAGS="-fPIC" export CXXFLAGS="-fPIC" From d22d0a23ab47c41b4710ffe2c34b3341e46ec2a4 Mon Sep 17 00:00:00 2001 From: SwayamInSync Date: Fri, 5 Sep 2025 15:16:40 +0000 Subject: [PATCH 15/55] Add QBLAS wrap dependency system --- .gitignore | 4 ++++ quaddtype/meson.build | 8 ++++---- quaddtype/numpy_quaddtype/src/quadblas_interface.cpp | 2 +- quaddtype/subprojects/packagefiles/qblas/meson.build | 8 ++++++++ quaddtype/subprojects/qblas.wrap | 8 ++++++++ 5 files changed, 25 insertions(+), 5 deletions(-) create mode 100644 quaddtype/subprojects/packagefiles/qblas/meson.build create mode 100644 quaddtype/subprojects/qblas.wrap diff --git a/.gitignore b/.gitignore index dc6d7cc2..ce3d2af0 100644 --- a/.gitignore +++ b/.gitignore @@ -137,3 +137,7 @@ compile_commands.json *.whl .DS_Store .idea/ + +# quddtype +/quaddtype/subprojects/qblas/ +.wraplock diff --git a/quaddtype/meson.build b/quaddtype/meson.build index 735db3fc..4553dd5f 100644 --- a/quaddtype/meson.build +++ b/quaddtype/meson.build @@ -25,7 +25,8 @@ incdir_numpy = run_command(py, # Add OpenMP dependency (optional, for threading) openmp_dep = dependency('openmp', required: false) -dependencies = [sleef_dep, py_dep] +qblas_dep = dependency('qblas', fallback: ['qblas', 'qblas_dep']) +dependencies = [sleef_dep, py_dep, qblas_dep] if openmp_dep.found() dependencies += openmp_dep endif @@ -66,12 +67,11 @@ configure_file( configuration: cdata ) -build_includes = include_directories('.') - +build_includes = include_directories('.') # compile time generated headers as per system includes = include_directories( [ incdir_numpy, - 'numpy_quaddtype/QBLAS/include', + # 'subprojects/qblas/include', 'numpy_quaddtype/src', ] ) diff --git a/quaddtype/numpy_quaddtype/src/quadblas_interface.cpp b/quaddtype/numpy_quaddtype/src/quadblas_interface.cpp index 65feb604..b51851a3 100644 --- a/quaddtype/numpy_quaddtype/src/quadblas_interface.cpp +++ b/quaddtype/numpy_quaddtype/src/quadblas_interface.cpp @@ -3,7 +3,7 @@ #include #ifndef DISABLE_QUADBLAS -#include "../QBLAS/include/quadblas/quadblas.hpp" +#include "../subprojects/qblas/include/quadblas/quadblas.hpp" #endif // DISABLE_QUADBLAS extern "C" { diff --git a/quaddtype/subprojects/packagefiles/qblas/meson.build b/quaddtype/subprojects/packagefiles/qblas/meson.build new file mode 100644 index 00000000..810ee5d0 --- /dev/null +++ b/quaddtype/subprojects/packagefiles/qblas/meson.build @@ -0,0 +1,8 @@ +project('qblas', version: '1.0.0') + +qblas_inc = include_directories('include') + +qblas_dep = declare_dependency( + include_directories: qblas_inc, + version: meson.project_version() +) diff --git a/quaddtype/subprojects/qblas.wrap b/quaddtype/subprojects/qblas.wrap new file mode 100644 index 00000000..7b4710ff --- /dev/null +++ b/quaddtype/subprojects/qblas.wrap @@ -0,0 +1,8 @@ +[wrap-git] +directory=qblas +url=https://github.com/SwayamInSync/QBLAS.git +revision=9468e24a02b731563eba2aee0350e9219b36c102 +patch_directory = qblas + +[provide] +qblas = qblas_dep From 9c31ce0882d7828df4583589dfbdd4587d243271 Mon Sep 17 00:00:00 2001 From: SwayamInSync Date: Fri, 5 Sep 2025 15:24:30 +0000 Subject: [PATCH 16/55] Add -fext-numeric-literals compiler flag for QBLAS compatibility --- quaddtype/meson.build | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/quaddtype/meson.build b/quaddtype/meson.build index 4553dd5f..a1214816 100644 --- a/quaddtype/meson.build +++ b/quaddtype/meson.build @@ -31,6 +31,12 @@ if openmp_dep.found() dependencies += openmp_dep endif +# compiler flags for QBLAS compatibility +if not is_windows + # QBLAS requires extended numeric literals for Q suffix support + add_project_arguments('-fext-numeric-literals', language: 'cpp') +endif + # Thread-local storage detection (borrowed from NumPy) optional_variable_attributes = [ ['thread_local', 'HAVE_THREAD_LOCAL'], # C23 From c1b35a8695d678d1821ed81697c27ef92cef1c41 Mon Sep 17 00:00:00 2001 From: SwayamInSync Date: Fri, 5 Sep 2025 15:32:14 +0000 Subject: [PATCH 17/55] Remove QBLAS submodule, replaced with Meson wrap dependency --- .gitmodules | 3 --- quaddtype/numpy_quaddtype/QBLAS | 1 - 2 files changed, 4 deletions(-) delete mode 160000 quaddtype/numpy_quaddtype/QBLAS diff --git a/.gitmodules b/.gitmodules index 523c79c8..e69de29b 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +0,0 @@ -[submodule "quaddtype/numpy_quaddtype/QBLAS"] - path = quaddtype/numpy_quaddtype/QBLAS - url = https://github.com/SwayamInSync/QBLAS diff --git a/quaddtype/numpy_quaddtype/QBLAS b/quaddtype/numpy_quaddtype/QBLAS deleted file mode 160000 index 9468e24a..00000000 --- a/quaddtype/numpy_quaddtype/QBLAS +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 9468e24a02b731563eba2aee0350e9219b36c102 From 1fc111d7391ea6f7e493d4a069a364b104a3f17f Mon Sep 17 00:00:00 2001 From: SwayamInSync Date: Fri, 5 Sep 2025 15:40:32 +0000 Subject: [PATCH 18/55] updating workflows --- .github/workflows/build_wheels.yml | 47 ++++++------------------------ .github/workflows/ci.yml | 8 ++--- 2 files changed, 11 insertions(+), 44 deletions(-) diff --git a/.github/workflows/build_wheels.yml b/.github/workflows/build_wheels.yml index ec19cdb4..77849b92 100644 --- a/.github/workflows/build_wheels.yml +++ b/.github/workflows/build_wheels.yml @@ -21,19 +21,12 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - with: - submodules: recursive - name: Set up Python uses: actions/setup-python@v4 with: python-version: ">=3.11.0" - - name: Verify QuadBLAS submodule - run: | - ls -la quaddtype/numpy_quaddtype/QBLAS/ - ls -la quaddtype/numpy_quaddtype/QBLAS/include/quadblas/ - - name: Install cibuildwheel run: pip install cibuildwheel==3.1.4 @@ -56,8 +49,8 @@ jobs: cmake --build build/ --clean-first -j cmake --install build --prefix /usr/local CIBW_ENVIRONMENT: > - CFLAGS="-I/usr/local/include -I{project}/numpy_quaddtype/QBLAS/include $CFLAGS" - CXXFLAGS="-I/usr/local/include -I{project}/numpy_quaddtype/QBLAS/include -fext-numeric-literals $CXXFLAGS" + CFLAGS="-I/usr/local/include $CFLAGS" + CXXFLAGS="-I/usr/local/include $CXXFLAGS" LDFLAGS="-L/usr/local/lib64 -L/usr/local/lib -Wl,-rpath,/usr/local/lib64 -Wl,-rpath,/usr/local/lib -fopenmp $LDFLAGS" LD_LIBRARY_PATH="/usr/local/lib64:/usr/local/lib:$LD_LIBRARY_PATH" PKG_CONFIG_PATH="/usr/local/lib64/pkgconfig:/usr/local/lib/pkgconfig:$PKG_CONFIG_PATH" @@ -89,8 +82,6 @@ jobs: steps: - uses: actions/checkout@v3 - with: - submodules: recursive - name: Set up Python uses: actions/setup-python@v4 @@ -123,11 +114,6 @@ jobs: cmake --build build/ --clean-first -j sudo cmake --install build --prefix /usr/local - - name: Verify QuadBLAS submodule - run: | - ls -la quaddtype/numpy_quaddtype/QBLAS/ - ls -la quaddtype/numpy_quaddtype/QBLAS/include/quadblas/ - - name: Installing Python dependencies run: | pip install -U pip @@ -143,8 +129,8 @@ jobs: CIBW_ENVIRONMENT: > MACOSX_DEPLOYMENT_TARGET="${{ matrix.os == 'macos-13' && '13.0' || '14.0' }}" DYLD_LIBRARY_PATH="/usr/local/lib:$DYLD_LIBRARY_PATH" - CFLAGS="-I/usr/local/include -I{project}/numpy_quaddtype/QBLAS/include $CFLAGS" - CXXFLAGS="-I/usr/local/include -I{project}/numpy_quaddtype/QBLAS/include $CXXFLAGS" + CFLAGS="-I/usr/local/include $CFLAGS" + CXXFLAGS="-I/usr/local/include $CXXFLAGS" LDFLAGS="-L/usr/local/lib $LDFLAGS" PKG_CONFIG_PATH="/usr/local/lib/pkgconfig:$PKG_CONFIG_PATH" CIBW_REPAIR_WHEEL_COMMAND: > @@ -176,8 +162,6 @@ jobs: steps: - uses: actions/checkout@v3 - with: - submodules: recursive - name: Setup MSVC uses: ilammy/msvc-dev-cmd@v1 @@ -193,12 +177,6 @@ jobs: - name: Install CMake uses: lukka/get-cmake@latest - - name: Verify QuadBLAS submodule - shell: pwsh - run: | - Get-ChildItem quaddtype/numpy_quaddtype/QBLAS/ - Get-ChildItem quaddtype/numpy_quaddtype/QBLAS/include/quadblas/ - - name: Clone and Build SLEEF shell: pwsh run: | @@ -226,11 +204,11 @@ jobs: CIBW_BEFORE_BUILD: | pip install meson meson-python ninja numpy CIBW_ENVIRONMENT: > - INCLUDE="C:/sleef/include;{project}/numpy_quaddtype/QBLAS/include;$INCLUDE" + INCLUDE="C:/sleef/include;$INCLUDE" LIB="C:/sleef/lib;$LIB" PATH="C:/sleef/bin;$PATH" - CFLAGS="/IC:/sleef/include /I{project}/numpy_quaddtype/QBLAS/include /DDISABLE_QUADBLAS $CFLAGS" - CXXFLAGS="/IC:/sleef/include /I{project}/numpy_quaddtype/QBLAS/include /DDISABLE_QUADBLAS $CXXFLAGS" + CFLAGS="/IC:/sleef/include /DDISABLE_QUADBLAS $CFLAGS" + CXXFLAGS="/IC:/sleef/include /DDISABLE_QUADBLAS $CXXFLAGS" LDFLAGS="C:/sleef/lib/sleef.lib C:/sleef/lib/sleefquad.lib $LDFLAGS" CIBW_REPAIR_WHEEL_COMMAND: 'delvewheel repair -w {dest_dir} {wheel} --add-path C:\sleef\bin' CIBW_TEST_COMMAND: | @@ -258,19 +236,12 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - with: - submodules: recursive - name: Set up Python uses: actions/setup-python@v4 with: python-version: ">=3.11.0" - - name: Verify QuadBLAS submodule - run: | - ls -la quaddtype/numpy_quaddtype/QBLAS/ - ls -la quaddtype/numpy_quaddtype/QBLAS/include/quadblas/ - - name: Install system dependencies run: | sudo apt-get update -y @@ -294,8 +265,8 @@ jobs: - name: Build SDist env: - CFLAGS: "-I/usr/local/include -I$(pwd)/numpy_quaddtype/QBLAS/include" - CXXFLAGS: "-I/usr/local/include -I$(pwd)/numpy_quaddtype/QBLAS/include -fext-numeric-literals" + CFLAGS: "-I/usr/local/include" + CXXFLAGS: "-I/usr/local/include" LDFLAGS: "-L/usr/local/lib64 -L/usr/local/lib -Wl,-rpath,/usr/local/lib64 -Wl,-rpath,/usr/local/lib -fopenmp" LD_LIBRARY_PATH: "/usr/local/lib64:/usr/local/lib:$LD_LIBRARY_PATH" PKG_CONFIG_PATH: "/usr/local/lib64/pkgconfig:/usr/local/lib/pkgconfig:$PKG_CONFIG_PATH" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 542093c5..b20b8211 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -73,13 +73,9 @@ jobs: - name: Install quaddtype working-directory: quaddtype run: | - # Initialize submodules first - git submodule update --init --recursive - ls -la numpy_quaddtype/QBLAS/ - # Set environment variables with proper export and correct paths - export CFLAGS="-I/usr/local/include -I$(pwd)/numpy_quaddtype/QBLAS/include" - export CXXFLAGS="-I/usr/local/include -I$(pwd)/numpy_quaddtype/QBLAS/include -fext-numeric-literals" + export CFLAGS="-I/usr/local/include" + export CXXFLAGS="-I/usr/local/include" export LDFLAGS="-L/usr/local/lib64 -L/usr/local/lib -Wl,-rpath,/usr/local/lib64 -Wl,-rpath,/usr/local/lib -fopenmp" export LD_LIBRARY_PATH="/usr/local/lib64:/usr/local/lib:$LD_LIBRARY_PATH" From 43a7c84fd8ecf0585a6073f7649f65ee7cda300b Mon Sep 17 00:00:00 2001 From: SwayamInSync Date: Fri, 5 Sep 2025 15:47:10 +0000 Subject: [PATCH 19/55] numeric literal only for gcc I guess --- quaddtype/meson.build | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/quaddtype/meson.build b/quaddtype/meson.build index a1214816..ce7bb2d7 100644 --- a/quaddtype/meson.build +++ b/quaddtype/meson.build @@ -23,7 +23,7 @@ incdir_numpy = run_command(py, check : true ).stdout().strip() -# Add OpenMP dependency (optional, for threading) +# OpenMP dependency (optional, for threading) openmp_dep = dependency('openmp', required: false) qblas_dep = dependency('qblas', fallback: ['qblas', 'qblas_dep']) dependencies = [sleef_dep, py_dep, qblas_dep] @@ -31,10 +31,13 @@ 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 - add_project_arguments('-fext-numeric-literals', language: 'cpp') + # if compiler supports (usually gcc) + if cpp.has_argument('-fext-numeric-literals') + add_project_arguments('-fext-numeric-literals', language: 'cpp') + endif endif # Thread-local storage detection (borrowed from NumPy) From 556988c73aeca5ab33406fa02ecba8e7e00348d7 Mon Sep 17 00:00:00 2001 From: SwayamInSync Date: Fri, 5 Sep 2025 18:57:47 +0000 Subject: [PATCH 20/55] hmm sleef package works --- .gitignore | 1 + quaddtype/meson.build | 11 ++-- .../packagefiles/sleef/meson.build | 55 +++++++++++++++++++ quaddtype/subprojects/sleef.wrap | 9 +++ 4 files changed, 70 insertions(+), 6 deletions(-) create mode 100644 quaddtype/subprojects/packagefiles/sleef/meson.build create mode 100644 quaddtype/subprojects/sleef.wrap diff --git a/.gitignore b/.gitignore index ce3d2af0..540372fa 100644 --- a/.gitignore +++ b/.gitignore @@ -140,4 +140,5 @@ compile_commands.json # quddtype /quaddtype/subprojects/qblas/ +/quaddtype/subprojects/sleef/ .wraplock diff --git a/quaddtype/meson.build b/quaddtype/meson.build index ce7bb2d7..9799ede6 100644 --- a/quaddtype/meson.build +++ b/quaddtype/meson.build @@ -13,10 +13,9 @@ if is_windows add_project_arguments('-DWIN32', '-D_WINDOWS', language : ['c', 'cpp']) endif -sleef_dep = [ - c.find_library('sleef', required : true), - c.find_library('sleefquad', required : true) -] +sleef_subproj = subproject('sleef', required: true) +sleef_dep = sleef_subproj.get_variable('sleef_dep') +sleefquad_dep = sleef_subproj.get_variable('sleefquad_dep') incdir_numpy = run_command(py, ['-c', 'import numpy; print(numpy.get_include())'], @@ -26,7 +25,7 @@ incdir_numpy = run_command(py, # OpenMP dependency (optional, for threading) openmp_dep = dependency('openmp', required: false) qblas_dep = dependency('qblas', fallback: ['qblas', 'qblas_dep']) -dependencies = [sleef_dep, py_dep, qblas_dep] +dependencies = [py_dep, qblas_dep, sleef_dep, sleefquad_dep] if openmp_dep.found() dependencies += openmp_dep endif @@ -126,7 +125,7 @@ py.install_sources( py.extension_module('_quaddtype_main', srcs, - link_args: is_windows ? ['/DEFAULTLIB:sleef', '/DEFAULTLIB:sleefquad'] : ['-lsleef', '-lsleefquad'], + # link_args: is_windows ? ['/DEFAULTLIB:sleef', '/DEFAULTLIB:sleefquad'] : ['-lsleef', '-lsleefquad'], link_language: 'cpp', dependencies: dependencies, install: true, diff --git a/quaddtype/subprojects/packagefiles/sleef/meson.build b/quaddtype/subprojects/packagefiles/sleef/meson.build new file mode 100644 index 00000000..545008e8 --- /dev/null +++ b/quaddtype/subprojects/packagefiles/sleef/meson.build @@ -0,0 +1,55 @@ +project('sleef', version: '3.8') + +cmake = find_program('cmake') +ninja = find_program('ninja', 'make', required: false) + +# Use relative paths from build directory +sleef_build_dir = 'sleef_build' +sleef_install_dir = 'sleef_install' + +# Configure SLEEF at configuration time +sleef_configure = run_command([ + cmake, + '-S', meson.current_source_dir(), + '-B', meson.current_build_dir() / sleef_build_dir, + '-DCMAKE_BUILD_TYPE=Release', + '-DSLEEF_BUILD_QUAD=ON', + '-DSLEEF_BUILD_SHARED_LIBS=ON', + '-DSLEEF_BUILD_TESTS=OFF', + '-DSLEEF_BUILD_INLINE_HEADERS=OFF', + '-DCMAKE_POSITION_INDEPENDENT_CODE=ON', + '-DCMAKE_INSTALL_PREFIX=' + meson.current_build_dir() / sleef_install_dir +], check: false, capture: true) + +if sleef_configure.returncode() != 0 + error('SLEEF CMake configuration failed: ' + sleef_configure.stderr()) +endif + +# Build target for SLEEF libraries - create a dummy output file +sleef_build_target = custom_target('sleef_build', + command: [cmake, '--build', meson.current_build_dir() / sleef_build_dir, '--target', 'install', '--parallel'], + output: 'sleef_built.stamp', # Dummy stamp file + console: true, + build_always_stale: true, + build_by_default: true +) + +# Path variables +sleef_include_path = meson.current_build_dir() / sleef_install_dir / 'include' +sleef_lib_path = meson.current_build_dir() / sleef_install_dir / 'lib' + +# Create a dependency that ensures the build happens but doesn't link the dummy file +sleef_build_dep = declare_dependency(sources: [sleef_build_target]) + +# Create the actual linking dependencies +sleef_dep = declare_dependency( + dependencies: [sleef_build_dep], # Ensures build happens first + compile_args: ['-I' + sleef_include_path], + link_args: ['-L' + sleef_lib_path, '-lsleef', '-Wl,-rpath,' + sleef_lib_path] +) + +sleefquad_dep = declare_dependency( + dependencies: [sleef_build_dep], # Ensures build happens first + compile_args: ['-I' + sleef_include_path], + link_args: ['-L' + sleef_lib_path, '-lsleefquad', '-Wl,-rpath,' + sleef_lib_path] +) \ No newline at end of file diff --git a/quaddtype/subprojects/sleef.wrap b/quaddtype/subprojects/sleef.wrap new file mode 100644 index 00000000..8e87d722 --- /dev/null +++ b/quaddtype/subprojects/sleef.wrap @@ -0,0 +1,9 @@ +[wrap-git] +directory=sleef +url=https://github.com/shibatch/sleef.git +revision=3.8 +patch_directory=sleef + +[provide] +sleef = sleef_dep +sleefquad = sleefquad_dep \ No newline at end of file From 10e5d025ebddb5f06d4c6a25dfdcadd16ae4b7d3 Mon Sep 17 00:00:00 2001 From: SwayamInSync Date: Fri, 5 Sep 2025 19:26:03 +0000 Subject: [PATCH 21/55] copying shared libs to somewhere consistent --- quaddtype/meson.build | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/quaddtype/meson.build b/quaddtype/meson.build index 9799ede6..76167473 100644 --- a/quaddtype/meson.build +++ b/quaddtype/meson.build @@ -79,7 +79,6 @@ build_includes = include_directories('.') # compile time generated headers as pe includes = include_directories( [ incdir_numpy, - # 'subprojects/qblas/include', 'numpy_quaddtype/src', ] ) @@ -131,4 +130,9 @@ py.extension_module('_quaddtype_main', install: true, subdir: 'numpy_quaddtype', include_directories: [includes, build_includes] +) + +meson.add_install_script('cp', '-r', + meson.current_build_dir() / 'subprojects/sleef/sleef_install/lib', + py.get_install_dir() / 'numpy_quaddtype/.libs' ) \ No newline at end of file From 253322a697215108687fd519a35ae004b1d7c605 Mon Sep 17 00:00:00 2001 From: SwayamInSync Date: Sat, 6 Sep 2025 07:34:21 +0000 Subject: [PATCH 22/55] sleef shared libs not found --- quaddtype/meson.build | 5 ----- 1 file changed, 5 deletions(-) diff --git a/quaddtype/meson.build b/quaddtype/meson.build index 76167473..6df865f3 100644 --- a/quaddtype/meson.build +++ b/quaddtype/meson.build @@ -130,9 +130,4 @@ py.extension_module('_quaddtype_main', install: true, subdir: 'numpy_quaddtype', include_directories: [includes, build_includes] -) - -meson.add_install_script('cp', '-r', - meson.current_build_dir() / 'subprojects/sleef/sleef_install/lib', - py.get_install_dir() / 'numpy_quaddtype/.libs' ) \ No newline at end of file From 84b29111bc86abbab9d3fe3d59c05a9845412e20 Mon Sep 17 00:00:00 2001 From: SwayamInSync Date: Sat, 6 Sep 2025 08:10:36 +0000 Subject: [PATCH 23/55] some utilities --- quaddtype/reinstall.sh | 20 ++++++-------------- quaddtype/sdist_test.sh | 10 ++++++++++ 2 files changed, 16 insertions(+), 14 deletions(-) create mode 100644 quaddtype/sdist_test.sh diff --git a/quaddtype/reinstall.sh b/quaddtype/reinstall.sh index 1c08f84e..aca36744 100755 --- a/quaddtype/reinstall.sh +++ b/quaddtype/reinstall.sh @@ -1,21 +1,13 @@ #!/bin/bash -set -xeuo pipefail -IFS=$'\n\t' +set -x -if [ -d "build/" ] -then +if [ -d "build/" ]; then rm -r build + rm -rf dist/ + rm -rf subprojects/qblas + rm -rf subprojects/sleef fi -export CC=clang -export CXX=clang++ -export SLEEF_DIR=$PWD/sleef/build -export LIBRARY_PATH=$SLEEF_DIR/lib -export C_INCLUDE_PATH=$SLEEF_DIR/include -export CPLUS_INCLUDE_PATH=$SLEEF_DIR/include - -# Set RPATH via LDFLAGS -export LDFLAGS="-Wl,-rpath,$SLEEF_DIR/lib" python -m pip uninstall -y numpy_quaddtype -python -m pip install . -v --no-build-isolation -Cbuilddir=build -C'compile-args=-v' \ No newline at end of file +python -m pip install . -v --no-build-isolation -Cbuilddir=build \ No newline at end of file diff --git a/quaddtype/sdist_test.sh b/quaddtype/sdist_test.sh new file mode 100644 index 00000000..88d5d268 --- /dev/null +++ b/quaddtype/sdist_test.sh @@ -0,0 +1,10 @@ +#!/bin/bash +set -x + +if [ -d "build/" ]; then + rm -rf dist/ +fi + +python -m pip uninstall -y numpy_quaddtype +python -m build --sdist --outdir dist/ +python -m pip install dist/numpy_quaddtype-0.1.0.tar.gz -v --no-build-isolation -Cbuilddir=build \ No newline at end of file From 0fbe0e6d66f8ab8bcc791c02fb8e03c76ca9ee01 Mon Sep 17 00:00:00 2001 From: swayaminsync Date: Sat, 6 Sep 2025 14:19:14 +0530 Subject: [PATCH 24/55] maybe build statically --- quaddtype/meson.build | 2 +- quaddtype/subprojects/packagefiles/sleef/meson.build | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/quaddtype/meson.build b/quaddtype/meson.build index 6df865f3..16698080 100644 --- a/quaddtype/meson.build +++ b/quaddtype/meson.build @@ -129,5 +129,5 @@ py.extension_module('_quaddtype_main', dependencies: dependencies, install: true, subdir: 'numpy_quaddtype', - include_directories: [includes, build_includes] + include_directories: [includes, build_includes], ) \ No newline at end of file diff --git a/quaddtype/subprojects/packagefiles/sleef/meson.build b/quaddtype/subprojects/packagefiles/sleef/meson.build index 545008e8..8deac111 100644 --- a/quaddtype/subprojects/packagefiles/sleef/meson.build +++ b/quaddtype/subprojects/packagefiles/sleef/meson.build @@ -14,7 +14,7 @@ sleef_configure = run_command([ '-B', meson.current_build_dir() / sleef_build_dir, '-DCMAKE_BUILD_TYPE=Release', '-DSLEEF_BUILD_QUAD=ON', - '-DSLEEF_BUILD_SHARED_LIBS=ON', + '-DBUILD_SHARED_LIBS=OFF', '-DSLEEF_BUILD_TESTS=OFF', '-DSLEEF_BUILD_INLINE_HEADERS=OFF', '-DCMAKE_POSITION_INDEPENDENT_CODE=ON', @@ -45,11 +45,11 @@ sleef_build_dep = declare_dependency(sources: [sleef_build_target]) sleef_dep = declare_dependency( dependencies: [sleef_build_dep], # Ensures build happens first compile_args: ['-I' + sleef_include_path], - link_args: ['-L' + sleef_lib_path, '-lsleef', '-Wl,-rpath,' + sleef_lib_path] + link_args: ['-L' + sleef_lib_path, '-lsleef'] ) sleefquad_dep = declare_dependency( dependencies: [sleef_build_dep], # Ensures build happens first compile_args: ['-I' + sleef_include_path], - link_args: ['-L' + sleef_lib_path, '-lsleefquad', '-Wl,-rpath,' + sleef_lib_path] + link_args: ['-L' + sleef_lib_path, '-lsleefquad'] ) \ No newline at end of file From 083f19234a74c5df950db52866ae8ed58ff8a4c4 Mon Sep 17 00:00:00 2001 From: swayaminsync Date: Sat, 6 Sep 2025 14:33:22 +0530 Subject: [PATCH 25/55] yeah static linking is fine --- quaddtype/meson.build | 1 - quaddtype/reinstall.sh | 2 +- quaddtype/sdist_test.sh | 2 +- .../subprojects/packagefiles/sleef/meson.build | 17 +++++++---------- 4 files changed, 9 insertions(+), 13 deletions(-) diff --git a/quaddtype/meson.build b/quaddtype/meson.build index 16698080..69e4edf7 100644 --- a/quaddtype/meson.build +++ b/quaddtype/meson.build @@ -124,7 +124,6 @@ py.install_sources( py.extension_module('_quaddtype_main', srcs, - # link_args: is_windows ? ['/DEFAULTLIB:sleef', '/DEFAULTLIB:sleefquad'] : ['-lsleef', '-lsleefquad'], link_language: 'cpp', dependencies: dependencies, install: true, diff --git a/quaddtype/reinstall.sh b/quaddtype/reinstall.sh index aca36744..b5e04876 100755 --- a/quaddtype/reinstall.sh +++ b/quaddtype/reinstall.sh @@ -10,4 +10,4 @@ fi python -m pip uninstall -y numpy_quaddtype -python -m pip install . -v --no-build-isolation -Cbuilddir=build \ No newline at end of file +python -m pip install . -v \ No newline at end of file diff --git a/quaddtype/sdist_test.sh b/quaddtype/sdist_test.sh index 88d5d268..b38d7f90 100644 --- a/quaddtype/sdist_test.sh +++ b/quaddtype/sdist_test.sh @@ -7,4 +7,4 @@ fi python -m pip uninstall -y numpy_quaddtype python -m build --sdist --outdir dist/ -python -m pip install dist/numpy_quaddtype-0.1.0.tar.gz -v --no-build-isolation -Cbuilddir=build \ No newline at end of file +python -m pip install dist/numpy_quaddtype-0.1.0.tar.gz -v \ No newline at end of file diff --git a/quaddtype/subprojects/packagefiles/sleef/meson.build b/quaddtype/subprojects/packagefiles/sleef/meson.build index 8deac111..a9118e2b 100644 --- a/quaddtype/subprojects/packagefiles/sleef/meson.build +++ b/quaddtype/subprojects/packagefiles/sleef/meson.build @@ -3,18 +3,18 @@ project('sleef', version: '3.8') cmake = find_program('cmake') ninja = find_program('ninja', 'make', required: false) -# Use relative paths from build directory + sleef_build_dir = 'sleef_build' sleef_install_dir = 'sleef_install' -# Configure SLEEF at configuration time + sleef_configure = run_command([ cmake, '-S', meson.current_source_dir(), '-B', meson.current_build_dir() / sleef_build_dir, '-DCMAKE_BUILD_TYPE=Release', '-DSLEEF_BUILD_QUAD=ON', - '-DBUILD_SHARED_LIBS=OFF', + '-DBUILD_SHARED_LIBS=OFF', # building & linnking statically '-DSLEEF_BUILD_TESTS=OFF', '-DSLEEF_BUILD_INLINE_HEADERS=OFF', '-DCMAKE_POSITION_INDEPENDENT_CODE=ON', @@ -25,31 +25,28 @@ if sleef_configure.returncode() != 0 error('SLEEF CMake configuration failed: ' + sleef_configure.stderr()) endif -# Build target for SLEEF libraries - create a dummy output file + sleef_build_target = custom_target('sleef_build', command: [cmake, '--build', meson.current_build_dir() / sleef_build_dir, '--target', 'install', '--parallel'], - output: 'sleef_built.stamp', # Dummy stamp file + output: 'sleef_built.stamp', console: true, build_always_stale: true, build_by_default: true ) -# Path variables sleef_include_path = meson.current_build_dir() / sleef_install_dir / 'include' sleef_lib_path = meson.current_build_dir() / sleef_install_dir / 'lib' -# Create a dependency that ensures the build happens but doesn't link the dummy file sleef_build_dep = declare_dependency(sources: [sleef_build_target]) -# Create the actual linking dependencies sleef_dep = declare_dependency( - dependencies: [sleef_build_dep], # Ensures build happens first + dependencies: [sleef_build_dep], compile_args: ['-I' + sleef_include_path], link_args: ['-L' + sleef_lib_path, '-lsleef'] ) sleefquad_dep = declare_dependency( - dependencies: [sleef_build_dep], # Ensures build happens first + dependencies: [sleef_build_dep], compile_args: ['-I' + sleef_include_path], link_args: ['-L' + sleef_lib_path, '-lsleefquad'] ) \ No newline at end of file From bda104d88728551126b18874ceb57ebe5cd7cd92 Mon Sep 17 00:00:00 2001 From: swayaminsync Date: Sat, 6 Sep 2025 14:41:38 +0530 Subject: [PATCH 26/55] workflow-edit --- .github/workflows/build_wheels.yml | 72 ++---------------------------- .github/workflows/ci.yml | 22 +-------- 2 files changed, 6 insertions(+), 88 deletions(-) diff --git a/.github/workflows/build_wheels.yml b/.github/workflows/build_wheels.yml index 77849b92..00b63267 100644 --- a/.github/workflows/build_wheels.yml +++ b/.github/workflows/build_wheels.yml @@ -39,21 +39,8 @@ jobs: CIBW_BEFORE_ALL: | yum update -y yum install -y cmake gcc gcc-c++ make git pkgconfig - # Install SLEEF in container - git clone --branch 3.8 https://github.com/shibatch/sleef.git - cd sleef - cmake -S . -B build \ - -DSLEEF_BUILD_QUAD:BOOL=ON \ - -DSLEEF_BUILD_SHARED_LIBS:BOOL=ON \ - -DCMAKE_POSITION_INDEPENDENT_CODE=ON - cmake --build build/ --clean-first -j - cmake --install build --prefix /usr/local CIBW_ENVIRONMENT: > - CFLAGS="-I/usr/local/include $CFLAGS" - CXXFLAGS="-I/usr/local/include $CXXFLAGS" - LDFLAGS="-L/usr/local/lib64 -L/usr/local/lib -Wl,-rpath,/usr/local/lib64 -Wl,-rpath,/usr/local/lib -fopenmp $LDFLAGS" - LD_LIBRARY_PATH="/usr/local/lib64:/usr/local/lib:$LD_LIBRARY_PATH" - PKG_CONFIG_PATH="/usr/local/lib64/pkgconfig:/usr/local/lib/pkgconfig:$PKG_CONFIG_PATH" + LDFLAGS="-fopenmp $LDFLAGS" CIBW_REPAIR_WHEEL_COMMAND: | auditwheel repair -w {dest_dir} --plat manylinux_2_28_x86_64 {wheel} CIBW_TEST_COMMAND: | @@ -98,22 +85,6 @@ jobs: brew cleanup brew install $packages - - name: Install SLEEF - env: - MACOSX_DEPLOYMENT_TARGET: ${{ matrix.os == 'macos-13' && '13.0' || '14.0' }} - run: | - git clone --branch 3.8 https://github.com/shibatch/sleef.git - cd sleef - cmake -S . -B build \ - -DSLEEF_BUILD_QUAD:BOOL=ON \ - -DSLEEF_BUILD_SHARED_LIBS:BOOL=ON \ - -DCMAKE_POSITION_INDEPENDENT_CODE=ON \ - -DCMAKE_OSX_DEPLOYMENT_TARGET=${{ matrix.os == 'macos-13' && '13.0' || '14.0' }} \ - -DCMAKE_INSTALL_RPATH="@loader_path/../lib" \ - -DCMAKE_BUILD_WITH_INSTALL_RPATH=ON - cmake --build build/ --clean-first -j - sudo cmake --install build --prefix /usr/local - - name: Installing Python dependencies run: | pip install -U pip @@ -126,13 +97,6 @@ jobs: CIBW_ENABLE: cpython-prerelease cpython-freethreading CIBW_ARCHS_MACOS: ${{ matrix.os == 'macos-13' && 'x86_64' || 'arm64' }} CIBW_BUILD_VERBOSITY: "3" - CIBW_ENVIRONMENT: > - MACOSX_DEPLOYMENT_TARGET="${{ matrix.os == 'macos-13' && '13.0' || '14.0' }}" - DYLD_LIBRARY_PATH="/usr/local/lib:$DYLD_LIBRARY_PATH" - CFLAGS="-I/usr/local/include $CFLAGS" - CXXFLAGS="-I/usr/local/include $CXXFLAGS" - LDFLAGS="-L/usr/local/lib $LDFLAGS" - PKG_CONFIG_PATH="/usr/local/lib/pkgconfig:$PKG_CONFIG_PATH" CIBW_REPAIR_WHEEL_COMMAND: > delocate-wheel --require-archs {delocate_archs} -w {dest_dir} -v {wheel} CIBW_TEST_COMMAND: | @@ -177,15 +141,6 @@ jobs: - name: Install CMake uses: lukka/get-cmake@latest - - name: Clone and Build SLEEF - shell: pwsh - run: | - git clone --branch 3.8 https://github.com/shibatch/sleef.git - cd sleef - cmake -S . -B build -G "Visual Studio 17 2022" -A ${{ matrix.architecture == 'x86' && 'Win32' || 'x64' }} -DSLEEF_BUILD_QUAD:BOOL=ON -DSLEEF_BUILD_SHARED_LIBS:BOOL=ON -DCMAKE_POSITION_INDEPENDENT_CODE=ON - cmake --build build --config Release - cmake --install build --prefix "C:/sleef" --config Release - - name: Install build dependencies shell: bash -l {0} run: | @@ -204,12 +159,8 @@ jobs: CIBW_BEFORE_BUILD: | pip install meson meson-python ninja numpy CIBW_ENVIRONMENT: > - INCLUDE="C:/sleef/include;$INCLUDE" - LIB="C:/sleef/lib;$LIB" - PATH="C:/sleef/bin;$PATH" - CFLAGS="/IC:/sleef/include /DDISABLE_QUADBLAS $CFLAGS" - CXXFLAGS="/IC:/sleef/include /DDISABLE_QUADBLAS $CXXFLAGS" - LDFLAGS="C:/sleef/lib/sleef.lib C:/sleef/lib/sleefquad.lib $LDFLAGS" + CFLAGS="/DDISABLE_QUADBLAS $CFLAGS" + CXXFLAGS="/DDISABLE_QUADBLAS $CXXFLAGS" CIBW_REPAIR_WHEEL_COMMAND: 'delvewheel repair -w {dest_dir} {wheel} --add-path C:\sleef\bin' CIBW_TEST_COMMAND: | pip install {package}[test] @@ -247,17 +198,6 @@ jobs: sudo apt-get update -y sudo apt-get install -y cmake gcc g++ make git pkg-config - - name: Install SLEEF - run: | - git clone --branch 3.8 https://github.com/shibatch/sleef.git - cd sleef - cmake -S . -B build \ - -DSLEEF_BUILD_QUAD:BOOL=ON \ - -DSLEEF_BUILD_SHARED_LIBS:BOOL=ON \ - -DCMAKE_POSITION_INDEPENDENT_CODE=ON - cmake --build build/ --clean-first -j - sudo cmake --install build --prefix /usr/local - - name: Install build dependencies run: | python -m pip install --upgrade pip @@ -265,11 +205,7 @@ jobs: - name: Build SDist env: - CFLAGS: "-I/usr/local/include" - CXXFLAGS: "-I/usr/local/include" - LDFLAGS: "-L/usr/local/lib64 -L/usr/local/lib -Wl,-rpath,/usr/local/lib64 -Wl,-rpath,/usr/local/lib -fopenmp" - LD_LIBRARY_PATH: "/usr/local/lib64:/usr/local/lib:$LD_LIBRARY_PATH" - PKG_CONFIG_PATH: "/usr/local/lib64/pkgconfig:/usr/local/lib/pkgconfig:$PKG_CONFIG_PATH" + LDFLAGS: "-fopenmp" run: | python -m build --sdist --outdir dist/ working-directory: ./quaddtype diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b20b8211..c6a39d64 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -60,31 +60,13 @@ jobs: sudo apt-get update sudo apt-get install -y libmpfr-dev libssl-dev libfftw3-dev - - name: Install SLEEF - run: | - sudo apt-get update -y - sudo apt-get install -y cmake gcc g++ make git pkg-config - git clone --branch 3.8 https://github.com/shibatch/sleef.git - cd sleef - cmake -S . -B build -DSLEEF_BUILD_QUAD:BOOL=ON -DSLEEF_BUILD_SHARED_LIBS:BOOL=ON -DCMAKE_POSITION_INDEPENDENT_CODE=ON - cmake --build build/ --clean-first -j - sudo cmake --install build --prefix /usr/local - - name: Install quaddtype working-directory: quaddtype run: | - # Set environment variables with proper export and correct paths - export CFLAGS="-I/usr/local/include" - export CXXFLAGS="-I/usr/local/include" - export LDFLAGS="-L/usr/local/lib64 -L/usr/local/lib -Wl,-rpath,/usr/local/lib64 -Wl,-rpath,/usr/local/lib -fopenmp" - export LD_LIBRARY_PATH="/usr/local/lib64:/usr/local/lib:$LD_LIBRARY_PATH" + export LDFLAGS="-fopenmp" # Install with meson args to ensure the C++ flags are passed through - python -m pip install . -v --no-build-isolation \ - -Cbuilddir=build \ - -C'compile-args=-v' \ - -Csetup-args="-Dbuildtype=debug" \ - -Csetup-args="-Dcpp_args=-fext-numeric-literals" + python -m pip install . -v - name: Run quaddtype tests working-directory: quaddtype From 797fd82aac964aa53e8aa4e40de645457406eef9 Mon Sep 17 00:00:00 2001 From: swayaminsync Date: Sat, 6 Sep 2025 14:56:37 +0530 Subject: [PATCH 27/55] workflow: fixing macos deployment target and dynamic libs on linux --- .github/workflows/build_wheels.yml | 2 ++ .../subprojects/packagefiles/sleef/meson.build | 17 +++++++++-------- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/.github/workflows/build_wheels.yml b/.github/workflows/build_wheels.yml index 00b63267..35e21590 100644 --- a/.github/workflows/build_wheels.yml +++ b/.github/workflows/build_wheels.yml @@ -97,6 +97,8 @@ jobs: CIBW_ENABLE: cpython-prerelease cpython-freethreading CIBW_ARCHS_MACOS: ${{ matrix.os == 'macos-13' && 'x86_64' || 'arm64' }} CIBW_BUILD_VERBOSITY: "3" + CIBW_ENVIRONMENT: > + MACOSX_DEPLOYMENT_TARGET="${{ matrix.os == 'macos-13' && '13.0' || '14.0' }}" CIBW_REPAIR_WHEEL_COMMAND: > delocate-wheel --require-archs {delocate_archs} -w {dest_dir} -v {wheel} CIBW_TEST_COMMAND: | diff --git a/quaddtype/subprojects/packagefiles/sleef/meson.build b/quaddtype/subprojects/packagefiles/sleef/meson.build index a9118e2b..f3a0b219 100644 --- a/quaddtype/subprojects/packagefiles/sleef/meson.build +++ b/quaddtype/subprojects/packagefiles/sleef/meson.build @@ -3,10 +3,14 @@ project('sleef', version: '3.8') cmake = find_program('cmake') ninja = find_program('ninja', 'make', required: false) - sleef_build_dir = 'sleef_build' sleef_install_dir = 'sleef_install' +# This can be done manually from user side, but lets handle it here as well +libdir = 'lib' +if host_machine.system() == 'linux' and host_machine.cpu_family() == 'x86_64' + libdir = 'lib64' +endif sleef_configure = run_command([ cmake, @@ -14,7 +18,7 @@ sleef_configure = run_command([ '-B', meson.current_build_dir() / sleef_build_dir, '-DCMAKE_BUILD_TYPE=Release', '-DSLEEF_BUILD_QUAD=ON', - '-DBUILD_SHARED_LIBS=OFF', # building & linnking statically + '-DSLEEF_BUILD_SHARED_LIBS=OFF', '-DSLEEF_BUILD_TESTS=OFF', '-DSLEEF_BUILD_INLINE_HEADERS=OFF', '-DCMAKE_POSITION_INDEPENDENT_CODE=ON', @@ -25,26 +29,23 @@ if sleef_configure.returncode() != 0 error('SLEEF CMake configuration failed: ' + sleef_configure.stderr()) endif - sleef_build_target = custom_target('sleef_build', command: [cmake, '--build', meson.current_build_dir() / sleef_build_dir, '--target', 'install', '--parallel'], - output: 'sleef_built.stamp', + output: 'sleef_built.stamp', # Dummy stamp file console: true, build_always_stale: true, build_by_default: true ) sleef_include_path = meson.current_build_dir() / sleef_install_dir / 'include' -sleef_lib_path = meson.current_build_dir() / sleef_install_dir / 'lib' +sleef_lib_path = meson.current_build_dir() / sleef_install_dir / libdir sleef_build_dep = declare_dependency(sources: [sleef_build_target]) - sleef_dep = declare_dependency( - dependencies: [sleef_build_dep], + dependencies: [sleef_build_dep], compile_args: ['-I' + sleef_include_path], link_args: ['-L' + sleef_lib_path, '-lsleef'] ) - sleefquad_dep = declare_dependency( dependencies: [sleef_build_dep], compile_args: ['-I' + sleef_include_path], From 7c15c98c8d184dbbf8d8e0aa30cbccece84a3c7d Mon Sep 17 00:00:00 2001 From: swayaminsync Date: Sat, 6 Sep 2025 15:02:42 +0530 Subject: [PATCH 28/55] workflow: windows dlink fix --- .../packagefiles/sleef/meson.build | 24 +++++++++++++++---- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/quaddtype/subprojects/packagefiles/sleef/meson.build b/quaddtype/subprojects/packagefiles/sleef/meson.build index f3a0b219..6ca22f1c 100644 --- a/quaddtype/subprojects/packagefiles/sleef/meson.build +++ b/quaddtype/subprojects/packagefiles/sleef/meson.build @@ -3,15 +3,17 @@ project('sleef', version: '3.8') cmake = find_program('cmake') ninja = find_program('ninja', 'make', required: false) +# Use relative paths from build directory sleef_build_dir = 'sleef_build' sleef_install_dir = 'sleef_install' -# This can be done manually from user side, but lets handle it here as well +# Dynamically set libdir based on platform conventions libdir = 'lib' if host_machine.system() == 'linux' and host_machine.cpu_family() == 'x86_64' libdir = 'lib64' endif +# Configure SLEEF at configuration time sleef_configure = run_command([ cmake, '-S', meson.current_source_dir(), @@ -29,6 +31,7 @@ if sleef_configure.returncode() != 0 error('SLEEF CMake configuration failed: ' + sleef_configure.stderr()) endif +# Build target for SLEEF libraries - create a dummy output file sleef_build_target = custom_target('sleef_build', command: [cmake, '--build', meson.current_build_dir() / sleef_build_dir, '--target', 'install', '--parallel'], output: 'sleef_built.stamp', # Dummy stamp file @@ -37,17 +40,28 @@ sleef_build_target = custom_target('sleef_build', build_by_default: true ) +# Path variables sleef_include_path = meson.current_build_dir() / sleef_install_dir / 'include' sleef_lib_path = meson.current_build_dir() / sleef_install_dir / libdir +# Create a dependency that ensures the build happens but doesn't link the dummy file sleef_build_dep = declare_dependency(sources: [sleef_build_target]) + +# Platform-specific define for static linking on Windows +sleef_static_define = '' +if host_machine.system() == 'windows' + sleef_static_define = '-DSLEEF_STATIC_LIBS' +endif + +# Create the actual linking dependencies sleef_dep = declare_dependency( - dependencies: [sleef_build_dep], - compile_args: ['-I' + sleef_include_path], + dependencies: [sleef_build_dep], # Ensures build happens first + compile_args: ['-I' + sleef_include_path, sleef_static_define], link_args: ['-L' + sleef_lib_path, '-lsleef'] ) + sleefquad_dep = declare_dependency( - dependencies: [sleef_build_dep], - compile_args: ['-I' + sleef_include_path], + dependencies: [sleef_build_dep], # Ensures build happens first + compile_args: ['-I' + sleef_include_path, sleef_static_define], link_args: ['-L' + sleef_lib_path, '-lsleefquad'] ) \ No newline at end of file From 976f8ed1df4129b2aeed64973800677b7186f28d Mon Sep 17 00:00:00 2001 From: swayaminsync Date: Sat, 6 Sep 2025 15:38:06 +0530 Subject: [PATCH 29/55] workflow: -fopenmp for linux --- .github/workflows/build_wheels.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build_wheels.yml b/.github/workflows/build_wheels.yml index 35e21590..b4be2581 100644 --- a/.github/workflows/build_wheels.yml +++ b/.github/workflows/build_wheels.yml @@ -40,7 +40,7 @@ jobs: yum update -y yum install -y cmake gcc gcc-c++ make git pkgconfig CIBW_ENVIRONMENT: > - LDFLAGS="-fopenmp $LDFLAGS" + LDFLAGS="-fopenmp" CIBW_REPAIR_WHEEL_COMMAND: | auditwheel repair -w {dest_dir} --plat manylinux_2_28_x86_64 {wheel} CIBW_TEST_COMMAND: | From 2181a3d010a763d7e5bde5ff7cc1e441e4be46ca Mon Sep 17 00:00:00 2001 From: swayaminsync Date: Sat, 6 Sep 2025 15:52:37 +0530 Subject: [PATCH 30/55] workflow: fix empty shared lib --- quaddtype/subprojects/packagefiles/sleef/meson.build | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/quaddtype/subprojects/packagefiles/sleef/meson.build b/quaddtype/subprojects/packagefiles/sleef/meson.build index 6ca22f1c..514ab0a1 100644 --- a/quaddtype/subprojects/packagefiles/sleef/meson.build +++ b/quaddtype/subprojects/packagefiles/sleef/meson.build @@ -53,15 +53,19 @@ if host_machine.system() == 'windows' sleef_static_define = '-DSLEEF_STATIC_LIBS' endif -# Create the actual linking dependencies +compile_args_list = ['-I' + sleef_include_path] +if sleef_static_define != '' + compile_args_list += sleef_static_define +endif + sleef_dep = declare_dependency( dependencies: [sleef_build_dep], # Ensures build happens first - compile_args: ['-I' + sleef_include_path, sleef_static_define], + compile_args: compile_args_list, link_args: ['-L' + sleef_lib_path, '-lsleef'] ) sleefquad_dep = declare_dependency( dependencies: [sleef_build_dep], # Ensures build happens first - compile_args: ['-I' + sleef_include_path, sleef_static_define], + compile_args: compile_args_list, link_args: ['-L' + sleef_lib_path, '-lsleefquad'] ) \ No newline at end of file From 9bf047a3631a61651983966d928e8f07083ed6d7 Mon Sep 17 00:00:00 2001 From: swayaminsync Date: Sat, 6 Sep 2025 16:06:13 +0530 Subject: [PATCH 31/55] workflow: CI fix --- .github/workflows/ci.yml | 2 -- quaddtype/subprojects/packagefiles/sleef/meson.build | 3 --- 2 files changed, 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c6a39d64..55c3f2dd 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -64,8 +64,6 @@ jobs: working-directory: quaddtype run: | export LDFLAGS="-fopenmp" - - # Install with meson args to ensure the C++ flags are passed through python -m pip install . -v - name: Run quaddtype tests diff --git a/quaddtype/subprojects/packagefiles/sleef/meson.build b/quaddtype/subprojects/packagefiles/sleef/meson.build index 514ab0a1..a642b875 100644 --- a/quaddtype/subprojects/packagefiles/sleef/meson.build +++ b/quaddtype/subprojects/packagefiles/sleef/meson.build @@ -9,9 +9,6 @@ sleef_install_dir = 'sleef_install' # Dynamically set libdir based on platform conventions libdir = 'lib' -if host_machine.system() == 'linux' and host_machine.cpu_family() == 'x86_64' - libdir = 'lib64' -endif # Configure SLEEF at configuration time sleef_configure = run_command([ From 6ea6b33d7faaceafda00568927b20774d3f0c19d Mon Sep 17 00:00:00 2001 From: swayaminsync Date: Sat, 6 Sep 2025 16:18:52 +0530 Subject: [PATCH 32/55] workflow: redhat vs ubuntu --- .../subprojects/packagefiles/sleef/meson.build | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/quaddtype/subprojects/packagefiles/sleef/meson.build b/quaddtype/subprojects/packagefiles/sleef/meson.build index a642b875..1b8a5934 100644 --- a/quaddtype/subprojects/packagefiles/sleef/meson.build +++ b/quaddtype/subprojects/packagefiles/sleef/meson.build @@ -7,9 +7,6 @@ ninja = find_program('ninja', 'make', required: false) sleef_build_dir = 'sleef_build' sleef_install_dir = 'sleef_install' -# Dynamically set libdir based on platform conventions -libdir = 'lib' - # Configure SLEEF at configuration time sleef_configure = run_command([ cmake, @@ -39,8 +36,10 @@ sleef_build_target = custom_target('sleef_build', # Path variables sleef_include_path = meson.current_build_dir() / sleef_install_dir / 'include' -sleef_lib_path = meson.current_build_dir() / sleef_install_dir / libdir - +sleef_lib_paths = [ + meson.current_build_dir() / sleef_install_dir / 'lib', + meson.current_build_dir() / sleef_install_dir / 'lib64' +] # Create a dependency that ensures the build happens but doesn't link the dummy file sleef_build_dep = declare_dependency(sources: [sleef_build_target]) @@ -58,11 +57,11 @@ endif sleef_dep = declare_dependency( dependencies: [sleef_build_dep], # Ensures build happens first compile_args: compile_args_list, - link_args: ['-L' + sleef_lib_path, '-lsleef'] + link_args: ['-L' + p for p in sleef_lib_paths] + ['-lsleef'] ) sleefquad_dep = declare_dependency( dependencies: [sleef_build_dep], # Ensures build happens first compile_args: compile_args_list, - link_args: ['-L' + sleef_lib_path, '-lsleefquad'] + link_args: ['-L' + p for p in sleef_lib_paths] + ['-lsleefquad'] ) \ No newline at end of file From 1c1dd3ce5b573ba62e128fac3c7cc3b8eb06c958 Mon Sep 17 00:00:00 2001 From: swayaminsync Date: Sat, 6 Sep 2025 16:22:15 +0530 Subject: [PATCH 33/55] workflow: redhat vs ubuntu --- quaddtype/subprojects/packagefiles/sleef/meson.build | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/quaddtype/subprojects/packagefiles/sleef/meson.build b/quaddtype/subprojects/packagefiles/sleef/meson.build index 1b8a5934..17bf5e3b 100644 --- a/quaddtype/subprojects/packagefiles/sleef/meson.build +++ b/quaddtype/subprojects/packagefiles/sleef/meson.build @@ -57,11 +57,11 @@ endif sleef_dep = declare_dependency( dependencies: [sleef_build_dep], # Ensures build happens first compile_args: compile_args_list, - link_args: ['-L' + p for p in sleef_lib_paths] + ['-lsleef'] + link_args: ['-L' + meson.current_build_dir() / sleef_install_dir / 'lib', '-L' + meson.current_build_dir() / sleef_install_dir / 'lib64', '-lsleef'] ) sleefquad_dep = declare_dependency( dependencies: [sleef_build_dep], # Ensures build happens first compile_args: compile_args_list, - link_args: ['-L' + p for p in sleef_lib_paths] + ['-lsleefquad'] + link_args: ['-L' + meson.current_build_dir() / sleef_install_dir / 'lib', '-L' + meson.current_build_dir() / sleef_install_dir / 'lib64', '-lsleefquad'] ) \ No newline at end of file From 69a7a999f213544a725bb43e1bf0b593370bf6be Mon Sep 17 00:00:00 2001 From: swayaminsync Date: Sat, 6 Sep 2025 16:24:24 +0530 Subject: [PATCH 34/55] workflow: redhat vs ubuntu --- quaddtype/subprojects/packagefiles/sleef/meson.build | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/quaddtype/subprojects/packagefiles/sleef/meson.build b/quaddtype/subprojects/packagefiles/sleef/meson.build index 17bf5e3b..0ca37edc 100644 --- a/quaddtype/subprojects/packagefiles/sleef/meson.build +++ b/quaddtype/subprojects/packagefiles/sleef/meson.build @@ -36,10 +36,7 @@ sleef_build_target = custom_target('sleef_build', # Path variables sleef_include_path = meson.current_build_dir() / sleef_install_dir / 'include' -sleef_lib_paths = [ - meson.current_build_dir() / sleef_install_dir / 'lib', - meson.current_build_dir() / sleef_install_dir / 'lib64' -] + # Create a dependency that ensures the build happens but doesn't link the dummy file sleef_build_dep = declare_dependency(sources: [sleef_build_target]) From 77f1a8ed56eba35c966c61a88c06cea41099d193 Mon Sep 17 00:00:00 2001 From: swayaminsync Date: Sat, 6 Sep 2025 17:00:33 +0530 Subject: [PATCH 35/55] windows parllel build off --- .../packagefiles/sleef/meson.build | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/quaddtype/subprojects/packagefiles/sleef/meson.build b/quaddtype/subprojects/packagefiles/sleef/meson.build index 0ca37edc..20faeff4 100644 --- a/quaddtype/subprojects/packagefiles/sleef/meson.build +++ b/quaddtype/subprojects/packagefiles/sleef/meson.build @@ -3,11 +3,15 @@ project('sleef', version: '3.8') cmake = find_program('cmake') ninja = find_program('ninja', 'make', required: false) -# Use relative paths from build directory sleef_build_dir = 'sleef_build' sleef_install_dir = 'sleef_install' -# Configure SLEEF at configuration time +# turning off parallel build in windows +parallel_flag = ['--parallel'] +if host_machine.system() == 'windows' + parallel_flag = [] +endif + sleef_configure = run_command([ cmake, '-S', meson.current_source_dir(), @@ -25,22 +29,18 @@ if sleef_configure.returncode() != 0 error('SLEEF CMake configuration failed: ' + sleef_configure.stderr()) endif -# Build target for SLEEF libraries - create a dummy output file sleef_build_target = custom_target('sleef_build', - command: [cmake, '--build', meson.current_build_dir() / sleef_build_dir, '--target', 'install', '--parallel'], - output: 'sleef_built.stamp', # Dummy stamp file + command: [cmake, '--build', meson.current_build_dir() / sleef_build_dir, '--target', 'install'] + parallel_flag, + output: 'sleef_built.stamp', console: true, build_always_stale: true, build_by_default: true ) -# Path variables sleef_include_path = meson.current_build_dir() / sleef_install_dir / 'include' -# Create a dependency that ensures the build happens but doesn't link the dummy file sleef_build_dep = declare_dependency(sources: [sleef_build_target]) -# Platform-specific define for static linking on Windows sleef_static_define = '' if host_machine.system() == 'windows' sleef_static_define = '-DSLEEF_STATIC_LIBS' @@ -52,13 +52,13 @@ if sleef_static_define != '' endif sleef_dep = declare_dependency( - dependencies: [sleef_build_dep], # Ensures build happens first + dependencies: [sleef_build_dep], compile_args: compile_args_list, - link_args: ['-L' + meson.current_build_dir() / sleef_install_dir / 'lib', '-L' + meson.current_build_dir() / sleef_install_dir / 'lib64', '-lsleef'] + link_args: ['-L' + meson.current_build_dir() / sleef_install_dir / 'lib', '-L' + meson.current_build_dir() / sleef_install_dir / 'lib64', '-lsleef'] #both lib and lib64 because of ubuntu vs redhat compatibility ) sleefquad_dep = declare_dependency( - dependencies: [sleef_build_dep], # Ensures build happens first + dependencies: [sleef_build_dep], compile_args: compile_args_list, link_args: ['-L' + meson.current_build_dir() / sleef_install_dir / 'lib', '-L' + meson.current_build_dir() / sleef_install_dir / 'lib64', '-lsleefquad'] ) \ No newline at end of file From 4d8f1707198e46904667e9ad8fd54b18d2736208 Mon Sep 17 00:00:00 2001 From: swayaminsync Date: Sat, 6 Sep 2025 18:50:13 +0530 Subject: [PATCH 36/55] copying LISCENSE to quaddtype --- quaddtype/LICENSE | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 quaddtype/LICENSE diff --git a/quaddtype/LICENSE b/quaddtype/LICENSE new file mode 100644 index 00000000..6d6c9a5c --- /dev/null +++ b/quaddtype/LICENSE @@ -0,0 +1,30 @@ +Copyright (c) 2022, NumPy Developers. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + + * Neither the name of the NumPy Developers nor the names of any + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. From 1d028fa56910c6c4ecab979ae63aacfef45f3431 Mon Sep 17 00:00:00 2001 From: swayaminsync Date: Sat, 6 Sep 2025 18:55:15 +0530 Subject: [PATCH 37/55] liscense in toml --- quaddtype/pyproject.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/quaddtype/pyproject.toml b/quaddtype/pyproject.toml index b46b3737..2353ca64 100644 --- a/quaddtype/pyproject.toml +++ b/quaddtype/pyproject.toml @@ -12,6 +12,7 @@ name = "numpy_quaddtype" description = "Quad (128-bit) float dtype for numpy" version = "0.1.0" readme = 'README.md' +license = { file = "LICENSE" } authors = [{name = "Swayam Singh", email = "singhswayam008@gmail.com"}] requires-python = ">=3.10.0" dependencies = [ From 67fe2c505652a64638b5f331b5fdb6d12db0e70f Mon Sep 17 00:00:00 2001 From: swayaminsync Date: Sat, 6 Sep 2025 21:57:07 +0530 Subject: [PATCH 38/55] building and testing sdist --- .github/workflows/build_wheels.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build_wheels.yml b/.github/workflows/build_wheels.yml index b4be2581..cea8768c 100644 --- a/.github/workflows/build_wheels.yml +++ b/.github/workflows/build_wheels.yml @@ -205,11 +205,13 @@ jobs: python -m pip install --upgrade pip python -m pip install build - - name: Build SDist + - name: Build SDist & test sdist env: LDFLAGS: "-fopenmp" run: | python -m build --sdist --outdir dist/ + pip install dist/*.tar.gz + pytest -s {project}/tests working-directory: ./quaddtype - name: Upload SDist artifact From 78c1465d148e18d1ffe68096d684070ad881aa3f Mon Sep 17 00:00:00 2001 From: swayaminsync Date: Sat, 6 Sep 2025 22:00:03 +0530 Subject: [PATCH 39/55] verbose and dep --- .github/workflows/build_wheels.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build_wheels.yml b/.github/workflows/build_wheels.yml index cea8768c..30607ed2 100644 --- a/.github/workflows/build_wheels.yml +++ b/.github/workflows/build_wheels.yml @@ -203,14 +203,14 @@ jobs: - name: Install build dependencies run: | python -m pip install --upgrade pip - python -m pip install build + python -m pip install build pytest - name: Build SDist & test sdist env: LDFLAGS: "-fopenmp" run: | python -m build --sdist --outdir dist/ - pip install dist/*.tar.gz + pip install dist/*.tar.gz -v pytest -s {project}/tests working-directory: ./quaddtype From 58d59b96f47451dd5d4fc339cc0b319673632190 Mon Sep 17 00:00:00 2001 From: swayaminsync Date: Sat, 6 Sep 2025 22:04:59 +0530 Subject: [PATCH 40/55] verbose and dep --- .github/workflows/build_wheels.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build_wheels.yml b/.github/workflows/build_wheels.yml index 30607ed2..37cb8436 100644 --- a/.github/workflows/build_wheels.yml +++ b/.github/workflows/build_wheels.yml @@ -211,7 +211,7 @@ jobs: run: | python -m build --sdist --outdir dist/ pip install dist/*.tar.gz -v - pytest -s {project}/tests + pytest -s tests working-directory: ./quaddtype - name: Upload SDist artifact From e11c8df576a5a23709bd92ab8e6ce68121e6e089 Mon Sep 17 00:00:00 2001 From: swayaminsync Date: Sat, 6 Sep 2025 22:42:54 +0530 Subject: [PATCH 41/55] updating README --- quaddtype/README.md | 86 ++++++++++++--------------------------------- 1 file changed, 22 insertions(+), 64 deletions(-) diff --git a/quaddtype/README.md b/quaddtype/README.md index 35740398..53dff4c0 100644 --- a/quaddtype/README.md +++ b/quaddtype/README.md @@ -25,28 +25,18 @@ np.array([1,2,3], dtype=QuadPrecDType("longdouble")) ## Installation from source -The code needs the quad precision pieces of the sleef library, which is not available on most systems by default, so we have to generate that first. Choose the appropriate section below based on your operating system. - -### Linux/Unix/macOS +#### Prerequisites -The below assumes one has the required pieces to build sleef (cmake and libmpfr-dev), and that one is in the package directory locally. +- **gcc/clang** +- **CMake** (≥3.15) +- **Python 3.10+** +- **Git** -```bash -git clone --branch 3.8 https://github.com/shibatch/sleef.git -cd sleef -cmake -S . -B build -DSLEEF_BUILD_QUAD:BOOL=ON -DSLEEF_BUILD_SHARED_LIBS:BOOL=ON -DCMAKE_POSITION_INDEPENDENT_CODE=ON -cmake --build build/ --clean-first -j -cd .. -``` +### Linux/Unix/macOS Building the `numpy-quaddtype` package from locally installed sleef: ```bash -export SLEEF_DIR=$PWD/sleef/build -export LIBRARY_PATH=$SLEEF_DIR/lib -export C_INCLUDE_PATH=$SLEEF_DIR/include -export CPLUS_INCLUDE_PATH=$SLEEF_DIR/include - # setup the virtual env python3 -m venv temp source temp/bin/activate @@ -55,15 +45,13 @@ source temp/bin/activate pip install meson-python numpy pytest # If you see errors about a missing atomics library, you might need -latomic -export LDFLAGS="-Wl,-rpath,$SLEEF_DIR/lib -fopenmp -lpthread" -export CFLAGS="-fPIC" -export CXXFLAGS="-fPIC" +export LDFLAGS="-fopenmp -lpthread" # To build without QBLAS (default for MSVC) -# export CFLAGS="-fPIC -DDISABLE_QUADBLAS" -# export CXXFLAGS="-fPIC -DDISABLE_QUADBLAS" +# export CFLAGS="-DDISABLE_QUADBLAS" +# export CXXFLAGS="-DDISABLE_QUADBLAS" -python -m pip install . -v --no-build-isolation -Cbuilddir=build -C'compile-args=-v' +python -m pip install . -v --no-build-isolation # Run the tests cd .. @@ -76,7 +64,7 @@ python -m pytest - **Visual Studio 2017 or later** (with MSVC compiler) - **CMake** (≥3.15) -- **Python 3.10+** +- **Python 3.10+** - **Git** #### Step-by-Step Installation @@ -85,24 +73,7 @@ python -m pytest Open a **Developer Command Prompt for VS** or **Developer PowerShell for VS** to ensure MSVC is properly configured. -2. **Clone and Build SLEEF** - - ```powershell - # Clone SLEEF library - git clone --branch 3.8 https://github.com/shibatch/sleef.git - cd sleef - - # Configure with CMake for Windows - cmake -S . -B build -G "Visual Studio 17 2022" -A x64 -DSLEEF_BUILD_QUAD:BOOL=ON -DSLEEF_BUILD_SHARED_LIBS:BOOL=ON -DCMAKE_POSITION_INDEPENDENT_CODE=ON - - # Build and install SLEEF - cmake --build build --config Release - cmake --install build --prefix "C:/sleef" --config Release - - cd .. - ``` - -3. **Setup Python Environment** +2. **Setup Python Environment** ```powershell # Create and activate virtual environment @@ -114,46 +85,33 @@ python -m pytest pip install meson-python numpy pytest ninja meson ``` -4. **Set Environment Variables** +3. **Set Environment Variables** ```powershell - # Set up paths and compiler flags - $env:INCLUDE = "C:/sleef/include;$env:INCLUDE" - $env:LIB = "C:/sleef/lib;$env:LIB" - $env:PATH = "C:/sleef/bin;$env:PATH" - # Note: QBLAS is disabled on Windows due to MSVC compatibility issues - $env:CFLAGS = "/IC:/sleef/include /DDISABLE_QUADBLAS" - $env:CXXFLAGS = "/IC:/sleef/include /DDISABLE_QUADBLAS" - $env:LDFLAGS = "C:/sleef/lib/sleef.lib C:/sleef/lib/sleefquad.lib" + $env:CFLAGS = "/DDISABLE_QUADBLAS" + $env:CXXFLAGS = "/DDISABLE_QUADBLAS" ``` -5. **Build and Install numpy-quaddtype** +4. **Build and Install numpy-quaddtype** ```powershell - # Ensure submodules are initialized - git submodule update --init --recursive - # Build and install the package - python -m pip install . -v --no-build-isolation -Cbuilddir=build -C'compile-args=-v' + python -m pip install . -v --no-build-isolation ``` -6. **Test Installation** +5. **Test Installation** ```powershell # Run tests pytest -s tests/ ``` -1. **QBLAS Disabled**: QuadBLAS optimization is automatically disabled on Windows builds due to MSVC compatibility issues. This is handled by the `-DDISABLE_QUADBLAS` compiler flag. +6. **QBLAS Disabled**: QuadBLAS optimization is automatically disabled on Windows builds due to MSVC compatibility issues. This is handled by the `-DDISABLE_QUADBLAS` compiler flag. + +7. **Visual Studio Version**: The instructions assume Visual Studio 2022. For other versions, adjust the generator string: -2. **Visual Studio Version**: The instructions assume Visual Studio 2022. For other versions, adjust the generator string: - VS 2019: `"Visual Studio 16 2019"` - VS 2017: `"Visual Studio 15 2017"` -3. **Architecture**: The instructions are for x64. For x86 builds, change `-A x64` to `-A Win32`. - -4. **Alternative SLEEF Location**: If you prefer to install SLEEF elsewhere, update all path references accordingly. - -#### Windows Troubleshooting -- **Link errors**: Verify that `sleef.lib` and `sleefquad.lib` exist in `C:/sleef/lib/` \ No newline at end of file +8. **Architecture**: The instructions are for x64. For x86 builds, change `-A x64` to `-A Win32`. From b726f2192fc191095dc53a9fbb0c2a7e1ed80fb7 Mon Sep 17 00:00:00 2001 From: swayaminsync Date: Sat, 6 Sep 2025 23:34:10 +0530 Subject: [PATCH 42/55] small typos --- .gitignore | 2 +- quaddtype/README.md | 2 +- quaddtype/sdist_test.sh | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 540372fa..e004ae30 100644 --- a/.gitignore +++ b/.gitignore @@ -138,7 +138,7 @@ compile_commands.json .DS_Store .idea/ -# quddtype +# quaddtype /quaddtype/subprojects/qblas/ /quaddtype/subprojects/sleef/ .wraplock diff --git a/quaddtype/README.md b/quaddtype/README.md index 53dff4c0..36625cc5 100644 --- a/quaddtype/README.md +++ b/quaddtype/README.md @@ -34,7 +34,7 @@ np.array([1,2,3], dtype=QuadPrecDType("longdouble")) ### Linux/Unix/macOS -Building the `numpy-quaddtype` package from locally installed sleef: +Building the `numpy-quaddtype` package: ```bash # setup the virtual env diff --git a/quaddtype/sdist_test.sh b/quaddtype/sdist_test.sh index b38d7f90..786f05fd 100644 --- a/quaddtype/sdist_test.sh +++ b/quaddtype/sdist_test.sh @@ -7,4 +7,4 @@ fi python -m pip uninstall -y numpy_quaddtype python -m build --sdist --outdir dist/ -python -m pip install dist/numpy_quaddtype-0.1.0.tar.gz -v \ No newline at end of file +python -m pip install dist/*.tar.gz -v \ No newline at end of file From 6bd71e99591dccff6f19a385d9a56c4bb0ebddfb Mon Sep 17 00:00:00 2001 From: Swayam Date: Mon, 8 Sep 2025 21:24:04 +0530 Subject: [PATCH 43/55] Apply suggestion from @ngoldbaum Co-authored-by: Nathan Goldbaum --- quaddtype/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/quaddtype/README.md b/quaddtype/README.md index 36625cc5..2bfda4f5 100644 --- a/quaddtype/README.md +++ b/quaddtype/README.md @@ -51,7 +51,7 @@ export LDFLAGS="-fopenmp -lpthread" # export CFLAGS="-DDISABLE_QUADBLAS" # export CXXFLAGS="-DDISABLE_QUADBLAS" -python -m pip install . -v --no-build-isolation +python -m pip install . -v # Run the tests cd .. From f14424c5de5659848b810ec85aeef559fb04f8cd Mon Sep 17 00:00:00 2001 From: Swayam Date: Mon, 8 Sep 2025 21:29:35 +0530 Subject: [PATCH 44/55] README simpilifications suggestions --- quaddtype/README.md | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/quaddtype/README.md b/quaddtype/README.md index 2bfda4f5..86eae750 100644 --- a/quaddtype/README.md +++ b/quaddtype/README.md @@ -42,10 +42,7 @@ python3 -m venv temp source temp/bin/activate # Install the package -pip install meson-python numpy pytest - -# If you see errors about a missing atomics library, you might need -latomic -export LDFLAGS="-fopenmp -lpthread" +pip install numpy pytest # To build without QBLAS (default for MSVC) # export CFLAGS="-DDISABLE_QUADBLAS" @@ -82,7 +79,7 @@ python -m pytest # Install build dependencies pip install -U pip - pip install meson-python numpy pytest ninja meson + pip install numpy pytest ninja meson ``` 3. **Set Environment Variables** @@ -97,7 +94,7 @@ python -m pytest ```powershell # Build and install the package - python -m pip install . -v --no-build-isolation + python -m pip install . -v ``` 5. **Test Installation** From c7bbac1b8731650e60180092ed6297a33b8db2cd Mon Sep 17 00:00:00 2001 From: Juniper Tyree <50025784+juntyr@users.noreply.github.com> Date: Sun, 7 Sep 2025 11:43:25 +0000 Subject: [PATCH 45/55] Implement cast support for ubyte and half Implement cast support for ubyte Use template magic to distinguish npy_bool and npy_half Implement cast support for half --- quaddtype/meson.build | 11 ++- quaddtype/numpy_quaddtype/src/casts.cpp | 97 +++++++++++++++++++++---- quaddtype/tests/test_quaddtype.py | 10 +++ 3 files changed, 101 insertions(+), 17 deletions(-) diff --git a/quaddtype/meson.build b/quaddtype/meson.build index 69e4edf7..04b506b7 100644 --- a/quaddtype/meson.build +++ b/quaddtype/meson.build @@ -13,6 +13,8 @@ if is_windows add_project_arguments('-DWIN32', '-D_WINDOWS', language : ['c', 'cpp']) endif +qblas_dep = dependency('qblas', fallback: ['qblas', 'qblas_dep']) + sleef_subproj = subproject('sleef', required: true) sleef_dep = sleef_subproj.get_variable('sleef_dep') sleefquad_dep = sleef_subproj.get_variable('sleefquad_dep') @@ -22,10 +24,13 @@ incdir_numpy = run_command(py, check : true ).stdout().strip() -# OpenMP dependency (optional, for threading) +npymath_path = incdir_numpy / '..' / 'lib' +npymath_lib = c.find_library('npymath', dirs: npymath_path) + +dependencies = [py_dep, qblas_dep, sleef_dep, sleefquad_dep, npymath_lib] + +# Add OpenMP dependency (optional, for threading) openmp_dep = dependency('openmp', required: false) -qblas_dep = dependency('qblas', fallback: ['qblas', 'qblas_dep']) -dependencies = [py_dep, qblas_dep, sleef_dep, sleefquad_dep] if openmp_dep.found() dependencies += openmp_dep endif diff --git a/quaddtype/numpy_quaddtype/src/casts.cpp b/quaddtype/numpy_quaddtype/src/casts.cpp index c662b4d5..263f4fe9 100644 --- a/quaddtype/numpy_quaddtype/src/casts.cpp +++ b/quaddtype/numpy_quaddtype/src/casts.cpp @@ -9,6 +9,7 @@ extern "C" { #include #include "numpy/arrayobject.h" +#include "numpy/halffloat.h" #include "numpy/ndarraytypes.h" #include "numpy/dtype_api.h" } @@ -20,7 +21,7 @@ extern "C" { #include "casts.h" #include "dtype.h" -#define NUM_CASTS 29 // 14 to_casts + 14 from_casts + 1 quad_to_quad +#define NUM_CASTS 33 // 16 to_casts + 16 from_casts + 1 quad_to_quad static NPY_CASTING quad_to_quad_resolve_descriptors(PyObject *NPY_UNUSED(self), @@ -150,15 +151,26 @@ quad_to_quad_strided_loop_aligned(PyArrayMethod_Context *context, char *const da return 0; } +// Template magic to ensure npy_bool/npy_ubyte and npy_half/npy_ushort do not alias in templates +struct my_npy_bool {}; +struct my_npy_half {}; + +template +struct NpyType { typedef T TYPE; }; +template<> +struct NpyType{ typedef npy_bool TYPE; }; +template<> +struct NpyType{ typedef npy_half TYPE; }; + // Casting from other types to QuadDType template static inline quad_value -to_quad(T x, QuadBackendType backend); +to_quad(typename NpyType::TYPE x, QuadBackendType backend); template <> inline quad_value -to_quad(npy_bool x, QuadBackendType backend) +to_quad(npy_bool x, QuadBackendType backend) { quad_value result; if (backend == BACKEND_SLEEF) { @@ -184,6 +196,20 @@ to_quad(npy_byte x, QuadBackendType backend) return result; } +template <> +inline quad_value +to_quad(npy_ubyte x, QuadBackendType backend) +{ + quad_value result; + if (backend == BACKEND_SLEEF) { + result.sleef_value = Sleef_cast_from_uint64q1(x); + } + else { + result.longdouble_value = (long double)x; + } + return result; +} + template <> inline quad_value to_quad(npy_short x, QuadBackendType backend) @@ -295,6 +321,21 @@ to_quad(npy_ulonglong x, QuadBackendType backend) } return result; } + +template <> +inline quad_value +to_quad(npy_half x, QuadBackendType backend) +{ + quad_value result; + if (backend == BACKEND_SLEEF) { + result.sleef_value = Sleef_cast_from_doubleq1(npy_half_to_double(x)); + } + else { + result.longdouble_value = (long double)npy_half_to_double(x); + } + return result; +} + template <> inline quad_value to_quad(float x, QuadBackendType backend) @@ -374,10 +415,10 @@ numpy_to_quad_strided_loop_unaligned(PyArrayMethod_Context *context, char *const size_t elem_size = (backend == BACKEND_SLEEF) ? sizeof(Sleef_quad) : sizeof(long double); while (N--) { - T in_val; + typename NpyType::TYPE in_val; quad_value out_val; - memcpy(&in_val, in_ptr, sizeof(T)); + memcpy(&in_val, in_ptr, sizeof(typename NpyType::TYPE)); out_val = to_quad(in_val, backend); memcpy(out_ptr, &out_val, elem_size); @@ -401,7 +442,7 @@ numpy_to_quad_strided_loop_aligned(PyArrayMethod_Context *context, char *const d QuadBackendType backend = descr_out->backend; while (N--) { - T in_val = *(T *)in_ptr; + typename NpyType::TYPE in_val = *(typename NpyType::TYPE *)in_ptr; quad_value out_val = to_quad(in_val, backend); if (backend == BACKEND_SLEEF) { @@ -420,12 +461,12 @@ numpy_to_quad_strided_loop_aligned(PyArrayMethod_Context *context, char *const d // Casting from QuadDType to other types template -static inline T +static inline typename NpyType::TYPE from_quad(quad_value x, QuadBackendType backend); template <> inline npy_bool -from_quad(quad_value x, QuadBackendType backend) +from_quad(quad_value x, QuadBackendType backend) { if (backend == BACKEND_SLEEF) { return Sleef_cast_to_int64q1(x.sleef_value) != 0; @@ -447,6 +488,18 @@ from_quad(quad_value x, QuadBackendType backend) } } +template <> +inline npy_ubyte +from_quad(quad_value x, QuadBackendType backend) +{ + if (backend == BACKEND_SLEEF) { + return (npy_ubyte)Sleef_cast_to_uint64q1(x.sleef_value); + } + else { + return (npy_ubyte)x.longdouble_value; + } +} + template <> inline npy_short from_quad(quad_value x, QuadBackendType backend) @@ -543,6 +596,18 @@ from_quad(quad_value x, QuadBackendType backend) } } +template <> +inline npy_half +from_quad(quad_value x, QuadBackendType backend) +{ + if (backend == BACKEND_SLEEF) { + return npy_double_to_half(Sleef_cast_to_doubleq1(x.sleef_value)); + } + else { + return npy_double_to_half((double)x.longdouble_value); + } +} + template <> inline float from_quad(quad_value x, QuadBackendType backend) @@ -611,8 +676,8 @@ quad_to_numpy_strided_loop_unaligned(PyArrayMethod_Context *context, char *const quad_value in_val; memcpy(&in_val, in_ptr, elem_size); - T out_val = from_quad(in_val, backend); - memcpy(out_ptr, &out_val, sizeof(T)); + typename NpyType::TYPE out_val = from_quad(in_val, backend); + memcpy(out_ptr, &out_val, sizeof(typename NpyType::TYPE)); in_ptr += strides[0]; out_ptr += strides[1]; @@ -642,8 +707,8 @@ quad_to_numpy_strided_loop_aligned(PyArrayMethod_Context *context, char *const d in_val.longdouble_value = *(long double *)in_ptr; } - T out_val = from_quad(in_val, backend); - *(T *)(out_ptr) = out_val; + typename NpyType::TYPE out_val = from_quad(in_val, backend); + *(typename NpyType::TYPE *)(out_ptr) = out_val; in_ptr += strides[0]; out_ptr += strides[1]; @@ -739,8 +804,9 @@ init_casts_internal(void) add_spec(quad2quad_spec); - add_cast_to(&PyArray_BoolDType); + add_cast_to(&PyArray_BoolDType); add_cast_to(&PyArray_ByteDType); + add_cast_to(&PyArray_UByteDType); add_cast_to(&PyArray_ShortDType); add_cast_to(&PyArray_UShortDType); add_cast_to(&PyArray_IntDType); @@ -749,12 +815,14 @@ init_casts_internal(void) add_cast_to(&PyArray_ULongDType); add_cast_to(&PyArray_LongLongDType); add_cast_to(&PyArray_ULongLongDType); + add_cast_to(&PyArray_HalfDType); add_cast_to(&PyArray_FloatDType); add_cast_to(&PyArray_DoubleDType); add_cast_to(&PyArray_LongDoubleDType); - add_cast_from(&PyArray_BoolDType); + add_cast_from(&PyArray_BoolDType); add_cast_from(&PyArray_ByteDType); + add_cast_from(&PyArray_UByteDType); add_cast_from(&PyArray_ShortDType); add_cast_from(&PyArray_UShortDType); add_cast_from(&PyArray_IntDType); @@ -763,6 +831,7 @@ init_casts_internal(void) add_cast_from(&PyArray_ULongDType); add_cast_from(&PyArray_LongLongDType); add_cast_from(&PyArray_ULongLongDType); + add_cast_from(&PyArray_HalfDType); add_cast_from(&PyArray_FloatDType); add_cast_from(&PyArray_DoubleDType); add_cast_from(&PyArray_LongDoubleDType); diff --git a/quaddtype/tests/test_quaddtype.py b/quaddtype/tests/test_quaddtype.py index 1833c4e6..29f677b7 100644 --- a/quaddtype/tests/test_quaddtype.py +++ b/quaddtype/tests/test_quaddtype.py @@ -39,6 +39,16 @@ def test_finfo_int_constant(name, value): assert getattr(numpy_quaddtype, name) == value +@pytest.mark.parametrize("dtype", ["bool", "byte", "int8", "ubyte", "uint8", "short", "int16", "ushort", "uint16", "int", "int32", "uint", "uint32", "long", "ulong", "longlong", "int64", "ulonglong", "uint64", "half", "float16", "float", "float32", "double", "float64", "longdouble"]) +def test_astype(dtype): + orig = np.array(1, dtype=dtype) + quad = orig.astype(QuadPrecDType, casting="safe") + back = quad.astype(dtype, casting="unsafe") + + assert quad == 1 + assert back == orig + + def test_basic_equality(): assert QuadPrecision("12") == QuadPrecision( "12.0") == QuadPrecision("12.00") From d398884d20615bb5f55e1785c1da3898eb394572 Mon Sep 17 00:00:00 2001 From: Juniper Tyree <50025784+juntyr@users.noreply.github.com> Date: Tue, 9 Sep 2025 06:02:08 +0000 Subject: [PATCH 46/55] Test casting for all dtypes --- quaddtype/numpy_quaddtype/src/casts.cpp | 27 ++++++++++++----------- quaddtype/tests/test_quaddtype.py | 29 +++++++++++++++++++++++-- 2 files changed, 41 insertions(+), 15 deletions(-) diff --git a/quaddtype/numpy_quaddtype/src/casts.cpp b/quaddtype/numpy_quaddtype/src/casts.cpp index 263f4fe9..e351e608 100644 --- a/quaddtype/numpy_quaddtype/src/casts.cpp +++ b/quaddtype/numpy_quaddtype/src/casts.cpp @@ -151,16 +151,17 @@ quad_to_quad_strided_loop_aligned(PyArrayMethod_Context *context, char *const da return 0; } -// Template magic to ensure npy_bool/npy_ubyte and npy_half/npy_ushort do not alias in templates -struct my_npy_bool {}; -struct my_npy_half {}; +// Tag dispatching to ensure npy_bool/npy_ubyte and npy_half/npy_ushort do not alias in templates +// see e.g. https://stackoverflow.com/q/32522279 +struct spec_npy_bool {}; +struct spec_npy_half {}; template struct NpyType { typedef T TYPE; }; template<> -struct NpyType{ typedef npy_bool TYPE; }; +struct NpyType{ typedef npy_bool TYPE; }; template<> -struct NpyType{ typedef npy_half TYPE; }; +struct NpyType{ typedef npy_half TYPE; }; // Casting from other types to QuadDType @@ -170,7 +171,7 @@ to_quad(typename NpyType::TYPE x, QuadBackendType backend); template <> inline quad_value -to_quad(npy_bool x, QuadBackendType backend) +to_quad(npy_bool x, QuadBackendType backend) { quad_value result; if (backend == BACKEND_SLEEF) { @@ -324,7 +325,7 @@ to_quad(npy_ulonglong x, QuadBackendType backend) template <> inline quad_value -to_quad(npy_half x, QuadBackendType backend) +to_quad(npy_half x, QuadBackendType backend) { quad_value result; if (backend == BACKEND_SLEEF) { @@ -466,7 +467,7 @@ from_quad(quad_value x, QuadBackendType backend); template <> inline npy_bool -from_quad(quad_value x, QuadBackendType backend) +from_quad(quad_value x, QuadBackendType backend) { if (backend == BACKEND_SLEEF) { return Sleef_cast_to_int64q1(x.sleef_value) != 0; @@ -598,7 +599,7 @@ from_quad(quad_value x, QuadBackendType backend) template <> inline npy_half -from_quad(quad_value x, QuadBackendType backend) +from_quad(quad_value x, QuadBackendType backend) { if (backend == BACKEND_SLEEF) { return npy_double_to_half(Sleef_cast_to_doubleq1(x.sleef_value)); @@ -804,7 +805,7 @@ init_casts_internal(void) add_spec(quad2quad_spec); - add_cast_to(&PyArray_BoolDType); + add_cast_to(&PyArray_BoolDType); add_cast_to(&PyArray_ByteDType); add_cast_to(&PyArray_UByteDType); add_cast_to(&PyArray_ShortDType); @@ -815,12 +816,12 @@ init_casts_internal(void) add_cast_to(&PyArray_ULongDType); add_cast_to(&PyArray_LongLongDType); add_cast_to(&PyArray_ULongLongDType); - add_cast_to(&PyArray_HalfDType); + add_cast_to(&PyArray_HalfDType); add_cast_to(&PyArray_FloatDType); add_cast_to(&PyArray_DoubleDType); add_cast_to(&PyArray_LongDoubleDType); - add_cast_from(&PyArray_BoolDType); + add_cast_from(&PyArray_BoolDType); add_cast_from(&PyArray_ByteDType); add_cast_from(&PyArray_UByteDType); add_cast_from(&PyArray_ShortDType); @@ -831,7 +832,7 @@ init_casts_internal(void) add_cast_from(&PyArray_ULongDType); add_cast_from(&PyArray_LongLongDType); add_cast_from(&PyArray_ULongLongDType); - add_cast_from(&PyArray_HalfDType); + add_cast_from(&PyArray_HalfDType); add_cast_from(&PyArray_FloatDType); add_cast_from(&PyArray_DoubleDType); add_cast_from(&PyArray_LongDoubleDType); diff --git a/quaddtype/tests/test_quaddtype.py b/quaddtype/tests/test_quaddtype.py index 29f677b7..275541a0 100644 --- a/quaddtype/tests/test_quaddtype.py +++ b/quaddtype/tests/test_quaddtype.py @@ -39,8 +39,22 @@ def test_finfo_int_constant(name, value): assert getattr(numpy_quaddtype, name) == value -@pytest.mark.parametrize("dtype", ["bool", "byte", "int8", "ubyte", "uint8", "short", "int16", "ushort", "uint16", "int", "int32", "uint", "uint32", "long", "ulong", "longlong", "int64", "ulonglong", "uint64", "half", "float16", "float", "float32", "double", "float64", "longdouble"]) -def test_astype(dtype): +@pytest.mark.parametrize("dtype", [ + "bool", + "byte", "int8", "ubyte", "uint8", + "short", "int16", "ushort", "uint16", + "int", "int32", "uint", "uint32", + "long", "ulong", + "longlong", "int64", "ulonglong", "uint64", + "half", "float16", + "float", "float32", + "double", "float64", + "longdouble", "float96", "float128", +]) +def test_supported_astype(dtype): + if dtype in ("float96", "float128") and getattr(np, dtype, None) is None: + pytest.skip(f"{dtype} is unsupported on the current platform") + orig = np.array(1, dtype=dtype) quad = orig.astype(QuadPrecDType, casting="safe") back = quad.astype(dtype, casting="unsafe") @@ -49,6 +63,17 @@ def test_astype(dtype): assert back == orig +@pytest.mark.parametrize("dtype", ["S10", "U10", "T", "V10", "datetime64[ms]", "timedelta64[ms]"]) +def test_unsupported_astype(dtype): + val = 1 if dtype != "V10" else b"1" + + with pytest.raises(TypeError if dtype != "V10" else ValueError, match="cast"): + np.array(val, dtype=dtype).astype(QuadPrecDType, casting="unsafe") + + with pytest.raises(TypeError if dtype != "V10" else ValueError, match="cast"): + np.array(QuadPrecision(1)).astype(dtype, casting="unsafe") + + def test_basic_equality(): assert QuadPrecision("12") == QuadPrecision( "12.0") == QuadPrecision("12.00") From bc9412c340378e144c0b838a66a354470b21823a Mon Sep 17 00:00:00 2001 From: Juniper Tyree <50025784+juntyr@users.noreply.github.com> Date: Tue, 9 Sep 2025 06:11:16 +0000 Subject: [PATCH 47/55] Skip segfault test --- quaddtype/tests/test_quaddtype.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/quaddtype/tests/test_quaddtype.py b/quaddtype/tests/test_quaddtype.py index 275541a0..4ade4e3a 100644 --- a/quaddtype/tests/test_quaddtype.py +++ b/quaddtype/tests/test_quaddtype.py @@ -70,7 +70,10 @@ def test_unsupported_astype(dtype): with pytest.raises(TypeError if dtype != "V10" else ValueError, match="cast"): np.array(val, dtype=dtype).astype(QuadPrecDType, casting="unsafe") - with pytest.raises(TypeError if dtype != "V10" else ValueError, match="cast"): + if dtype == "V10": + pytest.xfail("cast from QuadPrecision to V10 segfaults") + + with pytest.raises(TypeError, match="cast"): np.array(QuadPrecision(1)).astype(dtype, casting="unsafe") From 4f6fbe6e92816937bcc9eef9cf2976af2e084dbb Mon Sep 17 00:00:00 2001 From: Juniper Tyree <50025784+juntyr@users.noreply.github.com> Date: Tue, 9 Sep 2025 06:25:52 +0000 Subject: [PATCH 48/55] More segfaults? --- quaddtype/tests/test_quaddtype.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/quaddtype/tests/test_quaddtype.py b/quaddtype/tests/test_quaddtype.py index 4ade4e3a..1319ac86 100644 --- a/quaddtype/tests/test_quaddtype.py +++ b/quaddtype/tests/test_quaddtype.py @@ -65,13 +65,11 @@ def test_supported_astype(dtype): @pytest.mark.parametrize("dtype", ["S10", "U10", "T", "V10", "datetime64[ms]", "timedelta64[ms]"]) def test_unsupported_astype(dtype): - val = 1 if dtype != "V10" else b"1" - - with pytest.raises(TypeError if dtype != "V10" else ValueError, match="cast"): - np.array(val, dtype=dtype).astype(QuadPrecDType, casting="unsafe") - if dtype == "V10": - pytest.xfail("cast from QuadPrecision to V10 segfaults") + pytest.xfail("casts to and from V10 segfault") + + with pytest.raises(TypeError, match="cast"): + np.array(1, dtype=dtype).astype(QuadPrecDType, casting="unsafe") with pytest.raises(TypeError, match="cast"): np.array(QuadPrecision(1)).astype(dtype, casting="unsafe") From 6a1057cd7233223313a77e3698768f420636c6f0 Mon Sep 17 00:00:00 2001 From: SwayamInSync Date: Tue, 9 Sep 2025 14:35:03 +0000 Subject: [PATCH 49/55] void->quad gives error than segfault --- quaddtype/numpy_quaddtype/src/casts.cpp | 40 ++++++++++++++++++++++++- quaddtype/reinstall.sh | 3 +- 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/quaddtype/numpy_quaddtype/src/casts.cpp b/quaddtype/numpy_quaddtype/src/casts.cpp index c662b4d5..8ae6e153 100644 --- a/quaddtype/numpy_quaddtype/src/casts.cpp +++ b/quaddtype/numpy_quaddtype/src/casts.cpp @@ -20,7 +20,7 @@ extern "C" { #include "casts.h" #include "dtype.h" -#define NUM_CASTS 29 // 14 to_casts + 14 from_casts + 1 quad_to_quad +#define NUM_CASTS 30 // 14 to_casts + 14 from_casts + 1 quad_to_quad + 1 void_to_quad static NPY_CASTING quad_to_quad_resolve_descriptors(PyObject *NPY_UNUSED(self), @@ -717,6 +717,26 @@ add_cast_to(PyArray_DTypeMeta *from) add_spec(spec); } +static NPY_CASTING +void_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) +{ + PyErr_SetString(PyExc_TypeError, + "Cannot cast void dtype to QuadPrecDType. " + "Void arrays contain arbitrary binary data that cannot be meaningfully converted to quad-precision floats."); + return (NPY_CASTING)-1; +} + +static int +void_to_quad_strided_loop(PyArrayMethod_Context *context, char *const data[], + npy_intp const dimensions[], npy_intp const strides[], + void *NPY_UNUSED(auxdata)) +{ + PyErr_SetString(PyExc_RuntimeError, "void_to_quad_strided_loop should not be called"); + return -1; +} + PyArrayMethod_Spec ** init_casts_internal(void) { @@ -739,6 +759,24 @@ init_casts_internal(void) add_spec(quad2quad_spec); + PyArray_DTypeMeta **void_dtypes = new PyArray_DTypeMeta *[2]{&PyArray_VoidDType, &QuadPrecDType}; + PyType_Slot *void_slots = new PyType_Slot[]{ + {NPY_METH_resolve_descriptors, (void *)&void_to_quad_resolve_descriptors}, + {NPY_METH_strided_loop, (void *)&void_to_quad_strided_loop}, + {NPY_METH_unaligned_strided_loop, (void *)&void_to_quad_strided_loop}, + {0, nullptr}}; + + PyArrayMethod_Spec *void_spec = new PyArrayMethod_Spec{ + .name = "cast_Void_to_QuadPrec_ERROR", + .nin = 1, + .nout = 1, + .casting = NPY_UNSAFE_CASTING, + .flags = NPY_METH_SUPPORTS_UNALIGNED, + .dtypes = void_dtypes, + .slots = void_slots, + }; + add_spec(void_spec); + add_cast_to(&PyArray_BoolDType); add_cast_to(&PyArray_ByteDType); add_cast_to(&PyArray_ShortDType); diff --git a/quaddtype/reinstall.sh b/quaddtype/reinstall.sh index b5e04876..5a028f1c 100755 --- a/quaddtype/reinstall.sh +++ b/quaddtype/reinstall.sh @@ -8,6 +8,7 @@ if [ -d "build/" ]; then rm -rf subprojects/sleef fi - +export CFLAGS="-g -O0" +export CXXFLAGS="-g -O0" python -m pip uninstall -y numpy_quaddtype python -m pip install . -v \ No newline at end of file From 9131f140411d47517ab9e94752d148d81700194b Mon Sep 17 00:00:00 2001 From: SwayamInSync Date: Tue, 9 Sep 2025 17:03:32 +0000 Subject: [PATCH 50/55] updating branch --- quaddtype/numpy_quaddtype/src/casts.cpp | 42 ++++++++++++------------- quaddtype/tests/test_quaddtype.py | 13 ++++---- 2 files changed, 28 insertions(+), 27 deletions(-) diff --git a/quaddtype/numpy_quaddtype/src/casts.cpp b/quaddtype/numpy_quaddtype/src/casts.cpp index fa84cb75..bfd42966 100644 --- a/quaddtype/numpy_quaddtype/src/casts.cpp +++ b/quaddtype/numpy_quaddtype/src/casts.cpp @@ -151,6 +151,27 @@ quad_to_quad_strided_loop_aligned(PyArrayMethod_Context *context, char *const da return 0; } + +static NPY_CASTING +void_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) +{ + PyErr_SetString(PyExc_TypeError, + "Void to QuadPrecision cast is not implemented"); + return (NPY_CASTING)-1; +} + +static int +void_to_quad_strided_loop(PyArrayMethod_Context *context, char *const data[], + npy_intp const dimensions[], npy_intp const strides[], + void *NPY_UNUSED(auxdata)) +{ + PyErr_SetString(PyExc_RuntimeError, "void_to_quad_strided_loop should not be called"); + return -1; +} + + // Tag dispatching to ensure npy_bool/npy_ubyte and npy_half/npy_ushort do not alias in templates // see e.g. https://stackoverflow.com/q/32522279 struct spec_npy_bool {}; @@ -783,26 +804,6 @@ add_cast_to(PyArray_DTypeMeta *from) add_spec(spec); } -static NPY_CASTING -void_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) -{ - PyErr_SetString(PyExc_TypeError, - "Cannot cast void dtype to QuadPrecDType. " - "Void arrays contain arbitrary binary data that cannot be meaningfully converted to quad-precision floats."); - return (NPY_CASTING)-1; -} - -static int -void_to_quad_strided_loop(PyArrayMethod_Context *context, char *const data[], - npy_intp const dimensions[], npy_intp const strides[], - void *NPY_UNUSED(auxdata)) -{ - PyErr_SetString(PyExc_RuntimeError, "void_to_quad_strided_loop should not be called"); - return -1; -} - PyArrayMethod_Spec ** init_casts_internal(void) { @@ -843,7 +844,6 @@ init_casts_internal(void) }; add_spec(void_spec); - add_cast_to(&PyArray_BoolDType); add_cast_to(&PyArray_BoolDType); add_cast_to(&PyArray_ByteDType); add_cast_to(&PyArray_UByteDType); diff --git a/quaddtype/tests/test_quaddtype.py b/quaddtype/tests/test_quaddtype.py index 1319ac86..a761df14 100644 --- a/quaddtype/tests/test_quaddtype.py +++ b/quaddtype/tests/test_quaddtype.py @@ -66,13 +66,14 @@ def test_supported_astype(dtype): @pytest.mark.parametrize("dtype", ["S10", "U10", "T", "V10", "datetime64[ms]", "timedelta64[ms]"]) def test_unsupported_astype(dtype): if dtype == "V10": - pytest.xfail("casts to and from V10 segfault") - - with pytest.raises(TypeError, match="cast"): - np.array(1, dtype=dtype).astype(QuadPrecDType, casting="unsafe") + with pytest.raises(TypeError, match="cast"): + np.ones((3, 3), dtype="V10").astype(QuadPrecDType, casting="unsafe") + else: + with pytest.raises(TypeError, match="cast"): + np.array(1, dtype=dtype).astype(QuadPrecDType, casting="unsafe") - with pytest.raises(TypeError, match="cast"): - np.array(QuadPrecision(1)).astype(dtype, casting="unsafe") + with pytest.raises(TypeError, match="cast"): + np.array(QuadPrecision(1)).astype(dtype, casting="unsafe") def test_basic_equality(): From dff30c015193fa2793c543a7733194437881ec91 Mon Sep 17 00:00:00 2001 From: SwayamInSync Date: Thu, 11 Sep 2025 17:06:52 +0000 Subject: [PATCH 51/55] avoid direct union casting, bad --- quaddtype/numpy_quaddtype/src/umath/comparison_ops.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/quaddtype/numpy_quaddtype/src/umath/comparison_ops.cpp b/quaddtype/numpy_quaddtype/src/umath/comparison_ops.cpp index 095b6d39..e4b9579c 100644 --- a/quaddtype/numpy_quaddtype/src/umath/comparison_ops.cpp +++ b/quaddtype/numpy_quaddtype/src/umath/comparison_ops.cpp @@ -121,15 +121,19 @@ quad_generic_comp_strided_loop_aligned(PyArrayMethod_Context *context, char *con QuadPrecDTypeObject *descr = (QuadPrecDTypeObject *)context->descriptors[0]; QuadBackendType backend = descr->backend; while (N--) { - quad_value in1 = *(quad_value *)in1_ptr; - quad_value in2 = *(quad_value *)in2_ptr; + quad_value in1; + quad_value in2; npy_bool result; if (backend == BACKEND_SLEEF) { + in1.sleef_value = *(Sleef_quad *)in1_ptr; + in2.sleef_value = *(Sleef_quad *)in2_ptr; result = sleef_comp(&in1.sleef_value, &in2.sleef_value); } else { + in1.longdouble_value = *(long double *)in1_ptr; + in2.longdouble_value = *(long double *)in2_ptr; result = ld_comp(&in1.longdouble_value, &in2.longdouble_value); } From bcc67e60b9f707b888b7328fb575c7e5b547d460 Mon Sep 17 00:00:00 2001 From: SwayamInSync Date: Thu, 11 Sep 2025 19:14:26 +0000 Subject: [PATCH 52/55] bumping version to 0.2 --- quaddtype/pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/quaddtype/pyproject.toml b/quaddtype/pyproject.toml index 2353ca64..466b5231 100644 --- a/quaddtype/pyproject.toml +++ b/quaddtype/pyproject.toml @@ -10,7 +10,7 @@ build-backend = "mesonpy" [project] name = "numpy_quaddtype" description = "Quad (128-bit) float dtype for numpy" -version = "0.1.0" +version = "0.2.0" readme = 'README.md' license = { file = "LICENSE" } authors = [{name = "Swayam Singh", email = "singhswayam008@gmail.com"}] From 9a7147abdfe9004695c262b89d619d9c755197af Mon Sep 17 00:00:00 2001 From: SwayamInSync Date: Thu, 11 Sep 2025 20:10:34 +0000 Subject: [PATCH 53/55] switching to macos-14, 15 --- .github/workflows/build_wheels.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build_wheels.yml b/.github/workflows/build_wheels.yml index 37cb8436..6b205d96 100644 --- a/.github/workflows/build_wheels.yml +++ b/.github/workflows/build_wheels.yml @@ -65,7 +65,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - os: [macos-13, macos-14] + os: [macos-14, macos-15] steps: - uses: actions/checkout@v3 From 89745f0625d0bdeed14961564ae8947428f0337f Mon Sep 17 00:00:00 2001 From: SwayamInSync Date: Thu, 11 Sep 2025 20:14:31 +0000 Subject: [PATCH 54/55] updating macos deployment target --- .github/workflows/build_wheels.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build_wheels.yml b/.github/workflows/build_wheels.yml index 6b205d96..5703886e 100644 --- a/.github/workflows/build_wheels.yml +++ b/.github/workflows/build_wheels.yml @@ -95,10 +95,10 @@ jobs: env: CIBW_BUILD: "cp310-* cp311-* cp312-* cp313-* cp314-* cp313t-* cp314t-*" CIBW_ENABLE: cpython-prerelease cpython-freethreading - CIBW_ARCHS_MACOS: ${{ matrix.os == 'macos-13' && 'x86_64' || 'arm64' }} + # CIBW_ARCHS_MACOS: ${{ matrix.os == 'macos-13' && 'x86_64' || 'arm64' }} CIBW_BUILD_VERBOSITY: "3" CIBW_ENVIRONMENT: > - MACOSX_DEPLOYMENT_TARGET="${{ matrix.os == 'macos-13' && '13.0' || '14.0' }}" + MACOSX_DEPLOYMENT_TARGET="${{ matrix.os == 'macos-14' && '14.0' || '15.0' }}" CIBW_REPAIR_WHEEL_COMMAND: > delocate-wheel --require-archs {delocate_archs} -w {dest_dir} -v {wheel} CIBW_TEST_COMMAND: | From c3dd685438a4f993b008ff4b0073fa5c23a5630a Mon Sep 17 00:00:00 2001 From: Swayam Date: Fri, 12 Sep 2025 16:05:43 +0530 Subject: [PATCH 55/55] CI: Windows Pytest fix (#150) --- .github/workflows/build_wheels.yml | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/.github/workflows/build_wheels.yml b/.github/workflows/build_wheels.yml index 5703886e..5ec5bcea 100644 --- a/.github/workflows/build_wheels.yml +++ b/.github/workflows/build_wheels.yml @@ -164,15 +164,8 @@ jobs: CFLAGS="/DDISABLE_QUADBLAS $CFLAGS" CXXFLAGS="/DDISABLE_QUADBLAS $CXXFLAGS" CIBW_REPAIR_WHEEL_COMMAND: 'delvewheel repair -w {dest_dir} {wheel} --add-path C:\sleef\bin' - CIBW_TEST_COMMAND: | - pip install {package}[test] - if python -c "import sys; exit(0 if hasattr(sys, '_is_gil_enabled') and not sys._is_gil_enabled() else 1)"; then - pytest --parallel-threads=10 --iterations=10 {project}/tests - else - pytest -s {project}/tests - fi + CIBW_TEST_COMMAND_WINDOWS: pip install {package}[test] && pytest -s {project}/tests CIBW_TEST_EXTRAS: test - CIBW_TEST_FAIL_FAST: 1 shell: pwsh run: | python -m cibuildwheel --output-dir wheelhouse