github.com/whatap/golib@v0.0.22/util/hll/RegisterSet.go (about)

     1  /*
     2   * This file from
     3   *  https://github.com/addthis/stream-lib/blob/master/src/main/java/com/clearspring/analytics/stream/cardinality/RegisterSet.java
     4   *
     5   *  This class modified by Scouter-Project *   - original package :  com.clearspring.analytics.stream.cardinality
     6   *
     7   *  ====================================
     8   *
     9   * Copyright (C) 2012 Clearspring Technologies, Inc.
    10   *
    11   * Licensed under the Apache License, Version 2.0 (the "License");
    12   * you may not use this file except in compliance with the License.
    13   * You may obtain a copy of the License at
    14   *
    15   * http://www.apache.org/licenses/LICENSE-2.0
    16   *
    17   * Unless required by applicable law or agreed to in writing, software
    18   * distributed under the License is distributed on an "AS IS" BASIS,
    19   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    20   * See the License for the specific language governing permissions and
    21   * limitations under the License.
    22   */
    23  
    24  package hll
    25  
    26  import (
    27  //	"math"
    28  //	"strconv"
    29  )
    30  
    31  const (
    32  	LOG2_BITS_PER_WORD = 6
    33  	REGISTER_SIZE      = 5
    34  )
    35  
    36  type RegisterSet struct {
    37  	Count int
    38  	Size  int
    39  	M     []uint32
    40  }
    41  
    42  func NewRegisterSetInit(count int, initialValues []uint32) *RegisterSet {
    43  	p := new(RegisterSet)
    44  	p.Count = count
    45  	if initialValues == nil {
    46  		p.M = make([]uint32, getSizeForCount(count))
    47  	} else {
    48  		p.M = initialValues
    49  	}
    50  	p.Size = len(p.M)
    51  
    52  	return p
    53  }
    54  
    55  func NewRegisterSet(count int) *RegisterSet {
    56  	return NewRegisterSetInit(count, nil)
    57  }
    58  
    59  func (this *RegisterSet) Set(position, value uint32) {
    60  	bucketPos := position / LOG2_BITS_PER_WORD
    61  	shift := REGISTER_SIZE * (position - (bucketPos * LOG2_BITS_PER_WORD))
    62  	//this.M[bucketPos] = (this.M[bucketPos] & ~(0x1f << shift)) | (value << shift)
    63  	this.M[bucketPos] = (this.M[bucketPos] & ^ (0x1f << uint32(shift)) | (value << uint32(shift)))
    64  }
    65  func (this *RegisterSet) Get(position int) uint32 {
    66  	bucketPos := position / LOG2_BITS_PER_WORD
    67  	shift := REGISTER_SIZE * (position - (bucketPos * LOG2_BITS_PER_WORD))
    68  	//return (this.M[bucketPos] & (0x1f << shift)) >>> shift;
    69  	return (this.M[bucketPos]&(0x1f<<uint32(shift))) >> uint32(shift)
    70  }
    71  
    72  func (this *RegisterSet) UpdateIfGreater(position, value uint32) bool {
    73  	bucket := position / LOG2_BITS_PER_WORD
    74  	shift := REGISTER_SIZE * (position - (bucket * LOG2_BITS_PER_WORD))
    75  	mask := uint32(0x1f) << uint32(shift)
    76  	// Use long to avoid sign issues with the left-most shift
    77  	//long curVal = this.M[bucket] & mask;
    78  	//long newVal = value << shift;
    79  	curVal := uint64(this.M[bucket] & mask)
    80  	newVal := uint64(value) << uint32(shift)
    81  	if curVal < newVal {
    82  		//this.M[bucket] = (int) ((this.M[bucket] & ~mask) | newVal)
    83  		this.M[bucket] = uint32(uint64(this.M[bucket] & ^mask) | newVal)
    84  		return true
    85  	} else {
    86  		return false
    87  	}
    88  }
    89  func (this *RegisterSet) Merge(that *RegisterSet) {
    90  	for bucket := 0; bucket < len(this.M); bucket++ {
    91  		word := uint32(0)
    92  		for j := 0; j < LOG2_BITS_PER_WORD; j++ {
    93  			mask := uint32(0x1f << uint32(REGISTER_SIZE * j))
    94  			thisVal := (this.M[bucket] & mask)
    95  			thatVal := (that.M[bucket] & mask)
    96  			if thisVal < thatVal {
    97  				word |= thatVal
    98  			} else {
    99  				word |= thisVal
   100  			}
   101  		}
   102  		this.M[bucket] = word
   103  	}
   104  }
   105  func (this *RegisterSet) ReadOnlyBits() []uint32 {
   106  	return this.M
   107  }
   108  
   109  func (this *RegisterSet) Bits() []uint32 {
   110  	copy := this.M[0:]
   111  	return copy
   112  }
   113  
   114  func getBits(count int) int {
   115  	return count / LOG2_BITS_PER_WORD
   116  }
   117  
   118  func getSizeForCount(count int) int {
   119  	bits := getBits(count)
   120  	if bits == 0 {
   121  		return 1
   122  	} else if bits%32 == 0 {
   123  		return bits
   124  	} else {
   125  		return bits + 1
   126  	}
   127  }