texlive[60006] Master/texmfdist: texdimens (21jul21)
commits+karl at tug.org
commits+karl at tug.org
Wed Jul 21 22:46:24 CEST 2021
Revision: 60006
http://tug.org/svn/texlive?view=revision&revision=60006
Author: karl
Date: 20210721 22:46:23 +0200 (Wed, 21 Jul 2021)
Log Message:

texdimens (21jul21)
Modified Paths:

trunk/Master/texmfdist/doc/generic/texdimens/README.md
trunk/Master/texmfdist/tex/generic/texdimens/texdimens.sty
trunk/Master/texmfdist/tex/generic/texdimens/texdimens.tex
Modified: trunk/Master/texmfdist/doc/generic/texdimens/README.md
===================================================================
 trunk/Master/texmfdist/doc/generic/texdimens/README.md 20210721 20:46:10 UTC (rev 60005)
+++ trunk/Master/texmfdist/doc/generic/texdimens/README.md 20210721 20:46:23 UTC (rev 60006)
@@ 10,7 +10,7 @@
Development: https://github.com/jfbu/texdimens
Release: `0.9delta 2021/07/15`
+Release: `0.9 2021/07/21`
## Aim of this package
@@ 46,24 +46,24 @@
If `\foo` is a dimen register:
 `\number\foo` produces the integer `N` such as `\foo` is the same as `N sp`,
