summaryrefslogtreecommitdiff
path: root/macros/generic/texdimens/README.md
blob: ecd8631193172fb956b8a3ee9733f2e2487726fd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
texdimens
=========

## Copyright and License

Copyright (c) 2021 Jean-François Burnol

This file is part of the texdimens package distributed under the
LPPL 1.3c.  See file LICENSE.md.

Development: https://github.com/jfbu/texdimens

Release: `0.99 2021/11/02`

## Aim of this package

Utilities and documentation related to TeX dimensional units, usable
both with Plain (`\input texdimens`) and with LaTeX (`\usepackage{texdimens}`).

The aim of this package is to address the issue of expressing dimensions
(or dimension expressions evaluated by `\dimexpr`) in the various TeX
units, to the extent possible.

This project requires the e-TeX extensions `\dimexpr` and `\numexpr`.
The notation `<dim. expr.>` in the macro descriptions refers to a
*dimensional expression* as accepted by `\dimexpr`.  The syntax has some
peculiarities: among them the fact that `-(...)` (for example `-(3pt)`)
is illegal, one must use alternatives such as `0pt-(...)` or a
sub-expression `-\dimexpr...\relax` for example.

Notice that this is WIP and inaccuracies may exist even relative to
descriptions of TeX handlings due to limited time available for the
project.

## Quick review of basics: TeX points and scaled points

TeX dimensions are represented internally by a signed integer which is
in absolute value at most `0x3FFFFFFF`, i.e. `1073741823`.  The
corresponding unit is called the "scaled point", i.e. `1sp` is `1/65536`
of one TeX point `1pt`, or rather `1pt` is represented internally as `65536`.

If `\foo` is a dimen register:

- `\number\foo` produces the integer `N` such as `\foo` is the same as `Nsp`,

- inside `\numexpr`, `\foo` is replaced by `N`,

- `\the\foo` produces a decimal `D` (with at most five places) followed
  with `pt` (catcode 12 tokens) and this output `Dpt` can serve as input
  in a dimen assignment to produce the same dimension as `\foo`.  One can
  also use the catcode 11 characters `pt` for this.  Digits and decimal
  mark must have their standard catcode 12.

When TeX encounters a dimen denotation of the type `Dpt` it will
compute `N` in a way equivalent to `N = round(65536 D)` where ties are
rounded away from zero.  Only 17 decimal places of `D` are
kept as it can be shown that going beyond can not change the result.

When `\foo` has been assigned as `Dpt`, `\the\foo` will produce some
`Ept` where `E` is not necessarily the same as `D`.  But it is guaranteed
that `Ept` defines the same dimension as `Dpt̀`.

## Further units known to TeX on input

TeX understands on input further units: `bp`, `cm`, `mm`, `in`, `pc`,
`cc`, `nc`, `dd` and `nd`.  It also understands font-dependent units `ex` and
`em`, and PDFTeX adds the `px` dimension unit.  Japanese engines also
add specific units.

