Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
2420731
bitwise operations
hcirellu Mar 25, 2026
5501296
remove dev comment
hcirellu Mar 25, 2026
11c88ba
remove dev comment
hcirellu Mar 25, 2026
9d36455
fix macos check
hcirellu Mar 25, 2026
d0d64ec
debug ancient test
hcirellu Mar 26, 2026
a558f8f
debug ancient test
hcirellu Mar 26, 2026
6242fb8
fix hopefully test on ancient
hcirellu Mar 26, 2026
7403818
Gemini: adapt style to avoid macros
MichaelChirico Sep 1, 2026
f2c27d3
delint
MichaelChirico Sep 1, 2026
66f7360
Gemini: handle "dispatch" from C, not from combinatorial entry points
MichaelChirico Sep 1, 2026
856a86e
Gemini: remove unreachable code
MichaelChirico Sep 1, 2026
e76d455
move NEWS to devel
MichaelChirico Sep 1, 2026
b73220e
restructure to emphasize symmetry / reduce boilerplate
MichaelChirico Sep 1, 2026
6f788ae
Gemini: cascade the same refactor to the other routines
MichaelChirico Sep 1, 2026
ae212fa
better variable names
MichaelChirico Sep 1, 2026
a287e27
avoid eval(parse())
MichaelChirico Sep 1, 2026
cdb5923
try to be more explicit about error handling
MichaelChirico Sep 1, 2026
e1a2303
Gemini: clean up attempt to simplify/clarify tests
MichaelChirico Sep 1, 2026
5ad390b
delint, unnest
MichaelChirico Sep 1, 2026
0a0f13a
getExportedValue over get
MichaelChirico Sep 1, 2026
5c85d1d
use identical() test more
MichaelChirico Sep 1, 2026
620f830
use x_base to refer to "x as passed to the base function"
MichaelChirico Sep 1, 2026
ee59700
Gemini: drop my_if_else
MichaelChirico Sep 1, 2026
aab12bc
Gemini: simplify tryCatch for x_int
MichaelChirico Sep 1, 2026
1a24e86
Gemini: comment for posterity about the need for the complicated offs…
MichaelChirico Sep 1, 2026
a001629
rep_len issues on ancient R
MichaelChirico Sep 1, 2026
6c02618
Gemini: coverage tests
MichaelChirico Sep 1, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,12 @@ export(as.integer64)
export(as.ordered)
export(benchmark64)
export(binattr)
export(bitwAnd)
export(bitwNot)
export(bitwOr)
export(bitwShiftL)
export(bitwShiftR)
export(bitwXor)
export(cache)
export(colSums)
export(factor)
Expand Down
4 changes: 4 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@

1. Supplying `keep.names=` to `as.integer64()` now emits a warning, which will become an error in the next release.

## NEW FEATURES

