summaryrefslogtreecommitdiff
path: root/macros/latex/contrib/semantex
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2020-09-11 03:02:42 +0000
committerNorbert Preining <norbert@preining.info>2020-09-11 03:02:42 +0000
commit026bcd88f082ea4bb3f2ddbac395339309f00a63 (patch)
treecd37f4299d38f8630b60c5c47bd1b60c5851ef98 /macros/latex/contrib/semantex
parent7453287d9233f42e36d981105bc93baf3e2b3a6a (diff)
CTAN sync 202009110302
Diffstat (limited to 'macros/latex/contrib/semantex')
-rw-r--r--macros/latex/contrib/semantex/semantex.pdfbin359206 -> 360914 bytes
-rw-r--r--macros/latex/contrib/semantex/semantex.sty308
-rw-r--r--macros/latex/contrib/semantex/semantex.tex43
-rw-r--r--macros/latex/contrib/semantex/semtex.sty83
-rw-r--r--macros/latex/contrib/semantex/stripsemantex.lua5
-rw-r--r--macros/latex/contrib/semantex/stripsemantex.sty2
6 files changed, 277 insertions, 164 deletions
diff --git a/macros/latex/contrib/semantex/semantex.pdf b/macros/latex/contrib/semantex/semantex.pdf
index 7fc0a4927a..b59654a54c 100644
--- a/macros/latex/contrib/semantex/semantex.pdf
+++ b/macros/latex/contrib/semantex/semantex.pdf
Binary files differ
diff --git a/macros/latex/contrib/semantex/semantex.sty b/macros/latex/contrib/semantex/semantex.sty
index 2da252301b..80825c4d44 100644
--- a/macros/latex/contrib/semantex/semantex.sty
+++ b/macros/latex/contrib/semantex/semantex.sty
@@ -1,5 +1,5 @@
-\RequirePackage{xparse,l3keys2e,semtex,leftindex}
-\ProvidesExplPackage{semantex}{2020/09/08}{0.41beta}{}
+\RequirePackage{xparse,l3keys2e,leftindex}
+\ProvidesExplPackage{semantex}{2020/09/10}{0.42}{}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
@@ -29,6 +29,94 @@
\keys_set:nn { semantex } { #1 }
}
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% THE FOLLOWING SECTION IS IDENTICAL TO THE semtex PACKAGE
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+% These are some essential commands that are needed for bullets and parentheses,
+% and they are the only ones that will not be stripped by running the
+% stripsemantex algorithm. Therefore, they are also available as a standalone
+% package, called "semtex". This name is meant to suggest "stripped SemanTeX",
+% and at the same time, semtex is the name of a plastic explosive, suggesting
+% "blown-up SemanTeX".
+% (Mathematicians are not famous for the quality of their humour.)
+
+% Bullets:
+
+\box_if_exist:NF \g__semantex_bullet_box
+{
+ \box_new:N \g__semantex_bullet_box
+ \hbox_set:Nn \g__semantex_bullet_box { $\cdot$ }
+ \box_scale:Nnn \g__semantex_bullet_box {1.2} {1.2}
+ \tl_set:Nn\g_semantex_bullet
+ {
+ \box_move_up:nn{-0.25ex}{\box_use:N \g__semantex_bullet_box}
+ }
+
+ \tl_set:Nn\g_semantex_double_bullet{\g_semantex_bullet \g_semantex_bullet}
+
+ \tl_set_eq:NN\SemantexBullet \g_semantex_bullet
+
+ \tl_set_eq:NN \SemantexDoubleBullet \g_semantex_double_bullet
+}
+
+% Parentheses:
+
+\cs_set:Npn\SemantexLeft { \mathopen{}\mathclose\bgroup\left }
+
+\cs_set:Npn\SemantexRight { \aftergroup\egroup\right }
+
+\tl_set:Nn\SemantexDelimiterSize{}
+
+\DeclareDocumentCommand\SemantexParentheses { mmmm }
+{
+ \str_case:nnF { #1 } % This is where \big,\Big, etc. go.
+ {
+ { normal } {
+ \group_begin:
+ \tl_clear:N \SemantexDelimiterSize
+ \str_if_eq:nnF { #2 } { . } { \mathopen #2 }
+ #4
+ \str_if_eq:nnF { #3 } { . } { \mathclose #3 }
+ \group_end:
+ }
+ { auto } {
+ \group_begin:
+ \tl_set_eq:NN \SemantexDelimiterSize \middle
+ \SemantexLeft #2
+ #4
+ \SemantexRight #3
+ \group_end:
+ }
+ { * } {
+ \group_begin:
+ \tl_set_eq:NN \SemantexDelimiterSize \middle
+ \SemantexLeft #2
+ #4
+ \SemantexRight #3
+ \group_end:
+ }
+ }
+ {
+ \group_begin:
+ \tl_set_eq:NN\SemantexDelimiterSize #1
+ \mathopen #1 #2
+ #4
+ \mathclose #1 #3
+ \group_end:
+ }
+}
+
+\DeclareDocumentCommand\SemantexNoParentheses { m }
+{
+ \group_begin:
+ \tl_clear:N\SemantexDelimiterSize
+ #1
+ \group_end:
+}
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% THE .semtex FILE
@@ -1830,29 +1918,19 @@
\cs_new_protected:Npn\semantex_right_return:n#1
{
- \semantex_right_indices_return_store:nN { #1 }
- \l__semantex_rightreturn_right_indices_temp
- \semantex_data_tl_put_right:nnx { #1 } { symbol }
- {
- \exp_not:V \l__semantex_rightreturn_right_indices_temp
- }
- \semantex_data_bool_get:nnTF { #1 } { leftargument }
- {
- % do nothing
- }
- {
- \semantex_arg_return_store:nN { #1 } \l__semantex_rightreturn_arg_temp
- \semantex_data_tl_put_right:nnx { #1 } { symbol }
- {
- \exp_not:V
- \l__semantex_rightreturn_arg_temp
- }
- \semantex_data_tl_clear:nn { #1 } { arg }
- \semantex_data_tl_clear:nn { #1 } { prearg }
- \semantex_data_tl_clear:nn { #1 } { postarg }
- \semantex_data_int_clear:nn { #1 } { numberofarguments }
- \semantex_data_bool_set_false:nn { #1 } { nextargwithsep }
- }
+ \semantex_right_index_return:n { #1 }
+ \semantex_right_arg_return:n { #1 }
+}
+
+\cs_new_protected:Npn\semantex_right_pre_return:n#1
+{
+ \semantex_right_indices_pre_return:n { #1 }
+ \semantex_right_arg_pre_return:n { #1 }
+}
+
+\cs_new_protected:Npn\semantex_right_index_return:n#1
+{
+ \semantex_right_indices_pre_return:n { #1 }
\semantex_data_tl_clear:nn { #1 } { upper }
\semantex_data_tl_clear:nn { #1 } { preupper }
\semantex_data_tl_clear:nn { #1 } { postupper }
@@ -1865,30 +1943,17 @@
\semantex_data_int_clear:nn { #1 } { numberoflowerindices }
}
-\cs_new_protected:Npn\semantex_right_pre_return:n#1
+\cs_new_protected:Npn\semantex_right_indices_pre_return:n#1
{
- \semantex_right_indices_return_store:nN { #1 }
+ \_semantex_right_index_return_store:nN { #1 }
\l__semantex_rightreturn_right_indices_temp
\semantex_data_tl_put_right:nnx { #1 } { symbol }
{
\exp_not:V \l__semantex_rightreturn_right_indices_temp
}
- \semantex_data_bool_get:nnTF { #1 } { leftargument }
- {
- % do nothing
- }
- {
- \semantex_arg_return_store:nN { #1 } \l__semantex_rightreturn_arg_temp
- \semantex_data_tl_put_right:nnx { #1 } { symbol }
- {
- \exp_not:V
- \l__semantex_rightreturn_arg_temp
- }
- }
}
-
-\cs_new_protected:Npn \semantex_right_indices_return_store:nN#1#2
+\cs_new_protected:Npn \_semantex_right_index_return_store:nN#1#2
{
\tl_set:Nn#2{}
\semantex_data_int_if_positive:nnTF { #1 } { numberoflowerindices }
@@ -1923,28 +1988,19 @@
\cs_new_protected:Npn\semantex_left_return:n#1
{
- \semantex_left_indices_return_store:nN { #1 }
- \l__semantex_leftreturn_left_indices_temp
- \semantex_data_tl_put_left:nnx { #1 } { symbol }
- {
- \exp_not:V \l__semantex_leftreturn_left_indices_temp
- }
- \semantex_data_bool_get:nnTF { #1 } { leftargument }
- {
- \semantex_arg_return_store:nN { #1 } \l__semantex_leftreturn_arg_temp
- \semantex_data_tl_put_left:nnx { #1 } { symbol }
- {
- \exp_not:V \l__semantex_leftreturn_arg_temp
- }
- \semantex_data_tl_clear:nn { #1 } { arg }
- \semantex_data_tl_clear:nn { #1 } { prearg }
- \semantex_data_tl_clear:nn { #1 } { postarg }
- \semantex_data_int_clear:nn { #1 } { numberofarguments }
- \semantex_data_bool_set_false:nn { #1 } { nextargwithsep }
- }
- {
- % do nothing
- }
+ \semantex_left_index_return:n { #1 }
+ \semantex_left_arg_return:n { #1 }
+}
+
+\cs_new_protected:Npn\semantex_left_pre_return:n#1
+{
+ \semantex_left_indices_pre_return:n { #1 }
+ \semantex_left_arg_pre_return:n { #1 }
+}
+
+\cs_new_protected:Npn\semantex_left_index_return:n#1
+{
+ \semantex_left_indices_pre_return:n { #1 }
\semantex_data_tl_clear:nn { #1 } { upperleft }
\semantex_data_tl_clear:nn { #1 } { preupperleft }
\semantex_data_tl_clear:nn { #1 } { postupperleft }
@@ -1962,28 +2018,17 @@
\semantex_data_tl_clear:nn { #1 } { slantingphantom }
}
-\cs_new_protected:Npn\semantex_left_pre_return:n#1
+\cs_new_protected:Npn\semantex_left_indices_pre_return:n#1
{
- \semantex_left_indices_return_store:nN { #1 }
+ \_semantex_left_index_return_store:nN { #1 }
\l__semantex_leftreturn_left_indices_temp
\semantex_data_tl_put_left:nnx { #1 } { symbol }
{
\exp_not:V \l__semantex_leftreturn_left_indices_temp
}
- \semantex_data_bool_get:nnTF { #1 } { leftargument }
- {
- \semantex_arg_return_store:nN { #1 } \l__semantex_leftreturn_arg_temp
- \semantex_data_tl_put_left:nnx { #1 } { symbol }
- {
- \exp_not:V \l__semantex_leftreturn_arg_temp
- }
- }
- {
- % do nothing
- }
}
-\cs_new_protected:Npn \semantex_left_indices_return_store:nN#1#2
+\cs_new_protected:Npn \_semantex_left_index_return_store:nN#1#2
{
\tl_set:Nn#2{}
\semantex_data_int_if_positive:nnTF { #1 } { numberofupperleftindices }
@@ -2039,8 +2084,109 @@
}
}
+\cs_new_protected:Npn\semantex_right_arg_return:n#1
+{
+ \semantex_data_bool_get:nnTF { #1 } { leftargument }
+ {
+ % do nothing
+ }
+ {
+ \_semantex_arg_return_store:nN { #1 } \l__semantex_rightreturn_arg_temp
+ \semantex_data_tl_put_right:nnx { #1 } { symbol }
+ {
+ \exp_not:V
+ \l__semantex_rightreturn_arg_temp
+ }
+ \semantex_data_tl_clear:nn { #1 } { arg }
+ \semantex_data_tl_clear:nn { #1 } { prearg }
+ \semantex_data_tl_clear:nn { #1 } { postarg }
+ \semantex_data_int_clear:nn { #1 } { numberofarguments }
+ \semantex_data_bool_set_false:nn { #1 } { nextargwithsep }
+ }
+}
+
+\cs_new_protected:Npn\semantex_right_arg_pre_return:n#1
+{
+ \semantex_data_bool_get:nnTF { #1 } { leftargument }
+ {
+ % do nothing
+ }
+ {
+ \_semantex_arg_return_store:nN { #1 } \l__semantex_rightreturn_arg_temp
+ \semantex_data_tl_put_right:nnx { #1 } { symbol }
+ {
+ \exp_not:V
+ \l__semantex_rightreturn_arg_temp
+ }
+ }
+}
+
+\cs_new_protected:Npn\semantex_left_arg_return:n#1
+{
+ \semantex_data_bool_get:nnTF { #1 } { leftargument }
+ {
+ \_semantex_arg_return_store:nN { #1 } \l__semantex_leftreturn_arg_temp
+ \semantex_data_tl_put_left:nnx { #1 } { symbol }
+ {
+ \exp_not:V \l__semantex_leftreturn_arg_temp
+ }
+ \semantex_data_tl_clear:nn { #1 } { arg }
+ \semantex_data_tl_clear:nn { #1 } { prearg }
+ \semantex_data_tl_clear:nn { #1 } { postarg }
+ \semantex_data_int_clear:nn { #1 } { numberofarguments }
+ \semantex_data_bool_set_false:nn { #1 } { nextargwithsep }
+ }
+ {
+ % do nothing
+ }
+}
+
+\cs_new_protected:Npn\semantex_left_arg_pre_return:n#1
+{
+ \semantex_data_bool_get:nnTF { #1 } { leftargument }
+ {
+ \_semantex_arg_return_store:nN { #1 } \l__semantex_leftreturn_arg_temp
+ \semantex_data_tl_put_left:nnx { #1 } { symbol }
+ {
+ \exp_not:V \l__semantex_leftreturn_arg_temp
+ }
+ }
+ {
+ % do nothing
+ }
+}
+
+\cs_new_protected:Npn\semantex_arg_return:n#1
+{
+ \semantex_arg_pre_return:n { #1 }
+ \semantex_data_tl_clear:nn { #1 } { arg }
+ \semantex_data_tl_clear:nn { #1 } { prearg }
+ \semantex_data_tl_clear:nn { #1 } { postarg }
+ \semantex_data_int_clear:nn { #1 } { numberofarguments }
+ \semantex_data_bool_set_false:nn { #1 } { nextargwithsep }
+}
+
+\cs_new_protected:Npn\semantex_arg_pre_return:n#1
+{
+ \semantex_data_bool_get:nnTF { #1 } { leftargument }
+ {
+ \_semantex_arg_return_store:nN { #1 } \l__semantex_leftreturn_arg_temp
+ \semantex_data_tl_put_left:nnx { #1 } { symbol }
+ {
+ \exp_not:V \l__semantex_leftreturn_arg_temp
+ }
+ }
+ {
+ \_semantex_arg_return_store:nN { #1 } \l__semantex_rightreturn_arg_temp
+ \semantex_data_tl_put_right:nnx { #1 } { symbol }
+ {
+ \exp_not:V
+ \l__semantex_rightreturn_arg_temp
+ }
+ }
+}
-\cs_new_protected:Npn \semantex_arg_return_store:nN#1#2
+\cs_new_protected:Npn \_semantex_arg_return_store:nN#1#2
{
\semantex_data_tl_get_store:nnN { #1 } { parsize } \l__arg_return_store_parsize_temp_tl
\semantex_data_bool_get:nnTF { #1 } { par }
@@ -5577,6 +5723,12 @@
{innerreturn}{ execute={ \semantex_inner_return:n { ##1 } } },
{rightreturn}{ execute={ \semantex_right_return:n { ##1 } } },
{leftreturn}{ execute={ \semantex_left_return:n { ##1 } } },
+ {rightindexreturn}{ execute={ \semantex_right_index_return:n { ##1 } } },
+ {leftindexreturn}{ execute={ \semantex_left_index_return:n { ##1 } } },
+ {indexreturn}{ leftindexreturn, rightindexreturn },
+ {rightargreturn}{ execute={ \semantex_right_arg_return:n { ##1 } } },
+ {leftargreturn}{ execute={ \semantex_left_arg_return:n { ##1 } } },
+ {argreturn}{ execute={ \semantex_arg_return:n { ##1 } } },
{parse}{ execute={ \semantex_parse:n { ##1 } } },
{clearcommand}{ execute={ \semantex_data_seq_clear:nn { ##1 } { commands_sequence } } },
{...}{sidots},
diff --git a/macros/latex/contrib/semantex/semantex.tex b/macros/latex/contrib/semantex/semantex.tex
index ca5f0cc8be..a2b7f200f1 100644
--- a/macros/latex/contrib/semantex/semantex.tex
+++ b/macros/latex/contrib/semantex/semantex.tex
@@ -38,7 +38,7 @@
\usepackage[nameinlink]{cleveref}
-\title{Seman\!\TeX: semantic, keyval-based mathematics (v$0.41\beta$)}
+\title{Seman\!\TeX: semantic, keyval-based mathematics (v0.42)}
\date{\today}
\author{Sebastian Ørsted (\href{mailto:sorsted@gmail.com}{sorsted@gmail.com})}
@@ -2357,7 +2357,7 @@ HTML-like syntax, e.g.:
\begin{LTXexample}
$ \GL[order=\vn,field=\vk] $,
$ \Mat[rows=\vm,columns=\vn,
- field=\vk] $,
+ field=\vk] $,
$ \co[d=0,coef=\vR,space=\vX] $
\end{LTXexample}
The \lstinline!parse! routine is a collection of code which is
@@ -2367,6 +2367,15 @@ By default, the parse routine contains no code.
However, you can add code to it using the
key~\mylst!parseoptions={$\<keys\>$}!.
+Even though the \lstinline!parse!~routine is automatically invoked right before rendering, you can also invoke it at any time by force
+using the key~\lstinline!parse!. This will also empty the code from the
+\lstinline!parse!~routine so that it will not be executed twice:
+\begin{LTXexample}
+$ \GL[order=\vn,field=\vk,parse,
+ spar,op] $
+\end{LTXexample}
+(here we used the key~\lstinline!op! from \cref{sec:algebra}).
+
\section{Example: Matrix sets and groups}
Suppose we want to be able to write the group of invertible \( \vn \times \vn \)-matrices with entries in~\( \vk \)
@@ -3426,6 +3435,36 @@ In the following sections, we include the full list.
Invokes the inner return routine.
\item
+ \mylst!leftindexreturn!
+
+ Adds the left indices to the symbol, but not the left argument, if any such exists.
+
+ \item
+ \mylst!rightindexreturn!
+
+ Adds the right indices to the symbol, but not the right argument, if any such exists.
+
+ \item
+ \mylst!indexreturn!
+
+ Adds all indices to the symbol, left and right, but not the argument, if any such exists.
+
+ \item
+ \mylst!leftargreturn!
+
+ Adds the left argument, if any such exists, to the symbol, otherwise does nothing.
+
+ \item
+ \mylst!rightargreturn!
+
+ Adds the right argument, if any such exists, to the symbol, otherwise does nothing.
+
+ \item
+ \mylst!argreturn!
+
+ Adds the argument, if any such exists, to the symbol, otherwise does nothing.
+
+ \item
\mylst!output={$\<Class\>$}!
Sets the output class to~\<Class\>.
diff --git a/macros/latex/contrib/semantex/semtex.sty b/macros/latex/contrib/semantex/semtex.sty
deleted file mode 100644
index 3b9196c361..0000000000
--- a/macros/latex/contrib/semantex/semtex.sty
+++ /dev/null
@@ -1,83 +0,0 @@
-\RequirePackage{xparse}
-\ProvidesExplPackage{semtex}{2020/07/29}{0.1beta}{}
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-% %
-% semtex -- for documents stripped of SemanTeX markup %
-% https://ctan.org/pkg/semantex %
-% (C) 2020 Sebastian Ørsted %
-% sorsted@gmail.com %
-% %
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-% Bullets:
-
-\box_new:N \g__semantex_bullet_box
-\hbox_set:Nn \g__semantex_bullet_box { $\cdot$ }
-\box_scale:Nnn \g__semantex_bullet_box {1.2} {1.2}
-\tl_set:Nn\g_semantex_bullet
-{
- \box_move_up:nn{-0.25ex}{\box_use:N \g__semantex_bullet_box}
-}
-
-\tl_set:Nn\g_semantex_double_bullet{\g_semantex_bullet \g_semantex_bullet}
-
-\tl_set_eq:NN\SemantexBullet \g_semantex_bullet
-
-\tl_set_eq:NN \SemantexDoubleBullet \g_semantex_double_bullet
-
-
-% Parentheses:
-
-\cs_new:Npn\SemantexLeft { \mathopen{}\mathclose\bgroup\left }
-
-\cs_new:Npn\SemantexRight { \aftergroup\egroup\right }
-
-\tl_new:N\SemantexDelimiterSize
-
-\DeclareDocumentCommand\SemantexParentheses { mmmm }
-{
- \str_case:nnF { #1 } % This is where \big,\Big, etc. go.
- {
- { normal } {
- \group_begin:
- \tl_clear:N \SemantexDelimiterSize
- \str_if_eq:nnF { #2 } { . } { \mathopen #2 }
- #4
- \str_if_eq:nnF { #3 } { . } { \mathclose #3 }
- \group_end:
- }
- { auto } {
- \group_begin:
- \tl_set_eq:NN \SemantexDelimiterSize \middle
- \SemantexLeft #2
- #4
- \SemantexRight #3
- \group_end:
- }
- { * } {
- \group_begin:
- \tl_set_eq:NN \SemantexDelimiterSize \middle
- \SemantexLeft #2
- #4
- \SemantexRight #3
- \group_end:
- }
- }
- {
- \group_begin:
- \tl_set_eq:NN\SemantexDelimiterSize #1
- \mathopen #1 #2
- #4
- \mathclose #1 #3
- \group_end:
- }
-}
-
-\DeclareDocumentCommand\SemantexNoParentheses { m }
-{
- \group_begin:
- \tl_clear:N\SemantexDelimiterSize
- #1
- \group_end:
-} \ No newline at end of file
diff --git a/macros/latex/contrib/semantex/stripsemantex.lua b/macros/latex/contrib/semantex/stripsemantex.lua
index ba3eb9f2da..1ebce1f716 100644
--- a/macros/latex/contrib/semantex/stripsemantex.lua
+++ b/macros/latex/contrib/semantex/stripsemantex.lua
@@ -195,6 +195,11 @@ semantexIDluacommand = function(id, source, output)
output = output:gsub('\\mathclose \\rvert', '\\rvert')
output = output:gsub('\\mathopen \\lVert', '\\rVert')
output = output:gsub('\\mathclose \\rVert', '\\rVert')
+ output = output:gsub('%^{\\prime }', '\'')
+ output = output:gsub('%^{\\prime \\prime }', '\'\'')
+ output = output:gsub('%^{\\prime \\prime \\prime }', '\'\'\'')
+ output = output:gsub('%^{\\prime \\prime \\prime \\prime }', '\'\'\'\'')
+ output = output:gsub('%^{\\prime \\prime \\prime \\prime \\prime }', '\'\'\'\'\'')
output = output:gsub('%s+%f[{}%[%]%(%)%$,]','')
output = output:gsub('([}%]%)])%f[\\%w%+%-%(%[=]', '%1 ')
diff --git a/macros/latex/contrib/semantex/stripsemantex.sty b/macros/latex/contrib/semantex/stripsemantex.sty
index 96c40fdb87..19d3bc7db4 100644
--- a/macros/latex/contrib/semantex/stripsemantex.sty
+++ b/macros/latex/contrib/semantex/stripsemantex.sty
@@ -1,5 +1,5 @@
\RequirePackage{xparse}
-\ProvidesExplPackage{stripsemantex}{2020/09/05}{0.1alpha}{}
+\ProvidesExplPackage{stripsemantex}{2020/09/10}{0.42}{}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %