14

In nonstandard analysis, the nonstandard extension operator * is used frequently. Typesetting it is not straightforward, though, because the placement of * depends on the symbol to follow. E.g., the nonstandard extension of the reals is written

^*{\mathbb{R}}

whereas the nonstandard extension of a real function X is typically typeset

^*\!{X}

If the negative space \! is not included, the * and the X are spaced too far apart.

How negative spacing looks

I'd like to separate style from content in my LaTeX, but it's not clear how I would define a macro that expanded appropriately given the context. It would seem that I would need two macros—one where I needed a negative space, and another when I didn't. But this seems not much better than adding \! to the code. I've seen posts suggesting the tensor package, but the space is not correct.

EDIT: I've accepted an answer that allows one to specify the appropriate spacing for particular letters. A LuaLateX version is a more flexible version of this idea. The automatic approach is impressive and creative, but doesn't deliver the quality necessary for a professionally typeset document. I'm now inclined to think that an automatic approach is unlikely to suffice without detailed knowledge of the underlying font.

2
  • Did you see tex.stackexchange.com/questions/95878/… ?
    – egreg
    Apr 28, 2015 at 16:24
  • Yes, I saw that. It's useful for other issues, but not this one. The answer by Manuel below get's at the difficulties: X, V, A all need slightly different spacing.
    – Daniel Roy
    Apr 28, 2015 at 21:05

4 Answers 4

8

Until someone comes up with a nice solution, a brute-force one could be:

\documentclass{scrartcl}
\usepackage{xparse,dsfont}

