Added Matrix * Tuple4 operations
This commit is contained in:
parent
d85e2e7426
commit
b27ff44e1c
@ -1,5 +1,5 @@
|
|||||||
import strformat
|
import strformat
|
||||||
from "./tuple" import `=~`
|
from "./tuple" import `=~`, Tuple4, tuple4
|
||||||
|
|
||||||
type
|
type
|
||||||
Matrix* = object
|
Matrix* = object
|
||||||
@ -10,6 +10,7 @@ type
|
|||||||
MatrixMultiplicationException = object of CatchableError
|
MatrixMultiplicationException = object of CatchableError
|
||||||
IdentityMatrixCreationError = object of CatchableError
|
IdentityMatrixCreationError = object of CatchableError
|
||||||
MatrixInversionError = object of CatchableError
|
MatrixInversionError = object of CatchableError
|
||||||
|
MatrixConversionError = object of CatchableError
|
||||||
|
|
||||||
proc matrix(width, height: int): Matrix =
|
proc matrix(width, height: int): Matrix =
|
||||||
result.matrix = newSeq[float](width * height)
|
result.matrix = newSeq[float](width * height)
|
||||||
@ -23,9 +24,19 @@ proc matrix*(data: seq[float], width, height: int): Matrix =
|
|||||||
result.width = width
|
result.width = width
|
||||||
result.height = height
|
result.height = height
|
||||||
|
|
||||||
|
proc matrix*(input: Tuple4): Matrix =
|
||||||
|
result.matrix = @[input.x, input.y, input.z, input.w]
|
||||||
|
result.width = 1
|
||||||
|
result.height = 4
|
||||||
|
|
||||||
template `[]`*(mat: Matrix, row, column: int): float = mat.matrix[row * mat.width + column]
|
template `[]`*(mat: Matrix, row, column: int): float = mat.matrix[row * mat.width + column]
|
||||||
template `[]=`*(mat: var Matrix, row, column: int, val: float) = mat.matrix[row * mat.width + column] = val
|
template `[]=`*(mat: var Matrix, row, column: int, val: float) = mat.matrix[row * mat.width + column] = val
|
||||||
|
|
||||||
|
proc toTuple4(i: Matrix): Tuple4 =
|
||||||
|
if(i.width != 1 or i.height != 4):
|
||||||
|
raise newException(MatrixConversionError, "Matrix is of incorrect dimensions to convert to a Tuple4")
|
||||||
|
return tuple4(i[0,0], i[0,1], i[0,2], i[0,3])
|
||||||
|
|
||||||
proc `==`*(lhs, rhs: Matrix): bool =
|
proc `==`*(lhs, rhs: Matrix): bool =
|
||||||
if lhs.width != rhs.width or lhs.height != rhs.height: return false
|
if lhs.width != rhs.width or lhs.height != rhs.height: return false
|
||||||
for i in 0..<len(lhs.matrix):
|
for i in 0..<len(lhs.matrix):
|
||||||
@ -46,6 +57,8 @@ proc `*`*(lhs, rhs: Matrix): Matrix =
|
|||||||
collect += lhs[row, i] * rhs[i, col]
|
collect += lhs[row, i] * rhs[i, col]
|
||||||
result[row, col] = collect
|
result[row, col] = collect
|
||||||
|
|
||||||
|
proc `*`*(lhs: Matrix, rhs: Tuple4): Tuple4 = (lhs * matrix(rhs)).toTuple4()
|
||||||
|
|
||||||
template isSquare(mat: Matrix): bool = mat.height == mat.width and len(mat.matrix) == (mat.height * mat.width)
|
template isSquare(mat: Matrix): bool = mat.height == mat.width and len(mat.matrix) == (mat.height * mat.width)
|
||||||
|
|
||||||
proc identity(size: int): Matrix =
|
proc identity(size: int): Matrix =
|
||||||
@ -161,6 +174,11 @@ when isMainModule:
|
|||||||
let result = matrix(@[83.0, 63.0, 37.0, 75.0], 4, 1)
|
let result = matrix(@[83.0, 63.0, 37.0, 75.0], 4, 1)
|
||||||
check(mat1 * mat2 == result)
|
check(mat1 * mat2 == result)
|
||||||
|
|
||||||
|
test "Matrix multiplied by Tuple4":
|
||||||
|
let mat = matrix(@[1.0, 2.0, 3.0, 4.0, 2.0, 4.0, 4.0, 2.0, 8.0, 6.0, 4.0, 1.0, 0.0, 0.0, 0.0, 1.0], 4, 4)
|
||||||
|
let tup = tuple4(1.0, 2.0, 3.0, 1.0)
|
||||||
|
check(mat * tup == tuple4(18.0, 24.0, 33.0, 1.0))
|
||||||
|
|
||||||
test "Identity matrix creation":
|
test "Identity matrix creation":
|
||||||
check(identity(3) == matrix(@[1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0], 3, 3))
|
check(identity(3) == matrix(@[1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0], 3, 3))
|
||||||
check(identity(4) == matrix(@[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], 4, 4))
|
check(identity(4) == matrix(@[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], 4, 4))
|
||||||
@ -168,8 +186,10 @@ when isMainModule:
|
|||||||
test "Identity matrix multiplication":
|
test "Identity matrix multiplication":
|
||||||
let mat1 = matrix(@[0.0, 1.0, 2.0, 4.0, 1.0, 2.0, 4.0, 8.0, 2.0, 4.0, 8.0, 16.0, 4.0, 8.0, 16.0, 32.0], 4, 4)
|
let mat1 = matrix(@[0.0, 1.0, 2.0, 4.0, 1.0, 2.0, 4.0, 8.0, 2.0, 4.0, 8.0, 16.0, 4.0, 8.0, 16.0, 32.0], 4, 4)
|
||||||
check(mat1 * mat1.identity == mat1)
|
check(mat1 * mat1.identity == mat1)
|
||||||
let mat2 = matrix(@[1.0, 2.0, 3.0, 4.0], 4, 1)
|
|
||||||
check(mat2 * mat1.identity == mat2)
|
test "Tuple4 identity matrix multiplication":
|
||||||
|
let tup = tuple4(1.0, 2.0, 3.0, 4.0)
|
||||||
|
check(identity(4) * tup == tup)
|
||||||
|
|
||||||
test "Matrix transposition":
|
test "Matrix transposition":
|
||||||
let mat1 = matrix(@[0.0, 9.0, 3.0, 0.0, 9.0, 8.0, 0.0, 8.0, 1.0, 8.0, 5.0, 3.0, 0.0, 0.0, 5.0, 8.0], 4, 4)
|
let mat1 = matrix(@[0.0, 9.0, 3.0, 0.0, 9.0, 8.0, 0.0, 8.0, 1.0, 8.0, 5.0, 3.0, 0.0, 0.0, 5.0, 8.0], 4, 4)
|
||||||
|
Loading…
Reference in New Issue
Block a user