texlive[59939] Master/texmf-dist: texdimens (15jul21)

commits+karl at tug.org commits+karl at tug.org
Thu Jul 15 21:58:54 CEST 2021


Revision: 59939
          http://tug.org/svn/texlive?view=revision&revision=59939
Author:   karl
Date:     2021-07-15 21:58:54 +0200 (Thu, 15 Jul 2021)
Log Message:
-----------
texdimens (15jul21)

Modified Paths:
--------------
    trunk/Master/texmf-dist/doc/generic/texdimens/README.md
    trunk/Master/texmf-dist/tex/generic/texdimens/texdimens.sty
    trunk/Master/texmf-dist/tex/generic/texdimens/texdimens.tex

Modified: trunk/Master/texmf-dist/doc/generic/texdimens/README.md
===================================================================
--- trunk/Master/texmf-dist/doc/generic/texdimens/README.md	2021-07-15 19:58:41 UTC (rev 59938)
+++ trunk/Master/texmf-dist/doc/generic/texdimens/README.md	2021-07-15 19:58:54 UTC (rev 59939)
@@ -10,10 +10,12 @@
 
 Development: https://github.com/jfbu/texdimens
 
+Release: `0.9delta 2021/07/15`
+
 ## Aim of this package
 
 Utilities and documentation related to TeX dimensional units, usable
-both with Plain (\input texdimens) and with LaTeX (\usepackage{texdimens}).
+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
@@ -25,9 +27,15 @@
 The reader is supposed to be familiar with TeX basics.
 
 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.
+descriptions of TeX handlings due to limited time available for the
+project.
 
 ## TeX points and scaled points
 
@@ -57,17 +65,16 @@
 `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̀`.
 
-
 ## Further units known to TeX on input
 
 TeX understands on input further units: `bp`, `cm`, `mm`, `in`, `pc`,
-`cc`, `dd` and `nd`.  It also understands font-dependent units `ex` and
+`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.
 
 `ex`, `em`, `px` and other engine-dependent units, are all currently
 excluded from consideration in this project and the rest of this
-documentation is only for the `bp`, `cm`, `mm`, `in`, `pc`, `cc`, `dd`
+documentation is only for the `bp`, `cm`, `mm`, `in`, `pc`, `cc`, `nc`, `dd`
 and `nd` units. When we say "unit" we mean one of those or the `pt` (the
 `sp` is a special case and will be included or not tacitly in the "unit"
 denomination depending on the case).
@@ -76,7 +83,7 @@
 factor.  It is always `>1`:
 
     uu     phi      reduced  real approximation  1uu in sp=   x=[65536phi]/65536  \the<1uu>
-                                                 [65536phi]  (real approximation)
+                             (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
@@ -116,12 +123,19 @@
 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, it turns out that `0.6in` can
-not be expressed as `D cm`, whatever the `D`.  More surprisingly perhaps
-is that `1in==2.54cm` is **false** in TeX! But it is true that
-`100in==254cm`! It is also false that `10in==25.4cm` but it is true that
-`10in==254mm`! It is false though that `1in==25.4mm`!
+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` (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
+`cm`.
 
+In particular `1in==2.54cm` is **false** in TeX, but it is true that
+`100in==254cm`... 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);
@@ -135,17 +149,22 @@
     @_5     47362867, 47362867
 
 `\maxdimen` can be expressed only with `pt`, `bp`, and `nd`.  For the
-other units the maximal attainable dimensions are given in this table:
+other units the maximal attainable dimensions in `sp` unit are given in
+the middle column of the next table.
 
