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  }