Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,7 @@ jobs:
run: nim r -d:vmathArrayBased tests/tests.nim
- name: Test JavaScript
run: nim js -r tests/tests.nim
- name: Test JavaScript object based
run: nim js -r -d:vmathObjBased tests/tests.nim
- name: Test JavaScript array based
run: nim js -r -d:vmathArrayBased tests/tests.nim
185 changes: 158 additions & 27 deletions src/vmath.nim
Original file line number Diff line number Diff line change
Expand Up @@ -123,14 +123,19 @@ when defined(vmathArrayBased):

template `[]`*[T](a: GMat234[T], i, j: int): T = a[i][j]

template `[]=`*[T](a: var GMat2[T], i, j: int, v: T) =
cast[ptr T](cast[ByteAddress](a.addr) + (i * 2 + j) * sizeof(T))[] = v
when defined(js):
template `[]=`*[T](a: var GMat2[T], i, j: int, v: T) = a[i][j] = v
template `[]=`*[T](a: var GMat3[T], i, j: int, v: T) = a[i][j] = v
template `[]=`*[T](a: var GMat4[T], i, j: int, v: T) = a[i][j] = v
else:
template `[]=`*[T](a: var GMat2[T], i, j: int, v: T) =
cast[ptr T](cast[ByteAddress](a.addr) + (i * 2 + j) * sizeof(T))[] = v

template `[]=`*[T](a: var GMat3[T], i, j: int, v: T) =
cast[ptr T](cast[ByteAddress](a.addr) + (i * 3 + j) * sizeof(T))[] = v
template `[]=`*[T](a: var GMat3[T], i, j: int, v: T) =
cast[ptr T](cast[ByteAddress](a.addr) + (i * 3 + j) * sizeof(T))[] = v

template `[]=`*[T](a: var GMat4[T], i, j: int, v: T) =
cast[ptr T](cast[ByteAddress](a.addr) + (i * 4 + j) * sizeof(T))[] = v
template `[]=`*[T](a: var GMat4[T], i, j: int, v: T) =
cast[ptr T](cast[ByteAddress](a.addr) + (i * 4 + j) * sizeof(T))[] = v

elif defined(vmathObjBased):
type
Expand All @@ -152,18 +157,61 @@ elif defined(vmathObjBased):
template gvec4*[T](mx, my, mz, mw: T): GVec4[T] =
GVec4[T](x: mx, y: my, z: mz, w: mw)

template `[]`*[T](a: GVec2[T], i: int): T = cast[array[2, T]](a)[i]
template `[]`*[T](a: GVec3[T], i: int): T = cast[array[3, T]](a)[i]
template `[]`*[T](a: GVec4[T], i: int): T = cast[array[4, T]](a)[i]
when defined(js):
proc `[]`*[T](a: GVec2[T], i: int): T =
case i
of 0: a.x
of 1: a.y
else: raise newException(IndexDefect, "index out of bounds")

proc `[]`*[T](a: GVec3[T], i: int): T =
case i
of 0: a.x
of 1: a.y
of 2: a.z
else: raise newException(IndexDefect, "index out of bounds")

proc `[]`*[T](a: GVec4[T], i: int): T =
case i
of 0: a.x
of 1: a.y
of 2: a.z
of 3: a.w
else: raise newException(IndexDefect, "index out of bounds")

proc `[]=`*[T](a: var GVec2[T], i: int, v: T) =
case i
of 0: a.x = v
of 1: a.y = v
else: raise newException(IndexDefect, "index out of bounds")

proc `[]=`*[T](a: var GVec3[T], i: int, v: T) =
case i
of 0: a.x = v
of 1: a.y = v
of 2: a.z = v
else: raise newException(IndexDefect, "index out of bounds")

proc `[]=`*[T](a: var GVec4[T], i: int, v: T) =
case i
of 0: a.x = v
of 1: a.y = v
of 2: a.z = v
of 3: a.w = v
else: raise newException(IndexDefect, "index out of bounds")
else:
template `[]`*[T](a: GVec2[T], i: int): T = cast[array[2, T]](a)[i]
template `[]`*[T](a: GVec3[T], i: int): T = cast[array[3, T]](a)[i]
template `[]`*[T](a: GVec4[T], i: int): T = cast[array[4, T]](a)[i]

