Fix fmatch() matching logical NA to non-logical table values - #872
Merged
Conversation
The C fix in match_single() (only take the M=3 logical-specific hash path when table is also logical, otherwise fall back to generic integer hashing) was correct, but the regression test asserted `NA %iin% table` == NA_integer_. `%iin%` returns indices (via whichNA(..., invert = TRUE)), so a non-match correctly yields integer(0), not NA_integer_. Corrected the assertion and added a few more edge cases (larger table, table with a real NA, double table, genuine logical-vs-logical matching). Closes #870. Co-authored-by: Sebastian Krantz <48053842+SebKrantz@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
fmatch()(and thus%in%/%iin%and joins) matched a logicalNAinxto a non-logical integer value intable(e.g.,2L) instead of returningNAlikebase::match().src/match.c::match_single(), a logicalxalways took a specialized 3-bucket hash path (reserving one bucket for NA) regardless of whethertablewas actually logical, causing collisions with real table values.tableis also logical; otherwise fall back to the generic, collision-safe integer hashing path.NA %iin% tableshould beinteger(0), notNA_integer_, since%iin%returns matched indices.Closes #870.
Test plan
tests/testthat/test-fmatch.Rcomparing againstbase::match()Generated with Claude Code