From b45345f0ce322a17f2af1e4733f9187bcbf105b3 Mon Sep 17 00:00:00 2001 From: Michael Chirico Date: Thu, 1 Jan 2026 23:51:51 -0800 Subject: [PATCH 01/16] Fix seq(a, b, length.out=n) --- NEWS.md | 1 + R/integer64.R | 10 +++++----- tests/testthat/test-integer64.R | 19 +++++++++++++++++-- 3 files changed, 23 insertions(+), 7 deletions(-) diff --git a/NEWS.md b/NEWS.md index a60ba7b1..0e0e3239 100644 --- a/NEWS.md +++ b/NEWS.md @@ -49,6 +49,7 @@ 1. `min.integer64`, `max.integer64` and `range.integer64` now support `na.rm=TRUE` correctly when combining across mutliple inputs like `min(x, NA_integer64_, na.rm=TRUE)` (#142). 1. `as.integer64.integer64` is consistent with `as.integer.integer` in terms or returning a plain integer64 vector (i.e., stripped of attributes; #188). Thanks @hcirellu. +1. `seq.integer64` calculates `by=` correctly when `length.out=` is provided (#47). ## NOTES diff --git a/R/integer64.R b/R/integer64.R index 01e51222..b28fa577 100644 --- a/R/integer64.R +++ b/R/integer64.R @@ -1030,20 +1030,20 @@ rep.integer64 <- function(x, ...) { } #' @export -seq.integer64 <- function(from=NULL, to=NULL, by=NULL, length.out=NULL, along.with=NULL, ...) { +seq.integer64 = function(from=NULL, to=NULL, by=NULL, length.out=NULL, along.with=NULL, ...) { if (is.null(length.out)) - length.out <- length(along.with) + length.out = length(along.with) else - length.out <- as.integer(length.out) + length.out = as.integer(length.out) if (is.null(by)) { if (is.null(from) || is.null(to)) by <- as.integer64(1L) else - by <- as.integer64(if (to < from) -1L else 1L) + by <- as.integer64((to - from) / (length.out - 1L)) } else { by <- as.integer64(by) - if (!is.null(from) && !is.null(to) && (sign(by) != (if (to < from) -1L else 1L))) + if (!is.null(from) && !is.null(to) && (sign(by) != sign(to - from))) stop("wrong sign of 'by' argument") } diff --git a/tests/testthat/test-integer64.R b/tests/testthat/test-integer64.R index 79663eb6..74d49ef1 100644 --- a/tests/testthat/test-integer64.R +++ b/tests/testthat/test-integer64.R @@ -298,8 +298,23 @@ test_that("vector builders of integer64 work", { expect_identical(seq(x[1L], x[3L], by=1L), x) expect_identical(seq(x[1L], x[3L], by=x[1L]), x) expect_identical(seq(x[1L], to=10L, by=1L), as.integer64(1:10)) - expect_identical(seq(x[1L], to=11L, by=2L), as.integer64(c(1L, 3L, 5L, 7L, 9L, 11L))) - # TODO(#47): More tests when the behavior is corrected. + + odds = as.integer64(c(1L, 3L, 5L, 7L, 9L, 11L)) + expect_identical(seq(as.integer64(1L), to=11L, by=2L), odds) + expect_identical(seq(as.integer64(1L), to=11L, length.out=6L), odds) + expect_identical(seq(as.integer64(1L), by=2L, length.out=6L), odds) + expect_identical(seq(as.integer64(1L), to=as.integer64(11L), by=2L), odds) + expect_identical(seq(as.integer64(1L), to=as.integer64(11L), length.out=6L), odds) + expect_identical(seq(as.integer64(1L), by=as.integer64(2L), length.out=6L), odds) + expect_identical(seq(as.integer64(1L), to=11L, by=as.integer64(2L)), odds) + expect_identical(seq(as.integer64(1L), to=11L, length.out=as.integer64(6L)), odds) + expect_identical(seq(as.integer64(1L), by=2L, length.out=as.integer64(6L)), odds) + expect_identical(seq(as.integer64(1L), to=as.integer64(11L), by=as.integer64(2L)), odds) + expect_identical(seq(as.integer64(1L), to=as.integer64(11L), length.out=as.integer64(6L)), odds) + expect_identical(seq(as.integer64(1L), by=as.integer64(2L), length.out=as.integer64(6L)), odds) + + expect_identical(seq(as.integer64(1L), to=11L, by=3L), as.integer64(seq(1L, to=11L, by=3L))) + expect_identical(seq(as.integer64(1L), to=11L, length.out=4L), as.integer64(seq(1L, to=11L, length.out=4L))) }) # These tests were previously kept as tests under \examples{\dontshow{...}}. From 101637df8f3a5075d52be019f967df39fcb62741 Mon Sep 17 00:00:00 2001 From: Michael Chirico Date: Fri, 2 Jan 2026 08:08:03 -0800 Subject: [PATCH 02/16] starting full test suite --- R/integer64.R | 8 +++++--- tests/testthat/test-integer64.R | 20 ++++++++++++++++++++ 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/R/integer64.R b/R/integer64.R index b28fa577..973cab15 100644 --- a/R/integer64.R +++ b/R/integer64.R @@ -1031,10 +1031,12 @@ rep.integer64 <- function(x, ...) { #' @export seq.integer64 = function(from=NULL, to=NULL, by=NULL, length.out=NULL, along.with=NULL, ...) { - if (is.null(length.out)) - length.out = length(along.with) - else + if (!is.null(along.with)) return(seq.integer64(from, to, length.out=length(along.with))) + if (is.null(length.out)) { + length.out = abs(to - from) + 1L + } else { length.out = as.integer(length.out) + } if (is.null(by)) { if (is.null(from) || is.null(to)) diff --git a/tests/testthat/test-integer64.R b/tests/testthat/test-integer64.R index 74d49ef1..134c4746 100644 --- a/tests/testthat/test-integer64.R +++ b/tests/testthat/test-integer64.R @@ -294,11 +294,28 @@ test_that("vector builders of integer64 work", { expect_identical(x[1L]:x[3L], x) expect_identical(x[3L]:x[1L], x[3:1]) # rev() a separate method +}) +patrick::with_parameters_test_that( + "seq method works analogously to integer: 1 argument", + { + expect_identical(seq(as.integer64(n)), as.integer64(seq(n))) + expect_identical(seq(from=as.integer64(n)), as.integer64(seq(from=n))) + expect_identical(seq(to=as.integer64(n)), as.integer64(seq(to=n))) + expect_identical(seq(by=as.integer64(n)), as.integer64(seq(by=n))) + expect_identical(seq(length.out=as.integer64(n)), as.integer64(seq(length.out=n))) + expect_identical(seq(along.with=as.integer64(n)), as.integer64(seq(along.with=n))) + }, + n = list(0L, 5L, -1L, 2:6) +) + +test_that("seq method works analogously to integer: 2 arguments", { expect_identical(seq(x[1L], x[3L], by=1L), x) expect_identical(seq(x[1L], x[3L], by=x[1L]), x) expect_identical(seq(x[1L], to=10L, by=1L), as.integer64(1:10)) +}) +test_that("seq method works analogously to integer: 3 arguments", { odds = as.integer64(c(1L, 3L, 5L, 7L, 9L, 11L)) expect_identical(seq(as.integer64(1L), to=11L, by=2L), odds) expect_identical(seq(as.integer64(1L), to=11L, length.out=6L), odds) @@ -317,6 +334,9 @@ test_that("vector builders of integer64 work", { expect_identical(seq(as.integer64(1L), to=11L, length.out=4L), as.integer64(seq(1L, to=11L, length.out=4L))) }) +test_that("seq method works analogously to integer: 4 arguments", { +}) + # These tests were previously kept as tests under \examples{\dontshow{...}}. # Converted to "proper" unit tests for clarity, after making them more # canonical within {testthat}, e.g. better capturing expected warnings, From e41a441f7f31f45b37825b95cfe008ae15e0e78d Mon Sep 17 00:00:00 2001 From: Michael Chirico Date: Fri, 2 Jan 2026 23:27:41 -0800 Subject: [PATCH 03/16] complete initial combinatorial suite of tests --- tests/testthat/test-integer64.R | 135 +++++++++++++++++++++++++------- 1 file changed, 106 insertions(+), 29 deletions(-) diff --git a/tests/testthat/test-integer64.R b/tests/testthat/test-integer64.R index 3e225430..10017604 100644 --- a/tests/testthat/test-integer64.R +++ b/tests/testthat/test-integer64.R @@ -299,42 +299,119 @@ test_that("vector builders of integer64 work", { patrick::with_parameters_test_that( "seq method works analogously to integer: 1 argument", { - expect_identical(seq(as.integer64(n)), as.integer64(seq(n))) - expect_identical(seq(from=as.integer64(n)), as.integer64(seq(from=n))) - expect_identical(seq(to=as.integer64(n)), as.integer64(seq(to=n))) - expect_identical(seq(by=as.integer64(n)), as.integer64(seq(by=n))) - expect_identical(seq(length.out=as.integer64(n)), as.integer64(seq(length.out=n))) - expect_identical(seq(along.with=as.integer64(n)), as.integer64(seq(along.with=n))) + n64 = as.integer64(n) + expect_identical(seq(n64), as.integer64(seq(n))) + expect_identical(seq(from=n64), as.integer64(seq(from=n))) + expect_identical(seq(to=n64), as.integer64(seq(to=n))) + expect_identical(seq(by=n64), as.integer64(seq(by=n))) + expect_identical(seq(length.out=n64), as.integer64(seq(length.out=n))) + expect_identical(seq(along.with=n64), as.integer64(seq(along.with=n))) }, n = list(0L, 5L, -1L, 2:6) ) -test_that("seq method works analogously to integer: 2 arguments", { - expect_identical(seq(x[1L], x[3L], by=1L), x) - expect_identical(seq(x[1L], x[3L], by=x[1L]), x) - expect_identical(seq(x[1L], to=10L, by=1L), as.integer64(1:10)) -}) +patrick::with_parameters_test_that( + "seq method works analogously to integer: 2 arguments", + { + n1_64 = as.integer64(n1) + n2_64 = as.integer64(n2) -test_that("seq method works analogously to integer: 3 arguments", { - odds = as.integer64(c(1L, 3L, 5L, 7L, 9L, 11L)) - expect_identical(seq(as.integer64(1L), to=11L, by=2L), odds) - expect_identical(seq(as.integer64(1L), to=11L, length.out=6L), odds) - expect_identical(seq(as.integer64(1L), by=2L, length.out=6L), odds) - expect_identical(seq(as.integer64(1L), to=as.integer64(11L), by=2L), odds) - expect_identical(seq(as.integer64(1L), to=as.integer64(11L), length.out=6L), odds) - expect_identical(seq(as.integer64(1L), by=as.integer64(2L), length.out=6L), odds) - expect_identical(seq(as.integer64(1L), to=11L, by=as.integer64(2L)), odds) - expect_identical(seq(as.integer64(1L), to=11L, length.out=as.integer64(6L)), odds) - expect_identical(seq(as.integer64(1L), by=2L, length.out=as.integer64(6L)), odds) - expect_identical(seq(as.integer64(1L), to=as.integer64(11L), by=as.integer64(2L)), odds) - expect_identical(seq(as.integer64(1L), to=as.integer64(11L), length.out=as.integer64(6L)), odds) - expect_identical(seq(as.integer64(1L), by=as.integer64(2L), length.out=as.integer64(6L)), odds) - - expect_identical(seq(as.integer64(1L), to=11L, by=3L), as.integer64(seq(1L, to=11L, by=3L))) - expect_identical(seq(as.integer64(1L), to=11L, length.out=4L), as.integer64(seq(1L, to=11L, length.out=4L))) -}) + expect_identical(seq(n1_64, n2), as.integer64(seq(n1, n2))) + expect_identical(seq(n1_64, n2_64), as.integer64(seq(n1, n2))) + + expect_identical(seq(n1_64, by=n2), as.integer64(seq(n1, by=n2))) + expect_identical(seq(n1_64, by=n2_64), as.integer64(seq(n1, by=n2))) + + expect_identical(seq(n1_64, length.out=n2), as.integer64(seq(n1, length.out=n2))) + expect_identical(seq(n1_64, length.out=n2_64), as.integer64(seq(n1, length.out=n2))) + + expect_identical(seq(n1_64, along.with=n2), as.integer64(seq(n1, along.with=n2))) + expect_identical(seq(n1_64, along.with=n2_64), as.integer64(seq(n1, along.with=n2))) + + expect_identical(seq(to=n1_64, by=n2), as.integer64(seq(to=n1, by=n2))) + expect_identical(seq(to=n1_64, by=n2_64), as.integer64(seq(to=n1, by=n2))) + + expect_identical(seq(to=n1_64, length.out=n2), as.integer64(seq(to=n1, length.out=n2))) + expect_identical(seq(to=n1_64, length.out=n2_64), as.integer64(seq(to=n1, length.out=n2))) + + expect_identical(seq(to=n1_64, along.with=n2), as.integer64(seq(to=n1, along.with=n2))) + expect_identical(seq(to=n1_64, along.with=n2_64), as.integer64(seq(to=n1, along.with=n2))) + + expect_identical(seq(by=n1_64, length.out=n2), as.integer64(seq(by=n1, length.out=n2))) + expect_identical(seq(by=n1_64, length.out=n2_64), as.integer64(seq(by=n1, length.out=n2))) + + expect_identical(seq(by=n1_64, along.with=n2), as.integer64(seq(by=n1, along.with=n2))) + expect_identical(seq(by=n1_64, along.with=n2_64), as.integer64(seq(by=n1, along.with=n2))) + + expect_identical(seq(length.out=n1_64, along.with=n2), as.integer64(seq(length.out=n1, along.with=n2))) + expect_identical(seq(length.out=n1_64, along.with=n2_64), as.integer64(seq(length.out=n1, along.with=n2))) + }, + .cases = expand.grid(n1=list(0L, 5L, -1L, 2:6), n2=list(0L, 5L, -1L, 2:6)) +) + +patrick::with_parameters_test_that( + "seq method works analogously to integer: 3 arguments", + { + n1_64 = as.integer64(n1) + n2_64 = as.integer64(n2) + n3_64 = as.integer64(n3) + + expect_identical(seq(n1_64, n2, by=n3), as.integer64(seq(n1, n2, by=n3))) + expect_identical(seq(n1_64, n2_64, by=n3), as.integer64(seq(n1, n2, by=n3))) + expect_identical(seq(n1_64, n2, by=n3_64), as.integer64(seq(n1, n2, by=n3))) + expect_identical(seq(n1_64, n2_64, by=n3_64), as.integer64(seq(n1, n2, by=n3))) + + expect_identical(seq(n1_64, n2, length.out=n3), as.integer64(seq(n1, n2, length.out=n3))) + expect_identical(seq(n1_64, n2_64, length.out=n3), as.integer64(seq(n1, n2, length.out=n3))) + expect_identical(seq(n1_64, n2, length.out=n3_64), as.integer64(seq(n1, n2, length.out=n3))) + expect_identical(seq(n1_64, n2_64, length.out=n3_64), as.integer64(seq(n1, n2, length.out=n3))) + + expect_identical(seq(n1_64, n2, along.with=n3), as.integer64(seq(n1, n2, along.with=n3))) + expect_identical(seq(n1_64, n2_64, along.with=n3), as.integer64(seq(n1, n2, along.with=n3))) + expect_identical(seq(n1_64, n2, along.with=n3_64), as.integer64(seq(n1, n2, along.with=n3))) + expect_identical(seq(n1_64, n2_64, along.with=n3_64), as.integer64(seq(n1, n2, along.with=n3))) + + expect_identical(seq(n1_64, by=n2, length.out=n3), as.integer64(seq(n1, by=n2, length.out=n3))) + expect_identical(seq(n1_64, by=n2_64, length.out=n3), as.integer64(seq(n1, by=n2, length.out=n3))) + expect_identical(seq(n1_64, by=n2, length.out=n3_64), as.integer64(seq(n1, by=n2, length.out=n3))) + expect_identical(seq(n1_64, by=n2_64, length.out=n3_64), as.integer64(seq(n1, by=n2, length.out=n3))) + + expect_identical(seq(n1_64, by=n2, along.with=n3), as.integer64(seq(n1, by=n2, along.with=n3))) + expect_identical(seq(n1_64, by=n2_64, along.with=n3), as.integer64(seq(n1, by=n2, along.with=n3))) + expect_identical(seq(n1_64, by=n2, along.with=n3_64), as.integer64(seq(n1, by=n2, along.with=n3))) + expect_identical(seq(n1_64, by=n2_64, along.with=n3_64), as.integer64(seq(n1, by=n2, along.with=n3))) + + expect_identical(seq(n1_64, length.out=n2, along.with=n3), as.integer64(seq(n1, length.out=n2, along.with=n3))) + expect_identical(seq(n1_64, length.out=n2_64, along.with=n3), as.integer64(seq(n1, length.out=n2, along.with=n3))) + expect_identical(seq(n1_64, length.out=n2, along.with=n3_64), as.integer64(seq(n1, length.out=n2, along.with=n3))) + expect_identical(seq(n1_64, length.out=n2_64, along.with=n3_64), as.integer64(seq(n1, length.out=n2, along.with=n3))) + + expect_identical(seq(to=n1_64, by=n2, length.out=n3), as.integer64(seq(to=n1, by=n2, length.out=n3))) + expect_identical(seq(to=n1_64, by=n2_64, length.out=n3), as.integer64(seq(to=n1, by=n2, length.out=n3))) + expect_identical(seq(to=n1_64, by=n2, length.out=n3_64), as.integer64(seq(to=n1, by=n2, length.out=n3))) + expect_identical(seq(to=n1_64, by=n2_64, length.out=n3_64), as.integer64(seq(to=n1, by=n2, length.out=n3))) + + expect_identical(seq(to=n1_64, by=n2, along.with=n3), as.integer64(seq(to=n1, by=n2, along.with=n3))) + expect_identical(seq(to=n1_64, by=n2_64, along.with=n3), as.integer64(seq(to=n1, by=n2, along.with=n3))) + expect_identical(seq(to=n1_64, by=n2, along.with=n3_64), as.integer64(seq(to=n1, by=n2, along.with=n3))) + expect_identical(seq(to=n1_64, by=n2_64, along.with=n3_64), as.integer64(seq(to=n1, by=n2, along.with=n3))) + + expect_identical(seq(by=n1_64, length.out=n2, along.with=n3), as.integer64(seq(by=n1, length.out=n2, along.with=n3))) + expect_identical(seq(by=n1_64, length.out=n2_64, along.with=n3), as.integer64(seq(by=n1, length.out=n2, along.with=n3))) + expect_identical(seq(by=n1_64, length.out=n2, along.with=n3_64), as.integer64(seq(by=n1, length.out=n2, along.with=n3))) + expect_identical(seq(by=n1_64, length.out=n2_64, along.with=n3_64), as.integer64(seq(by=n1, length.out=n2, along.with=n3))) + }, + .cases = expand.grid(n1=list(0L, 5L, -1L, 2:6), n2=list(0L, 5L, -1L, 2:6), n3=list(0L, 5L, -1L, 2:6)) +) test_that("seq method works analogously to integer: 4 arguments", { + n = as.integer64(5L) + + expect_error(seq(n, n, by=n, length.out=n), "too many arguments") + expect_error(seq(n, n, by=n, along.with=n), "too many arguments") + expect_error(seq(n, n, length.out=n, along.with=n), "too many arguments") + expect_error(seq(n, by=n, length.out=n, along.with=n), "too many arguments") + expect_error(seq(to=n, by=n, length.out=n, along.with=n), "too many arguments") }) # These tests were previously kept as tests under \examples{\dontshow{...}}. From 15e741dc0400848717e0298250acd7e46f0cfcab Mon Sep 17 00:00:00 2001 From: Michael Chirico Date: Fri, 2 Jan 2026 23:35:04 -0800 Subject: [PATCH 04/16] starting progress implementing --- R/integer64.R | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/R/integer64.R b/R/integer64.R index c56b333c..467fb65c 100644 --- a/R/integer64.R +++ b/R/integer64.R @@ -1031,7 +1031,19 @@ rep.integer64 <- function(x, ...) { #' @export seq.integer64 = function(from=NULL, to=NULL, by=NULL, length.out=NULL, along.with=NULL, ...) { - if (!is.null(along.with)) return(seq.integer64(from, to, length.out=length(along.with))) + if (!is.null(along.with)) return(seq.integer64(from, to, by=by, length.out=length(along.with))) + + n_args = !is.null(from) + !is.null(to) + !is.null(by) + !is.null(length.out) + + if (n_args == 1L) { + one = as.integer64(1L) + if (!is.null(from)) return(one:from) + if (!is.null(to)) return(one:to) + if (!is.null(length.out)) return(one:length.out) + # match seq(by=integer(1)) + return(one) + } + if (is.null(length.out)) { length.out = abs(to - from) + 1L } else { From 34015413c22fe69be54d715a1a5eb6d9dc32f74c Mon Sep 17 00:00:00 2001 From: Michael Chirico Date: Fri, 2 Jan 2026 23:58:24 -0800 Subject: [PATCH 05/16] progress by ignoring along.with for now --- R/integer64.R | 19 +++++++++-- tests/testthat/test-integer64.R | 59 ++++++--------------------------- 2 files changed, 27 insertions(+), 51 deletions(-) diff --git a/R/integer64.R b/R/integer64.R index 467fb65c..a40958fb 100644 --- a/R/integer64.R +++ b/R/integer64.R @@ -1033,13 +1033,22 @@ rep.integer64 <- function(x, ...) { seq.integer64 = function(from=NULL, to=NULL, by=NULL, length.out=NULL, along.with=NULL, ...) { if (!is.null(along.with)) return(seq.integer64(from, to, by=by, length.out=length(along.with))) - n_args = !is.null(from) + !is.null(to) + !is.null(by) + !is.null(length.out) + n_args = 4L - is.null(from) - is.null(to) - is.null(by) - is.null(length.out) + + if (n_args == 4L) + stop("too many arguments") if (n_args == 1L) { one = as.integer64(1L) if (!is.null(from)) return(one:from) if (!is.null(to)) return(one:to) - if (!is.null(length.out)) return(one:length.out) + if (!is.null(length.out)) { + if (length.out < 0L) + stop("'length.out' must be a non-negative number") + if (length.out == 0L) + return(integer64()) + return(one:length.out) + } # match seq(by=integer(1)) return(one) } @@ -1048,10 +1057,14 @@ seq.integer64 = function(from=NULL, to=NULL, by=NULL, length.out=NULL, along.wit length.out = abs(to - from) + 1L } else { length.out = as.integer(length.out) + if (length(length.out) > 1L) { + warning("first element used of 'length.out' argument") + length.out = length.out[1L] + } } if (is.null(by)) { - if (is.null(from) || is.null(to)) + if (is.null(from) || is.null(to) || length.out == 1L) by <- as.integer64(1L) else by <- as.integer64((to - from) / (length.out - 1L)) diff --git a/tests/testthat/test-integer64.R b/tests/testthat/test-integer64.R index 10017604..48de4cca 100644 --- a/tests/testthat/test-integer64.R +++ b/tests/testthat/test-integer64.R @@ -297,21 +297,24 @@ test_that("vector builders of integer64 work", { }) patrick::with_parameters_test_that( - "seq method works analogously to integer: 1 argument", + "seq method works analogously to integer: 1 argument (except along.with);", { n64 = as.integer64(n) expect_identical(seq(n64), as.integer64(seq(n))) expect_identical(seq(from=n64), as.integer64(seq(from=n))) expect_identical(seq(to=n64), as.integer64(seq(to=n))) expect_identical(seq(by=n64), as.integer64(seq(by=n))) - expect_identical(seq(length.out=n64), as.integer64(seq(length.out=n))) - expect_identical(seq(along.with=n64), as.integer64(seq(along.with=n))) + if (n < 0L) { + expect_error(seq(length.out=n64), "'length.out' must be a non-negative number") + } else { + expect_identical(seq(length.out=n64), as.integer64(seq(length.out=n))) + } }, - n = list(0L, 5L, -1L, 2:6) + n = c(0L, 5L, -1L) ) patrick::with_parameters_test_that( - "seq method works analogously to integer: 2 arguments", + "seq method works analogously to integer: 2 arguments (except along.with)", { n1_64 = as.integer64(n1) n2_64 = as.integer64(n2) @@ -325,32 +328,20 @@ patrick::with_parameters_test_that( expect_identical(seq(n1_64, length.out=n2), as.integer64(seq(n1, length.out=n2))) expect_identical(seq(n1_64, length.out=n2_64), as.integer64(seq(n1, length.out=n2))) - expect_identical(seq(n1_64, along.with=n2), as.integer64(seq(n1, along.with=n2))) - expect_identical(seq(n1_64, along.with=n2_64), as.integer64(seq(n1, along.with=n2))) - expect_identical(seq(to=n1_64, by=n2), as.integer64(seq(to=n1, by=n2))) expect_identical(seq(to=n1_64, by=n2_64), as.integer64(seq(to=n1, by=n2))) expect_identical(seq(to=n1_64, length.out=n2), as.integer64(seq(to=n1, length.out=n2))) expect_identical(seq(to=n1_64, length.out=n2_64), as.integer64(seq(to=n1, length.out=n2))) - expect_identical(seq(to=n1_64, along.with=n2), as.integer64(seq(to=n1, along.with=n2))) - expect_identical(seq(to=n1_64, along.with=n2_64), as.integer64(seq(to=n1, along.with=n2))) - expect_identical(seq(by=n1_64, length.out=n2), as.integer64(seq(by=n1, length.out=n2))) expect_identical(seq(by=n1_64, length.out=n2_64), as.integer64(seq(by=n1, length.out=n2))) - - expect_identical(seq(by=n1_64, along.with=n2), as.integer64(seq(by=n1, along.with=n2))) - expect_identical(seq(by=n1_64, along.with=n2_64), as.integer64(seq(by=n1, along.with=n2))) - - expect_identical(seq(length.out=n1_64, along.with=n2), as.integer64(seq(length.out=n1, along.with=n2))) - expect_identical(seq(length.out=n1_64, along.with=n2_64), as.integer64(seq(length.out=n1, along.with=n2))) }, - .cases = expand.grid(n1=list(0L, 5L, -1L, 2:6), n2=list(0L, 5L, -1L, 2:6)) + .cases = expand.grid(n1=list(0L, 5L, -1L), n2=list(0L, 5L, -1L)) ) patrick::with_parameters_test_that( - "seq method works analogously to integer: 3 arguments", + "seq method works analogously to integer: 3 arguments (except along.with)", { n1_64 = as.integer64(n1) n2_64 = as.integer64(n2) @@ -366,42 +357,17 @@ patrick::with_parameters_test_that( expect_identical(seq(n1_64, n2, length.out=n3_64), as.integer64(seq(n1, n2, length.out=n3))) expect_identical(seq(n1_64, n2_64, length.out=n3_64), as.integer64(seq(n1, n2, length.out=n3))) - expect_identical(seq(n1_64, n2, along.with=n3), as.integer64(seq(n1, n2, along.with=n3))) - expect_identical(seq(n1_64, n2_64, along.with=n3), as.integer64(seq(n1, n2, along.with=n3))) - expect_identical(seq(n1_64, n2, along.with=n3_64), as.integer64(seq(n1, n2, along.with=n3))) - expect_identical(seq(n1_64, n2_64, along.with=n3_64), as.integer64(seq(n1, n2, along.with=n3))) - expect_identical(seq(n1_64, by=n2, length.out=n3), as.integer64(seq(n1, by=n2, length.out=n3))) expect_identical(seq(n1_64, by=n2_64, length.out=n3), as.integer64(seq(n1, by=n2, length.out=n3))) expect_identical(seq(n1_64, by=n2, length.out=n3_64), as.integer64(seq(n1, by=n2, length.out=n3))) expect_identical(seq(n1_64, by=n2_64, length.out=n3_64), as.integer64(seq(n1, by=n2, length.out=n3))) - expect_identical(seq(n1_64, by=n2, along.with=n3), as.integer64(seq(n1, by=n2, along.with=n3))) - expect_identical(seq(n1_64, by=n2_64, along.with=n3), as.integer64(seq(n1, by=n2, along.with=n3))) - expect_identical(seq(n1_64, by=n2, along.with=n3_64), as.integer64(seq(n1, by=n2, along.with=n3))) - expect_identical(seq(n1_64, by=n2_64, along.with=n3_64), as.integer64(seq(n1, by=n2, along.with=n3))) - - expect_identical(seq(n1_64, length.out=n2, along.with=n3), as.integer64(seq(n1, length.out=n2, along.with=n3))) - expect_identical(seq(n1_64, length.out=n2_64, along.with=n3), as.integer64(seq(n1, length.out=n2, along.with=n3))) - expect_identical(seq(n1_64, length.out=n2, along.with=n3_64), as.integer64(seq(n1, length.out=n2, along.with=n3))) - expect_identical(seq(n1_64, length.out=n2_64, along.with=n3_64), as.integer64(seq(n1, length.out=n2, along.with=n3))) - expect_identical(seq(to=n1_64, by=n2, length.out=n3), as.integer64(seq(to=n1, by=n2, length.out=n3))) expect_identical(seq(to=n1_64, by=n2_64, length.out=n3), as.integer64(seq(to=n1, by=n2, length.out=n3))) expect_identical(seq(to=n1_64, by=n2, length.out=n3_64), as.integer64(seq(to=n1, by=n2, length.out=n3))) expect_identical(seq(to=n1_64, by=n2_64, length.out=n3_64), as.integer64(seq(to=n1, by=n2, length.out=n3))) - - expect_identical(seq(to=n1_64, by=n2, along.with=n3), as.integer64(seq(to=n1, by=n2, along.with=n3))) - expect_identical(seq(to=n1_64, by=n2_64, along.with=n3), as.integer64(seq(to=n1, by=n2, along.with=n3))) - expect_identical(seq(to=n1_64, by=n2, along.with=n3_64), as.integer64(seq(to=n1, by=n2, along.with=n3))) - expect_identical(seq(to=n1_64, by=n2_64, along.with=n3_64), as.integer64(seq(to=n1, by=n2, along.with=n3))) - - expect_identical(seq(by=n1_64, length.out=n2, along.with=n3), as.integer64(seq(by=n1, length.out=n2, along.with=n3))) - expect_identical(seq(by=n1_64, length.out=n2_64, along.with=n3), as.integer64(seq(by=n1, length.out=n2, along.with=n3))) - expect_identical(seq(by=n1_64, length.out=n2, along.with=n3_64), as.integer64(seq(by=n1, length.out=n2, along.with=n3))) - expect_identical(seq(by=n1_64, length.out=n2_64, along.with=n3_64), as.integer64(seq(by=n1, length.out=n2, along.with=n3))) }, - .cases = expand.grid(n1=list(0L, 5L, -1L, 2:6), n2=list(0L, 5L, -1L, 2:6), n3=list(0L, 5L, -1L, 2:6)) + .cases = expand.grid(n1=list(0L, 5L, -1L), n2=list(0L, 5L, -1L), n3=list(0L, 5L, -1L)) ) test_that("seq method works analogously to integer: 4 arguments", { @@ -409,9 +375,6 @@ test_that("seq method works analogously to integer: 4 arguments", { expect_error(seq(n, n, by=n, length.out=n), "too many arguments") expect_error(seq(n, n, by=n, along.with=n), "too many arguments") - expect_error(seq(n, n, length.out=n, along.with=n), "too many arguments") - expect_error(seq(n, by=n, length.out=n, along.with=n), "too many arguments") - expect_error(seq(to=n, by=n, length.out=n, along.with=n), "too many arguments") }) # These tests were previously kept as tests under \examples{\dontshow{...}}. From ae259582f72608b5e1c02dd1cffc00fcfd3fbed2 Mon Sep 17 00:00:00 2001 From: Michael Chirico Date: Sat, 3 Jan 2026 17:29:34 -0800 Subject: [PATCH 06/16] basic outline done, progress winnowing down expected errors --- R/integer64.R | 60 ++++++++++----------------------- tests/testthat/test-integer64.R | 60 ++++++++++++++++++++++----------- 2 files changed, 59 insertions(+), 61 deletions(-) diff --git a/R/integer64.R b/R/integer64.R index a40958fb..c7a4b9ef 100644 --- a/R/integer64.R +++ b/R/integer64.R @@ -1053,53 +1053,29 @@ seq.integer64 = function(from=NULL, to=NULL, by=NULL, length.out=NULL, along.wit return(one) } - if (is.null(length.out)) { - length.out = abs(to - from) + 1L - } else { - length.out = as.integer(length.out) - if (length(length.out) > 1L) { - warning("first element used of 'length.out' argument") - length.out = length.out[1L] - } - } - - if (is.null(by)) { - if (is.null(from) || is.null(to) || length.out == 1L) - by <- as.integer64(1L) - else - by <- as.integer64((to - from) / (length.out - 1L)) - } else { - by <- as.integer64(by) - if (!is.null(from) && !is.null(to) && (sign(by) != sign(to - from))) - stop("wrong sign of 'by' argument") + if (n_args == 2L) { + if (!is.null(from) && !is.null(to)) return(seq.integer64(from, to, by=1L)) + if (!is.null(from) && !is.null(by)) return(seq.integer64(from, 1L, by=by)) + if (!is.null(from) && !is.null(length.out)) return(seq.integer64(from, from+length.out-1L, by=1L)) + if (!is.null(to) && !is.null(by)) return(seq.integer64(as.integer64(1L), to, by=by)) + if (!is.null(to) && !is.null(length.out)) return(seq.integer64(to-length.out+1L, from, by=1L)) + return(seq.integer64(as.integer64(1L), by=by, length.out=length.out)) } if (is.null(from)) { - if (length.out && length(to)) - from <- to - (length.out-1L)*by - else - from <- as.integer64(1L) - } else { - from <- as.integer64(from) + from = to - (length.out - 1L) * by + } else if (is.null(by)) { + by = (to - from) / (length.out - 1L) + } else if (is.null(length.out)) { + if (sign(to - from) != sign(by)) + stop("wrong sign in 'by' argument'") + length.out = (to - from) / by + 1L } - - if (!length(to)) { - if (length.out) - to <- from + (length.out-1L)*by - else - stop("not enough information provided") - } - - if (!length.out) { - length.out <- (to-from) %/% by + 1L - } - - if (!length.out) return(integer64()) - if (length.out==1L) return(from) - #return(cumsum(c(from, rep(by, length.out-1L)))) - ret <- .Call(C_seq_integer64, from, by, double(as.integer(length.out))) + if (length.out < 0L) + stop("'length.out' must be a non-negative number") + ret <- .Call(C_seq_integer64, as.integer64(from), as.integer64(by), double(as.integer(length.out))) oldClass(ret) <- "integer64" - return(ret) + ret } #' @rdname xor.integer64 diff --git a/tests/testthat/test-integer64.R b/tests/testthat/test-integer64.R index 48de4cca..5d1ddbca 100644 --- a/tests/testthat/test-integer64.R +++ b/tests/testthat/test-integer64.R @@ -347,25 +347,47 @@ patrick::with_parameters_test_that( n2_64 = as.integer64(n2) n3_64 = as.integer64(n3) - expect_identical(seq(n1_64, n2, by=n3), as.integer64(seq(n1, n2, by=n3))) - expect_identical(seq(n1_64, n2_64, by=n3), as.integer64(seq(n1, n2, by=n3))) - expect_identical(seq(n1_64, n2, by=n3_64), as.integer64(seq(n1, n2, by=n3))) - expect_identical(seq(n1_64, n2_64, by=n3_64), as.integer64(seq(n1, n2, by=n3))) - - expect_identical(seq(n1_64, n2, length.out=n3), as.integer64(seq(n1, n2, length.out=n3))) - expect_identical(seq(n1_64, n2_64, length.out=n3), as.integer64(seq(n1, n2, length.out=n3))) - expect_identical(seq(n1_64, n2, length.out=n3_64), as.integer64(seq(n1, n2, length.out=n3))) - expect_identical(seq(n1_64, n2_64, length.out=n3_64), as.integer64(seq(n1, n2, length.out=n3))) - - expect_identical(seq(n1_64, by=n2, length.out=n3), as.integer64(seq(n1, by=n2, length.out=n3))) - expect_identical(seq(n1_64, by=n2_64, length.out=n3), as.integer64(seq(n1, by=n2, length.out=n3))) - expect_identical(seq(n1_64, by=n2, length.out=n3_64), as.integer64(seq(n1, by=n2, length.out=n3))) - expect_identical(seq(n1_64, by=n2_64, length.out=n3_64), as.integer64(seq(n1, by=n2, length.out=n3))) - - expect_identical(seq(to=n1_64, by=n2, length.out=n3), as.integer64(seq(to=n1, by=n2, length.out=n3))) - expect_identical(seq(to=n1_64, by=n2_64, length.out=n3), as.integer64(seq(to=n1, by=n2, length.out=n3))) - expect_identical(seq(to=n1_64, by=n2, length.out=n3_64), as.integer64(seq(to=n1, by=n2, length.out=n3))) - expect_identical(seq(to=n1_64, by=n2_64, length.out=n3_64), as.integer64(seq(to=n1, by=n2, length.out=n3))) + if (sign(n2 - n1) == sign(n3)) { + expect_identical(seq(n1_64, n2, by=n3), as.integer64(seq(n1, n2, by=n3))) + expect_identical(seq(n1_64, n2_64, by=n3), as.integer64(seq(n1, n2, by=n3))) + expect_identical(seq(n1_64, n2, by=n3_64), as.integer64(seq(n1, n2, by=n3))) + expect_identical(seq(n1_64, n2_64, by=n3_64), as.integer64(seq(n1, n2, by=n3))) + } else { + expect_error( + seq(n1_64, n2, by=n3), + "wrong sign in 'by' argument", fixed=TRUE + ) + } + + if (n3 < 0L) { + expect_error( + seq(n1_64, n2, length.out=n3), + "'length.out' must be a non-negative", fixed=TRUE + ) + expect_error( + seq(n1_64, by=n2, length.out=n3), + "'length.out' must be a non-negative", fixed=TRUE + ) + expect_error( + seq(to=n1_64, by=n2, length.out=n3), + "'length.out' must be a non-negative", fixed=TRUE + ) + } else { + expect_identical(seq(n1_64, n2, length.out=n3), as.integer64(seq(n1, n2, length.out=n3))) + expect_identical(seq(n1_64, n2_64, length.out=n3), as.integer64(seq(n1, n2, length.out=n3))) + expect_identical(seq(n1_64, n2, length.out=n3_64), as.integer64(seq(n1, n2, length.out=n3))) + expect_identical(seq(n1_64, n2_64, length.out=n3_64), as.integer64(seq(n1, n2, length.out=n3))) + + expect_identical(seq(n1_64, by=n2, length.out=n3), as.integer64(seq(n1, by=n2, length.out=n3))) + expect_identical(seq(n1_64, by=n2_64, length.out=n3), as.integer64(seq(n1, by=n2, length.out=n3))) + expect_identical(seq(n1_64, by=n2, length.out=n3_64), as.integer64(seq(n1, by=n2, length.out=n3))) + expect_identical(seq(n1_64, by=n2_64, length.out=n3_64), as.integer64(seq(n1, by=n2, length.out=n3))) + + expect_identical(seq(to=n1_64, by=n2, length.out=n3), as.integer64(seq(to=n1, by=n2, length.out=n3))) + expect_identical(seq(to=n1_64, by=n2_64, length.out=n3), as.integer64(seq(to=n1, by=n2, length.out=n3))) + expect_identical(seq(to=n1_64, by=n2, length.out=n3_64), as.integer64(seq(to=n1, by=n2, length.out=n3))) + expect_identical(seq(to=n1_64, by=n2_64, length.out=n3_64), as.integer64(seq(to=n1, by=n2, length.out=n3))) + } }, .cases = expand.grid(n1=list(0L, 5L, -1L), n2=list(0L, 5L, -1L), n3=list(0L, 5L, -1L)) ) From b81838a16c53c89e61084271240db441405c183d Mon Sep 17 00:00:00 2001 From: Michael Chirico Date: Sun, 4 Jan 2026 12:55:02 -0800 Subject: [PATCH 07/16] more progress, edge case handling --- R/integer64.R | 8 +++- tests/testthat/test-integer64.R | 74 ++++++++++++++++++--------------- 2 files changed, 48 insertions(+), 34 deletions(-) diff --git a/R/integer64.R b/R/integer64.R index c7a4b9ef..9c9d1190 100644 --- a/R/integer64.R +++ b/R/integer64.R @@ -1054,7 +1054,9 @@ seq.integer64 = function(from=NULL, to=NULL, by=NULL, length.out=NULL, along.wit } if (n_args == 2L) { - if (!is.null(from) && !is.null(to)) return(seq.integer64(from, to, by=1L)) + if (!is.null(length.out) && length.out < 0L) + stop("'length.out' must be a non-negative number") + if (!is.null(from) && !is.null(to)) return(seq.integer64(from, to, by=sign(to - from))) if (!is.null(from) && !is.null(by)) return(seq.integer64(from, 1L, by=by)) if (!is.null(from) && !is.null(length.out)) return(seq.integer64(from, from+length.out-1L, by=1L)) if (!is.null(to) && !is.null(by)) return(seq.integer64(as.integer64(1L), to, by=by)) @@ -1067,6 +1069,10 @@ seq.integer64 = function(from=NULL, to=NULL, by=NULL, length.out=NULL, along.wit } else if (is.null(by)) { by = (to - from) / (length.out - 1L) } else if (is.null(length.out)) { + if (to != from && by == 0L) + stop("invalid '(to - from)/by'") + if (to == from) + return(as.integer64(from)) if (sign(to - from) != sign(by)) stop("wrong sign in 'by' argument'") length.out = (to - from) / by + 1L diff --git a/tests/testthat/test-integer64.R b/tests/testthat/test-integer64.R index 5d1ddbca..ada3ffde 100644 --- a/tests/testthat/test-integer64.R +++ b/tests/testthat/test-integer64.R @@ -322,22 +322,37 @@ patrick::with_parameters_test_that( expect_identical(seq(n1_64, n2), as.integer64(seq(n1, n2))) expect_identical(seq(n1_64, n2_64), as.integer64(seq(n1, n2))) - expect_identical(seq(n1_64, by=n2), as.integer64(seq(n1, by=n2))) - expect_identical(seq(n1_64, by=n2_64), as.integer64(seq(n1, by=n2))) - expect_identical(seq(n1_64, length.out=n2), as.integer64(seq(n1, length.out=n2))) - expect_identical(seq(n1_64, length.out=n2_64), as.integer64(seq(n1, length.out=n2))) + err_msg = if (n2 == 0L) "invalid '(to - from)/by'" else "wrong sign in 'by' argument" + if (sign(1L - n1) == sign(n2)) { + expect_identical(seq(n1_64, by=n2), as.integer64(seq(n1, by=n2))) + expect_identical(seq(n1_64, by=n2_64), as.integer64(seq(n1, by=n2))) - expect_identical(seq(to=n1_64, by=n2), as.integer64(seq(to=n1, by=n2))) - expect_identical(seq(to=n1_64, by=n2_64), as.integer64(seq(to=n1, by=n2))) + expect_error(seq(to=n1_64, by=n2), err_msg, fixed=TRUE) + } else { + expect_error(seq(n1_64, by=n2), err_msg, fixed=TRUE) + + expect_identical(seq(to=n1_64, by=n2), as.integer64(seq(to=n1, by=n2))) + expect_identical(seq(to=n1_64, by=n2_64), as.integer64(seq(to=n1, by=n2))) + } - expect_identical(seq(to=n1_64, length.out=n2), as.integer64(seq(to=n1, length.out=n2))) - expect_identical(seq(to=n1_64, length.out=n2_64), as.integer64(seq(to=n1, length.out=n2))) + if (n2 >= 0L) { + expect_identical(seq(n1_64, length.out=n2), as.integer64(seq(n1, length.out=n2))) + expect_identical(seq(n1_64, length.out=n2_64), as.integer64(seq(n1, length.out=n2))) - expect_identical(seq(by=n1_64, length.out=n2), as.integer64(seq(by=n1, length.out=n2))) - expect_identical(seq(by=n1_64, length.out=n2_64), as.integer64(seq(by=n1, length.out=n2))) + expect_identical(seq(to=n1_64, length.out=n2), as.integer64(seq(to=n1, length.out=n2))) + expect_identical(seq(to=n1_64, length.out=n2_64), as.integer64(seq(to=n1, length.out=n2))) + + expect_identical(seq(by=n1_64, length.out=n2), as.integer64(seq(by=n1, length.out=n2))) + expect_identical(seq(by=n1_64, length.out=n2_64), as.integer64(seq(by=n1, length.out=n2))) + } else { + err_msg = "'length.out' must be a non-negative number" + expect_error(seq(n1_64, length.out=n2), err_msg, fixed=TRUE) + expect_error(seq(to=n1_64, length.out=n2), err_msg, fixed=TRUE) + expect_error(seq(by=n1_64, length.out=n2), err_msg, fixed=TRUE) + } }, - .cases = expand.grid(n1=list(0L, 5L, -1L), n2=list(0L, 5L, -1L)) + .cases = expand.grid(n1=c(0L, 5L, -1L), n2=c(0L, 5L, -1L)) ) patrick::with_parameters_test_that( @@ -347,36 +362,29 @@ patrick::with_parameters_test_that( n2_64 = as.integer64(n2) n3_64 = as.integer64(n3) - if (sign(n2 - n1) == sign(n3)) { + if (n2 == n1 || sign(n2 - n1) == sign(n3)) { expect_identical(seq(n1_64, n2, by=n3), as.integer64(seq(n1, n2, by=n3))) expect_identical(seq(n1_64, n2_64, by=n3), as.integer64(seq(n1, n2, by=n3))) expect_identical(seq(n1_64, n2, by=n3_64), as.integer64(seq(n1, n2, by=n3))) expect_identical(seq(n1_64, n2_64, by=n3_64), as.integer64(seq(n1, n2, by=n3))) } else { - expect_error( - seq(n1_64, n2, by=n3), - "wrong sign in 'by' argument", fixed=TRUE - ) + err_msg <- if (n3 == 0L) "invalid '(to - from)/by'" else "wrong sign in 'by' argument" + expect_error(seq(n1_64, n2, by=n3), err_msg, fixed=TRUE) } if (n3 < 0L) { - expect_error( - seq(n1_64, n2, length.out=n3), - "'length.out' must be a non-negative", fixed=TRUE - ) - expect_error( - seq(n1_64, by=n2, length.out=n3), - "'length.out' must be a non-negative", fixed=TRUE - ) - expect_error( - seq(to=n1_64, by=n2, length.out=n3), - "'length.out' must be a non-negative", fixed=TRUE - ) + err_msg = "'length.out' must be a non-negative" + expect_error(seq(n1_64, n2, length.out=n3), err_msg, fixed=TRUE) + expect_error(seq(n1_64, by=n2, length.out=n3), err_msg, fixed=TRUE) + expect_error(seq(to=n1_64, by=n2, length.out=n3), err_msg, fixed=TRUE) } else { - expect_identical(seq(n1_64, n2, length.out=n3), as.integer64(seq(n1, n2, length.out=n3))) - expect_identical(seq(n1_64, n2_64, length.out=n3), as.integer64(seq(n1, n2, length.out=n3))) - expect_identical(seq(n1_64, n2, length.out=n3_64), as.integer64(seq(n1, n2, length.out=n3))) - expect_identical(seq(n1_64, n2_64, length.out=n3_64), as.integer64(seq(n1, n2, length.out=n3))) + # TODO(#47): restore parity to seq() here + if (((n2 - n1) / (n3 - 1L)) %% 1L == 0L) { + expect_identical(seq(n1_64, n2, length.out=n3), as.integer64(seq(n1, n2, length.out=n3))) + expect_identical(seq(n1_64, n2_64, length.out=n3), as.integer64(seq(n1, n2, length.out=n3))) + expect_identical(seq(n1_64, n2, length.out=n3_64), as.integer64(seq(n1, n2, length.out=n3))) + expect_identical(seq(n1_64, n2_64, length.out=n3_64), as.integer64(seq(n1, n2, length.out=n3))) + } expect_identical(seq(n1_64, by=n2, length.out=n3), as.integer64(seq(n1, by=n2, length.out=n3))) expect_identical(seq(n1_64, by=n2_64, length.out=n3), as.integer64(seq(n1, by=n2, length.out=n3))) @@ -389,7 +397,7 @@ patrick::with_parameters_test_that( expect_identical(seq(to=n1_64, by=n2_64, length.out=n3_64), as.integer64(seq(to=n1, by=n2, length.out=n3))) } }, - .cases = expand.grid(n1=list(0L, 5L, -1L), n2=list(0L, 5L, -1L), n3=list(0L, 5L, -1L)) + .cases = expand.grid(n1=c(0L, 5L, -1L), n2=c(0L, 5L, -1L), n3=c(0L, 5L, -1L)) ) test_that("seq method works analogously to integer: 4 arguments", { From e033db63f82b0b24143ba94352c3409efde2f307 Mon Sep 17 00:00:00 2001 From: Michael Chirico Date: Sun, 4 Jan 2026 13:25:23 -0800 Subject: [PATCH 08/16] suite passing --- R/integer64.R | 19 +++++++++++++------ tests/testthat/test-integer64.R | 11 +++++++---- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/R/integer64.R b/R/integer64.R index 9c9d1190..c4c85d8c 100644 --- a/R/integer64.R +++ b/R/integer64.R @@ -1054,14 +1054,21 @@ seq.integer64 = function(from=NULL, to=NULL, by=NULL, length.out=NULL, along.wit } if (n_args == 2L) { - if (!is.null(length.out) && length.out < 0L) - stop("'length.out' must be a non-negative number") + if (!is.null(length.out)) { + if (length.out == 0L) + return(integer64()) + if (length.out < 0L) + stop("'length.out' must be a non-negative number") + if (!is.null(from)) + return(seq.integer64(from, from+length.out-1L, by=1L)) + if (!is.null(to)) + return(seq.integer64(to-length.out+1L, to, by=1L)) + if (!is.null(by)) + return(seq.integer64(as.integer64(1L), by=by, length.out=length.out)) + } if (!is.null(from) && !is.null(to)) return(seq.integer64(from, to, by=sign(to - from))) if (!is.null(from) && !is.null(by)) return(seq.integer64(from, 1L, by=by)) - if (!is.null(from) && !is.null(length.out)) return(seq.integer64(from, from+length.out-1L, by=1L)) - if (!is.null(to) && !is.null(by)) return(seq.integer64(as.integer64(1L), to, by=by)) - if (!is.null(to) && !is.null(length.out)) return(seq.integer64(to-length.out+1L, from, by=1L)) - return(seq.integer64(as.integer64(1L), by=by, length.out=length.out)) + return(seq.integer64(as.integer64(1L), to, by=by)) } if (is.null(from)) { diff --git a/tests/testthat/test-integer64.R b/tests/testthat/test-integer64.R index ada3ffde..2c567b1d 100644 --- a/tests/testthat/test-integer64.R +++ b/tests/testthat/test-integer64.R @@ -323,14 +323,17 @@ patrick::with_parameters_test_that( expect_identical(seq(n1_64, n2_64), as.integer64(seq(n1, n2))) - err_msg = if (n2 == 0L) "invalid '(to - from)/by'" else "wrong sign in 'by' argument" - if (sign(1L - n1) == sign(n2)) { + if (n2 == 0) { + err_msg = "invalid '(to - from)/by'" + expect_error(seq(n1_64, by=n2), err_msg, fixed=TRUE) + expect_error(seq(to=n1_64, by=n2), err_msg, fixed=TRUE) + } else if (sign(1L - n1) == sign(n2)) { expect_identical(seq(n1_64, by=n2), as.integer64(seq(n1, by=n2))) expect_identical(seq(n1_64, by=n2_64), as.integer64(seq(n1, by=n2))) - expect_error(seq(to=n1_64, by=n2), err_msg, fixed=TRUE) + expect_error(seq(to=n1_64, by=n2), "wrong sign in 'by' argument", fixed=TRUE) } else { - expect_error(seq(n1_64, by=n2), err_msg, fixed=TRUE) + expect_error(seq(n1_64, by=n2), "wrong sign in 'by' argument", fixed=TRUE) expect_identical(seq(to=n1_64, by=n2), as.integer64(seq(to=n1, by=n2))) expect_identical(seq(to=n1_64, by=n2_64), as.integer64(seq(to=n1, by=n2))) From 5ac62056788b0a019d8fe5e3a9494bbf95d013ed Mon Sep 17 00:00:00 2001 From: Michael Chirico Date: Sun, 4 Jan 2026 13:27:29 -0800 Subject: [PATCH 09/16] no patrick:: for ancient --- tests/testthat/test-integer64.R | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/testthat/test-integer64.R b/tests/testthat/test-integer64.R index 2c567b1d..73a187c9 100644 --- a/tests/testthat/test-integer64.R +++ b/tests/testthat/test-integer64.R @@ -296,7 +296,7 @@ test_that("vector builders of integer64 work", { expect_identical(x[3L]:x[1L], x[3:1]) # rev() a separate method }) -patrick::with_parameters_test_that( +with_parameters_test_that( "seq method works analogously to integer: 1 argument (except along.with);", { n64 = as.integer64(n) @@ -313,7 +313,7 @@ patrick::with_parameters_test_that( n = c(0L, 5L, -1L) ) -patrick::with_parameters_test_that( +with_parameters_test_that( "seq method works analogously to integer: 2 arguments (except along.with)", { n1_64 = as.integer64(n1) @@ -358,7 +358,7 @@ patrick::with_parameters_test_that( .cases = expand.grid(n1=c(0L, 5L, -1L), n2=c(0L, 5L, -1L)) ) -patrick::with_parameters_test_that( +with_parameters_test_that( "seq method works analogously to integer: 3 arguments (except along.with)", { n1_64 = as.integer64(n1) From 872f6ee88823c9a53301716ac793cf8a020ab9ec Mon Sep 17 00:00:00 2001 From: Michael Chirico Date: Sun, 4 Jan 2026 21:47:45 -0800 Subject: [PATCH 10/16] Mix in some cases mixing fractions Also more skipped cases, for now, related to mixed integer64+double arithmetic. --- R/integer64.R | 9 ++++ tests/testthat/test-integer64.R | 80 ++++++++++++++++++++------------- 2 files changed, 58 insertions(+), 31 deletions(-) diff --git a/R/integer64.R b/R/integer64.R index c4c85d8c..ae280997 100644 --- a/R/integer64.R +++ b/R/integer64.R @@ -1059,6 +1059,9 @@ seq.integer64 = function(from=NULL, to=NULL, by=NULL, length.out=NULL, along.wit return(integer64()) if (length.out < 0L) stop("'length.out' must be a non-negative number") + # do before mixing with from/to to avoid integer64/double fraction arithmetic + if (is.double(length.out) && length.out %% 1L != 0L) + length.out = ceiling(length.out) if (!is.null(from)) return(seq.integer64(from, from+length.out-1L, by=1L)) if (!is.null(to)) @@ -1071,9 +1074,15 @@ seq.integer64 = function(from=NULL, to=NULL, by=NULL, length.out=NULL, along.wit return(seq.integer64(as.integer64(1L), to, by=by)) } + # match base behavior for seq(1, 2, length.out=1.5) + if (!is.null(length.out) && is.double(length.out)) + length.out = ceiling(length.out) + if (is.null(from)) { from = to - (length.out - 1L) * by } else if (is.null(by)) { + if (length.out == 1L) + return(as.integer64(from)) by = (to - from) / (length.out - 1L) } else if (is.null(length.out)) { if (to != from && by == 0L) diff --git a/tests/testthat/test-integer64.R b/tests/testthat/test-integer64.R index 73a187c9..acd4dc8f 100644 --- a/tests/testthat/test-integer64.R +++ b/tests/testthat/test-integer64.R @@ -316,38 +316,44 @@ with_parameters_test_that( with_parameters_test_that( "seq method works analogously to integer: 2 arguments (except along.with)", { + # be sure to coerce (truncate) consistently across actual/expected + n1_32 = as.integer(n1) + n2_32 = as.integer(n2) + n1_64 = as.integer64(n1) n2_64 = as.integer64(n2) - expect_identical(seq(n1_64, n2), as.integer64(seq(n1, n2))) - expect_identical(seq(n1_64, n2_64), as.integer64(seq(n1, n2))) + # TODO(#47): restore parity to seq() here + if (n2 %% 1L == 0L) expect_identical(seq(n1_64, n2), as.integer64(seq(n1_32, n2))) + expect_identical(seq(n1_64, n2_64), as.integer64(seq(n1_32, n2_32))) - if (n2 == 0) { + if (n2 == 0L) { err_msg = "invalid '(to - from)/by'" expect_error(seq(n1_64, by=n2), err_msg, fixed=TRUE) expect_error(seq(to=n1_64, by=n2), err_msg, fixed=TRUE) } else if (sign(1L - n1) == sign(n2)) { expect_identical(seq(n1_64, by=n2), as.integer64(seq(n1, by=n2))) - expect_identical(seq(n1_64, by=n2_64), as.integer64(seq(n1, by=n2))) + expect_identical(seq(n1_64, by=n2_64), as.integer64(seq(n1, by=n2_32))) expect_error(seq(to=n1_64, by=n2), "wrong sign in 'by' argument", fixed=TRUE) } else { expect_error(seq(n1_64, by=n2), "wrong sign in 'by' argument", fixed=TRUE) - expect_identical(seq(to=n1_64, by=n2), as.integer64(seq(to=n1, by=n2))) - expect_identical(seq(to=n1_64, by=n2_64), as.integer64(seq(to=n1, by=n2))) + # TODO(#47): restore parity to seq() here + if (n2 %% 1L == 0L) expect_identical(seq(to=n1_64, by=n2), as.integer64(seq(to=n1, by=n2))) + expect_identical(seq(to=n1_64, by=n2_64), as.integer64(seq(to=n1, by=n2_32))) } if (n2 >= 0L) { - expect_identical(seq(n1_64, length.out=n2), as.integer64(seq(n1, length.out=n2))) - expect_identical(seq(n1_64, length.out=n2_64), as.integer64(seq(n1, length.out=n2))) + expect_identical(seq(n1_64, length.out=n2), as.integer64(seq(n1_32, length.out=n2))) + expect_identical(seq(n1_64, length.out=n2_64), as.integer64(seq(n1_32, length.out=n2_32))) - expect_identical(seq(to=n1_64, length.out=n2), as.integer64(seq(to=n1, length.out=n2))) - expect_identical(seq(to=n1_64, length.out=n2_64), as.integer64(seq(to=n1, length.out=n2))) + expect_identical(seq(to=n1_64, length.out=n2), as.integer64(seq(to=n1_32, length.out=n2))) + expect_identical(seq(to=n1_64, length.out=n2_64), as.integer64(seq(to=n1_32, length.out=n2_32))) - expect_identical(seq(by=n1_64, length.out=n2), as.integer64(seq(by=n1, length.out=n2))) - expect_identical(seq(by=n1_64, length.out=n2_64), as.integer64(seq(by=n1, length.out=n2))) + expect_identical(seq(by=n1_64, length.out=n2), as.integer64(seq(by=n1_32, length.out=n2))) + expect_identical(seq(by=n1_64, length.out=n2_64), as.integer64(seq(by=n1_32, length.out=n2_32))) } else { err_msg = "'length.out' must be a non-negative number" expect_error(seq(n1_64, length.out=n2), err_msg, fixed=TRUE) @@ -355,21 +361,30 @@ with_parameters_test_that( expect_error(seq(by=n1_64, length.out=n2), err_msg, fixed=TRUE) } }, - .cases = expand.grid(n1=c(0L, 5L, -1L), n2=c(0L, 5L, -1L)) + .cases = expand.grid(n1=c(0L, 5L, -1L), n2=c(0.0, 5.0, -1.0, 1.5)) ) with_parameters_test_that( "seq method works analogously to integer: 3 arguments (except along.with)", { + # be sure to coerce (truncate) consistently across actual/expected + n1_32 = as.integer(n1) + n2_32 = as.integer(n2) + n3_32 = as.integer(n3) + n1_64 = as.integer64(n1) n2_64 = as.integer64(n2) n3_64 = as.integer64(n3) + # TODO(#47): restore parity to seq() here if (n2 == n1 || sign(n2 - n1) == sign(n3)) { - expect_identical(seq(n1_64, n2, by=n3), as.integer64(seq(n1, n2, by=n3))) - expect_identical(seq(n1_64, n2_64, by=n3), as.integer64(seq(n1, n2, by=n3))) - expect_identical(seq(n1_64, n2, by=n3_64), as.integer64(seq(n1, n2, by=n3))) - expect_identical(seq(n1_64, n2_64, by=n3_64), as.integer64(seq(n1, n2, by=n3))) + # TODO(#47): restore parity to seq() here + if (n2 %% 1L == 0L && n3 %% 1L == 0L) { + expect_identical(seq(n1_64, n2, by=n3), as.integer64(seq(n1_32, n2, by=n3))) + expect_identical(seq(n1_64, n2_64, by=n3), as.integer64(seq(n1_32, n2_32, by=n3))) + expect_identical(seq(n1_64, n2, by=n3_64), as.integer64(seq(n1_32, n2, by=n3_32))) + expect_identical(seq(n1_64, n2_64, by=n3_64), as.integer64(seq(n1_32, n2_32, by=n3_32))) + } } else { err_msg <- if (n3 == 0L) "invalid '(to - from)/by'" else "wrong sign in 'by' argument" expect_error(seq(n1_64, n2, by=n3), err_msg, fixed=TRUE) @@ -383,24 +398,27 @@ with_parameters_test_that( } else { # TODO(#47): restore parity to seq() here if (((n2 - n1) / (n3 - 1L)) %% 1L == 0L) { - expect_identical(seq(n1_64, n2, length.out=n3), as.integer64(seq(n1, n2, length.out=n3))) - expect_identical(seq(n1_64, n2_64, length.out=n3), as.integer64(seq(n1, n2, length.out=n3))) - expect_identical(seq(n1_64, n2, length.out=n3_64), as.integer64(seq(n1, n2, length.out=n3))) - expect_identical(seq(n1_64, n2_64, length.out=n3_64), as.integer64(seq(n1, n2, length.out=n3))) + expect_identical(seq(n1_64, n2, length.out=n3), as.integer64(seq(n1_32, n2, length.out=n3))) + expect_identical(seq(n1_64, n2_64, length.out=n3), as.integer64(seq(n1_32, n2_32, length.out=n3))) + expect_identical(seq(n1_64, n2, length.out=n3_64), as.integer64(seq(n1_32, n2, length.out=n3_32))) + expect_identical(seq(n1_64, n2_64, length.out=n3_64), as.integer64(seq(n1_32, n2_32, length.out=n3_32))) } - expect_identical(seq(n1_64, by=n2, length.out=n3), as.integer64(seq(n1, by=n2, length.out=n3))) - expect_identical(seq(n1_64, by=n2_64, length.out=n3), as.integer64(seq(n1, by=n2, length.out=n3))) - expect_identical(seq(n1_64, by=n2, length.out=n3_64), as.integer64(seq(n1, by=n2, length.out=n3))) - expect_identical(seq(n1_64, by=n2_64, length.out=n3_64), as.integer64(seq(n1, by=n2, length.out=n3))) - - expect_identical(seq(to=n1_64, by=n2, length.out=n3), as.integer64(seq(to=n1, by=n2, length.out=n3))) - expect_identical(seq(to=n1_64, by=n2_64, length.out=n3), as.integer64(seq(to=n1, by=n2, length.out=n3))) - expect_identical(seq(to=n1_64, by=n2, length.out=n3_64), as.integer64(seq(to=n1, by=n2, length.out=n3))) - expect_identical(seq(to=n1_64, by=n2_64, length.out=n3_64), as.integer64(seq(to=n1, by=n2, length.out=n3))) + # TODO(#47): restore parity to seq() here + if (n2 %% 1L == 0L) { + expect_identical(seq(n1_64, by=n2, length.out=n3), as.integer64(seq(n1_32, by=n2, length.out=n3))) + expect_identical(seq(n1_64, by=n2_64, length.out=n3), as.integer64(seq(n1_32, by=n2_32, length.out=n3))) + expect_identical(seq(n1_64, by=n2, length.out=n3_64), as.integer64(seq(n1_32, by=n2, length.out=n3_32))) + expect_identical(seq(n1_64, by=n2_64, length.out=n3_64), as.integer64(seq(n1_32, by=n2_32, length.out=n3_32))) + + expect_identical(seq(to=n1_64, by=n2, length.out=n3), as.integer64(seq(to=n1_32, by=n2, length.out=n3))) + expect_identical(seq(to=n1_64, by=n2_64, length.out=n3), as.integer64(seq(to=n1_32, by=n2_32, length.out=n3))) + expect_identical(seq(to=n1_64, by=n2, length.out=n3_64), as.integer64(seq(to=n1_32, by=n2, length.out=n3_32))) + expect_identical(seq(to=n1_64, by=n2_64, length.out=n3_64), as.integer64(seq(to=n1_32, by=n2_32, length.out=n3_32))) + } } }, - .cases = expand.grid(n1=c(0L, 5L, -1L), n2=c(0L, 5L, -1L), n3=c(0L, 5L, -1L)) + .cases = expand.grid(n1=c(0L, 5L, -1L), n2=c(0.0, 5.0, -1.0, 1.5), n3=c(0.0, 5.0, -1.0, 1.5)) ) test_that("seq method works analogously to integer: 4 arguments", { From 102990410bf43accf923b74fa03678ce4fef5b5d Mon Sep 17 00:00:00 2001 From: Michael Chirico Date: Sun, 4 Jan 2026 23:36:05 -0800 Subject: [PATCH 11/16] Some back-compatibility tests --- R/integer64.R | 5 ++++- tests/testthat/test-integer64.R | 12 ++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/R/integer64.R b/R/integer64.R index ae280997..75193729 100644 --- a/R/integer64.R +++ b/R/integer64.R @@ -1078,6 +1078,9 @@ seq.integer64 = function(from=NULL, to=NULL, by=NULL, length.out=NULL, along.wit if (!is.null(length.out) && is.double(length.out)) length.out = ceiling(length.out) + if (!is.null(by) && !is.integer64(by)) + by = as.integer64(by) + if (is.null(from)) { from = to - (length.out - 1L) * by } else if (is.null(by)) { @@ -1095,7 +1098,7 @@ seq.integer64 = function(from=NULL, to=NULL, by=NULL, length.out=NULL, along.wit } if (length.out < 0L) stop("'length.out' must be a non-negative number") - ret <- .Call(C_seq_integer64, as.integer64(from), as.integer64(by), double(as.integer(length.out))) + ret <- .Call(C_seq_integer64, as.integer64(from), by, double(as.integer(length.out))) oldClass(ret) <- "integer64" ret } diff --git a/tests/testthat/test-integer64.R b/tests/testthat/test-integer64.R index acd4dc8f..5bfcdd16 100644 --- a/tests/testthat/test-integer64.R +++ b/tests/testthat/test-integer64.R @@ -428,6 +428,18 @@ test_that("seq method works analogously to integer: 4 arguments", { expect_error(seq(n, n, by=n, along.with=n), "too many arguments") }) +test_that("seq() works back-compatibly w.r.t. mixed integer+double inputs", { + one = as.integer64(1L) + expect_identical(seq(one, 10L, by=1.5), as.integer64(1:10)) + expect_identical(seq(to=one, from=10L, by=-1.5), as.integer64(10:1)) + + expect_identical(seq(one, 10L, by=10.0/3.0), as.integer64(c(1L, 4L, 7L, 10L))) + expect_identical(seq(to=one, from=10L, by=-10.0/3.0), as.integer64(c(10L, 7L, 4L, 1L))) + + expect_error(seq(one, 10L, by=0.1), "invalid '(to - from)/by'", fixed=TRUE) + expect_error(seq(to=one, from=10L, by=-0.1), "invalid '(to - from)/by'", fixed=TRUE) +}) + # These tests were previously kept as tests under \examples{\dontshow{...}}. # Converted to "proper" unit tests for clarity, after making them more # canonical within {testthat}, e.g. better capturing expected warnings, From d8796632b32efca2ecd5506fb53dda10fb8f2d9d Mon Sep 17 00:00:00 2001 From: Michael Chirico Date: Sun, 4 Jan 2026 23:40:12 -0800 Subject: [PATCH 12/16] intermediate --- DESCRIPTION | 2 +- R/integer64.R | 59 +++++++++++++++----------------- man/as.character.integer64.Rd | 4 +-- man/benchmark64.Rd | 18 +++++----- man/cache.Rd | 4 +-- man/cumsum.integer64.Rd | 4 +-- man/extract.replace.integer64.Rd | 4 +-- man/hashmap.Rd | 10 +++--- man/match.integer64.Rd | 22 ++++++------ man/plusclass.Rd | 4 +-- man/qtile.Rd | 2 +- man/rep.integer64.Rd | 2 +- man/seq.integer64.Rd | 10 ++++++ man/xor.integer64.Rd | 2 +- 14 files changed, 76 insertions(+), 71 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index 8642ca22..5e3371fb 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -32,5 +32,5 @@ Suggests: Config/testthat/edition: 3 Config/Needs/development: patrick, testthat Config/Needs/website: tidyverse/tidytemplate -RoxygenNote: 7.3.2 +RoxygenNote: 7.3.3 Roxygen: list(markdown = TRUE) diff --git a/R/integer64.R b/R/integer64.R index 75193729..28f25c1e 100644 --- a/R/integer64.R +++ b/R/integer64.R @@ -301,37 +301,6 @@ NULL #' @name rep.integer64 NULL -#' integer64: Sequence Generation -#' -#' Generating sequence of integer64 values -#' -#' @param from integer64 scalar (in order to dispatch the integer64 method of [seq()]) -#' @param to scalar -#' @param by scalar -#' @param length.out scalar -#' @param along.with scalar -#' @param ... ignored -#' @details -#' `seq.integer64` does coerce its arguments 'from', 'to' and 'by' to `integer64`. -#' If not provided, the argument 'by' is automatically determined as `+1` or `-1`, -#' but the size of 'by' is not calculated as in [seq()] (because this might result -#' in a non-integer value). -#' -#' @returns an integer64 vector with the generated sequence -#' @note -#' In base R [`:`] currently is not generic and does not dispatch, see section -#' "Limitations inherited from Base R" in [integer64()] -#' -#' @keywords classes manip -#' @seealso [c.integer64()] [rep.integer64()] -#' [as.data.frame.integer64()] [integer64()] -#' @examples -#' # colon not activated: as.integer64(1):12 -#' seq(as.integer64(1), 12, 2) -#' seq(as.integer64(1), by=2, length.out=6) -#' @name seq.integer64 -NULL - #' integer64: Coercing to data.frame column #' #' Coercing integer64 vector to data.frame. @@ -1029,6 +998,34 @@ rep.integer64 <- function(x, ...) { ret } +#' integer64: Sequence Generation +#' +#' Generating sequence of integer64 values +#' +#' @param from integer64 scalar (in order to dispatch the integer64 method of [seq()]) +#' @param to scalar +#' @param by scalar +#' @param length.out scalar +#' @param along.with scalar +#' @param ... ignored +#' @details +#' `seq.integer64` does coerce its arguments 'from', 'to' and 'by' to `integer64`. +#' If not provided, the argument 'by' is automatically determined as `+1` or `-1`, +#' but the size of 'by' is not calculated as in [seq()] (because this might result +#' in a non-integer value). +#' +#' @returns an integer64 vector with the generated sequence +#' @note +#' In base R [`:`] currently is not generic and does not dispatch, see section +#' "Limitations inherited from Base R" in [integer64()] +#' +#' @keywords classes manip +#' @seealso [c.integer64()] [rep.integer64()] +#' [as.data.frame.integer64()] [integer64()] +#' @examples +#' # colon not activated: as.integer64(1):12 +#' seq(as.integer64(1), 12, 2) +#' seq(as.integer64(1), by=2, length.out=6) #' @export seq.integer64 = function(from=NULL, to=NULL, by=NULL, length.out=NULL, along.with=NULL, ...) { if (!is.null(along.with)) return(seq.integer64(from, to, by=by, length.out=length(along.with))) diff --git a/man/as.character.integer64.Rd b/man/as.character.integer64.Rd index e4aaafc4..0ef2b6d5 100644 --- a/man/as.character.integer64.Rd +++ b/man/as.character.integer64.Rd @@ -48,9 +48,7 @@ The methods \code{\link[=format]{format()}}, \code{\link[=as.character]{as.chara \examples{ as.character(lim.integer64()) as.bitstring(lim.integer64()) - as.bitstring(as.integer64(c( - -2,-1,NA,0:2 - ))) + as.bitstring(as.integer64(c(-2, -1, NA, 0:2))) } \seealso{ \code{\link[=as.integer64.character]{as.integer64.character()}} \code{\link[=integer64]{integer64()}} diff --git a/man/benchmark64.Rd b/man/benchmark64.Rd index ba44b16a..853e6381 100644 --- a/man/benchmark64.Rd +++ b/man/benchmark64.Rd @@ -41,7 +41,7 @@ named 'SESSION' contains the elapsed seconds of the exemplary sesssion. \code{optimizer64} returns a dimensioned list with one row for each high-level function timed and two columns named after the values of the \code{nsmall} and \code{nbig} sample sizes. Each list cell contains a matrix with timings, -low-level-methods in rows and three measurements \code{c("prep","both","use")} +low-level-methods in rows and three measurements \code{c("prep", "both", "use")} in columns. If it can be measured separately, \code{prep} contains the timing of preparatory work such as sorting and hashing, and \code{use} contains the timing of using the prepared work. If the function timed does both, @@ -63,11 +63,11 @@ Function for measuring algorithmic performance of high-level and low-level integ \tabular{rl}{ \strong{use case name} \tab \strong{explanation} \cr cache \tab filling the cache according to scenario \cr - match(s,b) \tab match small in big vector \cr + match(s, b) \tab match small in big vector \cr s \%in\% b \tab small \%in\% big vector \cr - match(b,s) \tab match big in small vector \cr + match(b, s) \tab match big in small vector \cr b \%in\% s \tab big \%in\% small vector \cr - match(b,b) \tab match big in (different) big vector \cr + match(b, b) \tab match big in (different) big vector \cr b \%in\% b \tab big \%in\% (different) big vector \cr duplicated(b) \tab duplicated of big vector \cr unique(b) \tab unique of big vector \cr @@ -111,12 +111,12 @@ message("let's look at the performance results on Core i7 Lenovo T410 with 8 GB data(benchmark64.data) print(benchmark64.data) -matplot(log2(benchmark64.data[-1,1]/benchmark64.data[-1,]) +matplot(log2(benchmark64.data[-1, 1]/benchmark64.data[-1, ]) , pch=c("3", "6", "h", "s", "o", "a") , xlab="tasks [last=session]" , ylab="log2(relative speed) [bigger is better]" ) -matplot(t(log2(benchmark64.data[-1,1]/benchmark64.data[-1,])) +matplot(t(log2(benchmark64.data[-1, 1]/benchmark64.data[-1, ])) , type="b", axes=FALSE , lwd=c(rep(1, 14), 3) , xlab="context" @@ -130,11 +130,11 @@ axis(2) data(optimizer64.data) print(optimizer64.data) oldpar <- par(no.readonly = TRUE) -par(mfrow=c(2,1)) +par(mfrow=c(2, 1)) par(cex=0.7) for (i in 1:nrow(optimizer64.data)) { for (j in 1:2) { - tim <- optimizer64.data[[i,j]] + tim <- optimizer64.data[[i, j]] barplot(t(tim)) if (rownames(optimizer64.data)[i]=="match") title(paste("match", colnames(optimizer64.data)[j], "in", colnames(optimizer64.data)[3-j])) @@ -144,7 +144,7 @@ for (i in 1:nrow(optimizer64.data)) { title(paste(rownames(optimizer64.data)[i], colnames(optimizer64.data)[j])) } } -par(mfrow=c(1,1)) +par(mfrow=c(1, 1)) } \seealso{ \code{\link[=integer64]{integer64()}} diff --git a/man/cache.Rd b/man/cache.Rd index e5e79cbb..5aaf5f0b 100644 --- a/man/cache.Rd +++ b/man/cache.Rd @@ -67,9 +67,9 @@ found to be outdated \examples{ x <- as.integer64(sample(c(rep(NA, 9), 1:9), 32, TRUE)) y <- x - bit::still.identical(x,y) + bit::still.identical(x, y) y[1] <- NA - bit::still.identical(x,y) + bit::still.identical(x, y) mycache <- newcache(x) ls(mycache) mycache diff --git a/man/cumsum.integer64.Rd b/man/cumsum.integer64.Rd index 6199f3e0..9c0a9140 100644 --- a/man/cumsum.integer64.Rd +++ b/man/cumsum.integer64.Rd @@ -38,9 +38,9 @@ Cumulative Sums, Products, Extremes and lagged differences } \examples{ cumsum(rep(as.integer64(1), 12)) - diff(as.integer64(c(0,1:12))) + diff(as.integer64(c(0, 1:12))) cumsum(as.integer64(c(0, 1:12))) - diff(cumsum(as.integer64(c(0,0,1:12))), differences=2) + diff(cumsum(as.integer64(c(0, 0, 1:12))), differences=2) } \seealso{ \code{\link[=sum.integer64]{sum.integer64()}} \code{\link[=integer64]{integer64()}} diff --git a/man/extract.replace.integer64.Rd b/man/extract.replace.integer64.Rd index 78b0166e..bf2e61d1 100644 --- a/man/extract.replace.integer64.Rd +++ b/man/extract.replace.integer64.Rd @@ -38,10 +38,10 @@ The current implementation returns \code{9218868437227407266} instead of \code{N \examples{ as.integer64(1:12)[1:3] x <- as.integer64(1:12) - dim(x) <- c(3,4) + dim(x) <- c(3, 4) x x[] - x[,2:3] + x[, 2:3] } \seealso{ \code{\link[base:Extract]{[}} \code{\link[=integer64]{integer64()}} diff --git a/man/hashmap.Rd b/man/hashmap.Rd index a4871679..ec28ceec 100644 --- a/man/hashmap.Rd +++ b/man/hashmap.Rd @@ -149,8 +149,8 @@ hashmapupo(y) hashtab(hy) hashmaptab(y) -stopifnot(identical(match(as.integer(x),as.integer(y)),hashpos(hy, x))) -stopifnot(identical(match(as.integer(x),as.integer(y)),hashrev(hx, y))) +stopifnot(identical(match(as.integer(x), as.integer(y)), hashpos(hy, x))) +stopifnot(identical(match(as.integer(x), as.integer(y)), hashrev(hx, y))) stopifnot(identical(as.integer(x) \%in\% as.integer(y), hashfin(hy, x))) stopifnot(identical(as.integer(x) \%in\% as.integer(y), hashrin(hx, y))) stopifnot(identical(duplicated(as.integer(y)), hashdup(hy))) @@ -173,12 +173,12 @@ stopifnot(identical(hashtab(hy), hashmaptab(y))) message("i.e. more data means less random access and more collisions") bits <- 24 b <- seq(-1, 0, 0.1) - tim <- matrix(NA, length(b), 2, dimnames=list(b, c("bits","bits+1"))) + tim <- matrix(NA, length(b), 2, dimnames=list(b, c("bits", "bits+1"))) for (i in 1:length(b)) { n <- as.integer(2^(bits+b[i])) x <- as.integer64(sample(n)) - tim[i,1] <- repeat.time(hashmap(x, hashbits=bits))[3] - tim[i,2] <- repeat.time(hashmap(x, hashbits=bits+1))[3] + tim[i, 1] <- repeat.time(hashmap(x, hashbits=bits))[3] + tim[i, 2] <- repeat.time(hashmap(x, hashbits=bits+1))[3] print(tim) matplot(b, tim) } diff --git a/man/match.integer64.Rd b/man/match.integer64.Rd index f3ec76e1..d3a7eede 100644 --- a/man/match.integer64.Rd +++ b/man/match.integer64.Rd @@ -84,7 +84,7 @@ stopifnot(identical("\%in\%.integer64"(x, table), as.integer(x) \%in\% as.intege library(bit) message("check when reverse hash-lookup beats standard hash-lookup") e <- 4:24 - timx <- timy <- matrix(NA, length(e), length(e), dimnames=list(e,e)) + timx <- timy <- matrix(NA, length(e), length(e), dimnames=list(e, e)) for (iy in seq_along(e)) for (ix in 1:iy) { nx <- 2^e[ix] @@ -92,23 +92,23 @@ stopifnot(identical("\%in\%.integer64"(x, table), as.integer(x) \%in\% as.intege x <- as.integer64(sample(ny, nx, FALSE)) y <- as.integer64(sample(ny, ny, FALSE)) #hashfun(x, bits=as.integer(5)) - timx[ix,iy] <- repeat.time({ + timx[ix, iy] <- repeat.time({ hx <- hashmap(x) py <- hashrev(hx, y) })[3] - timy[ix,iy] <- repeat.time({ + timy[ix, iy] <- repeat.time({ hy <- hashmap(y) px <- hashpos(hy, x) })[3] #identical(px, py) - print(round(timx[1:iy,1:iy]/timy[1:iy,1:iy], 2), na.print="") + print(round(timx[1:iy, 1:iy]/timy[1:iy, 1:iy], 2), na.print="") } message("explore best low-level method given size of x and table") B1 <- 1:27 B2 <- 1:27 tim <- array(NA, dim=c(length(B1), length(B2), 5) - , dimnames=list(B1, B2, c("hashpos","hashrev","sortpos1","sortpos2","sortpos3"))) + , dimnames=list(B1, B2, c("hashpos", "hashrev", "sortpos1", "sortpos2", "sortpos3"))) for (i1 in B1) for (i2 in B2) { @@ -118,13 +118,13 @@ stopifnot(identical("\%in\%.integer64"(x, table), as.integer(x) \%in\% as.intege n2 <- 2^b2 x1 <- as.integer64(c(sample(n2, n1-1, TRUE), NA)) x2 <- as.integer64(c(sample(n2, n2-1, TRUE), NA)) - tim[i1,i2,1] <- repeat.time({h <- hashmap(x2);hashpos(h, x1);rm(h)})[3] - tim[i1,i2,2] <- repeat.time({h <- hashmap(x1);hashrev(h, x2);rm(h)})[3] + tim[i1, i2, 1] <- repeat.time({h <- hashmap(x2);hashpos(h, x1);rm(h)})[3] + tim[i1, i2, 2] <- repeat.time({h <- hashmap(x1);hashrev(h, x2);rm(h)})[3] s <- clone(x2); o <- seq_along(s); ramsortorder(s, o) - tim[i1,i2,3] <- repeat.time(sortorderpos(s, o, x1, method=1))[3] - tim[i1,i2,4] <- repeat.time(sortorderpos(s, o, x1, method=2))[3] - tim[i1,i2,5] <- repeat.time(sortorderpos(s, o, x1, method=3))[3] - rm(s,o) + tim[i1, i2, 3] <- repeat.time(sortorderpos(s, o, x1, method=1))[3] + tim[i1, i2, 4] <- repeat.time(sortorderpos(s, o, x1, method=2))[3] + tim[i1, i2, 5] <- repeat.time(sortorderpos(s, o, x1, method=3))[3] + rm(s, o) print(apply(tim, 1:2, function(ti)if(any(is.na(ti)))NA else which.min(ti))) } } diff --git a/man/plusclass.Rd b/man/plusclass.Rd index 1d763ba2..1ec0e3fc 100644 --- a/man/plusclass.Rd +++ b/man/plusclass.Rd @@ -19,8 +19,8 @@ NULL or a character vector of class attributes Maintaining integer64 S3 class attribute. } \examples{ - plusclass("inheritingclass","integer64") - minusclass(c("inheritingclass","integer64"), "integer64") + plusclass("inheritingclass", "integer64") + minusclass(c("inheritingclass", "integer64"), "integer64") } \seealso{ \code{\link[=oldClass]{oldClass()}} \code{\link[=integer64]{integer64()}} diff --git a/man/qtile.Rd b/man/qtile.Rd index d86ac42c..9d28463d 100644 --- a/man/qtile.Rd +++ b/man/qtile.Rd @@ -31,7 +31,7 @@ qtile(x, probs = seq(0, 1, 0.25), ...) \arguments{ \item{x}{a integer64 vector} -\item{probs}{numeric vector of probabilities with values in \verb{[0,1]} - possibly containing \code{NA}s} +\item{probs}{numeric vector of probabilities with values in \verb{[0, 1]} - possibly containing \code{NA}s} \item{...}{ignored} diff --git a/man/rep.integer64.Rd b/man/rep.integer64.Rd index 8e0f0763..e4ada1d5 100644 --- a/man/rep.integer64.Rd +++ b/man/rep.integer64.Rd @@ -16,7 +16,7 @@ Replicate elements of integer64 vectors } \examples{ rep(as.integer64(1:2), 6) - rep(as.integer64(1:2), c(6,6)) + rep(as.integer64(1:2), c(6, 6)) rep(as.integer64(1:2), length.out=6) } \seealso{ diff --git a/man/seq.integer64.Rd b/man/seq.integer64.Rd index 05ea2070..63ae8d4b 100644 --- a/man/seq.integer64.Rd +++ b/man/seq.integer64.Rd @@ -3,6 +3,16 @@ \name{seq.integer64} \alias{seq.integer64} \title{integer64: Sequence Generation} +\usage{ +\method{seq}{integer64}( + from = NULL, + to = NULL, + by = NULL, + length.out = NULL, + along.with = NULL, + ... +) +} \arguments{ \item{from}{integer64 scalar (in order to dispatch the integer64 method of \code{\link[=seq]{seq()}})} diff --git a/man/xor.integer64.Rd b/man/xor.integer64.Rd index 5ac3f095..1d67314c 100644 --- a/man/xor.integer64.Rd +++ b/man/xor.integer64.Rd @@ -64,7 +64,7 @@ binattr(e1, e2) \item{y}{an atomic vector of class 'integer64'} } \value{ -\code{\link{&}}, \code{\link{|}}, \code{\link[=xor]{xor()}}, \code{\link{!=}}, \code{\link{==}}, +\code{\link{&}}, \code{\link{|}}, \code{\link[bit:xor]{bit::xor()}}, \code{\link{!=}}, \code{\link{==}}, \code{\link{<}}, \code{\link{<=}}, \code{\link{>}}, \code{\link{>=}} return a logical vector \code{\link{^}} and \code{\link{/}} return a double vector From 6bb895ee357cbd5aeaefdb63b3dcac4b7d342fe4 Mon Sep 17 00:00:00 2001 From: Michael Chirico Date: Mon, 5 Jan 2026 00:40:43 -0800 Subject: [PATCH 13/16] more back-compatibility tests --- tests/testthat/test-integer64.R | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/testthat/test-integer64.R b/tests/testthat/test-integer64.R index 5bfcdd16..a95897e0 100644 --- a/tests/testthat/test-integer64.R +++ b/tests/testthat/test-integer64.R @@ -438,6 +438,12 @@ test_that("seq() works back-compatibly w.r.t. mixed integer+double inputs", { expect_error(seq(one, 10L, by=0.1), "invalid '(to - from)/by'", fixed=TRUE) expect_error(seq(to=one, from=10L, by=-0.1), "invalid '(to - from)/by'", fixed=TRUE) + + expect_identical(seq(one, 2.5), as.integer64(1:2)) + expect_identical(seq(to=one, from=2.5), as.integer64(2:1)) + + expect_identical(seq(one, 5.5, by=1.5), as.integer64(1:5)) + expect_identical(seq(to=one, from=5.5, by=-1.5), as.integer64(5:1)) }) # These tests were previously kept as tests under \examples{\dontshow{...}}. From acb2c3e3ce1039634cacfbdb905c11b15d63e548 Mon Sep 17 00:00:00 2001 From: Michael Chirico Date: Mon, 5 Jan 2026 00:53:56 -0800 Subject: [PATCH 14/16] document, fix new bug --- R/integer64.R | 27 +++++++++++++-------------- man/seq.integer64.Rd | 26 +++++++++++++------------- tests/testthat/test-integer64.R | 2 +- 3 files changed, 27 insertions(+), 28 deletions(-) diff --git a/R/integer64.R b/R/integer64.R index 5f80bd03..add1b9e7 100644 --- a/R/integer64.R +++ b/R/integer64.R @@ -998,8 +998,6 @@ rep.integer64 <- function(x, ...) { ret } -#' integer64: Sequence Generation -#' #' Generating sequence of integer64 values #' #' @param from integer64 scalar (in order to dispatch the integer64 method of [seq()]) @@ -1009,23 +1007,24 @@ rep.integer64 <- function(x, ...) { #' @param along.with scalar #' @param ... ignored #' @details -#' `seq.integer64` does coerce its arguments 'from', 'to' and 'by' to `integer64`. -#' If not provided, the argument 'by' is automatically determined as `+1` or `-1`, -#' but the size of 'by' is not calculated as in [seq()] (because this might result -#' in a non-integer value). +#' `seq.integer64` coerces its arguments `from`, `to`, and `by` to `integer64`. Consistency +#' with [seq()] is typically maintained, though results may differ when mixing `integer64` and +#' `double` inputs, for the same reason that any arithmetic with these mixed types can be +#' ambiguous. Whereas `seq(1L, 10L, length.out=8L)` can back up to double storage to give an +#' exact result, this not possible for generic inputs `seq(i64, dbl, length.out=n)`. #' -#' @returns an integer64 vector with the generated sequence -#' @note -#' In base R [`:`] currently is not generic and does not dispatch, see section -#' "Limitations inherited from Base R" in [integer64()] +#' @returns An integer64 vector with the generated sequence #' #' @keywords classes manip #' @seealso [c.integer64()] [rep.integer64()] #' [as.data.frame.integer64()] [integer64()] #' @examples -#' # colon not activated: as.integer64(1):12 -#' seq(as.integer64(1), 12, 2) -#' seq(as.integer64(1), by=2, length.out=6) +#' seq(as.integer64(1), 12, 2) +#' seq(as.integer64(1), by=2, length.out=6) +#' +#' # truncation rules +#' seq(as.integer64(1), 10, by=1.5) +#' seq(as.integer64(1), 10, length.out=5) #' @export seq.integer64 = function(from=NULL, to=NULL, by=NULL, length.out=NULL, along.with=NULL, ...) { if (!is.null(along.with)) return(seq.integer64(from, to, by=by, length.out=length(along.with))) @@ -1083,7 +1082,7 @@ seq.integer64 = function(from=NULL, to=NULL, by=NULL, length.out=NULL, along.wit } else if (is.null(by)) { if (length.out == 1L) return(as.integer64(from)) - by = (to - from) / (length.out - 1L) + by = as.integer64((to - from) / (length.out - 1L)) } else if (is.null(length.out)) { if (to != from && by == 0L) stop("invalid '(to - from)/by'") diff --git a/man/seq.integer64.Rd b/man/seq.integer64.Rd index 63ae8d4b..a44eca5a 100644 --- a/man/seq.integer64.Rd +++ b/man/seq.integer64.Rd @@ -2,7 +2,7 @@ % Please edit documentation in R/integer64.R \name{seq.integer64} \alias{seq.integer64} -\title{integer64: Sequence Generation} +\title{Generating sequence of integer64 values} \usage{ \method{seq}{integer64}( from = NULL, @@ -27,25 +27,25 @@ \item{...}{ignored} } \value{ -an integer64 vector with the generated sequence +An integer64 vector with the generated sequence } \description{ Generating sequence of integer64 values } \details{ -\code{seq.integer64} does coerce its arguments 'from', 'to' and 'by' to \code{integer64}. -If not provided, the argument 'by' is automatically determined as \code{+1} or \code{-1}, -but the size of 'by' is not calculated as in \code{\link[=seq]{seq()}} (because this might result -in a non-integer value). -} -\note{ -In base R \code{\link{:}} currently is not generic and does not dispatch, see section -"Limitations inherited from Base R" in \code{\link[=integer64]{integer64()}} +\code{seq.integer64} coerces its arguments \code{from}, \code{to}, and \code{by} to \code{integer64}. Consistency +with \code{\link[=seq]{seq()}} is typically maintained, though results may differ when mixing \code{integer64} and +\code{double} inputs, for the same reason that any arithmetic with these mixed types can be +ambiguous. Whereas \code{seq(1L, 10L, length.out=8L)} can back up to double storage to give an +exact result, this not possible for generic inputs \code{seq(i64, dbl, length.out=n)}. } \examples{ - # colon not activated: as.integer64(1):12 - seq(as.integer64(1), 12, 2) - seq(as.integer64(1), by=2, length.out=6) +seq(as.integer64(1), 12, 2) +seq(as.integer64(1), by=2, length.out=6) + +# truncation rules +seq(as.integer64(1), 10, by=1.5) +seq(as.integer64(1), 10, length.out=5) } \seealso{ \code{\link[=c.integer64]{c.integer64()}} \code{\link[=rep.integer64]{rep.integer64()}} diff --git a/tests/testthat/test-integer64.R b/tests/testthat/test-integer64.R index a95897e0..0041350d 100644 --- a/tests/testthat/test-integer64.R +++ b/tests/testthat/test-integer64.R @@ -333,7 +333,7 @@ with_parameters_test_that( expect_error(seq(n1_64, by=n2), err_msg, fixed=TRUE) expect_error(seq(to=n1_64, by=n2), err_msg, fixed=TRUE) } else if (sign(1L - n1) == sign(n2)) { - expect_identical(seq(n1_64, by=n2), as.integer64(seq(n1, by=n2))) + if (n2 %% 1L == 0L) expect_identical(seq(n1_64, by=n2), as.integer64(seq(n1, by=n2))) expect_identical(seq(n1_64, by=n2_64), as.integer64(seq(n1, by=n2_32))) expect_error(seq(to=n1_64, by=n2), "wrong sign in 'by' argument", fixed=TRUE) From 92089d0f068665c5ffb28ebb55d0deefe27425f7 Mon Sep 17 00:00:00 2001 From: Michael Chirico Date: Mon, 5 Jan 2026 01:06:29 -0800 Subject: [PATCH 15/16] NEWS --- NEWS.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/NEWS.md b/NEWS.md index b3c3c350..679fa3ce 100644 --- a/NEWS.md +++ b/NEWS.md @@ -44,6 +44,12 @@ ## NEW FEATURES 1. `anyNA` gets an `integer64` method. Thanks @hcirellu. +1. The `seq()` method for `integer64` has been overhauled to better match features from the default method. + - The motivation is #47, where `seq(as.integer64(1L), 11L, length.out=6L)` calculated `by=` incorrectly to give `1:6` instead of `c(1L, 3L, ..., 9L, 11L)`. + - `length.out=` was also sometimes ignored, for example `seq(to=as.integer64(5L), length.out=0L)` will now always just give `integer64()`. + - `seq(a, a, by=by)` is no longer an error. + - We match the default method behavior of assuming `from=1` and `to=1` if needed in order to support usage like `seq(as.integer64(10L), by=-1L)` and `seq(by=as.integer64(3L), length.out=8L)`. + - `seq(a, a, length.out=n)` will give `rep(a, n)`, not `seq(a, by=1, length.out=n)`. ## BUG FIXES @@ -53,7 +59,6 @@ 1. `sortfin(integer64(), 1:10)` no longer segfaults (#164). 1. `orderfin(as.integer64(10:1), 1:3, 8:11)` enforces that `table` be sorted by `order` instead of segfaulting (#166). 1. `ordertab()` no longer segfaults when `nunique` is smaller than the actual number of unique values (#168). -1. `seq.integer64` calculates `by=` correctly when `length.out=` is provided (#47). ## NOTES From c6470245c6be49410ee497614e0a0c08b60ad53e Mon Sep 17 00:00:00 2001 From: Michael Chirico Date: Mon, 5 Jan 2026 01:08:42 -0800 Subject: [PATCH 16/16] Correct issue citation --- tests/testthat/test-integer64.R | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/testthat/test-integer64.R b/tests/testthat/test-integer64.R index 0041350d..538db9a1 100644 --- a/tests/testthat/test-integer64.R +++ b/tests/testthat/test-integer64.R @@ -323,7 +323,7 @@ with_parameters_test_that( n1_64 = as.integer64(n1) n2_64 = as.integer64(n2) - # TODO(#47): restore parity to seq() here + # TODO(#211): restore parity to seq() here if (n2 %% 1L == 0L) expect_identical(seq(n1_64, n2), as.integer64(seq(n1_32, n2))) expect_identical(seq(n1_64, n2_64), as.integer64(seq(n1_32, n2_32))) @@ -340,7 +340,7 @@ with_parameters_test_that( } else { expect_error(seq(n1_64, by=n2), "wrong sign in 'by' argument", fixed=TRUE) - # TODO(#47): restore parity to seq() here + # TODO(#211): restore parity to seq() here if (n2 %% 1L == 0L) expect_identical(seq(to=n1_64, by=n2), as.integer64(seq(to=n1, by=n2))) expect_identical(seq(to=n1_64, by=n2_64), as.integer64(seq(to=n1, by=n2_32))) } @@ -376,9 +376,9 @@ with_parameters_test_that( n2_64 = as.integer64(n2) n3_64 = as.integer64(n3) - # TODO(#47): restore parity to seq() here + # TODO(#211): restore parity to seq() here if (n2 == n1 || sign(n2 - n1) == sign(n3)) { - # TODO(#47): restore parity to seq() here + # TODO(#211): restore parity to seq() here if (n2 %% 1L == 0L && n3 %% 1L == 0L) { expect_identical(seq(n1_64, n2, by=n3), as.integer64(seq(n1_32, n2, by=n3))) expect_identical(seq(n1_64, n2_64, by=n3), as.integer64(seq(n1_32, n2_32, by=n3))) @@ -396,7 +396,7 @@ with_parameters_test_that( expect_error(seq(n1_64, by=n2, length.out=n3), err_msg, fixed=TRUE) expect_error(seq(to=n1_64, by=n2, length.out=n3), err_msg, fixed=TRUE) } else { - # TODO(#47): restore parity to seq() here + # TODO(#211): restore parity to seq() here if (((n2 - n1) / (n3 - 1L)) %% 1L == 0L) { expect_identical(seq(n1_64, n2, length.out=n3), as.integer64(seq(n1_32, n2, length.out=n3))) expect_identical(seq(n1_64, n2_64, length.out=n3), as.integer64(seq(n1_32, n2_32, length.out=n3))) @@ -404,7 +404,7 @@ with_parameters_test_that( expect_identical(seq(n1_64, n2_64, length.out=n3_64), as.integer64(seq(n1_32, n2_32, length.out=n3_32))) } - # TODO(#47): restore parity to seq() here + # TODO(#211): restore parity to seq() here if (n2 %% 1L == 0L) { expect_identical(seq(n1_64, by=n2, length.out=n3), as.integer64(seq(n1_32, by=n2, length.out=n3))) expect_identical(seq(n1_64, by=n2_64, length.out=n3), as.integer64(seq(n1_32, by=n2_32, length.out=n3)))