Skip to content

Conversation

@SwayamInSync
Copy link
Member

closes #153

As per the title

@SwayamInSync
Copy link
Member Author

New things fixed and added

  • For supporting -nan in strings, dragon4 has to preserve the sign in output to ensure the complete roundtrip
  • Sleef's vendored methods for casting to/from double aren't all supportable over platforms, can cause discripencies so we are explicitly handling those cases.

return Sleef_negq1(QUAD_ZERO); // -0.0
if (Sleef_icmpeqq1(result, QUAD_PRECISION_ZERO)) {
if (Sleef_icmpltq1(*b, QUAD_PRECISION_ZERO)) {
return Sleef_negq1(QUAD_PRECISION_ZERO); // -0.0
Copy link
Contributor

Choose a reason for hiding this comment

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

we have a const for negative zero

Copy link
Member Author

Choose a reason for hiding this comment

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

There's a subtle issues in using that, we didn't used QUAD_PRECISION_NEG_ZERO anywhere because qutil gave the logical representation but the sign information is stored in the actual IEEE 754 binary format, not in the integer literal itself. Basically the sign is encoded in the high mantissa bits. Simply putting a minus sign in front of 0x0 doesn't create a negative zero representation.

I can replace it with a valid representation maybe in future PRs, for now that is just an artifact in the code.

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.

LGTM with minor nits addressed

Copy link
Member

@ngoldbaum ngoldbaum left a comment

Choose a reason for hiding this comment

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

@mattip any chance you have time and interest to look this over?

@SwayamInSync
Copy link
Member Author

Details for easing the review process

Only casts.cpp and test_quaddtype requires the major review, I added comments wherever I made the changes to give reasoning for that step, the rest files are modified for the caues listed below

Small refactoring

  • quad_value union with __float128 causes lot of ABI & compiler optimization issues in C++, hence refactoring the methods to not perform any kind of copy of this passed union instead use pointers
  • Inter-backend operation is broken in previous builds, not sure why someone wants to go in that direction, but just for the sake of completeness I fixed it here as well, to implement the same_value casting between QuadPrecision with different backends
  • Remove the aligned/unlaigned separate loops with their templated versions

This is still valid, outside this are just tweaks and refactoring to make things work in stable manner

@mattip
Copy link
Member

mattip commented Dec 29, 2025

I can take a look after Jan 11.

@ngoldbaum
Copy link
Member

@SwayamInSync do you mind waiting a couple weeks on this? I'd like to have Matti look because he added same_value casting and also has a try at this in #161.

In the meantime: one thing that would help is to make the PR more atomic. There's a fair amount of renaming and other stuff like that you could do in another PR then rebase this once the other PR is merged to reduce the diff size.

In general I'd much rather review several smaller more focused PRs rather than one big PR.

@juntyr
Copy link
Contributor

juntyr commented Dec 30, 2025

I was hoping for a faster timeline to the release (since numpy-quaddtype is used in my research) but life is life and I'll adapt my own timelines if need be

@SwayamInSync
Copy link
Member Author

@SwayamInSync do you mind waiting a couple weeks on this? I'd like to have Matti look because he added same_value casting and also has a try at this in #161.

In the meantime: one thing that would help is to make the PR more atomic. There's a fair amount of renaming and other stuff like that you could do in another PR then rebase this once the other PR is merged to reduce the diff size.

In general I'd much rather review several smaller more focused PRs rather than one big PR.

Right, I also didn't want to make it this big, but it the design choice of using union with SIMD types in C++ gave a lot of ABI breaks (as __float128 isn't standard so on x86-64 machines, doing careless copies gives heisenbugs)
I can do some independent refactor PRs, and since we are allowing some time window I'll also get some work to do on docs 😄

@SwayamInSync
Copy link
Member Author

Cool so the diff got down now, mostly again covered by casts.cpp and tests

@SwayamInSync
Copy link
Member Author

Hi @mattip gentle ping to get this in your radar.

@juntyr
Copy link
Contributor

juntyr commented Jan 13, 2026

I'm also hoping that we can merge this PR and publish v1.0 soon

Copy link
Member

@ngoldbaum ngoldbaum left a comment

Choose a reason for hiding this comment

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

I did a pass over the C code and spotted some issues. I'd appreciate it if you could look elsewhere for similar patterns to the main issue I spotted: setting an error in an error path when an error is already set

}

// Helper function for quad-to-quad same_value check (inter-backend)
// NOTE: the inter-backend uses `double` as intermediate,
Copy link
Member

Choose a reason for hiding this comment

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

Does SLEEF not have any utilities for working with 80 bit floats? It’d be nice to not have this restriction. But also not critical.


// Perform same_value check if requested
if (same_value_casting) {
if (quad_to_string_same_value_check(&in_val, str_buf, str_size, backend) < 0) {
Copy link
Member

Choose a reason for hiding this comment

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

Is it possible for the same value not to be preserved here? I don't think it is - StringDType shouldn't truncate data. That means this check isn't necessary.

}

static inline int
quad_to_string_same_value_check(const quad_value *in_val, const char *str_buf, npy_intp str_len,
Copy link
Member

Choose a reason for hiding this comment

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

Maybe you could avoid allocating a temporary buffer to store a string if you knew how many digits are necessary to represent the quad precisely. Is that exposed by SLEEF?

I ask because this whole process - allocating and freeing a temporary and parsing the truncated string, seems very slow and probably adds a lot of overhead to the cast operation for the fixed-width strings.

val_str);
}
else {
PyErr_SetString(PyExc_ValueError,
Copy link
Member

Choose a reason for hiding this comment

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

This is wrong: you shouldn't set a new error here if quad_to_string_adaptive_cstr already set an error. I'd just bubble up the error instead of trying to give more context here.

val_str);
}
else {
PyErr_SetString(PyExc_ValueError,
Copy link
Member

Choose a reason for hiding this comment

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

same issue here - an error is already set, setting a new one without resetting the error indicator is wrong.

val_str);
}
else {
PyErr_SetString(PyExc_ValueError,
Copy link
Member

Choose a reason for hiding this comment

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

same error

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Use same_value casting in astype

4 participants