-
-
Notifications
You must be signed in to change notification settings - Fork 13
FEAT: Adding Byte support to QuadPrecision scalar constructor #223
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
ngoldbaum
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I spotted a bug and have a suggestion to refactor to avoid the buggy pattern you're replicating that occurs elsewhere in the library.
Otherwise looks good although I didn't look carefully at the tests.
| } | ||
| char *endptr = NULL; | ||
| if (backend == BACKEND_SLEEF) { | ||
| self->value.sleef_value = Sleef_strtoq(s, &endptr); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
here and in the other path you should check if the returned value is zero. If it is, the conversion failed and you should exit early.
I'm not sure but I think it's likely that in the current code in that case, endptr would still be NULL in that case and you'd segfault when you deference endptr in the next if block.
I'd also add some explicit tests for strings that contain values that are outside the range of representable values. You might also need to deal with errno, I'm not sure if sleef sets that like strtold is supposed to do.
It looks like we have similar bugs in our other uses of strtold and Sleef_strtoq:
goldbaum at Nathans-MBP in ~/Documents/numpy-user-dtypes on 216!
± rg -A 5 strtold
quaddtype/numpy_quaddtype/src/scalar.c
167: self->value.longdouble_value = strtold(s, &endptr);
168- }
169- if (*endptr != '\0' || endptr == s) {
170- PyErr_SetString(PyExc_ValueError, "Unable to parse string to QuadPrecision");
171- Py_DECREF(self);
172- return NULL;
quaddtype/numpy_quaddtype/src/dtype.c
364: long double val = strtold(buffer, &endptr);
365- if (endptr == buffer) {
366- return 0; /* Return 0 on parse error (no items read) */
367- }
368- *(long double *)dptr = val;
369- }
--
387: long double val = strtold(s, endptr);
388- if (*endptr == s) {
389- return -1;
390- }
391- *(long double *)dptr = val;
392- }
Maybe it makes sense to refactor this operation into a new function called string_to_quad?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I actually also had this doubt, so I read about it and as per C standards page-343's point 4 and 7 say
- If no conversion is performed,
strtoldreturns0.0Land setsendptrtos(the same string as input). - If a conversion partially succeeds,
endptrwill point to the first character after the converted part.
so in both possible cases, it can't be NULL
And from SLEEF doc's they say
This is a QP version of the
strtodfunction.
So this should also follow the same rules.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You might also need to deal with errno, I'm not sure if sleef sets that like strtold is supposed to do.
I am afraid as SLEEF does not set errno (as in implementation of nextafter, I was setting those myself in the draft PR)
| @pytest.mark.parametrize("invalid_bytes", [ | ||
| b"", # Empty bytes | ||
| b"not_a_number", # Invalid format | ||
| b"1.23abc", # Trailing garbage |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are some edge cases to make the sleef_strtoq fail
|
Sorry for missing all that! Still, what do you think about refactoring the code I commented on into a new |
|
Yup, I'll refactor that part into a utility header (will keep doing these capsule size refactors in future PRs as well) |
jorenham
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It could help to add bytes to the allowed input types in the stubs:
numpy-user-dtypes/quaddtype/numpy_quaddtype/_quaddtype_main.pyi
Lines 8 to 15 in 2cbc0c6
| _IntoQuad: TypeAlias = ( | |
| QuadPrecision | |
| | float | |
| | str | |
| | np.floating[Any] | |
| | np.integer[Any] | |
| | np.bool_ | |
| ) # fmt: skip |
Ah yes, sorry I missed that |
|
Also python |
|
This PR is part of the work making quaddtype compatible with NumPy testing for longdouble