2

I used to think that \jot is what determines the spacing between rows in gather and align environments.

enter image description here

but setting

\def\jot{0pt}

doesn't remove the spacing completely. enter image description here

With this MWE I can can specify just the right spacing that I want

\documentclass{article}
\usepackage{amsmath}
\setlength{\fboxsep}{0pt}
\setlength{\fboxrule}{.1pt}
\begin{document}

\renewcommand\arraystretch{0}

[ \begin{array}{c} \fbox{$a=b$} \[0pt] % exact height between rows \fbox{$\dfrac22$} \end{array} ]

\end{document}

enter image description here


So my question is what the precise spacing that's used in amsmath environments between rows is? So that I can specify it here \\[...] with array environment in the MWE above to be the same?

Recap:

Everything that I need is a dimension number (like 34.1pt or so), but it must be exact. Eyeballing the spacing isn't acceptable. And the proof based on the source code is required.

antshar
  • 4,238
  • 9
  • 30
  • Remark: \\[<length>] doesn't always give the space between rows; you need \noalign{\vspace{<lenght>}. See https://tex.stackexchange.com/questions/180099/vertical-spacing-in-tabular-with-bmatrix – L.J.R. Jun 01 '22 at 08:44
  • \\\noalign{\vspace{<lenght>} works fine in a minimal example on my computer. I think you need to minimalize your tex file and test it again. – L.J.R. Jun 01 '22 at 08:53
  • @L.J.R. Anyway, how does it relate to my actual question? – antshar Jun 01 '22 at 08:56
  • I edited the question to put in \usepackage{amsmath} since the code does not compile without it. – frabjous Jun 01 '22 at 16:32
  • If anything, I can make them completely squished together with \baselineskip=0pt\relax \lineskip=0pt\relax \def\jot{0pt} \savebox\strutbox {}. No idea what it does though. – user202729 Jun 05 '22 at 09:17
  • @user202729 with my instance of 2019 TeXLive, it doesn't remove spacings completely. https://i.stack.imgur.com/l3xpp.png – antshar Jun 05 '22 at 09:24
  • Ah, it's because of the tag number. Use gather* environment instead. (then maybe use \tag{\smash{...}} etc..) – user202729 Jun 05 '22 at 09:24
  • @user202729 alright, it's already something. But I'll wait for some other answer though in sake for explanation. – antshar Jun 05 '22 at 09:27
  • Note \jot is a dimension allocated by \newdimen, so you should use \setlength, instead of \def, to sets its value. – muzimuzhi Z Jun 06 '22 at 20:05
  • 2
    there is no exact dimension. The spacing depends on \jot, \lineskip, \baselineskip and the actual content of the lines. So your question is quite unclear. – Ulrike Fischer Jun 11 '22 at 14:02
  • @UlrikeFischer which is the dependency exactly? How can I replicate it with array code from my MWE? – antshar Jun 11 '22 at 14:06
  • • do you need to compute the value exactly or just need to reproduce the behavior? The latter is easier • do you really need source code proof? Or anything that is an expression of baselineskip/lineskip/jot/strutbox is sufficient (since it's shown above removing them kills the spacing) – user202729 Jun 11 '22 at 14:34
  • Well just because "the result is a complex formula instead of a constant" doesn't mean the question is ill-formed... – user202729 Jun 11 '22 at 14:49
  • @user202729 This question appeared to be much more difficult than I expected, so if you manage to the the same spacing in array as in amsmath environments, using expression with baselineskip/lineskip/jot/strutbox, it will satisfy me. I spent more than a couple of hours looking into the source code and I know how deep it's hidden somewhere, so I think I'll be fine even without a source code proof, because the actual goal is to achieve the precise spacing in array that would be the same as in amsmath environments. – antshar Jun 11 '22 at 15:38
  • After spending some time... I can get a solution that works in most value combination of jot/baselineskip/lineskip, but there are still some corner cases. I'd rather typesetting things in a box, measure the height difference, then add the spacing by exactly that amount. – user202729 Jun 12 '22 at 01:34
  • I put my partial progress here. It's an uncomprehensible mess of strut/rule, everything else though. – user202729 Jun 12 '22 at 01:50
  • Your question gives no reason why you actually need that. An array is an array and a multiline display math environment is something else and they have different (and complex) spacing and typesetting rules. Why are you trying to fake the one (gather) with the other (array) instead of using one of the many environments amsmath provides? – Ulrike Fischer Jun 12 '22 at 08:38
  • @UlrikeFischer because this question is a follow up to my previous one: Create display version of array environment. I figured out everything myself except for the spacings. – antshar Jun 12 '22 at 08:55
  • well I think you had the wrong starting point. You are trying to convert array into something that it isn't and your fighting with the spacing shows that that wasn't the best idea. – Ulrike Fischer Jun 12 '22 at 09:00
  • Alright I know that it's either \jot or \jot+lineskip (add the size of the tags into account) depends on whether the content are tall enough to touch each other (recall that TeX automatically adds lineskip distance whenever the distance between two adjacent vbox are ≤ lineskiplimit = 0pt by default), but array environment does not use lineskip so it would be a bit difficult to reimplement it. The alternative is to use the underlying TeX primitive (halign) and not use the array environment, might be easier. – user202729 Jun 12 '22 at 15:25
  • (also note that you may need to use L.J.R. 's method mentioned above to specify the exact length between two consecutive rows) -- by the way @L.J.R. nitpick, it's spelled length, not lenght. – user202729 Jun 12 '22 at 15:26
  • Actually... as David Carlisle point out in the comment it's possible to specify custom preamble for align environment family, wouldn't that be sufficient? (you don't really need to use array) – user202729 Jun 12 '22 at 15:37
  • @user202729 David's answer doesn't satisfy me because that solution doesn't support columns operators: *{n}{cols}, @{}, >{}, <{} nor vertical lines |. – antshar Jun 12 '22 at 16:06
  • I see. Still, you can probably figure out some things with @mkpream (which parses the preamble) which uses low level API but is in my opinion still easier than emulating it with array. – user202729 Jun 13 '22 at 00:14
  • Actually, thinking about it again "any glue between the lines of the tabular will spoil the vertical rules" means that the automatic lineskip will break the | anyway. https://tex.stackexchange.com/questions/374524/can-i-set-lineskiplimit-in-tabular – user202729 Jun 13 '22 at 00:44

1 Answers1

2

Not a completely automatic solution, but to reproduce the distance,

  • add a strut of \baselineskip on each row (normally array environment does automatically if \arraystretch is 1, and \baselineskip is equal to \normalbaselineskip; nevertheless we want some adjustment in row distance we will do this manually -- see note below)
  • then, the distance is \jot if the lines are "not tall" (in particular if the internal boxes doesn't touch each other), or \jot+\lineskip otherwise.

In this particular case it can be reproduced by:

%! TEX program = lualatex
\documentclass{article}
\usepackage{prettytok}  % ← alternatively comment this out and replace \pretty:x with \tl_show:x. This is just for debug printing
\usepackage{amsmath}
\usepackage{zref-savepos}
\begin{document}

%\def\texta{\dfrac22} \def\texta{a=b}

\def\textb{\dfrac22} %\def\textb{a=b}

\begin{gather} \texta \zsavepos{a1} \ \textb \zsavepos{b1} \end{gather}

[ \edef\oldlineskip{\the\lineskip} \def\arraystretch{0} \begin{array}{c} \texta \zsavepos{c1} \strut \[0pt]\[\dimexpr\jot+\oldlineskip\relax] %\[0pt]\[\jot] \textb \zsavepos{d1} \strut \end{array} ]

\ExplSyntaxOn \pretty:x{ \int_eval:n{\zposy{a1} - \zposy{b1}}sp = \int_eval:n{\zposy{c1} - \zposy{d1}}sp } \ExplSyntaxOff

\end{document}

(you need \oldlineskip because \lineskip is set to 0 in array environments. Alternatively just hard code the default value of \lineskip, which is 3pt, in.)

The zref-savepos proves that the vertical length are equal.

Nevertheless if the \textb is a=b instead, the vertical boxes doesn't "touch" each other and you need the second version (\\[\jot]) to get the same spacing.

Note: Struts does not always correctly reproduce TeX's behavior to space the baseline -- for example, I think if in an align environment both rows has height=0 and depth=0.5\baselineskip then the baselineskip will be exactly \baselineskip; nevertheless if the strut is added the height of the row below becomes 0.7\baselineskip and the distance will be something like 1.2\baselineskip+\lineskip instead?



To determine it automatically... I think there are two ways

  • you need to put the content into two boxes, then take the \dp of the row above and the \ht of the row below, add them together and compare with \baselineskip.

  • alternatively, use the zref-savepos itself and check if the two lines are \baselineskip apart, in that case add \lineskip.

Example (this may require up to 3 compilation passes however, or maybe 4 in some cases...?)

Make sure you understand what the code does and modify it accordingly. You'll get into trouble if the reference names/auxiliary macro name conflict etc.

%! TEX program = lualatex
\documentclass{article}
\usepackage{prettytok}  % ← alternatively comment this out and replace \pretty:x with \tl_show:x. This is just for debug printing
\usepackage{amsmath}
\usepackage{zref-savepos}
\begin{document}

%\def\texta{\dfrac22} \def\texta{a=b}

%\def\textb{\dfrac22} \def\textb{a=b}

\begin{gather} \texta \zsavepos{a1} \ \textb \zsavepos{b1} \end{gather}

% if this is first run \extradistance will be undefined \ifx\extradistance\relax \gdef\extradistance{0pt} \fi

% then compute extradistance \ifdim \dimexpr \zposy{c1}sp - \zposy{d1}sp \relax = \dimexpr \extradistance+\baselineskip \relax % the rows appears to be short, don't need add \lineskip \xdef\extradistance{\the\dimexpr\jot\relax} % \jot is probably not an internal dimen but just in case \else % otherwise, add \lineskip \xdef\extradistance{\the\dimexpr\jot+\lineskip\relax} \fi

\makeatletter % store the extradistance to aux file \write@auxout{\gdef\noexpand\extradistance{\extradistance}} \makeatother

[ \def\arraystretch{0} \begin{array}{c} \texta \zsavepos{c1} \strut \[0pt]\[\extradistance] \textb \zsavepos{d1} \strut \end{array} ]

\ExplSyntaxOn \pretty:x{ \int_eval:n{\zposy{a1} - \zposy{b1}}sp = \int_eval:n{\zposy{c1} - \zposy{d1}}sp }

\pretty:x{ \dim_to_decimal_in_sp:n {\jot+\baselineskip}sp } \ExplSyntaxOff

\end{document}

See also https://tex.stackexchange.com/a/95915/250119.

user202729
  • 7,143
  • Btw, you mentioned in the comments that vertical line | for columns won't and that's true as long as you use \\\noalign{\vspace{...}}, but using \\[...] doesn't break apart the line and keep the same spacing, so I see no reason to use \\\noalign{\vspace{\jot}} in favor of \\[\jot] – antshar Jun 13 '22 at 05:38
  • Is there any way of automatically determine the "tallness" of the row to use either \jot or \jot+\lineskip? Maybe using some latex3 code? – antshar Jun 13 '22 at 05:39
  • @antshar I think should be possible with the method I outline at the end of the post (the second bullet point takes two compilations though)? Will figure out some time later. – user202729 Jun 13 '22 at 05:40
  • Previously I asked one more question that might me potentially helpful about specifying the exact space between rows despite the height of the rows itself. I'm not sure whether it would be useful here, but just wanted to make sure you've seen this: https://tex.stackexchange.com/q/646234/213149 – antshar Jun 13 '22 at 05:44
  • I could create another post about further steps of automation, but I'm not even sure how to explain what I need to find out the "talness" or rows. That's because the initial question already became a chain of some other questions. – antshar Jun 13 '22 at 05:47
  • @antshar I edit the answer to give an example using the second solution (the first solution would probably be faster because it only require 1 compilation pass...?) – user202729 Jun 14 '22 at 03:15
  • Thank you for your attempt, but I'm afraid it's not close to automation, because relies on explicitly saved \zposy and expanding the solution to arbitrary amount of rows requires savvy solution. Additionally, I'd like to avoid extra packages and make do with expl3. Despite all of that, your answer covers the current question from this post, so I'll accept it and try to come up with something that could do that completely automatically. – antshar Jun 14 '22 at 09:55