@@ -168,40 +168,62 @@ test_that("Minus and plus edge cases and 'rev'", {
168168test_that(" Overflow edge cases for arithmetic and summary functions" , {
169169 max_val = lim.integer64()[2L ]
170170 min_val = lim.integer64()[1L ]
171+ half_min = as.integer64(" -4611686018427387904" ) # -2^62
172+ half_max = as.integer64(" 4611686018427387904" ) # 2^62
171173
172174 overflow_warning = " NAs produced by integer64 overflow"
173175
174- # Addition overflow
176+ # 1. C-level overflow (exceeds LLONG_MAX or below LLONG_MIN)
175177 expect_warning(expect_identical(max_val + 1L , NA_integer64_ ), overflow_warning )
176- expect_warning(expect_identical(min_val + (- 1L ), NA_integer64_ ), overflow_warning )
177-
178- # Subtraction overflow
179- expect_warning(expect_identical(min_val - 1L , NA_integer64_ ), overflow_warning )
178+ expect_warning(expect_identical(min_val + (- 2L ), NA_integer64_ ), overflow_warning )
180179 expect_warning(expect_identical(max_val - (- 1L ), NA_integer64_ ), overflow_warning )
181-
182- # Multiplication overflow
180+ expect_warning(expect_identical(min_val - 2L , NA_integer64_ ), overflow_warning )
183181 expect_warning(expect_identical(max_val * 2L , NA_integer64_ ), overflow_warning )
184182 expect_warning(expect_identical(min_val * 2L , NA_integer64_ ), overflow_warning )
185183 expect_warning(expect_identical(min_val * (- 2L ), NA_integer64_ ), overflow_warning )
186- expect_identical(min_val * (- 1L ), max_val )
187-
188- # sum() overflow
189- expect_warning(expect_identical(sum(max_val , 1L ), NA_integer64_ ), overflow_warning )
190- expect_warning(expect_identical(sum(c(max_val , 1L )), NA_integer64_ ), overflow_warning )
191- expect_warning(expect_identical(sum(c(min_val , - 1L ), na.rm = TRUE ), NA_integer64_ ), overflow_warning )
184+ expect_warning(expect_identical(diff(c(max_val , min_val - 1L )), NA_integer64_ ), overflow_warning )
192185
193- # prod() overflow
194- expect_warning(expect_identical(prod(c(max_val , 2L )), NA_integer64_ ), overflow_warning )
195- expect_warning(expect_identical(prod(c(min_val , 2L ), na.rm = TRUE ), NA_integer64_ ), overflow_warning )
196-
197- # cumsum() overflow
198- expect_warning(expect_identical(cumsum(c(max_val , 1L )), c(max_val , NA_integer64_ )), overflow_warning )
199-
200- # cumprod() overflow
201- expect_warning(expect_identical(cumprod(c(max_val , 2L )), c(max_val , NA_integer64_ )), overflow_warning )
202-
203- # diff() overflow
204- expect_warning(expect_identical(diff(c(max_val , min_val )), NA_integer64_ ), overflow_warning )
186+ # 2. NA_INTEGER64 sentinel collision: mathematical result is exactly LLONG_MIN (-2^63).
187+ # C-level __builtin_*_overflow does NOT overflow, but bit64 treats LLONG_MIN as NA.
188+ # These must produce NA_integer64_ with an overflow warning.
189+ expect_warning(expect_identical(min_val + (- 1L ), NA_integer64_ ), overflow_warning )
190+ expect_warning(expect_identical(half_min + half_min , NA_integer64_ ), overflow_warning )
191+ expect_warning(expect_identical(min_val - 1L , NA_integer64_ ), overflow_warning )
192+ expect_warning(expect_identical(as.integer64(- 2L ) * half_max , NA_integer64_ ), overflow_warning )
193+ expect_warning(expect_identical(as.integer64(" -2147483648" ) * as.integer64(" 4294967296" ), NA_integer64_ ), overflow_warning )
194+ expect_warning(expect_identical(diff(c(as.integer64(1L ), min_val )), NA_integer64_ ), overflow_warning )
195+ expect_warning(expect_identical(sum(min_val , - 1L ), NA_integer64_ ), overflow_warning )
196+ expect_warning(expect_identical(sum(c(half_min , half_min )), NA_integer64_ ), overflow_warning )
197+ expect_warning(expect_identical(prod(as.integer64(- 2L ), half_max ), NA_integer64_ ), overflow_warning )
198+ expect_warning(expect_identical(cumsum(c(min_val , - 1L )), c(min_val , NA_integer64_ )), overflow_warning )
199+ expect_warning(expect_identical(cumprod(c(as.integer64(- 2L ), half_max )), c(as.integer64(- 2L ), NA_integer64_ )), overflow_warning )
200+
201+ # 3. Boundary cases that are exactly on the representable range [-2^63 + 1, 2^63 - 1]
202+ # These must NOT overflow or warn.
203+ expect_identical(min_val + 0L , min_val )
204+ expect_identical(min_val + 1L , as.integer64(" -9223372036854775806" ))
205+ expect_identical(half_min + (half_min + 1L ), min_val )
206+ expect_identical(min_val - 0L , min_val )
207+ expect_identical(max_val - 0L , max_val )
208+ expect_identical(min_val * 1L , min_val )
209+ expect_identical(min_val * (- 1L ), max_val )
210+ expect_identical(max_val * (- 1L ), min_val )
211+ expect_identical(sum(min_val , 0L ), min_val )
212+ expect_identical(prod(min_val , 1L ), min_val )
213+
214+ # 4. NA propagation: when NA_INTEGER64 is an input, it should return NA without warning
215+ expect_no_warning(expect_identical(NA_integer64_ + 1L , NA_integer64_ ))
216+ expect_no_warning(expect_identical(1L + NA_integer64_ , NA_integer64_ ))
217+ expect_no_warning(expect_identical(NA_integer64_ - 1L , NA_integer64_ ))
218+ expect_no_warning(expect_identical(1L - NA_integer64_ , NA_integer64_ ))
219+ expect_no_warning(expect_identical(NA_integer64_ * 2L , NA_integer64_ ))
220+ expect_no_warning(expect_identical(2L * NA_integer64_ , NA_integer64_ ))
221+ expect_no_warning(expect_identical(sum(NA_integer64_ ), NA_integer64_ ))
222+ expect_no_warning(expect_identical(prod(NA_integer64_ ), NA_integer64_ ))
223+ expect_no_warning(expect_identical(cumsum(c(NA_integer64_ , 1L )), c(NA_integer64_ , NA_integer64_ )))
224+ expect_no_warning(expect_identical(cumprod(c(NA_integer64_ , 1L )), c(NA_integer64_ , NA_integer64_ )))
225+ expect_no_warning(expect_identical(diff(c(NA_integer64_ , as.integer64(1L ))), NA_integer64_ ))
226+ expect_no_warning(expect_identical(diff(c(as.integer64(1L ), NA_integer64_ )), NA_integer64_ ))
205227})
206228
207229test_that(" Logical operators" , {
0 commit comments