3

Very often there are questions like: "Why are the square roots so ugly? Why is there a difference in height?"

$\sqrt{x} \, \sqrt{y} \, \sqrt{X}$

Then the answers all sound like: "Use \phantom, \mathstrut or \smash[b]." Not really satisfying as all the suggestions are adjustments by hand.

Now we have had LuaTeX since more than 10 years. Why isn't there any solution with lua callbacks?

A good \sqrt sign should...

  • have a minimum height (example: by inserting \phantom{0}).
  • not grow into depth when there are only descenders of letters or subscripts (\smash[b]). Of couse the bottom should not be smashed when there is a big fraction or another big constuction.
  • ignore \underbraces.

If I had more knowledge about LuaTeX I would try to create an MWE. In the LuaTeX manual we find radical nodes and so on. Maybe someome has an idea.

EDIT (as an answer to projetmbc's comment):

The first of my suggestions would lead to the same square root height for \sqrt x, \sqrt X and \sqrt 2.

The second one would lead to equal heigt for $\sqrt g$, \sqrt x and \sqrt{x_1}.

The third one would prevent the square root sign from growing for an underbrace: $\sqrt{\underbrace{something}_{something}}$

I cannot imagine a solution without LuaTeX.

  • Could you give examples of real-life use cases to complement your general suggestions? I'm not sure that LuaLaTeX is essential here. – projetmbc Feb 12 '23 at 18:20
  • What exactly is the typographic issue you believe needs to be fixed? Why is it necessary, or at least desirable, to make the heights and depths of square root symbols "consistent"? Are you familiar with what Ralph Waldo Emerson had to say about consistency? – Mico Feb 12 '23 at 18:21
  • 1
    @Mico: See my example above ($\sqrt{x} \, \sqrt{y} \, \sqrt{X}$). This leads to 3 different square root signs (ugly). A solution is desireable because the adjustments by hand are annoying. – Weißer Kater Feb 12 '23 at 18:25
  • I suppose you consider the symbols to be ugly simply because their sizes aren't identical, or otherwise "consistent". (Who made you the arbiter over ugliness and beauty?) See the Emerson reference for what many people think about the value of consistency... – Mico Feb 12 '23 at 18:28
  • Ugliness can lie in the eye of the beholder – Peter Wilson Feb 12 '23 at 18:28
  • 1
    I accept other opinions, but I don't like the inconsistent square root signs. And many other users dislike them, too. Otherwise we wouldn't see such questions. – Weißer Kater Feb 12 '23 at 18:31
  • 1
    @projetmbc: See edit. :) – Weißer Kater Feb 12 '23 at 18:44
  • 1
    Would you be willing to give a list of those who dislike them? Perhaps their problems have been answered. – Peter Wilson Feb 12 '23 at 19:13
  • See for example here: https://tex.stackexchange.com/questions/121402/the-size-of-roots – Weißer Kater Feb 12 '23 at 19:15
  • 2
    There are only solutions by hand. You have to insert \smash[b] or \phantom by hand. With LuaTeX automatic solutions should be possible. – Weißer Kater Feb 12 '23 at 19:16
  • 1
    I do not think this is an engine thing, but a macro package thing. I doubt that \sqrt from LaTeX will be redefined, but maybe someone will suggest a better version of \sqrt here for you. Just as a comparison, the \sqrt in ConTeXt has by default a strut. It does not ignore subscripts or characters with depth, or underbraces, though (how would that even work? these things can be huge and interference with other stuff will likely occur...). – mickep Feb 13 '23 at 06:29
  • From your examples so far it seems a relatively simple solution would be to have a separate fixed-height version, let's call it \fixsqrt, that doesn't attempt to scale at all and would be around the height of the current \sqrt{X} (basically a top-aligned √ symbol with a horizontal line on top spanning the content), and another variable-height version for content with fractions and sums and the like which would behave exactly like the current \sqrt{}. Of course implementation would be greatly simplified if the user actually inputs \fixsqrt when needed instead of LaTeX trying to guess – Marijn Feb 13 '23 at 13:14
  • 1
    whether \sqrt or \fixsqrt is needed. Is that an accurate description of your requirement, or do you want something more complex? – Marijn Feb 13 '23 at 13:15
  • @Marijn: I know I can have 2 commands. But I think I with more modern engines the cases of manual adjustment should become less. ;) – Weißer Kater Feb 13 '23 at 18:36
  • @WeißerKater I understand the preference for a single automatic command, which is also what you got in Mico's answer below. However, just from size measurements of the contents it would be rather difficult to choose automatically, because you want, e.g., a fraction to have a big sqrt but a sub+superscripted variable of similar size as the fraction should have a small sqrt. Therefore I suggested to have two different commands. In the solution below it is automatic but very dependent on the list of regexes, for example \let\myfrac\frac would already break it. So in a sense [...] – Marijn Feb 13 '23 at 20:15
  • the two separate commands would make it more flexible because you can be sure that you can always (easily) get the result you want, whatever the input is that you throw at it. – Marijn Feb 13 '23 at 20:16

