Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .jules/bolt.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,6 @@
## 2024-05-15 - [R Performance: ifelse Overhead]
**Learning:** In R, ifelse evaluates both true and false branches entirely before subsetting, which is very inefficient for vector operations.
**Action:** Optimize this by preallocating with res <- Y * 0 to preserve attributes and using vectorized subsetting like if any cond res subset <- ...
## 2026-08-11 - Fast Vectorized Subsetting over `ifelse()`
**Learning:** `ifelse(cond, true_branch, false_branch)` evaluates both branches entirely before subsetting, which creates significant overhead, especially in hot loops or likelihood calculations. Replacing it with vectorized subsetting (e.g. `res <- true_branch; res[!cond] <- false_branch`) is much faster and retains the same NA handling as `ifelse()`. Using `which()` for indices can alter NA behavior (since `which()` drops NAs) and must be carefully evaluated, but simple vectorized assignment is safe and highly performant.
**Action:** Replace `ifelse()` with vectorized assignment (e.g. `res <- a/b; res[b == 0] <- 0`) when optimizing hot loops or performance-critical likelihood paths.
10 changes: 8 additions & 2 deletions R/llcont.R
Original file line number Diff line number Diff line change
Expand Up @@ -53,12 +53,18 @@ llcont.glm <- function(x, ...){
if(is.matrix(y)) {
## Bolt: replaced apply(..., 1, sum) with optimized rowSums() for performance
n <- rowSums(y)
y <- ifelse(n == 0, 0, y[, 1]/n)
## Bolt: replaced ifelse with vectorized subsetting for performance
y_new <- y[, 1]/n
y_new[n == 0] <- 0
y <- y_new
} else {
n <- rep.int(1, length(y))
}
m <- if (any(n > 1)) n else wt
wt <- ifelse(m > 0, (wt/m), 0)
## Bolt: replaced ifelse with vectorized subsetting for performance
wt_new <- wt/m
wt_new[m <= 0] <- 0
Comment on lines +57 to +66

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

πŸ“ Info: Edge-case behavior remains equivalent

Zero denominators are overwritten before use. Missing comparisons leave their existing NA results unchanged, matching both prior ifelse() expressions.

Devin Review

Was this helpful? React with πŸ‘ or πŸ‘Ž to provide feedback.

wt <- wt_new
dbinom(round(m * y), round(m), mpreds, log = TRUE) * wt
},
quasibinomial = {
Expand Down
Loading