The bm package^{∗}

David Carlisle with support by Frank Mittelbach

1996/12/19

1 Introduction

This package defines commands to access bold math symbols. The basic command is \bm which may be used to make the math expresion in its argument be typeset using bold fonts.

The syntax of \bm is: \bm{⟨math expression⟩}

So $\alpha \not= \bm{\alpha}$ produces α ≠ α.

\bm goes to some trouble to preserve the spacing, so that for instance \bm< is a bold < but with the correct \mathrel spacing that TEX gives to <. The calculations that TEX needs to do for \bm can be quite involved and so a definition form is provided.

\DeclareBoldMathCommand[⟨math version⟩]{⟨cmd⟩}{⟨math expression⟩} Defines \cmd to be the bold form of the math expression. The ⟨math version⟩

defaults to ‘bold’ (i.e., \boldmath).

For relatively simple expresions, the resulting definitions are very efficient, for instance after:

\DeclareBoldMathCommand\balpha{\alpha}

\balpha is a single ‘mathchardef’ token producing a bold alpha, and so is just as fast to execute as \alpha.

The above command is mainly intended for use in packages. For occasional use in L^{A}TEX documents, and for compatibility with the plain TEX support for the mathtime fonts, a ‘user-level’ version, \bmdefine is provided that is equivalent to:

\DeclareBoldMathCommand[bold].

If there is a ‘heavy’ math version defined (usually accessed by a user-command \heavymath) then a similar command \hm is defined which access these ‘ultra bold’ fonts. Currently this is probably only useful with the ‘mathtime plus’ font collection. Definitions of commands that use these fonts may be made by specifying the optional argument ‘heavy’ to \DeclareBoldMathCommand. Again an abbreviation, \hmdefine, is provided, equivalent to:

\DeclareBoldMathCommand[heavy].

∗This file has version number v0.9, last revised 1996/12/19.

The command names (but not the implementation) are taken from Michael Spivak’s macros to support the mathtime fonts for plain TEX. In those original

macros, the syntax for \bmdefine was \bmdefine\balpha{\bm\alpha} (with a

nested \bm). This syntax also works with this package.

2 Features

In most cases this package should work in a fairly self explanatory way, but there are some things that might not be obvious.

2.1 Interaction with Math Alphabet Commands

As mentioned above, \bm goes to some trouble to try to make a command that is just like its argument, but using a bold font. This does not always produce the effect that you might expect.

 $1 g \bm{g}$
 $2 \mathrm{g \bm{g}}$
 $3 {g} \bm{{g}}$
 $4 \mathrm{{g} \bm{{g}}}$
 $5 \mathrm{g} \bm{\mathrm{g}}$

produces the following:

1gg 2gg 3gg 4gg 5gg

In math mode ‘g’ is effectively a command that produces the letter ‘g’ from the ‘letters’ alphabet, unless a Math Alphabet command is in effect, in which case the ‘g’ comes from the specified alphabet. \bm{g} makes an equivalent command, but which defaults to a bold letter alphabet. So in the first example \bm{g} is bold math italic, but in the second example the \mathrm applies to both g and \bm{g} in the same way, and so they are both roman.

\bm only inspects the ‘top level’ definitinon of a command, for more complicated expresions, and anything inside a { } group, \bm forces bold fonts by essentially the same (slow) technique used by the AMS \boldsymbol command (but \bm still takes more care of the spacing). So the third example produces identical output to the first (but TEX takes more time producing it).

In the fourth example the \mathrm{\bm{g}} is essentially equivalent to \mathrm{\mbox{\boldmath$g$}}. Currently math alphabet settings are not passed down to ‘nested’ math lists, and so in this example, the \mathrm has no effect, and a bold math italic g is obtained.

Similarly the last example is equivalent to $\mbox{\boldmath$\mathrm{g}$}} and so in this case, one obtains a bold roman g.

2.2 Delimiters

TEX can treat character tokens in two^{1} ways. If there is a preceeding \left or \right it can treat them as a delimiter, otherwise it can treat them as a standard character. For example \left<\right> produces ⟨⟩, which is totally different from <>, which produces <>.

