Skip to content

Commit 050739d

Browse files
authored
Add a manual section: how to write code for matrix objects (#6320)
1 parent a1350d7 commit 050739d

1 file changed

Lines changed: 153 additions & 0 deletions

File tree

doc/ref/matobj.xml

Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -402,4 +402,157 @@ The following conventions hold for such a group <C>G</C>.
402402

403403
</Section>
404404

405+
<!-- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -->
406+
<Section Label="How to Write Code for Vector and Matrix Objects">
407+
<Heading>How to Write Code for Vector and Matrix Objects</Heading>
408+
409+
Vector and matrix objects have a number of different representations in &GAP;
410+
which are optimised for different things;
411+
see the list <Ref Var="ConstructingFiltersForMatrixGroupElements"/> for
412+
examples of available
413+
<Ref Attr="ConstructingFilter" Label="for a matrix object"/> values
414+
of matrix objects.
415+
Most &GAP; functions accepting vector or matrix objects as arguments
416+
do not depend on any particular representation for these objects.
417+
If the output of such a function involves vector and matrix objects,
418+
then these are expected to have the same representations as the inputs.
419+
For example, a function that computes the Kronecker product of two
420+
matrix objects <C>mat1</C>, <C>mat2</C> may take the two inputs,
421+
which must have the same
422+
<Ref Attr="ConstructingFilter" Label="for a matrix object"/> value,
423+
create a new matrix object which also lies in this filter,
424+
for example by calling <C>ZeroMatrix( m, n, mat1 )</C>,
425+
and then set the entries in this matrix.
426+
427+
<P/>
428+
429+
Functions like
430+
<Ref Oper="ZeroMatrix" Label="for dimensions and matrix object"/>,
431+
<Ref Oper="IdentityMatrix" Label="for dimension and matrix object"/>,
432+
and <Ref Oper="Matrix" Label="for a list and a matrix object"/>
433+
admit different kinds of inputs.
434+
<C>ZeroMatrix( R, m, n )</C> can be used, for example,
435+
if we want to leave the decision about the representation of the result
436+
to &GAP;.
437+
This might be useful if the result of <C>ZeroMatrix( R, m, n )</C> is
438+
the first matrix we create, and then later matrices are created
439+
relative to this matrix.
440+
If we already have a matrix object <C>M</C> and want <C>ZeroMatrix</C>
441+
to return a new matrix object that has the same representation as <C>M</C>,
442+
then <C>ZeroMatrix( R, m, n )</C> may not return a matrix with the expected
443+
representation.
444+
For example, even if we use the same <C>R</C> as before, &GAP; might decide
445+
to use a sparse representation for large enough <C>m</C> and <C>n</C>.
446+
It is possible to create a <C>ZeroMatrix</C> in the same representation
447+
as <C>M</C> by fully specifying this representation as follows
448+
<C>ZeroMatrix( ConstructingFilter( M ), BaseDomain( M ), m, n )</C>.
449+
It is also possible to produce the same result using the more convenient
450+
<C>ZeroMatrix( m, n, M )</C>.
451+
452+
<P/>
453+
454+
This approach works also in many situation where the input involves
455+
the <Q>list of list</Q> matrices in the filter <Ref Filt="IsMatrix"/>.
456+
In practice, the question is often the other way round:
457+
one has old &GAP; code that was written for objects in <Ref Filt="IsMatrix"/>,
458+
and wants to rewrite it such that it works for general matrix objects also.
459+
In such cases, the following guidelines may be useful.
460+
461+
<List>
462+
<Item>
463+
Use <C>M[i, j]</C> not <C>M[i][j]</C>
464+
for accessing/assigning matrix entries.
465+
<P/>
466+
<E>Reason:</E>
467+
<C>M[i][j]</C> means to fetch or even create <C>M[i]</C>
468+
and then take the <C>j</C>-th entry of it.
469+
</Item>
470+
<Item>
471+
Use <C>ExtractSubMatrix( M, rows, cols )</C> not <C>M{ rows }{ cols }</C>
472+
for accessing submatrices,
473+
similarly use <C>CopySubMatrix( src, dst, srows, drows, scols, dcols )</C>.
474+
<P/>
475+
<E>Reason:</E>
476+
The <C>M{ rows }</C> syntax is supported only for
477+
row-list matrices, see <Ref Filt="IsRowListMatrix"/>.
478+
</Item>
479+
<Item>
480+
Use <C>ZeroVector( R, n )</C> not <C>[ 1 .. n ] * Zero( R )</C> for
481+
creating a zero vector over a given domain <C>R</C>.
482+
<P/>
483+
<E>Reason:</E>
484+
The latter syntax creates an unnecessary new object <C>[ 1 .. n ]</C>,
485+
multiplies each of its entries with <C>Zero( R )</C>
486+
(not knowing that the result will be <C>Zero( R )</C> in each case),
487+
and creates not a vector object but a plain list of the results.
488+
</Item>
489+
<Item>
490+
Use <C>ZeroVector( n, M )</C> not <C>0 * M[1]</C> for a
491+
given matrix object <C>M</C> with <C>n</C> columns.
492+
<P/>
493+
<E>Reason:</E>
494+
Calling <C>M[1]</C> may have to create an unnecessary new object
495+
<C>M[1]</C>.
496+
</Item>
497+
<Item>
498+
Use <Ref Attr="BaseDomain" Label="for a matrix object"/>
499+
not <Ref Attr="DefaultFieldOfMatrix"/>.
500+
<P/>
501+
<E>Reason:</E>
502+
This is just a conceptual issue, the results should in fact coincide.
503+
A matrix object <C>M</C> which is not a list of lists stores its
504+
<Ref Attr="BaseDomain" Label="for a matrix object"/> value.
505+
For convenience, <C>DefaultFieldOfMatrix( M )</C> is defined
506+
to return this value (although this need not be a field).
507+
On the other hand, a list of lists <C>M</C> in <Ref Filt="IsMatrix"/>
508+
does not store the two attribute values,
509+
<Ref Attr="DefaultFieldOfMatrix"/> value is computed from the entries
510+
of <C>M</C>,
511+
and for convenience, <C>BaseDomain( M )</C> is defined to return the
512+
<Ref Attr="DefaultFieldOfMatrix"/> value.
513+
</Item>
514+
<Item>
515+
Do not use the unary versions of
516+
<Ref Func="ConvertToVectorRep" Label="for a list (and a field)"/>
517+
and <Ref Func="ConvertToMatrixRep" Label="for a list (and a field)"/>.
518+
<P/>
519+
<E>Reason:</E>
520+
For example, consider the two matrices <C>M1 = [ [ Z(4) ] ]</C> and
521+
<C>M2 = [ [ Z(4)^3 ] ]</C> over the field with four elements.
522+
The latter is in fact a matrix over the field with two elements,
523+
and <C>ConvertToMatrixRep( M2 )</C> turns it into a matrix in
524+
<Ref Filt="IsGF2MatrixRep"/>, whereas <C>ConvertToMatrixRep( M1 )</C>
525+
yields a matrix in <Ref Filt="Is8BitMatrixRep"/>.
526+
Thus computing products or sums of these matrices is more expensive
527+
than computations with two matrices in <Ref Filt="Is8BitMatrixRep"/>.
528+
</Item>
529+
<Item>
530+
Use <Ref Oper="ImmutableMatrix"/> and the binary versions of
531+
<Ref Func="ConvertToVectorRep" Label="for a list (and a field)"/>
532+
and <Ref Func="ConvertToMatrixRep" Label="for a list (and a field)"/>
533+
only when creating initial objects
534+
which need not be compatible with given vectors or matrices.
535+
<P/>
536+
<E>Reason:</E>
537+
The idea behind these functions is to choose a good representation
538+
for initial data (for example for some expensive MeatAxe computations,
539+
see Chapter <Ref Chap="The MeatAxe"/>).
540+
The results of computations with these data should then automatically
541+
be in the same representation.
542+
If not then the code in question has problems,
543+
and <Q>adjusting</Q> the representation of intermediate results by
544+
calling the abovementioned conversion functions just hides these problems.
545+
</Item>
546+
</List>
547+
548+
Conversely, do <E>not</E> use functions for vector and matrix objects
549+
when you want to create an object that shall be used just as a list.
550+
For example, use <C>ListWithIdenticalEntries( n, Zero( R ) )</C>
551+
not <C>Vector( R, n )</C> in this case.
552+
For creating a list with <C>n</C> entries, you can also first call
553+
<Ref Func="EmptyPlist"/> for creating a big enough list,
554+
and then enter the values.
555+
556+
</Section>
557+
405558
</Chapter>

0 commit comments

Comments
 (0)