# /*
# R-Code
# S3 atomic 64bit integers for R
# (c) 2011 Jens Oehlschägel
# Licence: GPL2
# Provided 'as is', use at your own risk
# Created: 2011-12-11
# Last changed:  2011-12-11
#*/

#! \name{bit64-package}
#! \alias{bit64-package}
#! \alias{bit64}
#! \alias{integer64}
#! \alias{is.integer64}
#! \alias{is.integer.integer64}
#! \alias{is.vector.integer64}
#! %as.vector.integer64 removed as requested by the CRAN maintainer \alias{as.vector.integer64}
#! \alias{length<-.integer64}
#! \alias{print.integer64}
#! \alias{str.integer64}
#! \docType{package}
#! \title{
#!    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. 
#! \cr
#! \bold{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). 
#! \cr
#! \bold{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', '%in%', 'duplicated', 'unique', 'table', 'sort', 'order', 'rank', 
#! '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)
#!  \method{is}{integer64}(x)
#!  \method{length}{integer64}(x) <- value
#!  \method{print}{integer64}(x, quote=FALSE, \dots)
#!  \method{str}{integer64}(object, vec.len  = strO$vec.len, give.head = TRUE, give.length = give.head, \dots)
#! }
#! \arguments{
#!   \item{length}{ length of vector using \code{\link{integer}} }
#!   \item{x}{ an integer64 vector }
#!   \item{object}{ an integer64 vector }
#!   \item{value}{ an integer64 vector of values to be assigned }
#!   \item{quote}{ logical, indicating whether or not strings should be printed with surrounding quotes. }
#!   \item{vec.len}{ see \code{\link[utils]{str}} }
#!   \item{give.head}{ see \code{\link[utils]{str}} }
#!   \item{give.length}{ see \code{\link[utils]{str}} }
#!   \item{\dots}{ further arguments to the \code{\link{NextMethod}} }
#! }
#! \details{
#! \tabular{ll}{
#!    Package: \tab bit64\cr
#!    Type: \tab Package\cr
#!    Version: \tab 0.5.0\cr
#!    Date: \tab 2011-12-12\cr
#!    License: \tab GPL-2\cr
#!    LazyLoad: \tab yes\cr
#!    Encoding: \tab latin1\cr
#! }
#! }
#! \section{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 \code{int64}, it is obvious: 
#!   Like the other atomic types in Base R, we model data type 'integer64' as a contiguous \code{\link{atomic}} vector in memory, 
#!   and we use the more basic \code{\link{S3}} class system, not \code{\link{S4}}. Like package \code{int64} we want our 'integer64' to be \code{\link{serialize}able}, 
#!   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 \code{\link{double}s}, \code{integer64} \code{\link{inherits}} some functionality such as \code{\link{is.atomic}}, \code{\link{length}}, 
#!   \code{\link{length<-}}, \code{\link{names}}, \code{\link{names<-}}, \code{\link{dim}}, \code{\link{dim<-}}, \code{\link{dimnames}}, \code{\link{dimnames}}.
#!   \cr
#!   Our R level functions strictly follow the functional programming paragdim: 
#!   no modification of arguments or other sideffects. 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 unnessary garbage collection.
#!   Prior to 0.93 \emph{within} our R functions we also deviated from conventional R programming by not using \code{\link{attr<-}} and \code{\link{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 \code{\link[bit:getsetattr]{setattr}} and \code{\link[bit:getsetattr]{setattributes}} from package \code{\link[bit]{bit}}. 
#!   From version 0.93 \code{\link[bit:getsetattr]{setattr}} is only used for manipulating \code{\link{cache}} objects, in \code{\link{ramsort.integer64}} and \code{\link{sort.integer64}} and in \code{\link{as.data.frame.integer64}}.
#! }
#! \section{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 \code{\link{integer}s}, the \code{integer64} are no longer a proper subset of \code{\link{double}}. 
#!   If a binary arithmetic operation does involve a \code{double} and a \code{integer}, it is a no-brainer to return \code{double} 
#!   without loss of information. If an \code{integer64} meets a \code{double}, it is not trivial what type to return. 
#!   Switching to \code{integer64} limits our ability to represent very large numbers, switching to \code{double} limits our ability 
#!   to distinguish \code{x} from \code{x+1}. Since the latter is the purpose of introducing 64 bit integers, we usually return \code{integer64} 
#!   from functions involving \code{integer64}, for example in \code{\link[=c.integer64]{c}}, \code{\link[=cbind.integer64]{cbind}} 
#!   and \code{\link[=rbind.integer64]{rbind}}. 
#!   \cr
#!   Different from Base R, our operators \code{\link[=+.integer64]{+}}, 
#!   \code{\link[=-.integer64]{-}}, \code{\link[=\%/\%.integer64]{\%/\%}} and \code{\link[=\%\%.integer64]{\%\%}} coerce their arguments to 
#!   \code{integer64} and always return \code{integer64}. 
#!   \cr
#!   The multiplication operator \code{\link[=*.integer64]{*}} coerces its first argument to \code{integer64} 
#!   but allows its second argument to be also \code{double}: the second argument is internaly coerced to 'long double' 
#!   and the result of the multiplication is returned as \code{integer64}. 
#!   \cr
#!   The division \code{\link[=/.integer64]{/}} and power \code{\link[=^.integer64]{^}} operators also coerce their first argument to \code{integer64} 
#!   and coerce internally their second argument to 'long double', they return as \code{double}, like \code{\link[=sqrt.integer64]{sqrt}}, 
#!   \code{\link[=log.integer64]{log}}, \code{\link[=log2.integer64]{log2}} and \code{\link[=log10.integer64]{log10}} do. 
#!
#!  \tabular{ccccccccc}{
#!   \bold{argument1} \tab \bold{op} \tab \bold{argument2} \tab \bold{->} \tab \bold{coerced1} \tab \bold{op} \tab \bold{coerced2} \tab \bold{->} \tab \bold{result} \cr
#!   integer64 \tab + \tab double \tab -> \tab integer64 \tab + \tab integer64 \tab -> \tab integer64 \cr
#!   double \tab + \tab integer64 \tab -> \tab integer64 \tab + \tab integer64 \tab -> \tab integer64 \cr
#!   integer64 \tab - \tab double \tab -> \tab integer64 \tab - \tab integer64 \tab -> \tab integer64 \cr
#!   double \tab - \tab integer64 \tab -> \tab integer64 \tab - \tab integer64 \tab -> \tab integer64 \cr
#!   integer64 \tab \%/\% \tab double \tab -> \tab integer64 \tab \%/\% \tab integer64 \tab -> \tab integer64 \cr
#!   double \tab \%/\% \tab integer64 \tab -> \tab integer64 \tab \%/\% \tab integer64 \tab -> \tab integer64 \cr
#!   integer64 \tab \%\% \tab double \tab -> \tab integer64 \tab \%\% \tab integer64 \tab -> \tab integer64 \cr
#!   double \tab \%\% \tab integer64 \tab -> \tab integer64 \tab \%\% \tab integer64 \tab -> \tab integer64 \cr
#!   integer64 \tab * \tab double \tab -> \tab integer64 \tab * \tab long double \tab -> \tab integer64 \cr
#!   double \tab * \tab integer64 \tab -> \tab integer64 \tab * \tab integer64 \tab -> \tab integer64 \cr
#!   integer64 \tab / \tab double \tab -> \tab integer64 \tab / \tab long double \tab -> \tab double \cr
#!   double \tab / \tab integer64 \tab -> \tab integer64 \tab / \tab long double \tab -> \tab double \cr
#!   integer64 \tab ^ \tab double \tab -> \tab integer64 \tab / \tab long double \tab -> \tab double \cr
#!   double \tab ^ \tab integer64 \tab -> \tab integer64 \tab / \tab long double \tab -> \tab double \cr
#!  }
#! }
#! \section{Creating and testing S3 class 'integer64'}{
#!   Our creator function \code{integer64} takes an argument \code{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'. 
#!   \cr
#!  \code{\link{is.double}} currently returns TRUE for \code{integer64} and might return FALSE in a later release.
#!  Consider \code{is.double} to have undefined behaviour and do query \code{is.integer64} \emph{before} querying \code{is.double}.
#! %As a second line of defense against misinterpretation we make \code{\link{is.double}}
#! %return \code{FALSE} by making it S3 generic and adding a method \code{\link{as.double.integer64}}. 
#!   The methods \code{\link{is.integer64}} and \code{\link{is.vector}} both return \code{TRUE} for \code{integer64}. 
#!  Note that we did not patch \code{\link{storage.mode}} and \code{\link{typeof}}, which both continue returning 'double' 
#!  Like for 32 bit \code{\link{integer}}, \code{\link{mode}} returns 'numeric' and \code{\link{as.double}}) tries coercing to \code{\link{double}}).
#!  It is possible that 'integer64' becomes a \code{vmode} in package \code{ff}. 
#!  \cr
#!  Further methods for creating \code{integer64} are \code{\link[=range.integer64]{range}} which returns the range of the data type if calles without arguments,
#!  \code{\link[=rep.integer64]{rep}}, \code{\link[=seq.integer64]{seq}}. 
#!  \cr
#!  For all available methods on \code{integer64} vectors see the index below and the examples.
#! }
#! \section{Index of implemented methods}{
#! \tabular{rrl}{
#!    \bold{creating,testing,printing} \tab \bold{see also}          \tab \bold{description} \cr
#!    \code{NA_integer64_} \tab \code{\link{NA_integer_}} \tab NA constant \cr
#!    \code{integer64} \tab \code{\link{integer}} \tab create zero atomic vector \cr
#!    \code{\link{runif64}} \tab \code{\link{runif}} \tab create random vector \cr
#!    \code{\link{rep.integer64}} \tab \code{\link{rep}} \tab  \cr
#!    \code{\link{seq.integer64}} \tab \code{\link{seq}} \tab  \cr
#!    \code{\link{is.integer64}} \tab \code{\link{is}} \tab  \cr
#!                                      \tab \code{\link{is.integer}} \tab inherited from Base R \cr
#!    %\code{\link{is.double.integer64}} \tab \code{\link{is.double}} \tab  \cr
#!    \code{\link{is.vector.integer64}} \tab \code{\link{is.vector}} \tab  \cr
#!    \code{\link{identical.integer64}} \tab \code{\link{identical}} \tab  \cr
#!    \code{\link{length<-.integer64}} \tab \code{\link{length<-}} \tab  \cr
#!                                      \tab \code{\link{length}} \tab inherited from Base R \cr
#!                                      \tab \code{\link{names<-}} \tab inherited from Base R \cr
#!                                      \tab \code{\link{names}} \tab inherited from Base R \cr
#!                                      \tab \code{\link{dim<-}} \tab inherited from Base R \cr
#!                                      \tab \code{\link{dim}} \tab inherited from Base R \cr
#!                                      \tab \code{\link{dimnames<-}} \tab inherited from Base R \cr
#!                                      \tab \code{\link{dimnames}} \tab inherited from Base R \cr
#!                                     \tab \code{\link{str}} \tab inherited from Base R, does not print values correctly \cr
#!    \code{\link{print.integer64}} \tab \code{\link{print}} \tab  \cr
#!    \code{\link{str.integer64}} \tab \code{\link{str}} \tab  \cr
#!  \cr
#!    \bold{coercing to integer64} \tab \bold{see also}          \tab \bold{description} \cr
#!    \code{\link{as.integer64}} \tab   \tab generic \cr
#!    \code{\link{as.integer64.bitstring}} \tab \code{\link{as.bitstring}} \tab  \cr
#!    \code{\link{as.integer64.character}} \tab \code{\link{character}} \tab  \cr
#!    \code{\link{as.integer64.double}} \tab \code{\link{double}} \tab  \cr
#!    \code{\link{as.integer64.integer}} \tab \code{\link{integer}} \tab  \cr
#!    \code{\link{as.integer64.integer64}} \tab \code{integer64} \tab  \cr
#!    \code{\link{as.integer64.logical}} \tab \code{\link{logical}} \tab  \cr
#!    \code{\link{as.integer64.NULL}} \tab \code{\link{NULL}} \tab  \cr
#!  \cr
#!    \bold{coercing from integer64} \tab \bold{see also}          \tab \bold{description} \cr
#!    \code{\link{as.bitstring}} \tab \code{\link{as.bitstring}} \tab generic \cr
#!    \code{\link{as.bitstring.integer64}} \tab  \tab  \cr
#!    \code{\link{as.character.integer64}} \tab \code{\link{as.character}} \tab  \cr
#!    \code{\link{as.double.integer64}} \tab \code{\link{as.double}} \tab  \cr
#!    \code{\link{as.integer.integer64}} \tab \code{\link{as.integer}} \tab  \cr
#!    \code{\link{as.logical.integer64}} \tab \code{\link{as.logical}} \tab  \cr
#!    %as.vector.integer64 removed as requested by the CRAN maintainer \code{\link{as.vector.integer64}} \tab \code{\link{as.vector}} \tab  \cr
#!  \cr
#!    \bold{data structures} \tab \bold{see also}          \tab \bold{description} \cr
#!    \code{\link{c.integer64}} \tab \code{\link{c}} \tab vector concatenate \cr
#!    \code{\link{cbind.integer64}} \tab \code{\link{cbind}} \tab column bind \cr
#!    \code{\link{rbind.integer64}} \tab \code{\link{rbind}} \tab row bind \cr
#!    \code{\link{as.data.frame.integer64}} \tab \code{\link{as.data.frame}} \tab coerce atomic object to data.frame \cr
#!                                          \tab \code{\link{data.frame}} \tab inherited from Base R since we have coercion \cr
#!  \cr
#!    \bold{subscripting} \tab \bold{see also}          \tab \bold{description} \cr
#!    \code{\link{[.integer64}} \tab \code{\link{[}} \tab vector and array extract \cr
#!    \code{\link{[<-.integer64}} \tab \code{\link{[<-}} \tab vector and array assign \cr
#!    \code{\link{[[.integer64}} \tab \code{\link{[[}} \tab scalar extract \cr
#!    \code{\link{[[<-.integer64}} \tab \code{\link{[[<-}} \tab scalar assign \cr
#!  \cr
#!    \bold{binary operators} \tab \bold{see also}          \tab \bold{description} \cr
#!    \code{\link{+.integer64}} \tab \code{\link{+}} \tab returns integer64 \cr
#!    \code{\link{-.integer64}} \tab \code{\link{-}} \tab returns integer64 \cr
#!    \code{\link{*.integer64}} \tab \code{\link{*}} \tab returns integer64 \cr
#!    \code{\link{^.integer64}} \tab \code{\link{^}} \tab returns double \cr
#!    \code{\link{/.integer64}} \tab \code{\link{/}} \tab returns double \cr
#!    \code{\link{\%/\%.integer64}} \tab \code{\link{\%/\%}} \tab returns integer64 \cr
#!    \code{\link{\%\%.integer64}} \tab \code{\link{\%\%}} \tab returns integer64 \cr
#!  \cr
#!    \bold{comparison operators} \tab \bold{see also}          \tab \bold{description} \cr
#!    \code{\link{==.integer64}} \tab \code{\link{==}} \tab  \cr
#!    \code{\link{!=.integer64}} \tab \code{\link{!=}} \tab  \cr
#!    \code{\link{<.integer64}} \tab \code{\link{<}} \tab  \cr
#!    \code{\link{<=.integer64}} \tab \code{\link{<=}} \tab  \cr
#!    \code{\link{>.integer64}} \tab \code{\link{>}} \tab  \cr
#!    \code{\link{>=.integer64}} \tab \code{\link{>=}} \tab  \cr
#!  \cr
#!    \bold{logical operators} \tab \bold{see also}          \tab \bold{description} \cr
#!    \code{\link{!.integer64}} \tab \code{\link{!}} \tab  \cr
#!    \code{\link{&.integer64}} \tab \code{\link{&}} \tab  \cr
#!    \code{\link{|.integer64}} \tab \code{\link{|}} \tab  \cr
#!    \code{\link{xor.integer64}} \tab \code{\link{xor}} \tab  \cr
#!  \cr
#!    \bold{math functions} \tab \bold{see also}          \tab \bold{description} \cr
#!    \code{\link{is.na.integer64}} \tab \code{\link{is.na}} \tab returns logical \cr
#!    \code{\link{format.integer64}} \tab \code{\link{format}} \tab returns character \cr
#!    \code{\link{abs.integer64}} \tab \code{\link{abs}} \tab returns integer64 \cr
#!    \code{\link{sign.integer64}} \tab \code{\link{sign}} \tab returns integer64 \cr
#!    \code{\link{log.integer64}} \tab \code{\link{log}} \tab returns double \cr
#!    \code{\link{log10.integer64}} \tab \code{\link{log10}} \tab  returns double \cr
#!    \code{\link{log2.integer64}} \tab \code{\link{log2}} \tab  returns double \cr
#!    \code{\link{sqrt.integer64}} \tab \code{\link{sqrt}} \tab  returns double \cr
#!    \code{\link{ceiling.integer64}} \tab \code{\link{ceiling}} \tab dummy returning its argument \cr
#!    \code{\link{floor.integer64}} \tab \code{\link{floor}} \tab dummy returning its argument \cr
#!    \code{\link{trunc.integer64}} \tab \code{\link{trunc}} \tab dummy returning its argument \cr
#!    \code{\link{round.integer64}} \tab \code{\link{round}} \tab dummy returning its argument \cr
#!    \code{\link{signif.integer64}} \tab \code{\link{signif}} \tab dummy returning its argument \cr
#!  \cr
#!    \bold{cumulative functions} \tab \bold{see also}          \tab \bold{description} \cr
#!    \code{\link{cummin.integer64}} \tab \code{\link{cummin}} \tab \cr
#!    \code{\link{cummax.integer64}} \tab \code{\link{cummax}} \tab \cr
#!    \code{\link{cumsum.integer64}} \tab \code{\link{cumsum}} \tab \cr
#!    \code{\link{cumprod.integer64}} \tab \code{\link{cumprod}} \tab \cr
#!    \code{\link{diff.integer64}} \tab \code{\link{diff}} \tab \cr
#!  \cr
#!    \bold{summary functions} \tab \bold{see also}          \tab \bold{description} \cr
#!    \code{\link{range.integer64}} \tab \code{\link{range}} \tab \cr
#!    \code{\link{min.integer64}} \tab \code{\link{min}} \tab  \cr
#!    \code{\link{max.integer64}} \tab \code{\link{max}} \tab  \cr
#!    \code{\link{sum.integer64}} \tab \code{\link{sum}} \tab  \cr
#!    \code{\link{mean.integer64}} \tab \code{\link{mean}} \tab  \cr
#!    \code{\link{prod.integer64}} \tab \code{\link{prod}} \tab  \cr
#!    \code{\link{all.integer64}} \tab \code{\link{all}} \tab  \cr
#!    \code{\link{any.integer64}} \tab \code{\link{any}} \tab  \cr
#!  \cr
#!    \bold{algorithmically complex functions} \tab \bold{see also}          \tab \bold{description (caching)}  \cr
#!    \code{\link{match.integer64}} \tab \code{\link{match}} \tab position of x in table (h//o/so) \cr
#!    \code{\link{\%in\%.integer64}} \tab \code{\link{\%in\%}} \tab is x in table? (h//o/so) \cr
#!    \code{\link{duplicated.integer64}} \tab \code{\link{duplicated}} \tab is current element duplicate of previous one? (h//o/so) \cr
#!    \code{\link{unique.integer64}} \tab \code{\link{unique}} \tab (shorter) vector of unique values only (h/s/o/so) \cr
#!    \code{\link{unipos.integer64}} \tab \code{\link{unipos}} \tab positions corresponding to unique values (h/s/o/so) \cr
#!    \code{\link{tiepos.integer64}} \tab \code{\link{tiepos}} \tab positions of values that are tied (//o/so) \cr
#!    \code{\link{keypos.integer64}} \tab \code{\link{keypos}} \tab position of current value in sorted list of unique values (//o/so) \cr
#!    \code{\link{as.factor.integer64}} \tab \code{\link{as.factor}} \tab convert to (unordered) factor with sorted levels of previous values (//o/so) \cr
#!    \code{\link{as.ordered.integer64}} \tab \code{\link{as.ordered}} \tab convert to ordered factor with sorted levels of previous values (//o/so) \cr
#!    \code{\link{table.integer64}} \tab \code{\link{table}} \tab unique values and their frequencies (h/s/o/so) \cr
#!    \code{\link{sort.integer64}} \tab \code{\link{sort}} \tab sorted vector (/s/o/so) \cr
#!    \code{\link{order.integer64}} \tab \code{\link{order}} \tab positions of elements that would create sorted vector (//o/so) \cr
#!    \code{\link{rank.integer64}} \tab \code{\link{rank}} \tab (average) ranks of non-NAs, NAs kept in place (/s/o/so) \cr
#!    \code{\link{quantile.integer64}} \tab \code{\link{quantile}} \tab (existing) values at specified percentiles (/s/o/so) \cr
#!    \code{\link{median.integer64}} \tab \code{\link{median}} \tab (existing) value at percentile 0.5 (/s/o/so) \cr
#!    \code{\link{summary.integer64}} \tab \code{\link{summary}} \tab  (/s/o/so) \cr
#!    \code{\link{all.equal.integer64}} \tab \code{\link{all.equal}} \tab test if two objects are (nearly) equal (/s/o/so) \cr
#!  \cr
#!    \bold{helper functions} \tab \bold{see also}          \tab \bold{description} \cr
#!    \code{\link{minusclass}} \tab \code{\link{minusclass}} \tab removing class attritbute \cr
#!    \code{\link{plusclass}} \tab \code{\link{plusclass}} \tab inserting class attribute \cr
#!    \code{\link{binattr}} \tab \code{\link{binattr}} \tab define binary op behaviour \cr
#!  \cr
#!    \bold{tested I/O functions} \tab \bold{see also}          \tab \bold{description} \cr
#!                                \tab \code{\link{read.table}} \tab inherited from Base R \cr
#!                                \tab \code{\link{write.table}} \tab inherited from Base R \cr
#!                                \tab \code{\link{serialize}} \tab inherited from Base R \cr
#!                                \tab \code{\link{unserialize}} \tab inherited from Base R \cr
#!                                \tab \code{\link{save}} \tab inherited from Base R \cr
#!                                \tab \code{\link{load}} \tab inherited from Base R \cr
#!                                \tab \code{\link{dput}} \tab inherited from Base R \cr
#!                                \tab \code{\link{dget}} \tab inherited from Base R \cr
#! }
#! }
#! \section{Limitations inherited from implementing 64 bit integers via an external package}{
#!   \itemize{
#!     \item \bold{vector size} of atomic vectors is still limited to \code{\link{.Machine}$integer.max}. 
#!     However, external memory extending packages such as \code{ff} or \code{bigmemory} 
#!     can extend their address space now with \code{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.
#!
#!     \item \bold{literals} such as \code{123LL} would require changes to Base R, up to then we need to write (and call) 
#!     \code{as.integer64(123L)} or \code{as.integer64(123)} or \code{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.
#!
#!   }
#! }
#! \section{Limitations inherited from Base R, Core team, can you change this?}{
#!   \itemize{
#!     \item \bold{\code{\link{identical}}} with default parameters does not distinguish all bit-patterns of doubles. 
#!     For testing purposes we provide a wrapper \code{\link{identical.integer64}} that will distinguish all bit-patterns.
#!     It would be desireable to have a single call of \code{\link{identical}} handle both, \code{\link{double}} and \code{integer64}.
#! 
#!     \item the \bold{colon} operator \code{\link{:}} officially does not dispatches S3 methods, however, we have made it generic
#!      \preformatted{
#!      from <- lim.integer64()[1]
#!      to <- from+99
#!      from:to
#!    }
#!    As a limitation remains: it will only dispatch at its first argument \code{from} but not at its second \code{to}.
#! 
#!     \item \bold{\code{\link{is.double}}} does not dispatches S3 methods, However, we have made it generic 
#!		and it will return \code{FALSE} on \code{integer64}.
#!
#!     \item \bold{\code{\link{c}}} only dispatches \code{\link{c.integer64}} if the first argument is \code{integer64}
#!     and it does not recursively dispatch the proper method when called with argument \code{recursive=TRUE}
#!     Therefore \preformatted{
#!       c(list(integer64,integer64))
#!     }
#!      does not work and for now you can only call \preformatted{
#!        c.integer64(list(x,x))
#!      }
#!
#!     \item \bold{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 
#!     \code{\link{bit}} and \code{\link{bitwhich}} sparsely representing boolean vectors 
#!     and we have methods \code{\link{&.bit}} and \code{\link{&.bitwhich}}. For an expression
#!     involving both as in \code{ bit & bitwhich}, none of the two methods is dispatched. 
#!     Instead a standard method is dispatched, which neither handles \code{\link{bit}} 
#!     nor \code{\link{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.
#!
#!     \item \bold{\code{\link{unlist}}} is not generic and if it were, we would face similar problems as with \code{c()}
#!
#!     \item \bold{\code{\link{vector}}} with argument \code{mode='integer64'} cannot work without adjustment of Base R
#!     \item \bold{\code{\link{as.vector}}} with argument \code{mode='integer64'} cannot work without adjustment of Base R
#!
#!     \item \bold{\code{\link{is.vector}}} does not dispatch its method \code{\link{is.vector.integer64}}
#!
#!     \item \bold{\code{\link{mode<-}}} drops the class 'integer64' which is returned from \code{as.integer64}.
#!        Also it does not remove an existing class 'integer64' when assigning mode 'integer'. 
#!
#!     \item \bold{\code{\link{storage.mode<-}}} does not support external data types such as \code{as.integer64}
#!
#!     \item \bold{\code{\link{matrix}}} does drop the 'integer64' class attribute.
#!
#!     \item \bold{\code{\link{array}}}  does drop the 'integer64' class attribute. 
#!            In current R versions (1.15.1) this can be circumvented by activating the function 
#!						\code{as.vector.integer64} further down this file.
#!						However, the CRAN maintainer has requested to remove \code{as.vector.integer64}, 
#! 						even at the price of breaking previously working functionality of the package. 
#!
#!     \item \bold{\code{\link{str}}} does not print the values of \code{integer64} correctly
#!
#!   }
#! }
#! \section{further limitations}{
#!   \itemize{
#!     \item \bold{subscripting} non-existing elements and subscripting with \code{NA}s is currently not supported. 
#!     Such subscripting currently returns \code{9218868437227407266} instead of \code{NA} (the \code{NA} value of the underlying double code).
#!     Following the full R behaviour here would either destroy performance or require extensive C-coding. 
#!   }
#! }
#! \note{
#!    \code{integer64} are useful for handling database keys and exact counting in +-2^63.
#!    Do not use them as replacement for 32bit integers, integer64 are not
#!    supported for subscripting by R-core and they have different semantics 
#!    when combined with double. Do understand that \code{integer64} can only be
#!    useful over \code{double} if we do not coerce it to \code{double}. \cr
#!   \cr
#!   While \cr
#!   integer + double -> double + double -> double \cr
#!   or \cr
#!   1L + 0.5 -> 1.5 \cr 
#!   for additive operations we coerce to \code{integer64} \cr
#!   integer64 + double ->  integer64 + integer64 -> integer64 \cr
#!   hence \cr
#!   as.integer64(1) + 0.5 -> 1LL + 0LL -> 1LL \cr
#!   \cr
#!   see section "Arithmetic precision and coercion" above
#! }
#! \value{
#!   \code{integer64} returns a vector of 'integer64', 
#!    i.e. a vector of \code{\link{double}} decorated with class 'integer64'.
#! }
#! \author{
#! Jens Oehlschlägel <Jens.Oehlschlaegel@truecluster.com>
#! Maintainer: Jens Oehlschlägel <Jens.Oehlschlaegel@truecluster.com>
#! }
#! \keyword{ package }
#! \keyword{ classes }
#! \keyword{ manip }
#! \seealso{ \code{\link{integer}} in base R }
#! \examples{
#! 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")
#! %y <- array(as.integer64(NA), dim=c(3,4), dimnames=list(letters[1:3], LETTERS[1:4]))
#! 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)<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)))))
#!
#! message("-- testing vector functions --")
#! stopifnot(identical.integer64( is.na(as.integer64(c(NA, -1:1))), is.na(c(NA, -1:1)) ))
#! stopifnot(identical.integer64( format(as.integer64(c(NA, -1:1))), format(c(NA, -1:1)) ))
#! stopifnot(identical.integer64( abs(as.integer64(c(NA, -1:1))), as.integer64(abs(c(NA, -1:1))) ))
#! stopifnot(identical.integer64( sign(as.integer64(c(NA, -1:1))), as.integer64(sign(c(NA, -1:1))) ))
#! stopifnot(identical.integer64( ceiling(as.integer64(c(NA, -1:1))), as.integer64(ceiling(c(NA, -1:1))) ))
#! stopifnot(identical.integer64( floor(as.integer64(c(NA, -1:1))), as.integer64(floor(c(NA, -1:1))) ))
#! stopifnot(identical.integer64( trunc(as.integer64(c(NA, -1:1))), as.integer64(trunc(c(NA, -1:1))) ))
#! stopifnot(identical.integer64( signif(as.integer64(c(NA, -1:1))), as.integer64(c(NA, -1:1)) ))
#!
#! message("Testing summary functions")
#! stopifnot(identical(all(as.integer(1)), all(as.integer64(1))))
#! stopifnot(identical(all(as.integer(0)), all(as.integer64(0))))
#! stopifnot(identical(all(as.integer(NA)), all(as.integer64(NA))))
#! stopifnot(identical(all(as.integer(NA), na.rm=TRUE), all(as.integer64(NA), na.rm=TRUE)))
#! stopifnot(identical(all(as.integer(1), NA), all(as.integer64(1), NA)))
#! stopifnot(identical(all(as.integer(0), NA), all(as.integer64(0), NA)))
#! stopifnot(identical(all(as.integer(1), NA, na.rm=TRUE), all(as.integer64(1), NA, na.rm=TRUE)))
#! stopifnot(identical(all(as.integer(0), NA, na.rm=TRUE), all(as.integer64(0), NA, na.rm=TRUE)))
#! stopifnot(identical(all(as.integer(c(1, NA))), all(as.integer64(c(1, NA)))))
#! stopifnot(identical(all(as.integer(c(0, NA))), all(as.integer64(c(0, NA)))))
#! stopifnot(identical(all(as.integer(c(1, NA)), na.rm=TRUE), all(as.integer64(c(1, NA)), na.rm=TRUE)))
#! stopifnot(identical(all(as.integer(c(0, NA)), na.rm=TRUE), all(as.integer64(c(0, NA)), na.rm=TRUE)))
#! 
#! stopifnot(identical(any(as.integer(1)), any(as.integer64(1))))
#! stopifnot(identical(any(as.integer(0)), any(as.integer64(0))))
#! stopifnot(identical(any(as.integer(NA)), any(as.integer64(NA))))
#! stopifnot(identical(any(as.integer(NA), na.rm=TRUE), any(as.integer64(NA), na.rm=TRUE)))
#! stopifnot(identical(any(as.integer(1), NA), any(as.integer64(1), NA)))
#! stopifnot(identical(any(as.integer(0), NA), any(as.integer64(0), NA)))
#! stopifnot(identical(any(as.integer(1), NA, na.rm=TRUE), any(as.integer64(1), NA, na.rm=TRUE)))
#! stopifnot(identical(any(as.integer(0), NA, na.rm=TRUE), any(as.integer64(0), NA, na.rm=TRUE)))
#! stopifnot(identical(any(as.integer(c(1, NA))), any(as.integer64(c(1, NA)))))
#! stopifnot(identical(any(as.integer(c(0, NA))), any(as.integer64(c(0, NA)))))
#! stopifnot(identical(any(as.integer(c(1, NA)), na.rm=TRUE), any(as.integer64(c(1, NA)), na.rm=TRUE)))
#! stopifnot(identical(any(as.integer(c(0, NA)), na.rm=TRUE), any(as.integer64(c(0, NA)), na.rm=TRUE)))
#! 
#! stopifnot(identical.integer64(as.integer64(sum(c(2, 3, NA))), sum(as.integer64(c(2, 3, NA)))))
#! stopifnot(identical.integer64(as.integer64(sum(c(2, 3, NA), na.rm=TRUE)), sum(as.integer64(c(2, 3, NA)), na.rm=TRUE)))
#! stopifnot(identical.integer64(as.integer64(sum(c(2, 3, NA))), sum(as.integer64(c(2, 3, NA)))))
#! stopifnot(identical.integer64(as.integer64(sum(c(2, 3, NA), na.rm=TRUE)), sum(as.integer64(c(2, 3, NA)), na.rm=TRUE)))
#! stopifnot(identical.integer64(as.integer64(sum(2, 3, NA)), sum(as.integer64(2), 3, NA)))
#! stopifnot(identical.integer64(as.integer64(sum(2, 3, NA, na.rm=TRUE)), sum(as.integer64(2), 3, NA, na.rm=TRUE)))
#! stopifnot(identical.integer64(as.integer64(sum(2, 3, NA)), sum(as.integer64(2), 3, NA)))
#! stopifnot(identical.integer64(as.integer64(sum(2, 3, NA, na.rm=TRUE)), sum(as.integer64(2), 3, NA, na.rm=TRUE)))
#! 
#! stopifnot(identical.integer64(as.integer64(prod(c(2, 3, NA))), prod(as.integer64(c(2, 3, NA)))))
#! stopifnot(identical.integer64(as.integer64(prod(c(2, 3, NA), na.rm=TRUE)), prod(as.integer64(c(2, 3, NA)), na.rm=TRUE)))
#! stopifnot(identical.integer64(as.integer64(prod(c(2, 3, NA))), prod(as.integer64(c(2, 3, NA)))))
#! stopifnot(identical.integer64(as.integer64(prod(c(2, 3, NA), na.rm=TRUE)), prod(as.integer64(c(2, 3, NA)), na.rm=TRUE)))
#! stopifnot(identical.integer64(as.integer64(prod(2, 3, NA)), prod(as.integer64(2), 3, NA)))
#! stopifnot(identical.integer64(as.integer64(prod(2, 3, NA, na.rm=TRUE)), prod(as.integer64(2), 3, NA, na.rm=TRUE)))
#! stopifnot(identical.integer64(as.integer64(prod(2, 3, NA)), prod(as.integer64(2), 3, NA)))
#! stopifnot(identical.integer64(as.integer64(prod(2, 3, NA, na.rm=TRUE)), prod(as.integer64(2), 3, NA, na.rm=TRUE)))
#! 
#! stopifnot(identical.integer64(as.integer64(min(c(2, 3, NA))), min(as.integer64(c(2, 3, NA)))))
#! stopifnot(identical.integer64(as.integer64(min(c(2, 3, NA), na.rm=TRUE)), min(as.integer64(c(2, 3, NA)), na.rm=TRUE)))
#! stopifnot(identical.integer64(as.integer64(min(c(2, 3, NA))), min(as.integer64(c(2, 3, NA)))))
#! stopifnot(identical.integer64(as.integer64(min(c(2, 3, NA), na.rm=TRUE)), min(as.integer64(c(2, 3, NA)), na.rm=TRUE)))
#! stopifnot(identical.integer64(as.integer64(min(2, 3, NA)), min(as.integer64(2), 3, NA)))
#! stopifnot(identical.integer64(as.integer64(min(2, 3, NA, na.rm=TRUE)), min(as.integer64(2), 3, NA, na.rm=TRUE)))
#! stopifnot(identical.integer64(as.integer64(min(2, 3, NA)), min(as.integer64(2), 3, NA)))
#! stopifnot(identical.integer64(as.integer64(min(2, 3, NA, na.rm=TRUE)), min(as.integer64(2), 3, NA, na.rm=TRUE)))
#! 
#! stopifnot(identical.integer64(as.integer64(max(c(2, 3, NA))), max(as.integer64(c(2, 3, NA)))))
#! stopifnot(identical.integer64(as.integer64(max(c(2, 3, NA), na.rm=TRUE)), max(as.integer64(c(2, 3, NA)), na.rm=TRUE)))
#! stopifnot(identical.integer64(as.integer64(max(c(2, 3, NA))), max(as.integer64(c(2, 3, NA)))))
#! stopifnot(identical.integer64(as.integer64(max(c(2, 3, NA), na.rm=TRUE)), max(as.integer64(c(2, 3, NA)), na.rm=TRUE)))
#! stopifnot(identical.integer64(as.integer64(max(2, 3, NA)), max(as.integer64(2), 3, NA)))
#! stopifnot(identical.integer64(as.integer64(max(2, 3, NA, na.rm=TRUE)), max(as.integer64(2), 3, NA, na.rm=TRUE)))
#! stopifnot(identical.integer64(as.integer64(max(2, 3, NA)), max(as.integer64(2), 3, NA)))
#! stopifnot(identical.integer64(as.integer64(max(2, 3, NA, na.rm=TRUE)), max(as.integer64(2), 3, NA, na.rm=TRUE)))
#! 
#! stopifnot(identical.integer64(as.integer64(range(c(2, 3, NA))), range(as.integer64(c(2, 3, NA)))))
#! stopifnot(identical.integer64(as.integer64(range(c(2, 3, NA), na.rm=TRUE)), range(as.integer64(c(2, 3, NA)), na.rm=TRUE)))
#! stopifnot(identical.integer64(as.integer64(range(c(2, 3, NA))), range(as.integer64(c(2, 3, NA)))))
#! stopifnot(identical.integer64(as.integer64(range(c(2, 3, NA), na.rm=TRUE)), range(as.integer64(c(2, 3, NA)), na.rm=TRUE)))
#! stopifnot(identical.integer64(as.integer64(range(2, 3, NA)), range(as.integer64(2), 3, NA)))
#! stopifnot(identical.integer64(as.integer64(range(2, 3, NA, na.rm=TRUE)), range(as.integer64(2), 3, NA, na.rm=TRUE)))
#! stopifnot(identical.integer64(as.integer64(range(2, 3, NA)), range(as.integer64(2), 3, NA)))
#! stopifnot(identical.integer64(as.integer64(range(2, 3, NA, na.rm=TRUE)), range(as.integer64(2), 3, NA, na.rm=TRUE)))
#! 
#! message("-- testing cummulative functions --")
#! stopifnot(identical.integer64(as.integer64(cumsum(c(2, 3, NA, 1, 4))), cumsum(as.integer64(c(2, 3, NA, 1, 4)))))
#! stopifnot(identical.integer64(as.integer64(cumprod(c(2, 3, NA, 1, 4))), cumprod(as.integer64(c(2, 3, NA, 1, 4)))))
#! stopifnot(identical.integer64(as.integer64(cummin(c(2, 3, NA, 1, 4))), cummin(as.integer64(c(2, 3, NA, 1, 4)))))
#! stopifnot(identical.integer64(as.integer64(cummax(c(2, 3, NA, 1, 4))), cummax(as.integer64(c(2, 3, NA, 1, 4)))))
#! 
#! message("testing diff")
#! d64 <- diffinv(rep(.Machine$integer.max, 100), lag=2, differences=2)
#! i64 <- as.integer64(d64)
#! identical(diff(d64, lag=2, differences=2), as.double(diff(i64, lag=2, differences=2)))
#!
#!   }
#!
#!   \dontrun{
#! message("== Differences between integer64 and int64 ==")
#! require(bit64)
#! require(int64)
#! 
#! message("-- integer64 is atomic --")
#! is.atomic(integer64())
#! #is.atomic(int64())
#! str(integer64(3))
#! #str(int64(3))
#! 
#! message("-- The following performance numbers are measured under RWin64  --")
#! message("-- under RWin32 the advantage of integer64 over int64 is smaller --")
#!
#! message("-- integer64 needs 7x/5x less RAM than int64 under 64/32 bit OS 
#! (and twice the RAM of integer as it should be) --")
#! #as.vector(object.size(int64(1e6))/object.size(integer64(1e6)))
#! as.vector(object.size(integer64(1e6))/object.size(integer(1e6)))
#! 
#! message("-- integer64 creates 2000x/1300x faster than int64 under 64/32 bit OS
#! (and 3x the time of integer) --")
#! t32 <- system.time(integer(1e8))
#! t64 <- system.time(integer64(1e8))
#! #T64 <- system.time(int64(1e7))*10  # using 1e8 as above stalls our R on an i7 8 GB RAM Thinkpad
#! #T64/t64
#! t64/t32
#! 
#! i32 <- sample(1e6)
#! d64 <- as.double(i32)
#! 
#! message("-- the following timings are rather conservative since timings
#!  of integer64 include garbage collection -- due to looped calls")
#! message("-- integer64 coerces 900x/100x faster than int64 
#!  under 64/32 bit OS (and 2x the time of coercing to integer) --")
#! t32 <- system.time(for(i in 1:1000)as.integer(d64))
#! t64 <- system.time(for(i in 1:1000)as.integer64(d64))
#! #T64 <- system.time(as.int64(d64))*1000
#! #T64/t64
#! t64/t32
#! td64 <- system.time(for(i in 1:1000)as.double(i32))
#! t64 <- system.time(for(i in 1:1000)as.integer64(i32))
#! #T64 <- system.time(for(i in 1:10)as.int64(i32))*100
#! #T64/t64
#! t64/td64
#! 
#! message("-- integer64 serializes 4x/0.8x faster than int64 
#!  under 64/32 bit OS (and less than 2x/6x the time of integer or double) --")
#! t32 <- system.time(for(i in 1:10)serialize(i32, NULL))
#! td64 <- system.time(for(i in 1:10)serialize(d64, NULL))
#! i64 <- as.integer64(i32); 
#! t64 <- system.time(for(i in 1:10)serialize(i64, NULL))
#! rm(i64); gc()
#! #I64 <- as.int64(i32); 
#! #T64 <- system.time(for(i in 1:10)serialize(I64, NULL))
#! #rm(I64); gc()
#! #T64/t64
#! t64/t32
#! t64/td64
#! 
#! 
#! message("-- integer64 adds 250x/60x faster than int64
#!  under 64/32 bit OS (and less than 6x the time of integer or double) --")
#! td64 <- system.time(for(i in 1:100)d64+d64)
#! t32 <- system.time(for(i in 1:100)i32+i32)
#! i64 <- as.integer64(i32); 
#! t64 <- system.time(for(i in 1:100)i64+i64)
#! rm(i64); gc()
#! #I64 <- as.int64(i32); 
#! #T64 <- system.time(for(i in 1:10)I64+I64)*10
#! #rm(I64); gc()
#! #T64/t64
#! t64/t32
#! t64/td64
#! 
#! message("-- integer64 sums 3x/0.2x faster than int64 
#! (and at about 5x/60X the time of integer and double) --")
#! td64 <- system.time(for(i in 1:100)sum(d64))
#! t32 <- system.time(for(i in 1:100)sum(i32))
#! i64 <- as.integer64(i32); 
#! t64 <- system.time(for(i in 1:100)sum(i64))
#! rm(i64); gc()
#! #I64 <- as.int64(i32); 
#! #T64 <- system.time(for(i in 1:100)sum(I64))
#! #rm(I64); gc()
#! #T64/t64
#! t64/t32
#! t64/td64
#! 
#! message("-- integer64 diffs 5x/0.85x faster than integer and double
#! (int64 version 1.0 does not support diff) --")
#! td64 <- system.time(for(i in 1:10)diff(d64, lag=2L, differences=2L))
#! t32 <- system.time(for(i in 1:10)diff(i32, lag=2L, differences=2L))
#! i64 <- as.integer64(i32); 
#! t64 <- system.time(for(i in 1:10)diff(i64, lag=2L, differences=2L))
#! rm(i64); gc()
#! t64/t32
#! t64/td64
#! 
#! 
#! message("-- integer64 subscripts 1000x/340x faster than int64
#! (and at the same speed / 10x slower as integer) --")
#! ts32 <- system.time(for(i in 1:1000)sample(1e6, 1e3))
#! t32<- system.time(for(i in 1:1000)i32[sample(1e6, 1e3)])
#! i64 <- as.integer64(i32); 
#! t64 <- system.time(for(i in 1:1000)i64[sample(1e6, 1e3)])
#! rm(i64); gc()
#! #I64 <- as.int64(i32); 
#! #T64 <- system.time(for(i in 1:100)I64[sample(1e6, 1e3)])*10
#! #rm(I64); gc()
#! #(T64-ts32)/(t64-ts32)
#! (t64-ts32)/(t32-ts32)
#! 
#! message("-- integer64 assigns 200x/90x faster than int64
#! (and 50x/160x slower than integer) --")
#! ts32 <- system.time(for(i in 1:100)sample(1e6, 1e3))
#! t32 <- system.time(for(i in 1:100)i32[sample(1e6, 1e3)] <- 1:1e3)
#! i64 <- as.integer64(i32); 
#! i64 <- system.time(for(i in 1:100)i64[sample(1e6, 1e3)] <- 1:1e3)
#! rm(i64); gc()
#! #I64 <- as.int64(i32); 
#! #I64 <- system.time(for(i in 1:10)I64[sample(1e6, 1e3)] <- 1:1e3)*10
#! #rm(I64); gc()
#! #(T64-ts32)/(t64-ts32)
#! (t64-ts32)/(t32-ts32)
#! 
#! 
#! tdfi32 <- system.time(dfi32 <- data.frame(a=i32, b=i32, c=i32))
#! tdfsi32 <- system.time(dfi32[1e6:1,])
#! fi32 <- tempfile()
#! tdfwi32 <- system.time(write.csv(dfi32, file=fi32, row.names=FALSE))
#! tdfri32 <- system.time(read.csv(fi32, colClasses=rep("integer", 3)))
#! unlink(fi32)
#! rm(dfi32); gc()
#! 
#! i64 <- as.integer64(i32); 
#! tdfi64 <- system.time(dfi64 <- data.frame(a=i64, b=i64, c=i64))
#! tdfsi64 <- system.time(dfi64[1e6:1,])
#! fi64 <- tempfile()
#! tdfwi64 <- system.time(write.csv(dfi64, file=fi64, row.names=FALSE))
#! tdfri64 <- system.time(read.csv(fi64, colClasses=rep("integer64", 3)))
#! unlink(fi64)
#! rm(i64, dfi64); gc()
#! 
#! #I64 <- as.int64(i32); 
#! #tdfI64 <- system.time(dfI64<-data.frame(a=I64, b=I64, c=I64))
#! #tdfsI64 <- system.time(dfI64[1e6:1,])
#! #fI64 <- tempfile()
#! #tdfwI64 <- system.time(write.csv(dfI64, file=fI64, row.names=FALSE))
#! #tdfrI64 <- system.time(read.csv(fI64, colClasses=rep("int64", 3)))
#! #unlink(fI64)
#! #rm(I64, dfI64); gc()
#! 
#! message("-- integer64 coerces 40x/6x faster to data.frame than int64
#! (and factor 1/9 slower than integer) --")
#! #tdfI64/tdfi64
#! tdfi64/tdfi32
#! message("-- integer64 subscripts from data.frame 20x/2.5x faster than int64
#!  (and 3x/13x slower than integer) --")
#! #tdfsI64/tdfsi64
#! tdfsi64/tdfsi32
#! message("-- integer64 csv writes about 2x/0.5x faster than int64
#! (and about 1.5x/5x slower than integer) --")
#! #tdfwI64/tdfwi64
#! tdfwi64/tdfwi32
#! message("-- integer64 csv reads about 3x/1.5 faster than int64
#! (and about 2x slower than integer) --")
#! #tdfrI64/tdfri64
#! tdfri64/tdfri32
#! 
#! rm(i32, d64); gc()
#! 
#! 
#! message("-- investigating the impact on garbage collection: --")
#! message("-- the fragmented structure of int64 messes up R's RAM --")
#! message("-- and slows down R's gargbage collection just by existing --")
#! 
#! td32 <- double(21)
#! td32[1] <- system.time(d64 <- double(1e7))[3]
#! for (i in 2:11)td32[i] <- system.time(gc(), gcFirst=FALSE)[3]
#! rm(d64)
#! for (i in 12:21)td32[i] <- system.time(gc(), gcFirst=FALSE)[3]
#! 
#! t64 <- double(21)
#! t64[1] <- system.time(i64 <- integer64(1e7))[3]
#! for (i in 2:11)t64[i] <- system.time(gc(), gcFirst=FALSE)[3]
#! rm(i64)
#! for (i in 12:21)t64[i] <- system.time(gc(), gcFirst=FALSE)[3]
#! 
#! #T64 <- double(21)
#! #T64[1] <- system.time(I64 <- int64(1e7))[3]
#! #for (i in 2:11)T64[i] <- system.time(gc(), gcFirst=FALSE)[3]
#! #rm(I64)
#! #for (i in 12:21)T64[i] <- system.time(gc(), gcFirst=FALSE)[3]
#! 
#! #matplot(1:21, cbind(td32, t64, T64), pch=c("d","i","I"), log="y")
#! matplot(1:21, cbind(td32, t64), pch=c("d","i"), log="y")
#!   }
#!
#! }
#! \name{identical.integer64}
#! \alias{identical.integer64}
#! \title{
#!    Identity function for class 'integer64'
#! }
#! \description{
#!   This will discover any deviation between objects containing integer64 vectors. 
#! }
#! \usage{
#!  identical.integer64(x, y, num.eq = FALSE, single.NA = FALSE
#! , attrib.as.set = TRUE, ignore.bytecode = TRUE)
#! }
#! \arguments{
#!   \item{x}{ atomic vector of class 'integer64' }
#!   \item{y}{ atomic vector of class 'integer64' }
#!   \item{num.eq}{ see \code{\link{identical}} }
#!   \item{single.NA}{ see \code{\link{identical}} }
#!   \item{attrib.as.set}{ see \code{\link{identical}} }
#!   \item{ignore.bytecode}{ see \code{\link{identical}} }
#! }
#! \details{
#!   This is simply a wrapper to \code{\link{identical}} with default arguments \code{num.eq = FALSE, single.NA = FALSE}.
#! }
#! \value{
#!   A single logical value, \code{TRUE} or \code{FALSE}, never \code{NA} and never anything other than a single value. 
#! }
#! \author{
#! Jens Oehlschlägel <Jens.Oehlschlaegel@truecluster.com>
#! }
#! \keyword{ classes }
#! \keyword{ manip }
#! \seealso{ \code{\link{==.integer64}} \code{\link{identical}} \code{\link{integer64}}  }
#! \examples{
#!   i64 <- as.double(NA); class(i64) <- "integer64"
#!   identical(i64-1, i64+1)
#!   identical.integer64(i64-1, i64+1)
#! }


