mirror of
https://github.com/KevinMidboe/linguist.git
synced 2025-10-29 17:50:22 +00:00
Add support for the GAP language
This commit is contained in:
@@ -620,6 +620,16 @@ Forth:
|
|||||||
extensions:
|
extensions:
|
||||||
- .4th
|
- .4th
|
||||||
|
|
||||||
|
GAP:
|
||||||
|
type: programming
|
||||||
|
lexer: Text only
|
||||||
|
primary_extension: .g
|
||||||
|
extensions:
|
||||||
|
- .g
|
||||||
|
- .gap
|
||||||
|
- .gd
|
||||||
|
- .gi
|
||||||
|
|
||||||
GAS:
|
GAS:
|
||||||
type: programming
|
type: programming
|
||||||
group: Assembly
|
group: Assembly
|
||||||
|
|||||||
@@ -129,6 +129,11 @@
|
|||||||
".forth",
|
".forth",
|
||||||
".fth"
|
".fth"
|
||||||
],
|
],
|
||||||
|
"GAP": [
|
||||||
|
".g",
|
||||||
|
".gd",
|
||||||
|
".gi"
|
||||||
|
],
|
||||||
"GAS": [
|
"GAS": [
|
||||||
".s"
|
".s"
|
||||||
],
|
],
|
||||||
|
|||||||
307
samples/GAP/Magic.gd
Normal file
307
samples/GAP/Magic.gd
Normal file
@@ -0,0 +1,307 @@
|
|||||||
|
#############################################################################
|
||||||
|
##
|
||||||
|
## Magic.gd AutoDoc package
|
||||||
|
##
|
||||||
|
## Copyright 2013, Max Horn, JLU Giessen
|
||||||
|
## Sebastian Gutsche, University of Kaiserslautern
|
||||||
|
##
|
||||||
|
#############################################################################
|
||||||
|
|
||||||
|
|
||||||
|
#! @Description
|
||||||
|
#! This is the main function of the &AutoDoc; package. It can perform
|
||||||
|
#! any combination of the following three tasks:
|
||||||
|
#! <Enum>
|
||||||
|
#! <Item>
|
||||||
|
#! It can (re)generate a scaffold for your package manual.
|
||||||
|
#! That is, it can produce two XML files in &GAPDoc; format to be used as part
|
||||||
|
#! of your manual: First, a file named <F>doc/PACKAGENAME.xml</F>
|
||||||
|
#! (with your package's name substituted) which is used as
|
||||||
|
#! main file for the package manual, i.e. this file sets the
|
||||||
|
#! XML DOCTYPE and defines various XML entities, includes
|
||||||
|
#! other XML files (both those generated by &AutoDoc; as well
|
||||||
|
#! as additional files created by other means), tells &GAPDoc;
|
||||||
|
#! to generate a table of content and an index, and more.
|
||||||
|
#! Secondly, it creates a file <F>doc/title.xml</F> containing a title
|
||||||
|
#! page for your documentation, with information about your package
|
||||||
|
#! (name, description, version), its authors and more, based
|
||||||
|
#! on the data in your <F>PackageInfo.g</F>.
|
||||||
|
#! </Item>
|
||||||
|
#! <Item>
|
||||||
|
#! It can scan your package for &AutoDoc; based documentation (by using &AutoDoc;
|
||||||
|
#! tags and the Autodoc command.
|
||||||
|
#! This will
|
||||||
|
#! produce further XML files to be used as part of the package manual.
|
||||||
|
#! </Item>
|
||||||
|
#! <Item>
|
||||||
|
#! It can use &GAPDoc; to generate PDF, text and HTML (with
|
||||||
|
#! MathJaX enabled) documentation from the &GAPDoc; XML files it
|
||||||
|
#! generated as well as additional such files provided by you. For
|
||||||
|
#! this, it invokes <Ref Func='MakeGAPDocDoc' BookName='gapdoc'/>
|
||||||
|
#! to convert the XML sources, and it also instructs &GAPDoc; to copy
|
||||||
|
#! supplementary files (such as CSS style files) into your doc directory
|
||||||
|
#! (see <Ref Func='CopyHTMLStyleFiles' BookName='gapdoc'/>).
|
||||||
|
#! </Item>
|
||||||
|
#! </Enum>
|
||||||
|
#! For more information and some examples, please refer to Chapter <Ref Label='Tutorials'/>.
|
||||||
|
#! <P/>
|
||||||
|
#! The parameters have the following meanings:
|
||||||
|
#! <List>
|
||||||
|
#!
|
||||||
|
#! <Mark><A>package_name</A></Mark>
|
||||||
|
#! <Item>
|
||||||
|
#! The name of the package whose documentation should be(re)generated.
|
||||||
|
#! </Item>
|
||||||
|
#!
|
||||||
|
#!
|
||||||
|
#! <Mark><A>option_record</A></Mark>
|
||||||
|
#! <Item>
|
||||||
|
#! <A>option_record</A> can be a record with some additional options.
|
||||||
|
#! The following are currently supported:
|
||||||
|
#! <List>
|
||||||
|
#! <Mark><A>dir</A></Mark>
|
||||||
|
#! <Item>
|
||||||
|
#! This should be a string containing a (relative) path or a
|
||||||
|
#! Directory() object specifying where the package documentation
|
||||||
|
#! (i.e. the &GAPDoc; XML files) are stored.
|
||||||
|
#! <Br/>
|
||||||
|
#! <E>Default value: <C>"doc/"</C>.</E>
|
||||||
|
#! </Item>
|
||||||
|
#! <Mark><A>scaffold</A></Mark>
|
||||||
|
#! <Item>
|
||||||
|
#! This controls whether and how to generate scaffold XML files
|
||||||
|
#! for the main and title page of the package's documentation.
|
||||||
|
#! <P/>
|
||||||
|
#! The value should be either <K>true</K>, <K>false</K> or a
|
||||||
|
#! record. If it is a record or <K>true</K> (the latter is
|
||||||
|
#! equivalent to specifying an empty record), then this feature is
|
||||||
|
#! enabled. It is also enabled if <A>opt.scaffold</A> is missing but the
|
||||||
|
#! package's info record in <F>PackageInfo.g</F> has an <C>AutoDoc</C> entry.
|
||||||
|
#! In all other cases (in particular if <A>opt.scaffold</A> is
|
||||||
|
#! <K>false</K>), scaffolding is disabled.
|
||||||
|
#! <P/>
|
||||||
|
#!
|
||||||
|
#! If <A>opt.scaffold</A> is a record, it may contain the following entries.
|
||||||
|
#!
|
||||||
|
#### TODO: mention merging with PackageInfo.AutoDoc!
|
||||||
|
#! <List>
|
||||||
|
#!
|
||||||
|
#! <Mark><A>includes</A></Mark>
|
||||||
|
#! <Item>
|
||||||
|
#! A list of XML files to be included in the body of the main XML file.
|
||||||
|
#! If you specify this list and also are using &AutoDoc; to document
|
||||||
|
#! your operations with &AutoDoc; comments,
|
||||||
|
#! you can add <F>AutoDocMainFile.xml</F> to this list
|
||||||
|
#! to control at which point the documentation produced by &AutoDoc;
|
||||||
|
#! is inserted. If you do not do this, it will be added after the last
|
||||||
|
#! of your own XML files.
|
||||||
|
#! </Item>
|
||||||
|
#!
|
||||||
|
#! <Mark><A>appendix</A></Mark>
|
||||||
|
#! <Item>
|
||||||
|
#! This entry is similar to <A>opt.scaffold.includes</A> but is used
|
||||||
|
#! to specify files to include after the main body of the manual,
|
||||||
|
#! i.e. typically appendices.
|
||||||
|
#! </Item>
|
||||||
|
#!
|
||||||
|
#! <Mark><A>bib</A></Mark>
|
||||||
|
#! <Item>
|
||||||
|
#! The name of a bibliography file, in Bibtex or XML format.
|
||||||
|
#! If this key is not set, but there is a file <F>doc/PACKAGENAME.bib</F>
|
||||||
|
#! then it is assumed that you want to use this as your bibliography.
|
||||||
|
#! </Item>
|
||||||
|
#!
|
||||||
|
#### TODO: The 'entities' param is a bit strange. We should probably change it to be a bit more
|
||||||
|
#### general, as one might want to define other entities... For now, we do not document it
|
||||||
|
#### to leave us the choice of revising how it works.
|
||||||
|
####
|
||||||
|
#### <Mark><A>entities</A></Mark>
|
||||||
|
#### <Item>
|
||||||
|
#### A list of package names or other entities which are used to define corresponding XML entities.
|
||||||
|
#### For example, if set to a list containing the string <Q>SomePackage</Q>,
|
||||||
|
#### then the following is added to the XML preamble:
|
||||||
|
#### <Listing><![CDATA[<!ENTITY SomePackage '<Package>SomePackage</Package>'>]]></Listing>
|
||||||
|
#### This allows you to write <Q>&SomePackage;</Q> in your documentation
|
||||||
|
#### to reference that package. If another type of entity is desired, one can simply add,
|
||||||
|
#### instead of a string, add a two entry list <A>a</A> to the list. It will be handled as
|
||||||
|
#### <Listing><![CDATA[<!ENTITY a[ 2 ] '<a[ 1 ]>a[ 2 ]</a[ 1 ]>'>]]></Listing>,
|
||||||
|
#### so please be careful.
|
||||||
|
#### </Item>
|
||||||
|
#!
|
||||||
|
#! <Mark><A>TitlePage</A></Mark>
|
||||||
|
#! <Item>
|
||||||
|
#! A record whose entries are used to embellish the generated titlepage
|
||||||
|
#! for the package manual with extra information, such as a copyright
|
||||||
|
#! statement or acknowledgments. To this end, the names of the record
|
||||||
|
#! components are used as XML element names, and the values of the
|
||||||
|
#! components are outputted as content of these XML elements. For
|
||||||
|
#! example, you could pass the following record to set a custom
|
||||||
|
#! acknowledgements text:
|
||||||
|
#! <Listing><![CDATA[
|
||||||
|
#! rec( Acknowledgements := "Many thanks to ..." )]]></Listing>
|
||||||
|
#! For a list of valid entries in the titlepage, please refer to the
|
||||||
|
#! &GAPDoc; manual, specifically section <Ref Subsect='Title' BookName='gapdoc'/>
|
||||||
|
#! and following.
|
||||||
|
#! </Item>
|
||||||
|
#! <Mark><A>document_class</A></Mark>
|
||||||
|
#! <Item>
|
||||||
|
#! Sets the document class of the resulting pdf. The value can either be a string
|
||||||
|
#! which has to be the name of the new document class, a list containing this string, or
|
||||||
|
#! a list of two strings. Then the first one has to be the document class name, the second one
|
||||||
|
#! the option string ( contained in [ ] ) in LaTeX.
|
||||||
|
#! </Item>
|
||||||
|
#! <Mark><A>latex_header_file</A></Mark>
|
||||||
|
#! <Item>
|
||||||
|
#! Replaces the standard header from &GAPDoc; completely with the header in this LaTeX file.
|
||||||
|
#! Please be careful here, and look at GAPDoc's latexheader.tex file for an example.
|
||||||
|
#! </Item>
|
||||||
|
#! <Mark><A>gapdoc_latex_options</A></Mark>
|
||||||
|
#! <Item>
|
||||||
|
#! Must be a record with entries which can be understood by SetGapDocLaTeXOptions. Each entry can be a string, which
|
||||||
|
#! will be given to &GAPDoc; directly, or a list containing of two entries: The first one must be the string "file",
|
||||||
|
#! the second one a filename. This file will be read and then its content is passed to &GAPDoc; as option with the name
|
||||||
|
#! of the entry.
|
||||||
|
#! </Item>
|
||||||
|
#!
|
||||||
|
#! </List>
|
||||||
|
#! </Item>
|
||||||
|
#!
|
||||||
|
#!
|
||||||
|
#! <Mark><A>autodoc</A></Mark>
|
||||||
|
#! <Item>
|
||||||
|
#! This controls whether and how to generate addition XML documentation files
|
||||||
|
#! by scanning for &AutoDoc; documentation comments.
|
||||||
|
#! <P/>
|
||||||
|
#! The value should be either <K>true</K>, <K>false</K> or a
|
||||||
|
#! record. If it is a record or <K>true</K> (the latter is
|
||||||
|
#! equivalent to specifying an empty record), then this feature is
|
||||||
|
#! enabled. It is also enabled if <A>opt.autodoc</A> is missing but the
|
||||||
|
#! package depends (directly) on the &AutoDoc; package.
|
||||||
|
#! In all other cases (in particular if <A>opt.autodoc</A> is
|
||||||
|
#! <K>false</K>), this feature is disabled.
|
||||||
|
#! <P/>
|
||||||
|
#!
|
||||||
|
#! If <A>opt.autodoc</A> is a record, it may contain the following entries.
|
||||||
|
#!
|
||||||
|
#! <List>
|
||||||
|
#!
|
||||||
|
#! <Mark><A>files</A></Mark>
|
||||||
|
#! <Item>
|
||||||
|
#! A list of files (given by paths relative to the package directory)
|
||||||
|
#! to be scanned for &AutoDoc; documentation comments.
|
||||||
|
#! Usually it is more convenient to use <A>autodoc.scan_dirs</A>, see below.
|
||||||
|
#! </Item>
|
||||||
|
#!
|
||||||
|
#! <Mark><A>scan_dirs</A></Mark>
|
||||||
|
#! <Item>
|
||||||
|
#! A list of subdirectories of the package directory (given as relative paths)
|
||||||
|
#! which &AutoDoc; then scans for .gi, .gd and .g files; all of these files
|
||||||
|
#! are then scanned for &AutoDoc; documentation comments.
|
||||||
|
#! <Br/>
|
||||||
|
#! <E>Default value: <C>[ "gap", "lib", "examples", "examples/doc" ]</C>.</E>
|
||||||
|
#! </Item>
|
||||||
|
#!
|
||||||
|
#! <Mark><A>level</A></Mark>
|
||||||
|
#! <Item>
|
||||||
|
#! This defines the level of the created documentation. The default value is 0.
|
||||||
|
#! When parts of the manual are declared with a higher value
|
||||||
|
#! they will not be printed into the manual.
|
||||||
|
#! </Item>
|
||||||
|
#!
|
||||||
|
#### TODO: Document section_intros later on.
|
||||||
|
#### However, note that thanks to the new AutoDoc comment syntax, the only remaining
|
||||||
|
#### use for this seems to be the ability to specify the order of chapters and
|
||||||
|
#### sections.
|
||||||
|
#### <Mark><A>section_intros</A></Mark>
|
||||||
|
#### <Item>
|
||||||
|
#### TODO.
|
||||||
|
#### </Item>
|
||||||
|
#!
|
||||||
|
#! </List>
|
||||||
|
#! </Item>
|
||||||
|
#!
|
||||||
|
#!
|
||||||
|
#! <Mark><A>gapdoc</A></Mark>
|
||||||
|
#! <Item>
|
||||||
|
#! This controls whether and how to invoke &GAPDoc; to create HTML, PDF and text
|
||||||
|
#! files from your various XML files.
|
||||||
|
#! <P/>
|
||||||
|
#! The value should be either <K>true</K>, <K>false</K> or a
|
||||||
|
#! record. If it is a record or <K>true</K> (the latter is
|
||||||
|
#! equivalent to specifying an empty record), then this feature is
|
||||||
|
#! enabled. It is also enabled if <A>opt.gapdoc</A> is missing.
|
||||||
|
#! In all other cases (in particular if <A>opt.gapdoc</A> is
|
||||||
|
#! <K>false</K>), this feature is disabled.
|
||||||
|
#! <P/>
|
||||||
|
#!
|
||||||
|
#! If <A>opt.gapdoc</A> is a record, it may contain the following entries.
|
||||||
|
#!
|
||||||
|
#! <List>
|
||||||
|
#!
|
||||||
|
#!
|
||||||
|
#### Note: 'main' is strictly speaking also used for the scaffold.
|
||||||
|
#### However, if one uses the scaffolding mechanism, then it is not
|
||||||
|
#### really necessary to specify a custom name for the main XML file.
|
||||||
|
#### Thus, the purpose of this parameter is to cater for packages
|
||||||
|
#### that have existing documentation using a different XML name,
|
||||||
|
#### and which do not wish to use scaffolding.
|
||||||
|
####
|
||||||
|
#### This explain why we only allow specifying gapdoc.main.
|
||||||
|
#### The scaffolding code will still honor it, though, just in case.
|
||||||
|
#! <Mark><A>main</A></Mark>
|
||||||
|
#! <Item>
|
||||||
|
#! The name of the main XML file of the package manual.
|
||||||
|
#! This exists primarily to support packages with existing manual
|
||||||
|
#! which use a filename here which differs from the default.
|
||||||
|
#! In particular, specifying this is unnecessary when using scaffolding.
|
||||||
|
#! <Br/>
|
||||||
|
#! <E>Default value: <C>PACKAGENAME.xml</C></E>.
|
||||||
|
#! </Item>
|
||||||
|
#!
|
||||||
|
#! <Mark><A>files</A></Mark>
|
||||||
|
#! <Item>
|
||||||
|
#! A list of files (given by paths relative to the package directory)
|
||||||
|
#! to be scanned for &GAPDoc; documentation comments.
|
||||||
|
#! Usually it is more convenient to use <A>gapdoc.scan_dirs</A>, see below.
|
||||||
|
#! </Item>
|
||||||
|
#!
|
||||||
|
#! <Mark><A>scan_dirs</A></Mark>
|
||||||
|
#! <Item>
|
||||||
|
#! A list of subdirectories of the package directory (given as relative paths)
|
||||||
|
#! which &AutoDoc; then scans for .gi, .gd and .g files; all of these files
|
||||||
|
#! are then scanned for &GAPDoc; documentation comments.
|
||||||
|
#! <Br/>
|
||||||
|
#! <E>Default value: <C>[ "gap", "lib", "examples", "examples/doc" ]</C>.</E>
|
||||||
|
#! </Item>
|
||||||
|
#!
|
||||||
|
#! </List>
|
||||||
|
#! </Item>
|
||||||
|
## This is the maketest part. Still under construction.
|
||||||
|
#! <Mark><A>maketest</A></Mark>
|
||||||
|
#! <Item>
|
||||||
|
#! The maketest item can be true or a record. When it is true,
|
||||||
|
#! a simple maketest.g is created in the main package directory,
|
||||||
|
#! which can be used to test the examples from the manual. As a record,
|
||||||
|
#! the entry can have the following entries itself, to specify some options.
|
||||||
|
#! <List>
|
||||||
|
#! <Mark>filename</Mark>
|
||||||
|
#! <Item>
|
||||||
|
#! Sets the name of the test file.
|
||||||
|
#! </Item>
|
||||||
|
#! <Mark>commands</Mark>
|
||||||
|
#! <Item>
|
||||||
|
#! A list of strings, each one a command, which
|
||||||
|
#! will be executed at the beginning of the test file.
|
||||||
|
#! </Item>
|
||||||
|
#! </List>
|
||||||
|
#! </Item>
|
||||||
|
#!
|
||||||
|
#! </List>
|
||||||
|
#! </Item>
|
||||||
|
#! </List>
|
||||||
|
#!
|
||||||
|
#! @Returns nothing
|
||||||
|
#! @Arguments package_name[, option_record ]
|
||||||
|
#! @ChapterInfo AutoDoc, The AutoDoc() function
|
||||||
|
DeclareGlobalFunction( "AutoDoc" );
|
||||||
|
|
||||||
534
samples/GAP/Magic.gi
Normal file
534
samples/GAP/Magic.gi
Normal file
@@ -0,0 +1,534 @@
|
|||||||
|
#############################################################################
|
||||||
|
##
|
||||||
|
## Magic.gi AutoDoc package
|
||||||
|
##
|
||||||
|
## Copyright 2013, Max Horn, JLU Giessen
|
||||||
|
## Sebastian Gutsche, University of Kaiserslautern
|
||||||
|
##
|
||||||
|
#############################################################################
|
||||||
|
|
||||||
|
# Check if a string has the given suffix or not. Another
|
||||||
|
# name for this would "StringEndsWithOtherString".
|
||||||
|
# For example, AUTODOC_HasSuffix("file.gi", ".gi") returns
|
||||||
|
# true while AUTODOC_HasSuffix("file.txt", ".gi") returns false.
|
||||||
|
BindGlobal( "AUTODOC_HasSuffix",
|
||||||
|
function(str, suffix)
|
||||||
|
local n, m;
|
||||||
|
n := Length(str);
|
||||||
|
m := Length(suffix);
|
||||||
|
return n >= m and str{[n-m+1..n]} = suffix;
|
||||||
|
end );
|
||||||
|
|
||||||
|
# Given a string containing a ".", , return its suffix,
|
||||||
|
# i.e. the bit after the last ".". For example, given "test.txt",
|
||||||
|
# it returns "txt".
|
||||||
|
BindGlobal( "AUTODOC_GetSuffix",
|
||||||
|
function(str)
|
||||||
|
local i;
|
||||||
|
i := Length(str);
|
||||||
|
while i > 0 and str[i] <> '.' do i := i - 1; od;
|
||||||
|
if i < 0 then return ""; fi;
|
||||||
|
return str{[i+1..Length(str)]};
|
||||||
|
end );
|
||||||
|
|
||||||
|
# Check whether the given directory exists, and if not, attempt
|
||||||
|
# to create it.
|
||||||
|
BindGlobal( "AUTODOC_CreateDirIfMissing",
|
||||||
|
function(d)
|
||||||
|
local tmp;
|
||||||
|
if not IsDirectoryPath(d) then
|
||||||
|
tmp := CreateDir(d); # Note: CreateDir is currently undocumented
|
||||||
|
if tmp = fail then
|
||||||
|
Error("Cannot create directory ", d, "\n",
|
||||||
|
"Error message: ", LastSystemError().message, "\n");
|
||||||
|
return false;
|
||||||
|
fi;
|
||||||
|
fi;
|
||||||
|
return true;
|
||||||
|
end );
|
||||||
|
|
||||||
|
|
||||||
|
# Scan the given (by name) subdirs of a package dir for
|
||||||
|
# files with one of the given extensions, and return the corresponding
|
||||||
|
# filenames, as relative paths (relative to the package dir).
|
||||||
|
#
|
||||||
|
# For example, the invocation
|
||||||
|
# AUTODOC_FindMatchingFiles("AutoDoc", [ "gap/" ], [ "gi", "gd" ]);
|
||||||
|
# might return a list looking like
|
||||||
|
# [ "gap/AutoDocMainFunction.gd", "gap/AutoDocMainFunction.gi", ... ]
|
||||||
|
BindGlobal( "AUTODOC_FindMatchingFiles",
|
||||||
|
function (pkg, subdirs, extensions)
|
||||||
|
local d_rel, d, tmp, files, result;
|
||||||
|
|
||||||
|
result := [];
|
||||||
|
|
||||||
|
for d_rel in subdirs do
|
||||||
|
# Get the absolute path to the directory in side the package...
|
||||||
|
d := DirectoriesPackageLibrary( pkg, d_rel );
|
||||||
|
if IsEmpty( d ) then
|
||||||
|
continue;
|
||||||
|
fi;
|
||||||
|
d := d[1];
|
||||||
|
# ... but also keep the relative path (such as "gap")
|
||||||
|
d_rel := Directory( d_rel );
|
||||||
|
|
||||||
|
files := DirectoryContents( d );
|
||||||
|
Sort( files );
|
||||||
|
for tmp in files do
|
||||||
|
if not AUTODOC_GetSuffix( tmp ) in [ "g", "gi", "gd", "autodoc" ] then
|
||||||
|
continue;
|
||||||
|
fi;
|
||||||
|
if not IsReadableFile( Filename( d, tmp ) ) then
|
||||||
|
continue;
|
||||||
|
fi;
|
||||||
|
Add( result, Filename( d_rel, tmp ) );
|
||||||
|
od;
|
||||||
|
od;
|
||||||
|
return result;
|
||||||
|
end );
|
||||||
|
|
||||||
|
|
||||||
|
# AutoDoc(pkg[, opt])
|
||||||
|
#
|
||||||
|
## Make this function callable with the package_name AutoDocWorksheet.
|
||||||
|
## Which will then create a worksheet!
|
||||||
|
InstallGlobalFunction( AutoDoc,
|
||||||
|
function( arg )
|
||||||
|
local pkg, package_info, opt, scaffold, gapdoc, maketest,
|
||||||
|
autodoc, pkg_dir, doc_dir, doc_dir_rel, d, tmp,
|
||||||
|
title_page, tree, is_worksheet, position_document_class, i, gapdoc_latex_option_record;
|
||||||
|
|
||||||
|
pkg := arg[1];
|
||||||
|
|
||||||
|
if LowercaseString( pkg ) = "autodocworksheet" then
|
||||||
|
is_worksheet := true;
|
||||||
|
package_info := rec( );
|
||||||
|
pkg_dir := DirectoryCurrent( );
|
||||||
|
else
|
||||||
|
is_worksheet := false;
|
||||||
|
package_info := PackageInfo( pkg )[ 1 ];
|
||||||
|
pkg_dir := DirectoriesPackageLibrary( pkg, "" )[1];
|
||||||
|
fi;
|
||||||
|
|
||||||
|
if Length(arg) >= 2 then
|
||||||
|
opt := arg[2];
|
||||||
|
else
|
||||||
|
opt := rec();
|
||||||
|
fi;
|
||||||
|
|
||||||
|
# Check for certain user supplied options, and if present, add them
|
||||||
|
# to the opt record.
|
||||||
|
tmp := function( key )
|
||||||
|
local val;
|
||||||
|
val := ValueOption( key );
|
||||||
|
if val <> fail then
|
||||||
|
opt.(key) := val;
|
||||||
|
fi;
|
||||||
|
end;
|
||||||
|
|
||||||
|
tmp( "dir" );
|
||||||
|
tmp( "scaffold" );
|
||||||
|
tmp( "autodoc" );
|
||||||
|
tmp( "gapdoc" );
|
||||||
|
tmp( "maketest" );
|
||||||
|
|
||||||
|
#
|
||||||
|
# Setup the output directory
|
||||||
|
#
|
||||||
|
if not IsBound( opt.dir ) then
|
||||||
|
doc_dir := "doc";
|
||||||
|
elif IsString( opt.dir ) or IsDirectory( opt.dir ) then
|
||||||
|
doc_dir := opt.dir;
|
||||||
|
else
|
||||||
|
Error( "opt.dir must be a string containing a path, or a directory object" );
|
||||||
|
fi;
|
||||||
|
|
||||||
|
if IsString( doc_dir ) then
|
||||||
|
# Record the relative version of the path
|
||||||
|
doc_dir_rel := Directory( doc_dir );
|
||||||
|
|
||||||
|
# We intentionally do not use
|
||||||
|
# DirectoriesPackageLibrary( pkg, "doc" )
|
||||||
|
# because it returns an empty list if the subdirectory is missing.
|
||||||
|
# But we want to handle that case by creating the directory.
|
||||||
|
doc_dir := Filename(pkg_dir, doc_dir);
|
||||||
|
doc_dir := Directory(doc_dir);
|
||||||
|
|
||||||
|
else
|
||||||
|
# TODO: doc_dir_rel = ... ?
|
||||||
|
fi;
|
||||||
|
|
||||||
|
# Ensure the output directory exists, create it if necessary
|
||||||
|
AUTODOC_CreateDirIfMissing(Filename(doc_dir, ""));
|
||||||
|
|
||||||
|
# Let the developer know where we are generating the documentation.
|
||||||
|
# This helps diagnose problems where multiple instances of a package
|
||||||
|
# are visible to GAP and the wrong one is used for generating the
|
||||||
|
# documentation.
|
||||||
|
# TODO: Using Info() instead of Print?
|
||||||
|
Print( "Generating documentation in ", doc_dir, "\n" );
|
||||||
|
|
||||||
|
#
|
||||||
|
# Extract scaffolding settings, which can be controlled via
|
||||||
|
# opt.scaffold or package_info.AutoDoc. The former has precedence.
|
||||||
|
#
|
||||||
|
if not IsBound(opt.scaffold) then
|
||||||
|
# Default: enable scaffolding if and only if package_info.AutoDoc is present
|
||||||
|
if IsBound( package_info.AutoDoc ) then
|
||||||
|
scaffold := rec( );
|
||||||
|
fi;
|
||||||
|
elif IsRecord(opt.scaffold) then
|
||||||
|
scaffold := opt.scaffold;
|
||||||
|
elif IsBool(opt.scaffold) then
|
||||||
|
if opt.scaffold = true then
|
||||||
|
scaffold := rec();
|
||||||
|
fi;
|
||||||
|
else
|
||||||
|
Error("opt.scaffold must be a bool or a record");
|
||||||
|
fi;
|
||||||
|
|
||||||
|
# Merge package_info.AutoDoc into scaffold
|
||||||
|
if IsBound(scaffold) and IsBound( package_info.AutoDoc ) then
|
||||||
|
AUTODOC_APPEND_RECORD_WRITEONCE( scaffold, package_info.AutoDoc );
|
||||||
|
fi;
|
||||||
|
|
||||||
|
if IsBound( scaffold ) then
|
||||||
|
AUTODOC_WriteOnce( scaffold, "TitlePage", true );
|
||||||
|
AUTODOC_WriteOnce( scaffold, "MainPage", true );
|
||||||
|
fi;
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Extract AutoDoc settings
|
||||||
|
#
|
||||||
|
if not IsBound(opt.autodoc) and not is_worksheet then
|
||||||
|
# Enable AutoDoc support if the package depends on AutoDoc.
|
||||||
|
tmp := Concatenation( package_info.Dependencies.NeededOtherPackages,
|
||||||
|
package_info.Dependencies.SuggestedOtherPackages );
|
||||||
|
if ForAny( tmp, x -> LowercaseString(x[1]) = "autodoc" ) then
|
||||||
|
autodoc := rec();
|
||||||
|
fi;
|
||||||
|
elif IsRecord(opt.autodoc) then
|
||||||
|
autodoc := opt.autodoc;
|
||||||
|
elif IsBool(opt.autodoc) and opt.autodoc = true then
|
||||||
|
autodoc := rec();
|
||||||
|
fi;
|
||||||
|
|
||||||
|
if IsBound(autodoc) then
|
||||||
|
if not IsBound( autodoc.files ) then
|
||||||
|
autodoc.files := [ ];
|
||||||
|
fi;
|
||||||
|
|
||||||
|
if not IsBound( autodoc.scan_dirs ) and not is_worksheet then
|
||||||
|
autodoc.scan_dirs := [ "gap", "lib", "examples", "examples/doc" ];
|
||||||
|
elif not IsBound( autodoc.scan_dirs ) and is_worksheet then
|
||||||
|
autodoc.scan_dirs := [ ];
|
||||||
|
fi;
|
||||||
|
|
||||||
|
if not IsBound( autodoc.level ) then
|
||||||
|
autodoc.level := 0;
|
||||||
|
fi;
|
||||||
|
|
||||||
|
PushOptions( rec( level_value := autodoc.level ) );
|
||||||
|
|
||||||
|
if not is_worksheet then
|
||||||
|
Append( autodoc.files, AUTODOC_FindMatchingFiles(pkg, autodoc.scan_dirs, [ "g", "gi", "gd" ]) );
|
||||||
|
fi;
|
||||||
|
fi;
|
||||||
|
|
||||||
|
#
|
||||||
|
# Extract GAPDoc settings
|
||||||
|
#
|
||||||
|
if not IsBound( opt.gapdoc ) then
|
||||||
|
# Enable GAPDoc support by default
|
||||||
|
gapdoc := rec();
|
||||||
|
elif IsRecord( opt.gapdoc ) then
|
||||||
|
gapdoc := opt.gapdoc;
|
||||||
|
elif IsBool( opt.gapdoc ) and opt.gapdoc = true then
|
||||||
|
gapdoc := rec();
|
||||||
|
fi;
|
||||||
|
|
||||||
|
#
|
||||||
|
# Extract test settings
|
||||||
|
#
|
||||||
|
|
||||||
|
if IsBound( opt.maketest ) then
|
||||||
|
if IsRecord( opt.maketest ) then
|
||||||
|
maketest := opt.maketest;
|
||||||
|
elif opt.maketest = true then
|
||||||
|
maketest := rec( );
|
||||||
|
fi;
|
||||||
|
fi;
|
||||||
|
|
||||||
|
if IsBound( gapdoc ) then
|
||||||
|
|
||||||
|
if not IsBound( gapdoc.main ) then
|
||||||
|
gapdoc.main := pkg;
|
||||||
|
fi;
|
||||||
|
|
||||||
|
# FIXME: the following may break if a package uses more than one book
|
||||||
|
if IsBound( package_info.PackageDoc ) and IsBound( package_info.PackageDoc[1].BookName ) then
|
||||||
|
gapdoc.bookname := package_info.PackageDoc[1].BookName;
|
||||||
|
elif not is_worksheet then
|
||||||
|
# Default: book name = package name
|
||||||
|
gapdoc.bookname := pkg;
|
||||||
|
|
||||||
|
Print("\n");
|
||||||
|
Print("WARNING: PackageInfo.g is missing a PackageDoc entry!\n");
|
||||||
|
Print("Without this, your package manual will not be recognized by the GAP help system.\n");
|
||||||
|
Print("You can correct this by adding the following to your PackageInfo.g:\n");
|
||||||
|
Print("PackageDoc := rec(\n");
|
||||||
|
Print(" BookName := ~.PackageName,\n");
|
||||||
|
#Print(" BookName := \"", pkg, "\",\n");
|
||||||
|
Print(" ArchiveURLSubset := [\"doc\"],\n");
|
||||||
|
Print(" HTMLStart := \"doc/chap0.html\",\n");
|
||||||
|
Print(" PDFFile := \"doc/manual.pdf\",\n");
|
||||||
|
Print(" SixFile := \"doc/manual.six\",\n");
|
||||||
|
Print(" LongTitle := ~.Subtitle,\n");
|
||||||
|
Print("),\n");
|
||||||
|
Print("\n");
|
||||||
|
fi;
|
||||||
|
|
||||||
|
if not IsBound( gapdoc.files ) then
|
||||||
|
gapdoc.files := [];
|
||||||
|
fi;
|
||||||
|
|
||||||
|
if not IsBound( gapdoc.scan_dirs ) and not is_worksheet then
|
||||||
|
gapdoc.scan_dirs := [ "gap", "lib", "examples", "examples/doc" ];
|
||||||
|
fi;
|
||||||
|
|
||||||
|
if not is_worksheet then
|
||||||
|
Append( gapdoc.files, AUTODOC_FindMatchingFiles(pkg, gapdoc.scan_dirs, [ "g", "gi", "gd" ]) );
|
||||||
|
fi;
|
||||||
|
|
||||||
|
# Attempt to weed out duplicates as they may confuse GAPDoc (this
|
||||||
|
# won't work if there are any non-normalized paths in the list).
|
||||||
|
gapdoc.files := Set( gapdoc.files );
|
||||||
|
|
||||||
|
# Convert the file paths in gapdoc.files, which are relative to
|
||||||
|
# the package directory, to paths which are relative to the doc directory.
|
||||||
|
# For this, we assume that doc_dir_rel is normalized (e.g.
|
||||||
|
# it does not contains '//') and relative.
|
||||||
|
d := Number( Filename( doc_dir_rel, "" ), x -> x = '/' );
|
||||||
|
d := Concatenation( ListWithIdenticalEntries(d, "../") );
|
||||||
|
gapdoc.files := List( gapdoc.files, f -> Concatenation( d, f ) );
|
||||||
|
fi;
|
||||||
|
|
||||||
|
|
||||||
|
# read tree
|
||||||
|
# FIXME: shouldn't tree be declared inside of an 'if IsBound(autodoc)' section?
|
||||||
|
tree := DocumentationTree( );
|
||||||
|
|
||||||
|
if IsBound( autodoc ) then
|
||||||
|
if IsBound( autodoc.section_intros ) then
|
||||||
|
AUTODOC_PROCESS_INTRO_STRINGS( autodoc.section_intros : Tree := tree );
|
||||||
|
fi;
|
||||||
|
|
||||||
|
AutoDocScanFiles( autodoc.files : PackageName := pkg, Tree := tree );
|
||||||
|
fi;
|
||||||
|
|
||||||
|
if is_worksheet then
|
||||||
|
# FIXME: We use scaffold and autodoc here without checking whether
|
||||||
|
# they are bound. Does that mean worksheets always use them?
|
||||||
|
if IsRecord( scaffold.TitlePage ) and IsBound( scaffold.TitlePage.Title ) then
|
||||||
|
pkg := scaffold.TitlePage.Title;
|
||||||
|
|
||||||
|
elif IsBound( tree!.TitlePage.Title ) then
|
||||||
|
pkg := tree!.TitlePage.Title;
|
||||||
|
|
||||||
|
elif IsBound( autodoc.files ) and Length( autodoc.files ) > 0 then
|
||||||
|
pkg := autodoc.files[ 1 ];
|
||||||
|
|
||||||
|
while Position( pkg, '/' ) <> fail do
|
||||||
|
Remove( pkg, 1 );
|
||||||
|
od;
|
||||||
|
|
||||||
|
while Position( pkg, '.' ) <> fail do
|
||||||
|
Remove( pkg, Length( pkg ) );
|
||||||
|
od;
|
||||||
|
|
||||||
|
else
|
||||||
|
Error( "could not figure out a title." );
|
||||||
|
fi;
|
||||||
|
|
||||||
|
if not IsString( pkg ) then
|
||||||
|
pkg := JoinStringsWithSeparator( pkg, " " );
|
||||||
|
fi;
|
||||||
|
|
||||||
|
gapdoc.main := ReplacedString( pkg, " ", "_" );
|
||||||
|
gapdoc.bookname := ReplacedString( pkg, " ", "_" );
|
||||||
|
fi;
|
||||||
|
|
||||||
|
#
|
||||||
|
# Generate scaffold
|
||||||
|
#
|
||||||
|
gapdoc_latex_option_record := rec( );
|
||||||
|
|
||||||
|
if IsBound( scaffold ) then
|
||||||
|
## Syntax is [ "class", [ "options" ] ]
|
||||||
|
if IsBound( scaffold.document_class ) then
|
||||||
|
position_document_class := PositionSublist( GAPDoc2LaTeXProcs.Head, "documentclass" );
|
||||||
|
|
||||||
|
if IsString( scaffold.document_class ) then
|
||||||
|
scaffold.document_class := [ scaffold.document_class ];
|
||||||
|
fi;
|
||||||
|
|
||||||
|
if position_document_class = fail then
|
||||||
|
Error( "something is wrong with the LaTeX header" );
|
||||||
|
fi;
|
||||||
|
|
||||||
|
GAPDoc2LaTeXProcs.Head := Concatenation(
|
||||||
|
GAPDoc2LaTeXProcs.Head{[ 1 .. PositionSublist( GAPDoc2LaTeXProcs.Head, "{", position_document_class ) ]},
|
||||||
|
scaffold.document_class[ 1 ],
|
||||||
|
GAPDoc2LaTeXProcs.Head{[ PositionSublist( GAPDoc2LaTeXProcs.Head, "}", position_document_class ) .. Length( GAPDoc2LaTeXProcs.Head ) ]} );
|
||||||
|
|
||||||
|
if Length( scaffold.document_class ) = 2 then
|
||||||
|
|
||||||
|
GAPDoc2LaTeXProcs.Head := Concatenation(
|
||||||
|
GAPDoc2LaTeXProcs.Head{[ 1 .. PositionSublist( GAPDoc2LaTeXProcs.Head, "[", position_document_class ) ]},
|
||||||
|
scaffold.document_class[ 2 ],
|
||||||
|
GAPDoc2LaTeXProcs.Head{[ PositionSublist( GAPDoc2LaTeXProcs.Head, "]", position_document_class ) .. Length( GAPDoc2LaTeXProcs.Head ) ]} );
|
||||||
|
fi;
|
||||||
|
fi;
|
||||||
|
|
||||||
|
if IsBound( scaffold.latex_header_file ) then
|
||||||
|
GAPDoc2LaTeXProcs.Head := StringFile( scaffold.latex_header_file );
|
||||||
|
fi;
|
||||||
|
|
||||||
|
if IsBound( scaffold.gapdoc_latex_options ) then
|
||||||
|
if IsRecord( scaffold.gapdoc_latex_options ) then
|
||||||
|
for i in RecNames( scaffold.gapdoc_latex_options ) do
|
||||||
|
if not IsString( scaffold.gapdoc_latex_options.( i ) )
|
||||||
|
and IsList( scaffold.gapdoc_latex_options.( i ) )
|
||||||
|
and LowercaseString( scaffold.gapdoc_latex_options.( i )[ 1 ] ) = "file" then
|
||||||
|
scaffold.gapdoc_latex_options.( i ) := StringFile( scaffold.gapdoc_latex_options.( i )[ 2 ] );
|
||||||
|
fi;
|
||||||
|
od;
|
||||||
|
|
||||||
|
gapdoc_latex_option_record := scaffold.gapdoc_latex_options;
|
||||||
|
fi;
|
||||||
|
fi;
|
||||||
|
|
||||||
|
if not IsBound( scaffold.includes ) then
|
||||||
|
scaffold.includes := [ ];
|
||||||
|
fi;
|
||||||
|
|
||||||
|
if IsBound( autodoc ) then
|
||||||
|
# If scaffold.includes is already set, then we add
|
||||||
|
# AutoDocMainFile.xml to it, but *only* if it not already
|
||||||
|
# there. This way, package authors can control where
|
||||||
|
# it is put in their includes list.
|
||||||
|
if not "AutoDocMainFile.xml" in scaffold.includes then
|
||||||
|
Add( scaffold.includes, "AutoDocMainFile.xml" );
|
||||||
|
fi;
|
||||||
|
fi;
|
||||||
|
|
||||||
|
if IsBound( scaffold.bib ) and IsBool( scaffold.bib ) then
|
||||||
|
if scaffold.bib = true then
|
||||||
|
scaffold.bib := Concatenation( pkg, ".bib" );
|
||||||
|
else
|
||||||
|
Unbind( scaffold.bib );
|
||||||
|
fi;
|
||||||
|
elif not IsBound( scaffold.bib ) then
|
||||||
|
# If there is a doc/PKG.bib file, assume that we want to reference it in the scaffold.
|
||||||
|
if IsReadableFile( Filename( doc_dir, Concatenation( pkg, ".bib" ) ) ) then
|
||||||
|
scaffold.bib := Concatenation( pkg, ".bib" );
|
||||||
|
fi;
|
||||||
|
fi;
|
||||||
|
|
||||||
|
AUTODOC_WriteOnce( scaffold, "index", true );
|
||||||
|
|
||||||
|
if IsBound( gapdoc ) then
|
||||||
|
if AUTODOC_GetSuffix( gapdoc.main ) = "xml" then
|
||||||
|
scaffold.main_xml_file := gapdoc.main;
|
||||||
|
else
|
||||||
|
scaffold.main_xml_file := Concatenation( gapdoc.main, ".xml" );
|
||||||
|
fi;
|
||||||
|
fi;
|
||||||
|
|
||||||
|
# TODO: It should be possible to only rebuild the title page. (Perhaps also only the main page? but this is less important)
|
||||||
|
if IsBound( scaffold.TitlePage ) then
|
||||||
|
if IsRecord( scaffold.TitlePage ) then
|
||||||
|
title_page := scaffold.TitlePage;
|
||||||
|
else
|
||||||
|
title_page := rec( );
|
||||||
|
fi;
|
||||||
|
|
||||||
|
AUTODOC_WriteOnce( title_page, "dir", doc_dir );
|
||||||
|
AUTODOC_APPEND_RECORD_WRITEONCE( title_page, tree!.TitlePage );
|
||||||
|
|
||||||
|
if not is_worksheet then
|
||||||
|
AUTODOC_APPEND_RECORD_WRITEONCE( title_page, ExtractTitleInfoFromPackageInfo( pkg ) );
|
||||||
|
fi;
|
||||||
|
|
||||||
|
CreateTitlePage( title_page );
|
||||||
|
fi;
|
||||||
|
|
||||||
|
if IsBound( scaffold.MainPage ) and scaffold.MainPage <> false then
|
||||||
|
scaffold.dir := doc_dir;
|
||||||
|
scaffold.book_name := pkg;
|
||||||
|
CreateMainPage( scaffold );
|
||||||
|
fi;
|
||||||
|
fi;
|
||||||
|
|
||||||
|
#
|
||||||
|
# Run AutoDoc
|
||||||
|
#
|
||||||
|
if IsBound( autodoc ) then
|
||||||
|
WriteDocumentation( tree, doc_dir );
|
||||||
|
fi;
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Run GAPDoc
|
||||||
|
#
|
||||||
|
if IsBound( gapdoc ) then
|
||||||
|
|
||||||
|
# Ask GAPDoc to use UTF-8 as input encoding for LaTeX, as the XML files
|
||||||
|
# of the documentation are also in UTF-8 encoding, and may contain characters
|
||||||
|
# not contained in the default Latin 1 encoding.
|
||||||
|
SetGapDocLaTeXOptions( "utf8", gapdoc_latex_option_record );
|
||||||
|
|
||||||
|
MakeGAPDocDoc( doc_dir, gapdoc.main, gapdoc.files, gapdoc.bookname, "MathJax" );
|
||||||
|
|
||||||
|
CopyHTMLStyleFiles( Filename( doc_dir, "" ) );
|
||||||
|
|
||||||
|
# The following (undocumented) API is there for compatibility
|
||||||
|
# with old-style gapmacro.tex based package manuals. It
|
||||||
|
# produces a manual.lab file which those packages can use if
|
||||||
|
# they wish to link to things in the manual we are currently
|
||||||
|
# generating. This can probably be removed eventually, but for
|
||||||
|
# now, doing it does not hurt.
|
||||||
|
|
||||||
|
# FIXME: It seems that this command does not work if pdflatex
|
||||||
|
# is not present. Maybe we should remove it.
|
||||||
|
|
||||||
|
if not is_worksheet then
|
||||||
|
GAPDocManualLab( pkg );
|
||||||
|
fi;
|
||||||
|
|
||||||
|
fi;
|
||||||
|
|
||||||
|
if IsBound( maketest ) then
|
||||||
|
|
||||||
|
AUTODOC_WriteOnce( maketest, "filename", "maketest.g" );
|
||||||
|
AUTODOC_WriteOnce( maketest, "folder", pkg_dir );
|
||||||
|
AUTODOC_WriteOnce( maketest, "scan_dir", doc_dir );
|
||||||
|
AUTODOC_WriteOnce( maketest, "files_to_scan", gapdoc.files );
|
||||||
|
|
||||||
|
if IsString( maketest.folder ) then
|
||||||
|
maketest.folder := Directory( maketest.folder );
|
||||||
|
fi;
|
||||||
|
|
||||||
|
if IsString( maketest.scan_dir ) then
|
||||||
|
maketest.scan_dir := Directory( maketest.scan_dir );
|
||||||
|
fi;
|
||||||
|
|
||||||
|
AUTODOC_WriteOnce( maketest, "commands", [ ] );
|
||||||
|
AUTODOC_WriteOnce( maketest, "book_name", gapdoc.main );
|
||||||
|
|
||||||
|
CreateMakeTest( maketest );
|
||||||
|
fi;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
end );
|
||||||
115
samples/GAP/PackageInfo.g
Normal file
115
samples/GAP/PackageInfo.g
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
#############################################################################
|
||||||
|
##
|
||||||
|
## PackageInfo.g for the package `cvec' Max Neunhoeffer
|
||||||
|
##
|
||||||
|
## (created from Frank Lübeck's PackageInfo.g template file)
|
||||||
|
##
|
||||||
|
|
||||||
|
SetPackageInfo( rec(
|
||||||
|
|
||||||
|
PackageName := "cvec",
|
||||||
|
Subtitle := "Compact vectors over finite fields",
|
||||||
|
Version := "2.5.1",
|
||||||
|
Date := "04/04/2014", # dd/mm/yyyy format
|
||||||
|
|
||||||
|
## Information about authors and maintainers.
|
||||||
|
Persons := [
|
||||||
|
rec(
|
||||||
|
LastName := "Neunhoeffer",
|
||||||
|
FirstNames := "Max",
|
||||||
|
IsAuthor := true,
|
||||||
|
IsMaintainer := false,
|
||||||
|
Email := "neunhoef@mcs.st-and.ac.uk",
|
||||||
|
WWWHome := "http://www-groups.mcs.st-and.ac.uk/~neunhoef/",
|
||||||
|
PostalAddress := Concatenation( [
|
||||||
|
"School of Mathematics and Statistics\n",
|
||||||
|
"University of St Andrews\n",
|
||||||
|
"Mathematical Institute\n",
|
||||||
|
"North Haugh\n",
|
||||||
|
"St Andrews, Fife KY16 9SS\n",
|
||||||
|
"Scotland, UK" ] ),
|
||||||
|
Place := "St Andrews",
|
||||||
|
Institution := "University of St Andrews"
|
||||||
|
),
|
||||||
|
],
|
||||||
|
|
||||||
|
## Status information. Currently the following cases are recognized:
|
||||||
|
## "accepted" for successfully refereed packages
|
||||||
|
## "deposited" for packages for which the GAP developers agreed
|
||||||
|
## to distribute them with the core GAP system
|
||||||
|
## "dev" for development versions of packages
|
||||||
|
## "other" for all other packages
|
||||||
|
##
|
||||||
|
# Status := "accepted",
|
||||||
|
Status := "deposited",
|
||||||
|
|
||||||
|
## You must provide the next two entries if and only if the status is
|
||||||
|
## "accepted" because is was successfully refereed:
|
||||||
|
# format: 'name (place)'
|
||||||
|
# CommunicatedBy := "Mike Atkinson (St. Andrews)",
|
||||||
|
#CommunicatedBy := "",
|
||||||
|
# format: mm/yyyy
|
||||||
|
# AcceptDate := "08/1999",
|
||||||
|
#AcceptDate := "",
|
||||||
|
|
||||||
|
PackageWWWHome := "http://neunhoef.github.io/cvec/",
|
||||||
|
README_URL := Concatenation(~.PackageWWWHome, "README"),
|
||||||
|
PackageInfoURL := Concatenation(~.PackageWWWHome, "PackageInfo.g"),
|
||||||
|
ArchiveURL := Concatenation("https://github.com/neunhoef/cvec/",
|
||||||
|
"releases/download/v", ~.Version,
|
||||||
|
"/cvec-", ~.Version),
|
||||||
|
ArchiveFormats := ".tar.gz .tar.bz2",
|
||||||
|
|
||||||
|
## Here you must provide a short abstract explaining the package content
|
||||||
|
## in HTML format (used on the package overview Web page) and an URL
|
||||||
|
## for a Webpage with more detailed information about the package
|
||||||
|
## (not more than a few lines, less is ok):
|
||||||
|
## Please, use '<span class="pkgname">GAP</span>' and
|
||||||
|
## '<span class="pkgname">MyPKG</span>' for specifing package names.
|
||||||
|
##
|
||||||
|
AbstractHTML :=
|
||||||
|
"This package provides an implementation of compact vectors over finite\
|
||||||
|
fields. Contrary to earlier implementations no table lookups are used\
|
||||||
|
but only word-based processor arithmetic. This allows for bigger finite\
|
||||||
|
fields and higher speed.",
|
||||||
|
|
||||||
|
PackageDoc := rec(
|
||||||
|
BookName := "cvec",
|
||||||
|
ArchiveURLSubset := ["doc"],
|
||||||
|
HTMLStart := "doc/chap0.html",
|
||||||
|
PDFFile := "doc/manual.pdf",
|
||||||
|
SixFile := "doc/manual.six",
|
||||||
|
LongTitle := "Compact vectors over finite fields",
|
||||||
|
),
|
||||||
|
|
||||||
|
Dependencies := rec(
|
||||||
|
GAP := ">=4.5.5",
|
||||||
|
NeededOtherPackages := [
|
||||||
|
["GAPDoc", ">= 1.2"],
|
||||||
|
["IO", ">= 4.1"],
|
||||||
|
["orb", ">= 4.2"],
|
||||||
|
],
|
||||||
|
SuggestedOtherPackages := [],
|
||||||
|
ExternalConditions := []
|
||||||
|
),
|
||||||
|
|
||||||
|
AvailabilityTest := function()
|
||||||
|
if not "cvec" in SHOW_STAT() and
|
||||||
|
Filename(DirectoriesPackagePrograms("cvec"), "cvec.so") = fail then
|
||||||
|
#Info(InfoWarning, 1, "cvec: kernel cvec functions not available.");
|
||||||
|
return fail;
|
||||||
|
fi;
|
||||||
|
return true;
|
||||||
|
end,
|
||||||
|
|
||||||
|
## *Optional*, but recommended: path relative to package root to a file which
|
||||||
|
## contains as many tests of the package functionality as sensible.
|
||||||
|
#TestFile := "tst/testall.g",
|
||||||
|
|
||||||
|
## *Optional*: Here you can list some keyword related to the topic
|
||||||
|
## of the package.
|
||||||
|
Keywords := []
|
||||||
|
|
||||||
|
));
|
||||||
|
|
||||||
|
|
||||||
23
samples/GAP/example.gd
Normal file
23
samples/GAP/example.gd
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
#############################################################################
|
||||||
|
##
|
||||||
|
#W example.gd
|
||||||
|
##
|
||||||
|
## This file contains a sample of a GAP declaration file.
|
||||||
|
##
|
||||||
|
DeclareProperty( "SomeProperty", IsLeftModule );
|
||||||
|
DeclareGlobalFunction( "SomeGlobalFunction" );
|
||||||
|
|
||||||
|
|
||||||
|
#############################################################################
|
||||||
|
##
|
||||||
|
#C IsQuuxFrobnicator(<R>)
|
||||||
|
##
|
||||||
|
## <ManSection>
|
||||||
|
## <Filt Name="IsQuuxFrobnicator" Arg='R' Type='Category'/>
|
||||||
|
##
|
||||||
|
## <Description>
|
||||||
|
## Tests whether R is a quux frobnicator.
|
||||||
|
## </Description>
|
||||||
|
## </ManSection>
|
||||||
|
##
|
||||||
|
DeclareSynonym( "IsQuuxFrobnicator", IsField and IsGroup );
|
||||||
64
samples/GAP/example.gi
Normal file
64
samples/GAP/example.gi
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
#############################################################################
|
||||||
|
##
|
||||||
|
#W example.gd
|
||||||
|
##
|
||||||
|
## This file contains a sample of a GAP implementation file.
|
||||||
|
##
|
||||||
|
|
||||||
|
|
||||||
|
#############################################################################
|
||||||
|
##
|
||||||
|
#M SomeOperation( <val> )
|
||||||
|
##
|
||||||
|
## performs some operation on <val>
|
||||||
|
##
|
||||||
|
InstallMethod( SomeProperty,
|
||||||
|
"for left modules",
|
||||||
|
[ IsLeftModule ], 0,
|
||||||
|
function( M )
|
||||||
|
if IsFreeLeftModule( M ) and not IsTrivial( M ) then
|
||||||
|
return true;
|
||||||
|
fi;
|
||||||
|
TryNextMethod();
|
||||||
|
end );
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#############################################################################
|
||||||
|
##
|
||||||
|
#F SomeGlobalFunction( )
|
||||||
|
##
|
||||||
|
## A global variadic funfion.
|
||||||
|
##
|
||||||
|
InstallGlobalFunction( SomeGlobalFunction, function( arg )
|
||||||
|
if Length( arg ) = 3 then
|
||||||
|
return arg[1] + arg[2] * arg[3];
|
||||||
|
elif Length( arg ) = 2 then
|
||||||
|
return arg[1] - arg[2]
|
||||||
|
else
|
||||||
|
Error( "usage: SomeGlobalFunction( <x>, <y>[, <z>] )" );
|
||||||
|
fi;
|
||||||
|
end );
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# A plain function.
|
||||||
|
#
|
||||||
|
SomeFunc := function(x, y)
|
||||||
|
local z, func, tmp, j;
|
||||||
|
z := x * 1.0;
|
||||||
|
y := 17^17 - y;
|
||||||
|
func := a -> a mod 5;
|
||||||
|
tmp := List( [1..50], func );
|
||||||
|
while y > 0 do
|
||||||
|
for j in tmp do
|
||||||
|
Print(j, "\n");
|
||||||
|
od;
|
||||||
|
repeat
|
||||||
|
y := y - 1;
|
||||||
|
until 0 < 1;
|
||||||
|
y := y -1;
|
||||||
|
od;
|
||||||
|
return z;
|
||||||
|
end;
|
||||||
|
|
||||||
822
samples/GAP/vspc.gd
Normal file
822
samples/GAP/vspc.gd
Normal file
@@ -0,0 +1,822 @@
|
|||||||
|
#############################################################################
|
||||||
|
##
|
||||||
|
#W vspc.gd GAP library Thomas Breuer
|
||||||
|
##
|
||||||
|
##
|
||||||
|
#Y Copyright (C) 1997, Lehrstuhl D für Mathematik, RWTH Aachen, Germany
|
||||||
|
#Y (C) 1998 School Math and Comp. Sci., University of St Andrews, Scotland
|
||||||
|
#Y Copyright (C) 2002 The GAP Group
|
||||||
|
##
|
||||||
|
## This file declares the operations for vector spaces.
|
||||||
|
##
|
||||||
|
## The operations for bases of free left modules can be found in the file
|
||||||
|
## <F>lib/basis.gd<F>.
|
||||||
|
##
|
||||||
|
|
||||||
|
|
||||||
|
#############################################################################
|
||||||
|
##
|
||||||
|
#C IsLeftOperatorRing(<R>)
|
||||||
|
##
|
||||||
|
## <ManSection>
|
||||||
|
## <Filt Name="IsLeftOperatorRing" Arg='R' Type='Category'/>
|
||||||
|
##
|
||||||
|
## <Description>
|
||||||
|
## </Description>
|
||||||
|
## </ManSection>
|
||||||
|
##
|
||||||
|
DeclareSynonym( "IsLeftOperatorRing",
|
||||||
|
IsLeftOperatorAdditiveGroup and IsRing and IsAssociativeLOpDProd );
|
||||||
|
#T really?
|
||||||
|
|
||||||
|
|
||||||
|
#############################################################################
|
||||||
|
##
|
||||||
|
#C IsLeftOperatorRingWithOne(<R>)
|
||||||
|
##
|
||||||
|
## <ManSection>
|
||||||
|
## <Filt Name="IsLeftOperatorRingWithOne" Arg='R' Type='Category'/>
|
||||||
|
##
|
||||||
|
## <Description>
|
||||||
|
## </Description>
|
||||||
|
## </ManSection>
|
||||||
|
##
|
||||||
|
DeclareSynonym( "IsLeftOperatorRingWithOne",
|
||||||
|
IsLeftOperatorAdditiveGroup and IsRingWithOne
|
||||||
|
and IsAssociativeLOpDProd );
|
||||||
|
#T really?
|
||||||
|
|
||||||
|
|
||||||
|
#############################################################################
|
||||||
|
##
|
||||||
|
#C IsLeftVectorSpace( <V> )
|
||||||
|
#C IsVectorSpace( <V> )
|
||||||
|
##
|
||||||
|
## <#GAPDoc Label="IsLeftVectorSpace">
|
||||||
|
## <ManSection>
|
||||||
|
## <Filt Name="IsLeftVectorSpace" Arg='V' Type='Category'/>
|
||||||
|
## <Filt Name="IsVectorSpace" Arg='V' Type='Category'/>
|
||||||
|
##
|
||||||
|
## <Description>
|
||||||
|
## A <E>vector space</E> in &GAP; is a free left module
|
||||||
|
## (see <Ref Func="IsFreeLeftModule"/>) over a division ring
|
||||||
|
## (see Chapter <Ref Chap="Fields and Division Rings"/>).
|
||||||
|
## <P/>
|
||||||
|
## Whenever we talk about an <M>F</M>-vector space <A>V</A> then <A>V</A> is
|
||||||
|
## an additive group (see <Ref Func="IsAdditiveGroup"/>) on which the
|
||||||
|
## division ring <M>F</M> acts via multiplication from the left such that
|
||||||
|
## this action and the addition in <A>V</A> are left and right distributive.
|
||||||
|
## The division ring <M>F</M> can be accessed as value of the attribute
|
||||||
|
## <Ref Func="LeftActingDomain"/>.
|
||||||
|
## <P/>
|
||||||
|
## Vector spaces in &GAP; are always <E>left</E> vector spaces,
|
||||||
|
## <Ref Filt="IsLeftVectorSpace"/> and <Ref Filt="IsVectorSpace"/> are
|
||||||
|
## synonyms.
|
||||||
|
## </Description>
|
||||||
|
## </ManSection>
|
||||||
|
## <#/GAPDoc>
|
||||||
|
##
|
||||||
|
DeclareSynonym( "IsLeftVectorSpace",
|
||||||
|
IsLeftModule and IsLeftActedOnByDivisionRing );
|
||||||
|
|
||||||
|
DeclareSynonym( "IsVectorSpace", IsLeftVectorSpace );
|
||||||
|
|
||||||
|
InstallTrueMethod( IsFreeLeftModule,
|
||||||
|
IsLeftModule and IsLeftActedOnByDivisionRing );
|
||||||
|
|
||||||
|
|
||||||
|
#############################################################################
|
||||||
|
##
|
||||||
|
#F IsGaussianSpace( <V> )
|
||||||
|
##
|
||||||
|
## <#GAPDoc Label="IsGaussianSpace">
|
||||||
|
## <ManSection>
|
||||||
|
## <Func Name="IsGaussianSpace" Arg='V'/>
|
||||||
|
##
|
||||||
|
## <Description>
|
||||||
|
## The filter <Ref Filt="IsGaussianSpace"/> (see <Ref Sect="Filters"/>)
|
||||||
|
## for the row space (see <Ref Func="IsRowSpace"/>)
|
||||||
|
## or matrix space (see <Ref Func="IsMatrixSpace"/>) <A>V</A>
|
||||||
|
## over the field <M>F</M>, say,
|
||||||
|
## indicates that the entries of all row vectors or matrices in <A>V</A>,
|
||||||
|
## respectively, are all contained in <M>F</M>.
|
||||||
|
## In this case, <A>V</A> is called a <E>Gaussian</E> vector space.
|
||||||
|
## Bases for Gaussian spaces can be computed using Gaussian elimination for
|
||||||
|
## a given list of vector space generators.
|
||||||
|
## <Example><![CDATA[
|
||||||
|
## gap> mats:= [ [[1,1],[2,2]], [[3,4],[0,1]] ];;
|
||||||
|
## gap> V:= VectorSpace( Rationals, mats );;
|
||||||
|
## gap> IsGaussianSpace( V );
|
||||||
|
## true
|
||||||
|
## gap> mats[1][1][1]:= E(4);; # an element in an extension field
|
||||||
|
## gap> V:= VectorSpace( Rationals, mats );;
|
||||||
|
## gap> IsGaussianSpace( V );
|
||||||
|
## false
|
||||||
|
## gap> V:= VectorSpace( Field( Rationals, [ E(4) ] ), mats );;
|
||||||
|
## gap> IsGaussianSpace( V );
|
||||||
|
## true
|
||||||
|
## ]]></Example>
|
||||||
|
## </Description>
|
||||||
|
## </ManSection>
|
||||||
|
## <#/GAPDoc>
|
||||||
|
##
|
||||||
|
DeclareFilter( "IsGaussianSpace", IsVectorSpace );
|
||||||
|
|
||||||
|
InstallTrueMethod( IsGaussianSpace,
|
||||||
|
IsVectorSpace and IsFullMatrixModule );
|
||||||
|
|
||||||
|
InstallTrueMethod( IsGaussianSpace,
|
||||||
|
IsVectorSpace and IsFullRowModule );
|
||||||
|
|
||||||
|
|
||||||
|
#############################################################################
|
||||||
|
##
|
||||||
|
#C IsDivisionRing( <D> )
|
||||||
|
##
|
||||||
|
## <#GAPDoc Label="IsDivisionRing">
|
||||||
|
## <ManSection>
|
||||||
|
## <Filt Name="IsDivisionRing" Arg='D' Type='Category'/>
|
||||||
|
##
|
||||||
|
## <Description>
|
||||||
|
## A <E>division ring</E> in &GAP; is a nontrivial associative algebra
|
||||||
|
## <A>D</A> with a multiplicative inverse for each nonzero element.
|
||||||
|
## In &GAP; every division ring is a vector space over a division ring
|
||||||
|
## (possibly over itself).
|
||||||
|
## Note that being a division ring is thus not a property that a ring can
|
||||||
|
## get, because a ring is usually not represented as a vector space.
|
||||||
|
## <P/>
|
||||||
|
## The field of coefficients is stored as the value of the attribute
|
||||||
|
## <Ref Func="LeftActingDomain"/> of <A>D</A>.
|
||||||
|
## </Description>
|
||||||
|
## </ManSection>
|
||||||
|
## <#/GAPDoc>
|
||||||
|
##
|
||||||
|
DeclareSynonymAttr( "IsDivisionRing",
|
||||||
|
IsMagmaWithInversesIfNonzero
|
||||||
|
and IsLeftOperatorRingWithOne
|
||||||
|
and IsLeftVectorSpace
|
||||||
|
and IsNonTrivial
|
||||||
|
and IsAssociative
|
||||||
|
and IsEuclideanRing );
|
||||||
|
|
||||||
|
|
||||||
|
#############################################################################
|
||||||
|
##
|
||||||
|
#A GeneratorsOfLeftVectorSpace( <V> )
|
||||||
|
#A GeneratorsOfVectorSpace( <V> )
|
||||||
|
##
|
||||||
|
## <#GAPDoc Label="GeneratorsOfLeftVectorSpace">
|
||||||
|
## <ManSection>
|
||||||
|
## <Attr Name="GeneratorsOfLeftVectorSpace" Arg='V'/>
|
||||||
|
## <Attr Name="GeneratorsOfVectorSpace" Arg='V'/>
|
||||||
|
##
|
||||||
|
## <Description>
|
||||||
|
## For an <M>F</M>-vector space <A>V</A>,
|
||||||
|
## <Ref Attr="GeneratorsOfLeftVectorSpace"/> returns a list of vectors in
|
||||||
|
## <A>V</A> that generate <A>V</A> as an <M>F</M>-vector space.
|
||||||
|
## <Example><![CDATA[
|
||||||
|
## gap> GeneratorsOfVectorSpace( FullRowSpace( Rationals, 3 ) );
|
||||||
|
## [ [ 1, 0, 0 ], [ 0, 1, 0 ], [ 0, 0, 1 ] ]
|
||||||
|
## ]]></Example>
|
||||||
|
## </Description>
|
||||||
|
## </ManSection>
|
||||||
|
## <#/GAPDoc>
|
||||||
|
##
|
||||||
|
DeclareSynonymAttr( "GeneratorsOfLeftVectorSpace",
|
||||||
|
GeneratorsOfLeftOperatorAdditiveGroup );
|
||||||
|
|
||||||
|
DeclareSynonymAttr( "GeneratorsOfVectorSpace",
|
||||||
|
GeneratorsOfLeftOperatorAdditiveGroup );
|
||||||
|
|
||||||
|
|
||||||
|
#############################################################################
|
||||||
|
##
|
||||||
|
#A CanonicalBasis( <V> )
|
||||||
|
##
|
||||||
|
## <#GAPDoc Label="CanonicalBasis">
|
||||||
|
## <ManSection>
|
||||||
|
## <Attr Name="CanonicalBasis" Arg='V'/>
|
||||||
|
##
|
||||||
|
## <Description>
|
||||||
|
## If the vector space <A>V</A> supports a <E>canonical basis</E> then
|
||||||
|
## <Ref Attr="CanonicalBasis"/> returns this basis,
|
||||||
|
## otherwise <K>fail</K> is returned.
|
||||||
|
## <P/>
|
||||||
|
## The defining property of a canonical basis is that its vectors are
|
||||||
|
## uniquely determined by the vector space.
|
||||||
|
## If canonical bases exist for two vector spaces over the same left acting
|
||||||
|
## domain (see <Ref Func="LeftActingDomain"/>) then the equality of
|
||||||
|
## these vector spaces can be decided by comparing the canonical bases.
|
||||||
|
## <P/>
|
||||||
|
## The exact meaning of a canonical basis depends on the type of <A>V</A>.
|
||||||
|
## Canonical bases are defined for example for Gaussian row and matrix
|
||||||
|
## spaces (see <Ref Sect="Row and Matrix Spaces"/>).
|
||||||
|
## <P/>
|
||||||
|
## If one designs a new kind of vector spaces
|
||||||
|
## (see <Ref Sect="How to Implement New Kinds of Vector Spaces"/>) and
|
||||||
|
## defines a canonical basis for these spaces then the
|
||||||
|
## <Ref Attr="CanonicalBasis"/> method one installs
|
||||||
|
## (see <Ref Func="InstallMethod"/>)
|
||||||
|
## must <E>not</E> call <Ref Func="Basis"/>.
|
||||||
|
## On the other hand, one probably should install a <Ref Func="Basis"/>
|
||||||
|
## method that simply calls <Ref Attr="CanonicalBasis"/>,
|
||||||
|
## the value of the method
|
||||||
|
## (see <Ref Sect="Method Installation"/> and
|
||||||
|
## <Ref Sect="Applicable Methods and Method Selection"/>)
|
||||||
|
## being <C>CANONICAL_BASIS_FLAGS</C>.
|
||||||
|
## <Example><![CDATA[
|
||||||
|
## gap> vecs:= [ [ 1, 2, 3 ], [ 1, 1, 1 ], [ 1, 1, 1 ] ];;
|
||||||
|
## gap> V:= VectorSpace( Rationals, vecs );;
|
||||||
|
## gap> B:= CanonicalBasis( V );
|
||||||
|
## CanonicalBasis( <vector space over Rationals, with 3 generators> )
|
||||||
|
## gap> BasisVectors( B );
|
||||||
|
## [ [ 1, 0, -1 ], [ 0, 1, 2 ] ]
|
||||||
|
## ]]></Example>
|
||||||
|
## </Description>
|
||||||
|
## </ManSection>
|
||||||
|
## <#/GAPDoc>
|
||||||
|
##
|
||||||
|
DeclareAttribute( "CanonicalBasis", IsFreeLeftModule );
|
||||||
|
|
||||||
|
|
||||||
|
#############################################################################
|
||||||
|
##
|
||||||
|
#F IsRowSpace( <V> )
|
||||||
|
##
|
||||||
|
## <#GAPDoc Label="IsRowSpace">
|
||||||
|
## <ManSection>
|
||||||
|
## <Func Name="IsRowSpace" Arg='V'/>
|
||||||
|
##
|
||||||
|
## <Description>
|
||||||
|
## A <E>row space</E> in &GAP; is a vector space that consists of
|
||||||
|
## row vectors (see Chapter <Ref Chap="Row Vectors"/>).
|
||||||
|
## </Description>
|
||||||
|
## </ManSection>
|
||||||
|
## <#/GAPDoc>
|
||||||
|
##
|
||||||
|
DeclareSynonym( "IsRowSpace", IsRowModule and IsVectorSpace );
|
||||||
|
|
||||||
|
|
||||||
|
#############################################################################
|
||||||
|
##
|
||||||
|
#F IsGaussianRowSpace( <V> )
|
||||||
|
##
|
||||||
|
## <ManSection>
|
||||||
|
## <Func Name="IsGaussianRowSpace" Arg='V'/>
|
||||||
|
##
|
||||||
|
## <Description>
|
||||||
|
## A row space is <E>Gaussian</E> if the left acting domain contains all
|
||||||
|
## scalars that occur in the vectors.
|
||||||
|
## Thus one can use Gaussian elimination in the calculations.
|
||||||
|
## <P/>
|
||||||
|
## (Otherwise the space is non-Gaussian.
|
||||||
|
## We will need a flag for this to write down methods that delegate from
|
||||||
|
## non-Gaussian spaces to Gaussian ones.)
|
||||||
|
## <!-- reformulate this when it becomes documented -->
|
||||||
|
## </Description>
|
||||||
|
## </ManSection>
|
||||||
|
##
|
||||||
|
DeclareSynonym( "IsGaussianRowSpace", IsGaussianSpace and IsRowSpace );
|
||||||
|
|
||||||
|
|
||||||
|
#############################################################################
|
||||||
|
##
|
||||||
|
#F IsNonGaussianRowSpace( <V> )
|
||||||
|
##
|
||||||
|
## <ManSection>
|
||||||
|
## <Func Name="IsNonGaussianRowSpace" Arg='V'/>
|
||||||
|
##
|
||||||
|
## <Description>
|
||||||
|
## If an <M>F</M>-vector space <A>V</A> is in the filter
|
||||||
|
## <Ref Func="IsNonGaussianRowSpace"/> then this expresses that <A>V</A>
|
||||||
|
## consists of row vectors (see <Ref Func="IsRowVector"/>) such
|
||||||
|
## that not all entries in these row vectors are contained in <M>F</M>
|
||||||
|
## (so Gaussian elimination cannot be used to compute an <M>F</M>-basis
|
||||||
|
## from a list of vector space generators),
|
||||||
|
## and that <A>V</A> is handled via the mechanism of nice bases
|
||||||
|
## (see <Ref ???="..."/>) in the following way.
|
||||||
|
## Let <M>K</M> be the field spanned by the entries of all vectors in
|
||||||
|
## <A>V</A>.
|
||||||
|
## Then the <Ref Attr="NiceFreeLeftModuleInfo"/> value of <A>V</A> is
|
||||||
|
## a basis <M>B</M> of the field extension <M>K / ( K \cap F )</M>,
|
||||||
|
## and the <Ref Func="NiceVector"/> value of <M>v \in <A>V</A></M>
|
||||||
|
## is defined by replacing each entry of <M>v</M> by the list of its
|
||||||
|
## <M>B</M>-coefficients, and then forming the concatenation.
|
||||||
|
## <P/>
|
||||||
|
## So the associated nice vector space is a Gaussian row space
|
||||||
|
## (see <Ref Func="IsGaussianRowSpace"/>).
|
||||||
|
## </Description>
|
||||||
|
## </ManSection>
|
||||||
|
##
|
||||||
|
DeclareHandlingByNiceBasis( "IsNonGaussianRowSpace",
|
||||||
|
"for non-Gaussian row spaces" );
|
||||||
|
|
||||||
|
|
||||||
|
#############################################################################
|
||||||
|
##
|
||||||
|
#F IsMatrixSpace( <V> )
|
||||||
|
##
|
||||||
|
## <#GAPDoc Label="IsMatrixSpace">
|
||||||
|
## <ManSection>
|
||||||
|
## <Func Name="IsMatrixSpace" Arg='V'/>
|
||||||
|
##
|
||||||
|
## <Description>
|
||||||
|
## A <E>matrix space</E> in &GAP; is a vector space that consists of matrices
|
||||||
|
## (see Chapter <Ref Chap="Matrices"/>).
|
||||||
|
## </Description>
|
||||||
|
## </ManSection>
|
||||||
|
## <#/GAPDoc>
|
||||||
|
##
|
||||||
|
DeclareSynonym( "IsMatrixSpace", IsMatrixModule and IsVectorSpace );
|
||||||
|
|
||||||
|
|
||||||
|
#############################################################################
|
||||||
|
##
|
||||||
|
#F IsGaussianMatrixSpace( <V> )
|
||||||
|
##
|
||||||
|
## <ManSection>
|
||||||
|
## <Func Name="IsGaussianMatrixSpace" Arg='V'/>
|
||||||
|
##
|
||||||
|
## <Description>
|
||||||
|
## A matrix space is Gaussian if the left acting domain contains all
|
||||||
|
## scalars that occur in the vectors.
|
||||||
|
## Thus one can use Gaussian elimination in the calculations.
|
||||||
|
## <P/>
|
||||||
|
## (Otherwise the space is non-Gaussian.
|
||||||
|
## We will need a flag for this to write down methods that delegate from
|
||||||
|
## non-Gaussian spaces to Gaussian ones.)
|
||||||
|
## </Description>
|
||||||
|
## </ManSection>
|
||||||
|
##
|
||||||
|
DeclareSynonym( "IsGaussianMatrixSpace", IsGaussianSpace and IsMatrixSpace );
|
||||||
|
|
||||||
|
|
||||||
|
#############################################################################
|
||||||
|
##
|
||||||
|
#F IsNonGaussianMatrixSpace( <V> )
|
||||||
|
##
|
||||||
|
## <ManSection>
|
||||||
|
## <Func Name="IsNonGaussianMatrixSpace" Arg='V'/>
|
||||||
|
##
|
||||||
|
## <Description>
|
||||||
|
## If an <M>F</M>-vector space <A>V</A> is in the filter
|
||||||
|
## <Ref Func="IsNonGaussianMatrixSpace"/>
|
||||||
|
## then this expresses that <A>V</A> consists of matrices
|
||||||
|
## (see <Ref Func="IsMatrix"/>)
|
||||||
|
## such that not all entries in these matrices are contained in <M>F</M>
|
||||||
|
## (so Gaussian elimination cannot be used to compute an <M>F</M>-basis
|
||||||
|
## from a list of vector space generators),
|
||||||
|
## and that <A>V</A> is handled via the mechanism of nice bases
|
||||||
|
## (see <Ref ???="..."/>) in the following way.
|
||||||
|
## Let <M>K</M> be the field spanned by the entries of all vectors in <A>V</A>.
|
||||||
|
## The <Ref Attr="NiceFreeLeftModuleInfo"/> value of <A>V</A> is irrelevant,
|
||||||
|
## and the <Ref Func="NiceVector"/> value of <M>v \in <A>V</A></M>
|
||||||
|
## is defined as the concatenation of the rows of <M>v</M>.
|
||||||
|
## <P/>
|
||||||
|
## So the associated nice vector space is a (not necessarily Gaussian)
|
||||||
|
## row space (see <Ref Func="IsRowSpace"/>).
|
||||||
|
## </Description>
|
||||||
|
## </ManSection>
|
||||||
|
##
|
||||||
|
DeclareHandlingByNiceBasis( "IsNonGaussianMatrixSpace",
|
||||||
|
"for non-Gaussian matrix spaces" );
|
||||||
|
|
||||||
|
|
||||||
|
#############################################################################
|
||||||
|
##
|
||||||
|
#A NormedRowVectors( <V> ) . . . normed vectors in a Gaussian row space <V>
|
||||||
|
##
|
||||||
|
## <#GAPDoc Label="NormedRowVectors">
|
||||||
|
## <ManSection>
|
||||||
|
## <Attr Name="NormedRowVectors" Arg='V'/>
|
||||||
|
##
|
||||||
|
## <Description>
|
||||||
|
## For a finite Gaussian row space <A>V</A>
|
||||||
|
## (see <Ref Func="IsRowSpace"/>, <Ref Func="IsGaussianSpace"/>),
|
||||||
|
## <Ref Attr="NormedRowVectors"/> returns a list of those nonzero
|
||||||
|
## vectors in <A>V</A> that have a one in the first nonzero component.
|
||||||
|
## <P/>
|
||||||
|
## The result list can be used as action domain for the action of a matrix
|
||||||
|
## group via <Ref Func="OnLines"/>, which yields the natural action on
|
||||||
|
## one-dimensional subspaces of <A>V</A>
|
||||||
|
## (see also <Ref Func="Subspaces"/>).
|
||||||
|
## <Example><![CDATA[
|
||||||
|
## gap> vecs:= NormedRowVectors( GF(3)^2 );
|
||||||
|
## [ [ 0*Z(3), Z(3)^0 ], [ Z(3)^0, 0*Z(3) ], [ Z(3)^0, Z(3)^0 ],
|
||||||
|
## [ Z(3)^0, Z(3) ] ]
|
||||||
|
## gap> Action( GL(2,3), vecs, OnLines );
|
||||||
|
## Group([ (3,4), (1,2,4) ])
|
||||||
|
## ]]></Example>
|
||||||
|
## </Description>
|
||||||
|
## </ManSection>
|
||||||
|
## <#/GAPDoc>
|
||||||
|
##
|
||||||
|
DeclareAttribute( "NormedRowVectors", IsGaussianSpace );
|
||||||
|
|
||||||
|
|
||||||
|
#############################################################################
|
||||||
|
##
|
||||||
|
#A TrivialSubspace( <V> )
|
||||||
|
##
|
||||||
|
## <#GAPDoc Label="TrivialSubspace">
|
||||||
|
## <ManSection>
|
||||||
|
## <Attr Name="TrivialSubspace" Arg='V'/>
|
||||||
|
##
|
||||||
|
## <Description>
|
||||||
|
## For a vector space <A>V</A>, <Ref Attr="TrivialSubspace"/> returns the
|
||||||
|
## subspace of <A>V</A> that consists of the zero vector in <A>V</A>.
|
||||||
|
## <Example><![CDATA[
|
||||||
|
## gap> V:= GF(3)^3;;
|
||||||
|
## gap> triv:= TrivialSubspace( V );
|
||||||
|
## <vector space over GF(3), with 0 generators>
|
||||||
|
## gap> AsSet( triv );
|
||||||
|
## [ [ 0*Z(3), 0*Z(3), 0*Z(3) ] ]
|
||||||
|
## ]]></Example>
|
||||||
|
## </Description>
|
||||||
|
## </ManSection>
|
||||||
|
## <#/GAPDoc>
|
||||||
|
##
|
||||||
|
DeclareSynonymAttr( "TrivialSubspace", TrivialSubmodule );
|
||||||
|
|
||||||
|
|
||||||
|
#############################################################################
|
||||||
|
##
|
||||||
|
#F VectorSpace( <F>, <gens>[, <zero>][, "basis"] )
|
||||||
|
##
|
||||||
|
## <#GAPDoc Label="VectorSpace">
|
||||||
|
## <ManSection>
|
||||||
|
## <Func Name="VectorSpace" Arg='F, gens[, zero][, "basis"]'/>
|
||||||
|
##
|
||||||
|
## <Description>
|
||||||
|
## For a field <A>F</A> and a collection <A>gens</A> of vectors,
|
||||||
|
## <Ref Func="VectorSpace"/> returns the <A>F</A>-vector space spanned by
|
||||||
|
## the elements in <A>gens</A>.
|
||||||
|
## <P/>
|
||||||
|
## The optional argument <A>zero</A> can be used to specify the zero element
|
||||||
|
## of the space; <A>zero</A> <E>must</E> be given if <A>gens</A> is empty.
|
||||||
|
## The optional string <C>"basis"</C> indicates that <A>gens</A> is known to
|
||||||
|
## be linearly independent over <A>F</A>, in particular the dimension of the
|
||||||
|
## vector space is immediately set;
|
||||||
|
## note that <Ref Func="Basis"/> need <E>not</E> return the basis formed by
|
||||||
|
## <A>gens</A> if the string <C>"basis"</C> is given as an argument.
|
||||||
|
## <!-- crossref. to <C>FreeLeftModule</C> as soon as the modules chapter
|
||||||
|
## is reliable!-->
|
||||||
|
## <Example><![CDATA[
|
||||||
|
## gap> V:= VectorSpace( Rationals, [ [ 1, 2, 3 ], [ 1, 1, 1 ] ] );
|
||||||
|
## <vector space over Rationals, with 2 generators>
|
||||||
|
## ]]></Example>
|
||||||
|
## </Description>
|
||||||
|
## </ManSection>
|
||||||
|
## <#/GAPDoc>
|
||||||
|
##
|
||||||
|
DeclareGlobalFunction( "VectorSpace" );
|
||||||
|
|
||||||
|
|
||||||
|
#############################################################################
|
||||||
|
##
|
||||||
|
#F Subspace( <V>, <gens>[, "basis"] ) . subspace of <V> generated by <gens>
|
||||||
|
#F SubspaceNC( <V>, <gens>[, "basis"] )
|
||||||
|
##
|
||||||
|
## <#GAPDoc Label="Subspace">
|
||||||
|
## <ManSection>
|
||||||
|
## <Func Name="Subspace" Arg='V, gens[, "basis"]'/>
|
||||||
|
## <Func Name="SubspaceNC" Arg='V, gens[, "basis"]'/>
|
||||||
|
##
|
||||||
|
## <Description>
|
||||||
|
## For an <M>F</M>-vector space <A>V</A> and a list or collection
|
||||||
|
## <A>gens</A> that is a subset of <A>V</A>,
|
||||||
|
## <Ref Func="Subspace"/> returns the <M>F</M>-vector space spanned by
|
||||||
|
## <A>gens</A>; if <A>gens</A> is empty then the trivial subspace
|
||||||
|
## (see <Ref Func="TrivialSubspace"/>) of <A>V</A> is returned.
|
||||||
|
## The parent (see <Ref Sect="Parents"/>) of the returned vector space
|
||||||
|
## is set to <A>V</A>.
|
||||||
|
## <P/>
|
||||||
|
## <Ref Func="SubspaceNC"/> does the same as <Ref Func="Subspace"/>,
|
||||||
|
## except that it omits the check whether <A>gens</A> is a subset of
|
||||||
|
## <A>V</A>.
|
||||||
|
## <P/>
|
||||||
|
## The optional string <A>"basis"</A> indicates that <A>gens</A> is known to
|
||||||
|
## be linearly independent over <M>F</M>.
|
||||||
|
## In this case the dimension of the subspace is immediately set,
|
||||||
|
## and both <Ref Func="Subspace"/> and <Ref Func="SubspaceNC"/> do
|
||||||
|
## <E>not</E> check whether <A>gens</A> really is linearly independent and
|
||||||
|
## whether <A>gens</A> is a subset of <A>V</A>.
|
||||||
|
## <!-- crossref. to <C>Submodule</C> as soon as the modules chapter
|
||||||
|
## is reliable!-->
|
||||||
|
## <Example><![CDATA[
|
||||||
|
## gap> V:= VectorSpace( Rationals, [ [ 1, 2, 3 ], [ 1, 1, 1 ] ] );;
|
||||||
|
## gap> W:= Subspace( V, [ [ 0, 1, 2 ] ] );
|
||||||
|
## <vector space over Rationals, with 1 generators>
|
||||||
|
## ]]></Example>
|
||||||
|
## </Description>
|
||||||
|
## </ManSection>
|
||||||
|
## <#/GAPDoc>
|
||||||
|
##
|
||||||
|
DeclareSynonym( "Subspace", Submodule );
|
||||||
|
|
||||||
|
DeclareSynonym( "SubspaceNC", SubmoduleNC );
|
||||||
|
|
||||||
|
|
||||||
|
#############################################################################
|
||||||
|
##
|
||||||
|
#O AsVectorSpace( <F>, <D> ) . . . . . . . . . view <D> as <F>-vector space
|
||||||
|
##
|
||||||
|
## <#GAPDoc Label="AsVectorSpace">
|
||||||
|
## <ManSection>
|
||||||
|
## <Oper Name="AsVectorSpace" Arg='F, D'/>
|
||||||
|
##
|
||||||
|
## <Description>
|
||||||
|
## Let <A>F</A> be a division ring and <A>D</A> a domain.
|
||||||
|
## If the elements in <A>D</A> form an <A>F</A>-vector space then
|
||||||
|
## <Ref Oper="AsVectorSpace"/> returns this <A>F</A>-vector space,
|
||||||
|
## otherwise <K>fail</K> is returned.
|
||||||
|
## <P/>
|
||||||
|
## <Ref Oper="AsVectorSpace"/> can be used for example to view a given
|
||||||
|
## vector space as a vector space over a smaller or larger division ring.
|
||||||
|
## <Example><![CDATA[
|
||||||
|
## gap> V:= FullRowSpace( GF( 27 ), 3 );
|
||||||
|
## ( GF(3^3)^3 )
|
||||||
|
## gap> Dimension( V ); LeftActingDomain( V );
|
||||||
|
## 3
|
||||||
|
## GF(3^3)
|
||||||
|
## gap> W:= AsVectorSpace( GF( 3 ), V );
|
||||||
|
## <vector space over GF(3), with 9 generators>
|
||||||
|
## gap> Dimension( W ); LeftActingDomain( W );
|
||||||
|
## 9
|
||||||
|
## GF(3)
|
||||||
|
## gap> AsVectorSpace( GF( 9 ), V );
|
||||||
|
## fail
|
||||||
|
## ]]></Example>
|
||||||
|
## </Description>
|
||||||
|
## </ManSection>
|
||||||
|
## <#/GAPDoc>
|
||||||
|
##
|
||||||
|
DeclareSynonym( "AsVectorSpace", AsLeftModule );
|
||||||
|
|
||||||
|
|
||||||
|
#############################################################################
|
||||||
|
##
|
||||||
|
#O AsSubspace( <V>, <U> ) . . . . . . . . . . . view <U> as subspace of <V>
|
||||||
|
##
|
||||||
|
## <#GAPDoc Label="AsSubspace">
|
||||||
|
## <ManSection>
|
||||||
|
## <Oper Name="AsSubspace" Arg='V, U'/>
|
||||||
|
##
|
||||||
|
## <Description>
|
||||||
|
## Let <A>V</A> be an <M>F</M>-vector space, and <A>U</A> a collection.
|
||||||
|
## If <A>U</A> is a subset of <A>V</A> such that the elements of <A>U</A>
|
||||||
|
## form an <M>F</M>-vector space then <Ref Oper="AsSubspace"/> returns this
|
||||||
|
## vector space, with parent set to <A>V</A>
|
||||||
|
## (see <Ref Func="AsVectorSpace"/>).
|
||||||
|
## Otherwise <K>fail</K> is returned.
|
||||||
|
## <Example><![CDATA[
|
||||||
|
## gap> V:= VectorSpace( Rationals, [ [ 1, 2, 3 ], [ 1, 1, 1 ] ] );;
|
||||||
|
## gap> W:= VectorSpace( Rationals, [ [ 1/2, 1/2, 1/2 ] ] );;
|
||||||
|
## gap> U:= AsSubspace( V, W );
|
||||||
|
## <vector space over Rationals, with 1 generators>
|
||||||
|
## gap> Parent( U ) = V;
|
||||||
|
## true
|
||||||
|
## gap> AsSubspace( V, [ [ 1, 1, 1 ] ] );
|
||||||
|
## fail
|
||||||
|
## ]]></Example>
|
||||||
|
## </Description>
|
||||||
|
## </ManSection>
|
||||||
|
## <#/GAPDoc>
|
||||||
|
##
|
||||||
|
DeclareOperation( "AsSubspace", [ IsVectorSpace, IsCollection ] );
|
||||||
|
|
||||||
|
|
||||||
|
#############################################################################
|
||||||
|
##
|
||||||
|
#F Intersection2Spaces( <AsStruct>, <Substruct>, <Struct> )
|
||||||
|
##
|
||||||
|
## <ManSection>
|
||||||
|
## <Func Name="Intersection2Spaces" Arg='AsStruct, Substruct, Struct'/>
|
||||||
|
##
|
||||||
|
## <Description>
|
||||||
|
## is a function that takes two arguments <A>V</A> and <A>W</A> which must
|
||||||
|
## be finite dimensional vector spaces,
|
||||||
|
## and returns the intersection of <A>V</A> and <A>W</A>.
|
||||||
|
## <P/>
|
||||||
|
## If the left acting domains are different then let <M>F</M> be their
|
||||||
|
## intersection.
|
||||||
|
## The intersection of <A>V</A> and <A>W</A> is computed as intersection of
|
||||||
|
## <C><A>AsStruct</A>( <A>F</A>, <A>V</A> )</C> and
|
||||||
|
## <C><A>AsStruct</A>( <A>F</A>, <A>V</A> )</C>.
|
||||||
|
## <P/>
|
||||||
|
## If the left acting domains are equal to <M>F</M> then the intersection of
|
||||||
|
## <A>V</A> and <A>W</A> is returned either as <M>F</M>-<A>Substruct</A>
|
||||||
|
## with the common parent of <A>V</A> and <A>W</A> or as
|
||||||
|
## <M>F</M>-<A>Struct</A>, in both cases with known basis.
|
||||||
|
## <P/>
|
||||||
|
## This function is used to handle the intersections of two vector spaces,
|
||||||
|
## two algebras, two algebras-with-one, two left ideals, two right ideals,
|
||||||
|
## two two-sided ideals.
|
||||||
|
## </Description>
|
||||||
|
## </ManSection>
|
||||||
|
##
|
||||||
|
DeclareGlobalFunction( "Intersection2Spaces" );
|
||||||
|
|
||||||
|
|
||||||
|
#############################################################################
|
||||||
|
##
|
||||||
|
#F FullRowSpace( <F>, <n> )
|
||||||
|
##
|
||||||
|
## <#GAPDoc Label="FullRowSpace">
|
||||||
|
## <ManSection>
|
||||||
|
## <Func Name="FullRowSpace" Arg='F, n'/>
|
||||||
|
## <Meth Name="\^" Arg='F, n' Label="for a field and an integer"/>
|
||||||
|
##
|
||||||
|
## <Description>
|
||||||
|
## For a field <A>F</A> and a nonnegative integer <A>n</A>,
|
||||||
|
## <Ref Func="FullRowSpace"/> returns the <A>F</A>-vector space that
|
||||||
|
## consists of all row vectors (see <Ref Func="IsRowVector"/>) of
|
||||||
|
## length <A>n</A> with entries in <A>F</A>.
|
||||||
|
## <P/>
|
||||||
|
## An alternative to construct this vector space is via
|
||||||
|
## <A>F</A><C>^</C><A>n</A>.
|
||||||
|
## <Example><![CDATA[
|
||||||
|
## gap> FullRowSpace( GF( 9 ), 3 );
|
||||||
|
## ( GF(3^2)^3 )
|
||||||
|
## gap> GF(9)^3; # the same as above
|
||||||
|
## ( GF(3^2)^3 )
|
||||||
|
## ]]></Example>
|
||||||
|
## </Description>
|
||||||
|
## </ManSection>
|
||||||
|
## <#/GAPDoc>
|
||||||
|
##
|
||||||
|
DeclareSynonym( "FullRowSpace", FullRowModule );
|
||||||
|
DeclareSynonym( "RowSpace", FullRowModule );
|
||||||
|
|
||||||
|
|
||||||
|
#############################################################################
|
||||||
|
##
|
||||||
|
#F FullMatrixSpace( <F>, <m>, <n> )
|
||||||
|
##
|
||||||
|
## <#GAPDoc Label="FullMatrixSpace">
|
||||||
|
## <ManSection>
|
||||||
|
## <Func Name="FullMatrixSpace" Arg='F, m, n'/>
|
||||||
|
## <Meth Name="\^" Arg='F, dims'
|
||||||
|
## Label="for a field and a pair of integers"/>
|
||||||
|
##
|
||||||
|
## <Description>
|
||||||
|
## For a field <A>F</A> and two positive integers <A>m</A> and <A>n</A>,
|
||||||
|
## <Ref Func="FullMatrixSpace"/> returns the <A>F</A>-vector space that
|
||||||
|
## consists of all <A>m</A> by <A>n</A> matrices
|
||||||
|
## (see <Ref Func="IsMatrix"/>) with entries in <A>F</A>.
|
||||||
|
## <P/>
|
||||||
|
## If <A>m</A><C> = </C><A>n</A> then the result is in fact an algebra
|
||||||
|
## (see <Ref Func="FullMatrixAlgebra"/>).
|
||||||
|
## <P/>
|
||||||
|
## An alternative to construct this vector space is via
|
||||||
|
## <A>F</A><C>^[</C><A>m</A>,<A>n</A><C>]</C>.
|
||||||
|
## <Example><![CDATA[
|
||||||
|
## gap> FullMatrixSpace( GF(2), 4, 5 );
|
||||||
|
## ( GF(2)^[ 4, 5 ] )
|
||||||
|
## gap> GF(2)^[ 4, 5 ]; # the same as above
|
||||||
|
## ( GF(2)^[ 4, 5 ] )
|
||||||
|
## ]]></Example>
|
||||||
|
## </Description>
|
||||||
|
## </ManSection>
|
||||||
|
## <#/GAPDoc>
|
||||||
|
##
|
||||||
|
DeclareSynonym( "FullMatrixSpace", FullMatrixModule );
|
||||||
|
DeclareSynonym( "MatrixSpace", FullMatrixModule );
|
||||||
|
DeclareSynonym( "MatSpace", FullMatrixModule );
|
||||||
|
|
||||||
|
|
||||||
|
#############################################################################
|
||||||
|
##
|
||||||
|
#C IsSubspacesVectorSpace( <D> )
|
||||||
|
##
|
||||||
|
## <#GAPDoc Label="IsSubspacesVectorSpace">
|
||||||
|
## <ManSection>
|
||||||
|
## <Filt Name="IsSubspacesVectorSpace" Arg='D' Type='Category'/>
|
||||||
|
##
|
||||||
|
## <Description>
|
||||||
|
## The domain of all subspaces of a (finite) vector space or of all
|
||||||
|
## subspaces of fixed dimension, as returned by <Ref Func="Subspaces"/>
|
||||||
|
## (see <Ref Func="Subspaces"/>) lies in the category
|
||||||
|
## <Ref Filt="IsSubspacesVectorSpace"/>.
|
||||||
|
## <Example><![CDATA[
|
||||||
|
## gap> D:= Subspaces( GF(3)^3 );
|
||||||
|
## Subspaces( ( GF(3)^3 ) )
|
||||||
|
## gap> Size( D );
|
||||||
|
## 28
|
||||||
|
## gap> iter:= Iterator( D );;
|
||||||
|
## gap> NextIterator( iter );
|
||||||
|
## <vector space over GF(3), with 0 generators>
|
||||||
|
## gap> NextIterator( iter );
|
||||||
|
## <vector space of dimension 1 over GF(3)>
|
||||||
|
## gap> IsSubspacesVectorSpace( D );
|
||||||
|
## true
|
||||||
|
## ]]></Example>
|
||||||
|
## </Description>
|
||||||
|
## </ManSection>
|
||||||
|
## <#/GAPDoc>
|
||||||
|
##
|
||||||
|
DeclareCategory( "IsSubspacesVectorSpace", IsDomain );
|
||||||
|
|
||||||
|
|
||||||
|
#############################################################################
|
||||||
|
##
|
||||||
|
#M IsFinite( <D> ) . . . . . . . . . . . . . . . . . for a subspaces domain
|
||||||
|
##
|
||||||
|
## Returns `true' if <D> is finite.
|
||||||
|
## We allow subspaces domains in `IsSubspacesVectorSpace' only for finite
|
||||||
|
## vector spaces.
|
||||||
|
##
|
||||||
|
InstallTrueMethod( IsFinite, IsSubspacesVectorSpace );
|
||||||
|
|
||||||
|
|
||||||
|
#############################################################################
|
||||||
|
##
|
||||||
|
#A Subspaces( <V>[, <k>] )
|
||||||
|
##
|
||||||
|
## <#GAPDoc Label="Subspaces">
|
||||||
|
## <ManSection>
|
||||||
|
## <Attr Name="Subspaces" Arg='V[, k]'/>
|
||||||
|
##
|
||||||
|
## <Description>
|
||||||
|
## Called with a finite vector space <A>v</A>,
|
||||||
|
## <Ref Oper="Subspaces"/> returns the domain of all subspaces of <A>V</A>.
|
||||||
|
## <P/>
|
||||||
|
## Called with <A>V</A> and a nonnegative integer <A>k</A>,
|
||||||
|
## <Ref Oper="Subspaces"/> returns the domain of all <A>k</A>-dimensional
|
||||||
|
## subspaces of <A>V</A>.
|
||||||
|
## <P/>
|
||||||
|
## Special <Ref Attr="Size"/> and <Ref Oper="Iterator"/> methods are
|
||||||
|
## provided for these domains.
|
||||||
|
## <!-- <C>Enumerator</C> would also be good ...
|
||||||
|
## (special treatment for full row spaces,
|
||||||
|
## other spaces delegate to this)-->
|
||||||
|
## </Description>
|
||||||
|
## </ManSection>
|
||||||
|
## <#/GAPDoc>
|
||||||
|
##
|
||||||
|
DeclareAttribute( "Subspaces", IsLeftModule );
|
||||||
|
DeclareOperation( "Subspaces", [ IsLeftModule, IsInt ] );
|
||||||
|
|
||||||
|
|
||||||
|
#############################################################################
|
||||||
|
##
|
||||||
|
#F IsSubspace( <V>, <U> )
|
||||||
|
##
|
||||||
|
## <ManSection>
|
||||||
|
## <Func Name="IsSubspace" Arg='V, U'/>
|
||||||
|
##
|
||||||
|
## <Description>
|
||||||
|
## check that <A>U</A> is a vector space that is contained in <A>V</A>
|
||||||
|
## <!-- Must also <A>V</A> be a vector space?
|
||||||
|
## If yes then must <A>V</A> and <A>U</A> have same left acting domain?
|
||||||
|
## (Is this function useful at all?) -->
|
||||||
|
## </Description>
|
||||||
|
## </ManSection>
|
||||||
|
##
|
||||||
|
DeclareGlobalFunction( "IsSubspace" );
|
||||||
|
|
||||||
|
|
||||||
|
#############################################################################
|
||||||
|
##
|
||||||
|
#A OrthogonalSpaceInFullRowSpace( <U> )
|
||||||
|
##
|
||||||
|
## <ManSection>
|
||||||
|
## <Attr Name="OrthogonalSpaceInFullRowSpace" Arg='U'/>
|
||||||
|
##
|
||||||
|
## <Description>
|
||||||
|
## For a Gaussian row space <A>U</A> over <M>F</M>,
|
||||||
|
## <Ref Attr="OrthogonalSpaceInFullRowSpace"/>
|
||||||
|
## returns a complement of <A>U</A> in the full row space of same vector
|
||||||
|
## dimension as <A>U</A> over <M>F</M>.
|
||||||
|
## </Description>
|
||||||
|
## </ManSection>
|
||||||
|
##
|
||||||
|
DeclareAttribute( "OrthogonalSpaceInFullRowSpace", IsGaussianSpace );
|
||||||
|
|
||||||
|
|
||||||
|
#############################################################################
|
||||||
|
##
|
||||||
|
#P IsVectorSpaceHomomorphism( <map> )
|
||||||
|
##
|
||||||
|
## <ManSection>
|
||||||
|
## <Prop Name="IsVectorSpaceHomomorphism" Arg='map'/>
|
||||||
|
##
|
||||||
|
## <Description>
|
||||||
|
## A mapping <M>f</M> is a vector space homomorphism (or linear mapping)
|
||||||
|
## if the source and range are vector spaces
|
||||||
|
## (see <Ref Func="IsVectorSpace"/>)
|
||||||
|
## over the same division ring <M>D</M>
|
||||||
|
## (see <Ref Func="LeftActingDomain"/>),
|
||||||
|
## and if <M>f( a + b ) = f(a) + f(b)</M> and <M>f( s * a ) = s * f(a)</M>
|
||||||
|
## hold for all elements <M>a</M>, <M>b</M> in the source of <M>f</M> and
|
||||||
|
## <M>s \in D</M>.
|
||||||
|
## </Description>
|
||||||
|
## </ManSection>
|
||||||
|
##
|
||||||
|
DeclareProperty( "IsVectorSpaceHomomorphism", IsGeneralMapping );
|
||||||
|
|
||||||
|
|
||||||
|
#############################################################################
|
||||||
|
##
|
||||||
|
#E
|
||||||
|
|
||||||
651
samples/GAP/vspc.gi
Normal file
651
samples/GAP/vspc.gi
Normal file
@@ -0,0 +1,651 @@
|
|||||||
|
#############################################################################
|
||||||
|
##
|
||||||
|
#W vspc.gi GAP library Thomas Breuer
|
||||||
|
##
|
||||||
|
##
|
||||||
|
#Y Copyright (C) 1997, Lehrstuhl D für Mathematik, RWTH Aachen, Germany
|
||||||
|
#Y (C) 1998 School Math and Comp. Sci., University of St Andrews, Scotland
|
||||||
|
#Y Copyright (C) 2002 The GAP Group
|
||||||
|
##
|
||||||
|
## This file contains generic methods for vector spaces.
|
||||||
|
##
|
||||||
|
|
||||||
|
|
||||||
|
#############################################################################
|
||||||
|
##
|
||||||
|
#M SetLeftActingDomain( <extL>, <D> )
|
||||||
|
##
|
||||||
|
## check whether the left acting domain <D> of the external left set <extL>
|
||||||
|
## knows that it is a division ring.
|
||||||
|
## This is used, e.g., to tell a free module over a division ring
|
||||||
|
## that it is a vector space.
|
||||||
|
##
|
||||||
|
InstallOtherMethod( SetLeftActingDomain,
|
||||||
|
"method to set also 'IsLeftActedOnByDivisionRing'",
|
||||||
|
[ IsAttributeStoringRep and IsLeftActedOnByRing, IsObject ],0,
|
||||||
|
function( extL, D )
|
||||||
|
if HasIsDivisionRing( D ) and IsDivisionRing( D ) then
|
||||||
|
SetIsLeftActedOnByDivisionRing( extL, true );
|
||||||
|
fi;
|
||||||
|
TryNextMethod();
|
||||||
|
end );
|
||||||
|
|
||||||
|
|
||||||
|
#############################################################################
|
||||||
|
##
|
||||||
|
#M IsLeftActedOnByDivisionRing( <M> )
|
||||||
|
##
|
||||||
|
InstallMethod( IsLeftActedOnByDivisionRing,
|
||||||
|
"method for external left set that is left acted on by a ring",
|
||||||
|
[ IsExtLSet and IsLeftActedOnByRing ],
|
||||||
|
function( M )
|
||||||
|
if IsIdenticalObj( M, LeftActingDomain( M ) ) then
|
||||||
|
TryNextMethod();
|
||||||
|
else
|
||||||
|
return IsDivisionRing( LeftActingDomain( M ) );
|
||||||
|
fi;
|
||||||
|
end );
|
||||||
|
|
||||||
|
|
||||||
|
#############################################################################
|
||||||
|
##
|
||||||
|
#F VectorSpace( <F>, <gens>[, <zero>][, "basis"] )
|
||||||
|
##
|
||||||
|
## The only difference between `VectorSpace' and `FreeLeftModule' shall be
|
||||||
|
## that the left acting domain of a vector space must be a division ring.
|
||||||
|
##
|
||||||
|
InstallGlobalFunction( VectorSpace, function( arg )
|
||||||
|
if Length( arg ) = 0 or not IsDivisionRing( arg[1] ) then
|
||||||
|
Error( "usage: VectorSpace( <F>, <gens>[, <zero>][, \"basis\"] )" );
|
||||||
|
fi;
|
||||||
|
return CallFuncList( FreeLeftModule, arg );
|
||||||
|
end );
|
||||||
|
|
||||||
|
|
||||||
|
#############################################################################
|
||||||
|
##
|
||||||
|
#M AsSubspace( <V>, <C> ) . . . . . . . for a vector space and a collection
|
||||||
|
##
|
||||||
|
InstallMethod( AsSubspace,
|
||||||
|
"for a vector space and a collection",
|
||||||
|
[ IsVectorSpace, IsCollection ],
|
||||||
|
function( V, C )
|
||||||
|
local newC;
|
||||||
|
|
||||||
|
if not IsSubset( V, C ) then
|
||||||
|
return fail;
|
||||||
|
fi;
|
||||||
|
newC:= AsVectorSpace( LeftActingDomain( V ), C );
|
||||||
|
if newC = fail then
|
||||||
|
return fail;
|
||||||
|
fi;
|
||||||
|
SetParent( newC, V );
|
||||||
|
UseIsomorphismRelation( C, newC );
|
||||||
|
UseSubsetRelation( C, newC );
|
||||||
|
|
||||||
|
return newC;
|
||||||
|
end );
|
||||||
|
|
||||||
|
|
||||||
|
#############################################################################
|
||||||
|
##
|
||||||
|
#M AsLeftModule( <F>, <V> ) . . . . . . for division ring and vector space
|
||||||
|
##
|
||||||
|
## View the vector space <V> as a vector space over the division ring <F>.
|
||||||
|
##
|
||||||
|
InstallMethod( AsLeftModule,
|
||||||
|
"method for a division ring and a vector space",
|
||||||
|
[ IsDivisionRing, IsVectorSpace ],
|
||||||
|
function( F, V )
|
||||||
|
|
||||||
|
local W, # the space, result
|
||||||
|
base, # basis vectors of field extension
|
||||||
|
gen, # loop over generators of 'V'
|
||||||
|
b, # loop over 'base'
|
||||||
|
gens, # generators of 'V'
|
||||||
|
newgens; # extended list of generators
|
||||||
|
|
||||||
|
if Characteristic( F ) <> Characteristic( LeftActingDomain( V ) ) then
|
||||||
|
|
||||||
|
# This is impossible.
|
||||||
|
return fail;
|
||||||
|
|
||||||
|
elif F = LeftActingDomain( V ) then
|
||||||
|
|
||||||
|
# No change of the left acting domain is necessary.
|
||||||
|
return V;
|
||||||
|
|
||||||
|
elif IsSubset( F, LeftActingDomain( V ) ) then
|
||||||
|
|
||||||
|
# Check whether 'V' is really a space over the bigger field,
|
||||||
|
# that is, whether the set of elements does not change.
|
||||||
|
base:= BasisVectors( Basis( AsField( LeftActingDomain( V ), F ) ) );
|
||||||
|
for gen in GeneratorsOfLeftModule( V ) do
|
||||||
|
for b in base do
|
||||||
|
if not b * gen in V then
|
||||||
|
|
||||||
|
# The field extension would change the set of elements.
|
||||||
|
return fail;
|
||||||
|
|
||||||
|
fi;
|
||||||
|
od;
|
||||||
|
od;
|
||||||
|
|
||||||
|
# Construct the space.
|
||||||
|
W:= LeftModuleByGenerators( F, GeneratorsOfLeftModule(V), Zero(V) );
|
||||||
|
|
||||||
|
elif IsSubset( LeftActingDomain( V ), F ) then
|
||||||
|
|
||||||
|
# View 'V' as a space over a smaller field.
|
||||||
|
# For that, the list of generators must be extended.
|
||||||
|
gens:= GeneratorsOfLeftModule( V );
|
||||||
|
if IsEmpty( gens ) then
|
||||||
|
W:= LeftModuleByGenerators( F, [], Zero( V ) );
|
||||||
|
else
|
||||||
|
|
||||||
|
base:= BasisVectors( Basis( AsField( F, LeftActingDomain( V ) ) ) );
|
||||||
|
newgens:= [];
|
||||||
|
for b in base do
|
||||||
|
for gen in gens do
|
||||||
|
Add( newgens, b * gen );
|
||||||
|
od;
|
||||||
|
od;
|
||||||
|
W:= LeftModuleByGenerators( F, newgens );
|
||||||
|
|
||||||
|
fi;
|
||||||
|
|
||||||
|
else
|
||||||
|
|
||||||
|
# View 'V' first as space over the intersection of fields,
|
||||||
|
# and then over the desired field.
|
||||||
|
return AsLeftModule( F,
|
||||||
|
AsLeftModule( Intersection( F,
|
||||||
|
LeftActingDomain( V ) ), V ) );
|
||||||
|
|
||||||
|
fi;
|
||||||
|
|
||||||
|
UseIsomorphismRelation( V, W );
|
||||||
|
UseSubsetRelation( V, W );
|
||||||
|
return W;
|
||||||
|
end );
|
||||||
|
|
||||||
|
|
||||||
|
#############################################################################
|
||||||
|
##
|
||||||
|
#M ViewObj( <V> ) . . . . . . . . . . . . . . . . . . . view a vector space
|
||||||
|
##
|
||||||
|
## print left acting domain, if known also dimension or no. of generators
|
||||||
|
##
|
||||||
|
InstallMethod( ViewObj,
|
||||||
|
"for vector space with known generators",
|
||||||
|
[ IsVectorSpace and HasGeneratorsOfLeftModule ],
|
||||||
|
function( V )
|
||||||
|
Print( "<vector space over ", LeftActingDomain( V ), ", with ",
|
||||||
|
Length( GeneratorsOfLeftModule( V ) ), " generators>" );
|
||||||
|
end );
|
||||||
|
|
||||||
|
InstallMethod( ViewObj,
|
||||||
|
"for vector space with known dimension",
|
||||||
|
[ IsVectorSpace and HasDimension ],
|
||||||
|
1, # override method for known generators
|
||||||
|
function( V )
|
||||||
|
Print( "<vector space of dimension ", Dimension( V ),
|
||||||
|
" over ", LeftActingDomain( V ), ">" );
|
||||||
|
end );
|
||||||
|
|
||||||
|
InstallMethod( ViewObj,
|
||||||
|
"for vector space",
|
||||||
|
[ IsVectorSpace ],
|
||||||
|
function( V )
|
||||||
|
Print( "<vector space over ", LeftActingDomain( V ), ">" );
|
||||||
|
end );
|
||||||
|
|
||||||
|
|
||||||
|
#############################################################################
|
||||||
|
##
|
||||||
|
#M PrintObj( <V> ) . . . . . . . . . . . . . . . . . . . for a vector space
|
||||||
|
##
|
||||||
|
InstallMethod( PrintObj,
|
||||||
|
"method for vector space with left module generators",
|
||||||
|
[ IsVectorSpace and HasGeneratorsOfLeftModule ],
|
||||||
|
function( V )
|
||||||
|
Print( "VectorSpace( ", LeftActingDomain( V ), ", ",
|
||||||
|
GeneratorsOfLeftModule( V ) );
|
||||||
|
if IsEmpty( GeneratorsOfLeftModule( V ) ) and HasZero( V ) then
|
||||||
|
Print( ", ", Zero( V ), " )" );
|
||||||
|
else
|
||||||
|
Print( " )" );
|
||||||
|
fi;
|
||||||
|
end );
|
||||||
|
|
||||||
|
InstallMethod( PrintObj,
|
||||||
|
"method for vector space",
|
||||||
|
[ IsVectorSpace ],
|
||||||
|
function( V )
|
||||||
|
Print( "VectorSpace( ", LeftActingDomain( V ), ", ... )" );
|
||||||
|
end );
|
||||||
|
|
||||||
|
|
||||||
|
#############################################################################
|
||||||
|
##
|
||||||
|
#M \/( <V>, <W> ) . . . . . . . . . factor of a vector space by a subspace
|
||||||
|
#M \/( <V>, <vectors> ) . . . . . . factor of a vector space by a subspace
|
||||||
|
##
|
||||||
|
InstallOtherMethod( \/,
|
||||||
|
"method for vector space and collection",
|
||||||
|
IsIdenticalObj,
|
||||||
|
[ IsVectorSpace, IsCollection ],
|
||||||
|
function( V, vectors )
|
||||||
|
if IsVectorSpace( vectors ) then
|
||||||
|
TryNextMethod();
|
||||||
|
else
|
||||||
|
return V / Subspace( V, vectors );
|
||||||
|
fi;
|
||||||
|
end );
|
||||||
|
|
||||||
|
InstallOtherMethod( \/,
|
||||||
|
"generic method for two vector spaces",
|
||||||
|
IsIdenticalObj,
|
||||||
|
[ IsVectorSpace, IsVectorSpace ],
|
||||||
|
function( V, W )
|
||||||
|
return ImagesSource( NaturalHomomorphismBySubspace( V, W ) );
|
||||||
|
end );
|
||||||
|
|
||||||
|
|
||||||
|
#############################################################################
|
||||||
|
##
|
||||||
|
#M Intersection2Spaces( <AsStruct>, <Substruct>, <Struct> )
|
||||||
|
##
|
||||||
|
InstallGlobalFunction( Intersection2Spaces,
|
||||||
|
function( AsStructure, Substructure, Structure )
|
||||||
|
return function( V, W )
|
||||||
|
local inters, # intersection, result
|
||||||
|
F, # coefficients field
|
||||||
|
gensV, # list of generators of 'V'
|
||||||
|
gensW, # list of generators of 'W'
|
||||||
|
VW, # sum of 'V' and 'W'
|
||||||
|
B; # basis of 'VW'
|
||||||
|
|
||||||
|
if LeftActingDomain( V ) <> LeftActingDomain( W ) then
|
||||||
|
|
||||||
|
# Compute the intersection as vector space over the intersection
|
||||||
|
# of the coefficients fields.
|
||||||
|
# (Note that the characteristic is the same.)
|
||||||
|
F:= Intersection2( LeftActingDomain( V ), LeftActingDomain( W ) );
|
||||||
|
return Intersection2( AsStructure( F, V ), AsStructure( F, W ) );
|
||||||
|
|
||||||
|
elif IsFiniteDimensional( V ) and IsFiniteDimensional( W ) then
|
||||||
|
|
||||||
|
# Compute the intersection of two spaces over the same field.
|
||||||
|
gensV:= GeneratorsOfLeftModule( V );
|
||||||
|
gensW:= GeneratorsOfLeftModule( W );
|
||||||
|
if IsEmpty( gensV ) then
|
||||||
|
if Zero( V ) in W then
|
||||||
|
inters:= V;
|
||||||
|
else
|
||||||
|
inters:= [];
|
||||||
|
fi;
|
||||||
|
elif IsEmpty( gensW ) then
|
||||||
|
if Zero( V ) in W then
|
||||||
|
inters:= W;
|
||||||
|
else
|
||||||
|
inters:= [];
|
||||||
|
fi;
|
||||||
|
else
|
||||||
|
# Compute a common coefficient space.
|
||||||
|
VW:= LeftModuleByGenerators( LeftActingDomain( V ),
|
||||||
|
Concatenation( gensV, gensW ) );
|
||||||
|
B:= Basis( VW );
|
||||||
|
|
||||||
|
# Construct the coefficient subspaces corresponding to 'V' and 'W'.
|
||||||
|
gensV:= List( gensV, x -> Coefficients( B, x ) );
|
||||||
|
gensW:= List( gensW, x -> Coefficients( B, x ) );
|
||||||
|
|
||||||
|
# Construct the intersection of row spaces, and carry back to VW.
|
||||||
|
inters:= List( SumIntersectionMat( gensV, gensW )[2],
|
||||||
|
x -> LinearCombination( B, x ) );
|
||||||
|
|
||||||
|
# Construct the intersection space, if possible with a parent.
|
||||||
|
if HasParent( V ) and HasParent( W )
|
||||||
|
and IsIdenticalObj( Parent( V ), Parent( W ) ) then
|
||||||
|
inters:= Substructure( Parent( V ), inters, "basis" );
|
||||||
|
elif IsEmpty( inters ) then
|
||||||
|
inters:= Substructure( V, inters, "basis" );
|
||||||
|
SetIsTrivial( inters, true );
|
||||||
|
else
|
||||||
|
inters:= Structure( LeftActingDomain( V ), inters, "basis" );
|
||||||
|
fi;
|
||||||
|
|
||||||
|
# Run implications by the subset relation.
|
||||||
|
UseSubsetRelation( V, inters );
|
||||||
|
UseSubsetRelation( W, inters );
|
||||||
|
fi;
|
||||||
|
|
||||||
|
# Return the result.
|
||||||
|
return inters;
|
||||||
|
|
||||||
|
else
|
||||||
|
TryNextMethod();
|
||||||
|
fi;
|
||||||
|
end;
|
||||||
|
end );
|
||||||
|
|
||||||
|
|
||||||
|
#############################################################################
|
||||||
|
##
|
||||||
|
#M Intersection2( <V>, <W> ) . . . . . . . . . . . . . for two vector spaces
|
||||||
|
##
|
||||||
|
InstallMethod( Intersection2,
|
||||||
|
"method for two vector spaces",
|
||||||
|
IsIdenticalObj,
|
||||||
|
[ IsVectorSpace, IsVectorSpace ],
|
||||||
|
Intersection2Spaces( AsLeftModule, SubspaceNC, VectorSpace ) );
|
||||||
|
|
||||||
|
|
||||||
|
#############################################################################
|
||||||
|
##
|
||||||
|
#M ClosureLeftModule( <V>, <a> ) . . . . . . . . . closure of a vector space
|
||||||
|
##
|
||||||
|
InstallMethod( ClosureLeftModule,
|
||||||
|
"method for a vector space with basis, and a vector",
|
||||||
|
IsCollsElms,
|
||||||
|
[ IsVectorSpace and HasBasis, IsVector ],
|
||||||
|
function( V, w )
|
||||||
|
local B; # basis of 'V'
|
||||||
|
|
||||||
|
# We can test membership easily.
|
||||||
|
B:= Basis( V );
|
||||||
|
#T why easily?
|
||||||
|
if Coefficients( B, w ) = fail then
|
||||||
|
|
||||||
|
# In the case of a vector space, we know a basis of the closure.
|
||||||
|
B:= Concatenation( BasisVectors( B ), [ w ] );
|
||||||
|
V:= LeftModuleByGenerators( LeftActingDomain( V ), B );
|
||||||
|
UseBasis( V, B );
|
||||||
|
|
||||||
|
fi;
|
||||||
|
return V;
|
||||||
|
end );
|
||||||
|
|
||||||
|
|
||||||
|
#############################################################################
|
||||||
|
##
|
||||||
|
## Methods for collections of subspaces of a vector space
|
||||||
|
##
|
||||||
|
|
||||||
|
|
||||||
|
#############################################################################
|
||||||
|
##
|
||||||
|
#R IsSubspacesVectorSpaceDefaultRep( <D> )
|
||||||
|
##
|
||||||
|
## is the representation of domains of subspaces of a vector space <V>,
|
||||||
|
## with the components 'structure' (with value <V>) and 'dimension'
|
||||||
|
## (with value either the dimension of the subspaces in the domain
|
||||||
|
## or the string '\"all\"', which means that the domain contains all
|
||||||
|
## subspaces of <V>).
|
||||||
|
##
|
||||||
|
DeclareRepresentation(
|
||||||
|
"IsSubspacesVectorSpaceDefaultRep",
|
||||||
|
IsComponentObjectRep,
|
||||||
|
[ "dimension", "structure" ] );
|
||||||
|
#T not IsAttributeStoringRep?
|
||||||
|
|
||||||
|
|
||||||
|
#############################################################################
|
||||||
|
##
|
||||||
|
#M PrintObj( <D> ) . . . . . . . . . . . . . . . . . for a subspaces domain
|
||||||
|
##
|
||||||
|
InstallMethod( PrintObj,
|
||||||
|
"method for a subspaces domain",
|
||||||
|
[ IsSubspacesVectorSpace and IsSubspacesVectorSpaceDefaultRep ],
|
||||||
|
function( D )
|
||||||
|
if IsInt( D!.dimension ) then
|
||||||
|
Print( "Subspaces( ", D!.structure, ", ", D!.dimension, " )" );
|
||||||
|
else
|
||||||
|
Print( "Subspaces( ", D!.structure, " )" );
|
||||||
|
fi;
|
||||||
|
end );
|
||||||
|
|
||||||
|
|
||||||
|
#############################################################################
|
||||||
|
##
|
||||||
|
#M Size( <D> ) . . . . . . . . . . . . . . . . . . . for a subspaces domain
|
||||||
|
##
|
||||||
|
## The number of $k$-dimensional subspaces in a $n$-dimensional space over
|
||||||
|
## the field with $q$ elements is
|
||||||
|
## $$
|
||||||
|
## a(n,k) = \prod_{i=0}^{k-1} \frac{q^n-q^i}{q^k-q^i} =
|
||||||
|
## \prod_{i=0}^{k-1} \frac{q^{n-i}-1}{q^{k-i}-1}.
|
||||||
|
## $$
|
||||||
|
## We have the recursion
|
||||||
|
## $$
|
||||||
|
## a(n,k+1) = a(n,k) \frac{q^{n-i}-1}{q^{i+1}-1}.
|
||||||
|
## $$
|
||||||
|
##
|
||||||
|
## (The number of all subspaces is $\sum_{k=0}^n a(n,k)$.)
|
||||||
|
##
|
||||||
|
InstallMethod( Size,
|
||||||
|
"method for a subspaces domain",
|
||||||
|
[ IsSubspacesVectorSpace and IsSubspacesVectorSpaceDefaultRep ],
|
||||||
|
function( D )
|
||||||
|
|
||||||
|
local k,
|
||||||
|
n,
|
||||||
|
q,
|
||||||
|
size,
|
||||||
|
qn,
|
||||||
|
qd,
|
||||||
|
ank,
|
||||||
|
i;
|
||||||
|
|
||||||
|
if D!.dimension = "all" then
|
||||||
|
|
||||||
|
# all subspaces of the space
|
||||||
|
n:= Dimension( D!.structure );
|
||||||
|
|
||||||
|
q:= Size( LeftActingDomain( D!.structure ) );
|
||||||
|
size:= 1;
|
||||||
|
qn:= q^n;
|
||||||
|
qd:= q;
|
||||||
|
|
||||||
|
# $a(n,0)$
|
||||||
|
ank:= 1;
|
||||||
|
|
||||||
|
for k in [ 1 .. Int( (n-1)/2 ) ] do
|
||||||
|
|
||||||
|
# Compute $a(n,k)$.
|
||||||
|
ank:= ank * ( qn - 1 ) / ( qd - 1 );
|
||||||
|
qn:= qn / q;
|
||||||
|
qd:= qd * q;
|
||||||
|
|
||||||
|
size:= size + ank;
|
||||||
|
|
||||||
|
od;
|
||||||
|
|
||||||
|
size:= 2 * size;
|
||||||
|
|
||||||
|
if n mod 2 = 0 then
|
||||||
|
|
||||||
|
# Add the number of spaces of dimension $n/2$.
|
||||||
|
size:= size + ank * ( qn - 1 ) / ( qd - 1 );
|
||||||
|
fi;
|
||||||
|
|
||||||
|
else
|
||||||
|
|
||||||
|
# number of spaces of dimension 'k' only
|
||||||
|
n:= Dimension( D!.structure );
|
||||||
|
if D!.dimension < 0 or
|
||||||
|
n < D!.dimension then
|
||||||
|
return 0;
|
||||||
|
elif n / 2 < D!.dimension then
|
||||||
|
k:= n - D!.dimension;
|
||||||
|
else
|
||||||
|
k:= D!.dimension;
|
||||||
|
fi;
|
||||||
|
|
||||||
|
q:= Size( LeftActingDomain( D!.structure ) );
|
||||||
|
size:= 1;
|
||||||
|
|
||||||
|
qn:= q^n;
|
||||||
|
qd:= q;
|
||||||
|
for i in [ 1 .. k ] do
|
||||||
|
size:= size * ( qn - 1 ) / ( qd - 1 );
|
||||||
|
qn:= qn / q;
|
||||||
|
qd:= qd * q;
|
||||||
|
od;
|
||||||
|
|
||||||
|
fi;
|
||||||
|
|
||||||
|
# Return the result.
|
||||||
|
return size;
|
||||||
|
end );
|
||||||
|
|
||||||
|
|
||||||
|
#############################################################################
|
||||||
|
##
|
||||||
|
#M Enumerator( <D> ) . . . . . . . . . . . . . . . . for a subspaces domain
|
||||||
|
##
|
||||||
|
## Use the iterator to compute the elements list.
|
||||||
|
#T This is not allowed!
|
||||||
|
##
|
||||||
|
InstallMethod( Enumerator,
|
||||||
|
"method for a subspaces domain",
|
||||||
|
[ IsSubspacesVectorSpace and IsSubspacesVectorSpaceDefaultRep ],
|
||||||
|
function( D )
|
||||||
|
local iter, # iterator for 'D'
|
||||||
|
elms; # elements list, result
|
||||||
|
|
||||||
|
iter:= Iterator( D );
|
||||||
|
elms:= [];
|
||||||
|
while not IsDoneIterator( iter ) do
|
||||||
|
Add( elms, NextIterator( iter ) );
|
||||||
|
od;
|
||||||
|
return elms;
|
||||||
|
end );
|
||||||
|
#T necessary?
|
||||||
|
|
||||||
|
|
||||||
|
#############################################################################
|
||||||
|
##
|
||||||
|
#M Iterator( <D> ) . . . . . . . . . . . . . . . . . for a subspaces domain
|
||||||
|
##
|
||||||
|
## uses the subspaces iterator for full row spaces and the mechanism of
|
||||||
|
## associated row spaces.
|
||||||
|
##
|
||||||
|
BindGlobal( "IsDoneIterator_Subspaces",
|
||||||
|
iter -> IsDoneIterator( iter!.associatedIterator ) );
|
||||||
|
|
||||||
|
BindGlobal( "NextIterator_Subspaces", function( iter )
|
||||||
|
local next;
|
||||||
|
next:= NextIterator( iter!.associatedIterator );
|
||||||
|
next:= List( GeneratorsOfLeftModule( next ),
|
||||||
|
x -> LinearCombination( iter!.basis, x ) );
|
||||||
|
return Subspace( iter!.structure, next, "basis" );
|
||||||
|
end );
|
||||||
|
|
||||||
|
BindGlobal( "ShallowCopy_Subspaces",
|
||||||
|
iter -> rec( structure := iter!.structure,
|
||||||
|
basis := iter!.basis,
|
||||||
|
associatedIterator := ShallowCopy(
|
||||||
|
iter!.associatedIterator ) ) );
|
||||||
|
|
||||||
|
InstallMethod( Iterator,
|
||||||
|
"for a subspaces domain",
|
||||||
|
[ IsSubspacesVectorSpace and IsSubspacesVectorSpaceDefaultRep ],
|
||||||
|
function( D )
|
||||||
|
local V; # the vector space
|
||||||
|
|
||||||
|
V:= D!.structure;
|
||||||
|
return IteratorByFunctions( rec(
|
||||||
|
IsDoneIterator := IsDoneIterator_Subspaces,
|
||||||
|
NextIterator := NextIterator_Subspaces,
|
||||||
|
ShallowCopy := ShallowCopy_Subspaces,
|
||||||
|
structure := V,
|
||||||
|
basis := Basis( V ),
|
||||||
|
associatedIterator := Iterator(
|
||||||
|
Subspaces( FullRowSpace( LeftActingDomain( V ),
|
||||||
|
Dimension( V ) ),
|
||||||
|
D!.dimension ) ) ) );
|
||||||
|
end );
|
||||||
|
|
||||||
|
|
||||||
|
#############################################################################
|
||||||
|
##
|
||||||
|
#M Subspaces( <V>, <dim> )
|
||||||
|
##
|
||||||
|
InstallMethod( Subspaces,
|
||||||
|
"for a vector space, and an integer",
|
||||||
|
[ IsVectorSpace, IsInt ],
|
||||||
|
function( V, dim )
|
||||||
|
if IsFinite( V ) then
|
||||||
|
return Objectify( NewType( CollectionsFamily( FamilyObj( V ) ),
|
||||||
|
IsSubspacesVectorSpace
|
||||||
|
and IsSubspacesVectorSpaceDefaultRep ),
|
||||||
|
rec(
|
||||||
|
structure := V,
|
||||||
|
dimension := dim
|
||||||
|
)
|
||||||
|
);
|
||||||
|
else
|
||||||
|
TryNextMethod();
|
||||||
|
fi;
|
||||||
|
end );
|
||||||
|
|
||||||
|
|
||||||
|
#############################################################################
|
||||||
|
##
|
||||||
|
#M Subspaces( <V> )
|
||||||
|
##
|
||||||
|
InstallMethod( Subspaces,
|
||||||
|
"for a vector space",
|
||||||
|
[ IsVectorSpace ],
|
||||||
|
function( V )
|
||||||
|
if IsFinite( V ) then
|
||||||
|
return Objectify( NewType( CollectionsFamily( FamilyObj( V ) ),
|
||||||
|
IsSubspacesVectorSpace
|
||||||
|
and IsSubspacesVectorSpaceDefaultRep ),
|
||||||
|
rec(
|
||||||
|
structure := V,
|
||||||
|
dimension := "all"
|
||||||
|
)
|
||||||
|
);
|
||||||
|
else
|
||||||
|
TryNextMethod();
|
||||||
|
fi;
|
||||||
|
end );
|
||||||
|
|
||||||
|
|
||||||
|
#############################################################################
|
||||||
|
##
|
||||||
|
#F IsSubspace( <V>, <U> ) . . . . . . . . . . . . . . . . . check <U> <= <V>
|
||||||
|
##
|
||||||
|
InstallGlobalFunction( IsSubspace, function( V, U )
|
||||||
|
return IsVectorSpace( U ) and IsSubset( V, U );
|
||||||
|
end );
|
||||||
|
|
||||||
|
|
||||||
|
#############################################################################
|
||||||
|
##
|
||||||
|
#M IsVectorSpaceHomomorphism( <map> )
|
||||||
|
##
|
||||||
|
InstallMethod( IsVectorSpaceHomomorphism,
|
||||||
|
[ IsGeneralMapping ],
|
||||||
|
function( map )
|
||||||
|
local S, R, F;
|
||||||
|
S:= Source( map );
|
||||||
|
if not IsVectorSpace( S ) then
|
||||||
|
return false;
|
||||||
|
fi;
|
||||||
|
R:= Range( map );
|
||||||
|
if not IsVectorSpace( R ) then
|
||||||
|
return false;
|
||||||
|
fi;
|
||||||
|
F:= LeftActingDomain( S );
|
||||||
|
return ( F = LeftActingDomain( R ) ) and IsLinearMapping( F, map );
|
||||||
|
end );
|
||||||
|
|
||||||
|
|
||||||
|
#############################################################################
|
||||||
|
##
|
||||||
|
#E
|
||||||
|
|
||||||
Reference in New Issue
Block a user