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:
parent
b1722b9fa4
commit
6db149a2be
801
src/vmath.nim
801
src/vmath.nim
File diff suppressed because it is too large
Load diff
262
tests/bench_rep.nim
Normal file
262
tests/bench_rep.nim
Normal 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
|
211
tests/test.nim
211
tests/test.nim
|
@ -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"
|
||||
|
|
Loading…
Reference in a new issue