-    16322.78954 bp  (\maxdimen = 1073741823 sp)
-    15355.51532 nd  (\maxdimen = 1073741823 sp)
-    15312.02583 dd  (1073741822 sp)
-     5758.31741 mm  (1073741822 sp)
-     1365.33333 pc  (1073741820 sp)
-     1279.62627 nc  (1073741814 sp)
-     1276.00215 cc  (1073741821 sp)
-      575.83174 cm  (1073741822 sp)
-      226.7054  in  (1073741768 sp)
+    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
 
 Perhaps for these various peculiarities with dimensional units, TeX does
 not provide an output facility for them similar to what `\the` achieves for
@@ -153,35 +172,33 @@
 
 ## Macros of this package
 
-All macros are expandable.  At time of writing they may not be
-f-expandable, but (perhaps) in future final versions will expand fully
-in two steps.  This refinement is anyhow not really important as TeX
-engines now support the `\expanded` primitive.
+The macros defined by the package are expandable, and will expand
+completely in an `\edef`, or in a `\dimexpr...\relax` construc.
+As they parse their inputs via `\dimexpr` they can be nested (with
+suitable postfix dimension unit added to inner macro).
 
-All macros handle negative dimensions via their absolute value then
-taking the opposite.
+Apart for the `\texdimin<uu>up` in case of a negative input, they will
+even expand completely under f-expansion.
 
-1. At time of writing only the `\texdimin<uu>` macros are implemented,
-The envisioned "down" and "up" variants are not done yet.
+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").
 
-2. For `dd`, `nc` and `in`, input equal to (or sufficiently close to)
-`\maxdimen` will produce also with `\texdimin<uu>` an output `D`
-representing the next "attainable" dimension above `\maxdimen` hence
-using `Duu` will trigger "Dimension too large error".
+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
+   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
+   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`.
 
-3. (not yet) For input 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" variants
-`\texdimin<uu>u` if used as `Duu` in a dimension assignment or
-expression will (naturally) trigger "Dimension too large" error.
-
-4. (not yet) For some units the "down" and "up" macros may trigger "Dimension too
-large" during their execution if used with an input too close to
-`\maxdimen`. "Safe" variants which are guaranteed never to trigger this
-error but have some extra overhead to filter out inputs too close to
-`\maxdimen` will *perhaps* be provided. But see 2. and 3. regarding the
-usability of the output anyhow.
-
 `\texdiminpt{<dim. expr.>}`
 
 > Does `\the\dimexpr <dim. expr.> \relax` then removes the `pt`.
@@ -188,73 +205,73 @@
 
 `\texdiminbp{<dim. expr.>}`
 
-> Produces a decimal (with up to five decimal places) `D` such that `D
-> bp` represents the dimension exactly if possible. If not possible it
+> Produces a decimal (with up to five decimal places) `D` such that `D bp`
+> 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`.
 
-`\texdiminbpd{<dim. expr.>}` NOT YET
+`\texdiminbpdown{<dim. expr.>}`
 
-> Produces a decimal (with up to five decimal places) `D` such that `D
-> bp` represents the dimension exactly if possible. If not possible it
+> Produces a decimal (with up to five decimal places) `D` such that `D bp`
+> represents the dimension exactly if possible. If not possible it
 > will be smaller by `1sp` from the original dimension.
 
-`\texdiminbpu{<dim. expr.>}` NOT YET
+`\texdiminbpup{<dim. expr.>}`
 
-> Produces a decimal (with up to five decimal places) `D` such that `D
-> bp` represents the dimension exactly if possible. If not possible it
+> Produces a decimal (with up to five decimal places) `D` such that `D bp`
+> represents the dimension exactly if possible. If not possible it
 > will be larger by `1sp` from the original dimension.
 
 `\texdiminnd{<dim. expr.>}`
 
