R/sortuse64.R

Defines functions orderqtl.integer64 orderqtl sortqtl.integer64 sortqtl sortorderrnk.integer64 sortorderrnk orderrnk.integer64 orderrnk sortorderkey.integer64 sortorderkey orderkey.integer64 orderkey sortordertab.integer64 sortordertab ordertab.integer64 ordertab sorttab.integer64 sorttab sortordertie.integer64 sortordertie ordertie.integer64 ordertie sortorderupo.integer64 sortorderupo orderupo.integer64 orderupo sortorderuni.integer64 sortorderuni orderuni.integer64 orderuni sortuni.integer64 sortuni sortorderdup.integer64 sortorderdup orderdup.integer64 orderdup sortorderpos.integer64 sortorderpos orderpos.integer64 orderpos orderfin.integer64 orderfin sortfin.integer64 sortfin ordernut.integer64 ordernut sortnut.integer64 sortnut

Documented in orderdup orderdup.integer64 orderfin orderfin.integer64 orderkey orderkey.integer64 ordernut ordernut.integer64 orderpos orderpos.integer64 orderqtl orderqtl.integer64 orderrnk orderrnk.integer64 ordertab ordertab.integer64 ordertie ordertie.integer64 orderuni orderuni.integer64 orderupo orderupo.integer64 sortfin sortfin.integer64 sortnut sortnut.integer64 sortorderdup sortorderdup.integer64 sortorderkey sortorderkey.integer64 sortorderpos sortorderpos.integer64 sortorderrnk sortorderrnk.integer64 sortordertab sortordertab.integer64 sortordertie sortordertie.integer64 sortorderuni sortorderuni.integer64 sortorderupo sortorderupo.integer64 sortqtl sortqtl.integer64 sorttab sorttab.integer64 sortuni sortuni.integer64

# /*
# R-Code for searching and merging
# 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{sortnut}
#! \alias{sortnut}
#! \alias{sortnut.integer64}
#! \alias{ordernut}
#! \alias{ordernut.integer64}
#! \alias{sortfin}
#! \alias{sortfin.integer64}
#! \alias{orderpos}
#! \alias{orderpos.integer64}
#! \alias{orderfin}
#! \alias{orderfin.integer64}
#! \alias{sortorderpos}
#! \alias{sortorderpos.integer64}
#! \alias{orderdup}
#! \alias{orderdup.integer64}
#! \alias{sortorderdup}
#! \alias{sortorderdup.integer64}
#! \alias{sortuni}
#! \alias{sortuni.integer64}
#! \alias{orderuni}
#! \alias{orderuni.integer64}
#! \alias{sortorderuni}
#! \alias{sortorderuni.integer64}
#! \alias{orderupo}
#! \alias{orderupo.integer64}
#! \alias{sortorderupo}
#! \alias{sortorderupo.integer64}
#! \alias{ordertie}
#! \alias{ordertie.integer64}
#! \alias{sortordertie}
#! \alias{sortordertie.integer64}
#! \alias{sorttab}
#! \alias{sorttab.integer64}
#! \alias{ordertab}
#! \alias{ordertab.integer64}
#! \alias{sortordertab}
#! \alias{sortordertab.integer64}
#! \alias{orderkey}
#! \alias{orderkey.integer64}
#! \alias{sortorderkey}
#! \alias{sortorderkey.integer64}
#! \alias{orderrnk}
#! \alias{orderrnk.integer64}
#! \alias{sortorderrnk}
#! \alias{sortorderrnk.integer64}
#! \alias{sortqtl}
#! \alias{sortqtl.integer64}
#! \alias{orderqtl}
#! \alias{orderqtl.integer64}
#! \title{
#!    Searching and other uses of sorting for 64bit integers
#! }
#! \description{
#!   This is roughly an implementation of hash functionality but based on sorting instead on a hasmap.
#!   Since sorting is more informative than hashingwe can do some more interesting things.
#! }
#! \usage{
#! sortnut(sorted, \dots)
#! ordernut(table, order, \dots)
#! sortfin(sorted, x, \dots)
#! orderfin(table, order, x, \dots)
#! orderpos(table, order, x, \dots)
#! sortorderpos(sorted, order, x, \dots)
#! orderdup(table, order, \dots)
#! sortorderdup(sorted, order, \dots)
#! sortuni(sorted, nunique, \dots)
#! orderuni(table, order, nunique, \dots)
#! sortorderuni(table, sorted, order, nunique, \dots)
#! orderupo(table, order, nunique, \dots)
#! sortorderupo(sorted, order, nunique, keep.order = FALSE, \dots)
#! ordertie(table, order, nties, \dots)
#! sortordertie(sorted, order, nties, \dots)
#! sorttab(sorted, nunique, \dots)
#! ordertab(table, order, nunique, \dots)
#! sortordertab(sorted, order, \dots)
#! orderkey(table, order, na.skip.num = 0L, \dots)
#! sortorderkey(sorted, order, na.skip.num = 0L, \dots)
#! orderrnk(table, order, na.count, \dots)
#! sortorderrnk(sorted, order, na.count, \dots)
#! \method{sortnut}{integer64}(sorted, \dots)
#! \method{ordernut}{integer64}(table, order, \dots)
#! \method{sortfin}{integer64}(sorted, x, method=NULL, \dots)
#! \method{orderfin}{integer64}(table, order, x, method=NULL, \dots)
#! \method{orderpos}{integer64}(table, order, x, nomatch=NA, method=NULL, \dots)
#! \method{sortorderpos}{integer64}(sorted, order, x, nomatch=NA, method=NULL, \dots)
#! \method{orderdup}{integer64}(table, order, method=NULL, \dots)
#! \method{sortorderdup}{integer64}(sorted, order, method=NULL, \dots)
#! \method{sortuni}{integer64}(sorted, nunique, \dots)
#! \method{orderuni}{integer64}(table, order, nunique, keep.order=FALSE, \dots)
#! \method{sortorderuni}{integer64}(table, sorted, order, nunique, \dots)
#! \method{orderupo}{integer64}(table, order, nunique, keep.order=FALSE, \dots)
#! \method{sortorderupo}{integer64}(sorted, order, nunique, keep.order = FALSE, \dots)
#! \method{ordertie}{integer64}(table, order, nties, \dots)
#! \method{sortordertie}{integer64}(sorted, order, nties, \dots)
#! \method{sorttab}{integer64}(sorted, nunique, \dots)
#! \method{ordertab}{integer64}(table, order, nunique, denormalize=FALSE, keep.order=FALSE, \dots)
#! \method{sortordertab}{integer64}(sorted, order, denormalize=FALSE, \dots)
#! \method{orderkey}{integer64}(table, order, na.skip.num = 0L, \dots)
#! \method{sortorderkey}{integer64}(sorted, order, na.skip.num = 0L, \dots)
#! \method{orderrnk}{integer64}(table, order, na.count, \dots)
#! \method{sortorderrnk}{integer64}(sorted, order, na.count, \dots)
#! \method{sortqtl}{integer64}(sorted, na.count, probs, \dots)
#! \method{orderqtl}{integer64}(table, order, na.count, probs, \dots)
#! }
#! \arguments{
#!   \item{x}{ an \code{\link{integer64}} vector }
#!   \item{sorted}{ a sorted \code{\link{integer64}} vector }
#!   \item{table}{ the original data with original order under the sorted vector }
#!   \item{order}{ an \code{\link{integer}} order vector that turns 'table' into 'sorted' }
#!   \item{nunique}{ number of unique elements, usually we get this from cache or call \code{sortnut} or \code{ordernut} }
#!   \item{nties}{ number of tied values, usually we get this from cache or call \code{sortnut} or \code{ordernut} }
#!   \item{denormalize}{ FALSE returns counts of unique values, TRUE returns each value with its counts }
#!   \item{nomatch}{ the value to be returned if an element is not found in the hashmap }
#!   \item{keep.order}{ determines order of results and speed: \code{FALSE} (the default) is faster and returns in sorted order, \code{TRUE} returns in the order of first appearance in the original data, but this requires extra work } 
#!   \item{probs}{ vector of probabilities in [0..1] for which we seek quantiles }
#!   \item{na.skip.num}{ 0 or the number of \code{NA}s. With 0, \code{NA}s are coded with 1L, with the number of \code{NA}s, these are coded with \code{NA}, the latter needed for \code{\link{as.factor.integer64}} }
#!   \item{na.count}{ the number of \code{NA}s, needed for this low-level function algorithm }
#!   \item{method}{ see details }
#!   \item{\dots}{ further arguments, passed from generics, ignored in methods }
#! }
#! \details{
#! \tabular{rrrrl}{
#!    \bold{sortfun} \tab \bold{orderfun} \tab \bold{sortorderfun} \tab \bold{see also}          \tab \bold{description} \cr
#!    \code{sortnut} \tab \code{ordernut} \tab                     \tab  \tab return number of tied and of unique values \cr
#!    \code{sortfin} \tab \code{orderfin} \tab                     \tab \code{\link{\%in\%.integer64}} \tab return logical whether \code{x} is in \code{table} \cr
#!                   \tab \code{orderpos} \tab \code{sortorderpos} \tab \code{\link[=match.integer64]{match}} \tab return positions of \code{x} in \code{table} \cr
#!                   \tab \code{orderdup} \tab \code{sortorderdup} \tab \code{\link[=duplicated.integer64]{duplicated}} \tab return logical whether values are duplicated \cr
#!    \code{sortuni} \tab \code{orderuni} \tab \code{sortorderuni} \tab \code{\link[=unique.integer64]{unique}} \tab return unique values (=dimensiontable) \cr
#!                   \tab \code{orderupo} \tab \code{sortorderupo} \tab \code{\link[=unique.integer64]{unique}} \tab return positions of unique values \cr
#!                   \tab \code{ordertie} \tab \code{sortordertie} \tab  \tab return positions of tied values \cr
#!                   \tab \code{orderkey} \tab \code{sortorderkey} \tab  \tab positions of values in vector of unique values (match in dimensiontable) \cr
#!    \code{sorttab} \tab \code{ordertab} \tab \code{sortordertab} \tab \code{\link[=table.integer64]{table}} \tab tabulate frequency of values  \cr
#!                   \tab \code{orderrnk} \tab \code{sortorderrnk} \tab  \tab rank averaging ties \cr
#!    \code{sortqtl} \tab \code{orderqtl} \tab                     \tab  \tab return quantiles given probabilities \cr
#! }
#! The functions \code{sortfin}, \code{orderfin}, \code{orderpos} and \code{sortorderpos} each offer three algorithms for finding \code{x} in \code{table}.  \cr
#! With \code{method=1L} each value of \code{x} is searched independently using \emph{binary search}, this is fastest for small \code{table}s. \cr
#! With \code{method=2L} the values of \code{x} are first sorted and then searched using \emph{doubly exponential search}, this is the best allround method. \cr
#! With \code{method=3L} the values of \code{x} are first sorted and then searched using simple merging, this is the fastest method if \code{table} is huge and \code{x} has similar size and distribution of values. \cr
#! With \code{method=NULL} the functions use a heuristic to determine the fastest algorithm. \cr
#!
#! The functions \code{orderdup} and \code{sortorderdup} each offer two algorithms for setting the truth values in the return vector.  \cr
#! With \code{method=1L} the return values are set directly which causes random write access on a possibly large return vector. \cr
#! With \code{method=2L} the return values are first set in a smaller bit-vector -- random access limited to a smaller memory region -- and finally written sequentially to the logical output  vector. \cr
#! With \code{method=NULL} the functions use a heuristic to determine the fastest algorithm. \cr
#! }
#! \value{
#!   see details
#! }
#! \author{
#! Jens Oehlschlägel <Jens.Oehlschlaegel@truecluster.com>
#! }
#! \keyword{ programming }
#! \keyword{ manip }
#! \seealso{ \code{\link[=match.integer64]{match}} }
#! \examples{
#!  message("check the code of 'optimizer64' for examples:")
#!  print(optimizer64)
#! }



