#' Generate all possible 0-1 patterns of given length,
#' or binary partition index matrix
#'
#' @param nitems  The length of the pattern
#' @param sort    =  1 to sort the result from the left \cr
#'                = -1 to sort the result from the right \cr
#'                =  2 to sort the result by rowSums and from the left \cr
#'                = -2 to sort the result by rowSums and from the right \cr
#' @param partition = 1 to generate binary partition index matrix
#' @param print = 1 to print the result
#'
#' @details
#' Schatzoff et al method is used. \cr
#' nitems must be less than log(.Machine$integer.max)/log(2). \cr
#' \cr
#' Essentially the same  as \cr
#'   cprod( rep(list(0:1),nitems) ) \cr
#' but gen01pat is much faster.
#'
#' @references
#' Schatzoff, M., Tsao, R.  and Fienberg, S. (1968)
#' Efficient Calculation of All Possible Regressions.  Technometrics.
#' Vol. 10, No. 4, pp. 769-779
#'
#' @examples
#' gen01pat( 4 )
#' gen01pat( 4, partition=1, sort=-2 )
#'
#' pindex=gen01pat( 4, partition=1 )
#' left=apply(pindex,1,function(x) letters[1:4][as.logical(x)])
#' right=lapply(left,function(x){setdiff(letters[1:4],x)})
#' res=mapply( function(x,y){list(left=x,right=y)}, left,right, SIMPLIFY=FALSE)
#' Print(res)
#'
#'
#' @return
#' \code{2^nitems x nitems} matrix \\
#' or when \code{partition=1} is given \\
#' \code{2^{nitems-1}-1 x nitems} matrix
#'
#'
#'
#' @export
#'
#'

gen01pat <- function( nitems, sort=0, partition=0, print=0 ){
 #  generation of all the possible 0-1 patterns of the length nitems
 #  by the Schatzoff et al method.
 #  Shin-ichi Mayekawa
 #  sas/matrix and iml version: 890127-011118
 #  20150729
 #  bugfix: 20150822
 #  partition: 20230314
 #  reference: 20230926
 #  sort=-2,2; 20231004
 #  nitems/2: 20231004
 #
 #  See sas proc matrix manual for details.
 #  Large # of items with 2##nitems > maximum integer
 #   must be handled by operating the modulus.  not ready yet!!
 #

 if( nitems > log(.Machine$integer.max)/log(2)-1 ){
  stop("\nerror1:(gen01pat) nitems must be less than or equal to ",
       round(log(.Machine$integer.max)/log(2)-1),". \n")
 }

 npat=2^nitems
 xall=matrix(integer(0),npat,nitems)

 n21=2^nitems-1+.00001

 if( partition ){
  if( nitems <= 1 ){
   stop("\nerror1:(gen01pat) nitems must be greater than 1.\n")
  }
  n21=2^(nitems-1)-1+.00001
  xall=matrix(integer(0),npat/2,nitems)
 }


 x=rep(0,nitems) # location of 1s
 mode(x)="integer"
 mode(xall)="integer"
 #Print(1,typeof(x), typeof(xall))
 xall[1,]=x

 # this is the loop for all the possible patterns
 for( k in 1:n21){
  # find the location to add/remove
  i=1; kk=k;
  while( kk %% 2 == 0 ){ i=i+1; kk=kk/2 }
  # here i is the number of trailng zeros of binary(k) + 1.
  # add/remove
  x[i]=!x[i]
  xall[k+1,]=x
 } # of k loop

 if( partition ){
   xall=xall[-1,,drop=0]
   loc=rowSums(xall) > nitems/2
   xall[loc,]=1-xall[loc,]
 }

 if( sort == -1 )
  xall=sortit( xall,  cols=ncol(xall)-(1:ncol(xall))+1 )
 else if( sort == 1 )
  xall=sortit( xall,  cols=1:ncol(xall) )
 else if( sort == -2 )
  xall=xall[do.call( order, data.frame(rowSums(xall),-xall) ),]
 else if( sort == 2 )
   xall=xall[do.call( order, data.frame(rowSums(xall),xall) ),]


 if( print ){
  Print(partition, sort)
  Print(xall)
 }

 return( xall )

} # end of gen01pat


