Learn R Programming

bit64 (version 4.5.2)

bit64-package: A S3 class for vectors of 64bit integers

Description

Package 'bit64' provides fast serializable S3 atomic 64bit (signed) integers that can be used in vectors, matrices, arrays and data.frames. Methods are available for coercion from and to logicals, integers, doubles, characters and factors as well as many elementwise and summary functions.
Version 0.8 With 'integer64' vectors you can store very large integers at the expense of 64 bits, which is by factor 7 better than 'int64' from package 'int64'. Due to the smaller memory footprint, the atomic vector architecture and using only S3 instead of S4 classes, most operations are one to three orders of magnitude faster: Example speedups are 4x for serialization, 250x for adding, 900x for coercion and 2000x for object creation. Also 'integer64' avoids an ongoing (potentially infinite) penalty for garbage collection observed during existence of 'int64' objects (see code in example section).
Version 0.9 Package 'bit64' - which extends R with fast 64-bit integers - now has fast (single-threaded) implementations the most important univariate algorithmic operations (those based on hashing and sorting). We now have methods for 'match', ' 'quantile', 'median' and 'summary'. Regarding data management we also have novel generics 'unipos' (positions of the unique values), 'tiepos' ( positions of ties), 'keypos' (positions of foreign keys in a sorted dimension table) and derived methods 'as.factor' and 'as.ordered'. This 64- bit functionality is implemented carefully to be not slower than the respective 32-bit operations in Base R and also to avoid outlying waiting times observed with 'order', 'rank' and 'table' (speedup factors 20/16/200 respective). This increases the dataset size with wich we can work truly interactive. The speed is achieved by simple heuristic optimizers in high- level functions choosing the best from multiple low-level algorithms and further taking advantage of a novel caching if activated. In an example R session using a couple of these operations the 64-bit integers performed 22x faster than base 32-bit integers, hash-caching improved this to 24x, sortorder-caching was most efficient with 38x (caching hashing and sorting is not worth it with 32x at duplicated RAM consumption).

Usage

integer64(length)
 # S3 method for integer64
is(x)
 # S3 method for integer64
length(x) <- value
 # S3 method for integer64
print(x, quote=FALSE, ...)
 # S3 method for integer64
str(object, vec.len  = strO$vec.len, give.head = TRUE, give.length = give.head, ...)

Value

integer64 returns a vector of 'integer64', i.e. a vector of double decorated with class 'integer64'.

Arguments

length

length of vector using integer

x

an integer64 vector

object

an integer64 vector

value

an integer64 vector of values to be assigned

quote

logical, indicating whether or not strings should be printed with surrounding quotes.

vec.len

see str

give.head

see str

give.length

see str

...

further arguments to the NextMethod

Design considerations

64 bit integers are related to big data: we need them to overcome address space limitations. Therefore performance of the 64 bit integer type is critical. In the S language -- designed in 1975 -- atomic objects were defined to be vectors for a couple of good reasons: simplicity, option for implicit parallelization, good cache locality. In recent years many analytical databases have learnt that lesson: column based data bases provide superior performance for many applications, the result are products such as MonetDB, Sybase IQ, Vertica, Exasol, Ingres Vectorwise. If we introduce 64 bit integers not natively in Base R but as an external package, we should at least strive to make them as 'basic' as possible. Therefore the design choice of bit64 not only differs from int64, it is obvious: Like the other atomic types in Base R, we model data type 'integer64' as a contiguous atomic vector in memory, and we use the more basic S3 class system, not S4. Like package int64 we want our 'integer64' to be serializeable, therefore we also use an existing data type as the basis. Again the choice is obvious: R has only one 64 bit data type: doubles. By using doubles, integer64 inherits some functionality such as is.atomic, length, length<-, names, names<-, dim, dim<-, dimnames, dimnames.
Our R level functions strictly follow the functional programming paragdim: no modification of arguments or other side-effects. Before version 0.93 we internally deviated from the strict paradigm in order to boost performance. Our C functions do not create new return values, instead we pass-in the memory to be returned as an argument. This gives us the freedom to apply the C-function to new or old vectors, which helps to avoid unnecessary memory allocation, unnecessary copying and unnecessary garbage collection. Prior to 0.93 within our R functions we also deviated from conventional R programming by not using attr<- and attributes<- because they always did new memory allocation and copying in older R versions. If we wanted to set attributes of return values that we have freshly created, we instead used functions setattr and setattributes from package bit. From version 0.93 setattr is only used for manipulating cache objects, in ramsort.integer64 and sort.integer64 and in as.data.frame.integer64.

