summaryrefslogtreecommitdiff
path: root/macros/latex/contrib/smartunits
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
committerNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
commite0c6872cf40896c7be36b11dcc744620f10adf1d (patch)
tree60335e10d2f4354b0674ec22d7b53f0f8abee672 /macros/latex/contrib/smartunits
Initial commit
Diffstat (limited to 'macros/latex/contrib/smartunits')
-rw-r--r--macros/latex/contrib/smartunits/README.md62
-rw-r--r--macros/latex/contrib/smartunits/smartunits.pdfbin0 -> 336458 bytes
-rw-r--r--macros/latex/contrib/smartunits/smartunits.sty190
-rw-r--r--macros/latex/contrib/smartunits/smartunits.tex427
4 files changed, 679 insertions, 0 deletions
diff --git a/macros/latex/contrib/smartunits/README.md b/macros/latex/contrib/smartunits/README.md
new file mode 100644
index 0000000000..e68f705ed0
--- /dev/null
+++ b/macros/latex/contrib/smartunits/README.md
@@ -0,0 +1,62 @@
+smartunits
+==========
+
+A [LaTeX](http://en.wikipedia.org/wiki/LaTeX) package that implements
+automatic conversions between (some) metric and Imperial units. All units are
+printed using siuntx
+
+Example
+-------
+
+```tex
+\documentclass{article}
+\usepackage{smartunits}
+\begin{document}
+ \SmartUnitSettings{metric imperial, places=1}
+ \SmartUnit{km=100.0,figures=1} % 100 km (60 mi)
+ \SmartUnit{miles=62.15,places=1} % 100 km (62.2 mi)
+ \SmartUnit{cm=10} % 10 cm (3.9")
+ \SmartUnit{celsius=20} % 20 C (68.0 F)
+ \SmartUnit{miles=5.0} % 8.0 km (5.0 mi)
+ \SmartUnit{miles=5.0, figures=1} % 8 km (5 mi)
+ \SmartUnit{hours=0, minutes=59} % 0:59 (12:59 AM)
+ \SmartUnit{hours=12, minutes=12} % 12:12 (12:12 PM)
+ \SmartUnit{kg=10.0, places=1} % 10.0kg (22.0 lbs)
+ \SmartUnit{pound=10.0,figures=1} % 5kg (10 lbs)
+ \SmartUnit{l=10.0, places=1} % 10.0l (2.6gal)
+ \SmartUnit{L=10.0, places=1,uk} % 10.0L (2.2gal)
+\end{document}
+```
+
+
+Units supported
+---------------
+
+Currently smartunits converts between the following five classes of units:
+
+ ============ ==============
+ Metric Imperial
+ ------------ -------------- -------------
+ kilometers miles (distance)
+ centimeters feet and inches (length)
+ Celsius Fahrenheit (temperature)
+ 24-hour time 12-hour time (time)
+ litres USA/UK gallons (volume)
+ kilograms pounds (weight)
+ ============ ============== =============
+
+It is quite easy to extend the code to other units. I am happy to consider new requests.
+
+Requirements
+------------
+
+The package requires
+[pgfkeys](https://www.ctan.org/pkg/pgfkeys) and
+[siunitx](https://www.ctan.org/pkg/siunitx).
+
+### Author
+
+Copyright (c) 2016 [Andrew Mathas](mailto:andrew.mathas@gmail.com)
+
+Released under the [LaTeX Project Public
+License](http://www.latex-project.org/lppl.txt) v1.3c or later
diff --git a/macros/latex/contrib/smartunits/smartunits.pdf b/macros/latex/contrib/smartunits/smartunits.pdf
new file mode 100644
index 0000000000..e55b6217b2
--- /dev/null
+++ b/macros/latex/contrib/smartunits/smartunits.pdf
Binary files differ
diff --git a/macros/latex/contrib/smartunits/smartunits.sty b/macros/latex/contrib/smartunits/smartunits.sty
new file mode 100644
index 0000000000..29ed4640e2
--- /dev/null
+++ b/macros/latex/contrib/smartunits/smartunits.sty
@@ -0,0 +1,190 @@
+%% ----------------------------------------------------------------
+%% smartunits --- A latex package that implements automatic conversions
+%% between certain metric and Imperial units.
+%% E-mail: andrew.mathas@gmail.com
+%% Released under the LaTeX Project Public License v1.3c or later
+%% See http://www.latex-project.org/lppl.txt
+%% ----------------------------------------------------------------
+
+% http://tex.stackexchange.com/questions/241169/is-it-possible-in-latex-to-print-all-numbers-between-imperial-and-metric/241179#241179
+\NeedsTeXFormat{LaTeX2e}
+\def\smart@version{Version 1.2 -- 2016/02/05}
+\ProvidesPackage{smartunits}[2016/02/05 \smart@version\space- Smart conversion between metric and Imperial units]
+\RequirePackage{siunitx,pgfmath,pgfkeys}
+
+% a global pgfkeyssetvalue from Martin Scharrer's answer to http://tex.stackexchange.com/questions/15204
+\newcommand{\pgfkeysgsetvalue}[2]{\pgfkeys@temptoks{#2}\expandafter\xdef\csname pgfk@#1\endcsname{\the\pgfkeys@temptoks}}
+
+% a shorthand for extracting key values from /SmartUnit
+\newcommand\smart@val[1]{\pgfkeysvalueof{/SmartUnit/#1}}
+
+% the pgfkey family for smart units
+\pgfkeys{/SmartUnit/.is family,/SmartUnit,%
+ %%%% /SmartUnit/unit <convert> keys are implicitly initialised through the
+ %%%% following. As a bonus this allows us to use \pgfkeysifdefined below.
+ .unknown/.code={\pgfkeyssetvalue{\pgfkeyscurrentpath/\pgfkeyscurrentname}{#1}},%
+ %%%% /SmartUnit/convert is used to determine which "smart unit" to print
+ %%%% printunit --> output --> injects the code to print the current <convert>
+ printunit/.code={\pgfkeysifdefined{/SmartUnit/convert}{\pgfkeys{/SmartUnit/output/\smart@val{format}}}{}},%
+ output/metric/.code={\pgfkeys{/SmartUnit/\smart@val{convert}/metric}},%
+ output/imperial/.code={\pgfkeys{/SmartUnit/\smart@val{convert}/imperial}},%
+ output/metric imperial/.code={\pgfkeys{/SmartUnit/\smart@val{convert}/metric}\space(\pgfkeys{/SmartUnit/\smart@val{convert}/imperial})},%
+ output/imperial metric/.code={\pgfkeys{/SmartUnit/\smart@val{convert}/imperial}\space(\pgfkeys{/SmartUnit/\smart@val{convert}/metric})},%
+ %%%% global flags for controlling when metric and imperial units are printed
+ format/.initial=metric,%
+ metric/.code={\pgfkeysgsetvalue{/SmartUnit/format}{metric}},%
+ imperial/.code={\pgfkeysgsetvalue{/SmartUnit/format}{imperial}},%
+ metric imperial/.code={\pgfkeysgsetvalue{/SmartUnit/format}{metric imperial}},%
+ imperial metric/.code={\pgfkeysgsetvalue{/SmartUnit/format}{imperial metric}},%
+ %%%% allow for both UK and US Imperial units
+ system/.initial=usa,% for purely demographic reasons
+ usa/.style={system=usa},%
+ uk/.style={system=uk},%
+ %%% for local changes to the siunitx precision
+ figures/.code={\sisetup{round-mode=figures, round-precision=#1}},
+ places/.code={\sisetup{round-mode=places, round-precision=#1}},
+ %%%%%%%%%%%%%%%%%%%% conversion routines %%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ % Generic case: #1 = (#2+#3)*#4 + #5 where #6 is the name of the unit
+ conversion/.code n args={6}{%{#1= to, #2= from, #3=pre-offset, #4=multiplier, #5=post-offset, #6= symbol}
+ \pgfkeysifdefined{/SmartUnit/unit #1}{\SI{\smart@val{unit #1}}{#6}}{\pgfmathparse{(\smart@val{unit #2}+#3)*#4+#5}\SI{\pgfmathresult}{#6}}%
+ },%
+ %%%% convert=distance: km <-> miles %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ km/.style={convert=distance, unit km=#1},%
+ mi/.style={convert=distance, unit miles=#1},%
+ miles/.style={convert=distance, unit miles=#1},%
+ distance/metric/.style={/SmartUnit/conversion={km}{miles}{0}{1.609344}{0}{\km}},%
+ distance/imperial/.style={/SmartUnit/conversion={miles}{km}{0}{0.62137119}{0}{\text{mi}}},%
+ %%%% convert=volume l <-> US gallons %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ gal/.style={convert=volume, unit gal=#1},%
+ gal/uk/.initial=0.21996925,% 1L = 0.21996925 gal (UK)
+ gal/usa/.initial=0.26417205,% 1L = 0.26417205 gal (USA)
+ gallons/.style={convert=volume, unit gal=#1},%
+ l/.style={convert=volume, unit L=#1, volume/symbol=l},%
+ L/.style={convert=volume, unit L=#1, volume/symbol=L},%
+ L/uk/.initial=4.54609,% 1 gal (UK) = 4.54609 L
+ L/usa/.initial=3.7854118,% 1 gal (USA) = 3.7854118 L
+ volume/symbol/.initial=l,% default symbol for litres
+ volume/metric/.style={/SmartUnit/conversion={L}{gal}{0}{\smart@val{L/\smart@val{system}}}{0}{\smart@val{volume/symbol}}},%
+ volume/imperial/.style={/SmartUnit/conversion={gal}{L}{0}{\smart@val{gal/\smart@val{system}}}{0}{\text{gal}}},%
+ %%%% convert=weight: kg <-> lbs %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ kg/.style={convert=weight, unit kg=#1},% 1 lbs = 0.45359237 kg
+ lbs/.style={convert=weight, unit pound=#1},% 1kg = 2.2046226 lbs (USA)
+ pound/.style={convert=weight, unit pound=#1},% 1kg = 2.2046226 lbs (USA)
+ weight/metric/.style={/SmartUnit/conversion={kg}{pound}{0}{0.45359237}{0}{\kg}},%
+ weight/imperial/.style={/SmartUnit/conversion={pound}{kg}{0}{2.2046226}{0}{\text{lbs}}},%
+ %%%% convert=temperature: C <-> F %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ celsius/.style={convert=temperature, unit celsius=#1},%
+ C/.style={convert=temperature, unit celsius=#1},%
+ fahrenheit/.style={convert=temperature, unit fahrenheit=#1},%
+ F/.style={convert=temperature, unit fahrenheit=#1},%
+ temperature/metric/.style={/SmartUnit/conversion={celsius}{fahrenheit}{-32}{5/9}{0}{\degreeCelsius}},%
+ temperature/imperial/.style={/SmartUnit/conversion={fahrenheit}{celsius}{0}{9/5}{32}{\si{\degree}\text{F}}},%
+ %%%% convert=length: cm <-> feet and inches %%%%%%%%%%%%%%%%%%%%%%%%%
+ cm/.style={convert=length, unit cm=#1},%
+ inches/.style={convert=length, unit inches=#1},%
+ feet/.style={convert=length, unit feet=#1},%
+ length/metric/.code={% called via /SmartUnit/printunit -> /SmartUnit/output with convert=length
+ \pgfkeysifdefined{/SmartUnit/unit cm}{\def\pgfmathresult{\smart@val{unit cm}}}%
+ {\pgfkeysifdefined{/SmartUnit/unit inches}{\pgfmathsetmacro{\smart@tmp}{2.54*\smart@val{unit inches}}}{\def\smart@tmp{0}}%
+ \pgfkeysifdefined{/SmartUnit/unit feet}{\pgfmathparse{\smart@tmp+30.84*\smart@val{unit feet}}}{\let\pgfmathresult\smart@tmp}%
+ }%
+ \SI{\pgfmathresult}{\cm}%
+ },
+ %%%% slightly tricker as we have to convert centimeters to feet and inches
+ length/imperial/.code={% called via /SmartUnit/printunit -> /SmartUnit/output with convert=length
+ \pgfkeysifdefined{/SmartUnit/unit inches}{\pgfkeysifdefined{/SmartUnit/unit feet}{\SI{\smart@val{unit feet}}{\arcminute}\enspace\SI{\smart@val{unit inches}}{\arcsecond}}%
+ {\enspace\SI{\smart@val{unit inches}}{\arcsecond}}%
+ }%
+ {\pgfkeysifdefined{/SmartUnit/unit feet}{\SI{\smart@val{unit feet}}{\arcminute}}%
+ {\pgfmathsetmacro{\smart@tmp}{0.39370079*\smart@val{unit cm}}% centimeters -> inches
+ \pgfmathparse{greater(\smart@tmp,11)}%
+ \ifnum\pgfmathresult=1%
+ \pgfmathparse{int(\smart@tmp/12)}\SI[round-mode=places,round-precision=0]{\pgfmathresult}{\arcminute}%
+ \pgfmathparse{\smart@tmp-12*\pgfmathresult}\enspace\SI{\pgfmathresult}{\arcsecond}%
+ \else%
+ \SI{\smart@tmp}{\arcsecond}%
+ \fi%
+ }%
+ }%
+ },%
+ %%%% convert=time: 24-hour times versus 12-hour time %%%%%%%%%%%%%%%%%%%%%%%%%
+ am/.style={convert=time, unit am=1},%
+ pm/.style={convert=time, unit pm=1},%
+ hours/.style={convert=time, unit hours=#1},%
+ minutes/.style={convert=time, unit minutes=#1},%
+ seconds/.style={convert=time, unit seconds=#1},%
+ time/metric/.code={%
+ \pgfkeysifdefined{/SmartUnit/unit pm}{\pgfmathparse{\smart@val{unit hours}+12}\num{\pgfmathresult}}{\num{\smart@val{unit hours}}}:\num[minimum-integer-digits=2]{\smart@val{unit minutes}}%
+ \pgfkeysifdefined{/SmartUnit/unit seconds}{:\num[minimum-integer-digits=2]{\smart@val{unit seconds}}}{}%
+ },%
+ time/imperial/.code={% extra cases here to for AM/PM when hours=12 <->
+ \pgfkeysifdefined{/SmartUnit/unit am}{\def\smart@tmp{AM}\num{\smart@val{unit hours}}}%
+ {\pgfkeysifdefined{/SmartUnit/unit pm}{\def\smart@tmp{PM}\num{\smart@val{unit hours}}}%
+ {\pgfmathparse{greater(\smart@val{unit hours}+\smart@val{unit minutes}/60,12)}%
+ \ifnum\pgfmathresult=1\def\smart@tmp{PM}\pgfmathparse{\smart@val{unit hours}==12?12:\smart@val{unit hours}-12}\num{\pgfmathresult}%
+ \else\pgfmathparse{\smart@val{unit hours}==0?12:\smart@val{unit hours}}\num{\pgfmathresult}\def\smart@tmp{AM}%
+ \fi%
+ }%
+ }%
+ :\num[minimum-integer-digits=2]{\smart@val{unit minutes}}%
+ \pgfkeysifdefined{/SmartUnit/unit seconds}{\pgfmathparse{greater(\smart@val{unit hours}+\smart@val{unit seconds}/60,12)}\ifnum\pgfmathresult=1\def\smart@tmp{PM}\fi%
+ :\num[minimum-integer-digits=2]{\smart@val{unit seconds}}}{}%
+ \enspace{\text{\smart@tmp}}%
+ },%
+}
+
+\newcommand\SmartUnit[1]{%
+ \bgroup%=> all pgfkeys changes are local to \SmartUnit => no need to reset
+ \pgfkeys{/SmartUnit,#1}% Pass the keys to /SmartUnit
+ \pgfkeys{/SmartUnit,printunit}% Calculate units and print
+ \egroup%
+}
+
+\newcommand\SmartUnitSettings[1]{\pgfkeys{/SmartUnit,#1}}
+
+\endinput
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% CHANGE LOG
+%%
+%% Version 1.2
+%% - corrections to the documentation and in particular to the incorrect conversion
+%% of 20 C to Fahrenheit as reported by Barbara Beeton
+%% - added shorthands C and F for temperature conversions
+%% - fixed bug that resulted in incorrect unit being printed for inches in length
+%% conversions with no feet and forced feet to always be printed as integers
+%%
+%% Version 1.1
+%% - initial release to ctan
+%%
+%% Version 1.0
+%% - initial version based on tex.stackexchange.com question
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Copyright (C) 2016 by Andrew Mathas <andrew.mathas@gmail.com>
+%%
+%% This work may be distributed and/or modified under the
+%% conditions of the LaTeX Project Public License (LPPL), either
+%% version 1.3c of this license or (at your option) any later
+%% version. The latest version of this license is in the file:
+%%
+%% http://www.latex-project.org/lppl.txt
+%%
+%% This work is "maintained" (as per LPPL maintenance status) by
+%% Andrew Mathas.
+%%
+%% This work consists of the files:
+%% smartunits.sty
+%% smartunits.tex
+%% smartunits.pdf
+%% README.md
+%%
+%% Copyright (c) 2016 Andrew Mathas <andrew.mathas@gmail.com>
+%% end of smartunits.sty
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% End of file `smartunits.sty'.
+%%
diff --git a/macros/latex/contrib/smartunits/smartunits.tex b/macros/latex/contrib/smartunits/smartunits.tex
new file mode 100644
index 0000000000..fe57502fbd
--- /dev/null
+++ b/macros/latex/contrib/smartunits/smartunits.tex
@@ -0,0 +1,427 @@
+\documentclass[svgnames]{report}
+\usepackage{smartunits}
+\usepackage{manfnt}
+\usepackage{enumitem}
+\setlist[description]{font=\sffamily\bfseries\color{DodgerBlue},labelwidth=\textwidth}
+\usepackage{booktabs}
+\usepackage[a4paper,margin=18mm]{geometry}
+\synctex=1
+
+\usepackage{fixltx2e} % LaTeX patches, \textsubscript
+\usepackage{cmap} % fix search and cut-and-paste in Acrobat
+\usepackage[T1]{fontenc}
+\usepackage[utf8]{inputenc}
+\setcounter{secnumdepth}{0}
+
+\usepackage{listings}\lstset{language=[LaTeX]TeX,framerule=2pt}
+\lstset{language=[LaTeX]TeX,
+ texcsstyle=*\bfseries\color{Blue},
+ backgroundcolor=\color{Ivory},
+ numbers=none,
+ breaklines=true,
+ keywordstyle=\color{Blue},
+ commentstyle=\color{Brown},
+ tabsize=2,
+ morekeywords={SmartUnit,SmartUnitSettings,sisetup},
+ resetmargins=true,
+}
+% hyperref links to ctan
+\newcommand\ctan[1]{\href{https://www.ctan.org/pkg/#1}{\texttt{#1}}}
+
+\usepackage{xparse}
+\NewDocumentCommand{\Verb}{v}{{\color{blue}#1}}
+
+\newcommand\Section[1]{\subsection{\textcolor{blue}{#1}}}
+
+\makeatletter
+\author{Andrew Mathas}
+\usepackage{tikz}
+\usetikzlibrary{shadows.blur}
+\tikzset{shadowed/.style={blur shadow={shadow blur steps=5},
+ bottom color=LightSkyBlue!30,
+ draw=MidnightBlue!70,shade,
+ font=\normalfont\Huge\bfseries\scshape,
+ rounded corners=8pt,
+ top color=SkyBlue,
+ },
+ boxes/.style={draw=MidnightBlue,
+ fill=Cornsilk,
+ font=\sffamily\small,
+ inner sep=5pt,
+ rectangle,
+ rounded corners=8pt,
+ text=RoyalBlue,
+ }
+}
+\def\SmartTitle{
+ \begin{tikzpicture}[remember picture,overlay]
+ \node[yshift=-3cm] at (current page.north west)
+ {\begin{tikzpicture}[remember picture, overlay]
+ \draw[shadowed](30mm,0) rectangle node[white]{Smart Units} (\paperwidth-30mm,16mm);
+ \node[anchor=west,boxes] at (4cm,0cm) {\@author};
+ \node[anchor=east,boxes] at (\paperwidth-4cm,0) {\smart@version};
+ \end{tikzpicture}
+ };
+ \end{tikzpicture}
+ \vspace*{20mm}
+}
+
+
+\def\@oddfoot{\textsc{Smart Units} -- \smart@version\hfill\thepage}
+
+\usepackage[colorlinks=true,linkcolor=blue,urlcolor=blue]{hyperref}
+\hypersetup{pdfcreator={ Generated by pdfLaTeX },
+ pdfinfo={Author ={ Andrew Mathas },
+ Keywords={ units, metric, Imperial },
+ License ={ LaTeX Project Public License v1.3c or later },
+ Subject ={ Convert between metric and Imperial units },
+ Title ={ smartunits - \smart@version }
+ },
+}
+\makeatother
+
+\begin{document}
+
+ \SmartTitle
+
+ %\Section{Smart units}
+ This package implements a \Verb|\SmartUnit| macro for
+ converting between the following metric and Imperial units:
+
+ \begin{center}
+ \begin{tabular}{@{\color{Grey!50}}ll@{\quad$\longleftrightarrow$\quad}l}\toprule
+ & Metric & Imperial \\\midrule
+ \color{LightSkyBlue}distance & kilometers & miles \\
+ \color{LightSkyBlue}length & centimeters & feet and inches \\
+ \color{LightSkyBlue}temperature & Celsius & Fahrenheit \\
+ \color{LightSkyBlue}time & 24-hour time& 12-hour time \\
+ \color{LightSkyBlue}volume & litres & USA/UK gallons \\
+ \color{LightSkyBlue}weight & kilograms & pounds \\
+ \bottomrule
+ \end{tabular}
+ \end{center}
+ Of course, the underlying unit for length and distance is the same
+ but it makes sense to convert between units of similar ``scale''.
+ The \Verb|\SmartUnit| macro is designed to print only one unit at a
+ time, where the quantity is given in terms of either metric or
+ Imperial units (there is no error checking, however). Depending on
+ the (global) settings the unit will be printed either as a metric
+ unit, or as an Imperial unit, or both. If the required unit is not
+ given as an argument to \Verb|\SmartUnit| then it is computed.
+
+ The units are printed using \ctan{siunitx}, so the formatting of the
+ units can be controlled using \Verb|\sisetup| together with
+ formatting parameters from \ctan{siunitx}. Some aspects of the
+ formatting can be controlled ``locally'' using \Verb|\SmartUnit| and
+ ``globally'' using \Verb|\SmartUnitSettings|.
+
+ The \Verb|\SmartUnit| macro can print units in the following
+ four different formats:
+
+ \begin{lstlisting}
+ \SmartUnit{metric} % --> metric
+ \SmartUnit{imperial} % --> Imperial
+ \SmartUnit{metric imperial} % --> metric (Imperial)
+ \SmartUnit{imperial metric} % --> Imperial (metric)
+ \end{lstlisting}
+
+ For the impatient, here are some examples:
+
+ \bgroup
+ \sisetup{round-mode=places,round-precision=2}
+ \small
+ \begin{lstlisting}[escapeinside=<>]
+ \documentclass{article}
+ \usepackage{smartunits}
+ \begin{document}
+ \SmartUnitSettings{places=2} % Some global settings < \SmartUnitSettings{places=2} >
+ \SmartUnit{metric imperial} % Output format: metric (Imperial) < \SmartUnit{metric imperial} >
+ \SmartUnit{cm=10} % < \SmartUnit{cm=10} >
+ \SmartUnit{cm=66} % < \SmartUnit{cm=66} >
+ \SmartUnit{feet=4,inches=3} % < \SmartUnit{feet=4,inches=3} >
+ \SmartUnit{celsius=20} % < \SmartUnit{celsius=20} >
+ \SmartUnit{metric} % Output format: metric < \SmartUnit{metric} >
+ \SmartUnit{miles=5, places=1} % < \SmartUnit{miles=5,places=1} >
+ \SmartUnit{imperial} % Output format: Imperial < \SmartUnit{imperial} >
+ \SmartUnit{hours=12, minutes=1} % < \SmartUnit{hours=12, minutes=1} >
+ \SmartUnit{km=5,places=3} % < \SmartUnit{km=5,places=3} >
+ \SmartUnit{imperial metric} % Output format: Imperial (metric) < \SmartUnit{imperial metric} >
+ \SmartUnit{miles=5, km=7} % < \SmartUnit{miles=5,km=7} >
+ \SmartUnit{l=1.0, places=1} % < \SmartUnit{l=1.0, places=1} >
+ \SmartUnit{L=1.0, places=1} % < \SmartUnit{L=1.0, places=1} >
+ \SmartUnit{gal=25.0,uk,places=2} % < \SmartUnit{gal=25.0, places=2,uk} >
+ \SmartUnit{gal=25.0,usa,places=2} % < \SmartUnit{gal=25.0, places=2,usa} >
+ \end{document}
+ \end{lstlisting}
+ \egroup
+
+ The calculations done by \Verb|\SmartUnit| are reasonably accurate
+ but LaTeX is not a calculator so rounding and other errors can and
+ do happen (indeed, see the displayed example below). In addition, even assuming
+ that the calculations done by \Verb|\SmartUnit| are accurate this
+ may not be what you want. For example, if the metric unit is given
+ as \SI{100}{km} then many people will want the Imperial unit to be
+ written as \SI{60}{\text{mi}}, rather than the more accurate
+ \SI{62.137119}{\text{mi}}. In fact, \Verb|\SmartUnit| can cater for
+ these considerations because all units are printed using the
+ \ctan{siunitx} package, which is really clever. The precision of the
+ printed units can be controlled using \Verb|\sisetup|, from the
+ \ctan{siunitx} package or by using the short-hands, \textsf{figures}
+ and \textsf{places}, provided by \Verb|\SmartUnit|:
+ \begin{lstlisting}[texcl]
+ \SmartUnit{km=100.0, figures=1} % \SmartUnit{km=100.0,figures=1}
+ \SmartUnit{km=100.0, places=5} % \SmartUnit{km=100.0,places=5}
+ \end{lstlisting}
+ \noindent (Comparing with the paragraph above, the last calculation
+ is only accurate to three decimal places!) The values of the
+ computed units can be overridden, during proof-reading for example,
+ by specifying both the metric and Imperial units:
+ \begin{lstlisting}[texcl]
+ \SmartUnit{km=100,miles=70} % \SmartUnit{km=100,miles=70}
+ \end{lstlisting}
+ \noindent \raisebox{3.9mm}{\dbend}\quad Of course, if you specify
+ units incorrectly like this then incorrect values will be printed.
+
+ Behind the scenes all units are printed using \ctan{siunitx}. Therefore,
+ the precision and formatting of the units can be changed using the
+ options to \Verb|\sisetup| described in the \ctan{siunitx}\ manual. In
+ particular, when the rounding capabilities of~\ctan{siunitx}\ are enabled
+ any units calculated by \Verb|\SmartUnit| will be rounded.
+ In this case there is a shorthand for overriding the global
+ \ctan{siunitx}\ settings for the rounding precision on an individual
+ ``smart unit'':
+
+ \begin{lstlisting}[escapeinside=<>]
+ % Locally=\sisetup{round-precision=3, round-mode=places}
+ \SmartUnit{cm=2, places=3} % < \SmartUnit{cm=2, places=3} >
+ \end{lstlisting}
+
+ Section~5.5 of the \ctan{siunitx}\ manual should be consulted for all of the
+ options for controlling ``post-processing'' of numbers. In particular,
+ units that are given as integers will always be printed as integers.
+ For example, the metric version of \Verb|\SmartUnit{cm=2, places=3}|
+ is printed as \SmartUnit{cm=2, places=3, metric} whereas the Imperial version is
+ \num{0.787}$'$. If, instead, we use
+ \Verb|\SmartUnit{cm=2.0, places=3}| then the metric unit is
+ printed as \SmartUnit{cm=2.0, places=3, metric}.
+
+
+ \Section{Unit conversions}
+ For all of these examples we use the following global settings:
+ \begin{lstlisting}[texcl]
+ \SmartUnitSettings{places=2, metric imperial} % Global settings
+ \end{lstlisting}
+ \SmartUnitSettings{places=2, metric imperial}
+ \noindent Of course, as in some of the example below, this can always be overridden locally.
+
+ \begin{description}
+ \item[Distance -- km, miles, mi]
+ Conversions between kilometers and miles. Miles can be specified
+ using either \textbf{miles} or \textbf{mi}.
+ \begin{lstlisting}[texcl]
+ \SmartUnit{km=100,miles=60} % \SmartUnit{km=100,miles=60}
+ \SmartUnit{km=100.0,figures=1} % \SmartUnit{km=100,figures=1}
+ \SmartUnit{miles=62.15,places=1} % \SmartUnit{miles=62.15,places=1}
+ \end{lstlisting}
+
+ \item[Length -- cm, inches, feet]
+ Feet are always printed as integers. Significant figures/places
+ are applied only to the printing of inches.
+ \begin{lstlisting}[texcl]
+ \SmartUnit{feet=7, inches=1} % \SmartUnit{feet=7, inches=1}
+ \SmartUnit{cm=189, feet=7, inches=1} % \SmartUnit{cm=189, feet=7, inches=1}
+ \SmartUnit{cm=191, places=1} % \SmartUnit{cm=191, places=1}
+ \end{lstlisting}
+
+ \item[Temperature -- celsius, fahrenheit]
+ Convesions between Celsius and Fehrenheit can be speficied using
+ \textsf{celsius}, \textsf{C}, \textsf{fahrenheit} or \textsf{F}.
+
+ \begin{lstlisting}[texcl]
+ \SmartUnit{celsius=32,places=3} % \SmartUnit{celsius=32,places=3}
+ \SmartUnit{celsius=0} % \SmartUnit{celsius=0}
+ \SmartUnit{C=37} % \SmartUnit{C=37}
+ \SmartUnit{fahrenheit=0} % \SmartUnit{fahrenheit=0,places=2}
+ \SmartUnit{F=22,figures=4} % \SmartUnit{F=212,figures=4}
+ \end{lstlisting}
+
+ \item[Time -- hours, minutes, seconds, am, pm]
+ \begin{lstlisting}[texcl]
+ \SmartUnit{hours=0, minutes=59} % \SmartUnit{hours=0, minutes=59}
+ \SmartUnit{hours=12, minutes=12} % \SmartUnit{hours=12, minutes=12}
+ \SmartUnit{hours=13, minutes=9} % \SmartUnit{hours=13, minutes=9}
+ \SmartUnit{hours=8, minutes=31, pm} % \SmartUnit{hours=8, minutes=31, pm}
+ \SmartUnit{hours=9, minutes=3, am} % \SmartUnit{hours=9, minutes=3, am}
+ \SmartUnit{hours=0, minutes=0,seconds=1} % \SmartUnit{hours=0, minutes=0,seconds=1}
+ \SmartUnit{hours=12, minutes=0,seconds=1} % \SmartUnit{hours=12, minutes=0,seconds=1}
+ \end{lstlisting}
+
+ \item[Volume -- L, l, gal, gallons]
+ Converting between litres and gallons. Liters can be specified
+ using \textbf{L} or \textbf{l} and gallons can be given with
+ \textbf{gallons} or \textbf{gal}. Both UK gallons and USA
+ gallons are supported, with USA gallons being the default.
+ \begin{lstlisting}[texcl]
+ \SmartUnit{l=10.0, places=1} % \SmartUnit{l=10.0, places=1}
+ \SmartUnit{L=10.0, places=1,uk} % \SmartUnit{L=10.0, places=1,uk}
+ \SmartUnit{gal=10.0, places=2} % \SmartUnit{gal=10.0, places=2}
+ \end{lstlisting}
+
+ \item[Weight -- kg, pounds, lbs]
+ \begin{lstlisting}[texcl]
+ \SmartUnit{kg=10.0, places=1} % \SmartUnit{kg=10.0, places=1}
+ \SmartUnit{pound=10.0, places=1} % \SmartUnit{pound=10.0, places=1}
+ \SmartUnit{pound=10.0,figures=1} % \SmartUnit{pound=10.0,figures=1}
+ \end{lstlisting}
+ \end{description}
+
+ \Section{Formatting options}
+
+ The following options can either be used inside \Verb|\SmartUnit| to
+ control the formatting \textit{locally} for just the unit being
+ printed. They can also be used as arguments to
+ \Verb|\SmartUnitSettings| to change the formatting of all subsequent
+ smart units (unless these settings are overridden locally). More
+ control over the formatting of the units is given by the
+ \Verb|\sisetup| macro from the \ctan{siunitx} package.
+
+ \begin{description}
+ \item[figures] This is equivalent to \Verb|\sisetup{round-mode=figures, precision=#1}|.
+ Units are printed with \#1 significant figures.
+ \begin{lstlisting}[texcl]
+ \SmartUnit{miles=60, metric, figures=0} % \SmartUnit{miles=60, metric, figures=0}
+ \SmartUnit{miles=60, metric, figures=1} % \SmartUnit{miles=60, metric, figures=1}
+ \SmartUnit{miles=60, metric, figures=2} % \SmartUnit{miles=60, metric, figures=2}
+ \SmartUnit{miles=60, metric, figures=3} % \SmartUnit{miles=60, metric, figures=3}
+ \SmartUnit{miles=60, metric, figures=4} % \SmartUnit{miles=60, metric, figures=4}
+ \end{lstlisting}
+
+ \item[places]
+ This is equivalent to \Verb|\sisetup{round-mode=places, precision=#1}|.
+ Units are printed with \#1 decimal places.
+ \begin{lstlisting}[texcl]
+ \SmartUnit{miles=60, metric, places=0} % \SmartUnit{miles=60, metric, places=0}
+ \SmartUnit{miles=60, metric, places=1} % \SmartUnit{miles=60, metric, places=1}
+ \SmartUnit{miles=60, metric, places=2} % \SmartUnit{miles=60, metric, places=2}
+ \SmartUnit{miles=60, metric, places=3} % \SmartUnit{miles=60, metric, places=3}
+ \SmartUnit{miles=60, metric, places=4} % \SmartUnit{miles=60, metric, places=4}
+ \end{lstlisting}
+
+
+ \item[imperial]
+ Print only Imperial units.
+ \begin{lstlisting}[texcl]
+ \SmartUnit{km=1.0, imperial} % \SmartUnit{km=1.0, imperial, figures=2}
+ \SmartUnit{miles=1.0, imperial} % \SmartUnit{miles=1.0, imperial, figures=2}
+ \end{lstlisting}
+ \item[imperial metric]
+ Print Imperial units with metric units enclosed in brackets.
+ \begin{lstlisting}[texcl]
+ \SmartUnit{km=1.0, imperial metric} % \SmartUnit{km=1.0, imperial metric, figures=2}
+ \SmartUnit{miles=1.0, imperial metric} % \SmartUnit{miles=1.0, imperial metric, figures=2}
+ \end{lstlisting}
+ \item[metric (default)]
+ Print only metric units.
+ \begin{lstlisting}[texcl]
+ \SmartUnit{km=1.0, metric} % \SmartUnit{km=1.0, metric, figures=2}
+ \SmartUnit{miles=1.0, metric} % \SmartUnit{miles=1.0, metric, figures=2}
+ \end{lstlisting}
+ \item[metric imperial]
+ Print metric units with Imperial units enclosed in brackets.
+ \begin{lstlisting}[texcl]
+ \SmartUnit{km=1.0, metric imperial} % \SmartUnit{km=1.0, metric imperial, figures=2}
+ \SmartUnit{miles=1.0, metric imperial} % \SmartUnit{miles=1.0, metric imperial, figures=2}
+ \end{lstlisting}
+ \item[uk]
+ Selects the UK variants of the Imperial units (currently this
+ only affects gallons):
+ \begin{lstlisting}[texcl]
+ \SmartUnit{l=1.0, imperial metric, figures=2,uk} % \SmartUnit{l=1.0, imperial metric, figures=2,uk}
+ \SmartUnit{gal=1.0, imperial metric, figures=2,uk} % \SmartUnit{gal=1.0, imperial metric, figures=2,uk}
+ \end{lstlisting}
+ \item[usa (default)]
+ Selects the USA variants of the Imperial units (currently this
+ only affects gallons):
+ \begin{lstlisting}[texcl]
+ \SmartUnit{l=1.0, imperial metric, figures=2,usa} % \SmartUnit{l=1.0, imperial metric, figures=2,usa}
+ \SmartUnit{gal=1.0, imperial metric, figures=2,usa} % \SmartUnit{gal=1.0, imperial metric, figures=2,usa}
+ \end{lstlisting}
+ By default \Verb|\SmartUnit| uses the American Imperial units.
+ This is a purely democratic choice dictated by the populations
+ of the two countries.
+ \end{description}
+
+ \Section{The code}
+ Behind the scenes, the \Verb|\SmartUnit| macro uses \ctan{pgfkeys} and
+ \ctan{pgfmath} to convert between the different units. The interface is
+ surprisingly simple and easy to extend. For example, the following
+ code takes care of the conversion between kilometers and miles:
+ \bgroup\footnotesize
+ \begin{lstlisting}
+ %%%% convert=distance: km <-> miles %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ km/.style={convert=distance, unit km=#1},%
+ mi/.style={convert=distance, unit miles=#1},%
+ miles/.style={convert=distance, unit miles=#1},%
+ distance/metric/.style={/SmartUnit/conversion={km}{miles}{0}{1.609344}{0}{km}},%
+ distance/imperial/.style={/SmartUnit/conversion={miles}{km}{0}{0.62137119}{0}{\text{mi}}},%
+ \end{lstlisting}
+ \egroup
+ \noindent
+ Most of the conversions are done in this way --- the exceptions are
+ ``length'' and ``time'', which are more complicated. The key
+ \Verb|/SmartUnit/conversion| is a macro that takes six arguments and
+ then implements the generic conversion formula:
+ \[
+ \text{New unit}(\Verb|#1|) = \Big(\text{Old unit}(\Verb|#2)|+\text{Pre-offset}(\Verb|#3|)\Big)*\text{Multiplier}(\Verb|#4|) + \text{Post-offset}(\Verb|#5|),
+ \]
+ where \Verb|#6| is the metric or Imperial symbol for the unit being
+ printed.
+
+ \textit{Adding additional conversions is quite straightforward and I am
+ happy to incorporate suggestions.}
+
+ There is, of course, some trickery driving how the units are printed.
+ Here is the definition of \Verb|\SmartUnit|:
+ \begin{lstlisting}
+ \newcommand\SmartUnit[1]{%
+ \bgroup%=> changes are local to \SmartUnit => no need to reset
+ \pgfkeys{/SmartUnit,#1}% Pass the keys to /SmartUnit
+ \pgfkeys{/SmartUnit,printunit}% Calculate units and print
+ \egroup%
+ }
+ \end{lstlisting}
+ So \Verb|\SmartUnit| calls \ctan{pgfkeys} twice: the first time to
+ set the keys and the second time to print them using
+ \Verb|/SmartUnit/printunit|. In turn, this uses
+ \Verb|/SmartUnit/convert| to identify the unit being printed,
+ after which the pgf key
+ \Verb|/SmartUnit/output| is called. This has subkeys for the four
+ different \textit{output formats}:
+ \begin{center}
+ \texttt{metric}, \texttt{imperial},
+ \texttt{metric imperial} and \texttt{imperial metric}.
+ \end{center}
+ Finally, \Verb|/SmartUnit/output/<format>| uses
+ \Verb|/SmartUnit/convert| to perform the required conversion.
+ This multi-step printing process is necessary for converting between
+ inputs like time or centimeters, feet and inches, where the
+ output units depend on more than one input value. It is also used to
+ print the four different output formats discussed above.
+
+
+ \Section{Acknowledgement}
+ The package was written in response to a
+ \href{http://tex.stackexchange.com/questions/241169/}{TeX.SX question},
+ partly as a proof-of-concept and partly as an exercise to learn how
+ to use \ctan{pgfkeys}. Thanks to Mark Adams for asking the question.
+
+ \Section{Author}
+ \href{mailto:Andrew.Mathas@gmail.com?smartunits}{Andrew Mathas},
+ \copyright\space 2015, 2016.
+
+ \Section{Licence}
+ Released under the
+ \href{http://www.latex-project.org/lppl.txt}%
+ {LaTeX Project Public License}, v1.3c or later.
+
+\end{document}