summaryrefslogtreecommitdiff
path: root/macros/generic/texdimens/texdimens.md
diff options
context:
space:
mode:
Diffstat (limited to 'macros/generic/texdimens/texdimens.md')
-rw-r--r--macros/generic/texdimens/texdimens.md297
1 files changed, 189 insertions, 108 deletions
diff --git a/macros/generic/texdimens/texdimens.md b/macros/generic/texdimens/texdimens.md
index 98ae9f5b3b..ec6ac406e0 100644
--- a/macros/generic/texdimens/texdimens.md
+++ b/macros/generic/texdimens/texdimens.md
@@ -10,7 +10,7 @@ LPPL 1.3c. See file LICENSE.md.
Repository: https://github.com/jfbu/texdimens
-Release: `0.99d 2021/11/04`
+Release: `1.0 2021/11/10`
## Usage
@@ -30,21 +30,33 @@ available TeX units, to the extent possible.
This package provides expandable macros:
-- `\texdimenpt`,
-- `\texdimenUU`, `\texdimenUUup` and
- `\texdimenUUdown` with `UU` standing for one of `bp`, `cm`, `mm`, `in`,
- `pc`, `cc`, `nc`, `dd` and `nd`,
-- `\texdimenbothincm` (and relatives not listed here, see below),
+- `\texdimenUU` with `UU` standing for one of `pt`, `bp`, `cm`, `mm`,
+ `in`, `pc`, `cc`, `nc`, `dd` and `nd`,
+- `\texdimenUUup` and `\texdimenUUdown` with `UU` as above except `pt`,
+- `\texdimenbothincm` and relatives,
+- `\texdimenbothbpmm` and relatives,
- `\texdimenwithunit`.
-For example `\texdimenbp` takes on input some dimension or dimension
-expression and produces on output a decimal `D` such that `D bp` is
-guaranteed to be the same dimension as the input, if that one admits any
-representation as `E bp`; else it will be either the closest match from
-above or from below (for this unit the error is at most `1sp`).
+`\texdimenbp` takes on input some dimension or dimension expression and
+produces on output a decimal `D` such that `D bp` is guaranteed to be
+the same dimension as the input, *if* it admits any representation as `E
+bp`; else it will be either the closest match from above or from
+below. For this unit, as well as for `nd` and `dd` the difference is at
+most `1sp`. For other units (not `pt` of course) the distance will
+usually be larger than `1sp` and one does not know if the approximant
+from the other direction would have been better or worst.
-The variants `\texdimenbpup` and `\texdimenbpdown` allow to choose the
-direction of approximation.
+The variants `\texdimenbpup` and `\texdimenbpdown` expand slightly less
+fast than `\texdimenbp` but they allow to choose the direction of
+approximation (in absolute value).
+
+The macros associated to the other units have
+the same descriptions.
+
+`\texdimenbothincm`, respectively `\texdimenbothbpmm`, find the largest
+(in absolute value) dimension not exceeding the input and exactly
+representable both with the `in` and `cm` units, respectively exactly
+representable both with the `bp` and `mm` units.
`\texdimenwithunit{<dimen1>}{<dimen2>}` produces a decimal `D` such that
`D \dimexpr dimen2\relax` is parsed by TeX into the same dimension as
@@ -54,9 +66,8 @@ attainable. If not attainable, the decimal `D` will ensure a closest
match from below or from above but one does not know if the
approximation from the other direction is better or worst.
-In a sense, this macro divides `<dimen1>` by `<dimen2>` but please continue
-reading this documentation for relevant
-information on how TeX handles dimensions.
+In a sense, this macro divides `<dimen1>` by `<dimen2>`, see additional
+details in the complete macro description.
## Quick review of basics: TeX points and scaled points
@@ -118,7 +129,7 @@ For core units however, the hard-coded ratio `n/d` never has a
denominator `d` which is a power of `2`, except for the `pc` whose
associated ratio factor is `12/1` (and arguably for the `sp` for which
morally `phi` is `1/65536` but we keep it separate from the general
-discussion).
+discussion; as well as `pt` with its unit conversion factor).
Here is a table with the hard-coded conversion factors:
@@ -138,7 +149,15 @@ Here is a table with the hard-coded conversion factors:
The values of `1uu` in the `sp` and `pt` units are irrelevant and even
misleading regarding the TeX parsing of `D uu` input. Notice for
example that `\the\dimexpr1bp\relax` gives `1.00374pt` but the actual
-conversion factor is `1.00375`.
+conversion factor is `1.00375` (and
+`1.00375pt=65782sp>1bp`...). Similarly `\the\dimexpr1in\relax` outputs
+`72.26999pt` and is represented internally as `4736286sp` but the actual
+conversion factor is `72.27=7227/100`, and
+`72.27pt=4736287sp>1in`... And for the other units except the `pc`, the
+conversion factors are not decimal numbers, so even less likely to match
+`\the<1uu>` as listed in the last column. Their denominators are not
+powers of `2` so they don't match exactly either `(1uu in sp)/65536` but
+are only close.
When TeX parses an assignment `U uu` with a decimal `U` and a unit `uu`,
be it a core unit, or a unit corresponding to an internal dimension,
@@ -229,26 +248,31 @@ at last step the sign (if result is not zero) is applied (so "down" means
Remarks about "Dimension too large" issues:
-1. For input `X` equal to (or sufficiently close to) `\maxdimen` and
+1. For input `X` equal to `\maxdimen` (or differing by a few `sp`'s) and
those units `uu` for which `\maxdimen` is not exactly representable
- (i.e. all core units except `pt`, `bp` and `nd`), the output `D` of the
- "up" macros `\texdimen<uu>up{X}`, if used as `Duu` in a dimension
- assignment or expression, will (naturally) trigger a "Dimension too
- large" error.
-2. The same potentially happens with `\texdimenwithunit{dimen1}{dimen2}`
- if `\maxdimen`
- is not representable exactly by `dimen2` used as a base dimension,
- (which may happen only if `dimen2>1pt`): it is possible that the
- output `D`, if consequently used as `D\dimexpr dimen2\relax` will
- trigger "Dimension too large".
-3. For `dd`, `nc` and `in`, and input `X` equal to (or sufficiently
- close to) `\maxdimen` it turns out that `\texdimen<uu>{X}` produces
- an output `D` such that `Duu` is the first "virtually attainable" TeX
- dimension *beyond* `\maxdimen`. Hence here also `Duu` will trigger on use
- "Dimension too large error".
-4. 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`.
+ (i.e. all core units except `pt`, `bp` and `nd`), the output `D` of
+ the "up" macros `\texdimen<uu>up{X}`, if used as `Duu` in a dimension
+ assignment or expression, will (as is logical) trigger a "Dimension
+ too large" error.
+2. For `dd`, `nc` and `in`, it turns out that `\texdimen<uu>{X}` chooses
+ the "up" approximant for `X` equal to or very near `\maxdimen` (check
+ the respective macro documentations),
+ i.e. the output `D` is such that `Duu` is the first virtually
+ attainable dimension beyond `\maxdimen`. Hence `Duu` will trigger on
+ use a "Dimension too large error". With the other units for which
+ `\maxdimen` is not attainable exactly, `\texdimen<uu>{\maxdimen}`
+ output is by luck the "down" approximant.
+3. Similarly the macro `\texdimenwithunit{D1pt}{D2pt}` covers the entire
+ dimension range, but its output `F` for `D1pt` equal to or very close
+ to `\maxdimen` may be such that `F<D2pt>` represents a dimension
+ beyond `\maxdimen`, if the latter is not exactly representable.
+ Hence `F<D2pt>` would trigger "Dimension too large" on use. This can
+ only happen if `D2pt>1pt` and (roughly) `D1pt>\maxdimen-D2sp`. As
+ `D2sp` is less than `0.25pt`, this is not likely to occur in real
+ life practice except if deliberately targeting `\maxdimen`. For
+ `D2pt<1pt`, all dimensions `D1pt` are exactly representable, in
+ particular `\maxdimen`, and the output `F` will always be such that
+ TeX parses `F<D2pt>` into exactly the same dimension as `D1pt`.
`\texdimenpt{<dim. expr.>}`
@@ -306,8 +330,9 @@ Remarks about "Dimension too large" issues:
> known in advance if it will be above or below.
> Warning: the output for `\maxdimen` is `15312.02585` but `15312.02585dd`
-> will trigger "Dimension too large" error.
-> `\maxdimen-1sp` is attainable via `15312.02584dd`.
+> will trigger on use "Dimension too large" error.
+> `\maxdimen-1sp` is the maximal input for which the output remains
+> less than `\maxdimen` (max attainable dimension: `\maxdimen-1sp`).
`\texdimendddown{<dim. expr.>}`
@@ -320,6 +345,9 @@ Remarks about "Dimension too large" issues:
> 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.
+>
+> If input is `\maxdimen`, then `Ddd` virtually represents
+> `\maxdimen+1sp` and will trigger on use "Dimension too large".
`\texdimenmm{<dim. expr.>}`
@@ -330,7 +358,7 @@ Remarks about "Dimension too large" issues:
> would have been closer).
> `\maxdimen` as input produces on output `5758.31741` and indeed the
-> maximal attainable dimension is `5758.31741mm` (`1073741822sp`).
+> maximal attainable dimension is `5758.31741mm` (`\maxdimen-1sp`).
`\texdimenmmdown{<dim. expr.>}`
@@ -343,6 +371,9 @@ Remarks about "Dimension too large" issues:
> 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.
+>
+> If input is `\maxdimen`, then `Dmm` virtually represents
+> `\maxdimen+2sp` and will trigger on use "Dimension too large".
`\texdimenpc{<dim. expr.>}`
@@ -352,7 +383,7 @@ Remarks about "Dimension too large" issues:
> from above is chosen).
> `\maxdimen` as input produces on output `1365.33333` and indeed the
-> maximal attainable dimension is `1365.33333pc` (`1073741820sp`).
+> maximal attainable dimension is `1365.33333pc` (`\maxdimen-3sp`).
`\texdimenpcdown{<dim. expr.>}`
@@ -365,6 +396,9 @@ Remarks about "Dimension too large" issues:
> 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.
+>
+> If input is `>\maxdimen-3sp`, then `Dpc` virtually represents
+> `\maxdimen+9sp` and will trigger on use "Dimension too large".
`\texdimennc{<dim. expr.>}`
@@ -374,9 +408,10 @@ Remarks about "Dimension too large" issues:
> known in advance which one (and it is not known if the other choice
> would have been closer).
-> Warning: the output for `\maxdimen` is `1279.62628` but `1279.62628nc`
-> will trigger "Dimension too large" error.
-> `\maxdimen-9sp` is attainable via `1279.62627nc`.
+> Warning: the output for `\maxdimen-1sp` is `1279.62628` but `1279.62628nc`
+> will trigger on use "Dimension too large" error.
+> `\maxdimen-2sp` is the maximal input for which the output remains
+> less than `\maxdimen` (max attainable dimension: `\maxdimen-9sp`).
`\texdimenncdown{<dim. expr.>}`
@@ -389,6 +424,9 @@ Remarks about "Dimension too large" issues:
> 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.
+>
+> If input is `>\maxdimen-9sp`, then `Dnc` virtually represents
+> `\maxdimen+4sp` and will trigger on use "Dimension too large".
`\texdimencc{<dim. expr.>}`
@@ -399,7 +437,7 @@ Remarks about "Dimension too large" issues:
> would have been closer).
> `\maxdimen` as input produces on output `1276.00215` and indeed the
-> maximal attainable dimension is `1276.00215cc` (`1073741821sp`).
+> maximal attainable dimension is `1276.00215cc` (`\maxdimen-2sp`).
`\texdimenccdown{<dim. expr.>}`
@@ -412,6 +450,9 @@ Remarks about "Dimension too large" issues:
> 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.
+>
+> If input is `>\maxdimen-2sp`, then `Dcc` virtually represents
+> `\maxdimen+11sp` and will trigger on use "Dimension too large".
`\texdimencm{<dim. expr.>}`
@@ -422,7 +463,7 @@ Remarks about "Dimension too large" issues:
> would have been closer).
> `\maxdimen` as input produces on output `575.83174` and indeed the
-> maximal attainable dimension is `575.83174cm` (`1073741822sp`).
+> maximal attainable dimension is `575.83174cm` (`\maxdimen-1sp`).
`\texdimencmdown{<dim. expr.>}`
@@ -435,6 +476,9 @@ Remarks about "Dimension too large" issues:
> 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.
+>
+> If input is `\maxdimen`, then `Dcm` virtually represents
+> `\maxdimen+28sp` and will trigger on use "Dimension too large".
`\texdimenin{<dim. expr.>}`
@@ -444,9 +488,10 @@ Remarks about "Dimension too large" issues:
> known in advance which one (and it is not known if the other choice
> would have been closer).
-> Warning: the output for `\maxdimen` is `226.70541` but `226.70541in`
-> will trigger "Dimension too large" error.
-> `\maxdimen-55sp` is maximal attainable dimension (via `226.7054in`).
+> Warning: the output for `\maxdimen-18sp` is `226.70541` but `226.70541in`
+> will trigger on use "Dimension too large" error.
+> `\maxdimen-19sp` is the maximal input for which the output remains
+> less than `\maxdimen` (max attainable dimension: `\maxdimen-55sp`).
`\texdimenindown{<dim. expr.>}`
@@ -459,102 +504,138 @@ Remarks about "Dimension too large" issues:
> 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.
+>
+> If input is `>\maxdimen-55sp`, then `Din` virtually represents
+> `\maxdimen+17sp` and will trigger on use "Dimension too large".
`\texdimenbothcmin{<dim. expr.>}`
-> Produces a decimal (with up to five decimal places) `D` such that `Din`
-> is the largest dimension smaller than the original one and
-> exactly representable both in the `in` and `cm` units.
+> Produces a decimal (with up to five decimal places) `D` such that
+> `Din` is the largest dimension not exceeding the original one (in
+> absolute value) and exactly representable both in the `in` and `cm`
+> units.
`\texdimenbothincm{<dim. expr.>}`
-> Produces a decimal (with up to five decimal places) `D` such that `Dcm`
-> is the largest dimension smaller than the original one and
-> exactly representable both in the `in` and `cm` units. It thus represents
-> the same dimension as `\texdimenbothcmin{<dim. expr.>}in`.
+> Produces a decimal (with up to five decimal places) `D` such that
+> `Dcm` is the largest dimension not exceeding the original one (in
+> absolute value) and exactly representable both in the `in` and `cm`
+> units. Thus both expressions `\texdimenbothcmin{<dim. expr.>}in` and
+> `\texdimenbothincm{<dim. expr.>}cm` represent the same dimension.
`\texdimenbothcminpt{<dim. expr.>}`
-> Produces a decimal (with up to five decimal places) `D` such that `Dpt`
-> is the largest dimension smaller than the original one and
-> exactly representable both in the `in` and `cm` units. It thus represents
-> the same dimension as the one provided by `\texdimenbothcmin` and
-> `\texdimenbothincm`.
+> Produces a decimal (with up to five decimal places) `D` such that
+> `Dpt` is the largest dimension not exceeding the original one (in
+> absolute value) and exactly representable both in the `in` and `cm`
+> units. It thus represents the same dimension as the one determined by
+> `\texdimenbothcmin` and `\texdimenbothincm`.
`\texdimenbothincmpt{<dim. expr.>}`
-> Same as `\texdimenbothcminpt`.
+> Alias for `\texdimenbothcminpt`.
`\texdimenbothcminsp{<dim. expr.>}`
-> Produces an integer (explicit digit tokens) `N` such that `Nsp`
-> is the largest dimension smaller than the original one and
+> Produces an integer (explicit digit tokens) `N` such that `Nsp` is the
+> largest dimension not exceeding the original one in absolute value and
> exactly representable both in the `in` and `cm` units.
`\texdimenbothincmsp{<dim. expr.>}`
-> Same as `\texdimenbothcminsp`.
+> Alias for `\texdimenbothcminsp`.
+
+`\texdimenbothbpmm{<dim. expr.>}`
+
+> Produces a decimal (with up to five decimal places) `D` such that
+> `Dmm` is the largest dimension smaller (in absolute value) than the
+> original one and exactly representable both in the `bp` and `mm`
+> units.
+
+`\texdimenbothmmbp{<dim. expr.>}`
+
+> Produces a decimal (with up to five decimal places) `D` such that
+> `Dbp` is the largest dimension smaller (in absolute value) than the
+> original one and exactly representable both in the `bp` and `mm`
+> units. Thus `\texdimenbothmmbp{<dim. expr.>}bp` is the same
+> dimension as `\texdimenbothbpmm{<dim. expr.>}mm`.
+
+`\texdimenbothbpmmpt{<dim. expr.>}`
+
+> Produces a decimal (with up to five decimal places) `D` such that
+> `Dpt` is the largest dimension not exceeding the original one and
+> exactly representable both in the `bp` and `mm` units.
+
+`\texdimenbothmmbppt{<dim. expr.>}`
+
+> Alias for `\texdimenbothbpmmpt`.
+
+`\texdimenbothbpmmsp{<dim. expr.>}`
+
+> Produces an integer (explicit digit tokens) `N` such that `Nsp`
+> is the largest dimension not exceeding the original one and
+> exactly representable both in the `bp` and `mm` units.
+
+`\texdimenbothmmbpsp{<dim. expr.>}`
+
+> Alias for `\texdimenbothbpmmsp`.
`\texdimenwithunit{<dim. expr. 1>}{<dim expr. 2>}`
> Produces a decimal `D` such that `D\dimexpr <dim expr. 2>\relax` is
> considered by TeX the same as `<dim. expr. 1>` if at all possible. If
-> not possible it will be a closest match either from above or below
-> (but one does not know if the other direction is a better or worst
-> match).
+> the (assumed non zero) second argument `<dim2>` is at most `1pt` (in
+> absolute value), then this is always possible. If the second argument
+> `<dim2>` is `>1pt` then this is not always possible and the output `D`
+> will ensure for `D<dim2>` to be a closest match to the first argument
+> `dim1` either from above or below, but one does not know if the other
+> direction would have given a better or worst match.
>
-> `\texdimenwithunit{dim}{1bp}` and `\texdimenbp{dim}` are not
+> `\texdimenwithunit{<dim>}{1bp}` and `\texdimenbp{<dim>}` are not
> the same: The former produces a decimal `D` such that `D\dimexpr
-> 1bp\relax` is represented internally as is `dim` if at all possible,
+> 1bp\relax` is represented internally as is `<dim>` if at all possible,
> whereas the latter produces a decimal `D` such that `D bp` is the one
-> aiming at being the same as `dim`. Using `D\dimexpr 1bp\relax` implies
+> aiming at being the same as `<dim>`. Using `D\dimexpr 1bp\relax` implies
> a conversion factor equal to `65781/65536`, whereas `D bp` involves
> the `803/800` conversion factor.
+>
+> `\texdimenwithunit{D1pt}{D2pt}` output is close to the mathematical
+> ratio `D1/D2`. But notwithstanding the various unavoidable "errors"
+> arising from conversion of decimal inputs to binary internals, and
+> from the latter to the former, the output `R` will tend to be
+> on average slightly larger (in its last decimal) than mathematical
+> `D1/D2`. The root cause being that the specification for `R` is that
+> `R<D2pt>` must be exactly `<D1pt>` after TeX parsing, if at all
+> possible; and it turns out this is always possible for `D2pt<1pt`. The
+> final step in the TeX parsing of a multiplication of a dimension by a
+> scalar is a *truncation* to an integer multiple of the `sp=1/65536pt`
+> unit, not a rounding. So `R` is basically (i.e. before conversion to a
+> decimal) `ceil(D1/D2,16)`, or to be more precise it is obtained as
+> `ceil(N1/N2,16)` with `D1pt->N1sp`, `D2pt->N2sp` and the second
+> argument of `ceil` means that `16` binary places are used. This
+> formula is the one used for `D2pt<1pt`, for `D2pt>1pt` the mathematics
+> is different, but the implication that `R` has a (less significant)
+> bias to be "shifted upwards" (in its last decimal place) compared to
+> the (rounded) value `D1/D2` or rather `N1/N2` still stands.
-## Extras?
-
-As already stated the "up" and also the "down" macros for the `dd`, `nc`
-and `in` units will trigger "Dimension too large" if used with inputs
-equal to or very near `\maxdimen`. "Safe" variants which are guaranteed
-never to trigger this error but have some extra overhead to filter out
-inputs very close to `\maxdimen` will *perhaps* be provided if there is
-some demand for it.
-
-But of course anyhow the output from the "up" macros if used
-as input with the corresponding unit will be beyond `\maxdimen` if the
-latter is not attainable, i.e. for all units except `bp`, and `nd`
-(and `pt` but there is no "up" macro for it).
-
-The
-dimensions representable with both `in` and `cm` units have the shape
-`trunc(3613.5*k)sp` for some integer `k`. The largest one smaller
-than a given dimension will thus differ from it by at most about `0.055pt`,
-which is also about `0.02mm`.
-
-For example `\texdimenbothincm{1cm}` expands to `0.99994cm` which maps
-internally to `1864566sp` which differs from TeX's `1cm` by only
-`-113sp`. It can be obtained from `0.39368in` or `28.45102pt`.
-
-And `\texdimenbothcmin{1in}` expands to `0.99945in`, maps internally to
-`4733685sp` which differs from TeX's `1in` by `-2601sp`. It can be obtained
-as `2.5386cm` or `72.2303pt`.
-
-Currently the package does not provide analogous approximations from above.
-For the `1in` for example it would be `4737298sp`, i.e. `1.00021in` which
-differs from TeX's `1in` by `+1012sp` and is obtained also as `2.54054cm`
-and `72.28543pt`.
-
## Acknowledgements
Thanks to Denis Bitouzé for raising an
[issue](https://github.com/latex3/latex3/issues/953)
on the LaTeX3 tracker which became the initial stimulus for this package.
-Thanks to Ruixi Zhang for reviving the above linked-to thread
-and opening up here [issue #2](https://github.com/jfbu/texdimens/issues/2)
-asking to add handling of the `ex`,`em`, and `px` cases. This was done
-at release `0.99` via the addition of `\texdimenwithunit`.
+Thanks to Ruixi Zhang for reviving the above linked-to thread and
+opening up on the package issue tracker the
+[issue #2](https://github.com/jfbu/texdimens/issues/2) asking to add
+handling of the `ex` and `em` cases. This was done at release `0.99` via
+the addition of `\texdimenwithunit`.
+
+Renewed thanks to Ruixi Zhang for analyzing at
+[issue #10](https://github.com/jfbu/texdimens/issues/10) what is at
+stake into finding dimensions exactly representable both in the `bp` and
+`mm` units. Macros `\texdimenbothbpmm` and `\texdimenbothmmbp` now
+address this (release `1.0`).
<!--
-->