+ `\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 `D pt` can serve as input
+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 `D pt` it will
+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 `D pt`, `\the\foo` will produce some
`E pt` where `E` is not necessarily the same as `D`. But it is guaranteed
that `E pt` defines the same dimension as `D pt̀`.
+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
@@ 100,8 +100,8 @@
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 `U uu` is concluded by defining the
value of the dimension to be `T sp`.
+`T=trunc(N*phi)`. The assignment `Uuu` is concluded by defining the
+value of the dimension to be `Tsp`.
Attention that although the mnemotic is `phi=1uu/1pt`, this formula
definitely does not apply with numerator and denominator interpreted as
@@ 129,7 +129,7 @@
for the `cm`, and as `1in` differs internally from `2.54cm` by only
`12sp` (see below the `xintsession` verbatim) it is impossible to adjust
either the `in` side or the `cm` side to obtain equality. See in the
[TODO] section the closest dimension attainable both via `in` and via
+[Extras?] section the closest dimension attainable both via `in` and via
`cm`.
In particular `1in==2.54cm` is **false** in TeX, but it is true that
@@ 152,19 +152,19 @@
other 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.99999 pt 1073741823 sp (=\maxdimen) 16383.99999237060546875 pt
 16322.78954 bp 1073741823 sp (=\maxdimen) 16322.78954315185546875 bp
 15355.51532 nd 1073741823 sp (=\maxdimen) 15355.51532745361328125 nd
 15312.02584 dd 1073741822 sp 15312.02584075927734375 dd
 5758.31742 mm 1073741822 sp 5758.31742095947265625 mm
 1365.33333 pc 1073741820 sp 1365.33333587646484375 pc
 1279.62627 nc 1073741814 sp 1279.62627410888671875 nc
 1276.00215 cc 1073741821 sp 1276.00215911865234375 cc
 575.83174 cm 1073741822 sp 575.83174896240234375 cm
 226.70540 in 1073741768 sp 226.70540618896484375 in
+ 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
@@ 173,11 +173,11 @@
## Macros of this package
The macros defined by the package are expandable, and will expand
completely in an `\edef`, or in a `\dimexpr...\relax` construc.
+completely in an `\edef`, or in a `\dimexpr...\relax` construct.
As they parse their inputs via `\dimexpr` they can be nested (with
suitable postfix dimension unit added to inner macro).
+the suitable dimension unit added as postfix to nested macro).
Apart for the `\texdimin<uu>up` in case of a negative input, they will
+Apart from the `\texdimen<uu>up` in case of a negative input, they will
even expand completely under fexpansion.
Negative dimensions behave as if replaced by their absolute value, then
@@ 187,25 +187,25 @@
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 units except `pt`, `bp` and `nd`), the output `D` of the
 "up" macros `\texdimin<uu>up{X}`, if used as `Duu` in a dimension
+ "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 `\texdimin<uu>{X}` produces
+ 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`.
+ with an input equal to (or sufficiently close to) `\maxdimen`.
`\texdiminpt{<dim. expr.>}`
+`\texdimenpt{<dim. expr.>}`
> Does `\the\dimexpr <dim. expr.> \relax` then removes the `pt`.
`\texdiminbp{<dim. expr.>}`
+`\texdimenbp{<dim. expr.>}`
> Produces a decimal (with up to five decimal places) `D` such that `D bp`
+> 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.
@@ 212,21 +212,21 @@
> `\maxdimen` on input produces `16322.78954` and indeed is realized as `16322.78954bp`.
`\texdiminbpdown{<dim. expr.>}`
+`\texdimenbpdown{<dim. expr.>}`
> Produces a decimal (with up to five decimal places) `D` such that `D bp`
+> 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.
`\texdiminbpup{<dim. expr.>}`
+`\texdimenbpup{<dim. expr.>}`
> Produces a decimal (with up to five decimal places) `D` such that `D bp`
+> 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.
`\texdiminnd{<dim. expr.>}`
+`\texdimennd{<dim. expr.>}`
> Produces a decimal (with up to five decimal places) `D` such that `D nd`
+> 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.
@@ 233,21 +233,21 @@
> `\maxdimen` on input produces `15355.51532` and indeed is realized as `15355.51532nd`.
`\texdiminnddown{<dim. expr.>}`
+`\texdimennddown{<dim. expr.>}`
> Produces a decimal (with up to five decimal places) `D` such that `D nd`
+> 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.
`\texdiminndup{<dim. expr.>}`
+`\texdimenndup{<dim. expr.>}`
> Produces a decimal (with up to five decimal places) `D` such that `D nd`
+> 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.
`\texdimindd{<dim. expr.>}`
+`\texdimendd{<dim. expr.>}`
> Produces a decimal (with up to five decimal places) `D` such that `D dd`
+> 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.
@@ 256,21 +256,21 @@
> will trigger "Dimension too large" error.
> `\maxdimen1sp` is attainable via `15312.02584dd`.
`\texdimindddown{<dim. expr.>}`
+`\texdimendddown{<dim. expr.>}`
> Produces a decimal (with up to five decimal places) `D` such that `D dd`
+> 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.
`\texdiminddup{<dim. expr.>}`
+`\texdimenddup{<dim. expr.>}`
> Produces a decimal (with up to five decimal places) `D` such that `D dd`
+> 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.
`\texdiminmm{<dim. expr.>}`
+`\texdimenmm{<dim. expr.>}`
> Produces a decimal (with up to five decimal places) `D` such that `D mm`
+> 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
@@ 279,21 +279,21 @@
> `\maxdimen` as input produces on output `5758.31741` and indeed the
> maximal attainable dimension is `5758.31741mm` (`1073741822sp`).
`\texdiminmmdown{<dim. expr.>}`
+`\texdimenmmdown{<dim. expr.>}`
> Produces a decimal (with up to five decimal places) `D` such that `D mm`
+> 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.
`\texdiminmmup{<dim. expr.>}`
+`\texdimenmmup{<dim. expr.>}`
> Produces a decimal (with up to five decimal places) `D` such that `D mm`
+> 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.
`\texdiminpc{<dim. expr.>}`
+`\texdimenpc{<dim. expr.>}`
> Produces a decimal (with up to five decimal places) `D` such that `D pc`
+> 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).
@@ 301,21 +301,21 @@
> `\maxdimen` as input produces on output `1365.33333` and indeed the
> maximal attainable dimension is `1365.33333pc` (`1073741820sp`).
`\texdiminpcdown{<dim. expr.>}`
+`\texdimenpcdown{<dim. expr.>}`
> Produces a decimal (with up to five decimal places) `D` such that `D pc`
+> 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.
`\texdiminpcup{<dim. expr.>}`
+`\texdimenpcup{<dim. expr.>}`
> Produces a decimal (with up to five decimal places) `D` such that `D pc`
+> 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.
`\texdiminnc{<dim. expr.>}`
+`\texdimennc{<dim. expr.>}`
> Produces a decimal (with up to five decimal places) `D` such that `D nc`
+> 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
@@ 325,21 +325,21 @@
> will trigger "Dimension too large" error.
> `\maxdimen9sp` is attainable via `1279.62627nc`.
`\texdiminncdown{<dim. expr.>}`
+`\texdimenncdown{<dim. expr.>}`
> Produces a decimal (with up to five decimal places) `D` such that `D nc`
+> 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.
`\texdiminncup{<dim. expr.>}`
+`\texdimenncup{<dim. expr.>}`
> Produces a decimal (with up to five decimal places) `D` such that `D nc`
+> 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.
`\texdimincc{<dim. expr.>}`
+`\texdimencc{<dim. expr.>}`
> Produces a decimal (with up to five decimal places) `D` such that `D cc`
+> 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
@@ 348,21 +348,21 @@
> `\maxdimen` as input produces on output `1276.00215` and indeed the
> maximal attainable dimension is `1276.00215cc` (`1073741821sp`).
`\texdiminccdown{<dim. expr.>}`
+`\texdimenccdown{<dim. expr.>}`
> Produces a decimal (with up to five decimal places) `D` such that `D cc`
+> 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.
`\texdiminccup{<dim. expr.>}`
+`\texdimenccup{<dim. expr.>}`
> Produces a decimal (with up to five decimal places) `D` such that `D cc`
+> 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.
`\texdimincm{<dim. expr.>}`
+`\texdimencm{<dim. expr.>}`
> Produces a decimal (with up to five decimal places) `D` such that `D cm`
+> 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
@@ 371,21 +371,21 @@
> `\maxdimen` as input produces on output `575.83174` and indeed the
> maximal attainable dimension is `575.83174cm` (`1073741822sp`).
`\texdimincmdown{<dim. expr.>}`
+`\texdimencmdown{<dim. expr.>}`
> Produces a decimal (with up to five decimal places) `D` such that `D cm`
+> 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.
`\texdimincmup{<dim. expr.>}`
+`\texdimencmup{<dim. expr.>}`
> Produces a decimal (with up to five decimal places) `D` such that `D cm`
+> 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.
`\texdiminin{<dim. expr.>}`
+`\texdimenin{<dim. expr.>}`
> Produces a decimal (with up to five decimal places) `D` such that `D in`
+> 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
@@ 395,18 +395,54 @@
> will trigger "Dimension too large" error.
> `\maxdimen55sp` is maximal attainable dimension (via `226.7054in`).
`\texdiminindown{<dim. expr.>}`
+`\texdimenindown{<dim. expr.>}`
> Produces a decimal (with up to five decimal places) `D` such that `D in`
+> 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.
`\texdimininup{<dim. expr.>}`
+`\texdimeninup{<dim. expr.>}`
> Produces a decimal (with up to five decimal places) `D` such that `D in`
+> 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.>}` (new with `0.9dev`)
+
+> 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.>}` (new with `0.9dev`)
+
+> 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.>}` (new with `0.9dev`)
+
+> 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.>}` (new with `0.9dev`)
+
+> Same as `\texdimenbothcminpt`.
+
+`\texdimenbothcminsp{<dim. expr.>}` (new with `0.9dev`)
+
+> 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.>}` (new with `0.9dev`)
+
+> Same as `\texdimenbothcminsp`.
+
+
## Extras?
As already stated the "up" and also the "down" macros for the `dd`, `nc`
@@ 418,46 +454,28 @@
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 atteignable, i.e. for all units except `bp`, and `nd`
+latter is not attainable, i.e. for all units except `bp`, and `nd`
(and `pt` but there is no "up" macro for it).
Provide a macro `\texdimforbothincm{<dim.expr.>}` which would output
the nearest dimension simultaneously representable both in `in` and in
`cm`?

According to a reference on the web by an anonymous contributor the
dimensions representable with both `in` and `cm` units have the shape
`trunc(3613.5*k) sp` for some integer `k`. So we basically may have a
delta up to about `1800sp` which is about `0.0275pt` and is still small
(less than one hundredth of a millimeter, i.e. less than ten micron),
so perhaps such a utility for
"safe dimensions" may be useful. Here are for example the dimensions
nearest to `1in` and realizable both in `in` and `cm` units:
+`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`.
 >>> \input texdimens.tex\relax
 (executing \input texdimens.tex\relax in background)
 (./texdimens.tex)
 >>> &exact
 exact mode (floating point evaluations use 16 digits)
 >>> (\texdiminin{4737298sp});
 @_10 1.00021
 >>> (\texdimincm{4737298sp});
 @_11 2.54054
 >>> (\dimexpr1.00021in, \dimexpr2.54054cm);
 @_12 4737298, 4737298
 >>> (\texdiminin{4733685sp});
 @_13 0.99945
 >>> (\texdimincm{4733685sp});
 @_14 2.5386
 >>> (\dimexpr0.99945in, \dimexpr2.5386cm);
 @_15 4733685, 4733685
+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`.
As promised, one of them, the upper approximation, is at less than
one hundredth of millimeter from the two nearby targets.
+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`.
Simpler however and more efficient
would be for people to finally adopt the French revolution Système
Métrique (rather than setting up giant financial paradises).
+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`.
+
<!
>
Modified: trunk/Master/texmfdist/tex/generic/texdimens/texdimens.sty
===================================================================
 trunk/Master/texmfdist/tex/generic/texdimens/texdimens.sty 20210721 20:46:10 UTC (rev 60005)
