Skip to content

Commit ef682c2

Browse files
HughParsonagecran-robot
authored andcommitted
version 0.10.10
1 parent fb7988e commit ef682c2

File tree

10 files changed

+207
-123
lines changed

10 files changed

+207
-123
lines changed

DESCRIPTION

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
Package: hutilscpp
22
Title: Miscellaneous Functions in C++
3-
Version: 0.10.8
3+
Version: 0.10.10
44
Authors@R:
55
c(person(given = "Hugh",
66
family = "Parsonage",
@@ -25,9 +25,9 @@ Imports: data.table, hutils, magrittr, utils
2525
RoxygenNote: 7.3.2
2626
Suggests: bench, parallel, TeXCheckR, withr, tinytest, covr
2727
NeedsCompilation: yes
28-
Packaged: 2025-03-06 13:36:42 UTC; hughp
28+
Packaged: 2025-03-20 07:45:30 UTC; hughp
2929
Author: Hugh Parsonage [aut, cre],
3030
Simon Urbanek [ctb] (fastmatch components)
3131
Maintainer: Hugh Parsonage <hugh.parsonage@gmail.com>
3232
Repository: CRAN
33-
Date/Publication: 2025-03-06 14:30:02 UTC
33+
Date/Publication: 2025-03-20 08:10:02 UTC

MD5

+9-9
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
158804aa42ed6cf3314770f6e6e0c31d *DESCRIPTION
1+
aabe5a0a9e5a2a7b334bceb7ced5616e *DESCRIPTION
22
d301d392eec076b41064a954bc8753db *NAMESPACE
3-
210d5a5774599f8a8373751c34dd0810 *NEWS.md
3+
08d4700c0edcee911ec0d6cb7867eb26 *NEWS.md
44
a1f1cd040c22ea2081499fbeaff3b625 *R/AnyCharMatch.R
55
cb494f5a99c1f068733401164da3b410 *R/Comma.R
66
f9c261a8d4bb8cd88ed83edfe0ac5348 *R/Implies.R
7-
1e95efd29929f352edcdea5bc4ece0f7 *R/ModeC.R
7+
01475d099b75e627687ee8308b6247b3 *R/ModeC.R
88
1c918049a947af138e46e1b807c5807b *R/R_xlen_t.R
99
e72b22013d6be80e1eb4514f90fd13f5 *R/abs_diff.R
1010
8fdc9ed4d6635e583c9940c5607d5b94 *R/allocate.R
@@ -95,7 +95,7 @@ f7c1aee03ae8d70412ad4c8902fac4ad *inst/tinytest/test-is_constant.R
9595
39da6a3a8768f1a07ad39b83d5932964 *inst/tinytest/test-is_sorted.R
9696
b52b949e5397c5b52b9d16a72050b025 *inst/tinytest/test-match_nrst_haversine.R
9797
7668d17d595a4fd9a11dba1d812eac2f *inst/tinytest/test-or3.R
98-
bd7a8b068372e75e39cd984563ea979b *inst/tinytest/test-or3s.R
98+
b50ac38713cf470c48f422ef646ebe75 *inst/tinytest/test-or3s.R
9999
5db4ac91bfda8634be2131b2d16a2cf5 *inst/tinytest/test-pmax0.R
100100
e6eb293b7a8c6b5047ee3b50f8b7dab5 *inst/tinytest/test-pmax3.R
101101
ceafca183320965923cc21d1a48478f2 *inst/tinytest/test-pmaxC.R
@@ -114,7 +114,7 @@ a7eaa41a330abb8e0d1e00e69d9ecee8 *inst/tinytest/test-sum_and3s.R
114114
2a64aa42f6135a1ab1d26e178ba421f0 *inst/tinytest/test-sum_isna.R
115115
74f83e4cc7727fe43436d3396c070c05 *inst/tinytest/test-sum_or3s.R
116116
eeaeaf160870c78f91306419971f12a4 *inst/tinytest/test-tex.R
117-
a83e3ba9c47b2eb1f7d0aa04addcd562 *inst/tinytest/test-texParse-internals.R
117+
bb3d6391397a4faafb8bd8b48e2f6d22 *inst/tinytest/test-texParse-internals.R
118118
05d9f4bae7a4714626c65986bd41298a *inst/tinytest/test-units2km.R
119119
165d878790996f6555a00f1f1396179b *inst/tinytest/test-utils.R
120120
5a100e63b7b8abc0a5328575ca346496 *inst/tinytest/test-valgrind.R
@@ -146,7 +146,7 @@ e8ee3599658e4024b224f4d4f65c413e *inst/tinytest/test_unique_fmatch.R
146146
638b6de6ebabbb13f1e4fc29b0f0c4a4 *inst/tinytest/test_which_raw.R
147147
758b8ccab47b1c2d3f270db230361166 *man/Comma.Rd
148148
5dcb9d29cd94060b95cdacef3359d02c *man/Implies.Rd
149-
8c8992558b8e7d0a19d7551887e58013 *man/ModeC.Rd
149+
b30c4889716dff893a0ed60346b25306 *man/ModeC.Rd
150150
b88cac8df059485459eb76fdd41c9ca2 *man/abs_diff.Rd
151151
c8cf8806fcc1969bf2c35ba840deb396 *man/allNA.Rd
152152
f589897fb3756e45dbfccd23f049b63e *man/anyOutside.Rd
@@ -186,7 +186,7 @@ b95ab2cca899d96c4ac8a304c153ee03 *man/which_true_onwards.Rd
186186
d46c1c272201c0e662f3489a5d95ee2c *src/CImplies.c
187187
191c336b39b4bbe4f75f3217d24fd215 *src/CSquish.c
188188
36733d7eed7f5a69f6a8c5b694424f1e *src/C_FLIP.c
189-
8b503999b728b0dd233aa0d51788013c *src/C_Mode.c
189+
5333c3d9a226732dba52f97a7b829847 *src/C_Mode.c
190190
c5801b092e1fc7707cbf8595e9f88733 *src/C_abs_diff.c
191191
4199c59690f629fc1ccdf1cd1acfc9e4 *src/C_character2integer.c
192192
03d2e2e33eed8912a7b7d4b4978831ad *src/C_empty.c
@@ -230,7 +230,7 @@ ab32e7ecc990531c46f700fb6f286dfa *src/character.c
230230
2534e19029d331d62bdaa431d5e0ebd3 *src/fmatchp_lgl.c
231231
2630c6002e34a43abebb2aa00666d246 *src/haversineDistance.c
232232
b08506d1b5170d405bb03aafd7c48e39 *src/hutilscpp.h
233-
356d3dd69078c090721bec43beec0a70 *src/init.c
233+
f43f71496f8ec9608b3690a1e6a44469 *src/init.c
234234
220b10138fdfcd944d57f90a82b1f608 *src/is_seq.c
235235
e986dad2ac29afd74b1940b5d497321b *src/is_true.c
236236
0efdf12a6dd78cc69a3fdda126965f39 *src/isntRaw.c
@@ -241,4 +241,4 @@ f9353379f760e640e9fb138c6235c81f *src/logical3.c
241241
b06fcf2d1ccbfd9a84706cefddcf16f5 *src/pcg_hash.c
242242
652f9549e240053757b8398557826b24 *src/single_ox_x1_x2.c
243243
648cc274d16ef212ce942c5433cf7fd9 *src/summary3.c
244-
b59fb405e9bee7923287aff8075b3eb9 *tests/tinytest.R
244+
3d2f045f1d73b8608577b29674ffbf5f *tests/tinytest.R

NEWS.md

+9-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,12 @@
1-
## hutilscpp
1+
## hutilscpp 0.10.10
2+
3+
- New unexported function `antiMode` for the least common element
4+
5+
### Internal
6+
7+
- Reduce tinytest verbosity to avoid excessive test logs. Thanks to CRAN for reporting.
8+
9+
210

311
### Internal
412

R/ModeC.R

+66-48
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,66 @@
1-
#' Most common element
2-
#' @param x An atomic vector.
3-
#' @param nThread Number of threads to use.
4-
#' @param .range_fmatch If the range of \code{x} differs by more than
5-
#' this amount, the mode will be calculated via \code{fmatchp}.
6-
#' @param option \code{integer(1)} Handle exceptional cases:
7-
#' \describe{
8-
#' \item{0}{Returns \code{NULL} quietly.}
9-
#' \item{1}{Returns an error if the mode cannot be calculated.}
10-
#' \item{2}{Emits a warning if the mode cannot be calculate, falls back to \code{hutils::Mode}}
11-
#' }
12-
#'
13-
#' @examples
14-
#' ModeC(c(1L, 1L, 2L))
15-
#'
16-
#'
17-
#' @export
18-
19-
20-
ModeC <- function(x,
21-
nThread = getOption("hutilscpp.nThread", 1L),
22-
.range_fmatch = 1e9,
23-
option = 1L) {
24-
if (!is.integer(x) ||
25-
anyNA(xminmax <- minmax(x, nThread = nThread)) ||
26-
xminmax[1] + .range_fmatch <= xminmax[2]) {
27-
fx <- fmatchp(x, x, nThread = nThread)
28-
mode_fx <- .Call("C_Mode", fx, nThread, NULL, PACKAGE = "hutilscpp")
29-
return(x[mode_fx])
30-
}
31-
ans <- .Call("C_Mode", x, nThread, xminmax, PACKAGE = "hutilscpp")
32-
# nocov start
33-
if (is.null(ans)) {
34-
if (option) {
35-
switch(option,
36-
stop("Unable to calculate ModeC."),
37-
{
38-
warning("Unable to calculate ModeC, falling back to hutils::Mode")
39-
return(hutils::Mode(x))
40-
})
41-
}
42-
}
43-
# nocov end
44-
ans
45-
}
46-
47-
48-
1+
#' Most common element
2+
#' @param x An atomic vector.
3+
#' @param nThread Number of threads to use.
4+
#' @param .range_fmatch If the range of \code{x} differs by more than
5+
#' this amount, the mode will be calculated via \code{fmatchp}.
6+
#' @param option \code{integer(1)} Handle exceptional cases:
7+
#' \describe{
8+
#' \item{0}{Returns \code{NULL} quietly.}
9+
#' \item{1}{Returns an error if the mode cannot be calculated.}
10+
#' \item{2}{Emits a warning if the mode cannot be calculate, falls back to \code{hutils::Mode}}
11+
#' }
12+
#'
13+
#' @examples
14+
#' ModeC(c(1L, 1L, 2L))
15+
#'
16+
#'
17+
#' @export
18+
19+
20+
ModeC <- function(x,
21+
nThread = getOption("hutilscpp.nThread", 1L),
22+
.range_fmatch = 1e9,
23+
option = 1L) {
24+
if (!is.integer(x) ||
25+
anyNA(xminmax <- minmax(x, nThread = nThread)) ||
26+
xminmax[1] + .range_fmatch <= xminmax[2]) {
27+
fx <- fmatchp(x, x, nThread = nThread)
28+
mode_fx <- .Call("C_Mode", fx, nThread, NULL, PACKAGE = "hutilscpp")
29+
return(x[mode_fx])
30+
}
31+
ans <- .Call("C_Mode", x, nThread, xminmax, PACKAGE = "hutilscpp")
32+
# nocov start
33+
if (is.null(ans)) {
34+
if (option) {
35+
switch(option,
36+
stop("Unable to calculate ModeC."),
37+
{
38+
warning("Unable to calculate ModeC, falling back to hutils::Mode")
39+
return(hutils::Mode(x))
40+
})
41+
}
42+
}
43+
# nocov end
44+
ans
45+
}
46+
47+
48+
antiModeC <- function(x, domain = NULL, domain_is_minmax = NULL, do_which = NA) {
49+
50+
ans <- .Call("C_antiMode", x,
51+
sort(domain %||% minmax(x), na.last = FALSE),
52+
domain_is_minmax %||% TRUE,
53+
isTRUE(do_which),
54+
PACKAGE = "hutilscpp")
55+
if (is.null(ans)) {
56+
ans <- which.min(tx <- table(x))
57+
if (isTRUE(do_which)) {
58+
return(unclass(ans))
59+
}
60+
ans <- tx[[ans]]
61+
}
62+
ans
63+
}
64+
65+
66+

inst/tinytest/test-or3s.R

+4
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@ library(hutilscpp)
22
library(hutils)
33
library(data.table)
44

5+
if (!at_home() && !hutilscpp:::is_covr()) {
6+
exit_file("neither at home nor covering")
7+
}
8+
59
x <- rep_len(c(TRUE, FALSE), 1e4)
610
expect_false(any(or3s(x %between% c(TRUE, FALSE))))
711
expect_false(any(or3s(x %(between)% c(FALSE, TRUE))))
+48-48
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,48 @@
1-
extractMandatory <- hutilscpp:::extractMandatory
2-
where_square_bracket_opens <- hutilscpp:::where_square_bracket_opens
3-
4-
5-
# test_that("where_square_bracket_opens", {
6-
s <- function(x) unlist(strsplit(x, split = "", fixed = TRUE))
7-
expect_equal(where_square_bracket_opens(s("0123[567]9"), -1), -1)
8-
expect_equal(where_square_bracket_opens(s("0123[567]9"), 0), -1)
9-
expect_equal(where_square_bracket_opens(s("0123[567]9"), 8L), 4L)
10-
expect_equal(where_square_bracket_opens(s("01234567]9"), 8L), 0L)
11-
expect_equal(where_square_bracket_opens(s("0123[{}4]9"), 8L), 4L)
12-
expect_equal(where_square_bracket_opens(s("{[[][]{}] "), 8L), 1L)
13-
expect_equal(where_square_bracket_opens(s(c("a",
14-
"[",
15-
"",
16-
"{",
17-
"a",
18-
"}",
19-
"]")),
20-
5L),
21-
1L)
22-
expect_equal(where_square_bracket_opens(s(c("a", # 0
23-
"[",
24-
"", # 2
25-
"\u2010",
26-
"{", # 4
27-
"{",
28-
"a", # 6
29-
"}",
30-
"}", # 8
31-
"]")),
32-
8L),
33-
1L)
34-
# STRING_ELT(x, i) != 1
35-
expect_equal(where_square_bracket_opens(c("a", # 0
36-
"[",
37-
"", # 2
38-
"aa", # <---- len 2
39-
"{", # 4
40-
"{",
41-
"aa", # 6
42-
"}",
43-
"}", # 8
44-
"]"),
45-
9L),
46-
1L)
47-
48-
1+
extractMandatory <- hutilscpp:::extractMandatory
2+
where_square_bracket_opens <- hutilscpp:::where_square_bracket_opens
3+
4+
5+
# test_that("where_square_bracket_opens", {
6+
s <- function(x) unlist(strsplit(x, split = "", fixed = TRUE))
7+
expect_equal(where_square_bracket_opens(s("0123[567]9"), -1), -1)
8+
expect_equal(where_square_bracket_opens(s("0123[567]9"), 0), -1)
9+
expect_equal(where_square_bracket_opens(s("0123[567]9"), 8L), 4L)
10+
expect_equal(where_square_bracket_opens(s("01234567]9"), 8L), 0L)
11+
expect_equal(where_square_bracket_opens(s("0123[{}4]9"), 8L), 4L)
12+
expect_equal(where_square_bracket_opens(s("{[[][]{}] "), 8L), 1L)
13+
expect_equal(where_square_bracket_opens(s(c("a",
14+
"[",
15+
"",
16+
"{",
17+
"a",
18+
"}",
19+
"]")),
20+
5L),
21+
1L)
22+
expect_equal(where_square_bracket_opens(s(c("a", # 0
23+
"[",
24+
"", # 2
25+
"\u2010",
26+
"{", # 4
27+
"{",
28+
"a", # 6
29+
"}",
30+
"}", # 8
31+
"]")),
32+
8L),
33+
1L)
34+
# STRING_ELT(x, i) != 1
35+
expect_equal(where_square_bracket_opens(c("a", # 0
36+
"[",
37+
"", # 2
38+
"aa", # <---- len 2
39+
"{", # 4
40+
"{",
41+
"aa", # 6
42+
"}",
43+
"}", # 8
44+
"]"),
45+
9L),
46+
1L)
47+
48+

man/ModeC.Rd

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/C_Mode.c

+50
Original file line numberDiff line numberDiff line change
@@ -127,5 +127,55 @@ SEXP CuniqueN_fmatch(SEXP fx, SEXP nthreads) {
127127
return ScalarInteger(o);
128128
}
129129

130+
SEXP C_antiMode(SEXP x, SEXP Domain, SEXP DomainIsMinMax, SEXP doWhich) {
131+
if (!isInteger(x) || !isInteger(Domain)) {
132+
error("non-integer not supported");
133+
}
134+
const int is_minmax = asLogical(DomainIsMinMax);
135+
const int is_doWhich = asLogical(doWhich);
136+
137+
const int * dp = INTEGER(Domain);
138+
R_xlen_t N_d = xlength(Domain);
139+
const int * xp = INTEGER(x);
140+
R_xlen_t N = xlength(x);
141+
if (N == 0) {
142+
error("`xlength(x) == 0` so no least common element.");
143+
}
144+
145+
int candidate = xp[0];
146+
if (N == 1) {
147+
return ScalarInteger(candidate);
148+
}
149+
if (is_minmax == 1) {
150+
const int dp0 = dp[0];
151+
int64_t range = dp[1];
152+
range -= dp0;
153+
if (range < 256) {
154+
uint64_t tbl[256] = {0};
155+
for (R_xlen_t i = 0; i < N; ++i) {
156+
tbl[xp[i] - dp0]++;
157+
}
158+
int which_min_ = 0;
159+
int n_min = tbl[0]; // note that the minimum should be occupied
160+
if (n_min == 0) {
161+
error("Internal error(n_min_antiMode) n_min = 0");
162+
}
163+
for (int j = 1; j < 256; ++j) {
164+
if (tbl[j] && tbl[j] < n_min) {
165+
which_min_ = j;
166+
n_min = tbl[j];
167+
}
168+
}
169+
return is_doWhich == 1 ? ScalarInteger(which_min_ + 1) : ScalarInteger(dp0 + which_min_);
170+
}
171+
}
172+
173+
174+
175+
return R_NilValue;
176+
}
177+
178+
179+
130180

131181

0 commit comments

Comments
 (0)