# Derived tensor product

I tried to write derived tensor products using semantex (copied from p. 27 in the manual).

\documentclass{article}

\usepackage{amsmath,semantex}

\NewSymbolClass\MyBinaryOperator[
define keys={
{Lder}{upper=L},
{Rder}{upper=R},
},
]
\NewObject\MyBinaryOperator\tensor{\otimes}[
define keys={
{der}{Lder},
},
]
\NewObject\MyBinaryOperator\fibre{\times}[
% Americans are free to call it \fiber instead
define keys={
{der}{Rder},
},
]

\begin{document}

$$A\tensor[R,der] B$$

\end{document}


But I would like the L to appear on top of the tensor symbol instead of to the right. Is this possible?

Thanks!

• Is my question unclear? I'm new to this site so just tell me if I can write it better. :) Nov 15 '20 at 13:17
• Use \overset{\tensor}{L}. Nov 15 '20 at 15:41
• @azetina Thanks for your answer! But is it possible to make it a key like above so I can still write \tensor[R,der]? Nov 15 '20 at 15:46
• Yes. Use command command=\overset{L}. Nov 15 '20 at 16:23

Here is a MWE using semantex. The idea is to use the command key and input the desired command. In this case, you want to over set the L on the symbol. Thus, using command=\overset{L} will suffice.

\documentclass{article}

\usepackage{amsmath,semantex}

\NewSymbolClass\MyBinaryOperator[
define keys={
{Lder}{command=\overset{L}},
{Rder}{upper=R},
},
]
\NewObject\MyBinaryOperator\tensor{\otimes}[
define keys={
{der}{Lder},
},
]
\NewObject\MyBinaryOperator\fibre{\times}[
% Americans are free to call it \fiber instead
define keys={
{der}{Rder},
},
]

\begin{document}

$$A\tensor[R,der] B$$

\end{document}

• Thanks, this was exactly what I wanted! :) Nov 15 '20 at 18:05
• Note that @egreg solution and Alan Xiang are also viable and robust. Nov 15 '20 at 18:10

I don't know how to do it with semantex, but it's not difficult with other tools.

\documentclass{article}
\usepackage{amsmath}
%\usepackage{xparse} % not needed with LaTeX 2020-10-01 or later

\ExplSyntaxOn

\keys_define:nn { cinque/tensor }
{
der .tl_set:N = \l__cinque_tensor_upper_tl,
der .default:n = L,
unknown .code:n = \tl_set_rescan:Nnx \l__cinque_tensor_subscript_tl { } { \l_keys_key_str },
}
\tl_new:N \l__cinque_tensor_subscript_tl

\NewDocumentCommand{\tensor}{O{}}
{
\group_begin:
\keys_set:nn { cinque/tensor } { #1 }
\tl_if_empty:NTF \l__cinque_tensor_upper_tl
{ \otimes }
{ \overset{\l__cinque_tensor_upper_tl}{\otimes} }
\tl_if_empty:NF \l__cinque_tensor_subscript_tl { \sb{\l__cinque_tensor_subscript_tl} }
\group_end:
}

\ExplSyntaxOff

\begin{document}

$A\otimes B$

$A\tensor B$

$A\tensor[R] B$

$A\tensor[der,R] B$

$A\tensor[R,der] B$

$A\tensor[\mathcal{X}] B$

\end{document}


• What does \sb mean? Nov 15 '20 at 16:30
• @azetina It's an alias for _; needed because _ doesn't mean “subscript” in the scope of \ExplSyntaxOn Nov 15 '20 at 16:45
• @egreg When I wrote semantex, I tried using the \tl_set_rescan:Nnn trick, but ran into issues since some math did not come out as expected after being turned into a string and rescanned. This (and a few other things) prompted me to build my own, separate keyval system (using \keyval_parse:NNn). I never quite figured out the pattern of what code survived the string-ification and rescan. Maybe you can enlighten me? Nov 15 '20 at 16:56
• @Gaussler I have no idea of what will turn out to be useful. I'd just do \NewDocumentCommand{\dertensor}{o}{\overset{L}{\otimes}\IfValueT{#1}{_{#1}}} which is simple and effective. Nov 15 '20 at 17:07
• @egreg Yes, but it’s sometimes hard to properly control your notation from the preamble. Imagine you make a command \stalk for stalks of a sheaf at a point so that \stalk{#1}{#2} produces #1_{#2}. Applying it to \mathcal{O}_{X}, and you get a double subscript error. I prefer a keyval-based solution where I can write \sheafF[\vX, stalk=\primep] (with \vX meaning “variable X” and \primep being the prime ideal fraktured p) and make it stack the subscripts according to a preprogrammed procedure. Nov 15 '20 at 17:12

\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage{xparse}
\usepackage{expl3}
\usepackage{amsmath}

\ExplSyntaxOn
\clist_new:N \l_doc_tmpa_clist
\tl_new:N \l_doc_tmpa_tl
\tl_new:N \l_doc_tmpb_tl

\tl_new:N \g_doc_template_a_tl
\tl_gset:Nn \g_doc_template_a_tl {
\overset{\tiny L}{*1}
}

\cs_generate_variant:Nn \tl_set_rescan:Nnn {NnV}

\DeclareDocumentCommand{\tensor}{O{}}{
\clist_set:Nn \l_doc_tmpa_clist {#1}
\tl_set:Nn \l_doc_tmpa_tl {\otimes}

\clist_map_inline:Nn \l_doc_tmpa_clist {
\str_case:nn {##1}{
{der} {
\tl_set_eq:NN \l_doc_tmpb_tl \g_doc_template_a_tl
\regex_replace_once:nnN {*1} {\u{\l_doc_tmpa_tl}} \l_doc_tmpb_tl
\tl_set_eq:NN \l_doc_tmpa_tl \l_doc_tmpb_tl
}
}
}

\clist_map_inline:Nn \l_doc_tmpa_clist {
\str_case:nn {##1}{
{R} {
\tl_set:No \l_doc_tmpa_tl {\l_doc_tmpa_tl \c_math_subscript_token {R}}
}
}
}

\mathbin{\tl_use:N \l_doc_tmpa_tl}
}
\ExplSyntaxOff

\begin{document}

\par $a \tensor[R] b$
\par $a \tensor[R,der] b$
\par $a \tensor[der] b$
\end{document}