Repository navigation
io.ascii fast C converter support for Fortran formats and extended precision - #5552
Conversation
ENH: added 'fortran_dexp' to fast_reader options, using the fast C converter to read 'd' or 'D' instead of 'e' as exponent character in scientific notation
At least 'Q' can potentially appear as an exponent as well, therefore changed the syntax to 'fortran_exp': `char`
Added support for auto-detection of any of 'E', 'D' or 'Q', or exponents beginning directly with the sign, by fortran_exp='A'
changed option name to exponent_style, updated fast_reader docs
another attempt to make Sphinx happy, hopefully handled the multiprocessing issue with test_fortran_reader
Reorganised exponent_style docs according to taldcroft's suggestions
Check for exactly 3 digits in exponential notation w/o character; tests added for parsing other cases as strings.
…ents Test for ascii input outside of float64 validity range to be returned as strings by the C parser; for non-standard exponent_style very small exponent numbers are returned as 0.0.
Moved check of fast_reader for invalid Fortran-style exponent patterns to separate test to avoid known issues (segfaults) with large exponents on Travis CI.
Fixed handling of a couple of corner cases in xstrtod() and made sure the function returns cleanly. str_to_double() returns values outside float64 range as -inf,0,inf, in accordance with the Python parser. Trying to get this through tests on Travis once more.
I suspect xstrtod returning without setting *endptr may have caused the segfaults...
Raise only warning for floats outside of float64 range read in by ascii fast reader and return +-inf/0; better handling of limiting cases like 0.00000314e+314 or 2500e-327.
Changed the fallback of io.ascii fast_reader for integers outside of int64 range to string columns, consistent with the Python reader behaviour. Removed auto-detect flag from strtol call in tokenizer.c so it won't try to interpret integers with leading zeros as octal. Added tests and cleaned up tests for Fortran exponent_style options. Note: return type of mixed huge integer/float columns still depends on row order!
|
Since this seems to be working now... @taldcroft, are you happy with it? I give it a quick look, and while I didn't dig deeply into the C code, it looks good to me. Should we squeeze it in for 1.3? @dhomeier - One thing that's missing is a changelog entry: you'll need to add a section under 1.3 -> "New Features" -> |
|
Actually, @dhomeier, here was a surprise: (where perhaps you should catch combinations where |
|
Thanks for catching, this; in fact I had some trouble with the fact that the fast_reader generally only works reliably with the format specified, and optimally even |
|
@dhomeier - thanks for getting back to this! @eteq - about pushing for 1.3, I'm just a little hesitant about rushing this now. The code changes are complex, and I don't know if anybody else actually has read and understood the patch. That's partly my fault, but to this day I'm not an expert on the fast C reader code. Recently @saimn appears to be learning this code so maybe he might be able to have a look? Another strategy is to trust the new code by testing, but honestly I have had trouble looking at the tests and deciding if they are complete. So here is a comment that I had earlier in #3655 that might help: Overall it is difficult to look at the tests and get a good understanding of what is being tested, in particular with regard to what parses and what does not. What would help is defining this in terms of a uniform test matrix like: You could actually do the same in code by just making a big list of tuples with those same three |
|
@taldcroft - thanks for the feedback! Not sure I understand 100% how you envision the implementation of the test matrix, but I have adopted some of your earlier suggestions into |
|
@dhomeier - I guess what I mean is this: If I do @taldcroft re: 1.3 - Other than the above, I think this is conceptually straightforward enough that even if there is a bug, I think it's better to get it in for live testing. (Partly I'm influenced by just having a couple people ask me about this feature in the past few weeks. It also turns out to be a feature Pandas is missing...) I'd be concerned if it were likely to cause regressions, but in my review I was mainly looking for that and didn't see evidence that that was at all likely. (we can have a discussion on this at the coordination telecon today if you like) So I'm inclined to say try to get it in for 1.3 but also hopefully @dhomeier can try to add some tests as you suggest? |
| long ret; | ||
| errno = 0; | ||
| ret = strtol(str, &tmp, 0); | ||
| ret = strtol(str, &tmp, 10); |
There was a problem hiding this comment.
What's happening in this diff? Why did 0 change to 10?
There was a problem hiding this comment.
this looks to be the base of the string->long change. Presumably because that's now being taken care of by setting the character? But it is a good question for @dhomeier : isn't this a subtle change in how long columns are interpreted?
There was a problem hiding this comment.
Yes, see the comment on that commit 7490bdd in the original PR. With the base set to auto-detect, strtol would interpret e.g. 0432437 as an octal no. and return it as (base-10) int 144671, whereas 0432438 would be identified as invalid octal and promoted to float, or with the updated fall-back scheme, to str. Hard to imagine anyone has used this 'feature', and anyway it was inconsistent with the Python parser's behaviour.
There was a problem hiding this comment.
Agreed - I think this was probably a subtle "bug" rather than a feature.
There was a problem hiding this comment.
A possible alternative would be to provide base as an additional keyword arg, but then it should better be supported by the slow reader as well. Not that far out of reach, since Python/Numpy int() does accept the same base option, unfortunately I don't see an easy way to get it handed down through the np.array call that handles the conversion.
Probably out of scope for the current PR.
@taldcroft - I had a look, but I'm afraid I cannot help you much here ... Overall it looks good, but there are some parts that I don't understand, and it's difficult to get the wide picture. |
|
@saimn - thanks for having a look. |
|
@eteq - completely taking your point, there is already a check raising an error if Re: your remark |
|
@dhomeier - I used the following table: And that gave me the following: Why didn't it work in the first case, despite me specifically asking for an (@taldcroft might have some insight to the above question?) |
|
Oh, and FYI, @dhomeier, we discussed this at the coordinators meeting today and we want to try to get this in for the feature freeze/1.3, but with an understanding that we need to be extra-vigilant on this because it's difficult for folks to review the C code of the parser given its complexity. So if it turns out this introduces a bug we missed and it's revealed in testing the RC, we might pull it back out or something. But if you can resolve my one lest question above, and add a changelog entry, I think this is good to go! |
|
@eteq - thanks for the positive feedback; of course if any bugs remain to show up this should not make it into the release! Maybe it just takes replacing with an |
|
@dhomeier - I took a shot at this (with a test) in https://github.com/eteq/astropy/tree/fortranexp2-fast-error , but it doesn't seem to work... But this does make me realize that the underlying problem is more than just (And I'll create a separate issue about this fast_reader confusing business to keep track of that). |
|
@eteq - thanks, but could you hold it for another hour or so - I had some (hopeful) clarifications to the tests I had not committed yet. |
This is the Fortran-exponents branch from #3655 merged into the current master, since that PR apparently could not make it through CI anymore. Updated the tests for more checks at the
float64precision limits.