-> Produces a decimal (with up to five decimal places) `D` such that `D
-> nd` represents the dimension exactly if possible. If not possible it
+> Produces a decimal (with up to five decimal places) `D` such that `D nd`
+> 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`.
 
-`\texdiminndd{<dim. expr.>}` NOT YET
+`\texdiminnddown{<dim. expr.>}`
 
-> Produces a decimal (with up to five decimal places) `D` such that `D
-> nd` represents the dimension exactly if possible. If not possible it
+> Produces a decimal (with up to five decimal places) `D` such that `D nd`
+> represents the dimension exactly if possible. If not possible it
 > will be smaller by `1sp` from the original dimension.
 
-`\texdiminndu{<dim. expr.>}` NOT YET
+`\texdiminndup{<dim. expr.>}`
 
-> Produces a decimal (with up to five decimal places) `D` such that `D
-> nd` represents the dimension exactly if possible. If not possible it
+> Produces a decimal (with up to five decimal places) `D` such that `D nd`
+> represents the dimension exactly if possible. If not possible it
 > will be larger by `1sp` from the original dimension.
 
 `\texdimindd{<dim. expr.>}`
 
-> Produces a decimal (with up to five decimal places) `D` such that `D
-> dd` represents the dimension exactly if possible. If not possible it
+> Produces a decimal (with up to five decimal places) `D` such that `D dd`
+> 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 atteignable via `15312.02583dd`.
+> `\maxdimen-1sp` is attainable via `15312.02584dd`.
 
-`\texdiminddd{<dim. expr.>}` NOT YET
+`\texdimindddown{<dim. expr.>}`
 
-> Produces a decimal (with up to five decimal places) `D` such that `D
-> dd` represents the dimension exactly if possible. If not possible it
+> Produces a decimal (with up to five decimal places) `D` such that `D dd`
+> represents the dimension exactly if possible. If not possible it
 > will be smaller by `1sp` from the original dimension.
 
-`\texdiminddu{<dim. expr.>}` NOT YET
+`\texdiminddup{<dim. expr.>}`
 
-> Produces a decimal (with up to five decimal places) `D` such that `D
-> dd` represents the dimension exactly if possible. If not possible it
+> Produces a decimal (with up to five decimal places) `D` such that `D dd`
+> represents the dimension exactly if possible. If not possible it
 > will be larger by `1sp` from the original dimension.
 
 `\texdiminmm{<dim. expr.>}`
 
-> Produces a decimal (with up to five decimal places) `D` such that `D
-> mm` represents the dimension exactly if possible. If not possible it
+> Produces a decimal (with up to five decimal places) `D` such that `D mm`
+> 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).
@@ -262,22 +279,22 @@
 > `\maxdimen` as input produces on output `5758.31741` and indeed the
 > maximal attainable dimension is `5758.31741mm` (`1073741822sp`).
 
-`\texdiminmmd{<dim. expr.>}` NOT YET
+`\texdiminmmdown{<dim. expr.>}`
 
-> Produces a decimal (with up to five decimal places) `D` such that `D
-> mm` represents the dimension exactly if possible. If not possible it
+> Produces a decimal (with up to five decimal places) `D` such that `D mm`
+> represents the dimension exactly if possible. If not possible it
 > will be largest representable dimension smaller than the original one.
 
-`\texdiminmmu{<dim. expr.>}` NOT YET
+`\texdiminmmup{<dim. expr.>}`
 
-> Produces a decimal (with up to five decimal places) `D` such that `D
-> mm` represents the dimension exactly if possible. If not possible it
+> Produces a decimal (with up to five decimal places) `D` such that `D mm`
+> represents the dimension exactly if possible. If not possible it
 > will be smallest representable dimension larger than the original one.
 
 `\texdiminpc{<dim. expr.>}`
 
-> Produces a decimal (with up to five decimal places) `D` such that `D
-> pc` represents the dimension exactly if possible. If not possible it
+> Produces a decimal (with up to five decimal places) `D` such that `D pc`
+> 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).
 
@@ -284,22 +301,22 @@
 > `\maxdimen` as input produces on output `1365.33333` and indeed the
 > maximal attainable dimension is `1365.33333pc` (`1073741820sp`).
 
-`\texdiminpcd{<dim. expr.>}` NOT YET
+`\texdiminpcdown{<dim. expr.>}`
 
-> Produces a decimal (with up to five decimal places) `D` such that `D
-> pc` represents the dimension exactly if possible. If not possible it
+> Produces a decimal (with up to five decimal places) `D` such that `D pc`
+> represents the dimension exactly if possible. If not possible it
 > will be largest representable dimension smaller than the original one.
 
-`\texdiminpcu{<dim. expr.>}` NOT YET
+`\texdiminpcup{<dim. expr.>}`
 
-> Produces a decimal (with up to five decimal places) `D` such that `D
-> pc` represents the dimension exactly if possible. If not possible it
+> Produces a decimal (with up to five decimal places) `D` such that `D pc`
+> represents the dimension exactly if possible. If not possible it
 > will be smallest representable dimension larger than the original one.
 
 `\texdiminnc{<dim. expr.>}`
 
-> Produces a decimal (with up to five decimal places) `D` such that `D
-> nc` represents the dimension exactly if possible. If not possible it
+> Produces a decimal (with up to five decimal places) `D` such that `D nc`
+> 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).
@@ -308,45 +325,45 @@
 > will trigger "Dimension too large" error.
 > `\maxdimen-9sp` is attainable via `1279.62627nc`.
 
-`\texdiminncd{<dim. expr.>}` NOT YET
+`\texdiminncdown{<dim. expr.>}`
 
-> Produces a decimal (with up to five decimal places) `D` such that `D
-> nc` represents the dimension exactly if possible. If not possible it
+> Produces a decimal (with up to five decimal places) `D` such that `D nc`
+> represents the dimension exactly if possible. If not possible it
 > will be largest representable dimension smaller than the original one.
 
-`\texdiminncu{<dim. expr.>}` NOT YET
+`\texdiminncup{<dim. expr.>}`
 
-> Produces a decimal (with up to five decimal places) `D` such that `D
-> nc` represents the dimension exactly if possible. If not possible it
+> Produces a decimal (with up to five decimal places) `D` such that `D nc`
+> represents the dimension exactly if possible. If not possible it
 > will be smallest representable dimension larger than the original one.
 
 `\texdimincc{<dim. expr.>}`
 
-> Produces a decimal (with up to five decimal places) `D` such that `D
-> cc` represents the dimension exactly if possible. If not possible it
+> Produces a decimal (with up to five decimal places) `D` such that `D cc`
+> 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 advacce which one (and it is not known if the other choice
+> 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`).
 
