11#include "data.table.h"
22
3- void nafillDouble (double * x , uint_fast64_t nx , unsigned int type , double fill , bool nan_is_na , ans_t * ans , bool verbose ) {
3+ void nafillDouble (double * x , uint_fast64_t nx , unsigned int type , double fill , bool nan_is_na , ans_t * ans , bool verbose , uint_fast64_t limit ) {
44 double tic = 0.0 ;
55 if (verbose )
66 tic = omp_get_wtime ();
7+ uint_fast64_t fills = 0 ;
78 if (type == 0 ) { // const
89 if (nan_is_na ) {
910 for (uint_fast64_t i = 0 ; i < nx ; i ++ ) {
10- ans -> dbl_v [i ] = ISNAN (x [i ]) ? fill : x [i ];
11+ if (ISNAN (x [i ])) {
12+ if (fills < limit ) { ans -> dbl_v [i ] = fill ; fills ++ ; }
13+ else ans -> dbl_v [i ] = x [i ];
14+ } else { ans -> dbl_v [i ] = x [i ]; fills = 0 ; }
1115 }
1216 } else {
1317 for (uint_fast64_t i = 0 ; i < nx ; i ++ ) {
14- ans -> dbl_v [i ] = ISNA (x [i ]) ? fill : x [i ];
18+ if (ISNA (x [i ])) {
19+ if (fills < limit ) { ans -> dbl_v [i ] = fill ; fills ++ ; }
20+ else ans -> dbl_v [i ] = x [i ];
21+ } else { ans -> dbl_v [i ] = x [i ]; fills = 0 ; }
1522 }
1623 }
1724 } else if (type == 1 ) { // locf
1825 if (nan_is_na ) {
19- ans -> dbl_v [0 ] = ISNAN (x [0 ]) ? fill : x [0 ];
26+ if (ISNAN (x [0 ]) && limit > 0 ) { ans -> dbl_v [0 ] = fill ; fills = 1 ; }
27+ else ans -> dbl_v [0 ] = x [0 ];
2028 for (uint_fast64_t i = 1 ; i < nx ; i ++ ) {
21- ans -> dbl_v [i ] = ISNAN (x [i ]) ? ans -> dbl_v [i - 1 ] : x [i ];
29+ if (ISNAN (x [i ])) {
30+ if (fills < limit ) { ans -> dbl_v [i ] = ans -> dbl_v [i - 1 ]; fills ++ ; }
31+ else ans -> dbl_v [i ] = x [i ];
32+ } else { ans -> dbl_v [i ] = x [i ]; fills = 0 ; }
2233 }
2334 } else {
24- ans -> dbl_v [0 ] = ISNA (x [0 ]) ? fill : x [0 ];
35+ if (ISNA (x [0 ]) && limit > 0 ) { ans -> dbl_v [0 ] = fill ; fills = 1 ; }
36+ else ans -> dbl_v [0 ] = x [0 ];
2537 for (uint_fast64_t i = 1 ; i < nx ; i ++ ) {
26- ans -> dbl_v [i ] = ISNA (x [i ]) ? ans -> dbl_v [i - 1 ] : x [i ];
38+ if (ISNA (x [i ])) {
39+ if (fills < limit ) { ans -> dbl_v [i ] = ans -> dbl_v [i - 1 ]; fills ++ ; }
40+ else ans -> dbl_v [i ] = x [i ];
41+ } else { ans -> dbl_v [i ] = x [i ]; fills = 0 ; }
2742 }
2843 }
2944 } else if (type == 2 ) { // nocb
3045 if (nan_is_na ) {
31- ans -> dbl_v [nx - 1 ] = ISNAN (x [nx - 1 ]) ? fill : x [nx - 1 ];
46+ if (ISNAN (x [nx - 1 ]) && limit > 0 ) { ans -> dbl_v [nx - 1 ] = fill ; fills = 1 ; }
47+ else ans -> dbl_v [nx - 1 ] = x [nx - 1 ];
3248 for (int_fast64_t i = nx - 2 ; i >=0 ; i -- ) {
33- ans -> dbl_v [i ] = ISNAN (x [i ]) ? ans -> dbl_v [i + 1 ] : x [i ];
49+ if (ISNAN (x [i ])) {
50+ if (fills < limit ) { ans -> dbl_v [i ] = ans -> dbl_v [i + 1 ]; fills ++ ; }
51+ else ans -> dbl_v [i ] = x [i ];
52+ } else { ans -> dbl_v [i ] = x [i ]; fills = 0 ; }
3453 }
3554 } else {
36- ans -> dbl_v [nx - 1 ] = ISNA (x [nx - 1 ]) ? fill : x [nx - 1 ];
55+ if (ISNA (x [nx - 1 ]) && limit > 0 ) { ans -> dbl_v [nx - 1 ] = fill ; fills = 1 ; }
56+ else ans -> dbl_v [nx - 1 ] = x [nx - 1 ];
3757 for (int_fast64_t i = nx - 2 ; i >=0 ; i -- ) {
38- ans -> dbl_v [i ] = ISNA (x [i ]) ? ans -> dbl_v [i + 1 ] : x [i ];
58+ if (ISNA (x [i ])) {
59+ if (fills < limit ) { ans -> dbl_v [i ] = ans -> dbl_v [i + 1 ]; fills ++ ; }
60+ else ans -> dbl_v [i ] = x [i ];
61+ } else { ans -> dbl_v [i ] = x [i ]; fills = 0 ; }
3962 }
4063 }
4164 }
4265 if (verbose )
4366 snprintf (ans -> message [0 ], 500 , _ ("%s: took %.3fs\n" ), __func__ , omp_get_wtime ()- tic );
4467}
45- void nafillInteger (int32_t * x , uint_fast64_t nx , unsigned int type , int32_t fill , ans_t * ans , bool verbose ) {
68+ void nafillInteger (int32_t * x , uint_fast64_t nx , unsigned int type , int32_t fill , ans_t * ans , bool verbose , uint_fast64_t limit ) {
4669 double tic = 0.0 ;
4770 if (verbose )
4871 tic = omp_get_wtime ();
72+ uint_fast64_t fills = 0 ;
4973 if (type == 0 ) { // const
5074 for (uint_fast64_t i = 0 ; i < nx ; i ++ ) {
51- ans -> int_v [i ] = x [i ]== NA_INTEGER ? fill : x [i ];
75+ if (x [i ]== NA_INTEGER ) {
76+ if (fills < limit ) { ans -> int_v [i ] = fill ; fills ++ ; }
77+ else ans -> int_v [i ] = x [i ];
78+ } else { ans -> int_v [i ] = x [i ]; fills = 0 ; }
5279 }
5380 } else if (type == 1 ) { // locf
54- ans -> int_v [0 ] = x [0 ]== NA_INTEGER ? fill : x [0 ];
81+ if (x [0 ]== NA_INTEGER && limit > 0 ) { ans -> int_v [0 ] = fill ; fills = 1 ; }
82+ else ans -> int_v [0 ] = x [0 ];
5583 for (uint_fast64_t i = 1 ; i < nx ; i ++ ) {
56- ans -> int_v [i ] = x [i ]== NA_INTEGER ? ans -> int_v [i - 1 ] : x [i ];
84+ if (x [i ]== NA_INTEGER ) {
85+ if (fills < limit ) { ans -> int_v [i ] = ans -> int_v [i - 1 ]; fills ++ ; }
86+ else ans -> int_v [i ] = x [i ];
87+ } else { ans -> int_v [i ] = x [i ]; fills = 0 ; }
5788 }
5889 } else if (type == 2 ) { // nocb
59- ans -> int_v [nx - 1 ] = x [nx - 1 ]== NA_INTEGER ? fill : x [nx - 1 ];
90+ if (x [nx - 1 ]== NA_INTEGER && limit > 0 ) { ans -> int_v [nx - 1 ] = fill ; fills = 1 ; }
91+ else ans -> int_v [nx - 1 ] = x [nx - 1 ];
6092 for (int_fast64_t i = nx - 2 ; i >=0 ; i -- ) {
61- ans -> int_v [i ] = x [i ]== NA_INTEGER ? ans -> int_v [i + 1 ] : x [i ];
93+ if (x [i ]== NA_INTEGER ) {
94+ if (fills < limit ) { ans -> int_v [i ] = ans -> int_v [i + 1 ]; fills ++ ; }
95+ else ans -> int_v [i ] = x [i ];
96+ } else { ans -> int_v [i ] = x [i ]; fills = 0 ; }
6297 }
6398 }
6499 if (verbose )
65100 snprintf (ans -> message [0 ], 500 , _ ("%s: took %.3fs\n" ), __func__ , omp_get_wtime ()- tic );
66101}
67- void nafillInteger64 (int64_t * x , uint_fast64_t nx , unsigned int type , int64_t fill , ans_t * ans , bool verbose ) {
102+ void nafillInteger64 (int64_t * x , uint_fast64_t nx , unsigned int type , int64_t fill , ans_t * ans , bool verbose , uint_fast64_t limit ) {
68103 double tic = 0.0 ;
69104 if (verbose )
70105 tic = omp_get_wtime ();
106+ uint_fast64_t fills = 0 ;
71107 if (type == 0 ) { // const
72108 for (uint_fast64_t i = 0 ; i < nx ; i ++ ) {
73- ans -> int64_v [i ] = x [i ]== NA_INTEGER64 ? fill : x [i ];
109+ if (x [i ]== NA_INTEGER64 ) {
110+ if (fills < limit ) { ans -> int64_v [i ] = fill ; fills ++ ; }
111+ else ans -> int64_v [i ] = x [i ];
112+ } else { ans -> int64_v [i ] = x [i ]; fills = 0 ; }
74113 }
75114 } else if (type == 1 ) { // locf
76- ans -> int64_v [0 ] = x [0 ]== NA_INTEGER64 ? fill : x [0 ];
115+ if (x [0 ]== NA_INTEGER64 && limit > 0 ) { ans -> int64_v [0 ] = fill ; fills = 1 ; }
116+ else ans -> int64_v [0 ] = x [0 ];
77117 for (uint_fast64_t i = 1 ; i < nx ; i ++ ) {
78- ans -> int64_v [i ] = x [i ]== NA_INTEGER64 ? ans -> int64_v [i - 1 ] : x [i ];
118+ if (x [i ]== NA_INTEGER64 ) {
119+ if (fills < limit ) { ans -> int64_v [i ] = ans -> int64_v [i - 1 ]; fills ++ ; }
120+ else ans -> int64_v [i ] = x [i ];
121+ } else { ans -> int64_v [i ] = x [i ]; fills = 0 ; }
79122 }
80123 } else if (type == 2 ) { // nocb
81- ans -> int64_v [nx - 1 ] = x [nx - 1 ]== NA_INTEGER64 ? fill : x [nx - 1 ];
124+ if (x [nx - 1 ]== NA_INTEGER64 && limit > 0 ) { ans -> int64_v [nx - 1 ] = fill ; fills = 1 ; }
125+ else ans -> int64_v [nx - 1 ] = x [nx - 1 ];
82126 for (int_fast64_t i = nx - 2 ; i >=0 ; i -- ) {
83- ans -> int64_v [i ] = x [i ]== NA_INTEGER64 ? ans -> int64_v [i + 1 ] : x [i ];
127+ if (x [i ]== NA_INTEGER64 ) {
128+ if (fills < limit ) { ans -> int64_v [i ] = ans -> int64_v [i + 1 ]; fills ++ ; }
129+ else ans -> int64_v [i ] = x [i ];
130+ } else { ans -> int64_v [i ] = x [i ]; fills = 0 ; }
84131 }
85132 }
86133 if (verbose )
87134 snprintf (ans -> message [0 ], 500 , _ ("%s: took %.3fs\n" ), __func__ , omp_get_wtime ()- tic );
88135}
89136
90- void nafillString (const SEXP * x , uint_fast64_t nx , unsigned int type , SEXP fill , ans_t * ans , bool verbose ) {
137+ void nafillString (const SEXP * x , uint_fast64_t nx , unsigned int type , SEXP fill , ans_t * ans , bool verbose , uint_fast64_t limit ) {
91138 double tic = 0.0 ;
92139 if (verbose )
93140 tic = omp_get_wtime ();
94- if (type == 0 ) { // const 1Code has comments. Press enter to view.
141+ uint_fast64_t fills = 0 ;
142+ if (type == 0 ) { // const
95143 for (uint_fast64_t i = 0 ; i < nx ; i ++ ) {
96- SET_STRING_ELT (ans -> char_v , i , x [i ]== NA_STRING ? fill : x [i ]);
144+ if (x [i ]== NA_STRING ) {
145+ if (fills < limit ) { SET_STRING_ELT (ans -> char_v , i , fill ); fills ++ ; }
146+ else SET_STRING_ELT (ans -> char_v , i , x [i ]);
147+ } else { SET_STRING_ELT (ans -> char_v , i , x [i ]); fills = 0 ; }
97148 }
98149 } else if (type == 1 ) { // locf
99- SET_STRING_ELT (ans -> char_v , 0 , x [0 ]== NA_STRING ? fill : x [0 ]);
150+ if (x [0 ]== NA_STRING && limit > 0 ) { SET_STRING_ELT (ans -> char_v , 0 , fill ); fills = 1 ; }
151+ else SET_STRING_ELT (ans -> char_v , 0 , x [0 ]);
100152 const SEXP * thisans = SEXPPTR_RO (ans -> char_v ); // takes out STRING_ELT from loop
101153 for (uint_fast64_t i = 1 ; i < nx ; i ++ ) {
102- SET_STRING_ELT (ans -> char_v , i , x [i ]== NA_STRING ? thisans [i - 1 ] : x [i ]);
154+ if (x [i ]== NA_STRING ) {
155+ if (fills < limit ) { SET_STRING_ELT (ans -> char_v , i , thisans [i - 1 ]); fills ++ ; }
156+ else SET_STRING_ELT (ans -> char_v , i , x [i ]);
157+ } else { SET_STRING_ELT (ans -> char_v , i , x [i ]); fills = 0 ; }
103158 }
104159 } else if (type == 2 ) { // nocb
105- SET_STRING_ELT (ans -> char_v , nx - 1 , x [nx - 1 ]== NA_STRING ? fill : x [nx - 1 ]);
160+ if (x [nx - 1 ]== NA_STRING && limit > 0 ) { SET_STRING_ELT (ans -> char_v , nx - 1 , fill ); fills = 1 ; }
161+ else SET_STRING_ELT (ans -> char_v , nx - 1 , x [nx - 1 ]);
106162 const SEXP * thisans = SEXPPTR_RO (ans -> char_v ); // takes out STRING_ELT from loop
107163 for (int_fast64_t i = nx - 2 ; i >=0 ; i -- ) {
108- SET_STRING_ELT (ans -> char_v , i , x [i ]== NA_STRING ? thisans [i + 1 ] : x [i ]);
164+ if (x [i ]== NA_STRING ) {
165+ if (fills < limit ) { SET_STRING_ELT (ans -> char_v , i , thisans [i + 1 ]); fills ++ ; }
166+ else SET_STRING_ELT (ans -> char_v , i , x [i ]);
167+ } else { SET_STRING_ELT (ans -> char_v , i , x [i ]); fills = 0 ; }
109168 }
110169 }
111170 if (verbose )
@@ -117,7 +176,7 @@ void nafillString(const SEXP *x, uint_fast64_t nx, unsigned int type, SEXP fill,
117176 over columns of the input data. This includes handling different data types
118177 and applying the designated filling method to each column in parallel.
119178*/
120- SEXP nafillR (SEXP obj , SEXP type , SEXP fill , SEXP nan_is_na_arg , SEXP inplace , SEXP cols ) {
179+ SEXP nafillR (SEXP obj , SEXP type , SEXP fill , SEXP nan_is_na_arg , SEXP inplace , SEXP cols , SEXP limit ) {
121180 int protecti = 0 ;
122181 const bool verbose = GetVerbose ();
123182
@@ -128,6 +187,9 @@ SEXP nafillR(SEXP obj, SEXP type, SEXP fill, SEXP nan_is_na_arg, SEXP inplace, S
128187 if (verbose )
129188 tic = omp_get_wtime ();
130189
190+ const double limit_d = REAL (limit )[0 ];
191+ const uint_fast64_t limit_n = !R_FINITE (limit_d ) || limit_d >= (double )UINT_FAST64_MAX ? UINT_FAST64_MAX : (uint_fast64_t )limit_d ;
192+
131193 bool copy = !LOGICAL (inplace )[0 ];
132194 if (!IS_TRUE_OR_FALSE (nan_is_na_arg ))
133195 error (_ ("'%s' must be TRUE or FALSE" ), "nan_is_na" ); // # nocov
@@ -253,16 +315,16 @@ SEXP nafillR(SEXP obj, SEXP type, SEXP fill, SEXP nan_is_na_arg, SEXP inplace, S
253315 switch (TYPEOF (VECTOR_ELT (x , i ))) {
254316 case REALSXP : {
255317 if (isInt64 [i ]) {
256- nafillInteger64 (i64x [i ], inx [i ], itype , hasFill ? ((int64_t * )fillp [i ])[0 ] : NA_INTEGER64 , & vans [i ], verbose );
318+ nafillInteger64 (i64x [i ], inx [i ], itype , hasFill ? ((int64_t * )fillp [i ])[0 ] : NA_INTEGER64 , & vans [i ], verbose , limit_n );
257319 } else {
258- nafillDouble (dx [i ], inx [i ], itype , hasFill ? ((double * )fillp [i ])[0 ] : NA_REAL , nan_is_na , & vans [i ], verbose );
320+ nafillDouble (dx [i ], inx [i ], itype , hasFill ? ((double * )fillp [i ])[0 ] : NA_REAL , nan_is_na , & vans [i ], verbose , limit_n );
259321 }
260322 } break ;
261323 case LGLSXP : case INTSXP : {
262- nafillInteger (ix [i ], inx [i ], itype , hasFill ? ((int32_t * )fillp [i ])[0 ] : NA_INTEGER , & vans [i ], verbose );
324+ nafillInteger (ix [i ], inx [i ], itype , hasFill ? ((int32_t * )fillp [i ])[0 ] : NA_INTEGER , & vans [i ], verbose , limit_n );
263325 } break ;
264326 case STRSXP : {
265- nafillString (sx [i ], inx [i ], itype , hasFill ? ((SEXP * )fillp [i ])[0 ] : NA_STRING , & vans [i ], verbose );
327+ nafillString (sx [i ], inx [i ], itype , hasFill ? ((SEXP * )fillp [i ])[0 ] : NA_STRING , & vans [i ], verbose , limit_n );
266328 } break ;
267329 }
268330 }
0 commit comments