%% skmath improved math commands %% %% Copyright (C) 2012-2019 by Simon Sigurdhsson %% %% 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\td{mm}{#1#2} \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\ee{}{e} \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.5a} \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} \changes{0.4b}{Track \pkg{expl3} changes (thanks to Joseph Wright)} \changes{0.5}{Added \cs{td} and \cs{ee}} \changes{0.5a}{Track \pkg{expl3} changes (thanks to Phelype Oleinik)} % 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\ee This command typesets Euler's number \(\ee = \sum_{n=0}^\infty\frac{1}{n!}\). The style is affected by the \opt{notation} option in the same way as \Macro\exp. \DescribeMacro\norm{} \DescribeMacro\abs{} 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{} 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*{}{,\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\td{}{} This macro typesets a total derivative. Unlike \Macro\pd, this macro does not have a starred variant, and only typesets full fractions: \begin{example} \begin{equation*} \td{f}{x^m} \end{equation*} \end{example} \DescribeMacro\E{} 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{\AlsoMacro\given } 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{} \DescribeMacro\cov{}{} 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[]{} \DescribeMacro\arcsin{} \DescribeMacro\cos[]{} \DescribeMacro\arccos{} \DescribeMacro\tan[]{} \DescribeMacro\arctan{} \DescribeMacro\cot[]{} \DescribeMacro\sinh[]{} \DescribeMacro\cosh[]{} \DescribeMacro\tanh[]{} 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{} 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[]{} 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*{} The exponential, \Macro\exp, is redefined to typeset its argument as a superscript of \(\ee\) 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*[]{} \DescribeMacro\argmin*[]{} \DescribeMacro\max*[]{} \DescribeMacro\argmax*[]{} \DescribeMacro\sup*[]{} \DescribeMacro\inf*[]{} 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{}{} The \Macro\frac command has been changed to improve typesetting, allowing displaystyle math in some settings. \DescribeMacro\bar{} \DescribeMacro\vec{} 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{} \DescribeMacro\Im{} 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. \item[\#29] The spacing between operator names and parentheses is typographically incorrect. A work-around until this is fixed in \pkg{skmath} is to use the \cs{mleftright} macro from \pkg{mleftright} to redefine \cs{left} and \cs{right}. \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} {2019/10/15}{0.5a}{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} } \cs_gset_nopar:Npn\__skmath_total_derivative_d:{ \msg_critical:nnn{skmath}{undefined-macro}{\__skmath_total_derivative_d: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:n = true, 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:n = true, natural-log .choice:, natural-log .value_required:n = true, 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:n = true, 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:n = true, total-derivative-d .choice:, total-derivative-d .value_required:n = true, total-derivative-d / upright .code:n = { \cs_gset_nopar:Npn\__skmath_total_derivative_d:{{\operator@font d}} }, total-derivative-d / slanted .code:n = { \cs_gset_nopar:Npn\__skmath_total_derivative_d:{{d}} }, } \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, total-derivative-d = upright, }, notation / german .meta:nn = {skmath / internal}{ integral-d = upright, isomath = true, natural-log = slanted, %??? imaginary-unit = slanted, %??? complex-part-symbols = true, %??? total-derivative-d = upright, %??? }, notation / english .meta:nn = {skmath / internal}{ integral-d = slanted, isomath = true, natural-log = slanted, %??? imaginary-unit = slanted, %??? complex-part-symbols = true, %??? total-derivative-d = slanted, %??? }, notation / legacy .meta:nn = {skmath / internal}{ integral-d = upright, isomath = true, natural-log = slanted, imaginary-unit = slanted, complex-part-symbols = true, total-derivative-d = slanted, }, % Possibly more style sets... ? notation .initial:n = legacy, % Or is it? Perhaps a legacy option is required. notation .value_required:n = true, % 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}{\ee} \begin{MacroCode}{package} \DeclareDocumentCommand\ee{}{\ensuremath{\__skmath_natural_log_e:}} \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 \cs{pd} and \cs{td}. \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_e: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<2}{ \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}{\int_use:N\l_tmpa_int} \bool_if:NF\l_tmpa_bool{ \int_compare:nT{\l_tmpa_int>\c_zero_int}{+} \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_int}{ \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<2}{ \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} \int_compare:nT{\seq_count:N\l_tmpa_seq>\c_zero_int}{ \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*} \begin{macro*}{\__skmath_td_fraction:nn}[2] {Tokens representing a mathematical function} {A single variable, possibly with a superscript} \begin{MacroCode}{package} \cs_new_nopar:Npn\__skmath_td_fraction:nn#1#2{ \frac{ \__skmath_total_derivative_d: \__skmath_pd_if_vars_sum_above_one:nT{#2}{ \c_math_superscript_token{\__skmath_pd_vars_sum:n{#2}} } {#1} }{ \__skmath_total_derivative_d: #2 } } \end{MacroCode} \end{macro*} Definition of \cs{bar}, \cs{pd}, \cs{td} 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 also have the total derivative macro, \begin{macro}{\td}[2] {Tokens representing a mathematical function} {A single variable, possibly with a superscript} \begin{MacroCode}{package} \DeclareDocumentCommand\td{mm}{ \ensuremath{ \__skmath_td_fraction:nn{#1}{#2} } } \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}