template `[]=`*[T](a: var GVec2[T], i: int, v: T) =
cast[ptr T](cast[ByteAddress](a.addr) + i * sizeof(T))[] = v
template `[]=`*[T](a: var GVec2[T], i: int, v: T) =
cast[ptr T](cast[ByteAddress](a.addr) + i * sizeof(T))[] = v

template `[]=`*[T](a: var GVec3[T], i: int, v: T) =
cast[ptr T](cast[ByteAddress](a.addr) + i * sizeof(T))[] = v
template `[]=`*[T](a: var GVec3[T], i: int, v: T) =
cast[ptr T](cast[ByteAddress](a.addr) + i * sizeof(T))[] = v

template `[]=`*[T](a: var GVec4[T], i: int, v: T) =
cast[ptr T](cast[ByteAddress](a.addr) + i * sizeof(T))[] = v
template `[]=`*[T](a: var GVec4[T], i: int, v: T) =
cast[ptr T](cast[ByteAddress](a.addr) + i * sizeof(T))[] = v

type
GMat2*[T] {.bycopy.} = object
Expand Down Expand Up @@ -206,23 +254,106 @@ elif defined(vmathObjBased):
result.m20 = m20; result.m21 = m21; result.m22 = m22; result.m23 = m23
result.m30 = m30; result.m31 = m31; result.m32 = m32; result.m33 = m33

template `[]`*[T](a: GMat2[T], i, j: int): T =
cast[array[4, T]](a)[i * 2 + j]
when defined(js):
proc `[]`*[T](a: GMat2[T], i, j: int): T =
case i * 2 + j
of 0: a.m00
of 1: a.m01
of 2: a.m10
of 3: a.m11
else: raise newException(IndexDefect, "index out of bounds")

proc `[]`*[T](a: GMat3[T], i, j: int): T =
case i * 3 + j
of 0: a.m00
of 1: a.m01
of 2: a.m02
of 3: a.m10
of 4: a.m11
of 5: a.m12
of 6: a.m20
of 7: a.m21
of 8: a.m22
else: raise newException(IndexDefect, "index out of bounds")

proc `[]`*[T](a: GMat4[T], i, j: int): T =
case i * 4 + j
of 0: a.m00
of 1: a.m01
of 2: a.m02
of 3: a.m03
of 4: a.m10
of 5: a.m11
of 6: a.m12
of 7: a.m13
of 8: a.m20
of 9: a.m21
of 10: a.m22
of 11: a.m23
of 12: a.m30
of 13: a.m31
of 14: a.m32
of 15: a.m33
else: raise newException(IndexDefect, "index out of bounds")

proc `[]=`*[T](a: var GMat2[T], i, j: int, v: T) =
case i * 2 + j
of 0: a.m00 = v
of 1: a.m01 = v
of 2: a.m10 = v
of 3: a.m11 = v
else: raise newException(IndexDefect, "index out of bounds")

proc `[]=`*[T](a: var GMat3[T], i, j: int, v: T) =
case i * 3 + j
of 0: a.m00 = v
of 1: a.m01 = v
of 2: a.m02 = v
of 3: a.m10 = v
of 4: a.m11 = v
of 5: a.m12 = v
of 6: a.m20 = v
of 7: a.m21 = v
of 8: a.m22 = v
else: raise newException(IndexDefect, "index out of bounds")

proc `[]=`*[T](a: var GMat4[T], i, j: int, v: T) =
case i * 4 + j
of 0: a.m00 = v
of 1: a.m01 = v
of 2: a.m02 = v
of 3: a.m03 = v
of 4: a.m10 = v
of 5: a.m11 = v
of 6: a.m12 = v
of 7: a.m13 = v
of 8: a.m20 = v
of 9: a.m21 = v
of 10: a.m22 = v
of 11: a.m23 = v
of 12: a.m30 = v
of 13: a.m31 = v
of 14: a.m32 = v
of 15: a.m33 = v
else: raise newException(IndexDefect, "index out of bounds")
else:
template `[]`*[T](a: GMat2[T], i, j: int): T =
cast[array[4, T]](a)[i * 2 + j]

template `[]`*[T](a: GMat3[T], i, j: int): T =
cast[array[9, T]](a)[i * 3 + j]
template `[]`*[T](a: GMat3[T], i, j: int): T =
cast[array[9, T]](a)[i * 3 + j]

template `[]`*[T](a: GMat4[T], i, j: int): T =
cast[array[16, T]](a)[i * 4 + j]
template `[]`*[T](a: GMat4[T], i, j: int): T =
cast[array[16, T]](a)[i * 4 + j]

template `[]=`*[T](a: var GMat2[T], i, j: int, v: T) =
cast[ptr T](cast[ByteAddress](a.addr) + (i * 2 + j) * sizeof(T))[] = v
template `[]=`*[T](a: var GMat2[T], i, j: int, v: T) =
cast[ptr T](cast[ByteAddress](a.addr) + (i * 2 + j) * sizeof(T))[] = v

template `[]=`*[T](a: var GMat3[T], i, j: int, v: T) =
cast[ptr T](cast[ByteAddress](a.addr) + (i * 3 + j) * sizeof(T))[] = v
template `[]=`*[T](a: var GMat3[T], i, j: int, v: T) =
cast[ptr T](cast[ByteAddress](a.addr) + (i * 3 + j) * sizeof(T))[] = v

template `[]=`*[T](a: var GMat4[T], i, j: int, v: T) =
cast[ptr T](cast[ByteAddress](a.addr) + (i * 4 + j) * sizeof(T))[] = v
template `[]=`*[T](a: var GMat4[T], i, j: int, v: T) =
cast[ptr T](cast[ByteAddress](a.addr) + (i * 4 + j) * sizeof(T))[] = v

template `[]`*[T](a: GMat2[T], i: int): GVec2[T] =
gvec2[T](
Expand Down
57 changes: 57 additions & 0 deletions tests/tests.nim
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,32 @@ suite "vector memory layout":
v4[0] = 1.0; v4[1] = 2.0; v4[2] = 3.0; v4[3] = 4.0
check v4 ~= vec4(1, 2, 3, 4)

test "vec indexed access across scalar types":
var bv = bvec4(false)
for i in 0 .. 3:
bv[i] = i mod 2 == 0
check bv == bvec4(true, false, true, false)

var iv = ivec4(0)
for i in 0 .. 3:
iv[i] = int32(-i - 1)
check iv == ivec4(-1, -2, -3, -4)

var uv = uvec4(0)
for i in 0 .. 3:
uv[i] = uint32(i + 10)
check uv == uvec4(10, 11, 12, 13)

var fv = vec4(0)
for i in 0 .. 3:
fv[i] = float32(i) + 0.5'f32
check fv == vec4(0.5, 1.5, 2.5, 3.5)

var dv = dvec4(0)
for i in 0 .. 3:
dv[i] = float64(i) + 0.25
check dv == dvec4(0.25, 1.25, 2.25, 3.25)

suite "mat2 memory layout and element access":
test "mat2 cast to flat array is column-major":
when not defined(js):
Expand Down Expand Up @@ -406,6 +432,37 @@ suite "mat4 memory layout and element access":
check fromScalars ~= fromVecs
check fromScalars ~= mat4()

test "mat indexed access across float types":
var m2 = mat2()
var m2Value = 1.0'f32
for i in 0 .. 1:
for j in 0 .. 1:
m2[i, j] = m2Value
m2Value += 1.0'f32
check m2[0, 0] == 1.0'f32
check m2[0, 1] == 2.0'f32
check m2[1] == vec2(3, 4)

var m3 = mat3()
var m3Value = 1.0'f32
for i in 0 .. 2:
for j in 0 .. 2:
m3[i, j] = m3Value
m3Value += 1.0'f32
check m3[0, 0] == 1.0'f32
check m3[2, 2] == 9.0'f32
check m3[2] == vec3(7, 8, 9)

var dm4 = dmat4()
var dm4Value = 0.5
for i in 0 .. 3:
for j in 0 .. 3:
dm4[i, j] = dm4Value
dm4Value += 0.5
check dm4[0, 0] == 0.5
check dm4[3, 3] == 8.0
check dm4[2] == dvec4(4.5, 5.0, 5.5, 6.0)

suite "mat4 operations":
let
a = when defined(js):
Expand Down
Loading