#! \name{as.character.integer64}
#! \alias{as.character.integer64}
#! \alias{as.double.integer64}
#! \alias{as.integer.integer64}
#! \alias{as.logical.integer64}
#! \alias{as.bitstring}
#! \alias{print.bitstring}
#! \alias{as.bitstring.integer64}
#! \alias{as.factor.integer64}
#! \alias{as.ordered.integer64}
#! \title{
#!    Coerce from integer64
#! }
#! \description{
#!   Methods to coerce integer64 to other atomic types. 
#!   'as.bitstring' coerces to a human-readable bit representation (strings of zeroes and ones). 
#!   The methods \code{\link{format}}, \code{\link{as.character}}, \code{\link{as.double}},
#!   \code{\link{as.logical}}, \code{\link{as.integer}} do what you would expect.
#! }
#! \usage{
#!  as.bitstring(x, \dots)
#!  \method{as.bitstring}{integer64}(x, \dots)
#!  \method{print}{bitstring}(x, \dots)
#!  \method{as.character}{integer64}(x, \dots)
#!  \method{as.double}{integer64}(x, keep.names = FALSE, \dots)
#!  \method{as.integer}{integer64}(x, \dots)
#!  \method{as.logical}{integer64}(x, \dots)
#!  \method{as.factor}{integer64}(x)
#!  \method{as.ordered}{integer64}(x)
#! }
#! \arguments{
#!   \item{x}{ an integer64 vector }
#!   \item{keep.names}{ FALSE, set to TRUE to keep a names vector }
#!   \item{\dots}{ further arguments to the \code{\link{NextMethod}} }
#! }
#! \value{
#!   \code{as.bitstring} returns a string of class 'bitstring'. \cr
#!   The other methods return atomic vectors of the expected types
#! }
#! \author{
#! Jens Oehlschlägel <Jens.Oehlschlaegel@truecluster.com>
#! }
#! \keyword{ classes }
#! \keyword{ manip }
#! \seealso{ \code{\link{as.integer64.character}} \code{\link{integer64}}  }
#! \examples{
#!   as.character(lim.integer64())
#!   as.bitstring(lim.integer64())
#!   as.bitstring(as.integer64(c(
#!    -2,-1,NA,0:2
#!   )))
#! }

#! \name{as.integer64.character}
#! \alias{as.integer64}
#! \alias{as.integer64.integer64}
#! \alias{as.integer64.NULL}
#! \alias{as.integer64.bitstring}
#! \alias{as.integer64.character}
#! \alias{as.integer64.double}
#! \alias{as.integer64.integer}
#! \alias{as.integer64.logical}
#! \alias{as.integer64.factor}
#! \alias{NA_integer64_}
#! \title{
#!    Coerce to integer64
#! }
#! \description{
#!   Methods to coerce from other atomic types to integer64. 
#! }
#! \usage{
#!  NA_integer64_
#!  as.integer64(x, \dots)
#!  \method{as.integer64}{integer64}(x, \dots)
#!  \method{as.integer64}{NULL}(x, \dots)
#!  \method{as.integer64}{character}(x, \dots)
#!  \method{as.integer64}{bitstring}(x, \dots)
#!  \method{as.integer64}{double}(x, keep.names = FALSE, \dots)
#!  \method{as.integer64}{integer}(x, \dots)
#!  \method{as.integer64}{logical}(x, \dots)
#!  \method{as.integer64}{factor}(x, \dots)
#! }
#! \arguments{
#!   \item{x}{ an atomic vector }
#!   \item{keep.names}{ FALSE, set to TRUE to keep a names vector }
#!   \item{\dots}{ further arguments to the \code{\link{NextMethod}} }
#! }
#! \details{
#!   \code{as.integer64.character} is realized using C function \code{strtoll} which does not support scientific notation. 
#!   Instead of '1e6' use '1000000'. 
#!   \code{as.integer64.bitstring} evaluates characters '0' anbd ' ' as zero-bit,
#!   all other one byte characters as one-bit,
#!   multi-byte characters are not allowed,
#!   strings shorter than 64 characters are treated as if they were left-padded with '0',
#!   strings longer than 64 bytes are mapped to \code{NA_INTEGER64} and a warning is emitted.
#! }
#! \value{
#!   The other methods return atomic vectors of the expected types
#! }
#! \author{
#! Jens Oehlschlägel <Jens.Oehlschlaegel@truecluster.com>
#! }
#! \keyword{ classes }
#! \keyword{ manip }
#! \seealso{ \code{\link{as.character.integer64}} \code{\link{integer64}}  }
#! \examples{
#! as.integer64(as.character(lim.integer64()))
#! as.integer64(
#!   structure(c("1111111111111111111111111111111111111111111111111111111111111110", 
#!               "1111111111111111111111111111111111111111111111111111111111111111", 
#!               "1000000000000000000000000000000000000000000000000000000000000000",
#!               "0000000000000000000000000000000000000000000000000000000000000000", 
#!               "0000000000000000000000000000000000000000000000000000000000000001", 
#!               "0000000000000000000000000000000000000000000000000000000000000010" 
#!   ), class = "bitstring")
#! )
#! as.integer64(
#!  structure(c("............................................................... ", 
#!              "................................................................", 
#!              ".                                                               ",
#!              "", 
#!              ".", 
#!              "10"
#!   ), class = "bitstring")
#! )
#! }


