when_doubled <- function(DT, dateCol, countCol) {
  cols_adding <- c("doubled_on", "time_to_double")
  if (any(cols_adding %in% names(DT)))
    stop("Some columns are already in DT.\nPlease manually drop these to continue: ", pasteQand(intersect(names(DT), cols_adding)))

  if (dateCol %ni% names(DT))
    stop("dateCol '", dateCol, "' is not a column in DT")
  if (countCol %ni% names(DT))
    stop("countCol '", countCol, "' is not a column in DT")

  DT[, doubled_on := as.Date(NA)]
  for (i in seq(nrow(DT)))
    DT[, doubled_on := {

          doubled_on[[i]] <- get(dateCol)[min_nowarn(which( get(countCol) >= DT[[countCol]][[i]] * 2))]
          doubled_on
        }]

  DT[, time_to_double := doubled_on - get(dateCol)]
  return(DT[])
}

when_halfed <- function(DT, dateCol, countCol) {
  cols_adding <- c("halfed_on", "time_since_halfed")
  if (any(cols_adding %in% names(DT)))
    stop("Some columns are already in DT.\nPlease manually drop these to continue: ", pasteQand(intersect(names(DT), cols_adding)))

  if (dateCol %ni% names(DT))
    stop("dateCol '", dateCol, "' is not a column in DT")
  if (countCol %ni% names(DT))
    stop("countCol '", countCol, "' is not a column in DT")

  DT[, halfed_on := as.Date(NA)]
  for (i in seq(nrow(DT)))
    DT[, halfed_on := {

          halfed_on[[i]] <- get(dateCol)[max_nowarn(which( get(countCol) <= DT[[countCol]][[i]] / 2))]
          halfed_on
        }]

  DT[, time_since_halfed := halfed_on - get(dateCol)]
  return(DT[])
}