sortnut <- function(sorted, ...)UseMethod("sortnut")
sortnut.integer64 <- function(sorted, ...)
{
  ret <- .Call(C_r_ram_integer64_sortnut, x = sorted, PACKAGE = "bit64")
  names(ret) <- c("nunique","nties")
  ret
}

ordernut <- function(table, order, ...)UseMethod("ordernut")
ordernut.integer64 <- function(table, order, ...)
{
  ret <- .Call(C_r_ram_integer64_ordernut, table = as.integer64(table), order = as.integer(order), PACKAGE = "bit64")
  names(ret) <- c("nunique","nties")
  ret
}

sortfin <- function(sorted, x, ...)UseMethod("sortfin")
sortfin.integer64 <- function(sorted, x, method=NULL, ...)
{
  n <- length(x)
  if (is.null(method)){
	if (n<2048){
	  method <- 1L
	}else if (n<length(sorted)/128){
	  method <- 2L
	}else{
	  method <- 3L
	}
  }else method <- as.integer(method)
  if (method==1L){
	  .Call(C_r_ram_integer64_sortfin_asc
	  , x = as.integer64(x)
	  , sorted = as.integer64(sorted)
	  , method= method
	  , ret = logical(n)
	  , PACKAGE = "bit64"
	  )
  }else{
    sx <- clone(as.integer64(x)); o <- seq_along(x); ramsortorder(sx, o, na.last=FALSE, ...)
    ret <- logical(n)
    ret[o] <- .Call(C_r_ram_integer64_sortfin_asc
	  , x = sx
	  , sorted = as.integer64(sorted)
	  , method= method
	  , ret = ret
	  , PACKAGE = "bit64"
	  )
	  ret
  }
}