\ExplSyntaxOn
\NewDocumentCommand \nsext { m }
 {
  {\vphantom{#1}}
  \sp
   {
    *
    \str_case:nn {#1}
     {
      { X } { \mskip-3mu }
      { A } { \mskip-6mu }
     }
   }
  #1
 }
\ExplSyntaxOff

\newcommand*{\R}{\mathds{R}}

\begin{document}
$\nsext\R \quad \nsext X \quad \nsext V \quad \nsext A$
\end{document}

You just need to add a pair inside the \str_case:nn second argument if you want to add a new letter and the according space to remove.

enter image description here

8
  • 2
    OK, but I would suggest you use \mkern minus whatever mu, instead of \! Apr 28, 2015 at 18:15
  • That's pretty nice, but will get unwieldy fast due to the case statement, although perhaps that's the price to pay. I'll wait a bit and see if anyone comes up with something else.
    – Daniel Roy
    Apr 28, 2015 at 21:03
  • @AndrewSwann It's already suggested, in an obscure way, though :) May be I will rewrite the answer.
    – Manuel
    Apr 28, 2015 at 21:18
  • @DanielRoy I'm not sure if there's an automatic way of looking inside the glyphs to see if there's room or not (at least for us mortals there's not, may be one of thos TeXnical gods find a way). In any case, I don't think it would be too much work; usually only a few letters (or macros, like \nsext\R) are used in a document, and you just have to add them once in the preamble.
    – Manuel
    Apr 28, 2015 at 21:21
  • @DanielRoy If I recall correctly, looking at glyphs like that is impossible (at least with a direct approach). TeX is only aware of a few font metrics – bounding box, baseline, etc. – necessary to string them together into words, lines, and paragraphs. It doesn't actually know what the character looks like. Apr 29, 2015 at 3:44
7

REVISED APPROACH

Comments from the OP indicated that my original solution, while perhaps nice to look at, relied on changing the math font to ptmx, which was not acceptable. So the issue seemed to be that the math kerning of the ptmx font was OK, but that of ComputerModern (CM) was inadequate for the current task.

With that in mind, I decided to declare the ptmx math alphabet separately, and use it only for positioning of the CM glyphs. EDITED to declare a new math alphabet. Then, when I am stacking the * over/before the given argument, I use the \mathptmx version of the argument (that I just declared) to govern the offset from the right hand.

To account for arguments that are not pure alphabetic glyphs, I start out with a catcode test. In this MWE below, you see my approach on the top line, compared with the raw ComputerModern construction of $^*<letter>$ on the second line.

EDITED (8/2016) to work in subscript math styles, per an e-mail request of a reader. For this, I use the \ThisStyle{...\SavedStyle...} feature of the scalerel package to import the math style to places where it would otherwise be lost. RE-EDITED to \leavevmode to handle use-case in \substack.

\documentclass{article}
\usepackage{amssymb,stackengine,xcolor,scalerel,mathtools}
\stackMath
\def\nsa#1{\leavevmode\ThisStyle{%
\def\stackalignment{r}\def\stacktype{L}%
\ifcat A#1
  \mkern-6.5mu\stackon[0pt]{\SavedStyle\phantom{f}#1}  
    {\SavedStyle^*\mkern-1.1mu\phantom{\mathptmx{#1}}}%
\else
  \mkern-4mu\stackon[0pt]{\SavedStyle\phantom{f}#1}  
    {\SavedStyle^*\mkern-1.7mu\phantom{#1}}%
\fi
}}
\def\R{\mathbb{R}}
\DeclareMathAlphabet{\mathptmx}{OML}{ztmcm}{m}{it}
\parskip 1ex
\begin{document}
\centering
$(\nsa\R) ~ (\nsa V) ~ (\nsa X) ~ (\nsa A) ~ (\nsa M)$

vs.

$(^*\R) ~ (^*V) ~ (^*X) ~ (^*A) ~ (^*M)$

\hrulefill

Other cases requiring EDIT to \textbackslash nsa:

$(x_n)_{n\in\nsa{\mathbb N}}$. 

$\bigcup_{\substack{U\subseteq X\\ \nsa U\subseteq \mathrm{Fin}(\nsa X)}}$
\end{document}

enter image description here

ORIGINAL APPROACH (ptmx math)

This tries to align the * approximately where the right end of an f might be. The first row shows the kerning I was trying to emulate (the model); the second row shows the implemented macro; while the third row shows how the macro succeeds at its goal (the method, with * overlaying right end of f)

\documentclass{article}
\usepackage{amssymb,mathptmx,stackengine,xcolor}
\stackMath
\def\nsa#1{\def\stackalignment{r}\def\stacktype{L}%
  \mkern-1mu\stackon[0pt]{\mkern-2mu\phantom{f}#1}{^*\mkern-1.7mu\phantom{#1}}}
\def\R{\mathbb{R}}
\begin{document}
$ f\R ~fV ~fX ~fA$ The model

$\nsa\R ~ \nsa V ~ \nsa X ~ \nsa A$ The macro

\def\nsa#1{\def\stackalignment{r}\def\stacktype{L}%
  \mkern-1mu\stackon[0pt]{\color{cyan}\mkern-2mu f#1}{^*\mkern-1.7mu #1}}
$\nsa\R ~ \nsa V ~ \nsa X ~ \nsa A$ The method
\end{document}

enter image description here

6
  • 1
    Interesting approach! Apr 29, 2015 at 3:47
  • Unfortunately, using the mathptmx package is a nonstarter. It changes the font of the entire document. I'm attempting a tweak...
    – Daniel Roy
    Apr 29, 2015 at 12:12
  • Unfortunately, in Computer Modern, the letter f and A are spaced quite far apart and so this trick of using f doesn't work. Though perhaps another letter might due the trick.
    – Daniel Roy
    Apr 29, 2015 at 12:18
  • @DanielRoy I see what you mean... the problem is really with the kerning of the underlying math font. Apr 29, 2015 at 12:20
  • @DanielRoy Please see my revision. Apr 29, 2015 at 17:01
5

Here's a LuaLaTeX-based solution, which sets up a Lua function that adjusts the space between the asterisk and the subsequent letter, where the adjustment amount depends on the shape of the letter.

The code defines LaTeX macro named \nsx (short for "nonstandard extension") that prefixes an asterisk to the macro's argument -- typically an uppercase letter; the default spacing adjustment between the asterisk and the letter is -4mu. (A negative thinspace, \!, equals -3mu.) The code next sets up a Lua function that overrides the default adjustment amount for selected letters.

See the table below for the adjustment amounts I've been able to come up with for the 26 uppercase letters of the Latin alphabet as well as for \mathbb{R} and \Gamma. Note that these adjustment amounts are optimized for the "Computer/Latin Modern" math fonts. Other font families will probably require different adjustment amounts.

enter image description here

% !TEX TS-program = lualatex
\documentclass{article}

\newcommand\nsx[2][4]{{}^{*}\mkern-#1mu#2}  % default neg. space: 4mu

\usepackage{amsfonts,array,booktabs} % just for this example

\usepackage{luacode,luatexbase}
\begin{luacode}
function adjust_ns ( line )
    if string.find ( line, "\\nsx" ) then
       line = string.gsub ( line, "\\nsx{([AJ])}", "\\nsx[6.5]{%1}" )
       line = string.gsub ( line, "\\nsx{([X])}", "\\nsx[4.5]{%1}" )
       line = string.gsub ( line, "\\nsx{([SZ])}", "\\nsx[3.5]{%1}" )
       line = string.gsub ( line, "\\nsx{([CGOQUVW])}", "\\nsx[2.5]{%1}" )
       line = string.gsub ( line, "\\nsx{([Y])}", "\\nsx[1.5]{%1}" )
       line = string.gsub ( line, "\\nsx{([T])}", "\\nsx[1]{%1}" )
       line = string.gsub ( line, "\\nsx{\\mathbb{R}}", "\\nsx[1.5]{\\mathbb{R}}" )
       line = string.gsub ( line, "\\nsx{\\Gamma}", "\\nsx[2]{\\Gamma}" )
    end
    return  line
end
luatexbase.add_to_callback ( "process_input_buffer", adjust_ns, "adjust_ns" )
\end{luacode}

\begin{document}

\noindent
\begin{tabular}{@{} >{$}l<{$} l @{}}
$Letter$ & Adjustment (in ``mu'')\\
\midrule
\nsx{B}\nsx{D}\nsx{E}\nsx{F}\nsx{H}\nsx{I}\nsx{K}\nsx{L}\nsx{M}\nsx{N}\nsx{P}
\nsx{R} & 4 (default)\\
\nsx{A}\nsx{J} & 6.5\\
\nsx{X} & 4.5\\
\nsx{S}\nsx{Z} & 3.5\\
\nsx{C}\nsx{G}\nsx{O}\nsx{Q}\nsx{U}\nsx{V}\nsx{W} & 2.5 \\
\nsx{Y} & 1.5 \\
\nsx{T} & 1 \\
\nsx{\mathbb{R}} & 1.5 \\
\nsx{\Gamma} & 2 \\
\end{tabular}
\end{document} 
6
  • Not sure about \mathop (this is understatement, of course).
    – egreg
    Apr 29, 2015 at 7:42
  • @egreg - I was going off the OP's own term -- "nonstandard extension operator" when I chose \ns to be of type mathop. Pls advise if you think there's a more compelling alternative.
    – Mico
    Apr 29, 2015 at 7:55
  • The * is an operator, but not in the same sense of \log, \sin or \sum. It just denotes the unique nonstandard object linked to a standard one. So * should just respect the type of the following symbol. See my answer to the question I linked above for a couple of examples.
    – egreg
    Apr 29, 2015 at 7:58
  • @egreg - Thanks for this explanation. (I had clearly misinterpreted the meaning of "operator"...) I've fixed the code.
    – Mico
    Apr 29, 2015 at 8:37
  • Thanks. I'm not that familiar with lualatex and so I'll have to look into whether, e.g., the journal I'm likely submitting to accepts lualatex. (Every journal in my various fields accepts latex... just not sure about lualatex.) The case statement here does seem to be more flexible than the one proposed by Manuel, but, unless I'm mistaken, the idea is similar.
    – Daniel Roy
    Apr 29, 2015 at 11:50
2

This code also recognizes some types, based on the macro \binrel@: binary operation and relations (no operators, though).

\documentclass{article}
\usepackage{amsmath}
\usepackage{amssymb}

\makeatletter
\DeclareRobustCommand{\nsext}[1]{%
  \binrel@{#1}% compute the type
  \binrel@@{%
    {\vphantom{#1}}^*% the asterisk at the proper height
    \kern-\scriptspace % remove the script space
    \csname mkern@\detokenize{#1}\endcsname % additional kerning
    {#1}% the symbol
  }%
}
\newcommand{\defineextkern}[2]{%
  \@namedef{mkern@\detokenize{#1}}{\mkern#2}%
}
\makeatother

% define some additional kerning
\defineextkern{X}{-3mu}
\defineextkern{\in}{-2mu}

\begin{document}

$x\nsext{\in}\nsext{\mathbb{R}}$

$\nsext{X}_{x\nsext{\in}\nsext{X}}$

\end{document}

enter image description here

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.