Calculations in lathe? So easily!

Those who have to write texts more difficult slugbot, you know that latex is a convenient add-on Tex — at the moment is almost the only effective way to quickly write high-quality texts of any complexity. But not a single text... Latex can be used for other purposes, which the Creator of Tex, Donald Knuth, and probably not thought.
I already wrote how you can make up to latehe presentation. Now I want to talk about how to carry out simple calculations directly forces lateja.

For lateja different people have written a lot of various packages that extend its functionality and facilitate the work of the coder. Not forgotten, and tools that help you work with numeric data. Simple calculations using floating point (single precision) you can perform directly under Tex. This is the package fp. Just want to note that because of the opportunities latehe to execute external commands, you can even perform more complex actions at compile time (for example, something to calculate in Octave, then build in MathGL graphics and paste them into the text), but this I may tell another time.
I did not set out to skopipastit the manual for the fp package (especially since it is quite small), and I want to tell you how I use this package for simple calculations when preparing any kind of technical tasks, reports, etc. And will show you how to use it to implement basic functionality "spreadsheet".
Let's create a command that allows you to insert a variety of ranging information (i.e., some parameters that in the future you can change), indicated in the draft setting these inserts with red accents, index and memo fields. The color in the document, we provide package colorx.
This team will work in three ways:
    the
  • without any parameters (i.e. if we need to mark the place in the text where not enough of something that I would need to paste in the future), in this case, we simply note the empty space in the text a red square with a Superscript index and will put on field a label with a question mark;
  • the
  • with a single parameter (i.e. we have inserted some data in the future will not be used), in this case, the inserted text is displayed with a Superscript index and the corresponding empty label in the fields;
  • the
  • with two parameters (i.e. our data will be used further and we want them to initialize some variable), it also shows that initializes the text index, but on the fields in front of this index is placed the name of the variable to which the number is entered, plus that initializes this variable.
so, here is the code:

the
\newcounter{InsC@unt@r} 
\def\Ind@x{\stepcounter{InsC@unt@r}% 
\hbox to 0pt{\raisebox{1ex}{\tiny\red{\arabic{InsC@unt@r}}}}} 
\def\Insm@rgimp@r#1{\marginpar{\red{\tiny\arabic{InsC@unt@r}:#1}}} 
\ifx\TextOut\undefined 
\def\InsTxt@#1#2{#1\Ind@x\Insm@rgimp@r{#2}} 
\else 
\def\InsTxt@#1#2{#1} 
\fi 
\def\Ins{\futurelet\next\Ins@i} 
\def\Ins@i{\ifx\next\bgroup\expandafter\Ins@ii\else\expandafter\Ins@end\fi} 
\def\Ins@ii#1{\def\temp@rg{#1}\futurelet\next\Ins@iii} 
\def\Ins@iii{\ifx\next\bgroup\expandafter\Ins@two@rgs% 
\else\expandafter\Ins@one@rg\fi} 
\def\Ins@two@rgs#1{\InsWFP{\temp@rg}{#1}} % Two arguments 
\def\InsWFP#1#2{\expandafter\FPset\csname #1\endcsname{#2}\InsTxt@{#2}{#1}} 
\def\Ins@one@rg{\InsTxt@{\temp@rg}{}} % One argument
\def\Ins@end{\red{\Square\Ind@x}\Insm@rgimp@r{?}\xspace} % No arguments 


I will explain it. First we declare a new counter which will be used to index numbering inserts. Then define various auxiliary commands to the primary command \Ins, which we will insert your details into the text.
The command \Ind@x and \Insm@rgimp@r is needed in order to celebrate our insertion in draft mode. The first command incrementorum counter inserts, creates not occupying the width of the space box and put a red Superscript number inserted. The second command puts a mark on the field. He draft is governed by the command \TextOut: if we define it (\def\TextOut{}) to this piece of code marks on the command \def\InsTxt is ("clean" mode of the layout), otherwise they will be placed.
The command \Ins@ii places the first argument of the command \Ins the macro \temp@rg, and again checks whether the next argument (\Ins@iii): if it is, run the command \Ins@two@rgs that initializes the variable, and inserts its value and label in the text; if not, run the command \Ins@one@rg, which simply inserts the text data and makes a mark.
In order to facilitate the conclusion of results of calculations, we will create the command \FPrint, similar in spelling to \FPprint from the package fp, but making a few more: her argument is expression:number, where expression — the calculation or command, and number — the number of digits after the decimal point to which to round the result. The system displays a rounded number. Here all simply enough implemented, so too will not comment.

