Smilebags / p5.dimensions.js

An addon for p5.js which adds support for higher dimensional calculations.
72 stars 24 forks source link

No matrix multiplication? #27

Open filonik opened 5 years ago

filonik commented 5 years ago

Why does the library not provide matrix multiplication? It seems kind of fundamental. Here is a simple implementation:

            if (output.size[1] != other.size[0]) {
                throw "Matrix is wrong size for this matrix";
            } else {
                var size = [output.size[0], other.size[1]];
                var input = [];
                for (var i = 0; i < output.size[0]; i++) {
                  for (var k = 0; k < other.size[1]; k++) {
                    input[(i * size[0]) + k] = 0;
                    for (var j = 0; j < output.size[1]; j++) {
                      input[(i * size[0]) + k] += Number(output.data[i][j] * other.data[j][k]);
                    }
                  }
                }
            }
            return nMatrix(size, input);
        };
Smilebags commented 5 years ago

Thanks for bringing this up. I did look at this when implementing it, the issue is that we want to provide a consistent API so splitting the method into two wasn't a very nice solution. I never revisited this after the initial work so it never got resolved.

I'd be happy to look at a PR with this. It should probably be part of in with nMatrix.multiply in the user-facing API, but they could be implemented as separate methods internally. We'd just need to do some argument type checking.

filonik commented 5 years ago

Yes, I see the reasoning behind that. I can work up a PR that uses the same method for both vectors and matrices; dispatching based on the argument type.

filonik commented 5 years ago

Upon closer inspection, vectors and matrices are just generic objects, which makes it difficult to distinguish between them. Any reason why they haven't been implemented as prototype-based JavaScript objects?

Smilebags commented 5 years ago

I think a suitable way of checking for a matrix would be something like this:

function isMatrix(obj) {
  if (
    !obj.size
    || obj.size.length !== 2
    || !obj.data
  ) {
    return false;
  }
  return obj.size[0] === obj.data.length
    && obj.size[1] === obj.data[0].length;
}

If the size property matches what we expect in data, I think we can treat it as a matrix.

Smilebags commented 5 years ago

To answer your question, no, there's no real reason. They are attached to the p5 prototype, so you can create them with p5.nVector etc, you might be able to use that for prototypal comparison if you want to go that route, but that makes it less polymorphic, I should be able to construct the necessary data and use it as an nVector without using the constructor.

Feel free to take a look at the interface shown in the TS source https://github.com/Smilebags/p5.dimensions.js/blob/master/libraries/p5.dimensions.ts#L34