-`\texdiminccd{<dim. expr.>}` NOT YET
+`\texdiminccdown{<dim. expr.>}`
 
-> Produces a decimal (with up to five decimal places) `D` such that `D
-> cc` represents the dimension exactly if possible. If not possible it
+> Produces a decimal (with up to five decimal places) `D` such that `D cc`
+> represents the dimension exactly if possible. If not possible it
 > will be largest representable dimension smaller than the original one.
 
-`\texdiminccu{<dim. expr.>}` NOT YET
+`\texdiminccup{<dim. expr.>}`
 
-> Produces a decimal (with up to five decimal places) `D` such that `D
-> cc` represents the dimension exactly if possible. If not possible it
+> Produces a decimal (with up to five decimal places) `D` such that `D cc`
+> represents the dimension exactly if possible. If not possible it
 > will be smallest representable dimension larger than the original one.
 
 `\texdimincm{<dim. expr.>}`
 
-> Produces a decimal (with up to five decimal places) `D` such that `D
-> cm` represents the dimension exactly if possible. If not possible it
+> Produces a decimal (with up to five decimal places) `D` such that `D cm`
+> 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).
@@ -354,22 +371,22 @@
 > `\maxdimen` as input produces on output `575.83174` and indeed the
 > maximal attainable dimension is `575.83174cm` (`1073741822sp`).
 
