summaryrefslogtreecommitdiff
path: root/Master/texmf-dist
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2021-11-16 21:22:46 +0000
committerKarl Berry <karl@freefriends.org>2021-11-16 21:22:46 +0000
commit0b16a00bb08a3220476425bdb01e5d41eae25c82 (patch)
tree90728786ab7b6f69bfbbcf7705636aebd9d2a46c /Master/texmf-dist
parentc38cad165ea5ccd7f4540bbd1573df38bb06e9db (diff)
texdimens (16nov21)
git-svn-id: svn://tug.org/texlive/trunk@61070 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist')
-rw-r--r--Master/texmf-dist/doc/generic/texdimens/LICENSE.md6
-rw-r--r--Master/texmf-dist/doc/generic/texdimens/README.md14
-rw-r--r--Master/texmf-dist/doc/generic/texdimens/texdimens.md189
-rw-r--r--Master/texmf-dist/doc/generic/texdimens/texdimens.pdfbin52009 -> 115110 bytes
-rw-r--r--Master/texmf-dist/tex/generic/texdimens/texdimens.sty4
-rw-r--r--Master/texmf-dist/tex/generic/texdimens/texdimens.tex387
6 files changed, 341 insertions, 259 deletions
diff --git a/Master/texmf-dist/doc/generic/texdimens/LICENSE.md b/Master/texmf-dist/doc/generic/texdimens/LICENSE.md
index 50c8cd28b91..95ed9eda158 100644
--- a/Master/texmf-dist/doc/generic/texdimens/LICENSE.md
+++ b/Master/texmf-dist/doc/generic/texdimens/LICENSE.md
@@ -1,4 +1,4 @@
-License for texdimens package
+License for the CTAN texdimens package
=======
Copyright (c) 2021 Jean-François Burnol
@@ -17,5 +17,5 @@ This Work has the LPPL maintenance status author-maintained.
The Author of this Work is Jean-François Burnol
This Work consists of the package files `texdimens.tex`, `texdimens.sty`,
-`README.md` and `LICENSE.md`.
-
+the documentation `texdimens.md` and its conversion `texdimens.pdf`,
+as well as `README.md` and the present `LICENSE.md`.
diff --git a/Master/texmf-dist/doc/generic/texdimens/README.md b/Master/texmf-dist/doc/generic/texdimens/README.md
index 107f8d73c05..cab1b523962 100644
--- a/Master/texmf-dist/doc/generic/texdimens/README.md
+++ b/Master/texmf-dist/doc/generic/texdimens/README.md
@@ -5,12 +5,10 @@ texdimens
Copyright (c) 2021 Jean-François Burnol
-This file is part of the texdimens package distributed under the
-LPPL 1.3c. See file LICENSE.md.
+This file is part of the texdimens package distributed (see file
+LICENSE.md) under the [LPPL 1.3c](https://ctan.org/license/lppl1.3c).
-Repository: https://github.com/jfbu/texdimens
-
-Release: `1.0 2021/11/10`
+Release: [1.1 2021/11/17](https://github.com/jfbu/texdimens/compare/1.0...1.1#files_bucket)
## Usage
@@ -20,6 +18,8 @@ Utilities and documentation related to TeX dimensional units, usable:
- with LaTeX: `\usepackage{texdimens}`
+Development and issue tracking: https://github.com/jfbu/texdimens
+
## Aim of this package
The aim of this package is to provide facilities to express dimensions
@@ -39,8 +39,8 @@ This package provides expandable macros:
`\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
+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
diff --git a/Master/texmf-dist/doc/generic/texdimens/texdimens.md b/Master/texmf-dist/doc/generic/texdimens/texdimens.md
index ec6ac406e07..ed0994f406c 100644
--- a/Master/texmf-dist/doc/generic/texdimens/texdimens.md
+++ b/Master/texmf-dist/doc/generic/texdimens/texdimens.md
@@ -1,16 +1,13 @@
-texdimens
-=========
+% texdimens 1.1
+% Jean-François Burnol
+% 2021/11/17
## Copyright and License
Copyright (c) 2021 Jean-François Burnol
-This file is part of the texdimens package distributed under the
-LPPL 1.3c. See file LICENSE.md.
-
-Repository: https://github.com/jfbu/texdimens
-
-Release: `1.0 2021/11/10`
+The texdimens [CTAN package](https://ctan.org/pkg/texdimens) is
+distributed under the [LPPL 1.3c](https://ctan.org/license/lppl1.3c).
## Usage
@@ -20,6 +17,9 @@ Utilities and documentation related to TeX dimensional units, usable:
- with LaTeX: `\usepackage{texdimens}`
+For reporting issues, use the
+[package repository](https://github.com/jfbu/texdimens).
+
## Aim of this package
The aim of this package is to provide facilities to express dimensions
@@ -39,8 +39,8 @@ This package provides expandable macros:
`\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
+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
@@ -71,13 +71,6 @@ details in the complete macro description.
## Quick review of basics: TeX points and scaled points
-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.
-
TeX dimensions are represented internally by a signed integer which is
in absolute value at most `0x3FFFFFFF`, i.e. `1073741823`. The
corresponding unit is called the "scaled point", i.e. `1sp` is `1/65536`
@@ -237,11 +230,21 @@ the `pt`.
## Macros of this package (full list)
-The macros are all expandable, and most are f-expandable (check the
-source code). They parse their arguments via `\dimexpr` so can be nested
+This project requires the `\dimexpr`, `\numexpr` e-TeX extensions. It
+also requires the `\expanded` primitive (available in all engines since
+TeXLive 2019).
+
+The macros provided by the package are all expandable, even
+f-expandable. They parse their arguments via `\dimexpr` so can be nested
(with appropriate units added, as the outputs always are bare decimal
numbers).
+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.
+
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").
@@ -274,11 +277,11 @@ Remarks about "Dimension too large" issues:
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.>}`
+### `\texdimenpt{<dim. expr.>}`
> Does `\the\dimexpr <dim. expr.> \relax` then removes the `pt`.
-`\texdimenbp{<dim. expr.>}`
+### `\texdimenbp{<dim. expr.>}`
> Produces a decimal (with up to five decimal places) `D` such that `Dbp`
> represents the dimension exactly if possible. If not possible it
@@ -288,19 +291,19 @@ Remarks about "Dimension too large" issues:
> `\maxdimen` on input produces `16322.78954` and indeed is realized as
> `16322.78954bp`.
-`\texdimenbpdown{<dim. expr.>}`
+### `\texdimenbpdown{<dim. expr.>}`
> Produces a decimal (with up to five decimal places) `D` such that `Dbp`
> represents the dimension exactly if possible. If not possible it
> will be smaller by `1sp` from the original dimension.
-`\texdimenbpup{<dim. expr.>}`
+### `\texdimenbpup{<dim. expr.>}`
> Produces a decimal (with up to five decimal places) `D` such that `Dbp`
> represents the dimension exactly if possible. If not possible it
> will be larger by `1sp` from the original dimension.
-`\texdimennd{<dim. expr.>}`
+### `\texdimennd{<dim. expr.>}`
> Produces a decimal (with up to five decimal places) `D` such that `Dnd`
> represents the dimension exactly if possible. If not possible it
@@ -310,19 +313,19 @@ Remarks about "Dimension too large" issues:
> `\maxdimen` on input produces `15355.51532` and indeed is realized as
> `15355.51532nd`.
-`\texdimennddown{<dim. expr.>}`
+### `\texdimennddown{<dim. expr.>}`
> Produces a decimal (with up to five decimal places) `D` such that `Dnd`
> represents the dimension exactly if possible. If not possible it
> will be smaller by `1sp` from the original dimension.
-`\texdimenndup{<dim. expr.>}`
+### `\texdimenndup{<dim. expr.>}`
> Produces a decimal (with up to five decimal places) `D` such that `Dnd`
> represents the dimension exactly if possible. If not possible it
> will be larger by `1sp` from the original dimension.
-`\texdimendd{<dim. expr.>}`
+### `\texdimendd{<dim. expr.>}`
> Produces a decimal (with up to five decimal places) `D` such that `Ddd`
> represents the dimension exactly if possible. If not possible it
@@ -334,13 +337,13 @@ Remarks about "Dimension too large" issues:
> `\maxdimen-1sp` is the maximal input for which the output remains
> less than `\maxdimen` (max attainable dimension: `\maxdimen-1sp`).
-`\texdimendddown{<dim. expr.>}`
+### `\texdimendddown{<dim. expr.>}`
> Produces a decimal (with up to five decimal places) `D` such that `Ddd`
> represents the dimension exactly if possible. If not possible it
> will be smaller by `1sp` from the original dimension.
-`\texdimenddup{<dim. expr.>}`
+### `\texdimenddup{<dim. expr.>}`
> Produces a decimal (with up to five decimal places) `D` such that `Ddd`
> represents the dimension exactly if possible. If not possible it
@@ -349,7 +352,7 @@ Remarks about "Dimension too large" issues:
> If input is `\maxdimen`, then `Ddd` virtually represents
> `\maxdimen+1sp` and will trigger on use "Dimension too large".
-`\texdimenmm{<dim. expr.>}`
+### `\texdimenmm{<dim. expr.>}`
> Produces a decimal (with up to five decimal places) `D` such that `Dmm`
> represents the dimension exactly if possible. If not possible it
@@ -360,13 +363,13 @@ Remarks about "Dimension too large" issues:
> `\maxdimen` as input produces on output `5758.31741` and indeed the
> maximal attainable dimension is `5758.31741mm` (`\maxdimen-1sp`).
-`\texdimenmmdown{<dim. expr.>}`
+### `\texdimenmmdown{<dim. expr.>}`
> Produces a decimal (with up to five decimal places) `D` such that `Dmm`
> represents the dimension exactly if possible. If not possible it
> will be largest representable dimension smaller than the original one.
-`\texdimenmmup{<dim. expr.>}`
+### `\texdimenmmup{<dim. expr.>}`
> Produces a decimal (with up to five decimal places) `D` such that `Dmm`
> represents the dimension exactly if possible. If not possible it
@@ -375,7 +378,7 @@ Remarks about "Dimension too large" issues:
> If input is `\maxdimen`, then `Dmm` virtually represents
> `\maxdimen+2sp` and will trigger on use "Dimension too large".
-`\texdimenpc{<dim. expr.>}`
+### `\texdimenpc{<dim. expr.>}`
> Produces a decimal (with up to five decimal places) `D` such that `Dpc`
> represents the dimension exactly if possible. If not possible it
@@ -385,13 +388,13 @@ Remarks about "Dimension too large" issues:
> `\maxdimen` as input produces on output `1365.33333` and indeed the
> maximal attainable dimension is `1365.33333pc` (`\maxdimen-3sp`).
-`\texdimenpcdown{<dim. expr.>}`
+### `\texdimenpcdown{<dim. expr.>}`
> Produces a decimal (with up to five decimal places) `D` such that `Dpc`
> represents the dimension exactly if possible. If not possible it
> will be largest representable dimension smaller than the original one.
-`\texdimenpcup{<dim. expr.>}`
+### `\texdimenpcup{<dim. expr.>}`
> Produces a decimal (with up to five decimal places) `D` such that `Dpc`
> represents the dimension exactly if possible. If not possible it
@@ -400,7 +403,7 @@ Remarks about "Dimension too large" issues:
> If input is `>\maxdimen-3sp`, then `Dpc` virtually represents
> `\maxdimen+9sp` and will trigger on use "Dimension too large".
-`\texdimennc{<dim. expr.>}`
+### `\texdimennc{<dim. expr.>}`
> Produces a decimal (with up to five decimal places) `D` such that `Dnc`
> represents the dimension exactly if possible. If not possible it
@@ -413,13 +416,13 @@ Remarks about "Dimension too large" issues:
> `\maxdimen-2sp` is the maximal input for which the output remains
> less than `\maxdimen` (max attainable dimension: `\maxdimen-9sp`).
-`\texdimenncdown{<dim. expr.>}`
+### `\texdimenncdown{<dim. expr.>}`
> Produces a decimal (with up to five decimal places) `D` such that `Dnc`
> represents the dimension exactly if possible. If not possible it
> will be largest representable dimension smaller than the original one.
-`\texdimenncup{<dim. expr.>}`
+### `\texdimenncup{<dim. expr.>}`
> Produces a decimal (with up to five decimal places) `D` such that `Dnc`
> represents the dimension exactly if possible. If not possible it
@@ -428,7 +431,7 @@ Remarks about "Dimension too large" issues:
> If input is `>\maxdimen-9sp`, then `Dnc` virtually represents
> `\maxdimen+4sp` and will trigger on use "Dimension too large".
-`\texdimencc{<dim. expr.>}`
+### `\texdimencc{<dim. expr.>}`
> Produces a decimal (with up to five decimal places) `D` such that `Dcc`
> represents the dimension exactly if possible. If not possible it
@@ -439,13 +442,13 @@ Remarks about "Dimension too large" issues:
> `\maxdimen` as input produces on output `1276.00215` and indeed the
> maximal attainable dimension is `1276.00215cc` (`\maxdimen-2sp`).
-`\texdimenccdown{<dim. expr.>}`
+### `\texdimenccdown{<dim. expr.>}`
> Produces a decimal (with up to five decimal places) `D` such that `Dcc`
> represents the dimension exactly if possible. If not possible it
> will be largest representable dimension smaller than the original one.
-`\texdimenccup{<dim. expr.>}`
+### `\texdimenccup{<dim. expr.>}`
> Produces a decimal (with up to five decimal places) `D` such that `Dcc`
> represents the dimension exactly if possible. If not possible it
@@ -454,7 +457,7 @@ Remarks about "Dimension too large" issues:
> If input is `>\maxdimen-2sp`, then `Dcc` virtually represents
> `\maxdimen+11sp` and will trigger on use "Dimension too large".
-`\texdimencm{<dim. expr.>}`
+### `\texdimencm{<dim. expr.>}`
> Produces a decimal (with up to five decimal places) `D` such that `Dcm`
> represents the dimension exactly if possible. If not possible it
@@ -465,13 +468,13 @@ Remarks about "Dimension too large" issues:
> `\maxdimen` as input produces on output `575.83174` and indeed the
> maximal attainable dimension is `575.83174cm` (`\maxdimen-1sp`).
-`\texdimencmdown{<dim. expr.>}`
+### `\texdimencmdown{<dim. expr.>}`
> Produces a decimal (with up to five decimal places) `D` such that `Dcm`
> represents the dimension exactly if possible. If not possible it
> will be largest representable dimension smaller than the original one.
-`\texdimencmup{<dim. expr.>}`
+### `\texdimencmup{<dim. expr.>}`
> Produces a decimal (with up to five decimal places) `D` such that `Dcm`
> represents the dimension exactly if possible. If not possible it
@@ -480,7 +483,7 @@ Remarks about "Dimension too large" issues:
> If input is `\maxdimen`, then `Dcm` virtually represents
> `\maxdimen+28sp` and will trigger on use "Dimension too large".
-`\texdimenin{<dim. expr.>}`
+### `\texdimenin{<dim. expr.>}`
> Produces a decimal (with up to five decimal places) `D` such that `Din`
> represents the dimension exactly if possible. If not possible it
@@ -493,13 +496,13 @@ Remarks about "Dimension too large" issues:
> `\maxdimen-19sp` is the maximal input for which the output remains
> less than `\maxdimen` (max attainable dimension: `\maxdimen-55sp`).
-`\texdimenindown{<dim. expr.>}`
+### `\texdimenindown{<dim. expr.>}`
> Produces a decimal (with up to five decimal places) `D` such that `Din`
> represents the dimension exactly if possible. If not possible it
> will be largest representable dimension smaller than the original one.
-`\texdimeninup{<dim. expr.>}`
+### `\texdimeninup{<dim. expr.>}`
> Produces a decimal (with up to five decimal places) `D` such that `Din`
> represents the dimension exactly if possible. If not possible it
@@ -508,14 +511,14 @@ Remarks about "Dimension too large" issues:
> If input is `>\maxdimen-55sp`, then `Din` virtually represents
> `\maxdimen+17sp` and will trigger on use "Dimension too large".
-`\texdimenbothcmin{<dim. expr.>}`
+### `\texdimenbothcmin{<dim. expr.>}`
> 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.>}`
+### `\texdimenbothincm{<dim. expr.>}`
> Produces a decimal (with up to five decimal places) `D` such that
> `Dcm` is the largest dimension not exceeding the original one (in
@@ -523,7 +526,7 @@ Remarks about "Dimension too large" issues:
> units. Thus both expressions `\texdimenbothcmin{<dim. expr.>}in` and
> `\texdimenbothincm{<dim. expr.>}cm` represent the same dimension.
-`\texdimenbothcminpt{<dim. expr.>}`
+### `\texdimenbothcminpt{<dim. expr.>}`
> Produces a decimal (with up to five decimal places) `D` such that
> `Dpt` is the largest dimension not exceeding the original one (in
@@ -531,28 +534,28 @@ Remarks about "Dimension too large" issues:
> units. It thus represents the same dimension as the one determined by
> `\texdimenbothcmin` and `\texdimenbothincm`.
-`\texdimenbothincmpt{<dim. expr.>}`
+### `\texdimenbothincmpt{<dim. expr.>}`
> Alias for `\texdimenbothcminpt`.
-`\texdimenbothcminsp{<dim. expr.>}`
+### `\texdimenbothcminsp{<dim. expr.>}`
> 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.>}`
+### `\texdimenbothincmsp{<dim. expr.>}`
> Alias for `\texdimenbothcminsp`.
-`\texdimenbothbpmm{<dim. expr.>}`
+### `\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.>}`
+### `\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
@@ -560,27 +563,27 @@ Remarks about "Dimension too large" issues:
> units. Thus `\texdimenbothmmbp{<dim. expr.>}bp` is the same
> dimension as `\texdimenbothbpmm{<dim. expr.>}mm`.
-`\texdimenbothbpmmpt{<dim. expr.>}`
+### `\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.>}`
+### `\texdimenbothmmbppt{<dim. expr.>}`
> Alias for `\texdimenbothbpmmpt`.
-`\texdimenbothbpmmsp{<dim. expr.>}`
+### `\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.>}`
+### `\texdimenbothmmbpsp{<dim. expr.>}`
> Alias for `\texdimenbothbpmmsp`.
-`\texdimenwithunit{<dim. expr. 1>}{<dim expr. 2>}`
+### `\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
@@ -592,8 +595,8 @@ Remarks about "Dimension too large" issues:
> direction would have given a better or worst match.
>
> `\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,
+> the same: The former produces a decimal `D` such that `D\dimexpr 1bp\relax`
+> is represented internally as is `<dim>` if at all possible,
> whereas the latter produces a decimal `D` such that `D bp` is the one
> aiming at being the same as `<dim>`. Using `D\dimexpr 1bp\relax` implies
> a conversion factor equal to `65781/65536`, whereas `D bp` involves
@@ -618,6 +621,68 @@ Remarks about "Dimension too large" issues:
> bias to be "shifted upwards" (in its last decimal place) compared to
> the (rounded) value `D1/D2` or rather `N1/N2` still stands.
+## Change log
+
+### [1.1 (2021/11/17)](https://github.com/jfbu/texdimens/compare/1.0...1.1#files_bucket)
+
+- internal refactorings across the entire code base aiming at (small)
+ efficiency gains from optimized TeX token manipulations
+- in particular, the algorithm for `\texdimenwithunit{<dim1>}{<dim2>}`
+ in the "`dim2<1pt`" branch got modified (output unchanged)
+- all macros now f-expandable (this was already the case at `1.0` except
+ for `\texdimenwithunit` with arguments of opposite signs, the
+ second one not exceeding `1pt` in absolute value)
+- the `\expanded` primitive is required (present in all engines since
+ TeXLive 2019)
+- the usual batch of documentation additions or fix-ups, also in
+ code comments (fix in particular issues #21, #22)
+- addition of this Change log to the pdf documentation
+- addition of the highlighted commented source code to the pdf documentation
+
+### [1.0 (2021/11/10)](https://github.com/jfbu/texdimens/compare/0.99d...1.0#files_bucket)
+
+- new: `\texdimenbothbpmm` and relatives (feature request #10)
+- breaking: `\texdimenwithunit` output for second argument `<1pt` still
+ obeys specs but is closer to mathematical ratio (feature request #16)
+- enhanced: all `up/down` macros (i.e. also for the `dd`, `nc`, `in`
+ units) accept the full range of dimensions (feature request #18)
+- enhanced: `\texdimenwithunit`'s second argument is now allowed
+ to be negative (feature request #13)
+
+### [0.99a-d (2021/11/04)](https://github.com/jfbu/texdimens/compare/0.99...0.99d#files_bucket)
+
+- documentation in TeX/LaTeX installations available in pdf format
+- the usual batch of documentation additions or fix-ups
+- let the CTAN `README.md` be much shortened, and provide `texdimens.md`
+ as the one matching the repo `README.md`
+- fix bugs of `\texdimenwithunit{<dim1>}{<dime2>}` for `dim1=0pt` or
+ `dim2=1pt` (#3, #4, #6, #8)
+
+### [0.99 (2021/11/02)](https://github.com/jfbu/texdimens/compare/0.9...0.99#files_bucket)
+
+- new: `\texdimenwithunit{<dim1>}{<dim2>}` (feature request #2)
+
+### [0.9 (2021/07/21)](https://github.com/jfbu/texdimens/compare/0.9delta...0.9#files_bucket)
+
+- new: `\texdimenbothincm` and relatives
+- breaking: use `\texdimen` prefix for all macros
+
+### [0.9delta (2021/07/15)](https://github.com/jfbu/texdimens/compare/0.9gamma...0.9delta#files_bucket)
+
+- internal refactorings
+
+### [0.9gamma (2021/07/14)](https://github.com/jfbu/texdimens/compare/0.9beta...0.9gamma#files_bucket)
+
+- new: `\texdiminbpdown` (now `\texdimenbpdown`), `\texdiminbpup`
+ (now `\texdimenbpup`) and similar named macros associated with
+ the other units
+
+### [0.9beta (2021/06/30)](https://github.com/jfbu/texdimens/compare/54f4eb13...0.9beta#files_bucket)
+
+- initial release: provides `\texdiminbp` (now `\texdimenbp`) and
+ similar named macros for the units `nd`, `dd`, `mm`, `pc`, `nc`, `cc`,
+ `cm`, `in`
+
## Acknowledgements
diff --git a/Master/texmf-dist/doc/generic/texdimens/texdimens.pdf b/Master/texmf-dist/doc/generic/texdimens/texdimens.pdf
index 29d727ab17c..11d42bacbae 100644
--- a/Master/texmf-dist/doc/generic/texdimens/texdimens.pdf
+++ b/Master/texmf-dist/doc/generic/texdimens/texdimens.pdf
Binary files differ
diff --git a/Master/texmf-dist/tex/generic/texdimens/texdimens.sty b/Master/texmf-dist/tex/generic/texdimens/texdimens.sty
index db0220f1db4..092759ed58f 100644
--- a/Master/texmf-dist/tex/generic/texdimens/texdimens.sty
+++ b/Master/texmf-dist/tex/generic/texdimens/texdimens.sty
@@ -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/11/10 v1.0 conversion of TeX dimensions to decimals (JFB)]
+\ProvidesPackage{texdimens}[2021/11/17 v1.1 conversion of TeX dimensions to decimals (JFB)]
\@@input texdimens.tex\relax
-\endinput \ No newline at end of file
+\endinput
diff --git a/Master/texmf-dist/tex/generic/texdimens/texdimens.tex b/Master/texmf-dist/tex/generic/texdimens/texdimens.tex
index de6f20e58fe..c3aa10fc73b 100644
--- a/Master/texmf-dist/tex/generic/texdimens/texdimens.tex
+++ b/Master/texmf-dist/tex/generic/texdimens/texdimens.tex
@@ -1,27 +1,38 @@
% 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/11/10 v1.0
+% 2021/11/17 v1.1
\edef\texdimensendinput{\endlinechar\the\endlinechar%
\catcode`\noexpand _=\the\catcode`\_%
\catcode`\noexpand @=\the\catcode`\@\relax\noexpand\endinput}%
\endlinechar13\relax%
-\catcode`\_=11 \catcode`\@=11 % only for using \p@ (also \z@ now) of Plain. Check exists?
+% only for using \p@ (also \z@ now) of Plain. Check if \p@, \z@ exists?
+\catcode`\_=11 \catcode`\@=11
+% so tempted to do \input xintkernel.sty to have some utilities...
+% not even a \@gobble in Plain...
+\def\texdimenfirstofone#1{#1}%
+\def\texdimengobtilminus#1-{}%
+\def\texdimenzerominusfork #10-#2#3\krof {#2}%
%
-% Mathematics (the challenge of the "down" and "up" macros)
-% ===========
+% \texdimenuu, \texdimenuudown, \texdimenuuup
+% ===========================================
+%
+% Mathematics
+% -----------
%
% In the entire discussion here, "uu" stands for some core unit,
% or some unit corresponding to an internal dimension > 1pt.
%
-% Is T sp attainable from unit "uu"?.
-% If not, what is largest dimension < Tsp which is attainable?
-% Here we suppose T>0.
+% Main question at the origin of this file was:
+% Is T sp attainable from unit "uu"?.
+% If not, what is largest dimension < Tsp which is?
+%
+% Here we suppose T>0. TeX parsing of D uu is equivalent to:
%
% D uu --> N = round(D * 65536) --> T = trunc (N * phi)
%
% phi>1 is the conversion factor associated to "uu"
% psi=1/phi, psi<1. Define U(N, phi) = trunc (N * phi)
-%
+%
% U(N,phi) is thus the strictly increasing sequence,
% indexed by non-negative integers, of non-negative
% attainable dimensions. (in sp unit)
@@ -35,23 +46,16 @@
%
% - the largest attainable dimension not exceeding T sp
% is obtained via the integer "Zd = ceil((T+1)psi) - 1 = N",
-% (i.e. find D with Zd=round(65536 D) then "D uu" is "down" approximation)
+% (i.e. find D with Zd=round(65536 D) then "D uu" is "down"
+% approximation)
%
% - the smallest attainable dimension at least equal to T sp
% is obtained from the integer "Zu = ceil(T psi) = M + 1"
%
% - the two "Z"'s are either equal (i.e. T is attained) or Zu=Zd+1.
%
-% The round((T+0.5)*psi) based approach (basis of the "\texdimenUU" macros)
-% -------------------------------------
-%
-% Recall in all of this T > 0. And phi>1, psi=1/phi<1.
-%
-% Let's return to our analysis of the
-%
-% U(N)<= T < U(N+1) and U(M)< T <= U(M+1)
-%
-% equations. We will also use the N=Zd, and M+1=Zu notations.
+% \texdimenUU macros use round((T+0.5)*psi)
+% -----------------------------------------
%
% case1: M = N, i.e. Zd<Zu, i.e. T is not attainable:
% M=N=Zd < T psi < (T+1) psi <= N+1=Zu
@@ -61,8 +65,8 @@
% and check if it is < T or > T.
%
% As will be explained later trunc(R phi) can be computed very
-% easily by hijacking TeX's handling of dimensions, we don't
-% have to launch into \numexpr evaluations for that.
+% easily by hijacking TeX's handling of dimensions, no \numexpr
+% chains is needed.
%
% case2: M = N - 1, i.e. T = Zd = Zu is attained:
% T psi <= N < (T+1) psi, T = trunc(N phi)
@@ -76,38 +80,38 @@
%
% - compute R = round((T+0.5) psi)
%
-% - if T is attained, then T = trunc(R * phi)
+% - if T is attained, then T = trunc(R * phi)
%
-% - if T is not attained then either { Zd = R and Zu = R+1 } or
-% {Zd = R-1 and Zu = R}.
+% - if T is not attained then either { Zd = R and Zu = R+1 } or
+% {Zd = R-1 and Zu = R}.
%
-% How do we check if R = Zd or Zu? We need to evaluate trunc(R phi) and
-% compare it with T. This trunc(R phi) can be computed the following way:
+% How do we check if R = Zd or Zu? We need to evaluate trunc(R phi) and
+% compare it with T. This trunc(R phi) can be computed the following way:
%
-% - obtain D pt from \the\dimexpr R sp. Knuth's algorithm guarantees
+% - obtain D pt from \the\dimexpr R sp. Knuth's algorithm guarantees
% that R = round(D * 65536)
%
-% - then D uu where uu is the unit with conversion factor phi is
-% converted by TeX into "trunc(R phi) sp", i.e. trunc(R phi) =
-% \number\dimexpr Duu\relax, where D pt = \the\dimexpr Rsp\relax.
+% - then D uu where uu is the unit with conversion factor phi is
+% converted by TeX into "trunc(R phi) sp", i.e. trunc(R phi) =
+% \number\dimexpr Duu\relax, where D pt = \the\dimexpr Rsp\relax.
%
% Conclusion:
%
% 1. the macro \texdimenuu does the one-liner R=round((T+0.5) psi)
-% then \the\dimexpr Rsp\relax and strips the "pt" unit
+% then \the\dimexpr Rsp\relax gives "Dpt", the "pt" is removed,
+% we have a decimal D such that "Duu" does what one wants.
%
-% 2. macros \texdimenuuup and \texdimenuudown go further and check
-% which one of Zd or Zu is R, obtaining thus Zd or Zu.
-% [update: this describes the macros prior to 1.0 release]
+% 2. to get Zd (resp. Zu) one can use the D obtained in 1. and check
+% if "D uu" is at most (or at least) the user input dimension.
%
% For units with conversion factor phi>2, a simplification is possible.
-% In that case let X = round(T psi) (it has the advantage compared to
+% In that case let X = round(T psi) (it has the advantage compared to
% R that we can apply the formula without checking the sign of T).
%
% Going back to our earlier analyis, now with psi < 0.5 (1uu>2pt)
%
% case1: T is not attainable
-% M=N=Zd < T psi < (T+1) psi <= N+1=Zu
+% M=N=Zd < T psi < (T+1) psi <= N+1=Zu
% As Zd < T psi < Zu, we have round(T psi) = Zd or Zu
%
% case2: T is attained, i.e. T psi <= N < (T+1) psi.
@@ -153,8 +157,8 @@
% This made all usable even with \maxdimen input and besided, proved
% on average slightly faster.
%
-% Overcoming the ceil() stumbling block (i.e. the 1.0 manner for "up/down")
-% -------------------------------------
+% Overcoming the ceil() stumbling block for \texdimenUU{up,down}
+% --------------------------------------------------------------
%
% I will in what follows refer to trunc(), floor() or ceil() only for
% positive arguments, obtained as ratios x/y or sometimes as a numexpr
@@ -182,7 +186,7 @@
% with x = n*100/7227, and n = 1+r, so 0<n<=7227
%
% Here we have a nice situation 0 < x <= 100. Then:
-%
+%
% ceil(x) = 100 - floor(100 - x)
% = 100 - (round(100 - x + 0.5) - 1)
% = 101 - round(100 * (1 - n/7227) + 0.5)
@@ -203,10 +207,6 @@
% Zu = ceil(T*100/7227) and for all core TeX units. See the comments
% below for all obtained formulae and some additional details.
%
-% Implementation
-% ==============
-%
-\def\texdimenfirstofone#1{#1}%
{\catcode`p 12\catcode`t 12
\csname expandafter\endcsname\gdef\csname texdimenstrippt\endcsname#1pt{#1}}%
%
@@ -216,24 +216,22 @@
%
% bp 7227/7200 = 803/800
%
-\def\texdimenbp#1{\expandafter\texdimenbp_\the\numexpr\dimexpr#1;}%
-\def\texdimenbp_#1#2;{%
- \expandafter\texdimenstrippt\the\dimexpr\numexpr(2*#1#2+\if-#1-\fi1)*400/803sp\relax
-}%
+\def\texdimenbp#1{\expandafter\texdimenstrippt\the\dimexpr\numexpr(%
+ \expandafter\texdimen_bpnddd_signcheck
+ \the\numexpr2*\dimexpr#1\relax\relax)*400/803sp\relax}%
+\def\texdimen_bpnddd_signcheck#1{\texdimengobtilminus#1-1+#1}%
%
% nd 685/642
%
-\def\texdimennd#1{\expandafter\texdimennd_\the\numexpr\dimexpr#1;}%
-\def\texdimennd_#1#2;{%
- \expandafter\texdimenstrippt\the\dimexpr\numexpr(2*#1#2+\if-#1-\fi1)*321/685sp\relax
-}%
+\def\texdimennd#1{\expandafter\texdimenstrippt\the\dimexpr\numexpr(%
+ \expandafter\texdimen_bpnddd_signcheck
+ \the\numexpr2*\dimexpr#1\relax\relax)*321/685sp\relax}%
%
% dd 1238/1157
%
-\def\texdimendd#1{\expandafter\texdimendd_\the\numexpr\dimexpr#1;}%
-\def\texdimendd_#1#2;{%
- \expandafter\texdimenstrippt\the\dimexpr\numexpr(2*#1#2+\if-#1-\fi1)*1157/2476sp\relax
-}%
+\def\texdimendd#1{\expandafter\texdimenstrippt\the\dimexpr\numexpr(%
+ \expandafter\texdimen_bpnddd_signcheck
+ \the\numexpr2*\dimexpr#1\relax\relax)*1157/2476sp\relax}%
%
% mm 7227/2540 phi now >2, use from here on the X = round(T psi) approach
%
@@ -259,8 +257,8 @@
%
\def\texdimenin#1{\expandafter\texdimenstrippt\the\dimexpr(#1)*100/7227\relax}%
%
-% "no test" ceil()-based approach to up and down macros (release 1.0)
-% =====================================================
+% "up and down macros"
+% --------------------
%
% The notation <u/v> means u/v in numexpr, which does rounding
% away from zero. It is essential that the argument be >-0.5 else <x+1>
@@ -523,8 +521,11 @@
\def\texdimeninup_c#1;#2;{\expandafter\texdimeninup_d\the\numexpr#2-7227*#1;#1;}%
\def\texdimeninup_d#1;#2;{\numexpr#200+101-(1452627-2*#100)/14454sp\relax}%
%
-% Mathematics ("both in and cm", added at release 0.9)
-% ===========
+% "both in and cm"
+% ================
+%
+% Mathematics
+% -----------
%
% Let a and b be two non-negative integers such that U = floor(a 7227/100) =
% floor(b 7227/254). It can be proven that a=50k, b=127k for some integer k.
@@ -548,7 +549,7 @@
% avoiding overflow.
%
% Implementation
-% ==============
+% --------------
%
% Regarding the output in pt or sp, we seem to need floor(k 7227/2).
% The computation of floor(k 7227/2) as <(7227 k - 1)/2> would require to
@@ -566,43 +567,33 @@
% else if U > T, replace it by U - 3614. This is alternative road to the maximal
% floor(k 7227/2) at most equal to T.
%
-% There is some slight under-efficiency to share macros across the 3 end targets
-% as I added one layer of parentheses.
\def\texdimenbothincm#1{\expandafter\texdimenstrippt\the\dimexpr
- \expandafter\texdimenboth_a\the\numexpr\dimexpr#1;127);}%
+ \expandafter\texdimenboth_a
+ \the\numexpr\dimexpr#1\relax\relax-3612)/7227)*127sp\relax}%
\def\texdimenbothcmin#1{\expandafter\texdimenstrippt\the\dimexpr
- \expandafter\texdimenboth_a\the\numexpr\dimexpr#1;50);}%
+ \expandafter\texdimenboth_a
+ \the\numexpr\dimexpr#1\relax\relax-3612)/7227)*50sp\relax}%
+\def\texdimenboth_a#1{\texdimengobtilminus#1\texdimenboth_neg-\numexpr((2*#1}%
+\def\texdimenboth_neg-\numexpr((2*-{-\numexpr((2*}%
+%
+\def\texdimenbothincmsp#1{\number
+ \expandafter\texdimenbothsp_a\the\numexpr\dimexpr#1\relax\relax
+ -3612)/7227)*7227+1)/2-1\relax}%
\def\texdimenbothincmpt#1{\expandafter\texdimenstrippt\the\dimexpr
- \expandafter\texdimenboth_a\the\numexpr\dimexpr#1;7227+1)/2-1;}%
-\let\texdimenbothcminpt\texdimenbothincmpt
-\def\texdimenboth_a#1{\if-#1\texdimenboth_neg\fi\texdimenboth_b#1}%
-% The opening parenthesis ( is closed in #2, it was added to share "pt" output
-% with the two others
-\def\texdimenboth_b#1;#2;{\numexpr(((2*#1-3612)/7227)*#2sp\relax}%
-% negative branch. This is expanded in a \dimexpr so we can insert the -
-% in front of the \numexpr.
-% #1 is \fi here and #2 is \texdimenboth_b
-\def\texdimenboth_neg#1#2-#3;#4;{#1-\numexpr(((2*#3-3612)/7227)*#4sp\relax}%
-%
-% \texdimenbothincmsp is done separately as I found no easy way to share
-% its macros with the others; alternative would have been to make it the
-% core, and derive the others from it, (\texdimencm{\texdimenbothincmsp{...}sp})
-% but then they would be less efficient than their current versions.
-% (it is a bit ironical to worry about not creating too many macros
-% in such a small package, by the way)
-\def\texdimenbothincmsp#1{\the\numexpr\expandafter\texdimenbothsp_a\the\numexpr\dimexpr#1;}%
-\def\texdimenbothsp_a#1{\if-#1\texdimenbothsp_neg\fi\texdimenbothsp_b#1}%
-\def\texdimenbothsp_b#1;{(((2*#1-3612)/7227)*7227+1)/2-1\relax}%
-% #1 is \fi
-% we need to regrab here or to add a \numexpr..\relax layer to
-% \texdimenbothsp_b (parentheses could do but using 0-(...) syntax)
-% finally doing the job of \texdimenbothsp_b directly
-\def\texdimenbothsp_neg#1#2-#3;{#1-\numexpr(((2*#3-3612)/7227)*7227+1)/2-1\relax\relax}%
+ \expandafter\texdimenbothsp_a\the\numexpr\dimexpr#1\relax\relax
+ -3612)/7227)*7227+1)/2-1sp\relax}%
+\def\texdimenbothsp_a#1{\texdimengobtilminus#1\texdimenbothsp_neg-\numexpr(((2*#1}%
+\def\texdimenbothsp_neg-\numexpr(((2*-{-\numexpr(((2*}%
%
+\let\texdimenbothcminpt\texdimenbothincmpt
\let\texdimenbothcminsp\texdimenbothincmsp
%
-% Mathematics and Algorithm ("both mm and bp", added at release 1.0)
-% =========================
+% "both mm and bp"
+% ================
+%
+% Mathematics and Algorithm
+% -------------------------
+%
% We start from a dimension expressed in sp unit, "T sp". Assume T positive.
% We know how to get largest "X sp <= T sp" which is exactly expressible
% in mm unit
@@ -640,7 +631,6 @@
% via an already positioned \dimexpr waiting to output final result.
\def\texdimenbothbpmm#1{\expandafter\texdimenstrippt\the\dimexpr
\expandafter\texdimenbothbpmm_fork\the\numexpr\dimexpr#1;}%
-% the \texdimenzerominusfork is defined in the \texdimenwithunit section
\def\texdimenbothbpmm_fork#1{\texdimenzerominusfork
#1-\texdimenbothbpmm_zero
0#1\texdimenbothbpmm_neg
@@ -693,9 +683,8 @@
% now the lazy way for \texdimenbothmmbp
\def\texdimenbothmmbp#1{\expandafter\texdimenstrippt\the\dimexpr
\expandafter\texdimenbothmmbp_a\the\numexpr\dimexpr\texdimenbothbpmm{#1}mm;}%
-% or remove the + and do \if-#1-\else+\fi1 ?
% If zero at this stage, we will correctly get 0.0 in the end
-\def\texdimenbothmmbp_a#1#2;{\numexpr(2*#1#2+\if-#1-\fi1)*400/803sp\relax}%
+\def\texdimenbothmmbp_a#1#2;{\numexpr(2*#1#2+\texdimengobtilminus#1-1)*400/803sp\relax}%
% \texdimenbothbpmmpt and its alias \texdimenbothmmbppt
\def\texdimenbothbpmmpt#1{\texdimenpt{\texdimenbothbpmm{#1}mm}}%
\let\texdimenbothmmbppt\texdimenbothbpmmpt
@@ -703,12 +692,15 @@
\def\texdimenbothbpmmsp#1{\the\numexpr\dimexpr\texdimenbothbpmm{#1}mm\relax\relax}%
\let\texdimenbothmmbpsp\texdimenbothbpmmsp
%
-% Mathematics (\texdimenwithunit, added at release 0.99, modified at 1.0)
-% ===========
+% \texdimenwithunit
+% =================
+%
+% Mathematics
+% -----------
+%
+% The ex and em units are handled by TeX as if multiplying by a
+% conversion factor f/65536 (here f sp = 1ex resp. = 1em).
%
-% As explained in the README.md, the ex and em units are
-% handled by TeX as if multiplying by a conversion factor f/65536
-% (here f sp = 1ex resp. = 1em).
% In particular, for any decimal D, input "D em" is handled the exact
% same way as input "D\dimexpr 1em\relax"; this is not
% the case for the core units except for pt and pc (and sp), whose
@@ -732,7 +724,7 @@
% If f/65536<1, all dimensions Tsp are attainable as D uu. Indeed
% D uu is parsed by TeX via N=round(D*65536), then T=trunc(N*phi),
% with phi=f/65536. Starting from T we need to find an N such that
-% T/phi <= N< (T+1)/phi.
+% T/phi <= N< (T+1)/phi.
%
% This is equivalent to ceil(T/phi)<= N < ceil((T+1)/phi)
%
@@ -749,7 +741,7 @@
% It is not obvious to compute this ceil(T/phi) without overflow.
%
% Implementation
-% ==============
+% --------------
%
% \texdimenwithunit{dim1}{dim2}
%
@@ -769,61 +761,98 @@
% or f<=65536.
% We will also need to check the sign of T (dim1=T sp).
% f>65536: we compute round((2T+1)*32768/f)
-% f=65536: merged with f<65536 branch
-% f<65536: we compute ceil(T*65536/f)
+% f=65536: merged with f<65536 branch (as it works and avoids checking for it)
+% f<65536: 0.99 release used the round((2T+1)*32768/f) formula
+% (it is funny that it works for all f except for f=65536)
%
-% rationale: round((2T+1)*32768/f) which was used at 0.99
-% would be ok [if f<65536 not f=65536 ! cf #3, #4]
-% also for this branch
-%
-% BUT it diverges noticeably from naive expectation
-% dim1/dim2 "=" T*65536/f the more so when f is small.
+% But the output then diverges noticeably from mathematical
+% dim1/dim2 "=" T*65536/f, the more so the smaller the dim2.
% See issue #16 and also the discussion at #13.
%
-% As was explained in comments to issue #2 which asked for a
-% \texdimenwithunit the ceil(T*65536/f) is the smallest
-% allowable choice
+% 1.0 release thus opted for the ceil(T*65536/f) formula, as it is the
+% smallest allowable choice, hence the closest to naive dim1/dim2.
%
% To avoid arithmetic overflow issues we first do the euclidean
-% division T = k f + r, 0<= r < f
+% division T = k f + r, 0<= r < f, 0<= k
+%
+% The final result in "sp" unit would be k*65536 + C with
+% C = ceil(r * 65536/f).
%
-% The final result in sp units will be k*65536 + ceil(r * 65536/f)
-% We don't do this k*65536 explicitly as it may overflow
-% but output the decimal k + E where E is the conversion
-% to a decimal 0.ddddd or 1.0 of "ceil(r * 65536/f) sp"
-% (which is at most 65536sp=1pt so E is at most 1.0).
+% We don't do this k*65536 explicitly as it may overflow and is
+% anyhow unneeded: the output will be the integer k concatenated with
+% the decimal E given by TeX from \the\dimexpr C sp, i.e. such that
+% E pt = C sp, with C = ceil(r*65536/f).
+%
+% As r is at most f-1, r*65536/f is at most 65536-65536/f, and as
+% 65536>=f (we use this branch also for f=65536), C<=65535. Hence
+% E is never 1.0 but always "0.<some digits>"
%
% To compute the Euclidean quotient k in \numexpr we use there
-% (2T-f)/(2f) i.e. round((2T-f)/2f) = trunc(T/f)
-% as we are careful to never have T=0 inthere...
+% <(2T-f)/(2f)> i.e. round((2T-f)/2f) = trunc(T/f)
+% as we are careful to never have T=0 in-there...
%
% Computing C = ceil(r * 65536/f) in \numexpr is the delicate
-% part, as r can be as large as f-1 hence 65535 and r*65536 would
-% overflow. We could compute R=round(r*65536/f) ("scaling operation")
-% then C=R+1 if R*f-65536*r<0, else C=R.
+% part, as r can be as large as f-1 hence 65535 and 65535*65536 would
+% overflow. Let's try anyhow to see how to compute ceil() with round():
+%
+% C = 65536 - floor(65536 * (1 - r/f))
+% = 65536 - round(65536*(f-r)/f - 0.5) (as r<f so no "round(-0.5)=-1")
+% = 65536 - <(2*65536*(f-r) - f)/(2f)>
+%
+% Here the problem is with small r, and large f, and naive implementation
+% of this formula can overflow...
+% Let's thus retreat to eTeX scaling operation <r*65536/f> as it
+% operates with temporary double precision.
+%
+% R=round(r*65536/f)=<r*65536/f> is either C-1 or C
+% Let x = mathematical exact r*65536/f:
+% - if R < x, C=R+1.
+% - if R >= x, C=R.
+%
+% C=ceil(r*65536/f) is the smallest integer such that
+% trunc(C*f/65536)>=r, or more precisely (as f<=65536) the
+% smallest integer with trunc(C*f/65536)=r. So trunc(R*f/65536)
+% will be either r (then R=C), or r-1, then R=C-1.
+%
+% Method from release 1.0: let's TeX compute P=trunc(R*f/65536) itself!
+% Via P sp = E <f sp> where E is a decimal such that E pt = R sp.
+% So
+% - if P>=r (it is then equal to r in fact) then C=R
+% - if P<r (it is then equal to r-1), then C=R+1.
+%
+% New method: overflow-free pure \numexpr way to get the sign of R-x.
+%
+% Write R=4*S+t, with say S=<R/4>=round(R/4), so t=-2,-1,0,+1.
+%
+% Then R*f-65536*r = 4*(S*f-16384*r)+t*f
%
-% The problem is then: how to get the sign of R*f-65536*r without
-% overflow? I considered various ways.
+% We know that R<=C<65536, so <R/4> <= 16384 and 16384*f
+% is at worst 2**(14+16)=\maxdimen+1 but we will be in \numexpr,
+% so no overflow!
+% And r<f<=65536 so also 16384*r can not overflow.
+% As |R - r*65536/f|<= 0.5, then |R*f-65536*r|<= f/2, so
+% 4*|S*f-16384*r| <= 2.5*f is very far from overflow risk
%
-% But in the end, opted for simply this:
-% - get R=round(r*65536/f) as \the\numexpr r*65536/f ("scaling" no overflow)
-% - hence get E pt=\the\dimexpr R sp
-% - let TeX compute E<f sp>: if it turns out < r sp,
-% then C=R+1,
-% else C=R. Done.
+% T>0, 0<f<=65536
+% k = <(2*T-f)/(2*f)>
+% r = T - k*f
+% R=<r*65536/f>
+% S=<R/4>
+% t=R-4*S
+%
+% IF: 4*(S*f-16384*r)+t*f < 0 THEN C=R+1 ELSE C=R.
+%
+% Ept=\the\dimexpr Csp, E=0.d...d
+%
+% End expansion with the contatenation k.d...d
%
\def\texdimenwithunit#1#2{\expandafter\texdimenwithunit_i
% no premultiplication of dim1 by 2 as was done for technical
% reasons when dim2<1pt branch used round((2T+1)*32768/f)
- \the\numexpr\dimexpr#2\expandafter;\the\numexpr\dimexpr#1;}%
-%
-% so tempted to do \input xintkernel.sty to have some utilities...
-% not even a \@gobble in Plain...
-\let\texdimenorthat\texdimenfirstofone
-\def\texdimendothis#1#2\texdimenorthat#3{\fi#1}%
-\def\texdimengobtominus#1-{}%
+ \the\numexpr\dimexpr#2\expandafter;\the\numexpr\dimexpr#1;%
+}%
\def\texdimenwithunit_i#1{%
- \texdimengobtominus#1\texdimenwithunit_switchsigns-%
+ \texdimengobtilminus#1\texdimenwithunit_switchsigns-%
\texdimenwithunit_j#1%
}%
\def\texdimenwithunit_switchsigns-\texdimenwithunit_j-#1;#2%
@@ -831,7 +860,7 @@
% due to \texdimenwithunit_Bneg we can not simply prefix dim1
% with -, as -0 is bad there. So let's check also if #2 is 0
\texdimenzerominusfork
- #2-\texdimenwithunit_Bzero % abusive double usage
+ #2-\texdimenwithunit_Bzero % also used in \texdimenwithunit_B
0#2\texdimenwithunit_j % abusive shortcut
0-{\texdimenwithunit_ic#2}%
\krof
@@ -839,19 +868,14 @@
}%
\def\texdimenwithunit_ic#1#2;{\texdimenwithunit_j#2;-#1}%
\def\texdimenwithunit_j#1;#2{%
- % \ifnum#1=\p@\texdimendothis\texdimenwithunit_p@\fi
- \ifnum#1>\p@\texdimendothis\texdimenwithunit_A\fi
- \texdimenorthat\texdimenwithunit_B#2#1;%
+ \ifnum#1>\p@\texdimenwithunit_A\fi
+ \texdimenwithunit_B#2#1;%
}%
-% not needed, as the "ceil" branch is fine to use for f = 65536
-% \def\texdimenwithunit_p@#1#2;#3;{%
-% \expandafter\texdimenstrippt\the\dimexpr#1#3sp/2\relax
-% }%
-% unit>1pt, handle this as for bp. Attention it would be wrong for
-% unit=1pt!
-\def\texdimenwithunit_A#1#2;#3;{%
+% unit>1pt, handle this as for bp.
+% Attention it would be wrong for unit=1pt!
+\def\texdimenwithunit_A\fi\texdimenwithunit_B#1#2;#3;{\fi
\expandafter\texdimenstrippt
- \the\dimexpr\numexpr(2*#1#3+\if-#1-\fi1)*32768/#2sp\relax
+ \the\dimexpr\numexpr(2*#1#3+\texdimengobtilminus#1-1)*32768/#2sp\relax
% - fine if dim1>0, <0, or =0
% - with *\p@ better but an early doubled dim2 would complicate 1pt
% test and not sure if doing \p@/(2*#2) here advantageous
@@ -862,47 +886,40 @@
% will even be at least 2 if f<65536).
% The dim1=0 case must get filtered out due to way of calculating the
% "ceil" in \numexpr
-\def\texdimenzerominusfork #10-#2#3\krof {#2}%
\def\texdimenwithunit_B#1{\texdimenzerominusfork
#1-\texdimenwithunit_Bzero
0#1\texdimenwithunit_Bneg
- 0-\texdimenwithunit_Ba
+ 0-\texdimenwithunit_Ba
\krof#1}%
+\def\texdimenwithunit_Bzero#1;#2;{0.0}%
\def\texdimenwithunit_Ba#1#2;#3;{%
- % no overflow possible from 2*#1#3=2*dim1
- \expandafter\texdimenwithunit_Bb\the\numexpr(2*#1#3-#2)/(2*#2);#1#3;#2;%
-}%
-% now k;T;f;. Get the remainder r=T-k*f
+ % no overflow possible from 2*#1#3 in \numexpr
+ \expanded{\expandafter\texdimenwithunit_Bb
+ \the\numexpr(2*#1#3-#2)/(2*#2);#1#3;#2;}%
+}%
+% I could have inserted \expanded\bgroup in \texdimenwithunit_B
+% but then needed to modify _Bzero (used also by \texdimenwithunit_switchsigns)
+% so easiest is to simply defined Bneg explicitly here rather than
+% insisting on deriving it from _Ba
+\def\texdimenwithunit_Bneg-#1;#2;{%
+ \expanded{-\expandafter\texdimenwithunit_Bb
+ \the\numexpr(2*#2-#1)/(2*#1);#2;#1;}%
+}%
+% now k;T;f;. Get the remainder r=T-k*f, and abandon k in the token stream.
+% the earlier \expanded maintains f-expandability
\def\texdimenwithunit_Bb#1;#2;#3;{%
- \expandafter\texdimenwithunit_Bc\the\numexpr#2-#1*#3;#1;#3;%
+ #1\expandafter\texdimenwithunit_Bc\the\numexpr#2-#1*#3;#3;%
}%
-% now r;k;f;. We can start \the\numexpr k+ ....
-% and there we will need to get R=round(r*65536/f), Ept=Rsp,
-% check if E"f sp"<"r sp", if yes replace R by R+1 else keep E etc.
-\def\texdimenwithunit_Bc#1;#2;#3;{%
-% \the\numexpr k+0.ddddd is handy because it can well be actually
-% \the\numexpr k+1.0, now that we use ceil approach in this branch
- \the\numexpr#2+\expandafter\texdimenwithunit_Bd
- \the\numexpr #1*\p@/#3;#1;#3;%
+% now r;f;. Get R=<r*65536/f>
+\def\texdimenwithunit_Bc#1;#2;{%
+ \expandafter\texdimenwithunit_Bd\the\numexpr #1*\p@/#2;#1;#2;%
}%
-% R;r;f;
-\def\texdimenwithunit_Bd#1;{%
- \expandafter\texdimenwithunit_Be\the\dimexpr#1sp;#1;%
+% R;r;f; Is 4*(S*f-16384*r)+t*f < 0 ? with S=<R/4>, t=R-4S
+\def\texdimenwithunit_Bd#1;#2;#3;{%
+ \expandafter\texdimenwithunitstripzeroandpt
+ \the\dimexpr\numexpr#1%
+ \ifnum\numexpr 4*((#1/4)*#3-16384*#2)<\numexpr(4*(#1/4)-#1)*#3\relax
+ +1\fi sp\relax
}%
-% Ept;R;r;f;
-% #1=0.ddd... or 1.0 but has no end marker hence the
-% \texdimenfirstofone{#1} as in \texdimendown_d and \texdimenup_d
-{\catcode`P 12\catcode`T 12
-\lowercase{\gdef\texdimenwithunit_Be#1PT};#2;#3;#4;{%
- \ifdim#1\dimexpr#4sp<#3sp \texdimenwithunit_Bf{#2}\fi
- \texdimenfirstofone{#1}%
- }%
-}%
-% #2 is \fi. Add a dimen storage \onesp for 1sp?
-\def\texdimenwithunit_Bf#1#2\texdimenfirstofone#3{#2%
- \expandafter\texdimenstrippt\the\dimexpr#1sp+1sp\relax
-}%
-% Here definitely not caring about f-expandability. Or efficiency.
-\def\texdimenwithunit_Bneg-{-\texdimenwithunit_Ba{}}%
-\def\texdimenwithunit_Bzero#1;#2;{0.0}%
+{\catcode`P12\catcode`T12\lowercase{\gdef\texdimenwithunitstripzeroandpt0#1PT}{#1}}%
\texdimensendinput