One of the problems with treating matrices and vectors like lists is that we have to adopt the rules for comparing lists; and two lists are equal if they have equal elements. This means that all 0-dimensional vectors and matrices over all base domains should be equal, at least as long as they are lists.
To resolve that, we want to have MatrixObj and VectorObj implementations which are not lists (see also #2148). But then we should still define precise semantics as to when two vectors or two matrices compare as equal. Here is a first suggestion for how that might work:
- a vectorobj and a matrixobj are never equal
- two vectorbj are equal if they ...
- have equal length,
- have "compatible" base domains,
- contain equal elements
- two matrixobj are equal if they ...
- have equal numbers of rows,
- have equal number of columns,
- have "compatible" base domains,
- contain equal elements
This leaves the question what constitutes "compatible" base domains. A simple but overly restrict definition would be to require the base domains to be equal.
This solves some problems, but would be a radical departure from how vectors in GAP
currently work, and I think that alone makes it a bad choice. There is also the matter of inconvenience caused by this when writing code.
Another definition would be to say two base domains are "compatible" if one is "contained" in the other, with compatible structure (i.e. addition/multiplication/subtraction of the "larger" base domain restrict to those of the "smaller" one.
So for fields, that just means they are compatible if one is a subfield of the other, which matches what we do right now, I think. [ UPDATE: what I really meant is that there should be a common super field containing both; for GF(q), that can be essentially tested by checkin for equal characteristic. ]
The one thing I am a bit worried here is whether we can tests this efficiently, i.e., I don't want risk introducing a bottleneck here.
Therefore, we might want to use a slightly different definition:
- a vectorobj and a matrixobj are never equal
- two vectorbj are equal if they ...
- have equal length,
- contain equal elements,
- and, if they are empty, then they must have "compatible" base domains.
- two matrixobj are equal if they ...
- have equal numbers of rows,
- have equal number of columns,
- have "compatible" base domains,
- contain equal elements
- and, if they are empty, then they must have "compatible" base domains.
This way, we only need to compare the base domains for empty vectors and matrices, which should be relatively rare. Drawback: it is a little bit less flexible. E.g. with the former model, people could write special "strict" base domains, which are not compatible with any other base domain, to get some kind of "strict typing" through the backdoor. Not sure if that's a good idea to start with, but I wanted to mention it for completeness.
As to how to implement testing for compatibility of base domains, I'd try to use method dispatch for that, to make it extensible:
DeclareOperation("IsCompatibleBaseDomain", [IsObject, IsObject]);
# identical base domains are always compatible
InstallMethod(IsCompatibleBaseDomain, IsIdenticalObj, [IsObject, IsObject], SUM_FLAGS,
function(bd1, bd2)
if IsIdenticalObj(bd1, bd2) then return true; fi;
TryNextMethod();
end);
# fallback: if no method fired, then assume the base domains are not compatible
InstallMethod(IsCompatibleBaseDomain,
[IsObject, IsObject],
ReturnFalse);
# cyclotomics are always compatible
InstallMethod(IsCompatibleBaseDomain, IsIdenticalObj,
[IsCyclotomicCollection, IsCyclotomicCollection],
ReturnTrue);
# FFE domains are compatible if they have equal characteristic
InstallMethod(IsCompatibleBaseDomain, IsIdenticalObj,
[IsFFECollection, IsFFECollection],
{bd1, bd2} -> Characteristic(bd1) = Characteristic(bd2));
One of the problems with treating matrices and vectors like lists is that we have to adopt the rules for comparing lists; and two lists are equal if they have equal elements. This means that all 0-dimensional vectors and matrices over all base domains should be equal, at least as long as they are lists.
To resolve that, we want to have MatrixObj and VectorObj implementations which are not lists (see also #2148). But then we should still define precise semantics as to when two vectors or two matrices compare as equal. Here is a first suggestion for how that might work:
This leaves the question what constitutes "compatible" base domains. A simple but overly restrict definition would be to require the base domains to be equal.
This solves some problems, but would be a radical departure from how vectors in GAP
currently work, and I think that alone makes it a bad choice. There is also the matter of inconvenience caused by this when writing code.
Another definition would be to say two base domains are "compatible" if one is "contained" in the other, with compatible structure (i.e. addition/multiplication/subtraction of the "larger" base domain restrict to those of the "smaller" one.
So for fields, that just means they are compatible if one is a subfield of the other, which matches what we do right now, I think. [ UPDATE: what I really meant is that there should be a common super field containing both; for
GF(q), that can be essentially tested by checkin for equal characteristic. ]The one thing I am a bit worried here is whether we can tests this efficiently, i.e., I don't want risk introducing a bottleneck here.
Therefore, we might want to use a slightly different definition:
This way, we only need to compare the base domains for empty vectors and matrices, which should be relatively rare. Drawback: it is a little bit less flexible. E.g. with the former model, people could write special "strict" base domains, which are not compatible with any other base domain, to get some kind of "strict typing" through the backdoor. Not sure if that's a good idea to start with, but I wanted to mention it for completeness.
As to how to implement testing for compatibility of base domains, I'd try to use method dispatch for that, to make it extensible: