ID:1606260
 
Code:
        Dot(var/Matrix/M) // Performs dot product of src and M if possible and returns the dot product. Otherwise return null
// I can't return 0 because 0 is an actual dot product

var/list/M1 = src.matrix ; var/list/L1 = M1[1]
var/list/M2 = M.matrix ; var/list/L2 = M2[1]
/*
L1 and L2 store number of rows via length.
The dot product is defined as long each matrix has as many rows as the other has columns and vice versa
*/

if(src.cols != L2.len || L1.len != M.cols) return null // Not defined in this case

var/Matrix/Dot = new(L1.len, M.cols)
var/sum = 0
for(var/row = 1 to M.cols)

for(var/col = 1 to src.cols)
L1 = list() // Gotta rewrite the list each time through

/*
What I'm essentially doing here, is creating vectors and dotting them and putting the sum in the proper spot in the final
matrix. The first vector is the row of the first matrix, and the second vector is the column of the second matrix.
*/

for(var/i = 1 to src.cols)
L1 += M1[row][i]
L2 = M2[col]

sum = 0
for(var/i = 1 to L1.len)
sum += L1[i] * L2[i] // This line is stated in runtime error

Dot.ChangeValue(col, row, sum)

return Dot // return the dot product (does not modify either matrix in operation)

mob
verb
Test()
var/Matrix/M = new(100, 100)
var/Matrix/M2 = new(100, 100)
M2.ConstAdd(1)
for(var/i = 1 to 100)
for(var/j = 1 to 100)
M.ChangeValue(i, j, rand(1, 100))

var/i = 100
while(i)
M2 = M2.Dot(M)
i --


Problem description:
I was running some tests on my Dot products because I need to use them for my AutoPath library, and I come across this issue. The loop is most certainly not infinite, but it is trying to run a loop 10000 times, so maybe that's causing it? Any ideas on how to handle this?

EDIT: Please note that the test proc works fine on smaller matrices.
Usually, this is fixed by adding a sleep() of the lowest possible value.
Sadly, I think I just call it too many times for this to be feasible. Transition matrices might be too much for BYOND to handle atm.
Well, you tend to prefer an internal solution for general matricies like this, as BYOND can then leverage MMX/SSE and basically perform these transforms a whole lot quicker.

I can't say I recall the discussions around matrix(), but could that not be extended (or have a new/matrix() call) to have size N 2D matricies, that you can access specific values of?
Maybe I don't understand the /matrix datum clearly, but it seems to be limited to 3x3 matrices and the last column has to be 0, 0, 1. I don't think that my Matrix datum has issues with calculations, as much as it does calculating it so many times.

My transition matrix (to be used in pathfinding) would require an NxN matrix where N controls the range of movement. Then I'd have to do AT LEAST N-1 dot products with itself to verify that a move to this destination is even possible. A 10x10 map yields a 100x100 matrix, which can require up to 99 moves. With my current code, that would take about 3 minutes to calculate if the move is even possible, and then I need to create a list of moves that I would then "unravel".
a sleep(world.tick_lag) in the loop isn't going to effect you, well..at all.

Try it out and see if the error still happens?
Didn't change much, lol. I'm trying to think of a way to cut down the calculations but I think I might just have to let this transition matrix idea go.
The keyword here is 'suspected'. The loop doesn't necessarily have to be infinite, but rather have a high enough number of iterations for Dream Seeker to become suspicious of it.

To solve this you can either:

1. Set world.loop_checks to 0, and this will disable the infinite loop protection altogether.

2. Add 'set background = 1' at the top of your proc. This will result in backlog checks and let other pending events go through, and pacify the loop checker.
Oh should also add, when the loop is suspected as an infinite loop, it's not being terminated. It's just being switched to a background procedure.
Setting this to background would not be optimal as background procs run intermittently, making the proc take even longer to complete.
Instead of stacking for()'s inside of each-other an alternative is to have a while() under a for() that runs through a temp list's first entry and removes it after it's processed.

I don't think it slows the process down but definitely shifts the workload.