非標準分析: コンテキストに応じて `^*` をタイプセットする

非標準分析: コンテキストに応じて `^*` をタイプセットする

非標準解析では、非標準拡張演算子 * が頻繁に使用されます。ただし、 * の位置は後続の記号に依存するため、タイプセットは簡単ではありません。たとえば、実数の非標準拡張は次のように記述されます。

^*{\mathbb{R}}

一方、実関数Xの非標準拡張は、典型的には

^*\!{X}

ネガティブスペース\!が含まれていない場合、* と X の間隔が離れすぎてしまいます。

ネガティブスペースの見え方

LaTeX でスタイルとコンテンツを分離したいのですが、コンテキストに応じて適切に拡張されるマクロをどのように定義すればよいかわかりません。2 つのマクロが必要になるようです。1 つは負のスペースが必要な場所で、もう 1 つは必要ない場合です。しかし、これは\!コードに追加するよりもあまり良くないようです。パッケージを提案する投稿を見たことがありますtensorが、スペースが正しくありません。

編集: 特定の文字に適切な間隔を指定できる回答を受け入れました。LuaLateX バージョンは、このアイデアのより柔軟なバージョンです。自動アプローチは印象的で創造的ですが、プロがタイプセットしたドキュメントに必要な品質は提供されません。今では、基礎となるフォントの詳細な知識がなければ、自動アプローチでは十分ではないと考えるようになりました。

答え1

誰かが良い解決策を思いつくまでは、次のような強引な方法があるかもしれません。

\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}

\str_case:nn新しい文字とそれに対応する削除するスペースを追加する場合は、2 番目の引数内にペアを追加するだけです。

ここに画像の説明を入力してください

答え2

改訂されたアプローチ

OP からのコメントによると、私の最初の解決策は、見た目は良いかもしれませんが、数学フォントを ptmx に変更することに依存しており、これは受け入れられないものでした。したがって、問題は、ptmx フォントの数式カーニングは問題ないが、ComputerModern (CM) のカーニングが現在のタスクには不十分であるということのようです。

それを念頭に置いて、私はptmx数学アルファベットを別途宣言することに決めました。CMグリフの配置にのみ使用します. 新しい数学アルファベットを宣言するように編集しました。次に、*指定された引数の上/前にスタックするときに、\mathptmx引数のバージョン (宣言したばかり) を使用して、右側からのオフセットを制御します。

純粋なアルファベットのグリフではない引数を考慮するために、まず catcode テストから始めます。以下の MWE では、一番上の行に私のアプローチを示し、$^*<letter>$2 行目には生の ComputerModern 構造を示します。

読者からの電子メールによるリクエストに応じて、下付き数式スタイルで動作するように編集しました (2016 年 8 月)。このために、パッケージ\ThisStyle{...\SavedStyle...}の機能を使用して、そうでなければ失われる場所に数式スタイルをインポートします。の使用ケースを処理できるようscalerelに再編集しました。\leavevmode\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}

ここに画像の説明を入力してください

オリジナルアプローチ (ptmx 数学)

これは、* を f の右端がどこにあるかおおよそ揃えようとします。最初の行は、私がエミュレートしようとしていたカーニング (モデル) を示しています。2 行目は実装されたマクロを示しています。3 行目は、マクロが目標を達成する方法 (*の右端を重ねた方法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}

ここに画像の説明を入力してください

答え3

これは LuaLaTeX ベースのソリューションです。アスタリスクと後続の文字の間のスペースを調整する Lua 関数を設定します。調整量は文字の形状によって異なります。

このコードは、\nsxマクロの引数の前にアスタリスク (通常は大文字) を付ける という名前の LaTeX マクロを定義します-4mu。アスタリスクと文字の間のデフォルトの間隔調整は です (負の薄いスペース\!は に等しい-3mu)。次に、このコードは、選択した文字のデフォルトの調整量をオーバーライドする Lua 関数を設定します。

\mathbb{R}ラテン アルファベットの 26 個の大文字と、およびについて私が考え出した調整量については、以下の表を参照してください。\Gammaこれらの調整量は、「Computer/Latin Modern」数学フォント用に最適化されていることに注意してください。他のフォント ファミリでは、おそらく異なる調整量が必要になります。

ここに画像の説明を入力してください

% !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} 

答え4

このコードは、マクロに基づいて\binrel@、バイナリ演算と関係(ただし演算子はなし)などのいくつかの型も認識します。

\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}

ここに画像の説明を入力してください

関連情報