%% skmath improved math commands
%%
%% Copyright (C) 2012-2016 by Simon Sigurdhsson <sigurdhsson@gmail.com>
%%
%% This work may be distributed and/or modified under the
%% conditions of the LaTeX Project Public License, either version 1.3
%% of this license or (at your option) any later version.
%% The latest version of this license is in
%%   http://www.latex-project.org/lppl.txt
%% and version 1.3 or later is part of all distributions of LaTeX
%% version 2005/12/01 or later.
%%
%% This work has the LPPL maintenance status `maintained'.
%%
%% The Current Maintainer of this work is Simon Sigurdhsson.
%%
%% This work consists of the file skmath.tex
%% and the derived file skmath.sty.
\PassOptionsToPackage{intlimits,sumlimits,namelimits}{amsmath}
\documentclass[commonsets,load]{skdoc}
\usepackage{amsmath}
\usepackage{csquotes}
\ProvideDocumentCommand\d{m}{#1}
\ProvideDocumentCommand\pd{smm}{#2#3}
\ProvideDocumentCommand\abs{m}{#1}
\ProvideDocumentCommand\norm{m}{#1}
\ProvideDocumentCommand\abs{m}{#1}
\ProvideDocumentCommand\P{m}{#1}
\ProvideDocumentCommand\given{}{}
\ProvideDocumentCommand\E{m}{#1}
\ProvideDocumentCommand\var{m}{#1}
\ProvideDocumentCommand\cov{mm}{#1#2}
\ProvideDocumentCommand\N{}{}
\ProvideDocumentCommand\Z{}{}
\ProvideDocumentCommand\Q{}{}
\ProvideDocumentCommand\R{}{}
\ProvideDocumentCommand\C{}{}
\ProvideDocumentCommand\ii{}{i}
\ProvideDocumentCommand\jj{}{j}
\ProvideDocumentCommand\sfrac{mm}{#1#2}
\ProvideDocumentCommand\argmin{om}{#1}
\ProvideDocumentCommand\argmax{om}{#1}

% Declare the target files
\SelfPreambleTo{\mypreamble}
\DeclareFile[key=package,preamble=\mypreamble]{skmath.sty}
\OnlyDescription

% Hack for LaTeX3 code
\ExplSyntaxOn
\cs_set_protected_nopar:Npn\ExplHack{
\char_set_catcode_letter:n{ 58 }
\char_set_catcode_letter:n{ 95 } }
\ExplSyntaxOff

% This is where the documentation begins
\begin{document}
  % Change & version info
  \version{0.4a}
  \changes{0.1}{Initial version}
  \changes{0.1c}{Moved package from \pkg{docstrip} to \pkg{skdoc}}
  \changes{0.1d}{Fixed fatal documentation and package errors}
  \changes{0.1e}{Added statistics commands}
  \changes{0.1g}{Documentation fixes}
  \changes{0.2}{Use \pkg{expl3} functionality throughout the package}
  \changes{0.3}{Added \cs{min}/\cs{max} and friends. Added \cs{pd}}
  \changes{0.3a}{Added \cs{sinh}, \cs{cosh} and \cs{tanh}}
  \changes{0.3b}{Detect empty arguments in trigonometric and logarithmic functions, fix \cs{ln}}
  \changes{0.4}{Added \opt{notation} option, macros for complex numbers}
  \changes{0.4a}{Replaced deprecated/removed \pkg{expl3} constructs}
  % Don't forget to update the version number and release date of
  % the package declaration in the implementation!

  % Metadata
  \package[ctan=skmath,vcs=https://github.com/urdh/skmath]{skmath}
  \author{Simon Sigurdhsson}
  \email{sigurdhsson@gmail.com}

  % First page
  \maketitle
  \begin{abstract}
    The \thepackage\ package provides improved and new math commands
    for superior typesetting with less effort.
  \end{abstract}

  \section{Introduction}
  This package intends to provide helpful (re-)definitions of commands
  related to typesetting mathematics, and specifically typesetting
  them in a more intuitive, less verbose and more beautiful way.
  It was originally not intended for use by the public, and as such
  there may be incompatibilities with other packages of which I am
  not aware, but I figured it could be useful to other people as well.

  \section{Usage}
  \subsection{Options}
  As of version \theversion, the package provides two key-value options.

  \Option{commonsets}\WithValues{true,false}\AndDefault{false}
  Optionally define \cs{N}, \cs{Z}, \cs{Q}, \cs{R} and \cs{C} as blackboard
  variants of the respective letters, to represent the common sets
  of numbers.

  \Option{notation}\WithValues{iso,english,german,legacy}\AndDefault{legacy}
  This option controls the style of a few typographic elements that differ
  between countries and standards (such as the style of integrals, derivatives
  and greek letters).

  \subsection{New commands}
  The package defines a number of new commands that aid in typesetting
  certain mathematical formulae.

  \DescribeMacro\N
  \DescribeMacro\Z
  \DescribeMacro\Q
  \DescribeMacro\R
  \DescribeMacro\C
  These commands are only available if the \opt{commonsets}
  option is given. They typeset the set of natural, integer, rational,
  real and complex numbers respectively.
\begin{example}
\begin{equation*}
  \N, \Z, \Q, \R, \C.
\end{equation*}
\end{example}

  \DescribeMacro\ii
  \DescribeMacro\jj
  These commands typeset the imaginary unit (either \(\ii\) as used in
  mathematics or \(\jj\) as used in electrotechnology). While normal use
  of the package simply results in italic characters, setting the \opt{notation}
  option to \texttt{iso} will set these upright.

  \DescribeMacro\norm{<expression>}
  \DescribeMacro\abs{<expression>}
  The commands \Macro\norm and \Macro\abs, quite expectedly, typeset
  the norm ans absolute value of an expression, respectively. They
  have one mandatory argument (the expression), and different norms
  can be achieved by appending a subscript after the argument of
  \Macro\norm.
\begin{example}
\begin{equation*}
  \norm{\vec{x}}_p =
    \left(\sum_{i=1}^n \abs{x_i}^p\right)%
      ^{\sfrac{1}{p}}
\end{equation*}
\end{example}

  \DescribeMacro\d{<variable>}
  There is also a command \Macro\d, with one mandatory argument, that
  typesets the differential part of an integral.
\begin{example}
\begin{equation*}
  \int_{\R}\! \frac{\sin{x}}{x} \d{x}
\end{equation*}
\end{example}

  \DescribeMacro\pd*{<function>}{<var>,\meta{var},...}
  This macro typesets a partial derivative. The starred variant typesets
  derivatives as subscripts, i.e. \(\pd*{f}{x^2,y}\), while the unstarred
  variant typesets full fractions:
\begin{example}
\begin{equation*}
  \pd{f}{x^m,y^n}
\end{equation*}
\end{example}

  As the example shows, the comma-separated list of variables also
  supports superscripts to denote the number of derivatives, and the
  sum of the variables is automatically calculated.

  \DescribeMacro\E{<expression>}
  The command \Macro\E typesets the expectation of a random variable.
\begin{example}
\begin{equation*}
  \E{\hat{\mu}} = \mu
\end{equation*}
\end{example}

  \DescribeMacro\P{<expression>\AlsoMacro\given <expression>}
  The \Macro\P command typesets a probability. The \Macro\given command
  can be used to typeset conditional probabilities, within \Macro\P.
\begin{example}
\begin{equation*}
  \P{A\given B} =
    \frac{\P{B\given A}\P{A}}{\P{B}}
\end{equation*}
\end{example}

  \DescribeMacro\var{<expression>}
  \DescribeMacro\cov{<expression>}{<expression>}
  The commands \Macro\var and \Macro\cov typeset the variance and
  covariance of an expression.
\begin{example}
\begin{gather*}
  \var{X} = \E{(X-\mu)^2}\\
  \cov{X}{Y} = \E{XY}-\E{X}\E{Y}
\end{gather*}
\end{example}

  \subsection{Improved commands}
  In addition to adding new commands, this package also redefines
  already existing commands in a mostly backwards-compatible way
  to improve their usefulness.

  \DescribeMacro\sin[<power>]{<expression>}
  \DescribeMacro\arcsin{<expression>}
  \DescribeMacro\cos[<power>]{<expression>}
  \DescribeMacro\arccos{<expression>}
  \DescribeMacro\tan[<power>]{<expression>}
  \DescribeMacro\arctan{<expression>}
  \DescribeMacro\cot[<power>]{<expression>}
  \DescribeMacro\sinh[<power>]{<expression>}
  \DescribeMacro\cosh[<power>]{<expression>}
  \DescribeMacro\tanh[<power>]{<expression>}
  The trigonometric functions have been redefined
  to typeset more easily. They typeset \meta{expression} as an
  argument of the expression, and (if applicable) \meta{power} as
  a superscript between the function and its argument,
  \emph{e.g.} \(\sin[2]{\phi}\).
  When the argument is empty, no parentheses are emitted: \(\cos{}\).

  \DescribeMacro\ln{<expression>}
  The natural logarithm macro \Macro\ln has also been redefined to
  require an argument which is typeset as the argument of the logarithm.
  \DescribeMacro\log[<base>]{<expression>}
  The related macro \Macro\log is redefined in a similar way, but also
  accepts an optional argument denoting the base of the logarithm:
  \(\log[2]{x}\).
  As with the trigonometric functions, no parentheses are emitted if
  the mandatory argument is empty: \(\log{}\).

  \DescribeMacro\exp*{<expression>}
  The exponential, \Macro\exp, is redefined to typeset its argument as a
  superscript of \(e\) in some display styles, and as an argument of
  \(\mathrm{exp}\) otherwise:
  \begin{equation*}
    \exp{\sqrt{2}\exp{x}}
  \end{equation*}
  Additionally, it is possible to force the \(\mathrm{exp}\) mode by
  using the starred variant.

  \DescribeMacro\min*[<domain>]{<expression>}
  \DescribeMacro\argmin*[<domain>]{<expression>}
  \DescribeMacro\max*[<domain>]{<expression>}
  \DescribeMacro\argmax*[<domain>]{<expression>}
  \DescribeMacro\sup*[<domain>]{<expression>}
  \DescribeMacro\inf*[<domain>]{<expression>}
  The maximum/minimum macros have been redefined in a manner similar to
  the trigonometric functions. They typeset \meta{expression} inside
  curly brackets (the starred version omits the brackets), with the
  optional \meta{domain} typeset in a subscript after the operator
  (\emph{e.g.} \(\min*[x\in\R_{+}]{f(x)}\)). Argument variants are also
  provided, and the \meta{expression} is centered underneath the operator
  if possible:
  \begin{equation*}
    \argmin*[x\in\R_{+}]{f(x)}
  \end{equation*}

  \subsection{Stylistic changes}
  Some commands have been redefined in a completely backwards-compatible
  way to improve the end result of their typesetting.

  \DescribeMacro\frac{<numerator>}{<denominator>}
  The \Macro\frac command has been changed to improve typesetting,
  allowing displaystyle math in some settings.

  \DescribeMacro\bar{<expression>}
  \DescribeMacro\vec{<expression>}
  The \Macro\bar command has been changed to cover the entire
  \meta{expression} (\emph{i.e.} \(\bar{uv}\)), and \Macro\vec has
  been changed to match the \cs{vectorsym} command provided by
  \pkg{isomath}.

  \DescribeMacro\Re{<expression>}
  \DescribeMacro\Im{<expression>}
  These commands typeset the real and imaginary part of a number. Standard use
  of the package takes definitions roughly from \pkg{amsmath}, while setting
  the \opt{notation} option to \texttt{iso} changes the definitions to match
  ISO~80000-2.

  \section{Known issues}
  A list of current issues is available in the Github repository of this
  package\footnote{\url{https://github.com/urdh/skmath/issues}}, but as
  of the release of \theversion, there is one known issue.
  \begin{description}
      \item[\#15] The package is incompatible with (at least)
        \pkg{blindtext}, when including math in the blind text. This
        is due to the redifinition of \cs{sin} (and friends), which
        is incompatible with the original \pkg{amsmath} definition.
        This is a feature, not a bug.
  \end{description}

  If you discover any bugs in this package, please report them to the issue
  tracker in the \thepackage\ Github repository.

  \Implementation\ExplHack
  \section{Implementation}
  The package implementation is very simple. First, we do the standard
  \LaTeXe\ preamble thing, then we require some dependencies.
  \changes{0.1b}{Load \pkg{amsmath} with \texttt{intlimits} option}
  \changes{0.2a}{Load \pkg{amsmath} with more \texttt{limits} options}
\begin{MacroCode}{package}
\RequirePackage{expl3,l3keys2e,xparse}
\ProvidesExplPackage{skmath}
    {2016/06/25}{0.4a}{improved math commands}
\PassOptionsToPackage{intlimits,sumlimits,namelimits}{amsmath}
\RequirePackage{amssymb,mathtools,xfrac}
\end{MacroCode}

We start by declaring internal options related to the notation styles.
First, some placeholders to detect failures.
\begin{MacroCode}{package}
\msg_new:nnnn{skmath}{undefined-macro}{The~macro~`\token_to_str:N#1'~was~undefined!}
  {This~is~an~error~in~the~notation~option~handling.~Please~file~an~issue\\
   on~Github~(https://github.com/urdh/skmath/issues)~with~a~copy~of~this\\
   message~attached~as~well~as~a~list~of~the~options~passed~to~`skmath'.}
\cs_gset_nopar:Npn\__skmath_integral_d:{
  \msg_critical:nnn{skmath}{undefined-macro}{\__skmath_integral_d:}
}
\cs_gset_nopar:Npn\__skmath_natural_log_e:{
  \msg_critical:nnn{skmath}{undefined-macro}{\__skmath_natural_log_e:}
}
\cs_gset_nopar:Npn\__skmath_imaginary_unit:n#1{
  \msg_critical:nnn{skmath}{undefined-macro}{\__skmath_imaginary_unit:n}
}
\end{MacroCode}
Then, the key-value options.
\begin{MacroCode}{package}
\keys_define:nn{skmath / internal}{
  % More on this:
  % * http://en.wikipedia.org/wiki/Typographical_conventions_in_mathematical_formulae
  % * ISO 80000-2
  % * http://www.tug.org/TUGboat/Articles/tb18-1/tb54becc.pdf
  % * http://tex.stackexchange.com/q/14821/66
  integral-d .choice:,
  integral-d .value_required:,
  integral-d / upright .code:n = { \cs_gset_nopar:Npn\__skmath_integral_d:{{\operator@font d}} },
  integral-d / slanted .code:n = { \cs_gset_nopar:Npn\__skmath_integral_d:{{d}} },
  isomath .bool_set:N = \g__skmath_load_isomath_bool,
  isomath .value_required:,
  natural-log .choice:,
  natural-log .value_required:,
  natural-log / upright .code:n = { \cs_gset_nopar:Npn\__skmath_natural_log_e:{{\operator@font e}} },
  natural-log / slanted .code:n = { \cs_gset_nopar:Npn\__skmath_natural_log_e:{{e}} },
  imaginary-unit .choice:,
  imaginary-unit .value_required:,
  imaginary-unit / upright .code:n = { \cs_gset_nopar:Npn\__skmath_imaginary_unit:n##1{{\operator@font ##1}} },
  imaginary-unit / slanted .code:n = { \cs_gset_nopar:Npn\__skmath_imaginary_unit:n##1{{##1}} },
  complex-part-symbols .bool_set_inverse:N = \g__skmath_iso_complex_parts_bool,
  complex-part-symbols .value_required:,
}
\end{MacroCode}

We also declare the \enquote{public} options.
\begin{MacroCode}{package}
\keys_define:nn{skmath}{
  commonsets .bool_set:N = \g__skmath_define_common_sets_bool,
  commonsets .default:n = true,
  commonsets .initial:n = false,
  % TODO: write tests for the notation option
  notation .choice:,
  notation / iso .meta:nn = {skmath / internal}{
    integral-d = upright,
    isomath    = true,
    natural-log = upright,
    imaginary-unit = upright,
    complex-part-symbols = false,
  },
  notation / german .meta:nn = {skmath / internal}{
    integral-d = upright,
    isomath    = true,
    natural-log = slanted, %???
    imaginary-unit = slanted, %???
    complex-part-symbols = true, %???
  },
  notation / english .meta:nn = {skmath / internal}{
    integral-d = slanted,
    isomath    = true,
    natural-log = slanted, %???
    imaginary-unit = slanted, %???
    complex-part-symbols = true, %???
  },
  notation / legacy .meta:nn = {skmath / internal}{
    integral-d = upright,
    isomath    = true,
    natural-log = slanted,
    imaginary-unit = slanted,
    complex-part-symbols = true,
  },
  % Possibly more style sets... ?
  notation .initial:n = legacy, % Or is it? Perhaps a legacy option is required.
  notation .value_required:,
  % Note also that the styles should probably affect isomath and/or other packages.
}
\ProcessKeysOptions{skmath}
\end{MacroCode}

We optionally load \pkg{isomath}, depending on notation style.
\begin{MacroCode}{package}
\bool_if:NTF\g__skmath_load_isomath_bool{
  \RequirePackage{isomath}
}{
  % TODO: check if there is an alternative package we should load here.
}
\end{MacroCode}

  Then, a utility conditional\ldots
  \begin{macro*}{\__skmath_if_novalue_or_empty:nF}[1]
    {Token or string}
\begin{MacroCode}{package}
\prg_new_conditional:Npnn\__skmath_if_novalue_or_empty:n#1{F}{
  \IfNoValueTF{#1}{
    \prg_return_true:
  }{
    \tl_if_empty:nTF{#1}{
      \prg_return_true:
    }{
      \prg_return_false:
    }
  }
}
\end{MacroCode}
  \end{macro*}

  \ldots and a helper macro.
  \begin{macro*}{\__skmath_parens:n}[1]
    {Argument to wrap in parentheses, unless empty}
\begin{MacroCode}{package}
\cs_new_nopar:Npn\__skmath_parens:n#1{
  \__skmath_if_novalue_or_empty:nF{#1}{\left(#1\right)}
}
\end{MacroCode}
  \end{macro*}

  We optionally provide commands to typeset common sets.
\begin{MacroCode}{package}
\bool_if:NT\g__skmath_define_common_sets_bool{
\end{MacroCode}
  \begin{macro}{\N}
  \changes{0.1b}{Moved to \textsf{xparse} command definition}
\begin{MacroCode}{package}
  \NewDocumentCommand\N{}{\ensuremath{\mathbb{N}}}
\end{MacroCode}
  \end{macro}
  \begin{macro}{\Z}
  \changes{0.1b}{Moved to \textsf{xparse} command definition}
\begin{MacroCode}{package}
  \NewDocumentCommand\Z{}{\ensuremath{\mathbb{Z}}}
\end{MacroCode}
  \end{macro}
  \begin{macro}{\Q}
  \changes{0.1b}{Moved to \textsf{xparse} command definition}
\begin{MacroCode}{package}
  \NewDocumentCommand\Q{}{\ensuremath{\mathbb{Q}}}
\end{MacroCode}
  \end{macro}
  \begin{macro}{\R}
  \changes{0.1b}{Moved to \textsf{xparse} command definition}
\begin{MacroCode}{package}
  \NewDocumentCommand\R{}{\ensuremath{\mathbb{R}}}
\end{MacroCode}
  \end{macro}
  \begin{macro}{\C}
  \changes{0.1b}{Moved to \textsf{xparse} command definition}
\begin{MacroCode}{package}
  \NewDocumentCommand\C{}{\ensuremath{\mathbb{C}}}
\end{MacroCode}
  \end{macro}
\begin{MacroCode}{package}
}
\end{MacroCode}

  Then, macros related to complex numbers are defined.
  \begin{macro}{\ii}
\begin{MacroCode}{package}
\DeclareDocumentCommand\ii{}{\ensuremath{\__skmath_imaginary_unit:n{i}}}
\end{MacroCode}
  \end{macro}
  \begin{macro}{\jj}
\begin{MacroCode}{package}
\DeclareDocumentCommand\jj{}{\ensuremath{\__skmath_imaginary_unit:n{j}}}
\end{MacroCode}
  \end{macro}
  \begin{macro}{\Re}
\begin{MacroCode}{package}
\bool_if:NTF\g__skmath_iso_complex_parts_bool{
  \cs_new_eq:NN\__skmath_Re:\Re
  \DeclareDocumentCommand\Re{m}{\ensuremath{\__skmath_Re:\__skmath_parens:n{#1}}}
}{
  \DeclareDocumentCommand\Re{m}{\ensuremath{{\operator@font Re}{#1}}}
}
\end{MacroCode}
  \end{macro}
  \begin{macro}{\Im}
\begin{MacroCode}{package}
\bool_if:NTF\g__skmath_iso_complex_parts_bool{
  \cs_new_eq:NN\__skmath_Im:\Im
  \DeclareDocumentCommand\Im{m}{\ensuremath{\__skmath_Im:\__skmath_parens:n{#1}}}
}{
  \DeclareDocumentCommand\Im{m}{\ensuremath{{\operator@font Im}{#1}}}
}
\end{MacroCode}
  \end{macro}

  This is followed by commands to typeset the norm and absolute value.
  \begin{macro}{\abs}
\begin{MacroCode}{package}
\DeclarePairedDelimiter\abs{\lvert}{\rvert}
\end{MacroCode}
  \end{macro}
  \begin{macro}{\norm}
\begin{MacroCode}{package}
\DeclarePairedDelimiter\norm{\lVert}{\rVert}
\end{MacroCode}
  \end{macro}

  Next come the statistical commands.
  \begin{macro}{\E}
  \changes{0.1e}{Added \cs{E} command}
  \changes{0.1f}{Fixed \enquote{Command \cs{E} already defined!} error}
  \changes{0.2}{Use \cs{operatorname}}
  Here, we define \cs{E} after the preamble since it may break otherwise.
\begin{MacroCode}{package}
\AtBeginDocument{
  \DeclareDocumentCommand\E{m}{%
    \ensuremath{\operatorname{E}\left[#1\right]}%
  }
}
\end{MacroCode}
  \end{macro}
  The \Macro\P command saves any old \Macro\given command, replacing
  it locally with the new \Macro\given command provided by the package.
  \begin{macro}{\P}
  \changes{0.1e}{Added \cs{P} command}
  \changes{0.2}{Use \cs{operatorname}, use \cs{cs_new_eq:NN} instead of
                \cs{let}}
\begin{MacroCode}{package}
\DeclareDocumentCommand\P{m}{%
  \ensuremath{\operatorname{P}%
    \mkern-1.5mu\left(%
    \cs_set_eq:NN\__skmath_saved_given:\given%
\end{MacroCode}
  \begin{macro}{\given}
  \changes{0.1e}{Added \cs{given} command}
\begin{MacroCode}{package}
    \DeclareDocumentCommand\given{}{\mid}%
\end{MacroCode}
  \end{macro}
\begin{MacroCode}{package}
    #1%
    \cs_set_eq:NN\given\__skmath_saved_given:%
    \right)%
  }%
}
\end{MacroCode}
  \end{macro}
  \begin{macro}{\var}
  \changes{0.1e}{Added \cs{var} command}
  \changes{0.2}{Use \cs{operatorname}}
\begin{MacroCode}{package}
\DeclareDocumentCommand\var{m}{%
  \ensuremath{\operatorname{Var}\left(#1\right)}%
}
\end{MacroCode}
  \end{macro}
  \begin{macro}{\cov}
  \changes{0.1e}{Added \cs{cov} command}
  \changes{0.2}{Use \cs{operatorname}}
\begin{MacroCode}{package}
\DeclareDocumentCommand\cov{mm}{%
  \ensuremath{\operatorname{Cov}\left(#1,#2\right)}%
}
\end{MacroCode}
  \end{macro}

  We replace all trigonometric functions and some other
  common functions with alternatives that take an argument
  (or optionally, several arguments).
\begin{MacroCode}{package}
\cs_new_eq:NN\__skmath_sin:\sin
\cs_new_eq:NN\__skmath_cos:\cos
\cs_new_eq:NN\__skmath_tan:\tan
\cs_new_eq:NN\__skmath_cot:\cot
\cs_new_eq:NN\__skmath_arcsin:\arcsin
\cs_new_eq:NN\__skmath_arccos:\arccos
\cs_new_eq:NN\__skmath_arctan:\arctan
\cs_new_eq:NN\__skmath_sinh:\sinh
\cs_new_eq:NN\__skmath_cosh:\cosh
\cs_new_eq:NN\__skmath_tanh:\tanh
\cs_new_eq:NN\__skmath_ln:\ln
\cs_new_eq:NN\__skmath_log:\log
\cs_new_eq:NN\__skmath_exp:\exp
\cs_new_eq:NN\__skmath_min:\min
\cs_new_eq:NN\__skmath_max:\max
\cs_new_eq:NN\__skmath_sup:\sup
\cs_new_eq:NN\__skmath_inf:\inf
\end{MacroCode}
  \begin{macro}{\sin}
\begin{MacroCode}{package}
\RenewDocumentCommand\sin{om}{%
  \IfNoValueTF{#1}
    {\ensuremath{\__skmath_sin:\__skmath_parens:n{#2}}}
    {\ensuremath{\__skmath_sin:\c_math_superscript_token{#1}\__skmath_parens:n{#2}}}%
}
\end{MacroCode}
  \end{macro}
  \begin{macro}{\cos}
\begin{MacroCode}{package}
\RenewDocumentCommand\cos{om}{%
  \IfNoValueTF{#1}
    {\ensuremath{\__skmath_cos:\__skmath_parens:n{#2}}}
    {\ensuremath{\__skmath_cos:\c_math_superscript_token{#1}\__skmath_parens:n{#2}}}%
}
\end{MacroCode}
  \end{macro}
  \begin{macro}{\tan}
\begin{MacroCode}{package}
\RenewDocumentCommand\tan{om}{%
  \IfNoValueTF{#1}
    {\ensuremath{\__skmath_tan:\__skmath_parens:n{#2}}}
    {\ensuremath{\__skmath_tan:\c_math_superscript_token{#1}\__skmath_parens:n{#2}}}%
}
\end{MacroCode}
  \end{macro}
  \begin{macro}{\cot}
\begin{MacroCode}{package}
\RenewDocumentCommand\cot{om}{%
  \IfNoValueTF{#1}
    {\ensuremath{\__skmath_cot:\__skmath_parens:n{#2}}}
    {\ensuremath{\__skmath_cot:\c_math_superscript_token{#1}\__skmath_parens:n{#2}}}%
}
\end{MacroCode}
  \end{macro}
  \begin{macro}{\arcsin}
\begin{MacroCode}{package}
\RenewDocumentCommand\arcsin{m}{%
  \ensuremath{\__skmath_arcsin:\__skmath_parens:n{#1}}%
}
\end{MacroCode}
  \end{macro}
  \begin{macro}{\arccos}
\begin{MacroCode}{package}
\RenewDocumentCommand\arccos{m}{%
  \ensuremath{\__skmath_arccos:\__skmath_parens:n{#1}}%
}
\end{MacroCode}
  \end{macro}
  \begin{macro}{\arctan}
\begin{MacroCode}{package}
\RenewDocumentCommand\arctan{m}{%
  \ensuremath{\__skmath_arctan:\__skmath_parens:n{#1}}%
}
\end{MacroCode}
  \end{macro}
  \begin{macro}{\sinh}
\begin{MacroCode}{package}
\RenewDocumentCommand\sinh{om}{%
  \IfNoValueTF{#1}
    {\ensuremath{\__skmath_sinh:\__skmath_parens:n{#2}}}
    {\ensuremath{\__skmath_sinh:\c_math_superscript_token{#1}\__skmath_parens:n{#2}}}%
}
\end{MacroCode}
  \end{macro}
  \begin{macro}{\cosh}
\begin{MacroCode}{package}
\RenewDocumentCommand\cosh{om}{%
  \IfNoValueTF{#1}
    {\ensuremath{\__skmath_cosh:\__skmath_parens:n{#2}}}
    {\ensuremath{\__skmath_cosh:\c_math_superscript_token{#1}\__skmath_parens:n{#2}}}%
}
\end{MacroCode}
  \end{macro}
  \begin{macro}{\tanh}
\begin{MacroCode}{package}
\RenewDocumentCommand\tanh{om}{%
  \IfNoValueTF{#1}
    {\ensuremath{\__skmath_tanh:\__skmath_parens:n{#2}}}
    {\ensuremath{\__skmath_tanh:\c_math_superscript_token{#1}\__skmath_parens:n{#2}}}%
}
\end{MacroCode}
  \end{macro}
  \begin{macro}{\ln}
\begin{MacroCode}{package}
\RenewDocumentCommand\ln{m}{%
  \ensuremath{\__skmath_ln:\__skmath_parens:n{#1}}%
}
\end{MacroCode}
  \end{macro}
  \begin{macro}{\log}
\begin{MacroCode}{package}
\RenewDocumentCommand\log{om}{%
  \IfNoValueTF{#1}
    {\ensuremath{\__skmath_log:\__skmath_parens:n{#2}}}
    {\ensuremath{\__skmath_log:\c_math_subscript_token{#1}\__skmath_parens:n{#2}}}%
}
\end{MacroCode}
  \end{macro}
  \begin{macro}{\exp}
  \changes{0.1b}{Moved to \textsf{xparse} command definition}
  \changes{0.3a}{Added starred variant}
\begin{MacroCode}{package}
\RenewDocumentCommand\exp{sm}{\ensuremath{
  \IfBooleanTF{#1}{
    \__skmath_exp:\__skmath_parens:n{#2}
  }{
    \mathchoice
      {\__skmath_natural_log_e:\c_math_superscript_token{#2}}
      {\__skmath_exp:\left(#2\right)}
      {\__skmath_exp:\left(#2\right)}
      {\__skmath_exp:\left(#2\right)}
  }
}}
\end{MacroCode}
  \end{macro}
  \begin{macro*}{\__skmath_minmax_backend:nnn}
\begin{MacroCode}{package}
\cs_new_nopar:Npn\__skmath_minmax_backend:nnnn#1#2#3#4{%
  \use:c{__skmath_#1:}
  \IfNoValueF{#3}{
    \c_math_subscript_token{
      \mathchoice{\mathclap{#3}}{#3}{#3}{#3}
    }
  }
  \IfBooleanTF{#2}{#4}{\left\{#4\right\}}
}
\end{MacroCode}
  \end{macro*}
  \begin{macro}{\min}
\begin{MacroCode}{package}
\RenewDocumentCommand\min{som}{%
  \ensuremath{\__skmath_minmax_backend:nnnn{min}{#1}{#2}{#3}}
}
\end{MacroCode}
  \end{macro}
  \begin{macro}{\argmin}
\begin{MacroCode}{package}
\NewDocumentCommand\argmin{som}{%
  \ensuremath{\arg\__skmath_minmax_backend:nnnn{min}{#1}{#2}{#3}}
}
\end{MacroCode}
  \end{macro}
  \begin{macro}{\max}
\begin{MacroCode}{package}
\RenewDocumentCommand\max{som}{%
  \ensuremath{\__skmath_minmax_backend:nnnn{max}{#1}{#2}{#3}}
}
\end{MacroCode}
  \end{macro}
  \begin{macro}{\argmax}
\begin{MacroCode}{package}
\NewDocumentCommand\argmax{som}{%
  \ensuremath{\arg\__skmath_minmax_backend:nnnn{max}{#1}{#2}{#3}}
}
\end{MacroCode}
  \end{macro}
  \begin{macro}{\sup}
\begin{MacroCode}{package}
\RenewDocumentCommand\sup{som}{%
  \ensuremath{\__skmath_minmax_backend:nnnn{sup}{#1}{#2}{#3}}
}
\end{MacroCode}
  \end{macro}
  \begin{macro}{\inf}
\begin{MacroCode}{package}
\RenewDocumentCommand\inf{som}{%
  \ensuremath{\__skmath_minmax_backend:nnnn{inf}{#1}{#2}{#3}}
}
\end{MacroCode}
  \end{macro}

  The fraction command is modified to improve typesetting.
  \begin{macro}{\frac}
  \changes{0.1b}{Moved to \textsf{xparse} command definition}
\begin{MacroCode}{package}
\RenewDocumentCommand\frac{mm}{\genfrac{}{}{}{}%
             {\displaystyle #1}{\displaystyle #2}}
\end{MacroCode}
  \end{macro}

  We introduce a couple of helper macros for the \cs{pd} macro backend.
  \begin{macro*}{\__skmath_if_numerical_p:n}
  \begin{macro*}{\__skmath_if_numerical:nT}
  \begin{macro*}{\__skmath_if_numerical:nF}
  \begin{macro*}{\__skmath_if_numerical:nTF}[1]
    {Token or string}
\begin{MacroCode}{package}
\prg_new_conditional:Npnn\__skmath_if_numerical:n#1{p,T,F,TF}{
  \str_case_x:nnTF{#1}{
    {0}{}
    {1}{}
    {2}{}
    {3}{}
    {4}{}
    {5}{}
    {6}{}
    {7}{}
    {8}{}
    {9}{}
  }
  {\prg_return_false:}
  {\prg_return_false:}
}
\end{MacroCode}
  \end{macro*}
  \end{macro*}
  \end{macro*}
  \end{macro*}
  \begin{macro*}{\__skmath_pd_vars_sum:n}[1]
    {Comma-separated list of variables, possibly with superscripts}
\begin{MacroCode}{package}
\cs_new_nopar:Npn\__skmath_pd_vars_sum:n#1{
  \tl_clear:N\l_tmpa_tl
  \int_zero:N\l_tmpa_int
  \bool_set_true:N\l_tmpa_bool
  \clist_set:Nn\l_tmpa_clist{#1}
  \clist_map_inline:Nn\l_tmpa_clist{
    \seq_set_split:Nnn\l_tmpa_seq{^}{##1}
    \int_compare:nT{\seq_count:N\l_tmpa_seq<\c_two}{
      \seq_put_right:Nn\l_tmpa_seq{1}
    }
    \seq_get_right:NN\l_tmpa_seq\l_tmpb_tl
    \__skmath_if_numerical:nTF{\tl_use:N\l_tmpb_tl}{
      \int_add:Nn\l_tmpa_int{\tl_use:N\l_tmpb_tl}
    }{
      \bool_set_false:N\l_tmpa_bool
      \tl_if_empty:NF\l_tmpa_tl{\tl_put_right:Nn\l_tmpa_tl{+}}
      \tl_put_right:Nx\l_tmpa_tl{\tl_use:N\l_tmpb_tl}
    }
  }
  \int_compare:nT{\l_tmpa_int>\c_zero}{\int_use:N\l_tmpa_int}
  \bool_if:NF\l_tmpa_bool{
    \int_compare:nT{\l_tmpa_int>\c_zero}{+}
    \tl_use:N\l_tmpa_tl
  }
}
\end{MacroCode}
  \end{macro*}
  \begin{macro*}{\__skmath_pd_if_vars_sum_above_one_p:n}
  \begin{macro*}{\__skmath_pd_if_vars_sum_above_one:nT}
  \begin{macro*}{\__skmath_pd_if_vars_sum_above_one:nF}
  \begin{macro*}{\__skmath_pd_if_vars_sum_above_one:nTF}[1]
    {Comma-separated list of variables, possibly with superscripts}
\begin{MacroCode}{package}
\prg_new_conditional:Npnn\__skmath_pd_if_vars_sum_above_one:n#1{p,T,F,TF}{
  \clist_set:Nn\l_tmpa_clist{#1}
  \int_compare:nTF{\clist_count:N\l_tmpa_clist>\c_one}{
    \prg_return_true:
  }{
    \clist_pop:NN\l_tmpa_clist\l_tmpa_tl
    \seq_set_split:NnV\l_tmpa_seq{^}{\l_tmpa_tl}
    \int_compare:nTF{\seq_count:N\l_tmpa_seq<\c_two}{
      \prg_return_false:
    }{
      \prg_return_true:
    }
  }
}
\end{MacroCode}
  \end{macro*}
  \end{macro*}
  \end{macro*}
  \end{macro*}
  \begin{macro*}{\__skmath_pd_superscript_vars:n}[1]
    {Comma-separated list of variables, possibly with superscripts}
\begin{MacroCode}{package}
\cs_new_nopar:Npn\__skmath_pd_superscript_vars:n#1{
  \clist_set:Nn\l_tmpa_clist{#1}
  \clist_map_inline:Nn\l_tmpa_clist{
    \partial
    \seq_set_split:Nnn\l_tmpa_seq{^}{##1}
    \seq_pop:NN\l_tmpa_seq\l_tmpb_tl
    \tl_use:N\l_tmpb_tl
    \int_compare:nT{\seq_count:N\l_tmpa_seq>0}{
      \seq_pop:NN\l_tmpa_seq\l_tmpb_tl
      \c_math_superscript_token
      \tl_use:N\l_tmpb_tl
    }
  }
}
\end{MacroCode}
  \end{macro*}
  \begin{macro*}{\__skmath_pd_subscript_vars:n}[1]
    {Comma-separated list of variables, possibly with superscripts}
\begin{MacroCode}{package}
\cs_new_nopar:Npn\__skmath_pd_subscript_vars:n#1{
  \clist_set:Nn\l_tmpa_clist{#1}
  \clist_map_inline:Nn\l_tmpa_clist{
    \seq_set_split:Nnn\l_tmpa_seq{^}{##1}
    \seq_pop:NN\l_tmpa_seq\l_tmpa_tl
    \int_set:Nn\l_tmpa_int{\c_one}
    \int_compare:nT{\seq_count:N\l_tmpa_seq>\c_zero}{
      \seq_pop:NN\l_tmpa_seq\l_tmpb_tl
      \int_set:Nn\l_tmpa_int{\tl_use:N\l_tmpb_tl}
    }
    \prg_replicate:nn{\l_tmpa_int}{\tl_use:N\l_tmpa_tl}
  }
}
\end{MacroCode}
  \end{macro*}
  \begin{macro*}{\__skmath_pd_fraction:nn}[2]
    {Tokens representing a mathematical function}
    {Comma-separated list of variables, possibly with superscripts}
\begin{MacroCode}{package}
\cs_new_nopar:Npn\__skmath_pd_fraction:nn#1#2{
  \frac{
    \partial
    \__skmath_pd_if_vars_sum_above_one:nT{#2}{
      \c_math_superscript_token{\__skmath_pd_vars_sum:n{#2}}
    }
    {#1}
  }{
    \__skmath_pd_superscript_vars:n{#2}
  }
}
\end{MacroCode}
  \end{macro*}
  \begin{macro*}{\__skmath_pd_subscript:nn}[2]
    {Tokens representing a mathematical function}
    {Comma-separated list of variables, possibly with superscripts}
\begin{MacroCode}{package}
\cs_new_nopar:Npn\__skmath_pd_subscript:nn#1#2{
  {#1}\c_math_subscript_token{
    \__skmath_pd_subscript_vars:n{#2}
  }
}
\end{MacroCode}
  \end{macro*}

  Definition of \cs{bar}, \cs{pd} and \cs{d} is deferred until after all
  packages are loaded to avoid collisions with other packages.
\begin{MacroCode}{package}
\AtBeginDocument{%
\end{MacroCode}
  The \cs{bar} command is modified to impove typesetting.
  \begin{macro}{\bar}
  \changes{0.1b}{Added \cs{bar} replacement}
  \changes{0.1h}{Wrap in \cs{AtBeginDocument}}
\begin{MacroCode}{package}
\DeclareDocumentCommand\bar{m}{%
    \ensuremath{\mkern 1.5mu\overline{\mkern-1.5mu{#1}\mkern-1.5mu}\mkern 1.5mu}}
\end{MacroCode}
  \end{macro}

  This is the partial derivative macro, but most of the functionality
  was defined as private macros earlier.
  \begin{macro}{\pd}[3]
    {Boolean distinguishing between starred and unstarred variant}
    {Tokens representing a mathematical function}
    {Comma-separated list of variables, possibly with superscripts}
\begin{MacroCode}{package}
\DeclareDocumentCommand\pd{smm}{
  \ensuremath{
    \IfBooleanTF{#1}
      {\__skmath_pd_subscript:nn{#2}{#3}}
      {\__skmath_pd_fraction:nn{#2}{#3}}
  }
}
\end{MacroCode}
  \end{macro}

  We introduce a command to typeset the differential part
  of integrals, shamefully stolen from an answer on \TeX.SE.
  \begin{macro}{\d}
  \changes{0.1a}{Fixed obtuse errors}
  \changes{0.1b}{Moved to \textsf{xparse} command definition}
  \changes{0.2}{Use \cs{peek_meaning_ignore_spaces:NT} instead of \cs{@ifnextchar}}
  \changes{0.3b}{Use \cs{operator@font} instead of \cs{mathrm}}
\begin{MacroCode}{package}
\DeclareDocumentCommand\d{m}{\ensuremath{\,\__skmath_integral_d: #1%
                              \peek_meaning_ignore_spaces:NT\d{\!}}}
\end{MacroCode}
  \end{macro}
\begin{MacroCode}{package}
}
\end{MacroCode}

  Finally, we define a nicer way to denote vectors.
  \begin{macro}{\vec}
  \changes{0.2}{Use \cs{cs_new_eq:NN} instead of \cs{let}}
\begin{MacroCode}{package}
\cs_set_eq:NN\vec\vectorsym
\end{MacroCode}
  \end{macro}

\begin{MacroCode}{package}
\endinput
\end{MacroCode}

    \Finale
    \section{Installation}
    The easiest way to install this package is using the package
    manager provided by your \LaTeX\ installation if such a program
    is available. Failing that, provided you have obtained the package
    source (\file{skmath.tex} and \file{Makefile}) from either CTAN
    or Github, running \texttt{make install} inside the source directory
    works well. This will extract the documentation and code from
    \file{skmath.tex}, install all files into the TDS tree at
    \texttt{TEXMFHOME} and run \texttt{mktexlsr}.

    If you want to extract code and documentation without installing
    the package, run \texttt{make all} instead. If you insist on not
    using \texttt{make}, remember that packages distributed using
    \pkg{skdoc} must be extracted using \texttt{pdflatex}, \emph{not}
    \texttt{tex} or \texttt{latex}.

    \PrintChanges
    \PrintIndex
\end{document}