The `ex`, `em`, and `px` units are handled somewhat differently by (pdf)TeX than
`bp`, `cm`, `mm`, `in`, `pc`, `cc`, `nc`, `dd` and `nd` units. For the former
(let's use the generic notation `uu`), the exact same dimensions are obtained
from an input `D uu` where `D` is some decimal or from `D <dimen>` where `<dimen>`
stands for some dimension register which records `1uu` or `\dimexpr1uu\relax`. In
contrast, among the latter, i.e. the core TeX units, this is false except for the
`pc` unit.

The explanation is as follows (in this discussion `sp` is kept aside).

TeX associates (explicitly for the core units, implicitly for the units corresponding
to internal dimensions) to each unit `uu` a fraction `phi` which is a conversion
factor.  For the internal dimensions `ex`, `em`, `px` or in the case of multiplying
a dimension by a decimal, this `phi` is morally `f/65536` where `f` is the integer
such that `1 uu=f sp`.  For core units however, the hard-coded ratio `n/d` never has a
denominator `d` whici is a power of `2`, except for the `pc` whose associated ratio
factor is `12/1` (and arguably for the `sp` for which morally `phi` is `1/65536` but
we keep it separate from the general discussion).

As a result the value of `1 uu` as `f sp` is at best irrelevant
or at worst misleading regarding the way TeX parses `D uu`.  Notice for example
that `1.00375` is the exact value of the `phi` factor for the `bp` unit but
that `1.00375pt>1bp` ...
Here is a table with the hard-coded conversion factors:

    uu     phi      reduced  real approximation  1uu in sp=   x=[65536phi]/65536  \the<1uu>
                             (Python output)     [65536phi]  (real approximation)
    --  ----------  -------  ------------------   ---------  -------------------- ----------
    bp  7227/7200   803/800   1.00375                 65781    1.0037384033203125  1.00374pt
    nd  685/642     same      1.0669781931464175      69925    1.0669708251953125  1.06697pt
    dd  1238/1157   same      1.070008643042351       70124    1.07000732421875    1.07pt   
    mm  7227/2540   same      2.8452755905511813     186467    2.8452606201171875  2.84526pt
    pc  12/1        12       12.0                    786432   12.0                12.0pt    
    nc  1370/107    same     12.80373831775701       839105   12.803726196289062  12.80373pt
    cc  14856/1157  same     12.84010371650821       841489   12.840103149414062  12.8401pt 
    cm  7227/254    same     28.45275590551181      1864679   28.452743530273438  28.45274pt
    in  7227/100    same     72.27                  4736286   72.26998901367188   72.26999pt

When TeX parses an assignment `U uu` with a decimal `U` and a unit `uu`,
be it a core unit, or a unit corresponding to an internal dimension,
it first handles `U` as with the `pt` unit.
This means that it computes `N = round(65536*U)`. It then multiplies
this `N` by the conversion factor `phi` and truncates towards zero the
mathematically exact result to obtain an integer `T`:
`T=trunc(N*phi)`. The assignment `Uuu` is concluded by defining the
value of the dimension to be `Tsp`.

Regarding the core units, we always have `phi>1`.
The increasing
sequence `0<=trunc(phi)<=trunc(2phi)<=...` is thus *strictly increasing*
and, as `phi` is never astronomically close to `1`, 
**it always has jumps**: not all TeX dimensions can be obtained from an
assignment using a core unit distinct from the `pt` (and `sp` of course,
but we already said it was kept out of the discussion here).

On the other hand when `phi<1`, then the sequence `trunc(N phi)` is not
strictly increasing, already because `trunc(phi)=0` and besides here
`phi=f/65536`, so the `65536` integers `0..65535` are mapped to `f`
integers `0..(f-1)` inducing non one-to-oneness. But
all integers in the `0..(2**30-1)` range will be attained for some input,
so there is surjectivity.

The "worst" unit is the largest i.e. the `in` whose conversion factor is
`72.27`.  The simplest unit to understand is the `pc` as it corresponds
to an integer ratio `12`: only dimensions which in scaled points are
multiple of `12` are exactly representable in the `pc` unit.

This also means that some dimensions expressible in one unit may not be
available with another unit.  For example, and perhaps surprisingly,
there is no decimal `D` which would achieve `1in==Dcm`: the "step"
between attainable dimensions is `72--73sp` for the `in` and `28--29sp`
for the `cm`, and as `1in` differs internally from `2.54cm` by only
`12sp` it is impossible to adjust
either the `in` side or the `cm` side to obtain equality.

In particular `1in==2.54cm` is **false** in TeX, but it is true that
`100in==254cm`... (it is already true that `50in==127cm`).  It is also
false that `10in==25.4cm` but it is true that `10in==254mm`... It is
false though that `1in==25.4mm`!

    >>> (\dimexpr1in, \dimexpr2.54cm);
    @_1     4736286, 4736274
    >>> (\dimexpr10in, \dimexpr25.4cm);
    @_2     47362867, 47362855
    >>> (\dimexpr100in, \dimexpr254cm);
    @_3     473628672, 473628672
    
    >>> (\dimexpr1in, \dimexpr25.4mm);
    @_4     4736286, 4736285
    >>> (\dimexpr10in, \dimexpr254mm);
    @_5     47362867, 47362867

`\maxdimen` can be expressed only with `pt`, `bp`, and `nd`.  For the
other core units the maximal attainable dimensions in `sp` unit are given in
the middle column of the next table.

    maximal allowed      the corresponding      minimal TeX dimen denotation
    (with 5 places)   maximal attainable dim.   causing "Dimension too large"
    ---------------  -------------------------  --------------------------
    16383.99999pt    1073741823sp (=\maxdimen)  16383.99999237060546875pt
    16322.78954bp    1073741823sp (=\maxdimen)  16322.78954315185546875bp
    15355.51532nd    1073741823sp (=\maxdimen)  15355.51532745361328125nd
    15312.02584dd    1073741822sp               15312.02584075927734375dd
     5758.31742mm    1073741822sp                5758.31742095947265625mm
     1365.33333pc    1073741820sp                1365.33333587646484375pc
     1279.62627nc    1073741814sp                1279.62627410888671875nc
     1276.00215cc    1073741821sp                1276.00215911865234375cc
      575.83174cm    1073741822sp                 575.83174896240234375cm
      226.70540in    1073741768sp                 226.70540618896484375in

Perhaps for these various peculiarities with dimensional units, TeX does
not provide an output facility for them similar to what `\the` achieves for
the `pt`.

## Macros of this package (summary)

This package provides expandable (most are f-expandable, see the code)
macros (they can be nested as they parse their inputs via `\dimexpr`):

- `\texdimenpt`,
- `\texdimenUU`, `\texdimenUUup` and
  `\texdimenUUdown` with `UU` standing for one of `bp`, `cm`, `mm`, `in`,
  `pc`, `cc`, `nc`, `dd` and `nd`,
- `\texdimenbothincm` (and relatives not listed here, see below),
- and `\texdimenwithunit`, added at `0.99`.

For example `\texdimenbp` takes on input some dimension or dimension
expression and produces on output a decimal `D` such that `D bp` is
guaranteed to be the same dimension as the input, if that one admits any
representation as `E bp`; else it will be either the closest match from
above or from below. The `\texdimenbpup` and `\texdimenbpdown` allow to
choose the direction of approximation.

`\texdimenwithunit{<dimen1>}{<dimen2>}` produces a decimal `D` such
that `D \dimexpr dimen2\relax` is represented internally the same as
`dimen1` if at all possible, else is a closest match, but one does not
know if from below or above. If `dimen2<1pt` all TeX dimensions `dimen1`
are attainable. If `dimen2>1pt` not all `dimen1` are attainable.

Negative dimensions behave as if replaced by their absolute value, then
at last step the sign (if result is not zero) is applied (so "down" means
"towards zero", and "up" means "away from zero").

Do not confuse `\texdimenwithunit{dim}{1bp}` with
`\texdimenbp{dim}`. The former produces a decimal `D` such that
`D\dimexpr 1bp\relax` is represented internally as is `dim` if at all
possible, whereas the latter produces a decimal `D` such that `D bp` is
the one aiming at being the same as `dim`. Using `D\dimexpr 1bp\relax`
implies a conversion factor equal to `65781/65536`, whereas `D bp`
involves the `803/800` conversion factor.


## Macros of this package (full list)

1. For input `X` equal to (or sufficiently close to) `\maxdimen` and
   those units `uu` for which `\maxdimen` is not exactly representable
   (i.e. all core units except `pt`, `bp` and `nd`), the output `D` of the
   "up" macros `\texdimen<uu>up{X}`, if used as `Duu` in a dimension
   assignment or expression, will (naturally) trigger a "Dimension too
   large" error.
2. For `dd`, `nc` and `in`, and input `X` equal to (or sufficiently
   close to) `\maxdimen` it turns out that `\texdimen<uu>{X}` produces
   an output `D` such that `Duu` is the first "virtually attainable" TeX
   dimension *beyond* `\maxdimen`.  Hence `Duu` will trigger on use
   "Dimension too large error".
3. Again for the `dd`, `nc` and `in` units, both the "down" and "up" macros
   will trigger "Dimension too large" during their execution if used
   with an input equal to (or sufficiently close to) `\maxdimen`.
4. With `\texdimenwithunit{dimen1}{dimen2}` and if `\maxdimen`
   is not representable exactly by `dimen2` used as a base dimension,
   (which may happen only if `dimen2>1pt`) it might
   be that the decimal `D` produced from `\maxdimen` or nearby dimensions
   will trigger "Dimension too large" if an attempt to use `D <dimen2>` is
   made.

`\texdimenpt{<dim. expr.>}`

> Does `\the\dimexpr <dim. expr.> \relax` then removes the `pt`.

`\texdimenbp{<dim. expr.>}`

> Produces a decimal (with up to five decimal places) `D` such that `Dbp`
> represents the dimension exactly if possible. If not possible it
> will differ by `1sp` from the original dimension, but it is not
> known in advance if it will be above or below.

> `\maxdimen` on input produces `16322.78954` and indeed is realized as `16322.78954bp`.

`\texdimenbpdown{<dim. expr.>}`

> Produces a decimal (with up to five decimal places) `D` such that `Dbp`
> represents the dimension exactly if possible. If not possible it
> will be smaller by `1sp` from the original dimension.

`\texdimenbpup{<dim. expr.>}`

> Produces a decimal (with up to five decimal places) `D` such that `Dbp`
> represents the dimension exactly if possible. If not possible it
> will be larger by `1sp` from the original dimension.

`\texdimennd{<dim. expr.>}`

> Produces a decimal (with up to five decimal places) `D` such that `Dnd`
> represents the dimension exactly if possible. If not possible it
> will differ by `1sp` from the original dimension, but it is not
> known in advance if it will be above or below.

> `\maxdimen` on input produces `15355.51532` and indeed is realized as `15355.51532nd`.

`\texdimennddown{<dim. expr.>}`

> Produces a decimal (with up to five decimal places) `D` such that `Dnd`
> represents the dimension exactly if possible. If not possible it
> will be smaller by `1sp` from the original dimension.

`\texdimenndup{<dim. expr.>}`

> Produces a decimal (with up to five decimal places) `D` such that `Dnd`
> represents the dimension exactly if possible. If not possible it
> will be larger by `1sp` from the original dimension.

`\texdimendd{<dim. expr.>}`

> Produces a decimal (with up to five decimal places) `D` such that `Ddd`
> represents the dimension exactly if possible. If not possible it
> will differ by `1sp` from the original dimension, but it is not
> known in advance if it will be above or below.

> Warning: the output for `\maxdimen` is `15312.02585` but `15312.02585dd`
> will trigger "Dimension too large" error.
> `\maxdimen-1sp` is attainable via `15312.02584dd`.

`\texdimendddown{<dim. expr.>}`

> Produces a decimal (with up to five decimal places) `D` such that `Ddd`
> represents the dimension exactly if possible. If not possible it
> will be smaller by `1sp` from the original dimension.

`\texdimenddup{<dim. expr.>}`

> Produces a decimal (with up to five decimal places) `D` such that `Ddd`
> represents the dimension exactly if possible. If not possible it
> will be larger by `1sp` from the original dimension.

`\texdimenmm{<dim. expr.>}`

> Produces a decimal (with up to five decimal places) `D` such that `Dmm`
> represents the dimension exactly if possible. If not possible it
> will either be the closest from below or from above, but it is not
> known in advance which one (and it is not known if the other choice
> would have been closer).

> `\maxdimen` as input produces on output `5758.31741` and indeed the
> maximal attainable dimension is `5758.31741mm` (`1073741822sp`).

`\texdimenmmdown{<dim. expr.>}`

> Produces a decimal (with up to five decimal places) `D` such that `Dmm`
> represents the dimension exactly if possible. If not possible it
> will be largest representable dimension smaller than the original one.

`\texdimenmmup{<dim. expr.>}`

> Produces a decimal (with up to five decimal places) `D` such that `Dmm`
> represents the dimension exactly if possible. If not possible it
> will be smallest representable dimension larger than the original one.

`\texdimenpc{<dim. expr.>}`

> Produces a decimal (with up to five decimal places) `D` such that `Dpc`
> represents the dimension exactly if possible. If not possible it
> will be the closest representable one (in case of tie, the approximant
> from above is chosen).

> `\maxdimen` as input produces on output `1365.33333` and indeed the
> maximal attainable dimension is `1365.33333pc` (`1073741820sp`).

`\texdimenpcdown{<dim. expr.>}`

> Produces a decimal (with up to five decimal places) `D` such that `Dpc`
> represents the dimension exactly if possible. If not possible it
> will be largest representable dimension smaller than the original one.

`\texdimenpcup{<dim. expr.>}`

> Produces a decimal (with up to five decimal places) `D` such that `Dpc`
> represents the dimension exactly if possible. If not possible it
> will be smallest representable dimension larger than the original one.

`\texdimennc{<dim. expr.>}`

> Produces a decimal (with up to five decimal places) `D` such that `Dnc`
> represents the dimension exactly if possible. If not possible it
> will either be the closest from below or from above, but it is not
> known in advance which one (and it is not known if the other choice
> would have been closer).

> Warning: the output for `\maxdimen` is `1279.62628` but `1279.62628nc`
> will trigger "Dimension too large" error.
> `\maxdimen-9sp` is attainable via `1279.62627nc`.

`\texdimenncdown{<dim. expr.>}`

> Produces a decimal (with up to five decimal places) `D` such that `Dnc`
> represents the dimension exactly if possible. If not possible it
> will be largest representable dimension smaller than the original one.

`\texdimenncup{<dim. expr.>}`

> Produces a decimal (with up to five decimal places) `D` such that `Dnc`
> represents the dimension exactly if possible. If not possible it
> will be smallest representable dimension larger than the original one.

`\texdimencc{<dim. expr.>}`

> Produces a decimal (with up to five decimal places) `D` such that `Dcc`
> represents the dimension exactly if possible. If not possible it
> will either be the closest from below or from above, but it is not
> known in advance which one (and it is not known if the other choice
> would have been closer).

> `\maxdimen` as input produces on output `1276.00215` and indeed the
> maximal attainable dimension is `1276.00215cc` (`1073741821sp`).

`\texdimenccdown{<dim. expr.>}`

> Produces a decimal (with up to five decimal places) `D` such that `Dcc`
> represents the dimension exactly if possible. If not possible it
> will be largest representable dimension smaller than the original one.

`\texdimenccup{<dim. expr.>}`

> Produces a decimal (with up to five decimal places) `D` such that `Dcc`
> represents the dimension exactly if possible. If not possible it
> will be smallest representable dimension larger than the original one.

`\texdimencm{<dim. expr.>}`

> Produces a decimal (with up to five decimal places) `D` such that `Dcm`
> represents the dimension exactly if possible. If not possible it
> will either be the closest from below or from above, but it is not
> known in advance which one (and it is not known if the other choice
> would have been closer).

> `\maxdimen` as input produces on output `575.83174` and indeed the
> maximal attainable dimension is `575.83174cm` (`1073741822sp`).

`\texdimencmdown{<dim. expr.>}`

> Produces a decimal (with up to five decimal places) `D` such that `Dcm`
> represents the dimension exactly if possible. If not possible it
> will be largest representable dimension smaller than the original one.

`\texdimencmup{<dim. expr.>}`

> Produces a decimal (with up to five decimal places) `D` such that `Dcm`
> represents the dimension exactly if possible. If not possible it
> will be smallest representable dimension larger than the original one.

`\texdimenin{<dim. expr.>}`

> Produces a decimal (with up to five decimal places) `D` such that `Din`
> represents the dimension exactly if possible. If not possible it
> will either be the closest from below or from above, but it is not
> known in advance which one (and it is not known if the other choice
> would have been closer).

> Warning: the output for `\maxdimen` is `226.70541` but `226.70541in`
> will trigger "Dimension too large" error.
> `\maxdimen-55sp` is maximal attainable dimension (via `226.7054in`).

`\texdimenindown{<dim. expr.>}`

> Produces a decimal (with up to five decimal places) `D` such that `Din`
> represents the dimension exactly if possible. If not possible it
> will be largest representable dimension smaller than the original one.

`\texdimeninup{<dim. expr.>}`

> Produces a decimal (with up to five decimal places) `D` such that `Din`
> represents the dimension exactly if possible. If not possible it
> will be smallest representable dimension larger than the original one.

`\texdimenbothcmin{<dim. expr.>}`

> Produces a decimal (with up to five decimal places) `D` such that `Din`
> is the largest dimension smaller than the original one and
> exactly representable both in the `in` and `cm` units.

`\texdimenbothincm{<dim. expr.>}`

> Produces a decimal (with up to five decimal places) `D` such that `Dcm`
> is the largest dimension smaller than the original one and
> exactly representable both in the `in` and `cm` units.  It thus represents
> the same dimension as `\texdimenbothcmin{<dim. expr.>}in`.

`\texdimenbothcminpt{<dim. expr.>}`

> Produces a decimal (with up to five decimal places) `D` such that `Dpt`
> is the largest dimension smaller than the original one and
> exactly representable both in the `in` and `cm` units.  It thus represents
> the same dimension as the one provided by `\texdimenbothcmin` and
> `\texdimenbothincm`.

`\texdimenbothincmpt{<dim. expr.>}`

> Same as `\texdimenbothcminpt`.

`\texdimenbothcminsp{<dim. expr.>}`

> Produces an integer (explicit digit tokens) `N` such that `Nsp`
> is the largest dimension smaller than the original one and
> exactly representable both in the `in` and `cm` units.

`\texdimenbothincmsp{<dim. expr.>}`

> Same as `\texdimenbothcminsp`.

`\texdimenwithunit{<dim. expr. 1>}{<dim expr. 2>}`

> Produces a decimal `D` such that `D\dimexpr <dim expr. 2>\relax` is
> considered by TeX the same as `<dim. expr. 1>` if at all possible.
> If not possible it will be a closest match either from above or below.


## Extras?

As already stated the "up" and also the "down" macros for the `dd`, `nc`
and `in` units will trigger "Dimension too large" if used with inputs
equal to or very near `\maxdimen`.  "Safe" variants which are guaranteed
never to trigger this error but have some extra overhead to filter out
inputs very close to `\maxdimen` will *perhaps* be provided if there is
some demand for it.

But of course anyhow the output from the "up" macros if used
as input with the corresponding unit will be beyond `\maxdimen` if the
latter is not attainable, i.e. for all units except `bp`, and `nd`
(and `pt` but there is no "up" macro for it).

The
dimensions representable with both `in` and `cm` units have the shape
`trunc(3613.5*k)sp` for some integer `k`. The largest one smaller
than a given dimension will thus differ from it by at most about `0.055pt`,
which is also about `0.02mm`.

For example `\texdimenbothincm{1cm}` expands to `0.99994cm` which maps
internally to `1864566sp` which differs from TeX's `1cm` by only
`-113sp`. It can be obtained from `0.39368in` or `28.45102pt`.

And `\texdimenbothcmin{1in}` expands to `0.99945in`, maps internally to
`4733685sp` which differs from TeX's `1in` by `-2601sp`. It can be obtained
as `2.5386cm` or `72.2303pt`.

Currently the package does not provide analogous approximations from above.
For the `1in` for example it would be `4737298sp`, i.e. `1.00021in` which
differs from TeX's `1in` by `+1012sp` and is obtained also as `2.54054cm`
and `72.28543pt`.

## Acknowledgements

Thanks to Denis Bitouzé for raising an issue on the LaTeX3 tracker which
gave the initial motivation for this package.

Thanks to Ruixi Zhang for reviving the topic about handling also
the `ex` and `em` cases, which led to `\texdimenwithunit`.

<!--
-->