-`\texdimincmd{<dim. expr.>}` NOT YET
+`\texdimincmdown{<dim. expr.>}`
 
-> Produces a decimal (with up to five decimal places) `D` such that `D
-> cm` represents the dimension exactly if possible. If not possible it
+> Produces a decimal (with up to five decimal places) `D` such that `D cm`
+> represents the dimension exactly if possible. If not possible it
 > will be largest representable dimension smaller than the original one.
 
-`\texdimincmu{<dim. expr.>}` NOT YET
+`\texdimincmup{<dim. expr.>}`
 
-> Produces a decimal (with up to five decimal places) `D` such that `D
-> cm` represents the dimension exactly if possible. If not possible it
+> Produces a decimal (with up to five decimal places) `D` such that `D cm`
+> represents the dimension exactly if possible. If not possible it
 > will be smallest representable dimension larger than the original one.
 
 `\texdiminin{<dim. expr.>}`
 
-> Produces a decimal (with up to five decimal places) `D` such that `D
-> in` represents the dimension exactly if possible. If not possible it
+> Produces a decimal (with up to five decimal places) `D` such that `D in`
+> 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).
@@ -378,31 +395,67 @@
 > will trigger "Dimension too large" error.
 > `\maxdimen-55sp` is maximal attainable dimension (via `226.7054in`).
 
-`\texdiminind{<dim. expr.>}` NOT YET
+`\texdiminindown{<dim. expr.>}`
 
-> Produces a decimal (with up to five decimal places) `D` such that `D
-> in` represents the dimension exactly if possible. If not possible it
+> Produces a decimal (with up to five decimal places) `D` such that `D in`
+> represents the dimension exactly if possible. If not possible it
 > will be largest representable dimension smaller than the original one.
 
-`\texdimininu{<dim. expr.>}` NOT YET
+`\texdimininup{<dim. expr.>}`
 
-> Produces a decimal (with up to five decimal places) `D` such that `D
-> in` represents the dimension exactly if possible. If not possible it
+> Produces a decimal (with up to five decimal places) `D` such that `D in`
+> represents the dimension exactly if possible. If not possible it
 > will be smallest representable dimension larger than the original one.
 
+## Extras?
 
-## TODO
+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.
 
-Implement the "up" and "down" variants.
+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`
+(and `pt` but there is no "up" macro for it).
 
-Provide a macro `\texdimnearest{in,cm}{<dim.expr.>}` which provides the
-nearest dimension simultaneously representable both in `in` and in `cm`?
+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
-available positive dimensions in scaled points have the shape
-`floor(3613.5*k) sp` for some integer `k`. So we basically may have a
+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), so perhaps such a utility for
-"safe dimensions" may be useful. Simpler however and more efficient
+(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:
+
+    >>> \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
+
+As promised, one of them, the upper approximation, is at less than
+one hundredth of millimeter from the two nearby targets.
+
+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).
 

Modified: trunk/Master/texmf-dist/tex/generic/texdimens/texdimens.sty
===================================================================
--- trunk/Master/texmf-dist/tex/generic/texdimens/texdimens.sty	2021-07-15 19:58:41 UTC (rev 59938)
+++ trunk/Master/texmf-dist/tex/generic/texdimens/texdimens.sty	2021-07-15 19:58:54 UTC (rev 59939)
@@ -1,5 +1,5 @@
 % This is file texdimens.tex, part of texdimens package, which
 % is distributed under the LPPL 1.3c. Copyright (c) 2021 Jean-François Burnol
-\ProvidesPackage{texdimens}[2021/06/30 v0.9beta conversion of TeX dimensions to decimals (JFB)]
+\ProvidesPackage{texdimens}[2021/07/15 v0.9delta conversion of TeX dimensions to decimals (JFB)]
 \@@input texdimens.tex\relax
 \endinput
\ No newline at end of file

Modified: trunk/Master/texmf-dist/tex/generic/texdimens/texdimens.tex
===================================================================
--- trunk/Master/texmf-dist/tex/generic/texdimens/texdimens.tex	2021-07-15 19:58:41 UTC (rev 59938)
+++ trunk/Master/texmf-dist/tex/generic/texdimens/texdimens.tex	2021-07-15 19:58:54 UTC (rev 59939)
@@ -1,101 +1,257 @@
 % This is file texdimens.tex, part of texdimens package, which
 % is distributed under the LPPL 1.3c. Copyright (c) 2021 Jean-François Burnol
-% 2021/06/30 v0.9beta
+% 2021/07/15 v0.9delta
 \edef\texdimensendinput{\endlinechar\the\endlinechar\catcode`\noexpand _=\the\catcode`\_\relax\noexpand\endinput}%
 \endlinechar13\relax%
 \catcode`\_=11
