Skip to content

Commit

Permalink
WIP: add IsRowPlistMatrixRep
Browse files Browse the repository at this point in the history
  • Loading branch information
fingolfin committed May 3, 2022
1 parent 448079e commit f58301a
Show file tree
Hide file tree
Showing 3 changed files with 144 additions and 37 deletions.
11 changes: 6 additions & 5 deletions doc/ref/matobj.xml
Original file line number Diff line number Diff line change
Expand Up @@ -173,10 +173,10 @@ for these matrix objects.

<P/>

One implementation of such matrices is given by the
Two implementation of such matrices is given by the
<Ref Attr="ConstructingFilter" Label="for a matrix object"/> value
<Ref Filt="IsPlistMatrixRep"/>,
and any row of these matrices is a vector object in
<Ref Filt="IsRowPlistMatrixRep"/>,
and any row of these matrices can be accessed as a vector object in
<Ref Filt="IsPlistVectorRep"/>.
Note that these objects do <E>not</E> lie in <Ref Filt="IsList"/>
(and in particular not in <Ref Filt="IsPlistRep"/>),
Expand All @@ -190,8 +190,9 @@ in the last position,
that is, the vector and matrix objects insist on being dense.
All rows of a matrix must have the same length and the same base domain.

<#Include Label="IsPlistVectorRep">
<#Include Label="IsPlistMatrixRep">
<#Include Label="IsRowPlistMatrixRep">
<#Include Label="IsPlistVectorRep"> <!-- TODO: this does not really belong here; where else? -->
<#Include Label="IsPlistMatrixRep"> <!-- TODO: this does not really belong here; where else? -->
<#Include Label="RowListMatObj_[]">
<#Include Label="RowListMatObj_[]_ASS">
<#Include Label="RowListMatObj_{}">
Expand Down
54 changes: 32 additions & 22 deletions lib/matobjplist.gd
Original file line number Diff line number Diff line change
Expand Up @@ -56,35 +56,45 @@ DeclareRepresentation( "IsPlistVectorRep",
##
## <Description>
## An object <A>obj</A> in <Ref Filt="IsPlistMatrixRep"/> describes
## a matrix object (see <Ref Filt="IsMatrixObj"/>) that internal stores its
## entries as a classic GAP matrix, that is as a plain list (see
## <Ref Filt="IsPlistRep"/>) of plain lists. Therefore any such GAP matrix
## can be represented as a <Ref Filt="IsPlistMatrixRep"/>, making this
## representation very versatile, and a good place to start if one wants to
## adapt code which previously produced such classic GAP matrices to instead
## produce matrix objects.
## </Description>
## </ManSection>
## <#/GAPDoc>
##
## Implementation note: a matrix in IsPlistMatrixRep is internally
## represented as a positional object that stores four entries:
## - its base domain
# - the number of rows
## - the number of columns
## - a plain list of its rows, each also a plain list
DeclareRepresentation( "IsPlistMatrixRep",
IsMatrixObj and IsPositionalObjectRep and IsNoImmediateMethodsObject, [] );


#############################################################################
##
## <#GAPDoc Label="IsRowPlistMatrixRep">
## <ManSection>
## <Filt Name="IsRowPlistMatrixRep" Arg='obj' Type="representation"/>
##
## <Description>
## An object <A>obj</A> in <Ref Filt="IsRowPlistMatrixRep"/> describes
## a matrix object (see <Ref Filt="IsMatrixObj"/>) that behaves similar to
## a list of its rows, in the sense defined in
## Section <Ref Sect="Operations for Row List Matrix Objects"/>.
## It is internally represented as a positional object
## (see <Ref Filt="IsPositionalObjectRep"/> that stores four entries:
## <Enum>
## <Item>
## its base domain
## (see <Ref Attr="BaseDomain" Label="for a matrix object"/>),
## </Item>
## <Item>
## the number of rows
## (see <Ref Attr="NumberRows" Label="for a matrix object"/>), and
## </Item>
## <Item>
## the number of columns
## (see <Ref Attr="NumberColumns" Label="for a matrix object"/>), and
## </Item>
## <Item>
## a plain list (see <Ref Filt="IsPlistRep"/> of its rows,
## each of them being an object in <Ref Filt="IsPlistVectorRep"/>.
## </Item>
## </Enum>
## Its rows can be accessed as objects in <Ref Filt="IsPlistVectorRep"/>,
## </Description>
## </ManSection>
## <#/GAPDoc>
##
DeclareRepresentation( "IsPlistMatrixRep",
IsRowListMatrix and IsPositionalObjectRep and IsNoImmediateMethodsObject, [] );
DeclareRepresentation( "IsRowPlistMatrixRep",
IsRowListMatrix and IsPlistMatrixRep, [] );


# Some constants for matrix access:
Expand Down
116 changes: 106 additions & 10 deletions lib/matobjplist.gi
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,9 @@
# Constructors:
############################################################################

InstallMethod( NewVector, "for IsPlistVectorRep, a semiring, and a list",
[ IsPlistVectorRep, IsSemiring, IsList ],
function( filter, basedomain, l )
local typ;
BindGlobal( "MakeIsPlistVectorRep",
function( basedomain, list )
local filter, typ;
filter := IsPlistVectorRep and IsMutable;
if HasCanEasilyCompareElements(Representative(basedomain)) and
CanEasilyCompareElements(Representative(basedomain)) then
Expand All @@ -33,14 +32,23 @@ InstallMethod( NewVector, "for IsPlistVectorRep, a semiring, and a list",
filter := filter and IsFFEVector;
fi;
typ := NewType(FamilyObj(basedomain), filter);
return Objectify(typ, [ basedomain, ShallowCopy(l) ]);
return Objectify(typ, [ basedomain, list ]);
end );


InstallMethod( NewVector, "for IsPlistVectorRep, a semiring, and a list",
[ IsPlistVectorRep, IsSemiring, IsList ],
function( filter, basedomain, list )
list := ShallowCopy( list );
return MakeIsPlistVectorRep( basedomain, list );
end );

InstallMethod( NewZeroVector, "for IsPlistVectorRep, a semiring, and an int",
[ IsPlistVectorRep, IsSemiring, IsInt ],
function( filter, basedomain, l )
l := ListWithIdenticalEntries(l,Zero(basedomain));
return NewVector( filter, basedomain, l );
function( filter, basedomain, len )
local list;
list := ListWithIdenticalEntries(len, Zero(basedomain));
return MakeIsPlistVectorRep( basedomain, list );
end );

InstallMethod( NewMatrix,
Expand Down Expand Up @@ -549,9 +557,97 @@ InstallMethod( IdentityMatrix, "for an integer and a plist matrix",
return res;
end );

# FIXME: does ShallowCopy even make sense for a matrixobj???

############################################################################
# A selection of list operations:
############################################################################

InstallOtherMethod( \[\], "for a plist matrix and a positive integer",
#T Once the declaration of '\[\]' for 'IsMatrixObj' disappears,
#T we can use 'InstallMethod'.
[ IsRowPlistMatrixRep, IsPosInt ],
function( m, i )
Info(InfoPerformance, 1, "for best performance avoid m[i]; e.g. use m[i,j] instead of m[i][j]");
# TODO: should we cache these row vectors?
return MakeIsPlistVectorRep( m![BDPOS], m![ROWSPOS][i] );
end );

InstallMethod( \[\]\:\=,
"for a plist matrix, a positive integer, and a plist vector",
[ IsRowPlistMatrixRep and IsMutable, IsPosInt, IsPlistVectorRep ],
function( m, i, v )
# TODO: verify that basedomain matches and that Length(v) = NrCols(m) ?
m![ROWSPOS][i] := v![ELSPOS];
# FIXME: really just assign the content, so that from now on any change to
# the vector object <v> will modify the i-th row of <m>??? yes, this
# emulates the old way of things, but it's also dangerous, and often leads to
# bugs; perhaps we should instead make a copy / copy over the data only?
end );

InstallMethod( \{\}, "for a plist matrix and a list",
[ IsRowPlistMatrixRep, IsList ],
function( m, p )
local l;
l := m![ROWSPOS]{p};
return Objectify(TypeObj(m),[m![BDPOS],m![NUM_ROWS_POS],m![NUM_COLS_POS],l]);
end );

InstallMethod( Add, "for a plist matrix and a plist vector",
[ IsRowPlistMatrixRep and IsMutable, IsPlistVectorRep ],
function( m, v )
Add(m![ROWSPOS],v);
end );

InstallMethod( Add, "for a plist matrix, a plist vector, and a pos. int",
[ IsRowPlistMatrixRep and IsMutable, IsPlistVectorRep, IsPosInt ],
function( m, v, p )
Add(m![ROWSPOS],v,p);
end );

InstallMethod( Remove, "for a plist matrix",
[ IsRowPlistMatrixRep and IsMutable ],
m -> Remove( m![ROWSPOS] ) );

InstallMethod( Remove, "for a plist matrix, and a position",
[ IsRowPlistMatrixRep and IsMutable, IsPosInt ],
function( m, p )
Remove( m![ROWSPOS],p );
end );
#T must return the removed row if it was bound

InstallMethod( IsBound\[\], "for a plist matrix, and a position",
[ IsRowPlistMatrixRep, IsPosInt ],
function( m, p )
# TODO: move this to the generic IsRowListMatrix interface?
return p <= NrRows(m);
end );

InstallMethod( Unbind\[\], "for a plist matrix, and a position",
[ IsRowPlistMatrixRep and IsMutable, IsPosInt ],
function( m, p )
# TODO: move this to the generic IsRowListMatrix interface?
if p <> NrRows(m) then
ErrorNoReturn("Unbind\\[\\]: Matrices must stay dense, you cannot Unbind here");
fi;
Remove(m);
end );

InstallMethod( \{\}\:\=, "for a plist matrix, a list, and a plist matrix",
[ IsRowPlistMatrixRep and IsMutable, IsList,
IsRowPlistMatrixRep ],
function( m, pp, n )
# TODO: verify that basedomain matches and that Length(v) = NrCols(m) ?
m![ROWSPOS]{pp} := n![ROWSPOS];
end );

InstallMethod( Append, "for two plist matrices",
[ IsRowPlistMatrixRep and IsMutable, IsRowPlistMatrixRep ],
function( m, n )
Append(m![ROWSPOS],n![ROWSPOS]);
end );

InstallMethod( ShallowCopy, "for a plist matrix",
[ IsPlistMatrixRep ],
[ IsRowPlistMatrixRep ],
function( m )
local res;
res := Objectify(TypeObj(m),[m![BDPOS],m![NUM_ROWS_POS],m![NUM_COLS_POS],
Expand Down

0 comments on commit f58301a

Please sign in to comment.