texlive[59939] Master/texmfdist: 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: 20210715 21:58:54 +0200 (Thu, 15 Jul 2021)
Log Message:

texdimens (15jul21)
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 20210715 19:58:41 UTC (rev 59938)
+++ trunk/Master/texmfdist/doc/generic/texdimens/README.md 20210715 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 eTeX 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
+subexpression `\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 fontdependent units `ex` and
+`cc`, `nc`, `dd` and `nd`. It also understands fontdependent units `ex` and
`em`, and PDFTeX adds the `px` dimension unit. Japanese engines also
add specific units.
`ex`, `em`, `px` and other enginedependent 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 `7273sp` for the `in` and `2829sp`
+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
fexpandable, 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 fexpansion.
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.
> `\maxdimen1sp` is atteignable via `15312.02583dd`.
+> `\maxdimen1sp` 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.
> `\maxdimen9sp` 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.
> `\maxdimen55sp` 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/texmfdist/tex/generic/texdimens/texdimens.sty
===================================================================
 trunk/Master/texmfdist/tex/generic/texdimens/texdimens.sty 20210715 19:58:41 UTC (rev 59938)
+++ trunk/Master/texmfdist/tex/generic/texdimens/texdimens.sty 20210715 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 JeanFranç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/texmfdist/tex/generic/texdimens/texdimens.tex
===================================================================
 trunk/Master/texmfdist/tex/generic/texdimens/texdimens.tex 20210715 19:58:41 UTC (rev 59938)
+++ trunk/Master/texmfdist/tex/generic/texdimens/texdimens.tex 20210715 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 JeanFranç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 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.
+%
+% 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
+% nonatteignable \maxdimen.
%
% 1. compute R = round((T+0.5) psi) in \numexpr. This forces
% to check for negative T because then we would want here (T0.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 nonattainable \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
% nonattainable \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#11sp\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 nonefficiently.
+% 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 fexpandability.
+% #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 regrab" 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 texlivecommits
mailing list.