orderfin <- function(table, order, x, ...)UseMethod("orderfin")
orderfin.integer64 <- function(table, order, x, method=NULL, ...)
{
  n <- length(x)
  if (is.null(method)){
	if (n<4096){
	  method <- 1L
	}else if (n<length(table)/8){
	  method <- 2L
	}else{
	  method <- 3L
	}
  }else method <- as.integer(method)
  if (method==1L){
	  .Call(C_r_ram_integer64_orderfin_asc
	  , x = as.integer64(x)
	  , table = as.integer64(table)
	  , order = as.integer(order)
	  , method= as.integer(method)
	  , ret = logical(n)
	  , PACKAGE = "bit64"
	  )
  }else{
    o <- seq_along(x); ramorder(x, o, na.last=FALSE, ...)
    ret <- logical(n)
    ret[o] <- .Call(C_r_ram_integer64_orderfin_asc
	  , x = x[o]
	  , table = as.integer64(table)
	  , order = as.integer(order)
	  , method= as.integer(method)
	  , ret = ret
	  , PACKAGE = "bit64"
	  )
	  ret
  }
}


orderpos <- function(table, order, x, ...)UseMethod("orderpos")
orderpos.integer64 <- function(table, order, x, nomatch=NA, method=NULL, ...)
{
  n <- length(x)
  if (is.null(method)){
	if (n<4096){
	  method <- 1L
	}else if (n<length(table)/8){
	  method <- 2L
	}else{
	  method <- 3L
	}
  }else method <- as.integer(method)
  if (method==1L){
	  .Call(C_r_ram_integer64_orderpos_asc
	  , x = as.integer64(x)
	  , table = as.integer64(table)
	  , order = as.integer(order)
	  , nomatch = as.integer(nomatch)
	  , method= as.integer(method)
	  , ret = integer(n)
	  , PACKAGE = "bit64"
	  )
  }else{
    o <- seq_along(x); ramorder(x, o, na.last=FALSE, ...)
    ret <- integer(n)
    ret[o] <- .Call(C_r_ram_integer64_orderpos_asc
	  , x = x[o]
	  , table = as.integer64(table)
	  , order = as.integer(order)
	  , nomatch = as.integer(nomatch)
	  , method= as.integer(method)
	  , ret = ret
	  , PACKAGE = "bit64"
	  )
	  ret
  }
}

sortorderpos <- function(sorted, order, x, ...)UseMethod("sortorderpos")
sortorderpos.integer64 <- function(sorted, order, x, nomatch=NA, method=NULL, ...)
{
  n <- length(x)
  if (is.null(method)){
	if (n<2048){
	  method <- 1L
	}else if (n<length(sorted)/128){
	  method <- 2L
	}else{
	  method <- 3L
	}
  }else method <- as.integer(method)
  if (method==1L){
	  .Call(C_r_ram_integer64_sortorderpos_asc
	  , x = as.integer64(x)
	  , sorted = as.integer64(sorted)
	  , order = as.integer(order)
	  , nomatch = as.integer(nomatch)
	  , method= as.integer(method)
	  , ret = integer(n)
	  , PACKAGE = "bit64"
	  )
  }else{
    sx <- clone(as.integer64(x)); o <- seq_along(x); ramsortorder(sx, o, na.last=FALSE, ...)
    ret <- integer(n)
    ret[o] <- .Call(C_r_ram_integer64_sortorderpos_asc
	  , x = sx
	  , sorted = as.integer64(sorted)
	  , order = as.integer(order)
	  , nomatch = as.integer(nomatch)
	  , method= as.integer(method)
	  , ret = ret
	  , PACKAGE = "bit64"
	  )
	  ret
  }
}



