fixed

package module
v0.3.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 1, 2026 License: MIT Imports: 3 Imported by: 0

README

fixed

fixed is a small Go package for signed fixed-point arithmetic. Equal inputs produce the same result bits on every supported architecture.

The package provides two formats without choosing a default. Q32 stores Q32.32 in an int64, with resolution 2⁻³² and range [-2³¹, 2³¹ - 2⁻³²]. Q16 stores Q16.16 in an int32, with resolution 2⁻¹⁶ and range [-2¹⁵, 2¹⁵ - 2⁻¹⁶]. Consumers choose the format that fits their range and storage requirements.

The module is pre-v1. Its import path may change before the first stable release. It requires Go 1.26.4 or newer.

Install

go get github.com/dhannyell/fixed

Quick start

package main

import (
	"fmt"

	"github.com/dhannyell/fixed"
)

func main() {
	a := fixed.Vec2{X: fixed.Q32FromInt(1), Y: fixed.Q32FromInt(2)}
	b := fixed.Vec2{X: fixed.Q32FromInt(4), Y: fixed.Q32FromInt(6)}
	distance := a.Distance(b)

	quarterTurn := fixed.RotFromTurns(fixed.Q32FromRatio(1, 4))
	direction := quarterTurn.Apply(fixed.Vec2{X: fixed.Q32One()})

	fmt.Println(distance)                 // 5
	fmt.Println(direction.X, direction.Y) // 0 1
}

Why there is no float constructor

Floating-point input can already contain small differences caused by an earlier computation. The package cannot recover the intended exact value from those bits. For this reason, fixed accepts only explicit inputs:

  • Q32FromInt and Q16FromInt for integers.
  • Q32FromRatio and Q16FromRatio for exact ratios.
  • Q32MustParse and Q16MustParse for decimal literals.
  • Q32FromRaw and Q16FromRaw for exact bit patterns.

String provides the inverse text boundary. It emits a canonical decimal representation, and every value satisfies:

fixed.Q32MustParse(q32.String()) == q32
fixed.Q16MustParse(q16.String()) == q16

Arithmetic contract

Both formats use the same explicit rule for each operation:

Operation Result
Add, Sub Exact result in the selected format, with saturation on overflow
Mul Product floored to the selected format, with saturation on overflow
Div, Q32FromRatio, Q16FromRatio Quotient truncated toward zero, with saturation on overflow
Sqrt Square root floored to the selected format
Round, Q32MustParse, Q16MustParse Nearest representable value; exact halves round away from zero
Q32.ToQ16 Floored to Q16.16, with saturation on overflow

Q16.ToQ32 is exact and never saturates. Narrowing and division deliberately use different rules: narrowing floors, while division truncates toward zero.

Division by zero panics. Sqrt of a negative value also panics.

Saturated addition is not associative near the limits. Reordering a sum can therefore change its result. Accumulators should have enough headroom to avoid saturation.

Every saturation increments a process-wide atomic counter. SaturationCount provides diagnostics without changing any fixed-point value or operation result.

Cost of operations

The contract promises bits, not speed. The numbers below are a guide for design choices on one machine: AMD Ryzen 7 5800X3D (amd64), Go 1.26.4. They are medians of ten runs with -benchtime=500ms; Windows scheduling produced occasional high outliers that the median excludes.

Operation Latency (ns) Throughput (ns) Throughput (M op/s) Fixed / float throughput
Q16.Add 0.5 0.5 2,000 0.83×
Q16.Mul 1.7 0.8 1,200 1.30×
Q16.Div 3.3 1.1 910 1.35×
Q16.Sqrt 10.3 3.2 310 3.05×
Q32.Add 0.4 0.5 1,900 0.73×
Q32.Mul 2.8 1.4 690 2.14×
Q32.Div 4.7 3.1 330 2.38×
Q32.Sqrt 13.6 6.1 160 2.65×
Vec2.Dot 3.3 3.4 290 5.35×
Vec2.Len 16.0 13.1 76 3.47×
Vec2.Normalize 26.4 18.3 55 4.82×
Vec2.Normalize axial 12.5 11.4 87 3.80×
Rot.Apply 5.5 5.9 170 7.88×
Rot.Mul 5.6 6.1 160 8.18×
Rot.Normalize 26.7 18.5 54 4.79×
SinTurns + CosTurns — 4.3 per pair 230 pairs 0.39×
RotFromTurns — 3.5 280 0.36×
Atan2Turns — 3.9 250 0.46×

