From 0166ccb791900529b8c3f84e4bee98858ebca3a4 Mon Sep 17 00:00:00 2001 From: Timon Ringwald Date: Tue, 23 Aug 2022 21:12:41 +0200 Subject: [PATCH] vectors implemented (up to 4d) --- aliases.go | 7 +++++ constraints.go | 17 +++++++++++ go.mod | 3 ++ vec.go | 45 ++++++++++++++++++++++++++++ vec2.go | 74 ++++++++++++++++++++++++++++++++++++++++++++++ vec3.go | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++ vec4.go | 76 ++++++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 301 insertions(+) create mode 100644 aliases.go create mode 100644 constraints.go create mode 100644 go.mod create mode 100644 vec.go create mode 100644 vec2.go create mode 100644 vec3.go create mode 100644 vec4.go diff --git a/aliases.go b/aliases.go new file mode 100644 index 0000000..3abe9c6 --- /dev/null +++ b/aliases.go @@ -0,0 +1,7 @@ +package advmath + +type Vec3f = Vec3[float64] +type Vec2f = Vec2[float64] + +type Vec3i = Vec3[int] +type Vec2i = Vec2[int] diff --git a/constraints.go b/constraints.go new file mode 100644 index 0000000..747b62a --- /dev/null +++ b/constraints.go @@ -0,0 +1,17 @@ +package advmath + +type Complex interface { + ~complex64 | ~complex128 | Real +} + +type Real interface { + ~float32 | ~float64 | Natural +} + +type Natural interface { + ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | Integer +} + +type Integer interface { + ~int | ~int8 | ~int16 | ~int32 | ~int64 +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..db4e29d --- /dev/null +++ b/go.mod @@ -0,0 +1,3 @@ +module git.milar.in/milarin/advmath + +go 1.18 diff --git a/vec.go b/vec.go new file mode 100644 index 0000000..32bc93a --- /dev/null +++ b/vec.go @@ -0,0 +1,45 @@ +package advmath + +// VecConst represents any vector of a given spacial dimension +// N is the number space of the vectors individual units +type VecConst[N Real] interface { + Vec2[N] | Vec3[N] | Vec4[N] +} + +// Vec represents any vector in a given spacial dimension (up to 4d) +// N is the number space of the vectors individual units +// V is the vector dimension (one of Vec2, Vec3, Vec4) +type Vec[N Real, V VecConst[N]] interface { + X() N + Y() N + Z() N + W() N + + // Add returns a new vector which represents the sum of this vector and o + Add(o Vec[N, V]) Vec[N, V] + // Add returns a new vector which represents the difference of this vector and o + Sub(o Vec[N, V]) Vec[N, V] + // Add returns a new vector which represents the multiplication of this vector and o + Mul(o Vec[N, V]) Vec[N, V] + // Add returns a new vector which represents the division of this vector and o + Div(o Vec[N, V]) Vec[N, V] + + // Len returns the length of this vector + Len() N + // Norm returns a new vector of length 1 pointing in the same direction + Norm() Vec[N, V] + + // Dot returns the dot product of this vector and o + Dot(o Vec[N, V]) N + + // Lerp returns the vector inbetween this vector and o. + // t should be between [0, 1] (both inclusive) and determines where the returning vector should be between these vectors. + Lerp(o Vec[N, V], t N) Vec[N, V] + + StringPrecise() string + String() string +} + +var _ Vec[int, Vec2[int]] = &Vec2[int]{} +var _ Vec[int, Vec3[int]] = &Vec3[int]{} +var _ Vec[int, Vec4[int]] = &Vec4[int]{} diff --git a/vec2.go b/vec2.go new file mode 100644 index 0000000..3b00907 --- /dev/null +++ b/vec2.go @@ -0,0 +1,74 @@ +package advmath + +import ( + "fmt" + "math" +) + +type Vec2[N Real] struct { + x N + y N +} + +func V2[N Real](x, y N) Vec[N, Vec2[N]] { + return Vec2[N]{x, y} +} + +func (v Vec2[N]) X() N { + return v.x +} + +func (v Vec2[N]) Y() N { + return v.y +} + +func (v Vec2[N]) Z() N { + return 0 +} + +func (v Vec2[N]) W() N { + return 0 +} + +func (v Vec2[N]) Add(o Vec[N, Vec2[N]]) Vec[N, Vec2[N]] { + return Vec2[N]{v.X() + o.X(), v.Y()} +} + +func (v Vec2[N]) Sub(o Vec[N, Vec2[N]]) Vec[N, Vec2[N]] { + return Vec2[N]{v.X() - o.X(), v.Y() - o.Y()} +} + +func (v Vec2[N]) Mul(o Vec[N, Vec2[N]]) Vec[N, Vec2[N]] { + return Vec2[N]{v.X() * o.X(), v.Y() * o.Y()} +} + +func (v Vec2[N]) Div(o Vec[N, Vec2[N]]) Vec[N, Vec2[N]] { + return Vec2[N]{v.X() / o.X(), v.Y() / o.Y()} +} + +func (v Vec2[N]) Len() N { + return N(math.Sqrt(float64(v.X()*v.X() + v.Y()*v.Y()))) +} + +func (v Vec2[N]) Norm() Vec[N, Vec2[N]] { + l := v.Len() + return Vec2[N]{v.X() / l, v.Y() / l} +} + +func (v Vec2[N]) Dot(o Vec[N, Vec2[N]]) N { + return N(v.X()*o.X() + v.Y()*o.Y()) +} + +func (v Vec2[N]) Lerp(o Vec[N, Vec2[N]], t N) Vec[N, Vec2[N]] { + t1 := 1 - t + return v.Mul(V2(t1, t1)).Add(o.Mul(V2(t, t))) +} + +func (v Vec2[N]) String() string { + const decimals = 100000 + return fmt.Sprintf("(%g | %g)", math.Round(float64(v.X())*decimals)/decimals, math.Round(float64(v.Y())*decimals)/decimals) +} + +func (v Vec2[N]) StringPrecise() string { + return fmt.Sprintf("(%f | %f)", float64(v.X()), float64(v.Y())) +} diff --git a/vec3.go b/vec3.go new file mode 100644 index 0000000..c0dbdf7 --- /dev/null +++ b/vec3.go @@ -0,0 +1,79 @@ +package advmath + +import ( + "fmt" + "math" +) + +type Vec3[N Real] struct { + x N + y N + z N +} + +func V3[N Real](x, y, z N) Vec3[N] { + return Vec3[N]{x, y, z} +} + +func (v Vec3[N]) X() N { + return v.x +} + +func (v Vec3[N]) Y() N { + return v.y +} + +func (v Vec3[N]) Z() N { + return v.z +} + +func (v Vec3[N]) W() N { + return 0 +} + +func (v Vec3[N]) Add(o Vec[N, Vec3[N]]) Vec[N, Vec3[N]] { + return Vec3[N]{v.X() + o.X(), v.Y() + o.Y(), v.Z() + o.Z()} +} + +func (v Vec3[N]) Sub(o Vec[N, Vec3[N]]) Vec[N, Vec3[N]] { + return Vec3[N]{v.X() - o.X(), v.Y() - o.Y(), v.Z() - o.Z()} +} + +func (v Vec3[N]) Mul(o Vec[N, Vec3[N]]) Vec[N, Vec3[N]] { + return Vec3[N]{v.X() * o.X(), v.Y() * o.Y(), v.Z() * o.Z()} +} + +func (v Vec3[N]) Div(o Vec[N, Vec3[N]]) Vec[N, Vec3[N]] { + return Vec3[N]{v.X() / o.X(), v.Y() / o.Y(), v.Z() / o.Z()} +} + +func (v Vec3[N]) Len() N { + return N(math.Sqrt(float64(v.X()*v.X() + v.Y()*v.Y() + v.Z()*v.Z()))) +} + +func (v Vec3[N]) Norm() Vec[N, Vec3[N]] { + l := v.Len() + return Vec3[N]{v.X() / l, v.Y() / l, v.Z() / l} +} + +func (v Vec3[N]) Dot(o Vec[N, Vec3[N]]) N { + return N(v.X()*o.X() + v.Y()*o.Y() + v.Z()*o.Z()) +} + +func (v Vec3[N]) Cross(o Vec3[N]) Vec3[N] { + return Vec3[N]{v.Y()*o.Z() - v.Z()*o.Y(), v.Z()*o.X() - v.X()*o.Z(), v.X()*o.Y() - v.Y()*o.X()} +} + +func (v Vec3[N]) Lerp(o Vec[N, Vec3[N]], t N) Vec[N, Vec3[N]] { + t1 := 1 - t + return v.Mul(V3(t1, t1, t1)).Add(o.Mul(V3(t, t, t))) +} + +func (v Vec3[N]) String() string { + const decimals = 100000 + return fmt.Sprintf("(%g | %g | %g)", math.Round(float64(v.X())*decimals)/decimals, math.Round(float64(v.Y())*decimals)/decimals, math.Round(float64(v.Z())*decimals)/decimals) +} + +func (v Vec3[N]) StringPrecise() string { + return fmt.Sprintf("(%f | %f | %f)", float64(v.X()), float64(v.Y()), float64(v.Z())) +} diff --git a/vec4.go b/vec4.go new file mode 100644 index 0000000..8ab9d82 --- /dev/null +++ b/vec4.go @@ -0,0 +1,76 @@ +package advmath + +import ( + "fmt" + "math" +) + +type Vec4[N Real] struct { + x N + y N + z N + w N +} + +func V4[N Real](x, y, z, w N) Vec4[N] { + return Vec4[N]{x, y, z, w} +} + +func (v Vec4[N]) X() N { + return v.x +} + +func (v Vec4[N]) Y() N { + return v.y +} + +func (v Vec4[N]) Z() N { + return v.z +} + +func (v Vec4[N]) W() N { + return v.w +} + +func (v Vec4[N]) Add(o Vec[N, Vec4[N]]) Vec[N, Vec4[N]] { + return Vec4[N]{v.X() + o.X(), v.Y() + o.Y(), v.Z() + o.Z(), v.W() + o.W()} +} + +func (v Vec4[N]) Sub(o Vec[N, Vec4[N]]) Vec[N, Vec4[N]] { + return Vec4[N]{v.X() - o.X(), v.Y() - o.Y(), v.Z() - o.Z(), v.W() + o.W()} +} + +func (v Vec4[N]) Mul(o Vec[N, Vec4[N]]) Vec[N, Vec4[N]] { + return Vec4[N]{v.X() * o.X(), v.Y() * o.Y(), v.Z() * o.Z(), v.W() + o.W()} +} + +func (v Vec4[N]) Div(o Vec[N, Vec4[N]]) Vec[N, Vec4[N]] { + return Vec4[N]{v.X() / o.X(), v.Y() / o.Y(), v.Z() / o.Z(), v.W() + o.W()} +} + +func (v Vec4[N]) Len() N { + return N(math.Sqrt(float64(v.X()*v.X() + v.Y()*v.Y() + v.Z()*v.Z() + v.W()*v.W()))) +} + +func (v Vec4[N]) Norm() Vec[N, Vec4[N]] { + l := v.Len() + return Vec4[N]{v.X() / l, v.Y() / l, v.Z() / l, v.W() / l} +} + +func (v Vec4[N]) Dot(o Vec[N, Vec4[N]]) N { + return N(v.X()*o.X() + v.Y()*o.Y() + v.Z()*o.Z() + v.W()*o.W()) +} + +func (v Vec4[N]) Lerp(o Vec[N, Vec4[N]], t N) Vec[N, Vec4[N]] { + t1 := 1 - t + return v.Mul(V4(t1, t1, t1, t1)).Add(o.Mul(V4(t, t, t, t))) +} + +func (v Vec4[N]) String() string { + const decimals = 100000 + return fmt.Sprintf("(%g | %g | %g | %g)", math.Round(float64(v.X())*decimals)/decimals, math.Round(float64(v.Y())*decimals)/decimals, math.Round(float64(v.Z())*decimals)/decimals, math.Round(float64(v.W())*decimals)/decimals) +} + +func (v Vec4[N]) StringPrecise() string { + return fmt.Sprintf("(%f | %f | %f | %f)", float64(v.X()), float64(v.Y()), float64(v.Z()), float64(v.W())) +}