From fea68bd3b9e4b695926c5bb2b61b47f5c0bfa31b Mon Sep 17 00:00:00 2001 From: SwayamInSync Date: Mon, 6 Oct 2025 11:01:21 +0000 Subject: [PATCH 1/3] small init fixes --- quaddtype/numpy_quaddtype/src/dtype.c | 1 - quaddtype/numpy_quaddtype/src/scalar.c | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/quaddtype/numpy_quaddtype/src/dtype.c b/quaddtype/numpy_quaddtype/src/dtype.c index 7d0fad37..b10d16df 100644 --- a/quaddtype/numpy_quaddtype/src/dtype.c +++ b/quaddtype/numpy_quaddtype/src/dtype.c @@ -184,7 +184,6 @@ static PyType_Slot QuadPrecDType_Slots[] = { {NPY_DT_setitem, &quadprec_setitem}, {NPY_DT_getitem, &quadprec_getitem}, {NPY_DT_default_descr, &quadprec_default_descr}, - {NPY_DT_PyArray_ArrFuncs_dotfunc, NULL}, {0, NULL}}; static PyObject * diff --git a/quaddtype/numpy_quaddtype/src/scalar.c b/quaddtype/numpy_quaddtype/src/scalar.c index 6d82d198..8c83f3fb 100644 --- a/quaddtype/numpy_quaddtype/src/scalar.c +++ b/quaddtype/numpy_quaddtype/src/scalar.c @@ -253,5 +253,6 @@ PyTypeObject QuadPrecision_Type = { int init_quadprecision_scalar(void) { + QuadPrecision_Type.tp_base = &PyFloatingArrType_Type; return PyType_Ready(&QuadPrecision_Type); } \ No newline at end of file From 317a961c9f777b475bfdd75811b863559b330745 Mon Sep 17 00:00:00 2001 From: SwayamInSync Date: Mon, 6 Oct 2025 11:02:17 +0000 Subject: [PATCH 2/3] small changes to reinstall.sh --- quaddtype/reinstall.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/quaddtype/reinstall.sh b/quaddtype/reinstall.sh index 5a028f1c..89e19194 100755 --- a/quaddtype/reinstall.sh +++ b/quaddtype/reinstall.sh @@ -8,7 +8,7 @@ if [ -d "build/" ]; then rm -rf subprojects/sleef fi -export CFLAGS="-g -O0" -export CXXFLAGS="-g -O0" +# 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 +python -m pip install . -v --no-build-isolation 2>&1 | tee build_log.txt \ No newline at end of file From 8ba5167e5b579590edfdc8e08a0d13cc2032e6a2 Mon Sep 17 00:00:00 2001 From: SwayamInSync Date: Mon, 6 Oct 2025 12:58:25 +0000 Subject: [PATCH 3/3] constant refactor and initial finfo support --- quaddtype/meson.build | 1 + quaddtype/numpy_quaddtype/src/constants.hpp | 133 ++++++++++++++++++ quaddtype/numpy_quaddtype/src/dtype.c | 86 +++++++++++ .../numpy_quaddtype/src/quaddtype_main.c | 102 +++----------- quaddtype/tests/test_finfo.py | 130 +++++++++++++++++ quaddtype/tests/test_quaddtype.py | 9 -- 6 files changed, 371 insertions(+), 90 deletions(-) create mode 100644 quaddtype/numpy_quaddtype/src/constants.hpp create mode 100644 quaddtype/tests/test_finfo.py diff --git a/quaddtype/meson.build b/quaddtype/meson.build index 75e9e382..5c851b11 100644 --- a/quaddtype/meson.build +++ b/quaddtype/meson.build @@ -117,6 +117,7 @@ srcs = [ 'numpy_quaddtype/src/umath/promoters.hpp', 'numpy_quaddtype/src/umath/matmul.h', 'numpy_quaddtype/src/umath/matmul.cpp', + 'numpy_quaddtype/src/constants.hpp', ] py.install_sources( diff --git a/quaddtype/numpy_quaddtype/src/constants.hpp b/quaddtype/numpy_quaddtype/src/constants.hpp new file mode 100644 index 00000000..c2c41260 --- /dev/null +++ b/quaddtype/numpy_quaddtype/src/constants.hpp @@ -0,0 +1,133 @@ +#ifndef QUAD_CONSTANTS_HPP +#define QUAD_CONSTANTS_HPP + +#include +#include +#include +#include + +// Quad precision constants using sleef_q macro +#define QUAD_PRECISION_ZERO sleef_q(+0x0000000000000LL, 0x0000000000000000ULL, -16383) +#define QUAD_PRECISION_ONE sleef_q(+0x1000000000000LL, 0x0000000000000000ULL, 0) +#define QUAD_PRECISION_INF sleef_q(+0x1000000000000LL, 0x0000000000000000ULL, 16384) +#define QUAD_PRECISION_NINF sleef_q(-0x1000000000000LL, 0x0000000000000000ULL, 16384) +#define QUAD_PRECISION_NAN sleef_q(+0x1ffffffffffffLL, 0xffffffffffffffffULL, 16384) + +// Additional constants +#define QUAD_PRECISION_MAX_FINITE SLEEF_QUAD_MAX +#define QUAD_PRECISION_MIN_FINITE Sleef_negq1(SLEEF_QUAD_MAX) +#define QUAD_PRECISION_RADIX sleef_q(+0x1000000000000LL, 0x0000000000000000ULL, 1) // 2.0 + +#ifdef SLEEF_QUAD_C +static const Sleef_quad SMALLEST_SUBNORMAL_VALUE = SLEEF_QUAD_DENORM_MIN; +#else +static const union { + struct { +#if defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) + uint64_t h, l; +#else + uint64_t l, h; +#endif + } parts; + Sleef_quad value; +} smallest_subnormal_const = {.parts = { +#if defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) + .h = 0x0000000000000000ULL, .l = 0x0000000000000001ULL +#else + .l = 0x0000000000000001ULL, .h = 0x0000000000000000ULL +#endif + }}; +#define SMALLEST_SUBNORMAL_VALUE (smallest_subnormal_const.value) +#endif + +// Integer constants for finfo +#define QUAD_NMANT 112 // mantissa bits (excluding implicit bit) +#define QUAD_MIN_EXP -16382 // minimum exponent for normalized numbers +#define QUAD_MAX_EXP 16384 // maximum exponent +#define QUAD_DECIMAL_DIGITS 33 // decimal digits of precision + +typedef enum ConstantResultType { + CONSTANT_QUAD, // Sleef_quad value + CONSTANT_INT64, // int64_t value + CONSTANT_ERROR // Error occurred +} ConstantResultType; + +typedef struct ConstantResult { + ConstantResultType type; + union { + Sleef_quad quad_value; + int64_t int_value; + } data; +} ConstantResult; + + +static inline ConstantResult get_sleef_constant_by_name(const char* constant_name) { + ConstantResult result; + + if (strcmp(constant_name, "pi") == 0) { + result.type = CONSTANT_QUAD; + result.data.quad_value = SLEEF_M_PIq; + } + else if (strcmp(constant_name, "e") == 0) { + result.type = CONSTANT_QUAD; + result.data.quad_value = SLEEF_M_Eq; + } + else if (strcmp(constant_name, "log2e") == 0) { + result.type = CONSTANT_QUAD; + result.data.quad_value = SLEEF_M_LOG2Eq; + } + else if (strcmp(constant_name, "log10e") == 0) { + result.type = CONSTANT_QUAD; + result.data.quad_value = SLEEF_M_LOG10Eq; + } + else if (strcmp(constant_name, "ln2") == 0) { + result.type = CONSTANT_QUAD; + result.data.quad_value = SLEEF_M_LN2q; + } + else if (strcmp(constant_name, "ln10") == 0) { + result.type = CONSTANT_QUAD; + result.data.quad_value = SLEEF_M_LN10q; + } + else if (strcmp(constant_name, "max_value") == 0) { + result.type = CONSTANT_QUAD; + result.data.quad_value = SLEEF_QUAD_MAX; + } + else if (strcmp(constant_name, "epsilon") == 0) { + result.type = CONSTANT_QUAD; + result.data.quad_value = SLEEF_QUAD_EPSILON; + } + else if (strcmp(constant_name, "smallest_normal") == 0) { + result.type = CONSTANT_QUAD; + result.data.quad_value = SLEEF_QUAD_MIN; + } + else if (strcmp(constant_name, "smallest_subnormal") == 0) { + result.type = CONSTANT_QUAD; + result.data.quad_value = SMALLEST_SUBNORMAL_VALUE; + } + else if (strcmp(constant_name, "bits") == 0) { + result.type = CONSTANT_INT64; + result.data.int_value = sizeof(Sleef_quad) * 8; + } + else if (strcmp(constant_name, "precision") == 0) { + result.type = CONSTANT_INT64; + // precision = int(-log10(epsilon)) + result.data.int_value = + Sleef_cast_to_int64q1(Sleef_negq1(Sleef_log10q1_u10(SLEEF_QUAD_EPSILON))); + } + else if (strcmp(constant_name, "resolution") == 0) { + result.type = CONSTANT_QUAD; + // precision = int(-log10(epsilon)) + int64_t precision = + Sleef_cast_to_int64q1(Sleef_negq1(Sleef_log10q1_u10(SLEEF_QUAD_EPSILON))); + // resolution = 10 ** (-precision) + result.data.quad_value = + Sleef_powq1_u10(Sleef_cast_from_int64q1(10), Sleef_cast_from_int64q1(-precision)); + } + else { + result.type = CONSTANT_ERROR; + } + + return result; +} + +#endif // QUAD_CONSTANTS_HPP \ No newline at end of file diff --git a/quaddtype/numpy_quaddtype/src/dtype.c b/quaddtype/numpy_quaddtype/src/dtype.c index b10d16df..5e1da52a 100644 --- a/quaddtype/numpy_quaddtype/src/dtype.c +++ b/quaddtype/numpy_quaddtype/src/dtype.c @@ -16,6 +16,7 @@ #include "casts.h" #include "dtype.h" #include "dragon4.h" +#include "constants.hpp" static inline int quad_load(void *x, char *data_ptr, QuadBackendType backend) @@ -176,6 +177,90 @@ quadprec_default_descr(PyArray_DTypeMeta *cls) return (PyArray_Descr *)temp; } +static int +quadprec_get_constant(PyArray_Descr *descr, int constant_id, void *ptr) +{ + QuadPrecDTypeObject *quad_descr = (QuadPrecDTypeObject *)descr; + + if (quad_descr->backend != BACKEND_SLEEF) { + /* Long double backend not yet implemented */ + return 0; + } + + Sleef_quad val; + + switch (constant_id) { + case NPY_CONSTANT_zero: + val = QUAD_PRECISION_ZERO; + break; + + case NPY_CONSTANT_one: + val = QUAD_PRECISION_ONE; + break; + + case NPY_CONSTANT_minimum_finite: + val = QUAD_PRECISION_MIN_FINITE; + break; + + case NPY_CONSTANT_maximum_finite: + val = QUAD_PRECISION_MAX_FINITE; + break; + + case NPY_CONSTANT_inf: + val = QUAD_PRECISION_INF; + break; + + case NPY_CONSTANT_ninf: + val = QUAD_PRECISION_NINF; + break; + + case NPY_CONSTANT_nan: + val = QUAD_PRECISION_NAN; + break; + + case NPY_CONSTANT_finfo_radix: + val = QUAD_PRECISION_RADIX; + break; + + case NPY_CONSTANT_finfo_eps: + val = SLEEF_QUAD_EPSILON; + break; + + case NPY_CONSTANT_finfo_smallest_normal: + val = SLEEF_QUAD_MIN; + break; + + case NPY_CONSTANT_finfo_smallest_subnormal: + val = SMALLEST_SUBNORMAL_VALUE; + break; + + /* Integer constants - these return npy_intp values */ + case NPY_CONSTANT_finfo_nmant: + *(npy_intp *)ptr = QUAD_NMANT; + return 1; + + case NPY_CONSTANT_finfo_min_exp: + *(npy_intp *)ptr = QUAD_MIN_EXP; + return 1; + + case NPY_CONSTANT_finfo_max_exp: + *(npy_intp *)ptr = QUAD_MAX_EXP; + return 1; + + case NPY_CONSTANT_finfo_decimal_digits: + *(npy_intp *)ptr = QUAD_DECIMAL_DIGITS; + return 1; + + default: + /* Constant not supported */ + return 0; + } + + /* Store the Sleef_quad value to the provided pointer */ + *(Sleef_quad *)ptr = val; + return 1; +} + static PyType_Slot QuadPrecDType_Slots[] = { {NPY_DT_ensure_canonical, &ensure_canonical}, {NPY_DT_common_instance, &common_instance}, @@ -184,6 +269,7 @@ static PyType_Slot QuadPrecDType_Slots[] = { {NPY_DT_setitem, &quadprec_setitem}, {NPY_DT_getitem, &quadprec_getitem}, {NPY_DT_default_descr, &quadprec_default_descr}, + {NPY_DT_get_constant, &quadprec_get_constant}, {0, NULL}}; static PyObject * diff --git a/quaddtype/numpy_quaddtype/src/quaddtype_main.c b/quaddtype/numpy_quaddtype/src/quaddtype_main.c index b8c2bc42..0cbb6523 100644 --- a/quaddtype/numpy_quaddtype/src/quaddtype_main.c +++ b/quaddtype/numpy_quaddtype/src/quaddtype_main.c @@ -17,6 +17,7 @@ #include "umath/umath.h" #include "quad_common.h" #include "quadblas_interface.h" +#include "constants.hpp" #include "float.h" static PyObject * @@ -30,28 +31,6 @@ py_is_longdouble_128(PyObject *self, PyObject *args) } } -#ifdef SLEEF_QUAD_C -static const Sleef_quad SMALLEST_SUBNORMAL_VALUE = SLEEF_QUAD_DENORM_MIN; -#else -static const union { - struct { -#if 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 = { -#if defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) - .h = 0x0000000000000000ULL, .l = 0x0000000000000001ULL -#else - .l = 0x0000000000000001ULL, .h = 0x0000000000000000ULL -#endif - }}; -#define SMALLEST_SUBNORMAL_VALUE (smallest_subnormal_const.value) -#endif - static PyObject * get_sleef_constant(PyObject *self, PyObject *args) { @@ -60,68 +39,29 @@ get_sleef_constant(PyObject *self, PyObject *args) return NULL; } - QuadPrecisionObject *result = QuadPrecision_raw_new(BACKEND_SLEEF); - if (result == NULL) { - return NULL; - } - - if (strcmp(constant_name, "pi") == 0) { - result->value.sleef_value = SLEEF_M_PIq; - } - else if (strcmp(constant_name, "e") == 0) { - result->value.sleef_value = SLEEF_M_Eq; - } - else if (strcmp(constant_name, "log2e") == 0) { - result->value.sleef_value = SLEEF_M_LOG2Eq; - } - else if (strcmp(constant_name, "log10e") == 0) { - result->value.sleef_value = SLEEF_M_LOG10Eq; - } - else if (strcmp(constant_name, "ln2") == 0) { - result->value.sleef_value = SLEEF_M_LN2q; - } - else if (strcmp(constant_name, "ln10") == 0) { - result->value.sleef_value = SLEEF_M_LN10q; - } - else if (strcmp(constant_name, "max_value") == 0) { - result->value.sleef_value = SLEEF_QUAD_MAX; - } - else if (strcmp(constant_name, "epsilon") == 0) { - result->value.sleef_value = SLEEF_QUAD_EPSILON; - } - else if (strcmp(constant_name, "smallest_normal") == 0) { - result->value.sleef_value = SLEEF_QUAD_MIN; - } - else if (strcmp(constant_name, "smallest_subnormal") == 0) { - // or just use sleef_q(+0x0000000000000LL, 0x0000000000000001ULL, -16383); - result->value.sleef_value = SMALLEST_SUBNORMAL_VALUE; - } - else if (strcmp(constant_name, "bits") == 0) { - Py_DECREF(result); - return PyLong_FromLong(sizeof(Sleef_quad) * CHAR_BIT); - } - else if (strcmp(constant_name, "precision") == 0) { - Py_DECREF(result); - // precision = int(-log10(epsilon)) - int64_t precision = - Sleef_cast_to_int64q1(Sleef_negq1(Sleef_log10q1_u10(SLEEF_QUAD_EPSILON))); - return PyLong_FromLong(precision); - } - else if (strcmp(constant_name, "resolution") == 0) { - // precision = int(-log10(epsilon)) - int64_t precision = - Sleef_cast_to_int64q1(Sleef_negq1(Sleef_log10q1_u10(SLEEF_QUAD_EPSILON))); - // resolution = 10 ** (-precision) - result->value.sleef_value = - Sleef_powq1_u10(Sleef_cast_from_int64q1(10), Sleef_cast_from_int64q1(-precision)); - } - else { + ConstantResult const_result = get_sleef_constant_by_name(constant_name); + + if (const_result.type == CONSTANT_ERROR) { PyErr_SetString(PyExc_ValueError, "Unknown constant name"); - Py_DECREF(result); return NULL; } - - return (PyObject *)result; + + if (const_result.type == CONSTANT_INT64) { + return PyLong_FromLongLong(const_result.data.int_value); + } + + if (const_result.type == CONSTANT_QUAD) { + QuadPrecisionObject *result = QuadPrecision_raw_new(BACKEND_SLEEF); + if (result == NULL) { + return NULL; + } + result->value.sleef_value = const_result.data.quad_value; + return (PyObject *)result; + } + + // Should never reach here + PyErr_SetString(PyExc_RuntimeError, "Unexpected constant result type"); + return NULL; } static PyMethodDef module_methods[] = { diff --git a/quaddtype/tests/test_finfo.py b/quaddtype/tests/test_finfo.py new file mode 100644 index 00000000..3fa186a3 --- /dev/null +++ b/quaddtype/tests/test_finfo.py @@ -0,0 +1,130 @@ +import pytest +import numpy as np +from numpy_quaddtype import QuadPrecDType, QuadPrecision + + +class TestFinfoConstants: + """Test suite for verifying all finfo constants are correctly implemented.""" + + def test_basic_integer_properties(self): + """Test basic integer properties of finfo.""" + dtype = QuadPrecDType() + finfo = np.finfo(dtype) + + # Test basic properties + assert finfo.bits == 128, f"Expected bits=128, got {finfo.bits}" + assert finfo.nmant == 112, f"Expected nmant=112 (mantissa bits), got {finfo.nmant}" + assert finfo.nexp == 15, f"Expected nexp=15 (exponent bits including sign and bias), got {finfo.nexp}" + assert finfo.iexp == 15, f"Expected iexp=15 (exponent bits), got {finfo.iexp}" + assert finfo.minexp == -16382, f"Expected minexp=-16382, got {finfo.minexp}" + assert finfo.maxexp == 16384, f"Expected maxexp=16384, got {finfo.maxexp}" + assert finfo.precision == 33, f"Expected precision=33 (decimal digits), got {finfo.precision}" + + def test_epsilon_values(self): + """Test epsilon values (eps and epsneg).""" + dtype = QuadPrecDType() + finfo = np.finfo(dtype) + + # eps = 2^-112 (difference between 1.0 and next larger representable float) + expected_eps = QuadPrecision("1.92592994438723585305597794258492732e-34") + assert isinstance(finfo.eps, QuadPrecision), f"eps should be QuadPrecision, got {type(finfo.eps)}" + assert str(finfo.eps) == str(expected_eps), f"eps: expected {expected_eps}, got {finfo.eps}" + + # epsneg = 2^-113 (difference between 1.0 and next smaller representable float) + expected_epsneg = QuadPrecision("9.62964972193617926527988971292463660e-35") + assert isinstance(finfo.epsneg, QuadPrecision), f"epsneg should be QuadPrecision, got {type(finfo.epsneg)}" + assert str(finfo.epsneg) == str(expected_epsneg), f"epsneg: expected {expected_epsneg}, got {finfo.epsneg}" + + def test_max_and_min_values(self): + """Test maximum and minimum finite values.""" + dtype = QuadPrecDType() + finfo = np.finfo(dtype) + + # max = SLEEF_QUAD_MAX + expected_max = QuadPrecision("1.18973149535723176508575932662800702e+4932") + assert isinstance(finfo.max, QuadPrecision), f"max should be QuadPrecision, got {type(finfo.max)}" + assert str(finfo.max) == str(expected_max), f"max: expected {expected_max}, got {finfo.max}" + + # min = -SLEEF_QUAD_MAX (most negative finite value) + expected_min = QuadPrecision("-1.18973149535723176508575932662800702e+4932") + assert isinstance(finfo.min, QuadPrecision), f"min should be QuadPrecision, got {type(finfo.min)}" + assert str(finfo.min) == str(expected_min), f"min: expected {expected_min}, got {finfo.min}" + + # Verify min is negative + assert str(finfo.min).startswith('-'), f"min should be negative, got {finfo.min}" + + def test_tiny_and_smallest_values(self): + """Test tiny (smallest_normal) and smallest_subnormal values.""" + dtype = QuadPrecDType() + finfo = np.finfo(dtype) + + # tiny = smallest_normal = SLEEF_QUAD_MIN = 2^-16382 + expected_tiny = QuadPrecision("3.36210314311209350626267781732175260e-4932") + assert isinstance(finfo.tiny, QuadPrecision), f"tiny should be QuadPrecision, got {type(finfo.tiny)}" + assert isinstance(finfo.smallest_normal, QuadPrecision), \ + f"smallest_normal should be QuadPrecision, got {type(finfo.smallest_normal)}" + + # tiny and smallest_normal should be the same + assert str(finfo.tiny) == str(finfo.smallest_normal), \ + f"tiny and smallest_normal should be equal, got {finfo.tiny} != {finfo.smallest_normal}" + assert str(finfo.tiny) == str(expected_tiny), f"tiny: expected {expected_tiny}, got {finfo.tiny}" + + # smallest_subnormal = 2^-16494 (smallest positive representable number) + expected_smallest_subnormal = QuadPrecision("6.47517511943802511092443895822764655e-4966") + assert isinstance(finfo.smallest_subnormal, QuadPrecision), \ + f"smallest_subnormal should be QuadPrecision, got {type(finfo.smallest_subnormal)}" + assert str(finfo.smallest_subnormal) == str(expected_smallest_subnormal), \ + f"smallest_subnormal: expected {expected_smallest_subnormal}, got {finfo.smallest_subnormal}" + + def test_resolution(self): + """Test resolution property (10^-precision).""" + dtype = QuadPrecDType() + finfo = np.finfo(dtype) + + # Resolution should be approximately 10^-33 for quad precision + expected_resolution = QuadPrecision("1e-33") + assert isinstance(finfo.resolution, QuadPrecision), \ + f"resolution should be QuadPrecision, got {type(finfo.resolution)}" + assert str(finfo.resolution) == str(expected_resolution), \ + f"resolution: expected {expected_resolution}, got {finfo.resolution}" + + def test_dtype_property(self): + """Test that finfo.dtype returns the correct dtype.""" + dtype = QuadPrecDType() + finfo = np.finfo(dtype) + + # finfo.dtype should return a QuadPrecDType + assert isinstance(finfo.dtype, type(dtype)), \ + f"finfo.dtype should be QuadPrecDType, got {type(finfo.dtype)}" + + def test_machep_and_negep(self): + """Test machep and negep exponent properties.""" + dtype = QuadPrecDType() + finfo = np.finfo(dtype) + + # machep: exponent that yields eps (should be -112 for quad precision: 2^-112) + # negep: exponent that yields epsneg (should be -113 for quad precision: 2^-113) + # These are calculated by NumPy from eps and epsneg values + + # Just verify they exist and are integers + assert isinstance(finfo.machep, (int, np.integer)), \ + f"machep should be integer, got {type(finfo.machep)}" + assert isinstance(finfo.negep, (int, np.integer)), \ + f"negep should be integer, got {type(finfo.negep)}" + + def test_finfo_comparison_with_float64(self): + """Verify quad precision has better precision than float64.""" + quad_finfo = np.finfo(QuadPrecDType()) + float64_finfo = np.finfo(np.float64) + + # Quad precision should have more precision + assert quad_finfo.bits > 64, \ + f"Quad bits ({quad_finfo.bits}) should be > 64" + assert quad_finfo.nmant > float64_finfo.nmant, \ + f"Quad nmant ({quad_finfo.nmant}) should be > float64 nmant ({float64_finfo.nmant})" + assert quad_finfo.precision > float64_finfo.precision, \ + f"Quad precision ({quad_finfo.precision}) should be > float64 precision ({float64_finfo.precision})" + + +if __name__ == "__main__": + pytest.main([__file__, "-v"]) diff --git a/quaddtype/tests/test_quaddtype.py b/quaddtype/tests/test_quaddtype.py index a761df14..a0b5335b 100644 --- a/quaddtype/tests/test_quaddtype.py +++ b/quaddtype/tests/test_quaddtype.py @@ -19,11 +19,6 @@ def test_math_constant(name, expected): assert np.float64(getattr(numpy_quaddtype, name)) == expected -@pytest.mark.parametrize("name", ["max_value", "epsilon", "smallest_normal", "smallest_subnormal", "resolution"]) -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 @@ -34,10 +29,6 @@ def test_smallest_subnormal_value(): 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 - @pytest.mark.parametrize("dtype", [ "bool",