Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

I want to re-define the \sqrt command (as detailed in Nice-looking p-th roots), and so far I have the following:

\documentclass{article}

\usepackage{fouriernc} % use the New Century Schoolbook font
\usepackage{amsmath}

\let\oldsqrt\sqrt
\def\sqrt[#1]{\oldsqrt[\leftroot{-3}\uproot{3}#1]}

\begin{document}
This $\sqrt[p]{a}$ looks better than $\oldsqrt[p]{a}$,
since the $p$ does not intersect the root symbol.
\end{document}

However, when I try writing \sqrt{a}, I get an error. How can I make the #1 argument optional, so that if it is not passed in, it leaves that area above the root symbol blank (as it would in the default \sqrt command)?

(This is a follow-up to the comments on David's and Harish's answers to above-mentioned question.)

share|improve this question
6  
I would suggest using LaTeX's \renewcommand which handles optional arguments for you: \renewcommand\sqrt[1][]{\oldsqrt[\leftroot{-3}\uproot{3}#1]}. –  Caramdir Mar 23 '12 at 1:34

4 Answers 4

up vote 2 down vote accepted

If you want commands with at most one optional argument, LaTeX's built in \newcommand and \renewcommand are an easy way to define them. The syntax is

\(re)newcommand⟨\name⟩[⟨number of arguments⟩][⟨default value for the first argument⟩]{⟨code⟩]

If you specify the second optional argument, then the first argument to \name will be optional. So in your case one can simply use

\renewcommand\sqrt[1][]{\oldsqrt[\leftroot{-3}\uproot{3}#1]}

Note that (as in your question), we do not need to specify the second argument, because \oldsqrt will look for it anyway, so that this definition is functionally equivalent to

\renewcommand\sqrt[2][]{\oldsqrt[\leftroot{-3}\uproot{3}#1]{#2}}

If you need several optional arguments or an argument other than the first one should be optional, you can either chain \@ifnextchars (as in Yiannis' answer), or use xparse (as in Peter's answer).

share|improve this answer
    
Thanks! Just to be clear, you still need the line \let\oldsqrt\sqrt before the \renewcommand. –  jamaicanworm Mar 23 '12 at 17:11

The primitive \def does not understand optional arguments. That is provided in LaTeX only. What you have defined is a delimited argument:

  \def\sqrt[#1]{...}

which means that the input must always be provided as [...], you could have written anything instead of []. To have an optional argument you need to define it in LaTeX using the following method:

  \DeclareRobustCommand\sqrt{\@ifnextchar[{true statement}{false statement}}

The @\ifnextchar checks to see if there is an [ and branches accordingly. You will need to modify your script on this basis.

The commands are normally defined to call two macros, one delimited and another undelimited, as for example:

  \makeatletter
  \DeclareRobustCommand\sqrt{\@ifnextchar[{\@@sqrt}{\@sqrt}}
  \def\@@sqrt[#1]{I have a square bracket #1}  
  \def\@sqrt#1{I don't have a square bracket #1}
  \sqrt{1}
  \sqrt[3]

Now redefining amsmath macros, is like walking barefoot on a coal fire, so a few more items need to be taken care of. Firstly to let save the old command, we use Oberdiek's package letltxmacro

   \LetLtxMacro{\oldsqrt}{\sqrt}

The rest are shown in the minimal below:

\documentclass{article}
\usepackage{fouriernc} % use the New Century Schoolbook font
\usepackage{amsmath}
\usepackage{letltxmacro}
\makeatletter
\begin{document}
\LetLtxMacro{\oldsqrt}{\sqrt}
\DeclareRobustCommand\sqrt{\@ifnextchar[\@@sqrt\oldsqrt}
\newcommand\@@sqrt[2][]{\oldsqrt[\leftroot{-3}\uproot{3}#1]{#2}}  
\[
   \sqrt{\alpha}\qquad
   \sqrt[\beta]{k} \qquad
   \sqrt[c]{k} \qquad
   \sqrt[d]{k}
\]
\end{document}

enter image description here

share|improve this answer
1  
@jamaicanworm It will freeze if you redefine it, as you will have infinite regression. Will post a full answer a bit later in the date. –  Yiannis Lazarides Mar 23 '12 at 2:10
1  
@jamaicanworm Please see edit done after two caffeine injections:) –  Yiannis Lazarides Mar 23 '12 at 3:21
1  
@YiannisLazarides The \ensuremath in the definition of \@@sqrt you're using is wrong and not from a stylistic point of view. Also it's not clear why using \DeclareRobustCommand for \@@sqrt. Note also that redefining \sqrt in this way will prevent further usage of \leftroot and \uproot. –  egreg Mar 23 '12 at 9:42
1  
@egreg Thanks. Was sure I missed something and the reason I am normally reluctant to touch anything amsmath. I would appreciate it if you edit a correction in, otherwise will apply a correction in the evening. OP wanted to fix the parameters so I am not over worried about losing \leftroot –  Yiannis Lazarides Mar 23 '12 at 10:06
2  
It is what I am looking for. (+100) –  In PSTricks we trust Mar 23 '12 at 16:42

Using a new command: \mysqrt:

This is what I was suggesting in the comments to Nice-looking p-th roots using the xparse package to make the first three parameters optional:

\NewDocumentCommand{\mysqrt}{O{} O{-2} O{2}  m}{\sqrt[\leftroot{#2}\uproot{#3}#1]{#4}}

Then $\mysqrt[p]{a}$ would produce the desired result:

enter image description here

Note that the first optional parameter in the index of the \sqrt. The following two options are the tweaks that get applied to the \leftroot (defaults to -2 in the above code) and the \uproot (defaults to 2).

The same examples from the linked question would be specified as where the left uses the default settings and the right uses the manual tweaks:

\[\mysqrt[\beta]{k}            \quad\mysqrt[\beta][-3][3]{k}          \]
\[\mysqrt[\beta]{\frac{k}{h}}  \quad\mysqrt[\beta][-2][6]{\frac{k}{h}}\]

yielding:

enter image description here

\documentclass{article}
\usepackage{amsmath}
\usepackage{xparse}

\NewDocumentCommand{\mysqrt}{O{} O{-2} O{2}  m}{%
    \sqrt[\leftroot{#2}\uproot{#3}#1]{#4}%
}%

\begin{document}\noindent
This $\mysqrt[p]{a}$ looks better than $\sqrt[p]{a}$,
since the $p$ does not intersect the root symbol.
\end{document}

Redefine the existing \sqrt macro:

If you wish to redfine the \sqrt globally then you have to use \LetLtxMacro from the letltxmacro package since \sqrt has optional parameters already.

References:

The following produces results identical to the second image above:

\documentclass{article}
\usepackage{amsmath}
\usepackage{xparse}
\usepackage{letltxmacro}

\LetLtxMacro{\OldSqrt}{\sqrt}

\RenewDocumentCommand{\sqrt}{O{} O{-2} O{2}  m}{\OldSqrt[\leftroot{#2}\uproot{#3}#1]{#4}}%

\begin{document}\noindent
\[\sqrt[\beta]{k}            \quad\sqrt[\beta][-3][3]{k}          \]
\[\sqrt[\beta]{\frac{k}{h}}  \quad\sqrt[\beta][-2][6]{\frac{k}{h}}\]
\end{document}
share|improve this answer
    
Thanks for your help! The problem is that I already have a long document with many uses of \sqrt. I want to re-define the \sqrt command at the top of the document, without having to find-and-replace each one with \mysqrt. –  jamaicanworm Mar 23 '12 at 1:35
1  
@jamaicanworm: Ok, have provided a solution for that as well. –  Peter Grill Mar 23 '12 at 1:41
1  
Nice piece of work! –  percusse Mar 23 '12 at 1:49

This answer is about solving the specific problem, that is, initializing \leftroot and \uproot to different values from the default, leaving intact the possibility of using them for particular cases.

The trick is to notice that amsmath uses the values given as arguments to \leftroot and \uproot to set two count registers, \leftroot@ and \uproot@ which are initialized to zero. This happens in the internal macro called \root. Thus one can do

\usepackage{etoolbox}
\makeatletter
\patchcmd{\root}{\uproot@\z@}{\uproot@3 }{}{}
\patchcmd{\root}{\leftroot@\z@}{\leftroot@-3 }{}{}
\makeatother

and now those initial values will be applied, but saying

\sqrt[\leftroot{1}x]{y}

would give the same result as \sqrt[\leftroot{1}\uproot{3}x]{y} without the patching, which might be useful in particular cases. Similarly, \sqrt[\leftroot{0}\uproot{0}x]{y} would give the same result as the original \sqrt[x]{y}.

As Stefan Lehmke points out in his comment, changing the meaning of \sqrt is not really recommended. However, setting a different default for \leftroot and \uproot could be justified with some document fonts. The important thing is to know how the new \sqrt behaves with respect to \leftroot and \uproot.

Making \leftroot and \uproot adding to the default requires a very extensive patching of \root:

\makeatletter
\def\default@leftroot{-3} % set the default value of leftroot
\def\default@uproot{3}    % set the default value of uproot
\renewcommand{\root}{\relaxnext@
  \DN@{\ifx\@let@token\uproot\let\next@\nextii@\else
   \ifx\@let@token\leftroot\let\next@\nextiii@\else
   \let\next@\plainroot@\fi\fi\next@}%
  \def\nextii@\uproot##1{\uproot@\numexpr(\default@uproot+##1)\relax\FN@\nextiv@}%
  \def\nextiv@{\ifx\@let@token\@sptoken\DN@. {\FN@\nextv@}\else
   \DN@.{\FN@\nextv@}\fi\next@.}%
  \def\nextv@{\ifx\@let@token\leftroot\let\next@\nextvi@\else
   \let\next@\plainroot@\fi\next@}%
  \def\nextvi@\leftroot##1{\leftroot@\numexpr(\default@leftroot+##1)\relax\plainroot@}%
   \def\nextiii@\leftroot##1{\leftroot@\numexpr(\default@leftroot+##1)\relax\FN@\nextvii@}%
  \def\nextvii@{\ifx\@let@token\@sptoken
   \DN@. {\FN@\nextviii@}\else
   \DN@.{\FN@\nextviii@}\fi\next@.}%
  \def\nextviii@{\ifx\@let@token\uproot\let\next@\nextix@\else
   \let\next@\plainroot@\fi\next@}%
  \def\nextix@\uproot##1{\uproot@\numexpr(\default@uproot+##1)\relax\plainroot@}%
  \bgroup\uproot@\default@uproot \leftroot@\default@leftroot\relax \FN@\next@}
\makeatother

(Thanks to Stefan Lehmke for spotting an error in the initial version.)

share|improve this answer
1  
Here's a slightly less invasive patch: \def\mynextvi@root\leftroot#1{\advance\leftroot@#1\relax\plainroot@}% \def\mynextiii@root\leftroot#1{\advance\leftroot@#1\relax\FN@\nextvii@}% \def\mynextii@root\uproot#1{\advance\uproot@#1\relax\FN@\nextiv@}% \patchcmd{\root}{\uproot@\z@}{\uproot@3 }{}{} \patchcmd{\root}{\leftroot@\z@}{\leftroot@-10\let\nextii@\mynextii@root\let\next‌​iii@\mynextiii@root\let\nextvi@\mynextvi@root}{}{} But that's a matter of taste I assume. While you're at it, you could consider putting the defaults into global registers... Darn, no newlines in comments... –  Stephan Lehmke Mar 23 '12 at 11:19
1  
Parametrizing the defaults was indeed the next step (I thought to it just after closing the edit, but I had to go and catch the train). –  egreg Mar 23 '12 at 11:22
    
Thanks! In your patch, why are \makeatletter and \makeatother necessary? –  jamaicanworm Mar 23 '12 at 15:35
1  
@jamaicanworm Those are necessary because we are using commands with @ in their names. –  egreg Mar 23 '12 at 15:56

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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