#! \name{extract.replace.integer64}
#! \alias{[.integer64}
#! \alias{[[.integer64}
#! \alias{[[<-.integer64}
#! \alias{[<-.integer64}
#! \title{
#!    Extract or Replace Parts of an integer64 vector
#! }
#! \description{
#!   Methods to extract and replace parts of an integer64 vector.
#! }
#! \usage{
#!  \method{[}{integer64}(x, i, \dots)
#!  \method{[}{integer64}(x, \dots) <- value 
#!  \method{[[}{integer64}(x, \dots)
#!  \method{[[}{integer64}(x, \dots) <- value
#! }
#! \arguments{
#!   \item{x}{ an atomic vector }
#!   \item{i}{ indices specifying elements to extract }
#!   \item{value}{ an atomic vector with values to be assigned }
#!   \item{\dots}{ further arguments to the \code{\link{NextMethod}} }
#! }
#! \note{
#!   You should not subscript non-existing elements and not use \code{NA}s as subscripts.
#!   The current implementation returns \code{9218868437227407266} instead of \code{NA}.
#! }
#! \value{
#!   A vector or scalar of class 'integer64'
#! }
#! \author{
#! Jens Oehlschlägel <Jens.Oehlschlaegel@truecluster.com>
#! }
#! \keyword{ classes }
#! \keyword{ manip }
#! \seealso{ \code{\link{[}} \code{\link{integer64}}  }
#! \examples{
#!   as.integer64(1:12)[1:3]
#!   x <- as.integer64(1:12)
#!   dim(x) <- c(3,4)
#!   x
#!   x[]
#!   x[,2:3]
#!   \dontshow{
#!     r <- c(runif64(1e3, lim.integer64()[1], lim.integer64()[2]), NA, -2:2)
#!     stopifnot(identical(r, as.integer64(as.bitstring(r))))
#!   }
#! }

