Skip to content

Plan cumulative functions of a logical tree - #461

Merged
jbearak merged 5 commits into
mainfrom
claude/cumulative-logical
Oct 27, 2026
Merged

jbearak merged 5 commits into
mainfrom
claude/cumulative-logical

Conversation

@jbearak

@jbearak jbearak commented Oct 27, 2026 •

Copy link
Copy Markdown
Owner

Summary

A planned arithmetic tree of a grouped mutate() or filter() takes cumsum(), cummax() and cummin() of a Stata numeric operand, as ADR 0085 allows. Of a comparison, such as the running count cumsum(b5 == 1), the tree went to the loop. The comparison gives a bare logical vector, and each group's evaluation called Ops.dta_numeric() and base's cumsum(). Over the 42,739 women in the first 100,000 rows of the India 2021 DHS births file, mutate(b, c = cumsum(b5 == 1), .by = caseid) took about 0.30 seconds, where a tibble takes about 0.060.

This PR lets the tree take cumsum(), cummax() and cummin() of a logical tree, which gives a bare integer vector for each group. The call must find base's primitive, which dispatches on no bare logical vector. The native evaluator computes the running count, maximum or minimum of the logical values as integers, missing from the first missing value on, as the primitive does. A logical vector no longer than INT_MAX cannot overflow cumsum()'s integer.

The result may be the whole expression of a mutate(), or compare with a bare number, as the positions from row_number() do under ADR 0099. The comparison gives a logical tree that mutate() and filter() take.

Behavior

Results are unchanged. ADR 0123 records the decision. Arithmetic of the counts, a summary of them, and abs() or the rounding functions of a logical vector, which give other types, still go to the loop.

Timing

Best of three runs in fresh R sessions, in seconds, with the builds interleaved, over the first 100,000 rows of the India 2021 DHS births file. Before is main.

Call Before After Tibble
mutate(b, c = cumsum(b5 == 1), .by = caseid) 0.30 0.050 0.060
filter(b, cumsum(b5 == 0) <= 1, .by = caseid) 0.43 0.059 0.059

Tests

  • A test runs each of the three functions of a comparison of each column of the plan tests' data, by .by and by group_by(). The columns' missing and tagged missing values make the rest of a group's results missing. It also runs other logical trees, nested counts, comparisons of the counts with a number in mutate() and filter(), and between() as the tree. Each case must give what the loop gives, and the plan must take every one.
  • A test checks that the plan leaves these to the loop: another function of the name where R finds it first, a column named cumsum, arithmetic of the counts, abs() of a comparison, cumsum(n() > 1), a summarise() and rowwise data.
  • The full suite passes: 169 files, 2,278 tests. The native manifest and repository guard tests pass. Codex review raised only a stale manifest, which the refresh fixed.

@coderabbitai

coderabbitai Bot commented Oct 27, 2026 •

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

Run configuration

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Comment @coderabbitai help to get the list of available commands.

@jbearak
jbearak changed the base branch from claude/slice-literal-plan to main October 27, 2026 01:41
@jbearak
jbearak marked this pull request as ready for review October 27, 2026 01:41
@jbearak
jbearak merged commit 441d55e into main Oct 27, 2026
4 of 7 checks passed
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.

1 participant