2 Answers2

12

I'm not convinced that it's an improvement to force (most) \sqrt expressions to have surds with the same height and depth. But, as always, if you really understand what you're doing, you'll probably be ok using the one-size-fits-almost-all approach.

The following, LuaLaTeX-based solution features (a) a utility LaTeX macro called \lsqrt and (b) two Lua functions: lsqrt does almost all of the real work, and checkroot (which is called by lsqrt) contains a list of conditions; if one (or more) of these conditions is met, \lsqrt does nothing special, i.e., it behaves like the basic \sqrt macro.

The default height of the horizontal bar of the square root symbol generated by \lsqrt is set so that something such as k^2 will just fit. Note that this is a bit taller than what the OP required; however, as the difference in heights is just 0.6pt (at least for Computer Modern with 10pt as the main document font size), I think it's justifiable to go for this ever so slightly greater height. Of course, if you prefer a height that accomodates k but not k^2, just change both instances of \\vphantom{k^2} to \\vphantom{k}. (Aside: the \\ double-backslash symbol occurs because for Lua, \ has a special meaning too; however, the Lua-special and TeX-special meanings of \ are completely different. To output a single backslash character in Lua, it's necessary to input \\.)

enter image description here

% !TEX TS-program = lualatex
\documentclass{article} 
\usepackage{amsmath}
\usepackage{luacode} % for 'luacode*' env. and '\luastringN' macro

%% Lua-side code: 2 Lua functions: checkoptargroot, lsqrt \begin{luacode*}

function checkroot ( s )
  if       s:find ( "\\[dt]?frac" ) -- \frac term
        or s:find ( "\\int" )       -- integral symbol
        or s:find ( "\\sum" )       -- summation symbol
        or s:find ( "%^%s?%b{}" )   -- exponent term encased in matching curly braces
     then
       return true
  else
       return false
  end
end

function lsqrt ( b , s ) -- this function does most of the work
  if b=="" then -- no optional argument was provided to "\lsqrt"
    if checkroot ( s ) then
      tex.sprint ( "\\sqrt{".. s .."}" ) -- nothing special to do
    else
      tex.sprint ( "\\sqrt{\\smash{".. s ..
                   "}\\vphantom{k^2}}\\vphantom{"..s.."}" )
    end
  else -- need to handle non-empty optional argument
    if checkroot ( s ) then
      tex.sprint ( "\\sqrt["..b.."]{".. s .."}" ) -- nothing special to do
    else
      tex.sprint ( "\\sqrt["..b.."]{\\smash{".. s ..
                   "}\\vphantom{k^2}}\\vphantom{"..s.."}" )
    end    
  end
end
\end{luacode*}