+%
+% Mathematics
+% ===========
+%
 % Is T sp attainable from unit "uu"?. Here we suppose T>0.
 % phi>1, psi=1/phi, psi<1
-% U(N,phi)=floor(N phi) is strictly increasing
+% U(N,phi)=trunc(N phi) is strictly increasing
 %     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:
-% -  M = N, i.e. T is not attainable, M=N < T psi < (T+1) psi <= N+1
-% -  M = N - 1, i.e. T is attained, T psi <= N < (T+1) psi, T = floor(N phi) 
+% 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) 
 %
-% In the latter case:
-% - as psi<1, |N - (T+0.5) psi| < 0.5, hence N = R := round((T+0.5) psi).
-%   Also works for T=0 but T<0 would need -0.5.
+% Let X = round(T psi). And let Y = trunc(X phi).
 %
-% - if psi<1/2, then N = round(T psi) is simpler formula which works
-%   also for attainable T<0.
+% case1: X can be N or N+1. It will be N+1 iff Y > T.
+% case2: X can be N or N-1. 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.
+%
+% If psi < 0.5
+% ------------
+%
+% The situation then simplifies:
+%
+% case1: X can be N or N+1. It will be N+1 iff Y = trunc(X phi) > T.
+% case2: X is necessarily N.
+%
+% Thus:
+% 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.
+% 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, 
+% ii) use \the\numexpr\dimexpr  to convert "D uu" into sp.
+% These steps give Y.
+%
+% This way we find the maximal dimension at most T sp exactly
+% representable in "uu" unit.
+%
+% 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.
+%
+% 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
+% a D such that D uu < T sp or D uu > T sp.
+%
+% If psi > 0.5
+% ------------
+%
+% For example unit "bp" has phi=803/800.
+%
+% It is then not true that if T sp is atteignable, the X = round(T psi)
+% will always work.
+%
+% But it is true that R = round((T + 0.5) psi) will always work.
+% Here we must use -0.5 if T < 0, though.
+%
 % This R=round((T+0.5) psi) can always be computed via \numexpr because 2T+1
 % will not trigger arithmetic overflow.
 %
-% If Tsp>0 is not attainable, this R can produce either N or N+1 (=M+1).
+% 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.
 %
-% If we try computing ceil(x) via round(x+0.5) (\numexpr rounds up)
-% this means for N, we need round((T+1)psi + 0.5), for example with
-% psi = 100/7227 for "in", this gives round((((T+1)200)+7227)/14454)
-% feasible via \numexpr only for (circa) 100 T less than \maxdimen.
+% But we can decide what happened by computing Z = trunc(R phi).
+% If and only if Z > T this means R was N+1.
 %
-% We could rather compute round(T psi) but we don't know if it gives
-% N or N+1. We know it is N if round(T psi)< round((T+1) psi)
-% but if the two are the same we don't know if they are both N or
-% both N+1.
+% 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.
 %