+++ trunk/Master/texmfdist/tex/generic/texdimens/texdimens.sty 20210721 20:46:23 UTC (rev 60006)
@@ 1,5 +1,5 @@
% This is file texdimens.tex, part of texdimens package, which
% is distributed under the LPPL 1.3c. Copyright (c) 2021 JeanFrançois Burnol
\ProvidesPackage{texdimens}[2021/07/15 v0.9delta conversion of TeX dimensions to decimals (JFB)]
+\ProvidesPackage{texdimens}[2021/07/21 v0.9 conversion of TeX dimensions to decimals (JFB)]
\@@input texdimens.tex\relax
\endinput
\ No newline at end of file
Modified: trunk/Master/texmfdist/tex/generic/texdimens/texdimens.tex
===================================================================
 trunk/Master/texmfdist/tex/generic/texdimens/texdimens.tex 20210721 20:46:10 UTC (rev 60005)
+++ trunk/Master/texmfdist/tex/generic/texdimens/texdimens.tex 20210721 20:46:23 UTC (rev 60006)
@@ 1,29 +1,70 @@
% This is file texdimens.tex, part of texdimens package, which
% is distributed under the LPPL 1.3c. Copyright (c) 2021 JeanFrançois Burnol
% 2021/07/15 v0.9delta
+% 2021/07/21 v0.9
+% All macros from 0.9delta release have changed names: \texdimen prefix
+% has replaced \texdimin.
\edef\texdimensendinput{\endlinechar\the\endlinechar\catcode`\noexpand _=\the\catcode`\_\relax\noexpand\endinput}%
\endlinechar13\relax%
\catcode`\_=11
%
% Mathematics
+% Mathematics ("down" and "up" macros)
% ===========
%
% Is T sp attainable from unit "uu"?. Here we suppose T>0.
% phi>1, psi=1/phi, psi<1
% U(N,phi)=trunc(N phi) is strictly increasing
+% Is T sp attainable from unit "uu"?.
+% If not, what is largest dimension < Tsp which is attainable?
+% Here we suppose T>0.
+%
+% phi>1, psi=1/phi, psi<1.
+%
+% U(N,phi)=trunc(N phi) is the strictly increasing sequence,
+% indexed by nonnegative integers, of attainable dimensions.
+% (in sp unit)
+%
% U(N)<= T < U(N+1) iff N = ceil((T+1)psi)  1
% U(M)< T <= U(M+1) iff M = ceil(T psi)  1
% Either:
+%
+% Stumbling block
+% 
+%
+% The stumbling block is that computing "ceil((T+1)psi)  1" without
+% overflow is not obvious: yes \numexpr/\dimexpr allow socalled
+% "scaling operations" but only in the "rounding up" variant.
+%
+% If we attempt computing the ceil(x) function via round(x+0.5),
+% for example with psi=100/7227 which corresponds to the unit "in",
+% this necessitates evaluating:
+%
+% round((((T+1)*200)+7227)/14454)
+%
+% But as far as I can tell currently, for this we need to be able
+% to evaluate without overflow (T+1)*200+7227 and this limits to
+% T's which are (roughly) such that 100 T is less than \maxdimen.
+%
+% A workaround
+% 
+%
+% The rest of the discussion is about an algorithm providing an
+% alternative route to N, using \numexpr/\dimexpr/TeX facilities,
+% and working with (almost, as we will see) the full range of allowed
+% T's, 0 < T <= \maxdimen. (that the algorithm works for T=0 is to be
+% checked manually after the main discussion).
+%
+% Let's return to the U(N)<= T < U(N+1) and U(M)< T <= U(M+1) equations.
+%
+% Either (recall in all of this T > 0):
+%
% case1: M = N, i.e. T is not attainable, M=N < T psi < (T+1) psi <= N+1
% case2: M = N  1, i.e. T is attained, T psi <= N < (T+1) psi, T = floor(N phi)
+% case2: M = N  1, i.e. T is attained, T psi <= N < (T+1) psi, T = trunc(N phi)
%
% Let X = round(T psi). And let Y = trunc(X phi).
+% Let X = round(T psi). And let Y = trunc(X phi). We will explain later
+% how X and Y can be computed using \numexpr/\dimexpr/TeX.
%
% case1: X can be N or N+1. It will be N+1 iff Y > T.
% case2: X can be N or N1. It will be N iff trunc((X+1)phi)>T.
%
% This is not convenient: if Y <= T it might still be that we are in case 2
% and we must check then if trunc((X+1) phi) > T or not.
+% This is not convenient: if Y < T it could be that we are in case 2
+% but to decide we must check if trunc((X+1) phi) = T or not, so
+% this means a second computation.
%
% If psi < 0.5
% 
@@ 37,11 +78,11 @@
% a) compute X = round(T psi)
% b) compute Y = trunc(X phi) and test if Y > T. If true, we
% were in case 1, replace X by X  1, else we were either
% in case 1 or case 2, but we can leave X as is.
+% in case 1 or case 2, and we leave X as it is.
% We have thus found N.
%
% The operation Y = trunc(X phi) can be achieved this way:
% i) use \the\dimexpr to convert X sp into D pt,
+% i) use \the\dimexpr to convert X sp into D pt,
% ii) use \the\numexpr\dimexpr to convert "D uu" into sp.
% These steps give Y.
%
@@ 50,14 +91,14 @@
%
% The computations of X and Y can be done independently of sign of T.
% But the final test has to be changed to Y < T if T < 0 and then
% one must replace X by X+1. So we must filter sign.
+% one must replace X by X+1. So we must filter out the sign of the input.
%
% If the goal is only to find a decimal D such that "D uu" is
+% If the goal is only to find a decimal D such that "D uu" is
% exactly T sp in the case this is possible, then things are simpler
% because from X = round(T psi) we get D such as X sp is same as D pt
% and "D uu" will work.
% We don't have to take sign into account for this computation.
% But if T sp was not atteignable we don't know if this X will give
+% But if T sp was not attainable we don't know if this X will give
% a D such that D uu < T sp or D uu > T sp.
%
% If psi > 0.5
@@ 65,7 +106,7 @@
%
% For example unit "bp" has phi=803/800.
%
% It is then not true that if T sp is atteignable, the X = round(T psi)
+% It is then not true that if T sp is attainable, the X = round(T psi)
% will always work.
%
% But it is true that R = round((T + 0.5) psi) will always work.
@@ 76,7 +117,7 @@
%
% So this gives an approach to find a D such that "D uu" is exactly
% T sp when this is possible.
%
+%
% If Tsp (positive) is not attainable, this R however can produce
% either N or N+1.
%
@@ 86,43 +127,39 @@
% It is slightly less costly to compute X = round(T psi) than
% R = round((T + 0.5) psi),
% but if we then realize that trunc(X phi) < T we do not yet know
% if trunc((X+1) phi) = T or is > T.
+% if trunc((X+1) phi) = T or is > T. So we proceed via R, not X,
+% to not have to make a second computation if a dimension comparison
+% test goes awry.
%
% To recapitulate: we have our algorithm for all units to find out
% maximal dimension exactly atteignable in "uu" unit and at most equal
+% maximal dimension exactly attainable in "uu" unit and at most equal
% to (positive) T sp.
%
% Unfortunately the check that Y (in case psi < 0.5) or Z (in case psi >
% 0.5) may trigger a Dimension too large error if T sp was near
% nonatteignable \maxdimen.
+% 0.5) verifies or not Y > T may trigger a Dimension too large error if
+% T sp was near nonattainable \maxdimen. It turns out this sad
+% situation happens only for the units `dd`, `nc`, and `in`, and T sp
+% very close to \maxdimen (like for all units apart from `pt`, `bp`,
+% `nd`, the \maxdimen is not attainable, and by bad luck for `dd`, `nc`,
+% and `in`, the X will correspond to a decimal D such that Duu>\maxdimen
+% is the nearest virtually attaible dimensions from above not from
+% below; see the README.md for the tabulation of the maximal usable inputs).
%
% For additional envisioned "safe versions" we would tabulate first per unit
% what is the integer Rmax such that trunc(Rmax phi) <= \maxdimen. Then
% the "safe" versions would have an extra check of X or R before
% proceeding further. But the "up macros" supposed to give the next
% dimension above Tsp and exactly atteignable in "uu" unit, if compliant
% to their description can not avoid "Dimension too large" for inputs
% close to nonattainable \maxdimen.
+% Regarding the \texdimen<uu> macros, and units with phi > 2, I
+% hesitated using either the round((T+0.5)psi) or round(T psi), but for
+% Tsp = \maxdimen, both formulas turned out to give the same result for
+% all such units, so I chose for these \texdimen<uu> macros and the
+% units with phi>2 to use the simpler round(T psi) which does not need
+% to check the sign of T.
%
% After having written the macros we will tabulate what is for each unit
% the maximal attainable dimension.
+% For the "up" and "down" macros, we again use the round(T psi), but do
+% have to check the sign anyhow. We could also have used the
+% round((T+0.5)psi) which requires a sign check too, but it costs a bit
+% more. It would have allowed though to share the same codebase for all
+% units, here we have to prepare some slightly different shared macros
+% for the first batch bp, nd, dd and the second batch mm, pc, nc, cc,
+% cm, in.
%
% About the macros such as \texdiminbp whose constraints are:
%  give a decimal D such that "Duu" = "T sp" for TeX if possible
%  else give nearest from below or above without knowing
% which one,
%
% there was some hesitation about whether or not using the simpler
% round(T psi) approach for units > 2pt and the \texdimin<uu> macros.
% Testing showed that this did not change the output for \maxdimen
% with the units "nc" and "in": still N+1 is returned...
%
% As it has great
% advantage to not have to check the sign of the input, the
% "simpler" approach was chosen for those units to which it
% applies, i.e. the units uu > 2pt (phi>2, psi<1/2), i.e.
% all units except bp, nd and dd.
%
% Implementation
% ==============
%
@@ 171,87 +208,164 @@
%
% pt
%
\def\texdiminpt#1{\expandafter\texdimenstrippt\the\dimexpr#1\relax}%
+\def\texdimenpt#1{\expandafter\texdimenstrippt\the\dimexpr#1\relax}%
%
% bp 7227/7200 = 803/800
%
\def\texdiminbp#1{\expandafter\texdiminbp_\the\numexpr\dimexpr#1;}%
\def\texdiminbp_#1#2;{%
+\def\texdimenbp#1{\expandafter\texdimenbp_\the\numexpr\dimexpr#1;}%
+\def\texdimenbp_#1#2;{%
\expandafter\texdimenstrippt\the\dimexpr\numexpr(2*#1#2+\if#1\fi1)*400/803sp\relax
}%
% \texdiminbpdown: maximal dim exactly expressible in bp and at most equal to input
\def\texdiminbpdown#1{\expandafter\texdimendown_A\the\numexpr\dimexpr#1;*400/803;bp;}%
% \texdiminbpup: minimal dim exactly expressible in bp and at least equal to input
\def\texdiminbpup#1{\expandafter\texdimenup_A\the\numexpr\dimexpr#1;*400/803;bp;}%
+% \texdimenbpdown: maximal dim exactly expressible in bp and at most equal to input
+\def\texdimenbpdown#1{\expandafter\texdimendown_A\the\numexpr\dimexpr#1;*400/803;bp;}%
+% \texdimenbpup: minimal dim exactly expressible in bp and at least equal to input
+\def\texdimenbpup#1{\expandafter\texdimenup_A\the\numexpr\dimexpr#1;*400/803;bp;}%
%
% nd 685/642
%
\def\texdiminnd#1{\expandafter\texdiminnd_\the\numexpr\dimexpr#1;}%
\def\texdiminnd_#1#2;{%
+\def\texdimennd#1{\expandafter\texdimennd_\the\numexpr\dimexpr#1;}%
+\def\texdimennd_#1#2;{%
\expandafter\texdimenstrippt\the\dimexpr\numexpr(2*#1#2+\if#1\fi1)*321/685sp\relax
}%
% \texdiminnddown: maximal dim exactly expressible in nd and at most equal to input
\def\texdiminnddown#1{\expandafter\texdimendown_A\the\numexpr\dimexpr#1;*321/685;nd;}%
% \texdiminndup: minimal dim exactly expressible in nd and at least equal to input
\def\texdiminndup#1{\expandafter\texdimenup_A\the\numexpr\dimexpr#1;*321/685;nd;}%
+% \texdimennddown: maximal dim exactly expressible in nd and at most equal to input
+\def\texdimennddown#1{\expandafter\texdimendown_A\the\numexpr\dimexpr#1;*321/685;nd;}%
+% \texdimenndup: minimal dim exactly expressible in nd and at least equal to input
+\def\texdimenndup#1{\expandafter\texdimenup_A\the\numexpr\dimexpr#1;*321/685;nd;}%
%
% dd 1238/1157
%
\def\texdimindd#1{\expandafter\texdimindd_\the\numexpr\dimexpr#1;}%
\def\texdimindd_#1#2;{%
+\def\texdimendd#1{\expandafter\texdimendd_\the\numexpr\dimexpr#1;}%
+\def\texdimendd_#1#2;{%
\expandafter\texdimenstrippt\the\dimexpr\numexpr(2*#1#2+\if#1\fi1)*1157/2476sp\relax
}%
% \texdimindddown: maximal dim exactly expressible in dd and at most equal to input
\def\texdimindddown#1{\expandafter\texdimendown_A\the\numexpr\dimexpr#1;*1157/2476;dd;}%
% \texdiminddup: minimal dim exactly expressible in dd and at least equal to input
\def\texdiminddup#1{\expandafter\texdimenup_A\the\numexpr\dimexpr#1;*1157/2476;dd;}%
+% \texdimendddown: maximal dim exactly expressible in dd and at most equal to input
+\def\texdimendddown#1{\expandafter\texdimendown_A\the\numexpr\dimexpr#1;*1157/2476;dd;}%
+% \texdimenddup: minimal dim exactly expressible in dd and at least equal to input
+\def\texdimenddup#1{\expandafter\texdimenup_A\the\numexpr\dimexpr#1;*1157/2476;dd;}%
%
% mm 7227/2540 phi now >2, use from here on the simpler approach
%
\def\texdiminmm#1{\expandafter\texdimenstrippt\the\dimexpr(#1)*2540/7227\relax}%
% \texdiminmmdown: maximal dim exactly expressible in mm and at most equal to input
\def\texdiminmmdown#1{\expandafter\texdimendown_a\the\numexpr\dimexpr#1;*2540/7227;mm;}%
% \texdiminmmup: minimal dim exactly expressible in mm and at least equal to input
\def\texdiminmmup#1{\expandafter\texdimenup_a\the\numexpr\dimexpr#1;*2540/7227;mm;}%
+\def\texdimenmm#1{\expandafter\texdimenstrippt\the\dimexpr(#1)*2540/7227\relax}%
+% \texdimenmmdown: maximal dim exactly expressible in mm and at most equal to input
+\def\texdimenmmdown#1{\expandafter\texdimendown_a\the\numexpr\dimexpr#1;*2540/7227;mm;}%
+% \texdimenmmup: minimal dim exactly expressible in mm and at least equal to input
+\def\texdimenmmup#1{\expandafter\texdimenup_a\the\numexpr\dimexpr#1;*2540/7227;mm;}%
%
% pc 12/1
%
\def\texdiminpc#1{\expandafter\texdimenstrippt\the\dimexpr(#1)/12\relax}%
% \texdiminpcdown: maximal dim exactly expressible in pc and at most equal to input
\def\texdiminpcdown#1{\expandafter\texdimendown_a\the\numexpr\dimexpr#1;/12;pc;}%
% \texdiminpcup: minimal dim exactly expressible in pc and at least equal to input
\def\texdiminpcup#1{\expandafter\texdimenup_a\the\numexpr\dimexpr#1;/12;pc;}%
+\def\texdimenpc#1{\expandafter\texdimenstrippt\the\dimexpr(#1)/12\relax}%
+% \texdimenpcdown: maximal dim exactly expressible in pc and at most equal to input
+\def\texdimenpcdown#1{\expandafter\texdimendown_a\the\numexpr\dimexpr#1;/12;pc;}%
+% \texdimenpcup: minimal dim exactly expressible in pc and at least equal to input
+\def\texdimenpcup#1{\expandafter\texdimenup_a\the\numexpr\dimexpr#1;/12;pc;}%
%
% nc 1370/107
%
\def\texdiminnc#1{\expandafter\texdimenstrippt\the\dimexpr(#1)*107/1370\relax}%
% \texdiminncdown: maximal dim exactly expressible in nc and at most equal to input
\def\texdiminncdown#1{\expandafter\texdimendown_a\the\numexpr\dimexpr#1;*107/1370;nc;}%
% \texdiminncup: minimal dim exactly expressible in nc and at least equal to input
\def\texdiminncup#1{\expandafter\texdimenup_a\the\numexpr\dimexpr#1;*107/1370;nc;}%
+\def\texdimennc#1{\expandafter\texdimenstrippt\the\dimexpr(#1)*107/1370\relax}%
+% \texdimenncdown: maximal dim exactly expressible in nc and at most equal to input
+\def\texdimenncdown#1{\expandafter\texdimendown_a\the\numexpr\dimexpr#1;*107/1370;nc;}%
+% \texdimenncup: minimal dim exactly expressible in nc and at least equal to input
+\def\texdimenncup#1{\expandafter\texdimenup_a\the\numexpr\dimexpr#1;*107/1370;nc;}%
%
% cc 14856/1157
%
\def\texdimincc#1{\expandafter\texdimenstrippt\the\dimexpr(#1)*1157/14856\relax}%
% \texdiminccdown: maximal dim exactly expressible in cc and at most equal to input
\def\texdiminccdown#1{\expandafter\texdimendown_a\the\numexpr\dimexpr#1;*1157/14856;cc;}%
% \texdiminccup: minimal dim exactly expressible in cc and at least equal to input
\def\texdiminccup#1{\expandafter\texdimenup_a\the\numexpr\dimexpr#1;*1157/14856;cc;}%
+\def\texdimencc#1{\expandafter\texdimenstrippt\the\dimexpr(#1)*1157/14856\relax}%
+% \texdimenccdown: maximal dim exactly expressible in cc and at most equal to input
+\def\texdimenccdown#1{\expandafter\texdimendown_a\the\numexpr\dimexpr#1;*1157/14856;cc;}%
+% \texdimenccup: minimal dim exactly expressible in cc and at least equal to input
+\def\texdimenccup#1{\expandafter\texdimenup_a\the\numexpr\dimexpr#1;*1157/14856;cc;}%
%
% cm 7227/254
%
\def\texdimincm#1{\expandafter\texdimenstrippt\the\dimexpr(#1)*254/7227\relax}%
% \texdimincmdown: maximal dim exactly expressible in cm and at most equal to input
\def\texdimincmdown#1{\expandafter\texdimendown_a\the\numexpr\dimexpr#1;*254/7227;cm;}%
% \texdimincmup: minimal dim exactly expressible in cm and at least equal to input
\def\texdimincmup#1{\expandafter\texdimenup_a\the\numexpr\dimexpr#1;*254/7227;cm;}%
+\def\texdimencm#1{\expandafter\texdimenstrippt\the\dimexpr(#1)*254/7227\relax}%
+% \texdimencmdown: maximal dim exactly expressible in cm and at most equal to input
+\def\texdimencmdown#1{\expandafter\texdimendown_a\the\numexpr\dimexpr#1;*254/7227;cm;}%
+% \texdimencmup: minimal dim exactly expressible in cm and at least equal to input
+\def\texdimencmup#1{\expandafter\texdimenup_a\the\numexpr\dimexpr#1;*254/7227;cm;}%
%
% in 7227/100
%
\def\texdiminin#1{\expandafter\texdimenstrippt\the\dimexpr(#1)*100/7227\relax}%
% \texdiminindown: maximal dim exactly expressible in in and at most equal to input
\def\texdiminindown#1{\expandafter\texdimendown_a\the\numexpr\dimexpr#1;*100/7227;in;}%
% \texdimininup: minimal dim exactly expressible in in and at least equal to input
\def\texdimininup#1{\expandafter\texdimenup_a\the\numexpr\dimexpr#1;*100/7227;in;}%
+\def\texdimenin#1{\expandafter\texdimenstrippt\the\dimexpr(#1)*100/7227\relax}%
+% \texdimenindown: maximal dim exactly expressible in in and at most equal to input
+\def\texdimenindown#1{\expandafter\texdimendown_a\the\numexpr\dimexpr#1;*100/7227;in;}%
+% \texdimeninup: minimal dim exactly expressible in in and at least equal to input
+\def\texdimeninup#1{\expandafter\texdimenup_a\the\numexpr\dimexpr#1;*100/7227;in;}%
+% both in and cm
+% Mathematics ("both" macros)
+% ===========
%
+% Let a and b be two nonnegative integers such that U = floor(a 7227/100) =
+% floor(b 7227/254). It can be proven that a=50k, b=127k for some integer k.
+% The proof is left to reader. So U = floor(7227 k /2) for some k.
+%
+% Let's now find the largest such U <= T. So U = floor(k 7227/2)<= T which is
+% equivalent (as k is integer) to k 7227/2 <= T + 1/2, i.e.
+%
+% kmax = floor((2T+1)/7227)
+%
+% If we used for x>0 the formula floor(x)=round(x1/2)=<x1/2> we would end
+% up basically with some 4T hence overflow problems even in \numexpr.
+% Here I used <.> to denote rounding in the sense of \numexpr. It is not
+% 1periodical due to how negative inputs are handled, but here x1/2>1/2.
+%
+% The following lemma holds: let T be a nonnegative integer then
+%
+% floor((2T+1)/7227) = <(2T  3612)/7227>
+%
+% So we can compute this k, hence get a=50k, b=127k, all within \numexpr and
+% avoiding overflow.
+%
+% Implementation
+% ==============
+%
+% Regarding the output in pt or sp, we seem to need floor(k 7227/2).
+% The computation of floor(k 7227/2) as <(7227 k  1)/2> would require to
+% check if k==0 so we do it rather as <(7227 k + 1)/2>  1. No overflow
+% can arise as k = 297147 for \maxdimen, and then 7227 k = 2**31  2279 and
+% there is ample room for 7227k+1 using \numexpr.
+%
+% But this step, as well as initial step to get kmax will require to separate
+% hangdling of negative input from positive one.
+%
+% Alternative
+% 
+%
+% For nonnegative T we can compute U = ((T+1)/7227)*7227. If U <= T keep it,
+% else if U > T, replace it by U  3614. This is alternative road to the maximal
+% floor(k 7227/2) at most equal to T.
+%
+% There is some slight underefficiency to share macros across the 3 end targets
+% as I added one layer of parentheses.
+\def\texdimenbothincm#1{\expandafter\texdimenstrippt\the\dimexpr
+ \expandafter\texdimenboth_a\the\numexpr\dimexpr#1;127);}%
+\def\texdimenbothcmin#1{\expandafter\texdimenstrippt\the\dimexpr
+ \expandafter\texdimenboth_a\the\numexpr\dimexpr#1;50);}%
+\def\texdimenbothincmpt#1{\expandafter\texdimenstrippt\the\dimexpr
+ \expandafter\texdimenboth_a\the\numexpr\dimexpr#1;7227+1)/21;}%
+\let\texdimenbothcminpt\texdimenbothincmpt
+\def\texdimenboth_a#1{\if#1\texdimenboth_neg\fi\texdimenboth_b#1}%
+% The opening parenthesis ( is closed in #2, it was added to share "pt" output
+% with the two others
+\def\texdimenboth_b#1;#2;{\numexpr(((2*#13612)/7227)*#2sp\relax}%
+% negative branch. This is expanded in a \dimexpr so we can insert the 
+% in front of the \numexpr.
+% #1 is \fi here and #2 is \texdimenboth_b
+\def\texdimenboth_neg#1#2#3;#4;{#1\numexpr(((2*#33612)/7227)*#4sp\relax}%
+%
+% \texdimenbothincmsp is done separately as I found no easy way to share
+% its macros with the others; alternative would have been to make it the
+% core, and derive the others from it, (\texdimencm{\texdimenbothincmsp{...}sp})
+% but then they would be less efficient than their current versions.
+% (it is a bit ironical to worry about not creating too many macros
+% in such a small package, by the way)
+\def\texdimenbothincmsp#1{\the\numexpr\expandafter\texdimenbothsp_a\the\numexpr\dimexpr#1;}%
+\def\texdimenbothsp_a#1{\if#1\texdimenbothsp_neg\fi\texdimenbothsp_b#1}%
+\def\texdimenbothsp_b#1;{(((2*#13612)/7227)*7227+1)/21\relax}%
+% #1 is \fi
+% we need to regrab here or to add a \numexpr..\relax layer to
+% \texdimenbothsp_b (parentheses could do but using 0(...) syntax)
+% finally doing the job of \texdimenbothsp_b directly
+\def\texdimenbothsp_neg#1#2#3;{#1\numexpr(((2*#33612)/7227)*7227+1)/21\relax\relax}%
+%
+\let\texdimenbothcminsp\texdimenbothincmsp
\texdimensendinput
More information about the texlivecommits
mailing list.