How do you use matrices in Nimrod?
Asked Answered
S

1

6

I found this project on GitHub; it was the only search term returned for "nimrod matrix". I took the bare bones of it and changed it a little bit so that it compiled without errors, and then I added the last two lines to build a simple matrix, and then output a value, but the "getter" function isn't working for some reason. I adapted the instructions for adding properties found here, but something isn't right.

Here is my code so far. I'd like to use the GNU Scientific Library from within Nimrod, and I figured that this was the first logical step.

type 
  TMatrix*[T] = object
    transposed: bool
    dataRows: int
    dataCols: int
    data: seq[T]

proc index[T](x: TMatrix[T], r,c: int): int {.inline.} = 
  if r<0  or  r>(x.rows()-1):
    raise newException(EInvalidIndex, "matrix index out of range")
  if c<0  or  c>(x.cols()-1):
    raise newException(EInvalidIndex, "matrix index out of range")
  result = if x.transposed: c*x.dataCols+r else: r*x.dataCols+c

proc rows*[T](x: TMatrix[T]): int {.inline.} = 
  ## Returns the number of rows in the matrix `x`.
  result = if x.transposed: x.dataCols else: x.dataRows

proc cols*[T](x: TMatrix[T]): int {.inline.}  = 
  ## Returns the number of columns in the matrix `x`.
  result = if x.transposed: x.dataRows else: x.dataCols

proc matrix*[T](rows, cols: int, d: openarray[T]): TMatrix[T] = 
  ## Constructor.  Initializes the matrix by allocating memory
  ## for the data and setting the number of rows and columns
  ## and sets the data to the values specified in `d`.
  result.dataRows = rows
  result.dataCols = cols
  newSeq(result.data, rows*cols)
  if len(d)>0:
    if len(d)<(rows*cols):
      raise newException(EInvalidIndex, "insufficient data supplied in matrix     constructor")

    for i in countup(0,rows*cols-1):
      result.data[i] = d[i]

proc `[][]`*[T](x: TMatrix[T], r,c: int): T = 
  ## Element access.  Returns the element at row `r` column `c`.
  result = x.data[x.index(r,c)]

proc `[][]=`*[T](x: var TMatrix[T], r,c: int, a: T) = 
  ## Sets the value of the element at row `r` column `c` to
  ## the value supplied in `a`.
  x.data[x.index(r,c)] = a

var m = matrix( 2, 2, [1,2,3,4] )

echo( $m[0][0] )

This is the error I get:

c:\program files (x86)\nimrod\config\nimrod.cfg(36, 11) Hint: added path:       'C:\Users\H127\.babel\libs\' [Path]
Hint: used config file 'C:\Program Files (x86)\Nimrod\config\nimrod.cfg' [Conf]
Hint: system [Processing]
Hint: mat [Processing]
mat.nim(48, 9) Error: type mismatch: got (TMatrix[int], int literal(0))
but expected one of: 
system.[](a: array[Idx, T], x: TSlice[Idx]): seq[T]
system.[](a: array[Idx, T], x: TSlice[int]): seq[T]
system.[](s: string, x: TSlice[int]): string
system.[](s: seq[T], x: TSlice[int]): seq[T]

Thanks you guys!

Shulamite answered 28/1, 2014 at 20:23 Comment(0)
L
2

I'd like to first point out that the matrix library you refer to is three years old. For a programming language in development that's a lot of time due to changes, and it doesn't compile any more with the current Nimrod git version:

$ nimrod c matrix
...
private/tmp/n/matrix/matrix.nim(97, 8) Error: ']' expected

It fails on the double array accessor, which seems to have changed syntax. I guess your attempt to create a double [][] accessor is problematic, it could be ambiguous: are you accessing the double array accessor of the object or are you accessing the nested array returned by the first brackets? I had to change the proc to the following:

proc `[]`*[T](x: TMatrix[T], r,c: int): T =

After that change you also need to change the way to access the matrix. Here's what I got:

for x in 0 .. <2:
  for y in 0 .. <2:
    echo "x: ", x, " y: ", y, " = ", m[x,y]

Basically, instead of specifying two bracket accesses you pass all the parameters inside a single bracket. That code generates:

x: 0 y: 0 = 1
x: 0 y: 1 = 2
x: 1 y: 0 = 3
x: 1 y: 1 = 4

With regards to finding software for Nimrod, I would like to recommend you using Nimble, Nimrod's package manager. Once you have it installed you can search available and maintained packages. The command nimble search math shows two potential packages: linagl and extmath. Not sure if they are what you are looking for, but at least they seem more fresh.

Lorrettalorri answered 29/1, 2014 at 9:27 Comment(2)
Yeah, I saw that it was old, I just took the basics out and tried to fiddle with them. I found extmath, but it didn't have what I needed; I'll definitely look at linalg. Thanks!Shulamite
Thanks again, for completeness, I'll add that the "setter" proc needs to be changed to proc `[]=`*[T](x: var TMatrix[T], r,c: int, a: T) = .Shulamite

© 2022 - 2024 — McMap. All rights reserved.