22# C-Code
33# S3 atomic 64bit integers for R
44# (c) 2011-2024 Jens Oehlschägel
5- # (c) 2025 Michael Chirico
5+ # (c) 2025-2026 Michael Chirico
66# Licence: GPL2
77# Provided 'as is', use at your own risk
88# Created: 2011-12-11
@@ -227,11 +227,13 @@ SEXP as_integer64_bitstring(SEXP x_, SEXP ret_){
227227 for (i = 0 ; i < n ; i ++ ){
228228 str = CHAR (STRING_ELT (x_ , i ));
229229 l = strlen (str );
230- if (l > BITS_INTEGER64 ){
230+ // # nocov start: only reachable with invalid bitstring input
231+ if (l > BITS_INTEGER64 ){
231232 ret [i ] = NA_INTEGER64 ;
232233 naflag = TRUE;
233234 break ;
234235 }
236+ // # nocov end
235237 mask = 1 ;
236238 v = 0 ;
237239 for (k = l - 1 ; k >=0 ; k -- ){
@@ -243,13 +245,13 @@ SEXP as_integer64_bitstring(SEXP x_, SEXP ret_){
243245 ret [i ] = v ;
244246 R_CheckUserInterrupt ();
245247 }
246- if (naflag )warning (BITSTRING_OVERFLOW_WARNING );
248+ if (naflag )warning (BITSTRING_OVERFLOW_WARNING ); // # nocov
247249 return ret_ ;
248250}
249251
250252
251253
252- __attribute__(( no_sanitize ( "signed-integer-overflow" ))) SEXP plus_integer64 (SEXP e1_ , SEXP e2_ , SEXP ret_ ){
254+ SEXP plus_integer64 (SEXP e1_ , SEXP e2_ , SEXP ret_ ){
253255 long long i , n = LENGTH (ret_ );
254256 long long i1 , n1 = LENGTH (e1_ );
255257 long long i2 , n2 = LENGTH (e2_ );
@@ -264,7 +266,7 @@ __attribute__((no_sanitize("signed-integer-overflow"))) SEXP plus_integer64(SEXP
264266 return ret_ ;
265267}
266268
267- __attribute__(( no_sanitize ( "signed-integer-overflow" ))) SEXP minus_integer64 (SEXP e1_ , SEXP e2_ , SEXP ret_ ){
269+ SEXP minus_integer64 (SEXP e1_ , SEXP e2_ , SEXP ret_ ){
268270 long long i , n = LENGTH (ret_ );
269271 long long i1 , n1 = LENGTH (e1_ );
270272 long long i2 , n2 = LENGTH (e2_ );
@@ -279,7 +281,7 @@ __attribute__((no_sanitize("signed-integer-overflow"))) SEXP minus_integer64(SEX
279281 return ret_ ;
280282}
281283
282- __attribute__(( no_sanitize ( "signed-integer-overflow" ))) SEXP diff_integer64 (SEXP x_ , SEXP lag_ , SEXP n_ , SEXP ret_ ){
284+ SEXP diff_integer64 (SEXP x_ , SEXP lag_ , SEXP n_ , SEXP ret_ ){
283285 long long i , n = * ((long long * ) REAL (n_ ));
284286 long long * x = (long long * ) REAL (x_ );
285287 long long * lag = (long long * ) REAL (lag_ );
@@ -326,7 +328,7 @@ SEXP mod_integer64(SEXP e1_, SEXP e2_, SEXP ret_){
326328}
327329
328330
329- __attribute__(( no_sanitize ( "signed-integer-overflow" ))) SEXP times_integer64_integer64 (SEXP e1_ , SEXP e2_ , SEXP ret_ ){
331+ SEXP times_integer64_integer64 (SEXP e1_ , SEXP e2_ , SEXP ret_ ){
330332 long long i , n = LENGTH (ret_ );
331333 long long i1 , n1 = LENGTH (e1_ );
332334 long long i2 , n2 = LENGTH (e2_ );
@@ -612,36 +614,31 @@ SEXP sum_integer64(SEXP e1_, SEXP na_rm_, SEXP ret_){
612614 long long i , n = LENGTH (e1_ );
613615 long long * e1 = (long long * ) REAL (e1_ );
614616 long long * ret = (long long * ) REAL (ret_ );
615- long long cumsum , tempsum ;
616- cumsum = 0 ;
617- if (asLogical (na_rm_ )){
618- for (i = 0 ; i < n ; i ++ ){
619- if (e1 [i ]!= NA_INTEGER64 ){
620- tempsum = cumsum + e1 [i ];
621- if (!GOODISUM64 (cumsum , e1 [i ], tempsum )){
622- warning (INTEGER64_OVERFLOW_WARNING );
623- ret [0 ] = NA_INTEGER64 ;
624- return ret_ ;
625- }
626- cumsum = tempsum ;
627- }
617+ long long cumsum = 0 ;
618+ if (asLogical (na_rm_ )){
619+ for (i = 0 ; i < n ; i ++ ){
620+ if (e1 [i ]!= NA_INTEGER64 ){
621+ if (add64_overflow (cumsum , e1 [i ], & cumsum )){
622+ warning (INTEGER64_OVERFLOW_WARNING );
623+ ret [0 ] = NA_INTEGER64 ;
624+ return ret_ ;
628625 }
629- }else {
630- for (i = 0 ; i < n ; i ++ ){
631- if (e1 [i ]== NA_INTEGER64 ){
632- ret [0 ] = NA_INTEGER64 ;
633- return ret_ ;
634- }else {
635- tempsum = cumsum + e1 [i ];
636- if (!GOODISUM64 (cumsum , e1 [i ], tempsum )){
637- warning (INTEGER64_OVERFLOW_WARNING );
638- ret [0 ] = NA_INTEGER64 ;
639- return ret_ ;
640- }
641- cumsum = tempsum ;
642- }
626+ }
627+ }
628+ }else {
629+ for (i = 0 ; i < n ; i ++ ){
630+ if (e1 [i ]== NA_INTEGER64 ){
631+ ret [0 ] = NA_INTEGER64 ;
632+ return ret_ ;
633+ }else {
634+ if (add64_overflow (cumsum , e1 [i ], & cumsum )){
635+ warning (INTEGER64_OVERFLOW_WARNING );
636+ ret [0 ] = NA_INTEGER64 ;
637+ return ret_ ;
643638 }
639+ }
644640 }
641+ }
645642 ret [0 ] = cumsum ;
646643 return ret_ ;
647644}
@@ -678,36 +675,31 @@ SEXP prod_integer64(SEXP e1_, SEXP na_rm_, SEXP ret_){
678675 long long i , n = LENGTH (e1_ );
679676 long long * e1 = (long long * ) REAL (e1_ );
680677 long long * ret = (long long * ) REAL (ret_ );
681- long long cumprod , tempprod ;
682- cumprod = 1 ;
683- if (asLogical (na_rm_ )){
684- for (i = 0 ; i < n ; i ++ ){
685- if (e1 [i ]!= NA_INTEGER64 ){
686- tempprod = cumprod * e1 [i ];
687- if (!GOODIPROD64 (cumprod , e1 [i ], tempprod )){
688- warning (INTEGER64_OVERFLOW_WARNING );
689- ret [0 ] = NA_INTEGER64 ;
690- return ret_ ;
691- }
692- cumprod = tempprod ;
693- }
678+ long long cumprod = 1 ;
679+ if (asLogical (na_rm_ )){
680+ for (i = 0 ; i < n ; i ++ ){
681+ if (e1 [i ]!= NA_INTEGER64 ){
682+ if (mul64_overflow (cumprod , e1 [i ], & cumprod )){
683+ warning (INTEGER64_OVERFLOW_WARNING );
684+ ret [0 ] = NA_INTEGER64 ;
685+ return ret_ ;
694686 }
695- }else {
696- for (i = 0 ; i < n ; i ++ ){
697- if (e1 [i ]== NA_INTEGER64 ){
698- ret [0 ] = NA_INTEGER64 ;
699- return ret_ ;
700- }else {
701- tempprod = cumprod * e1 [i ];
702- if (!GOODIPROD64 (cumprod , e1 [i ], tempprod )){
703- warning (INTEGER64_OVERFLOW_WARNING );
704- ret [0 ] = NA_INTEGER64 ;
705- return ret_ ;
706- }
707- cumprod = tempprod ;
708- }
687+ }
688+ }
689+ }else {
690+ for (i = 0 ; i < n ; i ++ ){
691+ if (e1 [i ]== NA_INTEGER64 ){
692+ ret [0 ] = NA_INTEGER64 ;
693+ return ret_ ;
694+ }else {
695+ if (mul64_overflow (cumprod , e1 [i ], & cumprod )){
696+ warning (INTEGER64_OVERFLOW_WARNING );
697+ ret [0 ] = NA_INTEGER64 ;
698+ return ret_ ;
709699 }
700+ }
710701 }
702+ }
711703 ret [0 ] = cumprod ;
712704 return ret_ ;
713705}
@@ -1065,7 +1057,7 @@ SEXP as_list_integer64(SEXP x_){
10651057 return x_ ;
10661058}
10671059
1068- __attribute__(( no_sanitize ( "signed-integer-overflow" ))) SEXP matmult_integer64_integer64 (SEXP x_ , SEXP y_ , SEXP ret_ ){
1060+ SEXP matmult_integer64_integer64 (SEXP x_ , SEXP y_ , SEXP ret_ ){
10691061 long long i , j , k ;
10701062 // get dimension of x
10711063 SEXP dim1 = getAttrib (x_ , R_DimSymbol );
@@ -1080,7 +1072,7 @@ __attribute__((no_sanitize("signed-integer-overflow"))) SEXP matmult_integer64_i
10801072 long long * y = (long long * ) REAL (y_ );
10811073 long long * ret = (long long * ) REAL (ret_ );
10821074 Rboolean naflag = FALSE;
1083- long long cumsum , tempsum , addValue ;
1075+ long long cumsum , addValue ;
10841076
10851077 for (i = 0 ; i < nrow1 ; i ++ ){
10861078 for (j = 0 ; j < ncol2 ; j ++ ){
@@ -1091,16 +1083,11 @@ __attribute__((no_sanitize("signed-integer-overflow"))) SEXP matmult_integer64_i
10911083 cumsum = NA_INTEGER64 ;
10921084 break ;
10931085 }
1094- tempsum = cumsum + addValue ;
1095- // for some reason GOODISUM64(cumsum, addValue, tempsum) does not work properly on macos-latest, compared to the others
1096- // therefore a workaround is tried here by adding the GOODISUM64 logic with long double casting
1097- if (!GOODISUM64 (cumsum , addValue , tempsum ) ||
1098- !((cumsum > 0 ) ? (((long double ) addValue ) < ((long double ) tempsum )) : ! (((long double ) addValue ) < ((long double ) tempsum )))){
1086+ if (add64_overflow (cumsum , addValue , & cumsum )){
10991087 naflag = TRUE;
11001088 cumsum = NA_INTEGER64 ;
11011089 break ;
11021090 }
1103- cumsum = tempsum ;
11041091 }
11051092 ret [i + j * nrow1 ] = cumsum ;
11061093 }
@@ -1125,7 +1112,7 @@ SEXP matmult_double_integer64(SEXP x_, SEXP y_, SEXP ret_){
11251112 long long * y = (long long * ) REAL (y_ );
11261113 long long * ret = (long long * ) REAL (ret_ );
11271114 Rboolean naflag = FALSE;
1128- long long cumsum , tempsum , addValue ;
1115+ long long cumsum , addValue ;
11291116 long double longret ;
11301117
11311118 for (i = 0 ; i < nrow1 ; i ++ ){
@@ -1137,13 +1124,11 @@ SEXP matmult_double_integer64(SEXP x_, SEXP y_, SEXP ret_){
11371124 cumsum = NA_INTEGER64 ;
11381125 break ;
11391126 }
1140- tempsum = cumsum + addValue ;
1141- if (!GOODISUM64 (cumsum , addValue , tempsum )){
1127+ if (add64_overflow (cumsum , addValue , & cumsum )){
11421128 naflag = TRUE;
11431129 cumsum = NA_INTEGER64 ;
11441130 break ;
11451131 }
1146- cumsum = tempsum ;
11471132 }
11481133 ret [i + j * nrow1 ] = cumsum ;
11491134 }
@@ -1167,7 +1152,7 @@ SEXP matmult_integer64_double(SEXP x_, SEXP y_, SEXP ret_){
11671152 double * y = REAL (y_ );
11681153 long long * ret = (long long * ) REAL (ret_ );
11691154 Rboolean naflag = FALSE;
1170- long long cumsum , tempsum , addValue ;
1155+ long long cumsum , addValue ;
11711156 long double longret ;
11721157
11731158 for (i = 0 ; i < nrow1 ; i ++ ){
@@ -1179,13 +1164,11 @@ SEXP matmult_integer64_double(SEXP x_, SEXP y_, SEXP ret_){
11791164 cumsum = NA_INTEGER64 ;
11801165 break ;
11811166 }
1182- tempsum = cumsum + addValue ;
1183- if (!GOODISUM64 (cumsum , addValue , tempsum )){
1167+ if (add64_overflow (cumsum , addValue , & cumsum )){
11841168 naflag = TRUE;
11851169 cumsum = NA_INTEGER64 ;
11861170 break ;
11871171 }
1188- cumsum = tempsum ;
11891172 }
11901173 ret [i + j * nrow1 ] = cumsum ;
11911174 }
0 commit comments