# Universal definition of vertically mirrored triangles on top of each other

In this question, we try to get two unfilled triangles on top of one another, mirrored vertically, as a relation symbol. Here is what we've tried so far:

\documentclass{article}
\pagestyle{empty}
\usepackage{unicode-math}
\usepackage{mathtools}
\setmathfont{XITSMath-Regular.otf}
\usepackage{todonotes}
\newcommand{\hasTypeA}[1]{
\mathrel{\raisebox{.3ex}{\scalebox{.55}{$$\genfrac{}{}{0pt}{3}{\vartriangle}{\triangledown}$$}}}
}
\newcommand{\hasTypeB}[1]{
\mathrel{\raisebox{.3ex}{\scalebox{.55}{$$\genfrac{}{}{0pt}{3}{\triangledown}{\vartriangle}$$}}}
}
\begin{document}\noindent
$$\mathit{var}\hasTypeA\mathit{Type}\ {}^{\mathit{var}\hasTypeA\mathit{Type}}\ {}^{{}^{\mathit{var}\hasTypeA\mathit{Type}}}$$
$\mathit{var}\hasTypeA\mathit{Type}\ {}^{\mathit{var}\hasTypeA\mathit{Type}}\ {}^{{}^{\mathit{var}\hasTypeA\mathit{Type}}}$
$$\mathit{var}\hasTypeB\mathit{Type}\ {}^{\mathit{var}\hasTypeB\mathit{Type}}\ {}^{{}^{\mathit{var}\hasTypeB\mathit{Type}}}$$
$\mathit{var}\hasTypeB\mathit{Type}\ {}^{\mathit{var}\hasTypeB\mathit{Type}}\ {}^{{}^{\mathit{var}\hasTypeB\mathit{Type}}}$
\todo[inline]{%
$$\mathit{var}\hasTypeA\mathit{Type}\ {}^{\mathit{var}\hasTypeA\mathit{Type}}\ {}^{{}^{\mathit{var}\hasTypeA\mathit{Type}}}$$
$\mathit{var}\hasTypeA\mathit{Type}\ {}^{\mathit{var}\hasTypeA\mathit{Type}}\ {}^{{}^{\mathit{var}\hasTypeA\mathit{Type}}}$
$$\mathit{var}\hasTypeB\mathit{Type}\ {}^{\mathit{var}\hasTypeB\mathit{Type}}\ {}^{{}^{\mathit{var}\hasTypeB\mathit{Type}}}$$
$\mathit{var}\hasTypeB\mathit{Type}\ {}^{\mathit{var}\hasTypeB\mathit{Type}}\ {}^{{}^{\mathit{var}\hasTypeB\mathit{Type}}}$
}
\end{document}


Compiling with xelatex yields

As you see, this result suffers from several problems.

First, the two triangles are rather far apart; it would be nicer to have them a little bit closer together at least in \hasTypeA and perhaps in \hasTypeB (but not as close as in ⧖ or ⟠). Second, they don't scale in (sub)subscripts and (super)superscripts. Third, the solution works only for xelatex, and for lualatex it gets ugly, and we'd need to do something different for pdflatex anyway.

While I would probably be able to provide a huge font-dependent definition with \mathpalette, \ifxetex, \ifluatex, stmaryrd, and, if necessary, tikz, it won't be nice or simple. Is there anything universal and simple at the same time, perhaps? Or has anyone done the huge dirty job so far in their papers and would like to share their attempts?

I'm not sure this should be a \mathrel. Anyway, for the script styles I chose to add some sidebearings with \nonscript\mkern-6mu\mkern6mu (the \nonscript only has effect in \displaystyle and \textstyle, so it will cancel out the kerns).

\documentclass{article}

\usepackage{todonotes}
\usepackage{graphicx}
\usepackage{mathtools}
\usepackage{unicode-math}

\setmathfont{XITSMath-Regular.otf}

