Skip to content

Commit 8b37b46

Browse files
authored
Adding swizzling. (#24)
1 parent 3a5b7a8 commit 8b37b46

File tree

5 files changed

+72
-0
lines changed

5 files changed

+72
-0
lines changed

arithmetic.go

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -364,3 +364,43 @@ func angle(a, b []float64) float64 {
364364
angle := math.Acos(dot(unit(clone(a)), unit(clone(b))))
365365
return angle
366366
}
367+
368+
func swizzle(a []float64, indices ...int) ([]float64, error) {
369+
370+
for _, i := range indices {
371+
if i < 0 || i >= len(a) {
372+
return nil, ErrNotValidSwizzleIndex
373+
}
374+
}
375+
376+
switch len(indices) {
377+
378+
case 0:
379+
return []float64{}, nil
380+
case 1:
381+
return []float64{a[indices[0]]}, nil
382+
case 2:
383+
return []float64{a[indices[0]], a[indices[1]]}, nil
384+
case 3:
385+
return []float64{a[indices[0]], a[indices[1]], a[indices[2]]}, nil
386+
case 4:
387+
return []float64{a[indices[0]], a[indices[1]], a[indices[2]], a[indices[3]]}, nil
388+
default:
389+
390+
vec := make([]float64, len(indices))
391+
392+
for i := 0; i < len(indices); i++ {
393+
394+
ind := indices[i]
395+
if ind >= len(a) {
396+
return nil, ErrNotValidSwizzleIndex
397+
}
398+
vec[i] = a[ind]
399+
400+
}
401+
402+
return vec, nil
403+
404+
}
405+
406+
}

arithmetic_test.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,3 +105,14 @@ func BenchmarkArithmeticAngle(b *testing.B) {
105105
angle(v1, v2)
106106
}
107107
}
108+
109+
func BenchmarkSwizzling(b *testing.B) {
110+
b.ReportAllocs()
111+
112+
v1 := Vector{1, 2, 19}
113+
114+
for i := 0; i < b.N; i++ {
115+
swizzle(v1, 0, 1, 2)
116+
}
117+
118+
}

errors.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,8 @@ var (
99
// ErrNotSameDimensions is an error that is returned when functions need both
1010
// Vectors provided to be the same dimensionally
1111
ErrNotSameDimensions = errors.New("the two vectors provided aren't the same dimensional size")
12+
13+
// ErrNotValidSwizzleIndex is an error that is returned when swizzling a vector and passing
14+
// an index that lies outside of the length of the vector
15+
ErrNotValidSwizzleIndex = errors.New("index for swizzling is not valid for the given vector")
1216
)

vector.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,13 @@ func (a Vector) Rotate(angle float64, axis ...Vector) Vector {
7777
return rotate(clone(a), angle, clone(as))
7878
}
7979

80+
// Swizzle returns a clone of the input vector altered using the provided swizzling indices.
81+
// For example, with `vector := {1, 3, 9}`, `vector.Swizzle(2,1,2,0)` will return `Vector{9,3,9,1}`.
82+
// Swizzle will return the swizzled vector, and an error if one of the provided indices is out of bounds.
83+
func (a Vector) Swizzle(swizzleIndices ...int) (Vector, error) {
84+
return swizzle(a, swizzleIndices...)
85+
}
86+
8087
// Angle returns the angle in radians from the first Vector to the second, and an error if the two Vectors
8188
// aren't of equal dimensions (length). For 0-dimension Vectors, the returned angle is 0. For 1-dimension Vectors,
8289
// the angle is Pi if the second Vector's coordinate is less than the first Vector's coordinate, and 0 otherwise.

vector_test.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,3 +90,13 @@ func TestXYZGetters(t *testing.T) {
9090
t.Error("getter methods for x, y, z did not return 0 when expected")
9191
}
9292
}
93+
94+
func TestSwizzling(t *testing.T) {
95+
v1 := vec{1, 12, 73.2, 99}
96+
v2, _ := v1.Swizzle(3, 0, 1, 2)
97+
98+
if v2[0] != 99 || v2[1] != 1 || v2[2] != 12 || v2[3] != 73.2 {
99+
t.Error("swizzling functions did not return values expected")
100+
}
101+
102+
}

0 commit comments

Comments
 (0)