diff options
author | Karl Berry <karl@freefriends.org> | 2021-07-21 20:46:23 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2021-07-21 20:46:23 +0000 |
commit | 0c500e6d48db042c1d7c0dfbd8b28c31d512a764 (patch) | |
tree | e240863f8ebed75011efbe8c8e74204fdd5e3590 /Master/texmf-dist/tex/generic/texdimens | |
parent | b03788d15a8e96a8631d99b12936f40b6341ddb2 (diff) |
texdimens (21jul21)
git-svn-id: svn://tug.org/texlive/trunk@60006 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/tex/generic/texdimens')
-rw-r--r-- | Master/texmf-dist/tex/generic/texdimens/texdimens.sty | 2 | ||||
-rw-r--r-- | Master/texmf-dist/tex/generic/texdimens/texdimens.tex | 308 |
2 files changed, 212 insertions, 98 deletions
diff --git a/Master/texmf-dist/tex/generic/texdimens/texdimens.sty b/Master/texmf-dist/tex/generic/texdimens/texdimens.sty index dbf39c72f80..8467e69a6f0 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/07/15 v0.9delta conversion of TeX dimensions to decimals (JFB)] +\ProvidesPackage{texdimens}[2021/07/21 v0.9 conversion of TeX dimensions to decimals (JFB)] \@@input texdimens.tex\relax \endinput
\ No newline at end of file diff --git a/Master/texmf-dist/tex/generic/texdimens/texdimens.tex b/Master/texmf-dist/tex/generic/texdimens/texdimens.tex index 189caca95d0..8103bef1cd0 100644 --- a/Master/texmf-dist/tex/generic/texdimens/texdimens.tex +++ b/Master/texmf-dist/tex/generic/texdimens/texdimens.tex @@ -1,29 +1,70 @@ % 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/07/15 v0.9delta +% 2021/07/21 v0.9 +% All macros from 0.9delta release have changed names: \texdimen prefix +% has replaced \texdimin. \edef\texdimensendinput{\endlinechar\the\endlinechar\catcode`\noexpand _=\the\catcode`\_\relax\noexpand\endinput}% \endlinechar13\relax% \catcode`\_=11 % -% Mathematics +% Mathematics ("down" and "up" macros) % =========== % -% Is T sp attainable from unit "uu"?. Here we suppose T>0. -% phi>1, psi=1/phi, psi<1 -% U(N,phi)=trunc(N phi) is strictly increasing +% Is T sp attainable from unit "uu"?. +% If not, what is largest dimension < Tsp which is attainable? +% Here we suppose T>0. +% +% phi>1, psi=1/phi, psi<1. +% +% U(N,phi)=trunc(N phi) is the strictly increasing sequence, +% indexed by non-negative integers, of attainable dimensions. +% (in sp unit) +% % U(N)<= T < U(N+1) iff N = ceil((T+1)psi) - 1 % U(M)< T <= U(M+1) iff M = ceil(T psi) - 1 -% Either: +% +% Stumbling block +% --------------- +% +% The stumbling block is that computing "ceil((T+1)psi) - 1" without +% overflow is not obvious: yes \numexpr/\dimexpr allow so-called +% "scaling operations" but only in the "rounding up" variant. +% +% If we attempt computing the ceil(x) function via round(x+0.5), +% for example with psi=100/7227 which corresponds to the unit "in", +% this necessitates evaluating: +% +% round((((T+1)*200)+7227)/14454) +% +% But as far as I can tell currently, for this we need to be able +% to evaluate without overflow (T+1)*200+7227 and this limits to +% T's which are (roughly) such that 100 T is less than \maxdimen. +% +% A work-around +% ------------- +% +% The rest of the discussion is about an algorithm providing an +% alternative route to N, using \numexpr/\dimexpr/TeX facilities, +% and working with (almost, as we will see) the full range of allowed +% T's, 0 < T <= \maxdimen. (that the algorithm works for T=0 is to be +% checked manually after the main discussion). +% +% Let's return to the U(N)<= T < U(N+1) and U(M)< T <= U(M+1) equations. +% +% Either (recall in all of this T > 0): +% % case1: M = N, i.e. T is not attainable, M=N < T psi < (T+1) psi <= N+1 -% case2: M = N - 1, i.e. T is attained, T psi <= N < (T+1) psi, T = floor(N phi) +% case2: M = N - 1, i.e. T is attained, T psi <= N < (T+1) psi, T = trunc(N phi) % -% Let X = round(T psi). And let Y = trunc(X phi). +% Let X = round(T psi). And let Y = trunc(X phi). We will explain later +% how X and Y can be computed using \numexpr/\dimexpr/TeX. % % case1: X can be N or N+1. It will be N+1 iff Y > T. % case2: X can be N or N-1. It will be N iff trunc((X+1)phi)>T. % -% This is not convenient: if Y <= T it might still be that we are in case 2 -% and we must check then if trunc((X+1) phi) > T or not. +% This is not convenient: if Y < T it could be that we are in case 2 +% but to decide we must check if trunc((X+1) phi) = T or not, so +% this means a second computation. % % If psi < 0.5 % ------------ @@ -37,11 +78,11 @@ % a) compute X = round(T psi) % b) compute Y = trunc(X phi) and test if Y > T. If true, we % were in case 1, replace X by X - 1, else we were either -% in case 1 or case 2, but we can leave X as is. +% in case 1 or case 2, and we leave X as it is. % We have thus found N. % % The operation Y = trunc(X phi) can be achieved this way: -% i) use \the\dimexpr to convert X sp into D pt, +% i) use \the\dimexpr to convert X sp into D pt, % ii) use \the\numexpr\dimexpr to convert "D uu" into sp. % These steps give Y. % @@ -50,14 +91,14 @@ % % The computations of X and Y can be done independently of sign of T. % But the final test has to be changed to Y < T if T < 0 and then -% one must replace X by X+1. So we must filter sign. +% one must replace X by X+1. So we must filter out the sign of the input. % -% If the goal is only to find a decimal D such that "D uu" is +% If the goal is only to find a decimal D such that "D uu" is % exactly T sp in the case this is possible, then things are simpler % because from X = round(T psi) we get D such as X sp is same as D pt % and "D uu" will work. % We don't have to take sign into account for this computation. -% But if T sp was not atteignable we don't know if this X will give +% But if T sp was not attainable we don't know if this X will give % a D such that D uu < T sp or D uu > T sp. % % If psi > 0.5 @@ -65,7 +106,7 @@ % % For example unit "bp" has phi=803/800. % -% It is then not true that if T sp is atteignable, the X = round(T psi) +% It is then not true that if T sp is attainable, the X = round(T psi) % will always work. % % But it is true that R = round((T + 0.5) psi) will always work. @@ -76,7 +117,7 @@ % % So this gives an approach to find a D such that "D uu" is exactly % T sp when this is possible. -% +% % If Tsp (positive) is not attainable, this R however can produce % either N or N+1. % @@ -86,42 +127,38 @@ % It is slightly less costly to compute X = round(T psi) than % R = round((T + 0.5) psi), % but if we then realize that trunc(X phi) < T we do not yet know -% if trunc((X+1) phi) = T or is > T. +% if trunc((X+1) phi) = T or is > T. So we proceed via R, not X, +% to not have to make a second computation if a dimension comparison +% test goes awry. % % To recapitulate: we have our algorithm for all units to find out -% maximal dimension exactly atteignable in "uu" unit and at most equal +% maximal dimension exactly attainable in "uu" unit and at most equal % to (positive) T sp. % % Unfortunately the check that Y (in case psi < 0.5) or Z (in case psi > -% 0.5) may trigger a Dimension too large error if T sp was near -% non-atteignable \maxdimen. -% -% For additional envisioned "safe versions" we would tabulate first per unit -% what is the integer Rmax such that trunc(Rmax phi) <= \maxdimen. Then -% the "safe" versions would have an extra check of X or R before -% proceeding further. But the "up macros" supposed to give the next -% dimension above Tsp and exactly atteignable in "uu" unit, if compliant -% to their description can not avoid "Dimension too large" for inputs -% close to non-attainable \maxdimen. -% -% After having written the macros we will tabulate what is for each unit -% the maximal attainable dimension. -% -% About the macros such as \texdiminbp whose constraints are: -% - give a decimal D such that "Duu" = "T sp" for TeX if possible -% - else give nearest from below or above without knowing -% which one, -% -% there was some hesitation about whether or not using the simpler -% round(T psi) approach for units > 2pt and the \texdimin<uu> macros. -% Testing showed that this did not change the output for \maxdimen -% with the units "nc" and "in": still N+1 is returned... -% -% As it has great -% advantage to not have to check the sign of the input, the -% "simpler" approach was chosen for those units to which it -% applies, i.e. the units uu > 2pt (phi>2, psi<1/2), i.e. -% all units except bp, nd and dd. +% 0.5) verifies or not Y > T may trigger a Dimension too large error if +% T sp was near non-attainable \maxdimen. It turns out this sad +% situation happens only for the units `dd`, `nc`, and `in`, and T sp +% very close to \maxdimen (like for all units apart from `pt`, `bp`, +% `nd`, the \maxdimen is not attainable, and by bad luck for `dd`, `nc`, +% and `in`, the X will correspond to a decimal D such that Duu>\maxdimen +% is the nearest virtually attaible dimensions from above not from +% below; see the README.md for the tabulation of the maximal usable inputs). +% +% Regarding the \texdimen<uu> macros, and units with phi > 2, I +% hesitated using either the round((T+0.5)psi) or round(T psi), but for +% Tsp = \maxdimen, both formulas turned out to give the same result for +% all such units, so I chose for these \texdimen<uu> macros and the +% units with phi>2 to use the simpler round(T psi) which does not need +% to check the sign of T. +% +% For the "up" and "down" macros, we again use the round(T psi), but do +% have to check the sign anyhow. We could also have used the +% round((T+0.5)psi) which requires a sign check too, but it costs a bit +% more. It would have allowed though to share the same codebase for all +% units, here we have to prepare some slightly different shared macros +% for the first batch bp, nd, dd and the second batch mm, pc, nc, cc, +% cm, in. % % Implementation % ============== @@ -171,87 +208,164 @@ % % pt % -\def\texdiminpt#1{\expandafter\texdimenstrippt\the\dimexpr#1\relax}% +\def\texdimenpt#1{\expandafter\texdimenstrippt\the\dimexpr#1\relax}% % % bp 7227/7200 = 803/800 % -\def\texdiminbp#1{\expandafter\texdiminbp_\the\numexpr\dimexpr#1;}% -\def\texdiminbp_#1#2;{% +\def\texdimenbp#1{\expandafter\texdimenbp_\the\numexpr\dimexpr#1;}% +\def\texdimenbp_#1#2;{% \expandafter\texdimenstrippt\the\dimexpr\numexpr(2*#1#2+\if-#1-\fi1)*400/803sp\relax }% -% \texdiminbpdown: maximal dim exactly expressible in bp and at most equal to input -\def\texdiminbpdown#1{\expandafter\texdimendown_A\the\numexpr\dimexpr#1;*400/803;bp;}% -% \texdiminbpup: minimal dim exactly expressible in bp and at least equal to input -\def\texdiminbpup#1{\expandafter\texdimenup_A\the\numexpr\dimexpr#1;*400/803;bp;}% +% \texdimenbpdown: maximal dim exactly expressible in bp and at most equal to input +\def\texdimenbpdown#1{\expandafter\texdimendown_A\the\numexpr\dimexpr#1;*400/803;bp;}% +% \texdimenbpup: minimal dim exactly expressible in bp and at least equal to input +\def\texdimenbpup#1{\expandafter\texdimenup_A\the\numexpr\dimexpr#1;*400/803;bp;}% % % nd 685/642 % -\def\texdiminnd#1{\expandafter\texdiminnd_\the\numexpr\dimexpr#1;}% -\def\texdiminnd_#1#2;{% +\def\texdimennd#1{\expandafter\texdimennd_\the\numexpr\dimexpr#1;}% +\def\texdimennd_#1#2;{% \expandafter\texdimenstrippt\the\dimexpr\numexpr(2*#1#2+\if-#1-\fi1)*321/685sp\relax }% -% \texdiminnddown: maximal dim exactly expressible in nd and at most equal to input -\def\texdiminnddown#1{\expandafter\texdimendown_A\the\numexpr\dimexpr#1;*321/685;nd;}% -% \texdiminndup: minimal dim exactly expressible in nd and at least equal to input -\def\texdiminndup#1{\expandafter\texdimenup_A\the\numexpr\dimexpr#1;*321/685;nd;}% +% \texdimennddown: maximal dim exactly expressible in nd and at most equal to input +\def\texdimennddown#1{\expandafter\texdimendown_A\the\numexpr\dimexpr#1;*321/685;nd;}% +% \texdimenndup: minimal dim exactly expressible in nd and at least equal to input +\def\texdimenndup#1{\expandafter\texdimenup_A\the\numexpr\dimexpr#1;*321/685;nd;}% % % dd 1238/1157 % -\def\texdimindd#1{\expandafter\texdimindd_\the\numexpr\dimexpr#1;}% -\def\texdimindd_#1#2;{% +\def\texdimendd#1{\expandafter\texdimendd_\the\numexpr\dimexpr#1;}% +\def\texdimendd_#1#2;{% \expandafter\texdimenstrippt\the\dimexpr\numexpr(2*#1#2+\if-#1-\fi1)*1157/2476sp\relax }% -% \texdimindddown: maximal dim exactly expressible in dd and at most equal to input -\def\texdimindddown#1{\expandafter\texdimendown_A\the\numexpr\dimexpr#1;*1157/2476;dd;}% -% \texdiminddup: minimal dim exactly expressible in dd and at least equal to input -\def\texdiminddup#1{\expandafter\texdimenup_A\the\numexpr\dimexpr#1;*1157/2476;dd;}% +% \texdimendddown: maximal dim exactly expressible in dd and at most equal to input +\def\texdimendddown#1{\expandafter\texdimendown_A\the\numexpr\dimexpr#1;*1157/2476;dd;}% +% \texdimenddup: minimal dim exactly expressible in dd and at least equal to input +\def\texdimenddup#1{\expandafter\texdimenup_A\the\numexpr\dimexpr#1;*1157/2476;dd;}% % % mm 7227/2540 phi now >2, use from here on the simpler approach % -\def\texdiminmm#1{\expandafter\texdimenstrippt\the\dimexpr(#1)*2540/7227\relax}% -% \texdiminmmdown: maximal dim exactly expressible in mm and at most equal to input -\def\texdiminmmdown#1{\expandafter\texdimendown_a\the\numexpr\dimexpr#1;*2540/7227;mm;}% -% \texdiminmmup: minimal dim exactly expressible in mm and at least equal to input -\def\texdiminmmup#1{\expandafter\texdimenup_a\the\numexpr\dimexpr#1;*2540/7227;mm;}% +\def\texdimenmm#1{\expandafter\texdimenstrippt\the\dimexpr(#1)*2540/7227\relax}% +% \texdimenmmdown: maximal dim exactly expressible in mm and at most equal to input +\def\texdimenmmdown#1{\expandafter\texdimendown_a\the\numexpr\dimexpr#1;*2540/7227;mm;}% +% \texdimenmmup: minimal dim exactly expressible in mm and at least equal to input +\def\texdimenmmup#1{\expandafter\texdimenup_a\the\numexpr\dimexpr#1;*2540/7227;mm;}% % % pc 12/1 % -\def\texdiminpc#1{\expandafter\texdimenstrippt\the\dimexpr(#1)/12\relax}% -% \texdiminpcdown: maximal dim exactly expressible in pc and at most equal to input -\def\texdiminpcdown#1{\expandafter\texdimendown_a\the\numexpr\dimexpr#1;/12;pc;}% -% \texdiminpcup: minimal dim exactly expressible in pc and at least equal to input -\def\texdiminpcup#1{\expandafter\texdimenup_a\the\numexpr\dimexpr#1;/12;pc;}% +\def\texdimenpc#1{\expandafter\texdimenstrippt\the\dimexpr(#1)/12\relax}% +% \texdimenpcdown: maximal dim exactly expressible in pc and at most equal to input +\def\texdimenpcdown#1{\expandafter\texdimendown_a\the\numexpr\dimexpr#1;/12;pc;}% +% \texdimenpcup: minimal dim exactly expressible in pc and at least equal to input +\def\texdimenpcup#1{\expandafter\texdimenup_a\the\numexpr\dimexpr#1;/12;pc;}% % % nc 1370/107 % -\def\texdiminnc#1{\expandafter\texdimenstrippt\the\dimexpr(#1)*107/1370\relax}% -% \texdiminncdown: maximal dim exactly expressible in nc and at most equal to input -\def\texdiminncdown#1{\expandafter\texdimendown_a\the\numexpr\dimexpr#1;*107/1370;nc;}% -% \texdiminncup: minimal dim exactly expressible in nc and at least equal to input -\def\texdiminncup#1{\expandafter\texdimenup_a\the\numexpr\dimexpr#1;*107/1370;nc;}% +\def\texdimennc#1{\expandafter\texdimenstrippt\the\dimexpr(#1)*107/1370\relax}% +% \texdimenncdown: maximal dim exactly expressible in nc and at most equal to input +\def\texdimenncdown#1{\expandafter\texdimendown_a\the\numexpr\dimexpr#1;*107/1370;nc;}% +% \texdimenncup: minimal dim exactly expressible in nc and at least equal to input +\def\texdimenncup#1{\expandafter\texdimenup_a\the\numexpr\dimexpr#1;*107/1370;nc;}% % % cc 14856/1157 % -\def\texdimincc#1{\expandafter\texdimenstrippt\the\dimexpr(#1)*1157/14856\relax}% -% \texdiminccdown: maximal dim exactly expressible in cc and at most equal to input -\def\texdiminccdown#1{\expandafter\texdimendown_a\the\numexpr\dimexpr#1;*1157/14856;cc;}% -% \texdiminccup: minimal dim exactly expressible in cc and at least equal to input -\def\texdiminccup#1{\expandafter\texdimenup_a\the\numexpr\dimexpr#1;*1157/14856;cc;}% +\def\texdimencc#1{\expandafter\texdimenstrippt\the\dimexpr(#1)*1157/14856\relax}% +% \texdimenccdown: maximal dim exactly expressible in cc and at most equal to input +\def\texdimenccdown#1{\expandafter\texdimendown_a\the\numexpr\dimexpr#1;*1157/14856;cc;}% +% \texdimenccup: minimal dim exactly expressible in cc and at least equal to input +\def\texdimenccup#1{\expandafter\texdimenup_a\the\numexpr\dimexpr#1;*1157/14856;cc;}% % % cm 7227/254 % -\def\texdimincm#1{\expandafter\texdimenstrippt\the\dimexpr(#1)*254/7227\relax}% -% \texdimincmdown: maximal dim exactly expressible in cm and at most equal to input -\def\texdimincmdown#1{\expandafter\texdimendown_a\the\numexpr\dimexpr#1;*254/7227;cm;}% -% \texdimincmup: minimal dim exactly expressible in cm and at least equal to input -\def\texdimincmup#1{\expandafter\texdimenup_a\the\numexpr\dimexpr#1;*254/7227;cm;}% +\def\texdimencm#1{\expandafter\texdimenstrippt\the\dimexpr(#1)*254/7227\relax}% +% \texdimencmdown: maximal dim exactly expressible in cm and at most equal to input +\def\texdimencmdown#1{\expandafter\texdimendown_a\the\numexpr\dimexpr#1;*254/7227;cm;}% +% \texdimencmup: minimal dim exactly expressible in cm and at least equal to input +\def\texdimencmup#1{\expandafter\texdimenup_a\the\numexpr\dimexpr#1;*254/7227;cm;}% % % in 7227/100 % -\def\texdiminin#1{\expandafter\texdimenstrippt\the\dimexpr(#1)*100/7227\relax}% -% \texdiminindown: maximal dim exactly expressible in in and at most equal to input -\def\texdiminindown#1{\expandafter\texdimendown_a\the\numexpr\dimexpr#1;*100/7227;in;}% -% \texdimininup: minimal dim exactly expressible in in and at least equal to input -\def\texdimininup#1{\expandafter\texdimenup_a\the\numexpr\dimexpr#1;*100/7227;in;}% +\def\texdimenin#1{\expandafter\texdimenstrippt\the\dimexpr(#1)*100/7227\relax}% +% \texdimenindown: maximal dim exactly expressible in in and at most equal to input +\def\texdimenindown#1{\expandafter\texdimendown_a\the\numexpr\dimexpr#1;*100/7227;in;}% +% \texdimeninup: minimal dim exactly expressible in in and at least equal to input +\def\texdimeninup#1{\expandafter\texdimenup_a\the\numexpr\dimexpr#1;*100/7227;in;}% +% both in and cm +% Mathematics ("both" macros) +% =========== +% +% Let a and b be two 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. +% The proof is left to reader. So U = floor(7227 k /2) for some k. +% +% Let's now find the largest such U <= T. So U = floor(k 7227/2)<= T which is +% equivalent (as k is integer) to k 7227/2 <= T + 1/2, i.e. +% +% kmax = floor((2T+1)/7227) +% +% If we used for x>0 the formula floor(x)=round(x-1/2)=<x-1/2> we would end +% up basically with some 4T hence overflow problems even in \numexpr. +% Here I used <.> to denote rounding in the sense of \numexpr. It is not +% 1-periodical due to how negative inputs are handled, but here x-1/2>-1/2. +% +% The following lemma holds: let T be a non-negative integer then +% +% floor((2T+1)/7227) = <(2T - 3612)/7227> +% +% So we can compute this k, hence get a=50k, b=127k, all within \numexpr and +% avoiding overflow. +% +% Implementation +% ============== % +% Regarding the output in pt or sp, we seem to need floor(k 7227/2). +% The computation of floor(k 7227/2) as <(7227 k - 1)/2> would require to +% check if k==0 so we do it rather as <(7227 k + 1)/2> - 1. No overflow +% can arise as k = 297147 for \maxdimen, and then 7227 k = 2**31 - 2279 and +% there is ample room for 7227k+1 using \numexpr. +% +% But this step, as well as initial step to get kmax will require to separate +% hangdling of negative input from positive one. +% +% Alternative +% ----------- +% +% For non-negative T we can compute U = ((T+1)/7227)*7227. If U <= T keep it, +% else if U > T, replace it by U - 3614. This is alternative road to the maximal +% floor(k 7227/2) at most equal to T. +% +% There is some slight 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);}% +\def\texdimenbothcmin#1{\expandafter\texdimenstrippt\the\dimexpr + \expandafter\texdimenboth_a\the\numexpr\dimexpr#1;50);}% +\def\texdimenbothincmpt#1{\expandafter\texdimenstrippt\the\dimexpr + \expandafter\texdimenboth_a\the\numexpr\dimexpr#1;7227+1)/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}% +% +\let\texdimenbothcminsp\texdimenbothincmsp \texdimensendinput |