2

I am trying to align some fairly long equations the way I would usually do with LaTeX in groff. The general form I am aiming for:

A = B + C
  = D * E
    + F * G
  = H + I   = J

In LaTeX I would do this as follows:

\documentclass[fleqn]{article}

\usepackage{amsmath}

\begin{document}
\begin{alignat*}{3}
A
  & = B + C \\
  & =
  \begin{aligned}[t]
    & D * E \\
    & + F * G
  \end{aligned} \\
  & = H + I
    && = J
\end{alignat*}
\end{document}

In eqn, equation alignment is accomplished with the mark and lineup commands. Quoting Kernighan and Cherry from Typesetting Mathematics 2nd Ed (found here) on how these work:

The word mark may appear once at any place in an equation. It remembers the horizontal position where it appeared. Successive equations can contain one occurence of the word lineup. The place where lineup appears is made to line up with the place marked by the previous mark if at all possible.

Upon reading this I was under the impression that the system does not prohibit both aligning with the previous mark with lineup as well as setting a new mark within the same line of an equation, e.g. I would expect the following:

.PP
.EQ I
A mark =
B + C
.EN
.EQ I
lineup = mark
D * E
.EN
.EQ I
lineup + F * G
.EN

to produce something like this:

A = B + C
  = D * E
    + F * G

That is not the case, however. eqn aligns the plus sign with the equals:

A = B + C
  = D * E
  + F * G

and produces a warning:

eqn:test.ms:10: multiple marks and lineups

I compile my .ms files with a small script:

eqn $1 -Tpdf | groff -ms -Tpdf > ${1/%.ms/.pdf}

I would like to know if there is some macro that would let me store multiple horizontal offsets (or how to define one). Some clarification as to how exactly mark and lineup macros work would also help.

Andrii Kozytskyi
  • 123
  • 2
  • 11

3 Answers3

2

It is very disappointing that eqn does not allow a new mark to be set. Here is a poor workaround that might be of some use. It consists of repeating the first equation but with the keyword mark in the new position, and diverting the output to nowhere so it does not appear. .di is a base troff to start and end a diversion.

.EQ I
A mark = B + C
.EN
.EQ I
lineup = D * E
.EN
.di mydump
.EQ I
A = mark B + C
.EN
.di
.EQ I
lineup + F * G
.EN

Note, you can also use eqn commands like fwd 99 to move right 99/100 ems, where an em is about the width of the character "m".

meuh
  • 11,500
  • 2
  • 29
  • 45
  • I find this very useful actually. This is essentially equivalent to the LaTeX `\phantom{}` command; not perfect perhaps, but definitely more rigorous and elegant than aligning the equations manually with tildes and spacing IMO. Thank you very much! – Andrii Kozytskyi Jun 05 '21 at 13:21
1

Here's a possible solution for having a second mark on the same line as lineup. It uses the base troff sequence \k to mark the current horizontal position into a register myposn. There is then an eqn macro mylineup which calls the eqn special command to run a troff define MyLineup which "returns" a character that has a horizontal movement of myposn units. Before the call eqn sets up some registers with the word following the call, and expects them to be updated to whatever output is desired at that point. We do not use this dummy word, which can be anything, but must not be omitted. For example,

.de MyLineup
. ds 0s "\h'\\n[myposn]u'
. nr 0w \\n[myposn]u
. nr 0h 0
. nr 0d 0
. nr 0skern 0
. nr 0skew 0
..

.EQ I
define mymark '\k[myposn]'
define mylineup 'special MyLineup'
A mark = B + C
.EN
.EQ I
lineup = mymark D * E
.EN
.EQ I
mylineup dummy + F * G
.EN

The lines from .de to .. are the MyLineup definition. The two define lines should be in the first equation. Thereafter, mymark and mylineup dummy can be used in place of mark and lineup. The original mark and lineup are unchanged. If necessary, the real mark can be used again in the line with mylineup, and so on.


To generalise this to having many marks is complicated. The first problem is that mymark is just an eqn define and cannot take a number parameter. It cannot use the special command because it needs to be inline. A trivial solution is just to create a lot of definitions at the start:

define mymark1 '\k[myposn1]'
define mymark2 '\k[myposn2]'

The second problem is that when eqn calls MyLineup it does not pass the following argument ("dummy" which we intend to change to "1") as a parameter of the call, but in the variable 0s; also the string is embedded in formatting code and is actually (in my test anyway) \f[R]\,1\/\fP. So we need to substring the number out of this, with .substring 0s 7 -6. The modified macro and test is:

.\"   gets passed 0s = \f[R]\,1\/\fP     !!! not just 1
.de MyLineup
. substring 0s 7 -6
. ds 0s \\h'\\n[myposn\\*[0s]]u'
. nr 0w \\n[myposn\\*[0s]]u
. nr 0h 0
. nr 0d 0
. nr 0skern 0
. nr 0skew 0
..
.EQ I
define mymark1 '\k[myposn1]'
define mymark2 '\k[myposn2]'
define mylineup 'special MyLineup'
A mark = B + C
.EN
.EQ I
lineup = mymark1 D * mymark2 E
.EN
.EQ I
mylineup 1 + F * G
.EN
.EQ I
mylineup 2 + X
.EN
.EQ I
lineup = H + I
.EN
meuh
  • 11,500
  • 2
  • 29
  • 45
  • Very nice, this is more like what I was looking for. I was just working on a macro using the `.di` method as well, I'll take your work into account and post it as an answer if I can get it to work. – Andrii Kozytskyi Jun 05 '21 at 16:45
  • So this works just fine with an additional mark, but what if I wanted to have several marks, something like `mymark myregister`? I tried to do something like `.ds 0s \h'\\n[$1]u'` in the definition of `MyLineup` and then `define mymark '\k[myregister]'` and `define mylineup 'special MyLineup \n[myregister]'` but that doesn't seem to work @meuh – Andrii Kozytskyi Jun 05 '21 at 22:12
  • 1
    I've added a solution, but are you sure the simple `matrix` answer is not what you need? – meuh Jun 06 '21 at 10:11
  • My issue with the `matrix` approach is the spacing and the fact that for longer lines, the equation becomes unwieldy and unreadable in the `.ms` file. I can typeset equations well enough with just two marks though, I was just hoping for a more elegant solution, but since this is much more complex than I expected I will stick to the simpler macro. Thank you for your help! – Andrii Kozytskyi Jun 06 '21 at 13:45
1

I may have been misled by there being several .EQ calls in your example. I was assuming there would be text between the calls and the equations. However, if the intention is to have a single, multi-line equation, it can be done using matrix (or perhaps lpile too). For example,

.nr PS 20p
.nr VS 24p
.PP
.EQ
matrix { 
 lcol { A }
 lcol { = above = above ~ above = }
 lcol { B + C above D * E above + F * G above H + I }
 lcol { ~ above ~ above ~ above = J }
}
.EN

equation

meuh
  • 11,500
  • 2
  • 29
  • 45