4

In the question Absolute Value Symbols I read about the best ways to write absolute values. I found the accepted answer pretty good and it works in almost all cases. Sadly, only in almost. For example on the letter "k" the pipes are drawn far under the lower end of the letter "k" in the PDF output. Why is this and what to do about it?

The bad thing is: I can not just skip the macro on all "k" vectors and use the regular pipes |\vec{k}| or the starred version of the abs* operator because as you will see from the last two lines in the minimal example, the regular pipes on the "k" are drawn to short at the top (not around the vector arrow). The "x" is drawn like expected by a reader, however.

The following is a minimal example that shows the problem (letter "x" works fine, letter "k" has to big/small pipes). In my real world document I also have T1 fontenc, and font packages loaded (libertine, fouriernc and inconsolata), so this behavior seems to be independent of all the font/math-related packages.

\documentclass{article}

\usepackage{mathtools}

%define abs
\DeclarePairedDelimiter\abs{\lvert}{\rvert}%

%switch starred and non-starred (auto-size)
\makeatletter
\let\oldabs\abs
\def\abs{\@ifstar{\oldabs}{\oldabs*}}
\makeatother

\begin{document}
  \[ \abs{\vec{x}} \]
  \[ \abs{\vec{k}} \]
  \[ |\vec{x}| \]
  \[ |\vec{k}| \]
\end{document}

The output:

enter image description here

I know about the nath package, but it always gives me a lot of errors and seems to be unmaintained. Also, to me it always feels a bit "strange" if things are auto-done to my document that can't be "looked inside" (without investing tons of non-available time to work through the nath package code). So, I'd rather like to not use it.

  • 2
    In my opinion the last row has nothing bad at all. – egreg Jan 4 '13 at 16:08
  • @egreg: IMHO, the pipes should also enclose the arrow. But besides the plain look'n'feel: It's annoying to have a letter-dependent command... If I use \abs{} I want correct sized pipes. If I just default-use the non-auto-size then it looks bad in all other cases except "k" (for example on \abs{\frac} combinations). Sadly in my use-case "k" appears often (along frac and other variable size output) – Foo Bar Jan 4 '13 at 16:12
  • Don't use \left and \right automatically, to begin with. It's wrong. The absolute value bar shouldn't change depending on the single symbol it encloses: what about |\vec{x}|+|\vec{k}|? I'd never want different bars. – egreg Jan 4 '13 at 16:18
  • But why, in the first place, do \left| \vec{x} \right| and |\vec{x}| give the same result, while the same for k is not true? I mean, x and k are just some letters and no special symbols. – Foo Bar Jan 4 '13 at 17:13
  • \left and \right have a "tolerance" on the amount of vertical space not covered. – egreg Jan 4 '13 at 17:17
3

I was able to use my scalerel package to hopefully give you what you want (scalerel was just sent to CTAN today, so until it propagates, you can find the style listing at How to horizontally merge two symbols?).

Using that package's features, my first cut was to create a command \myabs, which places abs bars around anything. It will stretch the size of the bars exactly to the argument. The downside of this first attempt is that you may have preferred the bars to extend a bit above and below the object being surrounded (addressed later in this answer). Here's the code for the first approach:

\documentclass{article}
\usepackage{scalerel}
\usepackage{mathtools}