Arithmetic precision and coercion

The fact that we introduce 64 bit long long integers -- without introducing 128-bit long doubles -- creates some subtle challenges: Unlike 32 bit integers, the integer64 are no longer a proper subset of double. If a binary arithmetic operation does involve a double and a integer, it is a no-brainer to return double without loss of information. If an integer64 meets a double, it is not trivial what type to return. Switching to integer64 limits our ability to represent very large numbers, switching to double limits our ability to distinguish x from x+1. Since the latter is the purpose of introducing 64 bit integers, we usually return integer64 from functions involving integer64, for example in c, cbind and rbind.
Different from Base R, our operators +, -, %/% and %% coerce their arguments to integer64 and always return integer64.
The multiplication operator * coerces its first argument to integer64 but allows its second argument to be also double: the second argument is internaly coerced to 'long double' and the result of the multiplication is returned as integer64.
The division / and power ^ operators also coerce their first argument to integer64 and coerce internally their second argument to 'long double', they return as double, like sqrt, log, log2 and log10 do.

argument1opargument2->coerced1opcoerced2->result
integer64+double->integer64+integer64->integer64
double+integer64->integer64+integer64->integer64
integer64-double->integer64-integer64->integer64
double-integer64->integer64-integer64->integer64
integer64%/%double->integer64%/%integer64->integer64
double%/%integer64->integer64%/%integer64->integer64
integer64%%double->integer64%%integer64->integer64
double%%integer64->integer64%%integer64->integer64
integer64*double->integer64*long double->integer64
double*integer64->integer64*integer64->integer64
integer64/double->integer64/long double->double
double/integer64->integer64/long double->double
integer64^double->integer64/long double->double
double^integer64->integer64/long double->double

Creating and testing S3 class 'integer64'

Our creator function integer64 takes an argument length, creates an atomic double vector of this length, attaches an S3 class attribute 'integer64' to it, and that's it. We simply rely on S3 method dispatch and interpret those 64bit elements as 'long long int'.
is.double currently returns TRUE for integer64 and might return FALSE in a later release. Consider is.double to have undefined behavior and do query is.integer64 before querying is.double. The methods is.integer64 and is.vector both return TRUE for integer64. Note that we did not patch storage.mode and typeof, which both continue returning 'double' Like for 32 bit integer, mode returns 'numeric' and as.double) tries coercing to double). It is possible that 'integer64' becomes a vmode in package ff.
Further methods for creating integer64 are range which returns the range of the data type if calles without arguments, rep, seq.
For all available methods on integer64 vectors see the index below and the examples.

Index of implemented methods

