diff --git a/pkg/hypercube/hypercubeset.go b/pkg/hypercube/hypercubeset.go index e8e022f..ff2461f 100644 --- a/pkg/hypercube/hypercubeset.go +++ b/pkg/hypercube/hypercubeset.go @@ -4,6 +4,7 @@ package hypercube import ( "errors" + "log" "slices" "sort" "strings" @@ -254,9 +255,12 @@ func (c *CanonicalSet) GetCubesList() [][]*interval.CanonicalSet { // SwapDimensions returns a new CanonicalSet object, built from the input CanonicalSet object, // with dimensions dim1 and dim2 swapped func (c *CanonicalSet) SwapDimensions(dim1, dim2 int) *CanonicalSet { - if c.IsEmpty() { + if c.IsEmpty() || dim1 == dim2 { return c.Copy() } + if min(dim1, dim2) < 0 || max(dim1, dim2) >= c.dimensions { + log.Panicf("invalid dimensions: %d, %d", dim1, dim2) + } res := NewCanonicalSet(c.dimensions) for _, cube := range c.GetCubesList() { if !cube[dim1].Equal(cube[dim2]) { diff --git a/pkg/hypercube/hypercubeset_test.go b/pkg/hypercube/hypercubeset_test.go index f9dd49a..6f8f5d1 100644 --- a/pkg/hypercube/hypercubeset_test.go +++ b/pkg/hypercube/hypercubeset_test.go @@ -369,3 +369,88 @@ func TestOr2(t *testing.T) { ) require.True(t, expected.Equal(a)) } + +// Assisted by WCA for GP +// Latest GenAI contribution: granite-20B-code-instruct-v2 model +// TestSwapDimensions tests the SwapDimensions method of the CanonicalSet type. +func TestSwapDimensions(t *testing.T) { + tests := []struct { + name string + c *hypercube.CanonicalSet + dim1 int + dim2 int + expected *hypercube.CanonicalSet + }{ + { + name: "empty set", + c: hypercube.NewCanonicalSet(2), + dim1: 0, + dim2: 1, + expected: hypercube.NewCanonicalSet(2), + }, + { + name: "0,0 of 1", + c: hypercube.Cube(1, 2), + dim1: 0, + dim2: 0, + expected: hypercube.Cube(1, 2), + }, + { + name: "0,1 of 2", + c: hypercube.Cube(1, 2, 3, 4), + dim1: 0, + dim2: 1, + expected: hypercube.Cube(3, 4, 1, 2), + }, + { + name: "0,1 of 2, no-op", + c: hypercube.Cube(1, 2, 1, 2), + dim1: 0, + dim2: 1, + expected: hypercube.Cube(1, 2, 1, 2), + }, + { + name: "0,1 of 3", + c: hypercube.Cube(1, 2, 3, 4, 5, 6), + dim1: 0, + dim2: 1, + expected: hypercube.Cube(3, 4, 1, 2, 5, 6), + }, + { + name: "1,2 of 3", + c: hypercube.Cube(1, 2, 3, 4, 5, 6), + dim1: 1, + dim2: 2, + expected: hypercube.Cube(1, 2, 5, 6, 3, 4), + }, + { + name: "0,2 of 3", + c: hypercube.Cube(1, 2, 3, 4, 5, 6), + dim1: 0, + dim2: 2, + expected: hypercube.Cube(5, 6, 3, 4, 1, 2), + }, + { + name: "0,1 of 2, non-cube", + c: union( + hypercube.Cube(1, 3, 7, 20), + hypercube.Cube(20, 23, 7, 20), + ), + dim1: 0, + dim2: 1, + expected: union( + hypercube.Cube(7, 20, 1, 3), + hypercube.Cube(7, 20, 20, 23), + ), + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + actual := tt.c.SwapDimensions(tt.dim1, tt.dim2) + require.True(t, tt.expected != actual) + require.True(t, tt.expected.Equal(actual)) + }) + } + require.Panics(t, func() { hypercube.Cube(1, 2).SwapDimensions(0, 1) }) + require.Panics(t, func() { hypercube.Cube(1, 2).SwapDimensions(-1, 0) }) +}