You can use closures or pass the data parameter as an input to the function.

Here is an example with closures
    
    
    type
      AbstractKernel[T] = proc(dst: var T, src: Matrix[T], i, j: int) 
{.closure.}
      Matrix[T] = object
        dim: array[2, int]
        data: seq[T]
    
    func newMatrix(rows, cols: int, T: typedesc): Matrix[T] =
      result.dim[0] = rows
      result.dim[1] = cols
      result.data.newSeq(rows * cols)
    
    func ncols(m: Matrix): int {.inline.} =
      m.dim[1]
    
    func nrows(m: Matrix): int {.inline.} =
      m.dim[0]
    
    template `[]`(m: Matrix, i, j: int): auto =
      m.data[i * m.dim[1] + j]
    
    template `[]=`[T](m: var Matrix[T], i, j: int, val: T) =
      m.data[i * m.dim[1] + j] = val
    
    proc calculateKernelMatrix*[T](m: Matrix[T], kernel: AbstractKernel[T]): 
Matrix[T] =
      result = newMatrix(m.nrows, m.ncols, T);
      for i in 0 ..< m.nrows:
        for j in 0 ..< m.ncols:
          kernel(result[i, j], m, i, j);
    
    let M = newMatrix(3, 3, int)
    echo M # (dim: [3, 3], data: @[0, 0, 0, 0, 0, 0, 0, 0, 0])
    
    let N = M.calculateKernelMatrix do (dst: var int, src: Matrix[int], i, j: 
int):
        let state = 100
        dst = state * i + j
    echo N # (dim: [3, 3], data: @[0, 1, 2, 100, 101, 102, 200, 201, 202])
    
    let K = N.calculateKernelMatrix do (dst: var int, src: Matrix[int], i, j: 
int):
        let state = -1
        dst = src[i, j] * state
    echo K # (dim: [3, 3], data: @[0, -1, -2, -100, -101, -102, -200, -201, 
-202])
    
    
    Run

`state` can be anything beyond a simple int.

Reply via email to