Skip to content

Commit

Permalink
Update readme to reflect current api (#18)
Browse files Browse the repository at this point in the history
* Update readme to reflect current API

Update docstrings and rename UnsafeVector to MutableVector.

* Remove build link
  • Loading branch information
quartercastle authored Nov 23, 2021
1 parent ac4bb73 commit 3a5b7a8
Show file tree
Hide file tree
Showing 4 changed files with 138 additions and 153 deletions.
37 changes: 8 additions & 29 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
# vector

[![Version](https://img.shields.io/github/release/kvartborg/vector.svg)](https://github.com/kvartborg/vector/releases)
[![Build Status](https://travis-ci.org/kvartborg/vector.svg?branch=master)](https://travis-ci.org/kvartborg/vector)
[![GoDoc](https://godoc.org/github.com/kvartborg/vector?status.svg)](https://pkg.go.dev/github.com/kvartborg/vector?tab=doc)
[![Go Report Card](https://goreportcard.com/badge/github.com/kvartborg/vector)](https://goreportcard.com/report/github.com/kvartborg/vector)

Expand Down Expand Up @@ -42,47 +41,27 @@ result := vec{1, 2}.Add(vec{2, 4})
```

A nice side effect of representing a vector as a list of `float64` values is that
we easily can turn a slice of `float64` into a vector by using type casting.
a slice of `float64` values can easily be turned into a vector by using type casting.
This elimitates the need for any constructor functions for the vector type.
```go
// Turn a list of floats into a vector
v := vec([]float64{1, 2, 3})
```

### Mutability vs Immutability
Most of the arithmetic operations provided by this package has a mutable and immutable implementation.
The way this is separated is that all package level functions are immutable
and methods called on the vector it self are mutable on the calling vector.
All arithmetic operations are immutable by default. But if needed a `Vector` can be
turned into a `MutableVector` with the `vector.In` function, see example below.
A mutable vector performs arithemetic operations much faster without taking up
any memory.
```go
// create vectors
v1, v2 := vec{1, 2}, vec{2, 4}

// Immutable addition, returns a new vector
result := vector.Add(v1, v2)

// Mutable addition, will do the calculation in place in the v1 vector
// Immutable addition, will return a new vector containing the result.
result := v1.Add(v2)
```

The mutable implementation is a lot faster and uses less memory compared to the immutable, this is because the calculation is done in place.
Mutable operations shall be used with care, because it can lead to bugs that can be hard to spot. A use case i find useful is to use the mutable operations when you are inlining the instantiation of the vectors.

```go
// example of safe usage of mutable operations when inlining vector instantiation.
result := vec{1, 2}.Add(vec{2, 4})
```

Or if you are creating a receiving vector where the calculation can be done in place.

```go
// Create result vector where the calculation can be done in place.
result := make(vec, 2)

// Create vectors
v1, v2 := vec{1, 2}, vec{2, 4}

// safe usage of mutable operation when called on a result vector
result.Add(v1, v2)
// Mutable addition, will do the calculation in place in the v1 vector
vector.In(v1).Add(v2)
```

### Slicing a vector
Expand Down
4 changes: 2 additions & 2 deletions doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,6 @@
// // Create a vector from a list of float64 values
// v2 := vec([]float64{2, 6})
//
// // Do operations with the vectors
// result := vector.Add(v1, v2)
// // Do arithmetic operations with the vectors
// result := v1.Add(v2)
package vector
128 changes: 128 additions & 0 deletions mutable_vector.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
package vector

// MutableVector is a vector where all arithmetic operations will be done in
// place on the calling vector. This will increase performance and minimize the
// memory consumption.
type MutableVector []float64

// In takes a vector and turns it into a mutable vector.
func In(a Vector) MutableVector {
return MutableVector(a)
}

// Clone a mutable vector.
func (a MutableVector) Clone() MutableVector {
return clone(a)
}

// Add a vector in place in the mutable vector
func (a MutableVector) Add(b Vector) MutableVector {
return add(a, b)
}

// Sum a vector with a vector or a set of vectors
func (a MutableVector) Sum(vectors ...Vector) MutableVector {
return sum(a, vectors)
}

// Sub subtracts a vector with another vector or a set of vectors
func (a MutableVector) Sub(b Vector) MutableVector {
return sub(a, b)
}

// Invert inverts the vector, and then returns it
func (a MutableVector) Invert() MutableVector {
return invert(a)
}

// Scale vector with a given size
func (a MutableVector) Scale(size float64) MutableVector {
return scale(a, size)
}

// Equal compares that two vectors are equal to each other
func (a MutableVector) Equal(b Vector) bool {
return equal(a, b)
}

// Magnitude of a vector
func (a MutableVector) Magnitude() float64 {
return magnitude(a)
}

// Unit returns a direction vector with the length of one.
func (a MutableVector) Unit() MutableVector {
return unit(a)
}

// Dot product of two vectors
func (a MutableVector) Dot(b Vector) float64 {
return dot(a, b)
}

// Cross product of two vectors
func (a MutableVector) Cross(b Vector) (Vector, error) {
return cross(a, b)
}

// Rotate is rotating a vector around an abitrary vector axis
// If no axis are specified it will default to rotate around the Z axis
//
// If a vector with more than 3-dimensions is rotated, it will cut the extra
// dimensions and return a 3-dimensional vector.
//
// NOTE: the ...MutableVector is just syntactic sugar that allows the vector axis to not be
// specified and default to the Z axis, if multiple axis is passed the first will be
// set as the rotational axis
func (a MutableVector) Rotate(angle float64, axis ...Vector) MutableVector {
as := Z

if len(axis) > 0 {
as = axis[0]
}

return rotate(a, angle, clone(as))
}

// Angle returns the angle in radians from the first MutableVector to the second, and an error if the two MutableVectors
// aren't of equal dimensions (length). For 0-dimension MutableVectors, the returned angle is 0. For 1-dimension MutableVectors,
// the angle is Pi if the second MutableVector's coordinate is less than the first MutableVector's coordinate, and 0 otherwise.
func (a MutableVector) Angle(axis ...Vector) float64 {
as := X

if len(axis) > 0 {
as = axis[0]
}

return angle(a, as)
}

// X is corresponding to doing a MutableVector[0] lookup, if index 0 does not exist yet, a
// 0 will be returned instead
func (a MutableVector) X() float64 {
if len(a) < 1 {
return 0
}

return a[x]
}

// Y is corresponding to doing a MutableVector[1] lookup, if index 1 does not exist yet, a
// 0 will be returned instead
func (a MutableVector) Y() float64 {
if len(a) < 2 {
return 0
}

return a[y]
}

// Z is corresponding to doing a MutableVector[2] lookup, if index 2 does not exist yet, a
// 0 will be returned instead
func (a MutableVector) Z() float64 {
if len(a) < 3 {
return 0
}

return a[z]
}
122 changes: 0 additions & 122 deletions unsafe_vector.go

This file was deleted.

0 comments on commit 3a5b7a8

Please sign in to comment.