\begin{document}
% [METHOD USED IN ORIGINAL QUESTION CODE HERE, REMOVED FROM THIS LISTING]
\newcommand\myabs[1]{%
  \setbox1\hbox{$#1$}%
  \stretchrel{\lvert}{\usebox1}\stretchrel*{\lvert}{\usebox1}%
}

\[ \myabs{\vec{k}}~~\myabs{\vec{x}}~~\myabs{\vec{A}}~~\myabs{\vec{q}} \]

\end{document}

and here's the output, as compared to your original

enter image description here

However, to answer ralfix's request to extend the vertical line a bit above and below the surrounding object, I just used the \addvbuffer routine from the verbatimbox package, setting the top and bottom add-on to 2pt:

\documentclass{article}
\usepackage{scalerel}
\usepackage{mathtools}
\usepackage{verbatimbox}

\setlength\boxtopsep{2pt}
\setlength\boxbottomsep{2pt}
\newcommand\myabs[1]{%
  \setbox1\hbox{$#1$}%
  \setbox2\hbox{\addvbuffer{\usebox1}}%
  \stretchrel{\lvert}{\usebox2}\stretchrel*{\lvert}{\usebox2}%
}

\begin{document}
\[ \myabs{\vec{k}}~~\myabs{\vec{x}}~~\myabs{\vec{A}}~~\myabs{\vec{q}} \]
\end{document}

enter image description here

But egreg commented that the height of the abs bar should not change with the argument. If that is the preferred embodiment of abs, then scalerel can fix that too:

\documentclass{article}
\usepackage{scalerel}

\def\lvert{|}
\begin{document}
METHOD 2: FIXED EXTENT
\newsavebox\mybox
\savebox{\mybox}{$\stretchrel*{|}{\rule[-.6ex]{0ex}{3ex}}$}
\def\myabs#1{\usebox\mybox#1\usebox\mybox}

\[ \myabs{\vec{k}}~~\myabs{\vec{x}}~~\myabs{\vec{A}}~~\myabs{\vec{q}} \]
\end{document}

enter image description here

  • How is it possible to extend the vertical line "a bit above and below" the surrounded object? – Peater de Xel Feb 27 '13 at 18:15
1

Fences are vertically centered around the math axis. They increase symmetrically, even if the formula is taller above the math axis than below.

The following example moves the formula to vertically center it to get minimized fences, then the fences with the formula are moved back to the correct vertical position.

Package mleftright is only used to get a variant of \left and \right as \mleft and \mright that do not add additional horizontal space.

\documentclass{article}
\usepackage{mleftright}

\makeatletter
\newcommand*{\trimabs}[1]{%
  \mathpalette{\@trimleftright{|}{|}}{#1}%
}
\newcommand*{\@trimleftright}[4]{%
  % #1: left fence
  % #2: right fence
  % #3: math style
  % #4: formula
  \sbox0{$#3#4\m@th$}%
  \sbox2{$#3\vcenter{}$}% Math axis: \ht2
  % \dimen0: min(height(formula), math axis)
  \dimen0=\ht0 %
  \ifdim\dimen0<\ht2 %
    \dimen0=\ht2 %
  \fi
  % \dimen2: min(depth(formula), 0)
  \dimen2=\dp0 %
  \ifdim\dimen2<\z@
    \dimen2=\z@
  \fi
  % \dimen0: vertical shift for centering
  \dimen0=\dimexpr(\dimen0-\dimen2)/2 -\ht2\relax
  \raisebox{\dimen0}{%
    $#3\mleft#1\raisebox{-\dimen0}{\box0}\mright#2\m@th$%
  }%
}
\makeatother

\begin{document}
\[
  |\vec x| + |\vec k|
  = \left|\vec x\right| + \left|\vec k\right|
  = \trimabs{\vec x} + \trimabs{\vec k}
\]
\end{document}

Result

Fine tuning

The depth of the fences of "k" have now a depth less in case of vector "x". This can be fixed, by making the formula larger. The example uses the size of the fences without contents:

\documentclass{article}
\usepackage{mleftright}

\makeatletter
\newcommand*{\trimabs}[1]{%
  \mathpalette{\@trimleftright{|}{|}}{#1}%
}
\newcommand*{\@trimleftright}[4]{%
  % #1: left fence
  % #2: right fence
  % #3: math style
  % #4: formula
  \sbox0{$#3#4\m@th$}%
  \sbox2{$#3\vcenter{}$}% Math axis: \ht2
  \sbox4{$#3\left#1\right#2$}%
  % \dimen0: min(height(formula), math axis)
  \dimen0=\ht0 %
  \ifdim\dimen0<\ht2 %
    \dimen0=\ht2 %
  \fi
  % \dimen2: min(depth(formula), 0)
  \dimen2=\dp0 %
  \ifdim\dimen2<\z@
    \dimen2=\z@
  \fi
  % Make formula as least as tall as the fences without content.
  \sbox4{$#3\left#1\right#2$}%
  \ifdim\ht4>\dimen0 %
    \dimen0=\ht4 %
  \fi
  \ifdim\dp4>\dimen2 %
    \dimen2=\dp4 %
  \fi
  % \dimen0: vertical shift for centering
  \dimen0=\dimexpr(\dimen0-\dimen2)/2 -\ht2\relax
  \raisebox{\dimen0}{%
    $#3\mleft#1\raisebox{-\dimen0}{\box0}\mright#2\m@th$%
  }%
}
\makeatother

\begin{document}
\[
  |\vec x| + |\vec k|
  = \left|\vec x\right| + \left|\vec k\right|
  = \trimabs{\vec x} + \trimabs{\vec k}
\]
\end{document}

Fine-tuning result

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.