TEX can only do this for character tokens. Commands such as \langle do not act in this way. This means that \bm has to decide whether to treat a character as a delimiter or not. The rule it uses is, it makes a delimiter command for a character if the previous token in the argument was \left or \right. So \left\bm{<} does not work, but \bm{\left<} does.

2.3 No Bold

This package^{2} never uses ‘poor man’s bold’. That is, overprinting the same character in slightly offset positions to give an appearance of boldness. This means that if a suitable bold font is not available, no bold symbol will be produced. In the standard Computer Modern font set, there is no bold ‘large symbols’ font, and so \bm\sum will produce the same weight symbol as \sum. In the ‘mathptm’ and (standard) mathtime font sets there are no bold math fonts, so this package does nothing useful. In the ‘mathtime plus’ font set there are suitable fonts for bold and heavy math setting, and so \bm and \hm work well.

3 Strange failures

In order to get the correct spacing, \bm has to ‘investigate’ the definition of the commands in its argument. It is possible that some strange constructions could ‘confuse’ this investigation. If this happens the L^{A}TEX will almost certainly stop with a strange error. This should not happen with any of the math symbols defined in the base L^{A}TEX or AMS distributions, or any commands defined in terms of those symbols using normal L^{A}TEX math constructs. However if some command does fail to work inside \bm you should always be able to surround it with an extra set of braces \bm{{\cmd}} rather than \bm{\cmd}. \bm will not then attempt to set the correct spacing, so you may need to set it explicitly, for instance, for a relation,

\bm{\mathrel{\cmd}}.

4 Implementation

The commands \bm and \hm work by defining a number of additional symbol fonts corresponding to the standard ones ‘operators’, ‘letters’, ‘symbols’, and ‘largesymbols’. The names for these symbols fonts are produced by prefixing the usual name with ‘bold’ or ‘heavy’.

1Well more than two really.

2Currently, at least.

For maximum flexibility we get the font definitions by looking in the corresponding math versions, i.e., into \mv@bold and if defined into \mv@heavy. This allows us to use this package with any math font setup that has at least a ‘bold’ version defined.

1 ⟨∗package⟩

If there is no bold math version, bail out now before we die in Frank’s fancy font lookup below. Actually \bm and friends could be made to do a \pmb ‘poor man’s bold’ overprinting fudge when no real bold equivalent is available for a given symbol, but that currently is not done.

 2 \ifx\mv@bold\@undefined
 3 \PackageWarningNoLine{bm}
 4  {No Bold Math, \noexpand\bm will do nothing}
 5 \let\bm\@firstofone
 6 \let\hm\@firstofone
 7 \newcommand\DeclareBoldMathCommand[1][]{\newcommand}
 8 \endinput\fi
\bm@setup@symbolfont The \bm@setup@symbolfont defines a new symbol font named #1#2 by looking

for the definition of the symbol font #2 in math version #1. You don’t want to know how it works, do you?

 9 \def\bm@setup@symbolfont#1#2{%
10 \@ifundefined{sym#1#2}{%
11  \def\@tempa{\def\@tempb####1}%
12  \expandafter\@tempa\csname sym#2\endcsname##2##3\@nil{%
13  \expandafter\expandafter\expandafter
14  \split@name\expandafter\@gobble\string##2/\@nil}%
15  \expandafter\expandafter\expandafter
16  \@tempb\csname mv@#1\endcsname\@nil
17  \expandafter\new@mathgroup\csname sym#1#2\endcsname
18  \expandafter\new@symbolfont\csname sym#1#2\endcsname
19  \f@encoding\f@family\f@series\f@shape
20 }{%
21  \PackageWarningNoLine{bm}%
22  {Symbol font #1#2 already defined.\MessageBreak
23  Not overwriting it}}}

At the end of the document preamble reclaim the space taken up by this definition.

24 \@onlypreamble\bm@setup@symbolfont

\symboldoperators Allocate four math groups for the bold fonts for \bm.