\makeatletter
\DeclareRobustCommand{\hasTypeA}{%
\mathrel{%
\nonscript\mkern-2mu\mkern2mu
\mathpalette\hasType@AB{\vartriangle\triangledown}%
\nonscript\mkern-2mu\mkern2mu
}%
}
\DeclareRobustCommand{\hasTypeB}{%
\mathrel{%
\nonscript\mkern-2mu\mkern2mu
\mathpalette\hasType@AB{\triangledown\vartriangle}%
\nonscript\mkern-2mu\mkern2mu
}%
}
\newcommand{\hasType@AB}[2]{\hasType@@AB#1#2}
\newcommand{\hasType@@AB}[3]{%
\begingroup
\sbox\z@{$#1x$}%
\resizebox{!}{\ht\z@}{%
\vbox{%
\ialign{%
##\cr
$\m@th#1#2$\cr
\noalign{\nointerlineskip\vskip0.4pt}%
$\m@th#1#3$\cr
}%
}%
}%
\endgroup
}
\makeatother

\begin{document}

$$\mathit{var}\hasTypeA\mathit{Type} \scriptstyle\mathit{var}\hasTypeA\mathit{Type} \scriptscriptstyle\mathit{var}\hasTypeA\mathit{Type}$$

$$\mathit{var}\hasTypeB\mathit{Type} \scriptstyle\mathit{var}\hasTypeB\mathit{Type} \scriptscriptstyle\mathit{var}\hasTypeB\mathit{Type}$$

$$\displaystyle \mathit{var}\hasTypeA\mathit{Type} \scriptstyle\mathit{var}\hasTypeA\mathit{Type} \scriptscriptstyle\mathit{var}\hasTypeA\mathit{Type}$$

$$\displaystyle \mathit{var}\hasTypeB\mathit{Type} \scriptstyle\mathit{var}\hasTypeB\mathit{Type} \scriptscriptstyle\mathit{var}\hasTypeB\mathit{Type}$$

\todo[inline]{$\hasTypeA$}

\end{document}


• @Just_A_Man Reduced the height. Commented Jun 24, 2020 at 15:36
• @Just_A_Man Use \DeclareRobustCommand as in the new code. Commented Jun 24, 2020 at 17:02

If you want to change the gap, edit the 4pt. If you want to change the overall height, change the {X} to something with a different vertical footprint (possibly a \rule expressed in ex measurement)

\documentclass{article}
\usepackage{scalerel,stackengine,tikz}
\usetikzlibrary{shapes.geometric}
\tikzset{
uptri/.style={
draw,
ultra thick,
regular polygon,
regular polygon sides=3,
}
}
\tikzset{
dntri/.style={
draw,
shape border rotate=180,
ultra thick,
regular polygon,
regular polygon sides=3,
}
}
\savestack\uptri{\tikz{\node[uptri]{}}}
\savestack\dntri{\tikz{\node[dntri]{}}}
\DeclareRobustCommand\outtri{\mathrel{\scalerel*{%
\stackengine{4pt}{\dntri}{\uptri}{O}{c}{F}{F}{S}}{X}}}
\DeclareRobustCommand\intri{\mathrel{\scalerel*{%
\stackengine{4pt}{\uptri}{\dntri}{O}{c}{F}{F}{S}}{X}}}
\begin{document}
$x \outtri Type\qquad x \intri Type$

$\scriptstyle x \outtri Type\qquad x \intri Type$

$\scriptscriptstyle x \outtri Type\qquad x \intri Type$
\end{document}


For example, redefining the overall height to the footprint of x rather than X, by way of

\DeclareRobustCommand\outtri{\mathrel{\scalerel*{%
\stackengine{4pt}{\dntri}{\uptri}{O}{c}{F}{F}{S}}{x}}}
\DeclareRobustCommand\intri{\mathrel{\scalerel*{%
\stackengine{4pt}{\uptri}{\dntri}{O}{c}{F}{F}{S}}{x}}}


changes the result thus:

• @Just_A_Man I chose tikz approach because I could easily make triangles with no space buffers above/below. With normal glyphs, there is surrounding space, which can adversely affect the layout of the "stack", especially if multiple math styles (sizes) are involved. Commented Jun 24, 2020 at 16:01
• @Just_A_Man Also, unicode-math precludes the use of pdflatex. Commented Jun 24, 2020 at 16:04
• @Just_A_Man I merely used \DeclareRobustCommand, rather than \newcommand, to make \intri and \outtri work with todonotes. I also used a \savestack rather than \newcommand for the underlying \uptri and \dntri. This saves having to re-render the tikz with each use, but instead saves the typeset image in a savebox. Commented Jun 24, 2020 at 17:31
• @Just_A_Man Your call. Neither of us will be offended, whoever you choose. Commented Jun 25, 2020 at 19:58