GithubHelp home page GithubHelp logo

xkonti / govec Goto Github PK

View Code? Open in Web Editor NEW
6.0 6.0 7.0 63 KB

Go library providing 2D and 3D vector operations

License: MIT License

Go 100.00%
game-development gamedev hacktoberfest math science vector

govec's People

Contributors

elliotwutingfeng avatar gray-adeyi avatar karoloslykos avatar pr0-c0der avatar sathuhebbar avatar xkonti avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

govec's Issues

Benchmark inlining helper functions

Set up benchmarks to compare performance between situations where a small helper function is implemented and where calculations are manually inlined. For example, what is the difference in performance here:

// Helper function 1
func dot(x1 T, y1 T, x2 T, y2 T) T {
	return x1*x2 + y1*y2
}

// Helper function 2
func magnitude(x, y) float64 {
	return math.Sqrt(float64(x*x + y*y))
}

// Using helpers:
func (v V2F[T]) AngleBetweenRad(v2 V2F[T]) float64 {
	dotProduct := dot(v.x, v.y, v2.x, v2.y)
	magnitudeV := magnitude(v.x, v.y)
	magnitudeV2 := magnitude(v2.x, v2.y)
	cosTheta := float64(dotProduct) / (magnitudeV * magnitudeV2)
	return math.Acos(math.Min(math.Max(cosTheta, -1.0), 1.0))
}

// Manually inlined code:
func (v V2F[T]) AngleBetweenRad(v2 V2F[T]) float64 {
	dotProduct := v.X*v2.X + v.Y*v2.Y
	magnitudeV := math.Sqrt(float64(v.X*v.X + v.Y*v.Y))
	magnitudeV2 := math.Sqrt(float64(v2.X*v2.X + v2.Y*v2.Y))
	cosTheta := float64(dotProduct) / (magnitudeV * magnitudeV2)
	return math.Acos(math.Min(math.Max(cosTheta, -1.0), 1.0))
}

This is to decide if the library needs to maintain lots of copy-pasted inlined code or it's safe to extract some of that complexity into reusable functions without reducing performance.

Implement `RandBetween` operation

Generates a vector with random components within a specified range. The range is specified by 2 vectors.

fromVec := V3F{12.3, 45.6, 78.9}
toX, toY, toZ := 12.0, 34.0, 15.0
toVec := V3F{toX, toY, toZ}

random1 := fromVec.RandBetween(toVec) // Returns a new random vector
random2 :=  fromVec.RandBetweenComp(toX, toY, toZ) // Returns a new random vector
rangeVec.RandBetweenInPlace(toVec) // Updates the existing vector with random values
rangeVec.RandBetweenInPlace(toX, toY, toZ) // Updates the existing vector with random values

Implement `ClampLen` operation

This operation clamps vector's length between specified values. This will basically scale the vector up or down in case it's length is too great or too little. Integer vectors will be converted into a float64 variant.

vec1.ClampLen(min, max)

Implement `Sin` operation

The operation calculates sinus of each vector components. For integer vectors it returns a float64 vector.

vec1.Sin()

Increase testing coverage

Please feel free to pick any of the not-implemented operation and add tests - even if not coplete.

Problem

All operations should be covered by tests to enforce that the library is correct at all times.

The challenge in thoroughly testing the library lays in the sheer amount of possible variants of each operation:

  • Each operation has 4 variants depending on vector type (V2F, V3F, V2I, V3I)
  • Some operations might have additional variants in form of Comp
  • Some operations might have additional variants in form of InPlace
  • Some operations might have additional variants in form of CompInPlace
  • Each of the 4 variants represents a range of allowed types:
    • V2F and V3F allow for float32 and float64 turning it from 2 to 4 permutations
    • V2I and V3I allow for int, int8, int16, int32 and int64 turning it from 2 to 10 permutations

An operation like Add could be considered to have a high number of variants:

  • Add, AddComp, AddInPlace, AddCompInPlace = 4 variants
  • V2F and V3F introduce 4 variants of each = 4*4 = 16variants
  • V2I and V3I introduce 10 more variants of each = 4*10 = 40variants

That produces 16+40=56 variants of Add to run multiple tests on!

Current status

