I have this Matrix type defined as follows:
type
Matrix*[W, H] = array[W, array[H, float]]
And for my raytracer I have to make a function that removes the last column and row. But I can't get this right because my submatrix function always returns a matrix of the same dimensions, and not it's dimensions minus 1.
This was the beginning version of my function:
func submatrix*(m: Matrix): Matrix =
for row in 0 ..< high(m):
for col in 0 ..< high(m[0]):
result[row][col] = m[row][col]
I also tried some other stuff like initializing the result matrix with the correct dimensions but I got an error saying it can't evaluate that at compile time.
So anybody got some tips on how to make a Nim-worthy submatrix function?
You may try
type
Matrix*[W, H: static int] = array[W, array[H, float]]
func submatrix*[W, H](m: Matrix[W, H]): Matrix[W - 1, H - 1] =
for row in 0 ..< high(m):
for col in 0 ..< high(m[0]):
result[row][col] = m[row][col]
var
m: Matrix[3, 3]
let s = submatrix(m)
echo s.len
echo s[0].len
I didn't know you could do that with generics damn.
My initiation function needs a rework with your solution, previously I had:
func newMatrix*[W, H](elements: array[W, array[H, float]]): Matrix[W, H] =
result = elements
But with that I get the error:
C:\Users\Administrator\stack\dev\naytracer\src\naytracerpkg\matrix.nim(6, 67) Error: cannot instantiate
Matrix
got: <static[type W](W), type H>
but expected: <W, H>
Currently also struggling with this type mismatch error with using this function:
# Remove specified row and column
func submatrix*[W, H](m: Matrix[W, H], rowIdx, colIdx: int): Matrix[W - 1, H - 1] =
for row in 0 .. high(m):
var resultRow = row
if row == rowIdx: continue
elif row > rowIdx: resultRow.dec(1)
for col in 0 .. high(m[0]):
var resultCol = col
if col == colIdx:
continue
elif col > colIdx: resultCol.dec(1)
result[resultRow][resultCol] = m[row][col]
The error being:
C:\Users\Administrator\.choosenim\toolchains\nim-1.0.6\lib\pure\unittest.nim(665, 14) Error: type misma
tch: got <Matrix[W - 1, H - 1], Matrix[3, 3]>
but expected one of:
proc `==`[I, T](x, y: array[I, T]): bool
first type mismatch at position: 2
required type for y: array[I, T]
but expression ':c2' is of type: Matrix[3, 3]
proc `==`[T](x, y: openArray[T]): bool
first type mismatch at position: 2
required type for y: openArray[T]
but expression ':c2' is of type: Matrix[3, 3]
func `==`[W, H](m1, m2: Matrix[W, H]): bool
first type mismatch at position: 2
required type for m2: Matrix[==.W, ==.H]
but expression ':c2' is of type: Matrix[3, 3]
24 other mismatching symbols have been suppressed; compile with --showAllMismatches:on to see them
Your error message makes no sense for me, and your proc compiles fine for me:
type
Matrix*[W, H: static int] = array[W, array[H, float]]
func xsubmatrix*[W, H](m: Matrix[W, H]): Matrix[W - 1, H - 1] =
for row in 0 ..< high(m):
for col in 0 ..< high(m[0]):
result[row][col] = m[row][col]
# Remove specified row and column
func submatrix*[W, H](m: Matrix[W, H], rowIdx, colIdx: int): Matrix[W - 1, H - 1] =
for row in 0 .. high(m):
var resultRow = row
if row == rowIdx: continue
elif row > rowIdx: resultRow.dec(1)
for col in 0 .. high(m[0]):
var resultCol = col
if col == colIdx:
continue
elif col > colIdx: resultCol.dec(1)
result[resultRow][resultCol] = m[row][col]
var
m: Matrix[3, 3]
let s = submatrix(m, 1, 1)
echo s.len
echo s[0].len
$ nim c -r t.nim
Hint: used config file '/home/stefan/Nim/config/nim.cfg' [Conf]
Hint: used config file '/home/stefan/Nim/config/config.nims' [Conf]
Hint: system [Processing]
Hint: widestrs [Processing]
Hint: io [Processing]
Hint: t [Processing]
Hint: [Link]
Hint: 21948 LOC; 0.167 sec; 24.613MiB peakmem; Debug build; proj: /tmp/hhh/t.nim; out: /tmp/hhh/t [SuccessX]
Hint: /tmp/hhh/t [Exec]
2
2
stefan@nuc /tmp/hhh $ nim -v
Nim Compiler Version 1.1.1 [Linux: amd64]
Compiled at 2020-03-13
Copyright (c) 2006-2019 by Andreas Rumpf
git hash: 9eeb514dda08f1caadb0d8e01a8595d991530b52
active boot switches: -d:release
stefan@nuc /tmp/hhh $
Ah yes I forgot I was using that function in a test like this:
test "getting the submatrix of a 4 x 4 matrix with row / column indicators":
check matrix4x4.submatrix(2, 1) == [[-6.0, 1.0, 6.0],
[-8.0, 8.0, 6.0],
[-7.0, -1.0, 1.0]
].newMatrix
This is my equality operator:
func `==`*[W,H](m1, m2: Matrix[W, H]): bool =
result = true
for x in 0 .. high(m1):
for y in 0 .. high(m1):
if not m1[x][y].equal(m2[x][y]):
return false
So with the == is where I'm getting that error.
I have no idea what exactly your newMatrix(), your equal(), your check() and your test() is, so it is too hard for me to guess the error.
So test() and check() are from the unittest module. As for my newMatrix function:
func newMatrix*[W, H: static int](elements: array[W, array[H, float]]): Matrix[W, H] =
result = elements
My equals() function being this float comparison function:
proc equal*(a, b: float): bool =
result = if abs(a - b) < epsilon:
true
else:
false
So with everything combined I get this: https://play.nim-lang.org/ Which.... compiles fine!? I have no idea why I'm getting this error then.
Fine that it works for you now.
For your equal test, I personally would never do it in that way, as with physics background we may work with really tiny values like plank constant (6 * 10^-34) and many more really small values.
Maybe better somethink like
(a/b - 1.0).abs < 1e-12
I think I used something like that in my cdt module, but mratsim will know better...
The idea is to not test abs difference, but relative.
See my project here: https://github.com/zetashift/naytracer the code I pasted in the playground comes from src/naytracerpkg/matrix.nim having the definitations and tests/tmatrix.nim having the test.
The test fails for me on my local machine with a type mismatch error. But since the code was copy pasted into the playground and works fine there I have no idea how to fix this.
The full error being:
C:\Users\Administrator\.choosenim\toolchains\nim-1.0.6\lib\pure\unittest.nim(665, 14) Error: type mism
atch: got <Matrix[W - 1, H - 1], Matrix[3, 3]>
but expected one of:
proc `==`[I, T](x, y: array[I, T]): bool
first type mismatch at position: 2
required type for y: array[I, T]
but expression ':c2' is of type: Matrix[3, 3]
proc `==`[T](x, y: openArray[T]): bool
first type mismatch at position: 2
required type for y: openArray[T]
but expression ':c2' is of type: Matrix[3, 3]
func `==`[W, H](m1, m2: Matrix[W, H]): bool
first type mismatch at position: 2
required type for m2: Matrix[==.W, ==.H]
but expression ':c2' is of type: Matrix[3, 3]
24 other mismatching symbols have been suppressed; compile with --showAllMismatches:on to see them
expression: :c1 == :c2
Tip: 1 messages have been suppressed, use --verbose to show them.
Error: Execution failed with exit code 1
... Command: "C:\Users\Administrator\.nimble\bin\nim.exe" c --noNimblePath -d:NimblePkgVersion
no idea how to fix this
I think you are only lazy :-)
The general approach would be to shrink and simplify the code -- the core problem seems to be the ==`() proc, so one would remove all what is not necessary to test this proc, and maybe to modify or simplify that proc. For example I would have started by replacing `func `==`*[W,H](m1, m2: Matrix[W, H]): bool = by proc isIdentical[W, H: static[int]](mx, my: Matrix[W, H]): bool =
Note that in your initial definition there is no space between W and H. Nim sometimes may love spaces.
The error message required type for m2: Matrix[==.W, ==.H] looks strange indeed.
I'm not the smartest but I tried to postpone this thread as long as possible to and try different things on my own, so I can't accept lazy man D: .
I can see why == is the main problem here, what blocks me is that it works fine on the playground, also when I run that playground snippet on my local laptop using nim c -r snippet.nim it also compiles fine. So it isn't arch/OS related.
If it works on the playground, and it works when you compile the snippet, whats in your projects nimcache that is conflicting/overriding it? Can you clean the nimcache and recompile everything?
Now, just for full disclosure, I have maybe 3 hours of Nim experience, but I have done lots of porting of code from one architecture to another, and that is what I would try with the symptoms you describe.
It is hard to believe that it is OS related, but maybe it is. I did my test on Linux 64 bit.
Maybe you can ask on IRC hoping that someone has the same OS and Nim version as you.
First I had the impression that it may be related to other packages that you may have installed, but when you do not import them, then they should do no harm.
I seem to be able to reproduce the problem on the playground too: https://play.nim-lang.org/#ix=2fGO
If you uncomment the lines in the suite it'll error out. So the problem wasn't with == but with something I'm setup-ing wrong in the suite I guess.. I'll tinker with this more.
Wow weird, I missed your post in it's entirety. Yardanico on IRC/Gitter also got the same error so it I don't think it's something that's wrong locally. Anyway I couldn't solve it,
I opened a GitHub issue here: https://github.com/nim-lang/Nim/issues/13785 about it because of the persistence of this no matter what I try.