-% It is slightly less costly to compute X = round(T psi) than R,
-% but if we then realize that X uu < T sp we do not yet know
-% if (X+1) uu = T sp or is > Tsp, except if psi<1/2, because
-% if T sp is attainable then X = round(T psi) is then necessarily N
-% so if X uu < T sp we now that T sp was not attainable.
+% To recapitulate: we have our algorithm for all units to find out
+% maximal dimension exactly atteignable in "uu" unit and at most equal
+% to (positive) T sp.
 %
-% We decide with some hesitation to not split whether psi<1/2 or
-% psi>1/2. Reverted! Currently following done only for psi>1/2,
-% i.e. bp, nd, dd.
+% 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
+% non-atteignable \maxdimen.
 %
-% 1. compute R = round((T+0.5) psi) in \numexpr. This forces
-%    to check for negative T because then we would want here (T-0.5)psi
+% 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 non-attainable \maxdimen.
 %
-% 2. check for the "up" and "down" variants whether R uu is <, =, or > T sp.
-%    But we have to choose here what "up" and "down" mean for T<0.
-%    Also, computation of R uu
-%    may trigger Dimension too large if T sp is not attainable,
-%    close to \maxdimen, and \maxdimen itself is not attainable.
-%
-% For the envisioned "safe versions" we would tabulate first per unit
-% what is Rmax such that Rmax uu <= \maxdimen. Then the "safe" versions
-% would have an extra check of R. But for \texdimeninuuu it will
-% then not be compliant to its definition for inputs close to
-% non-attainable \maxdimen.
-%
 % After having written the macros we will tabulate what is for each unit
 % the maximal attainable dimension.
 %
-% Hesitation about whether using simpler round(T psi) approach
-% for units > 2pt and the \texdimin<uu> macros.
+% 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,
 %
-% Testing shows that this would not change output for \maxdimen
-% with "nc" and "in": still N+1 is returned... but it has great
-% advantage to not have to check the sign.
+% 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...
 %
