summary refs log blame commit diff stats
path: root/compiler/bitsets.nim
blob: 2e8aa1db6e45a159eba6f57d04aa2cf5cc85c261 (plain) (tree)
1
2
3
4
5
6
7
8
9

 
                            
                                         




                                                   

                                                            
 
    

                                                                     

                                                                             
     





                                                       
 









                                                  
                                        

                
                                                
                                                                      
 
                                                   
                   

                                                        
 
                                                   

                                                         
 
                                              

                   
                                              
                                          

                                             
                                               

                                                
                                           

                                                  
                                           

                                        
                      
                    


                  
                                          
                      
                                   

                  

                                           

                                                   
 
                                        
            







                                       
 
 

                                             

       


                                         
                                       
#
#
#           The Nim Compiler
#        (c) Copyright 2012 Andreas Rumpf
#
#    See the file "copying.txt", included in this
#    distribution, for details about the copyright.
#

# this unit handles Nim sets; it implements bit sets
# the code here should be reused in the Nim standard library

type
  ElemType = byte
  TBitSet* = seq[ElemType]    # we use byte here to avoid issues with
                              # cross-compiling; uint would be more efficient
                              # however
const
  ElemSize* = 8
  One = ElemType(1)
  Zero = ElemType(0)

template modElemSize(arg: untyped): untyped = arg and 7
template divElemSize(arg: untyped): untyped = arg shr 3

proc bitSetInit*(b: var TBitSet, length: int)
proc bitSetUnion*(x: var TBitSet, y: TBitSet)
proc bitSetDiff*(x: var TBitSet, y: TBitSet)
proc bitSetSymDiff*(x: var TBitSet, y: TBitSet)
proc bitSetIntersect*(x: var TBitSet, y: TBitSet)
proc bitSetIncl*(x: var TBitSet, elem: BiggestInt)
proc bitSetExcl*(x: var TBitSet, elem: BiggestInt)
proc bitSetIn*(x: TBitSet, e: BiggestInt): bool
proc bitSetEquals*(x, y: TBitSet): bool
proc bitSetContains*(x, y: TBitSet): bool
proc bitSetCard*(x: TBitSet): BiggestInt
# implementation

proc bitSetIn(x: TBitSet, e: BiggestInt): bool =
  result = (x[int(e.divElemSize)] and (One shl e.modElemSize)) != Zero

proc bitSetIncl(x: var TBitSet, elem: BiggestInt) =
  assert(elem >= 0)
  x[int(elem.divElemSize)] = x[int(elem.divElemSize)] or
      (One shl elem.modElemSize)

proc bitSetExcl(x: var TBitSet, elem: BiggestInt) =
  x[int(elem.divElemSize)] = x[int(elem.divElemSize)] and
      not(One shl elem.modElemSize)

proc bitSetInit(b: var TBitSet, length: int) =
  newSeq(b, length)

proc bitSetUnion(x: var TBitSet, y: TBitSet) =
  for i in 0..high(x): x[i] = x[i] or y[i]

proc bitSetDiff(x: var TBitSet, y: TBitSet) =
  for i in 0..high(x): x[i] = x[i] and not y[i]

proc bitSetSymDiff(x: var TBitSet, y: TBitSet) =
  for i in 0..high(x): x[i] = x[i] xor y[i]

proc bitSetIntersect(x: var TBitSet, y: TBitSet) =
  for i in 0..high(x): x[i] = x[i] and y[i]

proc bitSetEquals(x, y: TBitSet): bool =
  for i in 0..high(x):
    if x[i] != y[i]:
      return false
  result = true

proc bitSetContains(x, y: TBitSet): bool =
  for i in 0..high(x):
    if (x[i] and not y[i]) != Zero:
      return false
  result = true

# Number of set bits for all values of int8
const populationCount: array[uint8, uint8] = block:
    var arr: array[uint8, uint8]

    proc countSetBits(x: uint8): uint8 =
      return
        ( x and 0b00000001'u8) +
        ((x and 0b00000010'u8) shr 1) +
        ((x and 0b00000100'u8) shr 2) +
        ((x and 0b00001000'u8) shr 3) +
        ((x and 0b00010000'u8) shr 4) +
        ((x and 0b00100000'u8) shr 5) +
        ((x and 0b01000000'u8) shr 6) +
        ((x and 0b10000000'u8) shr 7)


    for it in low(uint8)..high(uint8):
      arr[it] = countSetBits(cast[uint8](it))

    arr

proc bitSetCard(x: TBitSet): BiggestInt =
  for it in x:
    result.inc int(populationCount[it])