mirror of
https://git.sr.ht/~eliasnaur/gio
synced 2026-07-07 10:25:37 +00:00
f32: optimize Affine2D
encode/decode seem to introduce significant overhead. Inline them manually. It'll make code harder to read, however the performance wins are significant. name \ time/op before after delta TransformOffset-32 2.64ns ± 0% 0.25ns ± 0% ~ (p=0.100 n=3+3) TransformScale-32 2.64ns ± 0% 0.25ns ± 1% ~ (p=0.100 n=3+3) TransformRotate-32 2.65ns ± 0% 0.24ns ± 3% ~ (p=0.100 n=3+3) TransformTranslateMultiply-32 42.5ns ± 0% 12.9ns ± 0% ~ (p=0.100 n=3+3) TransformScaleMultiply-32 42.6ns ± 0% 12.9ns ± 0% ~ (p=0.100 n=3+3) TransformMultiply-32 42.2ns ± 0% 12.9ns ± 2% ~ (p=0.100 n=3+3) Signed-off-by: Egon Elbre <egonelbre@gmail.com>
This commit is contained in:
+27
-44
@@ -24,9 +24,9 @@ type Affine2D struct {
|
||||
// in row major order. The rows are: [sx, hx, ox], [hy, sy, oy], [0, 0, 1].
|
||||
func NewAffine2D(sx, hx, ox, hy, sy, oy float32) Affine2D {
|
||||
return Affine2D{
|
||||
a: sx, b: hx, c: ox,
|
||||
d: hy, e: sy, f: oy,
|
||||
}.encode()
|
||||
a: sx - 1, b: hx, c: ox,
|
||||
d: hy, e: sy - 1, f: oy,
|
||||
}
|
||||
}
|
||||
|
||||
// Offset the transformation.
|
||||
@@ -69,14 +69,13 @@ func (a Affine2D) Shear(origin Point, radiansX, radiansY float32) Affine2D {
|
||||
|
||||
// Mul returns A*B.
|
||||
func (A Affine2D) Mul(B Affine2D) (r Affine2D) {
|
||||
A, B = A.decode(), B.decode()
|
||||
r.a = A.a*B.a + A.b*B.d
|
||||
r.b = A.a*B.b + A.b*B.e
|
||||
r.c = A.a*B.c + A.b*B.f + A.c
|
||||
r.d = A.d*B.a + A.e*B.d
|
||||
r.e = A.d*B.b + A.e*B.e
|
||||
r.f = A.d*B.c + A.e*B.f + A.f
|
||||
return r.encode()
|
||||
r.a = (A.a+1)*(B.a+1) + A.b*B.d - 1
|
||||
r.b = (A.a+1)*B.b + A.b*(B.e+1)
|
||||
r.c = (A.a+1)*B.c + A.b*B.f + A.c
|
||||
r.d = A.d*(B.a+1) + (A.e+1)*B.d
|
||||
r.e = A.d*B.b + (A.e+1)*(B.e+1) - 1
|
||||
r.f = A.d*B.c + (A.e+1)*B.f + A.f
|
||||
return r
|
||||
}
|
||||
|
||||
// Invert the transformation. Note that if the matrix is close to singular
|
||||
@@ -85,70 +84,54 @@ func (a Affine2D) Invert() Affine2D {
|
||||
if a.a == 0 && a.b == 0 && a.d == 0 && a.e == 0 {
|
||||
return Affine2D{a: 0, b: 0, c: -a.c, d: 0, e: 0, f: -a.f}
|
||||
}
|
||||
a = a.decode()
|
||||
a.a += 1
|
||||
a.e += 1
|
||||
det := a.a*a.e - a.b*a.d
|
||||
a.a, a.e = a.e/det, a.a/det
|
||||
a.b, a.d = -a.b/det, -a.d/det
|
||||
temp := a.c
|
||||
a.c = -a.a*a.c - a.b*a.f
|
||||
a.f = -a.d*temp - a.e*a.f
|
||||
return a.encode()
|
||||
a.a -= 1
|
||||
a.e -= 1
|
||||
return a
|
||||
}
|
||||
|
||||
// Transform p by returning a*p.
|
||||
func (a Affine2D) Transform(p Point) Point {
|
||||
a = a.decode()
|
||||
return Point{
|
||||
X: p.X*a.a + p.Y*a.b + a.c,
|
||||
Y: p.X*a.d + p.Y*a.e + a.f,
|
||||
X: p.X*(a.a+1) + p.Y*a.b + a.c,
|
||||
Y: p.X*a.d + p.Y*(a.e+1) + a.f,
|
||||
}
|
||||
}
|
||||
|
||||
// Elems returns the matrix elements of the transform in row-major order. The
|
||||
// rows are: [sx, hx, ox], [hy, sy, oy], [0, 0, 1].
|
||||
func (a Affine2D) Elems() (sx, hx, ox, hy, sy, oy float32) {
|
||||
a = a.decode()
|
||||
return a.a, a.b, a.c, a.d, a.e, a.f
|
||||
}
|
||||
|
||||
func (a Affine2D) encode() Affine2D {
|
||||
// since we store with identity matrix subtracted
|
||||
a.a -= 1
|
||||
a.e -= 1
|
||||
return a
|
||||
}
|
||||
|
||||
func (a Affine2D) decode() Affine2D {
|
||||
// since we store with identity matrix subtracted
|
||||
a.a += 1
|
||||
a.e += 1
|
||||
return a
|
||||
return a.a + 1, a.b, a.c, a.d, a.e + 1, a.f
|
||||
}
|
||||
|
||||
func (a Affine2D) scale(factor Point) Affine2D {
|
||||
a = a.decode()
|
||||
return Affine2D{
|
||||
a.a * factor.X, a.b * factor.X, a.c * factor.X,
|
||||
a.d * factor.Y, a.e * factor.Y, a.f * factor.Y,
|
||||
}.encode()
|
||||
(a.a+1)*factor.X - 1, a.b * factor.X, a.c * factor.X,
|
||||
a.d * factor.Y, (a.e+1)*factor.Y - 1, a.f * factor.Y,
|
||||
}
|
||||
}
|
||||
|
||||
func (a Affine2D) rotate(radians float32) Affine2D {
|
||||
sin, cos := math.Sincos(float64(radians))
|
||||
s, c := float32(sin), float32(cos)
|
||||
a = a.decode()
|
||||
return Affine2D{
|
||||
a.a*c - a.d*s, a.b*c - a.e*s, a.c*c - a.f*s,
|
||||
a.a*s + a.d*c, a.b*s + a.e*c, a.c*s + a.f*c,
|
||||
}.encode()
|
||||
(a.a+1)*c - a.d*s - 1, a.b*c - (a.e+1)*s, a.c*c - a.f*s,
|
||||
(a.a+1)*s + a.d*c, a.b*s + (a.e+1)*c - 1, a.c*s + a.f*c,
|
||||
}
|
||||
}
|
||||
|
||||
func (a Affine2D) shear(radiansX, radiansY float32) Affine2D {
|
||||
tx := float32(math.Tan(float64(radiansX)))
|
||||
ty := float32(math.Tan(float64(radiansY)))
|
||||
a = a.decode()
|
||||
return Affine2D{
|
||||
a.a + a.d*tx, a.b + a.e*tx, a.c + a.f*tx,
|
||||
a.a*ty + a.d, a.b*ty + a.e, a.f*ty + a.f,
|
||||
}.encode()
|
||||
(a.a + 1) + a.d*tx - 1, a.b + (a.e+1)*tx, a.c + a.f*tx,
|
||||
(a.a+1)*ty + a.d, a.b*ty + (a.e + 1) - 1, a.f*ty + a.f,
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user