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 }