summaryrefslogtreecommitdiff
path: root/macros/generic/texdimens/texdimens.tex
blob: 471a07f807dd7c835c3b14ab12dcc398749ca196 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
% This is file texdimens.tex, part of texdimens package, which
% is distributed under the LPPL 1.3c. Copyright (c) 2021 Jean-François Burnol
% 2021/06/30 v0.9beta
\edef\texdimensendinput{\endlinechar\the\endlinechar\catcode`\noexpand _=\the\catcode`\_\relax\noexpand\endinput}%
\endlinechar13\relax%
\catcode`\_=11
% Is T sp attainable from unit "uu"?. Here we suppose T>0.
% phi>1, psi=1/phi, psi<1
% U(N,phi)=floor(N phi) is strictly increasing
%     U(N)<= T <  U(N+1)    iff    N = ceil((T+1)psi) - 1
%     U(M)<  T <= U(M+1)    iff    M = ceil(T psi)    - 1
% Either:
% -  M = N, i.e. T is not attainable, M=N < T psi < (T+1) psi <= N+1
% -  M = N - 1, i.e. T is attained, T psi <= N < (T+1) psi, T = floor(N phi) 
%
% In the latter case:
% - as psi<1, |N - (T+0.5) psi| < 0.5, hence N = R := round((T+0.5) psi).
%   Also works for T=0 but T<0 would need -0.5.
%
% - if psi<1/2, then N = round(T psi) is simpler formula which works
%   also for attainable T<0.
%
% This R=round((T+0.5) psi) can always be computed via \numexpr because 2T+1
% will not trigger arithmetic overflow.
%
% If Tsp>0 is not attainable, this R can produce either N or N+1 (=M+1).
%
% If we try computing ceil(x) via round(x+0.5) (\numexpr rounds up)
% this means for N, we need round((T+1)psi + 0.5), for example with
% psi = 100/7227 for "in", this gives round((((T+1)200)+7227)/14454)
% feasible via \numexpr only for (circa) 100 T less than \maxdimen.
%
% We could rather compute round(T psi) but we don't know if it gives
% N or N+1. We know it is N if round(T psi)< round((T+1) psi)
% but if the two are the same we don't know if they are both N or
% both N+1.
%
% It is slightly less costly to compute X = round(T psi) than R,
% but if we then realize that X uu < T sp we do not yet know
% if (X+1) uu = T sp or is > Tsp, except if psi<1/2, because
% if T sp is attainable then X = round(T psi) is then necessarily N
% so if X uu < T sp we now that T sp was not attainable.
%
% We decide with some hesitation to not split whether psi<1/2 or
% psi>1/2. Reverted! Currently following done only for psi>1/2,
% i.e. bp, nd, dd.
%
% 1. compute R = round((T+0.5) psi) in \numexpr. This forces
%    to check for negative T because then we would want here (T-0.5)psi
%
% 2. check for the "up" and "down" variants whether R uu is <, =, or > T sp.
%    But we have to choose here what "up" and "down" mean for T<0.
%    Also, computation of R uu
%    may trigger Dimension too large if T sp is not attainable,
%    close to \maxdimen, and \maxdimen itself is not attainable.
%
% For the envisioned "safe versions" we would tabulate first per unit
% what is Rmax such that Rmax uu <= \maxdimen. Then the "safe" versions
% would have an extra check of R. But for \texdimeninuuu it will
% then not be compliant to its definition for inputs close to
% non-attainable \maxdimen.
%
% After having written the macros we will tabulate what is for each unit
% the maximal attainable dimension.
%
% Hesitation about whether using simpler round(T psi) approach
% for units > 2pt and the \texdimin<uu> macros.
%
% Testing shows that this would not change output for \maxdimen
% with "nc" and "in": still N+1 is returned... but it has great
% advantage to not have to check the sign.
%
% OK let's do this,
% especially as I don't know if I will ever implement "up" and "down".
\def\texdiminpt#1{\expandafter\texdiminpt_\the\dimexpr#1\relax}%
{\catcode`p 12\catcode`t 12\csname expandafter\endcsname\gdef\csname texdiminpt_\endcsname#1pt{#1}}%
% bp 7227/7200 = 803/800
% complications and annoying overhead caused by sign
% and we don't want to evaluate #1 twice in a \dimexpr; if #1 was
% restricted to be a dimen register, we would avoid "\the and re-grab" step.
\def\texdiminbp#1{\expandafter\texdiminbp_\the\numexpr\dimexpr#1;}%
\def\texdiminbp_#1#2;{\texdiminpt{\numexpr(2*#1#2+\if-#1-\fi1)*400/803sp}}%
% nd 685/642
\def\texdiminnd#1{\expandafter\texdiminnd_\the\numexpr\dimexpr#1;}%
\def\texdiminnd_#1#2;{\texdiminpt{\numexpr(2*#1#2+\if-#1-\fi1)*321/685sp}}%
% dd 1238/1157
\def\texdimindd#1{\expandafter\texdimindd_\the\numexpr\dimexpr#1;}%
\def\texdimindd_#1#2;{\texdiminpt{\numexpr(2*#1#2+\if-#1-\fi1)*1157/2476sp}}%
% mm 7227/2540 phi now >2, use from here on the simpler approach
\def\texdiminmm#1{\texdiminpt{(#1)*2540/7227}}%
% pc 12/1
\def\texdiminpc#1{\texdiminpt{(#1)/12}}%
% nc 1370/107
\def\texdiminnc#1{\texdiminpt{(#1)*107/1370}}%
% cc 14856/1157
\def\texdimincc#1{\texdiminpt{(#1)*1157/14856}}%
% cm 7227/254
\def\texdimincm#1{\texdiminpt{(#1)*254/7227}}%
% in 7227/100
\def\texdiminin#1{\texdiminpt{(#1)*100/7227}}%
\texdimensendinput