the
\def\FPrint#1{\@@print@@#1} 
\def\@@print@@#1:#2{\FPeval{\res@lt}{round(#1:#2)}\res@lt} 


Storage some common to all text data (say, magnitude, which is calculated for several sections, and each section is calculated some part of it, and the amount we need to withdraw at the end of the text) define the command \Ini (initialisere user-defined variable that has one required argument — the name of the variable, and one optional — the value with which the variable is initialized), \Add (adds to variable of the first parameter is the expression of a second), \Sub (subtracts from a variable number) and \Show (displays the variable in the text, rounding it to two digits after the decimal point or up to the number of digits specified in the optional parameter).

the
\newcommand{\Ini}[2][0]{\expandafter\gdef\csname cntr#2\endcsname{#1}} 
\def\Add#1#2{\expandafter\FPeval\csname cntr#1\endcsname{cntr#1+(#2)}} 
\def\Sub#1#2{\expandafter\FPeval\csname cntr#1\endcsname{cntr#1-(#2)}} 
\newcommand{\Show}[2][2]{\FPrint{cntr#2:#1}} 


Due to the fact that the variable name user-defined prefix cntr, almost disappears the probability of accidental override any matejovsky macros.
Then move on to "spreadsheets". For a start get automatic numbering:

the
\newcount\@row@num\@row@num=15 
\def\@@nonum{} 
\def\@shownum{\ifx\@@nonum\empty\global\advance\@row@num1 \the\@row@num\else 
\gdef\@@nonum{}\fi} 
\def\NumIni{\global\@row@num=0\gdef\@@nonum{1}} 
\def\NoNum{\gdef\@@nonum{1}} 
\newcolumntype{N}[1] {>{\strut}#1 < {\@shownum}} 


The initialization of the counter must be performed manually by the beginning of the table the command \NumIni (or come up with something like \everypage, but for tables). With the help of package array we will comply with certain us teams for each cell in the desired column. This package allows you to define new types of columns: the column table in which we want to insert auto numbering, it will be necessary to mark the type N. If in some cell we don't need to insert a number, we mark it with the macro \NoNum.
We now turn to the definition of the column types that allow you to perform addition, subtraction, multiplication and division with numeric variables. Since the code for all these commands does not differ almost from each other (except for running in the \FPeval arithmetic operations), to begin to define a macro to facilitate defining new commands.
Warns you in advance: as to uniquely determine the end number in the table cell would have to scan it character by character (which greatly would increase the compile time of the text), I went the other way. At the end of each cell before the at sign the ampersand, you must insert a space, clearly symbolizing the end of the data within the cell. If you forget the gap, can appear "strange errors".
Explain in detail the following macro, I will not confine myself to a rough description. The command \@@def@cmd allows to define a new macro (whose name is specified in the first parameter), performing the arithmetic operation of the second parameter and to create a new type of a table column (the third parameter). As this command is used to initialize other commands, and even defines a new command by the name of the parameter used chehovskie such constructions as \expandafter (the suppression of the disclosure of the next token until the following reveals one token), \xdef (it is identical to \global\edef and defines a new macro, pre-opening macros from your body) \noexpand (prohibition of disclosure of the token "first reading"), \csname (the text in the macro name).
the
\def\@@def@cmd#1#2#3{% 
\expandafter\xdef\csname #1\endcsname##1\ignorespaces{% 
\xdef\noexpand\@fst@rg{##1}\futurelet\noexpand\next\expandafter\noexpand\csname 
@@#1@\endcsname} 
\expandafter\xdef\csname @@#1@\endcsname{% 
\noexpand\ifx\noexpand\next\unskip\relax 
\noexpand\else\noexpand\expandafter\expandafter\noexpand\csname 
@testminus@#1\endcsname\noexpand\fi} 
\expandafter\xdef\csname @testminus@#1\endcsname{% 
\noexpand\ifx\noexpand\next\noexpand\expandafter\expandafter\noexpand 
\csname @@m@#1\endcsname\noexpand\else 
\noexpand\expandafter\expandafter\noexpand 
\csname @@@#1\endcsname\noexpand\fi} 
\expandafter\xdef\csname the @@@#1\endcsname##1 {% 
\noexpand\ifnum1=1##1{}\noexpand\else##1 \noexpand#2{##1}\noexpand\fi} 
\expandafter\xdef\csname @@m@#1\endcsname##1 {##1 \noexpand#2{##1}} 
\newcolumntype{#3}[2] {>{\csname #1\endcsname{##1}}##2} 
} 


Now that we've done the dirty work, you can define key commands:

the
\def\@SET#1{\expandafter\xdef\csname cntr\@fst@rg\endcsname{#1}} 
\def\@ADD#1{\FPeval{\res@lt}{cntr\@fst@rg+(#1)}\@SET{\res@lt}} 
\def\@SUB#1{\FPeval{\res@lt}{cntr\@fst@rg-(#1)}\@SET{\res@lt}} 
\def\@MUL#1{\FPeval{\res@lt}{cntr\@fst@rg*(#1)}\@SET{\res@lt}} 
\def\@DIV#1{\FPeval{\res@lt}{cntr\@fst@rg/(#1)}\@SET{\res@lt}} 
\@@def@cmd{TAdd}{\@ADD}{+} 
\@@def@cmd{TSub}{\@SUB}{-} 
\@@def@cmd{TMul}{\@MUL}{*} 
\@@def@cmd{TDiv}{\@DIV}{/} 
\@@def@cmd{TSet}{\@SET}{X} 


We now have the following new types of columns that takes two arguments (the name of the variable and the standard type alignment cell). Types of +, -, * and / perform the corresponding operations between a variable from the first argument type of cell contained in the cell number. Type X sets the variable to the value contained in the cell. If the variable should be used, not inicializirati column X, it is necessary to initialize a table with the command \Ini. The contents of the cell is checked: if there is no number, then action is taken.
Now we have to declare another type of column that will display the results of a calculation (and, if necessary, to consider their sum).

the
\def\@@plus#1#2{\gdef\@fst@rg{#1}\@ADD{cntr#2}} 
\def\@Sho@@#1{\ifx\@@nonum\empty\@@plus{#1}{\temp@rg}\else\gdef\@@nonum{}\fi} 
\def\@Sh@{\ifx\next\bgroup\expandafter\@Sho@@\else\gdef\@@nonum{}\fi} 
\def\.#1{\ifx\@@nonum\empty\Show{#1}\fi\def\temp@rg{#1}\futurelet\next\@Sh@} 
\newcolumntype{S}[3] {>{\strut}#3<{\Sho{#1}{#2}}} 


We are creating a new column type S that has three parameters: the name of the variable, the variable name of the battery and the alignment type. This team also has \NoNum. The command \Sho that implements the S, can be run by itself. In this case we do not need to accumulate the results into a variable, we just give this command, only one argument.
And finally — a little bit of entertainment. Connect the package ifthen for the implementation of complex conditional instructions (those not allow nested if) and make the implementation cycles and the stack.
A simple for loop (non-nested) can be defined as:

the
\newcounter{f@rc@unter} 
\newcommand{\forplus}[4][1]{% 
\setcounter{f@rc@unter}{#2}\ifthenelse{\value{f@rc@unter} < #3}{#4% 
\addtocounter{f@rc@unter}{#1}% 
\forplus[#1]{\value{f@rc@unter}}{#3}{#4}}{}} 
\newcommand{\forminus}[4][-1]{% 
\setcounter{f@rc@unter}{#2}\ifthenelse{\value{f@rc@unter} > #3}{#4% 
\addtocounter{f@rc@unter}{#1}% 
\forminus[#1]{\value{f@rc@unter}}{#3}{#4}}{}} 
\def\iterator{\arabic{f@rc@unter}} 
\def\Loop#1#2{\forplus{0}{#1}{#2}} 


Here four teams. \forplus allows to implement a loop with the increment of the number specified in the first parameter to the value specified in the second, by performing each time the contents of the third parameter. An optional argument of a macro — step cycle. The command \forminus implements a loop with a decrement. \iterator allows you to display the contents of the iterator loop, and \Loop — to execute the contents of the second argument N times (where N is the first argument).
To work with the stack define a command \push and \pop and \stacklen (the number of elements in the stack) and \popall (output the entire contents of the stack) and \popalldel (the contents of a delimited).

the
\newcount\@buflen\@buflen=0 
\newtoks\@@stack 
\@@stack={\empty} 
\def\push#1{\advance\@buflen1\begingroup\toks0={{#1}}% 
\edef\act{\endgroup\global\@@stack={\the\toks0 \the\@@stack}}\act} 
\def\pop{\ifnum\@buflen>0\advance\@buflen-1\fi\begingroup% 
\edef\act{\endgroup\noexpand\splitList\the\@@stack(tail)\@@stack}\act} 
\def\splitList#1#2(tail)#3{\ifx#1\empty\red{Stack is empty!}\else{#1}\global#3={#2}\fi} 
\def\stacklen{\the\@buflen\xspace} 
\def\popalldel#1{\ifthenelse{\the\@buflen > 1}{\pop#1\popalldel{#1}}% 
{\ifnum\@buflen=1\pop\fi}} 
\def\popall{\popalldel{}} 


The stack is implemented using a simple list of tokens. The room to the stack just adds to the list a new token, and the choice of stack splits the list in the first token and returns it.

the

Examples

Example table:

the
\Ini[1]{yy} 
\Ini{zz} 
\begin{table}[!th] 
\begin{tabular}{|N{c}|X{xx}{c}|*{xx}{c}|S{xx}{zz}{c}|*{yy}{c}|} 
\hline 
\bf \NumIni \No{} n/p & A & B & A$\cdot$B\NoNum& C \\ 
\hline 
& -3.5 & 4.4 &&43.3 \\ 
& 31.31 &200.21 &&3 \\ 
&1.23 &3.33 &&1.2 \\ 
\hline 
\NoNum&&&\NoNum $\sum(A\cdot B)=\,$\Show{zz}&$\prod C=\,$\Show{yy} \\ 
\hline 
\end{tabular} 
\end{table} 




Example of initialized variables and calculations:

the
\Ini{totalmass} 
Let the variable {\tt totalmass} we have kept the total mass of something, the masses of parts of which we 
we calculate throughout the text. All these elements will as of a calculation to it 
add. 

So, here we compute something equal to \Ins{m1p}{45.1},\FPeval{m1}{3*m1p} 
and then multiply by three: $m_1=3\cdot\FPrint{m1p:1}=\FPrint{m1:1}$. Add that to the total 
mass.\Add{totalmass}{m1} Get: {\tt totalmass}$\,=\Show[1]{totalmass}$. 

Further, when we need to define a new variable equal to, say, 
\Ins{moreaddtoa}{3.45} and add it to ground, again use the same method. 
Get: {\tt totalmass}$\,\Add{totalmass}{moreaddtoa}=\Show[2]{totalmass}$. 

After some time, compute something. Let the density of something is equal to 
$\rho=\,$\Ins{therho}{5.43}, and the volume is $V=\,$\Ins{theV}{12.44}, then its mass is 
\FPeval{mi}{therho*theV}$m_i=\rho\cdot V=\FPrint{mi:3}$. Will add it to the total 
mass.\Add{totalmass}{mi} In the end we get: {\tt totalmass}$\,=\Show[3]{totalmass}$. 

The command \verb'\Ini', \verb'\Show' and \verb'\FPrint' may be used inside groups. 
The command \verb'\Ins' and team computing package {\tt fp} to use inside the formulas be: 
first because work with fields, the other "--- due to the fact that they do not use the command 
\verb'\global' and calculations made within the group, outside the group actions will not conceive. 




An example of working with cycles and stack:

the
Let the sides of a triangle are equal a=\Ins{a}{2.5}, b=\Ins{b}{3}, then 
the hypotenuse will be equal to $c=\sqrt{a^2+b^2}=\FPrint{root(2, (a^2 + b^2)):2}$ 

Cycle 1 to 4: \forplus{1}{5}{\iterator~} 

Loop from 1 to 10 with step 3: \forplus[3]{1}{11}{\iterator~} 

Cycle from 4 to 1: \forminus{4}{0}{\iterator~} 

The cycle from 10 to 1 step -3: \forminus[-3]{10}{0}{\iterator~} 

\Loop5{Five times! } 

\push{first}\push{second}\push{third}\push{latest} 
Stack content, separated by commas: \popalldel{, }. Left: \stacklen records. 




Text example
Resulting pdf
Article based on information from habrahabr.ru

Комментарии

Популярные сообщения из этого блога

mSearch: search + filter for MODX Revolution

Emulator data from GNSS receiver NMEA

The game Let's Twist: the Path into the unknown