Checkmark Name of the function Status
✖️ Abs Partial ( #37 )
✖️ Add Only basic for V2F and V2I implemented
✖️ AddScalar NONE
✖️ AngleBetweenDeg NONE
✖️ AngleBetweenRad NONE
✖️ Apply NONE
✖️ Array NONE
✖️ Ceil NONE
✖️ ClampComp NONE
✖️ ClampLen NONE
✖️ Cross NONE
✖️ Discard NONE
✖️ Distance NONE
✖️ Div NONE
✖️ DivScalar NONE
✖️ Dot NONE
✖️ Extend NONE
✖️ Floor NONE
✖️ Insert NONE
✖️ Inv NONE
✖️ IsZero NONE
✖️ Len NONE
✖️ LenSqrt NONE
✖️ Math NONE
✔️ Max Implemented
✔️ Min Implemented
✖️ Mod NONE
✖️ ModScalar NONE
✖️ Mul NONE
✖️ MulScalar NONE
✖️ Neg NONE
✖️ New NONE
✖️ Norm NONE
✖️ Pow NONE
✖️ Pow2 NONE
✖️ Pow3 NONE
✖️ PowN NONE
✖️ PowNFloat NONE
✖️ Round NONE
✖️ Slice NONE
✖️ Split NONE
✖️ Sqrt NONE
✖️ Sub NONE
✖️ SubScalar NONE
✖️ Swizzle NONE

Implement `Distance` operation

Calculates the distance between two vectors.

  1. Calculate vector pointing from one to the other (vec1 - vec2)
  2. Calculate the length of that vector
  3. Return the value (always float)

Functions:

  • (v V2F[T]) Distance(v2 V2F[T]) float64
  • (v V2F[T]) DistanceComp(x T, y T) float64
  • (v V3F[T]) Distance(v2 V3F[T]) float64
  • (v V3F[T]) DistanceComp(x T, y T, z T) float64
  • (v V2I[T]) Distance(v2 V2I[T]) float64
  • (v V2I[T]) DistanceComp(x T, y T) float64
  • (v V3I[T]) Distance(v2 V3I[T]) float64
  • (v V3I[T]) DistanceComp(x T, y T, z T) float64

Add GitHub Actions workflow for testing on every PR

Tests should be ran on every Pull Request. This will allow for:

  • Blocking merges if tests are failing
  • Will send clear message to contributors and maintainers that there's an issue (and often will hint where it's at)

Tests should be ran only for Pull Requests and not for merges to main branch as PRs are the only way to commit to main.

This could be a starting point for .github/workflows/pr-check.yml file:

name: Test PR

on:
  pull_request:
    branches:
      - main

jobs:
  check-pr:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout code
        uses: actions/checkout@v3

      - name: Set up Go
        uses: ???
      
      - name: Run tests
        uses: ???

Implement `IsZero` operation

Checks if the vector is a zero vector.

Example of usage:

vec1 := V2F[float64]{X: 12, Y: 0}
result := vec1.IsZero()
// result is false

Implement `Average` operation

The operation calculates the average of all vector components. For integer vectors it returns a float64 value.

vec1.Average()

Implement `Lerp` operation

Linearly interpolates between two vectors.

Functions for integer vectors should return a float vector.

Refactor library to use float32 instead of float64 whenever possible

Operations on float64 are more expensive than on float32. The library should be refactored so that float64 is as limited as possible. Things to consider:

  • cost of converting from float64 to float32 to perform further operations. It might be cheaper to continue with float64 in between areas where float64 is required.
  • If the return type of the function is not float64 the conversion cost might be considered free as it would need to happen at some point anyway.

Implement `Tan` operation

The operation calculates tangent of each vector components. For integer vectors it returns a float64 vector.

vec1.Tan()

Implement `RandIn` operation

Generates a vector with random components within a specified range. The range is specified by vector/component and a zero vector.

// These are the same
V2F{12, 13}.RandIn() == V2F{12, 13}.RandBetween(V2F{0, 0})

rangeX, rangeY, rangeZ := 12, 34, 15
rangeVec := V3I{rangeX, rangeY, rangeZ}

random1 := rangeVec.RandIn() // Returns a new random vector
rangeVec.RandInInPlace() // Updates the existing vector with random values

Implement `Cos` operation

The operation calculates cosine of each vector components. For integer vectors it returns a float64 vector.

vec1.Cos()

Implement `Rand` operation

Generates a normal vector with random components. Available only for float types. Make sure vector is normalized.

vec1 := govec.RandV2F[float64]()
vec2 := govec.RandV2F[float32]()
vec3 := govec.RandV3F[float64]()
vec4 := govec.RandV3F[float32]()

Implement `ClampComp` operation

This operation clamps each component between corresponding components of two provided vectors.

vec1.ClampComp(vec2, vec3)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.