#! \name{format.integer64}
#! \alias{format.integer64}
#! \alias{is.na.integer64}
#! \alias{is.nan.integer64}
#! \alias{is.finite.integer64}
#! \alias{is.infinite.integer64}
#! \alias{!.integer64}
#! \alias{sign.integer64}
#! \alias{abs.integer64}
#! \alias{sqrt.integer64}
#! \alias{log.integer64}
#! \alias{log2.integer64}
#! \alias{log10.integer64}
#! \alias{floor.integer64}
#! \alias{ceiling.integer64}
#! \alias{trunc.integer64}
#! \alias{round.integer64}
#! \alias{signif.integer64}
#! \alias{scale.integer64}
#! \title{
#!    Unary operators and functions for integer64 vectors
#! }
#! \description{
#!   Unary operators and functions for integer64 vectors.
#! }
#! \usage{
#! \method{format}{integer64}(x, justify="right", \dots)
#! \method{is.na}{integer64}(x)
#! \method{is.nan}{integer64}(x)
#! \method{is.finite}{integer64}(x)
#! \method{is.infinite}{integer64}(x)
#! \method{!}{integer64}(x)
#! \method{sign}{integer64}(x)
#! \method{abs}{integer64}(x)
#! \method{sqrt}{integer64}(x)
#! \method{log}{integer64}(x, base)
#! \method{log2}{integer64}(x)
#! \method{log10}{integer64}(x)
#! \method{floor}{integer64}(x)
#! \method{ceiling}{integer64}(x)
#! \method{trunc}{integer64}(x, \dots)
#! \method{round}{integer64}(x, digits=0)
#! \method{signif}{integer64}(x, digits=6)
#! \method{scale}{integer64}(x, center = TRUE, scale = TRUE)
#! }
#! \arguments{
#!   \item{x}{ an atomic vector of class 'integer64'}
#!   \item{base}{ an atomic scalar (we save 50\% log-calls by not allowing a vector base) }
#!   \item{digits}{ integer indicating the number of decimal places (round) or significant digits (signif) to be used. 
#!                  Negative values are allowed (see \code{\link{round}}) }
#!   \item{justify}{ should it be right-justified (the default), left-justified, centred or left alone. }
#!   \item{center}{ see \code{\link{scale}} }
#!   \item{scale}{  see \code{\link{scale}} }
#!   \item{\dots}{ further arguments to the \code{\link{NextMethod}} }
#! }
#! \value{
#!   \code{\link{format}} returns a character vector \cr
#!   \code{\link{is.na}} and \code{\link{!}} return a logical vector \cr
#!   \code{\link{sqrt}}, \code{\link{log}}, \code{\link{log2}} and \code{\link{log10}} return a double vector \cr
#!   \code{\link{sign}}, \code{\link{abs}}, \code{\link{floor}}, \code{\link{ceiling}}, \code{\link{trunc}} and 
#!   \code{\link{round}} return a vector of class 'integer64' \cr
#!   \code{\link{signif}} is not implemented 
#! }
#! \author{
#! Jens Oehlschlägel <Jens.Oehlschlaegel@truecluster.com>
#! }
#! \keyword{ classes }
#! \keyword{ manip }
#! \seealso{ \code{\link{xor.integer64}} \code{\link{integer64}}  }
#! \examples{
#!   sqrt(as.integer64(1:12))
#! \dontshow{
#! i <- -999:999
#! for (s in -3:3){
#! r <- as.integer64(round(as.integer(i), s))
#!   r64 <- round(as.integer64(i), s)
#!   stopifnot(identical(r,r64))
#! }
#! }
#! }

#! \name{xor.integer64}
#! \alias{&.integer64}
#! \alias{|.integer64}
#! \alias{xor.integer64}
#! \alias{!=.integer64}
#! \alias{==.integer64}
#! \alias{<.integer64}
#! \alias{<=.integer64}
#! \alias{>.integer64}
#! \alias{>=.integer64}
#! \alias{+.integer64}
#! \alias{-.integer64}
#! \alias{*.integer64}
#! \alias{^.integer64}
#! \alias{/.integer64}
#! \alias{\%/\%.integer64}
#! \alias{\%\%.integer64}
#! \alias{binattr}
#! \title{
#!    Binary operators for integer64 vectors
#! }
#! \description{
#!   Binary operators for integer64 vectors.
#! }
#! \usage{
#! \method{&}{integer64}(e1,e2)
#! \method{|}{integer64}(e1,e2)
#! \method{xor}{integer64}(x,y)
#! \method{!=}{integer64}(e1,e2)
#! \method{==}{integer64}(e1,e2)
#! \method{<}{integer64}(e1,e2)
#! \method{<=}{integer64}(e1,e2)
#! \method{>}{integer64}(e1,e2)
#! \method{>=}{integer64}(e1,e2)
#! \method{+}{integer64}(e1,e2)
#! \method{-}{integer64}(e1,e2)
#! \method{*}{integer64}(e1,e2)
#! \method{^}{integer64}(e1,e2)
#! \method{/}{integer64}(e1,e2)
#! \method{\%/\%}{integer64}(e1,e2)
#! \method{\%\%}{integer64}(e1,e2)
#! binattr(e1,e2) # for internal use only
#! }
#! \arguments{
#!   \item{e1}{ an atomic vector of class 'integer64'}
#!   \item{e2}{ an atomic vector of class 'integer64'}
#!   \item{x}{ an atomic vector of class 'integer64'}
#!   \item{y}{ an atomic vector of class 'integer64'}
#! }
#! \value{
#!   \code{\link{&}}, \code{\link{|}}, \code{\link{xor}}, \code{\link{!=}}, \code{\link{==}}, 
#!   \code{\link{<}}, \code{\link{<=}}, \code{\link{>}}, \code{\link{>=}} return a logical vector \cr
#!   \code{\link{^}} and \code{\link{/}} return a double vector\cr
#!   \code{\link{+}}, \code{\link{-}}, \code{\link{*}}, \code{\link{\%/\%}}, \code{\link{\%\%}}
#!    return a vector of class 'integer64'
#! }
#! \author{
#! Jens Oehlschlägel <Jens.Oehlschlaegel@truecluster.com>
#! }
#! \keyword{ classes }
#! \keyword{ manip }
#! \seealso{ \code{\link{format.integer64}} \code{\link{integer64}}  }
#! \examples{
#!   as.integer64(1:12) - 1
#! }


#! \name{sum.integer64}
#! \alias{all.integer64}
#! \alias{any.integer64}
#! \alias{min.integer64}
#! \alias{max.integer64}
#! \alias{range.integer64}
#! \alias{lim.integer64}
#! \alias{sum.integer64}
#! \alias{prod.integer64}
#! \title{
#!    Summary functions for integer64 vectors
#! }
#! \description{
#!   Summary functions for integer64 vectors. 
#!   Function 'range' without arguments returns the smallest and largest value of the 'integer64' class.
#! }
#! \usage{
#! \method{all}{integer64}(\dots, na.rm = FALSE)
#! \method{any}{integer64}(\dots, na.rm = FALSE)
#! \method{min}{integer64}(\dots, na.rm = FALSE)
#! \method{max}{integer64}(\dots, na.rm = FALSE)
#! \method{range}{integer64}(\dots, na.rm = FALSE, finite = FALSE)
#! lim.integer64()
#! \method{sum}{integer64}(\dots, na.rm = FALSE)
#! \method{prod}{integer64}(\dots, na.rm = FALSE)
#! }
#! \arguments{
#!   \item{\dots}{ atomic vectors of class 'integer64'}
#!   \item{na.rm}{ logical scalar indicating whether to ignore NAs }
#!   \item{finite}{ logical scalar indicating whether to ignore NAs (just for compatibility with \code{\link{range.default}}) }
#! }
#! \details{
#!   The numerical summary methods always return \code{integer64}. 
#!   Therefor the methods for \code{min},\code{max} and \code{range} do not return \code{+Inf,-Inf}
#!   on empty arguments, but \code{+9223372036854775807, -9223372036854775807} (in this sequence).
#!   The same is true if only  \code{NA}s are submitted with argument \code{na.rm=TRUE}. 
#!  \cr
#!   \code{lim.integer64} returns these limits in proper order \code{-9223372036854775807, +9223372036854775807} and without a \code{\link{warning}}.
#! }
#! \value{
#!   \code{\link{all}} and \code{\link{any}} return a logical scalar\cr
#!   \code{\link{range}} returns a integer64 vector with two elements\cr
#!   \code{\link{min}}, \code{\link{max}}, \code{\link{sum}} and \code{\link{prod}} return a integer64 scalar
#! }
#! \author{
#! Jens Oehlschlägel <Jens.Oehlschlaegel@truecluster.com>
#! }
#! \keyword{ classes }
#! \keyword{ manip }
#! \seealso{ \code{\link{mean.integer64}} \code{\link{cumsum.integer64}} \code{\link{integer64}}  }
#! \examples{
#!   lim.integer64()
#!   range(as.integer64(1:12))
#! }


#! \name{cumsum.integer64}
#! \alias{cummin.integer64}
#! \alias{cummax.integer64}
#! \alias{cumsum.integer64}
#! \alias{cumprod.integer64}
#! \alias{diff.integer64}
#! \title{
#!    Cumulative Sums, Products, Extremes and lagged differences
#! }
#! \description{
#!   Cumulative Sums, Products, Extremes and lagged differences
#! }
#! \usage{
#! \method{cummin}{integer64}(x)
#! \method{cummax}{integer64}(x)
#! \method{cumsum}{integer64}(x)
#! \method{cumprod}{integer64}(x)
#! \method{diff}{integer64}(x, lag = 1L, differences = 1L, \dots)
#! }
#! \arguments{
#!   \item{x}{ an atomic vector of class 'integer64'}
#!   \item{lag}{ see \code{\link{diff}} }
#!   \item{differences}{ see \code{\link{diff}} }
#!   \item{\dots}{ ignored }
#! }
#! \value{
#!   \code{\link{cummin}}, \code{\link{cummax}} , \code{\link{cumsum}} and \code{\link{cumprod}} 
#!      return a integer64 vector of the same length as their input\cr
#!   \code{\link{diff}} returns a integer64 vector shorter by \code{lag*differences} elements \cr
#! }
#! \author{
#! Jens Oehlschlägel <Jens.Oehlschlaegel@truecluster.com>
#! }
#! \keyword{ classes }
#! \keyword{ manip }
#! \seealso{ \code{\link{sum.integer64}} \code{\link{integer64}}  }
#! \examples{
#!   cumsum(rep(as.integer64(1), 12))
#!   diff(as.integer64(c(0,1:12)))
#!   cumsum(as.integer64(c(0, 1:12)))
#!   diff(cumsum(as.integer64(c(0,0,1:12))), differences=2)
#! }


#! \name{c.integer64}
#! \alias{c.integer64}
#! \alias{cbind.integer64}
#! \alias{rbind.integer64}
#! \title{
#!    Concatenating integer64 vectors
#! }
#! \description{
#!   The ususal functions 'c', 'cbind' and 'rbind'
#! }
#! \usage{
#! \method{c}{integer64}(\dots, recursive = FALSE)
#! \method{cbind}{integer64}(\dots)
#! \method{rbind}{integer64}(\dots)
#! }
#! \arguments{
#!   \item{\dots}{ two or more arguments coerced to 'integer64' and passed to \code{\link{NextMethod}} }
#!   \item{recursive}{ logical. If \code{recursive = TRUE}, the function recursively descends through lists (and pairlists) combining all their elements into a vector. }
#! }
#! \value{
#!   \code{\link{c}} returns a integer64 vector of the total length of the input \cr
#!   \code{\link{cbind}} and \code{\link{rbind}} return a integer64 matrix
#! }
#! \note{
#!   R currently only dispatches generic 'c' to method 'c.integer64' if the first argument is 'integer64'
#! }
#! \author{
#! Jens Oehlschlägel <Jens.Oehlschlaegel@truecluster.com>
#! }
#! \keyword{ classes }
#! \keyword{ manip }
#! \seealso{ \code{\link{rep.integer64}} \code{\link{seq.integer64}} 
#!           \code{\link{as.data.frame.integer64}} \code{\link{integer64}}  
#! }
#! \examples{
#!   c(as.integer64(1), 2:6)
#!   cbind(1:6, as.integer(1:6))
#!   rbind(1:6, as.integer(1:6))
#! }


#! \name{rep.integer64}
#! \alias{rep.integer64}
#! \title{
#!    Replicate elements of integer64 vectors
#! }
#! \description{
#!   Replicate elements of integer64 vectors
#! }
#! \usage{
#! \method{rep}{integer64}(x, \dots)
#! }
#! \arguments{
#!   \item{x}{ a vector of 'integer64' to be replicated }
#!   \item{\dots}{ further arguments passed to \code{\link{NextMethod}} }
#! }
#! \value{
#!   \code{\link{rep}} returns a integer64 vector
#! }
#! \author{
#! Jens Oehlschlägel <Jens.Oehlschlaegel@truecluster.com>
#! }
#! \keyword{ classes }
#! \keyword{ manip }
#! \seealso{ \code{\link{c.integer64}} \code{\link{rep.integer64}} 
#!           \code{\link{as.data.frame.integer64}} \code{\link{integer64}}  
#! }
#! \examples{
#!   rep(as.integer64(1:2), 6)
#!   rep(as.integer64(1:2), c(6,6))
#!   rep(as.integer64(1:2), length.out=6)
#! }


