Skip to content

Conversation

SwayamInSync
Copy link
Member

@SwayamInSync SwayamInSync commented Sep 19, 2025

Making this PR here as well, as a demonstration to how np.finfo and other related information can be passed to NumPy.

Edit: Below is not possible as QuadPrecDType is an immutable type

This maybe done from the Python side as well i.e. inside __init__.py something like

QuadPrecDType.finfo = lambda: QuadPrecFinfo()

But this just feels so illegal that's why registering as .tp_methods

From the NumPy side it requires numpy/numpy#29771 to get merged.

@SwayamInSync
Copy link
Member Author

@juntyr can you please take a look at the QuadPrecFinfo class and see whether the info is correct?

static PyObject *
QuadPrecDType_finfo(QuadPrecDTypeObject *self, PyObject *args)
{
PyObject *numpy_quaddtype_module = PyImport_ImportModule("numpy_quaddtype");
Copy link
Member Author

Choose a reason for hiding this comment

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

I don't like doing this as well, but for now it works so

eps: float = float(epsilon)
epsneg: float = float(epsilon)
iexp: int = int(precision)
machar: object = None
Copy link
Contributor

Choose a reason for hiding this comment

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

What is this property?

Copy link
Member Author

Choose a reason for hiding this comment

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

is just an object finfo uses to fetch the finfo properties for dtypes, since we are defining them in our package hence marking it as None

"""
bits: int = int(bits)
eps: float = float(epsilon)
epsneg: float = float(epsilon)
Copy link
Contributor

Choose a reason for hiding this comment

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

This is wrong - it should 1 - nextafter(1, 0) [similar to how exp is nextafter(1, 2) - 1], we can probably compute this in the C++ source and then expose it as a new constant

bits: int = int(bits)
eps: float = float(epsilon)
epsneg: float = float(epsilon)
iexp: int = int(precision)
Copy link
Contributor

Choose a reason for hiding this comment

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

iexp should be 15, I think?

epsneg: float = float(epsilon)
iexp: int = int(precision)
machar: object = None
machep: float = float(epsilon)
Copy link
Contributor

Choose a reason for hiding this comment

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

machep should be int(log2(epsilon))?

machar: object = None
machep: float = float(epsilon)
max: float = float(max_value)
maxexp: float = float(max_value)
Copy link
Contributor

Choose a reason for hiding this comment

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

This would probably be int(ceil(max_value))?

machep: float = float(epsilon)
max: float = float(max_value)
maxexp: float = float(max_value)
min: float = float(smallest_normal)
Copy link
Contributor

Choose a reason for hiding this comment

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

min = -max_value

max: float = float(max_value)
maxexp: float = float(max_value)
min: float = float(smallest_normal)
minexp: float = float(smallest_normal)
Copy link
Contributor

Choose a reason for hiding this comment

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

not sure how to compute this one

maxexp: float = float(max_value)
min: float = float(smallest_normal)
minexp: float = float(smallest_normal)
negep: float = float(epsilon)
Copy link
Contributor

Choose a reason for hiding this comment

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

int(log2(epsneg))

min: float = float(smallest_normal)
minexp: float = float(smallest_normal)
negep: float = float(epsilon)
nexp: int = int(bits) - int(precision) - 1
Copy link
Contributor

@juntyr juntyr Sep 20, 2025

Choose a reason for hiding this comment

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

maybe 15 + 1? not sure

minexp: float = float(smallest_normal)
negep: float = float(epsilon)
nexp: int = int(bits) - int(precision) - 1
nmant: int = int(precision)
Copy link
Contributor

Choose a reason for hiding this comment

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

113 or 112

Copy link
Contributor

@juntyr juntyr left a comment

Choose a reason for hiding this comment

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

Thanks @SwayamInSync for working on this!

I am really uncomfortable with all the casts to float, since at least for some of them they will undoubtedly over- or underflow. In my mind, the finfo values should have the same dtype as the type we're describing, but I know this would likely be a breaking change; but likely one we need since otherwise e.g. finfo(quad).max don't make any sense

@SwayamInSync
Copy link
Member Author

the finfo values should have the same dtype as the type we're describing, but I know this would likely be a breaking change; but likely one we need since otherwise e.g. finfo(quad).max don't make any sense

Hey yes good point, just fixed that

@juntyr
Copy link
Contributor

juntyr commented Sep 20, 2025

What's the reason for using the explicit field constructor?

@SwayamInSync SwayamInSync marked this pull request as draft September 21, 2025 18:33
@SwayamInSync SwayamInSync changed the title np.finfo support for quaddtyoe np.finfo support for quaddtype Sep 21, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants