55# Licence: GPL2
66# Provided 'as is', use at your own risk
77# Created: 2011-12-11
8- # Last changed: 2011-12-11
8+ # Last changed: 2026-01-09
99# */
1010
1111# ' Atomic Caching
6363# ' @describeIn cache creates a new cache referencing `x`
6464# ' @export
6565newcache = function (x ) {
66- env = new.env()
67- vmode = typeof(x )
68- if (vmode == " double" && is.integer64(x ))
69- vmode = " integer64"
70- setattr(env , " class" , c(paste(" cache" , vmode , sep = " _" ), " cache" , " environment" ))
71- assign(" x" , x , envir = env )
72- env
66+ env = new.env()
67+ vmode = typeof(x )
68+ if (vmode == " double" && is.integer64(x ))
69+ vmode = " integer64"
70+ setattr(env , " class" , c(paste(" cache" , vmode , sep = " _" ), " cache" , " environment" ))
71+ assign(" x" , x , envir = env )
72+ env
7373}
7474
7575# ' @describeIn cache forces `x` to have a cache
@@ -106,41 +106,41 @@ cache = function(x) {
106106# ' @param value An object to be stored in the cache
107107# ' @export
108108setcache = function (x , which , value ) {
109- env = jamcache(x )
110- assign(which , value , envir = env )
111- env
109+ env = jamcache(x )
110+ assign(which , value , envir = env )
111+ env
112112}
113113
114114# ' @describeIn cache gets cache value 'which' from `x`
115115# ' @export
116116getcache = function (x , which ) {
117- cache = attr(x , " cache" )
118- if (is.null(cache ))
119- return (NULL )
120- if (still.identical(x , get(" x" , envir = cache , inherits = FALSE ))) {
121- if (exists(which , envir = cache , inherits = FALSE ))
122- get(which , envir = cache , inherits = FALSE )
123- else
124- NULL
125- } else {
126- remcache(x )
127- warning(" removed outdated cache" )
117+ cache = attr(x , " cache" )
118+ if (is.null(cache ))
119+ return (NULL )
120+ if (still.identical(x , get(" x" , envir = cache , inherits = FALSE ))) {
121+ if (exists(which , envir = cache , inherits = FALSE ))
122+ get(which , envir = cache , inherits = FALSE )
123+ else
128124 NULL
129- }
125+ } else {
126+ remcache(x )
127+ warning(" removed outdated cache" )
128+ NULL
129+ }
130130}
131131
132132# ' @describeIn cache removes the cache from `x`
133133# ' @export
134134remcache = function (x ) {
135- setattr(x , " cache" , NULL )
136- invisible ()
135+ setattr(x , " cache" , NULL )
136+ invisible ()
137137}
138138
139139# ' @rdname cache
140140# ' @param all.names,pattern passed to [ls()] when listing the cache content
141141# ' @param ... ignored
142142# ' @export
143- print.cache = function (x , all.names = FALSE , pattern , ... ) {
143+ print.cache = function (x , all.names = FALSE , pattern , ... ) {
144144 l = ls(x , all.names , pattern = pattern )
145145 cat(class(x )[1L ], " : " , paste(l , collapse = " - " ), " \n " , sep = " " )
146146 invisible (l )
@@ -180,101 +180,100 @@ print.cache= function(x, all.names=FALSE, pattern, ...) {
180180# '
181181# ' @keywords environment
182182# ' @export
183- hashcache = function (x , nunique = NULL , ... ) {
184- env = jamcache(x )
185- if (is.null(nunique ))
186- nunique = env $ nunique
187- env = hashmap(x , nunique = nunique , cache = env , ... )
188- if (is.null(nunique ) && env $ nunique < sqrt(length(x )))
189- env = hashmap(x , nunique = env $ nunique , cache = env , ... )
190- na.count(x ) # since x has cache, na.count() will update the cache, unless its already there
191- # different from sortcache, ordercache and sortordercache we do not set nties: hastab is too expensive
192- invisible (env )
183+ hashcache = function (x , nunique = NULL , ... ) {
184+ env = jamcache(x )
185+ if (is.null(nunique ))
186+ nunique = env $ nunique
187+ env = hashmap(x , nunique = nunique , cache = env , ... )
188+ if (is.null(nunique ) && env $ nunique < sqrt(length(x )))
189+ env = hashmap(x , nunique = env $ nunique , cache = env , ... )
190+ na.count(x ) # since x has cache, na.count() will update the cache, unless its already there
191+ # different from sortcache, ordercache and sortordercache we do not set nties: hastab is too expensive
192+ invisible (env )
193193}
194194
195195# ' @rdname hashcache
196196# ' @param has.na boolean scalar defining whether the input vector might contain
197197# ' `NA`s. If we know we don't have `NA`s, this may speed-up. _Note_ that you
198198# ' risk a crash if there are unexpected `NA`s with `has.na=FALSE`.
199+ # ' @param na.last boolean scalar defining whether NA should be last.
199200# ' @export
200- sortcache = function (x , has.na = NULL ) {
201- if (is.null(has.na )) {
202- na.count = getcache(x , " na.count" )
203- if (is.null(na.count ))
204- has.na = TRUE
205- else
206- has.na = na.count > 0L
207- }
208- s = clone(x )
209- na.count = ramsort(s , has.na = has.na , na.last = FALSE , decreasing = FALSE , stable = FALSE , optimize = " time" )
210- nut = .Call(C_r_ram_integer64_sortnut , x = s )
211- setcache(x , " sort" , s )
212- setcache(x , " na.count" , na.count )
213- setcache(x , " nunique" , nut [[1L ]])
214- setcache(x , " nties" , nut [[2L ]])
215- invisible (x )
201+ sortcache = function (x , has.na = NULL , na.last = FALSE ) {
202+ if (is.null(has.na )) {
203+ na.count = getcache(x , " na.count" )
204+ if (is.null(na.count ))
205+ has.na = TRUE
206+ else
207+ has.na = na.count > 0L
208+ }
209+ s = clone(x )
210+ na.count = ramsort(s , has.na = has.na , na.last = na.last , decreasing = FALSE , stable = FALSE , optimize = " time" )
211+ nut = .Call(C_r_ram_integer64_sortnut , x = s )
212+ setcache(x , " sort" , s )
213+ setcache(x , " na.count" , na.count )
214+ setcache(x , " nunique" , nut [[1L ]])
215+ setcache(x , " nties" , nut [[2L ]])
216+ invisible (x )
216217}
217218
218219# ' @rdname hashcache
219220# ' @param stable boolean scalar defining whether stable sorting is needed. Allowing
220221# ' non-stable may speed-up.
221222# ' @export
222- sortordercache = function (x , has.na = NULL , stable = NULL ) {
223- if (is.null(has.na )) {
224- na.count = getcache(x , " na.count" )
225- if (is.null(na.count ))
226- has.na = TRUE
227- else
228- has.na = na.count > 0L
229- }
230- if (is.null(stable )) {
231- nunique = getcache(x , " nunique" )
232- if (is.null(nunique ))
233- stable = TRUE
234- else
235- stable = nunique < length(x )
236- }
237- s = clone(x )
238- o = seq_along(x )
239- na.count =
240- ramsortorder(s , o , has.na = has.na , na.last = FALSE , decreasing = FALSE , stable = stable , optimize = " time" )
241- nut = .Call(C_r_ram_integer64_sortnut , x = s )
242- setcache(x , " sort" , s )
243- setcache(x , " order" , o )
244- setcache(x , " na.count" , na.count )
245- setcache(x , " nunique" , nut [[1L ]])
246- setcache(x , " nties" , nut [[2L ]])
247- invisible (x )
223+ sortordercache = function (x , has.na = NULL , stable = NULL , na.last = FALSE ) {
224+ if (is.null(has.na )) {
225+ na.count = getcache(x , " na.count" )
226+ if (is.null(na.count ))
227+ has.na = TRUE
228+ else
229+ has.na = na.count > 0L
230+ }
231+ if (is.null(stable )) {
232+ nunique = getcache(x , " nunique" )
233+ if (is.null(nunique ))
234+ stable = TRUE
235+ else
236+ stable = nunique < length(x )
237+ }
238+ s = clone(x )
239+ o = seq_along(x )
240+ na.count = ramsortorder(s , o , has.na = has.na , na.last = na.last , decreasing = FALSE , stable = stable , optimize = " time" )
241+ nut = .Call(C_r_ram_integer64_sortnut , x = s )
242+ setcache(x , " sort" , s )
243+ setcache(x , " order" , o )
244+ setcache(x , " na.count" , na.count )
245+ setcache(x , " nunique" , nut [[1L ]])
246+ setcache(x , " nties" , nut [[2L ]])
247+ invisible (x )
248248}
249249
250250# ' @rdname hashcache
251251# ' @param optimize by default ramsort optimizes for 'time' which requires more RAM,
252252# ' set to 'memory' to minimize RAM requirements and sacrifice speed.
253253# ' @export
254- ordercache = function (x , has.na = NULL , stable = NULL , optimize = " time" ) {
255- if (is.null(has.na )) {
256- na.count = getcache(x , " na.count" )
257- if (is.null(na.count ))
258- has.na = TRUE
259- else
260- has.na = na.count > 0L
261- }
262- if (is.null(stable )) {
263- nunique = getcache(x , " nunique" )
264- if (is.null(nunique ))
265- stable = TRUE
266- else
267- stable = nunique < length(x )
268- }
269- o = seq_along(x )
270- na.count =
271- ramorder(x , o , has.na = has.na , na.last = FALSE , decreasing = FALSE , stable = stable , optimize = optimize )
272- nut = .Call(C_r_ram_integer64_ordernut , table = x , order = o )
273- setcache(x , " order" , o )
274- setcache(x , " na.count" , na.count )
275- setcache(x , " nunique" , nut [[1L ]])
276- setcache(x , " nties" , nut [[2L ]])
277- invisible (x )
254+ ordercache = function (x , has.na = NULL , stable = NULL , optimize = " time" , na.last = FALSE ) {
255+ if (is.null(has.na )) {
256+ na.count = getcache(x , " na.count" )
257+ if (is.null(na.count ))
258+ has.na = TRUE
259+ else
260+ has.na = na.count > 0L
261+ }
262+ if (is.null(stable )) {
263+ nunique = getcache(x , " nunique" )
264+ if (is.null(nunique ))
265+ stable = TRUE
266+ else
267+ stable = nunique < length(x )
268+ }
269+ o = seq_along(x )
270+ na.count = ramorder(x , o , has.na = has.na , na.last = na.last , decreasing = FALSE , stable = stable , optimize = optimize )
271+ nut = .Call(C_r_ram_integer64_ordernut , table = x , order = o )
272+ setcache(x , " order" , o )
273+ setcache(x , " na.count" , na.count )
274+ setcache(x , " nunique" , nut [[1L ]])
275+ setcache(x , " nties" , nut [[2L ]])
276+ invisible (x )
278277}
279278
280279# ' Small cache access methods
@@ -320,10 +319,10 @@ NULL
320319na.count.integer64 = function (x , ... ) {
321320 env = cache(x )
322321 if (is.null(env ))
323- return (.Call(C_r_ram_integer64_nacount , x = x ))
322+ return (.Call(C_r_ram_integer64_nacount , x = x ))
324323 if (exists(" na.count" , envir = env , inherits = FALSE ))
325324 return (get(" na.count" , envir = env , inherits = FALSE ))
326- ret = .Call(C_r_ram_integer64_nacount , x = x )
325+ ret = .Call(C_r_ram_integer64_nacount , x = x )
327326 assign(" na.count" , ret , envir = env )
328327 ret
329328}
@@ -332,61 +331,60 @@ na.count.integer64 = function(x, ...) {
332331# ' usually [length()] minus `na.count`.
333332# ' @export
334333nvalid.integer64 = function (x , ... ) {
335- length(x ) - na.count(x )
334+ length(x ) - na.count(x )
336335}
337336
338337# ' @describeIn is.sorted.integer64 checks for sortedness of `x` (NAs sorted first)
339338# ' @export
340339is.sorted.integer64 = function (x , ... ) {
341340 env = cache(x )
342341 if (is.null(env ))
343- return (.Call(C_r_ram_integer64_issorted_asc , x = x ))
342+ return (.Call(C_r_ram_integer64_issorted_asc , x = x ))
344343 if (exists(" is.sorted" , envir = env , inherits = FALSE ))
345344 return (get(" is.sorted" , envir = env , inherits = FALSE ))
346- ret = .Call(C_r_ram_integer64_issorted_asc , x = x )
345+ ret = .Call(C_r_ram_integer64_issorted_asc , x = x )
347346 assign(" is.sorted" , ret , envir = env )
348347 ret
349348}
350349
351350# ' @describeIn is.sorted.integer64 returns the number of unique values
352351# ' @export
353352nunique.integer64 = function (x , ... ) {
354- env = cache(x )
355- if (is.null(env ))
356- has.cache = FALSE
357- else if (exists(" nunique" , envir = env , inherits = FALSE ))
358- return (get(" nunique" , envir = env , inherits = FALSE ))
359- else # nolint: unreachable_code_linter. TODO(r-lib/lintr#2710): Re-enable.
360- has.cache = TRUE
361- if (is.sorted(x )) {
362- ret = .Call(C_r_ram_integer64_sortnut , x = x )
363- if (has.cache ) {
364- assign(" nunique" , ret [1L ], envir = env )
365- assign(" nties" , ret [2L ], envir = env )
366- }
367- ret [1L ]
368- } else {
369- h = hashmap(x )
370- if (has.cache )
371- assign(" nunique" , h $ nunique , envir = env )
372- h $ nunique
353+ env = cache(x )
354+ if (is.null(env ))
355+ has.cache = FALSE
356+ else if (exists(" nunique" , envir = env , inherits = FALSE ))
357+ return (get(" nunique" , envir = env , inherits = FALSE ))
358+ else # nolint: unreachable_code_linter. TODO(r-lib/lintr#2710): Re-enable.
359+ has.cache = TRUE
360+ if (is.sorted(x )) {
361+ ret = .Call(C_r_ram_integer64_sortnut , x = x )
362+ if (has.cache ) {
363+ assign(" nunique" , ret [1L ], envir = env )
364+ assign(" nties" , ret [2L ], envir = env )
373365 }
366+ ret [1L ]
367+ } else {
368+ h = hashmap(x )
369+ if (has.cache )
370+ assign(" nunique" , h $ nunique , envir = env )
371+ h $ nunique
372+ }
374373}
375374
376375# ' @describeIn is.sorted.integer64 returns the number of tied values.
377376# ' @export
378377nties.integer64 = function (x , ... ) {
379- cv = getcache(x , " nties" )
380- if (is.null(cv )) {
381- if (is.sorted(x )) {
382- cv = .Call(C_r_ram_integer64_sortnut , x = x )[2L ]
383- } else {
384- s = clone(x )
385- # nolint next: object_usage_linter. Keep the output of in-place ramsort for debugging.
386- na.count =
387- ramsort(s , has.na = TRUE , na.last = FALSE , decreasing = FALSE , stable = FALSE , optimize = " time" )
388- cv = .Call(C_r_ram_integer64_sortnut , x = s )[[2L ]]
389- }
378+ cv = getcache(x , " nties" )
379+ if (is.null(cv )) {
380+ if (is.sorted(x )) {
381+ cv = .Call(C_r_ram_integer64_sortnut , x = x )[2L ]
382+ } else {
383+ s = clone(x )
384+ # nolint next: object_usage_linter. Keep the output of in-place ramsort for debugging.
385+ na.count = ramsort(s , has.na = TRUE , na.last = FALSE , decreasing = FALSE , stable = FALSE , optimize = " time" )
386+ cv = .Call(C_r_ram_integer64_sortnut , x = s )[[2L ]]
390387 }
391- cv
388+ }
389+ cv
392390}
0 commit comments