Add 3 different vector/matrix representations. (#32)

* Add -d:vmathArrayBased to go to array vectors (slow).
* Add -d:vmathObjBased to go to object vectors (faster).
* Add default or just add -d:vmathObjArrayBased to go to object-array vectors (fastest).

Current speed test (using pixie, your results may vary):
```
nim c -r -d:release -d:vmathArrayBased .\tests\benchmark_svg.nim
svg decode ........................ 31.543 ms     38.110 ms    ±5.531  x1000

nim c -r -d:release -d:vmathObjBased .\tests\benchmark_svg.nim
svg decode ........................ 25.620 ms     33.569 ms    ±6.328  x1000

nim c -r -d:release .\tests\benchmark_svg.nim
svg decode ........................ 25.746 ms     33.059 ms    ±5.666  x1000
```
This commit is contained in:
treeform 2021-05-08 11:00:29 -07:00 committed by GitHub
parent b1722b9fa4
commit 6db149a2be
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 963 additions and 311 deletions

File diff suppressed because it is too large Load diff

262
tests/bench_rep.nim Normal file
View file

@ -0,0 +1,262 @@
import benchy
type
Vec3Obj = object
x, y, z: float32
Vec3Arr = array[3, float32]
Vec3ObjArr = object
arr: array[3, float32]
Vec3Tuple = tuple[x: float32, y: float32, z: float32]
proc vec3Obj(x, y, z: float32): Vec3Obj {.inline.} =
Vec3Obj(x: x, y: y, z: z)
proc vec3Arr(x, y, z: float32): Vec3Arr {.inline.} =
[x, y, z]
proc vec3ObjArr(x, y, z: float32): Vec3ObjArr {.inline.} =
Vec3ObjArr(arr: [x, y, z])
proc vec3Tuple(x, y, z: float32): Vec3Tuple {.inline.} =
(x, y, z)
timeIt "create vec3Obj", 1000:
var s = newSeq[Vec3Obj](100000)
for i in 0 .. 100000:
s[i] = vec3Obj(i.float32, 0, 0)
keep s
timeIt "create vec3Arr", 1000:
var s = newSeq[Vec3Arr](100000)
for i in 0 .. 100000:
s[i] = vec3Arr(i.float32, 0, 0)
keep s
timeIt "create vec3ObjArr", 1000:
var s = newSeq[Vec3ObjArr](100000)
for i in 0 .. 100000:
s[i] = vec3ObjArr(i.float32, 0, 0)
keep s
timeIt "create vec3Tuple", 1000:
var s = newSeq[Vec3Tuple](100000)
for i in 0 .. 100000:
s[i] = vec3Tuple(i.float32, 0, 0)
keep s
echo "..."
proc `[]`(a: Vec3Arr, i: int): float32 {.inline.} =
cast[array[3, float32]](a)[i]
proc `[]`(a: Vec3Obj, i: int): float32 {.inline.} =
cast[array[3, float32]](a)[i]
proc `[]`(a: Vec3ObjArr, i: int): float32 {.inline.} =
a.arr[i]
proc get(a: Vec3Tuple, i: int): float32 {.inline.} =
cast[array[3, float32]](a)[i]
timeIt "vec3Obj[static]", 1000:
var v = vec3Obj(1, 2, 3)
for i in 0 .. 1000000:
keep v[0]
keep v[1]
keep v[2]
timeIt "vec3Arr[static]", 1000:
var v = vec3Arr(1, 2, 3)
for i in 0 .. 1000000:
keep v[0]
keep v[1]
keep v[2]
timeIt "vec3ObjArr[static]", 1000:
var v = vec3ObjArr(1, 2, 3)
for i in 0 .. 1000000:
keep v[0]
keep v[1]
keep v[2]
timeIt "vec3Tuple[static]", 1000:
var v = vec3Tuple(1, 2, 3)
for i in 0 .. 1000000:
keep v[0]
keep v[1]
keep v[2]
echo "..."
timeIt "vec3Obj[]", 1000:
var v = vec3Obj(1, 2, 3)
for i in 0 .. 1000000:
keep v[i mod 3]
timeIt "vec3Arr[]", 1000:
var v = vec3Arr(1, 2, 3)
for i in 0 .. 1000000:
keep v[i mod 3]
timeIt "vec3ObjArr[]", 1000:
var v = vec3ObjArr(1, 2, 3)
for i in 0 .. 1000000:
keep v[i mod 3]
timeIt "vec3Tuple[]", 1000:
var v = vec3Tuple(1, 2, 3)
for i in 0 .. 1000000:
keep v.get(i mod 3)
echo "..."
proc `x`(a: Vec3Arr): float32 {.inline.} = a[0]
proc `y`(a: Vec3Arr): float32 {.inline.} = a[1]
proc `z`(a: Vec3Arr): float32 {.inline.} = a[2]
proc `x`(a: Vec3ObjArr): float32 {.inline.} = a.arr[0]
proc `y`(a: Vec3ObjArr): float32 {.inline.} = a.arr[1]
proc `z`(a: Vec3ObjArr): float32 {.inline.} = a.arr[2]
timeIt "vec3Obj.xyz", 1000:
var v = vec3Obj(1, 2, 3)
for i in 0 .. 1000000:
keep v.x
keep v.y
keep v.z
timeIt "vec3Arr.xyz", 1000:
var v = vec3Arr(1, 2, 3)
for i in 0 .. 1000000:
keep v.x
keep v.y
keep v.z
timeIt "vec3ObjArr.xyz", 1000:
var v = vec3ObjArr(1, 2, 3)
for i in 0 .. 1000000:
keep v.x
keep v.y
keep v.z
timeIt "vec3Tuple.xyz", 1000:
var v = vec3Tuple(1, 2, 3)
for i in 0 .. 1000000:
keep v.x
keep v.y
keep v.z
echo "..."
proc `[]=`(a: var Vec3Obj, i: int, v: float32) {.inline.} =
cast[ptr float32](cast[uint64](a.addr) + i.uint64 * sizeof(float32).uint64)[] = v
proc `[]=`(a: var Vec3ObjArr, i: int, v: float32) {.inline.} =
a.arr[i] = v
proc set(a: var Vec3Tuple, i: int, v: float32) {.inline.} =
cast[ptr float32](cast[uint64](a.addr) + i.uint64 * sizeof(float32).uint64)[] = v
timeIt "vec3Obj[static]=", 1000:
var v = vec3Obj(1, 2, 3)
for i in 0 .. 1000000:
v[0] = i.float32
v[1] = i.float32
v[2] = i.float32
keep v
timeIt "vec3Arr[static]=", 1000:
var v = vec3Arr(1, 2, 3)
for i in 0 .. 1000000:
v[0] = i.float32
v[1] = i.float32
v[2] = i.float32
keep v
timeIt "vec3ObjArr[static]=", 1000:
var v = vec3ObjArr(1, 2, 3)
for i in 0 .. 1000000:
v[0] = i.float32
v[1] = i.float32
v[2] = i.float32
keep v
timeIt "vec3Tuple[static]=", 1000:
var v = vec3Tuple(1, 2, 3)
for i in 0 .. 1000000:
v[0] = i.float32
v[1] = i.float32
v[2] = i.float32
keep v
echo "..."
proc `x=`(a: var Vec3Arr, v: float32) {.inline.} = a[0] = v
proc `y=`(a: var Vec3Arr, v: float32) {.inline.} = a[1] = v
proc `z=`(a: var Vec3Arr, v: float32) {.inline.} = a[2] = v
proc `x=`(a: var Vec3ObjArr, v: float32) {.inline.} = a.arr[0] = v
proc `y=`(a: var Vec3ObjArr, v: float32) {.inline.} = a.arr[1] = v
proc `z=`(a: var Vec3ObjArr, v: float32) {.inline.} = a.arr[2] = v
timeIt "vec3Obj.xyz=", 1000:
var v = vec3Obj(1, 2, 3)
for i in 0 .. 1000000:
v.x = i.float32
v.y = i.float32
v.z = i.float32
keep v
timeIt "vec3Arr.xyz=", 1000:
var v = vec3Arr(1, 2, 3)
for i in 0 .. 1000000:
v.x = i.float32
v.y = i.float32
v.z = i.float32
keep v
timeIt "vec3ObjArr.xyz=", 1000:
var v = vec3ObjArr(1, 2, 3)
for i in 0 .. 1000000:
v.x = i.float32
v.y = i.float32
v.z = i.float32
keep v
timeIt "vec3Tuple.xyz=", 1000:
var v = vec3Tuple(1, 2, 3)
for i in 0 .. 1000000:
v.x = i.float32
v.y = i.float32
v.z = i.float32
keep v
echo "..."
timeIt "vec3Obj[]=", 1000:
var v = vec3Obj(1, 2, 3)
for i in 0 .. 1000000:
v[i mod 3] = i.float32
keep v
timeIt "vec3Arr[]=", 1000:
var v = vec3Arr(1, 2, 3)
for i in 0 .. 1000000:
v[i mod 3] = i.float32
keep v
timeIt "vec3ObjArr[]=", 1000:
var v = vec3ObjArr(1, 2, 3)
for i in 0 .. 1000000:
v[i mod 3] = i.float32
keep v
timeIt "vec3Tuple[]=", 1000:
var v = vec3Tuple(1, 2, 3)
for i in 0 .. 1000000:
v.set(i mod 3, i.float32)
keep v

View file

@ -2,6 +2,7 @@ import random, vmath
randomize(1234)
block:
# Test ~=.
doAssert 1.0 ~= 1.0
@ -89,6 +90,25 @@ block:
doAssert a[0] ~= 1.0
doAssert a[1] ~= 2.0
block:
# Test position assignment
var
v2 = vec2(0)
v3 = vec3(0)
v4 = vec4(0)
v2[0] = 1.0
v2[1] = 2.0
doAssert v2 ~= vec2(1, 2)
v3[0] = 1.0
v3[1] = 2.0
v3[2] = 3.0
doAssert v3 ~= vec3(1, 2, 3)
v4[0] = 1.0
v4[1] = 2.0
v4[2] = 3.0
v4[3] = 4.0
doAssert v4 ~= vec4(1, 2, 3, 4)
block:
# Test vec2 constructor.
doAssert vec2(PI, PI) ~= vec2(PI)
@ -170,9 +190,9 @@ block:
_ = dvec3(1.0, 2.0, 3.0)
_ = dvec4(1.0, 2.0, 3.0, 4.0)
_ = bvec2(true, false)
_ = bvec3(true, false, true)
_ = bvec4(true, false, true, false)
_ = bvec2(true)
_ = bvec3(true)
_ = bvec4(true)
_ = ivec2(-1)
_ = ivec3(-1)
@ -190,8 +210,28 @@ block:
_ = dvec3(1.0)
_ = dvec4(1.0)
_ = bvec2()
_ = bvec3()
_ = bvec4()
_ = ivec2()
_ = ivec3()
_ = ivec4()
_ = uvec2()
_ = uvec3()
_ = uvec4()
_ = vec2()
_ = vec3()
_ = vec4()
_ = dvec2()
_ = dvec3()
_ = dvec4()
block:
# Test basic vector mat constructors.
# Test basic mat constructors.
block:
let
_ = mat2()
@ -276,84 +316,103 @@ block:
dvec4(0, 0, 0, 1)
)
block:
var
d2 = dmat2()
d3 = dmat3()
d4 = dmat4()
d2[0, 0] = 123.123
d2[1, 1] = 123.123
d3[0, 0] = 123.123
d3[1, 1] = 123.123
d3[2, 2] = 123.123
d4[0, 0] = 123.123
d4[1, 1] = 123.123
d4[2, 2] = 123.123
d4[3, 3] = 123.123
block:
# Test basic mat functions.
doAssert dmat3().transpose() ~= [
[1.0, 0.0, 0.0],
[0.0, 1.0, 0.0],
[0.0, 0.0, 1.0]
]
doAssert dmat4().transpose() ~= [
[1.0, 0.0, 0.0, 0.0],
[0.0, 1.0, 0.0, 0.0],
[0.0, 0.0, 1.0, 0.0],
[0.0, 0.0, 0.0, 1.0]
]
doAssert dmat3().transpose() ~= dmat3(
1.0, 0.0, 0.0,
0.0, 1.0, 0.0,
0.0, 0.0, 1.0
)
doAssert dmat4().transpose() ~= dmat4(
1.0, 0.0, 0.0, 0.0,
0.0, 1.0, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0
)
doAssert scale(dvec2(1, 2)) ~= [
[1.0, 0.0, 0.0],
[0.0, 2.0, 0.0],
[0.0, 0.0, 1.0]
]
doAssert scale(dvec3(2, 2, 3)) ~= [
[2.0, 0.0, 0.0, 0.0],
[0.0, 2.0, 0.0, 0.0],
[0.0, 0.0, 3.0, 0.0],
[0.0, 0.0, 0.0, 1.0]
]
doAssert scale(dvec2(1, 2)) ~= dmat3(
1.0, 0.0, 0.0,
0.0, 2.0, 0.0,
0.0, 0.0, 1.0
)
doAssert scale(dvec3(2, 2, 3)) ~= dmat4(
2.0, 0.0, 0.0, 0.0,
0.0, 2.0, 0.0, 0.0,
0.0, 0.0, 3.0, 0.0,
0.0, 0.0, 0.0, 1.0
)
doAssert translate(dvec2(1, 2)) ~= [
[1.0, 0.0, 0.0],
[0.0, 1.0, 0.0],
[1.0, 2.0, 1.0]
]
doAssert translate(dvec3(1, 2, 3)) ~= [
[1.0, 0.0, 0.0, 0.0],
[0.0, 1.0, 0.0, 0.0],
[0.0, 0.0, 1.0, 0.0],
[1.0, 2.0, 3.0, 1.0]
]
doAssert translate(dvec2(1, 2)) ~= dmat3(
1.0, 0.0, 0.0,
0.0, 1.0, 0.0,
1.0, 2.0, 1.0
)
doAssert translate(dvec3(1, 2, 3)) ~= dmat4(
1.0, 0.0, 0.0, 0.0,
0.0, 1.0, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
1.0, 2.0, 3.0, 1.0
)
doAssert rotate(1.0) ~= [
[0.5403023058681398, -0.8414709848078965, 0.0],
[0.8414709848078965, 0.5403023058681398, 0.0],
[0.0, 0.0, 1.0]
]
doAssert rotate(1.0) ~= dmat3(
0.5403023058681398, -0.8414709848078965, 0.0,
0.8414709848078965, 0.5403023058681398, 0.0,
0.0, 0.0, 1.0
)
doAssert scale(dvec2(2)) ~= [
[2.0, 0.0, 0.0],
[0.0, 2.0, 0.0],
[0.0, 0.0, 1.0]
]
doAssert scale(dvec3(2)) ~= [
[2.0, 0.0, 0.0, 0.0],
[0.0, 2.0, 0.0, 0.0],
[0.0, 0.0, 2.0, 0.0],
[0.0, 0.0, 0.0, 1.0]
]
doAssert translate(dvec2(2)) ~= [
[1.0, 0.0, 0.0],
[0.0, 1.0, 0.0],
[2.0, 2.0, 1.0]
]
doAssert translate(dvec3(2)) ~= [
[1.0, 0.0, 0.0, 0.0],
[0.0, 1.0, 0.0, 0.0],
[0.0, 0.0, 1.0, 0.0],
[2.0, 2.0, 2.0, 1.0]
]
doAssert scale(dvec2(2)) ~= dmat3(
2.0, 0.0, 0.0,
0.0, 2.0, 0.0,
0.0, 0.0, 1.0
)
doAssert scale(dvec3(2)) ~= dmat4(
2.0, 0.0, 0.0, 0.0,
0.0, 2.0, 0.0, 0.0,
0.0, 0.0, 2.0, 0.0,
0.0, 0.0, 0.0, 1.0
)
doAssert rotate(1.0).inverse() ~= [
[0.5403023058681398, 0.8414709848078965, -0.0],
[-0.8414709848078965, 0.5403023058681398, -0.0],
[0.0, -0.0, 1.0]
]
doAssert rotate(1.0, dvec3(1, 0, 0)).inverse() ~= [
[1.0, 0.0, 0.0, 0.0],
[-0.0, 0.5403022766113281, 0.8414710164070129, 0.0],
[0.0, -0.8414710164070129, 0.5403022766113281, 0.0],
[0.0, 0.0, 0.0, 1.0]
]
doAssert translate(dvec2(2)) ~= dmat3(
1.0, 0.0, 0.0,
0.0, 1.0, 0.0,
2.0, 2.0, 1.0
)
doAssert translate(dvec3(2)) ~= dmat4(
1.0, 0.0, 0.0, 0.0,
0.0, 1.0, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
2.0, 2.0, 2.0, 1.0
)
doAssert rotate(1.0).inverse() ~= dmat3(
0.5403023058681398, 0.8414709848078965, -0.0,
-0.8414709848078965, 0.5403023058681398, -0.0,
0.0, -0.0, 1.0
)
doAssert rotate(1.0, dvec3(1, 0, 0)).inverse() ~= dmat4(
1.0, 0.0, 0.0, 0.0,
-0.0, 0.5403022766113281, 0.8414710164070129, 0.0,
0.0, -0.8414710164070129, 0.5403022766113281, 0.0,
0.0, 0.0, 0.0, 1.0
)
doAssert translate(vec2(1, 2)).pos == vec2(1, 2)
@ -543,3 +602,5 @@ block:
b = vec3(rand(2.0)-0.5, rand(2.0)-0.5, rand(2.0)-0.5).normalize()
q = fromTwoVectors(a, b)
doAssert q.mat4 * a ~= b
echo "test finished successfully"