github.com/qioalice/ekago/v3@v3.3.2-0.20221202205325-5c262d586ee4/ekamath/bitset_test.go (about) 1 // Copyright © 2021. All rights reserved. 2 // Author: Ilya Stroy. 3 // Contacts: iyuryevich@pm.me, https://github.com/qioalice 4 // License: https://opensource.org/licenses/MIT 5 6 package ekamath_test 7 8 import ( 9 "fmt" 10 "runtime" 11 "testing" 12 13 "github.com/qioalice/ekago/v3/ekamath" 14 15 "github.com/stretchr/testify/require" 16 ) 17 18 func TestBitSet(t *testing.T) { 19 20 bs := ekamath.NewBitSet(32) 21 t.Cleanup(func() { 22 bs.DebugFullDump() 23 }) 24 25 //goland:noinspection GoSnakeCaseUsage 26 const ( 27 SET_1 = 2 28 SET_2 = 10 29 SET_3 = 1064 30 ) 31 32 require.True(t, bs.IsEmpty()) 33 34 bs.Set(SET_1, true) 35 bs.Set(SET_2, true) 36 bs.Set(SET_3, true) 37 38 require.False(t, bs.IsEmpty()) 39 require.EqualValues(t, 3, bs.Count()) 40 41 require.True(t, bs.IsSet(SET_1)) 42 require.True(t, bs.IsSet(SET_2)) 43 require.True(t, bs.IsSet(SET_3)) 44 45 require.False(t, bs.IsSet(SET_1-1)) 46 require.False(t, bs.IsSet(SET_2-1)) 47 require.False(t, bs.IsSet(SET_2+1)) 48 require.False(t, bs.IsSet(SET_3-1)) 49 require.False(t, bs.IsSet(SET_3+1)) 50 51 for _, testCase := range []struct { 52 idx string 53 arg uint 54 fn func(*ekamath.BitSet, uint) (uint, bool) 55 ok bool 56 val uint 57 }{ 58 {"A1", SET_1, (*ekamath.BitSet).NextUp, true, SET_2}, 59 {"A2", SET_2, (*ekamath.BitSet).NextUp, true, SET_3}, 60 {"A3", SET_3, (*ekamath.BitSet).NextUp, false, SET_3}, 61 62 {"B1", SET_3, (*ekamath.BitSet).PrevUp, true, SET_2}, 63 {"B2", SET_2, (*ekamath.BitSet).PrevUp, true, SET_1}, 64 {"B3", SET_1, (*ekamath.BitSet).PrevUp, false, SET_1}, 65 66 {"C1", SET_1 - 1, (*ekamath.BitSet).NextDown, true, SET_1 + 1}, 67 {"C2", SET_1, (*ekamath.BitSet).NextDown, true, SET_1 + 1}, 68 {"C3", SET_2 - 1, (*ekamath.BitSet).NextDown, true, SET_2 + 1}, 69 {"C4", SET_2, (*ekamath.BitSet).NextDown, true, SET_2 + 1}, 70 {"C5", SET_3 - 1, (*ekamath.BitSet).NextDown, true, SET_3 + 1}, 71 {"C6", SET_3, (*ekamath.BitSet).NextDown, true, SET_3 + 1}, 72 73 {"D1", SET_3 + 1, (*ekamath.BitSet).PrevDown, true, SET_3 - 1}, 74 {"D2", SET_3, (*ekamath.BitSet).PrevDown, true, SET_3 - 1}, 75 {"D3", SET_2 + 1, (*ekamath.BitSet).PrevDown, true, SET_2 - 1}, 76 {"D4", SET_2, (*ekamath.BitSet).PrevDown, true, SET_2 - 1}, 77 {"D5", SET_2 - 1, (*ekamath.BitSet).PrevDown, true, SET_2 - 2}, 78 {"D6", SET_1, (*ekamath.BitSet).PrevDown, true, SET_1 - 1}, 79 {"D7", SET_1 - 1, (*ekamath.BitSet).PrevDown, false, SET_1 - 1}, 80 } { 81 gotVal, gotOk := testCase.fn(bs, testCase.arg) 82 require.True(t, gotOk == testCase.ok, "Unexpected OK for [%s] case", testCase.idx) 83 require.EqualValues(t, int(testCase.val), int(gotVal), "Unexpected value for [%s] case", testCase.idx) 84 } 85 } 86 87 func TestBitSet_Operations(t *testing.T) { 88 89 bs1 := ekamath.NewBitSet(32) 90 bs2 := ekamath.NewBitSet(13) 91 92 set1 := []uint{1, 3, 6, 7, 3, 6, 10, 14, 30} 93 set2 := []uint{1, 2, 3, 3, 1, 4, 10, 31} 94 95 for _, set1Elem := range set1 { 96 bs1.Up(set1Elem) 97 } 98 99 for _, set2Elem := range set2 { 100 bs2.Up(set2Elem) 101 } 102 103 require.EqualValues(t, []uint{1, 3, 6, 7, 10, 14, 30}, bs1.DebugOnesAsSlice(32)) 104 require.EqualValues(t, []uint{1, 2, 3, 4, 10, 31}, bs2.DebugOnesAsSlice(32)) 105 106 bs3 := bs1.Clone() 107 bs3.Union(bs2) 108 109 require.EqualValues(t, []uint{1, 2, 3, 4, 6, 7, 10, 14, 30, 31}, bs3.DebugOnesAsSlice(32)) 110 111 bs3 = bs1.Clone() 112 bs3.Intersection(bs2) 113 114 require.EqualValues(t, []uint{1, 3, 10}, bs3.DebugOnesAsSlice(32)) 115 116 bs3 = bs1.Clone() 117 bs3.Difference(bs2) 118 119 require.EqualValues(t, []uint{6, 7, 14, 30}, bs3.DebugOnesAsSlice(32)) 120 121 bs3 = bs1.Clone() 122 bs3.SymmetricDifference(bs2) 123 124 require.EqualValues(t, []uint{2, 4, 6, 7, 14, 30, 31}, bs3.DebugOnesAsSlice(32)) 125 126 bs3 = bs1.Clone() 127 bs3.Complement() 128 129 zeroes := make([]uint, 0, 64) 130 for v, e := bs3.NextDown(0); e; v, e = bs3.NextDown(v) { 131 zeroes = append(zeroes, v) 132 } 133 134 require.EqualValues(t, []uint{1, 3, 6, 7, 10, 14, 30}, zeroes) 135 136 bs3.ShrinkUpTo(18) 137 138 require.EqualValues(t, []uint{2, 4, 5, 8, 9, 11, 12, 13, 15, 16, 17, 18}, bs3.DebugOnesAsSlice(32)) 139 } 140 141 func TestBitSet_CountBetween(t *testing.T) { 142 143 bs1 := ekamath.NewBitSet(32) 144 145 set1 := []uint{1, 2, 4, 5, 7, 10, 11, 17, 18, 19, 23, 25, 28, 29, 30, 31, 32} 146 for _, set1Elem := range set1 { 147 bs1.Up(set1Elem) 148 } 149 150 require.EqualValues(t, set1, bs1.DebugOnesAsSlice(32)) 151 152 c := bs1.CountBetween(1, 32) 153 require.EqualValues(t, len(set1), int(c)) 154 155 c = bs1.CountBetween(3, 20) 156 require.EqualValues(t, 8, int(c)) 157 158 c = bs1.CountBetween(12, 16) 159 require.EqualValues(t, 0, int(c)) 160 161 c = bs1.CountBetween(1, 2) 162 require.EqualValues(t, 2, int(c)) 163 } 164 165 func TestBitSet_CountBetween2(t *testing.T) { 166 167 bs2 := ekamath.NewBitSet(256) 168 169 set2 := []uint{ 170 /* 1..64 */ 3, 4, 6, 10, 15, 16, 33, 34, 36, 63, 64, 171 /* 65..128 */ 65, 67, 128, 172 /* 129..192 */ 129, 142, 145, 146, 173 /* 193..256 */ 200, 209, 210, 250, 174 } 175 for _, set2Elem := range set2 { 176 bs2.Up(set2Elem) 177 } 178 179 require.EqualValues(t, set2, bs2.DebugOnesAsSlice(256)) 180 181 c := bs2.CountBetween(1, 256) 182 require.EqualValues(t, len(set2), c) 183 184 c = bs2.CountBetween(10, 66) 185 require.EqualValues(t, 9, c) 186 187 c = bs2.CountBetween(10, 144) 188 require.EqualValues(t, 13, c) 189 190 c = bs2.CountBetween(10, 36) 191 require.EqualValues(t, 6, c) 192 193 c = bs2.CountBetween(10, 200) 194 require.EqualValues(t, 16, c) 195 196 c = bs2.CountBetween(40, 210) 197 require.EqualValues(t, 12, c) 198 199 c = bs2.CountBetween(5, 205) 200 require.EqualValues(t, 17, c) 201 } 202 203 func TestBitSet_EncodeDecode(t *testing.T) { 204 205 const MAX = uint(256) 206 belongs := func(data []uint, elem uint) bool { 207 for _, dataElem := range data { 208 if elem == dataElem { 209 return true 210 } 211 } 212 return false 213 } 214 215 bs2 := ekamath.NewBitSet(MAX) 216 217 set2 := []uint{ 218 /* 1..64 */ 3, 4, 6, 10, 15, 16, 33, 34, 36, 63, 64, 219 /* 65..128 */ 65, 67, 128, 220 /* 129..192 */ 129, 142, 145, 146, 221 /* 193..256 */ 200, 209, 210, 250, 222 } 223 for _, set2Elem := range set2 { 224 bs2.Up(set2Elem) 225 } 226 227 encodedBinary, err := bs2.MarshalBinary() 228 require.NoError(t, err) 229 230 runtime.GC() 231 232 bs2 = ekamath.NewBitSet(MAX) 233 err = bs2.UnmarshalBinary(encodedBinary) 234 require.NoError(t, err) 235 236 runtime.GC() 237 238 for i := uint(1); i <= MAX; i++ { 239 have := bs2.IsSet(i) 240 must := belongs(set2, i) 241 require.True(t, have == must, "Have: %t, Must: %t, Elem: %v", have, must, i) 242 } 243 244 runtime.GC() 245 246 encodedText, err := bs2.MarshalText() 247 require.NoError(t, err) 248 249 runtime.GC() 250 fmt.Println("Encoded data:", string(encodedText)) 251 bs2.DebugFullDump() 252 253 bs2 = ekamath.NewBitSet(MAX) 254 err = bs2.UnmarshalText(encodedText) 255 require.NoError(t, err) 256 257 runtime.GC() 258 259 for i := uint(1); i <= MAX; i++ { 260 have := bs2.IsSet(i) 261 must := belongs(set2, i) 262 require.True(t, have == must, "Have: %t, Must: %t, Elem: %v", have, must, i) 263 } 264 }