orderdup <- function(table, order, ...)UseMethod("orderdup")
orderdup.integer64 <- function(table, order, method=NULL, ...)
{
  if (is.null(method)){
    if (length(table)<4194304)
	    method <- 1L
	  else
	    method <- 2L
  }else method <- as.integer(method)
  .Call(C_r_ram_integer64_orderdup_asc
  , table = as.integer64(table)
  , order = as.integer(order)
  , method = method
  , ret = logical(length(table))
  , PACKAGE = "bit64"
  )
}


sortorderdup <- function(sorted, order, ...)UseMethod("sortorderdup")
sortorderdup.integer64 <- function(sorted, order, method=NULL, ...)
{
  if (is.null(method)){
    if (length(sorted)<4194304)
	    method <- 1L
	  else
	    method <- 2L
  }else method <- as.integer(method)
  .Call(C_r_ram_integer64_sortorderdup_asc
  , sorted = as.integer64(sorted)
  , order = as.integer(order)
  , method = method
  , ret = logical(length(sorted))
  , PACKAGE = "bit64"
  )
}


sortuni <- function(sorted, nunique, ...)UseMethod("sortuni")
sortuni.integer64 <- function(sorted, nunique, ...)
{
  .Call(C_r_ram_integer64_sortuni_asc
  , sorted = as.integer64(sorted)
  , ret = integer64(nunique)
  , PACKAGE = "bit64"
  )
}

orderuni <- function(table, order, nunique, ...)UseMethod("orderuni")
orderuni.integer64 <- function(table, order, nunique, keep.order=FALSE, ...)
{
  .Call(C_r_ram_integer64_orderuni_asc
  , table = as.integer64(table)
  , order = as.integer(order)
  , keep.order = as.logical(keep.order)
  , ret = integer64(nunique)
  , PACKAGE = "bit64"
  )
}

sortorderuni <- function(table, sorted, order, nunique, ...)UseMethod("sortorderuni")
sortorderuni.integer64 <- function(table, sorted, order, nunique, ...)
{
  .Call(C_r_ram_integer64_sortorderuni_asc
  , table = as.integer64(table)
  , sorted = as.integer64(sorted)
  , order = as.integer(order)
  , ret = integer64(nunique)
  , PACKAGE = "bit64"
  )
}

orderupo <- function(table, order, nunique, ...)UseMethod("orderupo")
orderupo.integer64 <- function(table, order, nunique, keep.order=FALSE, ...)
{
	.Call(C_r_ram_integer64_orderupo_asc
	, table = as.integer64(table)
	, order = as.integer(order)
	, keep.order = as.logical(keep.order)
	, ret = integer(nunique)
	, PACKAGE = "bit64"
	)
}

sortorderupo <- function(sorted, order, nunique, keep.order=FALSE, ...)UseMethod("sortorderupo")
sortorderupo.integer64 <- function(sorted, order, nunique, keep.order=FALSE, ...)
{
  .Call(C_r_ram_integer64_sortorderupo_asc
	, sorted = as.integer64(sorted)
	, order = as.integer(order)
	, keep.order = as.logical(keep.order)
	, ret = integer(nunique)
	, PACKAGE = "bit64"
	)
}


ordertie <- function(table, order, nties, ...)UseMethod("ordertie")
ordertie.integer64 <- function(table, order, nties, ...)
{
  .Call(C_r_ram_integer64_ordertie_asc
  , table = as.integer64(table)
  , order = as.integer(order)
  , ret = integer(nties)
  , PACKAGE = "bit64"
  )
}

sortordertie <- function(sorted, order, nties, ...)UseMethod("sortordertie")
sortordertie.integer64 <- function(sorted, order, nties, ...)
{
  .Call(C_r_ram_integer64_sortordertie_asc
  , sorted = as.integer64(sorted)
  , order = as.integer(order)
  , ret = integer(nties)
  , PACKAGE = "bit64"
  )
}