#! \name{seq.integer64}
#! \alias{seq.integer64}
#! \title{
#!    integer64: Sequence Generation
#! }
#! \description{
#!   Generating sequence of integer64 values
#! }
#! \usage{
#! \method{seq}{integer64}(from = NULL, to = NULL, by = NULL, length.out = NULL, along.with = NULL, \dots)
#! }
#! \arguments{
#!   \item{from}{ integer64 scalar (in order to dispatch the integer64 method of \code{\link{seq}} }
#!   \item{to}{ scalar }
#!   \item{by}{ scalar }
#!   \item{length.out}{ scalar }
#!   \item{along.with}{ scalar }
#!   \item{\dots}{ ignored }
#! }
#! \details{
#!   \code{seq.integer64} does coerce its arguments 'from', 'to' and 'by' to \code{integer64}.
#!   If not provided, the argument 'by' is automatically determined as \code{+1} or \code{-1},
#!   but the size of 'by' is not calculated as in \code{\link{seq}} (because this might result in a non-integer value).
#! }
#! \value{
#!   an integer64 vector with the generated sequence
#! }
#! \note{
#!   In base R \code{\link{:}} currently is not generic and does not dispatch, see section "Limitations inherited from Base R" in \code{\link{integer64}}
#! }
#! \author{
#! Jens Oehlschlägel <Jens.Oehlschlaegel@truecluster.com>
#! }
#! \keyword{ classes }
#! \keyword{ manip }
#! \seealso{ \code{\link{c.integer64}} \code{\link{rep.integer64}} 
#!           \code{\link{as.data.frame.integer64}} \code{\link{integer64}}  
#! }
#! \examples{
#!   # colon not activated: as.integer64(1):12
#!   seq(as.integer64(1), 12, 2)
#!   seq(as.integer64(1), by=2, length.out=6)
#! }


#! \name{as.data.frame.integer64}
#! \alias{as.data.frame.integer64}
#! \title{
#!    integer64: Coercing to data.frame column
#! }
#! \description{
#!   Coercing integer64 vector to data.frame.
#! }
#! \usage{
#!   \method{as.data.frame}{integer64}(x, \dots)
#! }
#! \arguments{
#!   \item{x}{ an integer64 vector }
#!   \item{\dots}{ passed to NextMethod \code{\link{as.data.frame}} after removing the 'integer64' class attribute }
#! }
#! \value{
#!   a one-column data.frame containing an integer64 vector
#! }
#! \details{
#!   'as.data.frame.integer64' is rather not intended to be called directly,
#!   but it is required to allow integer64 as data.frame columns.
#! }
#! \note{
#!   This is currently very slow -- any ideas for improvement?
#! }
#! \author{
#! Jens Oehlschlägel <Jens.Oehlschlaegel@truecluster.com>
#! }
#! \keyword{ classes }
#! \keyword{ manip }
#! \seealso{ 
#!   \code{\link{cbind.integer64}} \code{\link{integer64}}  %as.vector.integer64 removed as requested by the CRAN maintainer \code{\link{as.vector.integer64}} 
#! }
#! \examples{
#!   as.data.frame.integer64(as.integer64(1:12))
#!   data.frame(a=1:12, b=as.integer64(1:12))
#! }



#! \name{plusclass}
#! \alias{plusclass}
#! \alias{minusclass}
#! \title{
#!    integer64: Maintaining S3 class attribute
#! }
#! \description{
#!   Maintaining integer64 S3 class attribute.
#! }
#! \usage{
#!   plusclass(class, whichclass)
#!   minusclass(class, whichclass)
#! }
#! \arguments{
#!   \item{class}{ NULL or a character vector of class attributes }
#!   \item{whichclass}{ the (single) class name to add or remove from the class vector  }
#! }
#! \value{
#!   NULL or a character vector of class attributes
#! }
#! \author{
#! Jens Oehlschlägel <Jens.Oehlschlaegel@truecluster.com>
#! }
#! \keyword{ classes }
#! \keyword{ manip }
#! \keyword{ internal }
#! \seealso{ 
#!   \code{\link{oldClass}} \code{\link{integer64}}  
#! }
#! \examples{
#!   plusclass("inheritingclass","integer64")
#!   minusclass(c("inheritingclass","integer64"), "integer64")
#! }


#! \name{all.equal.integer64}
#! \alias{all.equal.integer64}
#! \title{
#!    Test if two integer64 vectors are all.equal
#! }
#! \description{
#!    A utility to compare integer64 objects 'x' and 'y' testing for ‘near equality’, see \code{\link{all.equal}}.
#! }
#! \usage{
#!   \method{all.equal}{integer64}(
#!   target
#! , current
#! , tolerance = sqrt(.Machine$double.eps)
#! , scale = NULL
#! , countEQ = FALSE
#! , formatFUN = function(err, what) format(err)
#! , ...
#! , check.attributes = TRUE
#! )
#! }
#! \arguments{
#!   \item{target}{ a vector of 'integer64' or an object that can be coerced with \code{\link{as.integer64}} }
#!   \item{current}{ a vector of 'integer64' or an object that can be coerced with \code{\link{as.integer64}} }
#!   \item{tolerance}{numeric \eqn{\ge} 0.  Differences smaller than
#!     \code{tolerance} are not reported.  The default value is close to
#!     \code{1.5e-8}.}
#!   \item{scale}{\code{NULL} or numeric > 0, typically of length 1 or
#!     \code{length(target)}.  See \sQuote{Details}.}
#!   \item{countEQ}{logical indicating if the \code{target == current}
#!     cases should be counted when computing the mean (absolute or
#!     relative) differences.  The default, \code{FALSE} may seem
#!     misleading in cases where \code{target} and \code{current} only
#!     differ in a few places; see the extensive example.}
#!   \item{formatFUN}{a \code{\link{function}} of two arguments,
#!     \code{err}, the relative, absolute or scaled error, and
#!     \code{what}, a character string indicating the \emph{kind} of error;
#!     maybe used, e.g., to format relative and absolute errors differently.}
#!   \item{\dots}{further arguments are ignored}
#!   \item{check.attributes}{logical indicating if the
#!     \code{\link{attributes}} of \code{target} and \code{current}
#!     (other than the names) should be compared.}
#! }
#! \value{
#!   Either ‘TRUE’ (‘NULL’ for ‘attr.all.equal’) or a vector of ‘mode’
#!   ‘"character"’ describing the differences between ‘target’ and
#!   ‘current’.
#! }
#! \details{
#!    In \code{\link{all.equal.numeric}} the type \code{integer} is treated as a proper subset of \code{double} 
#!    i.e. does not complain about comparing \code{integer} with \code{double}. 
#!    Following this logic \code{all.equal.integer64} treats \code{integer} as a proper subset of \code{integer64} 
#!    and does not complain about comparing \code{integer} with \code{integer64}. \code{double} also compares without warning 
#!    as long as the values are within \code{\link{lim.integer64}}, if \code{double} are bigger \code{all.equal.integer64}
#!    complains about the \code{all.equal.integer64 overflow warning}. For further details see \code{\link{all.equal}}.
#! }
#! \note{
#!    \code{\link{all.equal}} only dispatches to this method if the first argument is \code{integer64}, 
#!    calling \code{\link{all.equal}} with a \code{non-integer64} first and a \code{integer64} second argument 
#!    gives undefined behavior!
#! }
#! \author{
#!   Leonardo Silvestri (for package nanotime)
#! }
#! \seealso{
#!   \code{\link{all.equal}}
#! }
#! \examples{
#!   all.equal(as.integer64(1:10), as.integer64(0:9))
#!   all.equal(as.integer64(1:10), as.integer(1:10))
#!   all.equal(as.integer64(1:10), as.double(1:10))
#!   all.equal(as.integer64(1), as.double(1e300))
#! }

# if (!exists(":.default")){
	# ":.default" <- get(":")
	# ":" <- function(from,to)UseMethod(":")
# }

setOldClass("integer64")


# contributed by Leonardo Silvestri with modifications of JO
all.equal.integer64  <- function (
  target
, current
, tolerance = sqrt(.Machine$double.eps)
, scale = NULL
, countEQ = FALSE
, formatFUN = function(err, what) format(err)
, ...
, check.attributes = TRUE
) 
{
  if (!is.numeric(tolerance)) 
    stop("'tolerance' should be numeric")
  if (!is.numeric(scale) && !is.null(scale)) 
    stop("'scale' should be numeric or NULL")
  if (!is.logical(check.attributes)) 
    stop(gettextf("'%s' must be logical", "check.attributes"), 
         domain = NA)
  # JO: BEGIN respect that integer is a proper subset of integer64 like integer is a proper subset of double
  oldwarn <- getOption("warn")
  on.exit(options(warn=oldwarn))
  options(warn=2L)
  if (!is.integer64(target)){
    cl <- oldClass(target)
    oldClass(target) <- NULL
    target <- try(as.integer64(target))
    if (inherits(target, 'try-error'))
      return(paste("while coercing 'target' to 'integer64':",  attr(target, "condition")$message))
    oldClass(target) <- c(cl, "integer64")
  }
  if (!is.integer64(current)){
    cl <- oldClass(current)
    oldClass(current) <- NULL
    current <- try(as.integer64(current))
    if (inherits(current, 'try-error'))
      return(paste("while coercing 'current' to 'integer64':",  attr(current, "condition")$message))
    oldClass(current) <- c(cl, "integer64")
  }
  # JO: END respect that integer is a proper subset of integer64 like integer is a proper subset of double
  msg <- NULL
  msg <- if (check.attributes)
           attr.all.equal(target, current, tolerance = tolerance, 
                          scale = scale, ...)
  if (data.class(target) != data.class(current)) {
    msg <- c(msg, paste0("target is ", data.class(target), 
                         ", current is ", data.class(current)))
    return(msg)
  }
  lt <- length(target)
  lc <- length(current)
  if (lt != lc) {
    if (!is.null(msg)) 
      msg <- msg[-grep("\\bLengths\\b", msg)]
    msg <- c(msg, paste0("integer64: lengths (", lt, ", ", lc, ") differ"))
    return(msg)
  }
  out <- is.na(target)
  if (any(out != is.na(current))) {
    msg <- c(msg, paste("'is.NA' value mismatch:", sum(is.na(current)), 
                        "in current", sum(out), "in target"))
    return(msg)
  }
  out <- out | target == current
  if (all(out)) 
    return(if (is.null(msg)) TRUE else msg)
  if (countEQ) {
    N <- length(out)
    sabst0 <- sum(abs(target[out]))
  } else {
    sabst0 <- 0
  }
  target <- target[!out]
  current <- current[!out]
  if (!countEQ) 
    N <- length(target)
  xy <- sum(abs(target - current))/N
  what <- if (is.null(scale)) {
            xn <- (sabst0 + sum(abs(target)))/N
            if (is.finite(xn) && xn > tolerance) {
              xy <- xy/xn
              "relative"
            } else {
              "absolute"
            }
          } else {
            stopifnot(all(scale > 0))
            xy <- xy/scale
            if (all(abs(scale - 1) < 1e-07)) 
              "absolute"
            else "scaled"
          }
  if (is.na(xy) || xy > tolerance) 
    msg <- c(msg, paste("Mean", what, "difference:", formatFUN(xy, what)))
  if (is.null(msg)) {
    TRUE
  } else msg
}

if (FALSE){
  require(bit64)
  a <- as.integer64(1)
  b <- as.integer(10)
  oldClass(a) <- c("j", oldClass(a))
  oldClass(b) <- c("j", oldClass(b))
  all.equal(a,b)
  
  a <- as.double(1)
  b <- as.integer(10)
  oldClass(a) <- c("j", oldClass(a))
  oldClass(b) <- c("j", oldClass(b))
  all.equal(a,b)
  
  a <- as.integer64(9e17)
  b <- 9e18
  oldClass(a) <- c("j", oldClass(a))
  oldClass(b) <- c("j", oldClass(b))
  all.equal(a,b)
  
  a <- as.integer64(9e18)
  b <- 9e19
  oldClass(a) <- c("j", oldClass(a))
  oldClass(b) <- c("j", oldClass(b))
  all.equal(a,b)
  
  a <- as.integer64(c(1,NA))
  b <- as.integer(c(1,NA))
  all.equal(a,b)
  
  a <- as.integer64(c(1,NA))
  b <- as.double(c(1,NA))
  all.equal(a,b)
  
  a <- as.integer64(c(1,Inf))
  b <- as.integer(c(1,Inf))
  all.equal(a,b)
  
  a <- as.integer64(c(1,Inf))
  b <- as.double(c(1,Inf))
  all.equal(a,b)
}


identical.integer64 <- function(x, y
, num.eq = FALSE
, single.NA = FALSE
, attrib.as.set = TRUE
, ignore.bytecode = TRUE
)
identical(x=x, y=y
, num.eq = num.eq
, single.NA = single.NA
, attrib.as.set = attrib.as.set
, ignore.bytecode = ignore.bytecode
)


as.integer64 <- function (x, ...) 
UseMethod("as.integer64")

as.bitstring <- function(x, ...)
UseMethod("as.bitstring")



minusclass <- function(class, whichclass){
  if (length(class)){
	  i <- whichclass==class
	  if (any(i))
		class[!i]
	  else
		class
  }else
    class
}

plusclass <- function(class, whichclass){
  if (length(class)){
	  i <- whichclass==class
	  if (any(i))
		class
	  else
		c(class, whichclass)
  }else
    whichclass
}

if (FALSE){
  # version until 0.9-7
	binattr <- function(e1,e2){
		d1 <- dim(e1)
		d2 <- dim(e2)
		n1 <- length(e1)
		n2 <- length(e2)
		if (length(d1)){
		  if (length(d2)){
			if (!identical(dim(e1),dim(e2)))
			stop("non-conformable arrays")
		}else{
			if (n2>n1)
			  stop("length(e2) does not match dim(e1)")
			if (n1%%n2)
			warning("length(e1) not a multiple length(e2)")
		}
		attributes(e1)
		}else{
		  if (length(d2)){
			if (n1>n2)
			  stop("length(e1) does not match dim(n2)")
			if (n2%%n1)
			warning("length(e2) not a multiple length(e1)")
			attributes(e2)
		}else{
			if (n1<n2){
			if (n2%%n1)
				warning("length(e2) not a multiple length(e1)")
			}else{
			if (n1%%n2)
				warning("length(e1) not a multiple length(e2)")
			}
			attributes(e1)
		}
		}
	}
}

