bound: add Union function
Also update Intersection docs and return value name.
MODIFY
bound/bound.go
bound/bound.go
@@ -16,23 +16,45 @@ func (b Bound) IsValid() bool {
return b.Min <= b.Max
}
-// Intersection returns a Bound that is the intersection of the input bounds.
-// If the intersection is empty or if the input length is zero,
-// then the NaN Bound will be returned.
+// Intersection returns the intersection of the input bounds if possible.
+// Otherwise a NaN Bound is returned.
func Intersection(bounds ...Bound) Bound {
if len(bounds) == 0 {
return Bound{Min: math.NaN(), Max: math.NaN()}
}
- ret := Bound{Min: bounds[0].Min, Max: bounds[0].Max}
+ intersection := Bound{Min: bounds[0].Min, Max: bounds[0].Max}
for _, b := range bounds[1:] {
- ret.Min = math.Max(ret.Min, b.Min)
- ret.Max = math.Min(ret.Max, b.Max)
+ intersection.Min = math.Max(intersection.Min, b.Min)
+ intersection.Max = math.Min(intersection.Max, b.Max)
}
- if !ret.IsValid() {
+ if !intersection.IsValid() {
return Bound{Min: math.NaN(), Max: math.NaN()}
}
- return ret
+ return intersection
+}
+
+// Union returns the contiguous union of the input bounds if possible.
+// Otherwise a NaN Bound is returned.
+func Union(bounds ...Bound) Bound {
+ if len(bounds) == 0 {
+ return Bound{Min: math.NaN(), Max: math.NaN()}
+ }
+
+ union := Bound{Min: bounds[0].Min, Max: bounds[0].Max}
+ for _, b := range bounds[1:] {
+ if b.Max < union.Min || union.Max < b.Min {
+ return Bound{Min: math.NaN(), Max: math.NaN()}
+ }
+ union.Min = math.Min(union.Min, b.Min)
+ union.Max = math.Max(union.Max, b.Max)
+ }
+
+ if !union.IsValid() {
+ return Bound{Min: math.NaN(), Max: math.NaN()}
+ }
+
+ return union
}

MODIFY
bound/bound_test.go
bound/bound_test.go
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+// TODO: Rewrite these tests as table-driven.
+
package bound
import (
@@ -75,3 +77,45 @@ func TestIsValid(t *testing.T) {
t.Error("b4 is invalid")
}
}
+
+func TestUnion(t *testing.T) {
+ b0 := Bound{Min: 0.0, Max: 5.0}
+ b1 := Bound{Min: 3.0, Max: 4.0}
+ b2 := Bound{Min: -1.0, Max: 1.0}
+ b3 := Bound{Min: 1.0, Max: 2.0}
+ b4 := Bound{Min: 1.1, Max: 2.0}
+
+ ret := Union(b0)
+ expected := Bound{Min: 0.0, Max: 5.0}
+ if ret != expected {
+ t.Errorf("Intersection(b0) should be %v but got %v", expected, ret)
+ }
+
+ ret = Union(b0, b1)
+ expected = Bound{Min: 0.0, Max: 5.0}
+ if ret != expected {
+ t.Errorf("Intersection(b0, b1) should be %v but got %v", expected, ret)
+ }
+
+ ret = Union(b0, b2)
+ expected = Bound{Min: -1.0, Max: 5.0}
+ if ret != expected {
+ t.Errorf("Intersection(b0, b2) should be %v but got %v", expected, ret)
+ }
+
+ ret = Union(b2, b3)
+ expected = Bound{Min: -1.0, Max: 2.0}
+ if ret != expected {
+ t.Errorf("Intersection(b0, b2) should be %v but got %v", expected, ret)
+ }
+
+ ret = Union(b2, b4)
+ if ret.IsValid() {
+ t.Errorf("Intersection(b2, b4) should be be valid but got %v", ret)
+ }
+
+ ret = Union()
+ if ret.IsValid() {
+ t.Error("Intersection() with zero input length should not be valid")
+ }
+}

bound: add Union function

Also update Intersection docs and return value name.