The ionumbers package ∗
Christian Schneider
<software(at)chschneider(dot)eu>
April 14, 2014
Warning: Use with caution and on your own risk! Check output!
Contents
1 Details of number handling 2
1.1 General rules . . . 2
1.2 Caveats . . . 2
2 Conflicts with other packages 3 3 Usage 4 3.1 Package options concerning the separators in the input . . . 4
3.2 Package options concerning the separators in the output . . . 4
3.3 Package options concerning automatic grouping . . . 5
3.4 Local style changes . . . 5
3.5 User-defined values for output separators . . . 6
3.6 Enabling and disabling features . . . 6
4 License 6 5 Acknowledgements 7 6 Bugs, problems, and suggestions 7 7 Implementation 7 7.1 Default/global configuration . . . 7
7.2 Local style changes . . . 8
7.3 User-defined values for output separators . . . 9
7.4 Internal macros holding definitions forhkeyi=hvalueipairs . . . 10
7.5 Enabling and disabling features . . . 12
7.6 Definitions of active characters . . . 13
7.7 Test for conflicts with other packages . . . 21
7.8 Commands for current number . . . 22
∗This document corresponds to ionumbers v0.3.3, dated 2014/04/06. Copyright 2007–2009,2011,2012,2014 Christian Schneider <software(at)chschneider(dot)eu>, http://
chschneider.eu.
Abstract ionumbersstands for ‘input/output numbers’.
This package restyles numbers in math mode. If a number in the input file is written, e.g., as$3,231.44$as commonly used in English texts, this package is able to restyle it to be output as ‘3 231,44’ as commonly used in German texts (and vice versa). This may be very useful, if you have a large table and want to include it in texts with different output conventions without the need of changing the table.
Furthermore this package can automatically group digits left to the deci- mal separator (thousands) and right to the decimal separator (thousandths) without the need of specifing commas (English) or points (German) as sepa- rators. E.g., the input$1234.567890$can be output as ‘1 234.567 890’. By default, thousands/thousandths are grouped in triplets, but the grouping length is configurable, which is useful for numerical data.
Finally, an e starts the exponent of the number. For example, $21e6$
may be output as ‘26×106’.
1 Details of number handling
1.1 General rules
Every inputin math mode consisting of the following characters is treated by this package: .,+-0123456789. These characters get macro definitions. A number is any combination of these characters without anything—not even white spaces—in between them. There are two exceptions/special cases:
1. The separator characters. and, are not treated as part of the number at its end. This avoids problems with comma-separated lists (see below).
2. The sign characters +and- will only be considered as part of the number, if they appear at the begining of a number.
The lower case lettereplays a special role. Aneimmediatly following a number (as defined above) can be configured as begining of the exponential part. The letter ewill be eaten from the input in this case and substituted by some configurable output. The next number following this e in the same group (even with other characters inbetween the e and the number) will be treated as exponential part and grouped with curly braces {}.
It is a good practice to always add a space before/after each number such that ionumbersknows the beginning/end of a number and does not misinterpret other input as part of it. Below, you will find a couple of examples that might lead to surprising output, if this rule is not followed.
1.2 Caveats
Comma-separated lists of numbers must be input with a space after each comma to prevent , to be treated as part of the number. An example is the list 1, 2, 3, \ldots, where the commas are not part of in the numbers. Note, however, that the commas are treated as part of the numbers in the first two ap- pearances in 1,2,3,\ldots, as the commas are immediately followed by a digit.
Depending on the configuration, this may lead to strange spaces between the numbers, disappearing commas etc.
If you useindexes consisting of four or more digits together with automatic grouping of thousands, the grouping will also apply to the indexes. Soa_{1234}
might be output as a1,234. The simplest way to prevent undesired automatic grouping is to insert a space after each digit, ẹ g., as in a_{1 2 3 4}.
Please be aware that the first decimal separator of a number marks the be- gining of the thousandths part of a number; every part of a number appearing left to the first decimal separator is the thousands part. That is why, the input
$1.234.567$ with (only) the package option autothousandths=true (. is the decimal separator; options will be explained later) will lead to ‘1.234.567’ in the output. Note the small space after the second point as a result of 234.567 be- ing treated as thousandths part. The thousandths separator—by default a small space—will be output between the third and fourth digit of the thousandths part;
the ađitional point from the input will not be omitted. The input issyntactically incorrect (there must not be two decimal separators in one number!) and the output isnot a bug.
The number following anewhich has started the exponential part is treated as exponential part, even if there is arbitrary input inbetween. Hence, the input
$1e \Pi 2 with package option exponent=timestento (will be explained later) leads to a superscript 2 in the output. In some cases, ẹ g., $1e \sqrt 2$ or
$1ê2$witheconfigured as begining of the exponential part, even an error occurs.
Again, the input issyntactically incorrect and you might want to preventefrom being treated as start of the exponential part by ađing a space: $1 e \sqrt 2$
or$1 ê2$.
In some rare cases, ẹ g.,$\sqrt ,$or $ậ$, the usage of point and comma without curly braces {}around them will lead to an error. In these cases please ađ curly braces{}around the point or commạ (Thezifferpackage has the same problem, by the waỵ)
2 Conflicts with other packages
This package potentially conflicts with any other package that defines a macro for any of the following characters: .,+-0123456789
There are tests for these cases and warning or error messages may be output.
Please load ionumbers as last package to be able to detect as many conflicts as possiblẹ As there is no way to detect conflicts in any case, please report any package known to conflict withionumbersto the author.
Packages known to conflict withionumbersare:
ziffer this package can be replaced byionumbers except forzif- fer’s special handling of--enabled by\ZifferStrichAn dcolumn workaround: disable ionumbers for tabulars (ẹ g., put
them inside\ionumbersoff{h. . .i})
amsmath/amsopn load ionumbersas last package and disable ionumbers for
\operatorname{h. . .i}(ẹ g., put it inside
\ionumbersoff{h. . .i})
3 Usage
Package options are used to globally configure a default behaviour of ionumbers for the whole document. These options usually consist of a hkeyi=hvaluei pair.
Local changes from this global configuration for arbitrary parts of the document can be applied with special commands.
3.1 Package options concerning the separators in the input
The following options configure the meaning of separators in the LATEX input file:
comma=hvaluei comma ‘,’ will be treated ashvaluei point=hvaluei point ‘.’ will be treated ashvaluei The followinghvalueis can be chosen for both of them:
ignore the separator will be ignored (no output)
decimal decimal separator (separating the thousands from the thousandths part of a number)
thousands thousands separator (used for grouping of thousands part) default default behaviour ofionumbers(decimalforpoint;thousands
forcomma)
The separator for exponents is always the lowercase lettere. A thousandths separator does not exist in input files; such a separator will only be output, if automatic grouping of the thousandths part is enabled (see below).
3.2 Package options concerning the separators in the output
The previously described options assign ameaning to separators in the input file.
Theoutput of themeanings is configured via the following options:
thousands=hvaluei thousands separator will be output ashvaluei decimal=hvaluei decimal separator will be output ashvaluei thousandths=hvaluei thousandths separator will behvaluei
exponent=hvaluei exponent separator will be output ashvaluei The list of validhvalueis forthousands,decimal, andthousandthsis:
none will be ignored (no output)
point normal point; this is the default point withoutionumbers comma normal comma
punctpoint punctuation point (point followed by small space) punctcomma punctuation comma (point followed by small space); this
is the default comma withoutionumbers
apostrophe apostrophe (actually$^\prime$;not fordecimal) phantom space with width of a point ($\phantom{.}$; not for
decimal)
space small space ($\,$;not fordecimal)
default default behaviour ofionumbers(punctcommaforthousands;
pointfordecimal;spaceforthousandths)
If a number is handled as exponent, it will be put into curly braces {} for correct output of, e. g., signs without spacing around them (mathord). In the following list of valid hvalueis forexponent a number immediatly following ane will be handled as exponent, unless specified otherwise:
none will be ignored (not output; following numbernothandled as exponent)
original a simple character ‘e’ (following number not handled as exponent)
ite/itE italic lower/upper case letter ‘e’
rme/rmE roman lower/upper case letter ‘e’
timestento $\times10\,$ with following number output as super- script
cdottento $\cdot10\,$with following number output as superscript wedge $^\wedge$
default default behaviour of ionumbers(original)
3.3 Package options concerning automatic grouping
Automatic grouping is a feature that automatically adds the thousands and thou- sandths separator, respectively. The separator will by default be added after each triplet of digits, but this may be changed (see below). Automatic grouping can be enable or disabled with the following options:
autothousands=hvaluei automatic grouping of thousands (digits left to decimal separator)
autothousandths=hvaluei automatic grouping of thousandths (digits right to decimal separator)
The grouping length for the thousands and thousandths, respectively, can be changed be the following options:
grplenthousands=hnumberi group lengths for thousands (hnumberi must be smaller than10; defaults to3)
grplenthousandths=hnumberi group lengths for thousandths (hnumberi must be smaller than10; defaults to3)
The availablehvalueis aretrue andfalse(default).
Notes on automatic grouping:
1. Grouping of thousandths requires autothousandths=true in any case, as there is no thousandths separator for explicitly specifing separations in the input.
2. Automatic grouping of thousands will be skipped in a number, if it contains a thousands separator in the input.
3.4 Local style changes
The command\ionumbersstyle{hoption listi}changes the global style definitions
\ionumbersstyle
as specified as package options for the rest of the group. The hoption listi may contain any of the package options described in sections 3.1–3.3. An additional
hvaluei for allhkeyis is available inside \ionumbersstyle to switch back to the configuration specified as package options: reset.
The command\ionumbersresetstyleresets allhvalueis to the configuration
\ionumbersresetstyle
specified as package options. Actually, it is only a shorthand for
\ionumbersstyle{comma=reset,point=reset,decimal=reset,...}.
3.5 User-defined values for output separators
A user may specify further output separators. Any user-defined hvalueis for thousands, decimal, thousandths, andexponent can be used like the built-in options in section 3.2.
The command\newionumbersthousands{hvaluei}{hdefinitioni}has two manda-
\newionumbersthousands
\newionumbersdecimal
\newionumbersthousandths
\newionumbersexponent
tory arguments. The first one is the name of the newly defined hvaluei for the thousands hkeyi and the second one its definition. The commands
\newionumbersdecimal,\newionumbersthousandths, and\newionumbersexponent work the same way for thedecimal, thousandths, and exponenthkeyi, respec-
tively. There is a starred version of\newionumbersexponent(called\newionumbersexponent*) that typesets the following number as superscript.
To redefine an existing hkeyi definition there are \renew... versions of the
\renewionumbersthousands
\renewionumbersdecimal
\renewionumbersthousandths
\renewionumbersexponent
previously described commands.
Notes on definitions:
1. Allhdefinitionis are set inside\ionumbersoff(see section 3.6). This means that numbers appearing in thehdefinitionis are not treated by this package.
2. The valuecurrhas an internal meaning and shouldnotbe defined/redefined by the user.
3.6 Enabling and disabling features
The command\ionumbersmakes comma, point, signs, and digits active in math
\ionumbers
mode. This is equivalent to enabling the features of this package. This command applies to the end of the current group.
To disable the features by making comma, point, signs, and digits inactive
\endionumbers
again the command \endionumbers can be used. This command applies to the end of the current group.
The command\ionumbersoff{hstuffi}disables the features only forhstuffi.
\ionumbersoff
4 License
ionumbersis free software: you can redistribute it and/or modify it under the terms of the GNU General Public License version 3 as published by the Free Software Foundation, not any later version.
ionumbers is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with ionumbers. If not, see<http://www.gnu.org/licenses/>.
5 Acknowledgements
The idea and parts of this package are based on ziffer.sty v2.1 by Martin V¨ath
Furthermore the\l@addto@macro(with changed name) fromkoma-script bun- dlev2.9t by Markus Kohm and Frank Neukam is used in this package.
Thanks to Martin V¨ath and Markus Kohm for permitting to use their code in this package.
6 Bugs, problems, and suggestions
Please report bugs and problems or send suggestions for this package to Christian Schneider. Check for updates before reporting bugs at the website mentioned above. Donot bother Martin V¨ath, Markus Kohm, or Frank Neukam with bugs, problems or suggestions concerning this package!
7 Implementation
The implementation is briefly described in this section. First of all, we need the keyvalpackage forhkeyi=hvalueioptions:
1\RequirePackage{keyval}
———————————————————————
7.1 Default/global configuration
In principle the definitions of all available hkey’i=hvalue’i pairs is contained in the internal macros\ion@hkey’i@hvalue’i. Setting a package optionhkeyi=hvaluei defines\ion@hkeyi@resetto be\ion@hkeyi@hvaluei.
The followingifs will be required to remember, if automatic grouping is en- abled. The counts will be required for the grouping lengths.
2\newif\ifion@autothousands
3\newif\ifion@autothousandths
4\newcount\ion@grplenthousands
5\newcount\ion@grplenthousandths
The next macro will be used for syntax checks of numerical arguments.
6\newcommand*{\ion@grplencheck}[1]{%
7 \ifnum#1>9%
8 \PackageError{ionumbers}%
9 {Group length argument too large (#1).\MessageBreak%
10 Grouping lengths must be smaller than 10.}{}%
11 \fi%
12}
These shorthands are used to define the hkeyis for package options and set theirhvalueis usingkeyval, respectively.
13\newcommand*\ion@defpackopts{\define@key{ion@packopts}}
14\newcommand*\ion@setpackopts{\setkeys{ion@packopts}}
Next thehkeyis are defined.
15\ion@defpackopts{comma}{%
16 \def\ion@comma@reset{\csname ion@comma@#1\endcsname}%
17 \def\ion@aftercomma@reset{\csname ion@aftercomma@#1\endcsname}}
18\ion@defpackopts{point}{%
19 \def\ion@point@reset{\csname ion@point@#1\endcsname}%
20 \def\ion@afterpoint@reset{\csname ion@afterpoint@#1\endcsname}}
21\ion@defpackopts{decimal}{\def\ion@decimal@reset{%
22 \csname ion@decimal@#1\endcsname}}
23\ion@defpackopts{thousands}{\def\ion@thousands@reset{%
24 \csname ion@thousands@#1\endcsname}}
25\ion@defpackopts{thousandths}{\def\ion@thousandths@reset{%
26 \csname ion@thousandths@#1\endcsname}}
27\ion@defpackopts{exponent}{\def\ion@exponent@reset{%
28 \csname ion@exponent@#1\endcsname}}
29\ion@defpackopts{autothousands}[true]{\def\ion@autothousandsreset{%
30 \csname ion@autothousands#1\endcsname}\ion@autothousandsreset}
31\ion@defpackopts{autothousandths}[true]{\def\ion@autothousandthsreset{%
32 \csname ion@autothousandths#1\endcsname}\ion@autothousandthsreset}
33\ion@defpackopts{grplenthousands}{\ion@grplencheck{#1}%
34 \def\ion@grplenthousandsreset{\ion@grplenthousands=#1}%
35 \ion@grplenthousandsreset}
36\ion@defpackopts{grplenthousandths}{\ion@grplencheck{#1}%
37 \def\ion@grplenthousandthsreset{\ion@grplenthousandths=#1}%
38 \ion@grplenthousandthsreset}
Finally, the default hvalueis are set and—if specified by the user as package option—overwritten with the user’s configuration.
39\ion@setpackopts{comma=default,point=default,thousands=default,%
40 decimal=default,thousandths=default,exponent=default,autothousands=false,%
41 autothousandths=false,grplenthousands=3,grplenthousandths=3}
42\DeclareOption*{\expandafter\ion@setpackopts\expandafter{\CurrentOption}}
43\ProcessOptions\relax
———————————————————————
7.2 Local style changes
The currently active configuration of ahkeyiis stored in the macro\ion@hkeyi@curr.
The\ion@hkeyi@currmacros for all hkeyis are defined using the mechanism for local configuration changes.
The local options are defined and set—analogous to the package option case—
with two shorthands usingkeyval. The latter is publically available to the user.
44\newcommand*\ion@deflocopts{\define@key{ion@locopts}}
\ionumberstyle
45\newcommand*\ionumbersstyle[1]{\setkeys{ion@locopts}{#1}}
Now the hkeyis for the local options are defined (just as in the case of the package options):
46\ion@deflocopts{comma}{%
47 \def\ion@comma@curr{\csname ion@comma@#1\endcsname}%
48 \def\ion@aftercomma@curr{\csname ion@aftercomma@#1\endcsname}}
49\ion@deflocopts{point}{%
50 \def\ion@point@curr{\csname ion@point@#1\endcsname}%
51 \def\ion@afterpoint@curr{\csname ion@afterpoint@#1\endcsname}}
52\ion@deflocopts{decimal}{\def\ion@decimal@curr{%
53 \csname ion@decimal@#1\endcsname}}
54\ion@deflocopts{thousands}{\def\ion@thousands@curr{%
55 \csname ion@thousands@#1\endcsname}}
56\ion@deflocopts{thousandths}{\def\ion@thousandths@curr{%
57 \csname ion@thousandths@#1\endcsname}}
58\ion@deflocopts{exponent}{\def\ion@exponent@curr{%
59 \csname ion@exponent@#1\endcsname}}
60\ion@deflocopts{autothousands}[true]{\csname ion@autothousands#1\endcsname}
61\ion@deflocopts{autothousandths}[true]{\csname ion@autothousandths#1\endcsname}
62\ion@deflocopts{grplenthousands}{%
63 \def\@tempa{#1}%
64 \def\@tempb{reset}%
65 \ifx\@tempa\@tempb%
66 \ion@grplenthousandsreset%
67 \else%
68 \ion@grplencheck{#1}%
69 \ion@grplenthousands=#1%
70 \fi%
71}
72\ion@deflocopts{grplenthousandths}{%
73 \def\@tempa{#1}%
74 \def\@tempb{reset}%
75 \ifx\@tempa\@tempb%
76 \ion@grplenthousandthsreset%
77 \else%
78 \ion@grplencheck{#1}%
79 \ion@grplenthousandths=#1%
80 \fi%
81}
Finally, the command for resetting allhkeyis is defined.
\ionumbersresetstyle
82\newcommand*\ionumbersresetstyle{%
83 \ionumbersstyle{comma=reset,point=reset,thousands=reset,%
84 decimal=reset,thousandths=reset,exponent=reset,autothousands=reset,%
85 autothousandths=reset,grplenthousands=reset,grplenthousandths=reset}}
This command is issued at the end of the package to make the configuration of the package options active (and have no undefined\ion@hkeyi@curr macros).
86\AtEndOfPackage{\ionumbersresetstyle}
———————————————————————
7.3 User-defined values for output separators
The commands for user-defined hvalueis for output separators just (re)define the internal macro \ion@hkeyi@hvaluei storing the definition for the hkeyi=hvaluei pair.
\newionumbersthousands
87\newcommand*\newionumbersthousands[2]{\expandafter\newcommand%
88 \expandafter*\csname ion@thousands@#1\endcsname{\ionumbersoff{#2}}}
\newionumbersdecimal
89\newcommand*\newionumbersdecimal[2]{\expandafter\newcommand%
90 \expandafter*\csname ion@decimal@#1\endcsname{\ionumbersoff{#2}}}
\newionumbersthousandths
91\newcommand*\newionumbersthousandths[2]{\expandafter\newcommand%
92 \expandafter*\csname ion@thousandths@#1\endcsname{\ionumbersoff{#2}}}
\newionumbersexponent
93\newcommand*\newionumbersexponent{%
94 \@ifstar{\newionumbersexponent@@}{\newionumbersexponent@}}
95\newcommand*\newionumbersexponent@[2]{\expandafter\newcommand%
96 \expandafter*\csname ion@exponent@#1\endcsname{\ionumbersoff{#2}}}
97\newcommand*\newionumbersexponent@@[2]{\expandafter\newcommand%
98 \expandafter*\csname ion@exponent@#1\endcsname{\ionumbersoff{#2}%
99 \ion@exponent@superscripttrue}}
\renewionumbersthousands
100\newcommand*\renewionumbersthousands[2]{\expandafter\renewcommand%
101 \expandafter*\csname ion@thousands@#1\endcsname{\ionumbersoff{#2}}}
\renewionumbersdecimal
102\newcommand*\renewionumbersdecimal[2]{\expandafter\renewcommand%
103 \expandafter*\csname ion@decimal@#1\endcsname{\ionumbersoff{#2}}}
\renewionumbersthousandths
104\newcommand*\renewionumbersthousandths[2]{\expandafter\renewcommand%
105 \expandafter*\csname ion@thousandths@#1\endcsname{\ionumbersoff{#2}}}
\renewionumbersexponent
106\newcommand*\renewionumbersexponent{%
107 \@ifstar{\renewionumbersexponent@@}{\renewionumbersexponent@}}
108\newcommand*\renewionumbersexponent@[2]{\expandafter\renewcommand%
109 \expandafter*\csname ion@exponent@#1\endcsname{\ionumbersoff{#2}%
110 \ion@currnum@exponent}}
111\newcommand*\renewionumbersexponent@@[2]{\expandafter\renewcommand%
112 \expandafter*\csname ion@exponent@#1\endcsname{\ionumbersoff{#2}%
113 \ion@currnum@exponent\ion@exponent@superscripttrue}}
———————————————————————
7.4 Internal macros holding definitions for hkey i=hvalue i pairs
First of all, macros with the original character definitions are defined.
114\AtBeginDocument{
115 \mathchardef\ion@point@original=\the\mathcode‘.
116 \mathchardef\ion@comma@original=\the\mathcode‘,
117 \mathchardef\ion@plus@original=\the\mathcode‘+
118 \mathchardef\ion@minus@original=\the\mathcode‘-
119 \mathchardef\ion@zero@original=\the\mathcode‘0
120 \mathchardef\ion@one@original=\the\mathcode‘1
121 \mathchardef\ion@two@original=\the\mathcode‘2
122 \mathchardef\ion@three@original=\the\mathcode‘3
123 \mathchardef\ion@four@original=\the\mathcode‘4
124 \mathchardef\ion@five@original=\the\mathcode‘5
125 \mathchardef\ion@six@original=\the\mathcode‘6
126 \mathchardef\ion@seven@original=\the\mathcode‘7
127 \mathchardef\ion@eight@original=\the\mathcode‘8
128 \mathchardef\ion@nine@original=\the\mathcode‘9
129 \mathchardef\ion@e@original=\the\mathcode‘e
130 \mathchardef\ion@E@original=\the\mathcode‘E
131}
Here the\ion@hkeyi@hvalueimacros are defined, begining with the definitions for the comma as input separator.
132\def\ion@comma@ignore{}
133\def\ion@comma@decimal{\ion@decimal@curr}
134\def\ion@comma@thousands{\ion@thousands@curr}
135\def\ion@comma@default{\ion@comma@thousands}
The macros \ion@comma@hvaluei contain the output for a comma appearing in the input. Actually, a second set of\ion@aftercomma@hvalueimacros is required containing commands to be issued whenever a comma appears. If comma is the decimal separator, the appearance of comma in the input will mean that input of the thousands part is complete and the thousandths thousandths part starts (\ion@beforedecimalfalse must be issued). If comma is the thousands sepa- rator, the automatic grouping of thousands will be switched of for that number (\ion@noexplicitthousandsfalsemust be issued).
136\def\ion@aftercomma@ignore{}
137\def\ion@aftercomma@decimal{\ion@beforedecimalfalse}
138\def\ion@aftercomma@thousands{\ion@noexplicitthousandsfalse}
139\def\ion@aftercomma@default{\ion@aftercomma@thousands}
An analogous set of macros is defined for the point as input separator.
140\def\ion@point@ignore{}
141\def\ion@point@decimal{\ion@decimal@curr}
142\def\ion@point@thousands{\ion@thousands@curr}
143\def\ion@point@default{\ion@point@decimal}
For the same reasons as mentioned before a set of\ion@afterpoint@hvalueimacros is required.
144\def\ion@afterpoint@ignore{}
145\def\ion@afterpoint@decimal{\ion@beforedecimalfalse}
146\def\ion@afterpoint@thousands{\ion@noexplicitthousandsfalse}
147\def\ion@afterpoint@default{\ion@afterpoint@decimal}
Next the definitions for the decimal output separator, . . .
148\def\ion@decimal@point{\mathord{\ion@point@original}}
149\def\ion@decimal@comma{\mathord{\ion@comma@original}}
150\def\ion@decimal@punctpoint{\mathpunct{\ion@decimal@point}}
151\def\ion@decimal@punctcomma{\mathpunct{\ion@decimal@comma}}
152\def\ion@decimal@default{\ion@decimal@point}
. . . the thousands output separator, . . .
153\def\ion@thousands@none{}
154\def\ion@thousands@point{\mathord{\ion@point@original}}
155\def\ion@thousands@comma{\mathord{\ion@comma@original}}
156\def\ion@thousands@punctpoint{\mathpunct{\ion@decimal@point}}
157\def\ion@thousands@punctcomma{\mathpunct{\ion@decimal@comma}}
158\def\ion@thousands@apostrophe{^\prime}
159\def\ion@thousands@phantom{\phantom{\ion@point@original}}
160\def\ion@thousands@space{\,}
161\def\ion@thousands@default{\ion@thousands@punctcomma}
. . . the thousandths output separator, . . .
162\def\ion@thousandths@none{}
163\def\ion@thousandths@point{\mathord{\ion@point@original}}
164\def\ion@thousandths@comma{\mathord{\ion@comma@original}}
165\def\ion@thousandths@punctpoint{\mathpunct{\ion@decimal@point}}
166\def\ion@thousandths@punctcomma{\mathpunct{\ion@decimal@comma}}
167\def\ion@thousandths@apostrophe{^\prime}
168\def\ion@thousandths@phantom{\phantom{\ion@point@original}}
169\def\ion@thousandths@space{\,}
170\def\ion@thousandths@default{\ion@thousandths@space}
. . . and the exponent output separator are given.
171\def\ion@exponent@none{}
172\def\ion@exponent@original{\ion@e@original}
173\def\ion@exponent@ite{\mathit{\ion@e@original}\ion@currnum@exponenttrue}
174\def\ion@exponent@itE{\mathit{\ion@E@original}\ion@currnum@exponenttrue}
175\def\ion@exponent@rme{\mathrm{\ion@e@original}\ion@currnum@exponenttrue}
176\def\ion@exponent@rmE{\mathrm{\ion@E@original}\ion@currnum@exponenttrue}
177\def\ion@exponent@timestento{\times10\,\ion@currnum@exponenttrue%
178 \ion@exponent@superscripttrue}
179\def\ion@exponent@cdottento{\cdot10\,\ion@currnum@exponenttrue%
180 \ion@exponent@superscripttrue}
181\def\ion@exponent@wedge{^\wedge\ion@currnum@exponenttrue}
182\def\ion@exponent@default{\ion@exponent@original}
———————————————————————
7.5 Enabling and disabling features
The following helper macros make different subsets of.,+-0123456789active.
183\def\ion@separators@active{\catcode‘\,=\active\catcode‘\.=\active\relax}
184\def\ion@signs@active{\catcode‘\+=\active\catcode‘\-=\active\relax}
185\def\ion@digits@active{\catcode‘\,=\active\catcode‘\.=\active%
186 \catcode‘\0=\active\catcode‘\1=\active\catcode‘\2=\active%
187 \catcode‘\3=\active\catcode‘\4=\active\catcode‘\5=\active%
188 \catcode‘\6=\active\catcode‘\7=\active\catcode‘\8=\active%
189 \catcode‘\9=\active\relax}
An analogous set of macros makes subsets of these characters active/inactive in math mode.
190\def\ion@separators@math@active{\mathcode‘,="8000\mathcode‘.="8000\relax}
191\def\ion@signs@math@active{\mathcode‘+="8000\mathcode‘-="8000\relax}
192\def\ion@digits@math@active{\mathcode‘0="8000\mathcode‘1="8000\mathcode‘2="8000%
193 \mathcode‘3="8000\mathcode‘4="8000\mathcode‘5="8000\mathcode‘6="8000%
194 \mathcode‘7="8000\mathcode‘8="8000\mathcode‘9="8000\relax}
195\def\ion@separators@math@inactive{%
196 \mathcode‘,=\the\ion@comma@original%
197 \mathcode‘.=\the\ion@point@original%
198 \relax}
199\def\ion@signs@math@inactive{%
200 \mathcode‘+=\the\ion@plus@original%
201 \mathcode‘-=\the\ion@minus@original%
202 \relax}
203\def\ion@digits@math@inactive{%
204 \mathcode‘0=\the\ion@zero@original%
205 \mathcode‘1=\the\ion@one@original%
206 \mathcode‘2=\the\ion@two@original%
207 \mathcode‘3=\the\ion@three@original%
208 \mathcode‘4=\the\ion@four@original%
209 \mathcode‘5=\the\ion@five@original%
210 \mathcode‘6=\the\ion@six@original%
211 \mathcode‘7=\the\ion@seven@original%
212 \mathcode‘8=\the\ion@eight@original%
213 \mathcode‘9=\the\ion@nine@original%
214 \relax}
Next the user interface for making.,+-0123456789active/inactive follows.
\ionumbers
215\def\ionumbers{\ion@separators@math@active\ion@signs@math@active%
216 \ion@digits@math@active}
\endionumbers
217\def\endionumbers{\ion@separators@math@inactive\ion@signs@math@inactive%
218 \ion@digits@math@inactive}
\ionumbersoff
219\newcommand\ionumbersoff[1]{\begingroup\endionumbers#1\ionumbers\endgroup}
Of course, at the begining of the document the charactars shall be active by default.
220\AtBeginDocument{\ionumbers}
———————————————————————
7.6 Definitions of active characters
The macro definitions for the characters.,+-0123456789are hold in the following macros. Number processing works by looking at the next character and performing one or more from the following actions:
• the currently configured output for the character will be added to the end of \ion@currnum by\ion@currnum@append; \ion@currnum stores the cur- rently processed number
• only for comma/point: the corresponding after...macro will be issued
• the currently processed number will be output via \ion@currnum@output
• theewill be eaten and replaced by its configured output
The conditions in the macro definitions should be self-explanatory for each char- acter. The extra\ion@startnumberis required to avoid problems with input like
$a_0$or $\sqrt 2$, where curly braces around0and2have been omitted.
221\def\ion@comma{%
222 \ion@ifnextdigit{%
223 \ion@currnum@append*{\ion@comma@curr}\ion@aftercomma@curr%
224 }{%
225 \ion@ifnextseparator{%
226 \ion@currnum@append*{\ion@comma@curr}\ion@aftercomma@curr%
227 \@warning{Too many separators}%
228 }{%
229 \ion@ifnextchar e{%
230 \ion@currnum@append*{\ion@comma@curr}\ion@aftercomma@curr%
231 \ion@currnum@output\ion@exponent@curr\@gobble%
232 }{%
233 \ion@currnum@output\ion@comma@original%
234 }%
235 }%
236 }%
237}
238\def\ion@point{%
239 \ion@ifnextdigit{%
240 \ion@currnum@append*{\ion@point@curr}\ion@afterpoint@curr%
241 }{%
242 \ion@ifnextseparator{%
243 \ion@currnum@append*{\ion@point@curr}\ion@afterpoint@curr%
244 \@warning{Too many separators}%
245 }{%
246 \ion@ifnextchar e{%
247 \ion@currnum@append*{\ion@point@curr}\ion@afterpoint@curr%
248 \ion@currnum@output\ion@exponent@curr\@gobble%
249 }{%
250 \ion@currnum@output\ion@point@original%
251 }%
252 }%
253 }%
254}
255\def\ion@plus{%
256 \ion@iffirstchar{%
257 \ion@plus@original%
258 }{%
259 \ion@currnum@append*{\ion@plus@original}%
260 }%
261 \ion@ifnextdigit{%
262 %% nothing
263 }{%
264 \ion@ifnextseparator{%
265 %% nothing
266 }{%
267 \ion@ifnextsign{%
268 \@warning{Too many signs}%
269 }{%
270 \ion@currnum@output%
271 }%
272 }%
273 }%
274}
275\def\ion@minus{%
276 \ion@iffirstchar{%
277 \ion@minus@original%
278 }{%
279 \ion@currnum@append*{\ion@minus@original}%
280 }%
281 \ion@ifnextdigit{%
282 %% nothing
283 }{%
284 \ion@ifnextseparator{%
285 %% nothing
286 }{%
287 \ion@ifnextsign{%
288 \@warning{Too many signs}%
289 }{%
290 \ion@currnum@output%
291 }%
292 }%
293 }%
294}
295\def\ion@zero{%
296 \ion@iffirstchar{%
297 \ion@zero@original\ion@currnum@append{}%
298 }{%
299 \ion@currnum@append{\ion@zero@original}%
300 }%
301 \ion@ifnextdigit{%
302 %% nothing
303 }{%
304 \ion@ifnextseparator{%
305 %% nothing
306 }{%
307 \ion@ifnextchar e{%
308 \ion@currnum@output\ion@exponent@curr\@gobble%
309 }{%
310 \ion@currnum@output%
311 }%
312 }%
313 }%
314}
315\def\ion@one{%
316 \ion@iffirstchar{%
317 \ion@one@original\ion@currnum@append{}%
318 }{%
319 \ion@currnum@append{\ion@one@original}%
320 }%
321 \ion@ifnextdigit{%
322 %% nothing
323 }{%
324 \ion@ifnextseparator{%
325 %% nothing
326 }{%
327 \ion@ifnextchar e{%
328 \ion@currnum@output\ion@exponent@curr\@gobble%
329 }{%
330 \ion@currnum@output%
331 }%
332 }%
333 }%
334}
335\def\ion@two{%
336 \ion@iffirstchar{%
337 \ion@two@original\ion@currnum@append{}%
338 }{%
339 \ion@currnum@append{\ion@two@original}%
340 }%
341 \ion@ifnextdigit{%
342 %% nothing
343 }{%
344 \ion@ifnextseparator{%
345 %% nothing
346 }{%
347 \ion@ifnextchar e{%
348 \ion@currnum@output\ion@exponent@curr\@gobble%
349 }{%
350 \ion@currnum@output%
351 }%
352 }%
353 }%
354}
355\def\ion@three{%
356 \ion@iffirstchar{%
357 \ion@three@original\ion@currnum@append{}%
358 }{%
359 \ion@currnum@append{\ion@three@original}%
360 }%
361 \ion@ifnextdigit{%
362 %% nothing
363 }{%
364 \ion@ifnextseparator{%
365 %% nothing
366 }{%
367 \ion@ifnextchar e{%
368 \ion@currnum@output\ion@exponent@curr\@gobble%
369 }{%
370 \ion@currnum@output%
371 }%
372 }%
373 }%
374}
375\def\ion@four{%
376 \ion@iffirstchar{%
377 \ion@four@original\ion@currnum@append{}%
378 }{%
379 \ion@currnum@append{\ion@four@original}%
380 }%
381 \ion@ifnextdigit{%
382 %% nothing
383 }{%
384 \ion@ifnextseparator{%
385 %% nothing
386 }{%
387 \ion@ifnextchar e{%
388 \ion@currnum@output\ion@exponent@curr\@gobble%
389 }{%
390 \ion@currnum@output%
391 }%
392 }%
393 }%
394}
395\def\ion@five{%
396 \ion@iffirstchar{%
397 \ion@five@original\ion@currnum@append{}%
398 }{%
399 \ion@currnum@append{\ion@five@original}%
400 }%
401 \ion@ifnextdigit{%
402 %% nothing
403 }{%
404 \ion@ifnextseparator{%
405 %% nothing
406 }{%
407 \ion@ifnextchar e{%
408 \ion@currnum@output\ion@exponent@curr\@gobble%
409 }{%
410 \ion@currnum@output%
411 }%
412 }%
413 }%
414}
415\def\ion@six{%
416 \ion@iffirstchar{%
417 \ion@six@original\ion@currnum@append{}%
418 }{%
419 \ion@currnum@append{\ion@six@original}%
420 }%
421 \ion@ifnextdigit{%
422 %% nothing
423 }{%
424 \ion@ifnextseparator{%
425 %% nothing
426 }{%
427 \ion@ifnextchar e{%
428 \ion@currnum@output\ion@exponent@curr\@gobble%
429 }{%
430 \ion@currnum@output%
431 }%
432 }%
433 }%
434}
435\def\ion@seven{%
436 \ion@iffirstchar{%
437 \ion@seven@original\ion@currnum@append{}%
438 }{%
439 \ion@currnum@append{\ion@seven@original}%
440 }%
441 \ion@ifnextdigit{%
442 %% nothing
443 }{%
444 \ion@ifnextseparator{%
445 %% nothing
446 }{%
447 \ion@ifnextchar e{%
448 \ion@currnum@output\ion@exponent@curr\@gobble%
449 }{%
450 \ion@currnum@output%
451 }%
452 }%
453 }%
454}
455\def\ion@eight{%
456 \ion@iffirstchar{%
457 \ion@eight@original\ion@currnum@append{}%
458 }{%
459 \ion@currnum@append{\ion@eight@original}%
460 }%
461 \ion@ifnextdigit{%
462 %% nothing
463 }{%
464 \ion@ifnextseparator{%
465 %% nothing
466 }{%
467 \ion@ifnextchar e{%
468 \ion@currnum@output\ion@exponent@curr\@gobble%
469 }{%
470 \ion@currnum@output%
471 }%
472 }%
473 }%
474}
475\def\ion@nine{%
476 \ion@iffirstchar{%
477 \ion@nine@original\ion@currnum@append{}%
478 }{%
479 \ion@currnum@append{\ion@nine@original}%
480 }%
481 \ion@ifnextdigit{%
482 %% nothing
483 }{%
484 \ion@ifnextseparator{%
485 %% nothing
486 }{%
487 \ion@ifnextchar e{%
488 \ion@currnum@output\ion@exponent@curr\@gobble%
489 }{%
490 \ion@currnum@output%
491 }%
492 }%
493 }%
494}
The macro\ion@define@charmacros is used to assign the above macros to the (active) characters.,+-0123456789. It will be executed later in the conflict test section.
495\begingroup
496 \ion@separators@active\ion@signs@active\ion@digits@active
497 \gdef\ion@define@charmacros{%
498 \global\let,=\ion@comma%
499 \global\let.=\ion@point%
500 \global\let+=\ion@plus%
501 \global\let-=\ion@minus%
502 \global\let0=\ion@zero%
503 \global\let1=\ion@one%
504 \global\let2=\ion@two%
505 \global\let3=\ion@three%
506 \global\let4=\ion@four%
507 \global\let5=\ion@five%
508 \global\let6=\ion@six%
509 \global\let7=\ion@seven%
510 \global\let8=\ion@eight%
511 \global\let9=\ion@nine%
512 }
513\endgroup
If one of+-0123456789is the first character of a number and this number not part of an exponent, then argument ‘1’ will be used; otherwise argument ‘2’ will be used. This macro is required to handle single characters not grouped in curly braces{}in expressions like$a^0$ or$\sqrt 2$correctly.
514\def\ion@iffirstchar#1#2{%
515 \ifion@currnum@exponent%
516 #2%
517 \else%
518 \ifion@currnum@firstchar%
519 #1%
520 \else
521 #2%
522 \fi%
523 \fi%
524 \ion@currnum@firstcharfalse%
525}
Now the macros for the conditions in the above definitions follow. There are tests for a digit0123456789, . . .
526\long\def\ion@ifnextdigit#1#2{%
527 \def\reserved@a{#1}%
528 \def\reserved@b{#2}%
529 \futurelet\@let@token\ion@ifnextdigit@}
530\def\ion@ifnextdigit@{%
531 \ifx\@let@token1\let\reserved@c\reserved@a\else%
532 \ifx\@let@token2\let\reserved@c\reserved@a\else%
533 \ifx\@let@token3\let\reserved@c\reserved@a\else%
534 \ifx\@let@token4\let\reserved@c\reserved@a\else%
535 \ifx\@let@token5\let\reserved@c\reserved@a\else%
536 \ifx\@let@token6\let\reserved@c\reserved@a\else%
537 \ifx\@let@token7\let\reserved@c\reserved@a\else%
538 \ifx\@let@token8\let\reserved@c\reserved@a\else%
539 \ifx\@let@token9\let\reserved@c\reserved@a\else%
540 \ifx\@let@token0\let\reserved@c\reserved@a\else%
541 \let\reserved@c\reserved@b%
542 \fi%
543 \fi%
544 \fi%
545 \fi%
546 \fi%
547 \fi%
548 \fi%
549 \fi%
550 \fi%
551 \fi%
552 \reserved@c}
. . . for a separator.,, . . .
553\long\def\ion@ifnextseparator#1#2{%
554 \def\reserved@a{#1}%
555 \def\reserved@b{#2}%
556 \futurelet\@let@token\ion@ifnextseparator@}
557\def\ion@ifnextseparator@{%
558 \ifx\@let@token,\let\reserved@c\reserved@a\else%
559 \ifx\@let@token.\let\reserved@c\reserved@a\else%
560 \let\reserved@c\reserved@b%
561 \fi%
562 \fi%
563 \reserved@c}
. . . and for a sign+-as next character.
564\long\def\ion@ifnextsign#1#2{%
565 \def\reserved@a{#1}%
566 \def\reserved@b{#2}%
567 \futurelet\@let@token\ion@ifnextsign@}
568\def\ion@ifnextsign@{%
569 \ifx\@let@token+\let\reserved@c\reserved@a\else%
570 \ifx\@let@token-\let\reserved@c\reserved@a\else%
571 \let\reserved@c\reserved@b%
572 \fi%
573 \fi%
574 \reserved@c}
An additional test for an arbitrary character is also added. It obeys white spaces in contrast to LATEX’s\@ifnextchar.
575\long\def\ion@ifnextchar#1#2#3{%
576 \let\reserved@d=#1%
577 \def\reserved@a{#2}%
578 \def\reserved@b{#3}%
579 \futurelet\@let@token\ion@ifnextchar@}
580\def\ion@ifnextchar@{%
581 \ifx\@let@token\reserved@d%
582 \let\reserved@c\reserved@a%
583 \else%
584 \let\reserved@c\reserved@b%
585 \fi%
586 \reserved@c}
———————————————————————
7.7 Test for conflicts with other packages
First of all we test for some packages known to conflict withionumbers. This will be done by checking at the begining of the document, if one of these packages has been loaded and an error/warning will be issued.
587\newcommand*{\ion@conflict@package}[1]{%
588 \@ifpackageloaded{#1}{%
589 \PackageError{ionumbers}%
590 {Packages #1 and ionumbers conflict!\MessageBreak%
591 Do not load both packages in the same document}{}%
592 }{}%
593}
594\newcommand*{\ion@problem@package}[2]{%
595 \@ifpackageloaded{#1}{%
596 \PackageWarning{ionumbers}%
597 {Loading #1 and ionumbers is problematic!\MessageBreak#2}%
598 }{}%
599}
600
601\AtBeginDocument{%
602 \ion@conflict@package{ziffer}%
603 \ion@problem@package{dcolumn}{Use ‘tabular’s inside \string\ionumbersoff}%
604 \ion@problem@package{amsmath}{Load ionumbers after amsmath}%
605 \ion@problem@package{amsmath}{Use \string\operatorname\space inside
606 \string\ionumbersoff}%
607 \ion@problem@package{amsopn}{Use \string\operatorname\space inside
608 \string\ionumbersoff}%
609}
Next the characters .,+-0123456789 are checked for macro definitions (by other packages). This way conflicts with other packages may be detected with some probability (but only if the conflicting package has already been loaded).
610\newcommand*\ion@conflict@definedtest[1]{%
611 \ifx#1\@undefined\else\PackageWarning{ionumbers}%
612 {Potential conflict with other package(s) detected.\MessageBreak%
613 ‘\string#1’ has already been defined. I will redefine it.\MessageBreak%
614 This might break other package(s)!\MessageBreak}\fi}
615\begingroup
616 \ion@separators@active\ion@signs@active\ion@digits@active
617 \ion@conflict@definedtest{,}
618 \ion@conflict@definedtest{.}
619 \ion@conflict@definedtest{+}
620 \ion@conflict@definedtest{-}
621 \ion@conflict@definedtest{0}
622 \ion@conflict@definedtest{1}
623 \ion@conflict@definedtest{2}
624 \ion@conflict@definedtest{3}
625 \ion@conflict@definedtest{4}
626 \ion@conflict@definedtest{5}
627 \ion@conflict@definedtest{6}
628 \ion@conflict@definedtest{7}
629 \ion@conflict@definedtest{8}
630 \ion@conflict@definedtest{9}
631\endgroup
After the above test the definitions of the characters of ionumbers can be applied.
632\ion@define@charmacros
Additionally,ionumbers tests for redefinitions of the macros of the characters at the begining of the document.
633\newcommand*{\ion@conflict@redefinedtest}[2]{%
634 \ifx#1#2\else\PackageWarning{ionumbers}%
635 {Potential conflict with other package(s) detected.\MessageBreak%
636 ‘\string#1’ has been redefined. This might break ionumbers!\MessageBreak}%
637 \fi}
638\begingroup
639 \ion@separators@active\ion@signs@active\ion@digits@active
640 \gdef\ion@conflict@redefinedtest@macro{%
641 \ion@conflict@redefinedtest{,}{\ion@comma}%
642 \ion@conflict@redefinedtest{.}{\ion@point}%
643 \ion@conflict@redefinedtest{+}{\ion@plus}%
644 \ion@conflict@redefinedtest{-}{\ion@minus}%
645 \ion@conflict@redefinedtest{0}{\ion@zero}%
646 \ion@conflict@redefinedtest{1}{\ion@one}%
647 \ion@conflict@redefinedtest{2}{\ion@two}%
648 \ion@conflict@redefinedtest{3}{\ion@three}%
649 \ion@conflict@redefinedtest{4}{\ion@four}%
650 \ion@conflict@redefinedtest{5}{\ion@five}%
651 \ion@conflict@redefinedtest{6}{\ion@six}%
652 \ion@conflict@redefinedtest{7}{\ion@seven}%
653 \ion@conflict@redefinedtest{8}{\ion@eight}%
654 \ion@conflict@redefinedtest{9}{\ion@nine}%
655 }
656\endgroup
657\AtBeginDocument{\ion@conflict@redefinedtest@macro}
———————————————————————
7.8 Commands for current number
Numbers are processed by first storing one character after the other in an internal macro to be able to automatically group digits. The basic idea when adding single characters is
• remember, whether we are processing the thousands or the thousandths part of a number (\ifion@beforedecimal)
• calculate the number of digits processed modulo 3 plus 1 in the current part and
– for the thousands part: add\ion@thousands@sepafor 1,\ion@thousands@sepb for 2, \ion@thousands@sepcfor 3, . . . after a digit
– for the thousandths part: add\ion@thousandths@sepafter each third digit
The macros\ion@[email protected]\ion@thousandths@sep are empty by default. Before outputting the number, the number of digits in the thousands part is known and the correct \ion@[email protected] can be set to the thousands separator for correct grouping.
First of all, theifs, counters and empty separator macros are initialized.
658\newif\ifion@currnum@firstchar\ion@currnum@firstchartrue
659\newif\ifion@beforedecimal\ion@beforedecimaltrue
660\newif\ifion@noexplicitthousands\ion@noexplicitthousandstrue
661\newif\ifion@currnum@exponent\ion@currnum@exponentfalse
662\newif\ifion@exponent@superscript\ion@exponent@superscriptfalse
663\newcount\ion@thousands@currpos\ion@thousands@currpos=0
664\newcount\ion@thousandths@currpos\ion@thousandths@currpos=0
665\def\ion@currnum{}
666\def\ion@thousands@sepa{}
667\def\ion@thousands@sepb{}
668\def\ion@thousands@sepc{}
669\def\ion@thousands@sepd{}
670\def\ion@thousands@sepe{}
671\def\ion@thousands@sepf{}
672\def\ion@thousands@sepg{}
673\def\ion@thousands@seph{}
674\def\ion@thousands@sepi{}
675\def\ion@thousandths@sep{}
The macro \ion@currnum@append adds the character in its argument to the end of\ion@currnum. In the starred version adding of an empty separator macros is omitted.
676\newcommand{\ion@currnum@append}{%
677 \ion@currnum@firstcharfalse%
678 \@ifstar{\ion@currnum@append@@}{\ion@currnum@append@}%
679}
680\newcommand*{\ion@currnum@append@@}[1]{%
681 \ion@addto@macro{\ion@currnum}{#1}%
682}
683\newcommand*{\ion@currnum@append@}[1]{%
684 \ifion@beforedecimal%
685 %% push back (empty) separator and character
686 \ifcase\ion@thousands@currpos%
687 \ion@addto@macro{\ion@currnum}{#1}%
688 \or%
689 \ion@addto@macro{\ion@currnum}{\ion@thousands@sepa#1}%
690 \or%
691 \ion@addto@macro{\ion@currnum}{\ion@thousands@sepb#1}%
692 \or%
693 \ion@addto@macro{\ion@currnum}{\ion@thousands@sepc#1}%
694 \or%
695 \ion@addto@macro{\ion@currnum}{\ion@thousands@sepd#1}%
696 \or%
697 \ion@addto@macro{\ion@currnum}{\ion@thousands@sepe#1}%
698 \or%
699 \ion@addto@macro{\ion@currnum}{\ion@thousands@sepf#1}%
700 \or%
701 \ion@addto@macro{\ion@currnum}{\ion@thousands@sepg#1}%
702 \or%
703 \ion@addto@macro{\ion@currnum}{\ion@thousands@seph#1}%
704 \or%
705 \ion@addto@macro{\ion@currnum}{\ion@thousands@sepi#1}%
706 \fi%
707 %% advance thousands counter
708 \advance\ion@thousands@currpos by1\relax%
709 \ifnum\ion@thousands@currpos>\ion@grplenthousands%
710 \ion@thousands@currpos=1%
711 \fi%
712 \else%
713 %% push back (empty) separator and character
714 \ifnum\ion@thousandths@currpos=\ion@grplenthousandths%
715 \ion@addto@macro{\ion@currnum}{\ion@thousandths@sep#1}%
716 \else%
717 \ion@addto@macro{\ion@currnum}{#1}%
718 \fi%
719 %% advance thousandths counter
720 \advance\ion@thousandths@currpos by1\relax%
721 \ifnum\ion@thousandths@currpos>\ion@grplenthousandths%
722 \ion@thousandths@currpos=1%
723 \fi%
724 \fi%
725}
The \ion@currnum@output macro defines the empty separator macros (de- pending on the current configuration), outputs the current number, and resets everything for the next number.
726\newcommand*{\ion@currnum@output}{%
727 \begingroup%
728 %% set automatic thousands separator
729 \ifion@autothousands%
730 \ifion@noexplicitthousands%
731 \ifcase\ion@thousands@currpos%
732 %% do nothing
733 \or%
734 \def\ion@thousands@sepa{\ion@thousands@curr}%
735 \or%
736 \def\ion@thousands@sepb{\ion@thousands@curr}%
737 \or%
738 \def\ion@thousands@sepc{\ion@thousands@curr}%
739 \or%
740 \def\ion@thousands@sepd{\ion@thousands@curr}%
741 \or%
742 \def\ion@thousands@sepe{\ion@thousands@curr}%
743 \or%
744 \def\ion@thousands@sepf{\ion@thousands@curr}%
745 \or%
746 \def\ion@thousands@sepg{\ion@thousands@curr}%
747 \or%
748 \def\ion@thousands@seph{\ion@thousands@curr}%
749 \or%
750 \def\ion@thousands@sepi{\ion@thousands@curr}%
751 \fi%
752 \fi%
753 \fi%
754 %% set automatic thousandths separator
755 \ifion@autothousandths%
756 \def\ion@thousandths@sep{\ion@thousandths@curr}%
757 \fi%
758 %% output number
759 \ifion@currnum@exponent%
760 \ifion@exponent@superscript%
761 ^{\ion@currnum}%
762 \else%
763 {\ion@currnum}%
764 \fi%
765 \else
766 \ion@currnum%
767 \fi
768 \endgroup%
769 %% reset stuff for next number
770 \ion@thousands@currpos=0%
771 \ion@thousandths@currpos=0%
772 \def\ion@currnum{}%
773 \ion@currnum@firstchartrue%
774 \ion@beforedecimaltrue%
775 \ion@noexplicitthousandstrue%
776 \ion@currnum@exponentfalse%
777 \ion@exponent@superscriptfalse%
778}
This macro is identical to\l@addto@macrofromkoma-script bundle.
779\newcommand{\ion@addto@macro}[2]{%
780 \begingroup\toks@\expandafter{#1#2}%
781 \edef\@tempa{\endgroup\def\noexpand#1{\the\toks@}}%
782 \@tempa}
Change History
v0.2.0-alpha
General: initial .dtx version . . . 1 v0.2.1-alpha
General: replaced website by e-mail address in all fields containing contact information . . . 1 v0.2.2-alpha
General: fixed problem with sin-
gle digit numbers without {}- grouping; conflict with ams- math/amsopn documented and handled with warning messages;
thanks to Robert N¨urnberg for reporting these two problems . . 1 v0.2.3-alpha
General: saved one \if and made
sign/digit macros a bit clearer . 1 v0.2.4-alpha
General: fixed bug with curly braces in \ion@problem@package macro; thanks to Lars for re-
porting this problem . . . 1
v0.3.0-alpha General: added options for vari- able grouping lengths; extended LATEX test file . . . 1
v0.3.1-alpha General: fix in Makefile of package 1 v0.3.2-alpha General: added examples of usage . 1 v0.3.3 General: fixed problem when chang- ing the font, e. g., when load- ing the MnSymbol package; the original character defini- tions are not hard-coded any- more, but copied from the defi- nitions at the beginning of the document; thanks to Michael Sebastian Hitziger for his bug report . . . 1
Index
Numbers written in italic refer to the page where the corresponding entry is de- scribed; numbers underlined refer to the code line of the definition; numbers in roman refer to the code lines where the entry is used. Symbols \+ . . . 184\, . . . 160, 169, 177, 179, 183, 185 \- . . . 184
\. . . 183, 185 \@gobble . . 231, 248, 308, 328, 348, 368, 388, 408, 428, 448, 468, 488 \@ifpackageloaded . . . . 588, 595 \@ifstar . . 94, 107, 678 \@let@token . . . 529,
531–540, 556, 558, 559, 567, 569, 570, 579, 581 \@tempa . . . 63,
65, 73, 75, 781, 782 \@tempb . . 64, 65, 74, 75 \@undefined . . . 611
\@warning . . . . . 227, 244, 268, 288 Numbers \0 . . . 186
\1 . . . 186
\2 . . . 186
\3 . . . 187
\4 . . . 187
\5 . . . 187
\6 . . . 188
\7 . . . 188
\8 . . . 188
\9 . . . 189
A \active . . . 183–189 \AtBeginDocument . . . 114, 220, 601, 657 \AtEndOfPackage . . . 86
C \cdot . . . 179
\csname . . . 16,
17, 19, 20, 22, 24, 26, 28, 30, 32, 47, 48, 50, 51, 53, 55, 57, 59–61, 88, 90, 92, 96, 98, 101, 103, 105, 109, 112 \CurrentOption . . . . 42
D \DeclareOption . . . . 42
\define@key . . . 13, 44 E \endcsname . . . . 16,
17, 19, 20, 22, 24, 26, 28, 30, 32, 47, 48, 50, 51, 53, 55, 57, 59–61, 88, 90, 92, 96, 98, 101, 103, 105, 109, 112 \endionumbers . 217, 219 \expandafter . . . 42,
87–92, 95–98, 100–105, 108, 109, 111, 112, 780 F \fi . . . 11,
70, 80, 522, 523, 542–551, 561, 562, 572, 573, 585, 614, 637, 706, 711, 718, 723, 724, 751–
753, 757, 764, 767
\futurelet . . . . . 529, 556, 567, 579
G
\gdef . . . 497, 640
\global . . . 498–511 I
\ifcase . . . 686, 731
\ifion@autothousands . . . 2, 729
\ifion@autothousandths . . . 3, 755
\ifion@beforedecimal . . . 659, 684
\ifion@currnum@exponent . . . . 515, 661, 759
\ifion@currnum@firstchar . . . 518, 658
\ifion@exponent@superscript . . . 662, 760
\ifion@noexplicitthousands . . . 660, 730
\ifnum . . 7, 709, 714, 721
\ifx . 65, 75, 531–540, 558, 559, 569, 570, 581, 611, 634
\ion@addto@macro 681, 687, 689, 691, 693, 695, 697, 699, 701, 703, 705, 715, 717, 779
\ion@aftercomma@curr . 48, 223, 226, 230
\ion@aftercomma@decimal . . . 137
\ion@aftercomma@default . . . 139
\ion@aftercomma@ignore . . . 136
\ion@aftercomma@reset . . . 17
\ion@aftercomma@thousands . . . 138, 139
\ion@afterpoint@curr . 51, 240, 243, 247
\ion@afterpoint@decimal . . . 145, 147
\ion@afterpoint@default . . . 147
\ion@afterpoint@ignore . . . 144
\ion@afterpoint@reset . . . 20
\ion@afterpoint@thousands . . . 146
\ion@autothousandsreset . . . 29, 30
\ion@autothousandthsreset . . . 31, 32
\ion@beforedecimalfalse . . . 137, 145
\ion@beforedecimaltrue . . . 659, 774
\ion@comma 221, 498, 641
\ion@comma@curr . . . . 47, 223, 226, 230
\ion@comma@decimal . 133
\ion@comma@default . 135
\ion@comma@ignore . 132
\ion@comma@original . . . . 116, 149, 155, 164, 196, 233
\ion@comma@reset . . 16
\ion@comma@thousands . . . 134, 135
\ion@conflict@definedtest . . . . 610, 617–630
\ion@conflict@package . . . 587, 602
\ion@conflict@redefinedtest . . . . 633, 641–654
\ion@conflict@redefinedtest@macro . . . 640, 657
\ion@currnum 665, 681, 687, 689, 691, 693, 695, 697, 699, 701, 703, 705, 715, 717, 761, 763, 766, 772
\ion@currnum@append . . . 223, 226, 230, 240, 243, 247, 259, 279, 297, 299, 317, 319, 337, 339, 357, 359, 377, 379, 397, 399, 417, 419, 437, 439, 457, 459, 477, 479, 676
\ion@currnum@append@
. . . 678, 683
\ion@currnum@append@@
. . . 678, 680
\ion@currnum@exponent . . . 110, 113
\ion@currnum@exponentfalse . . . 661, 776
\ion@currnum@exponenttrue . 173–177, 179, 181
\ion@currnum@firstcharfalse . . . 524, 677
\ion@currnum@firstchartrue . . . 658, 773
\ion@currnum@output . . . . 231, 233, 248, 250, 270, 290, 308, 310, 328, 330, 348, 350, 368, 370, 388, 390, 408, 410, 428, 430, 448, 450, 468, 470, 488, 490, 726
\ion@decimal@comma . . 149, 151, 157, 166
\ion@decimal@curr . . . . 52, 133, 141
\ion@decimal@default . . . 152
\ion@decimal@point . . . . 148, 150, 152, 156, 165
\ion@decimal@punctcomma . . . 151
\ion@decimal@punctpoint . . . 150
\ion@decimal@reset . 21
\ion@define@charmacros . . . 497, 632
\ion@deflocopts 44, 46, 49, 52, 54, 56, 58, 60–62, 72
\ion@defpackopts . . . . . 13, 15, 18, 21, 23, 25, 27, 29, 31, 33, 36
\ion@digits@active . . 185, 496, 616, 639
\ion@digits@math@active . . . 192, 216
\ion@digits@math@inactive . . . 203, 218
\ion@E@original . . . . . . . 130, 174, 176
\ion@e@original . . . . 129, 172, 173, 175
\ion@eight 455, 510, 653
\ion@eight@original . 127, 212, 457, 459
\ion@exponent@cdottento . . . 179
\ion@exponent@curr . . . 58, 231, 248, 308, 328, 348, 368, 388, 408, 428, 448, 468, 488
\ion@exponent@default . . . 182
\ion@exponent@itE . 174
\ion@exponent@ite . 173
\ion@exponent@none . 171
\ion@exponent@original . . . 172, 182
\ion@exponent@reset 27
\ion@exponent@rmE . 176
\ion@exponent@rme . 175
\ion@exponent@superscriptfalse . . . 662, 777