-% OK let's do this,
-% especially as I don't know if I will ever implement "up" and "down".
-\def\texdiminpt#1{\expandafter\texdiminpt_\the\dimexpr#1\relax}%
-{\catcode`p 12\catcode`t 12\csname expandafter\endcsname\gdef\csname texdiminpt_\endcsname#1pt{#1}}%
+% 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
+% ==============
+%
+\def\texdimenfirstofone#1{#1}%
+{\catcode`p 12\catcode`t 12
+ \csname expandafter\endcsname\gdef\csname texdimenstrippt\endcsname#1pt{#1}}%
+%
+% down macros:
+% for units with phi < 2:
+\def\texdimendown_A#1{\if-#1\texdimendown_neg\fi\texdimendown_B#1}%
+\def\texdimendown_B#1;#2;{\expandafter\texdimendown_c\the\numexpr(2*#1+1)#2;#1;}%
+% for units with phi > 2:
+\def\texdimendown_a#1{\if-#1\texdimendown_neg\fi\texdimendown_b#1}%
+\def\texdimendown_b#1;#2;{\expandafter\texdimendown_c\the\numexpr#1#2;#1;}%
+% shared macros:
+\def\texdimendown_c#1;{\expandafter\texdimendown_d\the\dimexpr#1sp;#1;}%
+{\catcode`P 12\catcode`T 12\lowercase{\gdef\texdimendown_d#1PT};#2;#3;#4;%
+   {\ifdim#1#4>#3sp \texdimendown_e{#2}\fi\texdimenfirstofone{#1}}%
+}%
+% this #2 will be \fi
+\def\texdimendown_e#1#2#3#4{#2\expandafter\texdimenstrippt\the\dimexpr\numexpr#1-1sp\relax}%
+% negative branch:
+% The problem here is that if input very small, output can be 0.0, and we
+% do not want -0.0 as output.
+% So let's do this somewhat brutally and non-efficiently.
+% Anyhow, negative inputs are not our priority.
+% #1 is \fi here and #2 is \texdimendown_b or _B:
+\def\texdimendown_neg#1#2-#3;#4;#5;{#1\expandafter\texdimenstrippt\the\dimexpr-#2#3;#4;#5;pt\relax}%
+%
+% up macros:
+\def\texdimenup_A#1{\if-#1\texdimenup_neg\fi\texdimenup_B#1}%
+\def\texdimenup_B#1;#2;{\expandafter\texdimenup_c\the\numexpr(2*#1+1)#2;#1;}%
+\def\texdimenup_a#1{\if-#1\texdimenup_neg\fi\texdimenup_b#1}%
+\def\texdimenup_b#1;#2;{\expandafter\texdimenup_c\the\numexpr#1#2;#1;}%
+\def\texdimenup_c#1;{\expandafter\texdimenup_d\the\dimexpr#1sp;#1;}%
+{\catcode`P 12\catcode`T 12\lowercase{\gdef\texdimenup_d#1PT};#2;#3;#4;%
+   {\ifdim#1#4<#3sp \texdimenup_e{#2}\fi\texdimenfirstofone{#1}}%
+}%
+% this #2 will be \fi
+\def\texdimenup_e#1#2#3#4{#2\expandafter\texdimenstrippt\the\dimexpr\numexpr#1+1sp\relax}%
+% negative branch:
+% Here we can me more expeditive than for the "down" macros.
+% But this breaks f-expandability.
+% #1 will be \fi and #2 is \texdimenup_b or _B:
+\def\texdimenup_neg#1#2-{#1-#2}%
+%
+% pt
+%
+\def\texdiminpt#1{\expandafter\texdimenstrippt\the\dimexpr#1\relax}%
+%
 % bp 7227/7200 = 803/800
-% complications and annoying overhead caused by sign
-% and we don't want to evaluate #1 twice in a \dimexpr; if #1 was
-% restricted to be a dimen register, we would avoid "\the and re-grab" step.
+%
 \def\texdiminbp#1{\expandafter\texdiminbp_\the\numexpr\dimexpr#1;}%
-\def\texdiminbp_#1#2;{\texdiminpt{\numexpr(2*#1#2+\if-#1-\fi1)*400/803sp}}%
+\def\texdiminbp_#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;}%
+%
 % nd 685/642
+%
 \def\texdiminnd#1{\expandafter\texdiminnd_\the\numexpr\dimexpr#1;}%
-\def\texdiminnd_#1#2;{\texdiminpt{\numexpr(2*#1#2+\if-#1-\fi1)*321/685sp}}%
+\def\texdiminnd_#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;}%
+%
 % dd 1238/1157
+%
 \def\texdimindd#1{\expandafter\texdimindd_\the\numexpr\dimexpr#1;}%
-\def\texdimindd_#1#2;{\texdiminpt{\numexpr(2*#1#2+\if-#1-\fi1)*1157/2476sp}}%
+\def\texdimindd_#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;}%
+%
 % mm 7227/2540 phi now >2, use from here on the simpler approach
-\def\texdiminmm#1{\texdiminpt{(#1)*2540/7227}}%
+%
+\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;}%
+%
 % pc 12/1
-\def\texdiminpc#1{\texdiminpt{(#1)/12}}%
+%
+\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;}%
+%
 % nc 1370/107
-\def\texdiminnc#1{\texdiminpt{(#1)*107/1370}}%
+%
+\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;}%
+%
 % cc 14856/1157
-\def\texdimincc#1{\texdiminpt{(#1)*1157/14856}}%
+%
+\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;}%
+%
 % cm 7227/254
-\def\texdimincm#1{\texdiminpt{(#1)*254/7227}}%
+%
+\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;}%
+%
 % in 7227/100
-\def\texdiminin#1{\texdiminpt{(#1)*100/7227}}%
+%
+\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;}%
+%
 \texdimensendinput



More information about the tex-live-commits mailing list.