creating,testing,printingsee alsodescription
NA_integer64_NA_integer_NA constant
integer64integercreate zero atomic vector
runif64runifcreate random vector
rep.integer64rep
seq.integer64seq
is.integer64is
is.integerinherited from Base R
is.vector.integer64is.vector
identical.integer64identical
length<-.integer64length<-
lengthinherited from Base R
names<-inherited from Base R
namesinherited from Base R
dim<-inherited from Base R
diminherited from Base R
dimnames<-inherited from Base R
dimnamesinherited from Base R
strinherited from Base R, does not print values correctly
print.integer64print
str.integer64str
coercing to integer64see also
descriptionas.integer64
genericas.integer64.bitstringas.bitstring
as.integer64.charactercharacter
as.integer64.doubledouble
as.integer64.integerinteger
as.integer64.integer64integer64
as.integer64.logicallogical
as.integer64.NULLNULL
coercing from integer64
see alsodescriptionas.list.integer64
as.listgenericas.bitstring
as.bitstringgenericas.bitstring.integer64
as.character.integer64
as.characteras.double.integer64
as.doubleas.integer.integer64
as.integeras.logical.integer64
as.logical
data structuressee alsodescription
c.integer64cvector concatenate
cbind.integer64cbindcolumn bind
rbind.integer64rbindrow bind
as.data.frame.integer64as.data.framecoerce atomic object to data.frame
data.frameinherited from Base R since we have coercion
subscriptingsee also
description[.integer64[
vector and array extract[<-.integer64[<-
vector and array assign[[.integer64[[
scalar extract[[<-.integer64[[<-
scalar assignbinary operators
see alsodescription+.integer64
+returns integer64-.integer64
-returns integer64*.integer64
*returns integer64^.integer64
^returns double/.integer64
/returns double%/%.integer64
%/%returns integer64%%.integer64
%%returns integer64
comparison operatorssee alsodescription
==.integer64==
!=.integer64!=
<.integer64<
<=.integer64<=
>.integer64>
>=.integer64>=
logical operatorssee also
description!.integer64!
&.integer64&
|.integer64|
xor.integer64xor
math functions
see alsodescriptionis.na.integer64
is.nareturns logicalformat.integer64
formatreturns characterabs.integer64
absreturns integer64sign.integer64
signreturns integer64log.integer64
logreturns doublelog10.integer64
log10returns doublelog2.integer64
log2returns doublesqrt.integer64
sqrtreturns doubleceiling.integer64
ceilingdummy returning its argumentfloor.integer64
floordummy returning its argumenttrunc.integer64
truncdummy returning its argumentround.integer64
rounddummy returning its argumentsignif.integer64
signifdummy returning its argument
cumulative functionssee alsodescription
cummin.integer64cummin
cummax.integer64cummax
cumsum.integer64cumsum
cumprod.integer64cumprod
diff.integer64diff
summary functionssee also
descriptionrange.integer64range
min.integer64min
max.integer64max
sum.integer64sum
mean.integer64mean
prod.integer64prod
all.integer64all
any.integer64any
algorithmically complex functions
see alsodescription (caching)match.integer64
matchposition of x in table (h//o/so)%in%.integer64
%in%is x in table? (h//o/so)duplicated.integer64
duplicatedis current element duplicate of previous one? (h//o/so)unique.integer64
unique(shorter) vector of unique values only (h/s/o/so)unipos.integer64
unipospositions corresponding to unique values (h/s/o/so)tiepos.integer64
tiepospositions of values that are tied (//o/so)keypos.integer64
keyposposition of current value in sorted list of unique values (//o/so)as.factor.integer64
as.factorconvert to (unordered) factor with sorted levels of previous values (//o/so)as.ordered.integer64
as.orderedconvert to ordered factor with sorted levels of previous values (//o/so)table.integer64
tableunique values and their frequencies (h/s/o/so)sort.integer64
sortsorted vector (/s/o/so)order.integer64
orderpositions of elements that would create sorted vector (//o/so)rank.integer64
rank(average) ranks of non-NAs, NAs kept in place (/s/o/so)quantile.integer64
quantile(existing) values at specified percentiles (/s/o/so)median.integer64
median(existing) value at percentile 0.5 (/s/o/so)summary.integer64
summary(/s/o/so)all.equal.integer64
all.equaltest if two objects are (nearly) equal (/s/o/so)
helper functionssee alsodescription
minusclassminusclassremoving class attritbute
plusclassplusclassinserting class attribute
binattrbinattrdefine binary op behaviour
tested I/O functionssee also
descriptionread.table
inherited from Base Rwrite.table
inherited from Base Rserialize
inherited from Base Runserialize
inherited from Base Rsave
inherited from Base Rload
inherited from Base Rdput
inherited from Base Rdget

Limitations inherited from implementing 64 bit integers via an external package

  • vector size of atomic vectors is still limited to .Machine$integer.max. However, external memory extending packages such as ff or bigmemory can extend their address space now with integer64. Having 64 bit integers also help with those not so obvious address issues that arise once we exchange data with SQL databases and datawarehouses, which use big integers as surrogate keys, e.g. on indexed primary key columns. This puts R into a relatively strong position compared to certain commercial statistical softwares, which sell database connectivity but neither have the range of 64 bit integers, nor have integers at all, nor have a single numeric data type in their macro-glue-language.

  • literals such as 123LL would require changes to Base R, up to then we need to write (and call) as.integer64(123L) or as.integer64(123) or as.integer64('123'). Only the latter allows to specify numbers beyond Base R's numeric data types and therefore is the recommended way to use -- using only one way may facilitate migrating code to literals at a later stage.

Limitations inherited from Base R, Core team, can you change this?

  • identical with default parameters does not distinguish all bit-patterns of doubles. For testing purposes we provide a wrapper identical.integer64 that will distinguish all bit-patterns. It would be desireable to have a single call of identical handle both, double and integer64.

  • the colon operator : officially does not dispatches S3 methods, however, we have made it generic

    
         from <- lim.integer64()[1]
         to <- from+99
         from:to
       

    As a limitation remains: it will only dispatch at its first argument from but not at its second to.

  • is.double does not dispatches S3 methods, However, we have made it generic and it will return FALSE on integer64.

  • c only dispatches c.integer64 if the first argument is integer64 and it does not recursively dispatch the proper method when called with argument recursive=TRUE Therefore

    
          c(list(integer64,integer64))
        

    does not work and for now you can only call

    
           c.integer64(list(x,x))
         
  • generic binary operators fail to dispatch *any* user-defined S3 method if the two arguments have two different S3 classes. For example we have two classes bit and bitwhich sparsely representing boolean vectors and we have methods &.bit and &.bitwhich. For an expression involving both as in bit & bitwhich, none of the two methods is dispatched. Instead a standard method is dispatched, which neither handles bit nor bitwhich. Although it lacks symmetry, the better choice would be to dispatch simply the method of the class of the first argument in case of class conflict. This choice would allow authors of extension packages providing coherent behaviour at least within their contributed classes. But as long as none of the package authors methods is dispatched, he cannot handle the conflicting classes at all.

  • unlist is not generic and if it were, we would face similar problems as with c()

  • vector with argument mode='integer64' cannot work without adjustment of Base R

  • as.vector with argument mode='integer64' cannot work without adjustment of Base R

  • is.vector does not dispatch its method is.vector.integer64

  • mode<- drops the class 'integer64' which is returned from as.integer64. Also it does not remove an existing class 'integer64' when assigning mode 'integer'.

  • storage.mode<- does not support external data types such as as.integer64

  • matrix does drop the 'integer64' class attribute.

  • array does drop the 'integer64' class attribute. In current R versions (1.15.1) this can be circumvented by activating the function as.vector.integer64 further down this file. However, the CRAN maintainer has requested to remove as.vector.integer64, even at the price of breaking previously working functionality of the package.

  • str does not print the values of integer64 correctly

further limitations

  • subscripting non-existing elements and subscripting with NAs is currently not supported. Such subscripting currently returns 9218868437227407266 instead of NA (the NA value of the underlying double code). Following the full R behaviour here would either destroy performance or require extensive C-coding.

Author

Jens Oehlschlägel <Jens.Oehlschlaegel@truecluster.com> Maintainer: Jens Oehlschlägel <Jens.Oehlschlaegel@truecluster.com>

Details

Package:bit64
Type:Package
Version:0.5.0
Date:2011-12-12
License:GPL-2
LazyLoad:yes
Encoding:latin1

See Also

integer in base R

Examples

Run this code
message("Using integer64 in vector")
x <- integer64(8)    # create 64 bit vector
x
is.atomic(x)         # TRUE
is.integer64(x)      # TRUE
is.numeric(x)        # TRUE
is.integer(x)        # FALSE - debatable
is.double(x)         # FALSE - might change
x[] <- 1:2           # assigned value is recycled as usual
x[1:6]               # subscripting as usual
length(x) <- 13      # changing length as usual
x
rep(x, 2)            # replicate as usual
seq(as.integer64(1), 10)     # seq.integer64 is dispatched on first given argument
seq(to=as.integer64(10), 1)  # seq.integer64 is dispatched on first given argument
seq.integer64(along.with=x)  # or call seq.integer64 directly
# c.integer64 is dispatched only if *first* argument is integer64 ...
x <- c(x,runif(length(x), max=100))
# ... and coerces everything to integer64 - including double
x
names(x) <- letters  # use names as usual
x

message("Using integer64 in array - note that 'matrix' currently does not work")
message("as.vector.integer64 removed as requested by the CRAN maintainer")
message("as consequence 'array' also does not work anymore")

message("we still can create a matrix or array by assigning 'dim'")
y <- rep(as.integer64(NA), 12)
dim(y) <- c(3,4)
dimnames(y) <- list(letters[1:3], LETTERS[1:4])
y["a",] <- 1:2       # assigning as usual
y
y[1:2,-4]            # subscripting as usual
# cbind.integer64 dispatched on any argument and coerces everything to integer64
cbind(E=1:3, F=runif(3, 0, 100), G=c("-1","0","1"), y)

message("Using integer64 in data.frame")
str(as.data.frame(x))
str(as.data.frame(y))
str(data.frame(y))
str(data.frame(I(y)))
d <- data.frame(x=x, y=runif(length(x), 0, 100))
d
d$x

message("Using integer64 with csv files")
fi64 <- tempfile()
write.csv(d, file=fi64, row.names=FALSE)
e <- read.csv(fi64, colClasses=c("integer64", NA))
unlink(fi64)
str(e)
identical.integer64(d$x,e$x)

message("Serializing and unserializing integer64")
dput(d, fi64)
e <- dget(fi64)
identical.integer64(d$x,e$x)
e <- d[,]
save(e, file=fi64)
rm(e)
load(file=fi64)
identical.integer64(d,e)

### A couple of unit tests follow hidden in a dontshow{} directive ###
  # \dontshow{
message("Testing identical.integer64")
i64 <- as.double(NA); class(i64) <- "integer64"
stopifnot(identical(unclass(i64-1), unclass(i64+1)))
stopifnot(identical(i64-1, i64+1))
stopifnot(!identical.integer64(i64-1, i64+1))

message("Testing dispatch of 'c' method")
stopifnot(identical.integer64(c(integer64(0), NA), as.integer64(NA)))
message("Dispatch on the second argument fails and we want to be notified once that changes")
stopifnot(!identical.integer64(c(NA, integer64(0)), as.integer64(NA)))

message("Testing minus and plus")
d64 <- c(-.Machine$double.base^.Machine$double.digits, -.Machine$integer.max, -1, 0, 1, .Machine$integer.max, .Machine$double.base^.Machine$double.digits)
i64 <- as.integer64(d64)
stopifnot(identical.integer64(i64-1+1,i64))
stopifnot(identical.integer64(i64+1-1,i64))

message("Testing minus and plus edge cases and 'rev'\nUBSAN signed integer overflow expected for type 'long long int'\nThis is a false UBSAN alarm because overflow is detected and NA returned")
stopifnot(identical.integer64(lim.integer64()+1-1, c(lim.integer64()[1], NA)))
stopifnot(identical.integer64(rev(lim.integer64())-1+1, c(lim.integer64()[2], NA)))

message("Testing 'range.integer64', multiplication and integer division")
i64 <- integer64(63)
i64[1] <- 1
for (i in 2:63)
	i64[i] <- 2*i64[i-1]
stopifnot(identical.integer64(i64 * rev(i64), rep(i64[63], 63)))
for (i in 63:2)
	i64[i-1] <- i64[i]%/%2
stopifnot(identical.integer64(i64 * rev(i64), rep(i64[63], 63)))
for (i in 63:2)
	i64[i-1] <- i64[i]/2
stopifnot(identical.integer64(i64 * rev(i64), rep(i64[63], 63)))
stopifnot(identical.integer64(c( -i64[63] - (i64[63]-1), i64[63]+(i64[63]-1) ), lim.integer64()))

stopifnot(identical.integer64(i64[-1]%/%2*as.integer64(2), i64[-1]))
stopifnot(identical.integer64(i64[-1]%/%2L*as.integer64(2), i64[-1]))
stopifnot(identical.integer64(i64[-1]/2*as.integer64(2), i64[-1]))
stopifnot(identical.integer64(i64[-1]/2*as.integer64(2), i64[-1]))

stopifnot(identical.integer64(i64[-63]*2%/%2, i64[-63]))
stopifnot(identical.integer64(i64[-63]*2L%/%2L, i64[-63]))
stopifnot(identical.integer64(as.integer64(i64[-63]*2/2), i64[-63]))
stopifnot(identical.integer64(as.integer64(i64[-63]*2L/2L), i64[-63]))

message("Testing sqrt, power and log")
stopifnot(identical.integer64( as.integer64(sqrt(i64[-1][c(FALSE, TRUE)])*sqrt(i64[-1][c(FALSE, TRUE)])), i64[-1][c(FALSE, TRUE)] ))

stopifnot(identical.integer64(as.integer64(2)^(0:62), i64))
stopifnot(identical.integer64(as.integer64(0:62), as.integer64(round(log2(i64)))))
stopifnot(identical.integer64(as.integer64(round(log(as.integer64(2)^(0:62), 2))), as.integer64(0:62)))
stopifnot(identical.integer64(as.integer64(round(log(as.integer64(3)^(0:39), 3))), as.integer64(0:39)))
stopifnot(identical.integer64(as.integer64(round(log(as.integer64(10)^(0:18), 10))), as.integer64(0:18)))
stopifnot(identical.integer64(as.integer64(round(log10(as.integer64(10)^(0:18)))), as.integer64(0:18)))

stopifnot(identical.integer64((as.integer64(2)^(1:62))^(1/1:62), as.integer64(rep(2, 62))))
stopifnot(identical.integer64((as.integer64(3)^(1:39))^(1/1:39), as.integer64(rep(3, 39))))
stopifnot(identical.integer64((as.integer64(10)^(1:18))^(1/1:18), as.integer64(rep(10, 18))))

message("Testing c and rep")
stopifnot(identical.integer64( as.integer64(rep(1:3, 1:3)), rep(as.integer64(1:3), 1:3)))
stopifnot(identical.integer64( as.integer64(rep(1:3, 3)), rep(as.integer64(1:3), 3)))

x <- as.double(c(NA,NA,NA))
class(x) <- "integer64"
x <- x + -1:1
stopifnot(identical.integer64(rep(x, 3), c(x,x,x) ))
stopifnot(identical.integer64(c.integer64(list(x,x,x), recursive=TRUE), c(x,x,x) ))

message("Testing seq")
stopifnot(identical.integer64(seq(as.integer64(1), 10, 2), as.integer64(seq(1, 10, 2)) ))
stopifnot(identical.integer64(seq(as.integer64(1), by=2, length.out=5), as.integer64(seq(1, by=2, length.out=5)) ))
stopifnot(identical.integer64(seq(as.integer64(1), by=2, length.out=6), as.integer64(seq(1, by=2, length.out=6)) ))
stopifnot(identical.integer64(seq.integer64(along.with=3:5), as.integer64(seq(along.with=3:5)) ))
stopifnot(identical.integer64(seq(as.integer64(1), to=-9), as.integer64(seq(1, to=-9)) ))

message("Testing cbind and rbind")
stopifnot(identical.integer64( cbind(as.integer64(1:3), 1:3), {x <- rep(as.integer64(1:3), 2); dim(x)<-c(3,2);x}))
stopifnot(identical.integer64( rbind(as.integer64(1:3), 1:3), t({x <- rep(as.integer64(1:3), 2); dim(x)<-c(3,2);x})))

message("Testing coercion")
stopifnot(identical( as.double(as.integer64(c(NA, seq(0, 9, 0.25)))), as.double(as.integer(c(NA, seq(0, 9, 0.25))))))
stopifnot(identical( as.character(as.integer64(c(NA, seq(0, 9, 0.25)))), as.character(as.integer(c(NA, seq(0, 9, 0.25))))))
stopifnot(identical( as.integer(as.integer64(c(NA, seq(0, 9, 0.25)))), as.integer(c(NA, seq(0, 9, 0.25)))))
stopifnot(identical( as.logical(as.integer64(c(NA, seq(0, 9, 0.25)))), as.logical(as.integer(c(NA, seq(0, 9, 0.25))))))
stopifnot(identical( as.integer(as.integer64(c(NA, FALSE, TRUE))), as.integer(c(NA, FALSE, TRUE))))
stopifnot(identical( as.integer64(as.integer(as.integer64(-9:9))), as.integer64(-9:9)))
stopifnot(identical( as.integer64(as.double(as.integer64(-9:9))), as.integer64(-9:9)))
stopifnot(identical( as.integer64(as.character(as.integer64(-9:9))), as.integer64(-9:9)))
stopifnot(identical( as.integer64(as.character(lim.integer64())), lim.integer64()))

message("-- testing logical operators --")
stopifnot(identical.integer64(!c(NA, -1:1), !c(as.integer64(NA), -1:1)))
stopifnot(identical.integer64(rep(c(NA, -1:1), 4)&rep(c(NA, -1:1), rep(4, 4)), as.integer64(rep(c(NA, -1:1), 4))&as.integer64(rep(c(NA, -1:1), rep(4, 4)))))
stopifnot(identical.integer64(rep(c(NA, -1:1), 4)|rep(c(NA, -1:1), rep(4, 4)), as.integer64(rep(c(NA, -1:1), 4))|as.integer64(rep(c(NA, -1:1), rep(4, 4)))))
stopifnot(identical.integer64(xor(rep(c(NA, -1:1), 4),rep(c(NA, -1:1), rep(4, 4))), xor(as.integer64(rep(c(NA, -1:1), 4)),as.integer64(rep(c(NA, -1:1), rep(4, 4))))))

message("-- testing comparison operators --")
stopifnot(identical.integer64(rep(c(NA, -1:1), 4)==rep(c(NA, -1:1), rep(4, 4)), as.integer64(rep(c(NA, -1:1), 4))==as.integer64(rep(c(NA, -1:1), rep(4, 4)))))
stopifnot(identical.integer64(rep(c(NA, -1:1), 4)!=rep(c(NA, -1:1), rep(4, 4)), as.integer64(rep(c(NA, -1:1), 4))!=as.integer64(rep(c(NA, -1:1), rep(4, 4)))))
stopifnot(identical.integer64(rep(c(NA, -1:1), 4)>rep(c(NA, -1:1), rep(4, 4)), as.integer64(rep(c(NA, -1:1), 4))>as.integer64(rep(c(NA, -1:1), rep(4, 4)))))
stopifnot(identical.integer64(rep(c(NA, -1:1), 4)>=rep(c(NA, -1:1), rep(4, 4)), as.integer64(rep(c(NA, -1:1), 4))>=as.integer64(rep(c(NA, -1:1), rep(4, 4)))))
stopifnot(identical.integer64(rep(c(NA, -1:1), 4)

Run the code above in your browser using DataLab