# Version of Leonardo Silvestri
binattr <- function(e1, e2) {
  d1 <- dim(e1)
  d2 <- dim(e2)
  n1 <- length(e1)
  n2 <- length(e2)
  
  ## this first part takes care of erroring out when the dimensions
  ## are not compatible or warning if needed:
  if (length(d1)) {
    if (length(d2)) {
      if (!identical(dim(e1), dim(e2)))
        stop("non-conformable arrays")
    } else{
      if (n2 > n1 && n1)
        stop("length(e2) does not match dim(e1)")
      if (n2 && n1 %% n2)
        warning("length(e1) not a multiple length(e2)")
    }
  } else{
    if (length(d2)) {
      if (n1 > n2 && n2)
        stop("length(e1) does not match dim(n2)")
      if (n1 && n2 %% n1)
        warning("length(e2) not a multiple length(e1)")
    } else{
      if (n1 < n2 && n1) {
        if (n1 && n2 %% n1)
          warning("length(e2) not a multiple length(e1)")
      } else{
        if (n2 && n1 %% n2)
          warning("length(e1) not a multiple length(e2)")
      }
    }
  }
  
  ## in this part we mimic R's algo for selecting attributes:
  if (n1 == n2){
    ## if same size take attribute from e1 if it exists, else from e2
    if (n1==0){
      ae1 <- attributes(e1)[c("class","dim","dimnames")]
      ae2 <- attributes(e2)[c("class","dim","dimnames")]
    }
    ae1 <- attributes(e1)
    ae2 <- attributes(e2)
    nae1 <- names(attributes(e1))
    nae2 <- names(attributes(e2))
    if (n1==0){
      ae1 <- ae1[nae1 %in% c("class","dim","dimnames")]
      ae2 <- ae1[nae1 %in% c("class","dim","dimnames")]
    }
    allattr <- list()
    for (a in union(nae1, nae2))
      if (a %in% nae1)
        allattr[[a]] <- ae1[[a]]
    else
      allattr[[a]] <- ae2[[a]]
    allattr
  }else if (n1 == 0 || n1 > n2) {
    attributes(e1)
  } else {
    attributes(e2)
  }
}


if (FALSE){
  x <- integer64(0)
  y <- integer64(0)
  #dim(x) <- c(2L,2L)
  dim(y) <- c(0L,0L)
  dimnames(y) <- list(character(0),character(0))
  #dim(x) <- c(1L,4L)
  #dim(y) <- c(4L,1L)
  
  attr(x,"x") <- "x"
  attr(y,"y") <- "y"
  
  z <- x - y
  z
  dim(z)
  dimnames(z)
  
  z <- y - x
  z
  dim(z)
  dimnames(z)
  
  ret <- "integer64(0)"
  attributes(ret) <- list(dim = c(0L, 0L), class = character(0), dimnames = list(NULL,NULL))
  
}

integer64 <- function(length=0){
  ret <- double(length)
  oldClass(ret) <- "integer64"
  ret
}

is.integer64 <- function(x)inherits(x, "integer64")

as.integer64.NULL <- function (x, ...){
  ret <- double()
  oldClass(ret) <- "integer64"
  ret
}

as.integer64.integer64 <- function(x, ...)x

as.integer64.double <- function(x, keep.names=FALSE, ...){
  ret <- .Call(C_as_integer64_double, x, double(length(x)))
  if (keep.names)
    names(ret) <- names(x)
  oldClass(ret) <- "integer64"
  ret
}

as.integer64.logical <- as.integer64.integer <- function(x, ...){
  ret <- .Call(C_as_integer64_integer, x, double(length(x)))
  oldClass(ret) <- "integer64"
  ret
}

as.integer64.character <- function(x, ...){
  n <- length(x)
  ret <- .Call(C_as_integer64_character, x, rep(as.double(NA), n))
  oldClass(ret) <- "integer64"
  ret
}

as.integer64.factor <- function(x, ...)
as.integer64(unclass(x), ...)

as.double.integer64 <- function(x, keep.names=FALSE, ...){
  ret <- .Call(C_as_double_integer64, x, double(length(x)))
  if (keep.names)
    names(ret) <- names(x)
  ret
}

as.integer.integer64 <- function(x, ...){
  .Call(C_as_integer_integer64, x, integer(length(x)))
}

as.logical.integer64 <- function(x, ...){
  .Call(C_as_logical_integer64, x, logical(length(x)))
}

as.character.integer64 <- function(x, ...){
  n <- length(x)
  .Call(C_as_character_integer64, x, rep(as.character(NA), n))
}

as.bitstring.integer64 <- function(x, ...){
  n <- length(x)
  ret <- .Call(C_as_bitstring_integer64, x, rep(as.character(NA), n))
  oldClass(ret) <- 'bitstring'
  ret
}

print.bitstring <- function(x, ...){
  oldClass(x) <- minusclass(class(x), 'bitstring')
  NextMethod(x)
}

as.integer64.bitstring <- function(x, ...){
  n <- length(x)
  ret <- .Call(C_as_integer64_bitstring, x, double(length(x)))
  oldClass(ret) <- "integer64"
  ret
}


# read.table expects S4 as() 
setAs("character","integer64",function(from)as.integer64.character(from))
setAs("integer64","character",function(from)as.character.integer64(from))

# this is a trick to generate NA_integer64_ for namespace export before 
# as.integer64() is available because dll is not loaded
NA_integer64_ <- unserialize(as.raw(c(0x58, 0x0a, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x03, 
+ 0x00, 0x00, 0x02, 0x03, 0x00, 0x00, 0x00, 0x03, 0x0e, 0x00, 0x00, 
+ 0x00, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+ 0x00, 0x04, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x09, 
+ 0x00, 0x00, 0x00, 0x05, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x00, 0x00, 
+ 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x09, 0x00, 
+ 0x00, 0x00, 0x09, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x65, 0x72, 0x36, 
+ 0x34, 0x00, 0x00, 0x00, 0xfe)))

"length<-.integer64" <- function(x, value){
  cl <- oldClass(x)
  n <- length(x)
  x <- NextMethod()
  oldClass(x) <- cl
  if (value>n)
    x[(n+1):value] <- 0L
  x
}


format.integer64 <- function(x, justify="right", ...){
  a <- attributes(x)
  x <- as.character(x)
  ret <- format(x, justify=justify, ...)
  a$class <- minusclass(a$class, "integer64")
  attributes(ret) <- a
  ret
}

print.integer64 <- function(x, quote=FALSE, ...){
  a <- attributes(x)
  if (length(x)){
    cat("integer64\n")
    ret <- as.character(x)
    a$class <- minusclass(a$class, "integer64")
    attributes(ret) <- a
    print(ret, quote=quote, ...)
  }else{
    cat("integer64(0)\n")
  }
  invisible(x)
}

str.integer64 <- function(object
, vec.len  = strO$vec.len
, give.head = TRUE
, give.length = give.head
, ...
){
  strO <- strOptions()
  vec.len <- 2*vec.len
  n <- length(object)
  if (n>vec.len)
    object <- object[seq_len(vec.len)]
  cat(if (give.head)paste("integer64 ", if (give.length && n>1) paste("[1:",n,"] ",sep=""), sep=""), paste(as.character(object), collapse=" "),if(n>vec.len)" ...", " \n", sep="")
  invisible()
}

if (FALSE){
	require(microbenchmark)
	require(bit64)
	x <- runif64(1e7)
	microbenchmark(x[TRUE], times=10)
	microbenchmark(x[NA], times=10)
  i <- seq_along(x)
	i[1] <- NA
	microbenchmark(x[i], times=10)
	i <- rep(TRUE, length(x))
	i[1] <- NA
	microbenchmark(x[i], times=10)
  i <- seq_along(x)
	microbenchmark(x[i], times=10)
	i <- rep(TRUE, length(x))
	microbenchmark(x[i], times=10)

}


"[.integer64" <- function(x, i, ...){
	cl <- oldClass(x)
	ret <- NextMethod()
	# Begin NA-handling from Leonardo Silvestri
	if (!missing(i)){
		if (class(i) == "character") {
		  na_idx <- union(which(!(i %in% names(x))), which(is.na(i)))
		  if (length(na_idx))
				ret[na_idx] <- NA_integer64_
		}else{ 
			if (class(i) == "logical"){
		    i <- i[is.na(i) | i]
		    na_idx <- rep(is.na(i), length.out=length(ret))
		  }else{
		    na_idx <- is.na(i)
		  }
		  if (any(na_idx))
				ret[na_idx] <- NA_integer64_
		}
	}
	# End NA-handling from Leonardo Silvestri
	oldClass(ret) <- cl
	remcache(ret)
	ret
}


"[<-.integer64" <- function(x,...,value){
  cl <- oldClass(x)
  value <- as.integer64(value)
  ret <- NextMethod()
  oldClass(ret) <- cl
  ret
}

"[[.integer64" <- function(x,...){
  cl <- oldClass(x)
  ret <- NextMethod()
  oldClass(ret) <- cl
  ret
}

"[[<-.integer64" <- function(x,...,value){
  cl <- oldClass(x)
  value <- as.integer64(value)
  ret <- NextMethod()
  oldClass(ret) <- cl
  ret
}

c.integer64 <-
function (..., recursive = FALSE) 
{
	l <- list(...)
	K <- length(l)
	for (k in 1:K){
		if (recursive && is.list(l[[k]])){
			l[[k]] <- do.call("c.integer64", c(l[[k]], list(recursive = TRUE)))
		}else{
			if (!is.integer64(l[[k]])) {
				nam <- names(l[[k]])
				l[[k]] <- as.integer64(l[[k]])
				names(l[[k]]) <- nam
			}
			oldClass(l[[k]]) <- NULL
		}
	}
	ret <- do.call("c", l)
	oldClass(ret) <- "integer64"
	ret
}


cbind.integer64 <- function(...){
  l <- list(...)
	K <- length(l)
  for (k in 1:K){
		if (!is.integer64(l[[k]])){
			nam <- names(l[[k]])
			l[[k]] <- as.integer64(l[[k]])
			names(l[[k]]) <- nam
		}
		oldClass(l[[k]]) <- NULL
  }
  ret <- do.call("cbind", l)
	oldClass(ret) <- "integer64"
  ret
}

rbind.integer64 <- function(...){
  l <- list(...)
	K <- length(l)
  for (k in 1:K){
		if (!is.integer64(l[[k]])){
			nam <- names(l[[k]])
			l[[k]] <- as.integer64(l[[k]])
			names(l[[k]]) <- nam
		}
		oldClass(l[[k]]) <- NULL
  }
  ret <- do.call("rbind", l)
	oldClass(ret) <- "integer64"
  ret
}

# tenfold runtime if using attr() here instead of setattr()
# as.data.frame.integer64 <- function(x, ...){
  # cl <- oldClass(x)
  # oldClass(x) <- minusclass(cl, "integer64")
  # ret <- as.data.frame(x, ...)
  # k <- length(ret)
  # for (i in 1:k)
    # oldClass(ret[[i]]) <- cl
  # ret
# }
as.data.frame.integer64 <- function(x, ...){
  cl <- oldClass(x)
  on.exit(setattr(x, "class", cl))
  setattr(x, "class", minusclass(cl, "integer64"))
  ret <- as.data.frame(x, ...)
  k <- length(ret)
  for (i in 1:k)
   setattr(ret[[i]], "class", cl) 
  ret
}


"rep.integer64" <- function(x, ...){
	cl <- oldClass(x)
	ret <- NextMethod()
	oldClass(ret) <- cl
	ret
}

# FIXME no method dispatch for :
":.integer64" <- function(from, to){
  from <- as.integer64(from)
  to <- as.integer64(to)
  ret <- .Call(C_seq_integer64, from, as.integer64(1L), double(as.integer(to-from+1L)))
  oldClass(ret) <- "integer64"
  ret
}

"seq.integer64" <- function(from=NULL, to=NULL, by=NULL, length.out=NULL, along.with=NULL, ...){
    if (is.null(length.out))
      length.out <- length(along.with)
    else 
      length.out <- as.integer(length.out)
	
    if (is.null(by)){
      if (is.null(from) || is.null(to))
	    by <- as.integer64(1L)
	  else
	    by <- as.integer64(sign(to-from))
    }else{
	  by <- as.integer64(by)
	  if ((!is.null(from)) && (!is.null(to)) && sign(by)!=sign(to-from))
        stop("wrong sign of 'by' argument")
    }
  
    if (is.null(from)){
      if (length.out && length(to))
	    from <- to - (length.out-1L)*by
	  else
	    from <- as.integer64(1)
    }else 
	  from <- as.integer64(from)
	  
	if (!length(to)){
	  if (length.out)
	    to <- from + (length.out-1L)*by
      else
		stop("not enough informatoin provided")
	}
	
    if (!length.out){
	  length.out <- (to-from) %/% by + 1L
    }

    if (length.out){
      if (length.out==1L)
        return(from)
      else{
        #return(cumsum(c(from, rep(by, length.out-1L))))
		ret <- .Call(C_seq_integer64, from, by, double(as.integer(length.out)))
		oldClass(ret) <- "integer64"
		return(ret)
	  }
    }else
      return(integer64())
}


"+.integer64" <- function(e1, e2){
  if (missing(e2))
    return(e1)
  a <- binattr(e1,e2)
  e1 <- as.integer64(e1)
  e2 <- as.integer64(e2)
  ret <- .Call(C_plus_integer64, e1, e2, double(max(length(e1),length(e2))))
  a$class <- plusclass(a$class, "integer64")
  attributes(ret) <- a
  ret
}

"-.integer64" <- function(e1, e2){
  if (missing(e2)){
    e2 <- e1
	e1 <- 0L
  }
  a <- binattr(e1,e2)
  e1 <- as.integer64(e1)
  e2 <- as.integer64(e2)
  ret <- .Call(C_minus_integer64, e1, e2, double(max(length(e1),length(e2))))
  a$class <- plusclass(a$class, "integer64")
  attributes(ret) <- a
  ret
}

"%/%.integer64" <- function(e1, e2){
  a <- binattr(e1,e2)
  e1 <- as.integer64(e1)
  e2 <- as.integer64(e2)
  ret <- .Call(C_intdiv_integer64, e1, e2, double(max(length(e1), length(e2))))
  a$class <- plusclass(a$class, "integer64")
  attributes(ret) <- a
  ret
}