sorttab <- function(sorted, nunique, ...)UseMethod("sorttab")
sorttab.integer64 <- function(sorted, nunique, ...)
{
  .Call(C_r_ram_integer64_sorttab_asc
  , sorted = as.integer64(sorted)
  , ret = integer(nunique)
  , PACKAGE = "bit64"
  )
}

ordertab <- function(table, order, nunique, ...)UseMethod("ordertab")
ordertab.integer64 <- function(table, order, nunique, denormalize=FALSE, keep.order=FALSE, ...)
{
  denormalize <- as.logical(denormalize)
  keep.order <- as.logical(keep.order)
  .Call(C_r_ram_integer64_ordertab_asc
  , table = as.integer64(table)
  , order = as.integer(order)
  , denormalize = denormalize
  , keep.order = keep.order
  , ret = integer(if (denormalize || keep.order) length(table) else nunique)
  , PACKAGE = "bit64"
  )
}

sortordertab <- function(sorted, order, ...)UseMethod("sortordertab")
sortordertab.integer64 <- function(sorted, order, denormalize=FALSE, ...)
{
  .Call(C_r_ram_integer64_sortordertab_asc
  , sorted = as.integer64(sorted)
  , order = as.integer(order)
  , denormalize = as.logical(denormalize)
  , ret = integer(length(sorted))
  , PACKAGE = "bit64"
  )
}

orderkey <- function(table, order, na.skip.num=0L, ...)UseMethod("orderkey")
orderkey.integer64 <- function(table, order, na.skip.num=0L, ...)
{
	.Call(C_r_ram_integer64_orderkey_asc
	, table = as.integer64(table)
	, order = as.integer(order)
	, na.skip.num=na.skip.num
	, ret = integer(length(table))
	, PACKAGE = "bit64"
	)
}

sortorderkey <- function(sorted, order, na.skip.num=0L, ...)UseMethod("sortorderkey")
sortorderkey.integer64 <- function(sorted, order, na.skip.num=0L, ...)
{
	.Call(C_r_ram_integer64_sortorderkey_asc
	, sorted = as.integer64(sorted)
	, order = as.integer(order)
	, na.skip.num=na.skip.num
	, ret = integer(length(sorted))
	, PACKAGE = "bit64"
	)
}


orderrnk <- function(table, order, na.count, ...)UseMethod("orderrnk")
orderrnk.integer64 <- function(table, order, na.count, ...)
{
  .Call(C_r_ram_integer64_orderrnk_asc
  , table = as.integer64(table)
  , order = as.integer(order)
  , na.count=as.integer(na.count)
  , ret = double(length(table))
  , PACKAGE = "bit64"
  )
}

sortorderrnk <- function(sorted, order, na.count, ...)UseMethod("sortorderrnk")
sortorderrnk.integer64 <- function(sorted, order, na.count, ...)
{
  .Call(C_r_ram_integer64_sortorderrnk_asc
  , sorted = as.integer64(sorted)
  , order = as.integer(order)
  , na.count=as.integer(na.count)
  , ret = double(length(sorted))
  , PACKAGE = "bit64"
  )
}


sortqtl <- function(sorted, na.count, probs, ...)UseMethod("sortqtl")
sortqtl.integer64 <- function(sorted, na.count, probs, ...){
	n <- length(sorted) - na.count  # nvalid
	ret <- sorted[na.count + round(1L + probs*(n-1L))]
	ret[is.na(probs)] <- NA ## xx TODO this fix only neccessary until we have C-implementation of [.integer64 handling NA
	ret
}

orderqtl <- function(table, order, na.count, probs, ...)UseMethod("orderqtl")
orderqtl.integer64 <- function(table, order, na.count, probs, ...){
	n <- length(table) - na.count  # nvalid
	ret <- table[ order[na.count + round(1L + probs*(n-1L))] ]
	ret[is.na(probs)] <- NA ## xx TODO this fix only neccessary until we have C-implementation of [.integer64 handling NA
	ret
}

Try the bit64 package in your browser

Any scripts or data that you put into this service are public.

bit64 documentation built on Sept. 30, 2024, 9:23 a.m.