25 \bm@setup@symbolfont{bold}{operators}
26 \bm@setup@symbolfont{bold}{letters}
27 \bm@setup@symbolfont{bold}{symbols}
28 \bm@setup@symbolfont{bold}{largesymbols}

\bm@boldmodify The \bm version of \bm@modify. This offset (and the calls to \boldmath) are all that needs changing for \hm. This macro could be defined automatically based on the current font setup, but not done at present.

29 \def\bm@boldmodify#1{%
30 \ifnum\@tempcntb>\symlargesymbols
31 \else
32 \advance\count@"\the\symboldoperators00#1 %
33 \fi}
34 \ifx\mv@heavy\@undefined
35 \else

\symheavyletters Same for heavy (but no heavy operators font). The choice of fonts is hardwired to mathtime, but automatically working out which heavy fonts are available would be tedious, and since only mathtime provides them at present…

36 \bm@setup@symbolfont{heavy}{letters}
37 \bm@setup@symbolfont{heavy}{symbols}
38 \bm@setup@symbolfont{heavy}{largesymbols}

\bm@heavyoffset The offset to use to access the heavy fonts.

39 \count@\symheavyletters
40 \advance\count@-\symletters
41 \edef\bm@heavyoffset{\hexnumber@\count@}
\bm@heavymodify The \hm version of \bm@modify.
42 \def\bm@heavymodify#1{%
43  \advance\count@"%
44  \ifcase\@tempcntb
45  \the\symboldoperators\or
46  \bm@heavyoffset\or
47  \bm@heavyoffset\or
48  \bm@heavyoffset\else
49  0%
50  \fi
51  00#1 }
52 \fi

\mathbf As the bold font has been defined as a symbol font, make \mathbf access that rather than have it allocate a new math group for the same font.

53 \DeclareSymbolFontAlphabet\mathbf{boldoperators}
\bm@general  \bm is pretty much \bmdefine\bm@command followed by executing \bm@command.

It would in principle be possible to execute the emboldened tokens directly, rather than building up a macro first, but (as I learned the hard way) it’s difficult to do this in the midst of all these nested \if constructs. First extract the central bit of code for \hm\bm\hmdefine and \bmdefine. Note that in the case of the inline versions they take an argument and brace it, rather than relying on \bm@general to pick up the argument. This makes the code robust with respect to premature expansion.

54 \def\bm@general#1#2#3#4{%
55 \begingroup

First locally disable \bm and \hm, as they would mess things up terribly, and the original Spivak versions used the syntax \bmdefine\balpha{\bm\alpha}.

56  \let\bm\@empty
57  \let\hm\@empty

Now initialse the commands used to save the tokens constructed.

58  \global\let\bm@command\@empty
59  \let\@let@token\@empty

