Matrix multiplication extension


#1

Hi, I’m developing a 2D matrix multiplication extension that uses regular 2D arrays. To provide the final result matrix as another 2D array, I came up with the following strategy to create the 2D result array object in C and populate it with the custom values in vect[]:

object *fn_makemat (object *args, object *env) {
  (void) env;
  int bit;
  int rows, cols;
  rows = 4;
  cols = 4;

  // Make array object
  object *resdims = cons(number(rows), cons(number(cols), NULL));
  object *resarray = makearray(resdims, number(0), false);

  // Populate array with values
  int vect[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
  int index = 0;

  for(int i = 0; i < rows; ++i){
    for(int j = 0; j < cols; ++j) {
      object *rowcol = cons(number(i), cons(number(j), NULL));
      object *loc = *getarray(resarray, rowcol, 0, &bit);
      
      loc->integer = vect[index];
      ++index;
    }
  }
  return resarray;
}

But when I call the function from the uLisp REPL, I get the following array:

#2A((16 16 16 16) (16 16 16 16) (16 16 16 16) (16 16 16 16))

And the desired result is:

#2A((1 2 3 4) (5 6 7 8) (9 10 11 12) (13 14 15 16))

Apparently in every iteration the current value from the C vector: vect[index] is being assigned to all elements in the array.

Any tips on what I could be doing wrong? Thanks in advace!


#2

Nice application! The problem is that the array is initialised with every element pointing to the same integer object. Your loop is then successively changing the value of that object to 1 … 16.

What you need to do is create a new number object for each array element, like this:

  for(int i = 0; i < rows; ++i){
    for(int j = 0; j < cols; ++j) {
      object *rowcol = cons(number(i), cons(number(j), NULL));
      object **loc = getarray(resarray, rowcol, 0, &bit);

      *loc = number(vect[index]);
      ++index;
    }
  }

That should then work.

Regards,
David


#3

Hi David,

Yes it works! I’m still wrapping my head around the objects system implementation, mostly because C pointers are sometimes confusing, but this helps very much.

Thanks for your help!

Raul


#4

A bit late but I think a good rule of thumb is to never mutate the internal members of the object struct directly, only create and modify objects using uLisp’s C functions. If you’re concerned about memory usage, then either you can implement number interning:

Or you can just use a microcontroller with a huge amount of memory, such as the Teensy 4.1


#5

Hi @ dragoncoder047,

Thanks for your comment, I’ll take it into account. Regards!

Raul