"%%.integer64" <- function(e1, e2){
  a <- binattr(e1,e2)
  e1 <- as.integer64(e1)
  e2 <- as.integer64(e2)
  ret <- .Call(C_mod_integer64, e1, e2, double(max(length(e1), length(e2))))
  a$class <- plusclass(a$class, "integer64")
  attributes(ret) <- a
  ret
}


"*.integer64" <- function(e1, e2){
  a <- binattr(e1,e2)
  if (is.double(e2))  # implies !is.integer64(e2)
    ret <- .Call(C_times_integer64_double, as.integer64(e1), e2, double(max(length(e1),length(e2))))
  else
    ret <- .Call(C_times_integer64_integer64, as.integer64(e1), as.integer64(e2), double(max(length(e1),length(e2))))
  a$class <- plusclass(a$class, "integer64")
  attributes(ret) <- a
  ret
}

"^.integer64" <- function(e1, e2){
  a <- binattr(e1,e2)
  if (is.double(e2))  # implies !is.integer64(e2)
    ret <- .Call(C_power_integer64_double, as.integer64(e1), e2, double(max(length(e1),length(e2))))
  else
    ret <- .Call(C_power_integer64_integer64, as.integer64(e1), as.integer64(e2), double(max(length(e1),length(e2))))
  a$class <- plusclass(a$class, "integer64")
  attributes(ret) <- a
  ret
}

"/.integer64" <- function(e1, e2){
  a <- binattr(e1,e2)
  if (is.double(e2))  # implies !is.integer64(e2)
    ret <- .Call(C_divide_integer64_double, as.integer64(e1), e2, double(max(length(e1),length(e2))))
  else
    ret <- .Call(C_divide_integer64_integer64, as.integer64(e1), as.integer64(e2), double(max(length(e1),length(e2))))
  a$class <- minusclass(a$class, "integer64")
  attributes(ret) <- a
  ret
}


"sign.integer64" <- function(x){
  a <- attributes(x)
  ret <- .Call(C_sign_integer64, x, double(length(x)))
  attributes(ret) <- a
  ret
}

"abs.integer64" <- function(x){
  a <- attributes(x)
  ret <- .Call(C_abs_integer64, x, double(length(x)))
  attributes(ret) <- a
  ret
}

"sqrt.integer64" <- function(x){
  a <- attributes(x)
  ret <- .Call(C_sqrt_integer64, x, double(length(x)))
  a$class <- minusclass(a$class, "integer64")
  attributes(ret) <- a
  ret
}

"log.integer64" <- function(x, base=NULL){
  a <- attributes(x)
  ret <- if (is.null(base)){
	  .Call(C_log_integer64, x, double(max(length(x),length(base))))
  }else if(length(base)==1){
    .Call(C_logbase_integer64, x, as.double(base), double(max(length(x),length(base))))
  }else{
    .Call(C_logvect_integer64, x, as.double(base), double(max(length(x),length(base))))
  }
  a$class <- minusclass(a$class, "integer64")
  attributes(ret) <- a
  ret
}

"log10.integer64" <- function(x){
  a <- attributes(x)
  ret <- .Call(C_log10_integer64, x, double(length(x)))
  a$class <- minusclass(a$class, "integer64")
  attributes(ret) <- a
  ret
}

"log2.integer64" <- function(x){
  a <- attributes(x)
  ret <- .Call(C_log2_integer64, x, double(length(x)))
  a$class <- minusclass(a$class, "integer64")
  attributes(ret) <- a
  ret
}

"trunc.integer64" <- function(x, ...)x
"floor.integer64" <- "ceiling.integer64" <- function(x)x

"signif.integer64" <- function(x, digits=6)x

"scale.integer64" <- function(x, center = TRUE, scale = TRUE)scale(as.double(x, keep.names=TRUE), center=center, scale=scale)

"round.integer64" <- function(x, digits=0){
  if (digits<0){
    a <- attributes(x)
    b <- 10^round(-digits)
    b2 <- b %/% 2
    d <- (x %/% b)
    db <- d * b
    r <- abs(x-db)
    ret <- ifelse((r < b2) | (r == b2 & ((d %% 2L) == 0L)), db, db + sign(x)*b)
    #a$class <- minusclass(a$class, "integer64")
    attributes(ret) <- a
    ret
  }else
    x
}




"any.integer64" <- function(..., na.rm = FALSE){
  l <- list(...)
  if (length(l)==1){
		  .Call(C_any_integer64, l[[1]], na.rm, logical(1))
  }else{
	  any(sapply(l, function(e){
  		if (is.integer64(e)){
  		  .Call(C_any_integer64, e, na.rm, logical(1))
  		}else{
  		  any(e, na.rm = na.rm)
  		}
	  }), na.rm = na.rm)
  }
}

"all.integer64" <- function(..., na.rm = FALSE){
  l <- list(...)
  if (length(l)==1){
		  .Call(C_all_integer64, l[[1]], na.rm, logical(1))
  }else{
	  all(sapply(l, function(e){
  		if (is.integer64(e)){
  		  .Call(C_all_integer64, e, na.rm, logical(1))
  		}else{
  		  all(e, na.rm = na.rm)
  		}
	  }), na.rm = na.rm)
  }
}

"sum.integer64" <- function(..., na.rm = FALSE){
  l <- list(...)
  if (length(l)==1){
		  ret <- .Call(C_sum_integer64, l[[1]], na.rm, double(1))
		  oldClass(ret) <- "integer64"
		  ret
  }else{
	  ret <- sapply(l, function(e){
		if (is.integer64(e)){
		  .Call(C_sum_integer64, e, na.rm, double(1))
		}else{
		  as.integer64(sum(e, na.rm = na.rm))
		}
	  })
    oldClass(ret) <- "integer64"
	  sum(ret, na.rm = na.rm)
  }
}



"prod.integer64" <- function(..., na.rm = FALSE){
  l <- list(...)
  if (length(l)==1){
    ret <- .Call(C_prod_integer64, l[[1]], na.rm, double(1))
		oldClass(ret) <- "integer64"
		ret
  }else{
      ret <- sapply(l, function(e){
		if (is.integer64(e)){
		  .Call(C_prod_integer64, e, na.rm, double(1))
		}else{
		  as.integer64(prod(e, na.rm = na.rm))
		}
	  })
	  oldClass(ret) <- "integer64"
	  prod(ret, na.rm = na.rm)
  }
}


"min.integer64" <- function(..., na.rm = FALSE){
  l <- list(...)
  noval <- TRUE
  if (length(l)==1){
    if (length(l[[1]]))
      noval <- FALSE
    ret <- .Call(C_min_integer64, l[[1]], na.rm, double(1))
    oldClass(ret) <- "integer64"
  }else{
    ret <- sapply(l, function(e){
      if (length(e))
        noval <<- FALSE
      if (is.integer64(e)){
        .Call(C_min_integer64, e, na.rm, double(1))
      }else{
        as.integer64(min(e, na.rm = na.rm))
      }
    })
    oldClass(ret) <- "integer64"
    ret <- min(ret, na.rm = na.rm)
  }
  if (noval)
    warning("no non-NA value, returning +9223372036854775807")
  ret
}


"max.integer64" <- function(..., na.rm = FALSE){
  l <- list(...)
  noval <- TRUE
  if (length(l)==1){
	if (length(l[[1]]))
	  noval <- FALSE
	  ret <- .Call(C_max_integer64, l[[1]], na.rm, double(1))
	oldClass(ret) <- "integer64"
  }else{
	ret <- sapply(l, function(e){
	    if (length(e))
	      noval <<- FALSE
		if (is.integer64(e)){
		  .Call(C_max_integer64, e, na.rm, double(1))
		}else{
		  as.integer64(max(e, na.rm = na.rm))
		}
	})
	oldClass(ret) <- "integer64"
	ret <- max(ret, na.rm = na.rm)
  }
  if (noval)
	warning("no non-NA value, returning -9223372036854775807")
  ret
}


"range.integer64" <- function(..., na.rm = FALSE, finite = FALSE){
  if (finite)
    na.rm = TRUE
  l <- list(...)
  noval <- TRUE
  if (length(l)==1){
	if (length(l[[1]]))
	  noval <- FALSE
	  ret <- .Call(C_range_integer64, l[[1]], na.rm, double(2))
	oldClass(ret) <- "integer64"
  }else{
      ret <- unlist(sapply(l, function(e){
	    if (length(e))
	      noval <<- FALSE
		if (is.integer64(e)){
		  .Call(C_range_integer64, e, na.rm, double(2))
		}else{
		  as.integer64(range(e, na.rm = na.rm))
		}
	  }))
	  oldClass(ret) <- "integer64"
	  ret <- range(ret, na.rm = na.rm)
  }
  if (noval)
	warning("no non-NA value, returning c(+9223372036854775807, -9223372036854775807)")
  ret
}


lim.integer64 <- function(){
  ret <- .Call(C_lim_integer64, double(2))
	oldClass(ret) <- "integer64"
	return(ret)
}

"diff.integer64" <- function(x, lag=1L, differences=1L, ...){
  lag <- as.integer(lag)
  n <- length(x)
  d <- differences <- as.integer(differences)
  while(d > 0L){
    n <- n - lag
    if (n <= 0L){
      ret <- double()
      break
    }
    # not assigning ret<-.Call in the following is intended because faster
    if (d==differences){
      ret <- double(n)
      .Call(C_diff_integer64, x, as.integer64(lag), as.integer64(n), ret)
    }else{
      .Call(C_diff_integer64, ret, as.integer64(lag), as.integer64(n), ret)
    }
    d <- d - 1L
  }
  # length of ret is only change once here
  length(ret) <- n
  oldClass(ret) <- "integer64"
  ret
}


"cummin.integer64" <- function(x){
  ret <- .Call(C_cummin_integer64, x, double(length(x)))
  oldClass(ret) <- "integer64"
  ret
}
"cummax.integer64" <- function(x){
  ret <- .Call(C_cummax_integer64, x, double(length(x)))
  oldClass(ret) <- "integer64"
  ret
}

"cumsum.integer64" <- function(x){
  ret <- .Call(C_cumsum_integer64, x, double(length(x)))
  oldClass(ret) <- "integer64"
  ret
}

"cumprod.integer64" <- function(x){
  ret <- .Call(C_cumprod_integer64, x, double(length(x)))
  oldClass(ret) <- "integer64"
  ret
}



"is.na.integer64" <- function(x){
  a <- attributes(x)
  ret <- .Call(C_isna_integer64, x, logical(length(x)))
  a$class <- minusclass(a$class, "integer64")
  attributes(ret) <- a
  ret
}

"is.finite.integer64" <- function(x)!is.na(x)
"is.infinite.integer64" <- function(x)rep(FALSE, length(x))
"is.nan.integer64" <- function(x)rep(FALSE, length(x))


"==.integer64" <- function(e1, e2){
  a <- binattr(e1,e2)
  e1 <- as.integer64(e1)
  e2 <- as.integer64(e2)
  ret <- .Call(C_EQ_integer64, e1, e2, logical(max(length(e1), length(e2))))
  a$class <- minusclass(a$class, "integer64")
  attributes(ret) <- a
  ret
}

"!=.integer64" <- function(e1, e2){
  a <- binattr(e1,e2)
  e1 <- as.integer64(e1)
  e2 <- as.integer64(e2)
  ret <- .Call(C_NE_integer64, e1, e2, logical(max(length(e1), length(e2))))
  a$class <- minusclass(a$class, "integer64")
  attributes(ret) <- a
  ret
}

"<.integer64" <- function(e1, e2){
  a <- binattr(e1,e2)
  e1 <- as.integer64(e1)
  e2 <- as.integer64(e2)
  ret <- .Call(C_LT_integer64, e1, e2, logical(max(length(e1), length(e2))))
  a$class <- minusclass(a$class, "integer64")
  attributes(ret) <- a
  ret
}

"<=.integer64" <- function(e1, e2){
  a <- binattr(e1,e2)
  e1 <- as.integer64(e1)
  e2 <- as.integer64(e2)
  ret <- .Call(C_LE_integer64, e1, e2, logical(max(length(e1), length(e2))))
  a$class <- minusclass(a$class, "integer64")
  attributes(ret) <- a
  ret
}

">.integer64" <- function(e1, e2){
  a <- binattr(e1,e2)
  e1 <- as.integer64(e1)
  e2 <- as.integer64(e2)
  ret <- .Call(C_GT_integer64, e1, e2, logical(max(length(e1), length(e2))))
  a$class <- minusclass(a$class, "integer64")
  attributes(ret) <- a
  ret
}

">=.integer64" <- function(e1, e2){
  a <- binattr(e1,e2)
  e1 <- as.integer64(e1)
  e2 <- as.integer64(e2)
  ret <- .Call(C_GE_integer64, e1, e2, logical(max(length(e1), length(e2))))
  a$class <- minusclass(a$class, "integer64")
  attributes(ret) <- a
  ret
}

"&.integer64" <- function(e1, e2){
  a <- binattr(e1,e2)
  ret <- as.logical(e1) & as.logical(e2)
  a$class <- minusclass(a$class, "integer64")
  attributes(ret) <- a
  ret
}

"|.integer64" <- function(e1, e2){
  a <- binattr(e1,e2)
  ret <- as.logical(e1) | as.logical(e2)
  a$class <- minusclass(a$class, "integer64")
  attributes(ret) <- a
  ret
}

xor.integer64 <- function(x, y){
  a <- binattr(x,y)
  ret <- as.logical(x) != as.logical(y)
  a$class <- minusclass(a$class, "integer64")
  attributes(ret) <- a
  ret
}


"!.integer64" <- function(x){
  a <- attributes(x)
  ret <- !as.logical(x)
  a$class <- minusclass(a$class, "integer64")
  attributes(ret) <- a
  ret
}

# as.vector.integer64 removed as requested by the CRAN maintainer
# as.vector.integer64 <- function(x, mode="any"){
  # ret <- NextMethod()
  # if (mode=="any")
	# oldClass(ret) <- "integer64"
  # ret
# }

# bug in R does not dispatch
is.vector.integer64 <- function(x, mode="any"){
  cl <- minusclass(oldClass(x), "integer64")
  a <- attributes(x)
  a$class <- NULL
  a$names <- NULL
  if (is.na(match(mode, c("any","integer64"))) || length(cl) || length(a) )
    FALSE
  else
    TRUE
}


