implement caching in groupthm
This commit is contained in:
parent
64fbca35dd
commit
f1dacf4a5d
1 changed files with 251 additions and 109 deletions
|
@ -23,7 +23,7 @@
|
||||||
% https://www.latex-project.org/lppl.txt
|
% https://www.latex-project.org/lppl.txt
|
||||||
%
|
%
|
||||||
% -----------------------------------------------------------------------
|
% -----------------------------------------------------------------------
|
||||||
%<package>\ProvidesExplPackage{groupthm}{2022/01/17}{0.0.1}{Grouped theorems.}
|
%<package>\ProvidesExplPackage{groupthm}{2022/02/02}{0.0.2}{Grouped theorems.}
|
||||||
%
|
%
|
||||||
%<*driver>
|
%<*driver>
|
||||||
\documentclass[full,kernel]{l3doc}
|
\documentclass[full,kernel]{l3doc}
|
||||||
|
@ -846,25 +846,16 @@
|
||||||
%
|
%
|
||||||
% This is just a private wrapper around \cs{declaretheorem} of the \pkg{thmtools} package.
|
% This is just a private wrapper around \cs{declaretheorem} of the \pkg{thmtools} package.
|
||||||
%
|
%
|
||||||
|
% We additionally cache
|
||||||
|
%
|
||||||
% \begin{macrocode}
|
% \begin{macrocode}
|
||||||
\cs_new:Npn \@@_thmtools_declare_theorem:nn #1 #2
|
\cs_new:Npn \@@_thmtools_declare_theorem:nn #1 #2
|
||||||
{
|
{
|
||||||
\tl_log:n { Declaring ~ thmtools ~ theorem ~ #2 }
|
\tl_log:n { Declaring ~ thmtools ~ theorem ~ #2 }
|
||||||
\declaretheorem [ #1 ] { #2 }
|
\declaretheorem [ #1 ] { #2 }
|
||||||
\bool_if:NT \g_@@_cache_bool
|
\@@_cache:n
|
||||||
{
|
{
|
||||||
\hook_gput_code:nnn { enddocument / afterlastpage } { groupthm }
|
\csname @@_thmtools_declare_theorem:nn \endcsname { #1 } { #2 }
|
||||||
{
|
|
||||||
\iow_now:cn { @auxout }
|
|
||||||
{
|
|
||||||
\ExplSyntaxOn
|
|
||||||
\hook_gput_code:nnn { @@ / auxfile define cached } { groupthm }
|
|
||||||
{
|
|
||||||
\@@_thmtools_declare_theorem:nn { #1 } { #2 }
|
|
||||||
}
|
|
||||||
\ExplSyntaxOff
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
\cs_generate_variant:Nn \@@_thmtools_declare_theorem:nn { V n }
|
\cs_generate_variant:Nn \@@_thmtools_declare_theorem:nn { V n }
|
||||||
|
@ -982,10 +973,6 @@
|
||||||
\hook_new:n { @@/thmtools }
|
\hook_new:n { @@/thmtools }
|
||||||
% \end{macrocode}
|
% \end{macrocode}
|
||||||
% \begin{macrocode}
|
% \begin{macrocode}
|
||||||
\hook_new:n { @@/document define cached }
|
|
||||||
\hook_new:n { @@/auxfile define cached }
|
|
||||||
% \end{macrocode}
|
|
||||||
% \begin{macrocode}
|
|
||||||
\hook_new:n { @@/groupsort }
|
\hook_new:n { @@/groupsort }
|
||||||
% \end{macrocode}
|
% \end{macrocode}
|
||||||
%
|
%
|
||||||
|
@ -1109,6 +1096,36 @@
|
||||||
%
|
%
|
||||||
%
|
%
|
||||||
%
|
%
|
||||||
|
% \begin{variable}{\g_@@_lazy_document_tl, \g_@@_lazy_auxfile_tl}
|
||||||
|
%
|
||||||
|
% During the preamble, if in caching mode, we will collect definitions for
|
||||||
|
% theorems in these token lists. At the beginning of the document, we select the
|
||||||
|
% proper one.
|
||||||
|
%
|
||||||
|
% \begin{macrocode}
|
||||||
|
\tl_new:N \g_@@_lazy_document_tl
|
||||||
|
\tl_new:N \g_@@_lazy_auxfile_tl
|
||||||
|
% \end{macrocode}
|
||||||
|
% \end{variable}
|
||||||
|
%
|
||||||
|
%
|
||||||
|
%
|
||||||
|
% \begin{variable}{\g_@@_dump_auxfile_clist, \g_@@_dump_cache_clist}
|
||||||
|
%
|
||||||
|
% With these, we collect stuff written to the aux file at the end of the document
|
||||||
|
%
|
||||||
|
% The \cs{g_@@_dump_cache_clist} will be treated specially:
|
||||||
|
% We will dump such that in a re-run of \LaTeX, the contents will
|
||||||
|
% be available for execution in the \cs{g_@@_lazy_auxfile_tl}
|
||||||
|
% \begin{macrocode}
|
||||||
|
\clist_new:N \g_@@_dump_auxfile_clist
|
||||||
|
\clist_new:N \g_@@_dump_cache_clist
|
||||||
|
% \end{macrocode}
|
||||||
|
% \end{variable}
|
||||||
|
%
|
||||||
|
%
|
||||||
|
%
|
||||||
|
%
|
||||||
% \subsection{Key interface}
|
% \subsection{Key interface}
|
||||||
% As mentioned, all keys will set their corresponding local variables
|
% As mentioned, all keys will set their corresponding local variables
|
||||||
% (containing \enquote{\texttt{_key_}} in their name) and store the
|
% (containing \enquote{\texttt{_key_}} in their name) and store the
|
||||||
|
@ -1799,7 +1816,7 @@
|
||||||
{ \@@_Declarator: TheoremGroup }
|
{ \@@_Declarator: TheoremGroup }
|
||||||
{ O{} m }
|
{ O{} m }
|
||||||
{
|
{
|
||||||
\groupthm_do_cached:n
|
\@@_lazy:n
|
||||||
{
|
{
|
||||||
\use:c { groupthm_#1 _group:nn } { ##1 } { ##2 }
|
\use:c { groupthm_#1 _group:nn } { ##1 } { ##2 }
|
||||||
}
|
}
|
||||||
|
@ -1857,7 +1874,7 @@
|
||||||
% \begin{macrocode}
|
% \begin{macrocode}
|
||||||
\NewDocumentCommand { \DeclareTheoremGroupRule } { O{??} m m m }
|
\NewDocumentCommand { \DeclareTheoremGroupRule } { O{??} m m m }
|
||||||
{
|
{
|
||||||
\groupthm_do_cached:n
|
\@@_lazy:n
|
||||||
{
|
{
|
||||||
\groupthm_declare_group_rule:nnnn {#1} {#2} {#3} {#4}
|
\groupthm_declare_group_rule:nnnn {#1} {#2} {#3} {#4}
|
||||||
}
|
}
|
||||||
|
@ -1896,7 +1913,7 @@
|
||||||
% \begin{macrocode}
|
% \begin{macrocode}
|
||||||
\NewDocumentCommand { \AddTheoremGroupParent } { m m }
|
\NewDocumentCommand { \AddTheoremGroupParent } { m m }
|
||||||
{
|
{
|
||||||
\groupthm_do_cached:n
|
\@@lazy:n
|
||||||
{
|
{
|
||||||
\groupthm_add_parent:nn { #1 } { #2 }
|
\groupthm_add_parent:nn { #1 } { #2 }
|
||||||
}
|
}
|
||||||
|
@ -1986,9 +2003,10 @@
|
||||||
% \begin{macrocode}
|
% \begin{macrocode}
|
||||||
\NewDocumentCommand { \AppendToTheoremGroup } { O{} m }
|
\NewDocumentCommand { \AppendToTheoremGroup } { O{} m }
|
||||||
{
|
{
|
||||||
\groupthm_do_cached:n {
|
\@@lazy:n
|
||||||
\groupthm_append_to_group:nn { #1 } { #2 }
|
{
|
||||||
}
|
\groupthm_append_to_group:nn { #1 } { #2 }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
% \end{macrocode}
|
% \end{macrocode}
|
||||||
% \end{macro}
|
% \end{macro}
|
||||||
|
@ -2304,13 +2322,13 @@
|
||||||
{ \@@_Declarator: GroupedTheorem }
|
{ \@@_Declarator: GroupedTheorem }
|
||||||
{ s O{} m }
|
{ s O{} m }
|
||||||
{
|
{
|
||||||
\groupthm_do_cached:n
|
\@@_lazy:n
|
||||||
{
|
{
|
||||||
\use:c { groupthm_#1_theorem:nnn }
|
\use:c { groupthm_#1_theorem:nnn }
|
||||||
{ ##2 }
|
{ ##2 }
|
||||||
{ ##3 }
|
{ ##3 }
|
||||||
{ ##1 }
|
{ ##1 }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
% \end{macrocode}
|
% \end{macrocode}
|
||||||
% \end{macro}
|
% \end{macro}
|
||||||
|
@ -2457,13 +2475,13 @@
|
||||||
{ \@@_Declarator: GroupedTheoremFamily }
|
{ \@@_Declarator: GroupedTheoremFamily }
|
||||||
{ s O{} m }
|
{ s O{} m }
|
||||||
{
|
{
|
||||||
\groupthm_do_cached:n
|
\@@_lazy:n
|
||||||
{
|
{
|
||||||
\use:c { groupthm_#1_family:nnn }
|
\use:c { groupthm_#1_family:nnn }
|
||||||
{ ##2 }
|
{ ##2 }
|
||||||
{ ##3 }
|
{ ##3 }
|
||||||
{ ##1 }
|
{ ##1 }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
% \end{macrocode}
|
% \end{macrocode}
|
||||||
% \end{macro}
|
% \end{macro}
|
||||||
|
@ -2581,21 +2599,15 @@
|
||||||
\@@_sort_group_names:
|
\@@_sort_group_names:
|
||||||
\end { __#1__groups_ \clist_use:Nn \l_@@_group_clist { _ } }
|
\end { __#1__groups_ \clist_use:Nn \l_@@_group_clist { _ } }
|
||||||
}
|
}
|
||||||
\bool_if:NT \g_@@_cache_bool
|
% \end{macrocode}
|
||||||
{
|
%
|
||||||
\hook_gput_code:nnn { enddocument / afterlastpage } { groupthm }
|
% Cache this definition for re-runs of \LaTeX.
|
||||||
{
|
%
|
||||||
\iow_now:cn { @auxout }
|
% \begin{macrocode}
|
||||||
{
|
\@@_cache:n
|
||||||
\ExplSyntaxOn
|
{
|
||||||
\hook_gput_code:nnn { @@ / auxfile define cached } { groupthm }
|
\@@_define_family_options:nnnn { #1 } { #2 } { #3 } { #4 }
|
||||||
{
|
}
|
||||||
\@@_define_family_options:nnnn { #1 } { #2 } { #3 } { #4 }
|
|
||||||
}
|
|
||||||
\ExplSyntaxOff
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
% \end{macrocode}
|
% \end{macrocode}
|
||||||
% \end{macro}
|
% \end{macro}
|
||||||
|
@ -2658,7 +2670,7 @@
|
||||||
{ \@@_Declarator: GroupedTheoremFamilyOptions }
|
{ \@@_Declarator: GroupedTheoremFamilyOptions }
|
||||||
{ s O{} m m m }
|
{ s O{} m m m }
|
||||||
{
|
{
|
||||||
\groupthm_do_cached:n
|
\@@_lazy:n
|
||||||
{
|
{
|
||||||
\keys_set:nn { groupthm / theorem ~ family ~ options } { starred ~ version }
|
\keys_set:nn { groupthm / theorem ~ family ~ options } { starred ~ version }
|
||||||
\keys_set:nn { groupthm / theorem ~ family ~ options } { ##2 }
|
\keys_set:nn { groupthm / theorem ~ family ~ options } { ##2 }
|
||||||
|
@ -2697,88 +2709,218 @@
|
||||||
%
|
%
|
||||||
%
|
%
|
||||||
%
|
%
|
||||||
|
% We differentiate between caching and non-caching mode here.
|
||||||
|
% First, we provide some wrappers for writing to the aux file:
|
||||||
%
|
%
|
||||||
%
|
%
|
||||||
% \begin{macro}{\groupthm_do_cached:n}
|
|
||||||
% \begin{syntax}
|
|
||||||
% \cs{groupthm_do_cached:n}\marg{code}
|
|
||||||
% \end{syntax}
|
|
||||||
%
|
|
||||||
% Executes this code lazy at beginning of the document,
|
|
||||||
% iff caching is active.
|
|
||||||
%
|
|
||||||
% At beginning of document, code will be only executed
|
|
||||||
% if the aux file version was too old, otherwise dropped.
|
|
||||||
%
|
%
|
||||||
% \begin{macrocode}
|
% \begin{macrocode}
|
||||||
\cs_new:Npn \groupthm_do_cached:n
|
\bool_if:NTF \g_@@_cache_bool
|
||||||
{
|
{
|
||||||
\bool_if:NTF \g_@@_cache_bool
|
% \end{macrocode}
|
||||||
|
%
|
||||||
|
%
|
||||||
|
% \begin{macro}{\@@_write_auxout:n, \@@_write_auxout:x}
|
||||||
|
%
|
||||||
|
% Immediate write to aux file.
|
||||||
|
%
|
||||||
|
% \begin{macrocode}
|
||||||
|
\cs_new:Npn \@@_write_auxout:n
|
||||||
{
|
{
|
||||||
\hook_gput_code:nnn {@@/document define cached} { groupthm }
|
\iow_now:cn { @auxout }
|
||||||
}
|
}
|
||||||
|
\cs_generate_variant:Nn \@@_write_auxout:n { x }
|
||||||
|
% \end{macrocode}
|
||||||
|
% \end{macro}
|
||||||
|
%
|
||||||
|
%
|
||||||
|
% \begin{macro}{\@@_dump_auxfile:n}
|
||||||
|
%
|
||||||
|
% Dump to auxfile at end of document.
|
||||||
|
% This is used to dump to the aux file at any point of the document
|
||||||
|
% without messing with preamble / document treatment etc.
|
||||||
|
%
|
||||||
|
% \begin{macrocode}
|
||||||
|
\cs_new:Npn \@@_dump_auxfile:n
|
||||||
{
|
{
|
||||||
\use:n
|
\clist_gput_right:Nn \g_@@_dump_auxfile_clist
|
||||||
|
}
|
||||||
|
% \end{macrocode}
|
||||||
|
% \end{macro}
|
||||||
|
|
||||||
|
|
||||||
|
% \begin{macro}{\@@_cache_auxfile:n, \@@_cache_auxfile:V}
|
||||||
|
%
|
||||||
|
%
|
||||||
|
% This also pipes data through the auxfile,
|
||||||
|
% but will cache it to make it available in the next run.
|
||||||
|
%
|
||||||
|
% \begin{macrocode}
|
||||||
|
\cs_new:Npn \@@_cache_auxfile:n
|
||||||
|
{
|
||||||
|
\clist_gput_right:Nn \g_@@_dump_cache_clist
|
||||||
|
}
|
||||||
|
\cs_generate_variant:NN \@@_cache_auxfile:n { V }
|
||||||
|
% \end{macrocode}
|
||||||
|
% \end{macro}
|
||||||
|
|
||||||
|
|
||||||
|
% This handles the dumping to the auxfile at the end of the document:
|
||||||
|
% \begin{macrocode}
|
||||||
|
\hook_gput_code:nnn { enddocument } { groupthm }
|
||||||
|
{
|
||||||
|
% \end{macrocode}
|
||||||
|
% First, perform the regular dump:
|
||||||
|
% \begin{macrocode}
|
||||||
|
\clist_map_function:NN \g_@@_dump_auxfile_clist
|
||||||
|
\_@@_write_auxout:n
|
||||||
|
|
||||||
|
% \end{macrocode}
|
||||||
|
% Now, we want to dump the cached clist, but wrap it into the
|
||||||
|
% the corresponding macro call for storing it in
|
||||||
|
% \cs{g_@@_lazy_auxfile_tl} on re-reading the auxfile.
|
||||||
|
% For this, we have to put two single braces into the auxfile
|
||||||
|
% separately
|
||||||
|
% \begin{macrocode}
|
||||||
|
\_@@_write_auxout:n
|
||||||
|
{
|
||||||
|
\csname tl_gput_right:cn \endcsname
|
||||||
|
{
|
||||||
|
g_@@_lazy_auxfile_tl
|
||||||
|
}
|
||||||
|
}
|
||||||
|
\_@@_write_auxout:x { \str_use:N \c_left_brace_str }
|
||||||
|
% \end{macrocode}
|
||||||
|
% Now, dump the list
|
||||||
|
% \begin{macrocode}
|
||||||
|
\clist_map_function:NN \g_@@_dump_cache_clist
|
||||||
|
\_@@_write_auxout:n
|
||||||
|
|
||||||
|
\_@@_write_auxout:x { \str_use:N \c_right_brace_str }
|
||||||
|
}
|
||||||
|
% \end{macrocode}
|
||||||
|
|
||||||
|
|
||||||
|
% This makes sure that we restore the cache version
|
||||||
|
% on the next run of LaTeX
|
||||||
|
% \begin{macrocode}
|
||||||
|
\_@@_dump_auxfile:x
|
||||||
|
{
|
||||||
|
\ExplSyntaxOn
|
||||||
|
\int_gset:Nn \exp_not:N \g_@@_cache_version_aux_int
|
||||||
|
{
|
||||||
|
\int_use:N \g_@@_cache_version_document_int
|
||||||
|
}
|
||||||
|
\ExplSyntaxOff
|
||||||
|
}
|
||||||
|
% \end{macrocode}
|
||||||
|
%
|
||||||
|
%
|
||||||
|
% We can now provide the two main macros responsible for the caching feature.
|
||||||
|
%
|
||||||
|
% \begin{macro}{\@@_lazy:n}
|
||||||
|
% \begin{syntax}
|
||||||
|
% \cs{@@_lazy:n}\marg{code}
|
||||||
|
% \end{syntax}
|
||||||
|
%
|
||||||
|
% Lazy execution will just append to the corresponding token list
|
||||||
|
%
|
||||||
|
% \begin{macrocode}
|
||||||
|
\cs_new:Npn \@@_lazy:n
|
||||||
|
{
|
||||||
|
\tl_gput_right:Nn \g_@@_lazy_document_tl
|
||||||
}
|
}
|
||||||
}
|
|
||||||
% \end{macrocode}
|
% \end{macrocode}
|
||||||
% \end{macro}
|
% \end{macro}
|
||||||
%
|
%
|
||||||
%
|
%
|
||||||
%
|
%
|
||||||
% This makes sure that at the beginning of the document, after reading
|
|
||||||
% in the aux file with possible precomputed definitions of the last run,
|
|
||||||
% we will execute either the definitions of the auxfile or all the
|
|
||||||
% lazy computation from the current run that we collected.
|
|
||||||
%
|
%
|
||||||
% These hooks should actually be one-time hooks, but this would cause
|
% \begin{macro}{\@@_cache:n}
|
||||||
% problems when \LaTeX rereads the aux file a second time at the end
|
% \begin{syntax}
|
||||||
% of the document, since we want no declarations there
|
% \cs{@@_cache:n}\marg{code}
|
||||||
|
% \end{syntax}
|
||||||
|
%
|
||||||
|
% We have to replace parameter-tokens of category code 6
|
||||||
|
% with regular \enquote{\#} tokens of category code 12
|
||||||
|
% so that we don't double them when writing to the aux file.
|
||||||
|
% See
|
||||||
|
% \href
|
||||||
|
% {https://tex.stackexchange.com/questions/632294/writing-nested-argument-specifier-to-aux-file}
|
||||||
|
% {https://tex.stackexchange.com/questions/632294/writing-nested-argument-specifier-to-aux-file}
|
||||||
|
% for details.
|
||||||
|
%
|
||||||
|
% \begin{macrocode}
|
||||||
|
\cs_new:Npn \@@_cache:n #1
|
||||||
|
{
|
||||||
|
\tl_set:Nn \l_tmpa_tl
|
||||||
|
{
|
||||||
|
{ #1 }
|
||||||
|
}
|
||||||
|
\regex_replace_all:nnN { \cP\# } { \cO\# } \l_tmpa_tl
|
||||||
|
\@@_dump_cache:V \l_tmpa_tl
|
||||||
|
}
|
||||||
|
% \end{macrocode}
|
||||||
|
% \end{macro}
|
||||||
|
%
|
||||||
|
%
|
||||||
|
%
|
||||||
|
% Finally, at the beginning of the document, call the correct code for execution
|
||||||
|
% \begin{macrocode}
|
||||||
|
\hook_gput_code:nnn { begindocument } { groupthm }
|
||||||
|
{
|
||||||
|
\int_compare:nNnTF
|
||||||
|
\g_@@_cache_version_aux_int < \g_@@_cache_version_document_int
|
||||||
|
{
|
||||||
|
\tl_use:N \g_@@_lazy_document_tl
|
||||||
|
}
|
||||||
|
{
|
||||||
|
\tl_use:N \g_@@_lazy_auxfile_tl
|
||||||
|
}
|
||||||
|
}
|
||||||
|
% \end{macrocode}
|
||||||
|
%
|
||||||
|
%
|
||||||
|
% It remains to handle the non-caching case, in which
|
||||||
|
% we only have to define \cs{@@_cache:n} and \cs{@@_lazy:n} to be simple
|
||||||
|
% wrappers.
|
||||||
|
%
|
||||||
|
% \begin{macrocode}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
% \end{macrocode}
|
||||||
|
%
|
||||||
|
%
|
||||||
|
%
|
||||||
|
%
|
||||||
|
%
|
||||||
|
% \begin{macro}{\@@_cache:n}
|
||||||
%
|
%
|
||||||
%
|
%
|
||||||
% \begin{macrocode}
|
% \begin{macrocode}
|
||||||
\hook_gput_code:nnn { begindocument } { groupthm }
|
\cs_set_eq:NN \@@_cache:n \use_none:n
|
||||||
{
|
% \end{macrocode}
|
||||||
\bool_if:nTF
|
% \end{macro}
|
||||||
{
|
%
|
||||||
\g_@@_cache_bool
|
%
|
||||||
&&
|
% \begin{macro}{\@@_lazy:n}
|
||||||
\int_compare_p:n
|
%
|
||||||
{
|
%
|
||||||
\g_@@_cache_version_aux_int < \g_@@_cache_version_document_int
|
%
|
||||||
}
|
% \begin{macrocode}
|
||||||
}
|
\cs_set_eq:NN \@@_lazy:n \use:n
|
||||||
{
|
% \end{macrocode}
|
||||||
\hook_use:n { @@ / document define cached }
|
% \end{macro}
|
||||||
}
|
%
|
||||||
{
|
%
|
||||||
\hook_use:n { @@ / auxfile define cached }
|
% This ends the non-caching case.
|
||||||
}
|
%
|
||||||
|
% \begin{macrocode}
|
||||||
}
|
}
|
||||||
% \end{macrocode}
|
% \end{macrocode}
|
||||||
%
|
%
|
||||||
%
|
%
|
||||||
% This code makes sure that in the next run of \LaTeX, when reading in the aux-file,
|
|
||||||
% before processing the rest of the groupthm aux file macros,
|
|
||||||
% we set the depth of the document cache version available so that we can
|
|
||||||
% query this value in the next run as soon as possible.
|
|
||||||
%
|
%
|
||||||
% \begin{macrocode}
|
|
||||||
\bool_if:NT \g_@@_cache_bool
|
|
||||||
{
|
|
||||||
\hook_gput_code:nnn { enddocument / afterlastpage } { before-groupthm }
|
|
||||||
{
|
|
||||||
\iow_now:cx { @auxout }
|
|
||||||
{
|
|
||||||
\token_to_str:N \ExplSyntaxOn
|
|
||||||
\int_gset:Nn \g_@@_cache_version_aux_int
|
|
||||||
{ \int_use:N \g_@@_cache_version_document_int }
|
|
||||||
\token_to_str:N \ExplSyntaxOff
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
\hook_gset_rule:nnnn { enddocument / afterlastpage } { before-groupthm } { before } { groupthm }
|
|
||||||
% \end{macrocode}
|
|
||||||
%
|
%
|
||||||
%
|
%
|
||||||
% \begin{macrocode}
|
% \begin{macrocode}
|
||||||
|
|
Loading…
Reference in a new issue