%% LaTeX-side code: utility macro to access the 'lsqrt' function
\newcommand\lsqrt[2][]{\directlua{lsqrt(\luastringN{#1},\luastringN{#2})}}

\begin{document}

$\sqrt{y}$  $\sqrt{x}$  $\sqrt{t}$  $\sqrt{k}$  $\sqrt{b_q^2}$ vs.\
$\lsqrt{y}$ $\lsqrt{x}$ $\lsqrt{t}$ $\lsqrt{k}$ $\lsqrt{b_q^2}$

\medskip
$\sqrt[3]{y}$  $\sqrt[4]{x}$  $\sqrt[5]{t}$  $\sqrt[6]{k}$  $\sqrt[7]{b_q^2}$ vs.\
$\lsqrt[3]{y}$ $\lsqrt[4]{x}$ $\lsqrt[5]{t}$ $\lsqrt[6]{k}$ $\lsqrt[7]{b_q^2}$

\medskip
$\sqrt{\frac{1}{2}}$     $\lsqrt{\frac{1}{2}}$,
$\sqrt[3]{\dfrac{1}{5}}$ $\lsqrt[3]{\dfrac{1}{5}}$,
$\sqrt{a_q^{-x^2/2}}$    $\lsqrt{a_q^{-x^2/2}}$

\end{document} 
Mico
  • 506,678
  • 1
    Nice solution, this meets most of the requirements of the asker without being overly complicated I think. Note that (given the remarks of the asker that LuaLaTeX would probably be needed) this kind of approach could also be done with regex matching in expl3 for other compilers, or even with \IfSubStr from the xstring package. – Marijn Feb 13 '23 at 15:18
  • @Marijn - Thanks. Indeed, if somebody wants to come up with an latex3/regex solution, that would be quite welcome. (I won't be the one providing the alternative solution, though, as I'm much more familier with Lua and its string functions than with latex3 and its syntax.) – Mico Feb 13 '23 at 15:59
  • Your last bunch of examples seem to have a \sqrt where you probably meant \lsqrt (at least in the source). – mickep Feb 13 '23 at 17:36
  • @mickep - Good catch, now fixed. (The outputs of \sqrt{\frac{1}{2}} and \lsqrt{\frac{1}{2}} are identical, by design.) – Mico Feb 13 '23 at 17:57
  • @Mico: Thank you for this answer. :) I think my ideas were too complicated. I thought about radical nodes and the mlist_to_hlist callback ... – Weißer Kater Feb 13 '23 at 18:43
  • But ... Could you give me a hint how to make nested \lsqrts work? :) By the way, for Plain TeX it is not difficult to add :find ( "\\over" ), I found out. – Weißer Kater Feb 13 '23 at 18:45
  • @WeißerKater - How are nested copies of \lsqrt even supposed to work? By design, their surds have the same height and depth. Nesting them can only cause a disaster. About using \over in a LaTeX document -- my only, but strongly held, piece of advice on this subject is "don't do it!". See the posting What is the difference between \over and \frac? for a longer discussion of the issues involved. [shameless self-citation alert!] – Mico Feb 13 '23 at 18:51
  • @Mico: I usually use Plain LuaTeX, so there are very many \overs in my documents. I don't use LaTeX at all (only for testing). I think when there are nested roots the outer root should be a little bit taller than the inner one, like the standard behavior in $\sqrt{\sqrt 2}$. – Weißer Kater Feb 13 '23 at 18:56
  • @WeißerKater - Fair enough, I wasn't aware that you were using Plain-LuaTeX. (I guess you've also figured out in the meantime how to store the Lua code in an external file and how to load it via a \directlua{dofile()} instruction.) Well, there was a reason why I defined a macro with a new name instead of redefining \sqrt directly... About creating a nestable version of \lsqrt: may I suggest you post a new query? – Mico Feb 13 '23 at 19:02
  • @Mico: It's OK. :) You didn't post anything wrong. :) Yes, I know the \directlua{dofile()} method, but a \directlua with some \catcode changes works, too. OK, I will post a new question. :) – Weißer Kater Feb 13 '23 at 19:11
  • @WeißerKater -- For me, the only reasonable use case for \lsqrt is if you have to write something like The values of $\lsqrt{y}$, $\lsqrt{x}$, $\lsqrt{t}$, $\lsqrt{k}$, and $\lsqrt{k^2}$ are \ldots. Once one is dealing with nested square roots, I no longer see a use case for \lsqrt. I suppose one could add or s:find ( "\\[l]?sqrt") to the list of conditions that make the outer\lsqrt behave like \sqrt... – Mico Feb 13 '23 at 19:12
  • 1
    @Mico: I have added or s:find ( "\\[l]?sqrt") as you suggested. $\lsqrt{\lsqrt 2}$ looks perfect, but $\lsqrt{\lsqrt j}$ not. I think the \vphantoms in the lua code should be collected in the case of nested roots and added after all the nested roots have been typeset. ;) – Weißer Kater Feb 13 '23 at 19:34
  • @Marijn Last version of LaTeX3 has a rich interface for string manipulations : there is a \str_if_in macro. ;-) – projetmbc Feb 14 '23 at 15:10
  • 1
    @Mico Can I use your code in a GPL project? – projetmbc Feb 14 '23 at 15:11
  • 1
    @projetmbc - You are more than welcome to use use my code any way you see fit. :-) – Mico Feb 14 '23 at 15:15