Read each column alone; the columns measure different situations. Latency is the cost when each result feeds the next operation, as in an iterative solver. Throughput is the cost when independent operations overlap in the pipeline, as in a loop over many values. The rate column is the reciprocal of the throughput column, rounded to two digits; use it to size a frame budget. Each latency chain also contains one cheap companion operation that keeps the value in domain; bench_test.go shows the exact chains.

The comparison column comes from paired benchmarks over the same prebuilt inputs: Q16 is compared with float32, while Q32, vectors, and rotations are compared with float64. A value below 1× means fixed was faster; a value above 1× is the fixed-point penalty. These safe-domain float kernels do not reproduce the package's saturation, rounding, or cross-architecture bit contract. Run them with:

go test -run '^$' -bench '^BenchmarkCompare' -benchtime=500ms -count=10

Two portability notes. Div costs more on arm64, because the 128-bit division is a software routine there. Sqrt does not divide on any architecture: its hardware seed plus integer corrections stay within multiplications.

Vectors and angles

Vec2 provides the usual 2D operations over Q32: addition, scaling, dot product, length, normalization, distance, and interpolation. LenSq follows the scalar operation order and can saturate even when the length still fits. Len uses a 128-bit intermediate and saturates only when the final magnitude does not fit. Normalize scales the components before squaring them, which avoids intermediate overflow and underflow.

Angles use turns instead of radians. Q32One() is one complete revolution, Q32Half() is half a revolution, and Q32FromRatio(1, 4) is a quarter turn. This maps the fractional bits of Q32 directly onto the circle and avoids reduction through an approximation of pi.

SinTurns, CosTurns, and Atan2Turns use committed lookup tables and linear interpolation. Their maximum absolute error is 2⁻²⁰. Rot stores a rotation as its sine and cosine, which makes application, composition, and inversion available without another trigonometric lookup. The zero value of Rot is not a valid rotation; start with RotIdentity or RotFromTurns.

Architecture

fixed is a leaf module. The package imports only math, math/bits, and sync/atomic. The math import provides hardware seeds; exact integer comparisons close every result, so floating point never decides a bit. This small dependency surface lets applications use the numeric type without importing unrelated systems.

The Q32 and Q16 types are opaque. Their prefixed constructors make the chosen format explicit. Operations own saturation and rounding, and Raw is the boundary for exact bit access. Consumers that standardize on one format can define local aliases without imposing that choice on other users of the library.

The module is one flat package by design. Every public type shares one contract, so subpackages would only split the documentation and add import noise. File names carry the layers: q*/decimal* for the scalar, vec2* and rot* for the plane, trig* for the kernel. Directories exist only for content outside the package interface: internal/ for tools and .github/ for CI.

The Go implementation defines the bit-level contract. An independent implementation must preserve the rounding, saturation, and raw representation before it exchanges values with this package. A change to one of these rules is a semantic change, not an internal refactor.

Development

Run the standard checks before submitting a change:

go test ./...
go vet ./...
golangci-lint run ./...

See the package documentation for the API reference and the full behavioral contract.

License

fixed is available under the MIT License.

Documentation

Overview

Package fixed implements deterministic signed fixed-point arithmetic.

The package provides two formats without choosing a default. Q32 stores Q32.32 in an int64, with resolution 2⁻³² and range [-2³¹, 2³¹ - 2⁻³²]. Q16 stores Q16.16 in an int32, with resolution 2⁻¹⁶ and range [-2¹⁵, 2¹⁵ - 2⁻¹⁶]. Each operation produces the same bits on every supported architecture.

Overflow

An overflow saturates to the minimum or maximum of the selected format. SaturationCount reports saturation events for diagnostics. The counter does not affect fixed-point values or operation results.

Q32.Div and Q16.Div panic for a zero divisor. Q32FromRatio and Q16FromRatio panic for a zero denominator. Q32.Sqrt and Q16.Sqrt panic for a negative input.

Saturated addition is not associative near the range limits. Do not reorder an accumulation. Use enough numeric headroom to prevent saturation.

Rounding

Q32.Mul floors the 128-bit product when it converts the result to Q32.32. Q16.Mul floors the exact 62-bit product when it converts the result to Q16.16. Both operations match an arithmetic right shift.

Q32.Div, Q16.Div, Q32FromRatio, and Q16FromRatio truncate toward zero. Q32.Sqrt and Q16.Sqrt floor their results. Q32.Round, Q16.Round, Q32MustParse, and Q16MustParse round to the nearest representable value. An exact half rounds away from zero.

Formats and conversion

Q16.ToQ32 widens exactly and never saturates. Q32.ToQ16 floors to the Q16.16 grid and saturates outside the Q16 range. For any Q16 values a and b, a.Mul(b) equals a.ToQ32().Mul(b.ToQ32()).ToQ16(). The same identity does not hold for Div because division truncates toward zero and narrowing floors.

Construction and text

Q32 and Q16 are opaque. Construct Q32 values with Q32FromInt, Q32FromRatio, Q32MustParse, or Q32FromRaw. Construct Q16 values with Q16FromInt, Q16FromRatio, Q16MustParse, or Q16FromRaw. The package does not accept float values because a computed float can contain architecture-dependent bits.

Q32.String and Q16.String return exact canonical decimal forms. For every value q, parsing q.String() with the constructor for its format returns q.

Angles

Angles use turns. Q32One is a full revolution. The fractional bits of a Q32 map directly to the circle, so range reduction does not use pi and does not round.

SinTurns and CosTurns accept every Q32 value. They never panic or saturate, and their results stay in [-Q32One, Q32One]. They use a 1024-interval quarter-wave table. Table entries round to nearest, and linear interpolation floors. The maximum absolute error is 2⁻²⁰.

Atan2Turns returns an angle in (-1/2, 1/2] turns. It reduces the input to a ratio in [0, 1], truncates that ratio to Q32.32, and uses a 1024-interval table. Table entries round to nearest, and linear interpolation floors. Octant reconstruction is exact.

Vectors and rotations

Vec2.LenSq composes scalar multiplication and addition, so it can saturate even when the length fits in Q32.32. Vec2.Len computes the length with a 128-bit intermediate and saturates only when the final length is out of range. Vec2.Normalize scales the components before it squares them, so intermediate underflow cannot turn a nonzero vector into the zero vector.

Rot stores a rotation as its sine and cosine. The zero Rot is invalid. Use RotIdentity or RotFromTurns to construct a rotation. Repeated composition can introduce rounding drift; Rot.Normalize restores unit length.

Compatibility contract

The two raw representations, their conversions, saturation rules, and rounding rules are part of the public contract. An independent implementation must reproduce these rules before it exchanges raw values with this package. The trigonometric raw outputs are also part of the contract. A compatible implementation may use a different representation, but it must produce the same output bits.

Dependencies

The fixed package imports only math, math/bits, and sync/atomic. The math import provides hardware seeds; exact integer comparisons close every result, so floating point never decides a bit.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func ResetSaturationCount

func ResetSaturationCount()

ResetSaturationCount zeroes the saturation counter.

func SaturationCount

func SaturationCount() uint64

SaturationCount reports the number of saturation events since the last reset.

Types

type Q16 added in v0.3.0

type Q16 struct {
	// contains filtered or unexported fields
}

Q16 stores an opaque signed Q16.16 value. Its zero value is 0.

Example
package main

import (
	"fmt"

	"github.com/dhannyell/fixed"
)

func main() {
	// Q16 is the compact format. It converts to and from Q32.
	price := fixed.Q16FromRatio(5, 2)
	total := price.Mul(fixed.Q16FromInt(4))
	fmt.Println(total)
	fmt.Println(total.ToQ32().Eq(fixed.Q32FromInt(10)))
}
Output:
10
true

func Q16FromInt added in v0.3.0

func Q16FromInt(i int) Q16

Q16FromInt returns i as a Q16 value. It saturates outside [-2¹⁵, 2¹⁵-1].

func Q16FromRatio added in v0.3.0

func Q16FromRatio(num, den int) Q16

Q16FromRatio returns num/den truncated toward zero. It saturates on overflow. It panics when den is zero.

func Q16FromRaw added in v0.3.0

func Q16FromRaw(raw int32) Q16

Q16FromRaw returns the Q16 value with the specified signed bit pattern.

func Q16Half added in v0.3.0

func Q16Half() Q16

Q16Half returns the fixed-point value 1/2.

func Q16MaxValue added in v0.3.0

func Q16MaxValue() Q16

Q16MaxValue returns the largest representable Q16 value, 2¹⁵ - 2⁻¹⁶.

func Q16MinValue added in v0.3.0

func Q16MinValue() Q16

Q16MinValue returns the smallest representable Q16 value, -2¹⁵.

func Q16MustParse added in v0.3.0

func Q16MustParse(s string) Q16

Q16MustParse parses a decimal literal. It rounds to the nearest Q16 value, with exact halves away from zero. It saturates outside the Q16 range and panics on malformed input.

func Q16One added in v0.3.0

func Q16One() Q16

Q16One returns the fixed-point value 1.

func Q16Zero added in v0.3.0

func Q16Zero() Q16

Q16Zero returns the fixed-point value 0.

func (Q16) Abs added in v0.3.0

func (q Q16) Abs() Q16

Abs returns the magnitude of q. Abs of the minimum saturates to the maximum.

func (Q16) Add added in v0.3.0

func (q Q16) Add(o Q16) Q16

Add returns q+o. It saturates on overflow.

func (Q16) Ceil added in v0.3.0

func (q Q16) Ceil() Q16

Ceil returns the smallest integer multiple of Q16One not below q. It saturates when the result is outside the Q16 range.

func (Q16) Clamp added in v0.3.0

func (q Q16) Clamp(lo, hi Q16) Q16

Clamp returns q limited to [lo, hi]. It requires lo <= hi.

func (Q16) Cmp added in v0.3.0

func (q Q16) Cmp(o Q16) int

Cmp returns -1 when q < o, 0 when q == o, and 1 when q > o.

func (Q16) Div added in v0.3.0

func (q Q16) Div(o Q16) Q16

Div returns q/o truncated toward zero. It saturates on overflow. It panics when o is zero.

func (Q16) Eq added in v0.3.0

func (q Q16) Eq(o Q16) bool

Eq reports whether q == o.

func (Q16) Floor added in v0.3.0

func (q Q16) Floor() Q16

Floor returns the largest integer multiple of Q16One not above q.

func (Q16) Greater added in v0.3.0

func (q Q16) Greater(o Q16) bool

Greater reports whether q > o.

func (Q16) Int added in v0.3.0

func (q Q16) Int() int

Int returns the integer part truncated toward zero.

func (Q16) Less added in v0.3.0

func (q Q16) Less(o Q16) bool

Less reports whether q < o.

func (Q16) Max added in v0.3.0

func (q Q16) Max(o Q16) Q16

Max returns the larger of q and o.

func (Q16) Min added in v0.3.0

func (q Q16) Min(o Q16) Q16

Min returns the smaller of q and o.

func (Q16) Mul added in v0.3.0

func (q Q16) Mul(o Q16) Q16

Mul returns q*o. It floors the product to Q16.16 and saturates on overflow.

func (Q16) Neg added in v0.3.0

func (q Q16) Neg() Q16

Neg returns -q. Neg of the minimum saturates to the maximum.

func (Q16) Raw added in v0.3.0

func (q Q16) Raw() int32

Raw returns the signed Q16.16 bit pattern of q.

func (Q16) Round added in v0.3.0

func (q Q16) Round() Q16

Round returns the nearest integer multiple of Q16One. An exact half rounds away from zero. Round saturates when the result is outside the Q16 range.

func (Q16) Sqrt added in v0.3.0

func (q Q16) Sqrt() Q16

Sqrt returns floor(sqrt(q)). It panics when q is negative. The result cannot overflow.

func (Q16) String added in v0.3.0

func (q Q16) String() string

String returns the exact canonical decimal form of q. The widening conversion is exact, so the Q32 formatter emits the same value.

func (Q16) Sub added in v0.3.0

func (q Q16) Sub(o Q16) Q16

Sub returns q-o. It saturates on overflow.

func (Q16) ToQ32 added in v0.3.0

func (q Q16) ToQ32() Q32

ToQ32 returns q widened to Q32.32. The conversion is exact and never saturates.

type Q32 added in v0.3.0

type Q32 struct {
	// contains filtered or unexported fields
}

Q32 stores an opaque signed Q32.32 value. Its zero value is 0.

func Atan2Turns added in v0.2.1

func Atan2Turns(y, x Q32) Q32

Atan2Turns returns the angle of (x, y) in (-1/2, 1/2] turns. Atan2Turns(Zero(), Zero()) returns Zero. It never panics or saturates. The unit ratio is truncated to Q32.32, table entries round to nearest, and linear interpolation floors. The maximum absolute error is 2⁻²⁰ turn.

func CosTurns added in v0.2.1

func CosTurns(t Q32) Q32

CosTurns returns the cosine of t in turns. It uses the same rules as SinTurns with a quarter-turn shift.

func Q32FromInt added in v0.3.0

func Q32FromInt(i int) Q32

Q32FromInt returns i as a Q32 value. It saturates outside [-2³¹, 2³¹-1].

Example
package main

import (
	"fmt"

	"github.com/dhannyell/fixed"
)

func main() {
	fmt.Println(fixed.Q32FromInt(3))
	fmt.Println(fixed.Q32FromInt(-2))
}
Output:
3
-2

func Q32FromRatio added in v0.3.0

func Q32FromRatio(num, den int) Q32

Q32FromRatio returns num/den truncated toward zero. It saturates on overflow. It panics when den is zero.

Example
package main

import (
	"fmt"

	"github.com/dhannyell/fixed"
)

func main() {
	// Use a ratio for exact fractional constants. There is no FromFloat.
	q := fixed.Q32FromRatio(5, 2)
	fmt.Println(q)
}
Output:
2.5

func Q32FromRaw added in v0.3.0

func Q32FromRaw(raw int64) Q32

Q32FromRaw returns the Q32 value with the specified signed bit pattern.

func Q32Half added in v0.3.0

func Q32Half() Q32

Q32Half returns the fixed-point value 1/2.

func Q32MaxValue added in v0.3.0

func Q32MaxValue() Q32

Q32MaxValue returns the largest representable Q32 value, 2³¹ - 2⁻³².

func Q32MinValue added in v0.3.0

func Q32MinValue() Q32

Q32MinValue returns the smallest representable Q32 value, -2³¹.

func Q32MustParse added in v0.3.0

func Q32MustParse(s string) Q32

Q32MustParse parses a decimal literal. It rounds to the nearest Q32 value, with exact halves away from zero. It saturates outside the Q32 range and panics on malformed input.

Example
package main

import (
	"fmt"

	"github.com/dhannyell/fixed"
)

func main() {
	fmt.Println(fixed.Q32MustParse("6.25"))
	fmt.Println(fixed.Q32MustParse("-0.001"))
}
Output:
6.25
-0.00099999993108212947845458984375

func Q32One added in v0.3.0

func Q32One() Q32

Q32One returns the fixed-point value 1.

func Q32Zero added in v0.3.0

func Q32Zero() Q32

Q32Zero returns the fixed-point value 0.

func SinTurns added in v0.2.1

func SinTurns(t Q32) Q32

SinTurns returns the sine of t, where One is a full revolution. It uses only the fractional part of t, accepts every Q32 value, and returns a value in [-One, One] without saturation.

The 1024-interval quarter-wave table rounds entries to nearest. Linear interpolation floors. The maximum absolute error is 2⁻²⁰.

func (Q32) Abs added in v0.3.0

func (q Q32) Abs() Q32

Abs returns the magnitude of q. Abs of MinValue saturates to MaxValue.

func (Q32) Add added in v0.3.0

func (q Q32) Add(o Q32) Q32

Add returns q+o. It saturates on overflow.

func (Q32) Ceil added in v0.3.0

func (q Q32) Ceil() Q32

Ceil returns the smallest integer multiple of One that is not below q. It saturates when the result is outside the Q32 range.

func (Q32) Clamp added in v0.3.0

func (q Q32) Clamp(lo, hi Q32) Q32

Clamp returns q limited to [lo, hi]. It requires lo <= hi.

Example
package main

import (
	"fmt"

	"github.com/dhannyell/fixed"
)

func main() {
	speed := fixed.Q32FromInt(150)
	limited := speed.Clamp(fixed.Q32Zero(), fixed.Q32FromInt(100))
	fmt.Println(limited)
}
Output:
100

func (Q32) Cmp added in v0.3.0

func (q Q32) Cmp(o Q32) int

Cmp returns -1 when q < o, 0 when q == o, and 1 when q > o.

func (Q32) Div added in v0.3.0

func (q Q32) Div(o Q32) Q32

Div returns q/o truncated toward zero. It saturates on overflow. It panics when o is zero.

func (Q32) Eq added in v0.3.0

func (q Q32) Eq(o Q32) bool

Eq reports whether q == o.

func (Q32) Floor added in v0.3.0

func (q Q32) Floor() Q32

Floor returns the largest integer multiple of One not above q.

func (Q32) Greater added in v0.3.0

func (q Q32) Greater(o Q32) bool

Greater reports whether q > o.

func (Q32) Int added in v0.3.0

func (q Q32) Int() int

Int returns the integer part truncated toward zero.

func (Q32) Less added in v0.3.0

func (q Q32) Less(o Q32) bool

Less reports whether q < o.

func (Q32) Max added in v0.3.0

func (q Q32) Max(o Q32) Q32

Max returns the larger of q and o.

func (Q32) Min added in v0.3.0

func (q Q32) Min(o Q32) Q32

Min returns the smaller of q and o.

func (Q32) Mul added in v0.3.0

func (q Q32) Mul(o Q32) Q32

Mul returns q*o. It floors the product to Q32.32 and saturates on overflow.

Example
package main

import (
	"fmt"

	"github.com/dhannyell/fixed"
)

func main() {
	area := fixed.Q32FromRatio(5, 2).Mul(fixed.Q32FromInt(4))
	fmt.Println(area)
}
Output:
10

func (Q32) Neg added in v0.3.0

func (q Q32) Neg() Q32

Neg returns -q. Neg of MinValue saturates to MaxValue.

func (Q32) Raw added in v0.3.0

func (q Q32) Raw() int64

Raw returns the signed Q32.32 bit pattern of q.

func (Q32) Round added in v0.3.0

func (q Q32) Round() Q32

Round returns the nearest integer multiple of One. An exact half rounds away from zero. Round saturates when the result is outside the Q32 range.

func (Q32) Sqrt added in v0.3.0

func (q Q32) Sqrt() Q32

Sqrt returns floor(sqrt(q)). It panics when q is negative. The result cannot overflow.

func (Q32) String added in v0.3.0

func (q Q32) String() string

String returns the exact canonical decimal form of q, such as "-6.25". For every q, MustParse(q.String()) == q. Use Raw for the exact bit pattern.

Example
package main

import (
	"fmt"

	"github.com/dhannyell/fixed"
)

func main() {
	q := fixed.Q32FromRaw(1)
	text := q.String()
	fmt.Println(text)
	fmt.Println(fixed.Q32MustParse(text).Eq(q))
}
Output:
0.00000000023283064365386962890625
true

func (Q32) Sub added in v0.3.0

func (q Q32) Sub(o Q32) Q32

Sub returns q-o. It saturates on overflow.

func (Q32) ToQ16 added in v0.3.0

func (q Q32) ToQ16() Q16

ToQ16 floors q to the Q16.16 grid and saturates outside the Q16 range. Flooring matches the rounding of Mul.

type Rot added in v0.2.1

type Rot struct {
	Sin, Cos Q32
}

Rot is a 2D rotation stored as its sine and cosine.

The zero Rot is not a valid rotation; start from RotIdentity or RotFromTurns.

func RotFromTurns added in v0.2.1

func RotFromTurns(t Q32) Rot

RotFromTurns returns the rotation by the angle t in turns. It shares the kernel and the contract of SinTurns and CosTurns.

Example
package main

import (
	"fmt"

	"github.com/dhannyell/fixed"
)

func main() {
	// A quarter turn sends (1, 0) to (0, 1) exactly.
	r := fixed.RotFromTurns(fixed.Q32FromRatio(1, 4))
	v := r.Apply(fixed.Vec2{X: fixed.Q32One(), Y: fixed.Q32Zero()})
	fmt.Println(v.X, v.Y)
}
Output:
0 1

func RotIdentity added in v0.2.1

func RotIdentity() Rot

RotIdentity returns the rotation by zero turns.

func (Rot) Apply added in v0.2.1

func (r Rot) Apply(v Vec2) Vec2

Apply rotates the vector v by r.

func (Rot) Inv added in v0.2.1

func (r Rot) Inv() Rot

Inv returns the inverse rotation. For a unit rotation the inverse is the conjugate, so no division is needed.

func (Rot) Mul added in v0.2.1

func (r Rot) Mul(o Rot) Rot

Mul composes the rotations: the result rotates by r then by o. It uses the angle-sum identities, so each product floors once.

func (Rot) Normalize added in v0.2.1

func (r Rot) Normalize() Rot

Normalize rescales r to unit length. A zero r returns the identity.

type Vec2 added in v0.2.1

type Vec2 struct {
	X, Y Q32
}

Vec2 is a 2D vector of Q32 components.

func (Vec2) Add added in v0.2.1

func (v Vec2) Add(o Vec2) Vec2

Add returns the sum of two vectors.

func (Vec2) Distance added in v0.2.1

func (v Vec2) Distance(o Vec2) Q32

Distance returns the distance between v and o.

func (Vec2) DistanceSq added in v0.2.1

func (v Vec2) DistanceSq(o Vec2) Q32

DistanceSq returns the squared distance between v and o.

func (Vec2) Div added in v0.2.1

func (v Vec2) Div(s Q32) Vec2

Div returns v divided by s. It panics when s is zero.

func (Vec2) Dot added in v0.2.1

func (v Vec2) Dot(o Vec2) Q32

Dot returns the dot product of two vectors.

func (Vec2) Len added in v0.2.1

func (v Vec2) Len() Q32

Len returns the length of the vector, floored to the Q32.32 grid.

func (Vec2) LenSq added in v0.2.1

func (v Vec2) LenSq() Q32

LenSq returns the squared length of the vector. It uses the scalar multiplication and addition rules, including saturation.

func (Vec2) Lerp added in v0.2.1

func (v Vec2) Lerp(target Vec2, t Q32) Vec2

Lerp linearly interpolates between v and target by t. t is not clamped.

func (Vec2) Mul added in v0.2.1

func (v Vec2) Mul(s Q32) Vec2

Mul returns v scaled by s.

func (Vec2) Normalize added in v0.2.1

func (v Vec2) Normalize() Vec2

Normalize returns a unit vector with the same direction as v. The zero vector returns the zero vector.

Example
package main

import (
	"fmt"

	"github.com/dhannyell/fixed"
)

func main() {
	v := fixed.Vec2{X: fixed.Q32Zero(), Y: fixed.Q32FromInt(-7)}
	u := v.Normalize()
	fmt.Println(u.X, u.Y)
}
Output:
0 -1

func (Vec2) Sub added in v0.2.1

func (v Vec2) Sub(o Vec2) Vec2

Sub returns the difference between two vectors.

Directories

Path Synopsis
internal
gentable command
Command gentable writes the lookup tables used by the trigonometric functions.
Command gentable writes the lookup tables used by the trigonometric functions.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL