github.com/tunabay/go-bitarray@v1.3.1/bitarray_bitwise_test.go (about)

     1  // Copyright (c) 2021 Hirotsuna Mizuno. All rights reserved.
     2  // Use of this source code is governed by the MIT license that can be found in
     3  // the LICENSE file.
     4  
     5  package bitarray_test
     6  
     7  import (
     8  	"testing"
     9  
    10  	"github.com/tunabay/go-bitarray"
    11  )
    12  
    13  func TestBitArray_TrailingZeros(t *testing.T) {
    14  	tcs := []struct {
    15  		s string
    16  		n int
    17  	}{
    18  		{"", 0},
    19  		{"1", 0},
    20  		{"10", 1},
    21  		{"110", 1},
    22  		{"1110", 1},
    23  		{"0", 1},
    24  		{"00", 2},
    25  		{"000", 3},
    26  		{"0000", 4},
    27  		{"0000-0", 5},
    28  		{"0000-00", 6},
    29  		{"0000-000", 7},
    30  		{"0000-0000", 8},
    31  		{"0000-0000 0", 9},
    32  		{"0000-0000 00", 10},
    33  		{"0000-0000 000", 11},
    34  		{"0000-0000 0000", 12},
    35  		{"0000-0000 0000-0000 0000-0000 0000-0000 0000", 36},
    36  		{"0000-0000 0000-0000 0000-0000 0000-0000 0000-000", 39},
    37  		{"0000-0000 0000-0000 0000-0000 0000-0000 0000-0000", 40},
    38  		{"0000-0000 0000-0000 0000-0000 0000-0000 0000-0000 0", 41},
    39  		{"0000-0000 0000-0000 0000-0000 0000-0000 0000-0000 0000", 44},
    40  		{"0000-0000 0000-0000 0000-0000 0000-0000 0000-0000 0000-0000", 48},
    41  		{"0001-000", 3},
    42  		{"0001-0000", 4},
    43  		{"0001-0000 0", 5},
    44  		{"0001-0001", 0},
    45  		{"0001-0000 1", 0},
    46  		{"0001-0001 00", 2},
    47  		{"0001-0000 100", 2},
    48  		{"1100-0000 1011-0", 1},
    49  		{"1100-0000 1011-00", 2},
    50  		{"1100-0000 1011-000", 3},
    51  		{"1100-0000 1011-0000", 4},
    52  		{"1100-0000 1011-0000 0", 5},
    53  		{"1100-0000 1011-0000 1", 0},
    54  		{"1100-0000 1011-0000 10", 1},
    55  		{"1100-0000 1011-0000 11", 0},
    56  		{"1010-0000 0000-0000 00", 15},
    57  		{"1010-0000 0000-0000 0000-0000 00", 23},
    58  		{"1010-0000 0000-0000 0000-0000 0000-0000", 29},
    59  		{"1010-0000 0000-0000 0000-0000 0000-0000 0", 30},
    60  		{"1010-0000 0000-0000 0000-0000 0000-0000 00", 31},
    61  		{"1", 0},
    62  		{"11", 0},
    63  		{"111", 0},
    64  		{"1111", 0},
    65  		{"1111-1", 0},
    66  		{"1111-11", 0},
    67  		{"1111-111", 0},
    68  		{"1111-1111", 0},
    69  		{"1111-1111 0", 1},
    70  		{"1111-1111 00", 2},
    71  		{"1111-1111 1", 0},
    72  		{"1111-1111 10", 1},
    73  		{"1111-1111 1100-00", 4},
    74  		{"1111-1111 1100-000", 5},
    75  		{"1111-1111 1100-0000", 6},
    76  		{"1111-1111 1100-0000 0", 7},
    77  		{"1111-1111 1100-0000 00", 8},
    78  		{"1111-1111 1111-111", 0},
    79  		{"1111-1111 1111-1111", 0},
    80  		{"1111-1111 1111-1111 1", 0},
    81  		{"0000-0000 0000-0000 1111-1111 0000-0000 00", 10},
    82  		{"0000-0000 0000-0000 1111-1110 0000-0000 00", 11},
    83  		{"0000-0000 0000-0000 1111-1111 0000-0000 11", 0},
    84  	}
    85  	for _, tc := range tcs {
    86  		for i := 0; i < 3; i++ {
    87  			ba := bitarray.MustParse(tc.s)
    88  			switch i {
    89  			case 1:
    90  				ba = ba.ZExpand()
    91  			case 2:
    92  				ba = ba.ZOptimize()
    93  			}
    94  			if n := ba.TrailingZeros(); n != tc.n {
    95  				t.Errorf("unexpected result: got %d, want %d", n, tc.n)
    96  				t.Logf("data: %#b", ba)
    97  				t.Logf("data: %s", ba.D())
    98  			}
    99  		}
   100  	}
   101  }
   102  
   103  func TestBitArray_LeadingZeros(t *testing.T) {
   104  	tcs := []struct {
   105  		s string
   106  		n int
   107  	}{
   108  		{"", 0},
   109  		{"1", 0},
   110  		{"10", 0},
   111  		{"110", 0},
   112  		{"1110", 0},
   113  		{"1110-0000", 0},
   114  		{"1110-0000 0", 0},
   115  		{"1000-0000 0000-0000", 0},
   116  		{"1000-0000 0000-0000 0000-0000 0", 0},
   117  		{"1000-0000 0000-0000 0000-0000 1", 0},
   118  		{"1000-0000 0000-0000 0000-0000 01", 0},
   119  		{"01", 1},
   120  		{"001", 2},
   121  		{"0001", 3},
   122  		{"0", 1},
   123  		{"00", 2},
   124  		{"000", 3},
   125  		{"0000", 4},
   126  		{"0000-0", 5},
   127  		{"0000-00", 6},
   128  		{"0000-000", 7},
   129  		{"0000-0000", 8},
   130  		{"0000-0000 0", 9},
   131  		{"0000-0000 00", 10},
   132  		{"0000-0000 000", 11},
   133  		{"0000-0000 0000", 12},
   134  		{"0000-0000 0000-0000 0000-0000 0000-0000 0000", 36},
   135  		{"0000-0000 0000-0000 0000-0000 0000-0000 0000-000", 39},
   136  		{"0000-0000 0000-0000 0000-0000 0000-0000 0000-0000", 40},
   137  		{"0000-0000 0000-0000 0000-0000 0000-0000 0000-0000 0", 41},
   138  		{"0000-0000 0000-0000 0000-0000 0000-0000 0000-0000 0000", 44},
   139  		{"0000-0000 0000-0000 0000-0000 0000-0000 0000-0000 0000-0000", 48},
   140  		{"0001-000", 3},
   141  		{"0001-0000", 3},
   142  		{"0001-0000 0", 3},
   143  		{"0001-0001", 3},
   144  		{"0001-0000 1", 3},
   145  		{"0000-0000 0111-0", 9},
   146  		{"0000-0000 1111-0", 8},
   147  		{"0000-0001 0111-0", 7},
   148  		{"0000-0010 0111-0", 6},
   149  		{"0000-0100 0111-0", 5},
   150  		{"0000-0000 0000-0000 0000-0000 01", 25},
   151  		{"0000-0000 0000-0000 0000-0000 10", 24},
   152  		{"0000-0000 0000-0000 0000-0001 00", 23},
   153  		{"0000-0000 0000-0000 0001-0000 00", 19},
   154  		{"0000-0000 0000-0000 1000-0000 00", 16},
   155  		{"0000-0000 0000-0001 0000-0000 00", 15},
   156  		{"0000-0000 0000-0000 0000-0000 0000-0000", 32},
   157  		{"0000-0000 0000-0000 0000-0000 0000-0001", 31},
   158  		{"0000-0000 0000-0000 0000-0000 0000-0010", 30},
   159  		{"0000-0000 0000-0000 0000-0000 0001-0000", 27},
   160  		{"0000-0000 0000-0000 0000-0000 1000-0000", 24},
   161  	}
   162  	for _, tc := range tcs {
   163  		for i := 0; i < 3; i++ {
   164  			ba := bitarray.MustParse(tc.s)
   165  			switch i {
   166  			case 1:
   167  				ba = ba.ZExpand()
   168  			case 2:
   169  				ba = ba.ZOptimize()
   170  			}
   171  			if n := ba.LeadingZeros(); n != tc.n {
   172  				t.Errorf("unexpected result: got %d, want %d", n, tc.n)
   173  				t.Logf("data: %#b", ba)
   174  				t.Logf("data: %s", ba.D())
   175  			}
   176  		}
   177  	}
   178  }
   179  
   180  func TestBitArray_OnesCount(t *testing.T) {
   181  	tcs := []struct {
   182  		s string
   183  		n int
   184  	}{
   185  		{"", 0},
   186  		{"1", 1},
   187  		{"10", 1},
   188  		{"01", 1},
   189  		{"000", 0},
   190  		{"100", 1},
   191  		{"001", 1},
   192  		{"111", 3},
   193  		{"0010", 1},
   194  		{"0011-1100", 4},
   195  		{"0100-0010 0", 2},
   196  		{"1000-0011 1", 4},
   197  		{"0000-0110 0011-1000", 5},
   198  		{"0000-0000 0000-0000 0000-0000 00", 0},
   199  		{"0000-0000 0000-0000 0000-0000 0000-0000", 0},
   200  		{"0000-0000 0000-0000 0000-0000 01", 1},
   201  		{"0010-0000 0000-1000 0001-0000 10", 4},
   202  		{"0000-1111 1111-1111 1111-1111 1111-1111", 28},
   203  		{"1111-1111 1111-1111 1111-1111 1111-1111", 32},
   204  		{"1111-1111 1111-1111 1111-1111 1111-1111 111", 35},
   205  		{"0111-1111 1111-1111 1111-1111 1111-1111 110", 33},
   206  		{"0x_ffff_ffff_ffff_ffff_ffff_ffff_ffff_ffff_ffff_fff", 156},
   207  		{"0x_ffff_0000_ffff_ffff_ffff_ffff_ffff_ffff_00ff_ff", 128},
   208  	}
   209  	for _, tc := range tcs {
   210  		for i := 0; i < 3; i++ {
   211  			ba := bitarray.MustParse(tc.s)
   212  			switch i {
   213  			case 1:
   214  				ba = ba.ZExpand()
   215  			case 2:
   216  				ba = ba.ZOptimize()
   217  			}
   218  			if n := ba.OnesCount(); n != tc.n {
   219  				t.Errorf("unexpected result: got %d, want %d", n, tc.n)
   220  				t.Logf("data: %#b", ba)
   221  				t.Logf("data: %s", ba.D())
   222  			}
   223  		}
   224  	}
   225  }
   226  
   227  func TestBitArray_And(t *testing.T) {
   228  	tdt := []string{
   229  		"", "", "",
   230  		"0", "0", "0",
   231  		"1", "0", "0",
   232  		"0", "1", "0",
   233  		"1", "1", "1",
   234  		"0101-0101", "0000-1010", "0000-0000",
   235  		"0101-0101", "1100-0011", "0100-0001",
   236  		"0000-0000 0000-0000", "0000-0000 0000-0000", "0000-0000 0000-0000",
   237  		"0000-0000 0000-0000", "1111-1111 1111-1111", "0000-0000 0000-0000",
   238  		"1111-1111 1111-1111", "0000-0000 0000-0000", "0000-0000 0000-0000",
   239  		"0000-0000 0000-0000 0", "0000-0000 0000-0000 0", "0000-0000 0000-0000 0",
   240  		"0000-0000 0000-0000 0", "0000-0000 1111-1111 0", "0000-0000 0000-0000 0",
   241  		"0000-0000 0101-0101 0", "0000-0000 0000-0000 0", "0000-0000 0000-0000 0",
   242  		"1111-1111 1111-1111 1", "1111-1111 1111-1111 1", "1111-1111 1111-1111 1",
   243  		"1010-1010 1010-1010 1", "0101-0101 0101-0101 0", "0000-0000 0000-0000 0",
   244  
   245  		"0x_00ff_ff00_0000_ffff_0000_00ff_ff00_ffff_0000_ffff_0000_ffff_000f_f0",
   246  		"0x_0000_ffff_0000_0000_0000_ffff_0000_0000_0000_cafe_0000_39f0_0055_01",
   247  		"0x_0000_ff00_0000_0000_0000_00ff_0000_0000_0000_cafe_0000_39f0_0005_00",
   248  		// TODO: more test cases
   249  	}
   250  	chk := func(got, want *bitarray.BitArray) {
   251  		t.Helper()
   252  		got.V()
   253  		if !got.Equal(want) {
   254  			t.Error("unexpected result:")
   255  			t.Logf(" got: %#b", got)
   256  			t.Logf(" got: %s", got.D())
   257  			t.Logf("want: %#b", want)
   258  			t.FailNow()
   259  		}
   260  	}
   261  	for i := 0; i < len(tdt); i += 3 {
   262  		ba0 := bitarray.MustParse(tdt[i]).ZOptimize()
   263  		ba1 := bitarray.MustParse(tdt[i+1]).ZOptimize()
   264  		ba2 := bitarray.MustParse(tdt[i+2])
   265  		ba0E := ba0.ZExpand()
   266  		ba1E := ba1.ZExpand()
   267  		chk(ba0.And(ba1), ba2)
   268  		chk(ba0.And(ba1E), ba2)
   269  		chk(ba0E.And(ba1), ba2)
   270  		chk(ba0E.And(ba1E), ba2)
   271  		chk(ba1.And(ba0), ba2)
   272  		chk(ba1.And(ba0E), ba2)
   273  		chk(ba1E.And(ba0), ba2)
   274  		chk(ba1E.And(ba0E), ba2)
   275  	}
   276  	func() {
   277  		var ba *bitarray.BitArray
   278  		defer func() {
   279  			if recover() == nil {
   280  				t.Errorf("panic expected: got %#b", ba)
   281  			}
   282  		}()
   283  		ba0 := bitarray.MustParse("0101-0101 01")
   284  		ba1 := bitarray.MustParse("0101-01")
   285  		ba = ba0.And(ba1)
   286  	}()
   287  }
   288  
   289  func TestBitArray_Or(t *testing.T) {
   290  	tdt := []string{
   291  		"", "", "",
   292  		"0", "0", "0",
   293  		"1", "0", "1",
   294  		"0", "1", "1",
   295  		"1", "1", "1",
   296  		"0101-0101", "0000-1010", "0101-1111",
   297  		"0101-0101", "1100-0011", "1101-0111",
   298  		"0000-0000 0000-0000", "0000-0000 0000-0000", "0000-0000 0000-0000",
   299  		"0000-0000 0000-0000", "1111-1111 1111-1111", "1111-1111 1111-1111",
   300  		"1111-1111 1111-1111", "0000-0000 0000-0000", "1111-1111 1111-1111",
   301  		"0000-0000 0000-0000 0", "0000-0000 0000-0000 0", "0000-0000 0000-0000 0",
   302  		"0000-0000 0000-0000 0", "0000-0000 1111-1111 0", "0000-0000 1111-1111 0",
   303  		"0000-0000 0101-0101 0", "0000-0000 0000-0000 0", "0000-0000 0101-0101 0",
   304  		"1111-1111 1111-1111 1", "1111-1111 1111-1111 1", "1111-1111 1111-1111 1",
   305  		"1010-1010 1010-1010 1", "0101-0101 0101-0101 0", "1111-1111 1111-1111 1",
   306  
   307  		"0x_0000_0000_0000_ffff_0000_0000_0000_ffff_0000_0000_0000_ffff_0000_00",
   308  		"0x_0000_ffff_0000_0000_0000_ffff_0000_0000_0000_cafe_0000_0000_0055_01",
   309  		"0x_0000_ffff_0000_ffff_0000_ffff_0000_ffff_0000_cafe_0000_ffff_0055_01",
   310  		// TODO: more test cases
   311  	}
   312  	chk := func(got, want *bitarray.BitArray) {
   313  		t.Helper()
   314  		got.V()
   315  		if !got.Equal(want) {
   316  			t.Error("unexpected result:")
   317  			t.Logf(" got: %#b", got)
   318  			t.Logf(" got: %s", got.D())
   319  			t.Logf("want: %#b", want)
   320  			t.FailNow()
   321  		}
   322  	}
   323  	for i := 0; i < len(tdt); i += 3 {
   324  		ba0 := bitarray.MustParse(tdt[i]).ZOptimize()
   325  		ba1 := bitarray.MustParse(tdt[i+1]).ZOptimize()
   326  		ba2 := bitarray.MustParse(tdt[i+2])
   327  		ba0E := ba0.ZExpand()
   328  		ba1E := ba1.ZExpand()
   329  		chk(ba0.Or(ba1), ba2)
   330  		chk(ba0.Or(ba1E), ba2)
   331  		chk(ba0E.Or(ba1), ba2)
   332  		chk(ba0E.Or(ba1E), ba2)
   333  		chk(ba1.Or(ba0), ba2)
   334  		chk(ba1.Or(ba0E), ba2)
   335  		chk(ba1E.Or(ba0), ba2)
   336  		chk(ba1E.Or(ba0E), ba2)
   337  	}
   338  	func() {
   339  		var ba *bitarray.BitArray
   340  		defer func() {
   341  			if recover() == nil {
   342  				t.Errorf("panic expected: got %#b", ba)
   343  			}
   344  		}()
   345  		ba0 := bitarray.MustParse("0101-0101 01")
   346  		ba1 := bitarray.MustParse("0101-01")
   347  		ba = ba0.Or(ba1)
   348  	}()
   349  }
   350  
   351  func TestBitArray_Xor(t *testing.T) {
   352  	tdt := []string{
   353  		"", "", "",
   354  		"0", "0", "0",
   355  		"1", "0", "1",
   356  		"0", "1", "1",
   357  		"1", "1", "0",
   358  		"0101-0101", "0000-1010", "0101-1111",
   359  		"0101-0101", "1100-0011", "1001-0110",
   360  		"0000-0000 0000-0000", "0000-0000 0000-0000", "0000-0000 0000-0000",
   361  		"0000-0000 0000-0000", "1111-1111 1111-1111", "1111-1111 1111-1111",
   362  		"1111-1111 1111-1111", "0000-0000 0000-0000", "1111-1111 1111-1111",
   363  		"0000-0000 0000-0000 0", "0000-0000 0000-0000 0", "0000-0000 0000-0000 0",
   364  		"0000-0000 0000-0000 0", "0000-0000 1111-1111 0", "0000-0000 1111-1111 0",
   365  		"0000-0000 0101-0101 0", "0000-0000 0000-0000 0", "0000-0000 0101-0101 0",
   366  		"1111-1111 1111-1111 1", "1111-1111 1111-1111 1", "0000-0000 0000-0000 0",
   367  		"1010-1010 1010-1010 1", "0101-0101 0101-0101 0", "1111-1111 1111-1111 1",
   368  		"1010-1010 1010-1010 1", "1111-0000 1111-1111 1", "0101-1010 0101-0101 0",
   369  
   370  		"0x_0000_00ff_0000_ffff_0000_00ff_0000_ffff_0000_0000_0000_ffff_00f0_ff",
   371  		"0x_0000_ffff_0000_0000_0000_ffff_0000_f0f0_f0f0_cafe_0000_0000_0055_01",
   372  		"0x_0000_ff00_0000_ffff_0000_ff00_0000_0f0f_f0f0_cafe_0000_ffff_00a5_fe",
   373  		// TODO: more test cases
   374  	}
   375  	chk := func(got, want *bitarray.BitArray) {
   376  		t.Helper()
   377  		got.V()
   378  		if !got.Equal(want) {
   379  			t.Error("unexpected result:")
   380  			t.Logf(" got: %#b", got)
   381  			t.Logf(" got: %s", got.D())
   382  			t.Logf("want: %#b", want)
   383  			t.FailNow()
   384  		}
   385  	}
   386  	for i := 0; i < len(tdt); i += 3 {
   387  		ba0 := bitarray.MustParse(tdt[i]).ZOptimize()
   388  		ba1 := bitarray.MustParse(tdt[i+1]).ZOptimize()
   389  		ba2 := bitarray.MustParse(tdt[i+2])
   390  		ba0E := ba0.ZExpand()
   391  		ba1E := ba1.ZExpand()
   392  		chk(ba0.Xor(ba1), ba2)
   393  		chk(ba0.Xor(ba1E), ba2)
   394  		chk(ba0E.Xor(ba1), ba2)
   395  		chk(ba0E.Xor(ba1E), ba2)
   396  		chk(ba1.Xor(ba0), ba2)
   397  		chk(ba1.Xor(ba0E), ba2)
   398  		chk(ba1E.Xor(ba0), ba2)
   399  		chk(ba1E.Xor(ba0E), ba2)
   400  	}
   401  	func() {
   402  		var ba *bitarray.BitArray
   403  		defer func() {
   404  			if recover() == nil {
   405  				t.Errorf("panic expected: got %#b", ba)
   406  			}
   407  		}()
   408  		ba0 := bitarray.MustParse("0101-0101 01")
   409  		ba1 := bitarray.MustParse("0101-01")
   410  		ba = ba0.Xor(ba1)
   411  	}()
   412  }
   413  
   414  func TestBitArray_Not(t *testing.T) {
   415  	tdt := []string{
   416  		"", "",
   417  		"0", "1",
   418  		"1", "0",
   419  		"000", "111",
   420  		"111", "000",
   421  		"0101-0101", "1010-1010",
   422  		"0101-0101 11", "1010-1010 00",
   423  		"0000-0000 0000-000", "1111-1111 1111-111",
   424  		"0000-0000 0000-0000", "1111-1111 1111-1111",
   425  		"0000-0000 0000-0000 0", "1111-1111 1111-1111 1",
   426  		"1111-1111 1111-111", "0000-0000 0000-000",
   427  		"1111-1111 1111-1111", "0000-0000 0000-0000",
   428  		"1111-1111 1111-1111 1", "0000-0000 0000-0000 0",
   429  		"0000-1111 1111-0000 00", "1111-0000 0000-1111 11",
   430  		"1010-1010 1010-1010 1010-1", "0101-0101 0101-0101 0101-0",
   431  		"0x_f0f0_f0f0 0x_6969_6969 101", "0x_0f0f_0f0f 0x_9696_9696 010",
   432  		// TODO: more test cases
   433  	}
   434  	chk := func(got, want *bitarray.BitArray) {
   435  		t.Helper()
   436  		got.V()
   437  		if !got.Equal(want) {
   438  			t.Error("unexpected result:")
   439  			t.Logf(" got: %#b", got)
   440  			t.Logf(" got: %s", got.D())
   441  			t.Logf("want: %#b", want)
   442  			t.FailNow()
   443  		}
   444  	}
   445  	for i := 0; i < len(tdt); i += 2 {
   446  		ba0 := bitarray.MustParse(tdt[i]).ZOptimize()
   447  		exp := bitarray.MustParse(tdt[i+1])
   448  		ba0E := ba0.ZExpand()
   449  		chk(ba0.Not(), exp)
   450  		chk(ba0E.Not(), exp)
   451  	}
   452  }
   453  
   454  func TestBitArray_AndAt(t *testing.T) {
   455  	tcs := []struct {
   456  		off            int
   457  		src, mask, dst string
   458  	}{
   459  		{0, "", "", ""},
   460  		{3, "1111", "0", "1110"},
   461  		{4, "1010", "", "1010"},
   462  		{0, "0101-0101 01", "", "0101-0101 01"},
   463  		{1, "0000-0000 00", "1111-1111", "0000-0000 00"},
   464  		{2, "1111-1111 11", "0000", "1100-0011 11"},
   465  		{10, "0101-0101 01", "", "0101-0101 01"},
   466  		{1, "1111-0101 01", "0", "1011-0101 01"},
   467  		{9, "1111-1111 11", "0", "1111-1111 10"},
   468  		{6, "0000-0000 0000-0000 000", "1111-1111 1", "0000-0000 0000-0000 000"},
   469  		{6, "1111-1111 1111-1111 111", "0000-0000 0", "1111-1100 0000-0001 111"},
   470  		{7, "1111-1111 1111-1111 111", "0", "1111-1110 1111-1111 111"},
   471  		{8, "1111-1111 1111-1111 111", "0", "1111-1111 0111-1111 111"},
   472  		{9, "1111-1111 1111-1111 111", "0", "1111-1111 1011-1111 111"},
   473  		{5, "1111-1111 1111-1111 111", "000", "1111-1000 1111-1111 111"},
   474  		{6, "1111-1111 1111-1111 111", "000", "1111-1100 0111-1111 111"},
   475  		{7, "1111-1111 1111-1111 111", "000", "1111-1110 0011-1111 111"},
   476  		{8, "1111-1111 1111-1111 111", "000", "1111-1111 0001-1111 111"},
   477  		{5, "1111-1111 1111-1111 1111-1111", "0000-0000 0000-0000", "1111-1000 0000-0000 0000-0111"},
   478  		{5, "1111-1111 1111-1010 1111-1111", "0000-0000 1111-0000", "1111-1000 0000-0010 1000-0111"},
   479  		{8, "1111-1111 0101-1010 1111-1111 11", "0000-1111", "1111-1111 0000-1010 1111-1111 11"},
   480  		// TODO: more test cases
   481  	}
   482  	chk := func(got, want *bitarray.BitArray) {
   483  		t.Helper()
   484  		got.V()
   485  		if !got.Equal(want) {
   486  			t.Error("unexpected result:")
   487  			t.Logf(" got: %#b", got)
   488  			t.Logf(" got: %s", got.D())
   489  			t.Logf("want: %#b", want)
   490  		}
   491  	}
   492  	for _, tc := range tcs {
   493  		ba0 := bitarray.MustParse(tc.src).ZOptimize()
   494  		ba0E := ba0.ZExpand()
   495  		ba1 := bitarray.MustParse(tc.mask).ZOptimize()
   496  		ba1E := ba1.ZExpand()
   497  		want := bitarray.MustParse(tc.dst)
   498  		chk(ba0.AndAt(tc.off, ba1), want)
   499  		chk(ba0.AndAt(tc.off, ba1E), want)
   500  		chk(ba0E.AndAt(tc.off, ba1), want)
   501  		chk(ba0E.AndAt(tc.off, ba1E), want)
   502  	}
   503  	// panics
   504  	bap := bitarray.MustParse("1111")
   505  	chkpanic := func(off int, xs string) {
   506  		t.Helper()
   507  		var ba *bitarray.BitArray
   508  		x := bitarray.MustParse(xs)
   509  		defer func() {
   510  			t.Helper()
   511  			if recover() == nil {
   512  				t.Errorf("panic expected: off=%d, x=%#b: got %#b", off, x, ba)
   513  			}
   514  		}()
   515  		ba = bap.AndAt(off, x)
   516  	}
   517  	chkpanic(-1, "010")
   518  	chkpanic(0, "01010")
   519  	chkpanic(3, "01")
   520  }
   521  
   522  func TestBitArray_OrAt(t *testing.T) {
   523  	tcs := []struct {
   524  		off            int
   525  		src, mask, dst string
   526  	}{
   527  		{0, "", "", ""},
   528  		{3, "1111", "0", "1111"},
   529  		{4, "1010", "", "1010"},
   530  		{0, "0101-0101 01", "", "0101-0101 01"},
   531  		{1, "0000-0000 00", "1111-1111", "0111-1111 10"},
   532  		{2, "1111-1111 11", "0000", "1111-1111 11"},
   533  		{3, "1100-1010 11", "1010", "1101-1110 11"},
   534  		{10, "0101-0101 01", "", "0101-0101 01"},
   535  		{1, "1000-0101 01", "1", "1100-0101 01"},
   536  		{9, "1111-1111 10", "1", "1111-1111 11"},
   537  		{6, "0000-0000 0000-0000 000", "1111-1111 1", "0000-0011 1111-1110 000"},
   538  		{6, "1111-1111 1111-1111 111", "0000-0000 0", "1111-1111 1111-1111 111"},
   539  		{7, "0000-0000 0000-0000 000", "1", "0000-0001 0000-0000 000"},
   540  		{8, "0000-0000 0000-0000 000", "1", "0000-0000 1000-0000 000"},
   541  		{9, "0000-0000 0000-0000 000", "1", "0000-0000 0100-0000 000"},
   542  		{5, "0000-0000 0000-0000 000", "111", "0000-0111 0000-0000 000"},
   543  		{6, "0000-0000 0000-0000 000", "111", "0000-0011 1000-0000 000"},
   544  		{7, "0000-0000 0000-0000 000", "111", "0000-0001 1100-0000 000"},
   545  		{8, "0000-0000 0000-0000 000", "111", "0000-0000 1110-0000 000"},
   546  		{5, "0000-0000 0000-0000 0000-0000", "1111-1111 1111-1111", "0000-0111 1111-1111 1111-1000"},
   547  		{6, "0000-0000 0000-0000 0000-0000", "1111-1111 1111-1111", "0000-0011 1111-1111 1111-1100"},
   548  		{8, "0000-0000 1010-0101 0000-0000 00", "1111-0000", "0000-0000 1111-0101 0000-0000 00"},
   549  		// TODO: more test cases
   550  	}
   551  	chk := func(got, want *bitarray.BitArray) {
   552  		t.Helper()
   553  		got.V()
   554  		if !got.Equal(want) {
   555  			t.Error("unexpected result:")
   556  			t.Logf(" got: %#b", got)
   557  			t.Logf(" got: %s", got.D())
   558  			t.Logf("want: %#b", want)
   559  		}
   560  	}
   561  	for _, tc := range tcs {
   562  		ba0 := bitarray.MustParse(tc.src).ZOptimize()
   563  		ba0E := ba0.ZExpand()
   564  		ba1 := bitarray.MustParse(tc.mask).ZOptimize()
   565  		ba1E := ba1.ZExpand()
   566  		want := bitarray.MustParse(tc.dst)
   567  		chk(ba0.OrAt(tc.off, ba1), want)
   568  		chk(ba0.OrAt(tc.off, ba1E), want)
   569  		chk(ba0E.OrAt(tc.off, ba1), want)
   570  		chk(ba0E.OrAt(tc.off, ba1E), want)
   571  	}
   572  	// panics
   573  	bap := bitarray.MustParse("1111")
   574  	chkpanic := func(off int, xs string) {
   575  		t.Helper()
   576  		var ba *bitarray.BitArray
   577  		x := bitarray.MustParse(xs)
   578  		defer func() {
   579  			t.Helper()
   580  			if recover() == nil {
   581  				t.Errorf("panic expected: off=%d, x=%#b: got %#b", off, x, ba)
   582  			}
   583  		}()
   584  		ba = bap.OrAt(off, x)
   585  	}
   586  	chkpanic(-1, "010")
   587  	chkpanic(0, "01010")
   588  	chkpanic(3, "01")
   589  }
   590  
   591  func TestBitArray_XorAt(t *testing.T) {
   592  	tcs := []struct {
   593  		off            int
   594  		src, mask, dst string
   595  	}{
   596  		{0, "", "", ""},
   597  		{3, "1111", "0", "1111"},
   598  		{4, "1010", "", "1010"},
   599  		{0, "0101-0101 01", "", "0101-0101 01"},
   600  		{1, "0000-0000 00", "1111-1111", "0111-1111 10"},
   601  		{2, "1111-1111 11", "0011", "1111-0011 11"},
   602  		{3, "1100-1010 11", "1010", "1101-1110 11"},
   603  		{10, "0101-0101 01", "", "0101-0101 01"},
   604  		{1, "1111-0101 01", "1", "1011-0101 01"},
   605  		{9, "1111-1111 11", "1", "1111-1111 10"},
   606  		{6, "0000-0000 0000-0000 000", "1111-1111 1", "0000-0011 1111-1110 000"},
   607  		{6, "1111-1111 1111-1111 111", "1111-1111 1", "1111-1100 0000-0001 111"},
   608  		{7, "1111-1111 1111-1111 111", "1", "1111-1110 1111-1111 111"},
   609  		{8, "1111-1111 1111-1111 111", "1", "1111-1111 0111-1111 111"},
   610  		{9, "1111-1111 1111-1111 111", "1", "1111-1111 1011-1111 111"},
   611  		{5, "0000-1111 0000-0000 000", "111", "0000-1000 0000-0000 000"},
   612  		{6, "0000-1111 0000-0000 000", "111", "0000-1100 1000-0000 000"},
   613  		{7, "0000-1111 0000-0000 000", "111", "0000-1110 1100-0000 000"},
   614  		{8, "0000-1111 0000-0000 000", "111", "0000-1111 1110-0000 000"},
   615  		{5, "1111-0000 1111-0000 1111-0000", "1111-1111 1111-1111", "1111-0111 0000-1111 0000-1000"},
   616  		{6, "1111-0000 1111-0000 1111-0000", "1111-1111 1111-1111", "1111-0011 0000-1111 0000-1100"},
   617  		{8, "0000-0000 1010-0101 0000-0000 00", "1111-0000", "0000-0000 0101-0101 0000-0000 00"},
   618  		// TODO: more test cases
   619  	}
   620  	chk := func(got, want *bitarray.BitArray) {
   621  		t.Helper()
   622  		got.V()
   623  		if !got.Equal(want) {
   624  			t.Error("unexpected result:")
   625  			t.Logf(" got: %#b", got)
   626  			t.Logf(" got: %s", got.D())
   627  			t.Logf("want: %#b", want)
   628  		}
   629  	}
   630  	for _, tc := range tcs {
   631  		ba0 := bitarray.MustParse(tc.src).ZOptimize()
   632  		ba0E := ba0.ZExpand()
   633  		ba1 := bitarray.MustParse(tc.mask).ZOptimize()
   634  		ba1E := ba1.ZExpand()
   635  		want := bitarray.MustParse(tc.dst)
   636  		chk(ba0.XorAt(tc.off, ba1), want)
   637  		chk(ba0.XorAt(tc.off, ba1E), want)
   638  		chk(ba0E.XorAt(tc.off, ba1), want)
   639  		chk(ba0E.XorAt(tc.off, ba1E), want)
   640  	}
   641  	// panics
   642  	bap := bitarray.MustParse("1111")
   643  	chkpanic := func(off int, xs string) {
   644  		t.Helper()
   645  		var ba *bitarray.BitArray
   646  		x := bitarray.MustParse(xs)
   647  		defer func() {
   648  			t.Helper()
   649  			if recover() == nil {
   650  				t.Errorf("panic expected: off=%d, x=%#b: got %#b", off, x, ba)
   651  			}
   652  		}()
   653  		ba = bap.XorAt(off, x)
   654  	}
   655  	chkpanic(-1, "010")
   656  	chkpanic(0, "01010")
   657  	chkpanic(3, "01")
   658  }