As we want to expand the macros to look at their definition turn off protection. Otherwise the \protect will be carried over and apply to the wrong token, eg {.

60  \let\protect\@empty
61  \let\@typeset@protect\@empty

Set up either bold or heavy

62  \def\bm@mathchoice{\bm@m@thchoice#1}%
63  \def\bm@group{\bm@gr@up#1}%
64  \let\bm@modify#2%

These two save on the number of \ifx tests below.

65  \let\right\left
66  \let\mskip\mkern

For AMS Definitions

67  \let\DN@\copy
68  \let\FN@\copy
69  \let\next@\copy
70  \global\let\bm@first\@empty

Make sure things like \pounds take the ‘math branch’ even in \bmdefine (which is not executed in math mode).

71  \let\ifmmode\iftrue

The last redefinition just makes \mathit type commands re-insert themselves (more or less) as if they are allowed to expand they die horribly if the expansions are put into \mathchoice and so executed more than once.

72  \def\select@group##1##2##3##4{{%
73  \protect##1{##4}}}%
74  \def\use@mathgroup##1##2##3{{%
75  \protect\use@mathgroup##1{##2}{##3}}}%

So now start looking at the argument.

76  \bm@expand#4\@@end
77 \endgroup

Finally outside the group either execute \bm@command (for \bm) or save its definition (for \bmdefine).

78 #3}

\bm Set up the bold (rather than heavy) version, and run \bm@command right at the end, to execute the emboldened argument.

79 \DeclareRobustCommand\bm[1]{%
80 \bm@general\boldmath\bm@boldmodify\bm@command{#1}}
\DeclareBoldMathCommand \bm@declare  DeclareBoldMathCommand[⟨mathversion⟩]{⟨command⟩}{⟨math expression⟩}

looks like \bm except at the end the specified command is globally \let to \bm@command. The ⟨mathversion⟩ defaults to ‘bold’.

81 \def\DeclareBoldMathCommand{\@testopt\bm@declare{bold}}
82 \def\bm@declare[#1]#2{%
83 \expandafter\bm@general
84  \csname #1math\expandafter\endcsname
85  \csname bm@#1modify\endcsname
86  {\bm@define#2}}
\bmdefine  \bmdefine Shorthand for \DeclareBoldMathCommand[bold].

\bm is empty within the definition, so that either

\bmdefine\balpha{\bm\alpha} or \bmdefine\balpha{\alpha}

may be used. (The former just for compatibility with the original version for plain TEX).

87 \def\bmdefine{\DeclareBoldMathCommand[bold]}
\hm \hmdefine Same again for \hm.
88 \ifx\mv@heavy\@undefined

If there is no heavy math version defined, let \hm be defined as \bm. Currently there is no warning given, perhaps there should be, or even an error?

89 \let\hm\bm
90 \let\heavymath\boldmath
91 \let\bm@heavymodify\bm@boldmodify
92 \else

Otherwise define \hm and \hmdefine in direct analogy with the above.

93 \DeclareRobustCommand\hm[1]{%
94  \bm@general\heavymath\bm@heavymodify\bm@command{#1}}
95 \def\hmdefine{\DeclareBoldMathCommand[heavy]}
96 \fi

\bm@expand \afterassignment trick to fully expand the following tokens until the first nonexpandable token is revealed. This may discard a space token (which is what TEX is looking for) but that doesn’t matter in math mode.

97 \def\bm@expand{\afterassignment\bm@test\count@`\a}%

\bm@test Normally we will grab the non-expandable token as a macro argument but better check it is not { first. Save the previous token so we can check later if it was \left, in which case use the delcode rather than the mathcode if the current token is a character.

98 \def\bm@test{%
99 \let\bm@previous\@let@token
100 \futurelet\@let@token\bm@test@}

\bm@test@ If looking at a single token, switch to \bm@test@token, else if looking at a { } group, grab the whole group with \bm@group. A \bgroup token will take the wrong branch here (currently not trapped).

101 \def\bm@test@{%
102 \ifx\@let@token\bgroup
103  \expandafter\bm@group
104 \else
105  \expandafter\bm@test@token
106 \fi}

\bm@gr@up If faced with a group, If we are in math mode, stick it in a \boldsymbol like construct and then recurse on \bm@expand. Otherwise just use \bfseries\boldmath. The actual test is deferred till ‘run time’. Here and elsewhere could deal with the inner list with an inner call to \bm, but that doesn’t seem to gain very much, and complicates the code quite a bit.

   #1 is either \boldmath or \heavymath.
107 \def\bm@gr@up#1#2{%
108 \bm@add{{\bm@gr@@p#1{#2}}}}
\bm@gr@@p  #1 is either \boldmath or \heavymath.
109 \def\bm@gr@@p#1#2{%
110 \ifmmode
111  \bm@mchoice#1{#2}{#2}{#2}{#2}%
112 \else
113  \bfseries#1#2%
114 \fi}

\bm@test@token If not facing a { } group then test to see what we have. Basic idea: Trap \mathchardef tokens, character tokens, and calls to \mathchar, \mathaccent, etc, and change the math-group (fam) to point at the bold version. Other things just copy straight over to the command being built. (Anything inside a \mathop or similar will end up being made bold as the \mathop will be copied over, but its argument will be made bold by the group code above.

115 \def\bm@test@token#1{%
116 \let\bm@next\@empty

Stop here. Note that it is vital that the terminating token is non-expandable and defined, rather than the usual L^{A}TEX terminators \@nil or \@@. (Worse still would be a ‘quark’ like docstrip’s \qStop.)

117 \ifx#1\@@end

\bm@mathchoice uses macro arguments, so need to make the tail recursion explicit here. All the other cases recurse by way of \afterassignment which means all the trailing \fi are eaten while making the assignment.

118 \else\ifx#1\mathchoice
119  \let\bm@next\bm@mathchoice

The main point: Find these expresions, and change the mathgroup.

120 \else\ifx#1\mathchar
121  \afterassignment\bm@mathchar\count@
122 \else\ifx#1\mathaccent
123  \afterassignment\bm@mathaccent\count@
124 \else\ifx#1\delimiter
125  \afterassignment\bm@delimiter\count@
126 \else\ifx#1\radical
127  \afterassignment\bm@radical\count@

Need to trap spaces otherwise digits will get turned to bold mathchars.

128 \else\ifx#1\mkern
129  \bm@register#1{\muskip\z@}%
130 \else\ifx#1\kern
131  \bm@register#1\dimen@
132 \else\ifx#1\penalty
133  \bm@register#1\count@
134 \else\ifcat\noexpand#1\relax

Other command, look if it’s a mathchardef token (otherwise just add it).

135  \xdef\meaning@{\meaning#1}%
136  \expandafter\bm@mchar@test\meaning@""\@nil#1%

Character token. If it is of catcode 11 or 12, get its mathcode. If that is "80000 bail out and just copy the character else if the previous token was \left or \right, get the delcode instead of the mathcode. This currently means the ′ in a' does not go bold. but you can use a^\prime

137 \else\ifcat.\ifcat a#1.\else#1\fi
138  \ifx\bm@previous\left
139  \count@\delcode`#1%
140  \bm@delimiter
141  \else
142  \count@\mathcode`#1\relax
143  \ifnum\count@=\mathcode`\'%
144  \bm@add{#1}%
145  \else
146  \bm@mathchar
147  \fi
148  \fi
149 \else

And final possibility: a character token of catcode other than 11 or 12.

150  \bm@add{#1}%
151 \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi
152 \bm@next}

\bm@define End code for \bmdefine.Define the given command name to the robust form of

the accumulated code.

If \bm@command is equal to \@gtempa then it is a macro whose expansion is a single call to \mathchar, so that can be optimised with a \mathchardef.

153 \def\bm@define#1{%
154 \begingroup
155  \ifx\bm@command\@gtempa
156  \def\mathchar{\global\mathchardef#1}%
157  \bm@command
158  \else

Rather than simply \let#1\bm@command make the defined command robust. \bm@first is normally empty, but might be something like \DOTSI which needs to be lifted to the top level, in front of any \protect because of the lookahead mechanism used in the amsmath package.

159  \toks@\expandafter{\bm@command}%
160  \xdef#1{\bm@first\noexpand\bm@protect\noexpand#1{\the\toks@}}%
161  \fi
162 \endgroup}

\bm@protect Commands defined by \bmdefine re-insert themselves if protection is enabled.

163 \def\bm@protect#1{%
164 \ifx\protect\@typeset@protect
165  \expandafter\@firstofone
166 \else
167  \protect#1\expandafter\@gobble
168 \fi}
\bm@mchoice  \boldsymbol, more or less. #1 is either \boldmath or \heavymath.
169 \def\bm@mchoice#1#2#3#4#5{%
170 \mathchoice{\hbox{#1$\displaystyle\m@th#2$}}%
171  {\hbox{#1$\textstyle\m@th#3$}}%
172  {\hbox{#1$\scriptstyle\m@th#4$}}%
173  {\hbox{#1$\scriptscriptstyle\m@th#5$}}}

\bm@m@thchoice Action if you find a \mathchoice. Add the bold version to \bm@command then

recurse.

   #1 is either \boldmath or \heavymath.
174 \def\bm@m@thchoice#1#2#3#4#5{%
175 \bm@add{\bm@mchoice#1{#2}{#3}{#4}{#5}}}

\bm@register Combined code for setting up \bm@r@gister with the correct register type.

176 \def\bm@register#1#2{%
177 \def\@tempa{#1\the#2}%
178 \afterassignment\bm@r@gister#2}

\bm@r@gister \mkern itself would transfer to \bm@command without any special test, but any explict dimension following would be converted to \mathchar. So trap this and grab the muskip as a muskip. This is used in \iiint. \penalty was needed for the AMS version of \colon, and so do most of the others as well.

179 \def\bm@r@gister{%
180 \bm@xadd{\@tempa\space}}

\bm@mathchar Change the family (math group) of a mathcode and then use the modified code with \mathchar. Then recurse down the list.

181 \def\bm@mathchar{%
182 \bm@changefam{}%
183 \ifx\bm@command\@empty
184  \xdef\@gtempa{\mathchar\the\count@\space}%
185 \fi
186 \bm@xadd{\mathchar\the\count@\space}}

\bm@add A version of \g@addto@macro that internally uses a \begingroup rather than a brace group, to save creating a mathord. (Perhaps this should be changed in the L^{A}TEX kernel.)

As need to redefine it anyway, save some tokens by making it specific to \bm@command, and to execute \bm@expand to continue the loop.

187 \def\bm@add#1{%
188 \begingroup
189  \toks@\expandafter{\bm@command#1}\xdef\bm@command{\the\toks@}%
190 \endgroup
191 \bm@expand}
\bm@xadd An \xdef version of \bm@add.
192 \def\bm@xadd#1{%
193 \begingroup
194  \toks@\expandafter{\bm@command}\xdef\bm@command{\the\toks@#1}%
195 \endgroup
196 \bm@expand}

\bm@mathaccent \mathaccent version of \bm@mathchar. (Could share code, but needs to be a

 single token, for \afterassignment.
197 \def\bm@mathaccent{%
198 \bm@changefam{}%
199 \bm@xadd{\mathaccent\the\count@\space}}

\bm@delimiter Change both families (math groups) of a delcode and then use the modified code

 with \delimiter.
200 \def\bm@delimiter{%
201 \bm@changefam{}%
202 \bm@changefam{000}%
203 \bm@xadd{\delimiter\the\count@\space}}%
\bm@radical Same for \radical
204 \def\bm@radical{%
205 \bm@changefam{}%
206 \bm@changefam{000}%
207 \bm@xadd{\radical\the\count@\space}}%
\bm@mchar@ Catcode 12 \mathchar, for \ifx tests.
208 \edef\bm@mchar@{\meaning\mathchar}

\bm@mchar@test Test if the \meaning starts with \mathchar. If it does, grab the value into \count@ and call \bm@mathchar, else just copy the command into the accumulated tokens. #1, #2, #3 are all \meaning produced tokens, or ‘dummy tokens’ added at the time this is called. #4 is the original token, in case decide not to use the \meaning.

209 \def\bm@mchar@test#1"#2"#3\@nil#4{%
210 \xdef\meaning@{#1}%
211 \ifx\meaning@\bm@mchar@
212  \count@"#2\relax
213  \bm@mathchar
214 \else

Some other command: copy it straight over. If it is the first thing added, and it is a \relax token, save it in \bm@first for use in bm@define.

215  \ifx\bm@previous\@empty
216  \ifx\relax#4%
217  \gdef\bm@first{#4}%
218  \fi
219  \fi
220  \bm@add{#4}%
221 \fi}

\bm@changefam Pull out one specified hex digit and passes it to \bm@modify to change. argument is empty normally but 000 to access the second math group in a delimiter code.

222 \def\bm@changefam#1{%
223  \@tempcnta\count@
224  \divide\@tempcnta"1000#1 %
225  \multiply\@tempcnta"1000#1 %
226  \@tempcntb\count@
227  \advance\@tempcntb-\@tempcnta
228  \divide\@tempcntb"100#1 %
229  \bm@modify{#1}}

230 ⟨/package⟩