2

I think that you will not find one version that will fit you perfectly for all cases, and, as mentioned in a comment, I think this is something for the macro package. Since you have gotten a satisfying LaTeX answer, I provide a ConTeXt one, hopefully to help somebody.

In ConTeXt you have the possibilities to do setups and define your own instances of mathradicals. By default, the \sqrt has a strut that has height but no depth, but that can be changed. Also, as we will see, it is possible to set the height and depth of content. Let us show some examples

\usemodule[visual] % for \fakewords only

\starttext

\fakewords{25}{30}

\startformula \sqrt{y}+\sqrt{x} + \sqrt{b_q^2} + \sqrt{\frac{1}{5}} + \root[n=3]{x+y} \breakhere \sqrt[depth=1sp]{y} + \sqrt[strut=no]{x} + \sqrt[depth=1sp]{b_q^2} + \sqrt[depth=6pt]{\frac{1}{5}} + \sqrt[depth=1sp][3]{x+y} \stopformula

\fakewords{25}{30}

\definemathradical [mysqrt] [depth=1sp]

\startformula \mysqrt{y} + \mysqrt{x} + \mysqrt{b_q^2} + \mysqrt{\frac{1}{5}} + \mysqrt[depth=6pt]{\frac{1}{5}} + \mysqrt[3]{x+y} \stopformula

\fakewords{25}{30}

\startformula \sqrt{\int_a^c 2x\dd x} = \sqrt{\underbrace{c^2-a^2}{=b^2}} = \sqrt[depth=4pt]{\underbrace{c^2-a^2}{=b^2}} = \mysqrt{\underbrace{c^2-a^2}_{=b^2}} \stopformula

\fakewords{25}{30}

\stoptext

Compiling this file with context gives the result:

A very radical image

Some comments:

  • The first line in the first displayed formula shows the default \sqrt{}
  • The second line in the first displayed formula shows some variants, as we can get them by inserting options to the \sqrt macro.
  • For the third displayed formula, we have introduced our own instance of a math radical, \mysqrt, with the help of \definemathradical. To set the depth explicitly we need to set it to some non-zero value (this is by old construction, and the value zero will give just the original version back). We set it to something very small, 1sp. Note in the fraction 1/5 that it looks better with a slightly modified depth (that we can add as an optional argument to \mysqrt).
  • In the last displayed formula we show also some formula with an underbrace. Here you see three versions, and you can choose yourself which one you prefer.

A curiosity: After discussions with Hans, we agreed that using the name sqrt in \sqrt[3]{x} is a bit strange, so from now on the base math radical in ConTeXt will be \root instead of \sqrt (but with \sqrt as a copy of it, not to break compatibility). There will also be support for input like \root[n=3]{x} instead of \root[3]{x}.

mickep
  • 8,685