1. `bitwNot`, `bitwAnd`, `bitwOr`, `bitwXor`, `bitwShiftL` and `bitwShiftR` get an overload to work correctly with `integer64` (#33).

## NOTES

1. The R version dependency has been bumped from 3.5.0 (2018) to 3.6.0 (2019).
Expand Down
159 changes: 159 additions & 0 deletions R/bitwise64.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
# /*
# R-Code
# S3 atomic 64bit integers for R
# (c) 2026 Michael Chirico
# Licence: GPL2
# Provided 'as is', use at your own risk
#*/

#' @title Bitwise Logical Operations
#' @description Logical operations on integer vectors with elements viewed as sets of bits.
#' As soon as an integer64 vector is involved, the operations are performed using integer64
#' semantics. Otherwise the base package functions are called.
#' @inheritParams base::bitwAnd
#' @inheritParams base::bitShiftL
#' @return
#' An integer64 vector of length the longer of the arguments, or zero length if one is zero-length.
#'
#' @seealso [bitwAnd][base::bitwAnd], [bitwOr][base::bitwOr], [bitwXor][base::bitwXor],
#' [bitwNot][base::bitwNot], [bitwShiftL][base::bitwShiftL], [bitwShiftR][base::bitwShiftR]
#' @examples
#' x <- as.integer64(1:5)
#' y <- c(1L, 3L, 5L, 7L)
#' bitwAnd(x, y)
#' bitwOr(x, y)
#' bitwXor(x, y)
#' bitwNot(x)
#' bitwShiftL(x, 1L)
#' bitwShiftR(x, 1L)
#'
#' @export
#' @name bitwise
#' @rdname bitwise
bitwNot = function(a) {
if (!is.integer64(a))
return(base::bitwNot(a))

ret = .Call(C_bitwNot_integer64, a, double(length(a)))
oldClass(ret) = "integer64"
ret
}

#' @export
#' @rdname bitwise
bitwAnd = function(a, b) {
if (!(is.integer64(a) || is.integer64(b)))
return(base::bitwAnd(a, b))

if (is.factor(a) || inherits(a, "POSIXct") || inherits(a, "Date"))
a = as.integer(a)
if (is.factor(b) || inherits(b, "POSIXct") || inherits(b, "Date"))
b = as.integer(b)

if (!is.numeric(a) || !is.numeric(b))
stop("'a' and 'b' must have the same type", domain="R")

if (!is.integer64(a) && !is.integer(a))
a = as.integer64(a)
if (!is.integer64(b) && !is.integer(b))
b = as.integer64(b)

l1 = length(a)
l2 = length(b)
l = if (l1 == 0L || l2 == 0L) 0L else max(l1, l2)
ret = .Call(C_bitwAnd_integer64, a, b, double(l))
oldClass(ret) = "integer64"
ret
}

#' @export
#' @rdname bitwise
bitwOr = function(a, b) {
if (!(is.integer64(a) || is.integer64(b)))
return(base::bitwOr(a, b))

if (is.factor(a) || inherits(a, "POSIXct") || inherits(a, "Date"))
a = as.integer(a)
if (is.factor(b) || inherits(b, "POSIXct") || inherits(b, "Date"))
b = as.integer(b)

if (!is.numeric(a) || !is.numeric(b))
stop("'a' and 'b' must have the same type", domain="R")

if (!is.integer64(a) && !is.integer(a))
a = as.integer64(a)
if (!is.integer64(b) && !is.integer(b))
b = as.integer64(b)

l1 = length(a)
l2 = length(b)
l = if (l1 == 0L || l2 == 0L) 0L else max(l1, l2)
ret = .Call(C_bitwOr_integer64, a, b, double(l))
oldClass(ret) = "integer64"
ret
}

#' @export
#' @rdname bitwise
bitwXor = function(a, b) {
if (!(is.integer64(a) || is.integer64(b)))
return(base::bitwXor(a, b))

if (is.factor(a) || inherits(a, "POSIXct") || inherits(a, "Date"))
a = as.integer(a)
if (is.factor(b) || inherits(b, "POSIXct") || inherits(b, "Date"))
b = as.integer(b)

if (!is.numeric(a) || !is.numeric(b))
stop("'a' and 'b' must have the same type", domain="R")

if (!is.integer64(a) && !is.integer(a))
a = as.integer64(a)
if (!is.integer64(b) && !is.integer(b))
b = as.integer64(b)

l1 = length(a)
l2 = length(b)
l = if (l1 == 0L || l2 == 0L) 0L else max(l1, l2)
ret = .Call(C_bitwXor_integer64, a, b, double(l))
oldClass(ret) = "integer64"
ret
}

#' @export
#' @rdname bitwise
bitwShiftL = function(a, n) {
if (!(is.integer64(a) || is.integer64(n)))
return(base::bitwShiftL(a, n))
if (!is.integer64(a))
return(base::bitwShiftL(a, as.integer(n)))

if (!is.integer64(n))
n = as.integer(n)

l1 = length(a)
l2 = length(n)
l = if (l1 == 0L || l2 == 0L) 0L else max(l1, l2)
ret = .Call(C_bitwShiftL_integer64, a, n, double(l))
oldClass(ret) = "integer64"
ret
}

#' @export
#' @rdname bitwise
bitwShiftR = function(a, n) {
if (!(is.integer64(a) || is.integer64(n)))
return(base::bitwShiftR(a, n))
if (!is.integer64(a))
return(base::bitwShiftR(a, as.integer(n)))

if (!is.integer64(n))
n = as.integer(n)

l1 = length(a)
l2 = length(n)
l = if (l1 == 0L || l2 == 0L) 0L else max(l1, l2)
ret = .Call(C_bitwShiftR_integer64, a, n, double(l))
oldClass(ret) = "integer64"
ret
}
52 changes: 52 additions & 0 deletions man/bitwise.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading