Documentation
¶
Overview ¶
Package fixed implements deterministic Q32.32 fixed-point arithmetic.
Q stores one signed value in an int64. The high 32 bits contain the signed integer part. The low 32 bits contain the fraction. The resolution is 2⁻³². The range is [-2³¹, 2³¹ - 2⁻³²]. Each operation produces the same bits on every supported architecture.
Overflow ¶
An overflow saturates to MinValue or MaxValue. SaturationCount reports saturation events for diagnostics. The counter does not affect Q values or operation results.
Q.Div panics for a zero divisor. FromRatio panics for a zero denominator. Q.Sqrt panics 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 ¶
Q.Mul floors the 128-bit product when it converts the result to Q32.32. This operation matches an arithmetic right shift. Q.Div and FromRatio truncate toward zero. Q.Sqrt floors its result.
Q.Round and MustParse round to the nearest representable value. An exact half rounds away from zero.
Construction and text ¶
Q is opaque. Construct values with FromInt, FromRatio, MustParse, or FromRaw. The package does not accept float values because a computed float can contain architecture-dependent bits.
Q.String returns the exact canonical decimal form. For every q, MustParse(q.String()) == q.
Angles ¶
Angles use turns. One is a full revolution. The fractional bits of a Q map directly to the circle, so range reduction does not use pi and does not round.
SinTurns and CosTurns accept every Q value. They never panic or saturate, and their results stay in [-One, One]. 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 raw representation, 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/bits and sync/atomic.
Index ¶
- func ResetSaturationCount()
- func SaturationCount() uint64
- type Q
- func (q Q) Abs() Q
- func (q Q) Add(o Q) Q
- func (q Q) Ceil() Q
- func (q Q) Clamp(lo, hi Q) Q
- func (q Q) Cmp(o Q) int
- func (q Q) Div(o Q) Q
- func (q Q) Eq(o Q) bool
- func (q Q) Floor() Q
- func (q Q) Int() int
- func (q Q) Less(o Q) bool
- func (q Q) Max(o Q) Q
- func (q Q) Min(o Q) Q
- func (q Q) Mul(o Q) Q
- func (q Q) Neg() Q
- func (q Q) Raw() int64
- func (q Q) Round() Q
- func (q Q) Sqrt() Q
- func (q Q) String() string
- func (q Q) Sub(o Q) Q
- type Rot
- type Vec2
- func (v Vec2) Add(o Vec2) Vec2
- func (v Vec2) Distance(o Vec2) Q
- func (v Vec2) DistanceSq(o Vec2) Q
- func (v Vec2) Div(s Q) Vec2
- func (v Vec2) Dot(o Vec2) Q
- func (v Vec2) Len() Q
- func (v Vec2) LenSq() Q
- func (v Vec2) Lerp(target Vec2, t Q) Vec2
- func (v Vec2) Mul(s Q) Vec2
- func (v Vec2) Normalize() Vec2
- func (v Vec2) Sub(o Vec2) Vec2
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 Q ¶
type Q struct {
// contains filtered or unexported fields
}
Q stores an opaque signed Q32.32 value. Its zero value is 0.
func Atan2Turns ¶ added in v0.2.1
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
CosTurns returns the cosine of t in turns. It uses the same rules as SinTurns with a quarter-turn shift.
func FromInt ¶
FromInt returns i as a Q value. It saturates outside [-2³¹, 2³¹-1].
Example ¶
package main
import (
"fmt"
"github.com/dhannyell/fixed"
)
func main() {
fmt.Println(fixed.FromInt(3))
fmt.Println(fixed.FromInt(-2))
}
Output: 3 -2
func FromRatio ¶
FromRatio 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.FromRatio(5, 2)
fmt.Println(q)
}
Output: 2.5
func MustParse ¶
MustParse parses a decimal literal. It rounds to the nearest Q value, with exact halves away from zero. It saturates outside the Q range and panics on malformed input.
Example ¶
package main
import (
"fmt"
"github.com/dhannyell/fixed"
)
func main() {
fmt.Println(fixed.MustParse("6.25"))
fmt.Println(fixed.MustParse("-0.001"))
}
Output: 6.25 -0.00099999993108212947845458984375
func SinTurns ¶ added in v0.2.1
SinTurns returns the sine of t, where One is a full revolution. It uses only the fractional part of t, accepts every Q 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 (Q) Ceil ¶
Ceil returns the smallest integer multiple of One that is not below q. It saturates when the result is outside the Q range.
func (Q) Clamp ¶
Clamp returns q limited to [lo, hi]. It requires lo <= hi.
Example ¶
package main
import (
"fmt"
"github.com/dhannyell/fixed"
)
func main() {
speed := fixed.FromInt(150)
limited := speed.Clamp(fixed.Zero(), fixed.FromInt(100))
fmt.Println(limited)
}
Output: 100
func (Q) Div ¶
Div returns q/o truncated toward zero. It saturates on overflow. It panics when o is zero.
func (Q) Mul ¶
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.FromRatio(5, 2).Mul(fixed.FromInt(4))
fmt.Println(area)
}
Output: 10
func (Q) Round ¶
Round returns the nearest integer multiple of One. An exact half rounds away from zero. Round saturates when the result is outside the Q range.
func (Q) Sqrt ¶
Sqrt returns floor(sqrt(q)). It panics when q is negative. The result cannot overflow.
func (Q) 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.FromRaw(1)
text := q.String()
fmt.Println(text)
fmt.Println(fixed.MustParse(text).Eq(q))
}
Output: 0.00000000023283064365386962890625 true
type Rot ¶ added in v0.2.1
type Rot struct {
Sin, Cos Q
}
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
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.FromRatio(1, 4))
v := r.Apply(fixed.Vec2{X: fixed.One(), Y: fixed.Zero()})
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) Inv ¶ added in v0.2.1
Inv returns the inverse rotation. For a unit rotation the inverse is the conjugate, so no division is needed.
type Vec2 ¶ added in v0.2.1
type Vec2 struct {
X, Y Q
}
Vec2 is a 2D vector of Q components.
func (Vec2) DistanceSq ¶ added in v0.2.1
DistanceSq returns the squared distance between v and o.
func (Vec2) LenSq ¶ added in v0.2.1
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
Lerp linearly interpolates between v and target by t. t is not clamped.
func (Vec2) Normalize ¶ added in v0.2.1
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.Zero(), Y: fixed.FromInt(-7)}
u := v.Normalize()
fmt.Println(u.X, u.Y)
}
Output: 0 -1