While working on PR #2973, I noticed that most arithmetics there did not perform any checks on the dimensions of the involved input matrices. Likewise for vectors. (And actually, also no basedomain checks; but to keep things simpler, I'd like to focus on the dimensions in this issue; we can discuss basedomain checks separately; so for this issue, let's assume that all matrices and vectors have identical basedomain).
We should decide what we demand from resp. allow MatrixObj implementations to do when dimensions don't match. To simplify the discussion further, let's start by focusing on a single example:
What should happen two matrices are added whose dimensions differ?
If they are lists-of-lists, GAP will happily proceed; but the output may not be a matrix anymore:
gap> [[1,2]] + [[3],[4]];
[ [ 4, 2 ], [ 4 ] ]
Similarly, one can add lists of differing lengths; the missing entries in the shorter list are essentially treated as being zero.
So, here are some options I can think of:
-
We forbid this, and require that conformant MatrixObj implementations must check the dimensions, and must produce an error if the dimensions do not match
-
We document the behavior explicitly undefined. MatrixObj implementations may check the dimensions, and may produce an error if the dimensions do not match; but they can also produce bogus results
-
We explicitly allow this, and define what the resulting matrix should be (likely: taking the maximum of the number of rows, and the maximum of the number of columns, and create a matrix of that size; fill the result up with zeros as needed).
-
... other possibilities... ?
To me option 3 is the least interesting, as I see no applications of this rather artificial behavior. The drawback of option 1 is that it has a performance penalty, albeit probably a rather small one (this is a different once one considers the BaseDomain, though!).
I think I kind of prefer option 2 for this reason, although it has the drawback of letting buggy code slip through. But if we add checks inside of Assert statements in as many places as possible, one could simply set the assertion level up to get slower code that however immediately points out any such bugs.
This example of course has many variants, for addition, subtraction, multiplication; and also for vectors, and as I mentioned, for the basedomain. We should resolve all of those eventually.
While working on PR #2973, I noticed that most arithmetics there did not perform any checks on the dimensions of the involved input matrices. Likewise for vectors. (And actually, also no basedomain checks; but to keep things simpler, I'd like to focus on the dimensions in this issue; we can discuss basedomain checks separately; so for this issue, let's assume that all matrices and vectors have identical basedomain).
We should decide what we demand from resp. allow MatrixObj implementations to do when dimensions don't match. To simplify the discussion further, let's start by focusing on a single example:
What should happen two matrices are added whose dimensions differ?
If they are lists-of-lists, GAP will happily proceed; but the output may not be a matrix anymore:
Similarly, one can add lists of differing lengths; the missing entries in the shorter list are essentially treated as being zero.
So, here are some options I can think of:
We forbid this, and require that conformant MatrixObj implementations must check the dimensions, and must produce an error if the dimensions do not match
We document the behavior explicitly undefined. MatrixObj implementations may check the dimensions, and may produce an error if the dimensions do not match; but they can also produce bogus results
We explicitly allow this, and define what the resulting matrix should be (likely: taking the maximum of the number of rows, and the maximum of the number of columns, and create a matrix of that size; fill the result up with zeros as needed).
... other possibilities... ?
To me option 3 is the least interesting, as I see no applications of this rather artificial behavior. The drawback of option 1 is that it has a performance penalty, albeit probably a rather small one (this is a different once one considers the
BaseDomain, though!).I think I kind of prefer option 2 for this reason, although it has the drawback of letting buggy code slip through. But if we add checks inside of
Assertstatements in as many places as possible, one could simply set the assertion level up to get slower code that however immediately points out any such bugs.This example of course has many variants, for addition, subtraction, multiplication; and also for vectors, and as I mentioned, for the basedomain. We should resolve all of those eventually.